2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
27 #include "CSSParser.h"
29 #include "CSSAspectRatioValue.h"
30 #include "CSSBorderImage.h"
31 #include "CSSCanvasValue.h"
32 #include "CSSCrossfadeValue.h"
33 #include "CSSCursorImageValue.h"
34 #include "CSSFontFaceRule.h"
35 #include "CSSFontFaceSrcValue.h"
36 #include "CSSFunctionValue.h"
37 #include "CSSGradientValue.h"
38 #if ENABLE(CSS_IMAGE_SET)
39 #include "CSSImageSetValue.h"
41 #include "CSSImageValue.h"
42 #include "CSSImportRule.h"
43 #include "CSSInheritedValue.h"
44 #include "CSSInitialValue.h"
45 #include "CSSLineBoxContainValue.h"
46 #include "CSSMediaRule.h"
47 #include "CSSPageRule.h"
48 #include "CSSPrimitiveValue.h"
49 #include "CSSProperty.h"
50 #include "CSSPropertySourceData.h"
51 #include "CSSReflectValue.h"
52 #include "CSSSelector.h"
53 #include "CSSStyleRule.h"
54 #include "CSSStyleSheet.h"
55 #include "CSSTimingFunctionValue.h"
56 #include "CSSUnicodeRangeValue.h"
57 #include "CSSValueKeywords.h"
58 #include "CSSValueList.h"
59 #include "CSSValuePool.h"
60 #include "CSSWrapShapes.h"
63 #include "FloatConversion.h"
64 #include "FontFeatureValue.h"
65 #include "FontValue.h"
66 #include "HTMLParserIdioms.h"
67 #include "HashTools.h"
68 #include "MediaList.h"
69 #include "MediaQueryExp.h"
73 #include "RenderTheme.h"
75 #include "ShadowValue.h"
76 #include "StylePropertySet.h"
77 #include "StylePropertyShorthand.h"
78 #include "StyleRule.h"
79 #if ENABLE(CSS_FILTERS)
80 #include "WebKitCSSFilterValue.h"
82 #include "WebKitCSSKeyframeRule.h"
83 #include "WebKitCSSKeyframesRule.h"
84 #include "WebKitCSSRegionRule.h"
85 #include "WebKitCSSTransformValue.h"
86 #if ENABLE(CSS_SHADERS)
87 #include "WebKitCSSShaderValue.h"
90 #include <wtf/HexNumber.h>
92 #include <wtf/text/StringBuffer.h>
93 #include <wtf/text/StringBuilder.h>
95 #if ENABLE(DASHBOARD_SUPPORT)
96 #include "DashboardRegion.h"
102 extern int cssyydebug;
105 extern int cssyyparse(void* parser);
117 class ImplicitScope {
118 WTF_MAKE_NONCOPYABLE(ImplicitScope);
120 ImplicitScope(WebCore::CSSParser* parser, PropertyType propertyType)
123 m_parser->m_implicitShorthand = propertyType == PropertyImplicit;
128 m_parser->m_implicitShorthand = false;
132 WebCore::CSSParser* m_parser;
139 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
140 static const double MAX_SCALE = 1000000;
142 static bool equal(const CSSParserString& a, const char* b)
144 for (int i = 0; i < a.length; ++i) {
147 if (a.characters[i] != b[i])
153 static bool equalIgnoringCase(const CSSParserString& a, const char* b)
155 for (int i = 0; i < a.length; ++i) {
158 ASSERT(!isASCIIUpper(b[i]));
159 if (toASCIILower(a.characters[i]) != b[i])
165 static bool hasPrefix(const char* string, unsigned length, const char* prefix)
167 for (unsigned i = 0; i < length; ++i) {
170 if (string[i] != prefix[i])
176 inline void CSSParser::ensureCSSValuePool()
179 m_cssValuePool = CSSValuePool::create();
182 CSSParser::CSSParser(CSSParserMode cssParserMode)
183 : m_cssParserMode(cssParserMode)
185 , m_id(CSSPropertyInvalid)
187 , m_inParseShorthand(0)
188 , m_currentShorthand(CSSPropertyInvalid)
189 , m_implicitShorthand(false)
190 , m_hasFontFaceOnlyValues(false)
191 , m_hadSyntacticallyValidCSSRule(false)
192 , m_defaultNamespace(starAtom)
193 , m_inStyleRuleOrDeclaration(false)
194 , m_selectorListRange(0, 0)
195 , m_ruleBodyRange(0, 0)
196 , m_propertyRange(UINT_MAX, UINT_MAX)
198 , m_currentRuleData(0)
199 , m_parsingMode(NormalMode)
200 , m_currentCharacter(0)
203 , m_lastSelectorLineNumber(0)
204 , m_allowImportRules(true)
205 , m_allowNamespaceDeclarations(true)
210 CSSPropertySourceData::init();
213 CSSParser::~CSSParser()
217 fastDeleteAllValues(m_floatingSelectors);
218 deleteAllValues(m_floatingSelectorVectors);
219 deleteAllValues(m_floatingValueLists);
220 deleteAllValues(m_floatingFunctions);
223 void CSSParserString::lower()
225 // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
226 // that can potentially change the length of the string rather than the character
227 // by character kind. If we don't need Unicode lowercasing, it would be good to
228 // simplify this function.
230 if (charactersAreAllASCII(characters, length)) {
231 // Fast case for all-ASCII.
232 for (int i = 0; i < length; i++)
233 characters[i] = toASCIILower(characters[i]);
235 for (int i = 0; i < length; i++)
236 characters[i] = Unicode::toLower(characters[i]);
240 void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix)
242 int length = string.length() + strlen(prefix) + strlen(suffix) + 1;
244 m_dataStart = adoptArrayPtr(new UChar[length]);
245 for (unsigned i = 0; i < strlen(prefix); i++)
246 m_dataStart[i] = prefix[i];
248 memcpy(m_dataStart.get() + strlen(prefix), string.characters(), string.length() * sizeof(UChar));
250 unsigned start = strlen(prefix) + string.length();
251 unsigned end = start + strlen(suffix);
252 for (unsigned i = start; i < end; i++)
253 m_dataStart[i] = suffix[i - start];
255 m_dataStart[length - 1] = 0;
257 m_currentCharacter = m_tokenStart = m_dataStart.get();
258 resetRuleBodyMarks();
261 void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string, int startLineNumber, StyleRuleRangeMap* ruleRangeMap)
263 setStyleSheet(sheet);
264 m_defaultNamespace = starAtom; // Reset the default namespace.
265 m_ruleRangeMap = ruleRangeMap;
267 m_currentRuleData = CSSRuleSourceData::create();
268 m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
271 m_lineNumber = startLineNumber;
272 setupParser("", string, "");
275 m_currentRuleData = 0;
279 PassRefPtr<StyleRuleBase> CSSParser::parseRule(CSSStyleSheet* sheet, const String& string)
281 setStyleSheet(sheet);
282 m_allowNamespaceDeclarations = false;
283 setupParser("@-webkit-rule{", string, "} ");
285 return m_rule.release();
288 PassRefPtr<StyleKeyframe> CSSParser::parseKeyframeRule(CSSStyleSheet *sheet, const String &string)
290 setStyleSheet(sheet);
291 setupParser("@-webkit-keyframe-rule{ ", string, "} ");
293 return m_keyframe.release();
296 static inline bool isColorPropertyID(CSSPropertyID propertyId)
298 switch (propertyId) {
299 case CSSPropertyColor:
300 case CSSPropertyBackgroundColor:
301 case CSSPropertyBorderBottomColor:
302 case CSSPropertyBorderLeftColor:
303 case CSSPropertyBorderRightColor:
304 case CSSPropertyBorderTopColor:
305 case CSSPropertyOutlineColor:
306 case CSSPropertyTextLineThroughColor:
307 case CSSPropertyTextOverlineColor:
308 case CSSPropertyTextUnderlineColor:
309 case CSSPropertyWebkitBorderAfterColor:
310 case CSSPropertyWebkitBorderBeforeColor:
311 case CSSPropertyWebkitBorderEndColor:
312 case CSSPropertyWebkitBorderStartColor:
313 case CSSPropertyWebkitColumnRuleColor:
314 case CSSPropertyWebkitTextEmphasisColor:
315 case CSSPropertyWebkitTextFillColor:
316 case CSSPropertyWebkitTextStrokeColor:
323 static bool parseColorValue(StylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode, CSSStyleSheet* contextStyleSheet)
325 bool strict = isStrictParserMode(cssParserMode);
326 if (!string.length())
328 if (!isColorPropertyID(propertyId))
330 CSSParserString cssString;
331 cssString.characters = const_cast<UChar*>(string.characters());
332 cssString.length = string.length();
333 int valueID = cssValueKeywordID(cssString);
334 bool validPrimitive = false;
335 if (valueID == CSSValueWebkitText)
336 validPrimitive = true;
337 else if (valueID == CSSValueCurrentcolor)
338 validPrimitive = true;
339 else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
340 || (valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText && !strict)) {
341 validPrimitive = true;
344 Document* document = contextStyleSheet->findDocument();
345 if (validPrimitive) {
346 RefPtr<CSSValue> value;
348 value = document->cssValuePool()->createIdentifierValue(valueID);
350 value = CSSPrimitiveValue::createIdentifier(valueID);
351 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
355 if (!CSSParser::fastParseColor(color, string, strict && string[0] != '#'))
357 RefPtr<CSSValue> value;
359 value = document->cssValuePool()->createColorValue(color);
361 value = CSSPrimitiveValue::createColor(color);
362 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
366 static inline bool isSimpleLengthPropertyID(CSSPropertyID propertyId, bool& acceptsNegativeNumbers)
368 switch (propertyId) {
369 case CSSPropertyFontSize:
370 case CSSPropertyHeight:
371 case CSSPropertyWidth:
372 case CSSPropertyMinHeight:
373 case CSSPropertyMinWidth:
374 case CSSPropertyPaddingBottom:
375 case CSSPropertyPaddingLeft:
376 case CSSPropertyPaddingRight:
377 case CSSPropertyPaddingTop:
378 case CSSPropertyWebkitLogicalWidth:
379 case CSSPropertyWebkitLogicalHeight:
380 case CSSPropertyWebkitMinLogicalWidth:
381 case CSSPropertyWebkitMinLogicalHeight:
382 case CSSPropertyWebkitPaddingAfter:
383 case CSSPropertyWebkitPaddingBefore:
384 case CSSPropertyWebkitPaddingEnd:
385 case CSSPropertyWebkitPaddingStart:
386 case CSSPropertyWebkitWrapMargin:
387 case CSSPropertyWebkitWrapPadding:
388 acceptsNegativeNumbers = false;
390 case CSSPropertyBottom:
391 case CSSPropertyLeft:
392 case CSSPropertyMarginBottom:
393 case CSSPropertyMarginLeft:
394 case CSSPropertyMarginRight:
395 case CSSPropertyMarginTop:
396 case CSSPropertyRight:
397 case CSSPropertyTextIndent:
399 case CSSPropertyWebkitMarginAfter:
400 case CSSPropertyWebkitMarginBefore:
401 case CSSPropertyWebkitMarginEnd:
402 case CSSPropertyWebkitMarginStart:
403 acceptsNegativeNumbers = true;
410 static bool parseSimpleLengthValue(StylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode, CSSStyleSheet* contextStyleSheet)
412 bool acceptsNegativeNumbers;
413 bool strict = isStrictParserMode(cssParserMode);
414 unsigned length = string.length();
421 CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
423 if (string.is8Bit()) {
424 const LChar* characters8 = string.characters8();
428 if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
431 if (length > 2 && (characters8[length - 2] | 0x20) == 'p' && (characters8[length - 1] | 0x20) == 'x') {
433 unit = CSSPrimitiveValue::CSS_PX;
434 } else if (length > 1 && characters8[length - 1] == '%') {
436 unit = CSSPrimitiveValue::CSS_PERCENTAGE;
439 // We rely on charactersToDouble for validation as well. The function
440 // will set "ok" to "false" if the entire passed-in character range does
441 // not represent a double.
442 number = charactersToDouble(characters8, length, &ok);
444 const UChar* characters16 = string.characters16();
448 if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
451 if (length > 2 && (characters16[length - 2] | 0x20) == 'p' && (characters16[length - 1] | 0x20) == 'x') {
453 unit = CSSPrimitiveValue::CSS_PX;
454 } else if (length > 1 && characters16[length - 1] == '%') {
456 unit = CSSPrimitiveValue::CSS_PERCENTAGE;
459 // We rely on charactersToDouble for validation as well. The function
460 // will set "ok" to "false" if the entire passed-in character range does
461 // not represent a double.
462 number = charactersToDouble(characters16, length, &ok);
467 if (unit == CSSPrimitiveValue::CSS_NUMBER) {
468 if (number && strict)
470 unit = CSSPrimitiveValue::CSS_PX;
472 if (number < 0 && !acceptsNegativeNumbers)
475 Document* document = contextStyleSheet->findDocument();
476 RefPtr<CSSValue> value;
478 value = document->cssValuePool()->createValue(number, unit);
480 value = CSSPrimitiveValue::create(number, unit);
481 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
485 static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int valueID)
490 switch (propertyId) {
491 case CSSPropertyBorderCollapse: // collapse | separate | inherit
492 if (valueID == CSSValueCollapse || valueID == CSSValueSeparate)
495 case CSSPropertyBorderTopStyle: // <border-style> | inherit
496 case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
497 case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
498 case CSSPropertyBorderLeftStyle:
499 case CSSPropertyWebkitBorderAfterStyle:
500 case CSSPropertyWebkitBorderBeforeStyle:
501 case CSSPropertyWebkitBorderEndStyle:
502 case CSSPropertyWebkitBorderStartStyle:
503 case CSSPropertyWebkitColumnRuleStyle:
504 if (valueID >= CSSValueNone && valueID <= CSSValueDouble)
507 case CSSPropertyBoxSizing:
508 if (valueID == CSSValueBorderBox || valueID == CSSValueContentBox)
511 case CSSPropertyCaptionSide: // top | bottom | left | right | inherit
512 if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom)
515 case CSSPropertyClear: // none | left | right | both | inherit
516 if (valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth)
519 case CSSPropertyDirection: // ltr | rtl | inherit
520 if (valueID == CSSValueLtr || valueID == CSSValueRtl)
523 case CSSPropertyDisplay:
524 // inline | block | list-item | run-in | inline-block | table |
525 // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
526 // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none | inherit
527 // -webkit-flexbox | -webkit-inline-flexbox | -webkit-grid | -webkit-inline-grid
528 if ((valueID >= CSSValueInline && valueID <= CSSValueWebkitInlineFlexbox) || valueID == CSSValueNone)
530 #if ENABLE(CSS_GRID_LAYOUT)
531 if (valueID == CSSValueWebkitGrid || valueID == CSSValueWebkitInlineGrid)
535 case CSSPropertyEmptyCells: // show | hide | inherit
536 if (valueID == CSSValueShow || valueID == CSSValueHide)
539 case CSSPropertyFloat: // left | right | none | positioned | center (for buggy CSS, maps to none)
540 if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter || valueID == CSSValueWebkitPositioned)
543 case CSSPropertyFontStyle: // normal | italic | oblique | inherit
544 if (valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique)
547 case CSSPropertyImageRendering: // auto | optimizeContrast
548 if (valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast)
551 case CSSPropertyListStylePosition: // inside | outside | inherit
552 if (valueID == CSSValueInside || valueID == CSSValueOutside)
555 case CSSPropertyListStyleType:
556 // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
557 // for the list of supported list-style-types.
558 if ((valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone)
561 case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto | inherit
562 if (valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble))
565 case CSSPropertyOverflowX:
566 case CSSPropertyOverflowY: // visible | hidden | scroll | auto | marquee | overlay | inherit
567 if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitMarquee)
570 case CSSPropertyPointerEvents:
571 // none | visiblePainted | visibleFill | visibleStroke | visible |
572 // painted | fill | stroke | auto | all | inherit
573 if (valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueStroke))
576 case CSSPropertyPosition: // static | relative | absolute | fixed | inherit
577 if (valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed)
580 case CSSPropertyResize: // none | both | horizontal | vertical | auto
581 if (valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto)
584 case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation | inherit
585 if (valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation)
588 case CSSPropertyTableLayout: // auto | fixed | inherit
589 if (valueID == CSSValueAuto || valueID == CSSValueFixed)
592 case CSSPropertyTextLineThroughMode:
593 case CSSPropertyTextOverlineMode:
594 case CSSPropertyTextUnderlineMode:
595 if (valueID == CSSValueContinuous || valueID == CSSValueSkipWhiteSpace)
598 case CSSPropertyTextLineThroughStyle:
599 case CSSPropertyTextOverlineStyle:
600 case CSSPropertyTextUnderlineStyle:
601 if (valueID == CSSValueNone || valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDashed || valueID == CSSValueDotDash || valueID == CSSValueDotDotDash || valueID == CSSValueWave)
604 case CSSPropertyTextOverflow: // clip | ellipsis
605 if (valueID == CSSValueClip || valueID == CSSValueEllipsis)
608 case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
609 if (valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision)
612 case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none | inherit
613 if ((valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone)
616 case CSSPropertyVisibility: // visible | hidden | collapse | inherit
617 if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse)
620 case CSSPropertyWebkitAppearance:
621 if ((valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone)
624 case CSSPropertyWebkitBackfaceVisibility:
625 if (valueID == CSSValueVisible || valueID == CSSValueHidden)
628 case CSSPropertyWebkitBorderFit:
629 if (valueID == CSSValueBorder || valueID == CSSValueLines)
632 case CSSPropertyWebkitBoxAlign:
633 if (valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline)
636 case CSSPropertyWebkitBoxDirection:
637 if (valueID == CSSValueNormal || valueID == CSSValueReverse)
640 case CSSPropertyWebkitBoxLines:
641 if (valueID == CSSValueSingle || valueID == CSSValueMultiple)
644 case CSSPropertyWebkitBoxOrient:
645 if (valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis)
648 case CSSPropertyWebkitBoxPack:
649 if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify)
652 case CSSPropertyWebkitColorCorrection:
653 if (valueID == CSSValueSrgb || valueID == CSSValueDefault)
656 case CSSPropertyWebkitFlexAlign:
657 if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
660 case CSSPropertyWebkitFlexDirection:
661 if (valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse)
664 case CSSPropertyWebkitFlexItemAlign:
665 if (valueID == CSSValueAuto || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
668 case CSSPropertyWebkitFlexLinePack:
669 if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify || valueID == CSSValueDistribute || valueID == CSSValueStretch)
672 case CSSPropertyWebkitFlexPack:
673 if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify || valueID == CSSValueDistribute)
676 case CSSPropertyWebkitFlexWrap:
677 if (valueID == CSSValueNone || valueID == CSSValueWrap || valueID == CSSValueWrapReverse)
680 case CSSPropertyWebkitFontKerning:
681 if (valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone)
684 case CSSPropertyWebkitFontSmoothing:
685 if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased)
688 case CSSPropertyWebkitHyphens:
689 if (valueID == CSSValueNone || valueID == CSSValueManual || valueID == CSSValueAuto)
692 case CSSPropertyWebkitLineAlign:
693 if (valueID == CSSValueNone || valueID == CSSValueEdges)
696 case CSSPropertyWebkitLineBreak: // normal | after-white-space
697 if (valueID == CSSValueNormal || valueID == CSSValueAfterWhiteSpace)
700 case CSSPropertyWebkitLineSnap:
701 if (valueID == CSSValueNone || valueID == CSSValueBaseline || valueID == CSSValueContain)
704 case CSSPropertyWebkitMarginAfterCollapse:
705 case CSSPropertyWebkitMarginBeforeCollapse:
706 case CSSPropertyWebkitMarginBottomCollapse:
707 case CSSPropertyWebkitMarginTopCollapse:
708 if (valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard)
711 case CSSPropertyWebkitMarqueeDirection:
712 if (valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
713 || valueID == CSSValueUp || valueID == CSSValueAuto)
716 case CSSPropertyWebkitMarqueeStyle:
717 if (valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate)
720 case CSSPropertyWebkitMatchNearestMailBlockquoteColor: // normal | match
721 if (valueID == CSSValueNormal || valueID == CSSValueMatch)
724 case CSSPropertyWebkitNbspMode: // normal | space
725 if (valueID == CSSValueNormal || valueID == CSSValueSpace)
728 #if ENABLE(OVERFLOW_SCROLLING)
729 case CSSPropertyWebkitOverflowScrolling:
730 if (valueID == CSSValueAuto || valueID == CSSValueTouch)
734 case CSSPropertyWebkitPrintColorAdjust:
735 if (valueID == CSSValueExact || valueID == CSSValueEconomy)
738 case CSSPropertyWebkitRtlOrdering:
739 if (valueID == CSSValueLogical || valueID == CSSValueVisual)
742 case CSSPropertyWebkitTextCombine:
743 if (valueID == CSSValueNone || valueID == CSSValueHorizontal)
746 case CSSPropertyWebkitTextEmphasisPosition:
747 if (valueID == CSSValueOver || valueID == CSSValueUnder)
750 case CSSPropertyWebkitTextSecurity:
751 // disc | circle | square | none | inherit
752 if (valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone)
755 case CSSPropertyWebkitTextSizeAdjust:
756 if (valueID == CSSValueAuto || valueID == CSSValueNone)
759 case CSSPropertyWebkitTransformStyle:
760 if (valueID == CSSValueFlat || valueID == CSSValuePreserve3d)
763 case CSSPropertyWebkitUserDrag: // auto | none | element
764 if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement)
767 case CSSPropertyWebkitUserModify: // read-only | read-write
768 if (valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly)
771 case CSSPropertyWebkitUserSelect: // auto | none | text
772 if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText)
775 case CSSPropertyWebkitWrapFlow:
776 if (valueID == CSSValueAuto || valueID == CSSValueBoth || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueMaximum || valueID == CSSValueClear)
779 case CSSPropertyWebkitWrapThrough:
780 if (valueID == CSSValueWrap || valueID == CSSValueNone)
783 case CSSPropertyWebkitWritingMode:
784 if (valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt)
787 case CSSPropertyWhiteSpace: // normal | pre | nowrap | inherit
788 if (valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap)
791 case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
792 if (valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord)
795 case CSSPropertyWordWrap: // normal | break-word
796 if (valueID == CSSValueNormal || valueID == CSSValueBreakWord)
800 ASSERT_NOT_REACHED();
806 static inline bool isKeywordPropertyID(CSSPropertyID propertyId)
808 switch (propertyId) {
809 case CSSPropertyBorderBottomStyle:
810 case CSSPropertyBorderCollapse:
811 case CSSPropertyBorderLeftStyle:
812 case CSSPropertyBorderRightStyle:
813 case CSSPropertyBorderTopStyle:
814 case CSSPropertyBoxSizing:
815 case CSSPropertyCaptionSide:
816 case CSSPropertyClear:
817 case CSSPropertyDirection:
818 case CSSPropertyDisplay:
819 case CSSPropertyEmptyCells:
820 case CSSPropertyFloat:
821 case CSSPropertyFontStyle:
822 case CSSPropertyImageRendering:
823 case CSSPropertyListStylePosition:
824 case CSSPropertyListStyleType:
825 case CSSPropertyOutlineStyle:
826 case CSSPropertyOverflowX:
827 case CSSPropertyOverflowY:
828 case CSSPropertyPointerEvents:
829 case CSSPropertyPosition:
830 case CSSPropertyResize:
831 case CSSPropertySpeak:
832 case CSSPropertyTableLayout:
833 case CSSPropertyTextLineThroughMode:
834 case CSSPropertyTextLineThroughStyle:
835 case CSSPropertyTextOverflow:
836 case CSSPropertyTextOverlineMode:
837 case CSSPropertyTextOverlineStyle:
838 case CSSPropertyTextRendering:
839 case CSSPropertyTextTransform:
840 case CSSPropertyTextUnderlineMode:
841 case CSSPropertyTextUnderlineStyle:
842 case CSSPropertyVisibility:
843 case CSSPropertyWebkitAppearance:
844 case CSSPropertyWebkitBackfaceVisibility:
845 case CSSPropertyWebkitBorderAfterStyle:
846 case CSSPropertyWebkitBorderBeforeStyle:
847 case CSSPropertyWebkitBorderEndStyle:
848 case CSSPropertyWebkitBorderFit:
849 case CSSPropertyWebkitBorderStartStyle:
850 case CSSPropertyWebkitBoxAlign:
851 case CSSPropertyWebkitBoxDirection:
852 case CSSPropertyWebkitBoxLines:
853 case CSSPropertyWebkitBoxOrient:
854 case CSSPropertyWebkitBoxPack:
855 case CSSPropertyWebkitColorCorrection:
856 case CSSPropertyWebkitColumnRuleStyle:
857 case CSSPropertyWebkitFlexAlign:
858 case CSSPropertyWebkitFlexDirection:
859 case CSSPropertyWebkitFlexItemAlign:
860 case CSSPropertyWebkitFlexLinePack:
861 case CSSPropertyWebkitFlexPack:
862 case CSSPropertyWebkitFlexWrap:
863 case CSSPropertyWebkitFontKerning:
864 case CSSPropertyWebkitFontSmoothing:
865 case CSSPropertyWebkitHyphens:
866 case CSSPropertyWebkitLineAlign:
867 case CSSPropertyWebkitLineBreak:
868 case CSSPropertyWebkitLineSnap:
869 case CSSPropertyWebkitMarginAfterCollapse:
870 case CSSPropertyWebkitMarginBeforeCollapse:
871 case CSSPropertyWebkitMarginBottomCollapse:
872 case CSSPropertyWebkitMarginTopCollapse:
873 case CSSPropertyWebkitMarqueeDirection:
874 case CSSPropertyWebkitMarqueeStyle:
875 case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
876 case CSSPropertyWebkitNbspMode:
877 #if ENABLE(OVERFLOW_SCROLLING)
878 case CSSPropertyWebkitOverflowScrolling:
880 case CSSPropertyWebkitPrintColorAdjust:
881 case CSSPropertyWebkitRtlOrdering:
882 case CSSPropertyWebkitTextCombine:
883 case CSSPropertyWebkitTextEmphasisPosition:
884 case CSSPropertyWebkitTextSecurity:
885 case CSSPropertyWebkitTextSizeAdjust:
886 case CSSPropertyWebkitTransformStyle:
887 case CSSPropertyWebkitUserDrag:
888 case CSSPropertyWebkitUserModify:
889 case CSSPropertyWebkitUserSelect:
890 case CSSPropertyWebkitWrapFlow:
891 case CSSPropertyWebkitWrapThrough:
892 case CSSPropertyWebkitWritingMode:
893 case CSSPropertyWhiteSpace:
894 case CSSPropertyWordBreak:
895 case CSSPropertyWordWrap:
902 static bool parseKeywordValue(StylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSStyleSheet* contextStyleSheet)
904 if (string.isEmpty())
907 if (!isKeywordPropertyID(propertyId))
910 CSSParserString cssString;
911 cssString.characters = const_cast<UChar*>(string.characters());
912 cssString.length = string.length();
913 int valueID = cssValueKeywordID(cssString);
918 Document* document = contextStyleSheet->findDocument();
919 RefPtr<CSSValue> value;
920 CSSValuePool* cssValuePool = document ? document->cssValuePool().get() : 0;
921 if (valueID == CSSValueInherit)
922 value = cssValuePool ? cssValuePool->createInheritedValue() : CSSInheritedValue::create();
923 else if (valueID == CSSValueInitial)
924 value = cssValuePool ? cssValuePool->createExplicitInitialValue() : CSSInitialValue::createExplicit();
925 else if (isValidKeywordPropertyAndValue(propertyId, valueID))
926 value = cssValuePool ? cssValuePool->createIdentifierValue(valueID) : CSSPrimitiveValue::createIdentifier(valueID);
930 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
934 PassRefPtr<CSSValueList> CSSParser::parseFontFaceValue(const AtomicString& string, CSSStyleSheet* contextStyleSheet)
936 RefPtr<StylePropertySet> dummyStyle = StylePropertySet::create();
937 if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, CSSQuirksMode, contextStyleSheet))
939 return static_pointer_cast<CSSValueList>(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily));
942 bool CSSParser::parseValue(StylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, CSSStyleSheet* contextStyleSheet)
944 if (parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode, contextStyleSheet))
946 if (parseColorValue(declaration, propertyID, string, important, cssParserMode, contextStyleSheet))
948 if (parseKeywordValue(declaration, propertyID, string, important, contextStyleSheet))
950 CSSParser parser(cssParserMode);
951 return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet);
954 bool CSSParser::parseValue(StylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSStyleSheet* contextStyleSheet)
956 setStyleSheet(contextStyleSheet);
958 setupParser("@-webkit-value{", string, "} ");
961 m_important = important;
968 if (m_hasFontFaceOnlyValues)
969 deleteFontFaceOnlyValues();
970 if (!m_parsedProperties.isEmpty()) {
972 declaration->addParsedProperties(m_parsedProperties.data(), m_parsedProperties.size());
979 // The color will only be changed when string contains a valid CSS color, so callers
980 // can set it to a default color and ignore the boolean result.
981 bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict)
983 // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
984 if (fastParseColor(color, string, strict))
987 CSSParser parser(CSSStrictMode);
989 // In case the fast-path parser didn't understand the color, try the full parser.
990 if (!parser.parseColor(string))
993 CSSValue* value = parser.m_parsedProperties.first().value();
994 if (!value->isPrimitiveValue())
997 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
998 if (!primitiveValue->isRGBColor())
1001 color = primitiveValue->getRGBA32Value();
1005 bool CSSParser::parseColor(const String& string)
1007 // This function may be called without a stylesheet set on the parser, so we need to
1008 // make sure that we have a CSSValuePool or we'll crash below cssyyparse().
1009 ensureCSSValuePool();
1011 setupParser("@-webkit-decls{color:", string, "} ");
1015 return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor;
1018 bool CSSParser::parseSystemColor(RGBA32& color, const String& string, Document* document)
1020 if (!document || !document->page())
1023 CSSParserString cssColor;
1024 cssColor.characters = const_cast<UChar*>(string.characters());
1025 cssColor.length = string.length();
1026 int id = cssValueKeywordID(cssColor);
1030 color = document->page()->theme()->systemColor(id).rgb();
1034 void CSSParser::parseSelector(const String& string, Document* doc, CSSSelectorList& selectorList)
1036 RefPtr<CSSStyleSheet> dummyStyleSheet = CSSStyleSheet::create(doc);
1038 setStyleSheet(dummyStyleSheet.get());
1039 m_selectorListForParseSelector = &selectorList;
1041 setupParser("@-webkit-selector{", string, "}");
1045 m_selectorListForParseSelector = 0;
1047 // The style sheet will be deleted right away, so it won't outlive the document.
1048 ASSERT(dummyStyleSheet->hasOneRef());
1051 bool CSSParser::parseDeclaration(StylePropertySet* declaration, const String& string, RefPtr<CSSStyleSourceData>* styleSourceData, CSSStyleSheet* contextStyleSheet)
1053 // Length of the "@-webkit-decls{" prefix.
1054 static const unsigned prefixLength = 15;
1056 setStyleSheet(contextStyleSheet);
1058 if (styleSourceData) {
1059 m_currentRuleData = CSSRuleSourceData::create();
1060 m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
1061 m_inStyleRuleOrDeclaration = true;
1064 setupParser("@-webkit-decls{", string, "} ");
1069 if (m_hasFontFaceOnlyValues)
1070 deleteFontFaceOnlyValues();
1071 if (!m_parsedProperties.isEmpty()) {
1073 declaration->addParsedProperties(m_parsedProperties.data(), m_parsedProperties.size());
1077 if (m_currentRuleData) {
1078 m_currentRuleData->styleSourceData->styleBodyRange.start = 0;
1079 m_currentRuleData->styleSourceData->styleBodyRange.end = string.length();
1080 for (Vector<CSSPropertySourceData>::iterator it = m_currentRuleData->styleSourceData->propertyData.begin(), endIt = m_currentRuleData->styleSourceData->propertyData.end(); it != endIt; ++it) {
1081 (*it).range.start -= prefixLength;
1082 (*it).range.end -= prefixLength;
1086 if (styleSourceData) {
1087 *styleSourceData = m_currentRuleData->styleSourceData.release();
1088 m_currentRuleData = 0;
1089 m_inStyleRuleOrDeclaration = false;
1094 PassOwnPtr<MediaQuery> CSSParser::parseMediaQuery(const String& string)
1096 if (string.isEmpty())
1099 ASSERT(!m_mediaQuery);
1101 // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
1102 // instead insert one " " (which is WHITESPACE in CSSGrammar.y)
1103 setupParser("@-webkit-mediaquery ", string, "} ");
1106 return m_mediaQuery.release();
1109 void CSSParser::addProperty(CSSPropertyID propId, PassRefPtr<CSSValue> value, bool important, bool implicit)
1111 m_parsedProperties.append(CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand || implicit));
1114 void CSSParser::rollbackLastProperties(int num)
1117 ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num));
1118 m_parsedProperties.shrink(m_parsedProperties.size() - num);
1121 void CSSParser::clearProperties()
1123 m_parsedProperties.clear();
1124 m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1125 m_hasFontFaceOnlyValues = false;
1128 void CSSParser::setStyleSheet(CSSStyleSheet* styleSheet)
1130 m_styleSheet = styleSheet;
1131 Document* document = findDocument();
1132 m_cssValuePool = document ? document->cssValuePool() : CSSValuePool::create();
1135 Document* CSSParser::findDocument() const
1139 return m_styleSheet->findDocument();
1142 bool CSSParser::validCalculationUnit(CSSParserValue* value, Units unitflags)
1144 bool mustBeNonNegative = unitflags & FNonNeg;
1146 if (!parseCalculation(value, mustBeNonNegative ? CalculationRangeNonNegative : CalculationRangeAll))
1150 switch (m_parsedCalculation->category()) {
1152 b = (unitflags & FLength);
1155 b = (unitflags & FPercent);
1156 if (b && mustBeNonNegative && m_parsedCalculation->isNegative())
1160 b = (unitflags & FNumber);
1161 if (!b && (unitflags & FInteger) && m_parsedCalculation->isInt())
1163 if (b && mustBeNonNegative && m_parsedCalculation->isNegative())
1166 case CalcPercentLength:
1167 b = (unitflags & FPercent) && (unitflags & FLength);
1169 case CalcPercentNumber:
1170 b = (unitflags & FPercent) && (unitflags & FNumber);
1176 m_parsedCalculation.release();
1180 inline bool CSSParser::shouldAcceptUnitLessValues(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode)
1182 // Qirks mode and svg presentation attributes accept unit less values.
1183 return (unitflags & (FLength | FAngle | FTime)) && (!value->fValue || cssParserMode == CSSQuirksMode || cssParserMode == SVGAttributeMode);
1186 bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode)
1188 if (isCalculation(value))
1189 return validCalculationUnit(value, unitflags);
1192 switch (value->unit) {
1193 case CSSPrimitiveValue::CSS_NUMBER:
1194 b = (unitflags & FNumber);
1195 if (!b && shouldAcceptUnitLessValues(value, unitflags, cssParserMode)) {
1196 value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX :
1197 ((unitflags & FAngle) ? CSSPrimitiveValue::CSS_DEG : CSSPrimitiveValue::CSS_MS);
1200 if (!b && (unitflags & FInteger) && value->isInt)
1203 case CSSPrimitiveValue::CSS_PERCENTAGE:
1204 b = (unitflags & FPercent);
1206 case CSSParserValue::Q_EMS:
1207 case CSSPrimitiveValue::CSS_EMS:
1208 case CSSPrimitiveValue::CSS_REMS:
1209 case CSSPrimitiveValue::CSS_EXS:
1210 case CSSPrimitiveValue::CSS_PX:
1211 case CSSPrimitiveValue::CSS_CM:
1212 case CSSPrimitiveValue::CSS_MM:
1213 case CSSPrimitiveValue::CSS_IN:
1214 case CSSPrimitiveValue::CSS_PT:
1215 case CSSPrimitiveValue::CSS_PC:
1216 case CSSPrimitiveValue::CSS_VW:
1217 case CSSPrimitiveValue::CSS_VH:
1218 case CSSPrimitiveValue::CSS_VMIN:
1219 b = (unitflags & FLength);
1221 case CSSPrimitiveValue::CSS_MS:
1222 case CSSPrimitiveValue::CSS_S:
1223 b = (unitflags & FTime);
1225 case CSSPrimitiveValue::CSS_DEG:
1226 case CSSPrimitiveValue::CSS_RAD:
1227 case CSSPrimitiveValue::CSS_GRAD:
1228 case CSSPrimitiveValue::CSS_TURN:
1229 b = (unitflags & FAngle);
1231 case CSSPrimitiveValue::CSS_HZ:
1232 case CSSPrimitiveValue::CSS_KHZ:
1233 case CSSPrimitiveValue::CSS_DIMENSION:
1237 if (b && unitflags & FNonNeg && value->fValue < 0)
1242 inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(CSSParserValue* value)
1244 if (m_parsedCalculation) {
1245 ASSERT(isCalculation(value));
1246 return CSSPrimitiveValue::create(m_parsedCalculation.release());
1249 ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1250 || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
1251 || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN));
1252 return cssValuePool()->createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit));
1255 inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveStringValue(CSSParserValue* value)
1257 ASSERT(value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT);
1258 return cssValuePool()->createValue(value->string, CSSPrimitiveValue::CSS_STRING);
1261 static int unitFromString(CSSParserValue* value)
1263 if (value->unit != CSSPrimitiveValue::CSS_IDENT || value->id)
1266 if (equal(value->string, "em"))
1267 return CSSPrimitiveValue::CSS_EMS;
1268 if (equal(value->string, "rem"))
1269 return CSSPrimitiveValue::CSS_REMS;
1270 if (equal(value->string, "ex"))
1271 return CSSPrimitiveValue::CSS_EXS;
1272 if (equal(value->string, "px"))
1273 return CSSPrimitiveValue::CSS_PX;
1274 if (equal(value->string, "cm"))
1275 return CSSPrimitiveValue::CSS_CM;
1276 if (equal(value->string, "mm"))
1277 return CSSPrimitiveValue::CSS_MM;
1278 if (equal(value->string, "in"))
1279 return CSSPrimitiveValue::CSS_IN;
1280 if (equal(value->string, "pt"))
1281 return CSSPrimitiveValue::CSS_PT;
1282 if (equal(value->string, "pc"))
1283 return CSSPrimitiveValue::CSS_PC;
1284 if (equal(value->string, "deg"))
1285 return CSSPrimitiveValue::CSS_DEG;
1286 if (equal(value->string, "rad"))
1287 return CSSPrimitiveValue::CSS_RAD;
1288 if (equal(value->string, "grad"))
1289 return CSSPrimitiveValue::CSS_GRAD;
1290 if (equal(value->string, "turn"))
1291 return CSSPrimitiveValue::CSS_TURN;
1292 if (equal(value->string, "ms"))
1293 return CSSPrimitiveValue::CSS_MS;
1294 if (equal(value->string, "s"))
1295 return CSSPrimitiveValue::CSS_S;
1296 if (equal(value->string, "Hz"))
1297 return CSSPrimitiveValue::CSS_HZ;
1298 if (equal(value->string, "kHz"))
1299 return CSSPrimitiveValue::CSS_KHZ;
1300 if (equal(value->string, "vw"))
1301 return CSSPrimitiveValue::CSS_VW;
1302 if (equal(value->string, "vh"))
1303 return CSSPrimitiveValue::CSS_VH;
1304 if (equal(value->string, "vmin"))
1305 return CSSPrimitiveValue::CSS_VMIN;
1310 static inline bool isComma(CSSParserValue* value)
1312 return value && value->unit == CSSParserValue::Operator && value->iValue == ',';
1316 void CSSParser::checkForOrphanedUnits()
1318 if (inStrictMode() || inShorthand())
1321 // The purpose of this code is to implement the WinIE quirk that allows unit types to be separated from their numeric values
1322 // by whitespace, so e.g., width: 20 px instead of width:20px. This is invalid CSS, so we don't do this in strict mode.
1323 CSSParserValue* numericVal = 0;
1324 unsigned size = m_valueList->size();
1325 for (unsigned i = 0; i < size; i++) {
1326 CSSParserValue* value = m_valueList->valueAt(i);
1329 // Change the unit type of the numeric val to match.
1330 int unit = unitFromString(value);
1332 numericVal->unit = unit;
1335 // Now delete the bogus unit value.
1336 m_valueList->deleteValueAt(i);
1337 i--; // We're safe even though |i| is unsigned, since we only hit this code if we had a previous numeric value (so |i| is always > 0 here).
1343 numericVal = (value->unit == CSSPrimitiveValue::CSS_NUMBER) ? value : 0;
1347 inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(int identifier, CSSParserValue* value)
1350 return cssValuePool()->createIdentifierValue(identifier);
1351 if (value->unit == CSSPrimitiveValue::CSS_STRING)
1352 return createPrimitiveStringValue(value);
1353 if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1354 return createPrimitiveNumericValue(value);
1355 if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
1356 return createPrimitiveNumericValue(value);
1357 if (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN)
1358 return createPrimitiveNumericValue(value);
1359 if (value->unit >= CSSParserValue::Q_EMS)
1360 return CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS);
1361 if (isCalculation(value))
1362 return CSSPrimitiveValue::create(m_parsedCalculation.release());
1367 bool CSSParser::parseValue(CSSPropertyID propId, bool important)
1372 CSSParserValue* value = m_valueList->current();
1377 // Note: m_parsedCalculation is used to pass the calc value to validUnit and then cleared at the end of this function.
1378 // FIXME: This is to avoid having to pass parsedCalc to all validUnit callers.
1379 ASSERT(!m_parsedCalculation);
1383 // In quirks mode, we will look for units that have been incorrectly separated from the number they belong to
1384 // by a space. We go ahead and associate the unit with the number even though it is invalid CSS.
1385 checkForOrphanedUnits();
1387 int num = inShorthand() ? 1 : m_valueList->size();
1389 if (id == CSSValueInherit) {
1392 addProperty(propId, cssValuePool()->createInheritedValue(), important);
1395 else if (id == CSSValueInitial) {
1398 addProperty(propId, cssValuePool()->createExplicitInitialValue(), important);
1402 if (isKeywordPropertyID(propId)) {
1403 if (!isValidKeywordPropertyAndValue(propId, id))
1405 if (m_valueList->next() && !inShorthand())
1407 addProperty(propId, cssValuePool()->createIdentifierValue(id), important);
1411 bool validPrimitive = false;
1412 RefPtr<CSSValue> parsedValue;
1415 /* The comment to the left defines all valid value of this properties as defined
1416 * in CSS 2, Appendix F. Property index
1419 /* All the CSS properties are not supported by the renderer at the moment.
1420 * Note that all the CSS2 Aural properties are only checked, if CSS_AURAL is defined
1421 * (see parseAuralValues). As we don't support them at all this seems reasonable.
1424 case CSSPropertySize: // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
1425 return parseSize(propId, important);
1427 case CSSPropertyQuotes: // [<string> <string>]+ | none | inherit
1429 validPrimitive = true;
1431 return parseQuotes(propId, important);
1433 case CSSPropertyUnicodeBidi: // normal | embed | (bidi-override || isolate) | plaintext | inherit
1434 if (id == CSSValueNormal
1435 || id == CSSValueEmbed
1436 || id == CSSValueWebkitPlaintext)
1437 validPrimitive = true;
1439 RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
1440 bool isValid = true;
1441 while (isValid && value) {
1442 switch (value->id) {
1443 case CSSValueBidiOverride:
1444 case CSSValueWebkitIsolate:
1445 list->append(cssValuePool()->createIdentifierValue(value->id));
1450 value = m_valueList->next();
1452 if (list->length() && isValid) {
1453 parsedValue = list.release();
1454 m_valueList->next();
1459 case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right | inherit
1460 case CSSPropertyPageBreakBefore:
1461 case CSSPropertyWebkitColumnBreakAfter:
1462 case CSSPropertyWebkitColumnBreakBefore:
1463 case CSSPropertyWebkitRegionBreakAfter:
1464 case CSSPropertyWebkitRegionBreakBefore:
1465 if (id == CSSValueAuto
1466 || id == CSSValueAlways
1467 || id == CSSValueAvoid
1468 || id == CSSValueLeft
1469 || id == CSSValueRight)
1470 validPrimitive = ((propId == CSSPropertyWebkitRegionBreakAfter) || (propId == CSSPropertyWebkitRegionBreakBefore)) ? cssRegionsEnabled() : true;
1473 case CSSPropertyPageBreakInside: // avoid | auto | inherit
1474 case CSSPropertyWebkitColumnBreakInside:
1475 case CSSPropertyWebkitRegionBreakInside:
1476 if (id == CSSValueAuto || id == CSSValueAvoid)
1477 validPrimitive = (propId == CSSPropertyWebkitRegionBreakInside) ? cssRegionsEnabled() : true;
1480 case CSSPropertyContent: // [ <string> | <uri> | <counter> | attr(X) | open-quote |
1481 // close-quote | no-open-quote | no-close-quote ]+ | inherit
1482 return parseContent(propId, important);
1484 case CSSPropertyClip: // <shape> | auto | inherit
1485 if (id == CSSValueAuto)
1486 validPrimitive = true;
1487 else if (value->unit == CSSParserValue::Function)
1488 return parseClipShape(propId, important);
1491 /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
1492 * correctly and allows optimization in WebCore::applyRule(..)
1494 case CSSPropertyOverflow: {
1495 ShorthandScope scope(this, propId);
1496 if (num != 1 || !parseValue(CSSPropertyOverflowX, important))
1498 CSSValue* value = m_parsedProperties.last().value();
1499 addProperty(CSSPropertyOverflowY, value, important);
1503 case CSSPropertyTextAlign:
1504 // left | right | center | justify | webkit_left | webkit_right | webkit_center | webkit_match_parent |
1505 // start | end | <string> | inherit
1506 if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd
1507 || value->unit == CSSPrimitiveValue::CSS_STRING)
1508 validPrimitive = true;
1511 case CSSPropertyFontWeight: // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
1512 return parseFontWeight(important);
1514 case CSSPropertyBorderSpacing: {
1516 ShorthandScope scope(this, CSSPropertyBorderSpacing);
1517 if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important))
1519 CSSValue* value = m_parsedProperties.last().value();
1520 addProperty(CSSPropertyWebkitBorderVerticalSpacing, value, important);
1523 else if (num == 2) {
1524 ShorthandScope scope(this, CSSPropertyBorderSpacing);
1525 if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important) || !parseValue(CSSPropertyWebkitBorderVerticalSpacing, important))
1531 case CSSPropertyWebkitBorderHorizontalSpacing:
1532 case CSSPropertyWebkitBorderVerticalSpacing:
1533 validPrimitive = validUnit(value, FLength | FNonNeg);
1535 case CSSPropertyOutlineColor: // <color> | invert | inherit
1536 // Outline color has "invert" as additional keyword.
1537 // Also, we want to allow the special focus color even in strict parsing mode.
1538 if (id == CSSValueInvert || id == CSSValueWebkitFocusRingColor) {
1539 validPrimitive = true;
1543 case CSSPropertyBackgroundColor: // <color> | inherit
1544 case CSSPropertyBorderTopColor: // <color> | inherit
1545 case CSSPropertyBorderRightColor:
1546 case CSSPropertyBorderBottomColor:
1547 case CSSPropertyBorderLeftColor:
1548 case CSSPropertyWebkitBorderStartColor:
1549 case CSSPropertyWebkitBorderEndColor:
1550 case CSSPropertyWebkitBorderBeforeColor:
1551 case CSSPropertyWebkitBorderAfterColor:
1552 case CSSPropertyColor: // <color> | inherit
1553 case CSSPropertyTextLineThroughColor: // CSS3 text decoration colors
1554 case CSSPropertyTextUnderlineColor:
1555 case CSSPropertyTextOverlineColor:
1556 case CSSPropertyWebkitColumnRuleColor:
1557 case CSSPropertyWebkitTextEmphasisColor:
1558 case CSSPropertyWebkitTextFillColor:
1559 case CSSPropertyWebkitTextStrokeColor:
1560 if (id == CSSValueWebkitText)
1561 validPrimitive = true; // Always allow this, even when strict parsing is on,
1562 // since we use this in our UA sheets.
1563 else if (id == CSSValueCurrentcolor)
1564 validPrimitive = true;
1565 else if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu ||
1566 (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && inQuirksMode())) {
1567 validPrimitive = true;
1569 parsedValue = parseColor();
1571 m_valueList->next();
1575 case CSSPropertyCursor: {
1576 // [<uri>,]* [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
1577 // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize |
1578 // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help |
1579 // vertical-text | cell | context-menu | alias | copy | no-drop | not-allowed | -webkit-zoom-in
1580 // -webkit-zoom-out | all-scroll | -webkit-grab | -webkit-grabbing ] ] | inherit
1581 RefPtr<CSSValueList> list;
1582 while (value && value->unit == CSSPrimitiveValue::CSS_URI) {
1584 list = CSSValueList::createCommaSeparated();
1585 String uri = value->string;
1587 value = m_valueList->next();
1588 while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) {
1589 coords.append(int(value->fValue));
1590 value = m_valueList->next();
1592 IntPoint hotSpot(-1, -1);
1593 int nrcoords = coords.size();
1594 if (nrcoords > 0 && nrcoords != 2)
1597 hotSpot = IntPoint(coords[0], coords[1]);
1599 if (!uri.isNull() && m_styleSheet) {
1600 // FIXME: The completeURL call should be done when using the CSSCursorImageValue,
1601 // not when creating it.
1602 list->append(CSSCursorImageValue::create(m_styleSheet->completeURL(uri), hotSpot));
1605 if ((inStrictMode() && !value) || (value && !(value->unit == CSSParserValue::Operator && value->iValue == ',')))
1607 value = m_valueList->next(); // comma
1610 if (!value) { // no value after url list (MSIE 5 compatibility)
1611 if (list->length() != 1)
1613 } else if (inQuirksMode() && value->id == CSSValueHand) // MSIE 5 compatibility :/
1614 list->append(cssValuePool()->createIdentifierValue(CSSValuePointer));
1615 else if (value && ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone))
1616 list->append(cssValuePool()->createIdentifierValue(value->id));
1617 m_valueList->next();
1618 parsedValue = list.release();
1622 if (inQuirksMode() && value->id == CSSValueHand) { // MSIE 5 compatibility :/
1623 id = CSSValuePointer;
1624 validPrimitive = true;
1625 } else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)
1626 validPrimitive = true;
1630 case CSSPropertyBackgroundAttachment:
1631 case CSSPropertyBackgroundClip:
1632 case CSSPropertyWebkitBackgroundClip:
1633 case CSSPropertyWebkitBackgroundComposite:
1634 case CSSPropertyBackgroundImage:
1635 case CSSPropertyBackgroundOrigin:
1636 case CSSPropertyWebkitBackgroundOrigin:
1637 case CSSPropertyBackgroundPosition:
1638 case CSSPropertyBackgroundPositionX:
1639 case CSSPropertyBackgroundPositionY:
1640 case CSSPropertyBackgroundSize:
1641 case CSSPropertyWebkitBackgroundSize:
1642 case CSSPropertyBackgroundRepeat:
1643 case CSSPropertyBackgroundRepeatX:
1644 case CSSPropertyBackgroundRepeatY:
1645 case CSSPropertyWebkitMaskAttachment:
1646 case CSSPropertyWebkitMaskClip:
1647 case CSSPropertyWebkitMaskComposite:
1648 case CSSPropertyWebkitMaskImage:
1649 case CSSPropertyWebkitMaskOrigin:
1650 case CSSPropertyWebkitMaskPosition:
1651 case CSSPropertyWebkitMaskPositionX:
1652 case CSSPropertyWebkitMaskPositionY:
1653 case CSSPropertyWebkitMaskSize:
1654 case CSSPropertyWebkitMaskRepeat:
1655 case CSSPropertyWebkitMaskRepeatX:
1656 case CSSPropertyWebkitMaskRepeatY: {
1657 RefPtr<CSSValue> val1;
1658 RefPtr<CSSValue> val2;
1659 CSSPropertyID propId1, propId2;
1660 bool result = false;
1661 if (parseFillProperty(propId, propId1, propId2, val1, val2)) {
1662 OwnPtr<ShorthandScope> shorthandScope;
1663 if (propId == CSSPropertyBackgroundPosition ||
1664 propId == CSSPropertyBackgroundRepeat ||
1665 propId == CSSPropertyWebkitMaskPosition ||
1666 propId == CSSPropertyWebkitMaskRepeat) {
1667 shorthandScope = adoptPtr(new ShorthandScope(this, propId));
1669 addProperty(propId1, val1.release(), important);
1671 addProperty(propId2, val2.release(), important);
1674 m_implicitShorthand = false;
1677 case CSSPropertyListStyleImage: // <uri> | none | inherit
1678 case CSSPropertyBorderImageSource:
1679 case CSSPropertyWebkitMaskBoxImageSource:
1680 if (id == CSSValueNone) {
1681 parsedValue = cssValuePool()->createIdentifierValue(CSSValueNone);
1682 m_valueList->next();
1683 } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
1685 // FIXME: The completeURL call should be done when using the CSSImageValue,
1686 // not when creating it.
1687 parsedValue = CSSImageValue::create(m_styleSheet->completeURL(value->string));
1688 m_valueList->next();
1690 } else if (isGeneratedImageValue(value)) {
1691 if (parseGeneratedImage(m_valueList.get(), parsedValue))
1692 m_valueList->next();
1696 #if ENABLE(CSS_IMAGE_SET)
1697 else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "-webkit-image-set(")) {
1698 parsedValue = parseImageSet(m_valueList.get());
1701 m_valueList->next();
1706 case CSSPropertyWebkitTextStrokeWidth:
1707 case CSSPropertyOutlineWidth: // <border-width> | inherit
1708 case CSSPropertyBorderTopWidth: //// <border-width> | inherit
1709 case CSSPropertyBorderRightWidth: // Which is defined as
1710 case CSSPropertyBorderBottomWidth: // thin | medium | thick | <length>
1711 case CSSPropertyBorderLeftWidth:
1712 case CSSPropertyWebkitBorderStartWidth:
1713 case CSSPropertyWebkitBorderEndWidth:
1714 case CSSPropertyWebkitBorderBeforeWidth:
1715 case CSSPropertyWebkitBorderAfterWidth:
1716 case CSSPropertyWebkitColumnRuleWidth:
1717 if (id == CSSValueThin || id == CSSValueMedium || id == CSSValueThick)
1718 validPrimitive = true;
1720 validPrimitive = validUnit(value, FLength | FNonNeg);
1723 case CSSPropertyLetterSpacing: // normal | <length> | inherit
1724 case CSSPropertyWordSpacing: // normal | <length> | inherit
1725 if (id == CSSValueNormal)
1726 validPrimitive = true;
1728 validPrimitive = validUnit(value, FLength);
1731 case CSSPropertyTextIndent: // <length> | <percentage> | inherit
1732 validPrimitive = (!id && validUnit(value, FLength | FPercent));
1735 case CSSPropertyPaddingTop: //// <padding-width> | inherit
1736 case CSSPropertyPaddingRight: // Which is defined as
1737 case CSSPropertyPaddingBottom: // <length> | <percentage>
1738 case CSSPropertyPaddingLeft: ////
1739 case CSSPropertyWebkitPaddingStart:
1740 case CSSPropertyWebkitPaddingEnd:
1741 case CSSPropertyWebkitPaddingBefore:
1742 case CSSPropertyWebkitPaddingAfter:
1743 validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg));
1746 case CSSPropertyMaxHeight: // <length> | <percentage> | none | inherit
1747 case CSSPropertyMaxWidth: // <length> | <percentage> | none | inherit
1748 case CSSPropertyWebkitMaxLogicalWidth:
1749 case CSSPropertyWebkitMaxLogicalHeight:
1750 if (id == CSSValueNone) {
1751 validPrimitive = true;
1755 case CSSPropertyMinHeight: // <length> | <percentage> | inherit
1756 case CSSPropertyMinWidth: // <length> | <percentage> | inherit
1757 case CSSPropertyWebkitMinLogicalWidth:
1758 case CSSPropertyWebkitMinLogicalHeight:
1759 if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
1760 validPrimitive = true;
1762 validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg));
1765 case CSSPropertyFontSize:
1766 // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
1767 if (id >= CSSValueXxSmall && id <= CSSValueLarger)
1768 validPrimitive = true;
1770 validPrimitive = (validUnit(value, FLength | FPercent | FNonNeg));
1773 case CSSPropertyFontVariant: // normal | small-caps | inherit
1774 return parseFontVariant(important);
1776 case CSSPropertyVerticalAlign:
1777 // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
1778 // <percentage> | <length> | inherit
1780 if (id >= CSSValueBaseline && id <= CSSValueWebkitBaselineMiddle)
1781 validPrimitive = true;
1783 validPrimitive = (!id && validUnit(value, FLength | FPercent));
1786 case CSSPropertyHeight: // <length> | <percentage> | auto | inherit
1787 case CSSPropertyWidth: // <length> | <percentage> | auto | inherit
1788 case CSSPropertyWebkitLogicalWidth:
1789 case CSSPropertyWebkitLogicalHeight:
1790 if (id == CSSValueAuto || id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
1791 validPrimitive = true;
1792 else if (!id && validUnit(value, FLength | FPercent | FNonNeg))
1793 // ### handle multilength case where we allow relative units
1794 validPrimitive = true;
1797 case CSSPropertyBottom: // <length> | <percentage> | auto | inherit
1798 case CSSPropertyLeft: // <length> | <percentage> | auto | inherit
1799 case CSSPropertyRight: // <length> | <percentage> | auto | inherit
1800 case CSSPropertyTop: // <length> | <percentage> | auto | inherit
1801 case CSSPropertyMarginTop: //// <margin-width> | inherit
1802 case CSSPropertyMarginRight: // Which is defined as
1803 case CSSPropertyMarginBottom: // <length> | <percentage> | auto | inherit
1804 case CSSPropertyMarginLeft: ////
1805 case CSSPropertyWebkitMarginStart:
1806 case CSSPropertyWebkitMarginEnd:
1807 case CSSPropertyWebkitMarginBefore:
1808 case CSSPropertyWebkitMarginAfter:
1809 if (id == CSSValueAuto)
1810 validPrimitive = true;
1812 validPrimitive = (!id && validUnit(value, FLength | FPercent));
1815 case CSSPropertyZIndex: // auto | <integer> | inherit
1816 if (id == CSSValueAuto) {
1817 validPrimitive = true;
1821 case CSSPropertyOrphans: // <integer> | inherit
1822 case CSSPropertyWidows: // <integer> | inherit
1823 // ### not supported later on
1824 validPrimitive = (!id && validUnit(value, FInteger, CSSQuirksMode));
1827 case CSSPropertyLineHeight: // normal | <number> | <length> | <percentage> | inherit
1828 if (id == CSSValueNormal)
1829 validPrimitive = true;
1831 validPrimitive = (!id && validUnit(value, FNumber | FLength | FPercent | FNonNeg));
1833 case CSSPropertyCounterIncrement: // [ <identifier> <integer>? ]+ | none | inherit
1834 if (id != CSSValueNone)
1835 return parseCounter(propId, 1, important);
1836 validPrimitive = true;
1838 case CSSPropertyCounterReset: // [ <identifier> <integer>? ]+ | none | inherit
1839 if (id != CSSValueNone)
1840 return parseCounter(propId, 0, important);
1841 validPrimitive = true;
1843 case CSSPropertyFontFamily:
1844 // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
1846 parsedValue = parseFontFamily();
1850 case CSSPropertyTextDecoration:
1851 case CSSPropertyWebkitTextDecorationsInEffect:
1852 // none | [ underline || overline || line-through || blink ] | inherit
1853 if (id == CSSValueNone) {
1854 validPrimitive = true;
1856 RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
1857 bool isValid = true;
1858 while (isValid && value) {
1859 switch (value->id) {
1862 case CSSValueUnderline:
1863 case CSSValueOverline:
1864 case CSSValueLineThrough:
1865 list->append(cssValuePool()->createIdentifierValue(value->id));
1870 value = m_valueList->next();
1872 if (list->length() && isValid) {
1873 parsedValue = list.release();
1874 m_valueList->next();
1879 case CSSPropertyZoom: // normal | reset | document | <number> | <percentage> | inherit
1880 if (id == CSSValueNormal || id == CSSValueReset || id == CSSValueDocument)
1881 validPrimitive = true;
1883 validPrimitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg, CSSStrictMode));
1886 case CSSPropertySrc: // Only used within @font-face, so cannot use inherit | initial or be !important. This is a list of urls or local references.
1887 return parseFontFaceSrc();
1889 case CSSPropertyUnicodeRange:
1890 return parseFontFaceUnicodeRange();
1892 /* CSS3 properties */
1894 case CSSPropertyBorderImage: {
1895 RefPtr<CSSValue> result;
1896 return parseBorderImage(propId, result, important);
1898 case CSSPropertyWebkitBorderImage:
1899 case CSSPropertyWebkitMaskBoxImage: {
1900 RefPtr<CSSValue> result;
1901 if (parseBorderImage(propId, result)) {
1902 addProperty(propId, result, important);
1907 case CSSPropertyBorderImageOutset:
1908 case CSSPropertyWebkitMaskBoxImageOutset: {
1909 RefPtr<CSSPrimitiveValue> result;
1910 if (parseBorderImageOutset(result)) {
1911 addProperty(propId, result, important);
1916 case CSSPropertyBorderImageRepeat:
1917 case CSSPropertyWebkitMaskBoxImageRepeat: {
1918 RefPtr<CSSValue> result;
1919 if (parseBorderImageRepeat(result)) {
1920 addProperty(propId, result, important);
1925 case CSSPropertyBorderImageSlice:
1926 case CSSPropertyWebkitMaskBoxImageSlice: {
1927 RefPtr<CSSBorderImageSliceValue> result;
1928 if (parseBorderImageSlice(propId, result)) {
1929 addProperty(propId, result, important);
1934 case CSSPropertyBorderImageWidth:
1935 case CSSPropertyWebkitMaskBoxImageWidth: {
1936 RefPtr<CSSPrimitiveValue> result;
1937 if (parseBorderImageWidth(result)) {
1938 addProperty(propId, result, important);
1943 case CSSPropertyBorderTopRightRadius:
1944 case CSSPropertyBorderTopLeftRadius:
1945 case CSSPropertyBorderBottomLeftRadius:
1946 case CSSPropertyBorderBottomRightRadius: {
1947 if (num != 1 && num != 2)
1949 validPrimitive = validUnit(value, FLength | FPercent | FNonNeg);
1950 if (!validPrimitive)
1952 RefPtr<CSSPrimitiveValue> parsedValue1 = createPrimitiveNumericValue(value);
1953 RefPtr<CSSPrimitiveValue> parsedValue2;
1955 value = m_valueList->next();
1956 validPrimitive = validUnit(value, FLength | FPercent | FNonNeg);
1957 if (!validPrimitive)
1959 parsedValue2 = createPrimitiveNumericValue(value);
1961 parsedValue2 = parsedValue1;
1963 RefPtr<Pair> pair = Pair::create(parsedValue1.release(), parsedValue2.release());
1964 RefPtr<CSSPrimitiveValue> val = cssValuePool()->createValue(pair.release());
1965 addProperty(propId, val.release(), important);
1968 case CSSPropertyWebkitAspectRatio:
1969 return parseAspectRatio(important);
1970 case CSSPropertyBorderRadius:
1971 case CSSPropertyWebkitBorderRadius:
1972 return parseBorderRadius(propId, important);
1973 case CSSPropertyOutlineOffset:
1974 validPrimitive = validUnit(value, FLength | FPercent);
1976 case CSSPropertyTextShadow: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
1977 case CSSPropertyBoxShadow:
1978 case CSSPropertyWebkitBoxShadow:
1979 if (id == CSSValueNone)
1980 validPrimitive = true;
1982 RefPtr<CSSValueList> shadowValueList = parseShadow(m_valueList.get(), propId);
1983 if (shadowValueList) {
1984 addProperty(propId, shadowValueList.release(), important);
1985 m_valueList->next();
1991 case CSSPropertyWebkitBoxReflect:
1992 if (id == CSSValueNone)
1993 validPrimitive = true;
1995 return parseReflect(propId, important);
1997 case CSSPropertyOpacity:
1998 validPrimitive = validUnit(value, FNumber);
2000 case CSSPropertyWebkitBoxFlex:
2001 validPrimitive = validUnit(value, FNumber);
2003 case CSSPropertyWebkitBoxFlexGroup:
2004 case CSSPropertyWebkitBoxOrdinalGroup:
2005 validPrimitive = validUnit(value, FInteger | FNonNeg, CSSStrictMode);
2007 #if ENABLE(CSS_FILTERS)
2008 case CSSPropertyWebkitFilter:
2009 if (id == CSSValueNone)
2010 validPrimitive = true;
2012 RefPtr<CSSValue> val = parseFilter();
2014 addProperty(propId, val, important);
2021 case CSSPropertyWebkitFlex:
2022 if (id == CSSValueNone)
2023 validPrimitive = true;
2025 parsedValue = parseFlex(m_valueList.get());
2027 case CSSPropertyWebkitFlexOrder:
2028 if (validUnit(value, FInteger, CSSStrictMode)) {
2029 // 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.
2030 parsedValue = cssValuePool()->createValue(max(static_cast<double>(std::numeric_limits<int>::min() + 2), value->fValue),
2031 static_cast<CSSPrimitiveValue::UnitTypes>(value->unit));
2032 m_valueList->next();
2035 case CSSPropertyWebkitMarquee:
2036 return parseShorthand(propId, webkitMarqueeShorthand(), important);
2037 case CSSPropertyWebkitMarqueeIncrement:
2038 if (id == CSSValueSmall || id == CSSValueLarge || id == CSSValueMedium)
2039 validPrimitive = true;
2041 validPrimitive = validUnit(value, FLength | FPercent);
2043 case CSSPropertyWebkitMarqueeRepetition:
2044 if (id == CSSValueInfinite)
2045 validPrimitive = true;
2047 validPrimitive = validUnit(value, FInteger | FNonNeg);
2049 case CSSPropertyWebkitMarqueeSpeed:
2050 if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast)
2051 validPrimitive = true;
2053 validPrimitive = validUnit(value, FTime | FInteger | FNonNeg);
2055 case CSSPropertyWebkitFlowInto:
2056 if (!cssRegionsEnabled())
2058 return parseFlowThread(propId, important);
2059 case CSSPropertyWebkitFlowFrom:
2060 if (!cssRegionsEnabled())
2062 return parseRegionThread(propId, important);
2063 case CSSPropertyWebkitRegionOverflow:
2064 if (cssRegionsEnabled() && (id == CSSValueAuto || id == CSSValueBreak))
2065 validPrimitive = true;
2067 case CSSPropertyWebkitTransform:
2068 if (id == CSSValueNone)
2069 validPrimitive = true;
2071 PassRefPtr<CSSValue> val = parseTransform();
2073 addProperty(propId, val, important);
2079 case CSSPropertyWebkitTransformOrigin:
2080 case CSSPropertyWebkitTransformOriginX:
2081 case CSSPropertyWebkitTransformOriginY:
2082 case CSSPropertyWebkitTransformOriginZ: {
2083 RefPtr<CSSValue> val1;
2084 RefPtr<CSSValue> val2;
2085 RefPtr<CSSValue> val3;
2086 CSSPropertyID propId1, propId2, propId3;
2087 if (parseTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) {
2088 addProperty(propId1, val1.release(), important);
2090 addProperty(propId2, val2.release(), important);
2092 addProperty(propId3, val3.release(), important);
2097 case CSSPropertyWebkitPerspective:
2098 if (id == CSSValueNone)
2099 validPrimitive = true;
2101 // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property.
2102 if (validUnit(value, FNumber | FLength | FNonNeg)) {
2103 RefPtr<CSSValue> val = createPrimitiveNumericValue(value);
2105 addProperty(propId, val.release(), important);
2112 case CSSPropertyWebkitPerspectiveOrigin:
2113 case CSSPropertyWebkitPerspectiveOriginX:
2114 case CSSPropertyWebkitPerspectiveOriginY: {
2115 RefPtr<CSSValue> val1;
2116 RefPtr<CSSValue> val2;
2117 CSSPropertyID propId1, propId2;
2118 if (parsePerspectiveOrigin(propId, propId1, propId2, val1, val2)) {
2119 addProperty(propId1, val1.release(), important);
2121 addProperty(propId2, val2.release(), important);
2126 case CSSPropertyWebkitAnimationDelay:
2127 case CSSPropertyWebkitAnimationDirection:
2128 case CSSPropertyWebkitAnimationDuration:
2129 case CSSPropertyWebkitAnimationFillMode:
2130 case CSSPropertyWebkitAnimationName:
2131 case CSSPropertyWebkitAnimationPlayState:
2132 case CSSPropertyWebkitAnimationIterationCount:
2133 case CSSPropertyWebkitAnimationTimingFunction:
2134 case CSSPropertyWebkitTransitionDelay:
2135 case CSSPropertyWebkitTransitionDuration:
2136 case CSSPropertyWebkitTransitionTimingFunction:
2137 case CSSPropertyWebkitTransitionProperty: {
2138 RefPtr<CSSValue> val;
2139 if (parseAnimationProperty(propId, val)) {
2140 addProperty(propId, val.release(), important);
2145 #if ENABLE(CSS_GRID_LAYOUT)
2146 case CSSPropertyWebkitGridColumns:
2147 case CSSPropertyWebkitGridRows:
2148 return parseGridTrackList(propId, important);
2150 case CSSPropertyWebkitGridColumn:
2151 case CSSPropertyWebkitGridRow:
2152 validPrimitive = id == CSSValueAuto || validUnit(value, FInteger);
2155 case CSSPropertyWebkitMarginCollapse: {
2157 ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2158 if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important))
2160 CSSValue* value = m_parsedProperties.last().value();
2161 addProperty(webkitMarginCollapseShorthand().properties()[1], value, important);
2164 else if (num == 2) {
2165 ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2166 if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important) || !parseValue(webkitMarginCollapseShorthand().properties()[1], important))
2172 case CSSPropertyTextLineThroughWidth:
2173 case CSSPropertyTextOverlineWidth:
2174 case CSSPropertyTextUnderlineWidth:
2175 if (id == CSSValueAuto || id == CSSValueNormal || id == CSSValueThin ||
2176 id == CSSValueMedium || id == CSSValueThick)
2177 validPrimitive = true;
2179 validPrimitive = !id && validUnit(value, FNumber | FLength | FPercent);
2181 case CSSPropertyWebkitColumnCount:
2182 if (id == CSSValueAuto)
2183 validPrimitive = true;
2185 validPrimitive = !id && validUnit(value, FInteger | FNonNeg, CSSQuirksMode);
2187 case CSSPropertyWebkitColumnGap: // normal | <length>
2188 if (id == CSSValueNormal)
2189 validPrimitive = true;
2191 validPrimitive = validUnit(value, FLength | FNonNeg);
2193 case CSSPropertyWebkitColumnAxis:
2194 if (id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto)
2195 validPrimitive = true;
2197 case CSSPropertyWebkitColumnSpan: // all | 1
2198 if (id == CSSValueAll)
2199 validPrimitive = true;
2201 validPrimitive = validUnit(value, FNumber | FNonNeg) && value->fValue == 1;
2203 case CSSPropertyWebkitColumnWidth: // auto | <length>
2204 if (id == CSSValueAuto)
2205 validPrimitive = true;
2206 else // Always parse this property in strict mode, since it would be ambiguous otherwise when used in the 'columns' shorthand property.
2207 validPrimitive = validUnit(value, FLength, CSSStrictMode);
2209 // End of CSS3 properties
2211 // Apple specific properties. These will never be standardized and are purely to
2212 // support custom WebKit-based Apple applications.
2213 case CSSPropertyWebkitLineClamp:
2214 // When specifying number of lines, don't allow 0 as a valid value
2215 // When specifying either type of unit, require non-negative integers
2216 validPrimitive = (!id && (value->unit == CSSPrimitiveValue::CSS_PERCENTAGE || value->fValue) && validUnit(value, FInteger | FPercent | FNonNeg, CSSQuirksMode));
2219 case CSSPropertyWebkitFontSizeDelta: // <length>
2220 validPrimitive = validUnit(value, FLength);
2223 case CSSPropertyWebkitHighlight:
2224 if (id == CSSValueNone || value->unit == CSSPrimitiveValue::CSS_STRING)
2225 validPrimitive = true;
2228 case CSSPropertyWebkitHyphenateCharacter:
2229 if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
2230 validPrimitive = true;
2233 case CSSPropertyWebkitHyphenateLimitBefore:
2234 case CSSPropertyWebkitHyphenateLimitAfter:
2235 if (id == CSSValueAuto || validUnit(value, FInteger | FNonNeg, CSSStrictMode))
2236 validPrimitive = true;
2239 case CSSPropertyWebkitHyphenateLimitLines:
2240 if (id == CSSValueNoLimit || validUnit(value, FInteger | FNonNeg, CSSStrictMode))
2241 validPrimitive = true;
2244 case CSSPropertyWebkitLineGrid:
2245 if (id == CSSValueNone)
2246 validPrimitive = true;
2247 else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
2248 String lineGridValue = String(value->string);
2249 if (!lineGridValue.isEmpty()) {
2250 addProperty(propId, cssValuePool()->createValue(lineGridValue, CSSPrimitiveValue::CSS_STRING), important);
2255 case CSSPropertyWebkitLocale:
2256 if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
2257 validPrimitive = true;
2260 #if ENABLE(DASHBOARD_SUPPORT)
2261 case CSSPropertyWebkitDashboardRegion: // <dashboard-region> | <dashboard-region>
2262 if (value->unit == CSSParserValue::Function || id == CSSValueNone)
2263 return parseDashboardRegions(propId, important);
2266 // End Apple-specific properties
2268 #if ENABLE(TOUCH_EVENTS)
2269 case CSSPropertyWebkitTapHighlightColor:
2270 if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu
2271 || (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && inQuirksMode())) {
2272 validPrimitive = true;
2274 parsedValue = parseColor();
2276 m_valueList->next();
2281 /* shorthand properties */
2282 case CSSPropertyBackground: {
2283 // Position must come before color in this array because a plain old "0" is a legal color
2284 // in quirks mode but it's usually the X coordinate of a position.
2285 // FIXME: Add CSSPropertyBackgroundSize to the shorthand.
2286 const CSSPropertyID properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat,
2287 CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyBackgroundOrigin,
2288 CSSPropertyBackgroundClip, CSSPropertyBackgroundColor };
2289 return parseFillShorthand(propId, properties, 7, important);
2291 case CSSPropertyWebkitMask: {
2292 const CSSPropertyID properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
2293 CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition,
2294 CSSPropertyWebkitMaskOrigin, CSSPropertyWebkitMaskClip };
2295 return parseFillShorthand(propId, properties, 6, important);
2297 case CSSPropertyBorder:
2298 // [ 'border-width' || 'border-style' || <color> ] | inherit
2300 if (parseShorthand(propId, borderAbridgedShorthand(), important)) {
2301 // The CSS3 Borders and Backgrounds specification says that border also resets border-image. It's as
2302 // though a value of none was specified for the image.
2303 addProperty(CSSPropertyBorderImage, cssValuePool()->createImplicitInitialValue(), important);
2308 case CSSPropertyBorderTop:
2309 // [ 'border-top-width' || 'border-style' || <color> ] | inherit
2310 return parseShorthand(propId, borderTopShorthand(), important);
2311 case CSSPropertyBorderRight:
2312 // [ 'border-right-width' || 'border-style' || <color> ] | inherit
2313 return parseShorthand(propId, borderRightShorthand(), important);
2314 case CSSPropertyBorderBottom:
2315 // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
2316 return parseShorthand(propId, borderBottomShorthand(), important);
2317 case CSSPropertyBorderLeft:
2318 // [ 'border-left-width' || 'border-style' || <color> ] | inherit
2319 return parseShorthand(propId, borderLeftShorthand(), important);
2320 case CSSPropertyWebkitBorderStart:
2321 return parseShorthand(propId, webkitBorderStartShorthand(), important);
2322 case CSSPropertyWebkitBorderEnd:
2323 return parseShorthand(propId, webkitBorderEndShorthand(), important);
2324 case CSSPropertyWebkitBorderBefore:
2325 return parseShorthand(propId, webkitBorderBeforeShorthand(), important);
2326 case CSSPropertyWebkitBorderAfter:
2327 return parseShorthand(propId, webkitBorderAfterShorthand(), important);
2328 case CSSPropertyOutline:
2329 // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
2330 return parseShorthand(propId, outlineShorthand(), important);
2331 case CSSPropertyBorderColor:
2332 // <color>{1,4} | inherit
2333 return parse4Values(propId, borderColorShorthand().properties(), important);
2334 case CSSPropertyBorderWidth:
2335 // <border-width>{1,4} | inherit
2336 return parse4Values(propId, borderWidthShorthand().properties(), important);
2337 case CSSPropertyBorderStyle:
2338 // <border-style>{1,4} | inherit
2339 return parse4Values(propId, borderStyleShorthand().properties(), important);
2340 case CSSPropertyMargin:
2341 // <margin-width>{1,4} | inherit
2342 return parse4Values(propId, marginShorthand().properties(), important);
2343 case CSSPropertyPadding:
2344 // <padding-width>{1,4} | inherit
2345 return parse4Values(propId, paddingShorthand().properties(), important);
2346 case CSSPropertyWebkitFlexFlow:
2347 return parseShorthand(propId, webkitFlexFlowShorthand(), important);
2348 case CSSPropertyFont:
2349 // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
2350 // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
2351 if (id >= CSSValueCaption && id <= CSSValueStatusBar)
2352 validPrimitive = true;
2354 return parseFont(important);
2356 case CSSPropertyListStyle:
2357 return parseShorthand(propId, listStyleShorthand(), important);
2358 case CSSPropertyWebkitColumns:
2359 return parseShorthand(propId, webkitColumnsShorthand(), important);
2360 case CSSPropertyWebkitColumnRule:
2361 return parseShorthand(propId, webkitColumnRuleShorthand(), important);
2362 case CSSPropertyWebkitTextStroke:
2363 return parseShorthand(propId, webkitTextStrokeShorthand(), important);
2364 case CSSPropertyWebkitAnimation:
2365 return parseAnimationShorthand(important);
2366 case CSSPropertyWebkitTransition:
2367 return parseTransitionShorthand(important);
2368 case CSSPropertyInvalid:
2370 case CSSPropertyPage:
2371 return parsePage(propId, important);
2372 case CSSPropertyFontStretch:
2373 case CSSPropertyTextLineThrough:
2374 case CSSPropertyTextOverline:
2375 case CSSPropertyTextUnderline:
2377 // CSS Text Layout Module Level 3: Vertical writing support
2378 case CSSPropertyWebkitTextEmphasis:
2379 return parseShorthand(propId, webkitTextEmphasisShorthand(), important);
2381 case CSSPropertyWebkitTextEmphasisStyle:
2382 return parseTextEmphasisStyle(important);
2384 case CSSPropertyWebkitTextOrientation:
2385 // FIXME: For now just support upright and vertical-right.
2386 if (id == CSSValueVerticalRight || id == CSSValueUpright)
2387 validPrimitive = true;
2390 case CSSPropertyWebkitLineBoxContain:
2391 if (id == CSSValueNone)
2392 validPrimitive = true;
2394 return parseLineBoxContain(important);
2396 case CSSPropertyWebkitFontFeatureSettings:
2397 if (id == CSSValueNormal)
2398 validPrimitive = true;
2400 return parseFontFeatureSettings(important);
2403 case CSSPropertyWebkitFontVariantLigatures:
2404 if (id == CSSValueNormal)
2405 validPrimitive = true;
2407 return parseFontVariantLigatures(important);
2410 case CSSPropertyWebkitShapeInside:
2411 case CSSPropertyWebkitShapeOutside:
2412 if (id == CSSValueAuto)
2413 validPrimitive = true;
2414 else if (value->unit == CSSParserValue::Function)
2415 return parseExclusionShape((propId == CSSPropertyWebkitShapeInside), important);
2417 case CSSPropertyWebkitWrapMargin:
2418 case CSSPropertyWebkitWrapPadding:
2419 validPrimitive = (!id && validUnit(value, FLength | FNonNeg));
2421 case CSSPropertyWebkitWrap:
2422 return parseShorthand(propId, webkitWrapShorthand(), important);
2423 case CSSPropertyBorderBottomStyle:
2424 case CSSPropertyBorderCollapse:
2425 case CSSPropertyBorderLeftStyle:
2426 case CSSPropertyBorderRightStyle:
2427 case CSSPropertyBorderTopStyle:
2428 case CSSPropertyBoxSizing:
2429 case CSSPropertyCaptionSide:
2430 case CSSPropertyClear:
2431 case CSSPropertyDirection:
2432 case CSSPropertyDisplay:
2433 case CSSPropertyEmptyCells:
2434 case CSSPropertyFloat:
2435 case CSSPropertyFontStyle:
2436 case CSSPropertyImageRendering:
2437 case CSSPropertyListStylePosition:
2438 case CSSPropertyListStyleType:
2439 case CSSPropertyOutlineStyle:
2440 case CSSPropertyOverflowX:
2441 case CSSPropertyOverflowY:
2442 case CSSPropertyPointerEvents:
2443 case CSSPropertyPosition:
2444 case CSSPropertyResize:
2445 case CSSPropertySpeak:
2446 case CSSPropertyTableLayout:
2447 case CSSPropertyTextLineThroughMode:
2448 case CSSPropertyTextLineThroughStyle:
2449 case CSSPropertyTextOverflow:
2450 case CSSPropertyTextOverlineMode:
2451 case CSSPropertyTextOverlineStyle:
2452 case CSSPropertyTextRendering:
2453 case CSSPropertyTextTransform:
2454 case CSSPropertyTextUnderlineMode:
2455 case CSSPropertyTextUnderlineStyle:
2456 case CSSPropertyVisibility:
2457 case CSSPropertyWebkitAppearance:
2458 case CSSPropertyWebkitBackfaceVisibility:
2459 case CSSPropertyWebkitBorderAfterStyle:
2460 case CSSPropertyWebkitBorderBeforeStyle:
2461 case CSSPropertyWebkitBorderEndStyle:
2462 case CSSPropertyWebkitBorderFit:
2463 case CSSPropertyWebkitBorderStartStyle:
2464 case CSSPropertyWebkitBoxAlign:
2465 case CSSPropertyWebkitBoxDirection:
2466 case CSSPropertyWebkitBoxLines:
2467 case CSSPropertyWebkitBoxOrient:
2468 case CSSPropertyWebkitBoxPack:
2469 case CSSPropertyWebkitColorCorrection:
2470 case CSSPropertyWebkitColumnRuleStyle:
2471 case CSSPropertyWebkitFlexAlign:
2472 case CSSPropertyWebkitFlexDirection:
2473 case CSSPropertyWebkitFlexItemAlign:
2474 case CSSPropertyWebkitFlexLinePack:
2475 case CSSPropertyWebkitFlexPack:
2476 case CSSPropertyWebkitFlexWrap:
2477 case CSSPropertyWebkitFontKerning:
2478 case CSSPropertyWebkitFontSmoothing:
2479 case CSSPropertyWebkitHyphens:
2480 case CSSPropertyWebkitLineAlign:
2481 case CSSPropertyWebkitLineBreak:
2482 case CSSPropertyWebkitLineSnap:
2483 case CSSPropertyWebkitMarginAfterCollapse:
2484 case CSSPropertyWebkitMarginBeforeCollapse:
2485 case CSSPropertyWebkitMarginBottomCollapse:
2486 case CSSPropertyWebkitMarginTopCollapse:
2487 case CSSPropertyWebkitMarqueeDirection:
2488 case CSSPropertyWebkitMarqueeStyle:
2489 case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
2490 case CSSPropertyWebkitNbspMode:
2491 #if ENABLE(OVERFLOW_SCROLLING)
2492 case CSSPropertyWebkitOverflowScrolling:
2494 case CSSPropertyWebkitPrintColorAdjust:
2495 case CSSPropertyWebkitRtlOrdering:
2496 case CSSPropertyWebkitTextCombine:
2497 case CSSPropertyWebkitTextEmphasisPosition:
2498 case CSSPropertyWebkitTextSecurity:
2499 case CSSPropertyWebkitTextSizeAdjust:
2500 case CSSPropertyWebkitTransformStyle:
2501 case CSSPropertyWebkitUserDrag:
2502 case CSSPropertyWebkitUserModify:
2503 case CSSPropertyWebkitUserSelect:
2504 case CSSPropertyWebkitWrapFlow:
2505 case CSSPropertyWebkitWrapThrough:
2506 case CSSPropertyWebkitWritingMode:
2507 case CSSPropertyWhiteSpace:
2508 case CSSPropertyWordBreak:
2509 case CSSPropertyWordWrap:
2510 // These properties should be handled before in isValidKeywordPropertyAndValue().
2511 ASSERT_NOT_REACHED();
2515 return parseSVGValue(propId, important);
2519 if (validPrimitive) {
2520 parsedValue = parseValidPrimitive(id, value);
2521 m_valueList->next();
2523 ASSERT(!m_parsedCalculation);
2525 if (!m_valueList->current() || inShorthand()) {
2526 addProperty(propId, parsedValue.release(), important);
2533 void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
2536 if (lval->isValueList())
2537 static_cast<CSSValueList*>(lval.get())->append(rval);
2539 PassRefPtr<CSSValue> oldlVal(lval.release());
2540 PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2541 list->append(oldlVal);
2550 static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue, CSSValuePool* cssValuePool)
2552 if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox
2553 || parserValue->id == CSSValueContentBox || parserValue->id == CSSValueWebkitText) {
2554 cssValue = cssValuePool->createIdentifierValue(parserValue->id);
2560 const int cMaxFillProperties = 9;
2562 bool CSSParser::parseFillShorthand(CSSPropertyID propId, const CSSPropertyID* properties, int numProperties, bool important)
2564 ASSERT(numProperties <= cMaxFillProperties);
2565 if (numProperties > cMaxFillProperties)
2568 ShorthandScope scope(this, propId);
2570 bool parsedProperty[cMaxFillProperties] = { false };
2571 RefPtr<CSSValue> values[cMaxFillProperties];
2572 RefPtr<CSSValue> clipValue;
2573 RefPtr<CSSValue> positionYValue;
2574 RefPtr<CSSValue> repeatYValue;
2575 bool foundClip = false;
2578 while (m_valueList->current()) {
2579 CSSParserValue* val = m_valueList->current();
2580 if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2581 // We hit the end. Fill in all remaining values with the initial value.
2582 m_valueList->next();
2583 for (i = 0; i < numProperties; ++i) {
2584 if (properties[i] == CSSPropertyBackgroundColor && parsedProperty[i])
2585 // Color is not allowed except as the last item in a list for backgrounds.
2586 // Reject the entire property.
2589 if (!parsedProperty[i] && properties[i] != CSSPropertyBackgroundColor) {
2590 addFillValue(values[i], cssValuePool()->createImplicitInitialValue());
2591 if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2592 addFillValue(positionYValue, cssValuePool()->createImplicitInitialValue());
2593 if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2594 addFillValue(repeatYValue, cssValuePool()->createImplicitInitialValue());
2595 if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
2596 // If background-origin wasn't present, then reset background-clip also.
2597 addFillValue(clipValue, cssValuePool()->createImplicitInitialValue());
2600 parsedProperty[i] = false;
2602 if (!m_valueList->current())
2607 for (i = 0; !found && i < numProperties; ++i) {
2608 if (!parsedProperty[i]) {
2609 RefPtr<CSSValue> val1;
2610 RefPtr<CSSValue> val2;
2611 CSSPropertyID propId1, propId2;
2612 CSSParserValue* parserValue = m_valueList->current();
2613 if (parseFillProperty(properties[i], propId1, propId2, val1, val2)) {
2614 parsedProperty[i] = found = true;
2615 addFillValue(values[i], val1.release());
2616 if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2617 addFillValue(positionYValue, val2.release());
2618 if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2619 addFillValue(repeatYValue, val2.release());
2620 if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
2621 // Reparse the value as a clip, and see if we succeed.
2622 if (parseBackgroundClip(parserValue, val1, cssValuePool()))
2623 addFillValue(clipValue, val1.release()); // The property parsed successfully.
2625 addFillValue(clipValue, cssValuePool()->createImplicitInitialValue()); // Some value was used for origin that is not supported by clip. Just reset clip instead.
2627 if (properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) {
2629 addFillValue(clipValue, val1.release());
2636 // if we didn't find at least one match, this is an
2637 // invalid shorthand and we have to ignore it
2642 // Now add all of the properties we found.
2643 for (i = 0; i < numProperties; i++) {
2644 // Fill in any remaining properties with the initial value.
2645 if (!parsedProperty[i]) {
2646 addFillValue(values[i], cssValuePool()->createImplicitInitialValue());
2647 if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2648 addFillValue(positionYValue, cssValuePool()->createImplicitInitialValue());
2649 if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2650 addFillValue(repeatYValue, cssValuePool()->createImplicitInitialValue());
2651 if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin)) {
2652 // If background-origin wasn't present, then reset background-clip also.
2653 addFillValue(clipValue, cssValuePool()->createImplicitInitialValue());
2656 if (properties[i] == CSSPropertyBackgroundPosition) {
2657 addProperty(CSSPropertyBackgroundPositionX, values[i].release(), important);
2658 // it's OK to call positionYValue.release() since we only see CSSPropertyBackgroundPosition once
2659 addProperty(CSSPropertyBackgroundPositionY, positionYValue.release(), important);
2660 } else if (properties[i] == CSSPropertyWebkitMaskPosition) {
2661 addProperty(CSSPropertyWebkitMaskPositionX, values[i].release(), important);
2662 // it's OK to call positionYValue.release() since we only see CSSPropertyWebkitMaskPosition once
2663 addProperty(CSSPropertyWebkitMaskPositionY, positionYValue.release(), important);
2664 } else if (properties[i] == CSSPropertyBackgroundRepeat) {
2665 addProperty(CSSPropertyBackgroundRepeatX, values[i].release(), important);
2666 // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2667 addProperty(CSSPropertyBackgroundRepeatY, repeatYValue.release(), important);
2668 } else if (properties[i] == CSSPropertyWebkitMaskRepeat) {
2669 addProperty(CSSPropertyWebkitMaskRepeatX, values[i].release(), important);
2670 // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2671 addProperty(CSSPropertyWebkitMaskRepeatY, repeatYValue.release(), important);
2672 } else if ((properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) && !foundClip)
2673 // Value is already set while updating origin
2676 addProperty(properties[i], values[i].release(), important);
2678 // Add in clip values when we hit the corresponding origin property.
2679 if (properties[i] == CSSPropertyBackgroundOrigin && !foundClip)
2680 addProperty(CSSPropertyBackgroundClip, clipValue.release(), important);
2681 else if (properties[i] == CSSPropertyWebkitMaskOrigin && !foundClip)
2682 addProperty(CSSPropertyWebkitMaskClip, clipValue.release(), important);
2688 void CSSParser::addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
2691 if (lval->isValueList())
2692 static_cast<CSSValueList*>(lval.get())->append(rval);
2694 PassRefPtr<CSSValue> oldVal(lval.release());
2695 PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2696 list->append(oldVal);
2705 bool CSSParser::parseAnimationShorthand(bool important)
2707 const unsigned numProperties = webkitAnimationShorthand().length();
2708 ShorthandScope scope(this, CSSPropertyWebkitAnimation);
2710 bool parsedProperty[] = { false, false, false, false, false, false, false };
2711 RefPtr<CSSValue> values[7];
2714 unsigned initialParsedPropertyIndex = 0;
2715 while (m_valueList->current()) {
2716 CSSParserValue* val = m_valueList->current();
2717 if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2718 // We hit the end. Fill in all remaining values with the initial value.
2719 initialParsedPropertyIndex = 0;
2720 m_valueList->next();
2721 for (i = 0; i < numProperties; ++i) {
2722 if (!parsedProperty[i])
2723 addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
2724 parsedProperty[i] = false;
2726 if (!m_valueList->current())
2731 for (i = initialParsedPropertyIndex; !found && i < numProperties; ++i) {
2732 if (!parsedProperty[i]) {
2733 RefPtr<CSSValue> val;
2734 if (parseAnimationProperty(webkitAnimationShorthand().properties()[i], val)) {
2735 parsedProperty[i] = found = true;
2736 initialParsedPropertyIndex = 1;
2737 addAnimationValue(values[i], val.release());
2742 // if we didn't find at least one match, this is an
2743 // invalid shorthand and we have to ignore it
2748 // Fill in any remaining properties with the initial value.
2749 for (i = 0; i < numProperties; ++i) {
2750 if (!parsedProperty[i])
2751 addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
2754 // Now add all of the properties we found.
2755 for (i = 0; i < numProperties; i++)
2756 addProperty(webkitAnimationShorthand().properties()[i], values[i].release(), important);
2761 bool CSSParser::parseTransitionShorthand(bool important)
2763 const unsigned numProperties = webkitTransitionShorthand().length();
2765 ShorthandScope scope(this, CSSPropertyWebkitTransition);
2767 bool parsedProperty[] = { false, false, false, false };
2768 RefPtr<CSSValue> values[4];
2771 while (m_valueList->current()) {
2772 CSSParserValue* val = m_valueList->current();
2773 if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2774 // We hit the end. Fill in all remaining values with the initial value.
2775 m_valueList->next();
2776 for (i = 0; i < numProperties; ++i) {
2777 if (!parsedProperty[i])
2778 addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
2779 parsedProperty[i] = false;
2781 if (!m_valueList->current())
2786 for (i = 0; !found && i < numProperties; ++i) {
2787 if (!parsedProperty[i]) {
2788 RefPtr<CSSValue> val;
2789 if (parseAnimationProperty(webkitTransitionShorthand().properties()[i], val)) {
2790 parsedProperty[i] = found = true;
2791 addAnimationValue(values[i], val.release());
2796 // if we didn't find at least one match, this is an
2797 // invalid shorthand and we have to ignore it
2802 // Fill in any remaining properties with the initial value.
2803 for (i = 0; i < numProperties; ++i) {
2804 if (!parsedProperty[i])
2805 addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
2808 // Now add all of the properties we found.
2809 for (i = 0; i < numProperties; i++)
2810 addProperty(webkitTransitionShorthand().properties()[i], values[i].release(), important);
2815 bool CSSParser::parseShorthand(CSSPropertyID propId, const StylePropertyShorthand& shorthand, bool important)
2817 // We try to match as many properties as possible
2818 // We set up an array of booleans to mark which property has been found,
2819 // and we try to search for properties until it makes no longer any sense.
2820 ShorthandScope scope(this, propId);
2823 unsigned propertiesParsed = 0;
2824 bool propertyFound[6]= { false, false, false, false, false, false }; // 6 is enough size.
2826 while (m_valueList->current()) {
2828 for (unsigned propIndex = 0; !found && propIndex < shorthand.length(); ++propIndex) {
2829 if (!propertyFound[propIndex] && parseValue(shorthand.properties()[propIndex], important)) {
2830 propertyFound[propIndex] = found = true;
2835 // if we didn't find at least one match, this is an
2836 // invalid shorthand and we have to ignore it
2841 if (propertiesParsed == shorthand.length())
2844 // Fill in any remaining properties with the initial value.
2845 ImplicitScope implicitScope(this, PropertyImplicit);
2846 const StylePropertyShorthand* const* const propertiesForInitialization = shorthand.propertiesForInitialization();
2847 for (unsigned i = 0; i < shorthand.length(); ++i) {
2848 if (propertyFound[i])
2851 if (propertiesForInitialization) {
2852 const StylePropertyShorthand& initProperties = *(propertiesForInitialization[i]);
2853 for (unsigned propIndex = 0; propIndex < initProperties.length(); ++propIndex)
2854 addProperty(initProperties.properties()[propIndex], cssValuePool()->createImplicitInitialValue(), important);
2856 addProperty(shorthand.properties()[i], cssValuePool()->createImplicitInitialValue(), important);
2862 bool CSSParser::parse4Values(CSSPropertyID propId, const CSSPropertyID *properties, bool important)
2864 /* From the CSS 2 specs, 8.3
2865 * If there is only one value, it applies to all sides. If there are two values, the top and
2866 * bottom margins are set to the first value and the right and left margins are set to the second.
2867 * If there are three values, the top is set to the first value, the left and right are set to the
2868 * second, and the bottom is set to the third. If there are four values, they apply to the top,
2869 * right, bottom, and left, respectively.
2872 int num = inShorthand() ? 1 : m_valueList->size();
2874 ShorthandScope scope(this, propId);
2876 // the order is top, right, bottom, left
2879 if (!parseValue(properties[0], important))
2881 CSSValue *value = m_parsedProperties.last().value();
2882 ImplicitScope implicitScope(this, PropertyImplicit);
2883 addProperty(properties[1], value, important);
2884 addProperty(properties[2], value, important);
2885 addProperty(properties[3], value, important);
2889 if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
2891 CSSValue *value = m_parsedProperties[m_parsedProperties.size() - 2].value();
2892 ImplicitScope implicitScope(this, PropertyImplicit);
2893 addProperty(properties[2], value, important);
2894 value = m_parsedProperties[m_parsedProperties.size() - 2].value();
2895 addProperty(properties[3], value, important);
2899 if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
2901 CSSValue *value = m_parsedProperties[m_parsedProperties.size() - 2].value();
2902 ImplicitScope implicitScope(this, PropertyImplicit);
2903 addProperty(properties[3], value, important);
2907 if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
2908 !parseValue(properties[2], important) || !parseValue(properties[3], important))
2920 // auto | <identifier>
2921 bool CSSParser::parsePage(CSSPropertyID propId, bool important)
2923 ASSERT(propId == CSSPropertyPage);
2925 if (m_valueList->size() != 1)
2928 CSSParserValue* value = m_valueList->current();
2932 if (value->id == CSSValueAuto) {
2933 addProperty(propId, cssValuePool()->createIdentifierValue(value->id), important);
2935 } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) {
2936 addProperty(propId, createPrimitiveStringValue(value), important);
2942 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
2943 bool CSSParser::parseSize(CSSPropertyID propId, bool important)
2945 ASSERT(propId == CSSPropertySize);
2947 if (m_valueList->size() > 2)
2950 CSSParserValue* value = m_valueList->current();
2954 RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
2957 SizeParameterType paramType = parseSizeParameter(parsedValues.get(), value, None);
2958 if (paramType == None)
2961 // Second parameter, if any.
2962 value = m_valueList->next();
2964 paramType = parseSizeParameter(parsedValues.get(), value, paramType);
2965 if (paramType == None)
2969 addProperty(propId, parsedValues.release(), important);
2973 CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType)
2975 switch (value->id) {
2977 if (prevParamType == None) {
2978 parsedValues->append(cssValuePool()->createIdentifierValue(value->id));
2982 case CSSValueLandscape:
2983 case CSSValuePortrait:
2984 if (prevParamType == None || prevParamType == PageSize) {
2985 parsedValues->append(cssValuePool()->createIdentifierValue(value->id));
2994 case CSSValueLedger:
2996 case CSSValueLetter:
2997 if (prevParamType == None || prevParamType == Orientation) {
2998 // Normalize to Page Size then Orientation order by prepending.
2999 // This is not specified by the CSS3 Paged Media specification, but for simpler processing later (CSSStyleSelector::applyPageSizeProperty).
3000 parsedValues->prepend(cssValuePool()->createIdentifierValue(value->id));
3005 if (validUnit(value, FLength | FNonNeg) && (prevParamType == None || prevParamType == Length)) {
3006 parsedValues->append(createPrimitiveNumericValue(value));
3015 // [ <string> <string> ]+ | inherit | none
3016 // inherit and none are handled in parseValue.
3017 bool CSSParser::parseQuotes(CSSPropertyID propId, bool important)
3019 RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3020 while (CSSParserValue* val = m_valueList->current()) {
3021 RefPtr<CSSValue> parsedValue;
3022 if (val->unit == CSSPrimitiveValue::CSS_STRING)
3023 parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING);
3026 values->append(parsedValue.release());
3027 m_valueList->next();
3029 if (values->length()) {
3030 addProperty(propId, values.release(), important);
3031 m_valueList->next();
3037 // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
3038 // in CSS 2.1 this got somewhat reduced:
3039 // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
3040 bool CSSParser::parseContent(CSSPropertyID propId, bool important)
3042 RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3044 while (CSSParserValue* val = m_valueList->current()) {
3045 RefPtr<CSSValue> parsedValue;
3046 if (val->unit == CSSPrimitiveValue::CSS_URI && m_styleSheet) {
3048 // FIXME: The completeURL call should be done when using the CSSImageValue,
3049 // not when creating it.
3050 parsedValue = CSSImageValue::create(m_styleSheet->completeURL(val->string));
3051 } else if (val->unit == CSSParserValue::Function) {
3052 // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) | -webkit-gradient(...)
3053 CSSParserValueList* args = val->function->args.get();
3056 if (equalIgnoringCase(val->function->name, "attr(")) {
3057 parsedValue = parseAttr(args);
3060 } else if (equalIgnoringCase(val->function->name, "counter(")) {
3061 parsedValue = parseCounterContent(args, false);
3064 } else if (equalIgnoringCase(val->function->name, "counters(")) {
3065 parsedValue = parseCounterContent(args, true);
3068 #if ENABLE(CSS_IMAGE_SET)
3069 } else if (equalIgnoringCase(val->function->name, "-webkit-image-set(")) {
3070 parsedValue = parseImageSet(m_valueList.get());
3074 } else if (isGeneratedImageValue(val)) {
3075 if (!parseGeneratedImage(m_valueList.get(), parsedValue))
3079 } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
3085 // FIXME: These are not yet implemented (http://bugs.webkit.org/show_bug.cgi?id=6503).
3089 case CSSValueOpenQuote:
3090 case CSSValueCloseQuote:
3091 case CSSValueNoOpenQuote:
3092 case CSSValueNoCloseQuote:
3094 case CSSValueNormal:
3095 parsedValue = cssValuePool()->createIdentifierValue(val->id);
3097 } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
3098 parsedValue = createPrimitiveStringValue(val);
3102 values->append(parsedValue.release());
3103 m_valueList->next();
3106 if (values->length()) {
3107 addProperty(propId, values.release(), important);
3108 m_valueList->next();
3115 PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args)
3117 if (args->size() != 1)
3120 CSSParserValue* a = args->current();
3122 if (a->unit != CSSPrimitiveValue::CSS_IDENT)
3125 String attrName = a->string;
3126 // CSS allows identifiers with "-" at the start, like "-webkit-mask-image".
3127 // But HTML attribute names can't have those characters, and we should not
3128 // even parse them inside attr().
3129 if (attrName[0] == '-')
3132 Document* document = findDocument();
3133 if (document && document->isHTMLDocument())
3134 attrName = attrName.lower();
3136 return cssValuePool()->createValue(attrName, CSSPrimitiveValue::CSS_ATTR);
3139 PassRefPtr<CSSValue> CSSParser::parseBackgroundColor()
3141 int id = m_valueList->current()->id;
3142 if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor ||
3143 (id >= CSSValueGrey && id < CSSValueWebkitText && inQuirksMode()))
3144 return cssValuePool()->createIdentifierValue(id);
3145 return parseColor();
3148 bool CSSParser::parseFillImage(CSSParserValueList* valueList, RefPtr<CSSValue>& value)
3150 if (valueList->current()->id == CSSValueNone) {
3151 value = cssValuePool()->createIdentifierValue(CSSValueNone);
3154 if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
3155 // FIXME: The completeURL call should be done when using the CSSImageValue,
3156 // not when creating it.
3158 value = CSSImageValue::create(m_styleSheet->completeURL(valueList->current()->string));
3162 if (isGeneratedImageValue(valueList->current()))
3163 return parseGeneratedImage(valueList, value);
3165 #if ENABLE(CSS_IMAGE_SET)
3166 if (valueList->current()->unit == CSSParserValue::Function && equalIgnoringCase(valueList->current()->function->name, "-webkit-image-set(")) {
3167 value = parseImageSet(m_valueList.get());
3176 PassRefPtr<CSSValue> CSSParser::parseFillPositionX(CSSParserValueList* valueList)
3178 int id = valueList->current()->id;
3179 if (id == CSSValueLeft || id == CSSValueRight || id == CSSValueCenter) {
3181 if (id == CSSValueRight)
3183 else if (id == CSSValueCenter)
3185 return cssValuePool()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3187 if (validUnit(valueList->current(), FPercent | FLength))
3188 return createPrimitiveNumericValue(valueList->current());
3192 PassRefPtr<CSSValue> CSSParser::parseFillPositionY(CSSParserValueList* valueList)
3194 int id = valueList->current()->id;
3195 if (id == CSSValueTop || id == CSSValueBottom || id == CSSValueCenter) {
3197 if (id == CSSValueBottom)
3199 else if (id == CSSValueCenter)
3201 return cssValuePool()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3203 if (validUnit(valueList->current(), FPercent | FLength))
3204 return createPrimitiveNumericValue(valueList->current());
3208 PassRefPtr<CSSValue> CSSParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag)
3210 int id = valueList->current()->id;
3211 if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
3213 if (id == CSSValueLeft || id == CSSValueRight) {
3214 if (cumulativeFlags & XFillPosition)
3216 cumulativeFlags |= XFillPosition;
3217 individualFlag = XFillPosition;
3218 if (id == CSSValueRight)
3221 else if (id == CSSValueTop || id == CSSValueBottom) {
3222 if (cumulativeFlags & YFillPosition)
3224 cumulativeFlags |= YFillPosition;
3225 individualFlag = YFillPosition;
3226 if (id == CSSValueBottom)
3228 } else if (id == CSSValueCenter) {
3229 // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
3231 cumulativeFlags |= AmbiguousFillPosition;
3232 individualFlag = AmbiguousFillPosition;
3234 return cssValuePool()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3236 if (validUnit(valueList->current(), FPercent | FLength)) {
3237 if (!cumulativeFlags) {
3238 cumulativeFlags |= XFillPosition;
3239 individualFlag = XFillPosition;
3240 } else if (cumulativeFlags & (XFillPosition | AmbiguousFillPosition)) {
3241 cumulativeFlags |= YFillPosition;
3242 individualFlag = YFillPosition;
3244 if (m_parsedCalculation)
3245 m_parsedCalculation.release();
3248 return createPrimitiveNumericValue(valueList->current());
3253 void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
3255 CSSParserValue* value = valueList->current();
3257 // Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length.
3258 unsigned cumulativeFlags = 0;
3259 FillPositionFlag value1Flag = InvalidFillPosition;
3260 FillPositionFlag value2Flag = InvalidFillPosition;
3261 value1 = parseFillPositionComponent(valueList, cumulativeFlags, value1Flag);
3265 // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
3266 // can assume that any other values belong to the rest of the shorthand). If we're not parsing a shorthand, though, the
3267 // value was explicitly specified for our property.
3268 value = valueList->next();
3270 // First check for the comma. If so, we are finished parsing this value or value pair.
3275 value2 = parseFillPositionComponent(valueList, cumulativeFlags, value2Flag);
3279 if (!inShorthand()) {
3287 // Only one value was specified. If that value was not a keyword, then it sets the x position, and the y position
3288 // is simply 50%. This is our default.
3289 // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
3290 // For left/right/center, the default of 50% in the y is still correct.
3291 value2 = cssValuePool()->createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
3293 if (value1Flag == YFillPosition || value2Flag == XFillPosition)
3294 value1.swap(value2);
3297 void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
3299 CSSParserValue* value = m_valueList->current();
3301 int id = m_valueList->current()->id;
3302 if (id == CSSValueRepeatX) {
3303 m_implicitShorthand = true;
3304 value1 = cssValuePool()->createIdentifierValue(CSSValueRepeat);
3305 value2 = cssValuePool()->createIdentifierValue(CSSValueNoRepeat);
3306 m_valueList->next();
3309 if (id == CSSValueRepeatY) {
3310 m_implicitShorthand = true;
3311 value1 = cssValuePool()->createIdentifierValue(CSSValueNoRepeat);
3312 value2 = cssValuePool()->createIdentifierValue(CSSValueRepeat);
3313 m_valueList->next();
3316 if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)
3317 value1 = cssValuePool()->createIdentifierValue(id);
3323 value = m_valueList->next();
3325 // First check for the comma. If so, we are finished parsing this value or value pair.
3330 id = m_valueList->current()->id;
3332 if (value && (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)) {
3333 value2 = cssValuePool()->createIdentifierValue(id);
3334 m_valueList->next();
3336 // If only one value was specified, value2 is the same as value1.
3337 m_implicitShorthand = true;
3338 value2 = cssValuePool()->createIdentifierValue(static_cast<CSSPrimitiveValue*>(value1.get())->getIdent());
3342 PassRefPtr<CSSValue> CSSParser::parseFillSize(CSSPropertyID propId, bool& allowComma)
3345 CSSParserValue* value = m_valueList->current();
3347 if (value->id == CSSValueContain || value->id == CSSValueCover)
3348 return cssValuePool()->createIdentifierValue(value->id);
3350 RefPtr<CSSPrimitiveValue> parsedValue1;
3352 if (value->id == CSSValueAuto)
3353 parsedValue1 = cssValuePool()->createIdentifierValue(CSSValueAuto);
3355 if (!validUnit(value, FLength | FPercent))
3357 parsedValue1 = createPrimitiveNumericValue(value);
3360 RefPtr<CSSPrimitiveValue> parsedValue2;
3361 if ((value = m_valueList->next())) {
3362 if (value->unit == CSSParserValue::Operator && value->iValue == ',')
3364 else if (value->id != CSSValueAuto) {
3365 if (!validUnit(value, FLength | FPercent))
3367 parsedValue2 = createPrimitiveNumericValue(value);
3369 } else if (!parsedValue2 && propId == CSSPropertyWebkitBackgroundSize) {
3370 // For backwards compatibility we set the second value to the first if it is omitted.
3371 // We only need to do this for -webkit-background-size. It should be safe to let masks match