2011-05-19 Mike Lawther <mikelawther@chromium.org>
[WebKit-https.git] / Source / WebCore / css / CSSParser.cpp
1 /*
2  * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
4  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
5  * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
6  * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
7  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #include "config.h"
26 #include "CSSParser.h"
27
28 #include "CSSBorderImageValue.h"
29 #include "CSSCanvasValue.h"
30 #include "CSSCharsetRule.h"
31 #include "CSSCursorImageValue.h"
32 #include "CSSFontFaceRule.h"
33 #include "CSSFontFaceSrcValue.h"
34 #include "CSSGradientValue.h"
35 #include "CSSImageValue.h"
36 #include "CSSImportRule.h"
37 #include "CSSInheritedValue.h"
38 #include "CSSInitialValue.h"
39 #include "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] | 0x20) == 'p' && (characters[length - 1] | 0x20) == '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 | FNonNeg, 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 | FNonNeg, 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     case CSSPropertyImageRendering: // auto | optimizeContrast
1720         if (id == CSSValueAuto || id == CSSValueWebkitOptimizeContrast)
1721             validPrimitive = true;
1722         break;
1723     // End of CSS3 properties
1724
1725     // Apple specific properties.  These will never be standardized and are purely to
1726     // support custom WebKit-based Apple applications.
1727     case CSSPropertyWebkitLineClamp:
1728         // When specifying number of lines, don't allow 0 as a valid value
1729         // When specifying either type of unit, require non-negative integers
1730         validPrimitive = (!id && (value->unit == CSSPrimitiveValue::CSS_PERCENTAGE || value->fValue) && validUnit(value, FInteger | FPercent | FNonNeg, false));
1731         break;
1732     case CSSPropertyWebkitTextSizeAdjust:
1733         if (id == CSSValueAuto || id == CSSValueNone)
1734             validPrimitive = true;
1735         break;
1736     case CSSPropertyWebkitRtlOrdering:
1737         if (id == CSSValueLogical || id == CSSValueVisual)
1738             validPrimitive = true;
1739         break;
1740
1741     case CSSPropertyWebkitFontSizeDelta:           // <length>
1742         validPrimitive = validUnit(value, FLength, m_strict);
1743         break;
1744
1745     case CSSPropertyWebkitNbspMode:     // normal | space
1746         if (id == CSSValueNormal || id == CSSValueSpace)
1747             validPrimitive = true;
1748         break;
1749
1750     case CSSPropertyWebkitLineBreak:   // normal | after-white-space
1751         if (id == CSSValueNormal || id == CSSValueAfterWhiteSpace)
1752             validPrimitive = true;
1753         break;
1754
1755     case CSSPropertyWebkitMatchNearestMailBlockquoteColor:   // normal | match
1756         if (id == CSSValueNormal || id == CSSValueMatch)
1757             validPrimitive = true;
1758         break;
1759
1760     case CSSPropertyWebkitHighlight:
1761         if (id == CSSValueNone || value->unit == CSSPrimitiveValue::CSS_STRING)
1762             validPrimitive = true;
1763         break;
1764
1765     case CSSPropertyWebkitHyphens:
1766         if (id == CSSValueNone || id == CSSValueManual || id == CSSValueAuto)
1767             validPrimitive = true;
1768         break;
1769
1770     case CSSPropertyWebkitHyphenateCharacter:
1771         if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
1772             validPrimitive = true;
1773         break;
1774
1775     case CSSPropertyWebkitHyphenateLimitBefore:
1776     case CSSPropertyWebkitHyphenateLimitAfter:
1777         if (id == CSSValueAuto || validUnit(value, FInteger | FNonNeg, true))
1778             validPrimitive = true;
1779         break;
1780
1781     case CSSPropertyWebkitLocale:
1782         if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
1783             validPrimitive = true;
1784         break;
1785
1786     case CSSPropertyWebkitBorderFit:
1787         if (id == CSSValueBorder || id == CSSValueLines)
1788             validPrimitive = true;
1789         break;
1790
1791     case CSSPropertyWebkitTextSecurity:
1792         // disc | circle | square | none | inherit
1793         if (id == CSSValueDisc || id == CSSValueCircle || id == CSSValueSquare|| id == CSSValueNone)
1794             validPrimitive = true;
1795         break;
1796
1797     case CSSPropertyWebkitFontSmoothing:
1798         if (id == CSSValueAuto || id == CSSValueNone
1799             || id == CSSValueAntialiased || id == CSSValueSubpixelAntialiased)
1800             validPrimitive = true;
1801         break;
1802
1803 #if ENABLE(DASHBOARD_SUPPORT)
1804     case CSSPropertyWebkitDashboardRegion: // <dashboard-region> | <dashboard-region>
1805         if (value->unit == CSSParserValue::Function || id == CSSValueNone)
1806             return parseDashboardRegions(propId, important);
1807         break;
1808 #endif
1809     // End Apple-specific properties
1810
1811         /* shorthand properties */
1812     case CSSPropertyBackground: {
1813         // Position must come before color in this array because a plain old "0" is a legal color
1814         // in quirks mode but it's usually the X coordinate of a position.
1815         // FIXME: Add CSSPropertyBackgroundSize to the shorthand.
1816         const int properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat,
1817                                    CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyBackgroundOrigin,
1818                                    CSSPropertyBackgroundClip, CSSPropertyBackgroundColor };
1819         return parseFillShorthand(propId, properties, 7, important);
1820     }
1821     case CSSPropertyWebkitMask: {
1822         const int properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
1823                                    CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition,
1824                                    CSSPropertyWebkitMaskOrigin, CSSPropertyWebkitMaskClip };
1825         return parseFillShorthand(propId, properties, 6, important);
1826     }
1827     case CSSPropertyBorder:
1828         // [ 'border-width' || 'border-style' || <color> ] | inherit
1829     {
1830         const int properties[3] = { CSSPropertyBorderWidth, CSSPropertyBorderStyle,
1831                                     CSSPropertyBorderColor };
1832         return parseShorthand(propId, properties, 3, important);
1833     }
1834     case CSSPropertyBorderTop:
1835         // [ 'border-top-width' || 'border-style' || <color> ] | inherit
1836     {
1837         const int properties[3] = { CSSPropertyBorderTopWidth, CSSPropertyBorderTopStyle,
1838                                     CSSPropertyBorderTopColor};
1839         return parseShorthand(propId, properties, 3, important);
1840     }
1841     case CSSPropertyBorderRight:
1842         // [ 'border-right-width' || 'border-style' || <color> ] | inherit
1843     {
1844         const int properties[3] = { CSSPropertyBorderRightWidth, CSSPropertyBorderRightStyle,
1845                                     CSSPropertyBorderRightColor };
1846         return parseShorthand(propId, properties, 3, important);
1847     }
1848     case CSSPropertyBorderBottom:
1849         // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
1850     {
1851         const int properties[3] = { CSSPropertyBorderBottomWidth, CSSPropertyBorderBottomStyle,
1852                                     CSSPropertyBorderBottomColor };
1853         return parseShorthand(propId, properties, 3, important);
1854     }
1855     case CSSPropertyBorderLeft:
1856         // [ 'border-left-width' || 'border-style' || <color> ] | inherit
1857     {
1858         const int properties[3] = { CSSPropertyBorderLeftWidth, CSSPropertyBorderLeftStyle,
1859                                     CSSPropertyBorderLeftColor };
1860         return parseShorthand(propId, properties, 3, important);
1861     }
1862     case CSSPropertyWebkitBorderStart:
1863     {
1864         const int properties[3] = { CSSPropertyWebkitBorderStartWidth, CSSPropertyWebkitBorderStartStyle,
1865             CSSPropertyWebkitBorderStartColor };
1866         return parseShorthand(propId, properties, 3, important);
1867     }
1868     case CSSPropertyWebkitBorderEnd:
1869     {
1870         const int properties[3] = { CSSPropertyWebkitBorderEndWidth, CSSPropertyWebkitBorderEndStyle,
1871             CSSPropertyWebkitBorderEndColor };
1872         return parseShorthand(propId, properties, 3, important);
1873     }
1874     case CSSPropertyWebkitBorderBefore:
1875     {
1876         const int properties[3] = { CSSPropertyWebkitBorderBeforeWidth, CSSPropertyWebkitBorderBeforeStyle,
1877             CSSPropertyWebkitBorderBeforeColor };
1878         return parseShorthand(propId, properties, 3, important);
1879     }
1880     case CSSPropertyWebkitBorderAfter:
1881     {
1882         const int properties[3] = { CSSPropertyWebkitBorderAfterWidth, CSSPropertyWebkitBorderAfterStyle,
1883             CSSPropertyWebkitBorderAfterColor };
1884         return parseShorthand(propId, properties, 3, important);
1885     }
1886     case CSSPropertyOutline:
1887         // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
1888     {
1889         const int properties[3] = { CSSPropertyOutlineWidth, CSSPropertyOutlineStyle,
1890                                     CSSPropertyOutlineColor };
1891         return parseShorthand(propId, properties, 3, important);
1892     }
1893     case CSSPropertyBorderColor:
1894         // <color>{1,4} | inherit
1895     {
1896         const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor,
1897                                     CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
1898         return parse4Values(propId, properties, important);
1899     }
1900     case CSSPropertyBorderWidth:
1901         // <border-width>{1,4} | inherit
1902     {
1903         const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth,
1904                                     CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
1905         return parse4Values(propId, properties, important);
1906     }
1907     case CSSPropertyBorderStyle:
1908         // <border-style>{1,4} | inherit
1909     {
1910         const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle,
1911                                     CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
1912         return parse4Values(propId, properties, important);
1913     }
1914     case CSSPropertyMargin:
1915         // <margin-width>{1,4} | inherit
1916     {
1917         const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight,
1918                                     CSSPropertyMarginBottom, CSSPropertyMarginLeft };
1919         return parse4Values(propId, properties, important);
1920     }
1921     case CSSPropertyPadding:
1922         // <padding-width>{1,4} | inherit
1923     {
1924         const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight,
1925                                     CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
1926         return parse4Values(propId, properties, important);
1927     }
1928     case CSSPropertyFont:
1929         // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
1930         // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
1931         if (id >= CSSValueCaption && id <= CSSValueStatusBar)
1932             validPrimitive = true;
1933         else
1934             return parseFont(important);
1935         break;
1936     case CSSPropertyListStyle:
1937     {
1938         const int properties[3] = { CSSPropertyListStyleType, CSSPropertyListStylePosition,
1939                                     CSSPropertyListStyleImage };
1940         return parseShorthand(propId, properties, 3, important);
1941     }
1942     case CSSPropertyWebkitColumns: {
1943         const int properties[2] = { CSSPropertyWebkitColumnWidth, CSSPropertyWebkitColumnCount };
1944         return parseShorthand(propId, properties, 2, important);
1945     }
1946     case CSSPropertyWebkitColumnRule: {
1947         const int properties[3] = { CSSPropertyWebkitColumnRuleWidth, CSSPropertyWebkitColumnRuleStyle,
1948                                     CSSPropertyWebkitColumnRuleColor };
1949         return parseShorthand(propId, properties, 3, important);
1950     }
1951     case CSSPropertyWebkitTextStroke: {
1952         const int properties[2] = { CSSPropertyWebkitTextStrokeWidth, CSSPropertyWebkitTextStrokeColor };
1953         return parseShorthand(propId, properties, 2, important);
1954     }
1955     case CSSPropertyWebkitAnimation:
1956         return parseAnimationShorthand(important);
1957     case CSSPropertyWebkitTransition:
1958         return parseTransitionShorthand(important);
1959     case CSSPropertyInvalid:
1960         return false;
1961     case CSSPropertyPage:
1962         return parsePage(propId, important);
1963     case CSSPropertyFontStretch:
1964     case CSSPropertyTextLineThrough:
1965     case CSSPropertyTextOverline:
1966     case CSSPropertyTextUnderline:
1967         return false;
1968 #if ENABLE(WCSS)
1969     case CSSPropertyWapInputFormat:
1970         validPrimitive = true;
1971         break;
1972     case CSSPropertyWapInputRequired:
1973         parsedValue = parseWCSSInputProperty();
1974         break;
1975 #endif
1976
1977     // CSS Text Layout Module Level 3: Vertical writing support
1978     case CSSPropertyWebkitWritingMode:
1979         if (id >= CSSValueHorizontalTb && id <= CSSValueHorizontalBt)
1980             validPrimitive = true;
1981         break;
1982
1983     case CSSPropertyWebkitTextCombine:
1984         if (id == CSSValueNone || id == CSSValueHorizontal)
1985             validPrimitive = true;
1986         break;
1987
1988     case CSSPropertyWebkitTextEmphasis: {
1989         const int properties[] = { CSSPropertyWebkitTextEmphasisStyle, CSSPropertyWebkitTextEmphasisColor };
1990         return parseShorthand(propId, properties, WTF_ARRAY_LENGTH(properties), important);
1991     }
1992
1993     case CSSPropertyWebkitTextEmphasisPosition:
1994         if (id == CSSValueOver || id == CSSValueUnder)
1995             validPrimitive = true;
1996         break;
1997
1998     case CSSPropertyWebkitTextEmphasisStyle:
1999         return parseTextEmphasisStyle(important);
2000
2001     case CSSPropertyWebkitTextOrientation:
2002         // FIXME: For now just support upright and vertical-right.
2003         if (id == CSSValueVerticalRight || id == CSSValueUpright)
2004             validPrimitive = true;
2005         break;
2006
2007     case CSSPropertyWebkitLineBoxContain:
2008         if (id == CSSValueNone)
2009             validPrimitive = true;
2010         else
2011             return parseLineBoxContain(important);
2012         break;
2013
2014 #if ENABLE(SVG)
2015     default:
2016         return parseSVGValue(propId, important);
2017 #endif
2018     }
2019
2020     if (validPrimitive) {
2021         if (id != 0)
2022             parsedValue = primitiveValueCache()->createIdentifierValue(id);
2023         else if (value->unit == CSSPrimitiveValue::CSS_STRING)
2024             parsedValue = primitiveValueCache()->createValue(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
2025         else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
2026             parsedValue = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
2027         else if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
2028             parsedValue = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
2029         else if (value->unit >= CSSParserValue::Q_EMS)
2030             parsedValue = CSSQuirkPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_EMS);
2031         m_valueList->next();
2032     }
2033     if (parsedValue) {
2034         if (!m_valueList->current() || inShorthand()) {
2035             addProperty(propId, parsedValue.release(), important);
2036             return true;
2037         }
2038     }
2039     return false;
2040 }
2041
2042 #if ENABLE(WCSS)
2043 PassRefPtr<CSSValue> CSSParser::parseWCSSInputProperty()
2044 {
2045     RefPtr<CSSValue> parsedValue = 0;
2046     CSSParserValue* value = m_valueList->current();
2047     String inputProperty;
2048     if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT)
2049         inputProperty = String(value->string);
2050
2051     if (!inputProperty.isEmpty())
2052        parsedValue = primitiveValueCache()->createValue(inputProperty, CSSPrimitiveValue::CSS_STRING);
2053
2054     while (m_valueList->next()) {
2055     // pass all other values, if any. If we don't do this,
2056     // the parser will think that it's not done and won't process this property
2057     }
2058
2059     return parsedValue;
2060 }
2061 #endif
2062
2063 void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
2064 {
2065     if (lval) {
2066         if (lval->isValueList())
2067             static_cast<CSSValueList*>(lval.get())->append(rval);
2068         else {
2069             PassRefPtr<CSSValue> oldlVal(lval.release());
2070             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2071             list->append(oldlVal);
2072             list->append(rval);
2073             lval = list;
2074         }
2075     }
2076     else
2077         lval = rval;
2078 }
2079
2080 static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue, CSSPrimitiveValueCache* primitiveValueCache)
2081 {
2082     if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox
2083         || parserValue->id == CSSValueContentBox || parserValue->id == CSSValueWebkitText) {
2084         cssValue = primitiveValueCache->createIdentifierValue(parserValue->id);
2085         return true;
2086     }
2087     return false;
2088 }
2089
2090 const int cMaxFillProperties = 9;
2091
2092 bool CSSParser::parseFillShorthand(int propId, const int* properties, int numProperties, bool important)
2093 {
2094     ASSERT(numProperties <= cMaxFillProperties);
2095     if (numProperties > cMaxFillProperties)
2096         return false;
2097
2098     ShorthandScope scope(this, propId);
2099
2100     bool parsedProperty[cMaxFillProperties] = { false };
2101     RefPtr<CSSValue> values[cMaxFillProperties];
2102     RefPtr<CSSValue> clipValue;
2103     RefPtr<CSSValue> positionYValue;
2104     RefPtr<CSSValue> repeatYValue;
2105     bool foundClip = false;
2106     int i;
2107
2108     while (m_valueList->current()) {
2109         CSSParserValue* val = m_valueList->current();
2110         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2111             // We hit the end.  Fill in all remaining values with the initial value.
2112             m_valueList->next();
2113             for (i = 0; i < numProperties; ++i) {
2114                 if (properties[i] == CSSPropertyBackgroundColor && parsedProperty[i])
2115                     // Color is not allowed except as the last item in a list for backgrounds.
2116                     // Reject the entire property.
2117                     return false;
2118
2119                 if (!parsedProperty[i] && properties[i] != CSSPropertyBackgroundColor) {
2120                     addFillValue(values[i], CSSInitialValue::createImplicit());
2121                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2122                         addFillValue(positionYValue, CSSInitialValue::createImplicit());
2123                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2124                         addFillValue(repeatYValue, CSSInitialValue::createImplicit());
2125                     if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
2126                         // If background-origin wasn't present, then reset background-clip also.
2127                         addFillValue(clipValue, CSSInitialValue::createImplicit());
2128                     }                    
2129                 }
2130                 parsedProperty[i] = false;
2131             }
2132             if (!m_valueList->current())
2133                 break;
2134         }
2135
2136         bool found = false;
2137         for (i = 0; !found && i < numProperties; ++i) {
2138             if (!parsedProperty[i]) {
2139                 RefPtr<CSSValue> val1;
2140                 RefPtr<CSSValue> val2;
2141                 int propId1, propId2;
2142                 CSSParserValue* parserValue = m_valueList->current();
2143                 if (parseFillProperty(properties[i], propId1, propId2, val1, val2)) {
2144                     parsedProperty[i] = found = true;
2145                     addFillValue(values[i], val1.release());
2146                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2147                         addFillValue(positionYValue, val2.release());
2148                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2149                         addFillValue(repeatYValue, val2.release());
2150                     if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
2151                         // Reparse the value as a clip, and see if we succeed.
2152                         if (parseBackgroundClip(parserValue, val1, primitiveValueCache()))
2153                             addFillValue(clipValue, val1.release()); // The property parsed successfully.
2154                         else
2155                             addFillValue(clipValue, CSSInitialValue::createImplicit()); // Some value was used for origin that is not supported by clip. Just reset clip instead.
2156                     }
2157                     if (properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) {
2158                         // Update clipValue
2159                         addFillValue(clipValue, val1.release());
2160                         foundClip = true;
2161                     }
2162                 }
2163             }
2164         }
2165
2166         // if we didn't find at least one match, this is an
2167         // invalid shorthand and we have to ignore it
2168         if (!found)
2169             return false;
2170     }
2171
2172     // Fill in any remaining properties with the initial value.
2173     for (i = 0; i < numProperties; ++i) {
2174         if (!parsedProperty[i]) {
2175             addFillValue(values[i], CSSInitialValue::createImplicit());
2176             if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2177                 addFillValue(positionYValue, CSSInitialValue::createImplicit());
2178             if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2179                 addFillValue(repeatYValue, CSSInitialValue::createImplicit());
2180             if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
2181                 // If background-origin wasn't present, then reset background-clip also.
2182                 addFillValue(clipValue, CSSInitialValue::createImplicit());
2183             }
2184         }
2185     }
2186
2187     // Now add all of the properties we found.
2188     for (i = 0; i < numProperties; i++) {
2189         if (properties[i] == CSSPropertyBackgroundPosition) {
2190             addProperty(CSSPropertyBackgroundPositionX, values[i].release(), important);
2191             // it's OK to call positionYValue.release() since we only see CSSPropertyBackgroundPosition once
2192             addProperty(CSSPropertyBackgroundPositionY, positionYValue.release(), important);
2193         } else if (properties[i] == CSSPropertyWebkitMaskPosition) {
2194             addProperty(CSSPropertyWebkitMaskPositionX, values[i].release(), important);
2195             // it's OK to call positionYValue.release() since we only see CSSPropertyWebkitMaskPosition once
2196             addProperty(CSSPropertyWebkitMaskPositionY, positionYValue.release(), important);
2197         } else if (properties[i] == CSSPropertyBackgroundRepeat) {
2198             addProperty(CSSPropertyBackgroundRepeatX, values[i].release(), important);
2199             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2200             addProperty(CSSPropertyBackgroundRepeatY, repeatYValue.release(), important);
2201         } else if (properties[i] == CSSPropertyWebkitMaskRepeat) {
2202             addProperty(CSSPropertyWebkitMaskRepeatX, values[i].release(), important);
2203             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2204             addProperty(CSSPropertyWebkitMaskRepeatY, repeatYValue.release(), important);
2205         } else if ((properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) && !foundClip)
2206             // Value is already set while updating origin
2207             continue;
2208         else
2209             addProperty(properties[i], values[i].release(), important);
2210
2211         // Add in clip values when we hit the corresponding origin property.
2212         if (properties[i] == CSSPropertyBackgroundOrigin && !foundClip)
2213             addProperty(CSSPropertyBackgroundClip, clipValue.release(), important);
2214         else if (properties[i] == CSSPropertyWebkitMaskOrigin && !foundClip)
2215             addProperty(CSSPropertyWebkitMaskClip, clipValue.release(), important);
2216     }
2217
2218     return true;
2219 }
2220
2221 void CSSParser::addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
2222 {
2223     if (lval) {
2224         if (lval->isValueList())
2225             static_cast<CSSValueList*>(lval.get())->append(rval);
2226         else {
2227             PassRefPtr<CSSValue> oldVal(lval.release());
2228             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2229             list->append(oldVal);
2230             list->append(rval);
2231             lval = list;
2232         }
2233     }
2234     else
2235         lval = rval;
2236 }
2237
2238 bool CSSParser::parseAnimationShorthand(bool important)
2239 {
2240     const int properties[] = {  CSSPropertyWebkitAnimationName,
2241                                 CSSPropertyWebkitAnimationDuration,
2242                                 CSSPropertyWebkitAnimationTimingFunction,
2243                                 CSSPropertyWebkitAnimationDelay,
2244                                 CSSPropertyWebkitAnimationIterationCount,
2245                                 CSSPropertyWebkitAnimationDirection,
2246                                 CSSPropertyWebkitAnimationFillMode };
2247     const int numProperties = WTF_ARRAY_LENGTH(properties);
2248
2249     ShorthandScope scope(this, CSSPropertyWebkitAnimation);
2250
2251     bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
2252     RefPtr<CSSValue> values[numProperties];
2253
2254     int i;
2255     while (m_valueList->current()) {
2256         CSSParserValue* val = m_valueList->current();
2257         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2258             // We hit the end.  Fill in all remaining values with the initial value.
2259             m_valueList->next();
2260             for (i = 0; i < numProperties; ++i) {
2261                 if (!parsedProperty[i])
2262                     addAnimationValue(values[i], CSSInitialValue::createImplicit());
2263                 parsedProperty[i] = false;
2264             }
2265             if (!m_valueList->current())
2266                 break;
2267         }
2268
2269         bool found = false;
2270         for (i = 0; !found && i < numProperties; ++i) {
2271             if (!parsedProperty[i]) {
2272                 RefPtr<CSSValue> val;
2273                 if (parseAnimationProperty(properties[i], val)) {
2274                     parsedProperty[i] = found = true;
2275                     addAnimationValue(values[i], val.release());
2276                 }
2277             }
2278         }
2279
2280         // if we didn't find at least one match, this is an
2281         // invalid shorthand and we have to ignore it
2282         if (!found)
2283             return false;
2284     }
2285
2286     // Fill in any remaining properties with the initial value.
2287     for (i = 0; i < numProperties; ++i) {
2288         if (!parsedProperty[i])
2289             addAnimationValue(values[i], CSSInitialValue::createImplicit());
2290     }
2291
2292     // Now add all of the properties we found.
2293     for (i = 0; i < numProperties; i++)
2294         addProperty(properties[i], values[i].release(), important);
2295
2296     return true;
2297 }
2298
2299 bool CSSParser::parseTransitionShorthand(bool important)
2300 {
2301     const int properties[] = { CSSPropertyWebkitTransitionProperty,
2302                                CSSPropertyWebkitTransitionDuration,
2303                                CSSPropertyWebkitTransitionTimingFunction,
2304                                CSSPropertyWebkitTransitionDelay };
2305     const int numProperties = WTF_ARRAY_LENGTH(properties);
2306
2307     ShorthandScope scope(this, CSSPropertyWebkitTransition);
2308
2309     bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
2310     RefPtr<CSSValue> values[numProperties];
2311
2312     int i;
2313     while (m_valueList->current()) {
2314         CSSParserValue* val = m_valueList->current();
2315         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2316             // We hit the end.  Fill in all remaining values with the initial value.
2317             m_valueList->next();
2318             for (i = 0; i < numProperties; ++i) {
2319                 if (!parsedProperty[i])
2320                     addAnimationValue(values[i], CSSInitialValue::createImplicit());
2321                 parsedProperty[i] = false;
2322             }
2323             if (!m_valueList->current())
2324                 break;
2325         }
2326
2327         bool found = false;
2328         for (i = 0; !found && i < numProperties; ++i) {
2329             if (!parsedProperty[i]) {
2330                 RefPtr<CSSValue> val;
2331                 if (parseAnimationProperty(properties[i], val)) {
2332                     parsedProperty[i] = found = true;
2333                     addAnimationValue(values[i], val.release());
2334                 }
2335             }
2336         }
2337
2338         // if we didn't find at least one match, this is an
2339         // invalid shorthand and we have to ignore it
2340         if (!found)
2341             return false;
2342     }
2343
2344     // Fill in any remaining properties with the initial value.
2345     for (i = 0; i < numProperties; ++i) {
2346         if (!parsedProperty[i])
2347             addAnimationValue(values[i], CSSInitialValue::createImplicit());
2348     }
2349
2350     // Now add all of the properties we found.
2351     for (i = 0; i < numProperties; i++)
2352         addProperty(properties[i], values[i].release(), important);
2353
2354     return true;
2355 }
2356
2357 bool CSSParser::parseShorthand(int propId, const int *properties, int numProperties, bool important)
2358 {
2359     // We try to match as many properties as possible
2360     // We set up an array of booleans to mark which property has been found,
2361     // and we try to search for properties until it makes no longer any sense.
2362     ShorthandScope scope(this, propId);
2363
2364     bool found = false;
2365     bool fnd[6]; // Trust me ;)
2366     for (int i = 0; i < numProperties; i++)
2367         fnd[i] = false;
2368
2369     while (m_valueList->current()) {
2370         found = false;
2371         for (int propIndex = 0; !found && propIndex < numProperties; ++propIndex) {
2372             if (!fnd[propIndex]) {
2373                 if (parseValue(properties[propIndex], important))
2374                     fnd[propIndex] = found = true;
2375             }
2376         }
2377
2378         // if we didn't find at least one match, this is an
2379         // invalid shorthand and we have to ignore it
2380         if (!found)
2381             return false;
2382     }
2383
2384     // Fill in any remaining properties with the initial value.
2385     m_implicitShorthand = true;
2386     for (int i = 0; i < numProperties; ++i) {
2387         if (!fnd[i])
2388             addProperty(properties[i], CSSInitialValue::createImplicit(), important);
2389     }
2390     m_implicitShorthand = false;
2391
2392     return true;
2393 }
2394
2395 bool CSSParser::parse4Values(int propId, const int *properties,  bool important)
2396 {
2397     /* From the CSS 2 specs, 8.3
2398      * If there is only one value, it applies to all sides. If there are two values, the top and
2399      * bottom margins are set to the first value and the right and left margins are set to the second.
2400      * If there are three values, the top is set to the first value, the left and right are set to the
2401      * second, and the bottom is set to the third. If there are four values, they apply to the top,
2402      * right, bottom, and left, respectively.
2403      */
2404
2405     int num = inShorthand() ? 1 : m_valueList->size();
2406
2407     ShorthandScope scope(this, propId);
2408
2409     // the order is top, right, bottom, left
2410     switch (num) {
2411         case 1: {
2412             if (!parseValue(properties[0], important))
2413                 return false;
2414             CSSValue *value = m_parsedProperties[m_numParsedProperties-1]->value();
2415             m_implicitShorthand = true;
2416             addProperty(properties[1], value, important);
2417             addProperty(properties[2], value, important);
2418             addProperty(properties[3], value, important);
2419             m_implicitShorthand = false;
2420             break;
2421         }
2422         case 2: {
2423             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
2424                 return false;
2425             CSSValue *value = m_parsedProperties[m_numParsedProperties-2]->value();
2426             m_implicitShorthand = true;
2427             addProperty(properties[2], value, important);
2428             value = m_parsedProperties[m_numParsedProperties-2]->value();
2429             addProperty(properties[3], value, important);
2430             m_implicitShorthand = false;
2431             break;
2432         }
2433         case 3: {
2434             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
2435                 return false;
2436             CSSValue *value = m_parsedProperties[m_numParsedProperties-2]->value();
2437             m_implicitShorthand = true;
2438             addProperty(properties[3], value, important);
2439             m_implicitShorthand = false;
2440             break;
2441         }
2442         case 4: {
2443             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
2444                 !parseValue(properties[2], important) || !parseValue(properties[3], important))
2445                 return false;
2446             break;
2447         }
2448         default: {
2449             return false;
2450         }
2451     }
2452
2453     return true;
2454 }
2455
2456 // auto | <identifier>
2457 bool CSSParser::parsePage(int propId, bool important)
2458 {
2459     ASSERT(propId == CSSPropertyPage);
2460
2461     if (m_valueList->size() != 1)
2462         return false;
2463
2464     CSSParserValue* value = m_valueList->current();
2465     if (!value)
2466         return false;
2467
2468     if (value->id == CSSValueAuto) {
2469         addProperty(propId, primitiveValueCache()->createIdentifierValue(value->id), important);
2470         return true;
2471     } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) {
2472         addProperty(propId, primitiveValueCache()->createValue(value->string, CSSPrimitiveValue::CSS_STRING), important);
2473         return true;
2474     }
2475     return false;
2476 }
2477
2478 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
2479 bool CSSParser::parseSize(int propId, bool important)
2480 {
2481     ASSERT(propId == CSSPropertySize);
2482
2483     if (m_valueList->size() > 2)
2484         return false;
2485
2486     CSSParserValue* value = m_valueList->current();
2487     if (!value)
2488         return false;
2489
2490     RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
2491
2492     // First parameter.
2493     SizeParameterType paramType = parseSizeParameter(parsedValues.get(), value, None);
2494     if (paramType == None)
2495         return false;
2496
2497     // Second parameter, if any.
2498     value = m_valueList->next();
2499     if (value) {
2500         paramType = parseSizeParameter(parsedValues.get(), value, paramType);
2501         if (paramType == None)
2502             return false;
2503     }
2504
2505     addProperty(propId, parsedValues.release(), important);
2506     return true;
2507 }
2508
2509 CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType)
2510 {
2511     switch (value->id) {
2512     case CSSValueAuto:
2513         if (prevParamType == None) {
2514             parsedValues->append(primitiveValueCache()->createIdentifierValue(value->id));
2515             return Auto;
2516         }
2517         return None;
2518     case CSSValueLandscape:
2519     case CSSValuePortrait:
2520         if (prevParamType == None || prevParamType == PageSize) {
2521             parsedValues->append(primitiveValueCache()->createIdentifierValue(value->id));
2522             return Orientation;
2523         }
2524         return None;
2525     case CSSValueA3:
2526     case CSSValueA4:
2527     case CSSValueA5:
2528     case CSSValueB4:
2529     case CSSValueB5:
2530     case CSSValueLedger:
2531     case CSSValueLegal:
2532     case CSSValueLetter:
2533         if (prevParamType == None || prevParamType == Orientation) {
2534             // Normalize to Page Size then Orientation order by prepending.
2535             // This is not specified by the CSS3 Paged Media specification, but for simpler processing later (CSSStyleSelector::applyPageSizeProperty).
2536             parsedValues->prepend(primitiveValueCache()->createIdentifierValue(value->id));
2537             return PageSize;
2538         }
2539         return None;
2540     case 0:
2541         if (validUnit(value, FLength | FNonNeg, m_strict) && (prevParamType == None || prevParamType == Length)) {
2542             parsedValues->append(primitiveValueCache()->createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)));
2543             return Length;
2544         }
2545         return None;
2546     default:
2547         return None;
2548     }
2549 }
2550
2551 // [ <string> <string> ]+ | inherit | none
2552 // inherit and none are handled in parseValue.
2553 bool CSSParser::parseQuotes(int propId, bool important)
2554 {
2555     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
2556     while (CSSParserValue* val = m_valueList->current()) {
2557         RefPtr<CSSValue> parsedValue;
2558         if (val->unit == CSSPrimitiveValue::CSS_STRING)
2559             parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING);
2560         else
2561             break;
2562         values->append(parsedValue.release());
2563         m_valueList->next();
2564     }
2565     if (values->length()) {
2566         addProperty(propId, values.release(), important);
2567         m_valueList->next();
2568         return true;
2569     }
2570     return false;
2571 }
2572
2573 // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
2574 // in CSS 2.1 this got somewhat reduced:
2575 // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
2576 bool CSSParser::parseContent(int propId, bool important)
2577 {
2578     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
2579
2580     while (CSSParserValue* val = m_valueList->current()) {
2581         RefPtr<CSSValue> parsedValue;
2582         if (val->unit == CSSPrimitiveValue::CSS_URI && m_styleSheet) {
2583             // url
2584             // FIXME: The completeURL call should be done when using the CSSImageValue,
2585             // not when creating it.
2586             parsedValue = CSSImageValue::create(m_styleSheet->completeURL(val->string));
2587         } else if (val->unit == CSSParserValue::Function) {
2588             // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) | -webkit-gradient(...)
2589             CSSParserValueList* args = val->function->args.get();
2590             if (!args)
2591                 return false;
2592             if (equalIgnoringCase(val->function->name, "attr(")) {
2593                 parsedValue = parseAttr(args);
2594                 if (!parsedValue)
2595                     return false;
2596             } else if (equalIgnoringCase(val->function->name, "counter(")) {
2597                 parsedValue = parseCounterContent(args, false);
2598                 if (!parsedValue)
2599                     return false;
2600             } else if (equalIgnoringCase(val->function->name, "counters(")) {
2601                 parsedValue = parseCounterContent(args, true);
2602                 if (!parsedValue)
2603                     return false;
2604             } else if (isGeneratedImageValue(val)) {
2605                 if (!parseGeneratedImage(parsedValue))
2606                     return false;
2607             } else
2608                 return false;
2609         } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
2610             // open-quote
2611             // close-quote
2612             // no-open-quote
2613             // no-close-quote
2614             // inherit
2615             // FIXME: These are not yet implemented (http://bugs.webkit.org/show_bug.cgi?id=6503).
2616             // none
2617             // normal
2618             switch (val->id) {
2619             case CSSValueOpenQuote:
2620             case CSSValueCloseQuote:
2621             case CSSValueNoOpenQuote:
2622             case CSSValueNoCloseQuote:
2623             case CSSValueNone:
2624             case CSSValueNormal:
2625                 parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
2626             }
2627         } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
2628             parsedValue = primitiveValueCache()->createValue(val->string, CSSPrimitiveValue::CSS_STRING);
2629         }
2630         if (!parsedValue)
2631             break;
2632         values->append(parsedValue.release());
2633         m_valueList->next();
2634     }
2635
2636     if (values->length()) {
2637         addProperty(propId, values.release(), important);
2638         m_valueList->next();
2639         return true;
2640     }
2641
2642     return false;
2643 }
2644
2645 PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args)
2646 {
2647     if (args->size() != 1)
2648         return 0;
2649
2650     CSSParserValue* a = args->current();
2651
2652     if (a->unit != CSSPrimitiveValue::CSS_IDENT)
2653         return 0;
2654
2655     String attrName = a->string;
2656     // CSS allows identifiers with "-" at the start, like "-webkit-mask-image".
2657     // But HTML attribute names can't have those characters, and we should not
2658     // even parse them inside attr().
2659     if (attrName[0] == '-')
2660         return 0;
2661
2662     if (document() && document()->isHTMLDocument())
2663         attrName = attrName.lower();
2664
2665     return primitiveValueCache()->createValue(attrName, CSSPrimitiveValue::CSS_ATTR);
2666 }
2667
2668 PassRefPtr<CSSValue> CSSParser::parseBackgroundColor()
2669 {
2670     int id = m_valueList->current()->id;
2671     if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor ||
2672         (id >= CSSValueGrey && id < CSSValueWebkitText && !m_strict))
2673        return primitiveValueCache()->createIdentifierValue(id);
2674     return parseColor();
2675 }
2676
2677 bool CSSParser::parseFillImage(RefPtr<CSSValue>& value)
2678 {
2679     if (m_valueList->current()->id == CSSValueNone) {
2680         value = CSSImageValue::create();
2681         return true;
2682     }
2683     if (m_valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
2684         // FIXME: The completeURL call should be done when using the CSSImageValue,
2685         // not when creating it.
2686         if (m_styleSheet)
2687             value = CSSImageValue::create(m_styleSheet->completeURL(m_valueList->current()->string));
2688         return true;
2689     }
2690
2691     if (isGeneratedImageValue(m_valueList->current()))
2692         return parseGeneratedImage(value);
2693
2694     return false;
2695 }
2696
2697 PassRefPtr<CSSValue> CSSParser::parseFillPositionX(CSSParserValueList* valueList)
2698 {
2699     int id = valueList->current()->id;
2700     if (id == CSSValueLeft || id == CSSValueRight || id == CSSValueCenter) {
2701         int percent = 0;
2702         if (id == CSSValueRight)
2703             percent = 100;
2704         else if (id == CSSValueCenter)
2705             percent = 50;
2706         return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
2707     }
2708     if (validUnit(valueList->current(), FPercent | FLength, m_strict))
2709         return primitiveValueCache()->createValue(valueList->current()->fValue,
2710                                                   (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
2711     return 0;
2712 }
2713
2714 PassRefPtr<CSSValue> CSSParser::parseFillPositionY(CSSParserValueList* valueList)
2715 {
2716     int id = valueList->current()->id;
2717     if (id == CSSValueTop || id == CSSValueBottom || id == CSSValueCenter) {
2718         int percent = 0;
2719         if (id == CSSValueBottom)
2720             percent = 100;
2721         else if (id == CSSValueCenter)
2722             percent = 50;
2723         return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
2724     }
2725     if (validUnit(valueList->current(), FPercent | FLength, m_strict))
2726         return primitiveValueCache()->createValue(valueList->current()->fValue,
2727                                                   (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
2728     return 0;
2729 }
2730
2731 PassRefPtr<CSSValue> CSSParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag)
2732 {
2733     int id = valueList->current()->id;
2734     if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
2735         int percent = 0;
2736         if (id == CSSValueLeft || id == CSSValueRight) {
2737             if (cumulativeFlags & XFillPosition)
2738                 return 0;
2739             cumulativeFlags |= XFillPosition;
2740             individualFlag = XFillPosition;
2741             if (id == CSSValueRight)
2742                 percent = 100;
2743         }
2744         else if (id == CSSValueTop || id == CSSValueBottom) {
2745             if (cumulativeFlags & YFillPosition)
2746                 return 0;
2747             cumulativeFlags |= YFillPosition;
2748             individualFlag = YFillPosition;
2749             if (id == CSSValueBottom)
2750                 percent = 100;
2751         } else if (id == CSSValueCenter) {
2752             // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
2753             percent = 50;
2754             cumulativeFlags |= AmbiguousFillPosition;
2755             individualFlag = AmbiguousFillPosition;
2756         }
2757         return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
2758     }
2759     if (validUnit(valueList->current(), FPercent | FLength, m_strict)) {
2760         if (!cumulativeFlags) {
2761             cumulativeFlags |= XFillPosition;
2762             individualFlag = XFillPosition;
2763         } else if (cumulativeFlags & (XFillPosition | AmbiguousFillPosition)) {
2764             cumulativeFlags |= YFillPosition;
2765             individualFlag = YFillPosition;
2766         } else
2767             return 0;
2768         return primitiveValueCache()->createValue(valueList->current()->fValue,
2769                                                   (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
2770     }
2771     return 0;
2772 }
2773
2774 void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
2775 {
2776     CSSParserValue* value = valueList->current();
2777
2778     // Parse the first value.  We're just making sure that it is one of the valid keywords or a percentage/length.
2779     unsigned cumulativeFlags = 0;
2780     FillPositionFlag value1Flag = InvalidFillPosition;
2781     FillPositionFlag value2Flag = InvalidFillPosition;
2782     value1 = parseFillPositionComponent(valueList, cumulativeFlags, value1Flag);
2783     if (!value1)
2784         return;
2785
2786     // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
2787     // can assume that any other values belong to the rest of the shorthand).  If we're not parsing a shorthand, though, the
2788     // value was explicitly specified for our property.
2789     value = valueList->next();
2790
2791     // First check for the comma.  If so, we are finished parsing this value or value pair.
2792     if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
2793         value = 0;
2794
2795     if (value) {
2796         value2 = parseFillPositionComponent(valueList, cumulativeFlags, value2Flag);
2797         if (value2)
2798             valueList->next();
2799         else {
2800             if (!inShorthand()) {
2801                 value1.clear();
2802                 return;
2803             }
2804         }
2805     }
2806
2807     if (!value2)
2808         // Only one value was specified.  If that value was not a keyword, then it sets the x position, and the y position
2809         // is simply 50%.  This is our default.
2810         // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
2811         // For left/right/center, the default of 50% in the y is still correct.
2812         value2 = primitiveValueCache()->createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
2813
2814     if (value1Flag == YFillPosition || value2Flag == XFillPosition)
2815         value1.swap(value2);
2816 }
2817
2818 void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
2819 {
2820     CSSParserValue* value = m_valueList->current();
2821
2822     int id = m_valueList->current()->id;
2823     if (id == CSSValueRepeatX) {
2824         m_implicitShorthand = true;
2825         value1 = primitiveValueCache()->createIdentifierValue(CSSValueRepeat);
2826         value2 = primitiveValueCache()->createIdentifierValue(CSSValueNoRepeat);
2827         m_valueList->next();
2828         return;
2829     }
2830     if (id == CSSValueRepeatY) {
2831         m_implicitShorthand = true;
2832         value1 = primitiveValueCache()->createIdentifierValue(CSSValueNoRepeat);
2833         value2 = primitiveValueCache()->createIdentifierValue(CSSValueRepeat);
2834         m_valueList->next();
2835         return;
2836     }
2837     if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)
2838         value1 = primitiveValueCache()->createIdentifierValue(id);
2839     else {
2840         value1 = 0;
2841         return;
2842     }
2843
2844     value = m_valueList->next();
2845
2846     // First check for the comma.  If so, we are finished parsing this value or value pair.
2847     if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
2848         value = 0;
2849
2850     if (value)
2851         id = m_valueList->current()->id;
2852
2853     if (value && (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)) {
2854         value2 = primitiveValueCache()->createIdentifierValue(id);
2855         m_valueList->next();
2856     } else {
2857         // If only one value was specified, value2 is the same as value1.
2858         m_implicitShorthand = true;
2859         value2 = primitiveValueCache()->createIdentifierValue(static_cast<CSSPrimitiveValue*>(value1.get())->getIdent());
2860     }
2861 }
2862
2863 PassRefPtr<CSSValue> CSSParser::parseFillSize(int propId, bool& allowComma)
2864 {
2865     allowComma = true;
2866     CSSParserValue* value = m_valueList->current();
2867
2868     if (value->id == CSSValueContain || value->id == CSSValueCover)
2869         return primitiveValueCache()->createIdentifierValue(value->id);
2870
2871     RefPtr<CSSPrimitiveValue> parsedValue1;
2872
2873     if (value->id == CSSValueAuto)
2874         parsedValue1 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN);
2875     else {
2876         if (!validUnit(value, FLength | FPercent, m_strict))
2877             return 0;
2878         parsedValue1 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2879     }
2880
2881     CSSPropertyID property = static_cast<CSSPropertyID>(propId);
2882     RefPtr<CSSPrimitiveValue> parsedValue2;
2883     if ((value = m_valueList->next())) {
2884         if (value->id == CSSValueAuto)
2885             parsedValue2 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN);
2886         else if (value->unit == CSSParserValue::Operator && value->iValue == ',')
2887             allowComma = false;
2888         else {
2889             if (!validUnit(value, FLength | FPercent, m_strict))
2890                 return 0;
2891             parsedValue2 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2892         }
2893     }
2894     if (!parsedValue2) {
2895         if (property == CSSPropertyWebkitBackgroundSize || property == CSSPropertyWebkitMaskSize)
2896             parsedValue2 = parsedValue1;
2897         else
2898             parsedValue2 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN);
2899     }
2900
2901     return primitiveValueCache()->createValue(Pair::create(parsedValue1.release(), parsedValue2.release()));
2902 }
2903
2904 bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2,
2905                                   RefPtr<CSSValue>& retValue1, RefPtr<CSSValue>& retValue2)
2906 {
2907     RefPtr<CSSValueList> values;
2908     RefPtr<CSSValueList> values2;
2909     CSSParserValue* val;
2910     RefPtr<CSSValue> value;
2911     RefPtr<CSSValue> value2;
2912
2913     bool allowComma = false;
2914
2915     retValue1 = retValue2 = 0;
2916     propId1 = propId;
2917     propId2 = propId;
2918     if (propId == CSSPropertyBackgroundPosition) {
2919         propId1 = CSSPropertyBackgroundPositionX;
2920         propId2 = CSSPropertyBackgroundPositionY;
2921     } else if (propId == CSSPropertyWebkitMaskPosition) {
2922         propId1 = CSSPropertyWebkitMaskPositionX;
2923         propId2 = CSSPropertyWebkitMaskPositionY;
2924     } else if (propId == CSSPropertyBackgroundRepeat) {
2925         propId1 = CSSPropertyBackgroundRepeatX;
2926         propId2 = CSSPropertyBackgroundRepeatY;
2927     } else if (propId == CSSPropertyWebkitMaskRepeat) {
2928         propId1 = CSSPropertyWebkitMaskRepeatX;
2929         propId2 = CSSPropertyWebkitMaskRepeatY;
2930     }
2931
2932     while ((val = m_valueList->current())) {
2933         RefPtr<CSSValue> currValue;
2934         RefPtr<CSSValue> currValue2;
2935
2936         if (allowComma) {
2937             if (val->unit != CSSParserValue::Operator || val->iValue != ',')
2938                 return false;
2939             m_valueList->next();
2940             allowComma = false;
2941         } else {
2942             allowComma = true;
2943             switch (propId) {
2944                 case CSSPropertyBackgroundColor:
2945                     currValue = parseBackgroundColor();
2946                     if (currValue)
2947                         m_valueList->next();
2948                     break;
2949                 case CSSPropertyBackgroundAttachment:
2950                 case CSSPropertyWebkitMaskAttachment:
2951                     if (val->id == CSSValueScroll || val->id == CSSValueFixed || val->id == CSSValueLocal) {
2952                         currValue = primitiveValueCache()->createIdentifierValue(val->id);
2953                         m_valueList->next();
2954                     }
2955                     break;
2956                 case CSSPropertyBackgroundImage:
2957                 case CSSPropertyWebkitMaskImage:
2958                     if (parseFillImage(currValue))
2959                         m_valueList->next();
2960                     break;
2961                 case CSSPropertyWebkitBackgroundClip:
2962                 case CSSPropertyWebkitBackgroundOrigin:
2963                 case CSSPropertyWebkitMaskClip:
2964                 case CSSPropertyWebkitMaskOrigin:
2965                     // The first three values here are deprecated and do not apply to the version of the property that has
2966                     // the -webkit- prefix removed.
2967                     if (val->id == CSSValueBorder || val->id == CSSValuePadding || val->id == CSSValueContent ||
2968                         val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox ||
2969                         ((propId == CSSPropertyWebkitBackgroundClip || propId == CSSPropertyWebkitMaskClip) &&
2970                          (val->id == CSSValueText || val->id == CSSValueWebkitText))) {
2971                         currValue = primitiveValueCache()->createIdentifierValue(val->id);
2972                         m_valueList->next();
2973                     }
2974                     break;
2975                 case CSSPropertyBackgroundClip:
2976                     if (parseBackgroundClip(val, currValue, primitiveValueCache()))
2977                         m_valueList->next();
2978                     break;
2979                 case CSSPropertyBackgroundOrigin:
2980                     if (val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox) {
2981                         currValue = primitiveValueCache()->createIdentifierValue(val->id);
2982                         m_valueList->next();
2983                     }
2984                     break;
2985                 case CSSPropertyBackgroundPosition:
2986                 case CSSPropertyWebkitMaskPosition:
2987                     parseFillPosition(m_valueList, currValue, currValue2);
2988                     // parseFillPosition advances the m_valueList pointer
2989                     break;
2990                 case CSSPropertyBackgroundPositionX:
2991                 case CSSPropertyWebkitMaskPositionX: {
2992                     currValue = parseFillPositionX(m_valueList);
2993                     if (currValue)
2994                         m_valueList->next();
2995                     break;
2996                 }
2997                 case CSSPropertyBackgroundPositionY:
2998                 case CSSPropertyWebkitMaskPositionY: {
2999                     currValue = parseFillPositionY(m_valueList);
3000                     if (currValue)
3001                         m_valueList->next();
3002                     break;
3003                 }
3004                 case CSSPropertyWebkitBackgroundComposite:
3005                 case CSSPropertyWebkitMaskComposite:
3006                     if ((val->id >= CSSValueClear && val->id <= CSSValuePlusLighter) || val->id == CSSValueHighlight) {
3007                         currValue = primitiveValueCache()->createIdentifierValue(val->id);
3008                         m_valueList->next();
3009                     }
3010                     break;
3011                 case CSSPropertyBackgroundRepeat:
3012                 case CSSPropertyWebkitMaskRepeat:
3013                     parseFillRepeat(currValue, currValue2);
3014                     // parseFillRepeat advances the m_valueList pointer
3015                     break;
3016                 case CSSPropertyBackgroundSize:
3017                 case CSSPropertyWebkitBackgroundSize:
3018                 case CSSPropertyWebkitMaskSize: {
3019                     currValue = parseFillSize(propId, allowComma);
3020                     if (currValue)
3021                         m_valueList->next();
3022                     break;
3023                 }
3024             }
3025             if (!currValue)
3026                 return false;
3027
3028             if (value && !values) {
3029                 values = CSSValueList::createCommaSeparated();
3030                 values->append(value.release());
3031             }
3032
3033             if (value2 && !values2) {
3034                 values2 = CSSValueList::createCommaSeparated();
3035                 values2->append(value2.release());
3036             }
3037
3038             if (values)
3039                 values->append(currValue.release());
3040             else
3041                 value = currValue.release();
3042             if (currValue2) {
3043                 if (values2)
3044                     values2->append(currValue2.release());
3045                 else
3046                     value2 = currValue2.release();
3047             }
3048         }
3049
3050         // When parsing any fill shorthand property, we let it handle building up the lists for all
3051         // properties.
3052         if (inShorthand())
3053             break;
3054     }
3055
3056     if (values && values->length()) {
3057         retValue1 = values.release();
3058         if (values2 && values2->length())
3059             retValue2 = values2.release();
3060         return true;
3061     }
3062     if (value) {
3063         retValue1 = value.release();
3064         retValue2 = value2.release();
3065         return true;
3066     }
3067     return false;
3068 }
3069
3070 PassRefPtr<CSSValue> CSSParser::parseAnimationDelay()
3071 {
3072     CSSParserValue* value = m_valueList->current();
3073     if (validUnit(value, FTime, m_strict))
3074         return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
3075     return 0;
3076 }
3077
3078 PassRefPtr<CSSValue> CSSParser::parseAnimationDirection()
3079 {
3080     CSSParserValue* value = m_valueList->current();
3081     if (value->id == CSSValueNormal || value->id == CSSValueAlternate)
3082         return primitiveValueCache()->createIdentifierValue(value->id);
3083     return 0;
3084 }
3085
3086 PassRefPtr<CSSValue> CSSParser::parseAnimationDuration()
3087 {
3088     CSSParserValue* value = m_valueList->current();
3089     if (validUnit(value, FTime | FNonNeg, m_strict))
3090         return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
3091     return 0;
3092 }
3093
3094 PassRefPtr<CSSValue> CSSParser::parseAnimationFillMode()
3095 {
3096     CSSParserValue* value = m_valueList->current();
3097     if (value->id == CSSValueNone || value->id == CSSValueForwards || value->id == CSSValueBackwards || value->id == CSSValueBoth)
3098         return primitiveValueCache()->createIdentifierValue(value->id);
3099     return 0;
3100 }
3101
3102 PassRefPtr<CSSValue> CSSParser::parseAnimationIterationCount()
3103 {
3104     CSSParserValue* value = m_valueList->current();
3105     if (value->id == CSSValueInfinite)
3106         return primitiveValueCache()->createIdentifierValue(value->id);
3107     if (validUnit(value, FInteger | FNonNeg, m_strict))
3108         return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
3109     return 0;
3110 }
3111
3112 PassRefPtr<CSSValue> CSSParser::parseAnimationName()
3113 {
3114     CSSParserValue* value = m_valueList->current();
3115     if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT) {
3116         if (value->id == CSSValueNone || (value->unit == CSSPrimitiveValue::CSS_STRING && equalIgnoringCase(value->string, "none"))) {
3117             return primitiveValueCache()->createIdentifierValue(CSSValueNone);
3118         } else {
3119             return primitiveValueCache()->createValue(value->string, CSSPrimitiveValue::CSS_STRING);
3120         }
3121     }
3122     return 0;
3123 }
3124
3125 PassRefPtr<CSSValue> CSSParser::parseAnimationPlayState()
3126 {
3127     CSSParserValue* value = m_valueList->current();
3128     if (value->id == CSSValueRunning || value->id == CSSValuePaused)
3129         return primitiveValueCache()->createIdentifierValue(value->id);
3130     return 0;
3131 }
3132
3133 PassRefPtr<CSSValue> CSSParser::parseAnimationProperty()
3134 {
3135     CSSParserValue* value = m_valueList->current();
3136     if (value->unit != CSSPrimitiveValue::CSS_IDENT)
3137         return 0;
3138     int result = cssPropertyID(value->string);
3139     if (result)
3140         return primitiveValueCache()->createIdentifierValue(result);
3141     if (equalIgnoringCase(value->string, "all"))
3142         return primitiveValueCache()->createIdentifierValue(CSSValueAll);
3143     if (equalIgnoringCase(value->string, "none"))
3144         return primitiveValueCache()->createIdentifierValue(CSSValueNone);
3145     return 0;
3146 }
3147
3148 bool CSSParser::parseTransformOriginShorthand(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3)
3149 {
3150     parseFillPosition(m_valueList, value1, value2);
3151
3152     // now get z
3153     if (m_valueList->current()) {
3154         if (validUnit(m_valueList->current(), FLength, m_strict)) {
3155             value3 = primitiveValueCache()->createValue(m_valueList->current()->fValue,
3156                                              (CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit);
3157             m_valueList->next();
3158             return true;
3159         }
3160         return false;
3161     }
3162     return true;
3163 }
3164
3165 bool CSSParser::parseCubicBezierTimingFunctionValue(CSSParserValueList*& args, double& result)
3166 {
3167     CSSParserValue* v = args->current();
3168     if (!validUnit(v, FNumber, m_strict))
3169         return false;
3170     result = v->fValue;
3171     if (result < 0 || result > 1.0)
3172         return false;
3173     v = args->next();
3174     if (!v)
3175         // The last number in the function has no comma after it, so we're done.
3176         return true;
3177     if (v->unit != CSSParserValue::Operator && v->iValue != ',')
3178         return false;
3179     v = args->next();
3180     return true;
3181 }
3182
3183 PassRefPtr<CSSValue> CSSParser::parseAnimationTimingFunction()
3184 {
3185     CSSParserValue* value = m_valueList->current();
3186     if (value->id == CSSValueEase || value->id == CSSValueLinear || value->id == CSSValueEaseIn || value->id == CSSValueEaseOut
3187         || value->id == CSSValueEaseInOut || value->id == CSSValueStepStart || value->id == CSSValueStepEnd)
3188         return primitiveValueCache()->createIdentifierValue(value->id);
3189
3190     // We must be a function.
3191     if (value->unit != CSSParserValue::Function)
3192         return 0;
3193
3194     CSSParserValueList* args = value->function->args.get();
3195
3196     if (equalIgnoringCase(value->function->name, "steps(")) {
3197         // For steps, 1 or 2 params must be specified (comma-separated)
3198         if (!args || (args->size() != 1 && args->size() != 3))
3199             return 0;
3200
3201         // There are two values.
3202         int numSteps;
3203         bool stepAtStart = false;
3204
3205         CSSParserValue* v = args->current();
3206         if (!validUnit(v, FInteger, m_strict))
3207             return 0;
3208         numSteps = (int) min(v->fValue, (double)INT_MAX);
3209         if (numSteps < 1)
3210             return 0;
3211         v = args->next();
3212
3213         if (v) {
3214             // There is a comma so we need to parse the second value
3215             if (v->unit != CSSParserValue::Operator && v->iValue != ',')
3216                 return 0;
3217             v = args->next();
3218             if (v->id != CSSValueStart && v->id != CSSValueEnd)
3219                 return 0;
3220             stepAtStart = v->id == CSSValueStart;
3221         }
3222
3223         return CSSStepsTimingFunctionValue::create(numSteps, stepAtStart);
3224     }
3225     
3226     if (equalIgnoringCase(value->function->name, "cubic-bezier(")) {
3227         // For cubic bezier, 4 values must be specified.
3228         if (!args || args->size() != 7)
3229             return 0;
3230
3231         // There are two points specified.  The values must be between 0 and 1.
3232         double x1, y1, x2, y2;
3233
3234         if (!parseCubicBezierTimingFunctionValue(args, x1))
3235             return 0;
3236         if (!parseCubicBezierTimingFunctionValue(args, y1))
3237             return 0;
3238         if (!parseCubicBezierTimingFunctionValue(args, x2))
3239             return 0;
3240         if (!parseCubicBezierTimingFunctionValue(args, y2))
3241             return 0;
3242
3243         return CSSCubicBezierTimingFunctionValue::create(x1, y1, x2, y2);
3244     }
3245     
3246     return 0;
3247 }
3248
3249 bool CSSParser::parseAnimationProperty(int propId, RefPtr<CSSValue>& result)
3250 {
3251     RefPtr<CSSValueList> values;
3252     CSSParserValue* val;
3253     RefPtr<CSSValue> value;
3254     bool allowComma = false;
3255
3256     result = 0;
3257
3258     while ((val = m_valueList->current())) {
3259         RefPtr<CSSValue> currValue;
3260         if (allowComma) {
3261             if (val->unit != CSSParserValue::Operator || val->iValue != ',')
3262                 return false;
3263             m_valueList->next();
3264             allowComma = false;
3265         }
3266         else {
3267             switch (propId) {
3268                 case CSSPropertyWebkitAnimationDelay:
3269                 case CSSPropertyWebkitTransitionDelay:
3270                     currValue = parseAnimationDelay();
3271                     if (currValue)
3272                         m_valueList->next();
3273                     break;
3274                 case CSSPropertyWebkitAnimationDirection:
3275                     currValue = parseAnimationDirection();
3276                     if (currValue)
3277                         m_valueList->next();
3278                     break;
3279                 case CSSPropertyWebkitAnimationDuration:
3280                 case CSSPropertyWebkitTransitionDuration:
3281                     currValue = parseAnimationDuration();
3282                     if (currValue)
3283                         m_valueList->next();
3284                     break;
3285                 case CSSPropertyWebkitAnimationFillMode:
3286                     currValue = parseAnimationFillMode();
3287                     if (currValue)
3288                         m_valueList->next();
3289                     break;
3290                 case CSSPropertyWebkitAnimationIterationCount:
3291                     currValue = parseAnimationIterationCount();
3292                     if (currValue)
3293                         m_valueList->next();
3294                     break;
3295                 case CSSPropertyWebkitAnimationName:
3296                     currValue = parseAnimationName();
3297                     if (currValue)
3298                         m_valueList->next();
3299                     break;
3300                 case CSSPropertyWebkitAnimationPlayState:
3301                     currValue = parseAnimationPlayState();
3302                     if (currValue)
3303                         m_valueList->next();
3304                     break;
3305                 case CSSPropertyWebkitTransitionProperty:
3306                     currValue = parseAnimationProperty();
3307                     if (currValue)
3308                         m_valueList->next();
3309                     break;
3310                 case CSSPropertyWebkitAnimationTimingFunction:
3311                 case CSSPropertyWebkitTransitionTimingFunction:
3312                     currValue = parseAnimationTimingFunction();
3313                     if (currValue)
3314                         m_valueList->next();
3315                     break;
3316             }
3317
3318             if (!currValue)
3319                 return false;
3320
3321             if (value && !values) {
3322                 values = CSSValueList::createCommaSeparated();
3323                 values->append(value.release());