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