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