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