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