https://bugs.webkit.org/show_bug.cgi?id=80322
[WebKit-https.git] / Source / WebCore / css / CSSParser.cpp
1 /*
2  * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
4  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
5  * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
6  * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
7  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #include "config.h"
26 #include "CSSParser.h"
27
28 #include "CSSAspectRatioValue.h"
29 #include "CSSBorderImage.h"
30 #include "CSSCanvasValue.h"
31 #include "CSSCharsetRule.h"
32 #include "CSSCrossfadeValue.h"
33 #include "CSSCursorImageValue.h"
34 #include "CSSFlexValue.h"
35 #include "CSSFontFaceRule.h"
36 #include "CSSFontFaceSrcValue.h"
37 #include "CSSFunctionValue.h"
38 #include "CSSGradientValue.h"
39 #if ENABLE(CSS_IMAGE_SET)
40 #include "CSSImageSetValue.h"
41 #endif
42 #include "CSSImageValue.h"
43 #include "CSSImportRule.h"
44 #include "CSSInheritedValue.h"
45 #include "CSSInitialValue.h"
46 #include "CSSLineBoxContainValue.h"
47 #include "CSSMediaRule.h"
48 #include "CSSPageRule.h"
49 #include "CSSPrimitiveValue.h"
50 #include "CSSProperty.h"
51 #include "CSSPropertyNames.h"
52 #include "CSSPropertySourceData.h"
53 #include "CSSReflectValue.h"
54 #include "CSSRuleList.h"
55 #include "CSSSelector.h"
56 #include "CSSStyleRule.h"
57 #include "CSSStyleSheet.h"
58 #include "CSSTimingFunctionValue.h"
59 #include "CSSUnicodeRangeValue.h"
60 #include "CSSValueKeywords.h"
61 #include "CSSValueList.h"
62 #include "CSSValuePool.h"
63 #include "CSSWrapShapes.h"
64 #include "Counter.h"
65 #include "Document.h"
66 #include "FloatConversion.h"
67 #include "FontFeatureValue.h"
68 #include "FontValue.h"
69 #include "HTMLParserIdioms.h"
70 #include "HashTools.h"
71 #include "MediaList.h"
72 #include "MediaQueryExp.h"
73 #include "Page.h"
74 #include "Pair.h"
75 #include "Rect.h"
76 #include "RenderTheme.h"
77 #include "Settings.h"
78 #include "ShadowValue.h"
79 #include "StylePropertySet.h"
80 #include "StyleRule.h"
81 #if ENABLE(CSS_FILTERS)
82 #include "WebKitCSSFilterValue.h"
83 #endif
84 #include "WebKitCSSKeyframeRule.h"
85 #include "WebKitCSSKeyframesRule.h"
86 #include "WebKitCSSRegionRule.h"
87 #include "WebKitCSSTransformValue.h"
88 #if ENABLE(CSS_SHADERS)
89 #include "WebKitCSSShaderValue.h"
90 #endif
91 #include <limits.h>
92 #include <wtf/HexNumber.h>
93 #include <wtf/dtoa.h>
94 #include <wtf/text/StringBuffer.h>
95 #include <wtf/text/StringBuilder.h>
96
97 #if ENABLE(DASHBOARD_SUPPORT)
98 #include "DashboardRegion.h"
99 #endif
100
101 #define YYDEBUG 0
102
103 #if YYDEBUG > 0
104 extern int cssyydebug;
105 #endif
106
107 extern int cssyyparse(void* parser);
108
109 using namespace std;
110 using namespace WTF;
111
112 namespace {
113
114 enum PropertyType {
115     PropertyExplicit,
116     PropertyImplicit
117 };
118
119 class ImplicitScope {
120     WTF_MAKE_NONCOPYABLE(ImplicitScope);
121 public:
122     ImplicitScope(WebCore::CSSParser* parser, PropertyType propertyType)
123         : m_parser(parser)
124     {
125         m_parser->m_implicitShorthand = propertyType == PropertyImplicit;
126     }
127
128     ~ImplicitScope()
129     {
130         m_parser->m_implicitShorthand = false;
131     }
132
133 private:
134     WebCore::CSSParser* m_parser;
135 };
136
137 } // namespace
138
139 namespace WebCore {
140
141 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
142 static const double MAX_SCALE = 1000000;
143
144 static bool equal(const CSSParserString& a, const char* b)
145 {
146     for (int i = 0; i < a.length; ++i) {
147         if (!b[i])
148             return false;
149         if (a.characters[i] != b[i])
150             return false;
151     }
152     return !b[a.length];
153 }
154
155 static bool equalIgnoringCase(const CSSParserString& a, const char* b)
156 {
157     for (int i = 0; i < a.length; ++i) {
158         if (!b[i])
159             return false;
160         ASSERT(!isASCIIUpper(b[i]));
161         if (toASCIILower(a.characters[i]) != b[i])
162             return false;
163     }
164     return !b[a.length];
165 }
166
167 static bool hasPrefix(const char* string, unsigned length, const char* prefix)
168 {
169     for (unsigned i = 0; i < length; ++i) {
170         if (!prefix[i])
171             return true;
172         if (string[i] != prefix[i])
173             return false;
174     }
175     return false;
176 }
177
178 inline void CSSParser::ensureCSSValuePool()
179 {
180     if (!m_cssValuePool)
181         m_cssValuePool = CSSValuePool::create();
182 }
183
184 CSSParser::CSSParser(bool strictParsing)
185     : m_strict(strictParsing)
186     , m_important(false)
187     , m_id(0)
188     , m_styleSheet(0)
189     , m_inParseShorthand(0)
190     , m_currentShorthand(0)
191     , m_implicitShorthand(false)
192     , m_hasFontFaceOnlyValues(false)
193     , m_hadSyntacticallyValidCSSRule(false)
194     , m_defaultNamespace(starAtom)
195     , m_inStyleRuleOrDeclaration(false)
196     , m_selectorListRange(0, 0)
197     , m_ruleBodyRange(0, 0)
198     , m_propertyRange(UINT_MAX, UINT_MAX)
199     , m_ruleRangeMap(0)
200     , m_currentRuleData(0)
201     , m_parsingMode(NormalMode)
202     , m_currentCharacter(0)
203     , m_token(0)
204     , m_lineNumber(0)
205     , m_lastSelectorLineNumber(0)
206     , m_allowImportRules(true)
207     , m_allowNamespaceDeclarations(true)
208 {
209 #if YYDEBUG > 0
210     cssyydebug = 1;
211 #endif
212     CSSPropertySourceData::init();
213 }
214
215 CSSParser::~CSSParser()
216 {
217     clearProperties();
218
219     fastDeleteAllValues(m_floatingSelectors);
220     deleteAllValues(m_floatingSelectorVectors);
221     deleteAllValues(m_floatingValueLists);
222     deleteAllValues(m_floatingFunctions);
223 }
224
225 void CSSParserString::lower()
226 {
227     // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
228     // that can potentially change the length of the string rather than the character
229     // by character kind. If we don't need Unicode lowercasing, it would be good to
230     // simplify this function.
231
232     if (charactersAreAllASCII(characters, length)) {
233         // Fast case for all-ASCII.
234         for (int i = 0; i < length; i++)
235             characters[i] = toASCIILower(characters[i]);
236     } else {
237         for (int i = 0; i < length; i++)
238             characters[i] = Unicode::toLower(characters[i]);
239     }
240 }
241
242 void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix)
243 {
244     int length = string.length() + strlen(prefix) + strlen(suffix) + 1;
245
246     m_dataStart = adoptArrayPtr(new UChar[length]);
247     for (unsigned i = 0; i < strlen(prefix); i++)
248         m_dataStart[i] = prefix[i];
249
250     memcpy(m_dataStart.get() + strlen(prefix), string.characters(), string.length() * sizeof(UChar));
251
252     unsigned start = strlen(prefix) + string.length();
253     unsigned end = start + strlen(suffix);
254     for (unsigned i = start; i < end; i++)
255         m_dataStart[i] = suffix[i - start];
256
257     m_dataStart[length - 1] = 0;
258
259     m_currentCharacter = m_tokenStart = m_dataStart.get();
260     resetRuleBodyMarks();
261 }
262
263 void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string, int startLineNumber, StyleRuleRangeMap* ruleRangeMap)
264 {
265     setStyleSheet(sheet);
266     m_defaultNamespace = starAtom; // Reset the default namespace.
267     m_ruleRangeMap = ruleRangeMap;
268     if (ruleRangeMap) {
269         m_currentRuleData = CSSRuleSourceData::create();
270         m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
271     }
272
273     m_lineNumber = startLineNumber;
274     setupParser("", string, "");
275     cssyyparse(this);
276     m_ruleRangeMap = 0;
277     m_currentRuleData = 0;
278     m_rule = 0;
279 }
280
281 PassRefPtr<CSSRule> CSSParser::parseRule(CSSStyleSheet* sheet, const String& string)
282 {
283     setStyleSheet(sheet);
284     m_allowNamespaceDeclarations = false;
285     setupParser("@-webkit-rule{", string, "} ");
286     cssyyparse(this);
287     return m_rule.release();
288 }
289
290 PassRefPtr<WebKitCSSKeyframeRule> CSSParser::parseKeyframeRule(CSSStyleSheet *sheet, const String &string)
291 {
292     setStyleSheet(sheet);
293     setupParser("@-webkit-keyframe-rule{ ", string, "} ");
294     cssyyparse(this);
295     return m_keyframe.release();
296 }
297
298 static inline bool isColorPropertyID(int propertyId)
299 {
300     switch (propertyId) {
301     case CSSPropertyColor:
302     case CSSPropertyBackgroundColor:
303     case CSSPropertyBorderBottomColor:
304     case CSSPropertyBorderLeftColor:
305     case CSSPropertyBorderRightColor:
306     case CSSPropertyBorderTopColor:
307     case CSSPropertyOutlineColor:
308     case CSSPropertyTextLineThroughColor:
309     case CSSPropertyTextOverlineColor:
310     case CSSPropertyTextUnderlineColor:
311     case CSSPropertyWebkitBorderAfterColor:
312     case CSSPropertyWebkitBorderBeforeColor:
313     case CSSPropertyWebkitBorderEndColor:
314     case CSSPropertyWebkitBorderStartColor:
315     case CSSPropertyWebkitColumnRuleColor:
316     case CSSPropertyWebkitTextEmphasisColor:
317     case CSSPropertyWebkitTextFillColor:
318     case CSSPropertyWebkitTextStrokeColor:
319         return true;
320     default:
321         return false;
322     }
323 }
324
325 static bool parseColorValue(StylePropertySet* declaration, int propertyId, const String& string, bool important, bool strict, CSSStyleSheet* contextStyleSheet)
326 {
327     if (!string.length())
328         return false;
329     if (!isColorPropertyID(propertyId))
330         return false;
331     CSSParserString cssString;
332     cssString.characters = const_cast<UChar*>(string.characters());
333     cssString.length = string.length();
334     int valueID = cssValueKeywordID(cssString);
335     bool validPrimitive = false;
336     if (valueID == CSSValueWebkitText)
337         validPrimitive = true;
338     else if (valueID == CSSValueCurrentcolor)
339         validPrimitive = true;
340     else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
341              || (valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText && !strict)) {
342         validPrimitive = true;
343     }
344
345     Document* document = contextStyleSheet->findDocument();
346     if (validPrimitive) {
347         RefPtr<CSSValue> value;
348         if (document)
349             value = document->cssValuePool()->createIdentifierValue(valueID);
350         else
351             value = CSSPrimitiveValue::createIdentifier(valueID);
352         declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
353         return true;
354     }
355     RGBA32 color;
356     if (!CSSParser::fastParseColor(color, string, strict && string[0] != '#'))
357         return false;
358     RefPtr<CSSValue> value;
359     if (document)
360         value = document->cssValuePool()->createColorValue(color);
361     else
362         value = CSSPrimitiveValue::createColor(color);
363     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
364     return true;
365 }
366
367 static inline bool isSimpleLengthPropertyID(int propertyId, bool& acceptsNegativeNumbers)
368 {
369     switch (propertyId) {
370     case CSSPropertyFontSize:
371     case CSSPropertyHeight:
372     case CSSPropertyWidth:
373     case CSSPropertyMinHeight:
374     case CSSPropertyMinWidth:
375     case CSSPropertyPaddingBottom:
376     case CSSPropertyPaddingLeft:
377     case CSSPropertyPaddingRight:
378     case CSSPropertyPaddingTop:
379     case CSSPropertyWebkitLogicalWidth:
380     case CSSPropertyWebkitLogicalHeight:
381     case CSSPropertyWebkitMinLogicalWidth:
382     case CSSPropertyWebkitMinLogicalHeight:
383     case CSSPropertyWebkitPaddingAfter:
384     case CSSPropertyWebkitPaddingBefore:
385     case CSSPropertyWebkitPaddingEnd:
386     case CSSPropertyWebkitPaddingStart:
387     case CSSPropertyWebkitWrapMargin:
388     case CSSPropertyWebkitWrapPadding:
389         acceptsNegativeNumbers = false;
390         return true;
391     case CSSPropertyBottom:
392     case CSSPropertyLeft:
393     case CSSPropertyMarginBottom:
394     case CSSPropertyMarginLeft:
395     case CSSPropertyMarginRight:
396     case CSSPropertyMarginTop:
397     case CSSPropertyRight:
398     case CSSPropertyTextIndent:
399     case CSSPropertyTop:
400     case CSSPropertyWebkitMarginAfter:
401     case CSSPropertyWebkitMarginBefore:
402     case CSSPropertyWebkitMarginEnd:
403     case CSSPropertyWebkitMarginStart:
404         acceptsNegativeNumbers = true;
405         return true;
406     default:
407         return false;
408     }
409 }
410
411 static bool parseSimpleLengthValue(StylePropertySet* declaration, int propertyId, const String& string, bool important, bool strict, CSSStyleSheet* contextStyleSheet)
412 {
413     bool acceptsNegativeNumbers;
414     unsigned length = string.length();
415
416     if (!length)
417         return false;
418
419     double number;
420     bool ok;
421     CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
422
423     if (string.is8Bit()) {
424         const LChar* characters8 = string.characters8();
425         if (!characters8)
426             return false;
427
428         if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
429             return false;
430
431         if (length > 2 && (characters8[length - 2] | 0x20) == 'p' && (characters8[length - 1] | 0x20) == 'x') {
432             length -= 2;
433             unit = CSSPrimitiveValue::CSS_PX;
434         } else if (length > 1 && characters8[length - 1] == '%') {
435             length -= 1;
436             unit = CSSPrimitiveValue::CSS_PERCENTAGE;
437         }
438
439         // We rely on charactersToDouble for validation as well. The function
440         // will set "ok" to "false" if the entire passed-in character range does
441         // not represent a double.
442         number = charactersToDouble(characters8, length, &ok);
443     } else {
444         const UChar* characters16 = string.characters16();
445         if (!characters16)
446             return false;
447
448         if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
449             return false;
450
451         if (length > 2 && (characters16[length - 2] | 0x20) == 'p' && (characters16[length - 1] | 0x20) == 'x') {
452             length -= 2;
453             unit = CSSPrimitiveValue::CSS_PX;
454         } else if (length > 1 && characters16[length - 1] == '%') {
455             length -= 1;
456             unit = CSSPrimitiveValue::CSS_PERCENTAGE;
457         }
458
459         // We rely on charactersToDouble for validation as well. The function
460         // will set "ok" to "false" if the entire passed-in character range does
461         // not represent a double.
462         number = charactersToDouble(characters16, length, &ok);
463     }
464
465     if (!ok)
466         return false;
467     if (unit == CSSPrimitiveValue::CSS_NUMBER) {
468         if (number && strict)
469             return false;
470         unit = CSSPrimitiveValue::CSS_PX;
471     }
472     if (number < 0 && !acceptsNegativeNumbers)
473         return false;
474
475     Document* document = contextStyleSheet->findDocument();
476     RefPtr<CSSValue> value;
477     if (document)
478         value = document->cssValuePool()->createValue(number, unit);
479     else
480         value = CSSPrimitiveValue::create(number, unit);
481     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
482     return true;
483 }
484
485 static inline bool isValidKeywordPropertyAndValue(int propertyId, int valueID)
486 {
487     if (!valueID)
488         return false;
489
490     switch (propertyId) {
491     case CSSPropertyBorderCollapse: // collapse | separate | inherit
492         if (valueID == CSSValueCollapse || valueID == CSSValueSeparate)
493             return true;
494         break;
495     case CSSPropertyBorderTopStyle: // <border-style> | inherit
496     case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
497     case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
498     case CSSPropertyBorderLeftStyle:
499     case CSSPropertyWebkitBorderAfterStyle:
500     case CSSPropertyWebkitBorderBeforeStyle:
501     case CSSPropertyWebkitBorderEndStyle:
502     case CSSPropertyWebkitBorderStartStyle:
503     case CSSPropertyWebkitColumnRuleStyle:
504         if (valueID >= CSSValueNone && valueID <= CSSValueDouble)
505             return true;
506         break;
507     case CSSPropertyBoxSizing:
508          if (valueID == CSSValueBorderBox || valueID == CSSValueContentBox)
509              return true;
510          break;
511     case CSSPropertyCaptionSide: // top | bottom | left | right | inherit
512         if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom)
513             return true;
514         break;
515     case CSSPropertyClear: // none | left | right | both | inherit
516         if (valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth)
517             return true;
518         break;
519     case CSSPropertyDirection: // ltr | rtl | inherit
520         if (valueID == CSSValueLtr || valueID == CSSValueRtl)
521             return true;
522         break;
523     case CSSPropertyDisplay:
524         // inline | block | list-item | run-in | inline-block | table |
525         // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
526         // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none | inherit
527         // -webkit-flexbox | -webkit-inline-flexbox | -webkit-grid | -webkit-inline-grid
528         if ((valueID >= CSSValueInline && valueID <= CSSValueWebkitInlineFlexbox) || valueID == CSSValueNone)
529             return true;
530 #if ENABLE(CSS_GRID_LAYOUT)
531         if (valueID == CSSValueWebkitGrid || valueID == CSSValueWebkitInlineGrid)
532             return true;
533         break;
534 #endif
535     case CSSPropertyEmptyCells: // show | hide | inherit
536         if (valueID == CSSValueShow || valueID == CSSValueHide)
537             return true;
538         break;
539     case CSSPropertyFloat: // left | right | none | positioned | center (for buggy CSS, maps to none)
540         if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter || valueID == CSSValueWebkitPositioned)
541             return true;
542         break;
543     case CSSPropertyFontStyle: // normal | italic | oblique | inherit
544         if (valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique)
545             return true;
546         break;
547     case CSSPropertyImageRendering: // auto | optimizeContrast
548         if (valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast)
549             return true;
550         break;
551     case CSSPropertyListStylePosition: // inside | outside | inherit
552         if (valueID == CSSValueInside || valueID == CSSValueOutside)
553             return true;
554         break;
555     case CSSPropertyListStyleType:
556         // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
557         // for the list of supported list-style-types.
558         if ((valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone)
559             return true;
560         break;
561     case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto | inherit
562         if (valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble))
563             return true;
564         break;
565     case CSSPropertyOverflowX:
566     case CSSPropertyOverflowY: // visible | hidden | scroll | auto | marquee | overlay | inherit
567         if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitMarquee)
568             return true;
569         break;
570     case CSSPropertyPointerEvents:
571         // none | visiblePainted | visibleFill | visibleStroke | visible |
572         // painted | fill | stroke | auto | all | inherit
573         if (valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueStroke))
574             return true;
575         break;
576     case CSSPropertyPosition: // static | relative | absolute | fixed | inherit
577         if (valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed)
578             return true;
579         break;
580     case CSSPropertyResize: // none | both | horizontal | vertical | auto
581         if (valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto)
582             return true;
583         break;
584     case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation | inherit
585         if (valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation)
586             return true;
587         break;
588     case CSSPropertyTableLayout: // auto | fixed | inherit
589         if (valueID == CSSValueAuto || valueID == CSSValueFixed)
590             return true;
591         break;
592     case CSSPropertyTextLineThroughMode:
593     case CSSPropertyTextOverlineMode:
594     case CSSPropertyTextUnderlineMode:
595         if (valueID == CSSValueContinuous || valueID == CSSValueSkipWhiteSpace)
596             return true;
597         break;
598     case CSSPropertyTextLineThroughStyle:
599     case CSSPropertyTextOverlineStyle:
600     case CSSPropertyTextUnderlineStyle:
601         if (valueID == CSSValueNone || valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDashed || valueID == CSSValueDotDash || valueID == CSSValueDotDotDash || valueID == CSSValueWave)
602             return true;
603         break;
604     case CSSPropertyTextOverflow: // clip | ellipsis
605         if (valueID == CSSValueClip || valueID == CSSValueEllipsis)
606             return true;
607         break;
608     case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
609         if (valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision)
610             return true;
611         break;
612     case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none | inherit
613         if ((valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone)
614             return true;
615         break;
616     case CSSPropertyVisibility: // visible | hidden | collapse | inherit
617         if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse)
618             return true;
619         break;
620     case CSSPropertyWebkitAppearance:
621         if ((valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone)
622             return true;
623         break;
624     case CSSPropertyWebkitBackfaceVisibility:
625         if (valueID == CSSValueVisible || valueID == CSSValueHidden)
626             return true;
627         break;
628     case CSSPropertyWebkitBorderFit:
629         if (valueID == CSSValueBorder || valueID == CSSValueLines)
630             return true;
631         break;
632     case CSSPropertyWebkitBoxAlign:
633         if (valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline)
634             return true;
635         break;
636     case CSSPropertyWebkitBoxDirection:
637         if (valueID == CSSValueNormal || valueID == CSSValueReverse)
638             return true;
639         break;
640     case CSSPropertyWebkitBoxLines:
641         if (valueID == CSSValueSingle || valueID == CSSValueMultiple)
642                 return true;
643         break;
644     case CSSPropertyWebkitBoxOrient:
645         if (valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis)
646             return true;
647         break;
648     case CSSPropertyWebkitBoxPack:
649         if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify)
650             return true;
651         break;
652     case CSSPropertyWebkitColorCorrection:
653         if (valueID == CSSValueSrgb || valueID == CSSValueDefault)
654             return true;
655         break;
656     case CSSPropertyWebkitFlexAlign:
657         if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
658             return true;
659         break;
660     case CSSPropertyWebkitFlexDirection:
661         if (valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse)
662                 return true;
663         break;
664     case CSSPropertyWebkitFlexItemAlign:
665         if (valueID == CSSValueAuto || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
666             return true;
667         break;
668     case CSSPropertyWebkitFlexLinePack:
669          if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify || valueID == CSSValueDistribute || valueID == CSSValueStretch)
670              return true;
671          break;
672     case CSSPropertyWebkitFlexPack:
673         if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify || valueID == CSSValueDistribute)
674             return true;
675         break;
676     case CSSPropertyWebkitFlexWrap:
677         if (valueID == CSSValueNone || valueID == CSSValueWrap || valueID == CSSValueWrapReverse)
678              return true;
679         break;
680     case CSSPropertyWebkitFontKerning:
681         if (valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone)
682             return true;
683         break;
684     case CSSPropertyWebkitFontSmoothing:
685         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased)
686             return true;
687         break;
688     case CSSPropertyWebkitHyphens:
689         if (valueID == CSSValueNone || valueID == CSSValueManual || valueID == CSSValueAuto)
690             return true;
691         break;
692     case CSSPropertyWebkitLineAlign:
693         if (valueID == CSSValueNone || valueID == CSSValueEdges)
694             return true;
695         break;
696     case CSSPropertyWebkitLineBreak: // normal | after-white-space
697         if (valueID == CSSValueNormal || valueID == CSSValueAfterWhiteSpace)
698             return true;
699         break;
700     case CSSPropertyWebkitLineSnap:
701         if (valueID == CSSValueNone || valueID == CSSValueBaseline || valueID == CSSValueContain)
702             return true;
703         break;
704     case CSSPropertyWebkitMarginAfterCollapse:
705     case CSSPropertyWebkitMarginBeforeCollapse:
706     case CSSPropertyWebkitMarginBottomCollapse:
707     case CSSPropertyWebkitMarginTopCollapse:
708         if (valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard)
709             return true;
710         break;
711     case CSSPropertyWebkitMarqueeDirection:
712         if (valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
713             || valueID == CSSValueUp || valueID == CSSValueAuto)
714             return true;
715         break;
716     case CSSPropertyWebkitMarqueeStyle:
717         if (valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate)
718             return true;
719         break;
720     case CSSPropertyWebkitMatchNearestMailBlockquoteColor: // normal | match
721         if (valueID == CSSValueNormal || valueID == CSSValueMatch)
722             return true;
723         break;
724     case CSSPropertyWebkitNbspMode: // normal | space
725         if (valueID == CSSValueNormal || valueID == CSSValueSpace)
726             return true;
727         break;
728 #if ENABLE(OVERFLOW_SCROLLING)
729     case CSSPropertyWebkitOverflowScrolling:
730         if (valueID == CSSValueAuto || valueID == CSSValueTouch)
731             return true;
732         break;
733 #endif
734     case CSSPropertyWebkitPrintColorAdjust:
735         if (valueID == CSSValueExact || valueID == CSSValueEconomy)
736             return true;
737         break;
738     case CSSPropertyWebkitRtlOrdering:
739         if (valueID == CSSValueLogical || valueID == CSSValueVisual)
740             return true;
741         break;
742     case CSSPropertyWebkitTextCombine:
743         if (valueID == CSSValueNone || valueID == CSSValueHorizontal)
744             return true;
745         break;
746     case CSSPropertyWebkitTextEmphasisPosition:
747         if (valueID == CSSValueOver || valueID == CSSValueUnder)
748             return true;
749         break;
750     case CSSPropertyWebkitTextSecurity:
751         // disc | circle | square | none | inherit
752         if (valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone)
753             return true;
754         break;
755     case CSSPropertyWebkitTextSizeAdjust:
756         if (valueID == CSSValueAuto || valueID == CSSValueNone)
757             return true;
758         break;
759     case CSSPropertyWebkitTransformStyle:
760         if (valueID == CSSValueFlat || valueID == CSSValuePreserve3d)
761             return true;
762         break;
763     case CSSPropertyWebkitUserDrag: // auto | none | element
764         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement)
765             return true;
766         break;
767     case CSSPropertyWebkitUserModify: // read-only | read-write
768         if (valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly)
769             return true;
770         break;
771     case CSSPropertyWebkitUserSelect: // auto | none | text
772         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText)
773             return true;
774         break;
775     case CSSPropertyWebkitWrapFlow:
776         if (valueID == CSSValueAuto || valueID == CSSValueBoth || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueMaximum || valueID == CSSValueClear)
777             return true;
778         break;
779     case CSSPropertyWebkitWrapThrough:
780         if (valueID == CSSValueWrap || valueID == CSSValueNone)
781             return true;
782         break;
783     case CSSPropertyWebkitWritingMode:
784         if (valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt)
785             return true;
786         break;
787     case CSSPropertyWhiteSpace: // normal | pre | nowrap | inherit
788         if (valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap)
789             return true;
790         break;
791     case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
792         if (valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord)
793             return true;
794         break;
795     case CSSPropertyWordWrap: // normal | break-word
796         if (valueID == CSSValueNormal || valueID == CSSValueBreakWord)
797             return true;
798         break;
799     default:
800         ASSERT_NOT_REACHED();
801         return false;
802     }
803     return false;
804 }
805
806 static inline bool isKeywordPropertyID(int propertyId)
807 {
808     switch (propertyId) {
809     case CSSPropertyBorderBottomStyle:
810     case CSSPropertyBorderCollapse:
811     case CSSPropertyBorderLeftStyle:
812     case CSSPropertyBorderRightStyle:
813     case CSSPropertyBorderTopStyle:
814     case CSSPropertyBoxSizing:
815     case CSSPropertyCaptionSide:
816     case CSSPropertyClear:
817     case CSSPropertyDirection:
818     case CSSPropertyDisplay:
819     case CSSPropertyEmptyCells:
820     case CSSPropertyFloat:
821     case CSSPropertyFontStyle:
822     case CSSPropertyImageRendering:
823     case CSSPropertyListStylePosition:
824     case CSSPropertyListStyleType:
825     case CSSPropertyOutlineStyle:
826     case CSSPropertyOverflowX:
827     case CSSPropertyOverflowY:
828     case CSSPropertyPointerEvents:
829     case CSSPropertyPosition:
830     case CSSPropertyResize:
831     case CSSPropertySpeak:
832     case CSSPropertyTableLayout:
833     case CSSPropertyTextLineThroughMode:
834     case CSSPropertyTextLineThroughStyle:
835     case CSSPropertyTextOverflow:
836     case CSSPropertyTextOverlineMode:
837     case CSSPropertyTextOverlineStyle:
838     case CSSPropertyTextRendering:
839     case CSSPropertyTextTransform:
840     case CSSPropertyTextUnderlineMode:
841     case CSSPropertyTextUnderlineStyle:
842     case CSSPropertyVisibility:
843     case CSSPropertyWebkitAppearance:
844     case CSSPropertyWebkitBackfaceVisibility:
845     case CSSPropertyWebkitBorderAfterStyle:
846     case CSSPropertyWebkitBorderBeforeStyle:
847     case CSSPropertyWebkitBorderEndStyle:
848     case CSSPropertyWebkitBorderFit:
849     case CSSPropertyWebkitBorderStartStyle:
850     case CSSPropertyWebkitBoxAlign:
851     case CSSPropertyWebkitBoxDirection:
852     case CSSPropertyWebkitBoxLines:
853     case CSSPropertyWebkitBoxOrient:
854     case CSSPropertyWebkitBoxPack:
855     case CSSPropertyWebkitColorCorrection:
856     case CSSPropertyWebkitColumnRuleStyle:
857     case CSSPropertyWebkitFlexAlign:
858     case CSSPropertyWebkitFlexDirection:
859     case CSSPropertyWebkitFlexItemAlign:
860     case CSSPropertyWebkitFlexLinePack:
861     case CSSPropertyWebkitFlexPack:
862     case CSSPropertyWebkitFlexWrap:
863     case CSSPropertyWebkitFontKerning:
864     case CSSPropertyWebkitFontSmoothing:
865     case CSSPropertyWebkitHyphens:
866     case CSSPropertyWebkitLineAlign:
867     case CSSPropertyWebkitLineBreak:
868     case CSSPropertyWebkitLineSnap:
869     case CSSPropertyWebkitMarginAfterCollapse:
870     case CSSPropertyWebkitMarginBeforeCollapse:
871     case CSSPropertyWebkitMarginBottomCollapse:
872     case CSSPropertyWebkitMarginTopCollapse:
873     case CSSPropertyWebkitMarqueeDirection:
874     case CSSPropertyWebkitMarqueeStyle:
875     case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
876     case CSSPropertyWebkitNbspMode:
877 #if ENABLE(OVERFLOW_SCROLLING)
878     case CSSPropertyWebkitOverflowScrolling:
879 #endif
880     case CSSPropertyWebkitPrintColorAdjust:
881     case CSSPropertyWebkitRtlOrdering:
882     case CSSPropertyWebkitTextCombine:
883     case CSSPropertyWebkitTextEmphasisPosition:
884     case CSSPropertyWebkitTextSecurity:
885     case CSSPropertyWebkitTextSizeAdjust:
886     case CSSPropertyWebkitTransformStyle:
887     case CSSPropertyWebkitUserDrag:
888     case CSSPropertyWebkitUserModify:
889     case CSSPropertyWebkitUserSelect:
890     case CSSPropertyWebkitWrapFlow:
891     case CSSPropertyWebkitWrapThrough:
892     case CSSPropertyWebkitWritingMode:
893     case CSSPropertyWhiteSpace:
894     case CSSPropertyWordBreak:
895     case CSSPropertyWordWrap:
896         return true;
897     default:
898         return false;
899     }
900 }
901
902 static bool parseKeywordValue(StylePropertySet* declaration, int propertyId, const String& string, bool important, CSSStyleSheet* contextStyleSheet)
903 {
904     if (string.isEmpty())
905         return false;
906
907     if (!isKeywordPropertyID(propertyId))
908         return false;
909
910     CSSParserString cssString;
911     cssString.characters = const_cast<UChar*>(string.characters());
912     cssString.length = string.length();
913     int valueID = cssValueKeywordID(cssString);
914
915     if (!valueID)
916         return false;
917
918     Document* document = contextStyleSheet->findDocument();
919     RefPtr<CSSValue> value;
920     CSSValuePool* cssValuePool = document ? document->cssValuePool().get() : 0;
921     if (valueID == CSSValueInherit)
922         value = cssValuePool ? cssValuePool->createInheritedValue() : CSSInheritedValue::create();
923     else if (valueID == CSSValueInitial)
924         value = cssValuePool ? cssValuePool->createExplicitInitialValue() : CSSInitialValue::createExplicit();
925     else if (isValidKeywordPropertyAndValue(propertyId, valueID))
926         value = cssValuePool ? cssValuePool->createIdentifierValue(valueID) : CSSPrimitiveValue::createIdentifier(valueID);
927     else
928         return false;
929
930     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
931     return true;
932 }
933
934 PassRefPtr<CSSValueList> CSSParser::parseFontFaceValue(const AtomicString& string, CSSStyleSheet* contextStyleSheet)
935 {
936     RefPtr<StylePropertySet> dummyStyle = StylePropertySet::create();
937     if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, false, contextStyleSheet))
938         return 0;
939     return static_pointer_cast<CSSValueList>(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily));
940 }
941
942 bool CSSParser::parseValue(StylePropertySet* declaration, int propertyId, const String& string, bool important, bool strict, CSSStyleSheet* contextStyleSheet)
943 {
944     if (parseSimpleLengthValue(declaration, propertyId, string, important, strict, contextStyleSheet))
945         return true;
946     if (parseColorValue(declaration, propertyId, string, important, strict, contextStyleSheet))
947         return true;
948     if (parseKeywordValue(declaration, propertyId, string, important, contextStyleSheet))
949         return true;
950     CSSParser parser(strict);
951     return parser.parseValue(declaration, propertyId, string, important, contextStyleSheet);
952 }
953
954 bool CSSParser::parseValue(StylePropertySet* declaration, int propertyId, const String& string, bool important, CSSStyleSheet* contextStyleSheet)
955 {
956     setStyleSheet(contextStyleSheet);
957
958     setupParser("@-webkit-value{", string, "} ");
959
960     m_id = propertyId;
961     m_important = important;
962
963     cssyyparse(this);
964
965     m_rule = 0;
966
967     bool ok = false;
968     if (m_hasFontFaceOnlyValues)
969         deleteFontFaceOnlyValues();
970     if (!m_parsedProperties.isEmpty()) {
971         ok = true;
972         declaration->addParsedProperties(m_parsedProperties.data(), m_parsedProperties.size());
973         clearProperties();
974     }
975
976     return ok;
977 }
978
979 // The color will only be changed when string contains a valid CSS color, so callers
980 // can set it to a default color and ignore the boolean result.
981 bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict)
982 {
983     // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
984     if (fastParseColor(color, string, strict))
985         return true;
986
987     CSSParser parser(true);
988
989     // In case the fast-path parser didn't understand the color, try the full parser.
990     if (!parser.parseColor(string))
991         return false;
992
993     CSSValue* value = parser.m_parsedProperties.first().value();
994     if (!value->isPrimitiveValue())
995         return false;
996
997     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
998     if (!primitiveValue->isRGBColor())
999         return false;
1000
1001     color = primitiveValue->getRGBA32Value();
1002     return true;
1003 }
1004
1005 bool CSSParser::parseColor(const String& string)
1006 {
1007     // This function may be called without a stylesheet set on the parser, so we need to
1008     // make sure that we have a CSSValuePool or we'll crash below cssyyparse().
1009     ensureCSSValuePool();
1010
1011     setupParser("@-webkit-decls{color:", string, "} ");
1012     cssyyparse(this);
1013     m_rule = 0;
1014
1015     return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor;
1016 }
1017
1018 bool CSSParser::parseSystemColor(RGBA32& color, const String& string, Document* document)
1019 {
1020     if (!document || !document->page())
1021         return false;
1022
1023     CSSParserString cssColor;
1024     cssColor.characters = const_cast<UChar*>(string.characters());
1025     cssColor.length = string.length();
1026     int id = cssValueKeywordID(cssColor);
1027     if (id <= 0)
1028         return false;
1029
1030     color = document->page()->theme()->systemColor(id).rgb();
1031     return true;
1032 }
1033
1034 void CSSParser::parseSelector(const String& string, Document* doc, CSSSelectorList& selectorList)
1035 {
1036     RefPtr<CSSStyleSheet> dummyStyleSheet = CSSStyleSheet::create(doc);
1037
1038     setStyleSheet(dummyStyleSheet.get());
1039     m_selectorListForParseSelector = &selectorList;
1040
1041     setupParser("@-webkit-selector{", string, "}");
1042
1043     cssyyparse(this);
1044
1045     m_selectorListForParseSelector = 0;
1046
1047     // The style sheet will be deleted right away, so it won't outlive the document.
1048     ASSERT(dummyStyleSheet->hasOneRef());
1049 }
1050
1051 bool CSSParser::parseDeclaration(StylePropertySet* declaration, const String& string, RefPtr<CSSStyleSourceData>* styleSourceData, CSSStyleSheet* contextStyleSheet)
1052 {
1053     // Length of the "@-webkit-decls{" prefix.
1054     static const unsigned prefixLength = 15;
1055
1056     setStyleSheet(contextStyleSheet);
1057
1058     if (styleSourceData) {
1059         m_currentRuleData = CSSRuleSourceData::create();
1060         m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
1061         m_inStyleRuleOrDeclaration = true;
1062     }
1063
1064     setupParser("@-webkit-decls{", string, "} ");
1065     cssyyparse(this);
1066     m_rule = 0;
1067
1068     bool ok = false;
1069     if (m_hasFontFaceOnlyValues)
1070         deleteFontFaceOnlyValues();
1071     if (!m_parsedProperties.isEmpty()) {
1072         ok = true;
1073         declaration->addParsedProperties(m_parsedProperties.data(), m_parsedProperties.size());
1074         clearProperties();
1075     }
1076
1077     if (m_currentRuleData) {
1078         m_currentRuleData->styleSourceData->styleBodyRange.start = 0;
1079         m_currentRuleData->styleSourceData->styleBodyRange.end = string.length();
1080         for (Vector<CSSPropertySourceData>::iterator it = m_currentRuleData->styleSourceData->propertyData.begin(), endIt = m_currentRuleData->styleSourceData->propertyData.end(); it != endIt; ++it) {
1081             (*it).range.start -= prefixLength;
1082             (*it).range.end -= prefixLength;
1083         }
1084     }
1085
1086     if (styleSourceData) {
1087         *styleSourceData = m_currentRuleData->styleSourceData.release();
1088         m_currentRuleData = 0;
1089         m_inStyleRuleOrDeclaration = false;
1090     }
1091     return ok;
1092 }
1093
1094 bool CSSParser::parseMediaQuery(MediaList* queries, const String& string)
1095 {
1096     if (string.isEmpty())
1097         return true;
1098
1099     ASSERT(!m_mediaQuery);
1100
1101     // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
1102     // instead insert one " " (which is WHITESPACE in CSSGrammar.y)
1103     setupParser("@-webkit-mediaquery ", string, "} ");
1104     cssyyparse(this);
1105
1106     bool ok = false;
1107     if (m_mediaQuery) {
1108         ok = true;
1109         queries->appendMediaQuery(m_mediaQuery.release());
1110     }
1111
1112     return ok;
1113 }
1114
1115 void CSSParser::addProperty(int propId, PassRefPtr<CSSValue> value, bool important, bool implicit)
1116 {
1117     m_parsedProperties.append(CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand || implicit));
1118 }
1119
1120 void CSSParser::rollbackLastProperties(int num)
1121 {
1122     ASSERT(num >= 0);
1123     ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num));
1124     m_parsedProperties.shrink(m_parsedProperties.size() - num);
1125 }
1126
1127 void CSSParser::clearProperties()
1128 {
1129     m_parsedProperties.clear();
1130     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1131     m_hasFontFaceOnlyValues = false;
1132 }
1133
1134 void CSSParser::setStyleSheet(CSSStyleSheet* styleSheet)
1135 {
1136     m_styleSheet = styleSheet;
1137     Document* document = findDocument();
1138     m_cssValuePool = document ? document->cssValuePool() : CSSValuePool::create();
1139 }
1140
1141 Document* CSSParser::findDocument() const
1142 {
1143     if (!m_styleSheet)
1144         return 0;
1145     return m_styleSheet->findDocument();
1146 }
1147
1148 bool CSSParser::validCalculationUnit(CSSParserValue* value, Units unitflags)
1149 {
1150     bool mustBeNonNegative = unitflags & FNonNeg;
1151
1152     if (!parseCalculation(value, mustBeNonNegative ? CalculationRangeNonNegative : CalculationRangeAll))
1153         return false;
1154
1155     bool b = false;
1156     switch (m_parsedCalculation->category()) {
1157     case CalcLength:
1158         b = (unitflags & FLength);
1159         break;
1160     case CalcPercent:
1161         b = (unitflags & FPercent);
1162         if (b && mustBeNonNegative && m_parsedCalculation->isNegative())
1163             b = false;
1164         break;
1165     case CalcNumber:
1166         b = (unitflags & FNumber);
1167         if (!b && (unitflags & FInteger) && m_parsedCalculation->isInt())
1168             b = true;
1169         if (b && mustBeNonNegative && m_parsedCalculation->isNegative())
1170             b = false;
1171         break;
1172     case CalcPercentLength:
1173         b = (unitflags & FPercent) && (unitflags & FLength);
1174         break;
1175     case CalcPercentNumber:
1176         b = (unitflags & FPercent) && (unitflags & FNumber);
1177         break;
1178     case CalcOther:
1179         break;
1180     }
1181     if (!b)
1182         m_parsedCalculation.release();
1183     return b;    
1184 }
1185
1186 bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, bool strict)
1187 {
1188     if (isCalculation(value))
1189         return validCalculationUnit(value, unitflags);
1190         
1191     bool b = false;
1192     switch (value->unit) {
1193     case CSSPrimitiveValue::CSS_NUMBER:
1194         b = (unitflags & FNumber);
1195         if (!b && ((unitflags & (FLength | FAngle | FTime)) && (!value->fValue || !strict))) {
1196             value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX :
1197                           ((unitflags & FAngle) ? CSSPrimitiveValue::CSS_DEG : CSSPrimitiveValue::CSS_MS);
1198             b = true;
1199         }
1200         if (!b && (unitflags & FInteger) && value->isInt)
1201             b = true;
1202         break;
1203     case CSSPrimitiveValue::CSS_PERCENTAGE:
1204         b = (unitflags & FPercent);
1205         break;
1206     case CSSParserValue::Q_EMS:
1207     case CSSPrimitiveValue::CSS_EMS:
1208     case CSSPrimitiveValue::CSS_REMS:
1209     case CSSPrimitiveValue::CSS_EXS:
1210     case CSSPrimitiveValue::CSS_PX:
1211     case CSSPrimitiveValue::CSS_CM:
1212     case CSSPrimitiveValue::CSS_MM:
1213     case CSSPrimitiveValue::CSS_IN:
1214     case CSSPrimitiveValue::CSS_PT:
1215     case CSSPrimitiveValue::CSS_PC:
1216         b = (unitflags & FLength);
1217         break;
1218     case CSSPrimitiveValue::CSS_MS:
1219     case CSSPrimitiveValue::CSS_S:
1220         b = (unitflags & FTime);
1221         break;
1222     case CSSPrimitiveValue::CSS_DEG:
1223     case CSSPrimitiveValue::CSS_RAD:
1224     case CSSPrimitiveValue::CSS_GRAD:
1225     case CSSPrimitiveValue::CSS_TURN:
1226         b = (unitflags & FAngle);
1227         break;
1228     case CSSPrimitiveValue::CSS_HZ:
1229     case CSSPrimitiveValue::CSS_KHZ:
1230     case CSSPrimitiveValue::CSS_DIMENSION:
1231     default:
1232         break;
1233     }
1234     if (b && unitflags & FNonNeg && value->fValue < 0)
1235         b = false;
1236     return b;
1237 }
1238
1239 inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(CSSParserValue* value)
1240 {
1241     if (m_parsedCalculation) {
1242         ASSERT(isCalculation(value));
1243         return CSSPrimitiveValue::create(m_parsedCalculation.release());
1244     }
1245                
1246     ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1247            || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS));
1248     return cssValuePool()->createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit));
1249 }
1250
1251 inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveStringValue(CSSParserValue* value)
1252 {
1253     ASSERT(value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT);
1254     return cssValuePool()->createValue(value->string, CSSPrimitiveValue::CSS_STRING);
1255 }
1256
1257 static int unitFromString(CSSParserValue* value)
1258 {
1259     if (value->unit != CSSPrimitiveValue::CSS_IDENT || value->id)
1260         return 0;
1261
1262     if (equal(value->string, "em"))
1263         return CSSPrimitiveValue::CSS_EMS;
1264     if (equal(value->string, "rem"))
1265         return CSSPrimitiveValue::CSS_REMS;
1266     if (equal(value->string, "ex"))
1267         return CSSPrimitiveValue::CSS_EXS;
1268     if (equal(value->string, "px"))
1269         return CSSPrimitiveValue::CSS_PX;
1270     if (equal(value->string, "cm"))
1271         return CSSPrimitiveValue::CSS_CM;
1272     if (equal(value->string, "mm"))
1273         return CSSPrimitiveValue::CSS_MM;
1274     if (equal(value->string, "in"))
1275         return CSSPrimitiveValue::CSS_IN;
1276     if (equal(value->string, "pt"))
1277         return CSSPrimitiveValue::CSS_PT;
1278     if (equal(value->string, "pc"))
1279         return CSSPrimitiveValue::CSS_PC;
1280     if (equal(value->string, "deg"))
1281         return CSSPrimitiveValue::CSS_DEG;
1282     if (equal(value->string, "rad"))
1283         return CSSPrimitiveValue::CSS_RAD;
1284     if (equal(value->string, "grad"))
1285         return CSSPrimitiveValue::CSS_GRAD;
1286     if (equal(value->string, "turn"))
1287         return CSSPrimitiveValue::CSS_TURN;
1288     if (equal(value->string, "ms"))
1289         return CSSPrimitiveValue::CSS_MS;
1290     if (equal(value->string, "s"))
1291         return CSSPrimitiveValue::CSS_S;
1292     if (equal(value->string, "Hz"))
1293         return CSSPrimitiveValue::CSS_HZ;
1294     if (equal(value->string, "kHz"))
1295         return CSSPrimitiveValue::CSS_KHZ;
1296
1297     return 0;
1298 }
1299
1300 void CSSParser::checkForOrphanedUnits()
1301 {
1302     if (m_strict || inShorthand())
1303         return;
1304
1305     // The purpose of this code is to implement the WinIE quirk that allows unit types to be separated from their numeric values
1306     // by whitespace, so e.g., width: 20 px instead of width:20px.  This is invalid CSS, so we don't do this in strict mode.
1307     CSSParserValue* numericVal = 0;
1308     unsigned size = m_valueList->size();
1309     for (unsigned i = 0; i < size; i++) {
1310         CSSParserValue* value = m_valueList->valueAt(i);
1311
1312         if (numericVal) {
1313             // Change the unit type of the numeric val to match.
1314             int unit = unitFromString(value);
1315             if (unit) {
1316                 numericVal->unit = unit;
1317                 numericVal = 0;
1318
1319                 // Now delete the bogus unit value.
1320                 m_valueList->deleteValueAt(i);
1321                 i--; // We're safe even though |i| is unsigned, since we only hit this code if we had a previous numeric value (so |i| is always > 0 here).
1322                 size--;
1323                 continue;
1324             }
1325         }
1326
1327         numericVal = (value->unit == CSSPrimitiveValue::CSS_NUMBER) ? value : 0;
1328     }
1329 }
1330
1331 inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(int id, CSSParserValue* value)
1332 {
1333     if (id)
1334         return cssValuePool()->createIdentifierValue(id);
1335     if (value->unit == CSSPrimitiveValue::CSS_STRING)
1336         return createPrimitiveStringValue(value);
1337     if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1338         return createPrimitiveNumericValue(value);
1339     if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
1340         return createPrimitiveNumericValue(value);
1341     if (value->unit >= CSSParserValue::Q_EMS)
1342         return CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS);
1343     if (isCalculation(value))
1344         return CSSPrimitiveValue::create(m_parsedCalculation.release());
1345
1346     return 0;
1347 }
1348
1349 bool CSSParser::parseValue(int propId, bool important)
1350 {
1351     if (!m_valueList)
1352         return false;
1353
1354     CSSParserValue* value = m_valueList->current();
1355
1356     if (!value)
1357         return false;
1358
1359     // Note: m_parsedCalculation is used to pass the calc value to validUnit and then cleared at the end of this function.
1360     // FIXME: This is to avoid having to pass parsedCalc to all validUnit callers.
1361     ASSERT(!m_parsedCalculation);
1362     
1363     int id = value->id;
1364
1365     // In quirks mode, we will look for units that have been incorrectly separated from the number they belong to
1366     // by a space.  We go ahead and associate the unit with the number even though it is invalid CSS.
1367     checkForOrphanedUnits();
1368
1369     int num = inShorthand() ? 1 : m_valueList->size();
1370
1371     if (id == CSSValueInherit) {
1372         if (num != 1)
1373             return false;
1374         addProperty(propId, cssValuePool()->createInheritedValue(), important);
1375         return true;
1376     }
1377     else if (id == CSSValueInitial) {
1378         if (num != 1)
1379             return false;
1380         addProperty(propId, cssValuePool()->createExplicitInitialValue(), important);
1381         return true;
1382     }
1383
1384     if (isKeywordPropertyID(propId)) {
1385         if (!isValidKeywordPropertyAndValue(propId, id))
1386             return false;
1387         if (m_valueList->next() && !inShorthand())
1388             return false;
1389         addProperty(propId, cssValuePool()->createIdentifierValue(id), important);
1390         return true;
1391     }
1392
1393     bool validPrimitive = false;
1394     RefPtr<CSSValue> parsedValue;
1395
1396     switch (static_cast<CSSPropertyID>(propId)) {
1397         /* The comment to the left defines all valid value of this properties as defined
1398          * in CSS 2, Appendix F. Property index
1399          */
1400
1401         /* All the CSS properties are not supported by the renderer at the moment.
1402          * Note that all the CSS2 Aural properties are only checked, if CSS_AURAL is defined
1403          * (see parseAuralValues). As we don't support them at all this seems reasonable.
1404          */
1405
1406     case CSSPropertySize:                 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
1407         return parseSize(propId, important);
1408
1409     case CSSPropertyQuotes:               // [<string> <string>]+ | none | inherit
1410         if (id)
1411             validPrimitive = true;
1412         else
1413             return parseQuotes(propId, important);
1414         break;
1415     case CSSPropertyUnicodeBidi: // normal | embed | (bidi-override || isolate) | plaintext | inherit
1416         if (id == CSSValueNormal
1417             || id == CSSValueEmbed
1418             || id == CSSValueWebkitPlaintext)
1419             validPrimitive = true;
1420         else {
1421             RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
1422             bool isValid = true;
1423             while (isValid && value) {
1424                 switch (value->id) {
1425                 case CSSValueBidiOverride:
1426                 case CSSValueWebkitIsolate:
1427                     list->append(cssValuePool()->createIdentifierValue(value->id));
1428                     break;
1429                 default:
1430                     isValid = false;
1431                 }
1432                 value = m_valueList->next();
1433             }
1434             if (list->length() && isValid) {
1435                 parsedValue = list.release();
1436                 m_valueList->next();
1437             }
1438         }
1439         break;
1440
1441     case CSSPropertyPageBreakAfter:       // auto | always | avoid | left | right | inherit
1442     case CSSPropertyPageBreakBefore:
1443     case CSSPropertyWebkitColumnBreakAfter:
1444     case CSSPropertyWebkitColumnBreakBefore:
1445     case CSSPropertyWebkitRegionBreakAfter:
1446     case CSSPropertyWebkitRegionBreakBefore:
1447         if (id == CSSValueAuto
1448             || id == CSSValueAlways
1449             || id == CSSValueAvoid
1450             || id == CSSValueLeft
1451             || id == CSSValueRight)
1452             validPrimitive = ((propId == CSSPropertyWebkitRegionBreakAfter) || (propId == CSSPropertyWebkitRegionBreakBefore)) ? cssRegionsEnabled() : true;
1453         break;
1454
1455     case CSSPropertyPageBreakInside:     // avoid | auto | inherit
1456     case CSSPropertyWebkitColumnBreakInside:
1457     case CSSPropertyWebkitRegionBreakInside:
1458         if (id == CSSValueAuto || id == CSSValueAvoid)
1459             validPrimitive = (propId == CSSPropertyWebkitRegionBreakInside) ? cssRegionsEnabled() : true;
1460         break;
1461
1462     case CSSPropertyContent:              // [ <string> | <uri> | <counter> | attr(X) | open-quote |
1463         // close-quote | no-open-quote | no-close-quote ]+ | inherit
1464         return parseContent(propId, important);
1465
1466     case CSSPropertyClip:                 // <shape> | auto | inherit
1467         if (id == CSSValueAuto)
1468             validPrimitive = true;
1469         else if (value->unit == CSSParserValue::Function)
1470             return parseShape(propId, important);
1471         break;
1472
1473     /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
1474      * correctly and allows optimization in WebCore::applyRule(..)
1475      */
1476     case CSSPropertyOverflow: {
1477         ShorthandScope scope(this, propId);
1478         if (num != 1 || !parseValue(CSSPropertyOverflowX, important))
1479             return false;
1480         CSSValue* value = m_parsedProperties.last().value();
1481         addProperty(CSSPropertyOverflowY, value, important);
1482         return true;
1483     }
1484
1485     case CSSPropertyTextAlign:
1486         // left | right | center | justify | webkit_left | webkit_right | webkit_center | webkit_match_parent |
1487         // start | end | <string> | inherit
1488         if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd
1489             || value->unit == CSSPrimitiveValue::CSS_STRING)
1490             validPrimitive = true;
1491         break;
1492
1493     case CSSPropertyFontWeight:  // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
1494         return parseFontWeight(important);
1495
1496     case CSSPropertyBorderSpacing: {
1497         const int properties[2] = { CSSPropertyWebkitBorderHorizontalSpacing,
1498                                     CSSPropertyWebkitBorderVerticalSpacing };
1499         if (num == 1) {
1500             ShorthandScope scope(this, CSSPropertyBorderSpacing);
1501             if (!parseValue(properties[0], important))
1502                 return false;
1503             CSSValue* value = m_parsedProperties.last().value();
1504             addProperty(properties[1], value, important);
1505             return true;
1506         }
1507         else if (num == 2) {
1508             ShorthandScope scope(this, CSSPropertyBorderSpacing);
1509             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
1510                 return false;
1511             return true;
1512         }
1513         return false;
1514     }
1515     case CSSPropertyWebkitBorderHorizontalSpacing:
1516     case CSSPropertyWebkitBorderVerticalSpacing:
1517         validPrimitive = validUnit(value, FLength | FNonNeg, m_strict);
1518         break;
1519     case CSSPropertyOutlineColor:        // <color> | invert | inherit
1520         // Outline color has "invert" as additional keyword.
1521         // Also, we want to allow the special focus color even in strict parsing mode.
1522         if (id == CSSValueInvert || id == CSSValueWebkitFocusRingColor) {
1523             validPrimitive = true;
1524             break;
1525         }
1526         /* nobreak */
1527     case CSSPropertyBackgroundColor: // <color> | inherit
1528     case CSSPropertyBorderTopColor: // <color> | inherit
1529     case CSSPropertyBorderRightColor:
1530     case CSSPropertyBorderBottomColor:
1531     case CSSPropertyBorderLeftColor:
1532     case CSSPropertyWebkitBorderStartColor:
1533     case CSSPropertyWebkitBorderEndColor:
1534     case CSSPropertyWebkitBorderBeforeColor:
1535     case CSSPropertyWebkitBorderAfterColor:
1536     case CSSPropertyColor: // <color> | inherit
1537     case CSSPropertyTextLineThroughColor: // CSS3 text decoration colors
1538     case CSSPropertyTextUnderlineColor:
1539     case CSSPropertyTextOverlineColor:
1540     case CSSPropertyWebkitColumnRuleColor:
1541     case CSSPropertyWebkitTextEmphasisColor:
1542     case CSSPropertyWebkitTextFillColor:
1543     case CSSPropertyWebkitTextStrokeColor:
1544         if (id == CSSValueWebkitText)
1545             validPrimitive = true; // Always allow this, even when strict parsing is on,
1546                                     // since we use this in our UA sheets.
1547         else if (id == CSSValueCurrentcolor)
1548             validPrimitive = true;
1549         else if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu ||
1550              (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && !m_strict)) {
1551             validPrimitive = true;
1552         } else {
1553             parsedValue = parseColor();
1554             if (parsedValue)
1555                 m_valueList->next();
1556         }
1557         break;
1558
1559     case CSSPropertyCursor: {
1560         // [<uri>,]*  [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
1561         // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize |
1562         // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help |
1563         // vertical-text | cell | context-menu | alias | copy | no-drop | not-allowed | -webkit-zoom-in
1564         // -webkit-zoom-out | all-scroll | -webkit-grab | -webkit-grabbing ] ] | inherit
1565         RefPtr<CSSValueList> list;
1566         while (value && value->unit == CSSPrimitiveValue::CSS_URI) {
1567             if (!list)
1568                 list = CSSValueList::createCommaSeparated();
1569             String uri = value->string;
1570             Vector<int> coords;
1571             value = m_valueList->next();
1572             while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) {
1573                 coords.append(int(value->fValue));
1574                 value = m_valueList->next();
1575             }
1576             IntPoint hotSpot(-1, -1);
1577             int nrcoords = coords.size();
1578             if (nrcoords > 0 && nrcoords != 2)
1579                 return false;
1580             if (nrcoords == 2)
1581                 hotSpot = IntPoint(coords[0], coords[1]);
1582
1583             if (!uri.isNull() && m_styleSheet) {
1584                 // FIXME: The completeURL call should be done when using the CSSCursorImageValue,
1585                 // not when creating it.
1586                 list->append(CSSCursorImageValue::create(m_styleSheet->completeURL(uri), hotSpot));
1587             }
1588
1589             if ((m_strict && !value) || (value && !(value->unit == CSSParserValue::Operator && value->iValue == ',')))
1590                 return false;
1591             value = m_valueList->next(); // comma
1592         }
1593         if (list) {
1594             if (!value) { // no value after url list (MSIE 5 compatibility)
1595                 if (list->length() != 1)
1596                     return false;
1597             } else if (!m_strict && value->id == CSSValueHand) // MSIE 5 compatibility :/
1598                 list->append(cssValuePool()->createIdentifierValue(CSSValuePointer));
1599             else if (value && ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone))
1600                 list->append(cssValuePool()->createIdentifierValue(value->id));
1601             m_valueList->next();
1602             parsedValue = list.release();
1603             break;
1604         }
1605         id = value->id;
1606         if (!m_strict && value->id == CSSValueHand) { // MSIE 5 compatibility :/
1607             id = CSSValuePointer;
1608             validPrimitive = true;
1609         } else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)
1610             validPrimitive = true;
1611         break;
1612     }
1613
1614     case CSSPropertyBackgroundAttachment:
1615     case CSSPropertyBackgroundClip:
1616     case CSSPropertyWebkitBackgroundClip:
1617     case CSSPropertyWebkitBackgroundComposite:
1618     case CSSPropertyBackgroundImage:
1619     case CSSPropertyBackgroundOrigin:
1620     case CSSPropertyWebkitBackgroundOrigin:
1621     case CSSPropertyBackgroundPosition:
1622     case CSSPropertyBackgroundPositionX:
1623     case CSSPropertyBackgroundPositionY:
1624     case CSSPropertyBackgroundSize:
1625     case CSSPropertyWebkitBackgroundSize:
1626     case CSSPropertyBackgroundRepeat:
1627     case CSSPropertyBackgroundRepeatX:
1628     case CSSPropertyBackgroundRepeatY:
1629     case CSSPropertyWebkitMaskAttachment:
1630     case CSSPropertyWebkitMaskClip:
1631     case CSSPropertyWebkitMaskComposite:
1632     case CSSPropertyWebkitMaskImage:
1633     case CSSPropertyWebkitMaskOrigin:
1634     case CSSPropertyWebkitMaskPosition:
1635     case CSSPropertyWebkitMaskPositionX:
1636     case CSSPropertyWebkitMaskPositionY:
1637     case CSSPropertyWebkitMaskSize:
1638     case CSSPropertyWebkitMaskRepeat:
1639     case CSSPropertyWebkitMaskRepeatX:
1640     case CSSPropertyWebkitMaskRepeatY: {
1641         RefPtr<CSSValue> val1;
1642         RefPtr<CSSValue> val2;
1643         int propId1, propId2;
1644         bool result = false;
1645         if (parseFillProperty(propId, propId1, propId2, val1, val2)) {
1646             OwnPtr<ShorthandScope> shorthandScope;
1647             if (propId == CSSPropertyBackgroundPosition ||
1648                 propId == CSSPropertyBackgroundRepeat ||
1649                 propId == CSSPropertyWebkitMaskPosition ||
1650                 propId == CSSPropertyWebkitMaskRepeat) {
1651                 shorthandScope = adoptPtr(new ShorthandScope(this, propId));
1652             }
1653             addProperty(propId1, val1.release(), important);
1654             if (val2)
1655                 addProperty(propId2, val2.release(), important);
1656             result = true;
1657         }
1658         m_implicitShorthand = false;
1659         return result;
1660     }
1661     case CSSPropertyListStyleImage:     // <uri> | none | inherit
1662     case CSSPropertyBorderImageSource:
1663     case CSSPropertyWebkitMaskBoxImageSource:
1664         if (id == CSSValueNone) {
1665             parsedValue = cssValuePool()->createIdentifierValue(CSSValueNone);
1666             m_valueList->next();
1667         } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
1668             if (m_styleSheet) {
1669                 // FIXME: The completeURL call should be done when using the CSSImageValue,
1670                 // not when creating it.
1671                 parsedValue = CSSImageValue::create(m_styleSheet->completeURL(value->string));
1672                 m_valueList->next();
1673             }
1674         } else if (isGeneratedImageValue(value)) {
1675             if (parseGeneratedImage(m_valueList.get(), parsedValue))
1676                 m_valueList->next();
1677             else
1678                 return false;
1679         }
1680 #if ENABLE(CSS_IMAGE_SET)
1681         else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "-webkit-image-set(")) {
1682             parsedValue = parseImageSet(m_valueList.get());
1683             if (!parsedValue)
1684                 return false;
1685             m_valueList->next();
1686         }
1687 #endif
1688         break;
1689
1690     case CSSPropertyWebkitTextStrokeWidth:
1691     case CSSPropertyOutlineWidth:        // <border-width> | inherit
1692     case CSSPropertyBorderTopWidth:     //// <border-width> | inherit
1693     case CSSPropertyBorderRightWidth:   //   Which is defined as
1694     case CSSPropertyBorderBottomWidth:  //   thin | medium | thick | <length>
1695     case CSSPropertyBorderLeftWidth:
1696     case CSSPropertyWebkitBorderStartWidth:
1697     case CSSPropertyWebkitBorderEndWidth:
1698     case CSSPropertyWebkitBorderBeforeWidth:
1699     case CSSPropertyWebkitBorderAfterWidth:
1700     case CSSPropertyWebkitColumnRuleWidth:
1701         if (id == CSSValueThin || id == CSSValueMedium || id == CSSValueThick)
1702             validPrimitive = true;
1703         else
1704             validPrimitive = validUnit(value, FLength | FNonNeg, m_strict);
1705         break;
1706
1707     case CSSPropertyLetterSpacing:       // normal | <length> | inherit
1708     case CSSPropertyWordSpacing:         // normal | <length> | inherit
1709         if (id == CSSValueNormal)
1710             validPrimitive = true;
1711         else
1712             validPrimitive = validUnit(value, FLength, m_strict);
1713         break;
1714
1715     case CSSPropertyTextIndent:          // <length> | <percentage> | inherit
1716         validPrimitive = (!id && validUnit(value, FLength | FPercent, m_strict));
1717         break;
1718
1719     case CSSPropertyPaddingTop:          //// <padding-width> | inherit
1720     case CSSPropertyPaddingRight:        //   Which is defined as
1721     case CSSPropertyPaddingBottom:       //   <length> | <percentage>
1722     case CSSPropertyPaddingLeft:         ////
1723     case CSSPropertyWebkitPaddingStart:
1724     case CSSPropertyWebkitPaddingEnd:
1725     case CSSPropertyWebkitPaddingBefore:
1726     case CSSPropertyWebkitPaddingAfter:
1727         validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg, m_strict));
1728         break;
1729
1730     case CSSPropertyMaxHeight:           // <length> | <percentage> | none | inherit
1731     case CSSPropertyMaxWidth:            // <length> | <percentage> | none | inherit
1732     case CSSPropertyWebkitMaxLogicalWidth:
1733     case CSSPropertyWebkitMaxLogicalHeight:
1734         if (id == CSSValueNone) {
1735             validPrimitive = true;
1736             break;
1737         }
1738         /* nobreak */
1739     case CSSPropertyMinHeight:           // <length> | <percentage> | inherit
1740     case CSSPropertyMinWidth:            // <length> | <percentage> | inherit
1741     case CSSPropertyWebkitMinLogicalWidth:
1742     case CSSPropertyWebkitMinLogicalHeight:
1743         if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
1744             validPrimitive = true;
1745         else
1746             validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg, m_strict));
1747         break;
1748
1749     case CSSPropertyFontSize:
1750         // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
1751         if (id >= CSSValueXxSmall && id <= CSSValueLarger)
1752             validPrimitive = true;
1753         else
1754             validPrimitive = (validUnit(value, FLength | FPercent | FNonNeg, m_strict));
1755         break;
1756
1757     case CSSPropertyFontVariant:         // normal | small-caps | inherit
1758         return parseFontVariant(important);
1759
1760     case CSSPropertyVerticalAlign:
1761         // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
1762         // <percentage> | <length> | inherit
1763
1764         if (id >= CSSValueBaseline && id <= CSSValueWebkitBaselineMiddle)
1765             validPrimitive = true;
1766         else
1767             validPrimitive = (!id && validUnit(value, FLength | FPercent, m_strict));
1768         break;
1769
1770     case CSSPropertyHeight:               // <length> | <percentage> | auto | inherit
1771     case CSSPropertyWidth:                // <length> | <percentage> | auto | inherit
1772     case CSSPropertyWebkitLogicalWidth:
1773     case CSSPropertyWebkitLogicalHeight:
1774         if (id == CSSValueAuto || id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
1775             validPrimitive = true;
1776         else if (!id && validUnit(value, FLength | FPercent | FNonNeg, m_strict))
1777             // ### handle multilength case where we allow relative units
1778             validPrimitive = true;
1779         else if (value->unit == CSSParserValue::Function)
1780             return parseFlex(propId, important);
1781         break;
1782
1783     case CSSPropertyBottom:               // <length> | <percentage> | auto | inherit
1784     case CSSPropertyLeft:                 // <length> | <percentage> | auto | inherit
1785     case CSSPropertyRight:                // <length> | <percentage> | auto | inherit
1786     case CSSPropertyTop:                  // <length> | <percentage> | auto | inherit
1787     case CSSPropertyMarginTop:           //// <margin-width> | inherit
1788     case CSSPropertyMarginRight:         //   Which is defined as
1789     case CSSPropertyMarginBottom:        //   <length> | <percentage> | auto | inherit
1790     case CSSPropertyMarginLeft:          ////
1791     case CSSPropertyWebkitMarginStart:
1792     case CSSPropertyWebkitMarginEnd:
1793     case CSSPropertyWebkitMarginBefore:
1794     case CSSPropertyWebkitMarginAfter:
1795         if (id == CSSValueAuto)
1796             validPrimitive = true;
1797         else
1798             validPrimitive = (!id && validUnit(value, FLength | FPercent, m_strict));
1799         break;
1800
1801     case CSSPropertyZIndex:              // auto | <integer> | inherit
1802         if (id == CSSValueAuto) {
1803             validPrimitive = true;
1804             break;
1805         }
1806         /* nobreak */
1807     case CSSPropertyOrphans:              // <integer> | inherit
1808     case CSSPropertyWidows:               // <integer> | inherit
1809         // ### not supported later on
1810         validPrimitive = (!id && validUnit(value, FInteger, false));
1811         break;
1812
1813     case CSSPropertyLineHeight:          // normal | <number> | <length> | <percentage> | inherit
1814         if (id == CSSValueNormal)
1815             validPrimitive = true;
1816         else
1817             validPrimitive = (!id && validUnit(value, FNumber | FLength | FPercent | FNonNeg, m_strict));
1818         break;
1819     case CSSPropertyCounterIncrement:    // [ <identifier> <integer>? ]+ | none | inherit
1820         if (id != CSSValueNone)
1821             return parseCounter(propId, 1, important);
1822         validPrimitive = true;
1823         break;
1824     case CSSPropertyCounterReset:        // [ <identifier> <integer>? ]+ | none | inherit
1825         if (id != CSSValueNone)
1826             return parseCounter(propId, 0, important);
1827         validPrimitive = true;
1828         break;
1829     case CSSPropertyFontFamily:
1830         // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
1831     {
1832         parsedValue = parseFontFamily();
1833         break;
1834     }
1835
1836     case CSSPropertyTextDecoration:
1837     case CSSPropertyWebkitTextDecorationsInEffect:
1838         // none | [ underline || overline || line-through || blink ] | inherit
1839         if (id == CSSValueNone) {
1840             validPrimitive = true;
1841         } else {
1842             RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
1843             bool isValid = true;
1844             while (isValid && value) {
1845                 switch (value->id) {
1846                 case CSSValueBlink:
1847                     break;
1848                 case CSSValueUnderline:
1849                 case CSSValueOverline:
1850                 case CSSValueLineThrough:
1851                     list->append(cssValuePool()->createIdentifierValue(value->id));
1852                     break;
1853                 default:
1854                     isValid = false;
1855                 }
1856                 value = m_valueList->next();
1857             }
1858             if (list->length() && isValid) {
1859                 parsedValue = list.release();
1860                 m_valueList->next();
1861             }
1862         }
1863         break;
1864
1865     case CSSPropertyZoom:          // normal | reset | document | <number> | <percentage> | inherit
1866         if (id == CSSValueNormal || id == CSSValueReset || id == CSSValueDocument)
1867             validPrimitive = true;
1868         else
1869             validPrimitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg, true));
1870         break;
1871
1872     case CSSPropertySrc:  // Only used within @font-face, so cannot use inherit | initial or be !important.  This is a list of urls or local references.
1873         return parseFontFaceSrc();
1874
1875     case CSSPropertyUnicodeRange:
1876         return parseFontFaceUnicodeRange();
1877
1878     /* CSS3 properties */
1879
1880     case CSSPropertyBorderImage: {
1881         RefPtr<CSSValue> result;
1882         return parseBorderImage(propId, result, important);
1883     }
1884     case CSSPropertyWebkitBorderImage:
1885     case CSSPropertyWebkitMaskBoxImage: {
1886         RefPtr<CSSValue> result;
1887         if (parseBorderImage(propId, result)) {
1888             addProperty(propId, result, important);
1889             return true;
1890         }
1891         break;
1892     }
1893     case CSSPropertyBorderImageOutset:
1894     case CSSPropertyWebkitMaskBoxImageOutset: {
1895         RefPtr<CSSPrimitiveValue> result;
1896         if (parseBorderImageOutset(result)) {
1897             addProperty(propId, result, important);
1898             return true;
1899         }
1900         break;
1901     }
1902     case CSSPropertyBorderImageRepeat:
1903     case CSSPropertyWebkitMaskBoxImageRepeat: {
1904         RefPtr<CSSValue> result;
1905         if (parseBorderImageRepeat(result)) {
1906             addProperty(propId, result, important);
1907             return true;
1908         }
1909         break;
1910     }
1911     case CSSPropertyBorderImageSlice:
1912     case CSSPropertyWebkitMaskBoxImageSlice: {
1913         RefPtr<CSSBorderImageSliceValue> result;
1914         if (parseBorderImageSlice(propId, result)) {
1915             addProperty(propId, result, important);
1916             return true;
1917         }
1918         break;
1919     }
1920     case CSSPropertyBorderImageWidth:
1921     case CSSPropertyWebkitMaskBoxImageWidth: {
1922         RefPtr<CSSPrimitiveValue> result;
1923         if (parseBorderImageWidth(result)) {
1924             addProperty(propId, result, important);
1925             return true;
1926         }
1927         break;
1928     }
1929     case CSSPropertyBorderTopRightRadius:
1930     case CSSPropertyBorderTopLeftRadius:
1931     case CSSPropertyBorderBottomLeftRadius:
1932     case CSSPropertyBorderBottomRightRadius: {
1933         if (num != 1 && num != 2)
1934             return false;
1935         validPrimitive = validUnit(value, FLength | FPercent | FNonNeg, m_strict);
1936         if (!validPrimitive)
1937             return false;
1938         RefPtr<CSSPrimitiveValue> parsedValue1 = createPrimitiveNumericValue(value);
1939         RefPtr<CSSPrimitiveValue> parsedValue2;
1940         if (num == 2) {
1941             value = m_valueList->next();
1942             validPrimitive = validUnit(value, FLength | FPercent | FNonNeg, m_strict);
1943             if (!validPrimitive)
1944                 return false;
1945             parsedValue2 = createPrimitiveNumericValue(value);
1946         } else
1947             parsedValue2 = parsedValue1;
1948
1949         RefPtr<Pair> pair = Pair::create(parsedValue1.release(), parsedValue2.release());
1950         RefPtr<CSSPrimitiveValue> val = cssValuePool()->createValue(pair.release());
1951         addProperty(propId, val.release(), important);
1952         return true;
1953     }
1954     case CSSPropertyWebkitAspectRatio:
1955         return parseAspectRatio(important);
1956     case CSSPropertyBorderRadius:
1957     case CSSPropertyWebkitBorderRadius:
1958         return parseBorderRadius(propId, important);
1959     case CSSPropertyOutlineOffset:
1960         validPrimitive = validUnit(value, FLength | FPercent, m_strict);
1961         break;
1962     case CSSPropertyTextShadow: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
1963     case CSSPropertyBoxShadow:
1964     case CSSPropertyWebkitBoxShadow:
1965         if (id == CSSValueNone)
1966             validPrimitive = true;
1967         else {
1968             RefPtr<CSSValueList> shadowValueList = parseShadow(m_valueList.get(), propId);
1969             if (shadowValueList) {
1970                 addProperty(propId, shadowValueList.release(), important);
1971                 m_valueList->next();
1972                 return true;
1973             }
1974             return false;
1975         }
1976         break;
1977     case CSSPropertyWebkitBoxReflect:
1978         if (id == CSSValueNone)
1979             validPrimitive = true;
1980         else
1981             return parseReflect(propId, important);
1982         break;
1983     case CSSPropertyOpacity:
1984         validPrimitive = validUnit(value, FNumber, m_strict);
1985         break;
1986     case CSSPropertyWebkitBoxFlex:
1987         validPrimitive = validUnit(value, FNumber, m_strict);
1988         break;
1989     case CSSPropertyWebkitBoxFlexGroup:
1990     case CSSPropertyWebkitBoxOrdinalGroup:
1991         validPrimitive = validUnit(value, FInteger | FNonNeg, true);
1992         break;
1993 #if ENABLE(CSS_FILTERS)
1994     case CSSPropertyWebkitFilter:
1995         if (id == CSSValueNone)
1996             validPrimitive = true;
1997         else {
1998             RefPtr<CSSValue> val = parseFilter();
1999             if (val) {
2000                 addProperty(propId, val, important);
2001                 return true;
2002             }
2003             return false;
2004         }
2005         break;
2006 #endif
2007     case CSSPropertyWebkitFlexOrder:
2008         if (validUnit(value, FInteger, true)) {
2009             // We restrict the smallest value to int min + 2 because we use int min and int min + 1 as special values in a hash set.
2010             parsedValue = cssValuePool()->createValue(max(static_cast<double>(std::numeric_limits<int>::min() + 2), value->fValue),
2011                                                              static_cast<CSSPrimitiveValue::UnitTypes>(value->unit));
2012             m_valueList->next();
2013         }
2014         break;
2015     case CSSPropertyWebkitMarquee: {
2016         const int properties[5] = { CSSPropertyWebkitMarqueeDirection, CSSPropertyWebkitMarqueeIncrement,
2017                                     CSSPropertyWebkitMarqueeRepetition,
2018                                     CSSPropertyWebkitMarqueeStyle, CSSPropertyWebkitMarqueeSpeed };
2019         return parseShorthand(propId, properties, 5, important);
2020     }
2021     case CSSPropertyWebkitMarqueeIncrement:
2022         if (id == CSSValueSmall || id == CSSValueLarge || id == CSSValueMedium)
2023             validPrimitive = true;
2024         else
2025             validPrimitive = validUnit(value, FLength | FPercent, m_strict);
2026         break;
2027     case CSSPropertyWebkitMarqueeRepetition:
2028         if (id == CSSValueInfinite)
2029             validPrimitive = true;
2030         else
2031             validPrimitive = validUnit(value, FInteger | FNonNeg, m_strict);
2032         break;
2033     case CSSPropertyWebkitMarqueeSpeed:
2034         if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast)
2035             validPrimitive = true;
2036         else
2037             validPrimitive = validUnit(value, FTime | FInteger | FNonNeg, m_strict);
2038         break;
2039     case CSSPropertyWebkitFlowInto:
2040         if (!cssRegionsEnabled())
2041             return false;
2042         return parseFlowThread(propId, important);
2043     case CSSPropertyWebkitFlowFrom:
2044         if (!cssRegionsEnabled())
2045             return false;
2046         return parseRegionThread(propId, important);
2047     case CSSPropertyWebkitRegionOverflow:
2048         if (cssRegionsEnabled() && (id == CSSValueAuto || id == CSSValueBreak))
2049             validPrimitive = true;
2050         break;
2051     case CSSPropertyWebkitTransform:
2052         if (id == CSSValueNone)
2053             validPrimitive = true;
2054         else {
2055             PassRefPtr<CSSValue> val = parseTransform();
2056             if (val) {
2057                 addProperty(propId, val, important);
2058                 return true;
2059             }
2060             return false;
2061         }
2062         break;
2063     case CSSPropertyWebkitTransformOrigin:
2064     case CSSPropertyWebkitTransformOriginX:
2065     case CSSPropertyWebkitTransformOriginY:
2066     case CSSPropertyWebkitTransformOriginZ: {
2067         RefPtr<CSSValue> val1;
2068         RefPtr<CSSValue> val2;
2069         RefPtr<CSSValue> val3;
2070         int propId1, propId2, propId3;
2071         if (parseTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) {
2072             addProperty(propId1, val1.release(), important);
2073             if (val2)
2074                 addProperty(propId2, val2.release(), important);
2075             if (val3)
2076                 addProperty(propId3, val3.release(), important);
2077             return true;
2078         }
2079         return false;
2080     }
2081     case CSSPropertyWebkitPerspective:
2082         if (id == CSSValueNone)
2083             validPrimitive = true;
2084         else {
2085             // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property.
2086             if (validUnit(value, FNumber | FLength | FNonNeg, m_strict)) {
2087                 RefPtr<CSSValue> val = createPrimitiveNumericValue(value);
2088                 if (val) {
2089                     addProperty(propId, val.release(), important);
2090                     return true;
2091                 }
2092                 return false;
2093             }
2094         }
2095         break;
2096     case CSSPropertyWebkitPerspectiveOrigin:
2097     case CSSPropertyWebkitPerspectiveOriginX:
2098     case CSSPropertyWebkitPerspectiveOriginY: {
2099         RefPtr<CSSValue> val1;
2100         RefPtr<CSSValue> val2;
2101         int propId1, propId2;
2102         if (parsePerspectiveOrigin(propId, propId1, propId2, val1, val2)) {
2103             addProperty(propId1, val1.release(), important);
2104             if (val2)
2105                 addProperty(propId2, val2.release(), important);
2106             return true;
2107         }
2108         return false;
2109     }
2110     case CSSPropertyWebkitAnimationDelay:
2111     case CSSPropertyWebkitAnimationDirection:
2112     case CSSPropertyWebkitAnimationDuration:
2113     case CSSPropertyWebkitAnimationFillMode:
2114     case CSSPropertyWebkitAnimationName:
2115     case CSSPropertyWebkitAnimationPlayState:
2116     case CSSPropertyWebkitAnimationIterationCount:
2117     case CSSPropertyWebkitAnimationTimingFunction:
2118     case CSSPropertyWebkitTransitionDelay:
2119     case CSSPropertyWebkitTransitionDuration:
2120     case CSSPropertyWebkitTransitionTimingFunction:
2121     case CSSPropertyWebkitTransitionProperty: {
2122         RefPtr<CSSValue> val;
2123         if (parseAnimationProperty(propId, val)) {
2124             addProperty(propId, val.release(), important);
2125             return true;
2126         }
2127         return false;
2128     }
2129 #if ENABLE(CSS_GRID_LAYOUT)
2130     case CSSPropertyWebkitGridColumns:
2131     case CSSPropertyWebkitGridRows:
2132         return parseGridTrackList(propId, important);
2133
2134     case CSSPropertyWebkitGridColumn:
2135     case CSSPropertyWebkitGridRow:
2136         validPrimitive = id == CSSValueAuto || validUnit(value, FInteger, m_strict);
2137         break;
2138 #endif
2139     case CSSPropertyWebkitMarginCollapse: {
2140         const int properties[2] = { CSSPropertyWebkitMarginBeforeCollapse,
2141             CSSPropertyWebkitMarginAfterCollapse };
2142         if (num == 1) {
2143             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2144             if (!parseValue(properties[0], important))
2145                 return false;
2146             CSSValue* value = m_parsedProperties.last().value();
2147             addProperty(properties[1], value, important);
2148             return true;
2149         }
2150         else if (num == 2) {
2151             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2152             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
2153                 return false;
2154             return true;
2155         }
2156         return false;
2157     }
2158     case CSSPropertyTextLineThroughWidth:
2159     case CSSPropertyTextOverlineWidth:
2160     case CSSPropertyTextUnderlineWidth:
2161         if (id == CSSValueAuto || id == CSSValueNormal || id == CSSValueThin ||
2162             id == CSSValueMedium || id == CSSValueThick)
2163             validPrimitive = true;
2164         else
2165             validPrimitive = !id && validUnit(value, FNumber | FLength | FPercent, m_strict);
2166         break;
2167     case CSSPropertyWebkitColumnCount:
2168         if (id == CSSValueAuto)
2169             validPrimitive = true;
2170         else
2171             validPrimitive = !id && validUnit(value, FInteger | FNonNeg, false);
2172         break;
2173     case CSSPropertyWebkitColumnGap:         // normal | <length>
2174         if (id == CSSValueNormal)
2175             validPrimitive = true;
2176         else
2177             validPrimitive = validUnit(value, FLength | FNonNeg, m_strict);
2178         break;
2179     case CSSPropertyWebkitColumnAxis:
2180         if (id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto)
2181             validPrimitive = true;
2182         break;
2183     case CSSPropertyWebkitColumnSpan:        // all | 1
2184         if (id == CSSValueAll)
2185             validPrimitive = true;
2186         else
2187             validPrimitive = validUnit(value, FNumber | FNonNeg, m_strict) && value->fValue == 1;
2188         break;
2189     case CSSPropertyWebkitColumnWidth:         // auto | <length>
2190         if (id == CSSValueAuto)
2191             validPrimitive = true;
2192         else // Always parse this property in strict mode, since it would be ambiguous otherwise when used in the 'columns' shorthand property.
2193             validPrimitive = validUnit(value, FLength, true);
2194         break;
2195     // End of CSS3 properties
2196
2197     // Apple specific properties.  These will never be standardized and are purely to
2198     // support custom WebKit-based Apple applications.
2199     case CSSPropertyWebkitLineClamp:
2200         // When specifying number of lines, don't allow 0 as a valid value
2201         // When specifying either type of unit, require non-negative integers
2202         validPrimitive = (!id && (value->unit == CSSPrimitiveValue::CSS_PERCENTAGE || value->fValue) && validUnit(value, FInteger | FPercent | FNonNeg, false));
2203         break;
2204
2205     case CSSPropertyWebkitFontSizeDelta:           // <length>
2206         validPrimitive = validUnit(value, FLength, m_strict);
2207         break;
2208
2209     case CSSPropertyWebkitHighlight:
2210         if (id == CSSValueNone || value->unit == CSSPrimitiveValue::CSS_STRING)
2211             validPrimitive = true;
2212         break;
2213
2214     case CSSPropertyWebkitHyphenateCharacter:
2215         if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
2216             validPrimitive = true;
2217         break;
2218
2219     case CSSPropertyWebkitHyphenateLimitBefore:
2220     case CSSPropertyWebkitHyphenateLimitAfter:
2221         if (id == CSSValueAuto || validUnit(value, FInteger | FNonNeg, true))
2222             validPrimitive = true;
2223         break;
2224
2225     case CSSPropertyWebkitHyphenateLimitLines:
2226         if (id == CSSValueNoLimit || validUnit(value, FInteger | FNonNeg, true))
2227             validPrimitive = true;
2228         break;
2229
2230     case CSSPropertyWebkitLineGrid:
2231         if (id == CSSValueNone)
2232             validPrimitive = true;
2233         else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
2234             String lineGridValue = String(value->string);
2235             if (!lineGridValue.isEmpty()) {
2236                 addProperty(propId, cssValuePool()->createValue(lineGridValue, CSSPrimitiveValue::CSS_STRING), important);
2237                 return true;
2238             }
2239         }
2240         break;
2241     case CSSPropertyWebkitLocale:
2242         if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
2243             validPrimitive = true;
2244         break;
2245
2246 #if ENABLE(DASHBOARD_SUPPORT)
2247     case CSSPropertyWebkitDashboardRegion: // <dashboard-region> | <dashboard-region>
2248         if (value->unit == CSSParserValue::Function || id == CSSValueNone)
2249             return parseDashboardRegions(propId, important);
2250         break;
2251 #endif
2252     // End Apple-specific properties
2253
2254 #if ENABLE(TOUCH_EVENTS)
2255     case CSSPropertyWebkitTapHighlightColor:
2256         if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu
2257             || (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && !m_strict)) {
2258             validPrimitive = true;
2259         } else {
2260             parsedValue = parseColor();
2261             if (parsedValue)
2262                 m_valueList->next();
2263         }
2264         break;
2265 #endif
2266
2267         /* shorthand properties */
2268     case CSSPropertyBackground: {
2269         // Position must come before color in this array because a plain old "0" is a legal color
2270         // in quirks mode but it's usually the X coordinate of a position.
2271         // FIXME: Add CSSPropertyBackgroundSize to the shorthand.
2272         const int properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat,
2273                                    CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyBackgroundOrigin,
2274                                    CSSPropertyBackgroundClip, CSSPropertyBackgroundColor };
2275         return parseFillShorthand(propId, properties, 7, important);
2276     }
2277     case CSSPropertyWebkitMask: {
2278         const int properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
2279                                    CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition,
2280                                    CSSPropertyWebkitMaskOrigin, CSSPropertyWebkitMaskClip };
2281         return parseFillShorthand(propId, properties, 6, important);
2282     }
2283     case CSSPropertyBorder:
2284         // [ 'border-width' || 'border-style' || <color> ] | inherit
2285     {
2286         const int properties[3] = { CSSPropertyBorderWidth, CSSPropertyBorderStyle,
2287                                     CSSPropertyBorderColor };
2288         if (parseShorthand(propId, properties, 3, important)) {
2289             // The CSS3 Borders and Backgrounds specification says that border also resets border-image. It's as
2290             // though a value of none was specified for the image.
2291             addProperty(CSSPropertyBorderImage, cssValuePool()->createImplicitInitialValue(), important);
2292             return true;
2293         }
2294         return false;
2295     }
2296     case CSSPropertyBorderTop:
2297         // [ 'border-top-width' || 'border-style' || <color> ] | inherit
2298     {
2299         const int properties[3] = { CSSPropertyBorderTopWidth, CSSPropertyBorderTopStyle,
2300                                     CSSPropertyBorderTopColor};
2301         return parseShorthand(propId, properties, 3, important);
2302     }
2303     case CSSPropertyBorderRight:
2304         // [ 'border-right-width' || 'border-style' || <color> ] | inherit
2305     {
2306         const int properties[3] = { CSSPropertyBorderRightWidth, CSSPropertyBorderRightStyle,
2307                                     CSSPropertyBorderRightColor };
2308         return parseShorthand(propId, properties, 3, important);
2309     }
2310     case CSSPropertyBorderBottom:
2311         // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
2312     {
2313         const int properties[3] = { CSSPropertyBorderBottomWidth, CSSPropertyBorderBottomStyle,
2314                                     CSSPropertyBorderBottomColor };
2315         return parseShorthand(propId, properties, 3, important);
2316     }
2317     case CSSPropertyBorderLeft:
2318         // [ 'border-left-width' || 'border-style' || <color> ] | inherit
2319     {
2320         const int properties[3] = { CSSPropertyBorderLeftWidth, CSSPropertyBorderLeftStyle,
2321                                     CSSPropertyBorderLeftColor };
2322         return parseShorthand(propId, properties, 3, important);
2323     }
2324     case CSSPropertyWebkitBorderStart:
2325     {
2326         const int properties[3] = { CSSPropertyWebkitBorderStartWidth, CSSPropertyWebkitBorderStartStyle,
2327             CSSPropertyWebkitBorderStartColor };
2328         return parseShorthand(propId, properties, 3, important);
2329     }
2330     case CSSPropertyWebkitBorderEnd:
2331     {
2332         const int properties[3] = { CSSPropertyWebkitBorderEndWidth, CSSPropertyWebkitBorderEndStyle,
2333             CSSPropertyWebkitBorderEndColor };
2334         return parseShorthand(propId, properties, 3, important);
2335     }
2336     case CSSPropertyWebkitBorderBefore:
2337     {
2338         const int properties[3] = { CSSPropertyWebkitBorderBeforeWidth, CSSPropertyWebkitBorderBeforeStyle,
2339             CSSPropertyWebkitBorderBeforeColor };
2340         return parseShorthand(propId, properties, 3, important);
2341     }
2342     case CSSPropertyWebkitBorderAfter:
2343     {
2344         const int properties[3] = { CSSPropertyWebkitBorderAfterWidth, CSSPropertyWebkitBorderAfterStyle,
2345             CSSPropertyWebkitBorderAfterColor };
2346         return parseShorthand(propId, properties, 3, important);
2347     }
2348     case CSSPropertyOutline:
2349         // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
2350     {
2351         const int properties[3] = { CSSPropertyOutlineWidth, CSSPropertyOutlineStyle,
2352                                     CSSPropertyOutlineColor };
2353         return parseShorthand(propId, properties, 3, important);
2354     }
2355     case CSSPropertyBorderColor:
2356         // <color>{1,4} | inherit
2357     {
2358         const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor,
2359                                     CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
2360         return parse4Values(propId, properties, important);
2361     }
2362     case CSSPropertyBorderWidth:
2363         // <border-width>{1,4} | inherit
2364     {
2365         const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth,
2366                                     CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
2367         return parse4Values(propId, properties, important);
2368     }
2369     case CSSPropertyBorderStyle:
2370         // <border-style>{1,4} | inherit
2371     {
2372         const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle,
2373                                     CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
2374         return parse4Values(propId, properties, important);
2375     }
2376     case CSSPropertyMargin:
2377         // <margin-width>{1,4} | inherit
2378     {
2379         const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight,
2380                                     CSSPropertyMarginBottom, CSSPropertyMarginLeft };
2381         return parse4Values(propId, properties, important);
2382     }
2383     case CSSPropertyPadding:
2384         // <padding-width>{1,4} | inherit
2385     {
2386         const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight,
2387                                     CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
2388         return parse4Values(propId, properties, important);
2389     }
2390     case CSSPropertyWebkitFlexFlow:
2391     {
2392         const int properties[] = { CSSPropertyWebkitFlexDirection, CSSPropertyWebkitFlexWrap };
2393         return parseShorthand(propId, properties, 2, important);
2394     }
2395     case CSSPropertyFont:
2396         // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
2397         // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
2398         if (id >= CSSValueCaption && id <= CSSValueStatusBar)
2399             validPrimitive = true;
2400         else
2401             return parseFont(important);
2402         break;
2403     case CSSPropertyListStyle:
2404     {
2405         const int properties[3] = { CSSPropertyListStyleType, CSSPropertyListStylePosition,
2406                                     CSSPropertyListStyleImage };
2407         return parseShorthand(propId, properties, 3, important);
2408     }
2409     case CSSPropertyWebkitColumns: {
2410         const int properties[2] = { CSSPropertyWebkitColumnWidth, CSSPropertyWebkitColumnCount };
2411         return parseShorthand(propId, properties, 2, important);
2412     }
2413     case CSSPropertyWebkitColumnRule: {
2414         const int properties[3] = { CSSPropertyWebkitColumnRuleWidth, CSSPropertyWebkitColumnRuleStyle,
2415                                     CSSPropertyWebkitColumnRuleColor };
2416         return parseShorthand(propId, properties, 3, important);
2417     }
2418     case CSSPropertyWebkitTextStroke: {
2419         const int properties[2] = { CSSPropertyWebkitTextStrokeWidth, CSSPropertyWebkitTextStrokeColor };
2420         return parseShorthand(propId, properties, 2, important);
2421     }
2422     case CSSPropertyWebkitAnimation:
2423         return parseAnimationShorthand(important);
2424     case CSSPropertyWebkitTransition:
2425         return parseTransitionShorthand(important);
2426     case CSSPropertyInvalid:
2427         return false;
2428     case CSSPropertyPage:
2429         return parsePage(propId, important);
2430     case CSSPropertyFontStretch:
2431     case CSSPropertyTextLineThrough:
2432     case CSSPropertyTextOverline:
2433     case CSSPropertyTextUnderline:
2434         return false;
2435     // CSS Text Layout Module Level 3: Vertical writing support
2436     case CSSPropertyWebkitTextEmphasis: {
2437         const int properties[] = { CSSPropertyWebkitTextEmphasisStyle, CSSPropertyWebkitTextEmphasisColor };
2438         return parseShorthand(propId, properties, WTF_ARRAY_LENGTH(properties), important);
2439     }
2440
2441     case CSSPropertyWebkitTextEmphasisStyle:
2442         return parseTextEmphasisStyle(important);
2443
2444     case CSSPropertyWebkitTextOrientation:
2445         // FIXME: For now just support upright and vertical-right.
2446         if (id == CSSValueVerticalRight || id == CSSValueUpright)
2447             validPrimitive = true;
2448         break;
2449
2450     case CSSPropertyWebkitLineBoxContain:
2451         if (id == CSSValueNone)
2452             validPrimitive = true;
2453         else
2454             return parseLineBoxContain(important);
2455         break;
2456     case CSSPropertyWebkitFontFeatureSettings:
2457         if (id == CSSValueNormal)
2458             validPrimitive = true;
2459         else
2460             return parseFontFeatureSettings(important);
2461         break;
2462
2463     case CSSPropertyWebkitFontVariantLigatures:
2464         if (id == CSSValueNormal)
2465             validPrimitive = true;
2466         else
2467             return parseFontVariantLigatures(important);
2468         break;
2469
2470     case CSSPropertyWebkitWrapShapeInside:
2471     case CSSPropertyWebkitWrapShapeOutside:
2472         if (id == CSSValueAuto)
2473             validPrimitive = true;
2474         else if (value->unit == CSSParserValue::Function)
2475             return parseWrapShape((propId == CSSPropertyWebkitWrapShapeInside), important);
2476         break;
2477     case CSSPropertyWebkitWrapMargin:
2478     case CSSPropertyWebkitWrapPadding:
2479         validPrimitive = (!id && validUnit(value, FLength | FNonNeg, m_strict));
2480         break;
2481     case CSSPropertyWebkitWrap: {
2482         const int properties[] = { CSSPropertyWebkitWrapFlow, CSSPropertyWebkitWrapMargin, CSSPropertyWebkitWrapPadding };
2483         return parseShorthand(propId, properties, WTF_ARRAY_LENGTH(properties), important);
2484     }
2485     case CSSPropertyBorderBottomStyle:
2486     case CSSPropertyBorderCollapse:
2487     case CSSPropertyBorderLeftStyle:
2488     case CSSPropertyBorderRightStyle:
2489     case CSSPropertyBorderTopStyle:
2490     case CSSPropertyBoxSizing:
2491     case CSSPropertyCaptionSide:
2492     case CSSPropertyClear:
2493     case CSSPropertyDirection:
2494     case CSSPropertyDisplay:
2495     case CSSPropertyEmptyCells:
2496     case CSSPropertyFloat:
2497     case CSSPropertyFontStyle:
2498     case CSSPropertyImageRendering:
2499     case CSSPropertyListStylePosition:
2500     case CSSPropertyListStyleType:
2501     case CSSPropertyOutlineStyle:
2502     case CSSPropertyOverflowX:
2503     case CSSPropertyOverflowY:
2504     case CSSPropertyPointerEvents:
2505     case CSSPropertyPosition:
2506     case CSSPropertyResize:
2507     case CSSPropertySpeak:
2508     case CSSPropertyTableLayout:
2509     case CSSPropertyTextLineThroughMode:
2510     case CSSPropertyTextLineThroughStyle:
2511     case CSSPropertyTextOverflow:
2512     case CSSPropertyTextOverlineMode:
2513     case CSSPropertyTextOverlineStyle:
2514     case CSSPropertyTextRendering:
2515     case CSSPropertyTextTransform:
2516     case CSSPropertyTextUnderlineMode:
2517     case CSSPropertyTextUnderlineStyle:
2518     case CSSPropertyVisibility:
2519     case CSSPropertyWebkitAppearance:
2520     case CSSPropertyWebkitBackfaceVisibility:
2521     case CSSPropertyWebkitBorderAfterStyle:
2522     case CSSPropertyWebkitBorderBeforeStyle:
2523     case CSSPropertyWebkitBorderEndStyle:
2524     case CSSPropertyWebkitBorderFit:
2525     case CSSPropertyWebkitBorderStartStyle:
2526     case CSSPropertyWebkitBoxAlign:
2527     case CSSPropertyWebkitBoxDirection:
2528     case CSSPropertyWebkitBoxLines:
2529     case CSSPropertyWebkitBoxOrient:
2530     case CSSPropertyWebkitBoxPack:
2531     case CSSPropertyWebkitColorCorrection:
2532     case CSSPropertyWebkitColumnRuleStyle:
2533     case CSSPropertyWebkitFlexAlign:
2534     case CSSPropertyWebkitFlexDirection:
2535     case CSSPropertyWebkitFlexItemAlign:
2536     case CSSPropertyWebkitFlexLinePack:
2537     case CSSPropertyWebkitFlexPack:
2538     case CSSPropertyWebkitFlexWrap:
2539     case CSSPropertyWebkitFontKerning:
2540     case CSSPropertyWebkitFontSmoothing:
2541     case CSSPropertyWebkitHyphens:
2542     case CSSPropertyWebkitLineAlign:
2543     case CSSPropertyWebkitLineBreak:
2544     case CSSPropertyWebkitLineSnap:
2545     case CSSPropertyWebkitMarginAfterCollapse:
2546     case CSSPropertyWebkitMarginBeforeCollapse:
2547     case CSSPropertyWebkitMarginBottomCollapse:
2548     case CSSPropertyWebkitMarginTopCollapse:
2549     case CSSPropertyWebkitMarqueeDirection:
2550     case CSSPropertyWebkitMarqueeStyle:
2551     case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
2552     case CSSPropertyWebkitNbspMode:
2553 #if ENABLE(OVERFLOW_SCROLLING)
2554     case CSSPropertyWebkitOverflowScrolling:
2555 #endif
2556     case CSSPropertyWebkitPrintColorAdjust:
2557     case CSSPropertyWebkitRtlOrdering:
2558     case CSSPropertyWebkitTextCombine:
2559     case CSSPropertyWebkitTextEmphasisPosition:
2560     case CSSPropertyWebkitTextSecurity:
2561     case CSSPropertyWebkitTextSizeAdjust:
2562     case CSSPropertyWebkitTransformStyle:
2563     case CSSPropertyWebkitUserDrag:
2564     case CSSPropertyWebkitUserModify:
2565     case CSSPropertyWebkitUserSelect:
2566     case CSSPropertyWebkitWrapFlow:
2567     case CSSPropertyWebkitWrapThrough:
2568     case CSSPropertyWebkitWritingMode:
2569     case CSSPropertyWhiteSpace:
2570     case CSSPropertyWordBreak:
2571     case CSSPropertyWordWrap:
2572         // These properties should be handled before in isValidKeywordPropertyAndValue().
2573         ASSERT_NOT_REACHED();
2574         return false;
2575 #if ENABLE(SVG)
2576     default:
2577         return parseSVGValue(propId, important);
2578 #endif
2579     }
2580
2581     if (validPrimitive) {
2582         parsedValue = parseValidPrimitive(id, value);
2583         m_valueList->next();
2584     }
2585     ASSERT(!m_parsedCalculation);
2586     if (parsedValue) {
2587         if (!m_valueList->current() || inShorthand()) {
2588             addProperty(propId, parsedValue.release(), important);
2589             return true;
2590         }
2591     }
2592     return false;
2593 }
2594
2595 void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
2596 {
2597     if (lval) {
2598         if (lval->isValueList())
2599             static_cast<CSSValueList*>(lval.get())->append(rval);
2600         else {
2601             PassRefPtr<CSSValue> oldlVal(lval.release());
2602             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2603             list->append(oldlVal);
2604             list->append(rval);
2605             lval = list;
2606         }
2607     }
2608     else
2609         lval = rval;
2610 }
2611
2612 static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue, CSSValuePool* cssValuePool)
2613 {
2614     if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox
2615         || parserValue->id == CSSValueContentBox || parserValue->id == CSSValueWebkitText) {
2616         cssValue = cssValuePool->createIdentifierValue(parserValue->id);
2617         return true;
2618     }
2619     return false;
2620 }
2621
2622 const int cMaxFillProperties = 9;
2623
2624 bool CSSParser::parseFillShorthand(int propId, const int* properties, int numProperties, bool important)
2625 {
2626     ASSERT(numProperties <= cMaxFillProperties);
2627     if (numProperties > cMaxFillProperties)
2628         return false;
2629
2630     ShorthandScope scope(this, propId);
2631
2632     bool parsedProperty[cMaxFillProperties] = { false };
2633     RefPtr<CSSValue> values[cMaxFillProperties];
2634     RefPtr<CSSValue> clipValue;
2635     RefPtr<CSSValue> positionYValue;
2636     RefPtr<CSSValue> repeatYValue;
2637     bool foundClip = false;
2638     int i;
2639
2640     while (m_valueList->current()) {
2641         CSSParserValue* val = m_valueList->current();
2642         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2643             // We hit the end.  Fill in all remaining values with the initial value.
2644             m_valueList->next();
2645             for (i = 0; i < numProperties; ++i) {
2646                 if (properties[i] == CSSPropertyBackgroundColor && parsedProperty[i])
2647                     // Color is not allowed except as the last item in a list for backgrounds.
2648                     // Reject the entire property.
2649                     return false;
2650
2651                 if (!parsedProperty[i] && properties[i] != CSSPropertyBackgroundColor) {
2652                     addFillValue(values[i], cssValuePool()->createImplicitInitialValue());
2653                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2654                         addFillValue(positionYValue, cssValuePool()->createImplicitInitialValue());
2655                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2656                         addFillValue(repeatYValue, cssValuePool()->createImplicitInitialValue());
2657                     if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
2658                         // If background-origin wasn't present, then reset background-clip also.
2659                         addFillValue(clipValue, cssValuePool()->createImplicitInitialValue());
2660                     }
2661                 }
2662                 parsedProperty[i] = false;
2663             }
2664             if (!m_valueList->current())
2665                 break;
2666         }
2667
2668         bool found = false;
2669         for (i = 0; !found && i < numProperties; ++i) {
2670             if (!parsedProperty[i]) {
2671                 RefPtr<CSSValue> val1;
2672                 RefPtr<CSSValue> val2;
2673                 int propId1, propId2;
2674                 CSSParserValue* parserValue = m_valueList->current();
2675                 if (parseFillProperty(properties[i], propId1, propId2, val1, val2)) {
2676                     parsedProperty[i] = found = true;
2677                     addFillValue(values[i], val1.release());
2678                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2679                         addFillValue(positionYValue, val2.release());
2680                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2681                         addFillValue(repeatYValue, val2.release());
2682                     if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
2683                         // Reparse the value as a clip, and see if we succeed.
2684                         if (parseBackgroundClip(parserValue, val1, cssValuePool()))
2685                             addFillValue(clipValue, val1.release()); // The property parsed successfully.
2686                         else
2687                             addFillValue(clipValue, cssValuePool()->createImplicitInitialValue()); // Some value was used for origin that is not supported by clip. Just reset clip instead.
2688                     }
2689                     if (properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) {
2690                         // Update clipValue
2691                         addFillValue(clipValue, val1.release());
2692                         foundClip = true;
2693                     }
2694                 }
2695             }
2696         }
2697
2698         // if we didn't find at least one match, this is an
2699         // invalid shorthand and we have to ignore it
2700         if (!found)
2701             return false;
2702     }
2703
2704     // Now add all of the properties we found.
2705     for (i = 0; i < numProperties; i++) {
2706         // Fill in any remaining properties with the initial value.
2707         if (!parsedProperty[i]) {
2708             addFillValue(values[i], cssValuePool()->createImplicitInitialValue());
2709             if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2710                 addFillValue(positionYValue, cssValuePool()->createImplicitInitialValue());
2711             if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2712                 addFillValue(repeatYValue, cssValuePool()->createImplicitInitialValue());
2713             if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin)) {
2714                 // If background-origin wasn't present, then reset background-clip also.
2715                 addFillValue(clipValue, cssValuePool()->createImplicitInitialValue());
2716             }
2717         }
2718         if (properties[i] == CSSPropertyBackgroundPosition) {
2719             addProperty(CSSPropertyBackgroundPositionX, values[i].release(), important);
2720             // it's OK to call positionYValue.release() since we only see CSSPropertyBackgroundPosition once
2721             addProperty(CSSPropertyBackgroundPositionY, positionYValue.release(), important);
2722         } else if (properties[i] == CSSPropertyWebkitMaskPosition) {
2723             addProperty(CSSPropertyWebkitMaskPositionX, values[i].release(), important);
2724             // it's OK to call positionYValue.release() since we only see CSSPropertyWebkitMaskPosition once
2725             addProperty(CSSPropertyWebkitMaskPositionY, positionYValue.release(), important);
2726         } else if (properties[i] == CSSPropertyBackgroundRepeat) {
2727             addProperty(CSSPropertyBackgroundRepeatX, values[i].release(), important);
2728             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2729             addProperty(CSSPropertyBackgroundRepeatY, repeatYValue.release(), important);
2730         } else if (properties[i] == CSSPropertyWebkitMaskRepeat) {
2731             addProperty(CSSPropertyWebkitMaskRepeatX, values[i].release(), important);
2732             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2733             addProperty(CSSPropertyWebkitMaskRepeatY, repeatYValue.release(), important);
2734         } else if ((properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) && !foundClip)
2735             // Value is already set while updating origin
2736             continue;
2737         else
2738             addProperty(properties[i], values[i].release(), important);
2739
2740         // Add in clip values when we hit the corresponding origin property.
2741         if (properties[i] == CSSPropertyBackgroundOrigin && !foundClip)
2742             addProperty(CSSPropertyBackgroundClip, clipValue.release(), important);
2743         else if (properties[i] == CSSPropertyWebkitMaskOrigin && !foundClip)
2744             addProperty(CSSPropertyWebkitMaskClip, clipValue.release(), important);
2745     }
2746
2747     return true;
2748 }
2749
2750 void CSSParser::addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
2751 {
2752     if (lval) {
2753         if (lval->isValueList())
2754             static_cast<CSSValueList*>(lval.get())->append(rval);
2755         else {
2756             PassRefPtr<CSSValue> oldVal(lval.release());
2757             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2758             list->append(oldVal);
2759             list->append(rval);
2760             lval = list;
2761         }
2762     }
2763     else
2764         lval = rval;
2765 }
2766
2767 bool CSSParser::parseAnimationShorthand(bool important)
2768 {
2769     const int properties[] = {  CSSPropertyWebkitAnimationName,
2770                                 CSSPropertyWebkitAnimationDuration,
2771                                 CSSPropertyWebkitAnimationTimingFunction,
2772                                 CSSPropertyWebkitAnimationDelay,
2773                                 CSSPropertyWebkitAnimationIterationCount,
2774                                 CSSPropertyWebkitAnimationDirection,
2775                                 CSSPropertyWebkitAnimationFillMode };
2776     const int numProperties = WTF_ARRAY_LENGTH(properties);
2777
2778     ShorthandScope scope(this, CSSPropertyWebkitAnimation);
2779
2780     bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
2781     RefPtr<CSSValue> values[numProperties];
2782
2783     int i;
2784     int initialParsedPropertyIndex = 0;
2785     while (m_valueList->current()) {
2786         CSSParserValue* val = m_valueList->current();
2787         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2788             // We hit the end.  Fill in all remaining values with the initial value.
2789             initialParsedPropertyIndex = 0;
2790             m_valueList->next();
2791             for (i = 0; i < numProperties; ++i) {
2792                 if (!parsedProperty[i])
2793                     addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
2794                 parsedProperty[i] = false;
2795             }
2796             if (!m_valueList->current())
2797                 break;
2798         }
2799
2800         bool found = false;
2801         for (i = initialParsedPropertyIndex; !found && i < numProperties; ++i) {
2802             if (!parsedProperty[i]) {
2803                 RefPtr<CSSValue> val;
2804                 if (parseAnimationProperty(properties[i], val)) {
2805                     parsedProperty[i] = found = true;
2806                     initialParsedPropertyIndex = 1;
2807                     addAnimationValue(values[i], val.release());
2808                 }
2809             }
2810         }
2811
2812         // if we didn't find at least one match, this is an
2813         // invalid shorthand and we have to ignore it
2814         if (!found)
2815             return false;
2816     }
2817
2818     // Fill in any remaining properties with the initial value.
2819     for (i = 0; i < numProperties; ++i) {
2820         if (!parsedProperty[i])
2821             addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
2822     }
2823
2824     // Now add all of the properties we found.
2825     for (i = 0; i < numProperties; i++)
2826         addProperty(properties[i], values[i].release(), important);
2827
2828     return true;
2829 }
2830
2831 bool CSSParser::parseTransitionShorthand(bool important)
2832 {
2833     const int properties[] = { CSSPropertyWebkitTransitionProperty,
2834                                CSSPropertyWebkitTransitionDuration,
2835                                CSSPropertyWebkitTransitionTimingFunction,
2836                                CSSPropertyWebkitTransitionDelay };
2837     const int numProperties = WTF_ARRAY_LENGTH(properties);
2838
2839     ShorthandScope scope(this, CSSPropertyWebkitTransition);
2840
2841     bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
2842     RefPtr<CSSValue> values[numProperties];
2843
2844     int i;
2845     while (m_valueList->current()) {
2846         CSSParserValue* val = m_valueList->current();
2847         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2848             // We hit the end.  Fill in all remaining values with the initial value.
2849             m_valueList->next();
2850             for (i = 0; i < numProperties; ++i) {
2851                 if (!parsedProperty[i])
2852                     addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
2853                 parsedProperty[i] = false;
2854             }
2855             if (!m_valueList->current())
2856                 break;
2857         }
2858
2859         bool found = false;
2860         for (i = 0; !found && i < numProperties; ++i) {
2861             if (!parsedProperty[i]) {
2862                 RefPtr<CSSValue> val;
2863                 if (parseAnimationProperty(properties[i], val)) {
2864                     parsedProperty[i] = found = true;
2865                     addAnimationValue(values[i], val.release());
2866                 }
2867             }
2868         }
2869
2870         // if we didn't find at least one match, this is an
2871         // invalid shorthand and we have to ignore it
2872         if (!found)
2873             return false;
2874     }
2875
2876     // Fill in any remaining properties with the initial value.
2877     for (i = 0; i < numProperties; ++i) {
2878         if (!parsedProperty[i])
2879             addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
2880     }
2881
2882     // Now add all of the properties we found.
2883     for (i = 0; i < numProperties; i++)
2884         addProperty(properties[i], values[i].release(), important);
2885
2886     return true;
2887 }
2888
2889 bool CSSParser::parseShorthand(int propId, const int *properties, int numProperties, bool important)
2890 {
2891     // We try to match as many properties as possible
2892     // We set up an array of booleans to mark which property has been found,
2893     // and we try to search for properties until it makes no longer any sense.
2894     ShorthandScope scope(this, propId);
2895
2896     bool found = false;
2897     int propertiesParsed = 0;
2898     bool fnd[6]= { false, false, false, false, false, false }; // 6 is enough size.
2899
2900     while (m_valueList->current()) {
2901         found = false;
2902         for (int propIndex = 0; !found && propIndex < numProperties; ++propIndex) {
2903             if (!fnd[propIndex] && parseValue(properties[propIndex], important)) {
2904                     fnd[propIndex] = found = true;
2905                     propertiesParsed++;
2906             }
2907         }
2908
2909         // if we didn't find at least one match, this is an
2910         // invalid shorthand and we have to ignore it
2911         if (!found)
2912             return false;
2913     }
2914
2915     if (propertiesParsed == numProperties)
2916         return true;
2917
2918     // Fill in any remaining properties with the initial value.
2919     ImplicitScope implicitScope(this, PropertyImplicit);
2920     for (int i = 0; i < numProperties; ++i) {
2921         if (!fnd[i])
2922             addProperty(properties[i], cssValuePool()->createImplicitInitialValue(), important);
2923     }
2924
2925     return true;
2926 }
2927
2928 bool CSSParser::parse4Values(int propId, const int *properties,  bool important)
2929 {
2930     /* From the CSS 2 specs, 8.3
2931      * If there is only one value, it applies to all sides. If there are two values, the top and
2932      * bottom margins are set to the first value and the right and left margins are set to the second.
2933      * If there are three values, the top is set to the first value, the left and right are set to the
2934      * second, and the bottom is set to the third. If there are four values, they apply to the top,
2935      * right, bottom, and left, respectively.
2936      */
2937
2938     int num = inShorthand() ? 1 : m_valueList->size();
2939
2940     ShorthandScope scope(this, propId);
2941
2942     // the order is top, right, bottom, left
2943     switch (num) {
2944         case 1: {
2945             if (!parseValue(properties[0], important))
2946                 return false;
2947             CSSValue *value = m_parsedProperties.last().value();
2948             ImplicitScope implicitScope(this, PropertyImplicit);
2949             addProperty(properties[1], value, important);
2950             addProperty(properties[2], value, important);
2951             addProperty(properties[3], value, important);
2952             break;
2953         }
2954         case 2: {
2955             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
2956                 return false;
2957             CSSValue *value = m_parsedProperties[m_parsedProperties.size() - 2].value();
2958             ImplicitScope implicitScope(this, PropertyImplicit);
2959             addProperty(properties[2], value, important);
2960             value = m_parsedProperties[m_parsedProperties.size() - 2].value();
2961             addProperty(properties[3], value, important);
2962             break;
2963         }
2964         case 3: {
2965             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
2966                 return false;
2967             CSSValue *value = m_parsedProperties[m_parsedProperties.size() - 2].value();
2968             ImplicitScope implicitScope(this, PropertyImplicit);
2969             addProperty(properties[3], value, important);
2970             break;
2971         }
2972         case 4: {
2973             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
2974                 !parseValue(properties[2], important) || !parseValue(properties[3], important))
2975                 return false;
2976             break;
2977         }
2978         default: {
2979             return false;
2980         }
2981     }
2982
2983     return true;
2984 }
2985
2986 // auto | <identifier>
2987 bool CSSParser::parsePage(int propId, bool important)
2988 {
2989     ASSERT(propId == CSSPropertyPage);
2990
2991     if (m_valueList->size() != 1)
2992         return false;
2993
2994     CSSParserValue* value = m_valueList->current();
2995     if (!value)
2996         return false;
2997
2998     if (value->id == CSSValueAuto) {
2999         addProperty(propId, cssValuePool()->createIdentifierValue(value->id), important);
3000         return true;
3001     } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) {
3002         addProperty(propId, createPrimitiveStringValue(value), important);
3003         return true;
3004     }
3005     return false;
3006 }
3007
3008 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
3009 bool CSSParser::parseSize(int propId, bool important)
3010 {
3011     ASSERT(propId == CSSPropertySize);
3012
3013     if (m_valueList->size() > 2)
3014         return false;
3015
3016     CSSParserValue* value = m_valueList->current();
3017     if (!value)
3018         return false;
3019
3020     RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
3021
3022     // First parameter.
3023     SizeParameterType paramType = parseSizeParameter(parsedValues.get(), value, None);
3024     if (paramType == None)
3025         return false;
3026
3027     // Second parameter, if any.
3028     value = m_valueList->next();
3029     if (value) {
3030         paramType = parseSizeParameter(parsedValues.get(), value, paramType);
3031         if (paramType == None)
3032             return false;
3033     }
3034
3035     addProperty(propId, parsedValues.release(), important);
3036     return true;
3037 }
3038
3039 CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType)
3040 {
3041     switch (value->id) {
3042     case CSSValueAuto:
3043         if (prevParamType == None) {
3044             parsedValues->append(cssValuePool()->createIdentifierValue(value->id));
3045             return Auto;
3046         }
3047         return None;
3048     case CSSValueLandscape:
3049     case CSSValuePortrait:
3050         if (prevParamType == None || prevParamType == PageSize) {
3051             parsedValues->append(cssValuePool()->createIdentifierValue(value->id));
3052             return Orientation;
3053         }
3054         return None;
3055     case CSSValueA3:
3056     case CSSValueA4:
3057     case CSSValueA5:
3058     case CSSValueB4:
3059     case CSSValueB5:
3060     case CSSValueLedger:
3061     case CSSValueLegal:
3062     case CSSValueLetter:
3063         if (prevParamType == None || prevParamType == Orientation) {
3064             // Normalize to Page Size then Orientation order by prepending.
3065             // This is not specified by the CSS3 Paged Media specification, but for simpler processing later (CSSStyleSelector::applyPageSizeProperty).
3066             parsedValues->prepend(cssValuePool()->createIdentifierValue(value->id));
3067             return PageSize;
3068         }
3069         return None;
3070     case 0:
3071         if (validUnit(value, FLength | FNonNeg, m_strict) && (prevParamType == None || prevParamType == Length)) {
3072             parsedValues->append(createPrimitiveNumericValue(value));
3073             return Length;
3074         }
3075         return None;
3076     default:
3077         return None;
3078     }
3079 }
3080
3081 // [ <string> <string> ]+ | inherit | none
3082 // inherit and none are handled in parseValue.
3083 bool CSSParser::parseQuotes(int propId, bool important)
3084 {
3085     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3086     while (CSSParserValue* val = m_valueList->current()) {
3087         RefPtr<CSSValue> parsedValue;
3088         if (val->unit == CSSPrimitiveValue::CSS_STRING)
3089             parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING);
3090         else
3091             break;
3092         values->append(parsedValue.release());
3093         m_valueList->next();
3094     }
3095     if (values->length()) {
3096         addProperty(propId, values.release(), important);
3097         m_valueList->next();
3098         return true;
3099     }
3100     return false;
3101 }
3102
3103 // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
3104 // in CSS 2.1 this got somewhat reduced:
3105 // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
3106 bool CSSParser::parseContent(int propId, bool important)
3107 {
3108     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3109
3110     while (CSSParserValue* val = m_valueList->current()) {
3111         RefPtr<CSSValue> parsedValue;
3112         if (val->unit == CSSPrimitiveValue::CSS_URI && m_styleSheet) {
3113             // url
3114             // FIXME: The completeURL call should be done when using the CSSImageValue,
3115             // not when creating it.
3116             parsedValue = CSSImageValue::create(m_styleSheet->completeURL(val->string));
3117         } else if (val->unit == CSSParserValue::Function) {
3118             // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) | -webkit-gradient(...)
3119             CSSParserValueList* args = val->function->args.get();
3120             if (!args)
3121                 return false;
3122             if (equalIgnoringCase(val->function->name, "attr(")) {
3123                 parsedValue = parseAttr(args);
3124                 if (!parsedValue)
3125                     return false;
3126             } else if (equalIgnoringCase(val->function->name, "counter(")) {
3127                 parsedValue = parseCounterContent(args, false);
3128                 if (!parsedValue)
3129                     return false;
3130             } else if (equalIgnoringCase(val->function->name, "counters(")) {
3131                 parsedValue = parseCounterContent(args, true);
3132                 if (!parsedValue)
3133                     return false;
3134 #if ENABLE(CSS_IMAGE_SET)
3135             } else if (equalIgnoringCase(val->function->name, "-webkit-image-set(")) {
3136                 parsedValue = parseImageSet(m_valueList.get());
3137                 if (!parsedValue)
3138                     return false;
3139 #endif
3140             } else if (isGeneratedImageValue(val)) {
3141                 if (!parseGeneratedImage(m_valueList.get(), parsedValue))
3142                     return false;
3143             } else
3144                 return false;
3145         } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
3146             // open-quote
3147             // close-quote
3148             // no-open-quote
3149             // no-close-quote
3150             // inherit
3151             // FIXME: These are not yet implemented (http://bugs.webkit.org/show_bug.cgi?id=6503).
3152             // none
3153             // normal
3154             switch (val->id) {
3155             case CSSValueOpenQuote:
3156             case CSSValueCloseQuote:
3157             case CSSValueNoOpenQuote:
3158             case CSSValueNoCloseQuote:
3159             case CSSValueNone:
3160             case CSSValueNormal:
3161                 parsedValue = cssValuePool()->createIdentifierValue(val->id);
3162             }
3163         } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
3164             parsedValue = createPrimitiveStringValue(val);
3165         }
3166         if (!parsedValue)
3167             break;
3168         values->append(parsedValue.release());
3169         m_valueList->next();
3170     }
3171
3172     if (values->length()) {
3173         addProperty(propId, values.release(), important);
3174         m_valueList->next();
3175         return true;
3176     }
3177
3178     return false;
3179 }
3180
3181 PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args)
3182 {
3183     if (args->size() != 1)
3184         return 0;
3185
3186     CSSParserValue* a = args->current();
3187
3188     if (a->unit != CSSPrimitiveValue::CSS_IDENT)
3189         return 0;
3190
3191     String attrName = a->string;
3192     // CSS allows identifiers with "-" at the start, like "-webkit-mask-image".
3193     // But HTML attribute names can't have those characters, and we should not
3194     // even parse them inside attr().
3195     if (attrName[0] == '-')
3196         return 0;
3197
3198     Document* document = findDocument();
3199     if (document && document->isHTMLDocument())
3200         attrName = attrName.lower();
3201
3202     return cssValuePool()->createValue(attrName, CSSPrimitiveValue::CSS_ATTR);
3203 }
3204
3205 PassRefPtr<CSSValue> CSSParser::parseBackgroundColor()
3206 {
3207     int id = m_valueList->current()->id;
3208     if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor ||
3209         (id >= CSSValueGrey && id < CSSValueWebkitText && !m_strict))
3210         return cssValuePool()->createIdentifierValue(id);
3211     return parseColor();
3212 }
3213
3214 bool CSSParser::parseFillImage(CSSParserValueList* valueList, RefPtr<CSSValue>& value)
3215 {
3216     if (valueList->current()->id == CSSValueNone) {
3217         value = cssValuePool()->createIdentifierValue(CSSValueNone);
3218         return true;
3219     }
3220     if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
3221         // FIXME: The completeURL call should be done when using the CSSImageValue,
3222         // not when creating it.
3223         if (m_styleSheet)
3224             value = CSSImageValue::create(m_styleSheet->completeURL(valueList->current()->string));
3225         return true;
3226     }
3227
3228     if (isGeneratedImageValue(valueList->current()))
3229         return parseGeneratedImage(valueList, value);
3230     
3231 #if ENABLE(CSS_IMAGE_SET)
3232     if (valueList->current()->unit == CSSParserValue::Function && equalIgnoringCase(valueList->current()->function->name, "-webkit-image-set(")) {
3233         value = parseImageSet(m_valueList.get());
3234         if (value)
3235             return true;
3236     }
3237 #endif
3238
3239     return false;
3240 }
3241
3242 PassRefPtr<CSSValue> CSSParser::parseFillPositionX(CSSParserValueList* valueList)
3243 {
3244     int id = valueList->current()->id;
3245     if (id == CSSValueLeft || id == CSSValueRight || id == CSSValueCenter) {
3246         int percent = 0;
3247         if (id == CSSValueRight)
3248             percent = 100;
3249         else if (id == CSSValueCenter)
3250             percent = 50;
3251         return cssValuePool()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3252     }
3253     if (validUnit(valueList->current(), FPercent | FLength, m_strict))
3254         return createPrimitiveNumericValue(valueList->current());
3255     return 0;
3256 }
3257
3258 PassRefPtr<CSSValue> CSSParser::parseFillPositionY(CSSParserValueList* valueList)
3259 {
3260     int id = valueList->current()->id;
3261     if (id == CSSValueTop || id == CSSValueBottom || id == CSSValueCenter) {
3262         int percent = 0;
3263         if (id == CSSValueBottom)
3264             percent = 100;
3265         else if (id == CSSValueCenter)
3266             percent = 50;
3267         return cssValuePool()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3268     }
3269     if (validUnit(valueList->current(), FPercent | FLength, m_strict))
3270         return createPrimitiveNumericValue(valueList->current());
3271     return 0;
3272 }
3273
3274 PassRefPtr<CSSValue> CSSParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag)
3275 {
3276     int id = valueList->current()->id;
3277     if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
3278         int percent = 0;
3279         if (id == CSSValueLeft || id == CSSValueRight) {
3280             if (cumulativeFlags & XFillPosition)
3281                 return 0;
3282             cumulativeFlags |= XFillPosition;
3283             individualFlag = XFillPosition;
3284             if (id == CSSValueRight)
3285                 percent = 100;
3286         }
3287         else if (id == CSSValueTop || id == CSSValueBottom) {
3288             if (cumulativeFlags & YFillPosition)
3289                 return 0;
3290             cumulativeFlags |= YFillPosition;
3291             individualFlag = YFillPosition;
3292             if (id == CSSValueBottom)
3293                 percent = 100;
3294         } else if (id == CSSValueCenter) {
3295             // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
3296             percent = 50;
3297             cumulativeFlags |= AmbiguousFillPosition;
3298             individualFlag = AmbiguousFillPosition;
3299         }
3300         return cssValuePool()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3301     }
3302     if (validUnit(valueList->current(), FPercent | FLength, m_strict)) {
3303         if (!cumulativeFlags) {
3304             cumulativeFlags |= XFillPosition;
3305             individualFlag = XFillPosition;
3306         } else if (cumulativeFlags & (XFillPosition | AmbiguousFillPosition)) {
3307             cumulativeFlags |= YFillPosition;
3308             individualFlag = YFillPosition;
3309         } else {
3310             if (m_parsedCalculation)
3311                 m_parsedCalculation.release();
3312             return 0;
3313         }
3314         return createPrimitiveNumericValue(valueList->current());
3315     }
3316     return 0;
3317 }
3318
3319 void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
3320 {
3321     CSSParserValue* value = valueList->current();
3322
3323     // Parse the first value.  We're just making sure that it is one of the valid keywords or a percentage/length.
3324     unsigned cumulativeFlags = 0;
3325     FillPositionFlag value1Flag = InvalidFillPosition;
3326     FillPositionFlag value2Flag = InvalidFillPosition;
3327     value1 = parseFillPositionComponent(valueList, cumulativeFlags, value1Flag);
3328     if (!value1)
3329         return;
3330
3331     // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
3332     // can assume that any other values belong to the rest of the shorthand).  If we're not parsing a shorthand, though, the
3333     // value was explicitly specified for our property.
3334     value = valueList->next();
3335
3336     // First check for the comma.  If so, we are finished parsing this value or value pair.
3337     if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
3338         value = 0;
3339
3340     if (value) {
3341         value2 = parseFillPositionComponent(valueList, cumulativeFlags, value2Flag);
3342         if (value2)
3343             valueList->next();
3344         else {
3345             if (!inShorthand()) {
3346                 value1.clear();
3347                 return;
3348             }
3349         }
3350     }
3351
3352     if (!value2)
3353         // Only one value was specified.  If that value was not a keyword, then it sets the x position, and the y position
3354         // is simply 50%.  This is our default.
3355         // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
3356         // For left/right/center, the default of 50% in the y is still correct.
3357         value2 = cssValuePool()->createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
3358
3359     if (value1Flag == YFillPosition || value2Flag == XFillPosition)