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