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