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