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