1826d42c86ec6a8b7f2835aef4bca95bb3e8364f
[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 CSSPropertyWebkitColumnWidth:         // auto | <length>
1490         if (id == CSSValueAuto)
1491             validPrimitive = true;
1492         else // Always parse this property in strict mode, since it would be ambiguous otherwise when used in the 'columns' shorthand property.
1493             validPrimitive = validUnit(value, FLength, true);
1494         break;
1495     case CSSPropertyPointerEvents:
1496         // none | visiblePainted | visibleFill | visibleStroke | visible |
1497         // painted | fill | stroke | auto | all | inherit
1498         if (id == CSSValueVisible || id == CSSValueNone || id == CSSValueAll || id == CSSValueAuto ||
1499             (id >= CSSValueVisiblepainted && id <= CSSValueStroke))
1500             validPrimitive = true;
1501         break;
1502
1503     // End of CSS3 properties
1504
1505     // Apple specific properties.  These will never be standardized and are purely to
1506     // support custom WebKit-based Apple applications.
1507     case CSSPropertyWebkitLineClamp:
1508         // When specifying number of lines, don't allow 0 as a valid value
1509         // When specifying either type of unit, require non-negative integers
1510         validPrimitive = (!id && (value->unit == CSSPrimitiveValue::CSS_PERCENTAGE || value->fValue) && validUnit(value, FInteger | FPercent | FNonNeg, false));
1511         break;
1512     case CSSPropertyWebkitTextSizeAdjust:
1513         if (id == CSSValueAuto || id == CSSValueNone)
1514             validPrimitive = true;
1515         break;
1516     case CSSPropertyWebkitRtlOrdering:
1517         if (id == CSSValueLogical || id == CSSValueVisual)
1518             validPrimitive = true;
1519         break;
1520
1521     case CSSPropertyWebkitFontSizeDelta:           // <length>
1522         validPrimitive = validUnit(value, FLength, m_strict);
1523         break;
1524
1525     case CSSPropertyWebkitNbspMode:     // normal | space
1526         if (id == CSSValueNormal || id == CSSValueSpace)
1527             validPrimitive = true;
1528         break;
1529
1530     case CSSPropertyWebkitLineBreak:   // normal | after-white-space
1531         if (id == CSSValueNormal || id == CSSValueAfterWhiteSpace)
1532             validPrimitive = true;
1533         break;
1534
1535     case CSSPropertyWebkitMatchNearestMailBlockquoteColor:   // normal | match
1536         if (id == CSSValueNormal || id == CSSValueMatch)
1537             validPrimitive = true;
1538         break;
1539
1540     case CSSPropertyWebkitHighlight:
1541         if (id == CSSValueNone || value->unit == CSSPrimitiveValue::CSS_STRING)
1542             validPrimitive = true;
1543         break;
1544
1545     case CSSPropertyWebkitBorderFit:
1546         if (id == CSSValueBorder || id == CSSValueLines)
1547             validPrimitive = true;
1548         break;
1549
1550     case CSSPropertyWebkitTextSecurity:
1551         // disc | circle | square | none | inherit
1552         if (id == CSSValueDisc || id == CSSValueCircle || id == CSSValueSquare|| id == CSSValueNone)
1553             validPrimitive = true;
1554         break;
1555
1556     case CSSPropertyWebkitFontSmoothing:
1557         if (id == CSSValueAuto || id == CSSValueNone
1558             || id == CSSValueAntialiased || id == CSSValueSubpixelAntialiased)
1559             validPrimitive = true;
1560         break;
1561
1562 #if ENABLE(DASHBOARD_SUPPORT)
1563     case CSSPropertyWebkitDashboardRegion: // <dashboard-region> | <dashboard-region>
1564         if (value->unit == CSSParserValue::Function || id == CSSValueNone)
1565             return parseDashboardRegions(propId, important);
1566         break;
1567 #endif
1568     // End Apple-specific properties
1569
1570         /* shorthand properties */
1571     case CSSPropertyBackground: {
1572         // Position must come before color in this array because a plain old "0" is a legal color
1573         // in quirks mode but it's usually the X coordinate of a position.
1574         // FIXME: Add CSSPropertyBackgroundSize to the shorthand.
1575         const int properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat,
1576                                    CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyBackgroundOrigin,
1577                                    CSSPropertyBackgroundColor };
1578         return parseFillShorthand(propId, properties, 6, important);
1579     }
1580     case CSSPropertyWebkitMask: {
1581         const int properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
1582                                    CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition,
1583                                    CSSPropertyWebkitMaskOrigin };
1584         return parseFillShorthand(propId, properties, 5, important);
1585     }
1586     case CSSPropertyBorder:
1587         // [ 'border-width' || 'border-style' || <color> ] | inherit
1588     {
1589         const int properties[3] = { CSSPropertyBorderWidth, CSSPropertyBorderStyle,
1590                                     CSSPropertyBorderColor };
1591         return parseShorthand(propId, properties, 3, important);
1592     }
1593     case CSSPropertyBorderTop:
1594         // [ 'border-top-width' || 'border-style' || <color> ] | inherit
1595     {
1596         const int properties[3] = { CSSPropertyBorderTopWidth, CSSPropertyBorderTopStyle,
1597                                     CSSPropertyBorderTopColor};
1598         return parseShorthand(propId, properties, 3, important);
1599     }
1600     case CSSPropertyBorderRight:
1601         // [ 'border-right-width' || 'border-style' || <color> ] | inherit
1602     {
1603         const int properties[3] = { CSSPropertyBorderRightWidth, CSSPropertyBorderRightStyle,
1604                                     CSSPropertyBorderRightColor };
1605         return parseShorthand(propId, properties, 3, important);
1606     }
1607     case CSSPropertyBorderBottom:
1608         // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
1609     {
1610         const int properties[3] = { CSSPropertyBorderBottomWidth, CSSPropertyBorderBottomStyle,
1611                                     CSSPropertyBorderBottomColor };
1612         return parseShorthand(propId, properties, 3, important);
1613     }
1614     case CSSPropertyBorderLeft:
1615         // [ 'border-left-width' || 'border-style' || <color> ] | inherit
1616     {
1617         const int properties[3] = { CSSPropertyBorderLeftWidth, CSSPropertyBorderLeftStyle,
1618                                     CSSPropertyBorderLeftColor };
1619         return parseShorthand(propId, properties, 3, important);
1620     }
1621     case CSSPropertyOutline:
1622         // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
1623     {
1624         const int properties[3] = { CSSPropertyOutlineWidth, CSSPropertyOutlineStyle,
1625                                     CSSPropertyOutlineColor };
1626         return parseShorthand(propId, properties, 3, important);
1627     }
1628     case CSSPropertyBorderColor:
1629         // <color>{1,4} | inherit
1630     {
1631         const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor,
1632                                     CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
1633         return parse4Values(propId, properties, important);
1634     }
1635     case CSSPropertyBorderWidth:
1636         // <border-width>{1,4} | inherit
1637     {
1638         const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth,
1639                                     CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
1640         return parse4Values(propId, properties, important);
1641     }
1642     case CSSPropertyBorderStyle:
1643         // <border-style>{1,4} | inherit
1644     {
1645         const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle,
1646                                     CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
1647         return parse4Values(propId, properties, important);
1648     }
1649     case CSSPropertyMargin:
1650         // <margin-width>{1,4} | inherit
1651     {
1652         const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight,
1653                                     CSSPropertyMarginBottom, CSSPropertyMarginLeft };
1654         return parse4Values(propId, properties, important);
1655     }
1656     case CSSPropertyPadding:
1657         // <padding-width>{1,4} | inherit
1658     {
1659         const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight,
1660                                     CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
1661         return parse4Values(propId, properties, important);
1662     }
1663     case CSSPropertyFont:
1664         // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
1665         // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
1666         if (id >= CSSValueCaption && id <= CSSValueStatusBar)
1667             validPrimitive = true;
1668         else
1669             return parseFont(important);
1670         break;
1671     case CSSPropertyListStyle:
1672     {
1673         const int properties[3] = { CSSPropertyListStyleType, CSSPropertyListStylePosition,
1674                                     CSSPropertyListStyleImage };
1675         return parseShorthand(propId, properties, 3, important);
1676     }
1677     case CSSPropertyWebkitColumns: {
1678         const int properties[2] = { CSSPropertyWebkitColumnWidth, CSSPropertyWebkitColumnCount };
1679         return parseShorthand(propId, properties, 2, important);
1680     }
1681     case CSSPropertyWebkitColumnRule: {
1682         const int properties[3] = { CSSPropertyWebkitColumnRuleWidth, CSSPropertyWebkitColumnRuleStyle,
1683                                     CSSPropertyWebkitColumnRuleColor };
1684         return parseShorthand(propId, properties, 3, important);
1685     }
1686     case CSSPropertyWebkitTextStroke: {
1687         const int properties[2] = { CSSPropertyWebkitTextStrokeWidth, CSSPropertyWebkitTextStrokeColor };
1688         return parseShorthand(propId, properties, 2, important);
1689     }
1690     case CSSPropertyWebkitAnimation:
1691         return parseAnimationShorthand(important);
1692     case CSSPropertyWebkitTransition:
1693         return parseTransitionShorthand(important);
1694     case CSSPropertyInvalid:
1695         return false;
1696     case CSSPropertyPage:
1697         return parsePage(propId, important);
1698     case CSSPropertyFontStretch:
1699     case CSSPropertyTextLineThrough:
1700     case CSSPropertyTextOverline:
1701     case CSSPropertyTextUnderline:
1702     case CSSPropertyWebkitVariableDeclarationBlock:
1703         return false;
1704 #if ENABLE(WCSS)
1705     case CSSPropertyWapInputFormat:
1706         validPrimitive = true;
1707         break;
1708     case CSSPropertyWapInputRequired:
1709         parsedValue = parseWCSSInputProperty();
1710         break;
1711 #endif
1712
1713 #if ENABLE(SVG)
1714     default:
1715         return parseSVGValue(propId, important);
1716 #endif
1717     }
1718
1719     if (validPrimitive) {
1720         if (id != 0)
1721             parsedValue = CSSPrimitiveValue::createIdentifier(id);
1722         else if (value->unit == CSSPrimitiveValue::CSS_STRING)
1723             parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
1724         else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1725             parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
1726         else if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
1727             parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
1728         else if (value->unit >= CSSParserValue::Q_EMS)
1729             parsedValue = CSSQuirkPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_EMS);
1730         m_valueList->next();
1731     }
1732     if (parsedValue) {
1733         if (!m_valueList->current() || inShorthand()) {
1734             addProperty(propId, parsedValue.release(), important);
1735             return true;
1736         }
1737     }
1738     return false;
1739 }
1740
1741 #if ENABLE(WCSS)
1742 PassRefPtr<CSSValue> CSSParser::parseWCSSInputProperty()
1743 {
1744     RefPtr<CSSValue> parsedValue = 0;
1745     CSSParserValue* value = m_valueList->current();
1746     String inputProperty;
1747     if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT)
1748         inputProperty = String(value->string);
1749
1750     if (!inputProperty.isEmpty())
1751        parsedValue = CSSPrimitiveValue::create(inputProperty, CSSPrimitiveValue::CSS_STRING);
1752
1753     while (m_valueList->next()) {
1754     // pass all other values, if any. If we don't do this,
1755     // the parser will think that it's not done and won't process this property
1756     }
1757
1758     return parsedValue;
1759 }
1760 #endif
1761
1762 void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
1763 {
1764     if (lval) {
1765         if (lval->isValueList())
1766             static_cast<CSSValueList*>(lval.get())->append(rval);
1767         else {
1768             PassRefPtr<CSSValue> oldlVal(lval.release());
1769             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
1770             list->append(oldlVal);
1771             list->append(rval);
1772             lval = list;
1773         }
1774     }
1775     else
1776         lval = rval;
1777 }
1778
1779 static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue)
1780 {
1781     if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox || parserValue->id == CSSValueWebkitText) {
1782         cssValue = CSSPrimitiveValue::createIdentifier(parserValue->id);
1783         return true;
1784     }
1785     return false;
1786 }
1787
1788 const int cMaxFillProperties = 9;
1789
1790 bool CSSParser::parseFillShorthand(int propId, const int* properties, int numProperties, bool important)
1791 {
1792     ASSERT(numProperties <= cMaxFillProperties);
1793     if (numProperties > cMaxFillProperties)
1794         return false;
1795
1796     ShorthandScope scope(this, propId);
1797
1798     bool parsedProperty[cMaxFillProperties] = { false };
1799     RefPtr<CSSValue> values[cMaxFillProperties];
1800     RefPtr<CSSValue> clipValue;
1801     RefPtr<CSSValue> positionYValue;
1802     RefPtr<CSSValue> repeatYValue;
1803     int i;
1804
1805     while (m_valueList->current()) {
1806         CSSParserValue* val = m_valueList->current();
1807         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
1808             // We hit the end.  Fill in all remaining values with the initial value.
1809             m_valueList->next();
1810             for (i = 0; i < numProperties; ++i) {
1811                 if (properties[i] == CSSPropertyBackgroundColor && parsedProperty[i])
1812                     // Color is not allowed except as the last item in a list for backgrounds.
1813                     // Reject the entire property.
1814                     return false;
1815
1816                 if (!parsedProperty[i] && properties[i] != CSSPropertyBackgroundColor) {
1817                     addFillValue(values[i], CSSInitialValue::createImplicit());
1818                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
1819                         addFillValue(positionYValue, CSSInitialValue::createImplicit());
1820                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
1821                         addFillValue(repeatYValue, CSSInitialValue::createImplicit());
1822                     if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
1823                         // If background-origin wasn't present, then reset background-clip also.
1824                         addFillValue(clipValue, CSSInitialValue::createImplicit());
1825                     }
1826                 }
1827                 parsedProperty[i] = false;
1828             }
1829             if (!m_valueList->current())
1830                 break;
1831         }
1832
1833         bool found = false;
1834         for (i = 0; !found && i < numProperties; ++i) {
1835             if (!parsedProperty[i]) {
1836                 RefPtr<CSSValue> val1;
1837                 RefPtr<CSSValue> val2;
1838                 int propId1, propId2;
1839                 CSSParserValue* parserValue = m_valueList->current();
1840                 if (parseFillProperty(properties[i], propId1, propId2, val1, val2)) {
1841                     parsedProperty[i] = found = true;
1842                     addFillValue(values[i], val1.release());
1843                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
1844                         addFillValue(positionYValue, val2.release());
1845                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
1846                         addFillValue(repeatYValue, val2.release());
1847                     if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
1848                         // Reparse the value as a clip, and see if we succeed.
1849                         if (parseBackgroundClip(parserValue, val1))
1850                             addFillValue(clipValue, val1.release()); // The property parsed successfully.
1851                         else
1852                             addFillValue(clipValue, CSSInitialValue::createImplicit()); // Some value was used for origin that is not supported by clip. Just reset clip instead.
1853                     }
1854                 }
1855             }
1856         }
1857
1858         // if we didn't find at least one match, this is an
1859         // invalid shorthand and we have to ignore it
1860         if (!found)
1861             return false;
1862     }
1863
1864     // Fill in any remaining properties with the initial value.
1865     for (i = 0; i < numProperties; ++i) {
1866         if (!parsedProperty[i]) {
1867             addFillValue(values[i], CSSInitialValue::createImplicit());
1868             if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
1869                 addFillValue(positionYValue, CSSInitialValue::createImplicit());
1870             if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
1871                 addFillValue(repeatYValue, CSSInitialValue::createImplicit());
1872             if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
1873                 // If background-origin wasn't present, then reset background-clip also.
1874                 addFillValue(clipValue, CSSInitialValue::createImplicit());
1875             }
1876         }
1877     }
1878
1879     // Now add all of the properties we found.
1880     for (i = 0; i < numProperties; i++) {
1881         if (properties[i] == CSSPropertyBackgroundPosition) {
1882             addProperty(CSSPropertyBackgroundPositionX, values[i].release(), important);
1883             // it's OK to call positionYValue.release() since we only see CSSPropertyBackgroundPosition once
1884             addProperty(CSSPropertyBackgroundPositionY, positionYValue.release(), important);
1885         } else if (properties[i] == CSSPropertyWebkitMaskPosition) {
1886             addProperty(CSSPropertyWebkitMaskPositionX, values[i].release(), important);
1887             // it's OK to call positionYValue.release() since we only see CSSPropertyWebkitMaskPosition once
1888             addProperty(CSSPropertyWebkitMaskPositionY, positionYValue.release(), important);
1889         } else if (properties[i] == CSSPropertyBackgroundRepeat) {
1890             addProperty(CSSPropertyBackgroundRepeatX, values[i].release(), important);
1891             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
1892             addProperty(CSSPropertyBackgroundRepeatY, repeatYValue.release(), important);
1893         } else if (properties[i] == CSSPropertyWebkitMaskRepeat) {
1894             addProperty(CSSPropertyWebkitMaskRepeatX, values[i].release(), important);
1895             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
1896             addProperty(CSSPropertyWebkitMaskRepeatY, repeatYValue.release(), important);
1897         } else
1898             addProperty(properties[i], values[i].release(), important);
1899
1900         // Add in clip values when we hit the corresponding origin property.
1901         if (properties[i] == CSSPropertyBackgroundOrigin)
1902             addProperty(CSSPropertyBackgroundClip, clipValue.release(), important);
1903         else  if (properties[i] == CSSPropertyWebkitMaskOrigin)
1904             addProperty(CSSPropertyWebkitMaskClip, clipValue.release(), important);
1905     }
1906
1907     return true;
1908 }
1909
1910 void CSSParser::addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
1911 {
1912     if (lval) {
1913         if (lval->isValueList())
1914             static_cast<CSSValueList*>(lval.get())->append(rval);
1915         else {
1916             PassRefPtr<CSSValue> oldVal(lval.release());
1917             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
1918             list->append(oldVal);
1919             list->append(rval);
1920             lval = list;
1921         }
1922     }
1923     else
1924         lval = rval;
1925 }
1926
1927 bool CSSParser::parseAnimationShorthand(bool important)
1928 {
1929     const int properties[] = {  CSSPropertyWebkitAnimationName,
1930                                 CSSPropertyWebkitAnimationDuration,
1931                                 CSSPropertyWebkitAnimationTimingFunction,
1932                                 CSSPropertyWebkitAnimationDelay,
1933                                 CSSPropertyWebkitAnimationIterationCount,
1934                                 CSSPropertyWebkitAnimationDirection,
1935                                 CSSPropertyWebkitAnimationFillMode };
1936     const int numProperties = sizeof(properties) / sizeof(properties[0]);
1937
1938     ShorthandScope scope(this, CSSPropertyWebkitAnimation);
1939
1940     bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
1941     RefPtr<CSSValue> values[numProperties];
1942
1943     int i;
1944     while (m_valueList->current()) {
1945         CSSParserValue* val = m_valueList->current();
1946         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
1947             // We hit the end.  Fill in all remaining values with the initial value.
1948             m_valueList->next();
1949             for (i = 0; i < numProperties; ++i) {
1950                 if (!parsedProperty[i])
1951                     addAnimationValue(values[i], CSSInitialValue::createImplicit());
1952                 parsedProperty[i] = false;
1953             }
1954             if (!m_valueList->current())
1955                 break;
1956         }
1957
1958         bool found = false;
1959         for (i = 0; !found && i < numProperties; ++i) {
1960             if (!parsedProperty[i]) {
1961                 RefPtr<CSSValue> val;
1962                 if (parseAnimationProperty(properties[i], val)) {
1963                     parsedProperty[i] = found = true;
1964                     addAnimationValue(values[i], val.release());
1965                 }
1966             }
1967         }
1968
1969         // if we didn't find at least one match, this is an
1970         // invalid shorthand and we have to ignore it
1971         if (!found)
1972             return false;
1973     }
1974
1975     // Fill in any remaining properties with the initial value.
1976     for (i = 0; i < numProperties; ++i) {
1977         if (!parsedProperty[i])
1978             addAnimationValue(values[i], CSSInitialValue::createImplicit());
1979     }
1980
1981     // Now add all of the properties we found.
1982     for (i = 0; i < numProperties; i++)
1983         addProperty(properties[i], values[i].release(), important);
1984
1985     return true;
1986 }
1987
1988 bool CSSParser::parseTransitionShorthand(bool important)
1989 {
1990     const int properties[] = { CSSPropertyWebkitTransitionProperty,
1991                                CSSPropertyWebkitTransitionDuration,
1992                                CSSPropertyWebkitTransitionTimingFunction,
1993                                CSSPropertyWebkitTransitionDelay };
1994     const int numProperties = sizeof(properties) / sizeof(properties[0]);
1995
1996     ShorthandScope scope(this, CSSPropertyWebkitTransition);
1997
1998     bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
1999     RefPtr<CSSValue> values[numProperties];
2000
2001     int i;
2002     while (m_valueList->current()) {
2003         CSSParserValue* val = m_valueList->current();
2004         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2005             // We hit the end.  Fill in all remaining values with the initial value.
2006             m_valueList->next();
2007             for (i = 0; i < numProperties; ++i) {
2008                 if (!parsedProperty[i])
2009                     addAnimationValue(values[i], CSSInitialValue::createImplicit());
2010                 parsedProperty[i] = false;
2011             }
2012             if (!m_valueList->current())
2013                 break;
2014         }
2015
2016         bool found = false;
2017         for (i = 0; !found && i < numProperties; ++i) {
2018             if (!parsedProperty[i]) {
2019                 RefPtr<CSSValue> val;
2020                 if (parseAnimationProperty(properties[i], val)) {
2021                     parsedProperty[i] = found = true;
2022                     addAnimationValue(values[i], val.release());
2023                 }
2024             }
2025         }
2026
2027         // if we didn't find at least one match, this is an
2028         // invalid shorthand and we have to ignore it
2029         if (!found)
2030             return false;
2031     }
2032
2033     // Fill in any remaining properties with the initial value.
2034     for (i = 0; i < numProperties; ++i) {
2035         if (!parsedProperty[i])
2036             addAnimationValue(values[i], CSSInitialValue::createImplicit());
2037     }
2038
2039     // Now add all of the properties we found.
2040     for (i = 0; i < numProperties; i++)
2041         addProperty(properties[i], values[i].release(), important);
2042
2043     return true;
2044 }
2045
2046 bool CSSParser::parseShorthand(int propId, const int *properties, int numProperties, bool important)
2047 {
2048     // We try to match as many properties as possible
2049     // We set up an array of booleans to mark which property has been found,
2050     // and we try to search for properties until it makes no longer any sense.
2051     ShorthandScope scope(this, propId);
2052
2053     bool found = false;
2054     bool fnd[6]; // Trust me ;)
2055     for (int i = 0; i < numProperties; i++)
2056         fnd[i] = false;
2057
2058     while (m_valueList->current()) {
2059         found = false;
2060         for (int propIndex = 0; !found && propIndex < numProperties; ++propIndex) {
2061             if (!fnd[propIndex]) {
2062                 if (parseValue(properties[propIndex], important))
2063                     fnd[propIndex] = found = true;
2064             }
2065         }
2066
2067         // if we didn't find at least one match, this is an
2068         // invalid shorthand and we have to ignore it
2069         if (!found)
2070             return false;
2071     }
2072
2073     // Fill in any remaining properties with the initial value.
2074     m_implicitShorthand = true;
2075     for (int i = 0; i < numProperties; ++i) {
2076         if (!fnd[i])
2077             addProperty(properties[i], CSSInitialValue::createImplicit(), important);
2078     }
2079     m_implicitShorthand = false;
2080
2081     return true;
2082 }
2083
2084 bool CSSParser::parse4Values(int propId, const int *properties,  bool important)
2085 {
2086     /* From the CSS 2 specs, 8.3
2087      * If there is only one value, it applies to all sides. If there are two values, the top and
2088      * bottom margins are set to the first value and the right and left margins are set to the second.
2089      * If there are three values, the top is set to the first value, the left and right are set to the
2090      * second, and the bottom is set to the third. If there are four values, they apply to the top,
2091      * right, bottom, and left, respectively.
2092      */
2093
2094     int num = inShorthand() ? 1 : m_valueList->size();
2095
2096     ShorthandScope scope(this, propId);
2097
2098     // the order is top, right, bottom, left
2099     switch (num) {
2100         case 1: {
2101             if (!parseValue(properties[0], important))
2102                 return false;
2103             CSSValue *value = m_parsedProperties[m_numParsedProperties-1]->value();
2104             m_implicitShorthand = true;
2105             addProperty(properties[1], value, important);
2106             addProperty(properties[2], value, important);
2107             addProperty(properties[3], value, important);
2108             m_implicitShorthand = false;
2109             break;
2110         }
2111         case 2: {
2112             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
2113                 return false;
2114             CSSValue *value = m_parsedProperties[m_numParsedProperties-2]->value();
2115             m_implicitShorthand = true;
2116             addProperty(properties[2], value, important);
2117             value = m_parsedProperties[m_numParsedProperties-2]->value();
2118             addProperty(properties[3], value, important);
2119             m_implicitShorthand = false;
2120             break;
2121         }
2122         case 3: {
2123             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
2124                 return false;
2125             CSSValue *value = m_parsedProperties[m_numParsedProperties-2]->value();
2126             m_implicitShorthand = true;
2127             addProperty(properties[3], value, important);
2128             m_implicitShorthand = false;
2129             break;
2130         }
2131         case 4: {
2132             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
2133                 !parseValue(properties[2], important) || !parseValue(properties[3], important))
2134                 return false;
2135             break;
2136         }
2137         default: {
2138             return false;
2139         }
2140     }
2141
2142     return true;
2143 }
2144
2145 // auto | <identifier>
2146 bool CSSParser::parsePage(int propId, bool important)
2147 {
2148     ASSERT(propId == CSSPropertyPage);
2149
2150     if (m_valueList->size() != 1)
2151         return false;
2152
2153     CSSParserValue* value = m_valueList->current();
2154     if (!value)
2155         return false;
2156
2157     if (value->id == CSSValueAuto) {
2158         addProperty(propId, CSSPrimitiveValue::createIdentifier(value->id), important);
2159         return true;
2160     } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) {
2161         addProperty(propId, CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_STRING), important);
2162         return true;
2163     }
2164     return false;
2165 }
2166
2167 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
2168 bool CSSParser::parseSize(int propId, bool important)
2169 {
2170     ASSERT(propId == CSSPropertySize);
2171
2172     if (m_valueList->size() > 2)
2173         return false;
2174
2175     CSSParserValue* value = m_valueList->current();
2176     if (!value)
2177         return false;
2178
2179     RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
2180
2181     // First parameter.
2182     SizeParameterType paramType = parseSizeParameter(parsedValues.get(), value, None);
2183     if (paramType == None)
2184         return false;
2185
2186     // Second parameter, if any.
2187     value = m_valueList->next();
2188     if (value) {
2189         paramType = parseSizeParameter(parsedValues.get(), value, paramType);
2190         if (paramType == None)
2191             return false;
2192     }
2193
2194     addProperty(propId, parsedValues.release(), important);
2195     return true;
2196 }
2197
2198 CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType)
2199 {
2200     switch (value->id) {
2201     case CSSValueAuto:
2202         if (prevParamType == None) {
2203             parsedValues->append(CSSPrimitiveValue::createIdentifier(value->id));
2204             return Auto;
2205         }
2206         return None;
2207     case CSSValueLandscape:
2208     case CSSValuePortrait:
2209         if (prevParamType == None || prevParamType == PageSize) {
2210             parsedValues->append(CSSPrimitiveValue::createIdentifier(value->id));
2211             return Orientation;
2212         }
2213         return None;
2214     case CSSValueA3:
2215     case CSSValueA4:
2216     case CSSValueA5:
2217     case CSSValueB4:
2218     case CSSValueB5:
2219     case CSSValueLedger:
2220     case CSSValueLegal:
2221     case CSSValueLetter:
2222         if (prevParamType == None || prevParamType == Orientation) {
2223             // Normalize to Page Size then Orientation order by prepending.
2224             // This is not specified by the CSS3 Paged Media specification, but for simpler processing hereafter.
2225             parsedValues->prepend(CSSPrimitiveValue::createIdentifier(value->id));
2226             return PageSize;
2227         }
2228         return None;
2229     case 0:
2230         if (validUnit(value, FLength, m_strict) && (prevParamType == None || prevParamType == Length)) {
2231             parsedValues->append(CSSPrimitiveValue::create(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)));
2232             return Length;
2233         }
2234         return None;
2235     default:
2236         return None;
2237     }
2238 }
2239
2240 // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
2241 // in CSS 2.1 this got somewhat reduced:
2242 // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
2243 bool CSSParser::parseContent(int propId, bool important)
2244 {
2245     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
2246
2247     while (CSSParserValue* val = m_valueList->current()) {
2248         RefPtr<CSSValue> parsedValue;
2249         if (val->unit == CSSPrimitiveValue::CSS_URI && m_styleSheet) {
2250             // url
2251             // FIXME: The completeURL call should be done when using the CSSImageValue,
2252             // not when creating it.
2253             parsedValue = CSSImageValue::create(m_styleSheet->completeURL(val->string));
2254         } else if (val->unit == CSSParserValue::Function) {
2255             // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) | -webkit-gradient(...)
2256             CSSParserValueList* args = val->function->args;
2257             if (!args)
2258                 return false;
2259             if (equalIgnoringCase(val->function->name, "attr(")) {
2260                 parsedValue = parseAttr(args);
2261                 if (!parsedValue)
2262                     return false;
2263             } else if (equalIgnoringCase(val->function->name, "counter(")) {
2264                 parsedValue = parseCounterContent(args, false);
2265                 if (!parsedValue)
2266                     return false;
2267             } else if (equalIgnoringCase(val->function->name, "counters(")) {
2268                 parsedValue = parseCounterContent(args, true);
2269                 if (!parsedValue)
2270                     return false;
2271             } else if (equalIgnoringCase(val->function->name, "-webkit-gradient(")) {
2272                 if (!parseGradient(parsedValue))
2273                     return false;
2274             } else if (equalIgnoringCase(val->function->name, "-webkit-canvas(")) {
2275                 if (!parseCanvas(parsedValue))
2276                     return false;
2277             } else
2278                 return false;
2279         } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
2280             // open-quote
2281             // close-quote
2282             // no-open-quote
2283             // no-close-quote
2284             // FIXME: These are not yet implemented (http://bugs.webkit.org/show_bug.cgi?id=6503).
2285         } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
2286             parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING);
2287         }
2288         if (!parsedValue)
2289             break;
2290         values->append(parsedValue.release());
2291         m_valueList->next();
2292     }
2293
2294     if (values->length()) {
2295         addProperty(propId, values.release(), important);
2296         m_valueList->next();
2297         return true;
2298     }
2299
2300     return false;
2301 }
2302
2303 PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args)
2304 {
2305     if (args->size() != 1)
2306         return 0;
2307
2308     CSSParserValue* a = args->current();
2309
2310     if (a->unit != CSSPrimitiveValue::CSS_IDENT)
2311         return 0;
2312
2313     String attrName = a->string;
2314     // CSS allows identifiers with "-" at the start, like "-webkit-mask-image".
2315     // But HTML attribute names can't have those characters, and we should not
2316     // even parse them inside attr().
2317     if (attrName[0] == '-')
2318         return 0;
2319
2320     if (document() && document()->isHTMLDocument())
2321         attrName = attrName.lower();
2322
2323     return CSSPrimitiveValue::create(attrName, CSSPrimitiveValue::CSS_ATTR);
2324 }
2325
2326 PassRefPtr<CSSValue> CSSParser::parseBackgroundColor()
2327 {
2328     int id = m_valueList->current()->id;
2329     if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor ||
2330         (id >= CSSValueGrey && id < CSSValueWebkitText && !m_strict))
2331        return CSSPrimitiveValue::createIdentifier(id);
2332     return parseColor();
2333 }
2334
2335 bool CSSParser::parseFillImage(RefPtr<CSSValue>& value)
2336 {
2337     if (m_valueList->current()->id == CSSValueNone) {
2338         value = CSSImageValue::create();
2339         return true;
2340     }
2341     if (m_valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
2342         // FIXME: The completeURL call should be done when using the CSSImageValue,
2343         // not when creating it.
2344         if (m_styleSheet)
2345             value = CSSImageValue::create(m_styleSheet->completeURL(m_valueList->current()->string));
2346         return true;
2347     }
2348
2349     if (m_valueList->current()->unit == CSSParserValue::Function) {
2350         if (equalIgnoringCase(m_valueList->current()->function->name, "-webkit-gradient("))
2351             return parseGradient(value);
2352         if (equalIgnoringCase(m_valueList->current()->function->name, "-webkit-canvas("))
2353             return parseCanvas(value);
2354     }
2355
2356     return false;
2357 }
2358
2359 PassRefPtr<CSSValue> CSSParser::parseFillPositionXY(bool& xFound, bool& yFound)
2360 {
2361     int id = m_valueList->current()->id;
2362     if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
2363         int percent = 0;
2364         if (id == CSSValueLeft || id == CSSValueRight) {
2365             if (xFound)
2366                 return 0;
2367             xFound = true;
2368             if (id == CSSValueRight)
2369                 percent = 100;
2370         }
2371         else if (id == CSSValueTop || id == CSSValueBottom) {
2372             if (yFound)
2373                 return 0;
2374             yFound = true;
2375             if (id == CSSValueBottom)
2376                 percent = 100;
2377         }
2378         else if (id == CSSValueCenter)
2379             // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
2380             percent = 50;
2381         return CSSPrimitiveValue::create(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
2382     }
2383     if (validUnit(m_valueList->current(), FPercent | FLength, m_strict))
2384         return CSSPrimitiveValue::create(m_valueList->current()->fValue,
2385                                          (CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit);
2386
2387     return 0;
2388 }
2389
2390 void CSSParser::parseFillPosition(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
2391 {
2392     CSSParserValue* value = m_valueList->current();
2393
2394     // Parse the first value.  We're just making sure that it is one of the valid keywords or a percentage/length.
2395     bool value1IsX = false, value1IsY = false;
2396     value1 = parseFillPositionXY(value1IsX, value1IsY);
2397     if (!value1)
2398         return;
2399
2400     // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
2401     // can assume that any other values belong to the rest of the shorthand).  If we're not parsing a shorthand, though, the
2402     // value was explicitly specified for our property.
2403     value = m_valueList->next();
2404
2405     // First check for the comma.  If so, we are finished parsing this value or value pair.
2406     if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
2407         value = 0;
2408
2409     bool value2IsX = false, value2IsY = false;
2410     if (value) {
2411         value2 = parseFillPositionXY(value2IsX, value2IsY);
2412         if (value2)
2413             m_valueList->next();
2414         else {
2415             if (!inShorthand()) {
2416                 value1.clear();
2417                 return;
2418             }
2419         }
2420     }
2421
2422     if (!value2)
2423         // Only one value was specified.  If that value was not a keyword, then it sets the x position, and the y position
2424         // is simply 50%.  This is our default.
2425         // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
2426         // For left/right/center, the default of 50% in the y is still correct.
2427         value2 = CSSPrimitiveValue::create(50, CSSPrimitiveValue::CSS_PERCENTAGE);
2428
2429     if (value1IsY || value2IsX)
2430         value1.swap(value2);
2431 }
2432
2433 void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
2434 {
2435     CSSParserValue* value = m_valueList->current();
2436
2437     int id = m_valueList->current()->id;
2438     if (id == CSSValueRepeatX) {
2439         m_implicitShorthand = true;
2440         value1 = CSSPrimitiveValue::createIdentifier(CSSValueRepeat);
2441         value2 = CSSPrimitiveValue::createIdentifier(CSSValueNoRepeat);
2442         m_valueList->next();
2443         return;
2444     }
2445     if (id == CSSValueRepeatY) {
2446         m_implicitShorthand = true;
2447         value1 = CSSPrimitiveValue::createIdentifier(CSSValueNoRepeat);
2448         value2 = CSSPrimitiveValue::createIdentifier(CSSValueRepeat);
2449         m_valueList->next();
2450         return;
2451     }
2452     if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)
2453         value1 = CSSPrimitiveValue::createIdentifier(id);
2454     else {
2455         value1 = 0;
2456         return;
2457     }
2458
2459     value = m_valueList->next();
2460
2461     // First check for the comma.  If so, we are finished parsing this value or value pair.
2462     if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
2463         value = 0;
2464
2465     if (value)
2466         id = m_valueList->current()->id;
2467
2468     if (value && (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)) {
2469         value2 = CSSPrimitiveValue::createIdentifier(id);
2470         m_valueList->next();
2471     } else {
2472         // If only one value was specified, value2 is the same as value1.
2473         m_implicitShorthand = true;
2474         value2 = CSSPrimitiveValue::createIdentifier(static_cast<CSSPrimitiveValue*>(value1.get())->getIdent());
2475     }
2476 }
2477
2478 PassRefPtr<CSSValue> CSSParser::parseFillSize(int propId, bool& allowComma)
2479 {
2480     allowComma = true;
2481     CSSParserValue* value = m_valueList->current();
2482
2483     if (value->id == CSSValueContain || value->id == CSSValueCover)
2484         return CSSPrimitiveValue::createIdentifier(value->id);
2485
2486     RefPtr<CSSPrimitiveValue> parsedValue1;
2487
2488     if (value->id == CSSValueAuto)
2489         parsedValue1 = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_UNKNOWN);
2490     else {
2491         if (!validUnit(value, FLength | FPercent, m_strict))
2492             return 0;
2493         parsedValue1 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2494     }
2495
2496     CSSPropertyID property = static_cast<CSSPropertyID>(propId);
2497     RefPtr<CSSPrimitiveValue> parsedValue2;
2498     if ((value = m_valueList->next())) {
2499         if (value->id == CSSValueAuto)
2500             parsedValue2 = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_UNKNOWN);
2501         else if (value->unit == CSSParserValue::Operator && value->iValue == ',')
2502             allowComma = false;
2503         else {
2504             if (!validUnit(value, FLength | FPercent, m_strict))
2505                 return 0;
2506             parsedValue2 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2507         }
2508     }
2509     if (!parsedValue2) {
2510         if (property == CSSPropertyWebkitBackgroundSize || property == CSSPropertyWebkitMaskSize)
2511             parsedValue2 = parsedValue1;
2512         else
2513             parsedValue2 = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_UNKNOWN);
2514     }
2515
2516     return CSSPrimitiveValue::create(Pair::create(parsedValue1.release(), parsedValue2.release()));
2517 }
2518
2519 bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2,
2520                                   RefPtr<CSSValue>& retValue1, RefPtr<CSSValue>& retValue2)
2521 {
2522     RefPtr<CSSValueList> values;
2523     RefPtr<CSSValueList> values2;
2524     CSSParserValue* val;
2525     RefPtr<CSSValue> value;
2526     RefPtr<CSSValue> value2;
2527
2528     bool allowComma = false;
2529
2530     retValue1 = retValue2 = 0;
2531     propId1 = propId;
2532     propId2 = propId;
2533     if (propId == CSSPropertyBackgroundPosition) {
2534         propId1 = CSSPropertyBackgroundPositionX;
2535         propId2 = CSSPropertyBackgroundPositionY;
2536     } else if (propId == CSSPropertyWebkitMaskPosition) {
2537         propId1 = CSSPropertyWebkitMaskPositionX;
2538         propId2 = CSSPropertyWebkitMaskPositionY;
2539     } else if (propId == CSSPropertyBackgroundRepeat) {
2540         propId1 = CSSPropertyBackgroundRepeatX;
2541         propId2 = CSSPropertyBackgroundRepeatY;
2542     } else if (propId == CSSPropertyWebkitMaskRepeat) {
2543         propId1 = CSSPropertyWebkitMaskRepeatX;
2544         propId2 = CSSPropertyWebkitMaskRepeatY;
2545     }
2546
2547     while ((val = m_valueList->current())) {
2548         RefPtr<CSSValue> currValue;
2549         RefPtr<CSSValue> currValue2;
2550
2551         if (allowComma) {
2552             if (val->unit != CSSParserValue::Operator || val->iValue != ',')
2553                 return false;
2554             m_valueList->next();
2555             allowComma = false;
2556         } else {
2557             allowComma = true;
2558             switch (propId) {
2559                 case CSSPropertyBackgroundColor:
2560                     currValue = parseBackgroundColor();
2561                     if (currValue)
2562                         m_valueList->next();
2563                     break;
2564                 case CSSPropertyBackgroundAttachment:
2565                 case CSSPropertyWebkitMaskAttachment:
2566                     if (val->id == CSSValueScroll || val->id == CSSValueFixed || val->id == CSSValueLocal) {
2567                         currValue = CSSPrimitiveValue::createIdentifier(val->id);
2568                         m_valueList->next();
2569                     }
2570                     break;
2571                 case CSSPropertyBackgroundImage:
2572                 case CSSPropertyWebkitMaskImage:
2573                     if (parseFillImage(currValue))
2574                         m_valueList->next();
2575                     break;
2576                 case CSSPropertyWebkitBackgroundClip:
2577                 case CSSPropertyWebkitBackgroundOrigin:
2578                 case CSSPropertyWebkitMaskClip:
2579                 case CSSPropertyWebkitMaskOrigin:
2580                     // The first three values here are deprecated and do not apply to the version of the property that has
2581                     // the -webkit- prefix removed.
2582                     if (val->id == CSSValueBorder || val->id == CSSValuePadding || val->id == CSSValueContent ||
2583                         val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox ||
2584                         ((propId == CSSPropertyWebkitBackgroundClip || propId == CSSPropertyWebkitMaskClip) &&
2585                          (val->id == CSSValueText || val->id == CSSValueWebkitText))) {
2586                         currValue = CSSPrimitiveValue::createIdentifier(val->id);
2587                         m_valueList->next();
2588                     }
2589                     break;
2590                 case CSSPropertyBackgroundClip:
2591                     if (parseBackgroundClip(val, currValue))
2592                         m_valueList->next();
2593                     break;
2594                 case CSSPropertyBackgroundOrigin:
2595                     if (val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox) {
2596                         currValue = CSSPrimitiveValue::createIdentifier(val->id);
2597                         m_valueList->next();
2598                     }
2599                     break;
2600                 case CSSPropertyBackgroundPosition:
2601                 case CSSPropertyWebkitMaskPosition:
2602                     parseFillPosition(currValue, currValue2);
2603                     // parseFillPosition advances the m_valueList pointer
2604                     break;
2605                 case CSSPropertyBackgroundPositionX:
2606                 case CSSPropertyWebkitMaskPositionX: {
2607                     bool xFound = false, yFound = true;
2608                     currValue = parseFillPositionXY(xFound, yFound);
2609                     if (currValue)
2610                         m_valueList->next();
2611                     break;
2612                 }
2613                 case CSSPropertyBackgroundPositionY:
2614                 case CSSPropertyWebkitMaskPositionY: {
2615                     bool xFound = true, yFound = false;
2616                     currValue = parseFillPositionXY(xFound, yFound);
2617                     if (currValue)
2618                         m_valueList->next();
2619                     break;
2620                 }
2621                 case CSSPropertyWebkitBackgroundComposite:
2622                 case CSSPropertyWebkitMaskComposite:
2623                     if ((val->id >= CSSValueClear && val->id <= CSSValuePlusLighter) || val->id == CSSValueHighlight) {
2624                         currValue = CSSPrimitiveValue::createIdentifier(val->id);
2625                         m_valueList->next();
2626                     }
2627                     break;
2628                 case CSSPropertyBackgroundRepeat:
2629                 case CSSPropertyWebkitMaskRepeat:
2630                     parseFillRepeat(currValue, currValue2);
2631                     // parseFillRepeat advances the m_valueList pointer
2632                     break;
2633                 case CSSPropertyBackgroundSize:
2634                 case CSSPropertyWebkitBackgroundSize:
2635                 case CSSPropertyWebkitMaskSize: {
2636                     currValue = parseFillSize(propId, allowComma);
2637                     if (currValue)
2638                         m_valueList->next();
2639                     break;
2640                 }
2641             }
2642             if (!currValue)
2643                 return false;
2644
2645             if (value && !values) {
2646                 values = CSSValueList::createCommaSeparated();
2647                 values->append(value.release());
2648             }
2649
2650             if (value2 && !values2) {
2651                 values2 = CSSValueList::createCommaSeparated();
2652                 values2->append(value2.release());
2653             }
2654
2655             if (values)
2656                 values->append(currValue.release());
2657             else
2658                 value = currValue.release();
2659             if (currValue2) {
2660                 if (values2)
2661                     values2->append(currValue2.release());
2662                 else
2663                     value2 = currValue2.release();
2664             }
2665         }
2666
2667         // When parsing any fill shorthand property, we let it handle building up the lists for all
2668         // properties.
2669         if (inShorthand())
2670             break;
2671     }
2672
2673     if (values && values->length()) {
2674         retValue1 = values.release();
2675         if (values2 && values2->length())
2676             retValue2 = values2.release();
2677         return true;
2678     }
2679     if (value) {
2680         retValue1 = value.release();
2681         retValue2 = value2.release();
2682         return true;
2683     }
2684     return false;
2685 }
2686
2687 PassRefPtr<CSSValue> CSSParser::parseAnimationDelay()
2688 {
2689     CSSParserValue* value = m_valueList->current();
2690     if (validUnit(value, FTime, m_strict))
2691         return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2692     return 0;
2693 }
2694
2695 PassRefPtr<CSSValue> CSSParser::parseAnimationDirection()
2696 {
2697     CSSParserValue* value = m_valueList->current();
2698     if (value->id == CSSValueNormal || value->id == CSSValueAlternate)
2699         return CSSPrimitiveValue::createIdentifier(value->id);
2700     return 0;
2701 }
2702
2703 PassRefPtr<CSSValue> CSSParser::parseAnimationDuration()
2704 {
2705     CSSParserValue* value = m_valueList->current();
2706     if (validUnit(value, FTime | FNonNeg, m_strict))
2707         return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2708     return 0;
2709 }
2710
2711 PassRefPtr<CSSValue> CSSParser::parseAnimationFillMode()
2712 {
2713     CSSParserValue* value = m_valueList->current();
2714     if (value->id == CSSValueNone || value->id == CSSValueForwards || value->id == CSSValueBackwards || value->id == CSSValueBoth)
2715         return CSSPrimitiveValue::createIdentifier(value->id);
2716     return 0;
2717 }
2718
2719 PassRefPtr<CSSValue> CSSParser::parseAnimationIterationCount()
2720 {
2721     CSSParserValue* value = m_valueList->current();
2722     if (value->id == CSSValueInfinite)
2723         return CSSPrimitiveValue::createIdentifier(value->id);
2724     if (validUnit(value, FInteger | FNonNeg, m_strict))
2725         return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2726     return 0;
2727 }
2728
2729 PassRefPtr<CSSValue> CSSParser::parseAnimationName()
2730 {
2731     CSSParserValue* value = m_valueList->current();
2732     if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT) {
2733         if (value->id == CSSValueNone || (value->unit == CSSPrimitiveValue::CSS_STRING && equalIgnoringCase(value->string, "none"))) {
2734             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
2735         } else {
2736             return CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_STRING);
2737         }
2738     }
2739     return 0;
2740 }
2741
2742 PassRefPtr<CSSValue> CSSParser::parseAnimationPlayState()
2743 {
2744     CSSParserValue* value = m_valueList->current();
2745     if (value->id == CSSValueRunning || value->id == CSSValuePaused)
2746         return CSSPrimitiveValue::createIdentifier(value->id);
2747     return 0;
2748 }
2749
2750 PassRefPtr<CSSValue> CSSParser::parseAnimationProperty()
2751 {
2752     CSSParserValue* value = m_valueList->current();
2753     if (value->unit != CSSPrimitiveValue::CSS_IDENT)
2754         return 0;
2755     int result = cssPropertyID(value->string);
2756     if (result)
2757         return CSSPrimitiveValue::createIdentifier(result);
2758     if (equalIgnoringCase(value->string, "all"))
2759         return CSSPrimitiveValue::createIdentifier(CSSValueAll);
2760     if (equalIgnoringCase(value->string, "none"))
2761         return CSSPrimitiveValue::createIdentifier(CSSValueNone);
2762     return 0;
2763 }
2764
2765 void CSSParser::parseTransformOriginShorthand(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3)
2766 {
2767     parseFillPosition(value1, value2);
2768
2769     // now get z
2770     if (m_valueList->current() && validUnit(m_valueList->current(), FLength, m_strict))
2771         value3 = CSSPrimitiveValue::create(m_valueList->current()->fValue,
2772                                          (CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit);
2773     if (value3)
2774         m_valueList->next();
2775 }
2776
2777 bool CSSParser::parseTimingFunctionValue(CSSParserValueList*& args, double& result)
2778 {
2779     CSSParserValue* v = args->current();
2780     if (!validUnit(v, FNumber, m_strict))
2781         return false;
2782     result = v->fValue;
2783     if (result < 0 || result > 1.0)
2784         return false;
2785     v = args->next();
2786     if (!v)
2787         // The last number in the function has no comma after it, so we're done.
2788         return true;
2789     if (v->unit != CSSParserValue::Operator && v->iValue != ',')
2790         return false;
2791     v = args->next();
2792     return true;
2793 }
2794
2795 PassRefPtr<CSSValue> CSSParser::parseAnimationTimingFunction()
2796 {
2797     CSSParserValue* value = m_valueList->current();
2798     if (value->id == CSSValueEase || value->id == CSSValueLinear || value->id == CSSValueEaseIn || value->id == CSSValueEaseOut || value->id == CSSValueEaseInOut)
2799         return CSSPrimitiveValue::createIdentifier(value->id);
2800
2801     // We must be a function.
2802     if (value->unit != CSSParserValue::Function)
2803         return 0;
2804
2805     // The only timing function we accept for now is a cubic bezier function.  4 points must be specified.
2806     CSSParserValueList* args = value->function->args;
2807     if (!equalIgnoringCase(value->function->name, "cubic-bezier(") || !args || args->size() != 7)
2808         return 0;
2809
2810     // There are two points specified.  The values must be between 0 and 1.
2811     double x1, y1, x2, y2;
2812
2813     if (!parseTimingFunctionValue(args, x1))
2814         return 0;
2815     if (!parseTimingFunctionValue(args, y1))
2816         return 0;
2817     if (!parseTimingFunctionValue(args, x2))
2818         return 0;
2819     if (!parseTimingFunctionValue(args, y2))
2820         return 0;
2821
2822     return CSSTimingFunctionValue::create(x1, y1, x2, y2);
2823 }
2824
2825 bool CSSParser::parseAnimationProperty(int propId, RefPtr<CSSValue>& result)
2826 {
2827     RefPtr<CSSValueList> values;
2828     CSSParserValue* val;
2829     RefPtr<CSSValue> value;
2830     bool allowComma = false;
2831
2832     result = 0;
2833
2834     while ((val = m_valueList->current())) {
2835         RefPtr<CSSValue> currValue;
2836         if (allowComma) {
2837             if (val->unit != CSSParserValue::Operator || val->iValue != ',')
2838                 return false;
2839             m_valueList->next();
2840             allowComma = false;
2841         }
2842         else {
2843             switch (propId) {
2844                 case CSSPropertyWebkitAnimationDelay:
2845                 case CSSPropertyWebkitTransitionDelay:
2846                     currValue = parseAnimationDelay();
2847                     if (currValue)
2848                         m_valueList->next();
2849                     break;
2850                 case CSSPropertyWebkitAnimationDirection:
2851                     currValue = parseAnimationDirection();
2852                     if (currValue)
2853                         m_valueList->next();
2854                     break;
2855                 case CSSPropertyWebkitAnimationDuration:
2856                 case CSSPropertyWebkitTransitionDuration:
2857                     currValue = parseAnimationDuration();
2858                     if (currValue)
2859                         m_valueList->next();
2860                     break;
2861                 case CSSPropertyWebkitAnimationFillMode:
2862                     currValue = parseAnimationFillMode();
2863                     if (currValue)
2864                         m_valueList->next();
2865                     break;
2866                 case CSSPropertyWebkitAnimationIterationCount:
2867                     currValue = parseAnimationIterationCount();
2868                     if (currValue)
2869                         m_valueList->next();
2870                     break;
2871                 case CSSPropertyWebkitAnimationName:
2872                     currValue = parseAnimationName();
2873                     if (currValue)
2874                         m_valueList->next();
2875                     break;
2876                 case CSSPropertyWebkitAnimationPlayState:
2877                     currValue = parseAnimationPlayState();
2878                     if (currValue)
2879                         m_valueList->next();
2880                     break;
2881                 case CSSPropertyWebkitTransitionProperty:
2882                     currValue = parseAnimationProperty();
2883                     if (currValue)
2884                         m_valueList->next();
2885                     break;
2886                 case CSSPropertyWebkitAnimationTimingFunction:
2887                 case CSSPropertyWebkitTransitionTimingFunction:
2888                     currValue = parseAnimationTimingFunction();
2889                     if (currValue)
2890                         m_valueList->next();
2891                     break;
2892             }
2893
2894             if (!currValue)
2895                 return false;
2896
2897             if (value && !values) {
2898                 values = CSSValueList::createCommaSeparated();
2899                 values->append(value.release());
2900             }
2901
2902             if (values)
2903                 values->append(currValue.release());
2904             else
2905                 value = currValue.release();
2906
2907             allowComma = true;
2908         }
2909
2910         // When parsing the 'transition' shorthand property, we let it handle building up the lists for all
2911         // properties.
2912         if (inShorthand())
2913             break;
2914     }
2915
2916     if (values && values->length()) {
2917         result = values.release();
2918         return true;
2919     }
2920     if (value) {
2921         result = value.release();
2922         return true;
2923     }
2924     return false;
2925 }
2926
2927
2928
2929 #if ENABLE(DASHBOARD_SUPPORT)
2930
2931 #define DASHBOARD_REGION_NUM_PARAMETERS  6
2932 #define DASHBOARD_REGION_SHORT_NUM_PARAMETERS  2
2933
2934 static CSSParserValue* skipCommaInDashboardRegion(CSSParserValueList *args)
2935 {
2936     if (args->size() == (DASHBOARD_REGION_NUM_PARAMETERS*2-1) ||
2937          args->size() == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
2938         CSSParserValue* current = args->current();
2939         if (current->unit == CSSParserValue::Operator && current->iValue == ',')
2940             return args->next();
2941     }
2942     return args->current();
2943 }
2944
2945 bool CSSParser::parseDashboardRegions(int propId, bool important)
2946 {
2947     bool valid = true;
2948
2949     CSSParserValue* value = m_valueList->current();
2950
2951     if (value->id == CSSValueNone) {
2952         if (m_valueList->next())
2953             return false;
2954         addProperty(propId, CSSPrimitiveValue::createIdentifier(value->id), important);
2955         return valid;
2956     }
2957
2958     RefPtr<DashboardRegion> firstRegion = DashboardRegion::create();
2959     DashboardRegion* region = 0;
2960
2961     while (value) {
2962         if (region == 0) {
2963             region = firstRegion.get();
2964         } else {
2965             RefPtr<DashboardRegion> nextRegion = DashboardRegion::create();
2966             region->m_next = nextRegion;
2967             region = nextRegion.get();
2968         }
2969
2970         if (value->unit != CSSParserValue::Function) {
2971             valid = false;
2972             break;
2973         }
2974
2975         // Commas count as values, so allow:
2976         // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
2977         // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
2978         // also allow
2979         // dashboard-region(label, type) or dashboard-region(label type)
2980         // dashboard-region(label, type) or dashboard-region(label type)
2981         CSSParserValueList* args = value->function->args;
2982         if (!equalIgnoringCase(value->function->name, "dashboard-region(") || !args) {
2983             valid = false;
2984             break;
2985         }
2986
2987         int numArgs = args->size();
2988         if ((numArgs != DASHBOARD_REGION_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_NUM_PARAMETERS*2-1)) &&
2989             (numArgs != DASHBOARD_REGION_SHORT_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1))) {
2990             valid = false;
2991             break;
2992         }
2993
2994         // First arg is a label.
2995         CSSParserValue* arg = args->current();
2996         if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
2997             valid = false;
2998             break;
2999         }
3000
3001         region->m_label = arg->string;
3002
3003         // Second arg is a type.
3004         arg = args->next();
3005         arg = skipCommaInDashboardRegion(args);
3006         if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
3007             valid = false;
3008             break;
3009         }
3010
3011         if (equalIgnoringCase(arg->string, "circle"))
3012             region->m_isCircle = true;
3013         else if (equalIgnoringCase(arg->string, "rectangle"))
3014             region->m_isRectangle = true;
3015         else {
3016             valid = false;
3017             break;
3018         }
3019
3020         region->m_geometryType = arg->string;
3021
3022         if (numArgs == DASHBOARD_REGION_SHORT_NUM_PARAMETERS || numArgs == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
3023             // This originally used CSSValueInvalid by accident. It might be more logical to use something else.
3024             RefPtr<CSSPrimitiveValue> amount = CSSPrimitiveValue::createIdentifier(CSSValueInvalid);
3025
3026             region->setTop(amount);
3027             region->setRight(amount);
3028             region->setBottom(amount);
3029             region->setLeft(amount);
3030         } else {
3031             // Next four arguments must be offset numbers
3032             int i;
3033             for (i = 0; i < 4; i++) {
3034                 arg = args->next();
3035                 arg = skipCommaInDashboardRegion(args);
3036
3037                 valid = arg->id == CSSValueAuto || validUnit(arg, FLength, m_strict);
3038                 if (!valid)
3039                     break;
3040
3041                 RefPtr<CSSPrimitiveValue> amount = arg->id == CSSValueAuto ?
3042                     CSSPrimitiveValue::createIdentifier(CSSValueAuto) :
3043                     CSSPrimitiveValue::create(arg->fValue, (CSSPrimitiveValue::UnitTypes) arg->unit);
3044
3045                 if (i == 0)
3046                     region->setTop(amount);
3047                 else if (i == 1)
3048                     region->setRight(amount);
3049                 else if (i == 2)
3050                     region->setBottom(amount);
3051                 else
3052                     region->setLeft(amount);
3053             }
3054         }
3055
3056         if (args->next())
3057             return false;
3058
3059         value = m_valueList->next();
3060     }
3061
3062     if (valid)
3063         addProperty(propId, CSSPrimitiveValue::create(firstRegion.release()), important);
3064
3065     return valid;
3066 }
3067
3068 #endif /* ENABLE(DASHBOARD_SUPPORT) */
3069
3070 PassRefPtr<CSSValue> CSSParser::parseCounterContent(CSSParserValueList* args, bool counters)
3071 {
3072     unsigned numArgs = args->size();
3073     if (counters && numArgs != 3 && numArgs != 5)
3074         return 0;
3075     if (!counters && numArgs != 1 && numArgs != 3)
3076         return 0;
3077
3078     CSSParserValue* i = args->current();
3079     if (i->unit != CSSPrimitiveValue::CSS_IDENT)
3080         return 0;
3081     RefPtr<CSSPrimitiveValue> identifier = CSSPrimitiveValue::create(i->string, CSSPrimitiveValue::CSS_STRING);
3082
3083     RefPtr<CSSPrimitiveValue> separator;
3084     if (!counters)
3085         separator = CSSPrimitiveValue::create(String(), CSSPrimitiveValue::CSS_STRING);
3086     else {
3087         i = args->next();
3088         if (i->unit != CSSParserValue::Operator || i->iValue != ',')
3089             return 0;
3090
3091         i = args->next();
3092         if (i->unit != CSSPrimitiveValue::CSS_STRING)
3093             return 0;
3094
3095         separator = CSSPrimitiveValue::create(i->string, (CSSPrimitiveValue::UnitTypes) i->unit);
3096     }
3097
3098     RefPtr<CSSPrimitiveValue> listStyle;
3099     i = args->next();
3100     if (!i) // Make the list style default decimal
3101         listStyle = CSSPrimitiveValue::create(CSSValueDecimal - CSSValueDisc, CSSPrimitiveValue::CSS_NUMBER);
3102     else {
3103         if (i->unit != CSSParserValue::Operator || i->iValue != ',')
3104             return 0;
3105
3106         i = args->next();
3107         if (i->unit != CSSPrimitiveValue::CSS_IDENT)
3108             return 0;
3109
3110         short ls = 0;
3111         if (i->id == CSSValueNone)
3112             ls = CSSValueKatakanaIroha - CSSValueDisc + 1;
3113         else if (i->id >= CSSValueDisc && i->id <= CSSValueKatakanaIroha)
3114             ls = i->id - CSSValueDisc;
3115         else
3116             return 0;
3117
3118         listStyle = CSSPrimitiveValue::create(ls, (CSSPrimitiveValue::UnitTypes) i->unit);
3119     }
3120
3121     return CSSPrimitiveValue::create(Counter::create(identifier.release(), listStyle.release(), separator.release()));
3122 }
3123
3124 bool CSSParser::parseShape(int propId, bool important)
3125 {
3126     CSSParserValue* value = m_valueList->current();
3127     CSSParserValueList* args = value->function->args;
3128
3129     if (!equalIgnoringCase(value->function->name, "rect(") || !args)
3130         return false;
3131
3132     // rect(t, r, b, l) || rect(t r b l)
3133     if (args->size() != 4 && args->size() != 7)
3134         return false;
3135     RefPtr<Rect> rect = Rect::create();
3136     bool valid = true;
3137     int i = 0;
3138     CSSParserValue* a = args->current();
3139     while (a) {
3140         valid = a->id == CSSValueAuto || validUnit(a, FLength, m_strict);
3141         if (!valid)
3142             break;
3143         RefPtr<CSSPrimitiveValue> length = a->id == CSSValueAuto ?
3144             CSSPrimitiveValue::createIdentifier(CSSValueAuto) :
3145             CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit);
3146         if (i == 0)
3147             rect->setTop(length);
3148         else if (i == 1)
3149             rect->setRight(length);
3150         else if (i == 2)
3151             rect->setBottom(length);
3152         else
3153             rect->setLeft(length);
3154         a = args->next();
3155         if (a && args->size() == 7) {
3156             if (a->unit == CSSParserValue::Operator && a->iValue == ',') {
3157                 a = args->next();
3158             } else {
3159                 valid = false;
3160                 break;
3161             }
3162         }
3163         i++;
3164     }
3165     if (valid) {
3166         addProperty(propId, CSSPrimitiveValue::create(rect.release()), important);
3167         m_valueList->next();
3168         return true;
3169     }
3170     return false;
3171 }
3172
3173 // [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family'
3174 bool CSSParser::parseFont(bool important)
3175 {
3176     bool valid = true;
3177     CSSParserValue *value = m_valueList->current();
3178     RefPtr<FontValue> font = FontValue::create();
3179     // optional font-style, font-variant and font-weight
3180     while (value) {
3181         int id = value->id;
3182         if (id) {
3183             if (id == CSSValueNormal) {
3184                 // do nothing, it's the inital value for all three
3185             } else if (id == CSSValueItalic || id == CSSValueOblique) {
3186                 if (font->style)
3187                     return false;
3188                 font->style = CSSPrimitiveValue::createIdentifier(id);
3189             } else if (id == CSSValueSmallCaps) {
3190                 if (font->variant)
3191                     return false;
3192                 font->variant = CSSPrimitiveValue::createIdentifier(id);
3193             } else if (id >= CSSValueBold && id <= CSSValueLighter) {
3194                 if (font->weight)
3195                     return false;
3196                 font->weight = CSSPrimitiveValue::createIdentifier(id);
3197             } else {
3198                 valid = false;
3199             }
3200         } else if (!font->weight && validUnit(value, FInteger | FNonNeg, true)) {
3201             int weight = (int)value->fValue;
3202             int val = 0;
3203             if (weight == 100)
3204                 val = CSSValue100;
3205             else if (weight == 200)
3206                 val = CSSValue200;
3207             else if (weight == 300)
3208                 val = CSSValue300;
3209             else if (weight == 400)
3210                 val = CSSValue400;
3211             else if (weight == 500)
3212                 val = CSSValue500;
3213             else if (weight == 600)
3214                 val = CSSValue600;
3215             else if (weight == 700)
3216                 val = CSSValue700;
3217             else if (weight == 800)
3218                 val = CSSValue800;
3219             else if (weight == 900)
3220                 val = CSSValue900;
3221
3222             if (val)
3223                 font->weight = CSSPrimitiveValue::createIdentifier(val);
3224             else
3225                 valid = false;
3226         } else {
3227             valid = false;
3228         }
3229         if (!valid)
3230             break;
3231         value = m_valueList->next();
3232     }
3233     if (!value)
3234         return false;
3235
3236     // set undefined values to default
3237     if (!font->style)
3238         font->style = CSSPrimitiveValue::createIdentifier(CSSValueNormal);
3239     if (!font->variant)
3240         font->variant = CSSPrimitiveValue::createIdentifier(CSSValueNormal);
3241     if (!font->weight)
3242         font->weight = CSSPrimitiveValue::createIdentifier(CSSValueNormal);
3243
3244     // now a font size _must_ come
3245     // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
3246     if (value->id >= CSSValueXxSmall && value->id <= CSSValueLarger)
3247         font->size = CSSPrimitiveValue::createIdentifier(value->id);
3248     else if (validUnit(value, FLength | FPercent | FNonNeg, m_strict))
3249         font->size = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
3250     value = m_valueList->next();
3251     if (!font->size || !value)
3252         return false;
3253
3254     if (value->unit == CSSParserValue::Operator && value->iValue == '/') {
3255         // line-height
3256         value = m_valueList->next();
3257         if (!value)
3258             return false;
3259         if (value->id == CSSValueNormal) {
3260             // default value, nothing to do
3261         } else if (validUnit(value, FNumber | FLength | FPercent | FNonNeg, m_strict))
3262             font->lineHeight = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
3263         else
3264             return false;
3265         value = m_valueList->next();
3266         if (!value)
3267             return false;
3268     }
3269
3270     if (!font->lineHeight)
3271         font->lineHeight = CSSPrimitiveValue::createIdentifier(CSSValueNormal);
3272
3273     // font family must come now
3274     font->family = parseFontFamily();
3275
3276     if (m_valueList->current() || !font->family)
3277         return false;
3278
3279     addProperty(CSSPropertyFont, font.release(), important);
3280     return true;
3281 }
3282
3283 PassRefPtr<CSSValueList> CSSParser::parseFontFamily()
3284 {
3285     RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
3286     CSSParserValue* value = m_valueList->current();
3287
3288     FontFamilyValue* currFamily = 0;
3289     while (value) {
3290         CSSParserValue* nextValue = m_valueList->next();
3291         bool nextValBreaksFont = !nextValue ||
3292                                  (nextValue->unit == CSSParserValue::Operator && nextValue->iValue == ',');
3293         bool nextValIsFontName = nextValue &&
3294             ((nextValue->id >= CSSValueSerif && nextValue->id <= CSSValueWebkitBody) ||
3295             (nextValue->unit == CSSPrimitiveValue::CSS_STRING || nextValue->unit == CSSPrimitiveValue::CSS_IDENT));
3296
3297         if (value->id >= CSSValueSerif && value->id <= CSSValueWebkitBody) {
3298             if (currFamily)
3299                 currFamily->appendSpaceSeparated(value->string.characters, value->string.length);
3300             else if (nextValBreaksFont || !nextValIsFontName)
3301                 list->append(CSSPrimitiveValue::createIdentifier(value->id));
3302             else {
3303                 RefPtr<FontFamilyValue> newFamily = FontFamilyValue::create(value->string);
3304                 currFamily = newFamily.get();
3305                 list->append(newFamily.release());
3306             }
3307         } else if (value->unit == CSSPrimitiveValue::CSS_STRING) {
3308             // Strings never share in a family name.
3309             currFamily = 0;
3310             list->append(FontFamilyValue::create(value->string));
3311         } else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
3312             if (currFamily)
3313                 currFamily->appendSpaceSeparated(value->string.characters, value->string.length);
3314             else if (nextValBreaksFont || !nextValIsFontName)
3315                 list->append(FontFamilyValue::create(value->string));
3316             else {
3317                 RefPtr<FontFamilyValue> newFamily = FontFamilyValue::create(value->string);
3318                 currFamily = newFamily.get();
3319                 list->append(newFamily.release());
3320             }
3321         } else {
3322             break;
3323         }
3324
3325         if (!nextValue)
3326             break;
3327
3328         if (nextValBreaksFont) {
3329             value = m_valueList->next();
3330             currFamily = 0;
3331         }
3332         else if (nextValIsFontName)
3333             value = nextValue;
3334         else
3335             break;
3336     }
3337     if (!list->length())
3338         list = 0;
3339     return list.release();
3340 }
3341
3342 bool CSSParser::parseFontStyle(bool important)
3343 {
3344     RefPtr<CSSValueList> values;
3345     if (m_valueList->size() > 1)
3346         values = CSSValueList::createCommaSeparated();
3347     CSSParserValue* val;
3348     bool expectComma = false;
3349     while ((val = m_valueList->current())) {
3350         RefPtr<CSSPrimitiveValue> parsedValue;
3351         if (!expectComma) {
3352             expectComma = true;
3353             if (val->id == CSSValueNormal || val->id == CSSValueItalic || val->id == CSSValueOblique)
3354                 parsedValue = CSSPrimitiveValue::createIdentifier(val->id);
3355             else if (val->id == CSSValueAll && !values) {
3356                 // 'all' is only allowed in @font-face and with no other values. Make a value list to
3357                 // indicate that we are in the @font-face case.
3358                 values = CSSValueList::createCommaSeparated();
3359                 parsedValue = CSSPrimitiveValue::createIdentifier(val->id);
3360             }
3361         } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3362             expectComma = false;
3363             m_valueList->next();
3364             continue;
3365         }
3366
3367         if (!parsedValue)
3368             return false;
3369
3370         m_valueList->next();
3371
3372         if (values)
3373             values->append(parsedValue.release());
3374         else {
3375             addProperty(CSSPropertyFontStyle, parsedValue.release(), important);
3376             return true;
3377         }
3378     }
3379
3380     if (values && values->length()) {
3381         m_hasFontFaceOnlyValues = true;
3382         addProperty(CSSPropertyFontStyle, values.release(), important);
3383         return true;
3384     }
3385
3386     return false;
3387 }
3388
3389 bool CSSParser::parseFontVariant(bool important)
3390 {
3391     RefPtr<CSSValueList> values;
3392     if (m_valueList->size() > 1)
3393         values = CSSValueList::createCommaSeparated();
3394     CSSParserValue* val;
3395     bool expectComma = false;
3396     while ((val = m_valueList->current())) {
3397         RefPtr<CSSPrimitiveValue> parsedValue;
3398         if (!expectComma) {
3399             expectComma = true;
3400             if (val->id == CSSValueNormal || val->id == CSSValueSmallCaps)
3401                 parsedValue = CSSPrimitiveValue::createIdentifier(val->id);
3402             else if (val->id == CSSValueAll && !values) {
3403                 // 'all' is only allowed in @font-face and with no other values. Make a value list to
3404                 // indicate that we are in the @font-face case.
3405                 values = CSSValueList::createCommaSeparated();
3406                 parsedValue = CSSPrimitiveValue::createIdentifier(val->id);
3407             }
3408         } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3409             expectComma = false;
3410             m_valueList->next();
3411             continue;
3412         }
3413
3414         if (!parsedValue)
3415             return false;
3416
3417         m_valueList->next();
3418
3419         if (values)
3420             values->append(parsedValue.release());
3421         else {
3422             addProperty(CSSPropertyFontVariant, parsedValue.release(), important);
3423             return true;
3424         }
3425     }
3426
3427     if (values && values->length()) {
3428         m_hasFontFaceOnlyValues = true;
3429         addProperty(CSSPropertyFontVariant, values.release(), important);
3430         return true;
3431     }
3432
3433     return false;
3434 }
3435
3436 bool CSSParser::parseFontWeight(bool important)
3437 {
3438     RefPtr<CSSValueList> values;
3439     if (m_valueList->size() > 1)
3440         values = CSSValueList::createCommaSeparated();
3441     CSSParserValue* val;
3442     bool expectComma = false;
3443     while ((val = m_valueList->current())) {
3444         RefPtr<CSSPrimitiveValue> parsedValue;
3445         if (!expectComma) {
3446             expectComma = true;
3447             if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
3448                 if (val->id >= CSSValueNormal && val->id <= CSSValue900)
3449                     parsedValue = CSSPrimitiveValue::createIdentifier(val->id);
3450                 else if (val->id == CSSValueAll && !values) {
3451                     // 'all' is only allowed in @font-face and with no other values. Make a value list to
3452                     // indicate that we are in the @font-face case.
3453                     values = CSSValueList::createCommaSeparated();
3454                     parsedValue = CSSPrimitiveValue::createIdentifier(val->id);
3455                 }
3456             } else if (validUnit(val, FInteger | FNonNeg, false)) {
3457                 int weight = static_cast<int>(val->fValue);
3458                 if (!(weight % 100) && weight >= 100 && weight <= 900)
3459                     parsedValue = CSSPrimitiveValue::createIdentifier(CSSValue100 + weight / 100 - 1);
3460             }
3461         } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3462             expectComma = false;
3463             m_valueList->next();
3464             continue;
3465         }
3466
3467         if (!parsedValue)
3468             return false;
3469
3470         m_valueList->next();
3471
3472         if (values)
3473             values->append(parsedValue.release());
3474         else {
3475             addProperty(CSSPropertyFontWeight, parsedValue.release(), important);
3476             return true;
3477         }
3478     }
3479
3480     if (values && values->length()) {
3481         m_hasFontFaceOnlyValues = true;
3482         addProperty(CSSPropertyFontWeight, values.release(), important);
3483         return true;
3484     }
3485
3486     return false;
3487 }
3488
3489 static bool isValidFormatFunction(CSSParserValue* val)
3490 {
3491     CSSParserValueList* args = val->function->args;
3492     return equalIgnoringCase(val->function->name, "format(") && (args->current()->unit == CSSPrimitiveValue::CSS_STRING || args->current()->unit == CSSPrimitiveValue::CSS_IDENT);
3493 }
3494
3495 bool CSSParser::parseFontFaceSrc()
3496 {
3497     RefPtr<CSSValueList> values(CSSValueList::createCommaSeparated());
3498     CSSParserValue* val;
3499     bool expectComma = false;
3500     bool allowFormat = false;
3501     bool failed = false;
3502     RefPtr<CSSFontFaceSrcValue> uriValue;
3503     while ((val = m_valueList->current())) {
3504         RefPtr<CSSFontFaceSrcValue> parsedValue;
3505         if (val->unit == CSSPrimitiveValue::CSS_URI && !expectComma && m_styleSheet) {
3506             // FIXME: The completeURL call should be done when using the CSSFontFaceSrcValue,
3507             // not when creating it.
3508             parsedValue = CSSFontFaceSrcValue::create(m_styleSheet->completeURL(val->string));
3509             uriValue = parsedValue;
3510             allowFormat = true;
3511             expectComma = true;
3512         } else if (val->unit == CSSParserValue::Function) {
3513             // There are two allowed functions: local() and format().
3514             CSSParserValueList* args = val->function->args;
3515             if (args && args->size() == 1) {
3516                 if (equalIgnoringCase(val->function->name, "local(") && !expectComma) {
3517                     expectComma = true;
3518                     allowFormat = false;
3519                     CSSParserValue* a = args->current();
3520                     uriValue.clear();
3521                     parsedValue = CSSFontFaceSrcValue::createLocal(a->string);
3522                 } else if (allowFormat && uriValue && isValidFormatFunction(val)) {
3523                     expectComma = true;
3524                     allowFormat = false;
3525                     uriValue->setFormat(args->current()->string);
3526                     uriValue.clear();
3527                     m_valueList->next();
3528                     continue;
3529                 }
3530             }
3531         } else if (val->unit == CSSParserValue::Operator && val->iValue == ',' && expectComma) {
3532             expectComma = false;
3533             allowFormat = false;
3534             uriValue.clear();
3535             m_valueList->next();
3536             continue;
3537         }
3538
3539         if (parsedValue)
3540             values->append(parsedValue.release());
3541         else {
3542             failed = true;
3543             break;
3544         }
3545         m_valueList->next();
3546     }
3547
3548     if (values->length() && !failed) {
3549         addProperty(CSSPropertySrc, values.release(), m_important);
3550         m_valueList->next();
3551         return true;
3552     }
3553
3554     return false;
3555 }
3556
3557 bool CSSParser::parseFontFaceUnicodeRange()
3558 {
3559     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3560     CSSParserValue* currentValue;
3561     bool failed = false;
3562     while ((currentValue = m_valueList->current())) {
3563         if (m_valueList->current()->unit != CSSPrimitiveValue::CSS_UNICODE_RANGE) {
3564             failed = true;
3565             break;
3566         }
3567
3568         String rangeString = m_valueList->current()->string;
3569         UChar32 from = 0;
3570         UChar32 to = 0;
3571         unsigned length = rangeString.length();
3572
3573         if (length < 3) {
3574             failed = true;
3575             break;
3576         }
3577
3578         unsigned i = 2;
3579         while (i < length) {
3580             UChar c = rangeString[i];
3581             if (c == '-' || c == '?')
3582                 break;
3583             from *= 16;
3584             if (c >= '0' && c <= '9')
3585                 from += c - '0';
3586             else if (c >= 'A' && c <= 'F')
3587                 from += 10 + c - 'A';
3588             else if (c >= 'a' && c <= 'f')
3589                 from += 10 + c - 'a';
3590             else {
3591                 failed = true;
3592                 break;
3593             }
3594             i++;
3595         }
3596         if (failed)
3597             break;
3598
3599         if (i == length)
3600             to = from;
3601         else if (rangeString[i] == '?') {
3602             unsigned span = 1;
3603             while (i < length && rangeString[i] == '?') {
3604                 span *= 16;
3605                 from *= 16;
3606                 i++;
3607             }
3608             if (i < length)
3609                 failed = true;
3610             to = from + span - 1;
3611         } else {
3612             if (length < i + 2) {
3613                 failed = true;
3614                 break;
3615             }
3616             i++;
3617             while (i < length) {
3618                 UChar c = rangeString[i];
3619                 to *= 16;
3620                 if (c >= '0' && c <= '9')
3621                     to += c - '0';
3622                 else if (c >= 'A' && c <= 'F')
3623                     to += 10 + c - 'A';
3624                 else if (c >= 'a' && c <= 'f')
3625                     to += 10 + c - 'a';
3626                 else {
3627                     failed = true;
3628                     break;
3629                 }
3630                 i++;
3631             }
3632             if (failed)
3633                 break;
3634         }
3635         values->append(CSSUnicodeRangeValue::create(from, to));
3636         m_valueList->next();
3637     }
3638     if (failed || !values->length())
3639         return false;
3640     addProperty(CSSPropertyUnicodeRange, values.release(), m_important);
3641     return true;
3642 }
3643
3644 static inline bool isCSSWhitespace(UChar c)
3645 {
3646     return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f';
3647 }
3648
3649 static inline bool parseInt(const UChar*& string, const UChar* end, UChar terminator, int& value)
3650 {
3651     const UChar* current = string;
3652     int localValue = 0;
3653     bool negative = false;
3654     while (current != end && isCSSWhitespace(*current))
3655         current++;
3656     if (current != end && *current == '-') {
3657         negative = true;
3658         current++;
3659     }
3660     if (current == end || !isASCIIDigit(*current))
3661         return false;
3662     while (current != end && isASCIIDigit(*current))
3663         localValue = localValue * 10 + *current++ - '0';
3664     while (current != end && isCSSWhitespace(*current))
3665         current++;
3666     if (current == end || *current++ != terminator)
3667         return false;
3668     // Clamp negative values at zero.
3669     value = negative ? 0 : localValue;
3670     string = current;
3671     return true;
3672 }
3673
3674 bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict)
3675 {
3676     if (!strict && Color::parseHexColor(name, rgb))
3677         return true;
3678
3679     // Try rgb() syntax.
3680     if (name.startsWith("rgb(")) {
3681         const UChar* current = name.characters() + 4;
3682         const UChar* end = name.characters() + name.length();
3683         int red;
3684         int green;
3685         int blue;
3686         if (!parseInt(current, end, ',', red))
3687             return false;
3688         if (!parseInt(current, end, ',', green))
3689             return false;
3690         if (!parseInt(current, end, ')', blue))
3691             return false;
3692         if (current != end)
3693             return false;
3694         rgb = makeRGB(red, green, blue);
3695         return true;
3696     }
3697     // Try named colors.
3698     Color tc;
3699     tc.setNamedColor(name);
3700     if (tc.isValid()) {
3701         rgb = tc.rgb();
3702         return true;
3703     }
3704     return false;
3705 }
3706
3707 bool CSSParser::parseColorParameters(CSSParserValue* value, int* colorArray, bool parseAlpha)
3708 {
3709     CSSParserValueList* args = value->function->args;
3710     CSSParserValue* v = args->current();
3711     Units unitType = FUnknown;
3712     // Get the first value and its type
3713     if (validUnit(v, FInteger, true))
3714         unitType = FInteger;
3715     else if (validUnit(v, FPercent, true))
3716         unitType = FPercent;
3717     else
3718         return false;
3719     colorArray[0] = static_cast<int>(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0));
3720     for (int i = 1; i < 3; i++) {
3721         v = args->next();
3722         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
3723             return false;
3724         v = args->next();
3725         if (!validUnit(v, unitType, true))
3726             return false;
3727         colorArray[i] = static_cast<int>(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0));
3728     }
3729     if (parseAlpha) {
3730         v = args->next();
3731         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
3732             return false;
3733         v = args->next();
3734         if (!validUnit(v, FNumber, true))
3735             return false;
3736         // Convert the floating pointer number of alpha to an integer in the range [0, 256),
3737         // with an equal distribution across all 256 values.
3738         colorArray[3] = static_cast<int>(max(0.0, min(1.0, v->fValue)) * nextafter(256.0, 0.0));
3739     }
3740     return true;
3741 }
3742
3743 // The CSS3 specification defines the format of a HSL color as
3744 // hsl(<number>, <percent>, <percent>)
3745 // and with alpha, the format is
3746 // hsla(<number>, <percent>, <percent>, <number>)
3747 // The first value, HUE, is in an angle with a value between 0 and 360
3748 bool CSSParser::parseHSLParameters(CSSParserValue* value, double* colorArray, bool parseAlpha)
3749 {
3750     CSSParserValueList* args = value->function->args;
3751     CSSParserValue* v = args->current();
3752     // Get the first value
3753     if (!validUnit(v, FNumber, true))
3754         return false;
3755     // normalize the Hue value and change it to be between 0 and 1.0
3756     colorArray[0] = (((static_cast<int>(v->fValue) % 360) + 360) % 360) / 360.0;
3757     for (int i = 1; i < 3; i++) {
3758         v = args->next();
3759         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
3760             return false;
3761         v = args->next();
3762         if (!validUnit(v, FPercent, true))
3763             return false;
3764         colorArray[i] = max(0.0, min(100.0, v->fValue)) / 100.0; // needs to be value between 0 and 1.0
3765     }
3766     if (parseAlpha) {
3767         v = args->next();
3768         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
3769             return false;
3770         v = args->next();
3771         if (!validUnit(v, FNumber, true))
3772             return false;
3773         colorArray[3] = max(0.0, min(1.0, v->fValue));
3774     }
3775     return true;
3776 }
3777
3778 PassRefPtr<CSSPrimitiveValue> CSSParser::parseColor(CSSParserValue* value)
3779 {
3780     RGBA32 c = Color::transparent;
3781     if (!parseColorFromValue(value ? value : m_valueList->current(), c))
3782         return 0;
3783     return CSSPrimitiveValue::createColor(c);
3784 }
3785
3786 bool CSSParser::parseColorFromValue(CSSParserValue* value, RGBA32& c, bool svg)
3787 {
3788     if (!m_strict && value->unit == CSSPrimitiveValue::CSS_NUMBER &&
3789         value->fValue >= 0. && value->fValue < 1000000.) {
3790         String str = String::format("%06d", (int)(value->fValue+.5));
3791         if (!CSSParser::parseColor(str, c, m_strict))
3792             return false;
3793     } else if (value->unit == CSSPrimitiveValue::CSS_PARSER_HEXCOLOR ||
3794                 value->unit == CSSPrimitiveValue::CSS_IDENT ||
3795                 (!m_strict && value->unit == CSSPrimitiveValue::CSS_DIMENSION)) {
3796         if (!CSSParser::parseColor(value->string, c, m_strict && value->unit == CSSPrimitiveValue::CSS_IDENT))
3797             return false;
3798     } else if (value->unit == CSSParserValue::Function &&
3799                 value->function->args != 0 &&
3800                 value->function->args->size() == 5 /* rgb + two commas */ &&
3801                 equalIgnoringCase(value->function->name, "rgb(")) {
3802         int colorValues[3];
3803         if (!parseColorParameters(value, colorValues, false))
3804             return false;
3805         c = makeRGB(colorValues[0], colorValues[1], colorValues[2]);
3806     } else if (!svg) {
3807         if (value->unit == CSSParserValue::Function &&
3808                 value->function->args != 0 &&
3809                 value->function->args->size() == 7 /* rgba + three commas */ &&
3810                 equalIgnoringCase(value->function->name, "rgba(")) {
3811             int colorValues[4];
3812             if (!parseColorParameters(value, colorValues, true))
3813                 return false;
3814             c = makeRGBA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
3815         } else if (value->unit == CSSParserValue::Function &&
3816                     value->function->args != 0 &&
3817                     value->function->args->size() == 5 /* hsl + two commas */ &&
3818                     equalIgnoringCase(value->function->name, "hsl(")) {
3819             double colorValues[3];
3820             if (!parseHSLParameters(value, colorValues, false))
3821                 return false;
3822             c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], 1.0);
3823         } else if (value->unit == CSSParserValue::Function &&
3824                     value->function->args != 0 &&
3825                     value->function->args->size() == 7 /* hsla + three commas */ &&
3826                     equalIgnoringCase(value->function->name, "hsla(")) {
3827             double colorValues[4];
3828             if (!parseHSLParameters(value, colorValues, true))
3829                 return false;
3830             c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
3831         } else
3832             return false;
3833     } else
3834         return false;
3835
3836     return true;
3837 }
3838
3839 // This class tracks parsing state for shadow values.  If it goes out of scope (e.g., due to an early return)
3840 // without the allowBreak bit being set, then it will clean up all of the objects and destroy them.
3841 struct ShadowParseContext {
3842     ShadowParseContext(CSSPropertyID prop)
3843         : property(prop)
3844         , allowX(true)
3845         , allowY(false)
3846         , allowBlur(false)
3847         , allowSpread(false)
3848         , allowColor(true)
3849         , allowStyle(prop == CSSPropertyWebkitBoxShadow)
3850         , allowBreak(true)
3851     {
3852     }
3853
3854     bool allowLength() { return allowX || allowY || allowBlur || allowSpread; }
3855
3856     void commitValue()
3857     {
3858         // Handle the ,, case gracefully by doing nothing.
3859         if (x || y || blur || spread || color || style) {
3860             if (!values)
3861                 values = CSSValueList::createCommaSeparated();
3862
3863             // Construct the current shadow value and add it to the list.
3864             values->append(ShadowValue::create(x.release(), y.release(), blur.release(), spread.release(), style.release(), color.release()));
3865         }
3866
3867         // Now reset for the next shadow value.
3868         x = 0;
3869         y = 0;
3870         blur = 0;
3871         spread = 0;
3872         style = 0;
3873         color = 0;
3874
3875         allowX = true;
3876         allowColor = true;
3877         allowBreak = true;
3878         allowY = false;
3879         allowBlur = false;
3880         allowSpread = false;
3881         allowStyle = property == CSSPropertyWebkitBoxShadow;
3882     }
3883
3884     void commitLength(CSSParserValue* v)
3885     {
3886         RefPtr<CSSPrimitiveValue> val = CSSPrimitiveValue::create(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit);
3887
3888         if (allowX) {
3889             x = val.release();
3890             allowX = false;
3891             allowY = true;
3892             allowColor = false;
3893             allowStyle = false;
3894             allowBreak = false;
3895         } else if (allowY) {
3896             y = val.release();
3897             allowY = false;
3898             allowBlur = true;
3899             allowColor = true;
3900             allowStyle = property == CSSPropertyWebkitBoxShadow;
3901             allowBreak = true;
3902         } else if (allowBlur) {
3903             blur = val.release();
3904             allowBlur = false;
3905             allowSpread = property == CSSPropertyWebkitBoxShadow;
3906         } else if (allowSpread) {
3907             spread = val.release();
3908             allowSpread = false;
3909         }
3910     }
3911
3912     void commitColor(PassRefPtr<CSSPrimitiveValue> val)
3913     {
3914         color = val;
3915         allowColor = false;
3916         if (allowX) {
3917             allowStyle = false;
3918             allowBreak = false;
3919         } else {
3920             allowBlur = false;
3921             allowSpread = false;
3922             allowStyle = property == CSSPropertyWebkitBoxShadow;
3923         }
3924     }
3925
3926     void commitStyle(CSSParserValue* v)
3927     {
3928         style = CSSPrimitiveValue::createIdentifier(v->id);
3929         allowStyle = false;
3930         if (allowX)
3931             allowBreak = false;
3932         else {
3933             allowBlur = false;
3934             allowSpread = false;
3935             allowColor = false;
3936         }
3937     }
3938
3939     CSSPropertyID property;
3940
3941     RefPtr<CSSValueList> values;
3942     RefPtr<CSSPrimitiveValue> x;
3943     RefPtr<CSSPrimitiveValue> y;
3944     RefPtr<CSSPrimitiveValue> blur;
3945     RefPtr<CSSPrimitiveValue> spread;
3946     RefPtr<CSSPrimitiveValue> style;
3947     RefPtr<CSSPrimitiveValue> color;
3948
3949     bool allowX;
3950     bool allowY;
3951     bool allowBlur;
3952     bool allowSpread;
3953     bool allowColor;
3954     bool allowStyle;
3955     bool allowBreak;
3956 };
3957
3958 bool CSSParser::parseShadow(int propId, bool important)
3959 {
3960     ShadowParseContext context(static_cast<CSSPropertyID>(propId));
3961     CSSParserValue* val;
3962     while ((val = m_valueList->current())) {
3963         // Check for&n