Implement CSS `display: flow-root` (modern clearfix)
[WebKit-https.git] / Source / WebCore / css / CSSPrimitiveValueMappings.h
1 /*
2  * Copyright (C) 2007 Alexey Proskuryakov <ap@nypop.com>.
3  * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
4  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
5  * Copyright (C) 2009 Jeff Schiller <codedread@gmail.com>
6  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #pragma once
31
32 #include "CSSCalculationValue.h"
33 #include "CSSFontFamily.h"
34 #include "CSSPrimitiveValue.h"
35 #include "CSSReflectionDirection.h"
36 #include "CSSToLengthConversionData.h"
37 #include "CSSValueKeywords.h"
38 #include "GraphicsTypes.h"
39 #include "Length.h"
40 #include "LineClampValue.h"
41 #include "RenderStyleConstants.h"
42 #include "SVGRenderStyleDefs.h"
43 #include "TextFlags.h"
44 #include "ThemeTypes.h"
45 #include "TouchAction.h"
46 #include "UnicodeBidi.h"
47 #include "WritingMode.h"
48 #include <wtf/MathExtras.h>
49 #include <wtf/OptionSet.h>
50
51 #if ENABLE(CSS_IMAGE_ORIENTATION)
52 #include "ImageOrientation.h"
53 #endif
54
55 namespace WebCore {
56
57 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(short i)
58     : CSSValue(PrimitiveClass)
59 {
60     m_primitiveUnitType = CSS_NUMBER;
61     m_value.num = static_cast<double>(i);
62 }
63
64 template<> inline CSSPrimitiveValue::operator short() const
65 {
66     if (m_primitiveUnitType == CSS_NUMBER)
67         return clampTo<short>(m_value.num);
68
69     ASSERT_NOT_REACHED();
70     return 0;
71 }
72
73 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(unsigned short i)
74     : CSSValue(PrimitiveClass)
75 {
76     m_primitiveUnitType = CSS_NUMBER;
77     m_value.num = static_cast<double>(i);
78 }
79
80 template<> inline CSSPrimitiveValue::operator unsigned short() const
81 {
82     if (primitiveType() == CSS_NUMBER)
83         return value<unsigned short>();
84
85     ASSERT_NOT_REACHED();
86     return 0;
87 }
88
89 template<> inline CSSPrimitiveValue::operator int() const
90 {
91     if (primitiveType() == CSS_NUMBER)
92         return value<int>();
93
94     ASSERT_NOT_REACHED();
95     return 0;
96 }
97
98 template<> inline CSSPrimitiveValue::operator unsigned() const
99 {
100     if (primitiveType() == CSS_NUMBER)
101         return value<unsigned>();
102
103     ASSERT_NOT_REACHED();
104     return 0;
105 }
106
107
108 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(float i)
109     : CSSValue(PrimitiveClass)
110 {
111     m_primitiveUnitType = CSS_NUMBER;
112     m_value.num = static_cast<double>(i);
113 }
114
115 template<> inline CSSPrimitiveValue::operator float() const
116 {
117     if (primitiveType() == CSS_NUMBER)
118         return value<float>();
119
120     ASSERT_NOT_REACHED();
121     return 0.0f;
122 }
123
124 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LineClampValue i)
125     : CSSValue(PrimitiveClass)
126 {
127     m_primitiveUnitType = i.isPercentage() ? CSS_PERCENTAGE : CSS_NUMBER;
128     m_value.num = static_cast<double>(i.value());
129 }
130
131 template<> inline CSSPrimitiveValue::operator LineClampValue() const
132 {
133     if (primitiveType() == CSS_NUMBER)
134         return LineClampValue(value<int>(), LineClamp::LineCount);
135
136     if (primitiveType() == CSS_PERCENTAGE)
137         return LineClampValue(value<int>(), LineClamp::Percentage);
138
139     ASSERT_NOT_REACHED();
140     return LineClampValue();
141 }
142
143 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(CSSReflectionDirection e)
144     : CSSValue(PrimitiveClass)
145 {
146     m_primitiveUnitType = CSS_VALUE_ID;
147     switch (e) {
148     case ReflectionAbove:
149         m_value.valueID = CSSValueAbove;
150         break;
151     case ReflectionBelow:
152         m_value.valueID = CSSValueBelow;
153         break;
154     case ReflectionLeft:
155         m_value.valueID = CSSValueLeft;
156         break;
157     case ReflectionRight:
158         m_value.valueID = CSSValueRight;
159     }
160 }
161
162 template<> inline CSSPrimitiveValue::operator CSSReflectionDirection() const
163 {
164     ASSERT(isValueID());
165
166     switch (m_value.valueID) {
167     case CSSValueAbove:
168         return ReflectionAbove;
169     case CSSValueBelow:
170         return ReflectionBelow;
171     case CSSValueLeft:
172         return ReflectionLeft;
173     case CSSValueRight:
174         return ReflectionRight;
175     default:
176         break;
177     }
178
179     ASSERT_NOT_REACHED();
180     return ReflectionBelow;
181 }
182
183 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ColumnFill columnFill)
184     : CSSValue(PrimitiveClass)
185 {
186     m_primitiveUnitType = CSS_VALUE_ID;
187     switch (columnFill) {
188     case ColumnFill::Auto:
189         m_value.valueID = CSSValueAuto;
190         break;
191     case ColumnFill::Balance:
192         m_value.valueID = CSSValueBalance;
193         break;
194     }
195 }
196
197 template<> inline CSSPrimitiveValue::operator ColumnFill() const
198 {
199     if (m_primitiveUnitType == CSS_VALUE_ID) {
200         if (m_value.valueID == CSSValueBalance)
201             return ColumnFill::Balance;
202         if (m_value.valueID == CSSValueAuto)
203             return ColumnFill::Auto;
204     }
205     ASSERT_NOT_REACHED();
206     return ColumnFill::Balance;
207 }
208
209 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ColumnSpan columnSpan)
210     : CSSValue(PrimitiveClass)
211 {
212     m_primitiveUnitType = CSS_VALUE_ID;
213     switch (columnSpan) {
214     case ColumnSpan::All:
215         m_value.valueID = CSSValueAll;
216         break;
217     case ColumnSpan::None:
218         m_value.valueID = CSSValueNone;
219         break;
220     }
221 }
222
223 template<> inline CSSPrimitiveValue::operator ColumnSpan() const
224 {
225     // Map 1 to none for compatibility reasons.
226     if (m_primitiveUnitType == CSS_NUMBER && m_value.num == 1)
227         return ColumnSpan::None;
228
229     ASSERT(isValueID());
230
231     switch (m_value.valueID) {
232     case CSSValueAll:
233         return ColumnSpan::All;
234     case CSSValueNone:
235         return ColumnSpan::None;
236     default:
237         break;
238     }
239
240     ASSERT_NOT_REACHED();
241     return ColumnSpan::None;
242 }
243
244
245 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(PrintColorAdjust value)
246     : CSSValue(PrimitiveClass)
247 {
248     m_primitiveUnitType = CSS_VALUE_ID;
249     switch (value) {
250     case PrintColorAdjust::Exact:
251         m_value.valueID = CSSValueExact;
252         break;
253     case PrintColorAdjust::Economy:
254         m_value.valueID = CSSValueEconomy;
255         break;
256     }
257 }
258
259 template<> inline CSSPrimitiveValue::operator PrintColorAdjust() const
260 {
261     ASSERT(isValueID());
262
263     switch (m_value.valueID) {
264     case CSSValueEconomy:
265         return PrintColorAdjust::Economy;
266     case CSSValueExact:
267         return PrintColorAdjust::Exact;
268     default:
269         break;
270     }
271
272     ASSERT_NOT_REACHED();
273     return PrintColorAdjust::Economy;
274 }
275
276
277 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(BorderStyle e)
278     : CSSValue(PrimitiveClass)
279 {
280     m_primitiveUnitType = CSS_VALUE_ID;
281     switch (e) {
282     case BorderStyle::None:
283         m_value.valueID = CSSValueNone;
284         break;
285     case BorderStyle::Hidden:
286         m_value.valueID = CSSValueHidden;
287         break;
288     case BorderStyle::Inset:
289         m_value.valueID = CSSValueInset;
290         break;
291     case BorderStyle::Groove:
292         m_value.valueID = CSSValueGroove;
293         break;
294     case BorderStyle::Ridge:
295         m_value.valueID = CSSValueRidge;
296         break;
297     case BorderStyle::Outset:
298         m_value.valueID = CSSValueOutset;
299         break;
300     case BorderStyle::Dotted:
301         m_value.valueID = CSSValueDotted;
302         break;
303     case BorderStyle::Dashed:
304         m_value.valueID = CSSValueDashed;
305         break;
306     case BorderStyle::Solid:
307         m_value.valueID = CSSValueSolid;
308         break;
309     case BorderStyle::Double:
310         m_value.valueID = CSSValueDouble;
311         break;
312     }
313 }
314
315 template<> inline CSSPrimitiveValue::operator BorderStyle() const
316 {
317     ASSERT(isValueID());
318
319     if (m_value.valueID == CSSValueAuto) // Valid for CSS outline-style
320         return BorderStyle::Dotted;
321     return static_cast<BorderStyle>(m_value.valueID - CSSValueNone);
322 }
323
324 template<> inline CSSPrimitiveValue::operator OutlineIsAuto() const
325 {
326     ASSERT(isValueID());
327
328     if (m_value.valueID == CSSValueAuto)
329         return OutlineIsAuto::On;
330     return OutlineIsAuto::Off;
331 }
332
333 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(CompositeOperator e)
334     : CSSValue(PrimitiveClass)
335 {
336     m_primitiveUnitType = CSS_VALUE_ID;
337     switch (e) {
338     case CompositeClear:
339         m_value.valueID = CSSValueClear;
340         break;
341     case CompositeCopy:
342         m_value.valueID = CSSValueCopy;
343         break;
344     case CompositeSourceOver:
345         m_value.valueID = CSSValueSourceOver;
346         break;
347     case CompositeSourceIn:
348         m_value.valueID = CSSValueSourceIn;
349         break;
350     case CompositeSourceOut:
351         m_value.valueID = CSSValueSourceOut;
352         break;
353     case CompositeSourceAtop:
354         m_value.valueID = CSSValueSourceAtop;
355         break;
356     case CompositeDestinationOver:
357         m_value.valueID = CSSValueDestinationOver;
358         break;
359     case CompositeDestinationIn:
360         m_value.valueID = CSSValueDestinationIn;
361         break;
362     case CompositeDestinationOut:
363         m_value.valueID = CSSValueDestinationOut;
364         break;
365     case CompositeDestinationAtop:
366         m_value.valueID = CSSValueDestinationAtop;
367         break;
368     case CompositeXOR:
369         m_value.valueID = CSSValueXor;
370         break;
371     case CompositePlusDarker:
372         m_value.valueID = CSSValuePlusDarker;
373         break;
374     case CompositePlusLighter:
375         m_value.valueID = CSSValuePlusLighter;
376         break;
377     case CompositeDifference:
378         ASSERT_NOT_REACHED();
379         break;
380     }
381 }
382
383 template<> inline CSSPrimitiveValue::operator CompositeOperator() const
384 {
385     ASSERT(isValueID());
386
387     switch (m_value.valueID) {
388     case CSSValueClear:
389         return CompositeClear;
390     case CSSValueCopy:
391         return CompositeCopy;
392     case CSSValueSourceOver:
393         return CompositeSourceOver;
394     case CSSValueSourceIn:
395         return CompositeSourceIn;
396     case CSSValueSourceOut:
397         return CompositeSourceOut;
398     case CSSValueSourceAtop:
399         return CompositeSourceAtop;
400     case CSSValueDestinationOver:
401         return CompositeDestinationOver;
402     case CSSValueDestinationIn:
403         return CompositeDestinationIn;
404     case CSSValueDestinationOut:
405         return CompositeDestinationOut;
406     case CSSValueDestinationAtop:
407         return CompositeDestinationAtop;
408     case CSSValueXor:
409         return CompositeXOR;
410     case CSSValuePlusDarker:
411         return CompositePlusDarker;
412     case CSSValuePlusLighter:
413         return CompositePlusLighter;
414     default:
415         break;
416     }
417
418     ASSERT_NOT_REACHED();
419     return CompositeClear;
420 }
421
422 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ControlPart e)
423     : CSSValue(PrimitiveClass)
424 {
425     m_primitiveUnitType = CSS_VALUE_ID;
426     switch (e) {
427     case NoControlPart:
428         m_value.valueID = CSSValueNone;
429         break;
430     case CheckboxPart:
431         m_value.valueID = CSSValueCheckbox;
432         break;
433     case RadioPart:
434         m_value.valueID = CSSValueRadio;
435         break;
436     case PushButtonPart:
437         m_value.valueID = CSSValuePushButton;
438         break;
439     case SquareButtonPart:
440         m_value.valueID = CSSValueSquareButton;
441         break;
442     case ButtonPart:
443         m_value.valueID = CSSValueButton;
444         break;
445     case ButtonBevelPart:
446         m_value.valueID = CSSValueButtonBevel;
447         break;
448     case DefaultButtonPart:
449         m_value.valueID = CSSValueDefaultButton;
450         break;
451     case InnerSpinButtonPart:
452         m_value.valueID = CSSValueInnerSpinButton;
453         break;
454     case ListboxPart:
455         m_value.valueID = CSSValueListbox;
456         break;
457     case ListItemPart:
458         m_value.valueID = CSSValueListitem;
459         break;
460     case MediaEnterFullscreenButtonPart:
461         m_value.valueID = CSSValueMediaEnterFullscreenButton;
462         break;
463     case MediaExitFullscreenButtonPart:
464         m_value.valueID = CSSValueMediaExitFullscreenButton;
465         break;
466     case MediaPlayButtonPart:
467         m_value.valueID = CSSValueMediaPlayButton;
468         break;
469     case MediaOverlayPlayButtonPart:
470         m_value.valueID = CSSValueMediaOverlayPlayButton;
471         break;
472     case MediaMuteButtonPart:
473         m_value.valueID = CSSValueMediaMuteButton;
474         break;
475     case MediaSeekBackButtonPart:
476         m_value.valueID = CSSValueMediaSeekBackButton;
477         break;
478     case MediaSeekForwardButtonPart:
479         m_value.valueID = CSSValueMediaSeekForwardButton;
480         break;
481     case MediaRewindButtonPart:
482         m_value.valueID = CSSValueMediaRewindButton;
483         break;
484     case MediaReturnToRealtimeButtonPart:
485         m_value.valueID = CSSValueMediaReturnToRealtimeButton;
486         break;
487     case MediaToggleClosedCaptionsButtonPart:
488         m_value.valueID = CSSValueMediaToggleClosedCaptionsButton;
489         break;
490     case MediaSliderPart:
491         m_value.valueID = CSSValueMediaSlider;
492         break;
493     case MediaSliderThumbPart:
494         m_value.valueID = CSSValueMediaSliderthumb;
495         break;
496     case MediaVolumeSliderContainerPart:
497         m_value.valueID = CSSValueMediaVolumeSliderContainer;
498         break;
499     case MediaVolumeSliderPart:
500         m_value.valueID = CSSValueMediaVolumeSlider;
501         break;
502     case MediaVolumeSliderMuteButtonPart:
503         m_value.valueID = CSSValueMediaVolumeSliderMuteButton;
504         break;
505     case MediaVolumeSliderThumbPart:
506         m_value.valueID = CSSValueMediaVolumeSliderthumb;
507         break;
508     case MediaControlsBackgroundPart:
509         m_value.valueID = CSSValueMediaControlsBackground;
510         break;
511     case MediaControlsFullscreenBackgroundPart:
512         m_value.valueID = CSSValueMediaControlsFullscreenBackground;
513         break;
514     case MediaFullScreenVolumeSliderPart:
515         m_value.valueID = CSSValueMediaFullscreenVolumeSlider;
516         break;
517     case MediaFullScreenVolumeSliderThumbPart:
518         m_value.valueID = CSSValueMediaFullscreenVolumeSliderThumb;
519         break;
520     case MediaCurrentTimePart:
521         m_value.valueID = CSSValueMediaCurrentTimeDisplay;
522         break;
523     case MediaTimeRemainingPart:
524         m_value.valueID = CSSValueMediaTimeRemainingDisplay;
525         break;
526     case MediaControlsLightBarBackgroundPart:
527         m_value.valueID = CSSValueMediaControlsLightBarBackground;
528         break;
529     case MediaControlsDarkBarBackgroundPart:
530         m_value.valueID = CSSValueMediaControlsDarkBarBackground;
531         break;
532     case MenulistPart:
533         m_value.valueID = CSSValueMenulist;
534         break;
535     case MenulistButtonPart:
536         m_value.valueID = CSSValueMenulistButton;
537         break;
538     case MenulistTextPart:
539         m_value.valueID = CSSValueMenulistText;
540         break;
541     case MenulistTextFieldPart:
542         m_value.valueID = CSSValueMenulistTextfield;
543         break;
544     case MeterPart:
545         m_value.valueID = CSSValueMeter;
546         break;
547     case RelevancyLevelIndicatorPart:
548         m_value.valueID = CSSValueRelevancyLevelIndicator;
549         break;
550     case ContinuousCapacityLevelIndicatorPart:
551         m_value.valueID = CSSValueContinuousCapacityLevelIndicator;
552         break;
553     case DiscreteCapacityLevelIndicatorPart:
554         m_value.valueID = CSSValueDiscreteCapacityLevelIndicator;
555         break;
556     case RatingLevelIndicatorPart:
557         m_value.valueID = CSSValueRatingLevelIndicator;
558         break;
559     case ProgressBarPart:
560         m_value.valueID = CSSValueProgressBar;
561         break;
562     case ProgressBarValuePart:
563         m_value.valueID = CSSValueProgressBarValue;
564         break;
565     case SliderHorizontalPart:
566         m_value.valueID = CSSValueSliderHorizontal;
567         break;
568     case SliderVerticalPart:
569         m_value.valueID = CSSValueSliderVertical;
570         break;
571     case SliderThumbHorizontalPart:
572         m_value.valueID = CSSValueSliderthumbHorizontal;
573         break;
574     case SliderThumbVerticalPart:
575         m_value.valueID = CSSValueSliderthumbVertical;
576         break;
577     case CaretPart:
578         m_value.valueID = CSSValueCaret;
579         break;
580     case SearchFieldPart:
581         m_value.valueID = CSSValueSearchfield;
582         break;
583     case SearchFieldDecorationPart:
584         m_value.valueID = CSSValueSearchfieldDecoration;
585         break;
586     case SearchFieldResultsDecorationPart:
587         m_value.valueID = CSSValueSearchfieldResultsDecoration;
588         break;
589     case SearchFieldResultsButtonPart:
590         m_value.valueID = CSSValueSearchfieldResultsButton;
591         break;
592     case SearchFieldCancelButtonPart:
593         m_value.valueID = CSSValueSearchfieldCancelButton;
594         break;
595     case SnapshottedPluginOverlayPart:
596         m_value.valueID = CSSValueSnapshottedPluginOverlay;
597         break;
598     case TextFieldPart:
599         m_value.valueID = CSSValueTextfield;
600         break;
601     case TextAreaPart:
602         m_value.valueID = CSSValueTextarea;
603         break;
604     case CapsLockIndicatorPart:
605         m_value.valueID = CSSValueCapsLockIndicator;
606         break;
607 #if ENABLE(ATTACHMENT_ELEMENT)
608     case AttachmentPart:
609         m_value.valueID = CSSValueAttachment;
610         break;
611     case BorderlessAttachmentPart:
612         m_value.valueID = CSSValueBorderlessAttachment;
613         break;
614 #endif
615 #if ENABLE(SERVICE_CONTROLS)
616     case ImageControlsButtonPart:
617         m_value.valueID = CSSValueImageControlsButton;
618         break;
619 #endif
620 #if ENABLE(APPLE_PAY)
621     case ApplePayButtonPart:
622         m_value.valueID = CSSValueApplePayButton;
623         break;
624 #endif
625 #if ENABLE(INPUT_TYPE_COLOR)
626     case ColorWellPart:
627         m_value.valueID = CSSValueColorWell;
628         break;
629 #endif
630 #if ENABLE(DATALIST_ELEMENT)
631     case ListButtonPart:
632         m_value.valueID = CSSValueListButton;
633         break;
634 #endif
635     }
636 }
637
638 template<> inline CSSPrimitiveValue::operator ControlPart() const
639 {
640     ASSERT(isValueID());
641
642     if (m_value.valueID == CSSValueNone)
643         return NoControlPart;
644     return ControlPart(m_value.valueID - CSSValueCheckbox + 1);
645 }
646
647 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(BackfaceVisibility e)
648     : CSSValue(PrimitiveClass)
649 {
650     m_primitiveUnitType = CSS_VALUE_ID;
651     switch (e) {
652     case BackfaceVisibility::Visible:
653         m_value.valueID = CSSValueVisible;
654         break;
655     case BackfaceVisibility::Hidden:
656         m_value.valueID = CSSValueHidden;
657         break;
658     }
659 }
660
661 template<> inline CSSPrimitiveValue::operator BackfaceVisibility() const
662 {
663     ASSERT(isValueID());
664
665     switch (m_value.valueID) {
666     case CSSValueVisible:
667         return BackfaceVisibility::Visible;
668     case CSSValueHidden:
669         return BackfaceVisibility::Hidden;
670     default:
671         break;
672     }
673
674     ASSERT_NOT_REACHED();
675     return BackfaceVisibility::Hidden;
676 }
677
678
679 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FillAttachment e)
680     : CSSValue(PrimitiveClass)
681 {
682     m_primitiveUnitType = CSS_VALUE_ID;
683     switch (e) {
684     case FillAttachment::ScrollBackground:
685         m_value.valueID = CSSValueScroll;
686         break;
687     case FillAttachment::LocalBackground:
688         m_value.valueID = CSSValueLocal;
689         break;
690     case FillAttachment::FixedBackground:
691         m_value.valueID = CSSValueFixed;
692         break;
693     }
694 }
695
696 template<> inline CSSPrimitiveValue::operator FillAttachment() const
697 {
698     ASSERT(isValueID());
699
700     switch (m_value.valueID) {
701     case CSSValueScroll:
702         return FillAttachment::ScrollBackground;
703     case CSSValueLocal:
704         return FillAttachment::LocalBackground;
705     case CSSValueFixed:
706         return FillAttachment::FixedBackground;
707     default:
708         break;
709     }
710
711     ASSERT_NOT_REACHED();
712     return FillAttachment::ScrollBackground;
713 }
714
715 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FillBox e)
716     : CSSValue(PrimitiveClass)
717 {
718     m_primitiveUnitType = CSS_VALUE_ID;
719     switch (e) {
720     case FillBox::Border:
721         m_value.valueID = CSSValueBorderBox;
722         break;
723     case FillBox::Padding:
724         m_value.valueID = CSSValuePaddingBox;
725         break;
726     case FillBox::Content:
727         m_value.valueID = CSSValueContentBox;
728         break;
729     case FillBox::Text:
730         m_value.valueID = CSSValueText;
731         break;
732     }
733 }
734
735 template<> inline CSSPrimitiveValue::operator FillBox() const
736 {
737     ASSERT(isValueID());
738
739     switch (m_value.valueID) {
740     case CSSValueBorder:
741     case CSSValueBorderBox:
742         return FillBox::Border;
743     case CSSValuePadding:
744     case CSSValuePaddingBox:
745         return FillBox::Padding;
746     case CSSValueContent:
747     case CSSValueContentBox:
748         return FillBox::Content;
749     case CSSValueText:
750     case CSSValueWebkitText:
751         return FillBox::Text;
752     default:
753         break;
754     }
755
756     ASSERT_NOT_REACHED();
757     return FillBox::Border;
758 }
759
760 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FillRepeat e)
761     : CSSValue(PrimitiveClass)
762 {
763     m_primitiveUnitType = CSS_VALUE_ID;
764     switch (e) {
765     case FillRepeat::Repeat:
766         m_value.valueID = CSSValueRepeat;
767         break;
768     case FillRepeat::NoRepeat:
769         m_value.valueID = CSSValueNoRepeat;
770         break;
771     case FillRepeat::Round:
772         m_value.valueID = CSSValueRound;
773         break;
774     case FillRepeat::Space:
775         m_value.valueID = CSSValueSpace;
776         break;
777     }
778 }
779
780 template<> inline CSSPrimitiveValue::operator FillRepeat() const
781 {
782     ASSERT(isValueID());
783
784     switch (m_value.valueID) {
785     case CSSValueRepeat:
786         return FillRepeat::Repeat;
787     case CSSValueNoRepeat:
788         return FillRepeat::NoRepeat;
789     case CSSValueRound:
790         return FillRepeat::Round;
791     case CSSValueSpace:
792         return FillRepeat::Space;
793     default:
794         break;
795     }
796
797     ASSERT_NOT_REACHED();
798     return FillRepeat::Repeat;
799 }
800
801 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(BoxPack e)
802     : CSSValue(PrimitiveClass)
803 {
804     m_primitiveUnitType = CSS_VALUE_ID;
805     switch (e) {
806     case BoxPack::Start:
807         m_value.valueID = CSSValueStart;
808         break;
809     case BoxPack::Center:
810         m_value.valueID = CSSValueCenter;
811         break;
812     case BoxPack::End:
813         m_value.valueID = CSSValueEnd;
814         break;
815     case BoxPack::Justify:
816         m_value.valueID = CSSValueJustify;
817         break;
818     }
819 }
820
821 template<> inline CSSPrimitiveValue::operator BoxPack() const
822 {
823     ASSERT(isValueID());
824
825     switch (m_value.valueID) {
826     case CSSValueStart:
827         return BoxPack::Start;
828     case CSSValueEnd:
829         return BoxPack::End;
830     case CSSValueCenter:
831         return BoxPack::Center;
832     case CSSValueJustify:
833         return BoxPack::Justify;
834     default:
835         break;
836     }
837
838     ASSERT_NOT_REACHED();
839     return BoxPack::Justify;
840 }
841
842 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(BoxAlignment e)
843     : CSSValue(PrimitiveClass)
844 {
845     m_primitiveUnitType = CSS_VALUE_ID;
846     switch (e) {
847     case BoxAlignment::Stretch:
848         m_value.valueID = CSSValueStretch;
849         break;
850     case BoxAlignment::Start:
851         m_value.valueID = CSSValueStart;
852         break;
853     case BoxAlignment::Center:
854         m_value.valueID = CSSValueCenter;
855         break;
856     case BoxAlignment::End:
857         m_value.valueID = CSSValueEnd;
858         break;
859     case BoxAlignment::Baseline:
860         m_value.valueID = CSSValueBaseline;
861         break;
862     }
863 }
864
865 template<> inline CSSPrimitiveValue::operator BoxAlignment() const
866 {
867     ASSERT(isValueID());
868
869     switch (m_value.valueID) {
870     case CSSValueStretch:
871         return BoxAlignment::Stretch;
872     case CSSValueStart:
873         return BoxAlignment::Start;
874     case CSSValueEnd:
875         return BoxAlignment::End;
876     case CSSValueCenter:
877         return BoxAlignment::Center;
878     case CSSValueBaseline:
879         return BoxAlignment::Baseline;
880     default:
881         break;
882     }
883
884     ASSERT_NOT_REACHED();
885     return BoxAlignment::Stretch;
886 }
887
888 #if ENABLE(CSS_BOX_DECORATION_BREAK)
889 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(BoxDecorationBreak e)
890     : CSSValue(PrimitiveClass)
891 {
892     m_primitiveUnitType = CSS_VALUE_ID;
893     switch (e) {
894     case BoxDecorationBreak::Slice:
895         m_value.valueID = CSSValueSlice;
896         break;
897     case BoxDecorationBreak::Clone:
898         m_value.valueID = CSSValueClone;
899         break;
900     }
901 }
902
903 template<> inline CSSPrimitiveValue::operator BoxDecorationBreak() const
904 {
905     ASSERT(isValueID());
906
907     switch (m_value.valueID) {
908     case CSSValueSlice:
909         return BoxDecorationBreak::Slice;
910     case CSSValueClone:
911         return BoxDecorationBreak::Clone;
912     default:
913         break;
914     }
915
916     ASSERT_NOT_REACHED();
917     return BoxDecorationBreak::Slice;
918 }
919 #endif
920
921 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(Edge e)
922     : CSSValue(PrimitiveClass)
923 {
924     m_primitiveUnitType = CSS_VALUE_ID;
925     switch (e) {
926     case Edge::Top:
927         m_value.valueID = CSSValueTop;
928         break;
929     case Edge::Right:
930         m_value.valueID = CSSValueRight;
931         break;
932     case Edge::Bottom:
933         m_value.valueID = CSSValueBottom;
934         break;
935     case Edge::Left:
936         m_value.valueID = CSSValueLeft;
937         break;
938     }
939 }
940
941 template<> inline CSSPrimitiveValue::operator Edge() const
942 {
943     ASSERT(isValueID());
944
945     switch (m_value.valueID) {
946     case CSSValueTop:
947         return Edge::Top;
948     case CSSValueRight:
949         return Edge::Right;
950     case CSSValueBottom:
951         return Edge::Bottom;
952     case CSSValueLeft:
953         return Edge::Left;
954     default:
955         break;
956     }
957
958     ASSERT_NOT_REACHED();
959     return Edge::Top;
960 }
961
962 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(BoxSizing e)
963     : CSSValue(PrimitiveClass)
964 {
965     m_primitiveUnitType = CSS_VALUE_ID;
966     switch (e) {
967     case BoxSizing::BorderBox:
968         m_value.valueID = CSSValueBorderBox;
969         break;
970     case BoxSizing::ContentBox:
971         m_value.valueID = CSSValueContentBox;
972         break;
973     }
974 }
975
976 template<> inline CSSPrimitiveValue::operator BoxSizing() const
977 {
978     ASSERT(isValueID());
979
980     switch (m_value.valueID) {
981     case CSSValueBorderBox:
982         return BoxSizing::BorderBox;
983     case CSSValueContentBox:
984         return BoxSizing::ContentBox;
985     default:
986         break;
987     }
988
989     ASSERT_NOT_REACHED();
990     return BoxSizing::BorderBox;
991 }
992
993 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(BoxDirection e)
994     : CSSValue(PrimitiveClass)
995 {
996     m_primitiveUnitType = CSS_VALUE_ID;
997     switch (e) {
998     case BoxDirection::Normal:
999         m_value.valueID = CSSValueNormal;
1000         break;
1001     case BoxDirection::Reverse:
1002         m_value.valueID = CSSValueReverse;
1003         break;
1004     }
1005 }
1006
1007 template<> inline CSSPrimitiveValue::operator BoxDirection() const
1008 {
1009     ASSERT(isValueID());
1010
1011     switch (m_value.valueID) {
1012     case CSSValueNormal:
1013         return BoxDirection::Normal;
1014     case CSSValueReverse:
1015         return BoxDirection::Reverse;
1016     default:
1017         break;
1018     }
1019
1020     ASSERT_NOT_REACHED();
1021     return BoxDirection::Normal;
1022 }
1023
1024 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(BoxLines e)
1025     : CSSValue(PrimitiveClass)
1026 {
1027     m_primitiveUnitType = CSS_VALUE_ID;
1028     switch (e) {
1029     case BoxLines::Single:
1030         m_value.valueID = CSSValueSingle;
1031         break;
1032     case BoxLines::Multiple:
1033         m_value.valueID = CSSValueMultiple;
1034         break;
1035     }
1036 }
1037
1038 template<> inline CSSPrimitiveValue::operator BoxLines() const
1039 {
1040     ASSERT(isValueID());
1041
1042     switch (m_value.valueID) {
1043     case CSSValueSingle:
1044         return BoxLines::Single;
1045     case CSSValueMultiple:
1046         return BoxLines::Multiple;
1047     default:
1048         break;
1049     }
1050
1051     ASSERT_NOT_REACHED();
1052     return BoxLines::Single;
1053 }
1054
1055 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(BoxOrient e)
1056     : CSSValue(PrimitiveClass)
1057 {
1058     m_primitiveUnitType = CSS_VALUE_ID;
1059     switch (e) {
1060     case BoxOrient::Horizontal:
1061         m_value.valueID = CSSValueHorizontal;
1062         break;
1063     case BoxOrient::Vertical:
1064         m_value.valueID = CSSValueVertical;
1065         break;
1066     }
1067 }
1068
1069 template<> inline CSSPrimitiveValue::operator BoxOrient() const
1070 {
1071     ASSERT(isValueID());
1072
1073     switch (m_value.valueID) {
1074     case CSSValueHorizontal:
1075     case CSSValueInlineAxis:
1076         return BoxOrient::Horizontal;
1077     case CSSValueVertical:
1078     case CSSValueBlockAxis:
1079         return BoxOrient::Vertical;
1080     default:
1081         break;
1082     }
1083
1084     ASSERT_NOT_REACHED();
1085     return BoxOrient::Horizontal;
1086 }
1087
1088 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(CaptionSide e)
1089     : CSSValue(PrimitiveClass)
1090 {
1091     m_primitiveUnitType = CSS_VALUE_ID;
1092     switch (e) {
1093     case CaptionSide::Left:
1094         m_value.valueID = CSSValueLeft;
1095         break;
1096     case CaptionSide::Right:
1097         m_value.valueID = CSSValueRight;
1098         break;
1099     case CaptionSide::Top:
1100         m_value.valueID = CSSValueTop;
1101         break;
1102     case CaptionSide::Bottom:
1103         m_value.valueID = CSSValueBottom;
1104         break;
1105     }
1106 }
1107
1108 template<> inline CSSPrimitiveValue::operator CaptionSide() const
1109 {
1110     ASSERT(isValueID());
1111
1112     switch (m_value.valueID) {
1113     case CSSValueLeft:
1114         return CaptionSide::Left;
1115     case CSSValueRight:
1116         return CaptionSide::Right;
1117     case CSSValueTop:
1118         return CaptionSide::Top;
1119     case CSSValueBottom:
1120         return CaptionSide::Bottom;
1121     default:
1122         break;
1123     }
1124
1125     ASSERT_NOT_REACHED();
1126     return CaptionSide::Top;
1127 }
1128
1129 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(Clear e)
1130     : CSSValue(PrimitiveClass)
1131 {
1132     m_primitiveUnitType = CSS_VALUE_ID;
1133     switch (e) {
1134     case Clear::None:
1135         m_value.valueID = CSSValueNone;
1136         break;
1137     case Clear::Left:
1138         m_value.valueID = CSSValueLeft;
1139         break;
1140     case Clear::Right:
1141         m_value.valueID = CSSValueRight;
1142         break;
1143     case Clear::Both:
1144         m_value.valueID = CSSValueBoth;
1145         break;
1146     }
1147 }
1148
1149 template<> inline CSSPrimitiveValue::operator Clear() const
1150 {
1151     ASSERT(isValueID());
1152
1153     switch (m_value.valueID) {
1154     case CSSValueNone:
1155         return Clear::None;
1156     case CSSValueLeft:
1157         return Clear::Left;
1158     case CSSValueRight:
1159         return Clear::Right;
1160     case CSSValueBoth:
1161         return Clear::Both;
1162     default:
1163         break;
1164     }
1165
1166     ASSERT_NOT_REACHED();
1167     return Clear::None;
1168 }
1169
1170 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(CursorType e)
1171     : CSSValue(PrimitiveClass)
1172 {
1173     m_primitiveUnitType = CSS_VALUE_ID;
1174     switch (e) {
1175     case CursorType::Auto:
1176         m_value.valueID = CSSValueAuto;
1177         break;
1178     case CursorType::Default:
1179         m_value.valueID = CSSValueDefault;
1180         break;
1181     case CursorType::None:
1182         m_value.valueID = CSSValueNone;
1183         break;
1184     case CursorType::ContextMenu:
1185         m_value.valueID = CSSValueContextMenu;
1186         break;
1187     case CursorType::Help:
1188         m_value.valueID = CSSValueHelp;
1189         break;
1190     case CursorType::Pointer:
1191         m_value.valueID = CSSValuePointer;
1192         break;
1193     case CursorType::Progress:
1194         m_value.valueID = CSSValueProgress;
1195         break;
1196     case CursorType::Wait:
1197         m_value.valueID = CSSValueWait;
1198         break;
1199     case CursorType::Cell:
1200         m_value.valueID = CSSValueCell;
1201         break;
1202     case CursorType::Crosshair:
1203         m_value.valueID = CSSValueCrosshair;
1204         break;
1205     case CursorType::Text:
1206         m_value.valueID = CSSValueText;
1207         break;
1208     case CursorType::VerticalText:
1209         m_value.valueID = CSSValueVerticalText;
1210         break;
1211     case CursorType::Alias:
1212         m_value.valueID = CSSValueAlias;
1213         break;
1214     case CursorType::Copy:
1215         m_value.valueID = CSSValueCopy;
1216         break;
1217     case CursorType::Move:
1218         m_value.valueID = CSSValueMove;
1219         break;
1220     case CursorType::NoDrop:
1221         m_value.valueID = CSSValueNoDrop;
1222         break;
1223     case CursorType::NotAllowed:
1224         m_value.valueID = CSSValueNotAllowed;
1225         break;
1226     case CursorType::Grab:
1227         m_value.valueID = CSSValueGrab;
1228         break;
1229     case CursorType::Grabbing:
1230         m_value.valueID = CSSValueGrabbing;
1231         break;
1232     case CursorType::EResize:
1233         m_value.valueID = CSSValueEResize;
1234         break;
1235     case CursorType::NResize:
1236         m_value.valueID = CSSValueNResize;
1237         break;
1238     case CursorType::NEResize:
1239         m_value.valueID = CSSValueNeResize;
1240         break;
1241     case CursorType::NWResize:
1242         m_value.valueID = CSSValueNwResize;
1243         break;
1244     case CursorType::SResize:
1245         m_value.valueID = CSSValueSResize;
1246         break;
1247     case CursorType::SEResize:
1248         m_value.valueID = CSSValueSeResize;
1249         break;
1250     case CursorType::SWResize:
1251         m_value.valueID = CSSValueSwResize;
1252         break;
1253     case CursorType::WResize:
1254         m_value.valueID = CSSValueWResize;
1255         break;
1256     case CursorType::EWResize:
1257         m_value.valueID = CSSValueEwResize;
1258         break;
1259     case CursorType::NSResize:
1260         m_value.valueID = CSSValueNsResize;
1261         break;
1262     case CursorType::NESWResize:
1263         m_value.valueID = CSSValueNeswResize;
1264         break;
1265     case CursorType::NWSEResize:
1266         m_value.valueID = CSSValueNwseResize;
1267         break;
1268     case CursorType::ColumnResize:
1269         m_value.valueID = CSSValueColResize;
1270         break;
1271     case CursorType::RowResize:
1272         m_value.valueID = CSSValueRowResize;
1273         break;
1274     case CursorType::AllScroll:
1275         m_value.valueID = CSSValueAllScroll;
1276         break;
1277     case CursorType::ZoomIn:
1278         m_value.valueID = CSSValueZoomIn;
1279         break;
1280     case CursorType::ZoomOut:
1281         m_value.valueID = CSSValueZoomOut;
1282         break;
1283     }
1284 }
1285
1286 template<> inline CSSPrimitiveValue::operator CursorType() const
1287 {
1288     ASSERT(isValueID());
1289     switch (m_value.valueID) {
1290     case CSSValueCopy:
1291         return CursorType::Copy;
1292     case CSSValueWebkitGrab:
1293         return CursorType::Grab;
1294     case CSSValueWebkitGrabbing:
1295         return CursorType::Grabbing;
1296     case CSSValueWebkitZoomIn:
1297         return CursorType::ZoomIn;
1298     case CSSValueWebkitZoomOut:
1299         return CursorType::ZoomOut;
1300     case CSSValueNone:
1301         return CursorType::None;
1302     default:
1303         return static_cast<CursorType>(m_value.valueID - CSSValueAuto);
1304     }
1305 }
1306
1307 #if ENABLE(CURSOR_VISIBILITY)
1308 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(CursorVisibility e)
1309     : CSSValue(PrimitiveClass)
1310 {
1311     m_primitiveUnitType = CSS_VALUE_ID;
1312     switch (e) {
1313     case CursorVisibility::Auto:
1314         m_value.valueID = CSSValueAuto;
1315         break;
1316     case CursorVisibility::AutoHide:
1317         m_value.valueID = CSSValueAutoHide;
1318         break;
1319     }
1320 }
1321
1322 template<> inline CSSPrimitiveValue::operator CursorVisibility() const
1323 {
1324     ASSERT(isValueID());
1325
1326     if (m_value.valueID == CSSValueAuto)
1327         return CursorVisibility::Auto;
1328     if (m_value.valueID == CSSValueAutoHide)
1329         return CursorVisibility::AutoHide;
1330
1331     ASSERT_NOT_REACHED();
1332     return CursorVisibility::Auto;
1333 }
1334 #endif
1335
1336 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(DisplayType e)
1337     : CSSValue(PrimitiveClass)
1338 {
1339     m_primitiveUnitType = CSS_VALUE_ID;
1340     switch (e) {
1341     case DisplayType::Inline:
1342         m_value.valueID = CSSValueInline;
1343         break;
1344     case DisplayType::Block:
1345         m_value.valueID = CSSValueBlock;
1346         break;
1347     case DisplayType::ListItem:
1348         m_value.valueID = CSSValueListItem;
1349         break;
1350     case DisplayType::Compact:
1351         m_value.valueID = CSSValueCompact;
1352         break;
1353     case DisplayType::InlineBlock:
1354         m_value.valueID = CSSValueInlineBlock;
1355         break;
1356     case DisplayType::Table:
1357         m_value.valueID = CSSValueTable;
1358         break;
1359     case DisplayType::InlineTable:
1360         m_value.valueID = CSSValueInlineTable;
1361         break;
1362     case DisplayType::TableRowGroup:
1363         m_value.valueID = CSSValueTableRowGroup;
1364         break;
1365     case DisplayType::TableHeaderGroup:
1366         m_value.valueID = CSSValueTableHeaderGroup;
1367         break;
1368     case DisplayType::TableFooterGroup:
1369         m_value.valueID = CSSValueTableFooterGroup;
1370         break;
1371     case DisplayType::TableRow:
1372         m_value.valueID = CSSValueTableRow;
1373         break;
1374     case DisplayType::TableColumnGroup:
1375         m_value.valueID = CSSValueTableColumnGroup;
1376         break;
1377     case DisplayType::TableColumn:
1378         m_value.valueID = CSSValueTableColumn;
1379         break;
1380     case DisplayType::TableCell:
1381         m_value.valueID = CSSValueTableCell;
1382         break;
1383     case DisplayType::TableCaption:
1384         m_value.valueID = CSSValueTableCaption;
1385         break;
1386     case DisplayType::Box:
1387         m_value.valueID = CSSValueWebkitBox;
1388         break;
1389     case DisplayType::InlineBox:
1390         m_value.valueID = CSSValueWebkitInlineBox;
1391         break;
1392     case DisplayType::Flex:
1393     case DisplayType::WebKitFlex:
1394         m_value.valueID = CSSValueFlex;
1395         break;
1396     case DisplayType::InlineFlex:
1397     case DisplayType::WebKitInlineFlex:
1398         m_value.valueID = CSSValueInlineFlex;
1399         break;
1400     case DisplayType::Grid:
1401         m_value.valueID = CSSValueGrid;
1402         break;
1403     case DisplayType::InlineGrid:
1404         m_value.valueID = CSSValueInlineGrid;
1405         break;
1406     case DisplayType::None:
1407         m_value.valueID = CSSValueNone;
1408         break;
1409     case DisplayType::Contents:
1410         m_value.valueID = CSSValueContents;
1411         break;
1412     case DisplayType::FlowRoot:
1413         m_value.valueID = CSSValueFlowRoot;
1414         break;
1415     }
1416 }
1417
1418 template<> inline CSSPrimitiveValue::operator DisplayType() const
1419 {
1420     ASSERT(isValueID());
1421
1422     if (m_value.valueID == CSSValueNone)
1423         return DisplayType::None;
1424
1425     DisplayType display = static_cast<DisplayType>(m_value.valueID - CSSValueInline);
1426     ASSERT(display >= DisplayType::Inline && display <= DisplayType::None);
1427     if (display == DisplayType::WebKitFlex)
1428         return DisplayType::Flex;
1429     if (display == DisplayType::WebKitInlineFlex)
1430         return DisplayType::InlineFlex;
1431     return display;
1432 }
1433
1434 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EmptyCell e)
1435     : CSSValue(PrimitiveClass)
1436 {
1437     m_primitiveUnitType = CSS_VALUE_ID;
1438     switch (e) {
1439     case EmptyCell::Show:
1440         m_value.valueID = CSSValueShow;
1441         break;
1442     case EmptyCell::Hide:
1443         m_value.valueID = CSSValueHide;
1444         break;
1445     }
1446 }
1447
1448 template<> inline CSSPrimitiveValue::operator EmptyCell() const
1449 {
1450     ASSERT(isValueID());
1451
1452     switch (m_value.valueID) {
1453     case CSSValueShow:
1454         return EmptyCell::Show;
1455     case CSSValueHide:
1456         return EmptyCell::Hide;
1457     default:
1458         break;
1459     }
1460
1461     ASSERT_NOT_REACHED();
1462     return EmptyCell::Show;
1463 }
1464
1465 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FlexDirection e)
1466     : CSSValue(PrimitiveClass)
1467 {
1468     m_primitiveUnitType = CSS_VALUE_ID;
1469     switch (e) {
1470     case FlexDirection::Row:
1471         m_value.valueID = CSSValueRow;
1472         break;
1473     case FlexDirection::RowReverse:
1474         m_value.valueID = CSSValueRowReverse;
1475         break;
1476     case FlexDirection::Column:
1477         m_value.valueID = CSSValueColumn;
1478         break;
1479     case FlexDirection::ColumnReverse:
1480         m_value.valueID = CSSValueColumnReverse;
1481         break;
1482     }
1483 }
1484
1485 template<> inline CSSPrimitiveValue::operator FlexDirection() const
1486 {
1487     ASSERT(isValueID());
1488
1489     switch (m_value.valueID) {
1490     case CSSValueRow:
1491         return FlexDirection::Row;
1492     case CSSValueRowReverse:
1493         return FlexDirection::RowReverse;
1494     case CSSValueColumn:
1495         return FlexDirection::Column;
1496     case CSSValueColumnReverse:
1497         return FlexDirection::ColumnReverse;
1498     default:
1499         break;
1500     }
1501
1502     ASSERT_NOT_REACHED();
1503     return FlexDirection::Row;
1504 }
1505
1506 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(AlignContent e)
1507     : CSSValue(PrimitiveClass)
1508 {
1509     m_primitiveUnitType = CSS_VALUE_ID;
1510     switch (e) {
1511     case AlignContent::FlexStart:
1512         m_value.valueID = CSSValueFlexStart;
1513         break;
1514     case AlignContent::FlexEnd:
1515         m_value.valueID = CSSValueFlexEnd;
1516         break;
1517     case AlignContent::Center:
1518         m_value.valueID = CSSValueCenter;
1519         break;
1520     case AlignContent::SpaceBetween:
1521         m_value.valueID = CSSValueSpaceBetween;
1522         break;
1523     case AlignContent::SpaceAround:
1524         m_value.valueID = CSSValueSpaceAround;
1525         break;
1526     case AlignContent::Stretch:
1527         m_value.valueID = CSSValueStretch;
1528         break;
1529     }
1530 }
1531
1532 template<> inline CSSPrimitiveValue::operator AlignContent() const
1533 {
1534     ASSERT(isValueID());
1535
1536     switch (m_value.valueID) {
1537     case CSSValueFlexStart:
1538         return AlignContent::FlexStart;
1539     case CSSValueFlexEnd:
1540         return AlignContent::FlexEnd;
1541     case CSSValueCenter:
1542         return AlignContent::Center;
1543     case CSSValueSpaceBetween:
1544         return AlignContent::SpaceBetween;
1545     case CSSValueSpaceAround:
1546         return AlignContent::SpaceAround;
1547     case CSSValueStretch:
1548         return AlignContent::Stretch;
1549     default:
1550         break;
1551     }
1552
1553     ASSERT_NOT_REACHED();
1554     return AlignContent::Stretch;
1555 }
1556
1557 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FlexWrap e)
1558     : CSSValue(PrimitiveClass)
1559 {
1560     m_primitiveUnitType = CSS_VALUE_ID;
1561     switch (e) {
1562     case FlexWrap::NoWrap:
1563         m_value.valueID = CSSValueNowrap;
1564         break;
1565     case FlexWrap::Wrap:
1566         m_value.valueID = CSSValueWrap;
1567         break;
1568     case FlexWrap::Reverse:
1569         m_value.valueID = CSSValueWrapReverse;
1570         break;
1571     }
1572 }
1573
1574 template<> inline CSSPrimitiveValue::operator FlexWrap() const
1575 {
1576     ASSERT(isValueID());
1577
1578     switch (m_value.valueID) {
1579     case CSSValueNowrap:
1580         return FlexWrap::NoWrap;
1581     case CSSValueWrap:
1582         return FlexWrap::Wrap;
1583     case CSSValueWrapReverse:
1584         return FlexWrap::Reverse;
1585     default:
1586         break;
1587     }
1588
1589     ASSERT_NOT_REACHED();
1590     return FlexWrap::NoWrap;
1591 }
1592
1593 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(Float e)
1594     : CSSValue(PrimitiveClass)
1595 {
1596     m_primitiveUnitType = CSS_VALUE_ID;
1597     switch (e) {
1598     case Float::No:
1599         m_value.valueID = CSSValueNone;
1600         break;
1601     case Float::Left:
1602         m_value.valueID = CSSValueLeft;
1603         break;
1604     case Float::Right:
1605         m_value.valueID = CSSValueRight;
1606         break;
1607     }
1608 }
1609
1610 template<> inline CSSPrimitiveValue::operator Float() const
1611 {
1612     ASSERT(isValueID());
1613
1614     switch (m_value.valueID) {
1615     case CSSValueLeft:
1616         return Float::Left;
1617     case CSSValueRight:
1618         return Float::Right;
1619     case CSSValueNone:
1620     case CSSValueCenter: // Non-standard CSS value.
1621         return Float::No;
1622     default:
1623         break;
1624     }
1625
1626     ASSERT_NOT_REACHED();
1627     return Float::No;
1628 }
1629
1630 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LineBreak e)
1631     : CSSValue(PrimitiveClass)
1632 {
1633     m_primitiveUnitType = CSS_VALUE_ID;
1634     switch (e) {
1635     case LineBreak::Auto:
1636         m_value.valueID = CSSValueAuto;
1637         break;
1638     case LineBreak::Loose:
1639         m_value.valueID = CSSValueLoose;
1640         break;
1641     case LineBreak::Normal:
1642         m_value.valueID = CSSValueNormal;
1643         break;
1644     case LineBreak::Strict:
1645         m_value.valueID = CSSValueStrict;
1646         break;
1647     case LineBreak::AfterWhiteSpace:
1648         m_value.valueID = CSSValueAfterWhiteSpace;
1649         break;
1650     case LineBreak::Anywhere:
1651         m_value.valueID = CSSValueAnywhere;
1652         break;
1653     }
1654 }
1655
1656 template<> inline CSSPrimitiveValue::operator OptionSet<HangingPunctuation>() const
1657 {
1658     ASSERT(isValueID());
1659     
1660     switch (m_value.valueID) {
1661     case CSSValueNone:
1662         return OptionSet<HangingPunctuation> { };
1663     case CSSValueFirst:
1664         return HangingPunctuation::First;
1665     case CSSValueLast:
1666         return HangingPunctuation::Last;
1667     case CSSValueAllowEnd:
1668         return HangingPunctuation::AllowEnd;
1669     case CSSValueForceEnd:
1670         return HangingPunctuation::ForceEnd;
1671     default:
1672         break;
1673     }
1674     
1675     ASSERT_NOT_REACHED();
1676     return OptionSet<HangingPunctuation> { };
1677 }
1678
1679 template<> inline CSSPrimitiveValue::operator LineBreak() const
1680 {
1681     ASSERT(isValueID());
1682
1683     switch (m_value.valueID) {
1684     case CSSValueAuto:
1685         return LineBreak::Auto;
1686     case CSSValueLoose:
1687         return LineBreak::Loose;
1688     case CSSValueNormal:
1689         return LineBreak::Normal;
1690     case CSSValueStrict:
1691         return LineBreak::Strict;
1692     case CSSValueAfterWhiteSpace:
1693         return LineBreak::AfterWhiteSpace;
1694     case CSSValueAnywhere:
1695         return LineBreak::Anywhere;
1696     default:
1697         break;
1698     }
1699
1700     ASSERT_NOT_REACHED();
1701     return LineBreak::Auto;
1702 }
1703
1704 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ListStylePosition e)
1705     : CSSValue(PrimitiveClass)
1706 {
1707     m_primitiveUnitType = CSS_VALUE_ID;
1708     switch (e) {
1709     case ListStylePosition::Outside:
1710         m_value.valueID = CSSValueOutside;
1711         break;
1712     case ListStylePosition::Inside:
1713         m_value.valueID = CSSValueInside;
1714         break;
1715     }
1716 }
1717
1718 template<> inline CSSPrimitiveValue::operator ListStylePosition() const
1719 {
1720     ASSERT(isValueID());
1721
1722     switch (m_value.valueID) {
1723     case CSSValueOutside:
1724         return ListStylePosition::Outside;
1725     case CSSValueInside:
1726         return ListStylePosition::Inside;
1727     default:
1728         break;
1729     }
1730
1731     ASSERT_NOT_REACHED();
1732     return ListStylePosition::Outside;
1733 }
1734
1735 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ListStyleType e)
1736     : CSSValue(PrimitiveClass)
1737 {
1738     m_primitiveUnitType = CSS_VALUE_ID;
1739     switch (e) {
1740     case ListStyleType::Afar:
1741         m_value.valueID = CSSValueAfar;
1742         break;
1743     case ListStyleType::Amharic:
1744         m_value.valueID = CSSValueAmharic;
1745         break;
1746     case ListStyleType::AmharicAbegede:
1747         m_value.valueID = CSSValueAmharicAbegede;
1748         break;
1749     case ListStyleType::ArabicIndic:
1750         m_value.valueID = CSSValueArabicIndic;
1751         break;
1752     case ListStyleType::Armenian:
1753         m_value.valueID = CSSValueArmenian;
1754         break;
1755     case ListStyleType::Asterisks:
1756         m_value.valueID = CSSValueAsterisks;
1757         break;
1758     case ListStyleType::Binary:
1759         m_value.valueID = CSSValueBinary;
1760         break;
1761     case ListStyleType::Bengali:
1762         m_value.valueID = CSSValueBengali;
1763         break;
1764     case ListStyleType::Cambodian:
1765         m_value.valueID = CSSValueCambodian;
1766         break;
1767     case ListStyleType::Circle:
1768         m_value.valueID = CSSValueCircle;
1769         break;
1770     case ListStyleType::CjkEarthlyBranch:
1771         m_value.valueID = CSSValueCjkEarthlyBranch;
1772         break;
1773     case ListStyleType::CjkHeavenlyStem:
1774         m_value.valueID = CSSValueCjkHeavenlyStem;
1775         break;
1776     case ListStyleType::CJKIdeographic:
1777         m_value.valueID = CSSValueCjkIdeographic;
1778         break;
1779     case ListStyleType::DecimalLeadingZero:
1780         m_value.valueID = CSSValueDecimalLeadingZero;
1781         break;
1782     case ListStyleType::Decimal:
1783         m_value.valueID = CSSValueDecimal;
1784         break;
1785     case ListStyleType::Devanagari:
1786         m_value.valueID = CSSValueDevanagari;
1787         break;
1788     case ListStyleType::Disc:
1789         m_value.valueID = CSSValueDisc;
1790         break;
1791     case ListStyleType::Ethiopic:
1792         m_value.valueID = CSSValueEthiopic;
1793         break;
1794     case ListStyleType::EthiopicAbegede:
1795         m_value.valueID = CSSValueEthiopicAbegede;
1796         break;
1797     case ListStyleType::EthiopicAbegedeAmEt:
1798         m_value.valueID = CSSValueEthiopicAbegedeAmEt;
1799         break;
1800     case ListStyleType::EthiopicAbegedeGez:
1801         m_value.valueID = CSSValueEthiopicAbegedeGez;
1802         break;
1803     case ListStyleType::EthiopicAbegedeTiEr:
1804         m_value.valueID = CSSValueEthiopicAbegedeTiEr;
1805         break;
1806     case ListStyleType::EthiopicAbegedeTiEt:
1807         m_value.valueID = CSSValueEthiopicAbegedeTiEt;
1808         break;
1809     case ListStyleType::EthiopicHalehameAaEr:
1810         m_value.valueID = CSSValueEthiopicHalehameAaEr;
1811         break;
1812     case ListStyleType::EthiopicHalehameAaEt:
1813         m_value.valueID = CSSValueEthiopicHalehameAaEt;
1814         break;
1815     case ListStyleType::EthiopicHalehameAmEt:
1816         m_value.valueID = CSSValueEthiopicHalehameAmEt;
1817         break;
1818     case ListStyleType::EthiopicHalehameGez:
1819         m_value.valueID = CSSValueEthiopicHalehameGez;
1820         break;
1821     case ListStyleType::EthiopicHalehameOmEt:
1822         m_value.valueID = CSSValueEthiopicHalehameOmEt;
1823         break;
1824     case ListStyleType::EthiopicHalehameSidEt:
1825         m_value.valueID = CSSValueEthiopicHalehameSidEt;
1826         break;
1827     case ListStyleType::EthiopicHalehameSoEt:
1828         m_value.valueID = CSSValueEthiopicHalehameSoEt;
1829         break;
1830     case ListStyleType::EthiopicHalehameTiEr:
1831         m_value.valueID = CSSValueEthiopicHalehameTiEr;
1832         break;
1833     case ListStyleType::EthiopicHalehameTiEt:
1834         m_value.valueID = CSSValueEthiopicHalehameTiEt;
1835         break;
1836     case ListStyleType::EthiopicHalehameTig:
1837         m_value.valueID = CSSValueEthiopicHalehameTig;
1838         break;
1839     case ListStyleType::Footnotes:
1840         m_value.valueID = CSSValueFootnotes;
1841         break;
1842     case ListStyleType::Georgian:
1843         m_value.valueID = CSSValueGeorgian;
1844         break;
1845     case ListStyleType::Gujarati:
1846         m_value.valueID = CSSValueGujarati;
1847         break;
1848     case ListStyleType::Gurmukhi:
1849         m_value.valueID = CSSValueGurmukhi;
1850         break;
1851     case ListStyleType::Hangul:
1852         m_value.valueID = CSSValueHangul;
1853         break;
1854     case ListStyleType::HangulConsonant:
1855         m_value.valueID = CSSValueHangulConsonant;
1856         break;
1857     case ListStyleType::Hebrew:
1858         m_value.valueID = CSSValueHebrew;
1859         break;
1860     case ListStyleType::Hiragana:
1861         m_value.valueID = CSSValueHiragana;
1862         break;
1863     case ListStyleType::HiraganaIroha:
1864         m_value.valueID = CSSValueHiraganaIroha;
1865         break;
1866     case ListStyleType::Kannada:
1867         m_value.valueID = CSSValueKannada;
1868         break;
1869     case ListStyleType::Katakana:
1870         m_value.valueID = CSSValueKatakana;
1871         break;
1872     case ListStyleType::KatakanaIroha:
1873         m_value.valueID = CSSValueKatakanaIroha;
1874         break;
1875     case ListStyleType::Khmer:
1876         m_value.valueID = CSSValueKhmer;
1877         break;
1878     case ListStyleType::Lao:
1879         m_value.valueID = CSSValueLao;
1880         break;
1881     case ListStyleType::LowerAlpha:
1882         m_value.valueID = CSSValueLowerAlpha;
1883         break;
1884     case ListStyleType::LowerArmenian:
1885         m_value.valueID = CSSValueLowerArmenian;
1886         break;
1887     case ListStyleType::LowerGreek:
1888         m_value.valueID = CSSValueLowerGreek;
1889         break;
1890     case ListStyleType::LowerHexadecimal:
1891         m_value.valueID = CSSValueLowerHexadecimal;
1892         break;
1893     case ListStyleType::LowerLatin:
1894         m_value.valueID = CSSValueLowerLatin;
1895         break;
1896     case ListStyleType::LowerNorwegian:
1897         m_value.valueID = CSSValueLowerNorwegian;
1898         break;
1899     case ListStyleType::LowerRoman:
1900         m_value.valueID = CSSValueLowerRoman;
1901         break;
1902     case ListStyleType::Malayalam:
1903         m_value.valueID = CSSValueMalayalam;
1904         break;
1905     case ListStyleType::Mongolian:
1906         m_value.valueID = CSSValueMongolian;
1907         break;
1908     case ListStyleType::Myanmar:
1909         m_value.valueID = CSSValueMyanmar;
1910         break;
1911     case ListStyleType::None:
1912         m_value.valueID = CSSValueNone;
1913         break;
1914     case ListStyleType::Octal:
1915         m_value.valueID = CSSValueOctal;
1916         break;
1917     case ListStyleType::Oriya:
1918         m_value.valueID = CSSValueOriya;
1919         break;
1920     case ListStyleType::Oromo:
1921         m_value.valueID = CSSValueOromo;
1922         break;
1923     case ListStyleType::Persian:
1924         m_value.valueID = CSSValuePersian;
1925         break;
1926     case ListStyleType::Sidama:
1927         m_value.valueID = CSSValueSidama;
1928         break;
1929     case ListStyleType::Somali:
1930         m_value.valueID = CSSValueSomali;
1931         break;
1932     case ListStyleType::Square:
1933         m_value.valueID = CSSValueSquare;
1934         break;
1935     case ListStyleType::Telugu:
1936         m_value.valueID = CSSValueTelugu;
1937         break;
1938     case ListStyleType::Thai:
1939         m_value.valueID = CSSValueThai;
1940         break;
1941     case ListStyleType::Tibetan:
1942         m_value.valueID = CSSValueTibetan;
1943         break;
1944     case ListStyleType::Tigre:
1945         m_value.valueID = CSSValueTigre;
1946         break;
1947     case ListStyleType::TigrinyaEr:
1948         m_value.valueID = CSSValueTigrinyaEr;
1949         break;
1950     case ListStyleType::TigrinyaErAbegede:
1951         m_value.valueID = CSSValueTigrinyaErAbegede;
1952         break;
1953     case ListStyleType::TigrinyaEt:
1954         m_value.valueID = CSSValueTigrinyaEt;
1955         break;
1956     case ListStyleType::TigrinyaEtAbegede:
1957         m_value.valueID = CSSValueTigrinyaEtAbegede;
1958         break;
1959     case ListStyleType::UpperAlpha:
1960         m_value.valueID = CSSValueUpperAlpha;
1961         break;
1962     case ListStyleType::UpperArmenian:
1963         m_value.valueID = CSSValueUpperArmenian;
1964         break;
1965     case ListStyleType::UpperGreek:
1966         m_value.valueID = CSSValueUpperGreek;
1967         break;
1968     case ListStyleType::UpperHexadecimal:
1969         m_value.valueID = CSSValueUpperHexadecimal;
1970         break;
1971     case ListStyleType::UpperLatin:
1972         m_value.valueID = CSSValueUpperLatin;
1973         break;
1974     case ListStyleType::UpperNorwegian:
1975         m_value.valueID = CSSValueUpperNorwegian;
1976         break;
1977     case ListStyleType::UpperRoman:
1978         m_value.valueID = CSSValueUpperRoman;
1979         break;
1980     case ListStyleType::Urdu:
1981         m_value.valueID = CSSValueUrdu;
1982         break;
1983     }
1984 }
1985
1986 template<> inline CSSPrimitiveValue::operator ListStyleType() const
1987 {
1988     ASSERT(isValueID());
1989
1990     switch (m_value.valueID) {
1991     case CSSValueNone:
1992         return ListStyleType::None;
1993     default:
1994         return static_cast<ListStyleType>(m_value.valueID - CSSValueDisc);
1995     }
1996 }
1997
1998 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(MarginCollapse e)
1999     : CSSValue(PrimitiveClass)
2000 {
2001     m_primitiveUnitType = CSS_VALUE_ID;
2002     switch (e) {
2003     case MarginCollapse::Collapse:
2004         m_value.valueID = CSSValueCollapse;
2005         break;
2006     case MarginCollapse::Separate:
2007         m_value.valueID = CSSValueSeparate;
2008         break;
2009     case MarginCollapse::Discard:
2010         m_value.valueID = CSSValueDiscard;
2011         break;
2012     }
2013 }
2014
2015 template<> inline CSSPrimitiveValue::operator MarginCollapse() const
2016 {
2017     ASSERT(isValueID());
2018
2019     switch (m_value.valueID) {
2020     case CSSValueCollapse:
2021         return MarginCollapse::Collapse;
2022     case CSSValueSeparate:
2023         return MarginCollapse::Separate;
2024     case CSSValueDiscard:
2025         return MarginCollapse::Discard;
2026     default:
2027         break;
2028     }
2029
2030     ASSERT_NOT_REACHED();
2031     return MarginCollapse::Collapse;
2032 }
2033
2034 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(MarqueeBehavior e)
2035     : CSSValue(PrimitiveClass)
2036 {
2037     m_primitiveUnitType = CSS_VALUE_ID;
2038     switch (e) {
2039     case MarqueeBehavior::None:
2040         m_value.valueID = CSSValueNone;
2041         break;
2042     case MarqueeBehavior::Scroll:
2043         m_value.valueID = CSSValueScroll;
2044         break;
2045     case MarqueeBehavior::Slide:
2046         m_value.valueID = CSSValueSlide;
2047         break;
2048     case MarqueeBehavior::Alternate:
2049         m_value.valueID = CSSValueAlternate;
2050         break;
2051     }
2052 }
2053
2054 template<> inline CSSPrimitiveValue::operator MarqueeBehavior() const
2055 {
2056     ASSERT(isValueID());
2057
2058     switch (m_value.valueID) {
2059     case CSSValueNone:
2060         return MarqueeBehavior::None;
2061     case CSSValueScroll:
2062         return MarqueeBehavior::Scroll;
2063     case CSSValueSlide:
2064         return MarqueeBehavior::Slide;
2065     case CSSValueAlternate:
2066         return MarqueeBehavior::Alternate;
2067     default:
2068         break;
2069     }
2070
2071     ASSERT_NOT_REACHED();
2072     return MarqueeBehavior::None;
2073 }
2074
2075 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(MarqueeDirection direction)
2076     : CSSValue(PrimitiveClass)
2077 {
2078     m_primitiveUnitType = CSS_VALUE_ID;
2079     switch (direction) {
2080     case MarqueeDirection::Forward:
2081         m_value.valueID = CSSValueForwards;
2082         break;
2083     case MarqueeDirection::Backward:
2084         m_value.valueID = CSSValueBackwards;
2085         break;
2086     case MarqueeDirection::Auto:
2087         m_value.valueID = CSSValueAuto;
2088         break;
2089     case MarqueeDirection::Up:
2090         m_value.valueID = CSSValueUp;
2091         break;
2092     case MarqueeDirection::Down:
2093         m_value.valueID = CSSValueDown;
2094         break;
2095     case MarqueeDirection::Left:
2096         m_value.valueID = CSSValueLeft;
2097         break;
2098     case MarqueeDirection::Right:
2099         m_value.valueID = CSSValueRight;
2100         break;
2101     }
2102 }
2103
2104 template<> inline CSSPrimitiveValue::operator MarqueeDirection() const
2105 {
2106     ASSERT(isValueID());
2107
2108     switch (m_value.valueID) {
2109     case CSSValueForwards:
2110         return MarqueeDirection::Forward;
2111     case CSSValueBackwards:
2112         return MarqueeDirection::Backward;
2113     case CSSValueAuto:
2114         return MarqueeDirection::Auto;
2115     case CSSValueAhead:
2116     case CSSValueUp: // We don't support vertical languages, so AHEAD just maps to UP.
2117         return MarqueeDirection::Up;
2118     case CSSValueReverse:
2119     case CSSValueDown: // REVERSE just maps to DOWN, since we don't do vertical text.
2120         return MarqueeDirection::Down;
2121     case CSSValueLeft:
2122         return MarqueeDirection::Left;
2123     case CSSValueRight:
2124         return MarqueeDirection::Right;
2125     default:
2126         break;
2127     }
2128
2129     ASSERT_NOT_REACHED();
2130     return MarqueeDirection::Auto;
2131 }
2132
2133 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(NBSPMode e)
2134     : CSSValue(PrimitiveClass)
2135 {
2136     m_primitiveUnitType = CSS_VALUE_ID;
2137     switch (e) {
2138     case NBSPMode::Normal:
2139         m_value.valueID = CSSValueNormal;
2140         break;
2141     case NBSPMode::Space:
2142         m_value.valueID = CSSValueSpace;
2143         break;
2144     }
2145 }
2146
2147 template<> inline CSSPrimitiveValue::operator NBSPMode() const
2148 {
2149     ASSERT(isValueID());
2150
2151     switch (m_value.valueID) {
2152     case CSSValueSpace:
2153         return NBSPMode::Space;
2154     case CSSValueNormal:
2155         return NBSPMode::Normal;
2156     default:
2157         break;
2158     }
2159
2160     ASSERT_NOT_REACHED();
2161     return NBSPMode::Normal;
2162 }
2163
2164 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(Overflow e)
2165     : CSSValue(PrimitiveClass)
2166 {
2167     m_primitiveUnitType = CSS_VALUE_ID;
2168     switch (e) {
2169     case Overflow::Visible:
2170         m_value.valueID = CSSValueVisible;
2171         break;
2172     case Overflow::Hidden:
2173         m_value.valueID = CSSValueHidden;
2174         break;
2175     case Overflow::Scroll:
2176         m_value.valueID = CSSValueScroll;
2177         break;
2178     case Overflow::Auto:
2179         m_value.valueID = CSSValueAuto;
2180         break;
2181     case Overflow::PagedX:
2182         m_value.valueID = CSSValueWebkitPagedX;
2183         break;
2184     case Overflow::PagedY:
2185         m_value.valueID = CSSValueWebkitPagedY;
2186         break;
2187     }
2188 }
2189
2190 template<> inline CSSPrimitiveValue::operator Overflow() const
2191 {
2192     ASSERT(isValueID());
2193
2194     switch (m_value.valueID) {
2195     case CSSValueVisible:
2196         return Overflow::Visible;
2197     case CSSValueHidden:
2198         return Overflow::Hidden;
2199     case CSSValueScroll:
2200         return Overflow::Scroll;
2201     case CSSValueOverlay:
2202     case CSSValueAuto:
2203         return Overflow::Auto;
2204     case CSSValueWebkitPagedX:
2205         return Overflow::PagedX;
2206     case CSSValueWebkitPagedY:
2207         return Overflow::PagedY;
2208     default:
2209         break;
2210     }
2211
2212     ASSERT_NOT_REACHED();
2213     return Overflow::Visible;
2214 }
2215
2216 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(BreakBetween e)
2217     : CSSValue(PrimitiveClass)
2218 {
2219     m_primitiveUnitType = CSS_VALUE_ID;
2220     switch (e) {
2221     case BreakBetween::Auto:
2222         m_value.valueID = CSSValueAuto;
2223         break;
2224     case BreakBetween::Avoid:
2225         m_value.valueID = CSSValueAvoid;
2226         break;
2227     case BreakBetween::AvoidColumn:
2228         m_value.valueID = CSSValueAvoidColumn;
2229         break;
2230     case BreakBetween::AvoidPage:
2231         m_value.valueID = CSSValueAvoidPage;
2232         break;
2233     case BreakBetween::Column:
2234         m_value.valueID = CSSValueColumn;
2235         break;
2236     case BreakBetween::Page:
2237         m_value.valueID = CSSValuePage;
2238         break;
2239     case BreakBetween::LeftPage:
2240         m_value.valueID = CSSValueLeft;
2241         break;
2242     case BreakBetween::RightPage:
2243         m_value.valueID = CSSValueRight;
2244         break;
2245     case BreakBetween::RectoPage:
2246         m_value.valueID = CSSValueRecto;
2247         break;
2248     case BreakBetween::VersoPage:
2249         m_value.valueID = CSSValueVerso;
2250         break;
2251     }
2252 }
2253
2254 template<> inline CSSPrimitiveValue::operator BreakBetween() const
2255 {
2256     ASSERT(isValueID());
2257
2258     switch (m_value.valueID) {
2259     case CSSValueAuto:
2260         return BreakBetween::Auto;
2261     case CSSValueAvoid:
2262         return BreakBetween::Avoid;
2263     case CSSValueAvoidColumn:
2264         return BreakBetween::AvoidColumn;
2265     case CSSValueAvoidPage:
2266         return BreakBetween::AvoidPage;
2267     case CSSValueColumn:
2268         return BreakBetween::Column;
2269     case CSSValuePage:
2270         return BreakBetween::Page;
2271     case CSSValueLeft:
2272         return BreakBetween::LeftPage;
2273     case CSSValueRight:
2274         return BreakBetween::RightPage;
2275     case CSSValueRecto:
2276         return BreakBetween::RectoPage;
2277     case CSSValueVerso:
2278         return BreakBetween::VersoPage;
2279     default:
2280         break;
2281     }
2282
2283     ASSERT_NOT_REACHED();
2284     return BreakBetween::Auto;
2285 }
2286
2287 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(BreakInside e)
2288     : CSSValue(PrimitiveClass)
2289 {
2290     m_primitiveUnitType = CSS_VALUE_ID;
2291     switch (e) {
2292     case BreakInside::Auto:
2293         m_value.valueID = CSSValueAuto;
2294         break;
2295     case BreakInside::Avoid:
2296         m_value.valueID = CSSValueAvoid;
2297         break;
2298     case BreakInside::AvoidColumn:
2299         m_value.valueID = CSSValueAvoidColumn;
2300         break;
2301     case BreakInside::AvoidPage:
2302         m_value.valueID = CSSValueAvoidPage;
2303         break;
2304     }
2305 }
2306
2307 template<> inline CSSPrimitiveValue::operator BreakInside() const
2308 {
2309     ASSERT(isValueID());
2310     
2311     switch (m_value.valueID) {
2312     case CSSValueAuto:
2313         return BreakInside::Auto;
2314     case CSSValueAvoid:
2315         return BreakInside::Avoid;
2316     case CSSValueAvoidColumn:
2317         return BreakInside::AvoidColumn;
2318     case CSSValueAvoidPage:
2319         return BreakInside::AvoidPage;
2320     default:
2321         break;
2322     }
2323
2324     ASSERT_NOT_REACHED();
2325     return BreakInside::Auto;
2326 }
2327
2328 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(PositionType e)
2329     : CSSValue(PrimitiveClass)
2330 {
2331     m_primitiveUnitType = CSS_VALUE_ID;
2332     switch (e) {
2333     case PositionType::Static:
2334         m_value.valueID = CSSValueStatic;
2335         break;
2336     case PositionType::Relative:
2337         m_value.valueID = CSSValueRelative;
2338         break;
2339     case PositionType::Absolute:
2340         m_value.valueID = CSSValueAbsolute;
2341         break;
2342     case PositionType::Fixed:
2343         m_value.valueID = CSSValueFixed;
2344         break;
2345     case PositionType::Sticky:
2346         m_value.valueID = CSSValueSticky;
2347         break;
2348     }
2349 }
2350
2351 template<> inline CSSPrimitiveValue::operator PositionType() const
2352 {
2353     ASSERT(isValueID());
2354
2355     switch (m_value.valueID) {
2356     case CSSValueStatic:
2357         return PositionType::Static;
2358     case CSSValueRelative:
2359         return PositionType::Relative;
2360     case CSSValueAbsolute:
2361         return PositionType::Absolute;
2362     case CSSValueFixed:
2363         return PositionType::Fixed;
2364     case CSSValueSticky:
2365     case CSSValueWebkitSticky:
2366         return PositionType::Sticky;
2367     default:
2368         break;
2369     }
2370
2371     ASSERT_NOT_REACHED();
2372     return PositionType::Static;
2373 }
2374
2375 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(Resize e)
2376     : CSSValue(PrimitiveClass)
2377 {
2378     m_primitiveUnitType = CSS_VALUE_ID;
2379     switch (e) {
2380     case Resize::Both:
2381         m_value.valueID = CSSValueBoth;
2382         break;
2383     case Resize::Horizontal:
2384         m_value.valueID = CSSValueHorizontal;
2385         break;
2386     case Resize::Vertical:
2387         m_value.valueID = CSSValueVertical;
2388         break;
2389     case Resize::None:
2390         m_value.valueID = CSSValueNone;
2391         break;
2392     }
2393 }
2394
2395 template<> inline CSSPrimitiveValue::operator Resize() const
2396 {
2397     ASSERT(isValueID());
2398
2399     switch (m_value.valueID) {
2400     case CSSValueBoth:
2401         return Resize::Both;
2402     case CSSValueHorizontal:
2403         return Resize::Horizontal;
2404     case CSSValueVertical:
2405         return Resize::Vertical;
2406     case CSSValueAuto:
2407         ASSERT_NOT_REACHED(); // Depends on settings, thus should be handled by the caller.
2408         return Resize::None;
2409     case CSSValueNone:
2410         return Resize::None;
2411     default:
2412         break;
2413     }
2414
2415     ASSERT_NOT_REACHED();
2416     return Resize::None;
2417 }
2418
2419 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TableLayoutType e)
2420     : CSSValue(PrimitiveClass)
2421 {
2422     m_primitiveUnitType = CSS_VALUE_ID;
2423     switch (e) {
2424     case TableLayoutType::Auto:
2425         m_value.valueID = CSSValueAuto;
2426         break;
2427     case TableLayoutType::Fixed:
2428         m_value.valueID = CSSValueFixed;
2429         break;
2430     }
2431 }
2432
2433 template<> inline CSSPrimitiveValue::operator TableLayoutType() const
2434 {
2435     ASSERT(isValueID());
2436
2437     switch (m_value.valueID) {
2438     case CSSValueFixed:
2439         return TableLayoutType::Fixed;
2440     case CSSValueAuto:
2441         return TableLayoutType::Auto;
2442     default:
2443         break;
2444     }
2445
2446     ASSERT_NOT_REACHED();
2447     return TableLayoutType::Auto;
2448 }
2449
2450 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextAlignMode e)
2451     : CSSValue(PrimitiveClass)
2452 {
2453     m_primitiveUnitType = CSS_VALUE_ID;
2454     switch (e) {
2455     case TextAlignMode::Start:
2456         m_value.valueID = CSSValueStart;
2457         break;
2458     case TextAlignMode::End:
2459         m_value.valueID = CSSValueEnd;
2460         break;
2461     case TextAlignMode::Left:
2462         m_value.valueID = CSSValueLeft;
2463         break;
2464     case TextAlignMode::Right:
2465         m_value.valueID = CSSValueRight;
2466         break;
2467     case TextAlignMode::Center:
2468         m_value.valueID = CSSValueCenter;
2469         break;
2470     case TextAlignMode::Justify:
2471         m_value.valueID = CSSValueJustify;
2472         break;
2473     case TextAlignMode::WebKitLeft:
2474         m_value.valueID = CSSValueWebkitLeft;
2475         break;
2476     case TextAlignMode::WebKitRight:
2477         m_value.valueID = CSSValueWebkitRight;
2478         break;
2479     case TextAlignMode::WebKitCenter:
2480         m_value.valueID = CSSValueWebkitCenter;
2481         break;
2482     }
2483 }
2484
2485 template<> inline CSSPrimitiveValue::operator TextAlignMode() const
2486 {
2487     ASSERT(isValueID());
2488
2489     switch (m_value.valueID) {
2490     case CSSValueWebkitAuto: // Legacy -webkit-auto. Eqiuvalent to start.
2491     case CSSValueStart:
2492         return TextAlignMode::Start;
2493     case CSSValueEnd:
2494         return TextAlignMode::End;
2495     default:
2496         return static_cast<TextAlignMode>(m_value.valueID - CSSValueLeft);
2497     }
2498 }
2499
2500 #if ENABLE(CSS3_TEXT)
2501 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextAlignLast e)
2502     : CSSValue(PrimitiveClass)
2503 {
2504     m_primitiveUnitType = CSS_VALUE_ID;
2505     switch (e) {
2506     case TextAlignLast::Start:
2507         m_value.valueID = CSSValueStart;
2508         break;
2509     case TextAlignLast::End:
2510         m_value.valueID = CSSValueEnd;
2511         break;
2512     case TextAlignLast::Left:
2513         m_value.valueID = CSSValueLeft;
2514         break;
2515     case TextAlignLast::Right:
2516         m_value.valueID = CSSValueRight;
2517         break;
2518     case TextAlignLast::Center:
2519         m_value.valueID = CSSValueCenter;
2520         break;
2521     case TextAlignLast::Justify:
2522         m_value.valueID = CSSValueJustify;
2523         break;
2524     case TextAlignLast::Auto:
2525         m_value.valueID = CSSValueAuto;
2526         break;
2527     }
2528 }
2529
2530 template<> inline CSSPrimitiveValue::operator TextAlignLast() const
2531 {
2532     ASSERT(isValueID());
2533
2534     switch (m_value.valueID) {
2535     case CSSValueAuto:
2536         return TextAlignLast::Auto;
2537     case CSSValueStart:
2538         return TextAlignLast::Start;
2539     case CSSValueEnd:
2540         return TextAlignLast::End;
2541     case CSSValueLeft:
2542         return TextAlignLast::Left;
2543     case CSSValueRight:
2544         return TextAlignLast::Right;
2545     case CSSValueCenter:
2546         return TextAlignLast::Center;
2547     case CSSValueJustify:
2548         return TextAlignLast::Justify;
2549     default:
2550         break;
2551     }
2552
2553     ASSERT_NOT_REACHED();
2554     return TextAlignLast::Auto;
2555 }
2556
2557 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextJustify e)
2558     : CSSValue(PrimitiveClass)
2559 {
2560     m_primitiveUnitType = CSS_VALUE_ID;
2561     switch (e) {
2562     case TextJustify::Auto:
2563         m_value.valueID = CSSValueAuto;
2564         break;
2565     case TextJustify::None:
2566         m_value.valueID = CSSValueNone;
2567         break;
2568     case TextJustify::InterWord:
2569         m_value.valueID = CSSValueInterWord;
2570         break;
2571     case TextJustify::Distribute:
2572         m_value.valueID = CSSValueDistribute;
2573         break;
2574     }
2575 }
2576
2577 template<> inline CSSPrimitiveValue::operator TextJustify() const
2578 {
2579     ASSERT(isValueID());
2580
2581     switch (m_value.valueID) {
2582     case CSSValueAuto:
2583         return TextJustify::Auto;
2584     case CSSValueNone:
2585         return TextJustify::None;
2586     case CSSValueInterWord:
2587         return TextJustify::InterWord;
2588     case CSSValueDistribute:
2589         return TextJustify::Distribute;
2590     default:
2591         break;
2592     }
2593
2594     ASSERT_NOT_REACHED();
2595     return TextJustify::Auto;
2596 }
2597 #endif // CSS3_TEXT
2598
2599 template<> inline CSSPrimitiveValue::operator OptionSet<TextDecoration>() const
2600 {
2601     ASSERT(isValueID());
2602
2603     switch (m_value.valueID) {
2604     case CSSValueNone:
2605         return OptionSet<TextDecoration> { };
2606     case CSSValueUnderline:
2607         return TextDecoration::Underline;
2608     case CSSValueOverline:
2609         return TextDecoration::Overline;
2610     case CSSValueLineThrough:
2611         return TextDecoration::LineThrough;
2612     case CSSValueBlink:
2613         return TextDecoration::Blink;
2614 #if ENABLE(LETTERPRESS)
2615     case CSSValueWebkitLetterpress:
2616         return TextDecoration::Letterpress;
2617 #endif
2618     default:
2619         break;
2620     }
2621
2622     ASSERT_NOT_REACHED();
2623     return OptionSet<TextDecoration> { };
2624 }
2625
2626 template<> inline CSSPrimitiveValue::operator TextDecorationStyle() const
2627 {
2628     ASSERT(isValueID());
2629
2630     switch (m_value.valueID) {
2631     case CSSValueSolid:
2632         return TextDecorationStyle::Solid;
2633     case CSSValueDouble:
2634         return TextDecorationStyle::Double;
2635     case CSSValueDotted:
2636         return TextDecorationStyle::Dotted;
2637     case CSSValueDashed:
2638         return TextDecorationStyle::Dashed;
2639     case CSSValueWavy:
2640         return TextDecorationStyle::Wavy;
2641     default:
2642         break;
2643     }
2644
2645     ASSERT_NOT_REACHED();
2646     return TextDecorationStyle::Solid;
2647 }
2648
2649 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextUnderlinePosition position)
2650     : CSSValue(PrimitiveClass)
2651 {
2652     m_primitiveUnitType = CSS_VALUE_ID;
2653     switch (position) {
2654     case TextUnderlinePosition::Auto:
2655         m_value.valueID = CSSValueAuto;
2656         break;
2657     case TextUnderlinePosition::Under:
2658         m_value.valueID = CSSValueUnder;
2659         break;
2660     case TextUnderlinePosition::FromFont:
2661         m_value.valueID = CSSValueFromFont;
2662         break;
2663     }
2664
2665     // FIXME: Implement support for 'under left' and 'under right' values.
2666 }
2667
2668 template<> inline CSSPrimitiveValue::operator TextUnderlinePosition() const
2669 {
2670     ASSERT(isValueID());
2671
2672     switch (m_value.valueID) {
2673     case CSSValueAuto:
2674         return TextUnderlinePosition::Auto;
2675     case CSSValueUnder:
2676         return TextUnderlinePosition::Under;
2677     case CSSValueFromFont:
2678         return TextUnderlinePosition::FromFont;
2679     default:
2680         break;
2681     }
2682
2683     // FIXME: Implement support for 'under left' and 'under right' values.
2684     ASSERT_NOT_REACHED();
2685     return TextUnderlinePosition::Auto;
2686 }
2687
2688 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextSecurity e)
2689     : CSSValue(PrimitiveClass)
2690 {
2691     m_primitiveUnitType = CSS_VALUE_ID;
2692     switch (e) {
2693     case TextSecurity::None:
2694         m_value.valueID = CSSValueNone;
2695         break;
2696     case TextSecurity::Disc:
2697         m_value.valueID = CSSValueDisc;
2698         break;
2699     case TextSecurity::Circle:
2700         m_value.valueID = CSSValueCircle;
2701         break;
2702     case TextSecurity::Square:
2703         m_value.valueID = CSSValueSquare;
2704         break;
2705     }
2706 }
2707
2708 template<> inline CSSPrimitiveValue::operator TextSecurity() const
2709 {
2710     ASSERT(isValueID());
2711
2712     switch (m_value.valueID) {
2713     case CSSValueNone:
2714         return TextSecurity::None;
2715     case CSSValueDisc:
2716         return TextSecurity::Disc;
2717     case CSSValueCircle:
2718         return TextSecurity::Circle;
2719     case CSSValueSquare:
2720         return TextSecurity::Square;
2721     default:
2722         break;
2723     }
2724
2725     ASSERT_NOT_REACHED();
2726     return TextSecurity::None;
2727 }
2728
2729 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextTransform e)
2730     : CSSValue(PrimitiveClass)
2731 {
2732     m_primitiveUnitType = CSS_VALUE_ID;
2733     switch (e) {
2734     case TextTransform::Capitalize:
2735         m_value.valueID = CSSValueCapitalize;
2736         break;
2737     case TextTransform::Uppercase:
2738         m_value.valueID = CSSValueUppercase;
2739         break;
2740     case TextTransform::Lowercase:
2741         m_value.valueID = CSSValueLowercase;
2742         break;
2743     case TextTransform::None:
2744         m_value.valueID = CSSValueNone;
2745         break;
2746     }
2747 }
2748
2749 template<> inline CSSPrimitiveValue::operator TextTransform() const
2750 {
2751     ASSERT(isValueID());
2752
2753     switch (m_value.valueID) {
2754     case CSSValueCapitalize:
2755         return TextTransform::Capitalize;
2756     case CSSValueUppercase:
2757         return TextTransform::Uppercase;
2758     case CSSValueLowercase:
2759         return TextTransform::Lowercase;
2760     case CSSValueNone:
2761         return TextTransform::None;
2762     default:
2763         break;
2764     }
2765
2766     ASSERT_NOT_REACHED();
2767     return TextTransform::None;
2768 }
2769
2770 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EUnicodeBidi e)
2771     : CSSValue(PrimitiveClass)
2772 {
2773     m_primitiveUnitType = CSS_VALUE_ID;
2774     switch (e) {
2775     case UBNormal:
2776         m_value.valueID = CSSValueNormal;
2777         break;
2778     case Embed:
2779         m_value.valueID = CSSValueEmbed;
2780         break;
2781     case Override:
2782         m_value.valueID = CSSValueBidiOverride;
2783         break;
2784     case Isolate:
2785         m_value.valueID = CSSValueIsolate;
2786         break;
2787     case IsolateOverride:
2788         m_value.valueID = CSSValueIsolateOverride;
2789         break;
2790     case Plaintext:
2791         m_value.valueID = CSSValuePlaintext;
2792         break;
2793     }
2794 }
2795
2796 template<> inline CSSPrimitiveValue::operator EUnicodeBidi() const
2797 {
2798     ASSERT(isValueID());
2799
2800     switch (m_value.valueID) {
2801     case CSSValueNormal:
2802         return UBNormal;
2803     case CSSValueEmbed:
2804         return Embed;
2805     case CSSValueBidiOverride:
2806         return Override;
2807     case CSSValueIsolate:
2808     case CSSValueWebkitIsolate:
2809         return Isolate;
2810     case CSSValueIsolateOverride:
2811     case CSSValueWebkitIsolateOverride:
2812         return IsolateOverride;
2813     case CSSValuePlaintext:
2814     case CSSValueWebkitPlaintext:
2815         return Plaintext;
2816     default:
2817         break;
2818     }
2819
2820     ASSERT_NOT_REACHED();
2821     return UBNormal;
2822 }
2823
2824 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(UserDrag e)
2825     : CSSValue(PrimitiveClass)
2826 {
2827     m_primitiveUnitType = CSS_VALUE_ID;
2828     switch (e) {
2829     case UserDrag::Auto:
2830         m_value.valueID = CSSValueAuto;
2831         break;
2832     case UserDrag::None:
2833         m_value.valueID = CSSValueNone;
2834         break;
2835     case UserDrag::Element:
2836         m_value.valueID = CSSValueElement;
2837         break;
2838     default:
2839         break;
2840     }
2841 }
2842
2843 template<> inline CSSPrimitiveValue::operator UserDrag() const
2844 {
2845     ASSERT(isValueID());
2846
2847     switch (m_value.valueID) {
2848     case CSSValueAuto:
2849         return UserDrag::Auto;
2850     case CSSValueNone:
2851         return UserDrag::None;
2852     case CSSValueElement:
2853         return UserDrag::Element;
2854     default:
2855         break;
2856     }
2857
2858     ASSERT_NOT_REACHED();
2859     return UserDrag::Auto;
2860 }
2861
2862 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(UserModify e)
2863     : CSSValue(PrimitiveClass)
2864 {
2865     m_primitiveUnitType = CSS_VALUE_ID;
2866     switch (e) {
2867     case UserModify::ReadOnly:
2868         m_value.valueID = CSSValueReadOnly;
2869         break;
2870     case UserModify::ReadWrite:
2871         m_value.valueID = CSSValueReadWrite;
2872         break;
2873     case UserModify::ReadWritePlaintextOnly:
2874         m_value.valueID = CSSValueReadWritePlaintextOnly;
2875         break;
2876     }
2877 }
2878
2879 template<> inline CSSPrimitiveValue::operator UserModify() const
2880 {
2881     ASSERT(isValueID());
2882
2883     switch (m_value.valueID) {
2884     case CSSValueReadOnly:
2885         return UserModify::ReadOnly;
2886     case CSSValueReadWrite:
2887         return UserModify::ReadWrite;
2888     case CSSValueReadWritePlaintextOnly:
2889         return UserModify::ReadWritePlaintextOnly;
2890     default:
2891         break;
2892     }
2893
2894     ASSERT_NOT_REACHED();
2895     return UserModify::ReadOnly;
2896 }
2897
2898 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(UserSelect e)
2899     : CSSValue(PrimitiveClass)
2900 {
2901     m_primitiveUnitType = CSS_VALUE_ID;
2902     switch (e) {
2903     case UserSelect::None:
2904         m_value.valueID = CSSValueNone;
2905         break;
2906     case UserSelect::Text:
2907         m_value.valueID = CSSValueText;
2908         break;
2909     case UserSelect::All:
2910         m_value.valueID = CSSValueAll;
2911         break;
2912     }
2913 }
2914
2915 template<> inline CSSPrimitiveValue::operator UserSelect() const
2916 {
2917     ASSERT(isValueID());
2918
2919     switch (m_value.valueID) {
2920     case CSSValueAuto:
2921         return UserSelect::Text;
2922     case CSSValueNone:
2923         return UserSelect::None;
2924     case CSSValueText:
2925         return UserSelect::Text;
2926     case CSSValueAll:
2927         return UserSelect::All;
2928     default:
2929         break;
2930     }
2931
2932     ASSERT_NOT_REACHED();
2933     return UserSelect::Text;
2934 }
2935
2936 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(VerticalAlign a)
2937     : CSSValue(PrimitiveClass)
2938 {
2939     m_primitiveUnitType = CSS_VALUE_ID;
2940     switch (a) {
2941     case VerticalAlign::Top:
2942         m_value.valueID = CSSValueTop;
2943         break;
2944     case VerticalAlign::Bottom:
2945         m_value.valueID = CSSValueBottom;
2946         break;
2947     case VerticalAlign::Middle:
2948         m_value.valueID = CSSValueMiddle;
2949         break;
2950     case VerticalAlign::Baseline:
2951         m_value.valueID = CSSValueBaseline;
2952         break;
2953     case VerticalAlign::TextBottom:
2954         m_value.valueID = CSSValueTextBottom;
2955         break;
2956     case VerticalAlign::TextTop:
2957         m_value.valueID = CSSValueTextTop;
2958         break;
2959     case VerticalAlign::Sub:
2960         m_value.valueID = CSSValueSub;
2961         break;
2962     case VerticalAlign::Super:
2963         m_value.valueID = CSSValueSuper;
2964         break;
2965     case VerticalAlign::BaselineMiddle:
2966         m_value.valueID = CSSValueWebkitBaselineMiddle;
2967         break;
2968     case VerticalAlign::Length:
2969         m_value.valueID = CSSValueInvalid;
2970     }
2971 }
2972
2973 template<> inline CSSPrimitiveValue::operator VerticalAlign() const
2974 {
2975     ASSERT(isValueID());
2976
2977     switch (m_value.valueID) {
2978     case CSSValueTop:
2979         return VerticalAlign::Top;
2980     case CSSValueBottom:
2981         return VerticalAlign::Bottom;
2982     case CSSValueMiddle:
2983         return VerticalAlign::Middle;
2984     case CSSValueBaseline:
2985         return VerticalAlign::Baseline;
2986     case CSSValueTextBottom:
2987         return VerticalAlign::TextBottom;
2988     case CSSValueTextTop:
2989         return VerticalAlign::TextTop;
2990     case CSSValueSub:
2991         return VerticalAlign::Sub;
2992     case CSSValueSuper:
2993         return VerticalAlign::Super;
2994     case CSSValueWebkitBaselineMiddle:
2995         return VerticalAlign::BaselineMiddle;
2996     default:
2997         break;
2998     }
2999
3000     ASSERT_NOT_REACHED();
3001     return VerticalAlign::Top;
3002 }
3003
3004 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(Visibility e)
3005     : CSSValue(PrimitiveClass)
3006 {
3007     m_primitiveUnitType = CSS_VALUE_ID;
3008     switch (e) {
3009     case Visibility::Visible:
3010         m_value.valueID = CSSValueVisible;
3011         break;
3012     case Visibility::Hidden:
3013         m_value.valueID = CSSValueHidden;
3014         break;
3015     case Visibility::Collapse:
3016         m_value.valueID = CSSValueCollapse;
3017         break;
3018     }
3019 }
3020
3021 template<> inline CSSPrimitiveValue::operator Visibility() const
3022 {
3023     ASSERT(isValueID());
3024
3025     switch (m_value.valueID) {
3026     case CSSValueHidden:
3027         return Visibility::Hidden;
3028     case CSSValueVisible:
3029         return Visibility::Visible;
3030     case CSSValueCollapse:
3031         return Visibility::Collapse;
3032     default:
3033         break;
3034     }
3035
3036     ASSERT_NOT_REACHED();
3037     return Visibility::Visible;
3038 }
3039
3040 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(WhiteSpace e)
3041     : CSSValue(PrimitiveClass)
3042 {
3043     m_primitiveUnitType = CSS_VALUE_ID;
3044     switch (e) {
3045     case WhiteSpace::Normal:
3046         m_value.valueID = CSSValueNormal;
3047         break;
3048     case WhiteSpace::Pre:
3049         m_value.valueID = CSSValuePre;
3050         break;
3051     case WhiteSpace::PreWrap:
3052         m_value.valueID = CSSValuePreWrap;
3053         break;
3054     case WhiteSpace::PreLine:
3055         m_value.valueID = CSSValuePreLine;
3056         break;
3057     case WhiteSpace::NoWrap:
3058         m_value.valueID = CSSValueNowrap;
3059         break;
3060     case WhiteSpace::KHTMLNoWrap:
3061         m_value.valueID = CSSValueWebkitNowrap;
3062         break;
3063     case WhiteSpace::BreakSpaces:
3064         m_value.valueID = CSSValueBreakSpaces;
3065         break;
3066     }
3067 }
3068
3069 template<> inline CSSPrimitiveValue::operator WhiteSpace() const
3070 {
3071     ASSERT(isValueID());
3072
3073     switch (m_value.valueID) {
3074     case CSSValueWebkitNowrap:
3075         return WhiteSpace::KHTMLNoWrap;
3076     case CSSValueNowrap:
3077         return WhiteSpace::NoWrap;
3078     case CSSValuePre:
3079         return WhiteSpace::Pre;
3080     case CSSValuePreWrap:
3081         return WhiteSpace::PreWrap;
3082     case CSSValuePreLine:
3083         return WhiteSpace::PreLine;
3084     case CSSValueNormal:
3085         return WhiteSpace::Normal;
3086     case CSSValueBreakSpaces:
3087         return WhiteSpace::BreakSpaces;
3088     default:
3089         break;
3090     }
3091
3092     ASSERT_NOT_REACHED();
3093     return WhiteSpace::Normal;
3094 }
3095
3096 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(WordBreak e)
3097     : CSSValue(PrimitiveClass)
3098 {
3099     m_primitiveUnitType = CSS_VALUE_ID;
3100     switch (e) {
3101     case WordBreak::Normal:
3102         m_value.valueID = CSSValueNormal;
3103         break;
3104     case WordBreak::BreakAll:
3105         m_value.valueID = CSSValueBreakAll;
3106         break;
3107     case WordBreak::KeepAll:
3108         m_value.valueID = CSSValueKeepAll;
3109         break;
3110     case WordBreak::BreakWord:
3111         m_value.valueID = CSSValueBreakWord;
3112         break;
3113     }
3114 }
3115
3116 template<> inline CSSPrimitiveValue::operator WordBreak() const
3117 {
3118     ASSERT(isValueID());
3119
3120     switch (m_value.valueID) {
3121     case CSSValueBreakAll:
3122         return WordBreak::BreakAll;
3123     case CSSValueKeepAll:
3124         return WordBreak::KeepAll;
3125     case CSSValueBreakWord:
3126         return WordBreak::BreakWord;
3127     case CSSValueNormal:
3128         return WordBreak::Normal;
3129     default:
3130         break;
3131     }
3132
3133     ASSERT_NOT_REACHED();
3134     return WordBreak::Normal;
3135 }
3136
3137 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(OverflowWrap e)
3138     : CSSValue(PrimitiveClass)
3139 {
3140     m_primitiveUnitType = CSS_VALUE_ID;
3141     switch (e) {
3142     case OverflowWrap::Normal:
3143         m_value.valueID = CSSValueNormal;
3144         break;
3145     case OverflowWrap::Break:
3146         m_value.valueID = CSSValueBreakWord;
3147         break;
3148     }
3149 }
3150
3151 template<> inline CSSPrimitiveValue::operator OverflowWrap() const
3152 {
3153     ASSERT(isValueID());
3154
3155     switch (m_value.valueID) {
3156     case CSSValueBreakWord:
3157         return OverflowWrap::Break;
3158     case CSSValueNormal:
3159         return OverflowWrap::Normal;
3160     default:
3161         break;
3162     }
3163
3164     ASSERT_NOT_REACHED();
3165     return OverflowWrap::Normal;
3166 }
3167
3168 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextDirection e)
3169     : CSSValue(PrimitiveClass)
3170 {
3171     m_primitiveUnitType = CSS_VALUE_ID;
3172     switch (e) {
3173     case TextDirection::LTR:
3174         m_value.valueID = CSSValueLtr;
3175         break;
3176     case TextDirection::RTL:
3177         m_value.valueID = CSSValueRtl;
3178         break;
3179     }
3180 }
3181
3182 template<> inline CSSPrimitiveValue::operator TextDirection() const
3183 {
3184     ASSERT(isValueID());
3185
3186     switch (m_value.valueID) {
3187     case CSSValueLtr:
3188         return TextDirection::LTR;
3189     case CSSValueRtl:
3190         return TextDirection::RTL;
3191     default:
3192         break;
3193     }
3194
3195     ASSERT_NOT_REACHED();
3196     return TextDirection::LTR;
3197 }
3198
3199 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(WritingMode e)
3200     : CSSValue(PrimitiveClass)
3201 {
3202     m_primitiveUnitType = CSS_VALUE_ID;
3203     switch (e) {
3204     case TopToBottomWritingMode:
3205         m_value.valueID = CSSValueHorizontalTb;
3206         break;
3207     case RightToLeftWritingMode:
3208         m_value.valueID = CSSValueVerticalRl;
3209         break;
3210     case LeftToRightWritingMode:
3211         m_value.valueID = CSSValueVerticalLr;
3212         break;
3213     case BottomToTopWritingMode:
3214         m_value.valueID = CSSValueHorizontalBt;
3215         break;
3216     }
3217 }
3218
3219 template<> inline CSSPrimitiveValue::operator WritingMode() const
3220 {
3221     ASSERT(isValueID());
3222
3223     switch (m_value.valueID) {
3224     case CSSValueHorizontalTb:
3225     case CSSValueLr:
3226     case CSSValueLrTb:
3227     case CSSValueRl:
3228     case CSSValueRlTb:
3229         return TopToBottomWritingMode;
3230     case CSSValueVerticalRl:
3231     case CSSValueTb:
3232     case CSSValueTbRl:
3233         return RightToLeftWritingMode;
3234     case CSSValueVerticalLr:
3235         return LeftToRightWritingMode;
3236     case CSSValueHorizontalBt:
3237         return BottomToTopWritingMode;
3238     default:
3239         break;
3240     }
3241
3242     ASSERT_NOT_REACHED();
3243     return TopToBottomWritingMode;
3244 }
3245
3246 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextCombine e)
3247     : CSSValue(PrimitiveClass)
3248 {
3249     m_primitiveUnitType = CSS_VALUE_ID;
3250     switch (e) {
3251     case TextCombine::None:
3252         m_value.valueID = CSSValueNone;
3253         break;
3254     case TextCombine::Horizontal:
3255         m_value.valueID = CSSValueHorizontal;
3256         break;
3257     }
3258 }
3259
3260 template<> inline CSSPrimitiveValue::operator TextCombine() const
3261 {
3262     ASSERT(isValueID());
3263
3264     switch (m_value.valueID) {
3265     case CSSValueNone:
3266         return TextCombine::None;
3267     case CSSValueHorizontal:
3268         return TextCombine::Horizontal;
3269     default:
3270         break;
3271     }
3272
3273     ASSERT_NOT_REACHED();
3274     return TextCombine::None;
3275 }
3276
3277 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(RubyPosition position)
3278     : CSSValue(PrimitiveClass)
3279 {
3280     m_primitiveUnitType = CSS_VALUE_ID;
3281     switch (position) {
3282     case RubyPosition::Before:
3283         m_value.valueID = CSSValueBefore;
3284         break;
3285     case RubyPosition::After:
3286         m_value.valueID = CSSValueAfter;
3287         break;
3288     case RubyPosition::InterCharacter:
3289         m_value.valueID = CSSValueInterCharacter;
3290         break;
3291     }
3292 }
3293
3294 template<> inline CSSPrimitiveValue::operator RubyPosition() const
3295 {
3296     ASSERT(isValueID());
3297
3298     switch (m_value.valueID) {
3299     case CSSValueBefore:
3300         return RubyPosition::Before;
3301     case CSSValueAfter:
3302         return RubyPosition::After;
3303     case CSSValueInterCharacter:
3304         return RubyPosition::InterCharacter;
3305     default:
3306         break;
3307     }
3308
3309     ASSERT_NOT_REACHED();
3310     return RubyPosition::Before;
3311 }
3312
3313 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextOverflow overflow)
3314     : CSSValue(PrimitiveClass)
3315 {
3316     m_primitiveUnitType = CSS_VALUE_ID;
3317     switch (overflow) {
3318     case TextOverflow::Clip:
3319         m_value.valueID = CSSValueClip;
3320         break;
3321     case TextOverflow::Ellipsis:
3322         m_value.valueID = CSSValueEllipsis;
3323         break;
3324     }
3325 }
3326
3327 template<> inline CSSPrimitiveValue::operator TextOverflow() const
3328 {
3329     ASSERT(isValueID());
3330
3331     switch (m_value.valueID) {
3332     case CSSValueClip:
3333         return TextOverflow::Clip;
3334     case CSSValueEllipsis:
3335         return TextOverflow::Ellipsis;
3336     default:
3337         break;
3338     }
3339
3340     ASSERT_NOT_REACHED();
3341     return TextOverflow::Clip;
3342 }
3343
3344 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextEmphasisFill fill)
3345     : CSSValue(PrimitiveClass)
3346 {
3347     m_primitiveUnitType = CSS_VALUE_ID;
3348     switch (fill) {
3349     case TextEmphasisFill::Filled:
3350         m_value.valueID = CSSValueFilled;
3351         break;
3352     case TextEmphasisFill::Open:
3353         m_value.valueID = CSSValueOpen;
3354         break;
3355     }
3356 }
3357
3358 template<> inline CSSPrimitiveValue::operator TextEmphasisFill() const
3359 {
3360     ASSERT(isValueID());
3361
3362     switch (m_value.valueID) {
3363     case CSSValueFilled:
3364         return TextEmphasisFill::Filled;
3365     case CSSValueOpen:
3366         return TextEmphasisFill::Open;
3367     default:
3368         break;
3369     }
3370
3371     ASSERT_NOT_REACHED();
3372     return TextEmphasisFill::Filled;
3373 }
3374
3375 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextEmphasisMark mark)
3376     : CSSValue(PrimitiveClass)
3377 {
3378     m_primitiveUnitType = CSS_VALUE_ID;
3379     switch (mark) {
3380     case TextEmphasisMark::Dot:
3381         m_value.valueID = CSSValueDot;
3382         break;
3383     case TextEmphasisMark::Circle:
3384         m_value.valueID = CSSValueCircle;
3385         break;
3386     case TextEmphasisMark::DoubleCircle:
3387         m_value.valueID = CSSValueDoubleCircle;
3388         break;
3389     case TextEmphasisMark::Triangle:
3390         m_value.valueID = CSSValueTriangle;
3391         break;
3392     case TextEmphasisMark::Sesame:
3393         m_value.valueID = CSSValueSesame;
3394         break;
3395     case TextEmphasisMark::None:
3396     case TextEmphasisMark::Auto:
3397     case TextEmphasisMark::Custom:
3398         ASSERT_NOT_REACHED();
3399         m_value.valueID = CSSValueNone;
3400         break;
3401     }
3402 }
3403
3404 template<> inline CSSPrimitiveValue::operator TextEmphasisMark() const
3405 {
3406     ASSERT(isValueID());
3407
3408     switch (m_value.valueID) {
3409     case CSSValueNone:
3410         return TextEmphasisMark::None;
3411     case CSSValueDot:
3412         return TextEmphasisMark::Dot;
3413     case CSSValueCircle:
3414         return TextEmphasisMark::Circle;
3415     case CSSValueDoubleCircle:
3416         return TextEmphasisMark::DoubleCircle;
3417     case CSSValueTriangle:
3418         return TextEmphasisMark::Triangle;
3419     case CSSValueSesame:
3420         return TextEmphasisMark::Sesame;
3421     default:
3422         break;
3423     }
3424
3425     ASSERT_NOT_REACHED();
3426     return TextEmphasisMark::None;
3427 }
3428
3429 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextOrientation e)
3430     : CSSValue(PrimitiveClass)
3431 {
3432     m_primitiveUnitType = CSS_VALUE_ID;
3433     switch (e) {
3434     case TextOrientation::Sideways:
3435         m_value.valueID = CSSValueSideways;
3436         break;
3437     case TextOrientation::Mixed:
3438         m_value.valueID = CSSValueMixed;
3439         break;
3440     case TextOrientation::Upright:
3441         m_value.valueID = CSSValueUpright;
3442         break;
3443     }
3444 }
3445
3446 template<> inline CSSPrimitiveValue::operator TextOrientation() const
3447 {
3448     ASSERT(isValueID());
3449
3450     switch (m_value.valueID) {
3451     case CSSValueSideways:
3452         return TextOrientation::Sideways;
3453     case CSSValueSidewaysRight:
3454         return TextOrientation::Sideways;
3455     case CSSValueVerticalRight:
3456         return TextOrientation::Mixed;
3457     case CSSValueMixed:
3458         return TextOrientation::Mixed;
3459     case CSSValueUpright:
3460         return TextOrientation::Upright;
3461     default:
3462         break;
3463     }
3464
3465     ASSERT_NOT_REACHED();
3466     return TextOrientation::Mixed;
3467 }
3468
3469 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(PointerEvents e)
3470     : CSSValue(PrimitiveClass)
3471 {
3472     m_primitiveUnitType = CSS_VALUE_ID;
3473     switch (e) {
3474     case PointerEvents::None:
3475         m_value.valueID = CSSValueNone;
3476         break;
3477     case PointerEvents::Stroke:
3478         m_value.valueID = CSSValueStroke;
3479         break;
3480     case PointerEvents::Fill:
3481         m_value.valueID = CSSValueFill;
3482         break;
3483     case PointerEvents::Painted:
3484         m_value.valueID = CSSValuePainted;
3485         break;
3486     case PointerEvents::Visible:
3487         m_value.valueID = CSSValueVisible;
3488         break;
3489     case PointerEvents::VisibleStroke:
3490         m_value.valueID = CSSValueVisibleStroke;
3491         break;
3492     case PointerEvents::VisibleFill:
3493         m_value.valueID = CSSValueVisibleFill;
3494         break;
3495     case PointerEvents::VisiblePainted:
3496         m_value.valueID = CSSValueVisiblePainted;
3497         break;
3498     case PointerEvents::Auto:
3499         m_value.valueID = CSSValueAuto;
3500         break;
3501     case PointerEvents::All:
3502         m_value.valueID = CSSValueAll;
3503         break;
3504     }
3505 }
3506
3507 template<> inline CSSPrimitiveValue::operator PointerEvents() const
3508 {
3509     ASSERT(isValueID());
3510
3511     switch (m_value.valueID) {
3512     case CSSValueAll:
3513         return PointerEvents::All;
3514     case CSSValueAuto:
3515         return PointerEvents::Auto;
3516     case CSSValueNone:
3517         return PointerEvents::None;
3518     case CSSValueVisiblePainted:
3519         return PointerEvents::VisiblePainted;
3520     case CSSValueVisibleFill:
3521         return PointerEvents::VisibleFill;
3522     case CSSValueVisibleStroke:
3523         return PointerEvents::VisibleStroke;
3524     case CSSValueVisible:
3525         return PointerEvents::Visible;
3526     case CSSValuePainted:
3527         return PointerEvents::Painted;
3528     case CSSValueFill:
3529         return PointerEvents::Fill;
3530     case CSSValueStroke:
3531         return PointerEvents::Stroke;
3532     default:
3533         break;
3534     }
3535
3536     ASSERT_NOT_REACHED();
3537     return PointerEvents::All;
3538 }
3539
3540 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(Kerning kerning)
3541     : CSSValue(PrimitiveClass)
3542 {
3543     m_primitiveUnitType = CSS_VALUE_ID;
3544     switch (kerning) {
3545     case Kerning::Auto:
3546         m_value.valueID = CSSValueAuto;
3547         return;
3548     case Kerning::Normal:
3549         m_value.valueID = CSSValueNormal;
3550         return;
3551     case Kerning::NoShift:
3552         m_value.valueID = CSSValueNone;
3553         return;
3554     }
3555
3556     ASSERT_NOT_REACHED();
3557     m_value.valueID = CSSValueAuto;
3558 }
3559
3560 template<> inline CSSPrimitiveValue::operator Kerning() const
3561 {
3562     ASSERT(isValueID());
3563
3564     switch (m_value.valueID) {
3565     case CSSValueAuto:
3566         return Kerning::Auto;
3567     case CSSValueNormal:
3568         return Kerning::Normal;
3569     case CSSValueNone:
3570         return Kerning::NoShift;
3571     default:
3572         break;
3573     }
3574
3575     ASSERT_NOT_REACHED();
3576     return Kerning::Auto;
3577 }
3578
3579 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ObjectFit fit)