[CherryPick] Implement ValidityState::badInput
[framework/web/webkit-efl.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, 2012 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  * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "CSSParser.h"
28
29 #include "CSSAspectRatioValue.h"
30 #include "CSSBasicShapes.h"
31 #include "CSSBorderImage.h"
32 #include "CSSCanvasValue.h"
33 #include "CSSCrossfadeValue.h"
34 #include "CSSCursorImageValue.h"
35 #include "CSSFontFaceRule.h"
36 #include "CSSFontFaceSrcValue.h"
37 #include "CSSFunctionValue.h"
38 #include "CSSGradientValue.h"
39 #include "CSSImageValue.h"
40 #include "CSSInheritedValue.h"
41 #include "CSSInitialValue.h"
42 #include "CSSLineBoxContainValue.h"
43 #include "CSSMediaRule.h"
44 #include "CSSPageRule.h"
45 #include "CSSPrimitiveValue.h"
46 #include "CSSProperty.h"
47 #include "CSSPropertySourceData.h"
48 #include "CSSReflectValue.h"
49 #include "CSSSelector.h"
50 #include "CSSTimingFunctionValue.h"
51 #include "CSSUnicodeRangeValue.h"
52 #include "CSSValueKeywords.h"
53 #include "CSSValueList.h"
54 #include "CSSValuePool.h"
55 #if ENABLE(CSS_VARIABLES)
56 #include "CSSVariableValue.h"
57 #endif
58 #include "Counter.h"
59 #include "Document.h"
60 #include "FloatConversion.h"
61 #include "FontFeatureValue.h"
62 #include "FontValue.h"
63 #include "HTMLParserIdioms.h"
64 #include "HashTools.h"
65 #include "MediaList.h"
66 #include "MediaQueryExp.h"
67 #include "Page.h"
68 #include "Pair.h"
69 #include "Rect.h"
70 #include "RenderTheme.h"
71 #include "RuntimeEnabledFeatures.h"
72 #include "SVGParserUtilities.h"
73 #include "Settings.h"
74 #include "ShadowValue.h"
75 #include "StylePropertySet.h"
76 #include "StylePropertyShorthand.h"
77 #include "StyleRule.h"
78 #include "StyleRuleImport.h"
79 #include "StyleSheetContents.h"
80 #include "TextEncoding.h"
81 #include "WebKitCSSKeyframeRule.h"
82 #include "WebKitCSSKeyframesRule.h"
83 #include "WebKitCSSRegionRule.h"
84 #include "WebKitCSSTransformValue.h"
85 #include <limits.h>
86 #include <wtf/BitArray.h>
87 #include <wtf/HexNumber.h>
88 #include <wtf/dtoa.h>
89 #include <wtf/text/StringBuffer.h>
90 #include <wtf/text/StringBuilder.h>
91
92 #if ENABLE(CSS_IMAGE_SET)
93 #include "CSSImageSetValue.h"
94 #endif
95
96 #if ENABLE(CSS_FILTERS)
97 #include "WebKitCSSFilterValue.h"
98 #if ENABLE(SVG)
99 #include "WebKitCSSSVGDocumentValue.h"
100 #endif
101 #endif
102
103 #if ENABLE(CSS_SHADERS)
104 #include "WebKitCSSShaderValue.h"
105 #endif
106
107 #if ENABLE(DASHBOARD_SUPPORT)
108 #include "DashboardRegion.h"
109 #endif
110
111 #define YYDEBUG 0
112
113 #if YYDEBUG > 0
114 extern int cssyydebug;
115 #endif
116
117 extern int cssyyparse(void* parser);
118
119 using namespace std;
120 using namespace WTF;
121
122 namespace {
123
124 enum PropertyType {
125     PropertyExplicit,
126     PropertyImplicit
127 };
128
129 class ImplicitScope {
130     WTF_MAKE_NONCOPYABLE(ImplicitScope);
131 public:
132     ImplicitScope(WebCore::CSSParser* parser, PropertyType propertyType)
133         : m_parser(parser)
134     {
135         m_parser->m_implicitShorthand = propertyType == PropertyImplicit;
136     }
137
138     ~ImplicitScope()
139     {
140         m_parser->m_implicitShorthand = false;
141     }
142
143 private:
144     WebCore::CSSParser* m_parser;
145 };
146
147 } // namespace
148
149 namespace WebCore {
150
151 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
152 static const double MAX_SCALE = 1000000;
153
154 static bool equal(const CSSParserString& a, const char* b)
155 {
156     for (int i = 0; i < a.length; ++i) {
157         if (!b[i])
158             return false;
159         if (a.characters[i] != b[i])
160             return false;
161     }
162     return !b[a.length];
163 }
164
165 static bool equalIgnoringCase(const CSSParserString& a, const char* b)
166 {
167     for (int i = 0; i < a.length; ++i) {
168         if (!b[i])
169             return false;
170         ASSERT(!isASCIIUpper(b[i]));
171         if (toASCIILower(a.characters[i]) != b[i])
172             return false;
173     }
174     return !b[a.length];
175 }
176
177 static bool hasPrefix(const char* string, unsigned length, const char* prefix)
178 {
179     for (unsigned i = 0; i < length; ++i) {
180         if (!prefix[i])
181             return true;
182         if (string[i] != prefix[i])
183             return false;
184     }
185     return false;
186 }
187     
188 const CSSParserContext& strictCSSParserContext()
189 {
190     DEFINE_STATIC_LOCAL(CSSParserContext, strictContext, (CSSStrictMode));
191     return strictContext;
192 }
193
194 CSSParserContext::CSSParserContext(CSSParserMode mode, const KURL& baseURL)
195     : baseURL(baseURL)
196     , mode(mode)
197     , isHTMLDocument(false)
198     , isCSSCustomFilterEnabled(false)
199     , isCSSRegionsEnabled(false)
200     , isCSSGridLayoutEnabled(false)
201 #if ENABLE(CSS_VARIABLES)
202     , isCSSVariablesEnabled(false)
203 #endif
204     , needsSiteSpecificQuirks(false)
205     , enforcesCSSMIMETypeInNoQuirksMode(true)
206 {
207 }
208
209 CSSParserContext::CSSParserContext(Document* document, const KURL& baseURL, const String& charset)
210     : baseURL(baseURL.isNull() ? document->baseURL() : baseURL)
211     , charset(charset)
212     , mode(document->inQuirksMode() ? CSSQuirksMode : CSSStrictMode)
213     , isHTMLDocument(document->isHTMLDocument())
214     , isCSSCustomFilterEnabled(document->settings() ? document->settings()->isCSSCustomFilterEnabled() : false)
215     , isCSSRegionsEnabled(document->cssRegionsEnabled())
216     , isCSSGridLayoutEnabled(document->cssGridLayoutEnabled())
217 #if ENABLE(CSS_VARIABLES)
218     , isCSSVariablesEnabled(document->settings() ? document->settings()->cssVariablesEnabled() : false)
219 #endif
220     , needsSiteSpecificQuirks(document->settings() ? document->settings()->needsSiteSpecificQuirks() : false)
221     , enforcesCSSMIMETypeInNoQuirksMode(!document->settings() || document->settings()->enforceCSSMIMETypeInNoQuirksMode())
222 {
223 }
224
225 bool operator==(const CSSParserContext& a, const CSSParserContext& b)
226 {
227     return a.baseURL == b.baseURL
228         && a.charset == b.charset
229         && a.mode == b.mode
230         && a.isHTMLDocument == b.isHTMLDocument
231         && a.isCSSCustomFilterEnabled == b.isCSSCustomFilterEnabled
232         && a.isCSSRegionsEnabled == b.isCSSRegionsEnabled
233         && a.isCSSGridLayoutEnabled == b.isCSSGridLayoutEnabled
234 #if ENABLE(CSS_VARIABLES)
235         && a.isCSSVariablesEnabled == b.isCSSVariablesEnabled
236 #endif
237         && a.needsSiteSpecificQuirks == b.needsSiteSpecificQuirks
238         && a.enforcesCSSMIMETypeInNoQuirksMode == b.enforcesCSSMIMETypeInNoQuirksMode;
239 }
240
241 CSSParser::CSSParser(const CSSParserContext& context)
242     : m_context(context)
243     , m_important(false)
244     , m_id(CSSPropertyInvalid)
245     , m_styleSheet(0)
246     , m_selectorListForParseSelector(0)
247     , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
248     , m_inParseShorthand(0)
249     , m_currentShorthand(CSSPropertyInvalid)
250     , m_implicitShorthand(false)
251     , m_hasFontFaceOnlyValues(false)
252     , m_hadSyntacticallyValidCSSRule(false)
253     , m_defaultNamespace(starAtom)
254     , m_parsedTextPrefixLength(0)
255     , m_propertyRange(UINT_MAX, UINT_MAX)
256     , m_ruleSourceDataResult(0)
257     , m_parsingMode(NormalMode)
258     , m_currentCharacter(0)
259     , m_tokenStart(0)
260     , m_token(0)
261     , m_lineNumber(0)
262     , m_lastSelectorLineNumber(0)
263     , m_allowImportRules(true)
264     , m_allowNamespaceDeclarations(true)
265 {
266 #if YYDEBUG > 0
267     cssyydebug = 1;
268 #endif
269     CSSPropertySourceData::init();
270 }
271
272 CSSParser::~CSSParser()
273 {
274     clearProperties();
275
276     fastDeleteAllValues(m_floatingSelectors);
277     deleteAllValues(m_floatingSelectorVectors);
278     deleteAllValues(m_floatingValueLists);
279     deleteAllValues(m_floatingFunctions);
280 }
281
282 void CSSParserString::lower()
283 {
284     // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
285     // that can potentially change the length of the string rather than the character
286     // by character kind. If we don't need Unicode lowercasing, it would be good to
287     // simplify this function.
288
289     if (charactersAreAllASCII(characters, length)) {
290         // Fast case for all-ASCII.
291         for (int i = 0; i < length; i++)
292             characters[i] = toASCIILower(characters[i]);
293     } else {
294         for (int i = 0; i < length; i++)
295             characters[i] = Unicode::toLower(characters[i]);
296     }
297 }
298
299 void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix)
300 {
301     m_parsedTextPrefixLength = strlen(prefix);
302     int length = string.length() + m_parsedTextPrefixLength + strlen(suffix) + 1;
303
304     m_dataStart = adoptArrayPtr(new UChar[length]);
305     for (unsigned i = 0; i < m_parsedTextPrefixLength; i++)
306         m_dataStart[i] = prefix[i];
307
308     memcpy(m_dataStart.get() + m_parsedTextPrefixLength, string.characters(), string.length() * sizeof(UChar));
309
310     unsigned start = m_parsedTextPrefixLength + string.length();
311     unsigned end = start + strlen(suffix);
312     for (unsigned i = start; i < end; i++)
313         m_dataStart[i] = suffix[i - start];
314
315     m_dataStart[length - 1] = 0;
316
317     m_currentCharacter = m_tokenStart = m_dataStart.get();
318 }
319
320 void CSSParser::parseSheet(StyleSheetContents* sheet, const String& string, int startLineNumber, RuleSourceDataList* ruleSourceDataResult)
321 {
322     setStyleSheet(sheet);
323     m_defaultNamespace = starAtom; // Reset the default namespace.
324     if (ruleSourceDataResult)
325         m_currentRuleDataStack = adoptPtr(new RuleSourceDataList());
326     m_ruleSourceDataResult = ruleSourceDataResult;
327
328     m_lineNumber = startLineNumber;
329     setupParser("", string, "");
330     cssyyparse(this);
331     m_currentRuleDataStack.clear();
332     m_ruleSourceDataResult = 0;
333     m_rule = 0;
334 }
335
336 PassRefPtr<StyleRuleBase> CSSParser::parseRule(StyleSheetContents* sheet, const String& string)
337 {
338     setStyleSheet(sheet);
339     m_allowNamespaceDeclarations = false;
340     setupParser("@-webkit-rule{", string, "} ");
341     cssyyparse(this);
342     return m_rule.release();
343 }
344
345 PassRefPtr<StyleKeyframe> CSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string)
346 {
347     setStyleSheet(sheet);
348     setupParser("@-webkit-keyframe-rule{ ", string, "} ");
349     cssyyparse(this);
350     return m_keyframe.release();
351 }
352
353 static inline bool isColorPropertyID(CSSPropertyID propertyId)
354 {
355     switch (propertyId) {
356     case CSSPropertyColor:
357     case CSSPropertyBackgroundColor:
358     case CSSPropertyBorderBottomColor:
359     case CSSPropertyBorderLeftColor:
360     case CSSPropertyBorderRightColor:
361     case CSSPropertyBorderTopColor:
362     case CSSPropertyOutlineColor:
363     case CSSPropertyTextLineThroughColor:
364     case CSSPropertyTextOverlineColor:
365     case CSSPropertyTextUnderlineColor:
366     case CSSPropertyWebkitBorderAfterColor:
367     case CSSPropertyWebkitBorderBeforeColor:
368     case CSSPropertyWebkitBorderEndColor:
369     case CSSPropertyWebkitBorderStartColor:
370     case CSSPropertyWebkitColumnRuleColor:
371     case CSSPropertyWebkitTextEmphasisColor:
372     case CSSPropertyWebkitTextFillColor:
373     case CSSPropertyWebkitTextStrokeColor:
374         return true;
375     default:
376         return false;
377     }
378 }
379
380 static bool parseColorValue(StylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
381 {
382     ASSERT(!string.isEmpty());
383     bool strict = isStrictParserMode(cssParserMode);
384     if (!isColorPropertyID(propertyId))
385         return false;
386     CSSParserString cssString;
387     cssString.characters = const_cast<UChar*>(string.characters());
388     cssString.length = string.length();
389     int valueID = cssValueKeywordID(cssString);
390     bool validPrimitive = false;
391     if (valueID == CSSValueWebkitText)
392         validPrimitive = true;
393     else if (valueID == CSSValueCurrentcolor)
394         validPrimitive = true;
395     else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
396              || (valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText && !strict)) {
397         validPrimitive = true;
398     }
399
400     if (validPrimitive) {
401         RefPtr<CSSValue> value = cssValuePool().createIdentifierValue(valueID);
402         declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
403         return true;
404     }
405     RGBA32 color;
406     if (!CSSParser::fastParseColor(color, string, strict && string[0] != '#'))
407         return false;
408     RefPtr<CSSValue> value = cssValuePool().createColorValue(color);
409     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
410     return true;
411 }
412
413 static inline bool isSimpleLengthPropertyID(CSSPropertyID propertyId, bool& acceptsNegativeNumbers)
414 {
415     switch (propertyId) {
416     case CSSPropertyFontSize:
417     case CSSPropertyHeight:
418     case CSSPropertyWidth:
419     case CSSPropertyMinHeight:
420     case CSSPropertyMinWidth:
421     case CSSPropertyPaddingBottom:
422     case CSSPropertyPaddingLeft:
423     case CSSPropertyPaddingRight:
424     case CSSPropertyPaddingTop:
425     case CSSPropertyWebkitLogicalWidth:
426     case CSSPropertyWebkitLogicalHeight:
427     case CSSPropertyWebkitMinLogicalWidth:
428     case CSSPropertyWebkitMinLogicalHeight:
429     case CSSPropertyWebkitPaddingAfter:
430     case CSSPropertyWebkitPaddingBefore:
431     case CSSPropertyWebkitPaddingEnd:
432     case CSSPropertyWebkitPaddingStart:
433         acceptsNegativeNumbers = false;
434         return true;
435 #if ENABLE(CSS_EXCLUSIONS)
436     case CSSPropertyWebkitWrapMargin:
437     case CSSPropertyWebkitWrapPadding:
438         acceptsNegativeNumbers = false;
439         return RuntimeEnabledFeatures::cssExclusionsEnabled();
440 #endif
441     case CSSPropertyBottom:
442     case CSSPropertyLeft:
443     case CSSPropertyMarginBottom:
444     case CSSPropertyMarginLeft:
445     case CSSPropertyMarginRight:
446     case CSSPropertyMarginTop:
447     case CSSPropertyRight:
448     case CSSPropertyTextIndent:
449     case CSSPropertyTop:
450     case CSSPropertyWebkitMarginAfter:
451     case CSSPropertyWebkitMarginBefore:
452     case CSSPropertyWebkitMarginEnd:
453     case CSSPropertyWebkitMarginStart:
454         acceptsNegativeNumbers = true;
455         return true;
456     default:
457         return false;
458     }
459 }
460
461 template <typename CharType>
462 static inline bool parseSimpleLength(const CharType* characters, unsigned& length, CSSPrimitiveValue::UnitTypes& unit, double& number)
463 {
464     if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == 'x') {
465         length -= 2;
466         unit = CSSPrimitiveValue::CSS_PX;
467     } else if (length > 1 && characters[length - 1] == '%') {
468         length -= 1;
469         unit = CSSPrimitiveValue::CSS_PERCENTAGE;
470     }
471
472     // We rely on charactersToDouble for validation as well. The function
473     // will set "ok" to "false" if the entire passed-in character range does
474     // not represent a double.
475     bool ok;
476     number = charactersToDouble(characters, length, &ok);
477     return ok;
478 }
479
480 static bool parseSimpleLengthValue(StylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
481 {
482     ASSERT(!string.isEmpty());
483     bool acceptsNegativeNumbers;
484     if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
485         return false;
486
487     unsigned length = string.length();
488     double number;
489     CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
490
491     if (string.is8Bit()) {
492         if (!parseSimpleLength(string.characters8(), length, unit, number))
493             return false;
494     } else {
495         if (!parseSimpleLength(string.characters16(), length, unit, number))
496             return false;
497     }
498
499     if (unit == CSSPrimitiveValue::CSS_NUMBER) {
500         if (number && isStrictParserMode(cssParserMode))
501             return false;
502         unit = CSSPrimitiveValue::CSS_PX;
503     }
504     if (number < 0 && !acceptsNegativeNumbers)
505         return false;
506
507     RefPtr<CSSValue> value = cssValuePool().createValue(number, unit);
508     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
509     return true;
510 }
511
512 static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int valueID, const CSSParserContext& parserContext)
513 {
514     if (!valueID)
515         return false;
516
517     switch (propertyId) {
518     case CSSPropertyBorderCollapse: // collapse | separate | inherit
519         if (valueID == CSSValueCollapse || valueID == CSSValueSeparate)
520             return true;
521         break;
522     case CSSPropertyBorderTopStyle: // <border-style> | inherit
523     case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
524     case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
525     case CSSPropertyBorderLeftStyle:
526     case CSSPropertyWebkitBorderAfterStyle:
527     case CSSPropertyWebkitBorderBeforeStyle:
528     case CSSPropertyWebkitBorderEndStyle:
529     case CSSPropertyWebkitBorderStartStyle:
530     case CSSPropertyWebkitColumnRuleStyle:
531         if (valueID >= CSSValueNone && valueID <= CSSValueDouble)
532             return true;
533         break;
534     case CSSPropertyBoxSizing:
535          if (valueID == CSSValueBorderBox || valueID == CSSValueContentBox)
536              return true;
537          break;
538     case CSSPropertyCaptionSide: // top | bottom | left | right | inherit
539         if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom)
540             return true;
541         break;
542     case CSSPropertyClear: // none | left | right | both | inherit
543         if (valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth)
544             return true;
545         break;
546     case CSSPropertyDirection: // ltr | rtl | inherit
547         if (valueID == CSSValueLtr || valueID == CSSValueRtl)
548             return true;
549         break;
550     case CSSPropertyDisplay:
551         // inline | block | list-item | run-in | inline-block | table |
552         // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
553         // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none | inherit
554         // -webkit-flex | -webkit-inline-flex | -webkit-grid | -webkit-inline-grid
555         if ((valueID >= CSSValueInline && valueID <= CSSValueWebkitInlineBox) || valueID == CSSValueNone)
556             return true;
557 #if ENABLE(CSS3_FLEXBOX)
558         if (valueID == CSSValueWebkitFlex || valueID == CSSValueWebkitInlineFlex)
559             return true;
560 #endif
561         if (parserContext.isCSSGridLayoutEnabled && (valueID == CSSValueWebkitGrid || valueID == CSSValueWebkitInlineGrid))
562             return true;
563         break;
564
565     case CSSPropertyEmptyCells: // show | hide | inherit
566         if (valueID == CSSValueShow || valueID == CSSValueHide)
567             return true;
568         break;
569     case CSSPropertyFloat: // left | right | none | center (for buggy CSS, maps to none)
570         if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter)
571             return true;
572         break;
573     case CSSPropertyFontStyle: // normal | italic | oblique | inherit
574         if (valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique)
575             return true;
576         break;
577     case CSSPropertyImageRendering: // auto | optimizeContrast
578         if (valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast)
579             return true;
580         break;
581     case CSSPropertyListStylePosition: // inside | outside | inherit
582         if (valueID == CSSValueInside || valueID == CSSValueOutside)
583             return true;
584         break;
585     case CSSPropertyListStyleType:
586         // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
587         // for the list of supported list-style-types.
588         if ((valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone)
589             return true;
590         break;
591     case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto | inherit
592         if (valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble))
593             return true;
594         break;
595     case CSSPropertyOverflowWrap: // normal | break-word
596     case CSSPropertyWordWrap:
597         if (valueID == CSSValueNormal || valueID == CSSValueBreakWord)
598             return true;
599         break;
600     case CSSPropertyOverflowX:
601     case CSSPropertyOverflowY: // visible | hidden | scroll | auto | marquee | overlay | inherit
602         if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitMarquee)
603             return true;
604         break;
605     case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right | inherit
606     case CSSPropertyPageBreakBefore:
607     case CSSPropertyWebkitColumnBreakAfter:
608     case CSSPropertyWebkitColumnBreakBefore:
609         if (valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight)
610             return true;
611         break;
612     case CSSPropertyPageBreakInside: // avoid | auto | inherit
613     case CSSPropertyWebkitColumnBreakInside:
614         if (valueID == CSSValueAuto || valueID == CSSValueAvoid)
615             return true;
616         break;
617     case CSSPropertyPointerEvents:
618         // none | visiblePainted | visibleFill | visibleStroke | visible |
619         // painted | fill | stroke | auto | all | inherit
620         if (valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueStroke))
621             return true;
622         break;
623     case CSSPropertyPosition: // static | relative | absolute | fixed | sticky | inherit
624         if (valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed
625 #if ENABLE(CSS_STICKY_POSITION)
626             || valueID == CSSValueWebkitSticky
627 #endif
628             )
629             return true;
630         break;
631     case CSSPropertyResize: // none | both | horizontal | vertical | auto
632         if (valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto)
633             return true;
634         break;
635     case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation | inherit
636         if (valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation)
637             return true;
638         break;
639     case CSSPropertyTableLayout: // auto | fixed | inherit
640         if (valueID == CSSValueAuto || valueID == CSSValueFixed)
641             return true;
642         break;
643     case CSSPropertyTextLineThroughMode:
644     case CSSPropertyTextOverlineMode:
645     case CSSPropertyTextUnderlineMode:
646         if (valueID == CSSValueContinuous || valueID == CSSValueSkipWhiteSpace)
647             return true;
648         break;
649     case CSSPropertyTextLineThroughStyle:
650     case CSSPropertyTextOverlineStyle:
651     case CSSPropertyTextUnderlineStyle:
652         if (valueID == CSSValueNone || valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDashed || valueID == CSSValueDotDash || valueID == CSSValueDotDotDash || valueID == CSSValueWave)
653             return true;
654         break;
655     case CSSPropertyTextOverflow: // clip | ellipsis
656         if (valueID == CSSValueClip || valueID == CSSValueEllipsis)
657             return true;
658         break;
659     case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
660         if (valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision)
661             return true;
662         break;
663     case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none | inherit
664         if ((valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone)
665             return true;
666         break;
667     case CSSPropertyVisibility: // visible | hidden | collapse | inherit
668         if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse)
669             return true;
670         break;
671     case CSSPropertyWebkitAppearance:
672         if ((valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone)
673             return true;
674         break;
675     case CSSPropertyWebkitBackfaceVisibility:
676         if (valueID == CSSValueVisible || valueID == CSSValueHidden)
677             return true;
678         break;
679     case CSSPropertyWebkitBorderFit:
680         if (valueID == CSSValueBorder || valueID == CSSValueLines)
681             return true;
682         break;
683     case CSSPropertyWebkitBoxAlign:
684         if (valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline)
685             return true;
686         break;
687 #if ENABLE(CSS_BOX_DECORATION_BREAK)
688     case CSSPropertyWebkitBoxDecorationBreak:
689          if (valueID == CSSValueClone || valueID == CSSValueSlice)
690              return true;
691          break;
692 #endif
693     case CSSPropertyWebkitBoxDirection:
694         if (valueID == CSSValueNormal || valueID == CSSValueReverse)
695             return true;
696         break;
697     case CSSPropertyWebkitBoxLines:
698         if (valueID == CSSValueSingle || valueID == CSSValueMultiple)
699                 return true;
700         break;
701     case CSSPropertyWebkitBoxOrient:
702         if (valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis)
703             return true;
704         break;
705     case CSSPropertyWebkitBoxPack:
706         if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify)
707             return true;
708         break;
709     case CSSPropertyWebkitColorCorrection:
710         if (valueID == CSSValueSrgb || valueID == CSSValueDefault)
711             return true;
712         break;
713 #if ENABLE(CSS3_FLEXBOX)
714     case CSSPropertyWebkitAlignContent:
715          if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch)
716              return true;
717          break;
718     case CSSPropertyWebkitAlignItems:
719         if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
720             return true;
721         break;
722     case CSSPropertyWebkitAlignSelf:
723         if (valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
724             return true;
725         break;
726     case CSSPropertyWebkitFlexDirection:
727         if (valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse)
728             return true;
729         break;
730     case CSSPropertyWebkitFlexWrap:
731         if (valueID == CSSValueNone || valueID == CSSValueWrap || valueID == CSSValueWrapReverse)
732              return true;
733         break;
734     case CSSPropertyWebkitJustifyContent:
735         if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround)
736             return true;
737         break;
738 #endif
739     case CSSPropertyWebkitFontKerning:
740         if (valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone)
741             return true;
742         break;
743     case CSSPropertyWebkitFontSmoothing:
744         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased)
745             return true;
746         break;
747     case CSSPropertyWebkitHyphens:
748         if (valueID == CSSValueNone || valueID == CSSValueManual || valueID == CSSValueAuto)
749             return true;
750         break;
751     case CSSPropertyWebkitLineAlign:
752         if (valueID == CSSValueNone || valueID == CSSValueEdges)
753             return true;
754         break;
755     case CSSPropertyWebkitLineBreak: // normal | after-white-space
756         if (valueID == CSSValueNormal || valueID == CSSValueAfterWhiteSpace)
757             return true;
758         break;
759     case CSSPropertyWebkitLineSnap:
760         if (valueID == CSSValueNone || valueID == CSSValueBaseline || valueID == CSSValueContain)
761             return true;
762         break;
763     case CSSPropertyWebkitMarginAfterCollapse:
764     case CSSPropertyWebkitMarginBeforeCollapse:
765     case CSSPropertyWebkitMarginBottomCollapse:
766     case CSSPropertyWebkitMarginTopCollapse:
767         if (valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard)
768             return true;
769         break;
770     case CSSPropertyWebkitMarqueeDirection:
771         if (valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
772             || valueID == CSSValueUp || valueID == CSSValueAuto)
773             return true;
774         break;
775     case CSSPropertyWebkitMarqueeStyle:
776         if (valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate)
777             return true;
778         break;
779     case CSSPropertyWebkitNbspMode: // normal | space
780         if (valueID == CSSValueNormal || valueID == CSSValueSpace)
781             return true;
782         break;
783 #if ENABLE(OVERFLOW_SCROLLING)
784     case CSSPropertyWebkitOverflowScrolling:
785         if (valueID == CSSValueAuto || valueID == CSSValueTouch)
786             return true;
787         break;
788 #endif
789     case CSSPropertyWebkitPrintColorAdjust:
790         if (valueID == CSSValueExact || valueID == CSSValueEconomy)
791             return true;
792         break;
793 #if ENABLE(CSS_REGIONS)
794     case CSSPropertyWebkitRegionBreakAfter:
795     case CSSPropertyWebkitRegionBreakBefore:
796         if (parserContext.isCSSRegionsEnabled && (valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight))
797             return true;
798         break;
799     case CSSPropertyWebkitRegionBreakInside:
800         if (parserContext.isCSSRegionsEnabled && (valueID == CSSValueAuto || valueID == CSSValueAvoid))
801             return true;
802         break;
803     case CSSPropertyWebkitRegionOverflow:
804         if (parserContext.isCSSRegionsEnabled && (valueID == CSSValueAuto || valueID == CSSValueBreak))
805             return true;
806         break;
807 #endif
808     case CSSPropertyWebkitRtlOrdering:
809         if (valueID == CSSValueLogical || valueID == CSSValueVisual)
810             return true;
811         break;
812     case CSSPropertyWebkitTextCombine:
813         if (valueID == CSSValueNone || valueID == CSSValueHorizontal)
814             return true;
815         break;
816     case CSSPropertyWebkitTextEmphasisPosition:
817         if (valueID == CSSValueOver || valueID == CSSValueUnder)
818             return true;
819         break;
820     case CSSPropertyWebkitTextSecurity:
821         // disc | circle | square | none | inherit
822         if (valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone)
823             return true;
824         break;
825     case CSSPropertyWebkitTextSizeAdjust:
826         if (valueID == CSSValueAuto || valueID == CSSValueNone)
827             return true;
828         break;
829     case CSSPropertyWebkitTransformStyle:
830         if (valueID == CSSValueFlat || valueID == CSSValuePreserve3d)
831             return true;
832         break;
833     case CSSPropertyWebkitUserDrag: // auto | none | element
834         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement)
835             return true;
836         break;
837     case CSSPropertyWebkitUserModify: // read-only | read-write
838         if (valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly)
839             return true;
840         break;
841     case CSSPropertyWebkitUserSelect: // auto | none | text
842         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText)
843             return true;
844         break;
845 #if ENABLE(CSS_EXCLUSIONS)
846     case CSSPropertyWebkitWrapFlow:
847         if (!RuntimeEnabledFeatures::cssExclusionsEnabled())
848             return false;
849         if (valueID == CSSValueAuto || valueID == CSSValueBoth || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueMaximum || valueID == CSSValueClear)
850             return true;
851         break;
852     case CSSPropertyWebkitWrapThrough:
853         if (!RuntimeEnabledFeatures::cssExclusionsEnabled())
854             return false;
855         if (valueID == CSSValueWrap || valueID == CSSValueNone)
856             return true;
857         break;
858 #endif
859     case CSSPropertyWebkitWritingMode:
860         if (valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt)
861             return true;
862         break;
863     case CSSPropertyWhiteSpace: // normal | pre | nowrap | inherit
864         if (valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap)
865             return true;
866         break;
867     case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
868         if (valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord)
869             return true;
870         break;
871     default:
872         ASSERT_NOT_REACHED();
873         return false;
874     }
875     return false;
876 }
877
878 static inline bool isKeywordPropertyID(CSSPropertyID propertyId)
879 {
880     switch (propertyId) {
881     case CSSPropertyBorderBottomStyle:
882     case CSSPropertyBorderCollapse:
883     case CSSPropertyBorderLeftStyle:
884     case CSSPropertyBorderRightStyle:
885     case CSSPropertyBorderTopStyle:
886     case CSSPropertyBoxSizing:
887     case CSSPropertyCaptionSide:
888     case CSSPropertyClear:
889     case CSSPropertyDirection:
890     case CSSPropertyDisplay:
891     case CSSPropertyEmptyCells:
892     case CSSPropertyFloat:
893     case CSSPropertyFontStyle:
894     case CSSPropertyImageRendering:
895     case CSSPropertyListStylePosition:
896     case CSSPropertyListStyleType:
897     case CSSPropertyOutlineStyle:
898     case CSSPropertyOverflowWrap:
899     case CSSPropertyOverflowX:
900     case CSSPropertyOverflowY:
901     case CSSPropertyPageBreakAfter:
902     case CSSPropertyPageBreakBefore:
903     case CSSPropertyPageBreakInside:
904     case CSSPropertyPointerEvents:
905     case CSSPropertyPosition:
906     case CSSPropertyResize:
907     case CSSPropertySpeak:
908     case CSSPropertyTableLayout:
909     case CSSPropertyTextLineThroughMode:
910     case CSSPropertyTextLineThroughStyle:
911     case CSSPropertyTextOverflow:
912     case CSSPropertyTextOverlineMode:
913     case CSSPropertyTextOverlineStyle:
914     case CSSPropertyTextRendering:
915     case CSSPropertyTextTransform:
916     case CSSPropertyTextUnderlineMode:
917     case CSSPropertyTextUnderlineStyle:
918     case CSSPropertyVisibility:
919     case CSSPropertyWebkitAppearance:
920     case CSSPropertyWebkitBackfaceVisibility:
921     case CSSPropertyWebkitBorderAfterStyle:
922     case CSSPropertyWebkitBorderBeforeStyle:
923     case CSSPropertyWebkitBorderEndStyle:
924     case CSSPropertyWebkitBorderFit:
925     case CSSPropertyWebkitBorderStartStyle:
926     case CSSPropertyWebkitBoxAlign:
927 #if ENABLE(CSS_BOX_DECORATION_BREAK)
928     case CSSPropertyWebkitBoxDecorationBreak:
929 #endif
930     case CSSPropertyWebkitBoxDirection:
931     case CSSPropertyWebkitBoxLines:
932     case CSSPropertyWebkitBoxOrient:
933     case CSSPropertyWebkitBoxPack:
934     case CSSPropertyWebkitColorCorrection:
935     case CSSPropertyWebkitColumnBreakAfter:
936     case CSSPropertyWebkitColumnBreakBefore:
937     case CSSPropertyWebkitColumnBreakInside:
938     case CSSPropertyWebkitColumnRuleStyle:
939 #if ENABLE(CSS3_FLEXBOX)
940     case CSSPropertyWebkitAlignContent:
941     case CSSPropertyWebkitAlignItems:
942     case CSSPropertyWebkitAlignSelf:
943     case CSSPropertyWebkitFlexDirection:
944     case CSSPropertyWebkitFlexWrap:
945     case CSSPropertyWebkitJustifyContent:
946 #endif
947     case CSSPropertyWebkitFontKerning:
948     case CSSPropertyWebkitFontSmoothing:
949     case CSSPropertyWebkitHyphens:
950     case CSSPropertyWebkitLineAlign:
951     case CSSPropertyWebkitLineBreak:
952     case CSSPropertyWebkitLineSnap:
953     case CSSPropertyWebkitMarginAfterCollapse:
954     case CSSPropertyWebkitMarginBeforeCollapse:
955     case CSSPropertyWebkitMarginBottomCollapse:
956     case CSSPropertyWebkitMarginTopCollapse:
957     case CSSPropertyWebkitMarqueeDirection:
958     case CSSPropertyWebkitMarqueeStyle:
959     case CSSPropertyWebkitNbspMode:
960 #if ENABLE(OVERFLOW_SCROLLING)
961     case CSSPropertyWebkitOverflowScrolling:
962 #endif
963     case CSSPropertyWebkitPrintColorAdjust:
964 #if ENABLE(CSS_REGIONS)
965     case CSSPropertyWebkitRegionBreakAfter:
966     case CSSPropertyWebkitRegionBreakBefore:
967     case CSSPropertyWebkitRegionBreakInside:
968     case CSSPropertyWebkitRegionOverflow:
969 #endif
970     case CSSPropertyWebkitRtlOrdering:
971     case CSSPropertyWebkitTextCombine:
972     case CSSPropertyWebkitTextEmphasisPosition:
973     case CSSPropertyWebkitTextSecurity:
974     case CSSPropertyWebkitTextSizeAdjust:
975     case CSSPropertyWebkitTransformStyle:
976     case CSSPropertyWebkitUserDrag:
977     case CSSPropertyWebkitUserModify:
978     case CSSPropertyWebkitUserSelect:
979 #if ENABLE(CSS_EXCLUSIONS)
980     case CSSPropertyWebkitWrapFlow:
981     case CSSPropertyWebkitWrapThrough:
982 #endif
983     case CSSPropertyWebkitWritingMode:
984     case CSSPropertyWhiteSpace:
985     case CSSPropertyWordBreak:
986     case CSSPropertyWordWrap:
987         return true;
988     default:
989         return false;
990     }
991 }
992
993 static bool parseKeywordValue(StylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext)
994 {
995     ASSERT(!string.isEmpty());
996
997     if (!isKeywordPropertyID(propertyId))
998         return false;
999
1000     CSSParserString cssString;
1001     cssString.characters = const_cast<UChar*>(string.characters());
1002     cssString.length = string.length();
1003     int valueID = cssValueKeywordID(cssString);
1004
1005     if (!valueID)
1006         return false;
1007
1008     RefPtr<CSSValue> value;
1009     if (valueID == CSSValueInherit)
1010         value = cssValuePool().createInheritedValue();
1011     else if (valueID == CSSValueInitial)
1012         value = cssValuePool().createExplicitInitialValue();
1013     else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext))
1014         value = cssValuePool().createIdentifierValue(valueID);
1015     else
1016         return false;
1017
1018     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
1019     return true;
1020 }
1021
1022 template <typename CharType>
1023 static bool parseTransformArguments(WebKitCSSTransformValue* transformValue, CharType* characters, unsigned length, unsigned start, unsigned expectedCount)
1024 {
1025     while (expectedCount) {
1026         size_t end = WTF::find(characters, length, expectedCount == 1 ? ')' : ',', start);
1027         if (end == notFound || (expectedCount == 1 && end != length - 1))
1028             return false;
1029         unsigned argumentLength = end - start;
1030         CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
1031         double number;
1032         if (!parseSimpleLength(characters + start, argumentLength, unit, number))
1033             return false;
1034         if (unit != CSSPrimitiveValue::CSS_PX && (number || unit != CSSPrimitiveValue::CSS_NUMBER))
1035             return false;
1036         transformValue->append(cssValuePool().createValue(number, unit));
1037         start = end + 1;
1038         --expectedCount;
1039     }
1040     return true;
1041 }
1042
1043 static bool parseTransformValue(StylePropertySet* properties, CSSPropertyID propertyID, const String& string, bool important)
1044 {
1045     if (propertyID != CSSPropertyWebkitTransform)
1046         return false;
1047     static const unsigned shortestValidTransformStringLength = 12;
1048     static const unsigned likelyMultipartTransformStringLengthCutoff = 32;
1049     if (string.length() < shortestValidTransformStringLength || string.length() > likelyMultipartTransformStringLengthCutoff)
1050         return false;
1051     if (!string.startsWith("translate", false))
1052         return false;
1053     UChar c9 = toASCIILower(string[9]);
1054     UChar c10 = toASCIILower(string[10]);
1055
1056     WebKitCSSTransformValue::TransformOperationType transformType;
1057     unsigned expectedArgumentCount = 1;
1058     unsigned argumentStart = 11;
1059     if (c9 == 'x' && c10 == '(')
1060         transformType = WebKitCSSTransformValue::TranslateXTransformOperation;
1061     else if (c9 == 'y' && c10 == '(')
1062         transformType = WebKitCSSTransformValue::TranslateYTransformOperation;
1063     else if (c9 == 'z' && c10 == '(')
1064         transformType = WebKitCSSTransformValue::TranslateZTransformOperation;
1065     else if (c9 == '(') {
1066         transformType = WebKitCSSTransformValue::TranslateTransformOperation;
1067         expectedArgumentCount = 2;
1068         argumentStart = 10;
1069     } else if (c9 == '3' && c10 == 'd' && string[11] == '(') {
1070         transformType = WebKitCSSTransformValue::Translate3DTransformOperation;
1071         expectedArgumentCount = 3;
1072         argumentStart = 12;
1073     } else
1074         return false;
1075
1076     RefPtr<WebKitCSSTransformValue> transformValue = WebKitCSSTransformValue::create(transformType);
1077     bool success;
1078     if (string.is8Bit())
1079         success = parseTransformArguments(transformValue.get(), string.characters8(), string.length(), argumentStart, expectedArgumentCount);
1080     else
1081         success = parseTransformArguments(transformValue.get(), string.characters16(), string.length(), argumentStart, expectedArgumentCount);
1082     if (!success)
1083         return false;
1084     RefPtr<CSSValueList> result = CSSValueList::createSpaceSeparated();
1085     result->append(transformValue.release());
1086     properties->addParsedProperty(CSSProperty(CSSPropertyWebkitTransform, result.release(), important));
1087     return true;
1088 }
1089
1090 PassRefPtr<CSSValueList> CSSParser::parseFontFaceValue(const AtomicString& string)
1091 {
1092     if (string.isEmpty())
1093         return 0;
1094     RefPtr<StylePropertySet> dummyStyle = StylePropertySet::create();
1095     if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, CSSQuirksMode, 0))
1096         return 0;
1097     return static_pointer_cast<CSSValueList>(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily));
1098 }
1099
1100 #if ENABLE(CSS_VARIABLES)
1101 bool CSSParser::parseValue(StylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, Document* document)
1102 {
1103     ASSERT(!string.isEmpty());
1104
1105     CSSParserContext context(document);
1106
1107     if (parseSimpleLengthValue(declaration, propertyID, string, important, context.mode))
1108         return true;
1109     if (parseColorValue(declaration, propertyID, string, important, context.mode))
1110         return true;
1111     if (parseKeywordValue(declaration, propertyID, string, important, context))
1112         return true;
1113
1114     CSSParser parser(context);
1115     return parser.parseValue(declaration, propertyID, string, important, static_cast<StyleSheetContents*>(0));
1116 }
1117 #endif
1118
1119 bool CSSParser::parseValue(StylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, StyleSheetContents* contextStyleSheet)
1120 {
1121     ASSERT(!string.isEmpty());
1122     if (parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode))
1123         return true;
1124     if (parseColorValue(declaration, propertyID, string, important, cssParserMode))
1125         return true;
1126     if (parseKeywordValue(declaration, propertyID, string, important, contextStyleSheet->parserContext()))
1127         return true;
1128     if (parseTransformValue(declaration, propertyID, string, important))
1129         return true;
1130
1131     CSSParserContext context(cssParserMode);
1132     if (contextStyleSheet) {
1133         context = contextStyleSheet->parserContext();
1134         context.mode = cssParserMode;
1135     }
1136     CSSParser parser(context);
1137     return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet);
1138 }
1139
1140 bool CSSParser::parseValue(StylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, StyleSheetContents* contextStyleSheet)
1141 {
1142     setStyleSheet(contextStyleSheet);
1143
1144     setupParser("@-webkit-value{", string, "} ");
1145
1146     m_id = propertyID;
1147     m_important = important;
1148
1149     cssyyparse(this);
1150
1151     m_rule = 0;
1152
1153     bool ok = false;
1154     if (m_hasFontFaceOnlyValues)
1155         deleteFontFaceOnlyValues();
1156     if (!m_parsedProperties.isEmpty()) {
1157         ok = true;
1158         declaration->addParsedProperties(m_parsedProperties);
1159         clearProperties();
1160     }
1161
1162     return ok;
1163 }
1164
1165 // The color will only be changed when string contains a valid CSS color, so callers
1166 // can set it to a default color and ignore the boolean result.
1167 bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict)
1168 {
1169     // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
1170     if (fastParseColor(color, string, strict))
1171         return true;
1172
1173     CSSParser parser(CSSStrictMode);
1174
1175     // In case the fast-path parser didn't understand the color, try the full parser.
1176     if (!parser.parseColor(string))
1177         return false;
1178
1179     CSSValue* value = parser.m_parsedProperties.first().value();
1180     if (!value->isPrimitiveValue())
1181         return false;
1182
1183     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
1184     if (!primitiveValue->isRGBColor())
1185         return false;
1186
1187     color = primitiveValue->getRGBA32Value();
1188     return true;
1189 }
1190
1191 bool CSSParser::parseColor(const String& string)
1192 {
1193     setupParser("@-webkit-decls{color:", string, "} ");
1194     cssyyparse(this);
1195     m_rule = 0;
1196
1197     return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor;
1198 }
1199
1200 bool CSSParser::parseSystemColor(RGBA32& color, const String& string, Document* document)
1201 {
1202     if (!document || !document->page())
1203         return false;
1204
1205     CSSParserString cssColor;
1206     cssColor.characters = const_cast<UChar*>(string.characters());
1207     cssColor.length = string.length();
1208     int id = cssValueKeywordID(cssColor);
1209     if (id <= 0)
1210         return false;
1211
1212     color = document->page()->theme()->systemColor(id).rgb();
1213     return true;
1214 }
1215
1216 void CSSParser::parseSelector(const String& string, CSSSelectorList& selectorList)
1217 {
1218     m_selectorListForParseSelector = &selectorList;
1219
1220     setupParser("@-webkit-selector{", string, "}");
1221
1222     cssyyparse(this);
1223
1224     m_selectorListForParseSelector = 0;
1225 }
1226
1227 bool CSSParser::parseDeclaration(StylePropertySet* declaration, const String& string, PassRefPtr<CSSRuleSourceData> prpRuleSourceData, StyleSheetContents* contextStyleSheet)
1228 {
1229     // Length of the "@-webkit-decls{" prefix.
1230     static const unsigned prefixLength = 15;
1231
1232     setStyleSheet(contextStyleSheet);
1233
1234     RefPtr<CSSRuleSourceData> ruleSourceData = prpRuleSourceData;
1235     if (ruleSourceData) {
1236         m_currentRuleDataStack = adoptPtr(new RuleSourceDataList());
1237         m_currentRuleDataStack->append(ruleSourceData);
1238     }
1239
1240     setupParser("@-webkit-decls{", string, "} ");
1241     cssyyparse(this);
1242     m_rule = 0;
1243
1244     bool ok = false;
1245     if (m_hasFontFaceOnlyValues)
1246         deleteFontFaceOnlyValues();
1247     if (!m_parsedProperties.isEmpty()) {
1248         ok = true;
1249         declaration->addParsedProperties(m_parsedProperties);
1250         clearProperties();
1251     }
1252
1253     if (ruleSourceData) {
1254         ASSERT(m_currentRuleDataStack->size() == 1);
1255         ruleSourceData->ruleBodyRange.start = 0;
1256         ruleSourceData->ruleBodyRange.end = string.length();
1257         for (size_t i = 0, size = ruleSourceData->styleSourceData->propertyData.size(); i < size; ++i) {
1258             CSSPropertySourceData& propertyData = ruleSourceData->styleSourceData->propertyData.at(i);
1259             propertyData.range.start -= prefixLength;
1260             propertyData.range.end -= prefixLength;
1261         }
1262
1263         fixUnparsedPropertyRanges(ruleSourceData.get());
1264         m_currentRuleDataStack.clear();
1265     }
1266
1267     return ok;
1268 }
1269
1270 PassOwnPtr<MediaQuery> CSSParser::parseMediaQuery(const String& string)
1271 {
1272     if (string.isEmpty())
1273         return nullptr;
1274
1275     ASSERT(!m_mediaQuery);
1276
1277     // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
1278     // instead insert one " " (which is WHITESPACE in CSSGrammar.y)
1279     setupParser("@-webkit-mediaquery ", string, "} ");
1280     cssyyparse(this);
1281
1282     return m_mediaQuery.release();
1283 }
1284
1285 #if ENABLE(CSS_VARIABLES)
1286 static inline void filterProperties(bool important, const CSSParser::ParsedPropertyVector& input, Vector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties, HashSet<AtomicString>& seenVariables)
1287 #else
1288 static inline void filterProperties(bool important, const CSSParser::ParsedPropertyVector& input, Vector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties)
1289 #endif
1290 {
1291     // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found.
1292     for (int i = input.size() - 1; i >= 0; --i) {
1293         const CSSProperty& property = input[i];
1294         if (property.isImportant() != important)
1295             continue;
1296 #if ENABLE(CSS_VARIABLES)
1297         if (property.id() == CSSPropertyVariable) {
1298             const AtomicString& name = static_cast<CSSVariableValue*>(property.value())->name();
1299             if (seenVariables.contains(name))
1300                 continue;
1301             seenVariables.add(name);
1302             output[--unusedEntries] = property;
1303             continue;
1304         }
1305 #endif
1306         const unsigned propertyIDIndex = property.id() - firstCSSProperty;
1307         if (seenProperties.get(propertyIDIndex))
1308             continue;
1309         seenProperties.set(propertyIDIndex);
1310         output[--unusedEntries] = property;
1311     }
1312 }
1313
1314 PassRefPtr<StylePropertySet> CSSParser::createStylePropertySet()
1315 {
1316     BitArray<numCSSProperties> seenProperties;
1317     size_t unusedEntries = m_parsedProperties.size();
1318     Vector<CSSProperty, 256> results(unusedEntries);
1319
1320     // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found.
1321 #if ENABLE(CSS_VARIABLES)
1322     HashSet<AtomicString> seenVariables;
1323     filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties, seenVariables);
1324     filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties, seenVariables);
1325 #else
1326     filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties);
1327     filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties);
1328 #endif
1329     if (unusedEntries)
1330         results.remove(0, unusedEntries);
1331
1332     return StylePropertySet::createImmutable(results.data(), results.size(), m_context.mode);
1333 }
1334
1335 void CSSParser::addProperty(CSSPropertyID propId, PassRefPtr<CSSValue> value, bool important, bool implicit)
1336 {
1337     m_parsedProperties.append(CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand || implicit));
1338 }
1339
1340 void CSSParser::rollbackLastProperties(int num)
1341 {
1342     ASSERT(num >= 0);
1343     ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num));
1344     m_parsedProperties.shrink(m_parsedProperties.size() - num);
1345 }
1346
1347 void CSSParser::clearProperties()
1348 {
1349     m_parsedProperties.clear();
1350     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1351     m_hasFontFaceOnlyValues = false;
1352 }
1353
1354 void CSSParser::setStyleSheet(StyleSheetContents* styleSheet)
1355 {
1356     m_styleSheet = styleSheet;
1357 }
1358
1359 KURL CSSParser::completeURL(const CSSParserContext& context, const String& url)
1360 {
1361     if (url.isNull())
1362         return KURL();
1363     if (context.charset.isEmpty())
1364         return KURL(context.baseURL, url);
1365     return KURL(context.baseURL, url, context.charset);
1366 }
1367
1368 KURL CSSParser::completeURL(const String& url) const
1369 {
1370     return completeURL(m_context, url);
1371 }
1372
1373 bool CSSParser::validCalculationUnit(CSSParserValue* value, Units unitflags)
1374 {
1375     bool mustBeNonNegative = unitflags & FNonNeg;
1376
1377     if (!parseCalculation(value, mustBeNonNegative ? CalculationRangeNonNegative : CalculationRangeAll))
1378         return false;
1379
1380     bool b = false;
1381     switch (m_parsedCalculation->category()) {
1382     case CalcLength:
1383         b = (unitflags & FLength);
1384         break;
1385     case CalcPercent:
1386         b = (unitflags & FPercent);
1387         if (b && mustBeNonNegative && m_parsedCalculation->isNegative())
1388             b = false;
1389         break;
1390     case CalcNumber:
1391         b = (unitflags & FNumber);
1392         if (!b && (unitflags & FInteger) && m_parsedCalculation->isInt())
1393             b = true;
1394         if (b && mustBeNonNegative && m_parsedCalculation->isNegative())
1395             b = false;
1396         break;
1397     case CalcPercentLength:
1398         b = (unitflags & FPercent) && (unitflags & FLength);
1399         break;
1400     case CalcPercentNumber:
1401         b = (unitflags & FPercent) && (unitflags & FNumber);
1402         break;
1403     case CalcOther:
1404         break;
1405     }
1406     if (!b)
1407         m_parsedCalculation.release();
1408     return b;    
1409 }
1410
1411 inline bool CSSParser::shouldAcceptUnitLessValues(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode)
1412 {
1413     // Qirks mode and svg presentation attributes accept unit less values.
1414     return (unitflags & (FLength | FAngle | FTime)) && (!value->fValue || cssParserMode == CSSQuirksMode || cssParserMode == SVGAttributeMode);
1415 }
1416
1417 bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode)
1418 {
1419     if (isCalculation(value))
1420         return validCalculationUnit(value, unitflags);
1421         
1422     bool b = false;
1423     switch (value->unit) {
1424 #if ENABLE(CSS_VARIABLES)
1425     case CSSPrimitiveValue::CSS_VARIABLE_NAME:
1426         // Variables are checked at the point they are dereferenced because unit type is not available here.
1427         b = true;
1428         break;
1429 #endif
1430     case CSSPrimitiveValue::CSS_NUMBER:
1431         b = (unitflags & FNumber);
1432         if (!b && shouldAcceptUnitLessValues(value, unitflags, cssParserMode)) {
1433             value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX :
1434                           ((unitflags & FAngle) ? CSSPrimitiveValue::CSS_DEG : CSSPrimitiveValue::CSS_MS);
1435             b = true;
1436         }
1437         if (!b && (unitflags & FInteger) && value->isInt)
1438             b = true;
1439         break;
1440     case CSSPrimitiveValue::CSS_PERCENTAGE:
1441         b = (unitflags & FPercent);
1442         break;
1443     case CSSParserValue::Q_EMS:
1444     case CSSPrimitiveValue::CSS_EMS:
1445     case CSSPrimitiveValue::CSS_REMS:
1446     case CSSPrimitiveValue::CSS_EXS:
1447     case CSSPrimitiveValue::CSS_PX:
1448     case CSSPrimitiveValue::CSS_CM:
1449     case CSSPrimitiveValue::CSS_MM:
1450     case CSSPrimitiveValue::CSS_IN:
1451     case CSSPrimitiveValue::CSS_PT:
1452     case CSSPrimitiveValue::CSS_PC:
1453     case CSSPrimitiveValue::CSS_VW:
1454     case CSSPrimitiveValue::CSS_VH:
1455     case CSSPrimitiveValue::CSS_VMIN:
1456         b = (unitflags & FLength);
1457         break;
1458 #if ENABLE(TIZEN_MEDIA_QUERY)
1459     case CSSPrimitiveValue::CSS_DPCM:
1460         b = (unitflags & FLength);
1461         value->unit = CSSPrimitiveValue::CSS_DPCM;
1462         break;
1463 #endif
1464     case CSSPrimitiveValue::CSS_MS:
1465     case CSSPrimitiveValue::CSS_S:
1466         b = (unitflags & FTime);
1467         break;
1468     case CSSPrimitiveValue::CSS_DEG:
1469     case CSSPrimitiveValue::CSS_RAD:
1470     case CSSPrimitiveValue::CSS_GRAD:
1471     case CSSPrimitiveValue::CSS_TURN:
1472         b = (unitflags & FAngle);
1473         break;
1474 #if ENABLE(CSS_IMAGE_RESOLUTION)
1475     case CSSPrimitiveValue::CSS_DPPX:
1476     case CSSPrimitiveValue::CSS_DPI:
1477     case CSSPrimitiveValue::CSS_DPCM:
1478         b = (unitflags & FResolution);
1479         break;
1480 #endif
1481     case CSSPrimitiveValue::CSS_HZ:
1482     case CSSPrimitiveValue::CSS_KHZ:
1483     case CSSPrimitiveValue::CSS_DIMENSION:
1484     default:
1485         break;
1486     }
1487     if (b && unitflags & FNonNeg && value->fValue < 0)
1488         b = false;
1489     return b;
1490 }
1491
1492 inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(CSSParserValue* value)
1493 {
1494 #if ENABLE(CSS_VARIABLES)
1495     if (value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME)
1496         return CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_VARIABLE_NAME);
1497 #endif
1498
1499     if (m_parsedCalculation) {
1500         ASSERT(isCalculation(value));
1501         return CSSPrimitiveValue::create(m_parsedCalculation.release());
1502     }
1503                
1504 #if ENABLE(CSS_IMAGE_RESOLUTION)
1505     ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1506            || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
1507            || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN)
1508            || (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM));
1509 #else
1510     ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1511            || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
1512            || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN));
1513 #endif
1514     return cssValuePool().createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit));
1515 }
1516
1517 inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveStringValue(CSSParserValue* value)
1518 {
1519     ASSERT(value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT);
1520     return cssValuePool().createValue(value->string, CSSPrimitiveValue::CSS_STRING);
1521 }
1522
1523 static int unitFromString(CSSParserValue* value)
1524 {
1525     if (value->unit != CSSPrimitiveValue::CSS_IDENT || value->id)
1526         return 0;
1527
1528     if (equal(value->string, "em"))
1529         return CSSPrimitiveValue::CSS_EMS;
1530     if (equal(value->string, "rem"))
1531         return CSSPrimitiveValue::CSS_REMS;
1532     if (equal(value->string, "ex"))
1533         return CSSPrimitiveValue::CSS_EXS;
1534     if (equal(value->string, "px"))
1535         return CSSPrimitiveValue::CSS_PX;
1536     if (equal(value->string, "cm"))
1537         return CSSPrimitiveValue::CSS_CM;
1538     if (equal(value->string, "mm"))
1539         return CSSPrimitiveValue::CSS_MM;
1540     if (equal(value->string, "in"))
1541         return CSSPrimitiveValue::CSS_IN;
1542     if (equal(value->string, "pt"))
1543         return CSSPrimitiveValue::CSS_PT;
1544     if (equal(value->string, "pc"))
1545         return CSSPrimitiveValue::CSS_PC;
1546     if (equal(value->string, "deg"))
1547         return CSSPrimitiveValue::CSS_DEG;
1548     if (equal(value->string, "rad"))
1549         return CSSPrimitiveValue::CSS_RAD;
1550     if (equal(value->string, "grad"))
1551         return CSSPrimitiveValue::CSS_GRAD;
1552     if (equal(value->string, "turn"))
1553         return CSSPrimitiveValue::CSS_TURN;
1554     if (equal(value->string, "ms"))
1555         return CSSPrimitiveValue::CSS_MS;
1556     if (equal(value->string, "s"))
1557         return CSSPrimitiveValue::CSS_S;
1558     if (equal(value->string, "Hz"))
1559         return CSSPrimitiveValue::CSS_HZ;
1560     if (equal(value->string, "kHz"))
1561         return CSSPrimitiveValue::CSS_KHZ;
1562     if (equal(value->string, "vw"))
1563         return CSSPrimitiveValue::CSS_VW;
1564     if (equal(value->string, "vh"))
1565         return CSSPrimitiveValue::CSS_VH;
1566     if (equal(value->string, "vmin"))
1567         return CSSPrimitiveValue::CSS_VMIN;
1568 #if ENABLE(CSS_IMAGE_RESOLUTION)
1569     if (equal(value->string, "dppx"))
1570         return CSSPrimitiveValue::CSS_DPPX;
1571     if (equal(value->string, "dpi"))
1572         return CSSPrimitiveValue::CSS_DPI;
1573     if (equal(value->string, "dpcm"))
1574         return CSSPrimitiveValue::CSS_DPCM;
1575 #endif
1576
1577     return 0;
1578 }
1579
1580 static inline bool isComma(CSSParserValue* value)
1581
1582     return value && value->unit == CSSParserValue::Operator && value->iValue == ','; 
1583 }
1584
1585 bool CSSParser::validWidth(CSSParserValue* value)
1586 {
1587     int id = value->id;
1588     if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic || id == CSSValueWebkitMinContent || id == CSSValueWebkitMaxContent || id == CSSValueWebkitFillAvailable || id == CSSValueWebkitFitContent)
1589         return true;
1590     return !id && validUnit(value, FLength | FPercent | FNonNeg);
1591 }
1592
1593 // FIXME: Combine this with validWidth when we support fit-content, et al, for heights.
1594 bool CSSParser::validHeight(CSSParserValue* value)
1595 {
1596     int id = value->id;
1597     if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
1598         return true;
1599     return !id && validUnit(value, FLength | FPercent | FNonNeg);
1600 }
1601
1602 void CSSParser::checkForOrphanedUnits()
1603 {
1604     if (inStrictMode() || inShorthand())
1605         return;
1606
1607     // The purpose of this code is to implement the WinIE quirk that allows unit types to be separated from their numeric values
1608     // 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.
1609     CSSParserValue* numericVal = 0;
1610     unsigned size = m_valueList->size();
1611     for (unsigned i = 0; i < size; i++) {
1612         CSSParserValue* value = m_valueList->valueAt(i);
1613
1614         if (numericVal) {
1615             // Change the unit type of the numeric val to match.
1616             int unit = unitFromString(value);
1617             if (unit) {
1618                 numericVal->unit = unit;
1619                 numericVal = 0;
1620
1621                 // Now delete the bogus unit value.
1622                 m_valueList->deleteValueAt(i);
1623                 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).
1624                 size--;
1625                 continue;
1626             }
1627         }
1628
1629         numericVal = (value->unit == CSSPrimitiveValue::CSS_NUMBER) ? value : 0;
1630     }
1631 }
1632
1633 inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(int identifier, CSSParserValue* value)
1634 {
1635     if (identifier)
1636         return cssValuePool().createIdentifierValue(identifier);
1637     if (value->unit == CSSPrimitiveValue::CSS_STRING)
1638         return createPrimitiveStringValue(value);
1639     if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1640         return createPrimitiveNumericValue(value);
1641     if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
1642         return createPrimitiveNumericValue(value);
1643     if (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN)
1644         return createPrimitiveNumericValue(value);
1645 #if ENABLE(CSS_IMAGE_RESOLUTION)
1646     if (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM)
1647         return createPrimitiveNumericValue(value);
1648 #endif
1649     if (value->unit >= CSSParserValue::Q_EMS)
1650         return CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS);
1651     if (isCalculation(value))
1652         return CSSPrimitiveValue::create(m_parsedCalculation.release());
1653
1654     return 0;
1655 }
1656
1657 bool CSSParser::parseValue(CSSPropertyID propId, bool important)
1658 {
1659     if (!m_valueList)
1660         return false;
1661
1662     CSSParserValue* value = m_valueList->current();
1663
1664     if (!value)
1665         return false;
1666
1667     // Note: m_parsedCalculation is used to pass the calc value to validUnit and then cleared at the end of this function.
1668     // FIXME: This is to avoid having to pass parsedCalc to all validUnit callers.
1669     ASSERT(!m_parsedCalculation);
1670     
1671     int id = value->id;
1672
1673     // In quirks mode, we will look for units that have been incorrectly separated from the number they belong to
1674     // by a space.  We go ahead and associate the unit with the number even though it is invalid CSS.
1675     checkForOrphanedUnits();
1676
1677     int num = inShorthand() ? 1 : m_valueList->size();
1678
1679     if (id == CSSValueInherit) {
1680         if (num != 1)
1681             return false;
1682         addProperty(propId, cssValuePool().createInheritedValue(), important);
1683         return true;
1684     }
1685     else if (id == CSSValueInitial) {
1686         if (num != 1)
1687             return false;
1688         addProperty(propId, cssValuePool().createExplicitInitialValue(), important);
1689         return true;
1690     }
1691
1692 #if ENABLE(CSS_VARIABLES)
1693     if (!id && value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME && num == 1) {
1694         addProperty(propId, CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_VARIABLE_NAME), important);
1695         m_valueList->next();
1696         return true;
1697     }
1698     ASSERT(propId != CSSPropertyVariable);
1699 #endif
1700
1701     if (isKeywordPropertyID(propId)) {
1702         if (!isValidKeywordPropertyAndValue(propId, id, m_context))
1703             return false;
1704         if (m_valueList->next() && !inShorthand())
1705             return false;
1706         addProperty(propId, cssValuePool().createIdentifierValue(id), important);
1707         return true;
1708     }
1709
1710     bool validPrimitive = false;
1711     RefPtr<CSSValue> parsedValue;
1712
1713     switch (propId) {
1714     case CSSPropertySize:                 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
1715         return parseSize(propId, important);
1716
1717     case CSSPropertyQuotes:               // [<string> <string>]+ | none | inherit
1718         if (id)
1719             validPrimitive = true;
1720         else
1721             return parseQuotes(propId, important);
1722         break;
1723     case CSSPropertyUnicodeBidi: // normal | embed | (bidi-override || isolate) | plaintext | inherit
1724         if (id == CSSValueNormal
1725             || id == CSSValueEmbed
1726             || id == CSSValueWebkitPlaintext)
1727             validPrimitive = true;
1728         else {
1729             RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
1730             bool isValid = true;
1731             while (isValid && value) {
1732                 switch (value->id) {
1733                 case CSSValueBidiOverride:
1734                 case CSSValueWebkitIsolate:
1735                     list->append(cssValuePool().createIdentifierValue(value->id));
1736                     break;
1737                 default:
1738                     isValid = false;
1739                 }
1740                 value = m_valueList->next();
1741             }
1742             if (list->length() && isValid) {
1743                 parsedValue = list.release();
1744                 m_valueList->next();
1745             }
1746         }
1747         break;
1748
1749     case CSSPropertyContent:              // [ <string> | <uri> | <counter> | attr(X) | open-quote |
1750         // close-quote | no-open-quote | no-close-quote ]+ | inherit
1751         return parseContent(propId, important);
1752
1753     case CSSPropertyClip:                 // <shape> | auto | inherit
1754         if (id == CSSValueAuto)
1755             validPrimitive = true;
1756         else if (value->unit == CSSParserValue::Function)
1757             return parseClipShape(propId, important);
1758         break;
1759
1760     /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
1761      * correctly and allows optimization in WebCore::applyRule(..)
1762      */
1763     case CSSPropertyOverflow: {
1764         ShorthandScope scope(this, propId);
1765         if (num != 1 || !parseValue(CSSPropertyOverflowX, important))
1766             return false;
1767         CSSValue* value = m_parsedProperties.last().value();
1768         addProperty(CSSPropertyOverflowY, value, important);
1769         return true;
1770     }
1771
1772     case CSSPropertyTextAlign:
1773         // left | right | center | justify | -webkit-left | -webkit-right | -webkit-center | -webkit-match-parent
1774         // | start | end | <string> | inherit | -webkit-auto (converted to start)
1775         if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd
1776             || value->unit == CSSPrimitiveValue::CSS_STRING)
1777             validPrimitive = true;
1778         break;
1779
1780     case CSSPropertyFontWeight:  { // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
1781         if (m_valueList->size() != 1)
1782             return false;
1783         return parseFontWeight(important);
1784     }
1785     case CSSPropertyBorderSpacing: {
1786         if (num == 1) {
1787             ShorthandScope scope(this, CSSPropertyBorderSpacing);
1788             if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important))
1789                 return false;
1790             CSSValue* value = m_parsedProperties.last().value();
1791             addProperty(CSSPropertyWebkitBorderVerticalSpacing, value, important);
1792             return true;
1793         }
1794         else if (num == 2) {
1795             ShorthandScope scope(this, CSSPropertyBorderSpacing);
1796             if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important) || !parseValue(CSSPropertyWebkitBorderVerticalSpacing, important))
1797                 return false;
1798             return true;
1799         }
1800         return false;
1801     }
1802     case CSSPropertyWebkitBorderHorizontalSpacing:
1803     case CSSPropertyWebkitBorderVerticalSpacing:
1804         validPrimitive = validUnit(value, FLength | FNonNeg);
1805         break;
1806     case CSSPropertyOutlineColor:        // <color> | invert | inherit
1807         // Outline color has "invert" as additional keyword.
1808         // Also, we want to allow the special focus color even in strict parsing mode.
1809         if (id == CSSValueInvert || id == CSSValueWebkitFocusRingColor) {
1810             validPrimitive = true;
1811             break;
1812         }
1813         /* nobreak */
1814     case CSSPropertyBackgroundColor: // <color> | inherit
1815     case CSSPropertyBorderTopColor: // <color> | inherit
1816     case CSSPropertyBorderRightColor:
1817     case CSSPropertyBorderBottomColor:
1818     case CSSPropertyBorderLeftColor:
1819     case CSSPropertyWebkitBorderStartColor:
1820     case CSSPropertyWebkitBorderEndColor:
1821     case CSSPropertyWebkitBorderBeforeColor:
1822     case CSSPropertyWebkitBorderAfterColor:
1823     case CSSPropertyColor: // <color> | inherit
1824     case CSSPropertyTextLineThroughColor: // CSS3 text decoration colors
1825     case CSSPropertyTextUnderlineColor:
1826     case CSSPropertyTextOverlineColor:
1827     case CSSPropertyWebkitColumnRuleColor:
1828     case CSSPropertyWebkitTextEmphasisColor:
1829     case CSSPropertyWebkitTextFillColor:
1830     case CSSPropertyWebkitTextStrokeColor:
1831         if (id == CSSValueWebkitText)
1832             validPrimitive = true; // Always allow this, even when strict parsing is on,
1833                                     // since we use this in our UA sheets.
1834         else if (id == CSSValueCurrentcolor)
1835             validPrimitive = true;
1836         else if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu ||
1837              (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && inQuirksMode())) {
1838             validPrimitive = true;
1839         } else {
1840             parsedValue = parseColor();
1841             if (parsedValue)
1842                 m_valueList->next();
1843         }
1844         break;
1845
1846 #if ENABLE(TIZEN_CSS3_TEXT)
1847     case CSSPropertyWebkitTextAlignLast:
1848         // auto | start | end | left | right | center | justify
1849         if ((id >= CSSValueLeft && id <= CSSValueJustify) || id == CSSValueStart || id == CSSValueEnd || id == CSSValueAuto)
1850             validPrimitive = true;
1851         break;
1852 #endif // TIZEN_CSS3_TEXT
1853
1854     case CSSPropertyCursor: {
1855         // [<uri>,]*  [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
1856         // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize |
1857         // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help |
1858         // vertical-text | cell | context-menu | alias | copy | no-drop | not-allowed | -webkit-zoom-in
1859         // -webkit-zoom-out | all-scroll | -webkit-grab | -webkit-grabbing ] ] | inherit
1860         RefPtr<CSSValueList> list;
1861         while (value && value->unit == CSSPrimitiveValue::CSS_URI) {
1862             if (!list)
1863                 list = CSSValueList::createCommaSeparated();
1864             String uri = value->string;
1865             Vector<int> coords;
1866             value = m_valueList->next();
1867             while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) {
1868                 coords.append(int(value->fValue));
1869                 value = m_valueList->next();
1870             }
1871             IntPoint hotSpot(-1, -1);
1872             int nrcoords = coords.size();
1873             if (nrcoords > 0 && nrcoords != 2)
1874                 return false;
1875             if (nrcoords == 2)
1876                 hotSpot = IntPoint(coords[0], coords[1]);
1877
1878             if (!uri.isNull())
1879                 list->append(CSSCursorImageValue::create(completeURL(uri), hotSpot));
1880
1881             if ((inStrictMode() && !value) || (value && !(value->unit == CSSParserValue::Operator && value->iValue == ',')))
1882                 return false;
1883             value = m_valueList->next(); // comma
1884         }
1885         if (list) {
1886             if (!value) { // no value after url list (MSIE 5 compatibility)
1887                 if (list->length() != 1)
1888                     return false;
1889             } else if (inQuirksMode() && value->id == CSSValueHand) // MSIE 5 compatibility :/
1890                 list->append(cssValuePool().createIdentifierValue(CSSValuePointer));
1891             else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)
1892                 list->append(cssValuePool().createIdentifierValue(value->id));
1893             m_valueList->next();
1894             parsedValue = list.release();
1895             break;
1896         } else if (value) {
1897             id = value->id;
1898             if (inQuirksMode() && value->id == CSSValueHand) { // MSIE 5 compatibility :/
1899                 id = CSSValuePointer;
1900                 validPrimitive = true;
1901             } else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)
1902                 validPrimitive = true;
1903         } else {
1904             ASSERT_NOT_REACHED();
1905             return false;
1906         }
1907         break;
1908     }
1909
1910     case CSSPropertyBackgroundAttachment:
1911     case CSSPropertyBackgroundClip:
1912     case CSSPropertyWebkitBackgroundClip:
1913     case CSSPropertyWebkitBackgroundComposite:
1914     case CSSPropertyBackgroundImage:
1915     case CSSPropertyBackgroundOrigin:
1916     case CSSPropertyWebkitBackgroundOrigin:
1917     case CSSPropertyBackgroundPosition:
1918     case CSSPropertyBackgroundPositionX:
1919     case CSSPropertyBackgroundPositionY:
1920     case CSSPropertyBackgroundSize:
1921     case CSSPropertyWebkitBackgroundSize:
1922     case CSSPropertyBackgroundRepeat:
1923     case CSSPropertyBackgroundRepeatX:
1924     case CSSPropertyBackgroundRepeatY:
1925     case CSSPropertyWebkitMaskAttachment:
1926     case CSSPropertyWebkitMaskClip:
1927     case CSSPropertyWebkitMaskComposite:
1928     case CSSPropertyWebkitMaskImage:
1929     case CSSPropertyWebkitMaskOrigin:
1930     case CSSPropertyWebkitMaskPosition:
1931     case CSSPropertyWebkitMaskPositionX:
1932     case CSSPropertyWebkitMaskPositionY:
1933     case CSSPropertyWebkitMaskSize:
1934     case CSSPropertyWebkitMaskRepeat:
1935     case CSSPropertyWebkitMaskRepeatX:
1936     case CSSPropertyWebkitMaskRepeatY: {
1937         RefPtr<CSSValue> val1;
1938         RefPtr<CSSValue> val2;
1939         CSSPropertyID propId1, propId2;
1940         bool result = false;
1941         if (parseFillProperty(propId, propId1, propId2, val1, val2)) {
1942             OwnPtr<ShorthandScope> shorthandScope;
1943             if (propId == CSSPropertyBackgroundPosition ||
1944                 propId == CSSPropertyBackgroundRepeat ||
1945                 propId == CSSPropertyWebkitMaskPosition ||
1946                 propId == CSSPropertyWebkitMaskRepeat) {
1947                 shorthandScope = adoptPtr(new ShorthandScope(this, propId));
1948             }
1949             addProperty(propId1, val1.release(), important);
1950             if (val2)
1951                 addProperty(propId2, val2.release(), important);
1952             result = true;
1953         }
1954         m_implicitShorthand = false;
1955         return result;
1956     }
1957     case CSSPropertyListStyleImage:     // <uri> | none | inherit
1958     case CSSPropertyBorderImageSource:
1959     case CSSPropertyWebkitMaskBoxImageSource:
1960         if (id == CSSValueNone) {
1961             parsedValue = cssValuePool().createIdentifierValue(CSSValueNone);
1962             m_valueList->next();
1963         } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
1964             parsedValue = CSSImageValue::create(completeURL(value->string));
1965             m_valueList->next();
1966         } else if (isGeneratedImageValue(value)) {
1967             if (parseGeneratedImage(m_valueList.get(), parsedValue))
1968                 m_valueList->next();
1969             else
1970                 return false;
1971         }
1972 #if ENABLE(CSS_IMAGE_SET)
1973         else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "-webkit-image-set(")) {
1974             parsedValue = parseImageSet(m_valueList.get());
1975             if (!parsedValue)
1976                 return false;
1977             m_valueList->next();
1978         }
1979 #endif
1980         break;
1981
1982     case CSSPropertyWebkitTextStrokeWidth:
1983     case CSSPropertyOutlineWidth:        // <border-width> | inherit
1984     case CSSPropertyBorderTopWidth:     //// <border-width> | inherit
1985     case CSSPropertyBorderRightWidth:   //   Which is defined as
1986     case CSSPropertyBorderBottomWidth:  //   thin | medium | thick | <length>
1987     case CSSPropertyBorderLeftWidth:
1988     case CSSPropertyWebkitBorderStartWidth:
1989     case CSSPropertyWebkitBorderEndWidth:
1990     case CSSPropertyWebkitBorderBeforeWidth:
1991     case CSSPropertyWebkitBorderAfterWidth:
1992     case CSSPropertyWebkitColumnRuleWidth:
1993         if (id == CSSValueThin || id == CSSValueMedium || id == CSSValueThick)
1994             validPrimitive = true;
1995         else
1996             validPrimitive = validUnit(value, FLength | FNonNeg);
1997         break;
1998
1999     case CSSPropertyLetterSpacing:       // normal | <length> | inherit
2000     case CSSPropertyWordSpacing:         // normal | <length> | inherit
2001         if (id == CSSValueNormal)
2002             validPrimitive = true;
2003         else
2004             validPrimitive = validUnit(value, FLength);
2005         break;
2006
2007     case CSSPropertyTextIndent:          // <length> | <percentage> | inherit
2008         validPrimitive = (!id && validUnit(value, FLength | FPercent));
2009         break;
2010
2011     case CSSPropertyPaddingTop:          //// <padding-width> | inherit
2012     case CSSPropertyPaddingRight:        //   Which is defined as
2013     case CSSPropertyPaddingBottom:       //   <length> | <percentage>
2014     case CSSPropertyPaddingLeft:         ////
2015     case CSSPropertyWebkitPaddingStart:
2016     case CSSPropertyWebkitPaddingEnd:
2017     case CSSPropertyWebkitPaddingBefore:
2018     case CSSPropertyWebkitPaddingAfter:
2019         validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg));
2020         break;
2021
2022     case CSSPropertyMaxWidth:
2023     case CSSPropertyWebkitMaxLogicalWidth:
2024         validPrimitive = (id == CSSValueNone || validWidth(value));
2025         break;
2026
2027     case CSSPropertyMinWidth:
2028     case CSSPropertyWebkitMinLogicalWidth:
2029     case CSSPropertyWidth:
2030     case CSSPropertyWebkitLogicalWidth:
2031         validPrimitive = (id == CSSValueAuto || validWidth(value));
2032         break;
2033
2034     case CSSPropertyMaxHeight:
2035     case CSSPropertyWebkitMaxLogicalHeight:
2036         validPrimitive = (id == CSSValueNone || validHeight(value));
2037         break;
2038
2039     case CSSPropertyMinHeight:
2040     case CSSPropertyWebkitMinLogicalHeight:
2041     case CSSPropertyHeight:
2042     case CSSPropertyWebkitLogicalHeight:
2043         validPrimitive = (id == CSSValueAuto || validHeight(value));
2044         break;
2045
2046     case CSSPropertyFontSize:
2047         return parseFontSize(important);
2048
2049     case CSSPropertyFontVariant:         // normal | small-caps | inherit
2050         return parseFontVariant(important);
2051
2052     case CSSPropertyVerticalAlign:
2053         // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
2054         // <percentage> | <length> | inherit
2055
2056         if (id >= CSSValueBaseline && id <= CSSValueWebkitBaselineMiddle)
2057             validPrimitive = true;
2058         else
2059             validPrimitive = (!id && validUnit(value, FLength | FPercent));
2060         break;
2061
2062     case CSSPropertyBottom:               // <length> | <percentage> | auto | inherit
2063     case CSSPropertyLeft:                 // <length> | <percentage> | auto | inherit
2064     case CSSPropertyRight:                // <length> | <percentage> | auto | inherit
2065     case CSSPropertyTop:                  // <length> | <percentage> | auto | inherit
2066     case CSSPropertyMarginTop:           //// <margin-width> | inherit
2067     case CSSPropertyMarginRight:         //   Which is defined as
2068     case CSSPropertyMarginBottom:        //   <length> | <percentage> | auto | inherit
2069     case CSSPropertyMarginLeft:          ////
2070     case CSSPropertyWebkitMarginStart:
2071     case CSSPropertyWebkitMarginEnd:
2072     case CSSPropertyWebkitMarginBefore:
2073     case CSSPropertyWebkitMarginAfter:
2074         if (id == CSSValueAuto)
2075             validPrimitive = true;
2076         else
2077             validPrimitive = (!id && validUnit(value, FLength | FPercent));
2078         break;
2079
2080     case CSSPropertyZIndex:              // auto | <integer> | inherit
2081         if (id == CSSValueAuto) {
2082             validPrimitive = true;
2083             break;
2084         }
2085         /* nobreak */
2086     case CSSPropertyOrphans:              // <integer> | inherit
2087     case CSSPropertyWidows:               // <integer> | inherit
2088         // ### not supported later on
2089         validPrimitive = (!id && validUnit(value, FInteger, CSSQuirksMode));
2090         break;
2091
2092     case CSSPropertyLineHeight:
2093         return parseLineHeight(important);
2094     case CSSPropertyCounterIncrement:    // [ <identifier> <integer>? ]+ | none | inherit
2095         if (id != CSSValueNone)
2096             return parseCounter(propId, 1, important);
2097         validPrimitive = true;
2098         break;
2099     case CSSPropertyCounterReset:        // [ <identifier> <integer>? ]+ | none | inherit
2100         if (id != CSSValueNone)
2101             return parseCounter(propId, 0, important);
2102         validPrimitive = true;
2103         break;
2104     case CSSPropertyFontFamily:
2105         // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
2106     {
2107         parsedValue = parseFontFamily();
2108         break;
2109     }
2110
2111     case CSSPropertyTextDecoration:
2112     case CSSPropertyWebkitTextDecorationsInEffect:
2113         // none | [ underline || overline || line-through || blink ] | inherit
2114         if (id == CSSValueNone) {
2115             validPrimitive = true;
2116         } else {
2117             RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
2118             bool isValid = true;
2119             while (isValid && value) {
2120                 switch (value->id) {
2121                 case CSSValueBlink:
2122                     break;
2123                 case CSSValueUnderline:
2124                 case CSSValueOverline:
2125                 case CSSValueLineThrough:
2126                     list->append(cssValuePool().createIdentifierValue(value->id));
2127                     break;
2128                 default:
2129                     isValid = false;
2130                 }
2131                 value = m_valueList->next();
2132             }
2133             if (list->length() && isValid) {
2134                 parsedValue = list.release();
2135                 m_valueList->next();
2136             }
2137         }
2138         break;
2139
2140     case CSSPropertyZoom:          // normal | reset | document | <number> | <percentage> | inherit
2141         if (id == CSSValueNormal || id == CSSValueReset || id == CSSValueDocument)
2142             validPrimitive = true;
2143         else
2144             validPrimitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg, CSSStrictMode));
2145         break;
2146
2147     case CSSPropertySrc:  // Only used within @font-face, so cannot use inherit | initial or be !important.  This is a list of urls or local references.
2148         return parseFontFaceSrc();
2149
2150     case CSSPropertyUnicodeRange:
2151         return parseFontFaceUnicodeRange();
2152
2153     /* CSS3 properties */
2154
2155     case CSSPropertyBorderImage: {
2156         RefPtr<CSSValue> result;
2157         return parseBorderImage(propId, result, important);
2158     }
2159     case CSSPropertyWebkitBorderImage:
2160     case CSSPropertyWebkitMaskBoxImage: {
2161         RefPtr<CSSValue> result;
2162         if (parseBorderImage(propId, result)) {
2163             addProperty(propId, result, important);
2164             return true;
2165         }
2166         break;
2167     }
2168     case CSSPropertyBorderImageOutset:
2169     case CSSPropertyWebkitMaskBoxImageOutset: {
2170         RefPtr<CSSPrimitiveValue> result;
2171         if (parseBorderImageOutset(result)) {
2172             addProperty(propId, result, important);
2173             return true;
2174         }
2175         break;
2176     }
2177     case CSSPropertyBorderImageRepeat:
2178     case CSSPropertyWebkitMaskBoxImageRepeat: {
2179         RefPtr<CSSValue> result;
2180         if (parseBorderImageRepeat(result)) {
2181             addProperty(propId, result, important);
2182             return true;
2183         }
2184         break;
2185     }
2186     case CSSPropertyBorderImageSlice:
2187     case CSSPropertyWebkitMaskBoxImageSlice: {
2188         RefPtr<CSSBorderImageSliceValue> result;
2189         if (parseBorderImageSlice(propId, result)) {
2190             addProperty(propId, result, important);
2191             return true;
2192         }
2193         break;
2194     }
2195     case CSSPropertyBorderImageWidth:
2196     case CSSPropertyWebkitMaskBoxImageWidth: {
2197         RefPtr<CSSPrimitiveValue> result;
2198         if (parseBorderImageWidth(result)) {
2199             addProperty(propId, result, important);
2200             return true;
2201         }
2202         break;
2203     }
2204     case CSSPropertyBorderTopRightRadius:
2205     case CSSPropertyBorderTopLeftRadius:
2206     case CSSPropertyBorderBottomLeftRadius:
2207     case CSSPropertyBorderBottomRightRadius: {
2208         if (num != 1 && num != 2)
2209             return false;
2210         validPrimitive = validUnit(value, FLength | FPercent | FNonNeg);
2211         if (!validPrimitive)
2212             return false;
2213         RefPtr<CSSPrimitiveValue> parsedValue1 = createPrimitiveNumericValue(value);
2214         RefPtr<CSSPrimitiveValue> parsedValue2;
2215         if (num == 2) {
2216             value = m_valueList->next();
2217             validPrimitive = validUnit(value, FLength | FPercent | FNonNeg);
2218             if (!validPrimitive)
2219                 return false;
2220             parsedValue2 = createPrimitiveNumericValue(value);
2221         } else
2222             parsedValue2 = parsedValue1;
2223
2224         RefPtr<Pair> pair = Pair::create(parsedValue1.release(), parsedValue2.release());
2225         RefPtr<CSSPrimitiveValue> val = cssValuePool().createValue(pair.release());
2226         addProperty(propId, val.release(), important);
2227         return true;
2228     }
2229     case CSSPropertyTabSize:
2230         validPrimitive = validUnit(value, FInteger | FNonNeg);
2231         break;
2232     case CSSPropertyWebkitAspectRatio:
2233         return parseAspectRatio(important);
2234     case CSSPropertyBorderRadius:
2235     case CSSPropertyWebkitBorderRadius:
2236         return parseBorderRadius(propId, important);
2237     case CSSPropertyOutlineOffset:
2238         validPrimitive = validUnit(value, FLength | FPercent);
2239         break;
2240     case CSSPropertyTextShadow: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
2241     case CSSPropertyBoxShadow:
2242     case CSSPropertyWebkitBoxShadow:
2243         if (id == CSSValueNone)
2244             validPrimitive = true;
2245         else {
2246             RefPtr<CSSValueList> shadowValueList = parseShadow(m_valueList.get(), propId);
2247             if (shadowValueList) {
2248                 addProperty(propId, shadowValueList.release(), important);
2249                 m_valueList->next();
2250                 return true;
2251             }
2252             return false;
2253         }
2254         break;
2255     case CSSPropertyWebkitBoxReflect:
2256         if (id == CSSValueNone)
2257             validPrimitive = true;
2258         else
2259             return parseReflect(propId, important);
2260         break;
2261     case CSSPropertyOpacity:
2262         validPrimitive = validUnit(value, FNumber);
2263         break;
2264     case CSSPropertyWebkitBoxFlex:
2265         validPrimitive = validUnit(value, FNumber);
2266         break;
2267     case CSSPropertyWebkitBoxFlexGroup:
2268         validPrimitive = validUnit(value, FInteger | FNonNeg, CSSStrictMode);
2269         break;
2270     case CSSPropertyWebkitBoxOrdinalGroup:
2271         validPrimitive = validUnit(value, FInteger | FNonNeg, CSSStrictMode) && value->fValue;
2272         break;
2273 #if ENABLE(CSS_FILTERS)
2274     case CSSPropertyWebkitFilter:
2275         if (id == CSSValueNone)
2276             validPrimitive = true;
2277         else {
2278             RefPtr<CSSValue> val = parseFilter();
2279             if (val) {
2280                 addProperty(propId, val, important);
2281                 return true;
2282             }
2283             return false;
2284         }
2285         break;
2286 #endif
2287 #if ENABLE(CSS3_FLEXBOX)
2288     case CSSPropertyWebkitFlex: {
2289         ShorthandScope scope(this, propId);
2290         if (id == CSSValueNone) {
2291             addProperty(CSSPropertyWebkitFlexGrow, cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER), important);
2292             addProperty(CSSPropertyWebkitFlexShrink, cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER), important);
2293             addProperty(CSSPropertyWebkitFlexBasis, cssValuePool().createIdentifierValue(CSSValueAuto), important);
2294             return true;
2295         }
2296         return parseFlex(m_valueList.get(), important);
2297     }
2298     case CSSPropertyWebkitFlexBasis:
2299         // FIXME: Support intrinsic dimensions too.
2300         if (id == CSSValueAuto)
2301             validPrimitive = true;
2302         else
2303             validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg));
2304         break;
2305     case CSSPropertyWebkitFlexGrow:
2306     case CSSPropertyWebkitFlexShrink:
2307         validPrimitive = validUnit(value, FNumber | FNonNeg);
2308         break;
2309     case CSSPropertyWebkitOrder:
2310         validPrimitive = validUnit(value, FNumber);
2311         break;
2312 #endif
2313     case CSSPropertyWebkitMarquee:
2314         return parseShorthand(propId, webkitMarqueeShorthand(), important);
2315     case CSSPropertyWebkitMarqueeIncrement:
2316         if (id == CSSValueSmall || id == CSSValueLarge || id == CSSValueMedium)
2317             validPrimitive = true;
2318         else
2319             validPrimitive = validUnit(value, FLength | FPercent);
2320         break;
2321     case CSSPropertyWebkitMarqueeRepetition:
2322         if (id == CSSValueInfinite)
2323             validPrimitive = true;
2324         else
2325             validPrimitive = validUnit(value, FInteger | FNonNeg);
2326         break;
2327     case CSSPropertyWebkitMarqueeSpeed:
2328         if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast)
2329             validPrimitive = true;
2330         else
2331             validPrimitive = validUnit(value, FTime | FInteger | FNonNeg);
2332         break;
2333 #if ENABLE(CSS_REGIONS)
2334     case CSSPropertyWebkitFlowInto:
2335         if (!cssRegionsEnabled())
2336             return false;
2337         return parseFlowThread(propId, important);
2338     case CSSPropertyWebkitFlowFrom:
2339         if (!cssRegionsEnabled())
2340             return false;
2341         return parseRegionThread(propId, important);
2342 #endif
2343     case CSSPropertyWebkitTransform:
2344         if (id == CSSValueNone)
2345             validPrimitive = true;
2346         else {
2347             PassRefPtr<CSSValue> val = parseTransform();
2348             if (val) {
2349                 addProperty(propId, val, important);
2350                 return true;
2351             }
2352             return false;
2353         }
2354         break;
2355     case CSSPropertyWebkitTransformOrigin:
2356     case CSSPropertyWebkitTransformOriginX:
2357     case CSSPropertyWebkitTransformOriginY:
2358     case CSSPropertyWebkitTransformOriginZ: {
2359         RefPtr<CSSValue> val1;
2360         RefPtr<CSSValue> val2;
2361         RefPtr<CSSValue> val3;
2362         CSSPropertyID propId1, propId2, propId3;
2363         if (parseTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) {
2364             addProperty(propId1, val1.release(), important);
2365             if (val2)
2366                 addProperty(propId2, val2.release(), important);
2367             if (val3)
2368                 addProperty(propId3, val3.release(), important);
2369             return true;
2370         }
2371         return false;
2372     }
2373     case CSSPropertyWebkitPerspective:
2374         if (id == CSSValueNone)
2375             validPrimitive = true;
2376         else {
2377             // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property.
2378             if (validUnit(value, FNumber | FLength | FNonNeg)) {
2379                 RefPtr<CSSValue> val = createPrimitiveNumericValue(value);
2380                 if (val) {
2381                     addProperty(propId, val.release(), important);
2382                     return true;
2383                 }
2384                 return false;
2385             }
2386         }
2387         break;
2388     case CSSPropertyWebkitPerspectiveOrigin:
2389     case CSSPropertyWebkitPerspectiveOriginX:
2390     case CSSPropertyWebkitPerspectiveOriginY: {
2391         RefPtr<CSSValue> val1;
2392         RefPtr<CSSValue> val2;
2393         CSSPropertyID propId1, propId2;
2394         if (parsePerspectiveOrigin(propId, propId1, propId2, val1, val2)) {
2395             addProperty(propId1, val1.release(), important);
2396             if (val2)
2397                 addProperty(propId2, val2.release(), important);
2398             return true;
2399         }
2400         return false;
2401     }
2402     case CSSPropertyWebkitAnimationDelay:
2403     case CSSPropertyWebkitAnimationDirection:
2404     case CSSPropertyWebkitAnimationDuration:
2405     case CSSPropertyWebkitAnimationFillMode:
2406     case CSSPropertyWebkitAnimationName:
2407     case CSSPropertyWebkitAnimationPlayState:
2408     case CSSPropertyWebkitAnimationIterationCount:
2409     case CSSPropertyWebkitAnimationTimingFunction:
2410     case CSSPropertyWebkitTransitionDelay:
2411     case CSSPropertyWebkitTransitionDuration:
2412     case CSSPropertyWebkitTransitionTimingFunction:
2413     case CSSPropertyWebkitTransitionProperty: {
2414         RefPtr<CSSValue> val;
2415         if (parseAnimationProperty(propId, val)) {
2416             addProperty(propId, val.release(), important);
2417             return true;
2418         }
2419         return false;
2420     }
2421
2422     case CSSPropertyWebkitGridColumns:
2423     case CSSPropertyWebkitGridRows:
2424         if (!cssGridLayoutEnabled())
2425             return false;
2426         return parseGridTrackList(propId, important);
2427
2428     case CSSPropertyWebkitGridColumn:
2429     case CSSPropertyWebkitGridRow:
2430         if (!cssGridLayoutEnabled())
2431             return false;
2432         validPrimitive = id == CSSValueAuto || validUnit(value, FInteger);
2433         break;
2434
2435     case CSSPropertyWebkitMarginCollapse: {
2436         if (num == 1) {
2437             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2438             if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important))
2439                 return false;
2440             CSSValue* value = m_parsedProperties.last().value();
2441             addProperty(webkitMarginCollapseShorthand().properties()[1], value, important);
2442             return true;
2443         }
2444         else if (num == 2) {
2445             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2446             if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important) || !parseValue(webkitMarginCollapseShorthand().properties()[1], important))
2447                 return false;
2448             return true;
2449         }
2450         return false;
2451     }
2452     case CSSPropertyTextLineThroughWidth:
2453     case CSSPropertyTextOverlineWidth:
2454     case CSSPropertyTextUnderlineWidth:
2455         if (id == CSSValueAuto || id == CSSValueNormal || id == CSSValueThin ||
2456             id == CSSValueMedium || id == CSSValueThick)
2457             validPrimitive = true;
2458         else
2459             validPrimitive = !id && validUnit(value, FNumber | FLength | FPercent);
2460         break;
2461     case CSSPropertyWebkitColumnCount:
2462         if (id == CSSValueAuto)
2463             validPrimitive = true;
2464         else
2465             validPrimitive = !id && validUnit(value, FInteger | FNonNeg, CSSQuirksMode);
2466         break;
2467     case CSSPropertyWebkitColumnGap:         // normal | <length>
2468         if (id == CSSValueNormal)
2469             validPrimitive = true;
2470         else
2471             validPrimitive = validUnit(value, FLength | FNonNeg);
2472         break;
2473     case CSSPropertyWebkitColumnAxis:
2474         if (id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto)
2475             validPrimitive = true;
2476         break;
2477     case CSSPropertyWebkitColumnProgression:
2478         if (id == CSSValueNormal || id == CSSValueReverse)
2479             validPrimitive = true;
2480         break;
2481     case CSSPropertyWebkitColumnSpan: // none | all | 1 (will be dropped in the unprefixed property)
2482         if (id == CSSValueAll || id == CSSValueNone)
2483             validPrimitive = true;
2484         else
2485             validPrimitive = validUnit(value, FNumber | FNonNeg) && value->fValue == 1;
2486         break;
2487     case CSSPropertyWebkitColumnWidth:         // auto | <length>
2488         if (id == CSSValueAuto)
2489             validPrimitive = true;
2490         else // Always parse this property in strict mode, since it would be ambiguous otherwise when used in the 'columns' shorthand property.
2491             validPrimitive = validUnit(value, FLength, CSSStrictMode);
2492         break;
2493     // End of CSS3 properties
2494
2495     // Apple specific properties.  These will never be standardized and are purely to
2496     // support custom WebKit-based Apple applications.
2497     case CSSPropertyWebkitLineClamp:
2498         // When specifying number of lines, don't allow 0 as a valid value
2499         // When specifying either type of unit, require non-negative integers
2500         validPrimitive = (!id && (value->unit == CSSPrimitiveValue::CSS_PERCENTAGE || value->fValue) && validUnit(value, FInteger | FPercent | FNonNeg, CSSQuirksMode));
2501         break;
2502
2503     case CSSPropertyWebkitFontSizeDelta:           // <length>
2504         validPrimitive = validUnit(value, FLength);
2505         break;
2506
2507     case CSSPropertyWebkitHighlight:
2508         if (id == CSSValueNone || value->unit == CSSPrimitiveValue::CSS_STRING)
2509             validPrimitive = true;
2510         break;
2511
2512     case CSSPropertyWebkitHyphenateCharacter:
2513         if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
2514             validPrimitive = true;
2515         break;
2516
2517     case CSSPropertyWebkitHyphenateLimitBefore:
2518     case CSSPropertyWebkitHyphenateLimitAfter:
2519         if (id == CSSValueAuto || validUnit(value, FInteger | FNonNeg, CSSStrictMode))
2520             validPrimitive = true;
2521         break;
2522
2523     case CSSPropertyWebkitHyphenateLimitLines:
2524         if (id == CSSValueNoLimit || validUnit(value, FInteger | FNonNeg, CSSStrictMode))
2525             validPrimitive = true;
2526         break;
2527
2528     case CSSPropertyWebkitLineGrid:
2529         if (id == CSSValueNone)
2530             validPrimitive = true;
2531         else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
2532             String lineGridValue = String(value->string);
2533             if (!lineGridValue.isEmpty()) {
2534                 addProperty(propId, cssValuePool().createValue(lineGridValue, CSSPrimitiveValue::CSS_STRING), important);
2535                 return true;
2536             }
2537         }
2538         break;
2539     case CSSPropertyWebkitLocale:
2540         if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
2541             validPrimitive = true;
2542         break;
2543
2544 #if ENABLE(DASHBOARD_SUPPORT)
2545     case CSSPropertyWebkitDashboardRegion: // <dashboard-region> | <dashboard-region>
2546         if (value->unit == CSSParserValue::Function || id == CSSValueNone)
2547             return parseDashboardRegions(propId, important);
2548         break;
2549 #endif
2550     // End Apple-specific properties
2551
2552 #if ENABLE(TOUCH_EVENTS)
2553     case CSSPropertyWebkitTapHighlightColor:
2554         if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu
2555             || (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && inQuirksMode())) {
2556             validPrimitive = true;
2557         } else {
2558             parsedValue = parseColor();
2559             if (parsedValue)
2560                 m_valueList->next();
2561         }
2562         break;
2563 #endif
2564
2565         /* shorthand properties */
2566     case CSSPropertyBackground: {
2567         // Position must come before color in this array because a plain old "0" is a legal color
2568         // in quirks mode but it's usually the X coordinate of a position.
2569         const CSSPropertyID properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat,
2570                                    CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyBackgroundOrigin,
2571                                    CSSPropertyBackgroundClip, CSSPropertyBackgroundColor, CSSPropertyBackgroundSize };
2572         return parseFillShorthand(propId, properties, WTF_ARRAY_LENGTH(properties), important);
2573     }
2574     case CSSPropertyWebkitMask: {
2575         const CSSPropertyID properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
2576                                    CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition,
2577                                    CSSPropertyWebkitMaskOrigin, CSSPropertyWebkitMaskClip };
2578         return parseFillShorthand(propId, properties, 6, important);
2579     }
2580     case CSSPropertyBorder:
2581         // [ 'border-width' || 'border-style' || <color> ] | inherit
2582     {
2583         if (parseShorthand(propId, borderAbridgedShorthand(), important)) {
2584             // The CSS3 Borders and Backgrounds specification says that border also resets border-image. It's as
2585             // though a value of none was specified for the image.
2586             addProperty(CSSPropertyBorderImage, cssValuePool().createImplicitInitialValue(), important);
2587             return true;
2588         }
2589         return false;
2590     }
2591     case CSSPropertyBorderTop:
2592         // [ 'border-top-width' || 'border-style' || <color> ] | inherit
2593         return parseShorthand(propId, borderTopShorthand(), important);
2594     case CSSPropertyBorderRight:
2595         // [ 'border-right-width' || 'border-style' || <color> ] | inherit
2596         return parseShorthand(propId, borderRightShorthand(), important);
2597     case CSSPropertyBorderBottom:
2598         // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
2599         return parseShorthand(propId, borderBottomShorthand(), important);
2600     case CSSPropertyBorderLeft:
2601         // [ 'border-left-width' || 'border-style' || <color> ] | inherit
2602         return parseShorthand(propId, borderLeftShorthand(), important);
2603     case CSSPropertyWebkitBorderStart:
2604         return parseShorthand(propId, webkitBorderStartShorthand(), important);
2605     case CSSPropertyWebkitBorderEnd:
2606         return parseShorthand(propId, webkitBorderEndShorthand(), important);
2607     case CSSPropertyWebkitBorderBefore:
2608         return parseShorthand(propId, webkitBorderBeforeShorthand(), important);
2609     case CSSPropertyWebkitBorderAfter:
2610         return parseShorthand(propId, webkitBorderAfterShorthand(), important);
2611     case CSSPropertyOutline:
2612         // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
2613         return parseShorthand(propId, outlineShorthand(), important);
2614     case CSSPropertyBorderColor:
2615         // <color>{1,4} | inherit
2616         return parse4Values(propId, borderColorShorthand().properties(), important);
2617     case CSSPropertyBorderWidth:
2618         // <border-width>{1,4} | inherit
2619         return parse4Values(propId, borderWidthShorthand().properties(), important);
2620     case CSSPropertyBorderStyle:
2621         // <border-style>{1,4} | inherit
2622         return parse4Values(propId, borderStyleShorthand().properties(), important);
2623     case CSSPropertyMargin:
2624         // <margin-width>{1,4} | inherit
2625         return parse4Values(propId, marginShorthand().properties(), important);
2626     case CSSPropertyPadding:
2627         // <padding-width>{1,4} | inherit
2628         return parse4Values(propId, paddingShorthand().properties(), important);
2629 #if ENABLE(CSS3_FLEXBOX)
2630     case CSSPropertyWebkitFlexFlow:
2631         return parseShorthand(propId, webkitFlexFlowShorthand(), important);
2632 #endif
2633     case CSSPropertyFont:
2634         // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
2635         // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
2636         if (id >= CSSValueCaption && id <= CSSValueStatusBar)
2637             validPrimitive = true;
2638         else
2639             return parseFont(important);
2640         break;
2641     case CSSPropertyListStyle:
2642         return parseShorthand(propId, listStyleShorthand(), important);
2643     case CSSPropertyWebkitColumns:
2644         return parseShorthand(propId, webkitColumnsShorthand(), important);
2645     case CSSPropertyWebkitColumnRule:
2646         return parseShorthand(propId, webkitColumnRuleShorthand(), important);
2647     case CSSPropertyWebkitTextStroke:
2648         return parseShorthand(propId, webkitTextStrokeShorthand(), important);
2649     case CSSPropertyWebkitAnimation:
2650         return parseAnimationShorthand(important);
2651     case CSSPropertyWebkitTransition:
2652         return parseTransitionShorthand(important);
2653     case CSSPropertyInvalid:
2654         return false;
2655     case CSSPropertyPage:
2656         return parsePage(propId, important);
2657     case CSSPropertyFontStretch:
2658     case CSSPropertyTextLineThrough:
2659     case CSSPropertyTextOverline:
2660     case CSSPropertyTextUnderline:
2661         return false;
2662     // CSS Text Layout Module Level 3: Vertical writing support
2663     case CSSPropertyWebkitTextEmphasis:
2664         return parseShorthand(propId, webkitTextEmphasisShorthand(), important);
2665
2666     case CSSPropertyWebkitTextEmphasisStyle:
2667         return parseTextEmphasisStyle(important);
2668
2669     case CSSPropertyWebkitTextOrientation:
2670         // FIXME: For now just support upright and vertical-right.
2671         if (id == CSSValueVerticalRight || id == CSSValueUpright)
2672             validPrimitive = true;
2673         break;
2674
2675     case CSSPropertyWebkitLineBoxContain:
2676         if (id == CSSValueNone)
2677             validPrimitive = true;
2678         else
2679             return parseLineBoxContain(important);
2680         break;
2681     case CSSPropertyWebkitFontFeatureSettings:
2682         if (id == CSSValueNormal)
2683             validPrimitive = true;
2684         else
2685             return parseFontFeatureSettings(important);
2686         break;
2687
2688     case CSSPropertyWebkitFontVariantLigatures:
2689         if (id == CSSValueNormal)
2690             validPrimitive = true;
2691         else
2692             return parseFontVariantLigatures(important);
2693         break;
2694     case CSSPropertyWebkitClipPath:
2695         if (id == CSSValueNone)
2696             validPrimitive = true;
2697         else if (value->unit == CSSParserValue::Function)
2698             return parseBasicShape(propId, important);
2699         break;
2700 #if ENABLE(CSS_EXCLUSIONS)
2701     case CSSPropertyWebkitShapeInside:
2702     case CSSPropertyWebkitShapeOutside:
2703         if (!RuntimeEnabledFeatures::cssExclusionsEnabled())
2704             return false;
2705         if (id == CSSValueAuto)
2706             validPrimitive = true;
2707         else if (value->unit == CSSParserValue::Function)
2708             return parseBasicShape(propId, important);
2709         break;
2710     case CSSPropertyWebkitWrapMargin:
2711     case CSSPropertyWebkitWrapPadding:
2712         validPrimitive = (RuntimeEnabledFeatures::cssExclusionsEnabled() && !id && validUnit(value, FLength | FNonNeg));
2713         break;
2714     case CSSPropertyWebkitWrap:
2715         return RuntimeEnabledFeatures::cssExclusionsEnabled() && parseShorthand(propId, webkitWrapShorthand(), important);
2716 #endif
2717 #if ENABLE(CSS_IMAGE_ORIENTATION)
2718     case CSSPropertyImageOrientation:
2719         validPrimitive = !id && validUnit(value, FAngle);
2720         break;
2721 #endif
2722 #if ENABLE(CSS_IMAGE_RESOLUTION)
2723     case CSSPropertyImageResolution:
2724         parsedValue = parseImageResolution(m_valueList.get());
2725         if (!parsedValue)
2726             return false;
2727         m_valueList->next();
2728         break;
2729 #endif
2730     case CSSPropertyBorderBottomStyle:
2731     case CSSPropertyBorderCollapse:
2732     case CSSPropertyBorderLeftStyle:
2733     case CSSPropertyBorderRightStyle:
2734     case CSSPropertyBorderTopStyle:
2735     case CSSPropertyBoxSizing:
2736     case CSSPropertyCaptionSide:
2737     case CSSPropertyClear:
2738     case CSSPropertyDirection:
2739     case CSSPropertyDisplay:
2740     case CSSPropertyEmptyCells:
2741     case CSSPropertyFloat:
2742     case CSSPropertyFontStyle:
2743     case CSSPropertyImageRendering:
2744     case CSSPropertyListStylePosition:
2745     case CSSPropertyListStyleType:
2746     case CSSPropertyOutlineStyle:
2747     case CSSPropertyOverflowWrap:
2748     case CSSPropertyOverflowX:
2749     case CSSPropertyOverflowY:
2750     case CSSPropertyPageBreakAfter:
2751     case CSSPropertyPageBreakBefore:
2752     case CSSPropertyPageBreakInside:
2753     case CSSPropertyPointerEvents:
2754     case CSSPropertyPosition:
2755     case CSSPropertyResize:
2756     case CSSPropertySpeak:
2757     case CSSPropertyTableLayout:
2758     case CSSPropertyTextLineThroughMode:
2759     case CSSPropertyTextLineThroughStyle:
2760     case CSSPropertyTextOverflow:
2761     case CSSPropertyTextOverlineMode:
2762     case CSSPropertyTextOverlineStyle:
2763     case CSSPropertyTextRendering:
2764     case CSSPropertyTextTransform:
2765     case CSSPropertyTextUnderlineMode:
2766     case CSSPropertyTextUnderlineStyle:
2767 #if ENABLE(CSS_VARIABLES)
2768     case CSSPropertyVariable:
2769 #endif
2770     case CSSPropertyVisibility:
2771     case CSSPropertyWebkitAppearance:
2772     case CSSPropertyWebkitBackfaceVisibility:
2773     case CSSPropertyWebkitBorderAfterStyle:
2774     case CSSPropertyWebkitBorderBeforeStyle:
2775     case CSSPropertyWebkitBorderEndStyle:
2776     case CSSPropertyWebkitBorderFit:
2777     case CSSPropertyWebkitBorderStartStyle:
2778     case CSSPropertyWebkitBoxAlign:
2779 #if ENABLE(CSS_BOX_DECORATION_BREAK)
2780     case CSSPropertyWebkitBoxDecorationBreak:
2781 #endif
2782     case CSSPropertyWebkitBoxDirection:
2783     case CSSPropertyWebkitBoxLines:
2784     case CSSPropertyWebkitBoxOrient:
2785     case CSSPropertyWebkitBoxPack:
2786     case CSSPropertyWebkitColorCorrection:
2787     case CSSPropertyWebkitColumnBreakAfter:
2788     case CSSPropertyWebkitColumnBreakBefore:
2789     case CSSPropertyWebkitColumnBreakInside:
2790     case CSSPropertyWebkitColumnRuleStyle:
2791 #if ENABLE(CSS3_FLEXBOX)
2792     case CSSPropertyWebkitAlignContent:
2793     case CSSPropertyWebkitAlignItems:
2794     case CSSPropertyWebkitAlignSelf:
2795     case CSSPropertyWebkitFlexDirection:
2796     case CSSPropertyWebkitFlexWrap:
2797     case CSSPropertyWebkitJustifyContent:
2798 #endif
2799     case CSSPropertyWebkitFontKerning:
2800     case CSSPropertyWebkitFontSmoothing:
2801     case CSSPropertyWebkitHyphens:
2802     case CSSPropertyWebkitLineAlign:
2803     case CSSPropertyWebkitLineBreak:
2804     case CSSPropertyWebkitLineSnap:
2805     case CSSPropertyWebkitMarginAfterCollapse:
2806     case CSSPropertyWebkitMarginBeforeCollapse:
2807     case CSSPropertyWebkitMarginBottomCollapse:
2808     case CSSPropertyWebkitMarginTopCollapse:
2809     case CSSPropertyWebkitMarqueeDirection:
2810     case CSSPropertyWebkitMarqueeStyle:
2811     case CSSPropertyWebkitNbspMode:
2812 #if ENABLE(OVERFLOW_SCROLLING)
2813     case CSSPropertyWebkitOverflowScrolling:
2814 #endif
2815     case CSSPropertyWebkitPrintColorAdjust:
2816 #if ENABLE(CSS_REGIONS)
2817     case CSSPropertyWebkitRegionBreakAfter:
2818     case CSSPropertyWebkitRegionBreakBefore:
2819     case CSSPropertyWebkitRegionBreakInside:
2820     case CSSPropertyWebkitRegionOverflow:
2821 #endif
2822     case CSSPropertyWebkitRtlOrdering:
2823     case CSSPropertyWebkitTextCombine:
2824     case CSSPropertyWebkitTextEmphasisPosition:
2825     case CSSPropertyWebkitTextSecurity:
2826     case CSSPropertyWebkitTextSizeAdjust:
2827     case CSSPropertyWebkitTransformStyle:
2828     case CSSPropertyWebkitUserDrag:
2829     case CSSPropertyWebkitUserModify:
2830     case CSSPropertyWebkitUserSelect:
2831 #if ENABLE(CSS_EXCLUSIONS)
2832     case CSSPropertyWebkitWrapFlow:
2833     case CSSPropertyWebkitWrapThrough:
2834 #endif
2835     case CSSPropertyWebkitWritingMode:
2836     case CSSPropertyWhiteSpace:
2837     case CSSPropertyWordBreak:
2838     case CSSPropertyWordWrap:
2839         // These properties should be handled before in isValidKeywordPropertyAndValue().
2840         ASSERT_NOT_REACHED();
2841         return false;
2842 #if ENABLE(SVG)
2843     default:
2844         return parseSVGValue(propId, important);
2845 #endif
2846     }
2847
2848     if (validPrimitive) {
2849         parsedValue = parseValidPrimitive(id, value);
2850         m_valueList->next();
2851     }
2852     ASSERT(!m_parsedCalculation);
2853     if (parsedValue) {
2854         if (!m_valueList->current() || inShorthand()) {
2855             addProperty(propId, parsedValue.release(), important);
2856             return true;
2857         }
2858     }
2859     return false;
2860 }
2861
2862 void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
2863 {
2864     if (lval) {
2865         if (lval->isValueList())
2866             static_cast<CSSValueList*>(lval.get())->append(rval);
2867         else {
2868             PassRefPtr<CSSValue> oldlVal(lval.release());
2869             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2870             list->append(oldlVal);
2871             list->append(rval);
2872             lval = list;
2873         }
2874     }
2875     else
2876         lval = rval;
2877 }
2878
2879 static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue)
2880 {
2881     if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox
2882         || parserValue->id == CSSValueContentBox || parserValue->id == CSSValueWebkitText) {
2883         cssValue = cssValuePool().createIdentifierValue(parserValue->id);
2884         return true;
2885     }
2886     return false;
2887 }
2888
2889 const int cMaxFillProperties = 9;
2890
2891 bool CSSParser::parseFillShorthand(CSSPropertyID propId, const CSSPropertyID* properties, int numProperties, bool important)
2892 {
2893     ASSERT(numProperties <= cMaxFillProperties);
2894     if (numProperties > cMaxFillProperties)
2895         return false;
2896
2897     ShorthandScope scope(this, propId);
2898
2899     bool parsedProperty[cMaxFillProperties] = { false };
2900     RefPtr<CSSValue> values[cMaxFillProperties];
2901     RefPtr<CSSValue> clipValue;
2902     RefPtr<CSSValue> positionYValue;
2903     RefPtr<CSSValue> repeatYValue;
2904     bool foundClip = false;
2905     int i;
2906     bool foundBackgroundPositionCSSProperty = false;
2907
2908     while (m_valueList->current()) {
2909         CSSParserValue* val = m_valueList->current();
2910         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2911             // We hit the end.  Fill in all remaining values with the initial value.
2912             m_valueList->next();
2913             for (i = 0; i < numProperties; ++i) {
2914                 if (properties[i] == CSSPropertyBackgroundColor && parsedProperty[i])
2915                     // Color is not allowed except as the last item in a list for backgrounds.
2916                     // Reject the entire property.
2917                     return false;
2918
2919                 if (!parsedProperty[i] && properties[i] != CSSPropertyBackgroundColor) {
2920                     addFillValue(values[i], cssValuePool().createImplicitInitialValue());
2921                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2922                         addFillValue(positionYValue, cssValuePool().createImplicitInitialValue());
2923                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2924                         addFillValue(repeatYValue, cssValuePool().createImplicitInitialValue());
2925                     if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
2926                         // If background-origin wasn't present, then reset background-clip also.
2927                         addFillValue(clipValue, cssValuePool().createImplicitInitialValue());
2928                     }
2929                 }
2930                 parsedProperty[i] = false;
2931             }
2932             if (!m_valueList->current())
2933                 break;
2934         }
2935
2936         bool backgroundSizeCSSPropertyExpected = false;
2937         if ((val->unit == CSSParserValue::Operator && val->iValue == '/') && foundBackgroundPositionCSSProperty) {
2938             backgroundSizeCSSPropertyExpected = true;
2939             m_valueList->next();
2940         }
2941
2942         foundBackgroundPositionCSSProperty = false;
2943         bool found = false;
2944         for (i = 0; !found && i < numProperties; ++i) {
2945
2946             if (backgroundSizeCSSPropertyExpected && properties[i] != CSSPropertyBackgroundSize)
2947                 continue;
2948             if (!backgroundSizeCSSPropertyExpected && properties[i] == CSSPropertyBackgroundSize)
2949                 continue;
2950
2951             if (!parsedProperty[i]) {
2952                 RefPtr<CSSValue> val1;
2953                 RefPtr<CSSValue> val2;
2954                 CSSPropertyID propId1, propId2;
2955                 CSSParserValue* parserValue = m_valueList->current();
2956                 if (parseFillProperty(properties[i], propId1, propId2, val1, val2)) {
2957                     parsedProperty[i] = found = true;
2958                     addFillValue(values[i], val1.release());
2959                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2960                         addFillValue(positionYValue, val2.release());
2961                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2962                         addFillValue(repeatYValue, val2.release());
2963                     if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
2964                         // Reparse the value as a clip, and see if we succeed.
2965                         if (parseBackgroundClip(parserValue, val1))
2966                             addFillValue(clipValue, val1.release()); // The property parsed successfully.
2967                         else
2968                             addFillValue(clipValue, cssValuePool().createImplicitInitialValue()); // Some value was used for origin that is not supported by clip. Just reset clip instead.
2969                     }
2970                     if (properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) {
2971                         // Update clipValue
2972                         addFillValue(clipValue, val1.release());
2973                         foundClip = true;
2974                     }
2975                     if (properties[i] == CSSPropertyBackgroundPosition)
2976                         foundBackgroundPositionCSSProperty =  true;
2977                 }
2978             }
2979         }
2980
2981         // if we didn't find at least one match, this is an
2982         // invalid shorthand and we have to ignore it
2983         if (!found)
2984             return false;
2985     }
2986
2987     // Now add all of the properties we found.
2988     for (i = 0; i < numProperties; i++) {
2989         // Fill in any remaining properties with the initial value.
2990         if (!parsedProperty[i]) {
2991             addFillValue(values[i], cssValuePool().createImplicitInitialValue());
2992             if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2993                 addFillValue(positionYValue, cssValuePool().createImplicitInitialValue());
2994             if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2995                 addFillValue(repeatYValue, cssValuePool().createImplicitInitialValue());
2996             if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin)) {
2997                 // If background-origin wasn't present, then reset background-clip also.
2998                 addFillValue(clipValue, cssValuePool().createImplicitInitialValue());
2999             }
3000         }
3001         if (properties[i] == CSSPropertyBackgroundPosition) {
3002             addProperty(CSSPropertyBackgroundPositionX, values[i].release(), important);
3003             // it's OK to call positionYValue.release() since we only see CSSPropertyBackgroundPosition once
3004             addProperty(CSSPropertyBackgroundPositionY, positionYValue.release(), important);
3005         } else if (properties[i] == CSSPropertyWebkitMaskPosition) {
3006             addProperty(CSSPropertyWebkitMaskPositionX, values[i].release(), important);
3007             // it's OK to call positionYValue.release() since we only see CSSPropertyWebkitMaskPosition once
3008             addProperty(CSSPropertyWebkitMaskPositionY, positionYValue.release(), important);
3009         } else if (properties[i] == CSSPropertyBackgroundRepeat) {
3010             addProperty(CSSPropertyBackgroundRepeatX, values[i].release(), important);
3011             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
3012             addProperty(CSSPropertyBackgroundRepeatY, repeatYValue.release(), important);
3013         } else if (properties[i] == CSSPropertyWebkitMaskRepeat) {
3014             addProperty(CSSPropertyWebkitMaskRepeatX, values[i].release(), important);
3015             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
3016             addProperty(CSSPropertyWebkitMaskRepeatY, repeatYValue.release(), important);
3017         } else if ((properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) && !foundClip)
3018             // Value is already set while updating origin
3019             continue;
3020 #if ENABLE(TIZEN_NOT_INITIAIZE_BACKGROUND_SIZE_IN_SHORTHAND_WORKAROUND)
3021         else if (properties[i] == CSSPropertyBackgroundSize && !parsedProperty[i])
3022             continue;
3023 #endif
3024         else
3025             addProperty(properties[i], values[i].release(), important);
3026
3027         // Add in clip values when we hit the corresponding origin property.
3028         if (properties[i] == CSSPropertyBackgroundOrigin && !foundClip)
3029             addProperty(CSSPropertyBackgroundClip, clipValue.release(), important);
3030         else if (properties[i] == CSSPropertyWebkitMaskOrigin && !foundClip)
3031             addProperty(CSSPropertyWebkitMaskClip, clipValue.release(), important);
3032     }
3033
3034     return true;
3035 }
3036
3037 #if ENABLE(CSS_VARIABLES)
3038 bool CSSParser::cssVariablesEnabled() const
3039 {
3040     return m_context.isCSSVariablesEnabled;
3041 }
3042
3043 void CSSParser::storeVariableDeclaration(const CSSParserString& name, PassOwnPtr<CSSParserValueList> value, bool important)
3044 {
3045     ASSERT(name.length > 12);
3046     AtomicString variableName = String(name.characters + 12, name.length - 12);
3047
3048     StringBuilder builder;
3049     for (unsigned i = 0, size = value->size(); i < size; i++) {
3050         if (i)
3051             builder.append(' ');
3052         RefPtr<CSSValue> cssValue = value->valueAt(i)->createCSSValue();
3053         if (!cssValue)
3054             return;
3055         builder.append(cssValue->cssText());
3056     }
3057     addProperty(CSSPropertyVariable, CSSVariableValue::create(variableName, builder.toString()), important, false);
3058 }
3059 #endif
3060
3061 void CSSParser::addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
3062 {
3063     if (lval) {
3064         if (lval->isValueList())
3065             static_cast<CSSValueList*>(lval.get())->append(rval);
3066         else {
3067             PassRefPtr<CSSValue> oldVal(lval.release());
3068             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
3069             list->append(oldVal);
3070             list->append(rval);
3071             lval = list;
3072         }
3073     }
3074     else
3075         lval = rval;
3076 }
3077
3078 bool CSSParser::parseAnimationShorthand(bool important)
3079 {
3080     // When we parse the animation shorthand we need to look for animation-name
3081     // last because otherwise it might match against the keywords for fill mode,
3082     // timing functions and infinite iteration. This means that animation names
3083     // that are the same as keywords (e.g. 'forwards') won't always match in the
3084     // shorthand. In that case they should be using longhands (or reconsidering
3085     // their approach). This is covered by the animations spec bug:
3086     // https://www.w3.org/Bugs/Public/show_bug.cgi?id=14790
3087     // And in the spec (editor's draft) at:
3088     // http://dev.w3.org/csswg/css3-animations/#animation-shorthand-property
3089
3090     static const CSSPropertyID animationProperties[] = {
3091         CSSPropertyWebkitAnimationDuration,
3092         CSSPropertyWebkitAnimationTimingFunction,
3093         CSSPropertyWebkitAnimationDelay,
3094         CSSPropertyWebkitAnimationIterationCount,
3095         CSSPropertyWebkitAnimationDirection,
3096         CSSPropertyWebkitAnimationFillMode,
3097         CSSPropertyWebkitAnimationName
3098     };
3099     const unsigned numProperties = 7;
3100
3101     // The list of properties in the shorthand should be the same
3102     // length as the list we have here, even though they are
3103     // a different order.
3104     ASSERT(numProperties == webkitAnimationShorthand().length());
3105
3106     ShorthandScope scope(this, CSSPropertyWebkitAnimation);
3107
3108     bool parsedProperty[numProperties] = { false };
3109     RefPtr<CSSValue> values[numProperties];
3110
3111     unsigned i;
3112     while (m_valueList->current()) {
3113         CSSParserValue* val = m_valueList->current();
3114         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3115             // We hit the end.  Fill in all remaining values with the initial value.
3116             m_valueList->next();
3117             for (i = 0; i < numProperties; ++i) {
3118                 if (!parsedProperty[i])
3119                     addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3120                 parsedProperty[i] = false;
3121             }
3122             if (!m_valueList->current())
3123                 break;
3124         }
3125
3126         bool found = false;
3127         for (i = 0; i < numProperties; ++i) {
3128             if (!parsedProperty[i]) {
3129                 RefPtr<CSSValue> val;
3130                 if (parseAnimationProperty(animationProperties[i], val)) {
3131                     parsedProperty[i] = found = true;
3132                     addAnimationValue(values[i], val.release());
3133                     break;
3134                 }
3135             }
3136         }
3137
3138         // if we didn't find at least one match, this is an
3139         // invalid shorthand and we have to ignore it
3140         if (!found)
3141             return false;
3142     }
3143
3144     for (i = 0; i < numProperties; ++i) {
3145         // If we didn't find the property, set an intial value.
3146         if (!parsedProperty[i])
3147             addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3148
3149         addProperty(animationProperties[i], values[i].release(), important);
3150     }
3151
3152     return true;
3153 }
3154
3155 bool CSSParser::parseTransitionShorthand(bool important)
3156 {
3157     const unsigned numProperties = webkitTransitionShorthand().length();
3158
3159     ShorthandScope scope(this, CSSPropertyWebkitTransition);
3160
3161     bool parsedProperty[] = { false, false, false, false };
3162     RefPtr<CSSValue> values[4];
3163
3164     unsigned i;
3165     while (m_valueList->current()) {
3166         CSSParserValue* val = m_valueList->current();
3167         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3168             // We hit the end.  Fill in all remaining values with the initial value.
3169             m_valueList->next();
3170             for (i = 0; i < numProperties; ++i) {
3171                 if (!parsedProperty[i])
3172                     addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3173                 parsedProperty[i] = false;
3174             }
3175             if (!m_valueList->current())
3176                 break;
3177         }
3178
3179         bool found = false;
3180         for (i = 0; !found && i < numProperties; ++i) {
3181             if (!parsedProperty[i]) {
3182                 RefPtr<CSSValue> val;
3183                 if (parseAnimationProperty(webkitTransitionShorthand().properties()[i], val)) {
3184                     parsedProperty[i] = found = true;
3185                     addAnimationValue(values[i], val.release());
3186                 }
3187             }
3188         }
3189
3190         // if we didn't find at least one match, this is an
3191         // invalid shorthand and we have to ignore it
3192         if (!found)
3193             return false;
3194     }
3195
3196     // Fill in any remaining properties with the initial value.
3197     for (i = 0; i < numProperties; ++i) {
3198         if (!parsedProperty[i])
3199             addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3200     }
3201
3202     // Now add all of the properties we found.
3203     for (i = 0; i < numProperties; i++)
3204         addProperty(webkitTransitionShorthand().properties()[i], values[i].release(), important);
3205
3206     return true;
3207 }
3208
3209 bool CSSParser::parseShorthand(CSSPropertyID propId, const StylePropertyShorthand& shorthand, bool important)
3210 {
3211     // We try to match as many properties as possible
3212     // We set up an array of booleans to mark which property has been found,
3213     // and we try to search for properties until it makes no longer any sense.
3214     ShorthandScope scope(this, propId);
3215
3216     bool found = false;
3217     unsigned propertiesParsed = 0;
3218     bool propertyFound[6]= { false, false, false, false, false, false }; // 6 is enough size.
3219
3220     while (m_valueList->current()) {
3221         found = false;
3222         for (unsigned propIndex = 0; !found && propIndex < shorthand.length(); ++propIndex) {
3223             if (!propertyFound[propIndex] && parseValue(shorthand.properties()[propIndex], important)) {
3224                     propertyFound[propIndex] = found = true;
3225                     propertiesParsed++;
3226             }
3227         }
3228
3229         // if we didn't find at least one match, this is an
3230         // invalid shorthand and we have to ignore it
3231         if (!found)
3232             return false;
3233     }
3234
3235     if (propertiesParsed == shorthand.length())
3236         return true;
3237
3238     // Fill in any remaining properties with the initial value.
3239     ImplicitScope implicitScope(this, PropertyImplicit);
3240     const StylePropertyShorthand* const* const propertiesForInitialization = shorthand.propertiesForInitialization();
3241     for (unsigned i = 0; i < shorthand.length(); ++i) {
3242         if (propertyFound[i])
3243             continue;
3244
3245         if (propertiesForInitialization) {
3246             const StylePropertyShorthand& initProperties = *(propertiesForInitialization[i]);
3247             for (unsigned propIndex = 0; propIndex < initProperties.length(); ++propIndex)
3248                 addProperty(initProperties.properties()[propIndex], cssValuePool().createImplicitInitialValue(), important);
3249         } else
3250             addProperty(shorthand.properties()[i], cssValuePool().createImplicitInitialValue(), important);
3251     }
3252
3253     return true;
3254 }
3255
3256 bool CSSParser::parse4Values(CSSPropertyID propId, const CSSPropertyID *properties,  bool important)
3257 {
3258     /* From the CSS 2 specs, 8.3
3259      * If there is only one value, it applies to all sides. If there are two values, the top and
3260      * bottom margins are set to the first value and the right and left margins are set to the second.
3261      * If there are three values, the top is set to the first value, the left and right are set to the
3262      * second, and the bottom is set to the third. If there are four values, they apply to the top,
3263      * right, bottom, and left, respectively.
3264      */
3265
3266     int num = inShorthand() ? 1 : m_valueList->size();
3267
3268     ShorthandScope scope(this, propId);
3269
3270     // the order is top, right, bottom, left
3271     switch (num) {
3272         case 1: {
3273             if (!parseValue(properties[0], important))
3274                 return false;
3275             CSSValue *value = m_parsedProperties.last().value();
3276             ImplicitScope implicitScope(this, PropertyImplicit);
3277             addProperty(properties[1], value, important);
3278             addProperty(properties[2], value, important);
3279             addProperty(properties[3], value, important);
3280             break;
3281         }
3282         case 2: {
3283             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
3284                 return false;
3285             CSSValue *value = m_parsedProperties[m_parsedProperties.size() - 2].value();
3286             ImplicitScope implicitScope(this, PropertyImplicit);
3287             addProperty(properties[2], value, important);
3288             value = m_parsedProperties[m_parsedProperties.size() - 2].value();
3289             addProperty(properties[3], value, important);
3290             break;
3291         }
3292         case 3: {
3293             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
3294                 return false;
3295             CSSValue *value = m_parsedProperties[m_parsedProperties.size() - 2].value();
3296             ImplicitScope implicitScope(this, PropertyImplicit);
3297             addProperty(properties[3], value, important);
3298             break;
3299         }
3300         case 4: {
3301             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
3302                 !parseValue(properties[2], important) || !parseValue(properties[3], important))
3303                 return false;
3304             break;
3305         }
3306         default: {
3307             return false;
3308         }
3309     }
3310
3311     return true;
3312 }
3313
3314 // auto | <identifier>
3315 bool CSSParser::parsePage(CSSPropertyID propId, bool important)
3316 {
3317     ASSERT(propId == CSSPropertyPage);
3318
3319     if (m_valueList->size() != 1)
3320         return false;
3321
3322     CSSParserValue* value = m_valueList->current();
3323     if (!value)
3324         return false;
3325
3326     if (value->id == CSSValueAuto) {
3327         addProperty(propId, cssValuePool().createIdentifierValue(value->id), important);
3328         return true;
3329     } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) {
3330         addProperty(propId, createPrimitiveStringValue(value), important);
3331         return true;
3332     }
3333     return false;
3334 }
3335
3336 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
3337 bool CSSParser::parseSize(CSSPropertyID propId, bool important)
3338 {
3339     ASSERT(propId == CSSPropertySize);
3340
3341     if (m_valueList->size() > 2)
3342         return false;
3343
3344     CSSParserValue* value = m_valueList->current();
3345     if (!value)
3346         return false;
3347
3348     RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
3349
3350     // First parameter.
3351     SizeParameterType paramType = parseSizeParameter(parsedValues.get(), value, None);
3352     if (paramType == None)
3353         return false;
3354
3355     // Second parameter, if any.
3356     value = m_valueList->next();
3357     if (value) {
3358         paramType = parseSizeParameter(parsedValues.get(), value, paramType);
3359         if (paramType == None)
3360             return false;
3361     }
3362
3363     addProperty(propId, parsedValues.release(), important);
3364     return true;
3365 }
3366
3367 CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType)
3368 {
3369     switch (value->id) {
3370     case CSSValueAuto:
3371         if (prevParamType == None) {
3372             parsedValues->append(cssValuePool().createIdentifierValue(value->id));
3373             return Auto;
3374         }
3375         return None;
3376     case CSSValueLandscape:
3377     case CSSValuePortrait:
3378         if (prevParamType == None || prevParamType == PageSize) {
3379             parsedValues->append(cssValuePool().createIdentifierValue(value->id));
3380             return Orientation;
3381         }
3382         return None;
3383     case CSSValueA3:
3384     case CSSValueA4:
3385     case CSSValueA5:
3386     case CSSValueB4:
3387     case CSSValueB5:
3388     case CSSValueLedger:
3389     case CSSValueLegal:
3390     case CSSValueLetter:
3391         if (prevParamType == None || prevParamType == Orientation) {
3392             // Normalize to Page Size then Orientation order by prepending.
3393             // This is not specified by the CSS3 Paged Media specification, but for simpler processing later (StyleResolver::applyPageSizeProperty).
3394             parsedValues->prepend(cssValuePool().createIdentifierValue(value->id));
3395             return PageSize;
3396         }
3397         return None;
3398     case 0:
3399         if (validUnit(value, FLength | FNonNeg) && (prevParamType == None || prevParamType == Length)) {
3400             parsedValues->append(createPrimitiveNumericValue(value));
3401             return Length;
3402         }
3403         return None;
3404     default:
3405         return None;
3406     }
3407 }
3408
3409 // [ <string> <string> ]+ | inherit | none
3410 // inherit and none are handled in parseValue.
3411 bool CSSParser::parseQuotes(CSSPropertyID propId, bool important)
3412 {
3413     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3414     while (CSSParserValue* val = m_valueList->current()) {
3415         RefPtr<CSSValue> parsedValue;
3416         if (val->unit == CSSPrimitiveValue::CSS_STRING)
3417             parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING);
3418         else
3419             break;
3420         values->append(parsedValue.release());
3421         m_valueList->next();
3422     }
3423     if (values->length()) {
3424         addProperty(propId, values.release(), important);
3425         m_valueList->next();
3426         return true;
3427     }
3428     return false;
3429 }
3430
3431 // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
3432 // in CSS 2.1 this got somewhat reduced:
3433 // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
3434 bool CSSParser::parseContent(CSSPropertyID propId, bool important)
3435 {
3436     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3437
3438     while (CSSParserValue* val = m_valueList->current()) {
3439         RefPtr<CSSValue> parsedValue;
3440         if (val->unit == CSSPrimitiveValue::CSS_URI) {
3441             // url
3442             parsedValue = CSSImageValue::create(completeURL(val->string));
3443         } else if (val->unit == CSSParserValue::Function) {
3444             // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) | -webkit-gradient(...)
3445             CSSParserValueList* args = val->function->args.get();
3446             if (!args)
3447                 return false;
3448             if (equalIgnoringCase(val->function->name, "attr(")) {
3449                 parsedValue = parseAttr(args);
3450                 if (!parsedValue)
3451                     return false;
3452             } else if (equalIgnoringCase(val->function->name, "counter(")) {
3453                 parsedValue = parseCounterContent(args, false);
3454                 if (!parsedValue)
3455                     return false;
3456             } else if (equalIgnoringCase(val->function->name, "counters(")) {
3457                 parsedValue = parseCounterContent(args, true);
3458                 if (!parsedValue)
3459                     return false;
3460 #if ENABLE(CSS_IMAGE_SET)
3461             } else if (equalIgnoringCase(val->function->name, "-webkit-image-set(")) {
3462                 parsedValue = parseImageSet(m_valueList.get());
3463                 if (!parsedValue)
3464                     return false;
3465 #endif
3466             } else if (isGeneratedImageValue(val)) {
3467                 if (!parseGeneratedImage(m_valueList.get(), parsedValue))
3468                     return false;
3469             } else
3470                 return false;
3471         } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
3472             // open-quote
3473             // close-quote
3474             // no-open-quote
3475             // no-close-quote
3476             // inherit
3477             // FIXME: These are not yet implemented (http://bugs.webkit.org/show_bug.cgi?id=6503).
3478             // none
3479             // normal
3480             switch (val->id) {
3481             case CSSValueOpenQuote:
3482             case CSSValueCloseQuote:
3483             case CSSValueNoOpenQuote:
3484             case CSSValueNoCloseQuote:
3485             case CSSValueNone:
3486             case CSSValueNormal:
3487                 parsedValue = cssValuePool().createIdentifierValue(val->id);
3488             }
3489         } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
3490             parsedValue = createPrimitiveStringValue(val);
3491         }
3492         if (!parsedValue)
3493             break;
3494         values->append(parsedValue.release());
3495         m_valueList->next();
3496     }
3497
3498     if (values->length()) {
3499         addProperty(propId, values.release(), important);
3500         m_valueList->next();
3501         return true;
3502     }
3503
3504     return false;
3505 }
3506
3507 PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args)
3508 {
3509     if (args->size() != 1)
3510         return 0;
3511
3512     CSSParserValue* a = args->current();
3513
3514     if (a->unit != CSSPrimitiveValue::CSS_IDENT)
3515         return 0;
3516
3517     String attrName = a->string;
3518     // CSS allows identifiers with "-" at the start, like "-webkit-mask-image".
3519     // But HTML attribute names can't have those characters, and we should not
3520     // even parse them inside attr().
3521     if (attrName[0] == '-')
3522         return 0;
3523
3524     if (m_context.isHTMLDocument)
3525         attrName = attrName.lower();
3526
3527     return cssValuePool().createValue(attrName, CSSPrimitiveValue::CSS_ATTR);
3528 }
3529
3530 PassRefPtr<CSSValue> CSSParser::parseBackgroundColor()
3531 {
3532     int id = m_valueList->current()->id;
3533     if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor ||
3534         (id >= CSSValueGrey && id < CSSValueWebkitText && inQuirksMode()))
3535         return cssValuePool().createIdentifierValue(id);
3536     return parseColor();
3537 }
3538
3539 bool CSSParser::parseFillImage(CSSParserValueList* valueList, RefPtr<CSSValue>& value)
3540 {
3541     if (valueList->current()->id == CSSValueNone) {
3542         value = cssValuePool().createIdentifierValue(CSSValueNone);
3543         return true;
3544     }
3545     if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
3546         value = CSSImageValue::create(completeURL(valueList->current()->string));
3547         return true;
3548     }
3549
3550     if (isGeneratedImageValue(valueList->current()))
3551         return parseGeneratedImage(valueList, value);
3552     
3553 #if ENABLE(CSS_IMAGE_SET)
3554     if (valueList->current()->unit == CSSParserValue::Function && equalIgnoringCase(valueList->current()->function->name, "-webkit-image-set(")) {
3555         value = parseImageSet(m_valueList.get());
3556         if (value)
3557             return true;
3558     }
3559 #endif
3560
3561     return false;
3562 }
3563
3564 PassRefPtr<CSSValue> CSSParser::parseFillPositionX(CSSParserValueList* valueList)
3565 {
3566     int id = valueList->current()->id;
3567     if (id == CSSValueLeft || id == CSSValueRight || id == CSSValueCenter) {
3568         int percent = 0;
3569         if (id == CSSValueRight)
3570             percent = 100;
3571         else if (id == CSSValueCenter)
3572             percent = 50;
3573         return cssValuePool().createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3574     }
3575     if (validUnit(valueList->current(), FPercent | FLength))
3576         return createPrimitiveNumericValue(valueList->current());
3577     return 0;
3578 }
3579
3580 PassRefPtr<CSSValue> CSSParser::parseFillPositionY(CSSParserValueList* valueList)
3581 {
3582     int id = valueList->current()->id;
3583     if (id == CSSValueTop || id == CSSValueBottom || id == CSSValueCenter) {
3584         int percent = 0;
3585         if (id == CSSValueBottom)
3586             percent = 100;
3587         else if (id == CSSValueCenter)
3588             percent = 50;
3589         return cssValuePool().createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3590     }
3591     if (validUnit(valueList->current(), FPercent | FLength))
3592         return createPrimitiveNumericValue(valueList->current());
3593     return 0;
3594 }
3595
3596 PassRefPtr<CSSValue> CSSParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag)
3597 {
3598     int id = valueList->current()->id;
3599     if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
3600         int percent = 0;
3601         if (id == CSSValueLeft || id == CSSValueRight) {
3602             if (cumulativeFlags & XFillPosition)
3603                 return 0;
3604             cumulativeFlags |= XFillPosition;
3605             individualFlag = XFillPosition;
3606             if (id == CSSValueRight)
3607                 percent = 100;
3608         }
3609         else if (id == CSSValueTop || id == CSSValueBottom) {
3610             if (cumulativeFlags & YFillPosition)
3611                 return 0;
3612             cumulativeFlags |= YFillPosition;
3613             individualFlag = YFillPosition;
3614             if (id == CSSValueBottom)
3615                 percent = 100;
3616         } else if (id == CSSValueCenter) {
3617             // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
3618             percent = 50;
3619             cumulativeFlags |= AmbiguousFillPosition;
3620             individualFlag = AmbiguousFillPosition;
3621         }
3622         return cssValuePool().createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3623     }
3624     if (validUnit(valueList->current(), FPercent | FLength)) {
3625         if (!cumulativeFlags) {
3626             cumulativeFlags |= XFillPosition;
3627             individualFlag = XFillPosition;
3628         } else if (cumulativeFlags & (XFillPosition | AmbiguousFillPosition)) {
3629             cumulativeFlags |= YFillPosition;
3630             individualFlag = YFillPosition;
3631         } else {
3632             if (m_parsedCalculation)
3633                 m_parsedCalculation.release();
3634             return 0;
3635         }
3636         return createPrimitiveNumericValue(valueList->current());
3637     }
3638     return 0;
3639 }
3640
3641 void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
3642 {
3643     CSSParserValue* value = valueList->current();
3644
3645     // Parse the first value.  We're just making sure that it is one of the valid keywords or a percentage/length.
3646     unsigned cumulativeFlags = 0;
3647     FillPositionFlag value1Flag = InvalidFillPosition;
3648     FillPositionFlag value2Flag = InvalidFillPosition;
3649     value1 = parseFillPositionComponent(valueList, cumulativeFlags, value1Flag);
3650     if (!value1)
3651         return;
3652
3653     // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
3654     // can assume that any other values belong to the rest of the shorthand).  If we're not parsing a shorthand, though, the
3655     // value was explicitly specified for our property.
3656     value = valueList->next();
3657
3658     // First check for the comma.  If so, we are finished parsing this value or value pair.
3659     if (isComma(value))
3660         value = 0;
3661
3662     if (value) {
3663         value2 = parseFillPositionComponent(valueList, cumulativeFlags, value2Flag);
3664         if (value2)
3665             valueList->next();
3666         else {
3667             if (!inShorthand()) {
3668                 value1.clear();
3669                 return;
3670             }
3671         }
3672     }
3673
3674     if (!value2)
3675         // Only one value was specified.  If that value was not a keyword, then it sets the x position, and the y position
3676         // is simply 50%.  This is our default.
3677         // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
3678         // For left/right/center, the default of 50% in the y is still correct.
3679         value2 = cssValuePool().createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
3680
3681     if (value1Flag == YFillPosition || value2Flag == XFillPosition)
3682         value1.swap(value2);
3683 }
3684
3685 void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
3686 {
3687     int id = m_valueList->current()->id;
3688     if (id == CSSValueRepeatX) {
3689         m_implicitShorthand = true;
3690         value1 = cssValuePool().createIdentifierValue(CSSValueRepeat);
3691         value2 = cssValuePool().createIdentifierValue(CSSValueNoRepeat);
3692         m_valueList->next();
3693         return;
3694     }
3695     if (id == CSSValueRepeatY) {
3696         m_implicitShorthand = true;
3697         value1 = cssValuePool().createIdentifierValue(CSSValueNoRepeat);
3698         value2 = cssValuePool().createIdentifierValue(CSSValueRepeat);
3699         m_valueList->next();
3700         return;
3701     }
3702     if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)
3703         value1 = cssValuePool().createIdentifierValue(id);
3704     else {
3705         value1 = 0;
3706         return;
3707     }
3708
3709     CSSParserValue* value = m_valueList->next();
3710
3711     // Parse the second value if one is available
3712     if (value && !isComma(value)) {
3713         id = value->id;
3714         if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace) {
3715             value2 = cssValuePool().createIdentifierValue(id);
3716             m_valueList->next();
3717             return;
3718         }
3719     }
3720
3721     // If only one value was specified, value2 is the same as value1.
3722     m_implicitShorthand = true;
3723     value2 = cssValuePool().createIdentifierValue(static_cast<CSSPrimitiveValue*>(value1.get())->getIdent());
3724 }
3725
3726 PassRefPtr<CSSValue> CSSParser::parseFillSize(CSSPropertyID propId, bool& allowComma)
3727 {
3728     allowComma = true;
3729     CSSParserValue* value = m_valueList->current();
3730
3731     if (value->id == CSSValueContain || value->id == CSSValueCover)
3732         return cssValuePool().createIdentifierValue(value->id);
3733
3734     RefPtr<CSSPrimitiveValue> parsedValue1;
3735
3736     if (value->id == CSSValueAuto)
3737         parsedValue1 = cssValuePool().createIdentifierValue(CSSValueAuto);
3738     else {
3739         if (!validUnit(value, FLength | FPercent))
3740             return 0;
3741         parsedValue1 = createPrimitiveNumericValue(value);
3742     }
3743
3744     RefPtr<CSSPrimitiveValue> parsedValue2;
3745     if ((value = m_valueList->next())) {
3746         if (value->unit == CSSParserValue::Operator && value->iValue == ',')
3747             allowComma = false;
3748         else if (value->id != CSSValueAuto) {
3749             if (!validUnit(value, FLength | FPercent)) {
3750                 if (!inShorthand())
3751                     return 0;
3752                 // We need to rewind the value list, so that when it is advanced we'll end up back at this value.
3753                 m_valueList->previous();
3754             } else
3755                 parsedValue2 = createPrimitiveNumericValue(value);
3756         }
3757     } else if (!parsedValue2 && propId == CSSPropertyWebkitBackgroundSize) {
3758         // For backwards compatibility we set the second value to the first if it is omitted.
3759         // We only need to do this for -webkit-background-size. It should be safe to let masks match
3760         // the real property.
3761         parsedValue2 = parsedValue1;
3762     }
3763
3764     if (!parsedValue2)
3765         return parsedValue1;
3766     return cssValuePool().createValue(Pair::create(parsedValue1.release(), parsedValue2.release()));
3767 }
3768
3769 bool CSSParser::parseFillProperty(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2,
3770                                   RefPtr<CSSValue>& retValue1, RefPtr<CSSValue>& retValue2)
3771 {
3772     RefPtr<CSSValueList> values;
3773     RefPtr<CSSValueList> values2;
3774     CSSParserValue* val;
3775     RefPtr<CSSValue> value;
3776     RefPtr<CSSValue> value2;
3777
3778     bool allowComma = false;
3779
3780     retValue1 = retValue2 = 0;
3781     propId1 = propId;
3782     propId2 = propId;
3783     if (propId == CSSPropertyBackgroundPosition) {
3784         propId1 = CSSPropertyBackgroundPositionX;
3785         propId2 = CSSPropertyBackgroundPositionY;
3786     } else if (propId == CSSPropertyWebkitMaskPosition) {
3787         propId1 = CSSPropertyWebkitMaskPositionX;
3788         propId2 = CSSPropertyWebkitMaskPositionY;
3789     } else if (propId == CSSPropertyBackgroundRepeat) {
3790         propId1 = CSSPropertyBackgroundRepeatX;
3791         propId2 = CSSPropertyBackgroundRepeatY;
3792     } else if (propId == CSSPropertyWebkitMaskRepeat) {
3793         propId1 = CSSPropertyWebkitMaskRepeatX;
3794         propId2 = CSSPropertyWebkitMaskRepeatY;
3795     }
3796
3797     while ((val = m_valueList->current())) {
3798         RefPtr<CSSValue> currValue;
3799         RefPtr<CSSValue> currValue2;
3800
3801         if (allowComma) {
3802             if (!isComma(val))
3803                 return false;
3804             m_valueList->next();
3805             allowComma = false;
3806         } else {
3807             allowComma = true;
3808             switch (propId) {
3809                 case CSSPropertyBackgroundColor:
3810                     currValue = parseBackgroundColor();
3811                     if (currValue)
3812                         m_valueList->next();
3813                     break;
3814                 case CSSPropertyBackgroundAttachment:
3815                 case CSSPropertyWebkitMaskAttachment:
3816                     if (val->id == CSSValueScroll || val->id == CSSValueFixed || val->id == CSSValueLocal) {
3817                         currValue = cssValuePool().createIdentifierValue(val->id);
3818                         m_valueList->next();
3819                     }
3820                     break;
3821                 case CSSPropertyBackgroundImage:
3822                 case CSSPropertyWebkitMaskImage:
3823                     if (parseFillImage(m_valueList.get(), currValue))
3824                         m_valueList->next();
3825                     break;
3826                 case CSSPropertyWebkitBackgroundClip:
3827                 case CSSPropertyWebkitBackgroundOrigin:
3828                 case CSSPropertyWebkitMaskClip:
3829                 case CSSPropertyWebkitMaskOrigin:
3830                     // The first three values here are deprecated and do not apply to the version of the property that has
3831                     // the -webkit- prefix removed.
3832                     if (val->id == CSSValueBorder || val->id == CSSValuePadding || val->id == CSSValueContent ||
3833                         val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox ||
3834                         ((propId == CSSPropertyWebkitBackgroundClip || propId == CSSPropertyWebkitMaskClip) &&
3835                          (val->id == CSSValueText || val->id == CSSValueWebkitText))) {
3836                         currValue = cssValuePool().createIdentifierValue(val->id);
3837                         m_valueList->next();
3838                     }
3839                     break;
3840                 case CSSPropertyBackgroundClip:
3841                     if (parseBackgroundClip(val, currValue))
3842                         m_valueList->next();
3843                     break;
3844                 case CSSPropertyBackgroundOrigin:
3845                     if (val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox) {
3846                         currValue = cssValuePool().createIdentifierValue(val->id);
3847                         m_valueList->next();
3848                     }
3849                     break;
3850                 case CSSPropertyBackgroundPosition:
3851                 case CSSPropertyWebkitMaskPosition:
3852                     parseFillPosition(m_valueList.get(), currValue, currValue2);
3853                     // parseFillPosition advances the m_valueList pointer
3854                     break;
3855                 case CSSPropertyBackgroundPositionX:
3856                 case CSSPropertyWebkitMaskPositionX: {
3857                     currValue = parseFillPositionX(m_valueList.get());
3858                     if (currValue)
3859                         m_valueList->next();
3860                     break;
3861                 }
3862                 case CSSPropertyBackgroundPositionY:
3863                 case CSSPropertyWebkitMaskPositionY: {
3864                     currValue = parseFillPositionY(m_valueList.get());
3865                     if (currValue)
3866                         m_valueList->next();
3867                     break;
3868                 }
3869                 case CSSPropertyWebkitBackgroundComposite:
3870                 case CSSPropertyWebkitMaskComposite:
3871                     if ((val->id >= CSSValueClear && val->id <= CSSValuePlusLighter) || val->id == CSSValueHighlight) {
3872                         currValue = cssValuePool().createIdentifierValue(val->id);
3873                         m_valueList->next();
3874                     }
3875                     break;
3876                 case CSSPropertyBackgroundRepeat:
3877                 case CSSPropertyWebkitMaskRepeat:
3878                     parseFillRepeat(currValue, currValue2);
3879                     // parseFillRepeat advances the m_valueList pointer
3880                     break;
3881                 case CSSPropertyBackgroundSize:
3882                 case CSSPropertyWebkitBackgroundSize:
3883                 case CSSPropertyWebkitMaskSize: {
3884                     currValue = parseFillSize(propId, allowComma);
3885                     if (currValue)
3886                         m_valueList->next();
3887                     break;
3888                 }
3889                 default:
3890                     break;
3891             }
3892             if (!currValue)
3893                 return false;
3894
3895             if (value && !values) {
3896                 values = CSSValueList::createCommaSeparated();
3897                 values->append(value.release());
3898             }
3899
3900             if (value2 && !values2) {
3901                 values2 = CSSValueList::createCommaSeparated();
3902                 values2->append(value2.release());
3903             }
3904
3905             if (values)
3906                 values->append(currValue.release());
3907             else
3908                 value = currValue.release();
3909             if (currValue2) {
3910                 if (values2)
3911                     values2->append(currValue2.release());
3912                 else
3913                     value2 = currValue2.release();
3914             }
3915         }
3916
3917         // When parsing any fill shorthand property, we let it handle building up the lists for all
3918         // properties.
3919         if (inShorthand())
3920             break;
3921     }
3922
3923     if (values && values->length()) {
3924         retValue1 = values.release();
3925         if (values2 && values2->length())
3926             retValue2 = values2.release();
3927         return true;
3928     }
3929     if (value) {
3930         retValue1 = value.release();
3931         retValue2 = value2.release();
3932         return true;
3933     }
3934     return false;
3935 }
3936
3937 PassRefPtr<CSSValue> CSSParser::parseAnimationDelay()
3938 {
3939     CSSParserValue* value = m_valueList->current();
3940     if (validUnit(value, FTime))
3941         return createPrimitiveNumericValue(value);
3942     return 0;
3943 }
3944
3945 PassRefPtr<CSSValue> CSSParser::parseAnimationDirection()
3946 {
3947     CSSParserValue* value = m_valueList->current();
3948     if (value->id == CSSValueNormal || value->id == CSSValueAlternate || value->id == CSSValueReverse || value->id == CSSValueAlternateReverse)
3949         return cssValuePool().createIdentifierValue(value->id);
3950     return 0;
3951 }
3952
3953 PassRefPtr<CSSValue> CSSParser::parseAnimationDuration()
3954 {
3955     CSSParserValue* value = m_valueList->current();
3956     if (validUnit(value, FTime | FNonNeg))
3957         return createPrimitiveNumericValue(value);
3958     return 0;
3959 }
3960
3961 PassRefPtr<CSSValue> CSSParser::parseAnimationFillMode()
3962 {
3963     CSSParserValue* value = m_valueList->current();
3964     if (value->id == CSSValueNone || value->id == CSSValueForwards || value->id == CSSValueBackwards || value->id == CSSValueBoth)
3965         return cssValuePool().createIdentifierValue(value->id);
3966     return 0;
3967 }
3968
3969 PassRefPtr<CSSValue> CSSParser::parseAnimationIterationCount()
3970 {
3971     CSSParserValue* value = m_valueList->current();
3972     if (value->id == CSSValueInfinite)
3973         return cssValuePool().createIdentifierValue(value->id);
3974     if (validUnit(value, FNumber | FNonNeg))
3975         return createPrimitiveNumericValue(value);
3976     return 0;
3977 }
3978
3979 PassRefPtr<CSSValue> CSSParser::parseAnimationName()
3980 {
3981     CSSParserValue* value = m_valueList->current();
3982     if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT) {
3983         if (value->id == CSSValueNone || (value->unit == CSSPrimitiveValue::CSS_STRING && equalIgnoringCase(value->string, "none"))) {
3984             return cssValuePool().createIdentifierValue(CSSValueNone);
3985         } else {
3986             return createPrimitiveStringValue(value);
3987         }
3988     }
3989     return 0;
3990 }
3991
3992 PassRefPtr<CSSValue> CSSParser::parseAnimationPlayState()
3993 {
3994     CSSParserValue* value = m_valueList->current();
3995     if (value->id == CSSValueRunning || value->id == CSSValuePaused)
3996         return cssValuePool().createIdentifierValue(value->id);
3997     return 0;
3998 }
3999
4000 PassRefPtr<CSSValue> CSSParser::parseAnimationProperty()
4001 {
4002     CSSParserValue* value = m_valueList->current();
4003     if (value->unit != CSSPrimitiveValue::CSS_IDENT)
4004         return 0;
4005     int result = cssPropertyID(value->string);
4006     if (result)
4007         return cssValuePool().createIdentifierValue(result);
4008     if (equalIgnoringCase(value->string, "all"))
4009         return cssValuePool().createIdentifierValue(CSSValueAll);
4010     if (equalIgnoringCase(value->string, "none"))
4011         return cssValuePool().createIdentifierValue(CSSValueNone);
4012     return 0;
4013 }
4014
4015 bool CSSParser::parseTransformOriginShorthand(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3)
4016 {
4017     parseFillPosition(m_valueList.get(), value1, value2);
4018
4019     // now get z
4020     if (m_valueList->current()) {
4021         if (validUnit(m_valueList->current(), FLength)) {
4022             value3 = createPrimitiveNumericValue(m_valueList->current());
4023             m_valueList->next();
4024             return true;
4025         }
4026         return false;
4027     }
4028     value3 = cssValuePool().createImplicitInitialValue();
4029     return true;
4030 }
4031
4032 bool CSSParser::parseCubicBezierTimingFunctionValue(CSSParserValueList*& args, double& result)
4033 {
4034     CSSParserValue* v = args->current();
4035     if (!validUnit(v, FNumber))
4036         return false;
4037     result = v->fValue;
4038     v = args->next();
4039     if (!v)
4040         // The last number in the function has no comma after it, so we're done.
4041         return true;
4042     if (!isComma(v))
4043         return false;
4044     args->next();
4045     return true;
4046 }
4047
4048 PassRefPtr<CSSValue> CSSParser::parseAnimationTimingFunction()
4049 {
4050     CSSParserValue* value = m_valueList->current();
4051     if (value->id == CSSValueEase || value->id == CSSValueLinear || value->id == CSSValueEaseIn || value->id == CSSValueEaseOut
4052         || value->id == CSSValueEaseInOut || value->id == CSSValueStepStart || value->id == CSSValueStepEnd)
4053         return cssValuePool().createIdentifierValue(value->id);
4054
4055     // We must be a function.
4056     if (value->unit != CSSParserValue::Function)
4057         return 0;
4058
4059     CSSParserValueList* args = value->function->args.get();
4060
4061     if (equalIgnoringCase(value->function->name, "steps(")) {
4062         // For steps, 1 or 2 params must be specified (comma-separated)
4063         if (!args || (args->size() != 1 && args->size() != 3))
4064             return 0;
4065
4066         // There are two values.
4067         int numSteps;
4068         bool stepAtStart = false;
4069
4070         CSSParserValue* v = args->current();
4071         if (!validUnit(v, FInteger))
4072             return 0;
4073         numSteps = clampToInteger(v->fValue);
4074         if (numSteps < 1)
4075             return 0;
4076         v = args->next();
4077
4078         if (v) {
4079             // There is a comma so we need to parse the second value
4080             if (!isComma(v))
4081                 return 0;
4082             v = args->next();
4083             if (v->id != CSSValueStart && v->id != CSSValueEnd)
4084                 return 0;
4085             stepAtStart = v->id == CSSValueStart;
4086         }
4087
4088         return CSSStepsTimingFunctionValue::create(numSteps, stepAtStart);
4089     }
4090
4091     if (equalIgnoringCase(value->function->name, "cubic-bezier(")) {
4092         // For cubic bezier, 4 values must be specified.
4093         if (!args || args->size() != 7)
4094             return 0;
4095
4096         // There are two points specified.  The values must be between 0 and 1.
4097         double x1, y1, x2, y2;
4098
4099         if (!parseCubicBezierTimingFunctionValue(args, x1))
4100             return 0;
4101         if (!parseCubicBezierTimingFunctionValue(args, y1))
4102             return 0;
4103         if (!parseCubicBezierTimingFunctionValue(args, x2))
4104             return 0;
4105         if (!parseCubicBezierTimingFunctionValue(args, y2))
4106             return 0;
4107
4108         return CSSCubicBezierTimingFunctionValue::create(x1, y1, x2, y2);
4109     }
4110
4111     return 0;
4112 }
4113
4114 bool CSSParser::parseAnimationProperty(CSSPropertyID propId, RefPtr<CSSValue>& result)
4115 {
4116     RefPtr<CSSValueList> values;
4117     CSSParserValue* val;
4118     RefPtr<CSSValue> value;
4119     bool allowComma = false;
4120
4121     result = 0;
4122
4123     while ((val = m_valueList->current())) {
4124         RefPtr<CSSValue> currValue;
4125         if (allowComma) {
4126             if (!isComma(val))
4127                 return false;
4128             m_valueList->next();
4129             allowComma = false;
4130         }
4131         else {
4132             switch (propId) {
4133                 case CSSPropertyWebkitAnimationDelay:
4134                 case CSSPropertyWebkitTransitionDelay:
4135                     currValue = parseAnimationDelay();
4136                     if (currValue)
4137                         m_valueList->next();
4138                     break;
4139                 case CSSPropertyWebkitAnimationDirection:
4140                     currValue = parseAnimationDirection();
4141                     if (currValue)
4142                         m_valueList->next();
4143                     break;
4144                 case CSSPropertyWebkitAnimationDuration:
4145                 case CSSPropertyWebkitTransitionDuration:
4146                     currValue = parseAnimationDuration();
4147                     if (currValue)
4148                         m_valueList->next();
4149                     break;
4150                 case CSSPropertyWebkitAnimationFillMode:
4151                     currValue = parseAnimationFillMode();
4152                     if (currValue)
4153                         m_valueList->next();
4154                     break;
4155                 case CSSPropertyWebkitAnimationIterationCount:
4156                     currValue = parseAnimationIterationCount();
4157                     if (currValue)
4158                         m_valueList->next();
4159                     break;
4160                 case CSSPropertyWebkitAnimationName:
4161                     currValue = parseAnimationName();
4162                     if (currValue)
4163                         m_valueList->next();
4164                     break;
4165                 case CSSPropertyWebkitAnimationPlayState:
4166                     currValue = parseAnimationPlayState();
4167                     if (currValue)
4168                         m_valueList->next();
4169                     break;
4170                 case CSSPropertyWebkitTransitionProperty:
4171                     currValue = parseAnimationProperty();
4172                     if (currValue)
4173                         m_valueList->next();
4174                     break;
4175                 case CSSPropertyWebkitAnimationTimingFunction:
4176                 case CSSPropertyWebkitTransitionTimingFunction:
4177                     currValue = parseAnimationTimingFunction();
4178                     if (currValue)
4179                         m_valueList->next();
4180                     break;
4181                 default:
4182                     ASSERT_NOT_REACHED();
4183                     return false;
4184             }
4185
4186             if (!currValue)
4187                 return false;
4188
4189             if (value && !values) {
4190                 values = CSSValueList::createCommaSeparated();
4191                 values->append(value.release());
4192             }
4193
4194             if (values)
4195                 values->append(currValue.release());
4196             else
4197                 value = currValue.release();
4198
4199             allowComma = true;
4200         }
4201
4202         // When parsing the 'transition' shorthand property, we let it handle building up the lists for all
4203         // properties.
4204         if (inShorthand())
4205             break;
4206     }
4207
4208     if (values && values->length()) {
4209         result = values.release();
4210         return true;
4211     }
4212     if (value) {
4213         result = value.release();
4214         return true;
4215     }
4216     return false;
4217 }
4218
4219 bool CSSParser::parseGridTrackList(CSSPropertyID propId, bool important)
4220 {
4221     CSSParserValue* value = m_valueList->current();
4222     if (value->id == CSSValueNone) {
4223         if (m_valueList->next())
4224             return false;
4225
4226         addProperty(propId, cssValuePool().createIdentifierValue(value->id), important);
4227         return true;
4228     }
4229
4230     RefPtr<CSSValueList> values = CSSValueList::createSpaceSeparated();
4231     while (value) {
4232         bool valid = validUnit(value, FLength | FPercent) || value->id == CSSValueAuto;
4233         if (!valid)
4234             return false;
4235
4236         RefPtr<CSSPrimitiveValue> primitiveValue = value->id == CSSValueAuto ? cssValuePool().createIdentifierValue(CSSValueAuto) : createPrimitiveNumericValue(value);
4237         values->append(primitiveValue.release());
4238         value = m_valueList->next();
4239     }
4240     addProperty(propId, values.release(), important);
4241     return true;
4242 }
4243
4244
4245 #if ENABLE(DASHBOARD_SUPPORT)
4246
4247 #define DASHBOARD_REGION_NUM_PARAMETERS  6
4248 #define DASHBOARD_REGION_SHORT_NUM_PARAMETERS  2
4249
4250 static CSSParserValue* skipCommaInDashboardRegion(CSSParserValueList *args)
4251 {
4252     if (args->size() == (DASHBOARD_REGION_NUM_PARAMETERS*2-1) ||
4253          args->size() == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
4254         CSSParserValue* current = args->current();
4255         if (current->unit == CSSParserValue::Operator && current->iValue == ',')
4256             return args->next();
4257     }
4258     return args->current();
4259 }
4260
4261 bool CSSParser::parseDashboardRegions(CSSPropertyID propId, bool important)
4262 {
4263     bool valid = true;
4264
4265     CSSParserValue* value = m_valueList->current();
4266
4267     if (value->id == CSSValueNone) {
4268         if (m_valueList->next())
4269             return false;
4270         addProperty(propId, cssValuePool().createIdentifierValue(value->id), important);
4271         return valid;
4272     }
4273
4274     RefPtr<DashboardRegion> firstRegion = DashboardRegion::create();
4275     DashboardRegion* region = 0;
4276
4277     while (value) {
4278         if (region == 0) {
4279             region = firstRegion.get();
4280         } else {
4281             RefPtr<DashboardRegion> nextRegion = DashboardRegion::create();
4282             region->m_next = nextRegion;
4283             region = nextRegion.get();
4284         }
4285
4286         if (value->unit != CSSParserValue::Function) {
4287             valid = false;
4288             break;
4289         }
4290
4291         // Commas count as values, so allow:
4292         // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
4293         // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
4294         // also allow
4295         // dashboard-region(label, type) or dashboard-region(label type)
4296         // dashboard-region(label, type) or dashboard-region(label type)
4297         CSSParserValueList* args = value->function->args.get();
4298         if (!equalIgnoringCase(value->function->name, "dashboard-region(") || !args) {
4299             valid = false;
4300             break;
4301         }
4302
4303         int numArgs = args->size();
4304         if ((numArgs != DASHBOARD_REGION_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_NUM_PARAMETERS*2-1)) &&
4305             (numArgs != DASHBOARD_REGION_SHORT_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1))) {
4306             valid = false;
4307             break;
4308         }
4309
4310         // First arg is a label.
4311         CSSParserValue* arg = args->current();
4312         if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
4313             valid = false;
4314             break;
4315         }
4316
4317         region->m_label = arg->string;
4318
4319         // Second arg is a type.
4320         arg = args->next();
4321         arg = skipCommaInDashboardRegion(args);
4322         if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
4323             valid = false;
4324             break;
4325         }
4326
4327         if (equalIgnoringCase(arg->string, "circle"))
4328             region->m_isCircle = true;
4329         else if (equalIgnoringCase(arg->string, "rectangle"))
4330             region->m_isRectangle = true;
4331         else {
4332             valid = false;
4333             break;
4334         }
4335
4336         region->m_geometryType = arg->string;
4337
4338         if (numArgs == DASHBOARD_REGION_SHORT_NUM_PARAMETERS || numArgs == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
4339             // This originally used CSSValueInvalid by accident. It might be more logical to use something else.
4340             RefPtr<CSSPrimitiveValue> amount = cssValuePool().createIdentifierValue(CSSValueInvalid);
4341
4342             region->setTop(amount);
4343             region->setRight(amount);
4344             region->setBottom(amount);
4345             region->setLeft(amount);
4346         } else {
4347             // Next four arguments must be offset numbers
4348             int i;
4349             for (i = 0; i < 4; i++) {
4350                 arg = args->next();
4351                 arg = skipCommaInDashboardRegion(args);
4352
4353                 valid = arg->id == CSSValueAuto || validUnit(arg, FLength);
4354                 if (!valid)
4355                     break;
4356
4357                 RefPtr<CSSPrimitiveValue> amount = arg->id == CSSValueAuto ?
4358                     cssValuePool().createIdentifierValue(CSSValueAuto) :
4359                     createPrimitiveNumericValue(arg);
4360
4361                 if (i == 0)
4362                     region->setTop(amount);
4363                 else if (i == 1)
4364                     region->setRight(amount);
4365                 else if (i == 2)
4366                     region->setBottom(amount);
4367                 else
4368                     region->setLeft(amount);
4369             }
4370         }
4371
4372         if (args->next())
4373             return false;
4374
4375         value = m_valueList->next();
4376     }
4377
4378     if (valid)
4379         addProperty(propId, cssValuePool().createValue(firstRegion.release()), important);
4380
4381     return valid;
4382 }
4383
4384 #endif /* ENABLE(DASHBOARD_SUPPORT) */
4385
4386 PassRefPtr<CSSValue> CSSParser::parseCounterContent(CSSParserValueList* args, bool counters)
4387 {
4388     unsigned numArgs = args->size();
4389     if (counters && numArgs != 3 && numArgs != 5)
4390         return 0;
4391     if (!counters && numArgs != 1 && numArgs != 3)
4392         return 0;
4393
4394     CSSParserValue* i = args->current();
4395     if (i->unit != CSSPrimitiveValue::CSS_IDENT)
4396         return 0;
4397     RefPtr<CSSPrimitiveValue> identifier = createPrimitiveStringValue(i);
4398
4399     RefPtr<CSSPrimitiveValue> separator;
4400     if (!counters)
4401         separator = cssValuePool().createValue(String(), CSSPrimitiveValue::CSS_STRING);
4402     else {
4403         i = args->next();
4404         if (i->unit != CSSParserValue::Operator || i->iValue != ',')
4405             return 0;
4406
4407         i = args->next();
4408         if (i->unit != CSSPrimitiveValue::CSS_STRING)
4409             return 0;
4410
4411         separator = createPrimitiveStringValue(i);
4412     }
4413
4414     RefPtr<CSSPrimitiveValue> listStyle;
4415     i = args->next();
4416     if (!i) // Make the list style default decimal
4417         listStyle = cssValuePool().createIdentifierValue(CSSValueDecimal);
4418     else {
4419         if (i->unit != CSSParserValue::Operator || i->iValue != ',')
4420             return 0;
4421
4422         i = args->next();
4423         if (i->unit != CSSPrimitiveValue::CSS_IDENT)
4424             return 0;
4425
4426         int listStyleID = 0;
4427         if (i->id == CSSValueNone || (i->id >= CSSValueDisc && i->id <= CSSValueKatakanaIroha))
4428             listStyleID = i->id;
4429         else
4430             return 0;
4431
4432         listStyle = cssValuePool().createIdentifierValue(listStyleID);
4433     }
4434
4435     return cssValuePool().createValue(Counter::create(identifier.release(), listStyle.release(), separator.release()));
4436 }
4437
4438 bool CSSParser::parseClipShape(CSSPropertyID propId, bool important)
4439 {
4440     CSSParserValue* value = m_valueList->current();
4441     CSSParserValueList* args = value->function->args.get();
4442
4443     if (!equalIgnoringCase(value->function->name, "rect(") || !args)
4444         return false;
4445
4446     // rect(t, r, b, l) || rect(t r b l)
4447     if (args->size() != 4 && args->size() != 7)
4448         return false;
4449     RefPtr<Rect> rect = Rect::create();
4450     bool valid = true;
4451     int i = 0;
4452     CSSParserValue* a = args->current();
4453     while (a) {
4454         valid = a->id == CSSValueAuto || validUnit(a, FLength);
4455         if (!valid)
4456             break;
4457         RefPtr<CSSPrimitiveValue> length = a->id == CSSValueAuto ?
4458             cssValuePool().createIdentifierValue(CSSValueAuto) :
4459             createPrimitiveNumericValue(a);
4460         if (i == 0)
4461             rect->setTop(length);
4462         else if (i == 1)
4463             rect->setRight(length);
4464         else if (i == 2)
4465             rect->setBottom(length);
4466         else
4467             rect->setLeft(length);
4468         a = args->next();
4469         if (a && args->size() == 7) {
4470             if (a->unit == CSSParserValue::Operator && a->iValue == ',') {
4471                 a = args->next();
4472             } else {
4473                 valid = false;
4474                 break;
4475             }
4476         }
4477         i++;
4478     }
4479     if (valid) {
4480         addProperty(propId, cssValuePool().createValue(rect.release()), important);
4481         m_valueList->next();
4482         return true;
4483     }
4484     return false;
4485 }
4486
4487 PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapeRectangle(CSSParserValueList* args)
4488 {
4489     ASSERT(args);
4490
4491     // rect(x, y, width, height, [[rx], ry])
4492     if (args->size() != 7 && args->size() != 9 && args->size() != 11)
4493         return 0;
4494
4495     RefPtr<CSSBasicShapeRectangle> shape = CSSBasicShapeRectangle::create();
4496
4497     unsigned argumentNumber = 0;
4498     CSSParserValue* argument = args->current();
4499     while (argument) {
4500         Units unitFlags = FLength | FPercent;
4501         if (argumentNumber > 1) {
4502             // Arguments width, height, rx, and ry cannot be negative.
4503             unitFlags = unitFlags | FNonNeg;
4504         }
4505         if (!validUnit(argument, unitFlags))
4506             return 0;
4507
4508         RefPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument);
4509         ASSERT(argumentNumber < 6);
4510         switch (argumentNumber) {
4511         case 0:
4512             shape->setX(length);
4513             break;
4514         case 1:
4515             shape->setY(length);
4516             break;
4517         case 2:
4518             shape->setWidth(length);
4519             break;
4520         case 3:
4521             shape->setHeight(length);
4522             break;
4523         case 4:
4524             shape->setRadiusX(length);
4525             break;
4526         case 5:
4527             shape->setRadiusY(length);
4528             break;
4529         }
4530         argument = args->next();
4531         if (argument) {
4532             if (!isComma(argument))
4533                 return 0;
4534
4535             argument = args->next();
4536         }
4537         argumentNumber++;
4538     }
4539
4540     if (argumentNumber < 4)
4541         return 0;
4542     return shape;
4543 }
4544
4545 PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapeCircle(CSSParserValueList* args)
4546 {
4547     ASSERT(args);
4548
4549     // circle(centerX, centerY, radius)
4550     if (args->size() != 5)
4551         return 0;
4552
4553     RefPtr<CSSBasicShapeCircle> shape = CSSBasicShapeCircle::create();
4554
4555     unsigned argumentNumber = 0;
4556     CSSParserValue* argument = args->current();
4557     while (argument) {
4558         Units unitFlags = FLength | FPercent;
4559         if (argumentNumber == 2) {
4560             // Argument radius cannot be negative.
4561             unitFlags = unitFlags | FNonNeg;
4562         }
4563
4564         if (!validUnit(argument, unitFlags))
4565             return 0;
4566
4567         RefPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument);
4568         ASSERT(argumentNumber < 3);
4569         switch (argumentNumber) {
4570         case 0:
4571             shape->setCenterX(length);
4572             break;
4573         case 1:
4574             shape->setCenterY(length);
4575             break;
4576         case 2:
4577             shape->setRadius(length);
4578             break;
4579         }
4580
4581         argument = args->next();
4582         if (argument) {
4583             if (!isComma(argument))
4584                 return 0;
4585             argument = args->next();
4586         }
4587         argumentNumber++;
4588     }
4589
4590     if (argumentNumber < 3)
4591         return 0;
4592     return shape;
4593 }
4594
4595 PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapeEllipse(CSSParserValueList* args)
4596 {
4597     ASSERT(args);
4598
4599     // ellipse(centerX, centerY, radiusX, radiusY)
4600     if (args->size() != 7)
4601         return 0;
4602
4603     RefPtr<CSSBasicShapeEllipse> shape = CSSBasicShapeEllipse::create();
4604     unsigned argumentNumber = 0;
4605     CSSParserValue* argument = args->current();
4606     while (argument) {
4607         Units unitFlags = FLength | FPercent;
4608         if (argumentNumber > 1) {
4609             // Arguments radiusX and radiusY cannot be negative.
4610             unitFlags = unitFlags | FNonNeg;
4611         }
4612         if (!validUnit(argument, unitFlags))
4613             return 0;
4614
4615         RefPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument);
4616         ASSERT(argumentNumber < 4);
4617         switch (argumentNumber) {
4618         case 0:
4619             shape->setCenterX(length);
4620             break;
4621         case 1:
4622             shape->setCenterY(length);
4623             break;
4624         case 2:
4625             shape->setRadiusX(length);
4626             break;
4627         case 3:
4628             shape->setRadiusY(length);
4629             break;
4630         }
4631
4632         argument = args->next();
4633         if (argument) {
4634             if (!isComma(argument))
4635                 return 0;
4636             argument = args->next();
4637         }
4638         argumentNumber++;
4639     }
4640
4641     if (argumentNumber < 4)
4642         return 0;
4643     return shape;
4644 }
4645
4646 PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapePolygon(CSSParserValueList* args)
4647 {
4648     ASSERT(args);
4649
4650     unsigned size = args->size();
4651     if (!size)
4652         return 0;
4653
4654     RefPtr<CSSBasicShapePolygon> shape = CSSBasicShapePolygon::create();
4655
4656     CSSParserValue* argument = args->current();
4657     if (argument->id == CSSValueEvenodd || argument->id == CSSValueNonzero) {
4658         shape->setWindRule(argument->id == CSSValueEvenodd ? RULE_EVENODD : RULE_NONZERO);
4659
4660         if (!isComma(args->next()))
4661             return 0;
4662
4663         argument = args->next();
4664         size -= 2;
4665     }
4666
4667     // <length> <length>, ... <length> <length> -> each pair has 3 elements except the last one
4668     if (!size || (size % 3) - 2)
4669         return 0;
4670
4671     CSSParserValue* argumentX = argument;
4672     while (argumentX) {
4673         if (!validUnit(argumentX, FLength | FPercent))
4674             return 0;
4675
4676         CSSParserValue* argumentY = args->next();
4677         if (!argumentY || !validUnit(argumentY, FLength | FPercent))
4678             return 0;
4679
4680         RefPtr<CSSPrimitiveValue> xLength = createPrimitiveNumericValue(argumentX);
4681         RefPtr<CSSPrimitiveValue> yLength = createPrimitiveNumericValue(argumentY);
4682
4683         shape->appendPoint(xLength.release(), yLength.release());
4684
4685         CSSParserValue* commaOrNull = args->next();
4686         if (!commaOrNull)
4687             argumentX = 0;
4688         else if (!isComma(commaOrNull)) 
4689             return 0;
4690         else 
4691             argumentX = args->next();
4692     }
4693
4694     return shape;
4695 }
4696
4697 bool CSSParser::parseBasicShape(CSSPropertyID propId, bool important)
4698 {
4699     CSSParserValue* value = m_valueList->current();
4700     ASSERT(value->unit == CSSParserValue::Function);
4701     CSSParserValueList* args = value->function->args.get();
4702
4703     if (!args)
4704         return false;
4705
4706     RefPtr<CSSBasicShape> shape;
4707     if (equalIgnoringCase(value->function->name, "rectangle("))
4708         shape = parseBasicShapeRectangle(args);
4709     else if (equalIgnoringCase(value->function->name, "circle("))
4710         shape = parseBasicShapeCircle(args);
4711     else if (equalIgnoringCase(value->function->name, "ellipse("))
4712         shape = parseBasicShapeEllipse(args);
4713     else if (equalIgnoringCase(value->function->name, "polygon("))
4714         shape = parseBasicShapePolygon(args);
4715
4716     if (!shape)
4717         return false;
4718
4719     addProperty(propId, cssValuePool().createValue(shape.release()), important);
4720     m_valueList->next();
4721     return true;
4722 }
4723
4724 // [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family'
4725 bool CSSParser::parseFont(bool important)
4726 {
4727     // Let's check if there is an inherit or initial somewhere in the shorthand.
4728     for (unsigned i = 0; i < m_valueList->size(); ++i) {
4729         if (m_valueList->valueAt(i)->id == CSSValueInherit || m_valueList->valueAt(i)->id == CSSValueInitial)
4730             return false;
4731     }
4732
4733     ShorthandScope scope(this, CSSPropertyFont);
4734     // Optional font-style, font-variant and font-weight.
4735     bool fontStyleParsed = false;
4736     bool fontVariantParsed = false;
4737     bool fontWeightParsed = false;
4738     CSSParserValue* value;
4739     while ((value = m_valueList->current())) {
4740         if (!fontStyleParsed && isValidKeywordPropertyAndValue(CSSPropertyFontStyle, value->id, m_context)) {
4741             addProperty(CSSPropertyFontStyle, cssValuePool().createIdentifierValue(value->id), important);
4742             fontStyleParsed = true;
4743         } else if (!fontVariantParsed && (value->id == CSSValueNormal || value->id == CSSValueSmallCaps)) {
4744             // Font variant in the shorthand is particular, it only accepts normal or small-caps.
4745             addProperty(CSSPropertyFontVariant, cssValuePool().createIdentifierValue(value->id), important);
4746             fontVariantParsed = true;
4747         } else if (!fontWeightParsed && parseFontWeight(important))
4748             fontWeightParsed = true;
4749         else
4750             break;
4751         m_valueList->next();
4752     }
4753
4754     if (!value)
4755         return false;
4756
4757     if (!fontStyleParsed)
4758         addProperty(CSSPropertyFontStyle, cssValuePool().createIdentifierValue(CSSValueNormal), important, true);
4759     if (!fontVariantParsed)
4760         addProperty(CSSPropertyFontVariant, cssValuePool().createIdentifierValue(CSSValueNormal), important, true);
4761     if (!fontWeightParsed)
4762         addProperty(CSSPropertyFontWeight, cssValuePool().createIdentifierValue(CSSValueNormal), important, true);
4763
4764     // Now a font size _must_ come.
4765     // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
4766     if (!parseFontSize(important))
4767         return false;
4768
4769     value = m_valueList->current();
4770     if (!value)
4771         return false;
4772
4773     if (value->unit == CSSParserValue::Operator && value->iValue == '/') {
4774         // The line-height property.
4775         value = m_valueList->next();
4776         if (!value)
4777             return false;
4778         if (!parseLineHeight(important))
4779             return false;
4780     } else
4781         addProperty(CSSPropertyLineHeight, cssValuePool().createIdentifierValue(CSSValueNormal), important, true);
4782
4783     // Font family must come now.
4784     RefPtr<CSSValue> parsedFamilyValue = parseFontFamily();
4785     if (!parsedFamilyValue)
4786         return false;
4787
4788     addProperty(CSSPropertyFontFamily, parsedFamilyValue.release(), important);
4789
4790     // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20110324/#font-prop requires that
4791     // "font-stretch", "font-size-adjust", and "font-kerning" be reset to their initial values
4792     // but we don't seem to support them at the moment. They should also be added here once implemented.
4793     if (m_valueList->current())
4794         return false;
4795
4796     return true;
4797 }
4798
4799 class FontFamilyValueBuilder {
4800 public:
4801     FontFamilyValueBuilder(CSSValueList* list)
4802         : m_list(list)
4803     {
4804     }
4805
4806     void add(const CSSParserString& string)
4807     {
4808         if (!m_builder.isEmpty())
4809             m_builder.append(' ');
4810         m_builder.append(string.characters, string.length);
4811     }
4812
4813     void commit()
4814     {
4815         if (m_builder.isEmpty())
4816             return;
4817         m_list->append(cssValuePool().createFontFamilyValue(m_builder.toString()));
4818         m_builder.clear();
4819     }
4820
4821 private:
4822     StringBuilder m_builder;
4823     CSSValueList* m_list;
4824 };
4825
4826 PassRefPtr<CSSValueList> CSSParser::parseFontFamily()
4827 {
4828     RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
4829     CSSParserValue* value = m_valueList->current();
4830
4831     FontFamilyValueBuilder familyBuilder(list.get());
4832     bool inFamily = false;
4833
4834     while (value) {
4835         if (value->id == CSSValueInitial || value->id == CSSValueInherit || value->id == CSSValueDefault)
4836             return 0;
4837         CSSParserValue* nextValue = m_valueList->next();
4838         bool nextValBreaksFont = !nextValue ||
4839                                  (nextValue->unit == CSSParserValue::Operator && nextValue->iValue == ',');
4840         bool nextValIsFontName = nextValue &&
4841             ((nextValue->id >= CSSValueSerif && nextValue->id <= CSSValueWebkitBody) ||
4842             (nextValue->unit == CSSPrimitiveValue::CSS_STRING || nextValue->unit == CSSPrimitiveValue::CSS_IDENT));
4843
4844         if (value->id >= CSSValueSerif && value->id <= CSSValueWebkitBody) {
4845             if (inFamily)
4846                 familyBuilder.add(value->string);
4847             else if (nextValBreaksFont || !nextValIsFontName)
4848                 list->append(cssValuePool().createIdentifierValue(value->id));
4849             else {
4850                 familyBuilder.commit();
4851                 familyBuilder.add(value->string);
4852                 inFamily = true;
4853             }
4854         } else if (value->unit == CSSPrimitiveValue::CSS_STRING) {
4855             // Strings never share in a family name.
4856             inFamily = false;
4857             familyBuilder.commit();
4858             list->append(cssValuePool().createFontFamilyValue(value->string));
4859         } else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
4860             if (inFamily)
4861                 familyBuilder.add(value->string);
4862             else if (nextValBreaksFont || !nextValIsFontName)
4863                 list->append(cssValuePool().createFontFamilyValue(value->string));
4864             else {
4865                 familyBuilder.commit();
4866                 familyBuilder.add(value->string);
4867                 inFamily = true;
4868             }
4869         } else {
4870             break;
4871         }
4872
4873         if (!nextValue)
4874             break;
4875
4876         if (nextValBreaksFont) {
4877             value = m_valueList->next();
4878             familyBuilder.commit();
4879             inFamily = false;
4880         }
4881         else if (nextValIsFontName)
4882             value = nextValue;
4883         else
4884             break;
4885     }
4886     familyBuilder.commit();
4887
4888     if (!list->length())
4889         list = 0;
4890     return list.release();
4891 }
4892
4893 bool CSSParser::parseLineHeight(bool important)
4894 {
4895     CSSParserValue* value = m_valueList->current();
4896     int id = value->id;
4897     bool validPrimitive = false;
4898     // normal | <number> | <length> | <percentage> | inherit
4899     if (id == CSSValueNormal)
4900         validPrimitive = true;
4901     else
4902         validPrimitive = (!id && validUnit(value, FNumber | FLength | FPercent | FNonNeg));
4903     if (validPrimitive && (!m_valueList->next() || inShorthand()))
4904         addProperty(CSSPropertyLineHeight, parseValidPrimitive(id, value), important);
4905     return validPrimitive;
4906 }
4907
4908 bool CSSParser::parseFontSize(bool important)
4909 {
4910     CSSParserValue* value = m_valueList->current();
4911     int id = value->id;
4912     bool validPrimitive = false;
4913     // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
4914     if (id >= CSSValueXxSmall && id <= CSSValueLarger)
4915         validPrimitive = true;
4916     else
4917         validPrimitive = validUnit(value, FLength | FPercent | FNonNeg);
4918     if (validPrimitive && (!m_valueList->next() || inShorthand()))
4919         addProperty(CSSPropertyFontSize, parseValidPrimitive(id, value), important);
4920     return validPrimitive;
4921 }
4922
4923 bool CSSParser::parseFontVariant(bool important)
4924 {
4925     RefPtr<CSSValueList> values;
4926     if (m_valueList->size() > 1)
4927         values = CSSValueList::createCommaSeparated();
4928     CSSParserValue* val;
4929     bool expectComma = false;
4930     while ((val = m_valueList->current())) {
4931         RefPtr<CSSPrimitiveValue> parsedValue;
4932         if (!expectComma) {
4933             expectComma = true;
4934             if (val->id == CSSValueNormal || val->id == CSSValueSmallCaps)
4935                 parsedValue = cssValuePool().createIdentifierValue(val->id);
4936             else if (val->id == CSSValueAll && !values) {
4937                 // 'all' is only allowed in @font-face and with no other values. Make a value list to
4938                 // indicate that we are in the @font-face case.
4939                 values = CSSValueList::createCommaSeparated();
4940                 parsedValue = cssValuePool().createIdentifierValue(val->id);
4941             }
4942         } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
4943             expectComma = false;
4944             m_valueList->next();
4945             continue;
4946         }
4947
4948         if (!parsedValue)
4949             return false;
4950
4951         m_valueList->next();
4952
4953         if (values)
4954             values->append(parsedValue.release());
4955         else {
4956             addProperty(CSSPropertyFontVariant, parsedValue.release(), important);
4957             return true;
4958         }
4959     }
4960
4961     if (values && values->length()) {
4962         m_hasFontFaceOnlyValues = true;
4963         addProperty(CSSPropertyFontVariant, values.release(), important);
4964         return true;
4965     }
4966
4967     return false;
4968 }
4969
4970 bool CSSParser::parseFontWeight(bool important)
4971 {
4972     CSSParserValue* value = m_valueList->current();
4973     if ((value->id >= CSSValueNormal) && (value->id <= CSSValue900)) {
4974         addProperty(CSSPropertyFontWeight, cssValuePool().createIdentifierValue(value->id), important);
4975         return true;
4976     }
4977     if (validUnit(value, FInteger | FNonNeg, CSSQuirksMode)) {
4978         int weight = static_cast<int>(value->fValue);
4979         if (!(weight % 100) && weight >= 100 && weight <= 900) {
4980             addProperty(CSSPropertyFontWeight, cssValuePool().createIdentifierValue(CSSValue100 + weight / 100 - 1), important);
4981             return true;
4982         }
4983     }
4984     return false;
4985 }
4986
4987 bool CSSParser::parseFontFaceSrcURI(CSSValueList* valueList)
4988 {
4989     RefPtr<CSSFontFaceSrcValue> uriValue(CSSFontFaceSrcValue::create(completeURL(m_valueList->current()->string)));
4990
4991     CSSParserValue* value = m_valueList->next();
4992     if (!value) {
4993         valueList->append(uriValue.release());
4994         return true;
4995     }
4996     if (value->unit == CSSParserValue::Operator && value->iValue == ',') {
4997         m_valueList->next();
4998         valueList->append(uriValue.release());
4999         return true;
5000     }
5001
5002     if (value->unit != CSSParserValue::Function || !equalIgnoringCase(value->function->name, "format("))
5003         return false;
5004
5005     // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20111004/ says that format() contains a comma-separated list of strings,
5006     // but CSSFontFaceSrcValue stores only one format. Allowing one format for now.
5007     CSSParserValueList* args = value->function->args.get();
5008     if (!args || args->size() != 1 || (args->current()->unit != CSSPrimitiveValue::CSS_STRING && args->current()->unit != CSSPrimitiveValue::CSS_IDENT))
5009         return false;
5010     uriValue->setFormat(args->current()->string);
5011     valueList->append(uriValue.release());
5012     value = m_valueList->next();
5013     if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
5014         m_valueList->next();
5015     return true;
5016 }
5017
5018 bool CSSParser::parseFontFaceSrcLocal(CSSValueList* valueList)
5019 {
5020     CSSParserValueList* args = m_valueList->current()->function->args.get();
5021     if (!args || !args->size())
5022         return false;
5023
5024     if (args->size() == 1 && args->current()->unit == CSSPrimitiveValue::CSS_STRING)
5025         valueList->append(CSSFontFaceSrcValue::createLocal(args->current()->string));
5026     else if (args->current()->unit == CSSPrimitiveValue::CSS_IDENT) {
5027         StringBuilder builder;
5028         for (CSSParserValue* localValue = args->current(); localValue; localValue = args->next()) {
5029             if (localValue->unit != CSSPrimitiveValue::CSS_IDENT)
5030                 return false;
5031             if (!builder.isEmpty())
5032                 builder.append(' ');
5033             builder.append(localValue->string);
5034         }
5035         valueList->append(CSSFontFaceSrcValue::createLocal(builder.toString()));
5036     } else
5037         return false;
5038
5039     if (CSSParserValue* value = m_valueList->next()) {
5040         if (value->unit == CSSParserValue::Operator && value->iValue == ',')
5041             m_valueList->next();
5042     }
5043     return true;
5044 }
5045
5046 bool CSSParser::parseFontFaceSrc()
5047 {
5048     RefPtr<CSSValueList> values(CSSValueList::createCommaSeparated());
5049
5050     while (CSSParserValue* value = m_valueList->current()) {
5051         if (value->unit == CSSPrimitiveValue::CSS_URI) {
5052             if (!parseFontFaceSrcURI(values.get()))
5053                 return false;
5054         } else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "local(")) {
5055             if (!parseFontFaceSrcLocal(values.get()))
5056                 return false;
5057         } else
5058             return false;
5059     }
5060     if (!values->length())
5061         return false;
5062
5063     addProperty(CSSPropertySrc, values.release(), m_important);
5064     m_valueList->next();
5065     return true;
5066 }
5067
5068 bool CSSParser::parseFontFaceUnicodeRange()
5069 {
5070     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
5071     bool failed = false;
5072     bool operatorExpected = false;
5073     for (; m_valueList->current(); m_valueList->next(), operatorExpected = !operatorExpected) {
5074         if (operatorExpected) {
5075             if (m_valueList->current()->unit == CSSParserValue::Operator && m_valueList->current()->iValue == ',')
5076                 continue;
5077             failed = true;
5078             break;
5079         }
5080         if (m_valueList->current()->unit != CSSPrimitiveValue::CSS_UNICODE_RANGE) {
5081             failed = true;
5082             break;
5083         }
5084
5085         String rangeString = m_valueList->current()->string;
5086         UChar32 from = 0;
5087         UChar32 to = 0;
5088         unsigned length = rangeString.length();
5089
5090         if (length < 3) {
5091             failed = true;
5092             break;
5093         }
5094
5095         unsigned i = 2;
5096         while (i < length) {
5097             UChar c = rangeString[i];
5098             if (c == '-' || c == '?')
5099                 break;
5100             from *= 16;
5101             if (c >= '0' && c <= '9')
5102                 from += c - '0';
5103             else if (c >= 'A' && c <= 'F')
5104                 from += 10 + c - 'A';
5105             else if (c >= 'a' && c <= 'f')
5106                 from += 10 + c - 'a';
5107             else {
5108                 failed = true;
5109                 break;
5110             }
5111             i++;
5112         }
5113         if (failed)
5114             break;
5115
5116         if (i == length)
5117             to = from;
5118         else if (rangeString[i] == '?') {
5119             unsigned span = 1;
5120             while (i < length && rangeString[i] == '?') {
5121                 span *= 16;
5122                 from *= 16;
5123                 i++;
5124             }
5125             if (i < length)
5126                 failed = true;
5127             to = from + span - 1;
5128         } else {
5129             if (length < i + 2) {
5130                 failed = true;
5131                 break;
5132             }
5133             i++;
5134             while (i < length) {
5135                 UChar c = rangeString[i];
5136                 to *= 16;
5137                 if (c >= '0' && c <= '9')
5138                     to += c - '0';
5139                 else if (c >= 'A' && c <= 'F')
5140                     to += 10 + c - 'A';
5141                 else if (c >= 'a' && c <= 'f')
5142                     to += 10 + c - 'a';
5143                 else {
5144                     failed = true;
5145                     break;
5146                 }
5147                 i++;
5148             }
5149             if (failed)
5150                 break;
5151         }
5152         if (from <= to)
5153             values->append(CSSUnicodeRangeValue::create(from, to));
5154     }
5155     if (failed || !values->length())
5156         return false;
5157     addProperty(CSSPropertyUnicodeRange, values.release(), m_important);
5158     return true;
5159 }
5160
5161 // Returns the number of characters which form a valid double
5162 // and are terminated by the given terminator character
5163 static int checkForValidDouble(const UChar* string, const UChar* end, const char terminator)
5164 {
5165     int length = end - string;
5166     if (length < 1)
5167         return 0;
5168
5169     bool decimalMarkSeen = false;
5170     int processedLength = 0;
5171
5172     for (int i = 0; i < length; ++i) {
5173         if (string[i] == terminator) {
5174             processedLength = i;
5175             break;
5176         }
5177         if (!isASCIIDigit(string[i])) {
5178             if (!decimalMarkSeen && string[i] == '.')
5179                 decimalMarkSeen = true;
5180             else
5181                 return 0;
5182         }
5183     }
5184
5185     if (decimalMarkSeen && processedLength == 1)
5186         return 0;
5187
5188     return processedLength;
5189 }
5190
5191 // Returns the number of characters consumed for parsing a valid double
5192 // terminated by the given terminator character
5193 static int parseDouble(const UChar* string, const UChar* end, const char terminator, double& value)
5194 {
5195     int length = checkForValidDouble(string, end, terminator);
5196     if (!length)
5197         return 0;
5198
5199     int position = 0;
5200     double localValue = 0;
5201
5202     // The consumed characters here are guaranteed to be
5203     // ASCII digits with or without a decimal mark
5204     for (; position < length; ++position) {
5205         if (string[position] == '.')
5206             break;
5207         localValue = localValue * 10 + string[position] - '0';
5208     }
5209
5210     if (++position == length) {
5211         value = localValue;
5212         return length;
5213     }
5214
5215     double fraction = 0;
5216     double scale = 1;
5217
5218     while (position < length && scale < MAX_SCALE) {
5219         fraction = fraction * 10 + string[position++] - '0';
5220         scale *= 10;
5221     }
5222
5223     value = localValue + fraction / scale;
5224     return length;
5225 }
5226
5227 static bool parseColorIntOrPercentage(const UChar*& string, const UChar* end, const char terminator, CSSPrimitiveValue::UnitTypes& expect, int& value)
5228 {
5229     const UChar* current = string;
5230     double localValue = 0;
5231     bool negative = false;
5232     while (current != end && isHTMLSpace(*current))
5233         current++;
5234     if (current != end && *current == '-') {
5235         negative = true;
5236         current++;
5237     }
5238     if (current == end || !isASCIIDigit(*current))
5239         return false;
5240     while (current != end && isASCIIDigit(*current)) {
5241         double newValue = localValue * 10 + *current++ - '0';
5242         if (newValue >= 255) {
5243             // Clamp values at 255.
5244             localValue = 255;
5245             while (current != end && isASCIIDigit(*current))
5246                 ++current;
5247             break;
5248         }
5249         localValue = newValue;
5250     }
5251
5252     if (current == end)
5253         return false;
5254
5255     if (expect == CSSPrimitiveValue::CSS_NUMBER && (*current == '.' || *current == '%'))
5256         return false;
5257
5258     if (*current == '.') {
5259         // We already parsed the integral part, try to parse
5260         // the fraction part of the percentage value.
5261         double percentage = 0;
5262         int numCharactersParsed = parseDouble(current, end, '%', percentage);
5263         if (!numCharactersParsed)
5264             return false;
5265         current += numCharactersParsed;
5266         if (*current != '%')
5267             return false;
5268         localValue += percentage;
5269     }
5270
5271     if (expect == CSSPrimitiveValue::CSS_PERCENTAGE && *current != '%')
5272         return false;
5273
5274     if (*current == '%') {
5275         expect = CSSPrimitiveValue::CSS_PERCENTAGE;
5276         localValue = localValue / 100.0 * 256.0;
5277         // Clamp values at 255 for percentages over 100%
5278         if (localValue > 255)
5279             localValue = 255;
5280         current++;
5281     } else
5282         expect = CSSPrimitiveValue::CSS_NUMBER;
5283
5284     while (current != end && isHTMLSpace(*current))
5285         current++;
5286     if (current == end || *current++ != terminator)
5287         return false;
5288     // Clamp negative values at zero.
5289     value = negative ? 0 : static_cast<int>(localValue);
5290     string = current;
5291     return true;
5292 }
5293
5294 static inline bool isTenthAlpha(const UChar* string, const int length)
5295 {
5296     // "0.X"
5297     if (length == 3 && string[0] == '0' && string[1] == '.' && isASCIIDigit(string[2]))
5298         return true;
5299
5300     // ".X"
5301     if (length == 2 && string[0] == '.' && isASCIIDigit(string[1]))
5302         return true;
5303
5304     return false;
5305 }
5306
5307 static inline bool parseAlphaValue(const UChar*& string, const UChar* end, const char terminator, int& value)
5308 {
5309     while (string != end && isHTMLSpace(*string))
5310         string++;
5311
5312     bool negative = false;
5313
5314     if (string != end && *string == '-') {
5315         negative = true;
5316         string++;
5317     }
5318
5319     value = 0;
5320
5321     int length = end - string;
5322     if (length < 2)
5323         return false;
5324
5325     if (string[length - 1] != terminator || !isASCIIDigit(string[length - 2]))
5326         return false;
5327
5328     if (string[0] != '0' && string[0] != '1' && string[0] != '.') {
5329         if (checkForValidDouble(string, end, terminator)) {
5330             value = negative ? 0 : 255;
5331             string = end;
5332             return true;
5333         }
5334         return false;
5335     }
5336
5337     if (length == 2 && string[0] != '.') {
5338         value = !negative && string[0] == '1' ? 255 : 0;
5339         string = end;
5340         return true;
5341     }
5342
5343     if (isTenthAlpha(string, length - 1)) {
5344         static const int tenthAlphaValues[] = { 0, 25, 51, 76, 102, 127, 153, 179, 204, 230 };
5345         value = negative ? 0 : tenthAlphaValues[string[length - 2] - '0'];
5346         string = end;
5347         return true;
5348     }
5349
5350     double alpha = 0;
5351     if (!parseDouble(string, end, terminator, alpha))
5352         return false;
5353     value = negative ? 0 : static_cast<int>(alpha * nextafter(256.0, 0.0));
5354     string = end;
5355     return true;
5356 }
5357
5358 static inline bool mightBeRGBA(const UChar* characters, unsigned length)
5359 {
5360     if (length < 5)
5361         return false;
5362     return characters[4] == '('
5363         && isASCIIAlphaCaselessEqual(characters[0], 'r')
5364         && isASCIIAlphaCaselessEqual(characters[1], 'g')
5365         && isASCIIAlphaCaselessEqual(characters[2], 'b')
5366         && isASCIIAlphaCaselessEqual(characters[3], 'a');
5367 }
5368
5369 static inline bool mightBeRGB(const UChar* characters, unsigned length)
5370 {
5371     if (length < 4)
5372         return false;
5373     return characters[3] == '('
5374         && isASCIIAlphaCaselessEqual(characters[0], 'r')
5375         && isASCIIAlphaCaselessEqual(characters[1], 'g')
5376         && isASCIIAlphaCaselessEqual(characters[2], 'b');
5377 }
5378
5379 bool CSSParser::fastParseColor(RGBA32& rgb, const String& name, bool strict)
5380 {
5381     const UChar* characters = name.characters();
5382     unsigned length = name.length();
5383     CSSPrimitiveValue::UnitTypes expect = CSSPrimitiveValue::CSS_UNKNOWN;
5384
5385     if (!strict && length >= 3) {
5386         if (name[0] == '#') {
5387             if (Color::parseHexColor(characters + 1, length - 1, rgb))
5388                 return true;
5389         } else {
5390             if (Color::parseHexColor(characters, length, rgb))
5391                 return true;
5392         }
5393     }
5394
5395     // Try rgba() syntax.
5396     if (mightBeRGBA(characters, length)) {
5397         const UChar* current = characters + 5;
5398         const UChar* end = characters + length;
5399         int red;
5400         int green;
5401         int blue;
5402         int alpha;
5403
5404         if (!parseColorIntOrPercentage(current, end, ',', expect, red))
5405             return false;
5406         if (!parseColorIntOrPercentage(current, end, ',', expect, green))
5407             return false;
5408         if (!parseColorIntOrPercentage(current, end, ',', expect, blue))
5409             return false;
5410         if (!parseAlphaValue(current, end, ')', alpha))
5411             return false;
5412         if (current != end)
5413             return false;
5414         rgb = makeRGBA(red, green, blue, alpha);
5415         return true;
5416     }
5417
5418     // Try rgb() syntax.
5419     if (mightBeRGB(characters, length)) {
5420         const UChar* current = characters + 4;
5421         const UChar* end = characters + length;
5422         int red;
5423         int green;
5424         int blue;
5425         if (!parseColorIntOrPercentage(current, end, ',', expect, red))
5426             return false;
5427         if (!parseColorIntOrPercentage(current, end, ',', expect, green))
5428             return false;
5429         if (!parseColorIntOrPercentage(current, end, ')', expect, blue))
5430             return false;
5431         if (current != end)
5432             return false;
5433         rgb = makeRGB(red, green, blue);
5434         return true;
5435     }
5436
5437     // Try named colors.
5438     Color tc;
5439     tc.setNamedColor(name);
5440     if (tc.isValid()) {
5441         rgb = tc.rgb();
5442         return true;
5443     }
5444     return false;
5445 }
5446     
5447 inline double CSSParser::parsedDouble(CSSParserValue *v, ReleaseParsedCalcValueCondition releaseCalc)
5448 {
5449     const double result = m_parsedCalculation ? m_parsedCalculation->doubleValue() : v->fValue;
5450     if (releaseCalc == ReleaseParsedCalcValue)
5451         m_parsedCalculation.release();
5452     return result;
5453 }
5454
5455 bool CSSParser::isCalculation(CSSParserValue* value) 
5456 {
5457     return (value->unit == CSSParserValue::Function) 
5458         && (equalIgnoringCase(value->function->name, "-webkit-calc(")
5459             || equalIgnoringCase(value->function->name, "-webkit-min(")
5460             || equalIgnoringCase(value->function->name, "-webkit-max("));
5461 }
5462
5463 inline int CSSParser::colorIntFromValue(CSSParserValue* v)
5464 {
5465     bool isPercent;
5466     
5467     if (m_parsedCalculation)
5468         isPercent = m_parsedCalculation->category() == CalcPercent;
5469     else
5470         isPercent = v->unit == CSSPrimitiveValue::CSS_PERCENTAGE;
5471
5472     const double value = parsedDouble(v, ReleaseParsedCalcValue);
5473     
5474     if (value <= 0.0)
5475         return 0;
5476
5477     if (isPercent) {
5478         if (value >= 100.0)
5479             return 255;
5480         return static_cast<int>(value * 256.0 / 100.0);
5481     }
5482
5483     if (value >= 255.0)
5484         return 255;
5485
5486     return static_cast<int>(value);
5487 }
5488
5489 bool CSSParser::parseColorParameters(CSSParserValue* value, int* colorArray, bool parseAlpha)
5490 {
5491     CSSParserValueList* args = value->function->args.get();
5492     CSSParserValue* v = args->current();
5493     Units unitType = FUnknown;
5494     // Get the first value and its type
5495     if (validUnit(v, FInteger, CSSStrictMode))
5496         unitType = FInteger;
5497     else if (validUnit(v, FPercent, CSSStrictMode))
5498         unitType = FPercent;
5499     else
5500         return false;
5501     
5502     colorArray[0] = colorIntFromValue(v);
5503     for (int i = 1; i < 3; i++) {
5504         v = args->next();
5505         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
5506             return false;
5507         v = args->next();
5508         if (!validUnit(v, unitType, CSSStrictMode))
5509             return false;
5510         colorArray[i] = colorIntFromValue(v);
5511     }
5512     if (parseAlpha) {
5513         v = args->next();
5514         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
5515             return false;
5516         v = args->next();
5517         if (!validUnit(v, FNumber, CSSStrictMode))
5518             return false;
5519         const double value = parsedDouble(v, ReleaseParsedCalcValue);
5520         // Convert the floating pointer number of alpha to an integer in the range [0, 256),
5521         // with an equal distribution across all 256 values.
5522         colorArray[3] = static_cast<int>(max(0.0, min(1.0, value)) * nextafter(256.0, 0.0));
5523     }
5524     return true;
5525 }
5526
5527 // The CSS3 specification defines the format of a HSL color as
5528 // hsl(<number>, <percent>, <percent>)
5529 // and with alpha, the format is
5530 // hsla(<number>, <percent>, <percent>, <number>)
5531 // The first value, HUE, is in an angle with a value between 0 and 360
5532 bool CSSParser::parseHSLParameters(CSSParserValue* value, double* colorArray, bool parseAlpha)
5533 {
5534     CSSParserValueList* args = value->function->args.get();
5535     CSSParserValue* v = args->current();
5536     // Get the first value
5537     if (!validUnit(v, FNumber, CSSStrictMode))
5538         return false;
5539     // normalize the Hue value and change it to be between 0 and 1.0
5540     colorArray[0] = (((static_cast<int>(parsedDouble(v, ReleaseParsedCalcValue)) % 360) + 360) % 360) / 360.0;
5541     for (int i = 1; i < 3; i++) {
5542         v = args->next();
5543         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
5544             return false;
5545         v = args->next();
5546         if (!validUnit(v, FPercent, CSSStrictMode))
5547             return false;
5548         colorArray[i] = max(0.0, min(100.0, parsedDouble(v, ReleaseParsedCalcValue))) / 100.0; // needs to be value between 0 and 1.0
5549     }
5550     if (parseAlpha) {
5551         v = args->next();
5552         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
5553             return false;
5554         v = args->next();
5555         if (!validUnit(v, FNumber, CSSStrictMode))
5556             return false;
5557         colorArray[3] = max(0.0, min(1.0, parsedDouble(v, ReleaseParsedCalcValue)));
5558     }
5559     return true;
5560 }
5561
5562 PassRefPtr<CSSPrimitiveValue> CSSParser::parseColor(CSSParserValue* value)
5563 {
5564     RGBA32 c = Color::transparent;
5565     if (!parseColorFromValue(value ? value : m_valueList->current(), c))
5566         return 0;
5567     return cssValuePool().createColorValue(c);
5568 }
5569
5570 bool CSSParser::parseColorFromValue(CSSParserValue* value, RGBA32& c)
5571 {
5572     if (inQuirksMode() && value->unit == CSSPrimitiveValue::CSS_NUMBER
5573         && value->fValue >= 0. && value->fValue < 1000000.) {
5574         String str = String::format("%06d", static_cast<int>((value->fValue+.5)));
5575         // FIXME: This should be strict parsing for SVG as well.
5576         if (!fastParseColor(c, str, inStrictMode()))
5577             return false;
5578     } else if (value->unit == CSSPrimitiveValue::CSS_PARSER_HEXCOLOR ||
5579                 value->unit == CSSPrimitiveValue::CSS_IDENT ||
5580                 (inQuirksMode() && value->unit == CSSPrimitiveValue::CSS_DIMENSION)) {
5581         if (!fastParseColor(c, value->string, inStrictMode() && value->unit == CSSPrimitiveValue::CSS_IDENT))
5582             return false;
5583     } else if (value->unit == CSSParserValue::Function &&
5584                 value->function->args != 0 &&
5585                 value->function->args->size() == 5 /* rgb + two commas */ &&
5586                 equalIgnoringCase(value->function->name, "rgb(")) {
5587         int colorValues[3];
5588         if (!parseColorParameters(value, colorValues, false))
5589             return false;
5590         c = makeRGB(colorValues[0], colorValues[1], colorValues[2]);
5591     } else {
5592         if (value->unit == CSSParserValue::Function &&
5593                 value->function->args != 0 &&
5594                 value->function->args->size() == 7 /* rgba + three commas */ &&
5595                 equalIgnoringCase(value->function->name, "rgba(")) {
5596             int colorValues[4];
5597             if (!parseColorParameters(value, colorValues, true))
5598                 return false;
5599             c = makeRGBA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
5600         } else if (value->unit == CSSParserValue::Function &&
5601                     value->function->args != 0 &&
5602                     value->function->args->size() == 5 /* hsl + two commas */ &&
5603                     equalIgnoringCase(value->function->name, "hsl(")) {
5604             double colorValues[3];
5605             if (!parseHSLParameters(value, colorValues, false))
5606                 return false;
5607             c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], 1.0);
5608         } else if (value->unit == CSSParserValue::Function &&
5609                     value->function->args != 0 &&
5610                     value->function->args->size() == 7 /* hsla + three commas */ &&
5611                     equalIgnoringCase(value->function->name, "hsla(")) {
5612             double colorValues[4];
5613             if (!parseHSLParameters(value, colorValues, true))
5614                 return false;
5615             c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
5616         } else
5617             return false;
5618     }
5619
5620     return true;
5621 }
5622
5623 // This class tracks parsing state for shadow values.  If it goes out of scope (e.g., due to an early return)
5624 // without the allowBreak bit being set, then it will clean up all of the objects and destroy them.
5625 struct ShadowParseContext {
5626     ShadowParseContext(CSSPropertyID prop, CSSParser* parser)
5627         : property(prop)
5628         , m_parser(parser)
5629         , allowX(true)
5630         , allowY(false)
5631         , allowBlur(false)
5632         , allowSpread(false)
5633         , allowColor(true)
5634         , allowStyle(prop == CSSPropertyWebkitBoxShadow || prop == CSSPropertyBoxShadow)
5635         , allowBreak(true)
5636     {
5637     }
5638
5639     bool allowLength() { return allowX || allowY || allowBlur || allowSpread; }
5640
5641     void commitValue()
5642     {
5643         // Handle the ,, case gracefully by doing nothing.
5644         if (x || y || blur || spread || color || style) {
5645             if (!values)
5646                 values = CSSValueList::createCommaSeparated();
5647
5648             // Construct the current shadow value and add it to the list.
5649             values->append(ShadowValue::create(x.release(), y.release(), blur.release(), spread.release(), style.release(), color.release()));
5650         }
5651
5652         // Now reset for the next shadow value.
5653         x = 0;
5654         y = 0;
5655         blur = 0;
5656         spread = 0;
5657         style = 0;
5658         color = 0;
5659
5660         allowX = true;
5661         allowColor = true;
5662         allowBreak = true;
5663         allowY = false;
5664         allowBlur = false;
5665         allowSpread = false;
5666         allowStyle = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
5667     }
5668
5669     void commitLength(CSSParserValue* v)
5670     {
5671         RefPtr<CSSPrimitiveValue> val = m_parser->createPrimitiveNumericValue(v);
5672
5673         if (allowX) {
5674             x = val.release();
5675             allowX = false;
5676             allowY = true;
5677             allowColor = false;
5678             allowStyle = false;
5679             allowBreak = false;
5680         } else if (allowY) {
5681             y = val.release();
5682             allowY = false;
5683             allowBlur = true;
5684             allowColor = true;
5685             allowStyle = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
5686             allowBreak = true;
5687         } else if (allowBlur) {
5688             blur = val.release();
5689             allowBlur = false;
5690             allowSpread = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
5691         } else if (allowSpread) {
5692             spread = val.release();
5693             allowSpread = false;
5694         }
5695     }
5696
5697     void commitColor(PassRefPtr<CSSPrimitiveValue> val)
5698     {
5699         color = val;
5700         allowColor = false;
5701         if (allowX) {
5702             allowStyle = false;
5703             allowBreak = false;
5704         } else {
5705             allowBlur = false;
5706             allowSpread = false;
5707             allowStyle = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
5708         }
5709     }
5710
5711     void commitStyle(CSSParserValue* v)
5712     {
5713         style = cssValuePool().createIdentifierValue(v->id);
5714         allowStyle = false;
5715         if (allowX)
5716             allowBreak = false;
5717         else {
5718             allowBlur = false;
5719             allowSpread = false;
5720             allowColor = false;
5721         }
5722     }
5723
5724     CSSPropertyID property;
5725     CSSParser* m_parser;
5726
5727     RefPtr<CSSValueList> values;
5728     RefPtr<CSSPrimitiveValue> x;
5729     RefPtr<CSSPrimitiveValue> y;
5730     RefPtr<CSSPrimitiveValue> blur;
5731     RefPtr<CSSPrimitiveValue> spread;
5732     RefPtr<CSSPrimitiveValue> style;
5733     RefPtr<CSSPrimitiveValue> color;
5734
5735     bool allowX;
5736     bool allowY;
5737     bool allowBlur;
5738     bool allowSpread;
5739     bool allowColor;
5740     bool allowStyle; // inset or not.
5741     bool allowBreak;
5742 };
5743
5744 PassRefPtr<CSSValueList> CSSParser::parseShadow(CSSParserValueList* valueList, CSSPropertyID propId)
5745 {
5746     ShadowParseContext context(propId, this);
5747     CSSParserValue* val;
5748     while ((val = valueList->current())) {
5749         // Check for a comma break first.
5750         if (val->unit == CSSParserValue::Operator) {
5751             if (val->iValue != ',' || !context.allowBreak)
5752                 // Other operators aren't legal or we aren't done with the current shadow
5753                 // value.  Treat as invalid.
5754                 return 0;
5755 #if ENABLE(SVG)
5756             // -webkit-svg-shadow does not support multiple values.
5757             if (propId == CSSPropertyWebkitSvgShadow)
5758                 return 0;
5759 #endif
5760             // The value is good.  Commit it.
5761             context.commitValue();
5762         } else if (validUnit(val, FLength, CSSStrictMode)) {
5763             // We required a length and didn't get one. Invalid.
5764             if (!context.allowLength())
5765                 return 0;
5766
5767             // A length is allowed here.  Construct the value and add it.
5768             context.commitLength(val);
5769         } else if (val->id == CSSValueInset) {
5770             if (!context.allowStyle)
5771                 return 0;
5772
5773             context.commitStyle(val);
5774         } else {
5775             // The only other type of value that's ok is a color value.
5776             RefPtr<CSSPrimitiveValue> parsedColor;
5777             bool isColor = ((val->id >= CSSValueAqua && val->id <= CSSValueWindowtext) || val->id == CSSValueMenu
5778                             || (val->id >= CSSValueWebkitFocusRingColor && val->id <= CSSValueWebkitText && inQuirksMode())
5779                             || val->id == CSSValueCurrentcolor);
5780             if (isColor) {
5781                 if (!context.allowColor)
5782                     return 0;
5783                 parsedColor = cssValuePool().createIdentifierValue(val->id);
5784             }
5785
5786             if (!parsedColor)
5787                 // It's not built-in. Try to parse it as a color.
5788                 parsedColor = parseColor(val);
5789
5790             if (!parsedColor || !context.allowColor)
5791                 return 0; // This value is not a color or length and is invalid or
5792                           // it is a color, but a color isn't allowed at this point.
5793
5794             context.commitColor(parsedColor.release());
5795         }
5796
5797         valueList->next();
5798     }
5799
5800     if (context.allowBreak) {
5801         context.commitValue();
5802         if (context.values && context.values->length())
5803             return context.values.release();
5804     }
5805
5806     return 0;
5807 }
5808
5809 bool CSSParser::parseReflect(CSSPropertyID propId, bool important)
5810 {
5811     // box-reflect: <direction> <offset> <mask>
5812
5813     // Direction comes first.
5814     CSSParserValue* val = m_valueList->current();
5815     CSSReflectionDirection direction;
5816     switch (val->id) {
5817         case CSSValueAbove:
5818             direction = ReflectionAbove;
5819             break;
5820         case CSSValueBelow:
5821             direction = ReflectionBelow;
5822             break;
5823         case CSSValueLeft:
5824             direction = ReflectionLeft;
5825             break;
5826         case CSSValueRight:
5827             direction = ReflectionRight;
5828             break;
5829         default:
5830             return false;
5831     }
5832
5833     // The offset comes next.
5834     val = m_valueList->next();
5835     RefPtr<CSSPrimitiveValue> offset;
5836     if (!val)
5837         offset = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_PX);
5838     else {
5839         if (!validUnit(val, FLength | FPercent))
5840             return false;
5841         offset = createPrimitiveNumericValue(val);
5842     }
5843
5844     // Now for the mask.
5845     RefPtr<CSSValue> mask;
5846     val = m_valueList->next();
5847     if (val) {
5848         if (!parseBorderImage(propId, mask))
5849             return false;
5850     }
5851
5852     RefPtr<CSSReflectValue> reflectValue = CSSReflectValue::create(direction, offset.release(), mask.release());
5853     addProperty(propId, reflectValue.release(), important);
5854     m_valueList->next();
5855     return true;
5856 }
5857
5858 #if ENABLE(CSS3_FLEXBOX)
5859
5860 bool CSSParser::parseFlex(CSSParserValueList* args, bool important)
5861 {
5862     if (!args || !args->size() || args->size() > 3)
5863         return false;
5864     static const double unsetValue = -1;
5865     double flexGrow = unsetValue;
5866     double flexShrink = unsetValue;
5867     RefPtr<CSSPrimitiveValue> flexBasis;
5868
5869     while (CSSParserValue* arg = args->current()) {
5870         if (validUnit(arg, FNumber | FNonNeg)) {
5871             if (flexGrow == unsetValue)
5872                 flexGrow = arg->fValue;
5873             else if (flexShrink == unsetValue)
5874                 flexShrink = arg->fValue;
5875             else if (!arg->fValue) {
5876                 // flex only allows a basis of 0 (sans units) if flex-grow and flex-shrink values have already been set.
5877                 flexBasis = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_PX);
5878             } else {
5879                 // We only allow 3 numbers without units if the last value is 0. E.g., flex:1 1 1 is invalid.
5880                 return false;
5881             }
5882         } else if (!flexBasis && (arg->id == CSSValueAuto || validUnit(arg, FLength | FPercent | FNonNeg)))
5883             flexBasis = parseValidPrimitive(arg->id, arg);
5884         else {
5885             // Not a valid arg for flex.
5886             return false;
5887         }
5888         args->next();
5889     }
5890
5891     if (flexGrow == unsetValue)
5892         flexGrow = 0;
5893     if (flexShrink == unsetValue)
5894         flexShrink = 1;
5895     if (!flexBasis)
5896         flexBasis = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_PX);
5897
5898     addProperty(CSSPropertyWebkitFlexGrow, cssValuePool().createValue(clampToFloat(flexGrow), CSSPrimitiveValue::CSS_NUMBER), important);
5899     addProperty(CSSPropertyWebkitFlexShrink, cssValuePool().createValue(clampToFloat(flexShrink), CSSPrimitiveValue::CSS_NUMBER), important);
5900     addProperty(CSSPropertyWebkitFlexBasis, flexBasis, important);
5901     return true;
5902 }
5903
5904 #endif
5905
5906 struct BorderImageParseContext {
5907     BorderImageParseContext()
5908     : m_canAdvance(false)
5909     , m_allowCommit(true)
5910     , m_allowImage(true)
5911     , m_allowImageSlice(true)
5912     , m_allowRepeat(true)
5913     , m_allowSlash(false)
5914     , m_requireWidth(false)
5915     , m_requireOutset(false)
5916     {}
5917
5918     bool canAdvance() const { return m_canAdvance; }
5919     void setCanAdvance(bool canAdvance) { m_canAdvance = canAdvance; }
5920
5921     bool allowCommit() const { return m_allowCommit; }
5922     bool allowImage() const { return m_allowImage; }
5923     bool allowImageSlice() const { return m_allowImageSlice; }
5924     bool allowRepeat() const { return m_allowRepeat; }
5925     bool allowSlash() const { return m_allowSlash; }
5926
5927     bool requireWidth() const { return m_requireWidth; }
5928     bool requireOutset() const { return m_requireOutset; }
5929
5930     void commitImage(PassRefPtr<CSSValue> image)
5931     {
5932         m_image = image;
5933         m_canAdvance = true;
5934         m_allowCommit = true;
5935         m_allowImage = m_allowSlash = m_requireWidth = m_requireOutset = false;
5936         m_allowImageSlice = !m_imageSlice;
5937         m_allowRepeat = !m_repeat;
5938     }
5939     void commitImageSlice(PassRefPtr<CSSBorderImageSliceValue> slice)
5940     {
5941         m_imageSlice = slice;
5942         m_canAdvance = true;
5943         m_allowCommit = m_allowSlash = true;
5944         m_allowImageSlice = m_requireWidth = m_requireOutset = false;
5945         m_allowImage = !m_image;
5946         m_allowRepeat = !m_repeat;
5947     }
5948     void commitSlash()
5949     {
5950         m_canAdvance = true;
5951         m_allowCommit = m_allowImage = m_allowImageSlice = m_allowRepeat = m_allowSlash = false;
5952         if (!m_borderSlice) {
5953             m_requireWidth = true;
5954             m_requireOutset = false;
5955         } else {
5956             m_requireOutset = true;
5957             m_requireWidth = false;
5958         }
5959     }
5960     void commitBorderWidth(PassRefPtr<CSSPrimitiveValue> slice)
5961     {
5962         m_borderSlice = slice;
5963         m_canAdvance = true;
5964         m_allowCommit = m_allowSlash = true;
5965         m_allowImageSlice = m_requireWidth = m_requireOutset = false;
5966         m_allowImage = !m_image;
5967         m_allowRepeat = !m_repeat;
5968     }
5969     void commitBorderOutset(PassRefPtr<CSSPrimitiveValue> outset)
5970     {
5971         m_outset = outset;
5972         m_canAdvance = true;
5973         m_allowCommit = true;
5974         m_allowImageSlice = m_allowSlash = m_requireWidth = m_requireOutset = false;
5975         m_allowImage = !m_image;
5976         m_allowRepeat = !m_repeat;
5977     }
5978     void commitRepeat(PassRefPtr<CSSValue> repeat)
5979     {
5980         m_repeat = repeat;
5981         m_canAdvance = true;
5982         m_allowCommit = true;
5983         m_allowRepeat = m_allowSlash = m_requireWidth = m_requireOutset = false;
5984         m_allowImageSlice = !m_imageSlice;
5985         m_allowImage = !m_image;
5986     }
5987
5988     PassRefPtr<CSSValue> commitWebKitBorderImage()
5989     {
5990         return createBorderImageValue(m_image, m_imageSlice, m_borderSlice, m_outset, m_repeat);
5991     }
5992
5993     void commitBorderImage(CSSParser* parser, bool important)
5994     {
5995         commitBorderImageProperty(CSSPropertyBorderImageSource, parser, m_image, important);
5996         commitBorderImageProperty(CSSPropertyBorderImageSlice, parser, m_imageSlice, important);
5997         commitBorderImageProperty(CSSPropertyBorderImageWidth, parser, m_borderSlice, important);
5998         commitBorderImageProperty(CSSPropertyBorderImageOutset, parser, m_outset, important);
5999         commitBorderImageProperty(CSSPropertyBorderImageRepeat, parser, m_repeat, important);
6000     }
6001
6002     void commitBorderImageProperty(CSSPropertyID propId, CSSParser* parser, PassRefPtr<CSSValue> value, bool important)
6003     {
6004         if (value)
6005             parser->addProperty(propId, value, important);
6006         else
6007             parser->addProperty(propId, cssValuePool().createImplicitInitialValue(), important, true);
6008     }
6009
6010     bool m_canAdvance;
6011
6012     bool m_allowCommit;
6013     bool m_allowImage;
6014     bool m_allowImageSlice;
6015     bool m_allowRepeat;
6016     bool m_allowSlash;
6017
6018     bool m_requireWidth;
6019     bool m_requireOutset;
6020
6021     RefPtr<CSSValue> m_image;
6022     RefPtr<CSSBorderImageSliceValue> m_imageSlice;
6023     RefPtr<CSSPrimitiveValue> m_borderSlice;
6024     RefPtr<CSSPrimitiveValue> m_outset;
6025
6026     RefPtr<CSSValue> m_repeat;
6027 };
6028
6029 bool CSSParser::parseBorderImage(CSSPropertyID propId, RefPtr<CSSValue>& result, bool important)
6030 {
6031     ShorthandScope scope(this, propId);
6032     BorderImageParseContext context;
6033     while (CSSParserValue* val = m_valueList->current()) {
6034         context.setCanAdvance(false);
6035
6036         if (!context.canAdvance() && context.allowSlash() && val->unit == CSSParserValue::Operator && val->iValue == '/')
6037             context.commitSlash();
6038
6039         if (!context.canAdvance() && context.allowImage()) {
6040             if (val->unit == CSSPrimitiveValue::CSS_URI)
6041                 context.commitImage(CSSImageValue::create(completeURL(val->string)));
6042             else if (isGeneratedImageValue(val)) {
6043                 RefPtr<CSSValue> value;
6044                 if (parseGeneratedImage(m_valueList.get(), value))
6045                     context.commitImage(value);
6046                 else
6047                     return false;
6048 #if ENABLE(CSS_IMAGE_SET)
6049             } else if (val->unit == CSSParserValue::Function && equalIgnoringCase(val->function->name, "-webkit-image-set(")) {
6050                 RefPtr<CSSValue> value = parseImageSet(m_valueList.get());
6051                 if (value)
6052                     context.commitImage(value);
6053                 else
6054                     return false;
6055 #endif
6056             } else if (val->id == CSSValueNone)
6057                 context.commitImage(cssValuePool().createIdentifierValue(CSSValueNone));
6058         }
6059
6060         if (!context.canAdvance() && context.allowImageSlice()) {
6061             RefPtr<CSSBorderImageSliceValue> imageSlice;
6062             if (parseBorderImageSlice(propId, imageSlice))
6063                 context.commitImageSlice(imageSlice.release());
6064         }
6065
6066         if (!context.canAdvance() && context.allowRepeat()) {
6067             RefPtr<CSSValue> repeat;
6068             if (parseBorderImageRepeat(repeat))
6069                 context.commitRepeat(repeat);
6070         }
6071
6072         if (!context.canAdvance() && context.requireWidth()) {
6073             RefPtr<CSSPrimitiveValue> borderSlice;
6074             if (parseBorderImageWidth(borderSlice))
6075                 context.commitBorderWidth(borderSlice.release());
6076         }
6077
6078         if (!context.canAdvance() && context.requireOutset()) {
6079             RefPtr<CSSPrimitiveValue> borderOutset;
6080             if (parseBorderImageOutset(borderOutset))
6081                 context.commitBorderOutset(borderOutset.release());
6082         }
6083
6084         if (!context.canAdvance())
6085             return false;
6086
6087         m_valueList->next();
6088     }
6089
6090     if (context.allowCommit()) {
6091         if (propId == CSSPropertyBorderImage)
6092             context.commitBorderImage(this, important);
6093         else
6094             // Need to fully commit as a single value.
6095             result = context.commitWebKitBorderImage();
6096         return true;
6097     }
6098
6099     return false;
6100 }
6101
6102 static bool isBorderImageRepeatKeyword(int id)
6103 {
6104     return id == CSSValueStretch || id == CSSValueRepeat || id == CSSValueSpace || id == CSSValueRound;
6105 }
6106
6107 bool CSSParser::parseBorderImageRepeat(RefPtr<CSSValue>& result)
6108 {
6109     RefPtr<CSSPrimitiveValue> firstValue;
6110     RefPtr<CSSPrimitiveValue> secondValue;
6111     CSSParserValue* val = m_valueList->current();
6112     if (!val)
6113         return false;
6114     if (isBorderImageRepeatKeyword(val->id))
6115         firstValue = cssValuePool().createIdentifierValue(val->id);
6116     else
6117         return false;
6118
6119     val = m_valueList->next();
6120     if (val) {
6121         if (isBorderImageRepeatKeyword(val->id))
6122             secondValue = cssValuePool().createIdentifierValue(val->id);
6123         else if (!inShorthand()) {
6124             // If we're not parsing a shorthand then we are invalid.
6125             return false;
6126         } else {
6127             // We need to rewind the value list, so that when its advanced we'll
6128             // end up back at this value.
6129             m_valueList->previous();
6130         }
6131     } else
6132         secondValue = firstValue;
6133
6134     result = cssValuePool().createValue(Pair::create(firstValue, secondValue));
6135     return true;
6136 }
6137
6138 class BorderImageSliceParseContext {
6139 public:
6140     BorderImageSliceParseContext(CSSParser* parser)
6141     : m_parser(parser)
6142     , m_allowNumber(true)
6143     , m_allowFill(true)
6144     , m_allowFinalCommit(false)
6145     , m_fill(false)
6146     { }
6147
6148     bool allowNumber() const { return m_allowNumber; }
6149     bool allowFill() const { return m_allowFill; }
6150     bool allowFinalCommit() const { return m_allowFinalCommit; }
6151     CSSPrimitiveValue* top() const { return m_top.get(); }
6152
6153     void commitNumber(CSSParserValue* v)
6154     {
6155         RefPtr<CSSPrimitiveValue> val = m_parser->createPrimitiveNumericValue(v);
6156         if (!m_top)
6157             m_top = val;
6158         else if (!m_right)
6159             m_right = val;
6160         else if (!m_bottom)
6161             m_bottom = val;
6162         else {
6163             ASSERT(!m_left);
6164             m_left = val;
6165         }
6166
6167         m_allowNumber = !m_left;
6168         m_allowFinalCommit = true;
6169     }
6170
6171     void commitFill() { m_fill = true; m_allowFill = false; m_allowNumber = !m_top; }
6172
6173     PassRefPtr<CSSBorderImageSliceValue> commitBorderImageSlice()
6174     {
6175         // We need to clone and repeat values for any omissions.
6176         ASSERT(m_top);
6177         if (!m_right) {
6178             m_right = m_top;
6179             m_bottom = m_top;
6180             m_left = m_top;
6181         }
6182         if (!m_bottom) {
6183             m_bottom = m_top;
6184             m_left = m_right;
6185         }
6186         if (!m_left)
6187             m_left = m_right;
6188
6189         // Now build a rect value to hold all four of our primitive values.
6190         RefPtr<Quad> quad = Quad::create();
6191         quad->setTop(m_top);
6192         quad->setRight(m_right);
6193         quad->setBottom(m_bottom);
6194         quad->setLeft(m_left);
6195
6196         // Make our new border image value now.
6197         return CSSBorderImageSliceValue::create(cssValuePool().createValue(quad.release()), m_fill);
6198     }
6199
6200 private:
6201     CSSParser* m_parser;
6202
6203     bool m_allowNumber;
6204     bool m_allowFill;
6205     bool m_allowFinalCommit;
6206
6207     RefPtr<CSSPrimitiveValue> m_top;
6208     RefPtr<CSSPrimitiveValue> m_right;
6209     RefPtr<CSSPrimitiveValue> m_bottom;
6210     RefPtr<CSSPrimitiveValue> m_left;
6211
6212     bool m_fill;
6213 };
6214
6215 bool CSSParser::parseBorderImageSlice(CSSPropertyID propId, RefPtr<CSSBorderImageSliceValue>& result)
6216 {
6217     BorderImageSliceParseContext context(this);
6218     CSSParserValue* val;
6219     while ((val = m_valueList->current())) {
6220         // FIXME calc() http://webkit.org/b/16662 : calc is parsed but values are not created yet.
6221         if (context.allowNumber() && !isCalculation(val) && validUnit(val, FInteger | FNonNeg | FPercent, CSSStrictMode)) {
6222             context.commitNumber(val);
6223         } else if (context.allowFill() && val->id == CSSValueFill)
6224             context.commitFill();
6225         else if (!inShorthand()) {
6226             // If we're not parsing a shorthand then we are invalid.
6227             return false;
6228         } else {
6229             if (context.allowFinalCommit()) {
6230                 // We're going to successfully parse, but we don't want to consume this token.
6231                 m_valueList->previous();
6232             }
6233             break;
6234         }
6235         m_valueList->next();
6236     }
6237
6238     if (context.allowFinalCommit()) {
6239         // FIXME: For backwards compatibility, -webkit-border-image, -webkit-mask-box-image and -webkit-box-reflect have to do a fill by default.
6240         // FIXME: What do we do with -webkit-box-reflect and -webkit-mask-box-image? Probably just have to leave them filling...
6241         if (propId == CSSPropertyWebkitBorderImage || propId == CSSPropertyWebkitMaskBoxImage || propId == CSSPropertyWebkitBoxReflect)
6242             context.commitFill();
6243
6244         // Need to fully commit as a single value.
6245         result = context.commitBorderImageSlice();
6246         return true;
6247     }
6248
6249     return false;
6250 }
6251
6252 class BorderImageQuadParseContext {
6253 public:
6254     BorderImageQuadParseContext(CSSParser* parser)
6255     : m_parser(parser)
6256     , m_allowNumber(true)
6257     , m_allowFinalCommit(false)
6258     { }
6259
6260     bool allowNumber() const { return m_allowNumber; }
6261     bool allowFinalCommit() const { return m_allowFinalCommit; }
6262     CSSPrimitiveValue* top() const { return m_top.get(); }
6263
6264     void commitNumber(CSSParserValue* v)
6265     {
6266         RefPtr<CSSPrimitiveValue> val;
6267         if (v->id == CSSValueAuto)
6268             val = cssValuePool().createIdentifierValue(v->id);
6269         else
6270             val = m_parser->createPrimitiveNumericValue(v);
6271
6272         if (!m_top)
6273             m_top = val;
6274         else if (!m_right)
6275             m_right = val;
6276         else if (!m_bottom)
6277             m_bottom = val;
6278         else {
6279             ASSERT(!m_left);
6280             m_left = val;
6281         }
6282
6283         m_allowNumber = !m_left;
6284         m_allowFinalCommit = true;
6285     }
6286
6287     void setAllowFinalCommit() { m_allowFinalCommit = true; }
6288     void setTop(PassRefPtr<CSSPrimitiveValue> val) { m_top = val; }
6289
6290     PassRefPtr<CSSPrimitiveValue> commitBorderImageQuad()
6291     {
6292         // We need to clone and repeat values for any omissions.
6293         ASSERT(m_top);
6294         if (!m_right) {
6295             m_right = m_top;
6296             m_bottom = m_top;
6297             m_left = m_top;
6298         }
6299         if (!m_bottom) {
6300             m_bottom = m_top;
6301             m_left = m_right;
6302         }
6303         if (!m_left)
6304             m_left = m_right;
6305
6306         // Now build a quad value to hold all four of our primitive values.
6307         RefPtr<Quad> quad = Quad::create();
6308         quad->setTop(m_top);
6309         quad->setRight(m_right);
6310         quad->setBottom(m_bottom);
6311         quad->setLeft(m_left);
6312
6313         // Make our new value now.
6314         return cssValuePool().createValue(quad.release());
6315     }
6316
6317 private:
6318     CSSParser* m_parser;
6319
6320     bool m_allowNumber;
6321     bool m_allowFinalCommit;
6322
6323     RefPtr<CSSPrimitiveValue> m_top;
6324     RefPtr<CSSPrimitiveValue> m_right;
6325     RefPtr<CSSPrimitiveValue> m_bottom;
6326     RefPtr<CSSPrimitiveValue> m_left;
6327 };
6328
6329 bool CSSParser::parseBorderImageQuad(Units validUnits, RefPtr<CSSPrimitiveValue>& result)
6330 {
6331     BorderImageQuadParseContext context(this);
6332     CSSParserValue* val;
6333     while ((val = m_valueList->current())) {
6334         if (context.allowNumber() && (validUnit(val, validUnits, CSSStrictMode) || val->id == CSSValueAuto)) {
6335             context.commitNumber(val);
6336         } else if (!inShorthand()) {
6337             // If we're not parsing a shorthand then we are invalid.
6338             return false;
6339         } else {
6340             if (context.allowFinalCommit())
6341                 m_valueList->previous(); // The shorthand loop will advance back to this point.
6342             break;
6343         }
6344         m_valueList->next();
6345     }
6346
6347     if (context.allowFinalCommit()) {
6348         // Need to fully commit as a single value.
6349         result = context.commitBorderImageQuad();
6350         return true;
6351     }
6352     return false;
6353 }
6354
6355 bool CSSParser::parseBorderImageWidth(RefPtr<CSSPrimitiveValue>& result)
6356 {
6357     return parseBorderImageQuad(FLength | FInteger | FNonNeg | FPercent, result);
6358 }
6359
6360 bool CSSParser::parseBorderImageOutset(RefPtr<CSSPrimitiveValue>& result)
6361 {
6362     return parseBorderImageQuad(FLength | FInteger | FNonNeg, result);
6363 }
6364
6365 static void completeBorderRadii(RefPtr<CSSPrimitiveValue> radii[4])
6366 {
6367     if (radii[3])
6368         return;
6369     if (!radii[2]) {
6370         if (!radii[1])
6371             radii[1] = radii[0];
6372         radii[2] = radii[0];
6373     }
6374     radii[3] = radii[1];
6375 }
6376
6377 bool CSSParser::parseBorderRadius(CSSPropertyID propId, bool important)
6378 {
6379     unsigned num = m_valueList->size();
6380     if (num > 9)
6381         return false;
6382
6383     ShorthandScope scope(this, propId);
6384     RefPtr<CSSPrimitiveValue> radii[2][4];
6385
6386     unsigned indexAfterSlash = 0;
6387     for (unsigned i = 0; i < num; ++i) {
6388         CSSParserValue* value = m_valueList->valueAt(i);
6389         if (value->unit == CSSParserValue::Operator) {
6390             if (value->iValue != '/')
6391                 return false;
6392
6393             if (!i || indexAfterSlash || i + 1 == num || num > i + 5)
6394                 return false;
6395
6396             indexAfterSlash = i + 1;
6397             completeBorderRadii(radii[0]);
6398             continue;
6399         }
6400
6401         if (i - indexAfterSlash >= 4)
6402             return false;
6403
6404         if (!validUnit(value, FLength | FPercent | FNonNeg))
6405             return false;
6406
6407         RefPtr<CSSPrimitiveValue> radius = createPrimitiveNumericValue(value);
6408
6409         if (!indexAfterSlash) {
6410             radii[0][i] = radius;
6411
6412             // Legacy syntax: -webkit-border-radius: l1 l2; is equivalent to border-radius: l1 / l2;
6413             if (num == 2 && propId == CSSPropertyWebkitBorderRadius) {
6414                 indexAfterSlash = 1;
6415                 completeBorderRadii(radii[0]);
6416             }
6417         } else
6418             radii[1][i - indexAfterSlash] = radius.release();
6419     }
6420
6421     if (!indexAfterSlash) {
6422         completeBorderRadii(radii[0]);
6423         for (unsigned i = 0; i < 4; ++i)
6424             radii[1][i] = radii[0][i];
6425     } else
6426         completeBorderRadii(radii[1]);
6427
6428     ImplicitScope implicitScope(this, PropertyImplicit);
6429     addProperty(CSSPropertyBorderTopLeftRadius, cssValuePool().createValue(Pair::create(radii[0][0].release(), radii[1][0].release())), important);
6430     addProperty(CSSPropertyBorderTopRightRadius, cssValuePool().createValue(Pair::create(radii[0][1].release(), radii[1][1].release())), important);
6431     addProperty(CSSPropertyBorderBottomRightRadius, cssValuePool().createValue(Pair::create(radii[0][2].release(), radii[1][2].release())), important);
6432     addProperty(CSSPropertyBorderBottomLeftRadius, cssValuePool().createValue(Pair::create(radii[0][3].release(), radii[1][3].release())), important);
6433     return true;
6434 }
6435
6436 bool CSSParser::parseAspectRatio(bool important)
6437 {
6438     unsigned num = m_valueList->size();
6439     if (num == 1 && m_valueList->valueAt(0)->id == CSSValueNone) {
6440         addProperty(CSSPropertyWebkitAspectRatio, cssValuePool().createIdentifierValue(CSSValueNone), important);
6441         return true;
6442     }
6443
6444     if (num != 3)
6445         return false;
6446
6447     CSSParserValue* lvalue = m_valueList->valueAt(0);
6448     CSSParserValue* op = m_valueList->valueAt(1);
6449     CSSParserValue* rvalue = m_valueList->valueAt(2);
6450
6451     if (op->unit != CSSParserValue::Operator || op->iValue != '/')
6452         return false;
6453
6454     if (!validUnit(lvalue, FNumber | FNonNeg) || !validUnit(rvalue, FNumber | FNonNeg))
6455         return false;
6456
6457     if (!lvalue->fValue || !rvalue->fValue)
6458         return false;
6459
6460     addProperty(CSSPropertyWebkitAspectRatio, CSSAspectRatioValue::create(narrowPrecisionToFloat(lvalue->fValue), narrowPrecisionToFloat(rvalue->fValue)), important);
6461
6462     return true;
6463 }
6464
6465 bool CSSParser::parseCounter(CSSPropertyID propId, int defaultValue, bool important)
6466 {
6467     enum { ID, VAL } state = ID;
6468
6469     RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
6470     RefPtr<CSSPrimitiveValue> counterName;
6471
6472     while (true) {
6473         CSSParserValue* val = m_valueList->current();
6474         switch (state) {
6475             case ID:
6476                 if (val && val->unit == CSSPrimitiveValue::CSS_IDENT) {
6477                     counterName = createPrimitiveStringValue(val);
6478                     state = VAL;
6479                     m_valueList->next();
6480                     continue;
6481                 }
6482                 break;
6483             case VAL: {
6484                 int i = defaultValue;
6485                 if (val && val->unit == CSSPrimitiveValue::CSS_NUMBER) {
6486                     i = clampToInteger(val->fValue);
6487                     m_valueList->next();
6488                 }
6489
6490                 list->append(cssValuePool().createValue(Pair::create(counterName.release(),
6491                     cssValuePool().createValue(i, CSSPrimitiveValue::CSS_NUMBER))));
6492                 state = ID;
6493                 continue;
6494             }
6495         }
6496         break;
6497     }
6498
6499     if (list->length() > 0) {
6500         addProperty(propId, list.release(), important);
6501         return true;
6502     }
6503
6504     return false;
6505 }
6506
6507 // This should go away once we drop support for -webkit-gradient
6508 static PassRefPtr<CSSPrimitiveValue> parseDeprecatedGradientPoint(CSSParserValue* a, bool horizontal)
6509 {
6510     RefPtr<CSSPrimitiveValue> result;
6511     if (a->unit == CSSPrimitiveValue::CSS_IDENT) {
6512         if ((equalIgnoringCase(a->string, "left") && horizontal)
6513             || (equalIgnoringCase(a->string, "top") && !horizontal))
6514             result = cssValuePool().createValue(0., CSSPrimitiveValue::CSS_PERCENTAGE);
6515         else if ((equalIgnoringCase(a->string, "right") && horizontal)
6516                  || (equalIgnoringCase(a->string, "bottom") && !horizontal))
6517             result = cssValuePool().createValue(100., CSSPrimitiveValue::CSS_PERCENTAGE);
6518         else if (equalIgnoringCase(a->string, "center"))
6519             result = cssValuePool().createValue(50., CSSPrimitiveValue::CSS_PERCENTAGE);
6520     } else if (a->unit == CSSPrimitiveValue::CSS_NUMBER || a->unit == CSSPrimitiveValue::CSS_PERCENTAGE)
6521         result = cssValuePool().createValue(a->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(a->unit));
6522     return result;
6523 }
6524
6525 static bool parseDeprecatedGradientColorStop(CSSParser* p, CSSParserValue* a, CSSGradientColorStop& stop)
6526 {
6527     if (a->unit != CSSParserValue::Function)
6528         return false;
6529
6530     if (!equalIgnoringCase(a->function->name, "from(") &&
6531         !equalIgnoringCase(a->function->name, "to(") &&
6532         !equalIgnoringCase(a->function->name, "color-stop("))
6533         return false;
6534
6535     CSSParserValueList* args = a->function->args.get();
6536     if (!args)
6537         return false;
6538
6539     if (equalIgnoringCase(a->function->name, "from(")
6540         || equalIgnoringCase(a->function->name, "to(")) {
6541         // The "from" and "to" stops expect 1 argument.
6542         if (args->size() != 1)
6543             return false;
6544
6545         if (equalIgnoringCase(a->function->name, "from("))
6546             stop.m_position = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER);
6547         else
6548             stop.m_position = cssValuePool().createValue(1, CSSPrimitiveValue::CSS_NUMBER);
6549
6550         int id = args->current()->id;
6551         if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu)
6552             stop.m_color = cssValuePool().createIdentifierValue(id);
6553         else
6554             stop.m_color = p->parseColor(args->current());
6555         if (!stop.m_color)
6556             return false;
6557     }
6558
6559     // The "color-stop" function expects 3 arguments.
6560     if (equalIgnoringCase(a->function->name, "color-stop(")) {
6561         if (args->size() != 3)
6562             return false;
6563
6564         CSSParserValue* stopArg = args->current();
6565         if (stopArg->unit == CSSPrimitiveValue::CSS_PERCENTAGE)
6566             stop.m_position = cssValuePool().createValue(stopArg->fValue / 100, CSSPrimitiveValue::CSS_NUMBER);
6567         else if (stopArg->unit == CSSPrimitiveValue::CSS_NUMBER)
6568             stop.m_position = cssValuePool().createValue(stopArg->fValue, CSSPrimitiveValue::CSS_NUMBER);
6569         else
6570             return false;
6571
6572         stopArg = args->next();
6573         if (stopArg->unit != CSSParserValue::Operator || stopArg->iValue != ',')
6574             return false;
6575
6576         stopArg = args->next();
6577         int id = stopArg->id;
6578         if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu)
6579             stop.m_color = cssValuePool().createIdentifierValue(id);
6580         else
6581             stop.m_color = p->parseColor(stopArg);
6582         if (!stop.m_color)
6583             return false;
6584     }
6585
6586     return true;
6587 }
6588
6589 bool CSSParser::parseDeprecatedGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient)
6590 {
6591     // Walk the arguments.
6592     CSSParserValueList* args = valueList->current()->function->args.get();
6593     if (!args || args->size() == 0)
6594         return false;
6595
6596     // The first argument is the gradient type.  It is an identifier.
6597     CSSGradientType gradientType;
6598     CSSParserValue* a = args->current();
6599     if (!a || a->unit != CSSPrimitiveValue::CSS_IDENT)
6600         return false;
6601     if (equalIgnoringCase(a->string, "linear"))
6602         gradientType = CSSLinearGradient;
6603     else if (equalIgnoringCase(a->string, "radial"))
6604         gradientType = CSSRadialGradient;
6605     else
6606         return false;
6607
6608     RefPtr<CSSGradientValue> result;
6609     switch (gradientType) {
6610         case CSSLinearGradient:
6611             result = CSSLinearGradientValue::create(NonRepeating, true);
6612             break;
6613         case CSSRadialGradient:
6614             result = CSSRadialGradientValue::create(NonRepeating, true);
6615             break;
6616     }
6617
6618     // Comma.
6619     a = args->next();
6620     if (!isComma(a))
6621         return false;
6622
6623     // Next comes the starting point for the gradient as an x y pair.  There is no
6624     // comma between the x and the y values.
6625     // First X.  It can be left, right, number or percent.
6626     a = args->next();
6627     if (!a)
6628         return false;
6629     RefPtr<CSSPrimitiveValue> point = parseDeprecatedGradientPoint(a, true);
6630     if (!point)
6631         return false;
6632     result->setFirstX(point.release());
6633
6634     // First Y.  It can be top, bottom, number or percent.
6635     a = args->next();
6636     if (!a)
6637         return false;
6638     point = parseDeprecatedGradientPoint(a, false);
6639     if (!point)
6640         return false;
6641     result->setFirstY(point.release());
6642
6643     // Comma after the first point.
6644     a = args->next();
6645     if (!isComma(a))
6646         return false;
6647
6648     // For radial gradients only, we now expect a numeric radius.
6649     if (gradientType == CSSRadialGradient) {
6650         a = args->next();
6651         if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER)
6652             return false;
6653         static_cast<CSSRadialGradientValue*>(result.get())->setFirstRadius(createPrimitiveNumericValue(a));
6654
6655         // Comma after the first radius.
6656         a = args->next();
6657         if (!isComma(a))
6658             return false;
6659     }
6660
6661     // Next is the ending point for the gradient as an x, y pair.
6662     // Second X.  It can be left, right, number or percent.
6663     a = args->next();
6664     if (!a)
6665         return false;
6666     point = parseDeprecatedGradientPoint(a, true);
6667     if (!point)
6668         return false;
6669     result->setSecondX(point.release());
6670
6671     // Second Y.  It can be top, bottom, number or percent.
6672     a = args->next();
6673     if (!a)
6674         return false;
6675     point = parseDeprecatedGradientPoint(a, false);
6676     if (!point)
6677         return false;
6678     result->setSecondY(point.release());
6679
6680     // For radial gradients only, we now expect the second radius.
6681     if (gradientType == CSSRadialGradient) {
6682         // Comma after the second point.
6683         a = args->next();
6684         if (!isComma(a))
6685             return false;
6686
6687         a = args->next();
6688         if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER)
6689             return false;
6690         static_cast<CSSRadialGradientValue*>(result.get())->setSecondRadius(createPrimitiveNumericValue(a));
6691     }
6692
6693     // We now will accept any number of stops (0 or more).
6694     a = args->next();
6695     while (a) {
6696         // Look for the comma before the next stop.
6697         if (!isComma(a))
6698             return false;
6699
6700         // Now examine the stop itself.
6701         a = args->next();
6702         if (!a)
6703             return false;
6704
6705         // The function name needs to be one of "from", "to", or "color-stop."
6706         CSSGradientColorStop stop;
6707         if (!parseDeprecatedGradientColorStop(this, a, stop))
6708             return false;
6709         result->addStop(stop);
6710
6711         // Advance
6712         a = args->next();
6713     }
6714
6715     gradient = result.release();
6716     return true;
6717 }
6718
6719 static PassRefPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, bool& isHorizontal)
6720 {
6721     if (a->unit != CSSPrimitiveValue::CSS_IDENT)
6722         return 0;
6723
6724     switch (a->id) {
6725         case CSSValueLeft:
6726         case CSSValueRight:
6727             isHorizontal = true;
6728             break;
6729         case CSSValueTop:
6730         case CSSValueBottom:
6731             isHorizontal = false;
6732             break;
6733         default:
6734             return 0;
6735     }
6736     return cssValuePool().createIdentifierValue(a->id);
6737 }
6738
6739 static PassRefPtr<CSSPrimitiveValue> parseGradientColorOrKeyword(CSSParser* p, CSSParserValue* value)
6740 {
6741     int id = value->id;
6742     if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor)
6743         return cssValuePool().createIdentifierValue(id);
6744
6745     return p->parseColor(value);
6746 }
6747
6748 bool CSSParser::parseLinearGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating)
6749 {
6750     RefPtr<CSSLinearGradientValue> result = CSSLinearGradientValue::create(repeating);
6751
6752     // Walk the arguments.
6753     CSSParserValueList* args = valueList->current()->function->args.get();
6754     if (!args || !args->size())
6755         return false;
6756
6757     CSSParserValue* a = args->current();
6758     if (!a)
6759         return false;
6760
6761     bool expectComma = false;
6762     // Look for angle.
6763     if (validUnit(a, FAngle, CSSStrictMode)) {
6764         result->setAngle(createPrimitiveNumericValue(a));
6765
6766         args->next();
6767         expectComma = true;
6768     } else {
6769         // Look one or two optional keywords that indicate a side or corner.
6770         RefPtr<CSSPrimitiveValue> startX, startY;
6771
6772         RefPtr<CSSPrimitiveValue> location;
6773         bool isHorizontal = false;
6774         if ((location = valueFromSideKeyword(a, isHorizontal))) {
6775             if (isHorizontal)
6776                 startX = location;
6777             else
6778                 startY = location;
6779
6780             if ((a = args->next())) {
6781                 if ((location = valueFromSideKeyword(a, isHorizontal))) {
6782                     if (isHorizontal) {
6783                         if (startX)
6784                             return false;
6785                         startX = location;
6786                     } else {
6787                         if (startY)
6788                             return false;
6789                         startY = location;
6790                     }
6791
6792                     args->next();
6793                 }
6794             }
6795
6796             expectComma = true;
6797         }
6798
6799         if (!startX && !startY)
6800             startY = cssValuePool().createIdentifierValue(CSSValueTop);
6801
6802         result->setFirstX(startX.release());
6803         result->setFirstY(startY.release());
6804     }
6805
6806     if (!parseGradientColorStops(args, result.get(), expectComma))
6807         return false;
6808
6809     Vector<CSSGradientColorStop>& stops = result->stops();
6810     if (stops.isEmpty())
6811         return false;
6812
6813     gradient = result.release();
6814     return true;
6815 }
6816
6817 bool CSSParser::parseRadialGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating)
6818 {
6819     RefPtr<CSSRadialGradientValue> result = CSSRadialGradientValue::create(repeating);
6820
6821     // Walk the arguments.
6822     CSSParserValueList* args = valueList->current()->function->args.get();
6823     if (!args || !args->size())
6824         return false;
6825
6826     CSSParserValue* a = args->current();
6827     if (!a)
6828         return false;
6829
6830     bool expectComma = false;
6831
6832     // Optional background-position
6833     RefPtr<CSSValue> centerX;
6834     RefPtr<CSSValue> centerY;
6835     // parseFillPosition advances the args next pointer.
6836     parseFillPosition(args, centerX, centerY);
6837     a = args->current();
6838     if (!a)
6839         return false;
6840
6841     if (centerX || centerY) {
6842         // Comma
6843         if (!isComma(a))
6844             return false;
6845
6846         a = args->next();
6847         if (!a)
6848             return false;
6849     }
6850
6851     ASSERT(!centerX || centerX->isPrimitiveValue());
6852     ASSERT(!centerY || centerY->isPrimitiveValue());
6853
6854     result->setFirstX(static_cast<CSSPrimitiveValue*>(centerX.get()));
6855     result->setSecondX(static_cast<CSSPrimitiveValue*>(centerX.get()));
6856     // CSS3 radial gradients always share the same start and end point.
6857     result->setFirstY(static_cast<CSSPrimitiveValue*>(centerY.get()));
6858     result->setSecondY(static_cast<CSSPrimitiveValue*>(centerY.get()));
6859
6860     RefPtr<CSSPrimitiveValue> shapeValue;
6861     RefPtr<CSSPrimitiveValue> sizeValue;
6862
6863     // Optional shape and/or size in any order.
6864     for (int i = 0; i < 2; ++i) {
6865         if (a->unit != CSSPrimitiveValue::CSS_IDENT)
6866             break;
6867
6868         bool foundValue = false;
6869         switch (a->id) {
6870         case CSSValueCircle:
6871         case CSSValueEllipse:
6872             shapeValue = cssValuePool().createIdentifierValue(a->id);
6873             foundValue = true;
6874             break;
6875         case CSSValueClosestSide:
6876         case CSSValueClosestCorner:
6877         case CSSValueFarthestSide:
6878         case CSSValueFarthestCorner:
6879         case CSSValueContain:
6880         case CSSValueCover:
6881             sizeValue = cssValuePool().createIdentifierValue(a->id);
6882             foundValue = true;
6883             break;
6884         }
6885
6886         if (foundValue) {
6887             a = args->next();
6888             if (!a)
6889                 return false;
6890
6891             expectComma = true;
6892         }
6893     }
6894
6895     result->setShape(shapeValue);
6896     result->setSizingBehavior(sizeValue);
6897
6898     // Or, two lengths or percentages
6899     RefPtr<CSSPrimitiveValue> horizontalSize;
6900     RefPtr<CSSPrimitiveValue> verticalSize;
6901
6902     if (!shapeValue && !sizeValue) {
6903         if (validUnit(a, FLength | FPercent)) {
6904             horizontalSize = createPrimitiveNumericValue(a);
6905             a = args->next();
6906             if (!a)
6907                 return false;
6908
6909             expectComma = true;
6910         }
6911
6912         if (validUnit(a, FLength | FPercent)) {
6913             verticalSize = createPrimitiveNumericValue(a);
6914
6915             a = args->next();
6916             if (!a)
6917                 return false;
6918             expectComma = true;
6919         }
6920     }
6921
6922     // Must have neither or both.
6923     if (!horizontalSize != !verticalSize)
6924         return false;
6925
6926     result->setEndHorizontalSize(horizontalSize);
6927     result->setEndVerticalSize(verticalSize);
6928
6929     if (!parseGradientColorStops(args, result.get(), expectComma))
6930         return false;
6931
6932     gradient = result.release();
6933     return true;
6934 }
6935
6936 bool CSSParser::parseGradientColorStops(CSSParserValueList* valueList, CSSGradientValue* gradient, bool expectComma)
6937 {
6938     CSSParserValue* a = valueList->current();
6939
6940     // Now look for color stops.
6941     while (a) {
6942         // Look for the comma before the next stop.
6943         if (expectComma) {
6944             if (!isComma(a))
6945                 return false;
6946
6947             a = valueList->next();
6948             if (!a)
6949                 return false;
6950         }
6951
6952         // <color-stop> = <color> [ <percentage> | <length> ]?
6953         CSSGradientColorStop stop;
6954         stop.m_color = parseGradientColorOrKeyword(this, a);
6955         if (!stop.m_color)
6956             return false;
6957
6958         a = valueList->next();
6959         if (a) {
6960             if (validUnit(a, FLength | FPercent)) {
6961                 stop.m_position = createPrimitiveNumericValue(a);
6962                 a = valueList->next();
6963             }
6964         }
6965
6966         gradient->addStop(stop);
6967         expectComma = true;
6968     }
6969
6970     // Must have 2 or more stops to be valid.
6971     return gradient->stops().size() > 1;
6972 }
6973
6974 bool CSSParser::isGeneratedImageValue(CSSParserValue* val) const
6975 {
6976     if (val->unit != CSSParserValue::Function)
6977         return false;
6978
6979     return equalIgnoringCase(val->function->name, "-webkit-gradient(")
6980         || equalIgnoringCase(val->function->name, "-webkit-linear-gradient(")
6981         || equalIgnoringCase(val->function->name, "-webkit-repeating-linear-gradient(")
6982         || equalIgnoringCase(val->function->name, "-webkit-radial-gradient(")
6983         || equalIgnoringCase(val->function->name, "-webkit-repeating-radial-gradient(")
6984         || equalIgnoringCase(val->function->name, "-webkit-canvas(")
6985         || equalIgnoringCase(val->function->name, "-webkit-cross-fade(");
6986 }
6987
6988 bool CSSParser::parseGeneratedImage(CSSParserValueList* valueList, RefPtr<CSSValue>& value)
6989 {
6990     CSSParserValue* val = valueList->current();
6991
6992     if (val->unit != CSSParserValue::Function)
6993         return false;
6994
6995     if (equalIgnoringCase(val->function->name, "-webkit-gradient("))
6996         return parseDeprecatedGradient(valueList, value);
6997
6998     if (equalIgnoringCase(val->function->name, "-webkit-linear-gradient("))
6999         return parseLinearGradient(valueList, value, NonRepeating);
7000
7001     if (equalIgnoringCase(val->function->name, "-webkit-repeating-linear-gradient("))
7002         return parseLinearGradient(valueList, value, Repeating);
7003
7004     if (equalIgnoringCase(val->function->name, "-webkit-radial-gradient("))
7005         return parseRadialGradient(valueList, value, NonRepeating);
7006
7007     if (equalIgnoringCase(val->function->name, "-webkit-repeating-radial-gradient("))
7008         return parseRadialGradient(valueList, value, Repeating);
7009
7010     if (equalIgnoringCase(val->function->name, "-webkit-canvas("))
7011         return parseCanvas(valueList, value);
7012
7013     if (equalIgnoringCase(val->function->name, "-webkit-cross-fade("))
7014         return parseCrossfade(valueList, value);
7015
7016     return false;
7017 }
7018
7019 bool CSSParser::parseCrossfade(CSSParserValueList* valueList, RefPtr<CSSValue>& crossfade)
7020 {
7021     RefPtr<CSSCrossfadeValue> result;
7022
7023     // Walk the arguments.
7024     CSSParserValueList* args = valueList->current()->function->args.get();
7025     if (!args || args->size() != 5)
7026         return false;
7027     CSSParserValue* a = args->current();
7028     RefPtr<CSSValue> fromImageValue;
7029     RefPtr<CSSValue> toImageValue;
7030
7031     // The first argument is the "from" image. It is a fill image.
7032     if (!a || !parseFillImage(args, fromImageValue))
7033         return false;
7034     a = args->next();
7035
7036     // Skip a comma
7037     if (!isComma(a))
7038         return false;
7039     a = args->next();
7040
7041     // The second argument is the "to" image. It is a fill image.
7042     if (!a || !parseFillImage(args, toImageValue))
7043         return false;
7044     a = args->next();
7045
7046     // Skip a comma
7047     if (!isComma(a))
7048         return false;
7049     a = args->next();
7050
7051     // The third argument is the crossfade value. It is a percentage or a fractional number.
7052     RefPtr<CSSPrimitiveValue> percentage;
7053     if (!a)
7054         return false;
7055     
7056     if (a->unit == CSSPrimitiveValue::CSS_PERCENTAGE)
7057         percentage = cssValuePool().createValue(clampTo<double>(a->fValue / 100, 0, 1), CSSPrimitiveValue::CSS_NUMBER);
7058     else if (a->unit == CSSPrimitiveValue::CSS_NUMBER)
7059         percentage = cssValuePool().createValue(clampTo<double>(a->fValue, 0, 1), CSSPrimitiveValue::CSS_NUMBER);
7060     else
7061         return false;
7062
7063     result = CSSCrossfadeValue::create(fromImageValue, toImageValue);
7064     result->setPercentage(percentage);
7065
7066     crossfade = result;
7067
7068     return true;
7069 }
7070
7071 bool CSSParser::parseCanvas(CSSParserValueList* valueList, RefPtr<CSSValue>& canvas)
7072 {
7073     // Walk the arguments.
7074     CSSParserValueList* args = valueList->current()->function->args.get();
7075     if (!args || args->size() != 1)
7076         return false;
7077
7078     // The first argument is the canvas name.  It is an identifier.
7079     CSSParserValue* value = args->current();
7080     if (!value || value->unit != CSSPrimitiveValue::CSS_IDENT)
7081         return false;
7082
7083     canvas = CSSCanvasValue::create(value->string);
7084     return true;
7085 }
7086
7087 #if ENABLE(CSS_IMAGE_RESOLUTION)
7088 PassRefPtr<CSSValue> CSSParser::parseImageResolution(CSSParserValueList* valueList)
7089 {
7090     RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
7091     bool haveResolution = false;
7092     bool haveFromImage = false;
7093     bool haveSnap = false;
7094
7095     CSSParserValue* value = valueList->current();
7096     while (value) {
7097         if (!haveFromImage && value->id == CSSValueFromImage) {
7098             list->append(cssValuePool().createIdentifierValue(value->id));
7099             haveFromImage = true;
7100         } else if (!haveSnap && value->id == CSSValueSnap) {
7101             list->append(cssValuePool().createIdentifierValue(value->id));
7102             haveSnap = true;
7103         } else if (!haveResolution && validUnit(value, FResolution | FNonNeg) && value->fValue > 0) {
7104             list->append(createPrimitiveNumericValue(value));
7105             haveResolution = true;
7106         } else
7107             return 0;
7108         value = m_valueList->next();
7109     }
7110     if (!list->length())
7111         return 0;
7112     if (!haveFromImage && !haveResolution)
7113         return 0;
7114     return list;
7115 }
7116 #endif
7117
7118 #if ENABLE(CSS_IMAGE_SET)
7119 PassRefPtr<CSSValue> CSSParser::parseImageSet(CSSParserValueList* valueList)
7120 {
7121     CSSParserValue* function = valueList->current();
7122
7123     if (function->unit != CSSParserValue::Function)
7124         return 0;
7125
7126     CSSParserValueList* functionArgs = valueList->current()->function->args.get();
7127     if (!functionArgs || !functionArgs->size() || !functionArgs->current())
7128         return 0;
7129
7130     RefPtr<CSSImageSetValue> imageSet = CSSImageSetValue::create();
7131
7132     CSSParserValue* arg = functionArgs->current();
7133     while (arg) {
7134         if (arg->unit != CSSPrimitiveValue::CSS_URI)
7135             return 0;
7136
7137         RefPtr<CSSImageValue> image = CSSImageValue::create(completeURL(arg->string));
7138         imageSet->append(image);
7139     
7140         arg = functionArgs->next();
7141         if (!arg || arg->unit != CSSPrimitiveValue::CSS_DIMENSION)
7142             return 0;
7143
7144         double imageScaleFactor = 0;
7145         const String& string = arg->string;
7146         const UChar* current = string.characters();
7147         const UChar* end = current + string.length();
7148         parseDouble(current, end, 'x', imageScaleFactor);
7149         if (imageScaleFactor <= 0)
7150             return 0;
7151         imageSet->append(cssValuePool().createValue(imageScaleFactor, CSSPrimitiveValue::CSS_NUMBER));
7152
7153         // If there are no more arguments, we're done.
7154         arg = functionArgs->next();
7155         if (!arg)
7156             break;
7157
7158         // If there are more arguments, they should be after a comma.
7159         if (!isComma(arg))
7160             return 0;
7161
7162         // Skip the comma and move on to the next argument.
7163         arg = functionArgs->next();
7164     }
7165
7166     return imageSet;
7167 }
7168 #endif
7169
7170 class TransformOperationInfo {
7171 public:
7172     TransformOperationInfo(const CSSParserString& name)
7173     : m_type(WebKitCSSTransformValue::UnknownTransformOperation)
7174     , m_argCount(1)
7175     , m_allowSingleArgument(false)
7176     , m_unit(CSSParser::FUnknown)
7177     {
7178         if (equalIgnoringCase(name, "scale(") || equalIgnoringCase(name, "scalex(") || equalIgnoringCase(name, "scaley(") || equalIgnoringCase(name, "scalez(")) {
7179             m_unit = CSSParser::FNumber;
7180             if (equalIgnoringCase(name, "scale("))
7181                 m_type = WebKitCSSTransformValue::ScaleTransformOperation;
7182             else if (equalIgnoringCase(name, "scalex("))
7183                 m_type = WebKitCSSTransformValue::ScaleXTransformOperation;
7184             else if (equalIgnoringCase(name, "scaley("))
7185                 m_type = WebKitCSSTransformValue::ScaleYTransformOperation;
7186             else
7187                 m_type = WebKitCSSTransformValue::ScaleZTransformOperation;
7188         } else if (equalIgnoringCase(name, "scale3d(")) {
7189             m_type = WebKitCSSTransformValue::Scale3DTransformOperation;
7190             m_argCount = 5;
7191             m_unit = CSSParser::FNumber;
7192         } else if (equalIgnoringCase(name, "rotate(")) {
7193             m_type = WebKitCSSTransformValue::RotateTransformOperation;
7194             m_unit = CSSParser::FAngle;
7195         } else if (equalIgnoringCase(name, "rotatex(") ||
7196                    equalIgnoringCase(name, "rotatey(") ||
7197                    equalIgnoringCase(name, "rotatez(")) {
7198             m_unit = CSSParser::FAngle;
7199             if (equalIgnoringCase(name, "rotatex("))
7200                 m_type = WebKitCSSTransformValue::RotateXTransformOperation;
7201             else if (equalIgnoringCase(name, "rotatey("))
7202                 m_type = WebKitCSSTransformValue::RotateYTransformOperation;
7203             else
7204                 m_type = WebKitCSSTransformValue::RotateZTransformOperation;
7205         } else if (equalIgnoringCase(name, "rotate3d(")) {
7206             m_type = WebKitCSSTransformValue::Rotate3DTransformOperation;
7207             m_argCount = 7;
7208             m_unit = CSSParser::FNumber;
7209         } else if (equalIgnoringCase(name, "skew(") || equalIgnoringCase(name, "skewx(") || equalIgnoringCase(name, "skewy(")) {
7210             m_unit = CSSParser::FAngle;
7211             if (equalIgnoringCase(name, "skew("))
7212                 m_type = WebKitCSSTransformValue::SkewTransformOperation;
7213             else if (equalIgnoringCase(name, "skewx("))
7214                 m_type = WebKitCSSTransformValue::SkewXTransformOperation;
7215             else
7216                 m_type = WebKitCSSTransformValue::SkewYTransformOperation;
7217         } else if (equalIgnoringCase(name, "translate(") || equalIgnoringCase(name, "translatex(") || equalIgnoringCase(name, "translatey(") || equalIgnoringCase(name, "translatez(")) {
7218             m_unit = CSSParser::FLength | CSSParser::FPercent;
7219             if (equalIgnoringCase(name, "translate("))
7220                 m_type = WebKitCSSTransformValue::TranslateTransformOperation;
7221             else if (equalIgnoringCase(name, "translatex("))
7222                 m_type = WebKitCSSTransformValue::TranslateXTransformOperation;
7223             else if (equalIgnoringCase(name, "translatey("))
7224                 m_type = WebKitCSSTransformValue::TranslateYTransformOperation;
7225             else
7226                 m_type = WebKitCSSTransformValue::TranslateZTransformOperation;
7227         } else if (equalIgnoringCase(name, "translate3d(")) {
7228             m_type = WebKitCSSTransformValue::Translate3DTransformOperation;
7229             m_argCount = 5;
7230             m_unit = CSSParser::FLength | CSSParser::FPercent;
7231         } else if (equalIgnoringCase(name, "matrix(")) {
7232             m_type = WebKitCSSTransformValue::MatrixTransformOperation;
7233             m_argCount = 11;
7234             m_unit = CSSParser::FNumber;
7235         } else if (equalIgnoringCase(name, "matrix3d(")) {
7236             m_type = WebKitCSSTransformValue::Matrix3DTransformOperation;
7237             m_argCount = 31;
7238             m_unit = CSSParser::FNumber;
7239         } else if (equalIgnoringCase(name, "perspective(")) {
7240             m_type = WebKitCSSTransformValue::PerspectiveTransformOperation;
7241             m_unit = CSSParser::FNumber;
7242         }
7243
7244         if (equalIgnoringCase(name, "scale(") || equalIgnoringCase(name, "skew(") || equalIgnoringCase(name, "translate(")) {
7245             m_allowSingleArgument = true;
7246             m_argCount = 3;
7247         }
7248     }
7249
7250     WebKitCSSTransformValue::TransformOperationType type() const { return m_type; }
7251     unsigned argCount() const { return m_argCount; }
7252     CSSParser::Units unit() const { return m_unit; }
7253
7254     bool unknown() const { return m_type == WebKitCSSTransformValue::UnknownTransformOperation; }
7255     bool hasCorrectArgCount(unsigned argCount) { return m_argCount == argCount || (m_allowSingleArgument && argCount == 1); }
7256
7257 private:
7258     WebKitCSSTransformValue::TransformOperationType m_type;
7259     unsigned m_argCount;
7260     bool m_allowSingleArgument;
7261     CSSParser::Units m_unit;
7262 };
7263
7264 PassRefPtr<CSSValueList> CSSParser::parseTransform()
7265 {
7266     if (!m_valueList)
7267         return 0;
7268
7269     // The transform is a list of functional primitives that specify transform operations.
7270     // We collect a list of WebKitCSSTransformValues, where each value specifies a single operation.
7271     RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
7272     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
7273         if (value->unit != CSSParserValue::Function || !value->function)
7274             return 0;
7275
7276         // Every primitive requires at least one argument.
7277         CSSParserValueList* args = value->function->args.get();
7278         if (!args)
7279             return 0;
7280
7281         // See if the specified primitive is one we understand.
7282         TransformOperationInfo info(value->function->name);
7283         if (info.unknown())
7284             return 0;
7285
7286         if (!info.hasCorrectArgCount(args->size()))
7287             return 0;
7288
7289         // Create the new WebKitCSSTransformValue for this operation and add it to our list.
7290         RefPtr<WebKitCSSTransformValue> transformValue = WebKitCSSTransformValue::create(info.type());
7291         list->append(transformValue);
7292
7293         // Snag our values.
7294         CSSParserValue* a = args->current();
7295         unsigned argNumber = 0;
7296         while (a) {
7297             CSSParser::Units unit = info.unit();
7298
7299             if (info.type() == WebKitCSSTransformValue::Rotate3DTransformOperation && argNumber == 3) {
7300                 // 4th param of rotate3d() is an angle rather than a bare number, validate it as such
7301                 if (!validUnit(a, FAngle, CSSStrictMode))
7302                     return 0;
7303             } else if (info.type() == WebKitCSSTransformValue::Translate3DTransformOperation && argNumber == 2) {
7304                 // 3rd param of translate3d() cannot be a percentage
7305                 if (!validUnit(a, FLength, CSSStrictMode))
7306                     return 0;
7307             } else if (info.type() == WebKitCSSTransformValue::TranslateZTransformOperation && argNumber == 0) {
7308                 // 1st param of translateZ() cannot be a percentage
7309                 if (!validUnit(a, FLength, CSSStrictMode))
7310                     return 0;
7311             } else if (info.type() == WebKitCSSTransformValue::PerspectiveTransformOperation && argNumber == 0) {
7312                 // 1st param of perspective() must be a non-negative number (deprecated) or length.
7313                 if (!validUnit(a, FNumber | FLength | FNonNeg, CSSStrictMode))
7314                     return 0;
7315             } else if (!validUnit(a, unit, CSSStrictMode))
7316                 return 0;
7317
7318             // Add the value to the current transform operation.
7319             transformValue->append(createPrimitiveNumericValue(a));
7320
7321             a = args->next();
7322             if (!a)
7323                 break;
7324             if (a->unit != CSSParserValue::Operator || a->iValue != ',')
7325                 return 0;
7326             a = args->next();
7327
7328             argNumber++;
7329         }
7330     }
7331
7332     return list.release();
7333 }
7334
7335 #if ENABLE(CSS_FILTERS)
7336
7337 static void filterInfoForName(const CSSParserString& name, WebKitCSSFilterValue::FilterOperationType& filterType, unsigned& maximumArgumentCount)
7338 {
7339     if (equalIgnoringCase(name, "grayscale("))
7340         filterType = WebKitCSSFilterValue::GrayscaleFilterOperation;
7341     else if (equalIgnoringCase(name, "sepia("))
7342         filterType = WebKitCSSFilterValue::SepiaFilterOperation;
7343     else if (equalIgnoringCase(name, "saturate("))
7344         filterType = WebKitCSSFilterValue::SaturateFilterOperation;
7345     else if (equalIgnoringCase(name, "hue-rotate("))
7346         filterType = WebKitCSSFilterValue::HueRotateFilterOperation;
7347     else if (equalIgnoringCase(name, "invert("))
7348         filterType = WebKitCSSFilterValue::InvertFilterOperation;
7349     else if (equalIgnoringCase(name, "opacity("))
7350         filterType = WebKitCSSFilterValue::OpacityFilterOperation;
7351     else if (equalIgnoringCase(name, "brightness("))
7352         filterType = WebKitCSSFilterValue::BrightnessFilterOperation;
7353     else if (equalIgnoringCase(name, "contrast("))
7354         filterType = WebKitCSSFilterValue::ContrastFilterOperation;
7355     else if (equalIgnoringCase(name, "blur("))
7356         filterType = WebKitCSSFilterValue::BlurFilterOperation;
7357     else if (equalIgnoringCase(name, "drop-shadow(")) {
7358         filterType = WebKitCSSFilterValue::DropShadowFilterOperation;
7359         maximumArgumentCount = 4;  // x-offset, y-offset, blur-radius, color -- spread and inset style not allowed.
7360     }
7361 #if ENABLE(CSS_SHADERS)
7362     else if (equalIgnoringCase(name, "custom("))
7363         filterType = WebKitCSSFilterValue::CustomFilterOperation;
7364 #endif
7365 }
7366
7367 #if ENABLE(CSS_SHADERS)
7368 static bool acceptCommaOperator(CSSParserValueList* argsList)
7369 {
7370     if (CSSParserValue* arg = argsList->current()) {
7371         if (!isComma(arg))
7372             return false;
7373         argsList->next();
7374     }
7375     return true;
7376 }
7377
7378 PassRefPtr<WebKitCSSFilterValue> CSSParser::parseCustomFilter(CSSParserValue* value)
7379 {
7380     CSSParserValueList* argsList = value->function->args.get();
7381     if (!argsList)
7382         return 0;
7383
7384     RefPtr<WebKitCSSFilterValue> filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::CustomFilterOperation);
7385
7386     // Custom filter syntax:
7387     //
7388     // vertexShader:    <uri> | none
7389     // fragmentShader:  <uri> | none
7390     //
7391     // box: filter-box | border-box | padding-box | content-box
7392     // vertexMesh:  +<integer>{1,2}[wsp<box>][wsp'detached']
7393     //
7394     // param-value: true|false[wsp+true|false]{0-3} |
7395     //              <number>[wsp+<number>]{0-3} |
7396     //              <array> |
7397     //              <transform> |
7398     //              <texture(<uri>)>
7399     // array: 'array('<number>[wsp<number>]*')'
7400     // css-3d-transform: <transform-function>;[<transform-function>]*
7401     // transform:   <css-3d-transform> | <mat>
7402     // mat:         'mat2('<number>(,<number>){3}')' | 
7403     //              'mat3('<number>(,<number>){8}')' | 
7404     //              'mat4('<number>(,<number>){15}')' )
7405     // param-def:   <param-name>wsp<param-value>
7406     // param-name:  <ident>
7407     // params:      [<param-def>[,<param-def>*]]
7408     //
7409     // custom(<vertex-shader>[wsp<fragment-shader>][,<vertex-mesh>][,<params>])
7410     
7411     // 1. Parse the shader URLs: <vertex-shader>[wsp<fragment-shader>]
7412     RefPtr<CSSValueList> shadersList = CSSValueList::createSpaceSeparated();
7413     bool hadAtLeastOneCustomShader = false;
7414     CSSParserValue* arg;
7415     while ((arg = argsList->current())) {
7416         RefPtr<CSSValue> value;
7417         if (arg->id == CSSValueNone)
7418             value = cssValuePool().createIdentifierValue(CSSValueNone);
7419         else if (arg->unit == CSSPrimitiveValue::CSS_URI) {
7420             KURL shaderURL = completeURL(arg->string);
7421             value = WebKitCSSShaderValue::create(shaderURL.string());
7422             hadAtLeastOneCustomShader = true;
7423         }
7424         if (!value)
7425             break;
7426         shadersList->append(value.release());
7427         argsList->next();
7428     }
7429
7430     if (!shadersList->length() || !hadAtLeastOneCustomShader || shadersList->length() > 2 || !acceptCommaOperator(argsList))
7431         return 0;
7432         
7433     filterValue->append(shadersList.release());
7434     
7435     // 2. Parse the mesh size <vertex-mesh>
7436     RefPtr<CSSValueList> meshSizeList = CSSValueList::createSpaceSeparated();
7437     
7438     while ((arg = argsList->current())) {
7439         if (!validUnit(arg, FInteger | FNonNeg, CSSStrictMode))
7440             break;
7441         int integerValue = clampToInteger(arg->fValue);
7442         // According to the specification we can only accept positive non-zero values.
7443         if (integerValue < 1)
7444             return 0;
7445         meshSizeList->append(cssValuePool().createValue(integerValue, CSSPrimitiveValue::CSS_NUMBER));
7446         argsList->next();
7447     }
7448     
7449     if (meshSizeList->length() > 2)
7450         return 0;
7451     
7452     if ((arg = argsList->current()) && (arg->id == CSSValueBorderBox || arg->id == CSSValuePaddingBox
7453         || arg->id == CSSValueContentBox || arg->id == CSSValueFilterBox)) {
7454         meshSizeList->append(cssValuePool().createIdentifierValue(arg->id));
7455         argsList->next();
7456     }
7457     
7458     if ((arg = argsList->current()) && arg->id == CSSValueDetached) {
7459         meshSizeList->append(cssValuePool().createIdentifierValue(arg->id));
7460         argsList->next();
7461     }
7462     
7463     if (meshSizeList->length()) {
7464         if (!acceptCommaOperator(argsList))
7465             return 0;
7466         filterValue->append(meshSizeList.release());
7467     }
7468     
7469     // 3. Parser the parameters.
7470     RefPtr<CSSValueList> paramList = CSSValueList::createCommaSeparated();
7471     
7472     while ((arg = argsList->current())) {
7473         if (arg->id || arg->unit != CSSPrimitiveValue::CSS_IDENT)
7474             return 0;
7475
7476         RefPtr<CSSValueList> parameter = CSSValueList::createSpaceSeparated();
7477         parameter->append(createPrimitiveStringValue(arg));
7478         argsList->next();
7479
7480         if (!(arg = argsList->current()))
7481             return 0;
7482
7483         // TODO: Implement other parameters types parsing.
7484         // textures: https://bugs.webkit.org/show_bug.cgi?id=71442
7485         // 3d-transforms: https://bugs.webkit.org/show_bug.cgi?id=71443
7486         // mat2, mat3, mat4: https://bugs.webkit.org/show_bug.cgi?id=71444
7487         RefPtr<CSSValueList> paramValueList = CSSValueList::createSpaceSeparated();
7488         while ((arg = argsList->current())) {
7489             // If we hit a comma it means we finished this parameter's values.
7490             if (isComma(arg))
7491                 break;
7492             if (!validUnit(arg, FNumber, CSSStrictMode))
7493                 return 0;
7494             paramValueList->append(cssValuePool().createValue(arg->fValue, CSSPrimitiveValue::CSS_NUMBER));
7495             argsList->next();
7496         }
7497         if (!paramValueList->length() || paramValueList->length() > 4)
7498             return 0;
7499         parameter->append(paramValueList.release());
7500         paramList->append(parameter.release());
7501         if (!acceptCommaOperator(argsList))
7502             return 0;
7503     }
7504     
7505     if (paramList->length())
7506         filterValue->append(paramList.release());
7507     
7508     return filterValue;
7509 }
7510 #endif
7511
7512 PassRefPtr<WebKitCSSFilterValue> CSSParser::parseBuiltinFilterArguments(CSSParserValueList* args, WebKitCSSFilterValue::FilterOperationType filterType)
7513 {
7514     RefPtr<WebKitCSSFilterValue> filterValue = WebKitCSSFilterValue::create(filterType);
7515     ASSERT(args);
7516
7517     switch (filterType) {    
7518     case WebKitCSSFilterValue::GrayscaleFilterOperation:
7519     case WebKitCSSFilterValue::SepiaFilterOperation:
7520     case WebKitCSSFilterValue::SaturateFilterOperation:
7521     case WebKitCSSFilterValue::InvertFilterOperation:
7522     case WebKitCSSFilterValue::OpacityFilterOperation:
7523     case WebKitCSSFilterValue::ContrastFilterOperation: {
7524         // One optional argument, 0-1 or 0%-100%, if missing use 100%.
7525         if (args->size() > 1)
7526             return 0;
7527
7528         if (args->size()) {
7529             CSSParserValue* value = args->current();
7530             if (!validUnit(value, FNumber | FPercent | FNonNeg, CSSStrictMode))
7531                 return 0;
7532                 
7533             double amount = value->fValue;
7534             
7535             // Saturate and Contrast allow values over 100%.
7536             if (filterType != WebKitCSSFilterValue::SaturateFilterOperation
7537                 && filterType != WebKitCSSFilterValue::ContrastFilterOperation) {
7538                 double maxAllowed = value->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 100.0 : 1.0;
7539                 if (amount > maxAllowed)
7540                     return 0;
7541             }
7542
7543             filterValue->append(cssValuePool().createValue(amount, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)));
7544         }
7545         break;
7546     }
7547     case WebKitCSSFilterValue::BrightnessFilterOperation: {
7548         // One optional argument, -1 to +1 or -100% to +100%, if missing use 0,
7549         if (args->size() > 1)
7550             return 0;
7551
7552         if (args->size()) {
7553             CSSParserValue* value = args->current();
7554             if (!validUnit(value, FNumber | FPercent, CSSStrictMode))
7555                 return 0;
7556                 
7557             double amount = value->fValue;
7558             double minAllowed = value->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? -100.0 : -1.0;
7559             double maxAllowed = value->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 100.0 : 1.0;
7560             if (amount < minAllowed || amount > maxAllowed)
7561                 return 0;
7562
7563             filterValue->append(cssValuePool().createValue(amount, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)));
7564         }
7565         break;
7566     }
7567     case WebKitCSSFilterValue::HueRotateFilterOperation: {
7568         // hue-rotate() takes one optional angle.
7569         if (args->size() > 1)
7570             return 0;
7571         
7572         if (args->size()) {
7573             CSSParserValue* argument = args->current();
7574             if (!validUnit(argument, FAngle, CSSStrictMode))
7575                 return 0;
7576         
7577             filterValue->append(createPrimitiveNumericValue(argument));
7578         }
7579         break;
7580     }
7581     case WebKitCSSFilterValue::BlurFilterOperation: {
7582         // Blur takes a single length. Zero parameters are allowed.
7583         if (args->size() > 1)
7584             return 0;
7585         
7586         if (args->size()) {
7587             CSSParserValue* argument = args->current();
7588             if (!validUnit(argument, FLength | FNonNeg, CSSStrictMode))
7589                 return 0;
7590
7591             filterValue->append(createPrimitiveNumericValue(argument));
7592         }
7593         break;
7594     }
7595     case WebKitCSSFilterValue::DropShadowFilterOperation: {
7596         // drop-shadow() takes a single shadow.
7597         RefPtr<CSSValueList> shadowValueList = parseShadow(args, CSSPropertyWebkitFilter);
7598         if (!shadowValueList || shadowValueList->length() != 1)
7599             return 0;
7600         
7601         filterValue->append((shadowValueList.release())->itemWithoutBoundsCheck(0));
7602         break;
7603     }
7604     default:
7605         ASSERT_NOT_REACHED();
7606     }
7607     return filterValue.release();
7608 }
7609
7610 PassRefPtr<CSSValueList> CSSParser::parseFilter()
7611 {
7612     if (!m_valueList)
7613         return 0;
7614
7615     // The filter is a list of functional primitives that specify individual operations.
7616     RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
7617     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
7618         if (value->unit != CSSPrimitiveValue::CSS_URI && (value->unit != CSSParserValue::Function || !value->function))
7619             return 0;
7620
7621         WebKitCSSFilterValue::FilterOperationType filterType = WebKitCSSFilterValue::UnknownFilterOperation;
7622
7623         // See if the specified primitive is one we understand.
7624         if (value->unit == CSSPrimitiveValue::CSS_URI) {
7625 #if ENABLE(SVG)
7626             RefPtr<WebKitCSSFilterValue> referenceFilterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::ReferenceFilterOperation);
7627             list->append(referenceFilterValue);
7628             referenceFilterValue->append(WebKitCSSSVGDocumentValue::create(value->string));
7629 #endif
7630         } else {
7631             const CSSParserString name = value->function->name;
7632             unsigned maximumArgumentCount = 1;
7633
7634             filterInfoForName(name, filterType, maximumArgumentCount);
7635
7636             if (filterType == WebKitCSSFilterValue::UnknownFilterOperation)
7637                 return 0;
7638
7639 #if ENABLE(CSS_SHADERS)
7640             if (filterType == WebKitCSSFilterValue::CustomFilterOperation) {
7641                 // Make sure parsing fails if custom filters are disabled.
7642                 if (!m_context.isCSSCustomFilterEnabled)
7643                     return 0;
7644                 
7645                 RefPtr<WebKitCSSFilterValue> filterValue = parseCustomFilter(value);
7646                 if (!filterValue)
7647                     return 0;
7648                 list->append(filterValue.release());
7649                 continue;
7650             }
7651 #endif
7652             CSSParserValueList* args = value->function->args.get();
7653             if (!args)
7654                 return 0;
7655
7656             RefPtr<WebKitCSSFilterValue> filterValue = parseBuiltinFilterArguments(args, filterType);
7657             if (!filterValue)
7658                 return 0;
7659             
7660             list->append(filterValue);
7661         }
7662     }
7663
7664     return list.release();
7665 }
7666 #endif
7667
7668 #if ENABLE(CSS_REGIONS)
7669 static bool validFlowName(const String& flowName)
7670 {
7671     return !(equalIgnoringCase(flowName, "auto")
7672             || equalIgnoringCase(flowName, "default")
7673             || equalIgnoringCase(flowName, "inherit")
7674             || equalIgnoringCase(flowName, "initial")
7675             || equalIgnoringCase(flowName, "none"));
7676 }
7677 #endif
7678
7679 bool CSSParser::cssRegionsEnabled() const
7680 {
7681     return m_context.isCSSRegionsEnabled;
7682 }
7683
7684 bool CSSParser::cssGridLayoutEnabled() const
7685 {
7686     return m_context.isCSSGridLayoutEnabled;
7687 }
7688
7689 #if ENABLE(CSS_REGIONS)
7690 bool CSSParser::parseFlowThread(const String& flowName)
7691 {
7692     setupParser("@-webkit-decls{-webkit-flow-into:", flowName, "}");
7693     cssyyparse(this);
7694
7695     m_rule = 0;
7696
7697     return ((m_parsedProperties.size() == 1) && (m_parsedProperties.first().id() == CSSPropertyWebkitFlowInto));
7698 }
7699
7700 // none | <ident>
7701 bool CSSParser::parseFlowThread(CSSPropertyID propId, bool important)
7702 {
7703     ASSERT(propId == CSSPropertyWebkitFlowInto);
7704     ASSERT(cssRegionsEnabled());
7705
7706     if (m_valueList->size() != 1)
7707         return false;
7708
7709     CSSParserValue* value = m_valueList->current();
7710     if (!value)
7711         return false;
7712
7713     if (value->unit != CSSPrimitiveValue::CSS_IDENT)
7714         return false;
7715
7716     if (value->id == CSSValueNone) {
7717         addProperty(propId, cssValuePool().createIdentifierValue(value->id), important);
7718         return true;
7719     }
7720
7721     String inputProperty = String(value->string);
7722     if (!inputProperty.isEmpty()) {
7723         if (!validFlowName(inputProperty))
7724             return false;
7725         addProperty(propId, cssValuePool().createValue(inputProperty, CSSPrimitiveValue::CSS_STRING), important);
7726     } else
7727         addProperty(propId, cssValuePool().createIdentifierValue(CSSValueNone), important);
7728
7729     return true;
7730 }
7731
7732 // -webkit-flow-from: none | <ident>
7733 bool CSSParser::parseRegionThread(CSSPropertyID propId, bool important)
7734 {
7735     ASSERT(propId == CSSPropertyWebkitFlowFrom);
7736     ASSERT(cssRegionsEnabled());
7737
7738     if (m_valueList->size() != 1)
7739         return false;
7740
7741     CSSParserValue* value = m_valueList->current();
7742     if (!value)
7743         return false;
7744
7745     if (value->unit != CSSPrimitiveValue::CSS_IDENT)
7746         return false;
7747
7748     if (value->id == CSSValueNone)
7749         addProperty(propId, cssValuePool().createIdentifierValue(value->id), important);
7750     else {
7751         String inputProperty = String(value->string);
7752         if (!inputProperty.isEmpty()) {
7753             if (!validFlowName(inputProperty))
7754                 return false;
7755             addProperty(propId, cssValuePool().createValue(inputProperty, CSSPrimitiveValue::CSS_STRING), important);
7756         } else
7757             addProperty(propId, cssValuePool().createIdentifierValue(CSSValueNone), important);
7758     }
7759
7760     return true;
7761 }
7762 #endif
7763
7764 bool CSSParser::parseTransformOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, CSSPropertyID& propId3, RefPtr<CSSValue>& value, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3)
7765 {
7766     propId1 = propId;
7767     propId2 = propId;
7768     propId3 = propId;
7769     if (propId == CSSPropertyWebkitTransformOrigin) {
7770         propId1 = CSSPropertyWebkitTransformOriginX;
7771         propId2 = CSSPropertyWebkitTransformOriginY;
7772         propId3 = CSSPropertyWebkitTransformOriginZ;
7773     }
7774
7775     switch (propId) {
7776         case CSSPropertyWebkitTransformOrigin:
7777             if (!parseTransformOriginShorthand(value, value2, value3))
7778                 return false;
7779             // parseTransformOriginShorthand advances the m_valueList pointer
7780             break;
7781         case CSSPropertyWebkitTransformOriginX: {
7782             value = parseFillPositionX(m_valueList.get());
7783             if (value)
7784                 m_valueList->next();
7785             break;
7786         }
7787         case CSSPropertyWebkitTransformOriginY: {
7788             value = parseFillPositionY(m_valueList.get());
7789             if (value)
7790                 m_valueList->next();
7791             break;
7792         }
7793         case CSSPropertyWebkitTransformOriginZ: {
7794             if (validUnit(m_valueList->current(), FLength))
7795                 value = createPrimitiveNumericValue(m_valueList->current());
7796             if (value)
7797                 m_valueList->next();
7798             break;
7799         }
7800         default:
7801             ASSERT_NOT_REACHED();
7802             return false;
7803     }
7804
7805     return value;
7806 }
7807
7808 bool CSSParser::parsePerspectiveOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, RefPtr<CSSValue>& value, RefPtr<CSSValue>& value2)
7809 {
7810     propId1 = propId;
7811     propId2 = propId;
7812     if (propId == CSSPropertyWebkitPerspectiveOrigin) {
7813         propId1 = CSSPropertyWebkitPerspectiveOriginX;
7814         propId2 = CSSPropertyWebkitPerspectiveOriginY;
7815     }
7816
7817     switch (propId) {
7818         case CSSPropertyWebkitPerspectiveOrigin:
7819             if (m_valueList->size() > 2)
7820                 return false;
7821             parseFillPosition(m_valueList.get(), value, value2);
7822             break;
7823         case CSSPropertyWebkitPerspectiveOriginX: {
7824             value = parseFillPositionX(m_valueList.get());
7825             if (value)
7826                 m_valueList->next();
7827             break;
7828         }
7829         case CSSPropertyWebkitPerspectiveOriginY: {
7830             value = parseFillPositionY(m_valueList.get());
7831             if (value)
7832                 m_valueList->next();
7833             break;
7834         }
7835         default:
7836             ASSERT_NOT_REACHED();
7837             return false;
7838     }
7839
7840     return value;
7841 }
7842
7843 bool CSSParser::parseTextEmphasisStyle(bool important)
7844 {
7845     unsigned valueListSize = m_valueList->size();
7846
7847     RefPtr<CSSPrimitiveValue> fill;
7848     RefPtr<CSSPrimitiveValue> shape;
7849
7850     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
7851         if (value->unit == CSSPrimitiveValue::CSS_STRING) {
7852             if (fill || shape || (valueListSize != 1 && !inShorthand()))
7853                 return false;
7854             addProperty(CSSPropertyWebkitTextEmphasisStyle, createPrimitiveStringValue(value), important);
7855             m_valueList->next();
7856             return true;
7857         }
7858
7859         if (value->id == CSSValueNone) {
7860             if (fill || shape || (valueListSize != 1 && !inShorthand()))
7861                 return false;
7862             addProperty(CSSPropertyWebkitTextEmphasisStyle, cssValuePool().createIdentifierValue(CSSValueNone), important);
7863             m_valueList->next();
7864             return true;
7865         }
7866
7867         if (value->id == CSSValueOpen || value->id == CSSValueFilled) {
7868             if (fill)
7869                 return false;
7870             fill = cssValuePool().createIdentifierValue(value->id);
7871         } else if (value->id == CSSValueDot || value->id == CSSValueCircle || value->id == CSSValueDoubleCircle || value->id == CSSValueTriangle || value->id == CSSValueSesame) {
7872             if (shape)
7873                 return false;
7874             shape = cssValuePool().createIdentifierValue(value->id);
7875         } else if (!inShorthand())
7876             return false;
7877         else
7878             break;
7879     }
7880
7881     if (fill && shape) {
7882         RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
7883         parsedValues->append(fill.release());
7884         parsedValues->append(shape.release());
7885         addProperty(CSSPropertyWebkitTextEmphasisStyle, parsedValues.release(), important);
7886         return true;
7887     }
7888     if (fill) {
7889         addProperty(CSSPropertyWebkitTextEmphasisStyle, fill.release(), important);
7890         return true;
7891     }
7892     if (shape) {
7893         addProperty(CSSPropertyWebkitTextEmphasisStyle, shape.release(), important);
7894         return true;
7895     }
7896
7897     return false;
7898 }
7899
7900 bool CSSParser::parseLineBoxContain(bool important)
7901 {
7902     LineBoxContain lineBoxContain = LineBoxContainNone;
7903
7904     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
7905         if (value->id == CSSValueBlock) {
7906             if (lineBoxContain & LineBoxContainBlock)
7907                 return false;
7908             lineBoxContain |= LineBoxContainBlock;
7909         } else if (value->id == CSSValueInline) {
7910             if (lineBoxContain & LineBoxContainInline)
7911                 return false;
7912             lineBoxContain |= LineBoxContainInline;
7913         } else if (value->id == CSSValueFont) {
7914             if (lineBoxContain & LineBoxContainFont)
7915                 return false;
7916             lineBoxContain |= LineBoxContainFont;
7917         } else if (value->id == CSSValueGlyphs) {
7918             if (lineBoxContain & LineBoxContainGlyphs)
7919                 return false;
7920             lineBoxContain |= LineBoxContainGlyphs;
7921         } else if (value->id == CSSValueReplaced) {
7922             if (lineBoxContain & LineBoxContainReplaced)
7923                 return false;
7924             lineBoxContain |= LineBoxContainReplaced;
7925         } else if (value->id == CSSValueInlineBox) {
7926             if (lineBoxContain & LineBoxContainInlineBox)
7927                 return false;
7928             lineBoxContain |= LineBoxContainInlineBox;
7929         } else
7930             return false;
7931     }
7932
7933     if (!lineBoxContain)
7934         return false;
7935
7936     addProperty(CSSPropertyWebkitLineBoxContain, CSSLineBoxContainValue::create(lineBoxContain), important);
7937     return true;
7938 }
7939
7940 bool CSSParser::parseFontFeatureTag(CSSValueList* settings)
7941 {
7942     // Feature tag name consists of 4-letter characters.
7943     static const int tagNameLength = 4;
7944
7945     CSSParserValue* value = m_valueList->current();
7946     // Feature tag name comes first
7947     if (value->unit != CSSPrimitiveValue::CSS_STRING)
7948         return false;
7949     if (value->string.length != tagNameLength)
7950         return false;
7951     for (int i = 0; i < tagNameLength; ++i) {
7952         // Limits the range of characters to 0x20-0x7E, following the tag name rules defiend in the OpenType specification.
7953         UChar character = value->string.characters[i];
7954         if (character < 0x20 || character > 0x7E)
7955             return false;
7956     }
7957
7958     String tag = value->string;
7959     int tagValue = 1;
7960     // Feature tag values could follow: <integer> | on | off
7961     value = m_valueList->next();
7962     if (value) {
7963         if (value->unit == CSSPrimitiveValue::CSS_NUMBER && value->isInt && value->fValue >= 0) {
7964             tagValue = clampToInteger(value->fValue);
7965             if (tagValue < 0)
7966                 return false;
7967             m_valueList->next();
7968         } else if (value->id == CSSValueOn || value->id == CSSValueOff) {
7969             tagValue = value->id == CSSValueOn;
7970             m_valueList->next();
7971         }
7972     }
7973     settings->append(FontFeatureValue::create(tag, tagValue));
7974     return true;
7975 }
7976
7977 bool CSSParser::parseFontFeatureSettings(bool important)
7978 {
7979     if (m_valueList->size() == 1 && m_valueList->current()->id == CSSValueNormal) {
7980         RefPtr<CSSPrimitiveValue> normalValue = cssValuePool().createIdentifierValue(CSSValueNormal);
7981         m_valueList->next();
7982         addProperty(CSSPropertyWebkitFontFeatureSettings, normalValue.release(), important);
7983         return true;
7984     }
7985
7986     RefPtr<CSSValueList> settings = CSSValueList::createCommaSeparated();
7987     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
7988         if (!parseFontFeatureTag(settings.get()))
7989             return false;
7990
7991         // If the list isn't parsed fully, the current value should be comma.
7992         value = m_valueList->current();
7993         if (value && !isComma(value))
7994             return false;
7995     }
7996     if (settings->length()) {
7997         addProperty(CSSPropertyWebkitFontFeatureSettings, settings.release(), important);
7998         return true;
7999     }
8000     return false;
8001 }
8002
8003 bool CSSParser::parseFontVariantLigatures(bool important)
8004 {
8005     RefPtr<CSSValueList> ligatureValues = CSSValueList::createSpaceSeparated();
8006     bool sawCommonLigaturesValue = false;
8007     bool sawDiscretionaryLigaturesValue = false;
8008     bool sawHistoricalLigaturesValue = false;
8009
8010     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
8011         if (value->unit != CSSPrimitiveValue::CSS_IDENT)
8012             return false;
8013
8014         switch (value->id) {
8015         case CSSValueNoCommonLigatures:
8016         case CSSValueCommonLigatures:
8017             if (sawCommonLigaturesValue)
8018                 return false;
8019             sawCommonLigaturesValue = true;
8020             ligatureValues->append(cssValuePool().createIdentifierValue(value->id));
8021             break;
8022         case CSSValueNoDiscretionaryLigatures:
8023         case CSSValueDiscretionaryLigatures:
8024             if (sawDiscretionaryLigaturesValue)
8025                 return false;
8026             sawDiscretionaryLigaturesValue = true;
8027             ligatureValues->append(cssValuePool().createIdentifierValue(value->id));
8028             break;
8029         case CSSValueNoHistoricalLigatures:
8030         case CSSValueHistoricalLigatures:
8031             if (sawHistoricalLigaturesValue)
8032                 return false;
8033             sawHistoricalLigaturesValue = true;
8034             ligatureValues->append(cssValuePool().createIdentifierValue(value->id));
8035             break;
8036         default:
8037             return false;
8038         }
8039     }
8040
8041     if (!ligatureValues->length())
8042         return false;
8043
8044     addProperty(CSSPropertyWebkitFontVariantLigatures, ligatureValues.release(), important);
8045     return true;
8046 }
8047
8048 bool CSSParser::parseCalculation(CSSParserValue* value, CalculationPermittedValueRange range) 
8049 {
8050     ASSERT(isCalculation(value));
8051     
8052     CSSParserValueList* args = value->function->args.get();
8053     if (!args || !args->size())
8054         return false;
8055
8056     ASSERT(!m_parsedCalculation);
8057     m_parsedCalculation = CSSCalcValue::create(value->function->name, args, range);
8058     
8059     if (!m_parsedCalculation)
8060         return false;
8061     
8062     return true;
8063 }
8064
8065 #define END_TOKEN 0
8066
8067 #include "CSSGrammar.h"
8068
8069 enum CharacterType {
8070     // Types for the main switch.
8071
8072     // The first 4 types must be grouped together, as they
8073     // represent the allowed chars in an identifier.
8074     CharacterCaselessU,
8075     CharacterIdentifierStart,
8076     CharacterNumber,
8077     CharacterDash,
8078
8079     CharacterOther,
8080     CharacterNull,
8081     CharacterWhiteSpace,
8082     CharacterEndMediaQuery,
8083     CharacterEndNthChild,
8084     CharacterQuote,
8085     CharacterExclamationMark,
8086     CharacterHashmark,
8087     CharacterDollar,
8088     CharacterAsterisk,
8089     CharacterPlus,
8090     CharacterDot,
8091     CharacterSlash,
8092     CharacterLess,
8093     CharacterAt,
8094     CharacterBackSlash,
8095     CharacterXor,
8096     CharacterVerticalBar,
8097     CharacterTilde,
8098 };
8099
8100 // 128 ASCII codes
8101 static const CharacterType typesOfASCIICharacters[128] = {
8102 /*   0 - Null               */ CharacterNull,
8103 /*   1 - Start of Heading   */ CharacterOther,
8104 /*   2 - Start of Text      */ CharacterOther,
8105 /*   3 - End of Text        */ CharacterOther,
8106 /*   4 - End of Transm.     */ CharacterOther,
8107 /*   5 - Enquiry            */ CharacterOther,
8108 /*   6 - Acknowledgment     */ CharacterOther,
8109 /*   7 - Bell               */ CharacterOther,
8110 /*   8 - Back Space         */ CharacterOther,
8111 /*   9 - Horizontal Tab     */ CharacterWhiteSpace,
8112 /*  10 - Line Feed          */ CharacterWhiteSpace,
8113 /*  11 - Vertical Tab       */ CharacterOther,
8114 /*  12 - Form Feed          */ CharacterWhiteSpace,
8115 /*  13 - Carriage Return    */ CharacterWhiteSpace,
8116 /*  14 - Shift Out          */ CharacterOther,
8117 /*  15 - Shift In           */ CharacterOther,
8118 /*  16 - Data Line Escape   */ CharacterOther,
8119 /*  17 - Device Control 1   */ CharacterOther,
8120 /*  18 - Device Control 2   */ CharacterOther,
8121 /*  19 - Device Control 3   */ CharacterOther,
8122 /*  20 - Device Control 4   */ CharacterOther,
8123 /*  21 - Negative Ack.      */ CharacterOther,
8124 /*  22 - Synchronous Idle   */ CharacterOther,
8125 /*  23 - End of Transmit    */ CharacterOther,
8126 /*  24 - Cancel             */ CharacterOther,
8127 /*  25 - End of Medium      */ CharacterOther,
8128 /*  26 - Substitute         */ CharacterOther,
8129 /*  27 - Escape             */ CharacterOther,
8130 /*  28 - File Separator     */ CharacterOther,
8131 /*  29 - Group Separator    */ CharacterOther,
8132 /*  30 - Record Separator   */ CharacterOther,
8133 /*  31 - Unit Separator     */ CharacterOther,
8134 /*  32 - Space              */ CharacterWhiteSpace,
8135 /*  33 - !                  */ CharacterExclamationMark,
8136 /*  34 - "                  */ CharacterQuote,
8137 /*  35 - #                  */ CharacterHashmark,
8138 /*  36 - $                  */ CharacterDollar,
8139 /*  37 - %                  */ CharacterOther,
8140 /*  38 - &                  */ CharacterOther,
8141 /*  39 - '                  */ CharacterQuote,
8142 /*  40 - (                  */ CharacterOther,
8143 /*  41 - )                  */ CharacterEndNthChild,
8144 /*  42 - *                  */ CharacterAsterisk,
8145 /*  43 - +                  */ CharacterPlus,
8146 /*  44 - ,                  */ CharacterOther,
8147 /*  45 - -                  */ CharacterDash,
8148 /*  46 - .                  */ CharacterDot,
8149 /*  47 - /                  */ CharacterSlash,
8150 /*  48 - 0                  */ CharacterNumber,
8151 /*  49 - 1                  */ CharacterNumber,
8152 /*  50 - 2                  */ CharacterNumber,
8153 /*  51 - 3                  */ CharacterNumber,
8154 /*  52 - 4                  */ CharacterNumber,
8155 /*  53 - 5                  */ CharacterNumber,
8156 /*  54 - 6                  */ CharacterNumber,
8157 /*  55 - 7                  */ CharacterNumber,
8158 /*  56 - 8                  */ CharacterNumber,
8159 /*  57 - 9                  */ CharacterNumber,
8160 /*  58 - :                  */ CharacterOther,
8161 /*  59 - ;                  */ CharacterEndMediaQuery,
8162 /*  60 - <                  */ CharacterLess,
8163 /*  61 - =                  */ CharacterOther,
8164 /*  62 - >                  */ CharacterOther,
8165 /*  63 - ?                  */ CharacterOther,
8166 /*  64 - @                  */ CharacterAt,
8167 /*  65 - A                  */ CharacterIdentifierStart,
8168 /*  66 - B                  */ CharacterIdentifierStart,
8169 /*  67 - C                  */ CharacterIdentifierStart,
8170 /*  68 - D                  */ CharacterIdentifierStart,
8171 /*  69 - E                  */ CharacterIdentifierStart,
8172 /*  70 - F                  */ CharacterIdentifierStart,
8173 /*  71 - G                  */ CharacterIdentifierStart,
8174 /*  72 - H                  */ CharacterIdentifierStart,
8175 /*  73 - I                  */ CharacterIdentifierStart,
8176 /*  74 - J                  */ CharacterIdentifierStart,
8177 /*  75 - K                  */ CharacterIdentifierStart,
8178 /*  76 - L                  */ CharacterIdentifierStart,
8179 /*  77 - M                  */ CharacterIdentifierStart,
8180 /*  78 - N                  */ CharacterIdentifierStart,
8181 /*  79 - O                  */ CharacterIdentifierStart,
8182 /*  80 - P                  */ CharacterIdentifierStart,
8183 /*  81 - Q                  */ CharacterIdentifierStart,
8184 /*  82 - R                  */ CharacterIdentifierStart,
8185 /*  83 - S                  */ CharacterIdentifierStart,
8186 /*  84 - T                  */ CharacterIdentifierStart,
8187 /*  85 - U                  */ CharacterCaselessU,
8188 /*  86 - V                  */ CharacterIdentifierStart,
8189 /*  87 - W                  */ CharacterIdentifierStart,
8190 /*  88 - X                  */ CharacterIdentifierStart,
8191 /*  89 - Y                  */ CharacterIdentifierStart,
8192 /*  90 - Z                  */ CharacterIdentifierStart,
8193 /*  91 - [                  */ CharacterOther,
8194 /*  92 - \                  */ CharacterBackSlash,
8195 /*  93 - ]                  */ CharacterOther,
8196 /*  94 - ^                  */ CharacterXor,
8197 /*  95 - _                  */ CharacterIdentifierStart,
8198 /*  96 - `                  */ CharacterOther,
8199 /*  97 - a                  */ CharacterIdentifierStart,
8200 /*  98 - b                  */ CharacterIdentifierStart,
8201 /*  99 - c                  */ CharacterIdentifierStart,
8202 /* 100 - d                  */ CharacterIdentifierStart,
8203 /* 101 - e                  */ CharacterIdentifierStart,
8204 /* 102 - f                  */ CharacterIdentifierStart,
8205 /* 103 - g                  */ CharacterIdentifierStart,
8206 /* 104 - h                  */ CharacterIdentifierStart,
8207 /* 105 - i                  */ CharacterIdentifierStart,
8208 /* 106 - j                  */ CharacterIdentifierStart,
8209 /* 107 - k                  */ CharacterIdentifierStart,
8210 /* 108 - l                  */ CharacterIdentifierStart,
8211 /* 109 - m                  */ CharacterIdentifierStart,
8212 /* 110 - n                  */ CharacterIdentifierStart,
8213 /* 111 - o                  */ CharacterIdentifierStart,
8214 /* 112 - p                  */ CharacterIdentifierStart,
8215 /* 113 - q                  */ CharacterIdentifierStart,
8216 /* 114 - r                  */ CharacterIdentifierStart,
8217 /* 115 - s                  */ CharacterIdentifierStart,
8218 /* 116 - t                  */ CharacterIdentifierStart,
8219 /* 117 - u                  */ CharacterCaselessU,
8220 /* 118 - v                  */ CharacterIdentifierStart,
8221 /* 119 - w                  */ CharacterIdentifierStart,
8222 /* 120 - x                  */ CharacterIdentifierStart,
8223 /* 121 - y                  */ CharacterIdentifierStart,
8224 /* 122 - z                  */ CharacterIdentifierStart,
8225 /* 123 - {                  */ CharacterEndMediaQuery,
8226 /* 124 - |                  */ CharacterVerticalBar,
8227 /* 125 - }                  */ CharacterOther,
8228 /* 126 - ~                  */ CharacterTilde,
8229 /* 127 - Delete             */ CharacterOther,
8230 };
8231
8232 // Utility functions for the CSS tokenizer.
8233
8234 static inline bool isCSSLetter(UChar character)
8235 {
8236     return character >= 128 || typesOfASCIICharacters[character] <= CharacterDash;
8237 }
8238
8239 static inline bool isCSSEscape(UChar character)
8240 {
8241     return character >= ' ' && character != 127;
8242 }
8243
8244 static inline bool isURILetter(UChar character)
8245 {
8246     return (character >= '*' && character != 127) || (character >= '#' && character <= '&') || character == '!';
8247 }
8248
8249 static inline bool isIdentifierStartAfterDash(UChar* currentCharacter)
8250 {
8251     return isASCIIAlpha(currentCharacter[0]) || currentCharacter[0] == '_' || currentCharacter[0] >= 128
8252         || (currentCharacter[0] == '\\' && isCSSEscape(currentCharacter[1]));
8253 }
8254
8255 static inline bool isEqualToCSSIdentifier(UChar* cssString, const char* constantString)
8256 {
8257     // Compare an UChar memory data with a zero terminated string.
8258     do {
8259         // The input must be part of an identifier if constantChar or constString
8260         // contains '-'. Otherwise toASCIILowerUnchecked('\r') would be equal to '-'.
8261         ASSERT((*constantString >= 'a' && *constantString <= 'z') || *constantString == '-');
8262         ASSERT(*constantString != '-' || isCSSLetter(*cssString));
8263         if (toASCIILowerUnchecked(*cssString++) != (*constantString++))
8264             return false;
8265     } while (*constantString);
8266     return true;
8267 }
8268
8269 static UChar* checkAndSkipEscape(UChar* currentCharacter)
8270 {
8271     // Returns with 0, if escape check is failed. Otherwise
8272     // it returns with the following character.
8273     ASSERT(*currentCharacter == '\\');
8274
8275     ++currentCharacter;
8276     if (!isCSSEscape(*currentCharacter))
8277         return 0;
8278
8279     if (isASCIIHexDigit(*currentCharacter)) {
8280         int length = 6;
8281
8282         do {
8283             ++currentCharacter;
8284         } while (isASCIIHexDigit(*currentCharacter) && --length);
8285
8286         // Optional space after the escape sequence.
8287         if (isHTMLSpace(*currentCharacter))
8288             ++currentCharacter;
8289         return currentCharacter;
8290     }
8291     return currentCharacter + 1;
8292 }
8293
8294 static inline UChar* skipWhiteSpace(UChar* currentCharacter)
8295 {
8296     while (isHTMLSpace(*currentCharacter))
8297         ++currentCharacter;
8298     return currentCharacter;
8299 }
8300
8301 // Main CSS tokenizer functions.
8302
8303 inline bool CSSParser::isIdentifierStart()
8304 {
8305     // Check whether an identifier is started.
8306     return isIdentifierStartAfterDash((*m_currentCharacter != '-') ? m_currentCharacter : m_currentCharacter + 1);
8307 }
8308
8309 inline UChar* CSSParser::checkAndSkipString(UChar* currentCharacter, UChar quote)
8310 {
8311     // Returns with 0, if string check is failed. Otherwise
8312     // it returns with the following character. This is necessary
8313     // since we cannot revert escape sequences, thus strings
8314     // must be validated before parsing.
8315     while (true) {
8316         if (UNLIKELY(*currentCharacter == quote)) {
8317             // String parsing is successful.
8318             return currentCharacter + 1;
8319         }
8320         if (UNLIKELY(!*currentCharacter)) {
8321             // String parsing is successful up to end of input.
8322             return currentCharacter;
8323         }
8324         if (UNLIKELY(*currentCharacter <= '\r' && (*currentCharacter == '\n' || (*currentCharacter | 0x1) == '\r'))) {
8325             // String parsing is failed for character '\n', '\f' or '\r'.
8326             return 0;
8327         }
8328
8329         if (LIKELY(currentCharacter[0] != '\\'))
8330             ++currentCharacter;
8331         else if (currentCharacter[1] == '\n' || currentCharacter[1] == '\f')
8332             currentCharacter += 2;
8333         else if (currentCharacter[1] == '\r')
8334             currentCharacter += currentCharacter[2] == '\n' ? 3 : 2;
8335         else {
8336             currentCharacter = checkAndSkipEscape(currentCharacter);
8337             if (!currentCharacter)
8338                 return 0;
8339         }
8340     }
8341 }
8342
8343 void CSSParser::parseEscape(UChar*& result)
8344 {
8345     ASSERT(*m_currentCharacter == '\\' && isCSSEscape(m_currentCharacter[1]));
8346
8347     ++m_currentCharacter;
8348     if (isASCIIHexDigit(*m_currentCharacter)) {
8349         unsigned unicode = 0;
8350         int length = 6;
8351
8352         do {
8353             unicode = (unicode << 4) + toASCIIHexValue(*m_currentCharacter++);
8354         } while (--length && isASCIIHexDigit(*m_currentCharacter));
8355
8356         // Characters above 0x10ffff are not handled.
8357         if (unicode > 0x10ffff)
8358             unicode = 0xfffd;
8359
8360         // Optional space after the escape sequence.
8361         if (isHTMLSpace(*m_currentCharacter))
8362             ++m_currentCharacter;
8363
8364         // Replace unicode with a surrogate pairs when it is bigger than 0xffff
8365         if (U16_LENGTH(unicode) == 2) {
8366             *result++ = U16_LEAD(unicode);
8367             *result = U16_TRAIL(unicode);
8368         } else
8369             *result = unicode;
8370     } else
8371         *result = *m_currentCharacter++;
8372     ++result;
8373 }
8374
8375 inline void CSSParser::parseIdentifier(UChar*& result, bool& hasEscape)
8376 {
8377     // If a valid identifier start is found, we can safely
8378     // parse the identifier until the next invalid character.
8379     ASSERT(isIdentifierStart());
8380     hasEscape = false;
8381     do {
8382         if (LIKELY(*m_currentCharacter != '\\'))
8383             *result++ = *m_currentCharacter++;
8384         else {
8385             hasEscape = true;
8386             parseEscape(result);
8387         }
8388     } while (isCSSLetter(m_currentCharacter[0]) || (m_currentCharacter[0] == '\\' && isCSSEscape(m_currentCharacter[1])));
8389 }
8390
8391 inline void CSSParser::parseString(UChar*& result, UChar quote)
8392 {
8393     while (true) {
8394         if (UNLIKELY(*m_currentCharacter == quote)) {
8395             // String parsing is done.
8396             ++m_currentCharacter;
8397             return;
8398         }
8399         if (UNLIKELY(!*m_currentCharacter)) {
8400             // String parsing is done, but don't advance pointer if at the end of input.
8401             return;
8402         }
8403         ASSERT(*m_currentCharacter > '\r' || (*m_currentCharacter < '\n' && *m_currentCharacter) || *m_currentCharacter == '\v');
8404
8405         if (LIKELY(m_currentCharacter[0] != '\\'))
8406             *result++ = *m_currentCharacter++;
8407         else if (m_currentCharacter[1] == '\n' || m_currentCharacter[1] == '\f')
8408             m_currentCharacter += 2;
8409         else if (m_currentCharacter[1] == '\r')
8410             m_currentCharacter += m_currentCharacter[2] == '\n' ? 3 : 2;
8411         else
8412             parseEscape(result);
8413     }
8414 }
8415
8416 inline void CSSParser::parseURI(UChar*& start, UChar*& result)
8417 {
8418     UChar* uriStart = skipWhiteSpace(m_currentCharacter);
8419
8420     if (*uriStart == '"' || *uriStart == '\'') {
8421         UChar quote = *uriStart;
8422         ++uriStart;
8423
8424         UChar* stringEnd = checkAndSkipString(uriStart, quote);
8425         if (!stringEnd)
8426             return;
8427         stringEnd = skipWhiteSpace(stringEnd);
8428         if (*stringEnd != ')')
8429             return;
8430
8431         start = result = m_currentCharacter = uriStart;
8432         parseString(result, quote);
8433
8434         m_currentCharacter = stringEnd + 1;
8435         m_token = URI;
8436     } else {
8437         UChar* stringEnd = uriStart;
8438
8439         while (isURILetter(*stringEnd)) {
8440             if (*stringEnd != '\\')
8441                 ++stringEnd;
8442             else {
8443                 stringEnd = checkAndSkipEscape(stringEnd);
8444                 if (!stringEnd)
8445                     return;
8446             }
8447         }
8448
8449         stringEnd = skipWhiteSpace(stringEnd);
8450         if (*stringEnd != ')')
8451             return;
8452
8453         start = result = m_currentCharacter = uriStart;
8454         while (isURILetter(*m_currentCharacter)) {
8455             if (LIKELY(*m_currentCharacter != '\\'))
8456                 *result++ = *m_currentCharacter++;
8457             else
8458                 parseEscape(result);
8459         }
8460
8461         m_currentCharacter = stringEnd + 1;
8462         m_token = URI;
8463     }
8464 }
8465
8466 inline bool CSSParser::parseUnicodeRange()
8467 {
8468     UChar* currentCharacter = m_currentCharacter + 1;
8469     int length = 6;
8470     ASSERT(*m_currentCharacter == '+');
8471
8472     while (isASCIIHexDigit(*currentCharacter) && length) {
8473         ++currentCharacter;
8474         --length;
8475     }
8476
8477     if (length && *currentCharacter == '?') {
8478         // At most 5 hex digit followed by a question mark.
8479         do {
8480             ++currentCharacter;
8481             --length;
8482         } while (*currentCharacter == '?' && length);
8483         m_currentCharacter = currentCharacter;
8484         return true;
8485     }
8486
8487     if (length < 6) {
8488         // At least one hex digit.
8489         if (currentCharacter[0] == '-' && isASCIIHexDigit(currentCharacter[1])) {
8490             // Followed by a dash and a hex digit.
8491             ++currentCharacter;
8492             length = 6;
8493             do {
8494                 ++currentCharacter;
8495             } while (--length && isASCIIHexDigit(*currentCharacter));
8496         }
8497         m_currentCharacter = currentCharacter;
8498         return true;
8499     }
8500     return false;
8501 }
8502
8503 bool CSSParser::parseNthChild()
8504 {
8505     UChar* currentCharacter = m_currentCharacter;
8506
8507     while (isASCIIDigit(*currentCharacter))
8508         ++currentCharacter;
8509     if (isASCIIAlphaCaselessEqual(*currentCharacter, 'n')) {
8510         m_currentCharacter = currentCharacter + 1;
8511         return true;
8512     }
8513     return false;
8514 }
8515
8516 bool CSSParser::parseNthChildExtra()
8517 {
8518     UChar* currentCharacter = skipWhiteSpace(m_currentCharacter);
8519     if (*currentCharacter != '+' && *currentCharacter != '-')
8520         return false;
8521
8522     currentCharacter = skipWhiteSpace(currentCharacter + 1);
8523     if (!isASCIIDigit(*currentCharacter))
8524         return false;
8525
8526     do {
8527         ++currentCharacter;
8528     } while (isASCIIDigit(*currentCharacter));
8529
8530     m_currentCharacter = currentCharacter;
8531     return true;
8532 }
8533
8534 inline void CSSParser::detectFunctionTypeToken(int length)
8535 {
8536     ASSERT(length > 0);
8537     UChar* name = m_tokenStart;
8538
8539     switch (length) {
8540     case 3:
8541         if (isASCIIAlphaCaselessEqual(name[0], 'n') && isASCIIAlphaCaselessEqual(name[1], 'o') && isASCIIAlphaCaselessEqual(name[2], 't'))
8542             m_token = NOTFUNCTION;
8543         else if (isASCIIAlphaCaselessEqual(name[0], 'u') && isASCIIAlphaCaselessEqual(name[1], 'r') && isASCIIAlphaCaselessEqual(name[2], 'l'))
8544             m_token = URI;
8545         return;
8546
8547     case 9:
8548         if (isEqualToCSSIdentifier(name, "nth-child"))
8549             m_parsingMode = NthChildMode;
8550         return;
8551
8552     case 11:
8553         if (isEqualToCSSIdentifier(name, "nth-of-type"))
8554             m_parsingMode = NthChildMode;
8555         return;
8556
8557     case 14:
8558         if (isEqualToCSSIdentifier(name, "nth-last-child"))
8559             m_parsingMode = NthChildMode;
8560         return;
8561
8562     case 16:
8563         if (isEqualToCSSIdentifier(name, "nth-last-of-type"))
8564             m_parsingMode = NthChildMode;
8565         return;
8566     }
8567 }
8568
8569 inline void CSSParser::detectMediaQueryToken(int length)
8570 {
8571     ASSERT(m_parsingMode == MediaQueryMode);
8572     UChar* name = m_tokenStart;
8573
8574     if (length == 3) {
8575         if (isASCIIAlphaCaselessEqual(name[0], 'a') && isASCIIAlphaCaselessEqual(name[1], 'n') && isASCIIAlphaCaselessEqual(name[2], 'd'))
8576             m_token = MEDIA_AND;
8577         else if (isASCIIAlphaCaselessEqual(name[0], 'n') && isASCIIAlphaCaselessEqual(name[1], 'o') && isASCIIAlphaCaselessEqual(name[2], 't'))
8578             m_token = MEDIA_NOT;
8579     } else if (length == 4) {
8580         if (isASCIIAlphaCaselessEqual(name[0], 'o') && isASCIIAlphaCaselessEqual(name[1], 'n')
8581                 && isASCIIAlphaCaselessEqual(name[2], 'l') && isASCIIAlphaCaselessEqual(name[3], 'y'))
8582             m_token = MEDIA_ONLY;
8583     }
8584 }
8585
8586 inline void CSSParser::detectNumberToken(UChar* type, int length)
8587 {
8588     ASSERT(length > 0);
8589
8590     switch (toASCIILowerUnchecked(type[0])) {
8591     case 'c':
8592         if (length == 2 && isASCIIAlphaCaselessEqual(type[1], 'm'))
8593             m_token = CMS;
8594         return;
8595
8596     case 'd':
8597         if (length == 3 && isASCIIAlphaCaselessEqual(type[1], 'e') && isASCIIAlphaCaselessEqual(type[2], 'g'))
8598             m_token = DEGS;
8599 #if ENABLE(CSS_IMAGE_RESOLUTION)
8600         else if (length > 2 && isASCIIAlphaCaselessEqual(type[1], 'p')) {
8601             if (length == 4) {
8602                 // There is a discussion about the name of this unit on www-style.
8603                 // Keep this compile time guard in place until that is resolved.
8604                 // http://lists.w3.org/Archives/Public/www-style/2012May/0915.html
8605                 if (isASCIIAlphaCaselessEqual(type[2], 'p') && isASCIIAlphaCaselessEqual(type[3], 'x'))
8606                     m_token = DPPX;
8607                 else if (isASCIIAlphaCaselessEqual(type[2], 'c') && isASCIIAlphaCaselessEqual(type[3], 'm'))
8608                     m_token = DPCM;
8609             } else if (length == 3 && isASCIIAlphaCaselessEqual(type[2], 'i'))
8610                     m_token = DPI;
8611         }
8612 #endif
8613         return;
8614
8615     case 'e':
8616         if (length == 2) {
8617             if (isASCIIAlphaCaselessEqual(type[1], 'm'))
8618                 m_token = EMS;
8619             else if (isASCIIAlphaCaselessEqual(type[1], 'x'))
8620                 m_token = EXS;
8621         }
8622         return;
8623
8624     case 'g':
8625         if (length == 4 && isASCIIAlphaCaselessEqual(type[1], 'r')
8626                 && isASCIIAlphaCaselessEqual(type[2], 'a') && isASCIIAlphaCaselessEqual(type[3], 'd'))
8627             m_token = GRADS;
8628         return;
8629
8630     case 'h':
8631         if (length == 2 && isASCIIAlphaCaselessEqual(type[1], 'z'))
8632             m_token = HERTZ;
8633         return;
8634
8635     case 'i':
8636         if (length == 2 && isASCIIAlphaCaselessEqual(type[1], 'n'))
8637             m_token = INS;
8638         return;
8639
8640     case 'k':
8641         if (length == 3 && isASCIIAlphaCaselessEqual(type[1], 'h') && isASCIIAlphaCaselessEqual(type[2], 'z'))
8642             m_token = KHERTZ;
8643         return;
8644
8645     case 'm':
8646         if (length == 2) {
8647             if (isASCIIAlphaCaselessEqual(type[1], 'm'))
8648                 m_token = MMS;
8649             else if (isASCIIAlphaCaselessEqual(type[1], 's'))
8650                 m_token = MSECS;
8651         }
8652         return;
8653
8654     case 'p':
8655         if (length == 2) {
8656             if (isASCIIAlphaCaselessEqual(type[1], 'x'))
8657                 m_token = PXS;
8658             else if (isASCIIAlphaCaselessEqual(type[1], 't'))
8659                 m_token = PTS;
8660             else if (isASCIIAlphaCaselessEqual(type[1], 'c'))
8661                 m_token = PCS;
8662         }
8663         return;
8664
8665     case 'r':
8666         if (length == 3) {
8667             if (isASCIIAlphaCaselessEqual(type[1], 'a') && isASCIIAlphaCaselessEqual(type[2], 'd'))
8668                 m_token = RADS;
8669             else if (isASCIIAlphaCaselessEqual(type[1], 'e') && isASCIIAlphaCaselessEqual(type[2], 'm'))
8670                 m_token = REMS;
8671         }
8672         return;
8673
8674     case 's':
8675         if (length == 1)
8676             m_token = SECS;
8677         return;
8678
8679     case 't':
8680         if (length == 4 && isASCIIAlphaCaselessEqual(type[1], 'u')
8681                 && isASCIIAlphaCaselessEqual(type[2], 'r') && isASCIIAlphaCaselessEqual(type[3], 'n'))
8682             m_token = TURNS;
8683         return;
8684     case 'v':
8685         if (length == 2) {
8686             if (isASCIIAlphaCaselessEqual(type[1], 'w'))
8687                 m_token = VW;
8688             else if (isASCIIAlphaCaselessEqual(type[1], 'h'))
8689                 m_token = VH;
8690         } else if (length == 4 && isASCIIAlphaCaselessEqual(type[1], 'm')
8691                 && isASCIIAlphaCaselessEqual(type[2], 'i') && isASCIIAlphaCaselessEqual(type[3], 'n'))
8692             m_token = VMIN;
8693         return;
8694
8695     default:
8696         if (type[0] == '_' && length == 5 && type[1] == '_' && isASCIIAlphaCaselessEqual(type[2], 'q')
8697                 && isASCIIAlphaCaselessEqual(type[3], 'e') && isASCIIAlphaCaselessEqual(type[4], 'm'))
8698             m_token = QEMS;
8699         return;
8700     }
8701 }
8702
8703 inline void CSSParser::detectDashToken(int length)
8704 {
8705     UChar* name = m_tokenStart;
8706
8707     if (length == 11) {
8708         if (isASCIIAlphaCaselessEqual(name[10], 'y') && isEqualToCSSIdentifier(name + 1, "webkit-an"))
8709             m_token = ANYFUNCTION;
8710         else if (isASCIIAlphaCaselessEqual(name[10], 'n') && isEqualToCSSIdentifier(name + 1, "webkit-mi"))
8711             m_token = MINFUNCTION;
8712         else if (isASCIIAlphaCaselessEqual(name[10], 'x') && isEqualToCSSIdentifier(name + 1, "webkit-ma"))
8713             m_token = MAXFUNCTION;
8714 #if ENABLE(CSS_VARIABLES)
8715         else if (cssVariablesEnabled() && isASCIIAlphaCaselessEqual(name[10], 'r') && isEqualToCSSIdentifier(name + 1, "webkit-va"))
8716             m_token = VARFUNCTION;
8717 #endif
8718     } else if (length == 12 && isEqualToCSSIdentifier(name + 1, "webkit-calc"))
8719         m_token = CALCFUNCTION;
8720 }
8721
8722 inline void CSSParser::detectAtToken(int length, bool hasEscape)
8723 {
8724     UChar* name = m_tokenStart;
8725     ASSERT(name[0] == '@' && length >= 2);
8726
8727     // charset, font-face, import, media, namespace, page,
8728     // -webkit-keyframes, and -webkit-mediaquery are not affected by hasEscape.
8729     switch (toASCIILowerUnchecked(name[1])) {
8730     case 'b':
8731         if (hasEscape)
8732             return;
8733
8734         switch (length) {
8735         case 12:
8736             if (isEqualToCSSIdentifier(name + 2, "ottom-left"))
8737                 m_token = BOTTOMLEFT_SYM;
8738             return;
8739
8740         case 13:
8741             if (isEqualToCSSIdentifier(name + 2, "ottom-right"))
8742                 m_token = BOTTOMRIGHT_SYM;
8743             return;
8744
8745         case 14:
8746             if (isEqualToCSSIdentifier(name + 2, "ottom-center"))
8747                 m_token = BOTTOMCENTER_SYM;
8748             return;
8749
8750         case 19:
8751             if (isEqualToCSSIdentifier(name + 2, "ottom-left-corner"))
8752                 m_token = BOTTOMLEFTCORNER_SYM;
8753             return;
8754
8755         case 20:
8756             if (isEqualToCSSIdentifier(name + 2, "ottom-right-corner"))
8757                 m_token = BOTTOMRIGHTCORNER_SYM;
8758             return;
8759         }
8760         return;
8761
8762     case 'c':
8763         if (length == 8 && isEqualToCSSIdentifier(name + 2, "harset"))
8764             m_token = CHARSET_SYM;
8765         return;
8766
8767     case 'f':
8768         if (length == 10 && isEqualToCSSIdentifier(name + 2, "ont-face"))
8769             m_token = FONT_FACE_SYM;
8770         return;
8771
8772     case 'i':
8773         if (length == 7 && isEqualToCSSIdentifier(name + 2, "mport")) {
8774             m_parsingMode = MediaQueryMode;
8775             m_token = IMPORT_SYM;
8776         }
8777         return;
8778
8779 #if ENABLE(TIZEN_CSS_ALIASES)
8780     case 'k':
8781         if (length == 10 && isEqualToCSSIdentifier(name + 2, "eyframes"))
8782             m_token = WEBKIT_KEYFRAMES_SYM;
8783         else if (!hasEscape && isEqualToCSSIdentifier(name + 2, "webkit-keyframe-rule"))
8784             m_token = WEBKIT_KEYFRAME_RULE_SYM;
8785         return;
8786 #endif
8787
8788     case 'l':
8789         if (hasEscape)
8790             return;
8791
8792         if (length == 9) {
8793             if (isEqualToCSSIdentifier(name + 2, "eft-top"))
8794                 m_token = LEFTTOP_SYM;
8795         } else if (length == 12) {
8796             // Checking the last character first could further reduce the possibile cases.
8797             if (isASCIIAlphaCaselessEqual(name[11], 'e') && isEqualToCSSIdentifier(name + 2, "eft-middl"))
8798                 m_token = LEFTMIDDLE_SYM;
8799             else if (isASCIIAlphaCaselessEqual(name[11], 'm') && isEqualToCSSIdentifier(name + 2, "eft-botto"))
8800                 m_token = LEFTBOTTOM_SYM;
8801         }
8802         return;
8803
8804     case 'm':
8805         if (length == 6 && isEqualToCSSIdentifier(name + 2, "edia")) {
8806             m_parsingMode = MediaQueryMode;
8807             m_token = MEDIA_SYM;
8808         }
8809         return;
8810
8811     case 'n':
8812         if (length == 10 && isEqualToCSSIdentifier(name + 2, "amespace"))
8813             m_token = NAMESPACE_SYM;
8814         return;
8815
8816     case 'p':
8817         if (length == 5 && isEqualToCSSIdentifier(name + 2, "age"))
8818             m_token = PAGE_SYM;
8819         return;
8820
8821     case 'r':
8822         if (hasEscape)
8823             return;
8824
8825         if (length == 10) {
8826             if (isEqualToCSSIdentifier(name + 2, "ight-top"))
8827                 m_token = RIGHTTOP_SYM;
8828         } else if (length == 13) {
8829             // Checking the last character first could further reduce the possibile cases.
8830             if (isASCIIAlphaCaselessEqual(name[12], 'e') && isEqualToCSSIdentifier(name + 2, "ight-middl"))
8831                 m_token = RIGHTMIDDLE_SYM;
8832             else if (isASCIIAlphaCaselessEqual(name[12], 'm') && isEqualToCSSIdentifier(name + 2, "ight-botto"))
8833                 m_token = RIGHTBOTTOM_SYM;
8834         }
8835         return;
8836
8837     case 't':
8838         if (hasEscape)
8839             return;
8840
8841         switch (length) {
8842         case 9:
8843             if (isEqualToCSSIdentifier(name + 2, "op-left"))
8844                 m_token = TOPLEFT_SYM;
8845             return;
8846
8847         case 10:
8848             if (isEqualToCSSIdentifier(name + 2, "op-right"))
8849                 m_token = TOPRIGHT_SYM;
8850             return;
8851
8852         case 11:
8853             if (isEqualToCSSIdentifier(name + 2, "op-center"))
8854                 m_token = TOPCENTER_SYM;
8855             return;
8856
8857         case 16:
8858             if (isEqualToCSSIdentifier(name + 2, "op-left-corner"))
8859                 m_token = TOPLEFTCORNER_SYM;
8860             return;
8861
8862         case 17:
8863             if (isEqualToCSSIdentifier(name + 2, "op-right-corner"))
8864                 m_token = TOPRIGHTCORNER_SYM;
8865             return;
8866         }
8867         return;
8868
8869     case '-':
8870         switch (length) {
8871         case 13:
8872             if (!hasEscape && isEqualToCSSIdentifier(name + 2, "webkit-rule"))
8873                 m_token = WEBKIT_RULE_SYM;
8874             return;
8875
8876         case 14:
8877             if (hasEscape)
8878                 return;
8879
8880             // Checking the last character first could further reduce the possibile cases.
8881             if (isASCIIAlphaCaselessEqual(name[13], 's') && isEqualToCSSIdentifier(name + 2, "webkit-decl"))
8882                 m_token = WEBKIT_DECLS_SYM;
8883             else if (isASCIIAlphaCaselessEqual(name[13], 'e') && isEqualToCSSIdentifier(name + 2, "webkit-valu"))
8884                 m_token = WEBKIT_VALUE_SYM;
8885             return;
8886
8887         case 15:
8888 #if ENABLE(CSS_REGIONS)
8889             if (!hasEscape && isEqualToCSSIdentifier(name + 2, "webkit-region"))
8890                 m_token = WEBKIT_REGION_RULE_SYM;
8891 #endif
8892             return;
8893
8894         case 17:
8895             if (!hasEscape && isEqualToCSSIdentifier(name + 2, "webkit-selector"))
8896                 m_token = WEBKIT_SELECTOR_SYM;
8897             return;
8898
8899         case 18:
8900             if (isEqualToCSSIdentifier(name + 2, "webkit-keyframes"))
8901                 m_token = WEBKIT_KEYFRAMES_SYM;
8902             return;
8903
8904         case 19:
8905             if (isEqualToCSSIdentifier(name + 2, "webkit-mediaquery")) {
8906                 m_parsingMode = MediaQueryMode;
8907                 m_token = WEBKIT_MEDIAQUERY_SYM;
8908             }
8909             return;
8910
8911         case 22:
8912             if (!hasEscape && isEqualToCSSIdentifier(name + 2, "webkit-keyframe-rule"))
8913                 m_token = WEBKIT_KEYFRAME_RULE_SYM;
8914             return;
8915         }
8916     }
8917 }
8918
8919 int CSSParser::lex(void* yylvalWithoutType)
8920 {
8921     YYSTYPE* yylval = static_cast<YYSTYPE*>(yylvalWithoutType);
8922     // Write pointer for the next character.
8923     UChar* result;
8924     bool hasEscape;
8925
8926     // The input buffer is terminated by a \0 character, so
8927     // it is safe to read one character ahead of a known non-null.
8928
8929 #ifndef NDEBUG
8930     // In debug we check with an ASSERT that the length is > 0 for string types.
8931     yylval->string.characters = 0;
8932     yylval->string.length = 0;
8933 #endif
8934
8935 restartAfterComment:
8936     m_tokenStart = result = m_currentCharacter;
8937     m_token = *m_currentCharacter;
8938     ++m_currentCharacter;
8939
8940     switch ((m_token <= 127) ? typesOfASCIICharacters[m_token] : CharacterIdentifierStart) {
8941     case CharacterCaselessU:
8942         if (UNLIKELY(*m_currentCharacter == '+'))
8943             if (parseUnicodeRange()) {
8944                 m_token = UNICODERANGE;
8945                 yylval->string.characters = m_tokenStart;
8946                 yylval->string.length = m_currentCharacter - m_tokenStart;
8947                 break;
8948             }
8949         // Fall through to CharacterIdentifierStart.
8950
8951     case CharacterIdentifierStart:
8952         --m_currentCharacter;
8953         parseIdentifier(result, hasEscape);
8954         m_token = IDENT;
8955
8956         yylval->string.characters = m_tokenStart;
8957         yylval->string.length = result - m_tokenStart;
8958
8959         if (UNLIKELY(*m_currentCharacter == '(')) {
8960             m_token = FUNCTION;
8961             if (!hasEscape)
8962                 detectFunctionTypeToken(result - m_tokenStart);
8963             ++m_currentCharacter;
8964             ++result;
8965             ++yylval->string.length;
8966
8967             if (token() == URI) {
8968                 m_token = FUNCTION;
8969                 // Check whether it is really an URI.
8970                 parseURI(yylval->string.characters, result);
8971                 yylval->string.length = result - yylval->string.characters;
8972             }
8973         } else if (UNLIKELY(m_parsingMode != NormalMode) && !hasEscape) {
8974             if (m_parsingMode == MediaQueryMode)
8975                 detectMediaQueryToken(result - m_tokenStart);
8976             else if (m_parsingMode == NthChildMode && isASCIIAlphaCaselessEqual(m_tokenStart[0], 'n')) {
8977                 if (result - m_tokenStart == 1) {
8978                     // String "n" is IDENT but "n+1" is NTH.
8979                     if (parseNthChildExtra()) {
8980                         m_token = NTH;
8981                         yylval->string.length = m_currentCharacter - m_tokenStart;
8982                     }
8983                 } else if (result - m_tokenStart >= 2 && m_tokenStart[1] == '-') {
8984                     // String "n-" is IDENT but "n-1" is NTH.
8985                     // Set m_currentCharacter to '-' to continue parsing.
8986                     UChar* nextCharacter = result;
8987                     m_currentCharacter = m_tokenStart + 1;
8988                     if (parseNthChildExtra()) {
8989                         m_token = NTH;
8990                         yylval->string.length = m_currentCharacter - m_tokenStart;
8991                     } else {
8992                         // Revert the change to m_currentCharacter if unsuccessful.
8993                         m_currentCharacter = nextCharacter;
8994                     }
8995                 }
8996             }
8997         }
8998         break;
8999     case CharacterDot:
9000         if (!isASCIIDigit(m_currentCharacter[0]))
9001             break;
9002         // Fall through to CharacterNumber.
9003
9004     case CharacterNumber: {
9005         bool dotSeen = (m_token == '.');
9006
9007         while (true) {
9008             if (!isASCIIDigit(m_currentCharacter[0])) {
9009                 // Only one dot is allowed for a number,
9010                 // and it must be followed by a digit.
9011                 if (m_currentCharacter[0] != '.' || dotSeen || !isASCIIDigit(m_currentCharacter[1]))
9012                     break;
9013                 dotSeen = true;
9014             }
9015             ++m_currentCharacter;
9016         }
9017
9018         if (UNLIKELY(m_parsingMode == NthChildMode) && !dotSeen && isASCIIAlphaCaselessEqual(*m_currentCharacter, 'n')) {
9019             // "[0-9]+n" is always an NthChild.
9020             ++m_currentCharacter;
9021             parseNthChildExtra();
9022             m_token = NTH;
9023             yylval->string.characters = m_tokenStart;
9024             yylval->string.length = m_currentCharacter - m_tokenStart;
9025             break;
9026         }
9027
9028 #if ENABLE(SVG)
9029         // Use SVG parser for numbers on SVG presentation attributes.
9030         if (m_context.mode == SVGAttributeMode) {
9031             // We need to take care of units like 'em' or 'ex'.
9032             UChar* currentCharacter = m_currentCharacter;
9033             if (isASCIIAlphaCaselessEqual(*currentCharacter, 'e')) {
9034                 ASSERT(currentCharacter - m_tokenStart > 0);
9035                 ++currentCharacter;
9036                 if (*currentCharacter == '-' || *currentCharacter == '+' || isASCIIDigit(*currentCharacter)) {
9037                     ++currentCharacter;
9038                     while (isASCIIDigit(*currentCharacter))
9039                         ++currentCharacter;
9040                     // Use FLOATTOKEN if the string contains exponents.
9041                     dotSeen = true;
9042                     m_currentCharacter = currentCharacter;
9043                 }
9044             }
9045             if (!parseSVGNumber(m_tokenStart, currentCharacter - m_tokenStart, yylval->number))
9046                 break;
9047         } else
9048 #endif
9049             yylval->number = charactersToDouble(m_tokenStart, m_currentCharacter - m_tokenStart);
9050  
9051         // Type of the function.
9052         if (isIdentifierStart()) {
9053             UChar* type = m_currentCharacter;
9054             result = m_currentCharacter;
9055
9056             parseIdentifier(result, hasEscape);
9057             if (*m_currentCharacter == '+') {
9058                 // Any identifier followed by a '+' sign is an invalid dimension.
9059                 ++m_currentCharacter;
9060                 m_token = INVALIDDIMEN;
9061             } else {
9062                 m_token = DIMEN;
9063                 if (!hasEscape)
9064                     detectNumberToken(type, m_currentCharacter - type);
9065
9066                 if (m_token == DIMEN) {
9067                     // The decoded number is overwritten, but this is intentional.
9068                     yylval->string.characters = m_tokenStart;
9069                     yylval->string.length = m_currentCharacter - m_tokenStart;
9070                 }
9071             }
9072         } else if (*m_currentCharacter == '%') {
9073             // Although the CSS grammar says {num}% we follow
9074             // webkit at the moment which uses {num}%+.
9075             do {
9076                 ++m_currentCharacter;
9077             } while (*m_currentCharacter == '%');
9078             m_token = PERCENTAGE;
9079         } else
9080             m_token = dotSeen ? FLOATTOKEN : INTEGER;
9081         break;
9082     }
9083
9084     case CharacterDash:
9085         if (isIdentifierStartAfterDash(m_currentCharacter)) {
9086             --m_currentCharacter;
9087             parseIdentifier(result, hasEscape);
9088             m_token = IDENT;
9089
9090 #if ENABLE(CSS_VARIABLES)
9091             if (cssVariablesEnabled() && isEqualToCSSIdentifier(m_tokenStart + 1, "webkit-var") && m_tokenStart[11] == '-' && isIdentifierStartAfterDash(m_tokenStart + 12))
9092                 m_token = VAR_DEFINITION;
9093             else
9094 #endif
9095             if (*m_currentCharacter == '(') {
9096                 m_token = FUNCTION;
9097                 if (!hasEscape)
9098                     detectDashToken(result - m_tokenStart);
9099                 ++m_currentCharacter;
9100                 ++result;
9101             } else if (UNLIKELY(m_parsingMode == NthChildMode) && !hasEscape && isASCIIAlphaCaselessEqual(m_tokenStart[1], 'n')) {
9102                 if (result - m_tokenStart == 2) {
9103                     // String "-n" is IDENT but "-n+1" is NTH.
9104                     if (parseNthChildExtra()) {
9105                         m_token = NTH;
9106                         result = m_currentCharacter;
9107                     }
9108                 } else if (result - m_tokenStart >= 3 && m_tokenStart[2] == '-') {
9109                     // String "-n-" is IDENT but "-n-1" is NTH.
9110                     // Set m_currentCharacter to second '-' of '-n-' to continue parsing.
9111                     UChar* nextCharacter = result;
9112                     m_currentCharacter = m_tokenStart + 2;
9113                     if (parseNthChildExtra()) {
9114                         m_token = NTH;
9115                         result = m_currentCharacter;
9116                     } else {
9117                         // Revert the change to m_currentCharacter if unsuccessful.
9118                         m_currentCharacter = nextCharacter;
9119                     }
9120                 }
9121             }
9122             yylval->string.characters = m_tokenStart;
9123             yylval->string.length = result - m_tokenStart;
9124         } else if (m_currentCharacter[0] == '-' && m_currentCharacter[1] == '>') {
9125             m_currentCharacter += 2;
9126             m_token = SGML_CD;
9127         } else if (UNLIKELY(m_parsingMode == NthChildMode)) {
9128             // "-[0-9]+n" is always an NthChild.
9129             if (parseNthChild()) {
9130                 parseNthChildExtra();
9131                 m_token = NTH;
9132                 yylval->string.characters = m_tokenStart;
9133                 yylval->string.length = m_currentCharacter - m_tokenStart;
9134             }
9135         }
9136         break;
9137
9138     case CharacterOther:
9139         // m_token is simply the current character.
9140         break;
9141
9142     case CharacterNull:
9143         // Do not advance pointer at the end of input.
9144         --m_currentCharacter;
9145         break;
9146
9147     case CharacterWhiteSpace:
9148         m_token = WHITESPACE;
9149         // Might start with a '\n'.
9150         --m_currentCharacter;
9151         do {
9152             if (*m_currentCharacter == '\n')
9153                 ++m_lineNumber;
9154             ++m_currentCharacter;
9155         } while (*m_currentCharacter <= ' ' && (typesOfASCIICharacters[*m_currentCharacter] == CharacterWhiteSpace));
9156         break;
9157
9158     case CharacterEndMediaQuery:
9159         if (m_parsingMode == MediaQueryMode)
9160             m_parsingMode = NormalMode;
9161         break;
9162
9163     case CharacterEndNthChild:
9164         if (m_parsingMode == NthChildMode)
9165             m_parsingMode = NormalMode;
9166         break;
9167
9168     case CharacterQuote:
9169         if (checkAndSkipString(m_currentCharacter, m_token)) {
9170             ++result;
9171             parseString(result, m_token);
9172             m_token = STRING;
9173             yylval->string.characters = m_tokenStart + 1;
9174             yylval->string.length = result - (m_tokenStart + 1);
9175         }
9176         break;
9177
9178     case CharacterExclamationMark: {
9179         UChar* start = skipWhiteSpace(m_currentCharacter);
9180         if (isEqualToCSSIdentifier(start, "important")) {
9181             m_token = IMPORTANT_SYM;
9182             m_currentCharacter = start + 9;
9183         }
9184         break;
9185     }
9186
9187     case CharacterHashmark: {
9188         UChar* start = m_currentCharacter;
9189         result = m_currentCharacter;
9190
9191         if (isASCIIDigit(*m_currentCharacter)) {
9192             // This must be a valid hex number token.
9193             do {
9194                 ++m_currentCharacter;
9195             } while (isASCIIHexDigit(*m_currentCharacter));
9196             m_token = HEX;
9197             yylval->string.characters = start;
9198             yylval->string.length = m_currentCharacter - start;
9199         } else if (isIdentifierStart()) {
9200             m_token = IDSEL;
9201             parseIdentifier(result, hasEscape);
9202             if (!hasEscape) {
9203                 // Check whether the identifier is also a valid hex number.
9204                 UChar* current = start;
9205                 m_token = HEX;
9206                 do {
9207                     if (!isASCIIHexDigit(*current)) {
9208                         m_token = IDSEL;
9209                         break;
9210                     }
9211                     ++current;
9212                 } while (current < result);
9213             }
9214             yylval->string.characters = start;
9215             yylval->string.length = result - start;
9216         }
9217         break;
9218     }
9219
9220     case CharacterSlash:
9221         // Ignore comments. They are not even considered as white spaces.
9222         if (*m_currentCharacter == '*') {
9223             ++m_currentCharacter;
9224             while (m_currentCharacter[0] != '*' || m_currentCharacter[1] != '/') {
9225                 if (*m_currentCharacter == '\n')
9226                     ++m_lineNumber;
9227                 if (*m_currentCharacter == '\0') {
9228                     // Unterminated comments are simply ignored.
9229                     m_currentCharacter -= 2;
9230                     break;
9231                 }
9232                 ++m_currentCharacter;
9233             }
9234             m_currentCharacter += 2;
9235             goto restartAfterComment;
9236         }
9237         break;
9238
9239     case CharacterDollar:
9240         if (*m_currentCharacter == '=') {
9241             ++m_currentCharacter;
9242             m_token = ENDSWITH;
9243         }
9244         break;
9245
9246     case CharacterAsterisk:
9247         if (*m_currentCharacter == '=') {
9248             ++m_currentCharacter;
9249             m_token = CONTAINS;
9250         }
9251         break;
9252
9253     case CharacterPlus:
9254         if (UNLIKELY(m_parsingMode == NthChildMode)) {
9255             // Simplest case. "+[0-9]*n" is always NthChild.
9256             if (parseNthChild()) {
9257                 parseNthChildExtra();
9258                 m_token = NTH;
9259                 yylval->string.characters = m_tokenStart;
9260                 yylval->string.length = m_currentCharacter - m_tokenStart;
9261             }
9262         }
9263         break;
9264
9265     case CharacterLess:
9266         if (m_currentCharacter[0] == '!' && m_currentCharacter[1] == '-' && m_currentCharacter[2] == '-') {
9267             m_currentCharacter += 3;
9268             m_token = SGML_CD;
9269         }
9270         break;
9271
9272     case CharacterAt:
9273         if (isIdentifierStart()) {
9274             m_token = ATKEYWORD;
9275             ++result;
9276             parseIdentifier(result, hasEscape);
9277             detectAtToken(result - m_tokenStart, hasEscape);
9278         }
9279         break;
9280
9281     case CharacterBackSlash:
9282         if (isCSSEscape(*m_currentCharacter)) {
9283             --m_currentCharacter;
9284             parseIdentifier(result, hasEscape);
9285             m_token = IDENT;
9286             yylval->string.characters = m_tokenStart;
9287             yylval->string.length = result - m_tokenStart;
9288         }
9289         break;
9290
9291     case CharacterXor:
9292         if (*m_currentCharacter == '=') {
9293             ++m_currentCharacter;
9294             m_token = BEGINSWITH;
9295         }
9296         break;
9297
9298     case CharacterVerticalBar:
9299         if (*m_currentCharacter == '=') {
9300             ++m_currentCharacter;
9301             m_token = DASHMATCH;
9302         }
9303         break;
9304
9305     case CharacterTilde:
9306         if (*m_currentCharacter == '=') {
9307             ++m_currentCharacter;
9308             m_token = INCLUDES;
9309         }
9310         break;
9311
9312     default:
9313         ASSERT_NOT_REACHED();
9314         break;
9315     }
9316
9317 #ifndef NDEBUG
9318     switch (token()) {
9319     case STRING:
9320         ASSERT(yylval->string.characters == m_tokenStart + 1);
9321         break;
9322
9323     case IDENT:
9324     case NTH:
9325     case DIMEN:
9326     case UNICODERANGE:
9327     case FUNCTION:
9328     case ANYFUNCTION:
9329     case NOTFUNCTION:
9330     case CALCFUNCTION:
9331     case MINFUNCTION:
9332     case MAXFUNCTION:
9333         ASSERT(yylval->string.characters == m_tokenStart && yylval->string.length > 0);
9334         break;
9335
9336     case URI:
9337         ASSERT(yylval->string.characters && yylval->string.characters != m_tokenStart);
9338         break;
9339
9340     case HEX:
9341     case IDSEL:
9342         ASSERT(yylval->string.characters == m_tokenStart + 1 && yylval->string.length > 0);
9343         break;
9344
9345 #if ENABLE(TIZEN_MEDIA_QUERY)
9346     //FIXME : Upversion - Must reviewd by Gyuyoung Kim
9347     case DPIS:
9348     case DPCMS:
9349         break;
9350 #endif
9351     }
9352 #endif
9353
9354     return token();
9355 }
9356
9357 CSSParserSelector* CSSParser::createFloatingSelector()
9358 {
9359     CSSParserSelector* selector = new CSSParserSelector;
9360     m_floatingSelectors.add(selector);
9361     return selector;
9362 }
9363
9364 PassOwnPtr<CSSParserSelector> CSSParser::sinkFloatingSelector(CSSParserSelector* selector)
9365 {
9366     if (selector) {
9367         ASSERT(m_floatingSelectors.contains(selector));
9368         m_floatingSelectors.remove(selector);
9369     }
9370     return adoptPtr(selector);
9371 }
9372
9373 Vector<OwnPtr<CSSParserSelector> >* CSSParser::createFloatingSelectorVector()
9374 {
9375     Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >;
9376     m_floatingSelectorVectors.add(selectorVector);
9377     return selectorVector;
9378 }
9379
9380 PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > CSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector)
9381 {
9382     if (selectorVector) {
9383         ASSERT(m_floatingSelectorVectors.contains(selectorVector));
9384         m_floatingSelectorVectors.remove(selectorVector);
9385     }
9386     return adoptPtr(selectorVector);
9387 }
9388
9389 CSSParserValueList* CSSParser::createFloatingValueList()
9390 {
9391     CSSParserValueList* list = new CSSParserValueList;
9392     m_floatingValueLists.add(list);
9393     return list;
9394 }
9395
9396 PassOwnPtr<CSSParserValueList> CSSParser::sinkFloatingValueList(CSSParserValueList* list)
9397 {
9398     if (list) {
9399         ASSERT(m_floatingValueLists.contains(list));
9400         m_floatingValueLists.remove(list);
9401     }
9402     return adoptPtr(list);
9403 }
9404
9405 CSSParserFunction* CSSParser::createFloatingFunction()
9406 {
9407     CSSParserFunction* function = new CSSParserFunction;
9408     m_floatingFunctions.add(function);
9409     return function;
9410 }
9411
9412 PassOwnPtr<CSSParserFunction> CSSParser::sinkFloatingFunction(CSSParserFunction* function)
9413 {
9414     if (function) {
9415         ASSERT(m_floatingFunctions.contains(function));
9416         m_floatingFunctions.remove(function);
9417     }
9418     return adoptPtr(function);
9419 }
9420
9421 CSSParserValue& CSSParser::sinkFloatingValue(CSSParserValue& value)
9422 {
9423     if (value.unit == CSSParserValue::Function) {
9424         ASSERT(m_floatingFunctions.contains(value.function));
9425         m_floatingFunctions.remove(value.function);
9426     }
9427     return value;
9428 }
9429
9430 MediaQueryExp* CSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values)
9431 {
9432     m_floatingMediaQueryExp = MediaQueryExp::create(mediaFeature, values);
9433     return m_floatingMediaQueryExp.get();
9434 }
9435
9436 PassOwnPtr<MediaQueryExp> CSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression)
9437 {
9438     ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp);
9439     return m_floatingMediaQueryExp.release();
9440 }
9441
9442 Vector<OwnPtr<MediaQueryExp> >* CSSParser::createFloatingMediaQueryExpList()
9443 {
9444     m_floatingMediaQueryExpList = adoptPtr(new Vector<OwnPtr<MediaQueryExp> >);
9445     return m_floatingMediaQueryExpList.get();
9446 }
9447
9448 PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > CSSParser::sinkFloatingMediaQueryExpList(Vector<OwnPtr<MediaQueryExp> >* list)
9449 {
9450     ASSERT_UNUSED(list, list == m_floatingMediaQueryExpList);
9451     return m_floatingMediaQueryExpList.release();
9452 }
9453
9454 MediaQuery* CSSParser::createFloatingMediaQuery(MediaQuery::Restrictor restrictor, const String& mediaType, PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > expressions)
9455 {
9456     m_floatingMediaQuery = adoptPtr(new MediaQuery(restrictor, mediaType, expressions));
9457     return m_floatingMediaQuery.get();
9458 }
9459
9460 MediaQuery* CSSParser::createFloatingMediaQuery(PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > expressions)
9461 {
9462     return createFloatingMediaQuery(MediaQuery::None, "all", expressions);
9463 }
9464
9465 PassOwnPtr<MediaQuery> CSSParser::sinkFloatingMediaQuery(MediaQuery* query)
9466 {
9467     ASSERT_UNUSED(query, query == m_floatingMediaQuery);
9468     return m_floatingMediaQuery.release();
9469 }
9470
9471 Vector<RefPtr<StyleKeyframe> >* CSSParser::createFloatingKeyframeVector()
9472 {
9473     m_floatingKeyframeVector = adoptPtr(new Vector<RefPtr<StyleKeyframe> >());
9474     return m_floatingKeyframeVector.get();
9475 }
9476
9477 PassOwnPtr<Vector<RefPtr<StyleKeyframe> > > CSSParser::sinkFloatingKeyframeVector(Vector<RefPtr<StyleKeyframe> >* keyframeVector)
9478 {
9479     ASSERT_UNUSED(keyframeVector, m_floatingKeyframeVector == keyframeVector);
9480     return m_floatingKeyframeVector.release();
9481 }
9482
9483 MediaQuerySet* CSSParser::createMediaQuerySet()
9484 {
9485     RefPtr<MediaQuerySet> queries = MediaQuerySet::create();
9486     MediaQuerySet* result = queries.get();
9487     m_parsedMediaQuerySets.append(queries.release());
9488     return result;
9489 }
9490
9491 StyleRuleBase* CSSParser::createImportRule(const CSSParserString& url, MediaQuerySet* media)
9492 {
9493     if (!media || !m_allowImportRules)
9494         return 0;
9495     RefPtr<StyleRuleImport> rule = StyleRuleImport::create(url, media);
9496     StyleRuleImport* result = rule.get();
9497     m_parsedRules.append(rule.release());
9498     processAndAddNewRuleToSourceTreeIfNeeded();
9499     return result;
9500 }
9501
9502 StyleRuleBase* CSSParser::createMediaRule(MediaQuerySet* media, RuleList* rules)
9503 {
9504     m_allowImportRules = m_allowNamespaceDeclarations = false;
9505     RefPtr<StyleRuleMedia> rule;
9506     if (rules)
9507         rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create(), *rules);
9508     else {
9509         RuleList emptyRules;
9510         rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create(), emptyRules);
9511     }
9512     StyleRuleMedia* result = rule.get();
9513     m_parsedRules.append(rule.release());
9514     processAndAddNewRuleToSourceTreeIfNeeded();
9515     return result;
9516 }
9517
9518 CSSParser::RuleList* CSSParser::createRuleList()
9519 {
9520     OwnPtr<RuleList> list = adoptPtr(new RuleList);
9521     RuleList* listPtr = list.get();
9522
9523     m_parsedRuleLists.append(list.release());
9524     return listPtr;
9525 }
9526
9527 void CSSParser::processAndAddNewRuleToSourceTreeIfNeeded()
9528 {
9529     if (!isExtractingSourceData())
9530         return;
9531     markRuleBodyEnd();
9532     RefPtr<CSSRuleSourceData> rule = popRuleData();
9533     fixUnparsedPropertyRanges(rule.get());
9534     addNewRuleToSourceTree(rule.release());
9535 }
9536
9537 void CSSParser::addNewRuleToSourceTree(PassRefPtr<CSSRuleSourceData> rule)
9538 {
9539     // Precondition: (isExtractingSourceData()).
9540     if (!m_ruleSourceDataResult)
9541         return;
9542     if (m_currentRuleDataStack->isEmpty())
9543         m_ruleSourceDataResult->append(rule);
9544     else
9545         m_currentRuleDataStack->last()->childRules.append(rule);
9546 }
9547
9548 PassRefPtr<CSSRuleSourceData> CSSParser::popRuleData()
9549 {
9550     if (!m_ruleSourceDataResult)
9551         return 0;
9552
9553     ASSERT(!m_currentRuleDataStack->isEmpty());
9554     RefPtr<CSSRuleSourceData> data = m_currentRuleDataStack->last();
9555     m_currentRuleDataStack->removeLast();
9556     return data.release();
9557 }
9558
9559 StyleRuleKeyframes* CSSParser::createKeyframesRule(const String& name, PassOwnPtr<Vector<RefPtr<StyleKeyframe> > > popKeyframes)
9560 {
9561     OwnPtr<Vector<RefPtr<StyleKeyframe> > > keyframes = popKeyframes;
9562     m_allowImportRules = m_allowNamespaceDeclarations = false;
9563     RefPtr<StyleRuleKeyframes> rule = StyleRuleKeyframes::create();
9564     for (size_t i = 0; i < keyframes->size(); ++i)
9565         rule->parserAppendKeyframe(keyframes->at(i));
9566     rule->setName(name);
9567     StyleRuleKeyframes* rulePtr = rule.get();
9568     m_parsedRules.append(rule.release());
9569     processAndAddNewRuleToSourceTreeIfNeeded();
9570     return rulePtr;
9571 }
9572
9573 StyleRuleBase* CSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors)
9574 {
9575     StyleRule* result = 0;
9576     if (selectors) {
9577         m_allowImportRules = m_allowNamespaceDeclarations = false;
9578         RefPtr<StyleRule> rule = StyleRule::create(m_lastSelectorLineNumber);
9579         rule->parserAdoptSelectorVector(*selectors);
9580         if (m_hasFontFaceOnlyValues)
9581             deleteFontFaceOnlyValues();
9582         rule->setProperties(createStylePropertySet());
9583         result = rule.get();
9584         m_parsedRules.append(rule.release());
9585         processAndAddNewRuleToSourceTreeIfNeeded();
9586     } else
9587         popRuleData();
9588     clearProperties();
9589     return result;
9590 }
9591
9592 StyleRuleBase* CSSParser::createFontFaceRule()
9593 {
9594     m_allowImportRules = m_allowNamespaceDeclarations = false;
9595     for (unsigned i = 0; i < m_parsedProperties.size(); ++i) {
9596         CSSProperty& property = m_parsedProperties[i];
9597         if (property.id() == CSSPropertyFontVariant && property.value()->isPrimitiveValue())
9598             property.wrapValueInCommaSeparatedList();
9599         else if (property.id() == CSSPropertyFontFamily && (!property.value()->isValueList() || static_cast<CSSValueList*>(property.value())->length() != 1)) {
9600             // Unlike font-family property, font-family descriptor in @font-face rule
9601             // has to be a value list with exactly one family name. It cannot have a
9602             // have 'initial' value and cannot 'inherit' from parent.
9603             // See http://dev.w3.org/csswg/css3-fonts/#font-family-desc
9604             clearProperties();
9605             return 0;
9606         }
9607     }
9608     RefPtr<StyleRuleFontFace> rule = StyleRuleFontFace::create();
9609     rule->setProperties(createStylePropertySet());
9610     clearProperties();
9611     StyleRuleFontFace* result = rule.get();
9612     m_parsedRules.append(rule.release());
9613     processAndAddNewRuleToSourceTreeIfNeeded();
9614     return result;
9615 }
9616
9617 void CSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri)
9618 {
9619     if (!m_styleSheet || !m_allowNamespaceDeclarations)
9620         return;
9621     m_allowImportRules = false;
9622     m_styleSheet->parserAddNamespace(prefix, uri);
9623     if (prefix.isEmpty() && !uri.isNull())
9624         m_defaultNamespace = uri;
9625 }
9626
9627 QualifiedName CSSParser::determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName)
9628 {
9629     if (!m_styleSheet)
9630         return QualifiedName(prefix, localName, m_defaultNamespace);
9631     return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(prefix));
9632 }
9633
9634 void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers)
9635 {
9636     AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
9637     QualifiedName tag = QualifiedName(namespacePrefix, elementName, determinedNamespace);
9638     if (!specifiers->isUnknownPseudoElement()) {
9639         specifiers->setTag(tag);
9640         return;
9641     }
9642
9643     CSSParserSelector* lastShadowDescendant = specifiers;
9644     CSSParserSelector* history = specifiers;
9645     while (history->tagHistory()) {
9646         history = history->tagHistory();
9647         if (history->isUnknownPseudoElement() || history->hasShadowDescendant())
9648             lastShadowDescendant = history;
9649     }
9650
9651     if (lastShadowDescendant->tagHistory()) {
9652         lastShadowDescendant->tagHistory()->setTag(tag);
9653         return;
9654     }
9655
9656     // For shadow-ID pseudo-elements to be correctly matched, the ShadowDescendant combinator has to be used.
9657     // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
9658     OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector);
9659     elementNameSelector->setTag(tag);
9660     lastShadowDescendant->setTagHistory(elementNameSelector.release());
9661     lastShadowDescendant->setRelation(CSSSelector::ShadowDescendant);
9662 }
9663
9664 CSSParserSelector* CSSParser::updateSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier)
9665 {
9666     if (newSpecifier->isUnknownPseudoElement()) {
9667         // Unknown pseudo element always goes at the top of selector chain.
9668         newSpecifier->appendTagHistory(CSSSelector::ShadowDescendant, sinkFloatingSelector(specifiers));
9669         return newSpecifier;
9670     }
9671     if (specifiers->isUnknownPseudoElement()) {
9672         // Specifiers for unknown pseudo element go right behind it in the chain.
9673         specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowDescendant);
9674         return specifiers;
9675     }
9676     specifiers->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier));
9677     return specifiers;
9678 }
9679
9680 StyleRuleBase* CSSParser::createPageRule(PassOwnPtr<CSSParserSelector> pageSelector)
9681 {
9682     // FIXME: Margin at-rules are ignored.
9683     m_allowImportRules = m_allowNamespaceDeclarations = false;
9684     StyleRulePage* pageRule = 0;
9685     if (pageSelector) {
9686         RefPtr<StyleRulePage> rule = StyleRulePage::create();
9687         Vector<OwnPtr<CSSParserSelector> > selectorVector;
9688         selectorVector.append(pageSelector);
9689         rule->parserAdoptSelectorVector(selectorVector);
9690         rule->setProperties(createStylePropertySet());
9691         pageRule = rule.get();
9692         m_parsedRules.append(rule.release());
9693         processAndAddNewRuleToSourceTreeIfNeeded();
9694     }
9695     clearProperties();
9696     return pageRule;
9697 }
9698
9699 void CSSParser::setReusableRegionSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectors)
9700 {
9701     if (selectors)
9702         m_reusableRegionSelectorVector.swap(*selectors);
9703 }
9704
9705 StyleRuleBase* CSSParser::createRegionRule(Vector<OwnPtr<CSSParserSelector> >* regionSelector, RuleList* rules)
9706 {
9707     if (!cssRegionsEnabled() || !regionSelector || !rules)
9708         return 0;
9709
9710     m_allowImportRules = m_allowNamespaceDeclarations = false;
9711
9712     RefPtr<StyleRuleRegion> regionRule = StyleRuleRegion::create(regionSelector, *rules);
9713
9714     StyleRuleRegion* result = regionRule.get();
9715     m_parsedRules.append(regionRule.release());
9716     if (isExtractingSourceData())
9717         addNewRuleToSourceTree(CSSRuleSourceData::createUnknown());
9718
9719     return result;
9720 }
9721
9722 StyleRuleBase* CSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */)
9723 {
9724     // FIXME: Implement margin at-rule here, using:
9725     //        - marginBox: margin box
9726     //        - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_parsedProperties.size()] are for this at-rule.
9727     // Don't forget to also update the action for page symbol in CSSGrammar.y such that margin at-rule data is cleared if page_selector is invalid.
9728
9729     endDeclarationsForMarginBox();
9730     return 0; // until this method is implemented.
9731 }
9732
9733 void CSSParser::startDeclarationsForMarginBox()
9734 {
9735     m_numParsedPropertiesBeforeMarginBox = m_parsedProperties.size();
9736 }
9737
9738 void CSSParser::endDeclarationsForMarginBox()
9739 {
9740     rollbackLastProperties(m_parsedProperties.size() - m_numParsedPropertiesBeforeMarginBox);
9741     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
9742 }
9743
9744 void CSSParser::deleteFontFaceOnlyValues()
9745 {
9746     ASSERT(m_hasFontFaceOnlyValues);
9747     for (unsigned i = 0; i < m_parsedProperties.size();) {
9748         CSSProperty& property = m_parsedProperties[i];
9749         if (property.id() == CSSPropertyFontVariant && property.value()->isValueList()) {
9750             m_parsedProperties.remove(i);
9751             continue;
9752         }
9753         ++i;
9754     }
9755 }
9756
9757 StyleKeyframe* CSSParser::createKeyframe(CSSParserValueList* keys)
9758 {
9759     // Create a key string from the passed keys
9760     String keyString;
9761     for (unsigned i = 0; i < keys->size(); ++i) {
9762         float key = static_cast<float>(keys->valueAt(i)->fValue);
9763         if (i != 0)
9764             keyString += ",";
9765         keyString += String::number(key);
9766         keyString += "%";
9767     }
9768
9769     RefPtr<StyleKeyframe> keyframe = StyleKeyframe::create();
9770     keyframe->setKeyText(keyString);
9771     keyframe->setProperties(createStylePropertySet());
9772
9773     clearProperties();
9774
9775     StyleKeyframe* keyframePtr = keyframe.get();
9776     m_parsedKeyframes.append(keyframe.release());
9777     return keyframePtr;
9778 }
9779
9780 void CSSParser::invalidBlockHit()
9781 {
9782     if (m_styleSheet && !m_hadSyntacticallyValidCSSRule)
9783         m_styleSheet->setHasSyntacticallyValidCSSHeader(false);
9784 }
9785
9786 void CSSParser::updateLastSelectorLineAndPosition()
9787 {
9788     m_lastSelectorLineNumber = m_lineNumber;
9789     markRuleBodyStart();
9790 }
9791
9792 void CSSParser::updateLastMediaLine(MediaQuerySet* media)
9793 {
9794     media->setLastLine(m_lineNumber);
9795 }
9796
9797 void CSSParser::fixUnparsedPropertyRanges(CSSRuleSourceData* ruleData)
9798 {
9799     if (!ruleData->styleSourceData)
9800         return;
9801     Vector<CSSPropertySourceData>& propertyData = ruleData->styleSourceData->propertyData;
9802     unsigned size = propertyData.size();
9803     if (!size)
9804         return;
9805
9806     unsigned styleStart = ruleData->ruleBodyRange.start;
9807     const UChar* characters = m_dataStart.get() + m_parsedTextPrefixLength;
9808     CSSPropertySourceData* nextData = &(propertyData.at(0));
9809     for (unsigned i = 0; i < size; ++i) {
9810         CSSPropertySourceData* currentData = nextData;
9811         nextData = i < size - 1 ? &(propertyData.at(i + 1)) : 0;
9812
9813         if (currentData->parsedOk)
9814             continue;
9815         if (currentData->range.end > 0 && characters[styleStart + currentData->range.end - 1] == ';')
9816             continue;
9817
9818         unsigned propertyEndInStyleSheet;
9819         if (!nextData)
9820             propertyEndInStyleSheet = ruleData->ruleBodyRange.end - 1;
9821         else
9822             propertyEndInStyleSheet = styleStart + nextData->range.start - 1;
9823
9824         while (isHTMLSpace(characters[propertyEndInStyleSheet]))
9825             --propertyEndInStyleSheet;
9826
9827         // propertyEndInStyleSheet points at the last property text character.
9828         unsigned newPropertyEnd = propertyEndInStyleSheet - styleStart + 1; // Exclusive of the last property text character.
9829         if (currentData->range.end != newPropertyEnd) {
9830             currentData->range.end = newPropertyEnd;
9831             unsigned valueStartInStyleSheet = styleStart + currentData->range.start + currentData->name.length();
9832             while (valueStartInStyleSheet < propertyEndInStyleSheet && characters[valueStartInStyleSheet] != ':')
9833                 ++valueStartInStyleSheet;
9834             if (valueStartInStyleSheet < propertyEndInStyleSheet)
9835                 ++valueStartInStyleSheet; // Shift past the ':'.
9836             while (valueStartInStyleSheet < propertyEndInStyleSheet && isHTMLSpace(characters[valueStartInStyleSheet]))
9837                 ++valueStartInStyleSheet;
9838             // Need to exclude the trailing ';' from the property value.
9839             currentData->value = String(characters + valueStartInStyleSheet, propertyEndInStyleSheet - valueStartInStyleSheet + (characters[propertyEndInStyleSheet] == ';' ? 0 : 1));
9840         }
9841     }
9842 }
9843
9844 void CSSParser::markRuleHeaderStart(CSSRuleSourceData::Type ruleType)
9845 {
9846     if (!isExtractingSourceData())
9847         return;
9848     RefPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(ruleType);
9849     data->ruleHeaderRange.start = m_tokenStart - m_dataStart.get();
9850     m_currentRuleDataStack->append(data.release());
9851 }
9852
9853 void CSSParser::markRuleHeaderEnd()
9854 {
9855     if (!isExtractingSourceData())
9856         return;
9857     ASSERT(!m_currentRuleDataStack->isEmpty());
9858     UChar* listEnd = m_tokenStart;
9859     while (listEnd > m_dataStart.get() + 1) {
9860         if (isHTMLSpace(*(listEnd - 1)))
9861             --listEnd;
9862         else
9863             break;
9864     }
9865     m_currentRuleDataStack->last()->ruleHeaderRange.end = listEnd - m_dataStart.get();
9866 }
9867
9868 void CSSParser::markRuleBodyStart()
9869 {
9870     if (!isExtractingSourceData())
9871         return;
9872     unsigned offset = m_tokenStart - m_dataStart.get();
9873     if (*m_tokenStart == '{')
9874         ++offset; // Skip the rule body opening brace.
9875     ASSERT(!m_currentRuleDataStack->isEmpty());
9876     m_currentRuleDataStack->last()->ruleBodyRange.start = offset;
9877 }
9878
9879 void CSSParser::markRuleBodyEnd()
9880 {
9881     // Precondition: (!isExtractingSourceData())
9882     unsigned offset = m_tokenStart - m_dataStart.get();
9883     ASSERT(!m_currentRuleDataStack->isEmpty());
9884     m_currentRuleDataStack->last()->ruleBodyRange.end = offset;
9885 }
9886
9887 void CSSParser::markPropertyStart()
9888 {
9889     if (!isExtractingSourceData())
9890         return;
9891     if (m_currentRuleDataStack->isEmpty() || !m_currentRuleDataStack->last()->styleSourceData)
9892         return;
9893
9894     m_propertyRange.start = m_tokenStart - m_dataStart.get();
9895 }
9896
9897 void CSSParser::markPropertyEnd(bool isImportantFound, bool isPropertyParsed)
9898 {
9899     if (!isExtractingSourceData())
9900         return;
9901     if (m_currentRuleDataStack->isEmpty() || !m_currentRuleDataStack->last()->styleSourceData)
9902         return;
9903
9904     unsigned offset = m_tokenStart - m_dataStart.get();
9905     if (*m_tokenStart == ';') // Include semicolon into the property text.
9906         ++offset;
9907     m_propertyRange.end = offset;
9908     if (m_propertyRange.start != UINT_MAX && !m_currentRuleDataStack->isEmpty()) {
9909         // This stuff is only executed when the style data retrieval is requested by client.
9910         const unsigned start = m_propertyRange.start;
9911         const unsigned end = m_propertyRange.end;
9912         ASSERT(start < end);
9913         String propertyString = String(m_dataStart.get() + start, end - start).stripWhiteSpace();
9914         if (propertyString.endsWith(';'))
9915             propertyString = propertyString.left(propertyString.length() - 1);
9916         size_t colonIndex = propertyString.find(':');
9917         ASSERT(colonIndex != notFound);
9918
9919         String name = propertyString.left(colonIndex).stripWhiteSpace();
9920         String value = propertyString.substring(colonIndex + 1, propertyString.length()).stripWhiteSpace();
9921         // The property range is relative to the declaration start offset.
9922         SourceRange& topRuleBodyRange = m_currentRuleDataStack->last()->ruleBodyRange;
9923         m_currentRuleDataStack->last()->styleSourceData->propertyData.append(
9924             CSSPropertySourceData(name, value, isImportantFound, isPropertyParsed, SourceRange(start - topRuleBodyRange.start, end - topRuleBodyRange.start)));
9925     }
9926     resetPropertyRange();
9927 }
9928
9929 static CSSPropertyID cssPropertyID(const UChar* propertyName, unsigned length)
9930 {
9931     if (!length)
9932         return CSSPropertyInvalid;
9933     if (length > maxCSSPropertyNameLength)
9934         return CSSPropertyInvalid;
9935
9936     char buffer[maxCSSPropertyNameLength + 1 + 1]; // 1 to turn "apple"/"khtml" into "webkit", 1 for null character
9937
9938     for (unsigned i = 0; i != length; ++i) {
9939         UChar c = propertyName[i];
9940         if (c == 0 || c >= 0x7F)
9941             return CSSPropertyInvalid; // illegal character
9942         buffer[i] = toASCIILower(c);
9943     }
9944     buffer[length] = '\0';
9945
9946     const char* name = buffer;
9947     if (buffer[0] == '-') {
9948 #if ENABLE(LEGACY_CSS_VENDOR_PREFIXES)
9949         // If the prefix is -apple- or -khtml-, change it to -webkit-.
9950         // This makes the string one character longer.
9951         if (hasPrefix(buffer, length, "-apple-") || hasPrefix(buffer, length, "-khtml-")) {
9952             memmove(buffer + 7, buffer + 6, length + 1 - 6);
9953             memcpy(buffer, "-webkit", 7);
9954             ++length;
9955         }
9956 #endif
9957 #if PLATFORM(IOS)
9958         cssPropertyNameIOSAliasing(buffer, name, length);
9959 #endif
9960     }
9961
9962     const Property* hashTableEntry = findProperty(name, length);
9963     return hashTableEntry ? static_cast<CSSPropertyID>(hashTableEntry->id) : CSSPropertyInvalid;
9964 }
9965
9966 CSSPropertyID cssPropertyID(const String& string)
9967 {
9968     return cssPropertyID(string.characters(), string.length());
9969 }
9970
9971 CSSPropertyID cssPropertyID(const CSSParserString& string)
9972 {
9973     return cssPropertyID(string.characters, string.length);
9974 }
9975
9976 #if PLATFORM(IOS)
9977 void cssPropertyNameIOSAliasing(const char* propertyName, const char*& propertyNameAlias, unsigned& newLength)
9978 {
9979     if (!strcmp(propertyName, "-webkit-hyphenate-locale")) {
9980         // Worked in iOS 4.2.
9981         static const char* const webkitLocale = "-webkit-locale";
9982         propertyNameAlias = webkitLocale;
9983         newLength = strlen(webkitLocale);
9984     }
9985 }
9986 #endif
9987
9988 int cssValueKeywordID(const CSSParserString& string)
9989 {
9990     unsigned length = string.length;
9991     if (!length)
9992         return 0;
9993     if (length > maxCSSValueKeywordLength)
9994         return 0;
9995
9996     char buffer[maxCSSValueKeywordLength + 1 + 1]; // 1 to turn "apple"/"khtml" into "webkit", 1 for null character
9997
9998     for (unsigned i = 0; i != length; ++i) {
9999         UChar c = string.characters[i];
10000         if (c == 0 || c >= 0x7F)
10001             return 0; // illegal character
10002         buffer[i] = WTF::toASCIILower(c);
10003     }
10004     buffer[length] = '\0';
10005
10006     if (buffer[0] == '-') {
10007         // If the prefix is -apple- or -khtml-, change it to -webkit-.
10008         // This makes the string one character longer.
10009         if (hasPrefix(buffer, length, "-apple-") || hasPrefix(buffer, length, "-khtml-")) {
10010             memmove(buffer + 7, buffer + 6, length + 1 - 6);
10011             memcpy(buffer, "-webkit", 7);
10012             ++length;
10013         }
10014     }
10015
10016     const Value* hashTableEntry = findValue(buffer, length);
10017     return hashTableEntry ? hashTableEntry->id : 0;
10018 }
10019
10020 // "ident" from the CSS tokenizer, minus backslash-escape sequences
10021 static bool isCSSTokenizerIdentifier(const String& string)
10022 {
10023     const UChar* p = string.characters();
10024     const UChar* end = p + string.length();
10025
10026     // -?
10027     if (p != end && p[0] == '-')
10028         ++p;
10029
10030     // {nmstart}
10031     if (p == end || !(p[0] == '_' || p[0] >= 128 || isASCIIAlpha(p[0])))
10032         return false;
10033     ++p;
10034
10035     // {nmchar}*
10036     for (; p != end; ++p) {
10037         if (!(p[0] == '_' || p[0] == '-' || p[0] >= 128 || isASCIIAlphanumeric(p[0])))
10038             return false;
10039     }
10040
10041     return true;
10042 }
10043
10044 // "url" from the CSS tokenizer, minus backslash-escape sequences
10045 static bool isCSSTokenizerURL(const String& string)
10046 {
10047     const UChar* p = string.characters();
10048     const UChar* end = p + string.length();
10049
10050     for (; p != end; ++p) {
10051         UChar c = p[0];
10052         switch (c) {
10053             case '!':
10054             case '#':
10055             case '$':
10056             case '%':
10057             case '&':
10058                 break;
10059             default:
10060                 if (c < '*')
10061                     return false;
10062                 if (c <= '~')
10063                     break;
10064                 if (c < 128)
10065                     return false;
10066         }
10067     }
10068
10069     return true;
10070 }
10071
10072 // We use single quotes for now because markup.cpp uses double quotes.
10073 String quoteCSSString(const String& string)
10074 {
10075     // This function expands each character to at most 3 characters ('\u0010' -> '\' '1' '0') as well as adds
10076     // 2 quote characters (before and after). Make sure the resulting size (3 * length + 2) will not overflow unsigned.
10077     if (string.length() >= (std::numeric_limits<unsigned>::max() / 3) - 2)
10078         return "";
10079
10080     // For efficiency, we first pre-calculate the length of the quoted string, then we build the actual one.
10081     // Please see below for the actual logic.
10082     unsigned quotedStringSize = 2; // Two quotes surrounding the entire string.
10083     bool afterEscape = false;
10084     for (unsigned i = 0; i < string.length(); ++i) {
10085         UChar ch = string[i];
10086         if (ch == '\\' || ch == '\'') {
10087             quotedStringSize += 2;
10088             afterEscape = false;
10089         } else if (ch < 0x20 || ch == 0x7F) {
10090             quotedStringSize += 2 + (ch >= 0x10);
10091             afterEscape = true;
10092         } else {
10093             quotedStringSize += 1 + (afterEscape && (isASCIIHexDigit(ch) || ch == ' '));
10094             afterEscape = false;
10095         }
10096     }
10097
10098     StringBuffer<UChar> buffer(quotedStringSize);
10099     unsigned index = 0;
10100     buffer[index++] = '\'';
10101     afterEscape = false;
10102     for (unsigned i = 0; i < string.length(); ++i) {
10103         UChar ch = string[i];
10104         if (ch == '\\' || ch == '\'') {
10105             buffer[index++] = '\\';
10106             buffer[index++] = ch;
10107             afterEscape = false;
10108         } else if (ch < 0x20 || ch == 0x7F) { // Control characters.
10109             buffer[index++] = '\\';
10110             placeByteAsHexCompressIfPossible(ch, buffer, index, Lowercase);
10111             afterEscape = true;
10112         } else {
10113             // Space character may be required to separate backslash-escape sequence and normal characters.
10114             if (afterEscape && (isASCIIHexDigit(ch) || ch == ' '))
10115                 buffer[index++] = ' ';
10116             buffer[index++] = ch;
10117             afterEscape = false;
10118         }
10119     }
10120     buffer[index++] = '\'';
10121
10122     ASSERT(quotedStringSize == index);
10123     return String::adopt(buffer);
10124 }
10125
10126 String quoteCSSStringIfNeeded(const String& string)
10127 {
10128     return isCSSTokenizerIdentifier(string) ? string : quoteCSSString(string);
10129 }
10130
10131 String quoteCSSURLIfNeeded(const String& string)
10132 {
10133     return isCSSTokenizerURL(string) ? string : quoteCSSString(string);
10134 }
10135
10136 bool isValidNthToken(const CSSParserString& token)
10137 {
10138     // The tokenizer checks for the construct of an+b.
10139     // However, since the {ident} rule precedes the {nth} rule, some of those
10140     // tokens are identified as string literal. Furthermore we need to accept
10141     // "odd" and "even" which does not match to an+b.
10142     return equalIgnoringCase(token, "odd") || equalIgnoringCase(token, "even")
10143         || equalIgnoringCase(token, "n") || equalIgnoringCase(token, "-n");
10144 }
10145
10146 }