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 "CSSFlexValue.h"
35 #include "CSSFontFaceRule.h"
36 #include "CSSFontFaceSrcValue.h"
37 #include "CSSFunctionValue.h"
38 #include "CSSGradientValue.h"
39 #if ENABLE(CSS_IMAGE_SET)
40 #include "CSSImageSetValue.h"
42 #include "CSSImageValue.h"
43 #include "CSSImportRule.h"
44 #include "CSSInheritedValue.h"
45 #include "CSSInitialValue.h"
46 #include "CSSLineBoxContainValue.h"
47 #include "CSSMediaRule.h"
48 #include "CSSPageRule.h"
49 #include "CSSPrimitiveValue.h"
50 #include "CSSProperty.h"
51 #include "CSSPropertySourceData.h"
52 #include "CSSReflectValue.h"
53 #include "CSSSelector.h"
54 #include "CSSStyleRule.h"
55 #include "CSSStyleSheet.h"
56 #include "CSSTimingFunctionValue.h"
57 #include "CSSUnicodeRangeValue.h"
58 #include "CSSValueKeywords.h"
59 #include "CSSValueList.h"
60 #include "CSSValuePool.h"
61 #include "CSSWrapShapes.h"
64 #include "FloatConversion.h"
65 #include "FontFeatureValue.h"
66 #include "FontValue.h"
67 #include "HTMLParserIdioms.h"
68 #include "HashTools.h"
69 #include "MediaList.h"
70 #include "MediaQueryExp.h"
74 #include "RenderTheme.h"
76 #include "ShadowValue.h"
77 #include "StylePropertySet.h"
78 #include "StylePropertyShorthand.h"
79 #include "StyleRule.h"
80 #if ENABLE(CSS_FILTERS)
81 #include "WebKitCSSFilterValue.h"
83 #include "WebKitCSSKeyframeRule.h"
84 #include "WebKitCSSKeyframesRule.h"
85 #include "WebKitCSSRegionRule.h"
86 #include "WebKitCSSTransformValue.h"
87 #if ENABLE(CSS_SHADERS)
88 #include "WebKitCSSShaderValue.h"
91 #include <wtf/HexNumber.h>
93 #include <wtf/text/StringBuffer.h>
94 #include <wtf/text/StringBuilder.h>
96 #if ENABLE(DASHBOARD_SUPPORT)
97 #include "DashboardRegion.h"
103 extern int cssyydebug;
106 extern int cssyyparse(void* parser);
118 class ImplicitScope {
119 WTF_MAKE_NONCOPYABLE(ImplicitScope);
121 ImplicitScope(WebCore::CSSParser* parser, PropertyType propertyType)
124 m_parser->m_implicitShorthand = propertyType == PropertyImplicit;
129 m_parser->m_implicitShorthand = false;
133 WebCore::CSSParser* m_parser;
140 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
141 static const double MAX_SCALE = 1000000;
143 static bool equal(const CSSParserString& a, const char* b)
145 for (int i = 0; i < a.length; ++i) {
148 if (a.characters[i] != b[i])
154 static bool equalIgnoringCase(const CSSParserString& a, const char* b)
156 for (int i = 0; i < a.length; ++i) {
159 ASSERT(!isASCIIUpper(b[i]));
160 if (toASCIILower(a.characters[i]) != b[i])
166 static bool hasPrefix(const char* string, unsigned length, const char* prefix)
168 for (unsigned i = 0; i < length; ++i) {
171 if (string[i] != prefix[i])
177 inline void CSSParser::ensureCSSValuePool()
180 m_cssValuePool = CSSValuePool::create();
183 CSSParser::CSSParser(CSSParserMode cssParserMode)
184 : m_cssParserMode(cssParserMode)
188 , m_inParseShorthand(0)
189 , m_currentShorthand(0)
190 , m_implicitShorthand(false)
191 , m_hasFontFaceOnlyValues(false)
192 , m_hadSyntacticallyValidCSSRule(false)
193 , m_defaultNamespace(starAtom)
194 , m_inStyleRuleOrDeclaration(false)
195 , m_selectorListRange(0, 0)
196 , m_ruleBodyRange(0, 0)
197 , m_propertyRange(UINT_MAX, UINT_MAX)
199 , m_currentRuleData(0)
200 , m_parsingMode(NormalMode)
201 , m_currentCharacter(0)
204 , m_lastSelectorLineNumber(0)
205 , m_allowImportRules(true)
206 , m_allowNamespaceDeclarations(true)
211 CSSPropertySourceData::init();
214 CSSParser::~CSSParser()
218 fastDeleteAllValues(m_floatingSelectors);
219 deleteAllValues(m_floatingSelectorVectors);
220 deleteAllValues(m_floatingValueLists);
221 deleteAllValues(m_floatingFunctions);
224 void CSSParserString::lower()
226 // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
227 // that can potentially change the length of the string rather than the character
228 // by character kind. If we don't need Unicode lowercasing, it would be good to
229 // simplify this function.
231 if (charactersAreAllASCII(characters, length)) {
232 // Fast case for all-ASCII.
233 for (int i = 0; i < length; i++)
234 characters[i] = toASCIILower(characters[i]);
236 for (int i = 0; i < length; i++)
237 characters[i] = Unicode::toLower(characters[i]);
241 void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix)
243 int length = string.length() + strlen(prefix) + strlen(suffix) + 1;
245 m_dataStart = adoptArrayPtr(new UChar[length]);
246 for (unsigned i = 0; i < strlen(prefix); i++)
247 m_dataStart[i] = prefix[i];
249 memcpy(m_dataStart.get() + strlen(prefix), string.characters(), string.length() * sizeof(UChar));
251 unsigned start = strlen(prefix) + string.length();
252 unsigned end = start + strlen(suffix);
253 for (unsigned i = start; i < end; i++)
254 m_dataStart[i] = suffix[i - start];
256 m_dataStart[length - 1] = 0;
258 m_currentCharacter = m_tokenStart = m_dataStart.get();
259 resetRuleBodyMarks();
262 void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string, int startLineNumber, StyleRuleRangeMap* ruleRangeMap)
264 setStyleSheet(sheet);
265 m_defaultNamespace = starAtom; // Reset the default namespace.
266 m_ruleRangeMap = ruleRangeMap;
268 m_currentRuleData = CSSRuleSourceData::create();
269 m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
272 m_lineNumber = startLineNumber;
273 setupParser("", string, "");
276 m_currentRuleData = 0;
280 PassRefPtr<StyleRuleBase> CSSParser::parseRule(CSSStyleSheet* sheet, const String& string)
282 setStyleSheet(sheet);
283 m_allowNamespaceDeclarations = false;
284 setupParser("@-webkit-rule{", string, "} ");
286 return m_rule.release();
289 PassRefPtr<StyleKeyframe> CSSParser::parseKeyframeRule(CSSStyleSheet *sheet, const String &string)
291 setStyleSheet(sheet);
292 setupParser("@-webkit-keyframe-rule{ ", string, "} ");
294 return m_keyframe.release();
297 static inline bool isColorPropertyID(int propertyId)
299 switch (propertyId) {
300 case CSSPropertyColor:
301 case CSSPropertyBackgroundColor:
302 case CSSPropertyBorderBottomColor:
303 case CSSPropertyBorderLeftColor:
304 case CSSPropertyBorderRightColor:
305 case CSSPropertyBorderTopColor:
306 case CSSPropertyOutlineColor:
307 case CSSPropertyTextLineThroughColor:
308 case CSSPropertyTextOverlineColor:
309 case CSSPropertyTextUnderlineColor:
310 case CSSPropertyWebkitBorderAfterColor:
311 case CSSPropertyWebkitBorderBeforeColor:
312 case CSSPropertyWebkitBorderEndColor:
313 case CSSPropertyWebkitBorderStartColor:
314 case CSSPropertyWebkitColumnRuleColor:
315 case CSSPropertyWebkitTextEmphasisColor:
316 case CSSPropertyWebkitTextFillColor:
317 case CSSPropertyWebkitTextStrokeColor:
324 static bool parseColorValue(StylePropertySet* declaration, int propertyId, const String& string, bool important, CSSParserMode cssParserMode, CSSStyleSheet* contextStyleSheet)
326 bool strict = isStrictParserMode(cssParserMode);
327 if (!string.length())
329 if (!isColorPropertyID(propertyId))
331 CSSParserString cssString;
332 cssString.characters = const_cast<UChar*>(string.characters());
333 cssString.length = string.length();
334 int valueID = cssValueKeywordID(cssString);
335 bool validPrimitive = false;
336 if (valueID == CSSValueWebkitText)
337 validPrimitive = true;
338 else if (valueID == CSSValueCurrentcolor)
339 validPrimitive = true;
340 else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
341 || (valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText && !strict)) {
342 validPrimitive = true;
345 Document* document = contextStyleSheet->findDocument();
346 if (validPrimitive) {
347 RefPtr<CSSValue> value;
349 value = document->cssValuePool()->createIdentifierValue(valueID);
351 value = CSSPrimitiveValue::createIdentifier(valueID);
352 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
356 if (!CSSParser::fastParseColor(color, string, strict && string[0] != '#'))
358 RefPtr<CSSValue> value;
360 value = document->cssValuePool()->createColorValue(color);
362 value = CSSPrimitiveValue::createColor(color);
363 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
367 static inline bool isSimpleLengthPropertyID(int propertyId, bool& acceptsNegativeNumbers)
369 switch (propertyId) {
370 case CSSPropertyFontSize:
371 case CSSPropertyHeight:
372 case CSSPropertyWidth:
373 case CSSPropertyMinHeight:
374 case CSSPropertyMinWidth:
375 case CSSPropertyPaddingBottom:
376 case CSSPropertyPaddingLeft:
377 case CSSPropertyPaddingRight:
378 case CSSPropertyPaddingTop:
379 case CSSPropertyWebkitLogicalWidth:
380 case CSSPropertyWebkitLogicalHeight:
381 case CSSPropertyWebkitMinLogicalWidth:
382 case CSSPropertyWebkitMinLogicalHeight:
383 case CSSPropertyWebkitPaddingAfter:
384 case CSSPropertyWebkitPaddingBefore:
385 case CSSPropertyWebkitPaddingEnd:
386 case CSSPropertyWebkitPaddingStart:
387 case CSSPropertyWebkitWrapMargin:
388 case CSSPropertyWebkitWrapPadding:
389 acceptsNegativeNumbers = false;
391 case CSSPropertyBottom:
392 case CSSPropertyLeft:
393 case CSSPropertyMarginBottom:
394 case CSSPropertyMarginLeft:
395 case CSSPropertyMarginRight:
396 case CSSPropertyMarginTop:
397 case CSSPropertyRight:
398 case CSSPropertyTextIndent:
400 case CSSPropertyWebkitMarginAfter:
401 case CSSPropertyWebkitMarginBefore:
402 case CSSPropertyWebkitMarginEnd:
403 case CSSPropertyWebkitMarginStart:
404 acceptsNegativeNumbers = true;
411 static bool parseSimpleLengthValue(StylePropertySet* declaration, int propertyId, const String& string, bool important, CSSParserMode cssParserMode, CSSStyleSheet* contextStyleSheet)
413 bool acceptsNegativeNumbers;
414 bool strict = isStrictParserMode(cssParserMode);
415 unsigned length = string.length();
422 CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
424 if (string.is8Bit()) {
425 const LChar* characters8 = string.characters8();
429 if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
432 if (length > 2 && (characters8[length - 2] | 0x20) == 'p' && (characters8[length - 1] | 0x20) == 'x') {
434 unit = CSSPrimitiveValue::CSS_PX;
435 } else if (length > 1 && characters8[length - 1] == '%') {
437 unit = CSSPrimitiveValue::CSS_PERCENTAGE;
440 // We rely on charactersToDouble for validation as well. The function
441 // will set "ok" to "false" if the entire passed-in character range does
442 // not represent a double.
443 number = charactersToDouble(characters8, length, &ok);
445 const UChar* characters16 = string.characters16();
449 if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
452 if (length > 2 && (characters16[length - 2] | 0x20) == 'p' && (characters16[length - 1] | 0x20) == 'x') {
454 unit = CSSPrimitiveValue::CSS_PX;
455 } else if (length > 1 && characters16[length - 1] == '%') {
457 unit = CSSPrimitiveValue::CSS_PERCENTAGE;
460 // We rely on charactersToDouble for validation as well. The function
461 // will set "ok" to "false" if the entire passed-in character range does
462 // not represent a double.
463 number = charactersToDouble(characters16, length, &ok);
468 if (unit == CSSPrimitiveValue::CSS_NUMBER) {
469 if (number && strict)
471 unit = CSSPrimitiveValue::CSS_PX;
473 if (number < 0 && !acceptsNegativeNumbers)
476 Document* document = contextStyleSheet->findDocument();
477 RefPtr<CSSValue> value;
479 value = document->cssValuePool()->createValue(number, unit);
481 value = CSSPrimitiveValue::create(number, unit);
482 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
486 static inline bool isValidKeywordPropertyAndValue(int propertyId, int valueID)
491 switch (propertyId) {
492 case CSSPropertyBorderCollapse: // collapse | separate | inherit
493 if (valueID == CSSValueCollapse || valueID == CSSValueSeparate)
496 case CSSPropertyBorderTopStyle: // <border-style> | inherit
497 case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
498 case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
499 case CSSPropertyBorderLeftStyle:
500 case CSSPropertyWebkitBorderAfterStyle:
501 case CSSPropertyWebkitBorderBeforeStyle:
502 case CSSPropertyWebkitBorderEndStyle:
503 case CSSPropertyWebkitBorderStartStyle:
504 case CSSPropertyWebkitColumnRuleStyle:
505 if (valueID >= CSSValueNone && valueID <= CSSValueDouble)
508 case CSSPropertyBoxSizing:
509 if (valueID == CSSValueBorderBox || valueID == CSSValueContentBox)
512 case CSSPropertyCaptionSide: // top | bottom | left | right | inherit
513 if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom)
516 case CSSPropertyClear: // none | left | right | both | inherit
517 if (valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth)
520 case CSSPropertyDirection: // ltr | rtl | inherit
521 if (valueID == CSSValueLtr || valueID == CSSValueRtl)
524 case CSSPropertyDisplay:
525 // inline | block | list-item | run-in | inline-block | table |
526 // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
527 // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none | inherit
528 // -webkit-flexbox | -webkit-inline-flexbox | -webkit-grid | -webkit-inline-grid
529 if ((valueID >= CSSValueInline && valueID <= CSSValueWebkitInlineFlexbox) || valueID == CSSValueNone)
531 #if ENABLE(CSS_GRID_LAYOUT)
532 if (valueID == CSSValueWebkitGrid || valueID == CSSValueWebkitInlineGrid)
536 case CSSPropertyEmptyCells: // show | hide | inherit
537 if (valueID == CSSValueShow || valueID == CSSValueHide)
540 case CSSPropertyFloat: // left | right | none | positioned | center (for buggy CSS, maps to none)
541 if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter || valueID == CSSValueWebkitPositioned)
544 case CSSPropertyFontStyle: // normal | italic | oblique | inherit
545 if (valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique)
548 case CSSPropertyImageRendering: // auto | optimizeContrast
549 if (valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast)
552 case CSSPropertyListStylePosition: // inside | outside | inherit
553 if (valueID == CSSValueInside || valueID == CSSValueOutside)
556 case CSSPropertyListStyleType:
557 // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
558 // for the list of supported list-style-types.
559 if ((valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone)
562 case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto | inherit
563 if (valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble))
566 case CSSPropertyOverflowX:
567 case CSSPropertyOverflowY: // visible | hidden | scroll | auto | marquee | overlay | inherit
568 if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitMarquee)
571 case CSSPropertyPointerEvents:
572 // none | visiblePainted | visibleFill | visibleStroke | visible |
573 // painted | fill | stroke | auto | all | inherit
574 if (valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueStroke))
577 case CSSPropertyPosition: // static | relative | absolute | fixed | inherit
578 if (valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed)
581 case CSSPropertyResize: // none | both | horizontal | vertical | auto
582 if (valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto)
585 case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation | inherit
586 if (valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation)
589 case CSSPropertyTableLayout: // auto | fixed | inherit
590 if (valueID == CSSValueAuto || valueID == CSSValueFixed)
593 case CSSPropertyTextLineThroughMode:
594 case CSSPropertyTextOverlineMode:
595 case CSSPropertyTextUnderlineMode:
596 if (valueID == CSSValueContinuous || valueID == CSSValueSkipWhiteSpace)
599 case CSSPropertyTextLineThroughStyle:
600 case CSSPropertyTextOverlineStyle:
601 case CSSPropertyTextUnderlineStyle:
602 if (valueID == CSSValueNone || valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDashed || valueID == CSSValueDotDash || valueID == CSSValueDotDotDash || valueID == CSSValueWave)
605 case CSSPropertyTextOverflow: // clip | ellipsis
606 if (valueID == CSSValueClip || valueID == CSSValueEllipsis)
609 case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
610 if (valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision)
613 case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none | inherit
614 if ((valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone)
617 case CSSPropertyVisibility: // visible | hidden | collapse | inherit
618 if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse)
621 case CSSPropertyWebkitAppearance:
622 if ((valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone)
625 case CSSPropertyWebkitBackfaceVisibility:
626 if (valueID == CSSValueVisible || valueID == CSSValueHidden)
629 case CSSPropertyWebkitBorderFit:
630 if (valueID == CSSValueBorder || valueID == CSSValueLines)
633 case CSSPropertyWebkitBoxAlign:
634 if (valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline)
637 case CSSPropertyWebkitBoxDirection:
638 if (valueID == CSSValueNormal || valueID == CSSValueReverse)
641 case CSSPropertyWebkitBoxLines:
642 if (valueID == CSSValueSingle || valueID == CSSValueMultiple)
645 case CSSPropertyWebkitBoxOrient:
646 if (valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis)
649 case CSSPropertyWebkitBoxPack:
650 if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify)
653 case CSSPropertyWebkitColorCorrection:
654 if (valueID == CSSValueSrgb || valueID == CSSValueDefault)
657 case CSSPropertyWebkitFlexAlign:
658 if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
661 case CSSPropertyWebkitFlexDirection:
662 if (valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse)
665 case CSSPropertyWebkitFlexItemAlign:
666 if (valueID == CSSValueAuto || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
669 case CSSPropertyWebkitFlexLinePack:
670 if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify || valueID == CSSValueDistribute || valueID == CSSValueStretch)
673 case CSSPropertyWebkitFlexPack:
674 if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify || valueID == CSSValueDistribute)
677 case CSSPropertyWebkitFlexWrap:
678 if (valueID == CSSValueNone || valueID == CSSValueWrap || valueID == CSSValueWrapReverse)
681 case CSSPropertyWebkitFontKerning:
682 if (valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone)
685 case CSSPropertyWebkitFontSmoothing:
686 if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased)
689 case CSSPropertyWebkitHyphens:
690 if (valueID == CSSValueNone || valueID == CSSValueManual || valueID == CSSValueAuto)
693 case CSSPropertyWebkitLineAlign:
694 if (valueID == CSSValueNone || valueID == CSSValueEdges)
697 case CSSPropertyWebkitLineBreak: // normal | after-white-space
698 if (valueID == CSSValueNormal || valueID == CSSValueAfterWhiteSpace)
701 case CSSPropertyWebkitLineSnap:
702 if (valueID == CSSValueNone || valueID == CSSValueBaseline || valueID == CSSValueContain)
705 case CSSPropertyWebkitMarginAfterCollapse:
706 case CSSPropertyWebkitMarginBeforeCollapse:
707 case CSSPropertyWebkitMarginBottomCollapse:
708 case CSSPropertyWebkitMarginTopCollapse:
709 if (valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard)
712 case CSSPropertyWebkitMarqueeDirection:
713 if (valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
714 || valueID == CSSValueUp || valueID == CSSValueAuto)
717 case CSSPropertyWebkitMarqueeStyle:
718 if (valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate)
721 case CSSPropertyWebkitMatchNearestMailBlockquoteColor: // normal | match
722 if (valueID == CSSValueNormal || valueID == CSSValueMatch)
725 case CSSPropertyWebkitNbspMode: // normal | space
726 if (valueID == CSSValueNormal || valueID == CSSValueSpace)
729 #if ENABLE(OVERFLOW_SCROLLING)
730 case CSSPropertyWebkitOverflowScrolling:
731 if (valueID == CSSValueAuto || valueID == CSSValueTouch)
735 case CSSPropertyWebkitPrintColorAdjust:
736 if (valueID == CSSValueExact || valueID == CSSValueEconomy)
739 case CSSPropertyWebkitRtlOrdering:
740 if (valueID == CSSValueLogical || valueID == CSSValueVisual)
743 case CSSPropertyWebkitTextCombine:
744 if (valueID == CSSValueNone || valueID == CSSValueHorizontal)
747 case CSSPropertyWebkitTextEmphasisPosition:
748 if (valueID == CSSValueOver || valueID == CSSValueUnder)
751 case CSSPropertyWebkitTextSecurity:
752 // disc | circle | square | none | inherit
753 if (valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone)
756 case CSSPropertyWebkitTextSizeAdjust:
757 if (valueID == CSSValueAuto || valueID == CSSValueNone)
760 case CSSPropertyWebkitTransformStyle:
761 if (valueID == CSSValueFlat || valueID == CSSValuePreserve3d)
764 case CSSPropertyWebkitUserDrag: // auto | none | element
765 if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement)
768 case CSSPropertyWebkitUserModify: // read-only | read-write
769 if (valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly)
772 case CSSPropertyWebkitUserSelect: // auto | none | text
773 if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText)
776 case CSSPropertyWebkitWrapFlow:
777 if (valueID == CSSValueAuto || valueID == CSSValueBoth || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueMaximum || valueID == CSSValueClear)
780 case CSSPropertyWebkitWrapThrough:
781 if (valueID == CSSValueWrap || valueID == CSSValueNone)
784 case CSSPropertyWebkitWritingMode:
785 if (valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt)
788 case CSSPropertyWhiteSpace: // normal | pre | nowrap | inherit
789 if (valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap)
792 case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
793 if (valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord)
796 case CSSPropertyWordWrap: // normal | break-word
797 if (valueID == CSSValueNormal || valueID == CSSValueBreakWord)
801 ASSERT_NOT_REACHED();
807 static inline bool isKeywordPropertyID(int propertyId)
809 switch (propertyId) {
810 case CSSPropertyBorderBottomStyle:
811 case CSSPropertyBorderCollapse:
812 case CSSPropertyBorderLeftStyle:
813 case CSSPropertyBorderRightStyle:
814 case CSSPropertyBorderTopStyle:
815 case CSSPropertyBoxSizing:
816 case CSSPropertyCaptionSide:
817 case CSSPropertyClear:
818 case CSSPropertyDirection:
819 case CSSPropertyDisplay:
820 case CSSPropertyEmptyCells:
821 case CSSPropertyFloat:
822 case CSSPropertyFontStyle:
823 case CSSPropertyImageRendering:
824 case CSSPropertyListStylePosition:
825 case CSSPropertyListStyleType:
826 case CSSPropertyOutlineStyle:
827 case CSSPropertyOverflowX:
828 case CSSPropertyOverflowY:
829 case CSSPropertyPointerEvents:
830 case CSSPropertyPosition:
831 case CSSPropertyResize:
832 case CSSPropertySpeak:
833 case CSSPropertyTableLayout:
834 case CSSPropertyTextLineThroughMode:
835 case CSSPropertyTextLineThroughStyle:
836 case CSSPropertyTextOverflow:
837 case CSSPropertyTextOverlineMode:
838 case CSSPropertyTextOverlineStyle:
839 case CSSPropertyTextRendering:
840 case CSSPropertyTextTransform:
841 case CSSPropertyTextUnderlineMode:
842 case CSSPropertyTextUnderlineStyle:
843 case CSSPropertyVisibility:
844 case CSSPropertyWebkitAppearance:
845 case CSSPropertyWebkitBackfaceVisibility:
846 case CSSPropertyWebkitBorderAfterStyle:
847 case CSSPropertyWebkitBorderBeforeStyle:
848 case CSSPropertyWebkitBorderEndStyle:
849 case CSSPropertyWebkitBorderFit:
850 case CSSPropertyWebkitBorderStartStyle:
851 case CSSPropertyWebkitBoxAlign:
852 case CSSPropertyWebkitBoxDirection:
853 case CSSPropertyWebkitBoxLines:
854 case CSSPropertyWebkitBoxOrient:
855 case CSSPropertyWebkitBoxPack:
856 case CSSPropertyWebkitColorCorrection:
857 case CSSPropertyWebkitColumnRuleStyle:
858 case CSSPropertyWebkitFlexAlign:
859 case CSSPropertyWebkitFlexDirection:
860 case CSSPropertyWebkitFlexItemAlign:
861 case CSSPropertyWebkitFlexLinePack:
862 case CSSPropertyWebkitFlexPack:
863 case CSSPropertyWebkitFlexWrap:
864 case CSSPropertyWebkitFontKerning:
865 case CSSPropertyWebkitFontSmoothing:
866 case CSSPropertyWebkitHyphens:
867 case CSSPropertyWebkitLineAlign:
868 case CSSPropertyWebkitLineBreak:
869 case CSSPropertyWebkitLineSnap:
870 case CSSPropertyWebkitMarginAfterCollapse:
871 case CSSPropertyWebkitMarginBeforeCollapse:
872 case CSSPropertyWebkitMarginBottomCollapse:
873 case CSSPropertyWebkitMarginTopCollapse:
874 case CSSPropertyWebkitMarqueeDirection:
875 case CSSPropertyWebkitMarqueeStyle:
876 case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
877 case CSSPropertyWebkitNbspMode:
878 #if ENABLE(OVERFLOW_SCROLLING)
879 case CSSPropertyWebkitOverflowScrolling:
881 case CSSPropertyWebkitPrintColorAdjust:
882 case CSSPropertyWebkitRtlOrdering:
883 case CSSPropertyWebkitTextCombine:
884 case CSSPropertyWebkitTextEmphasisPosition:
885 case CSSPropertyWebkitTextSecurity:
886 case CSSPropertyWebkitTextSizeAdjust:
887 case CSSPropertyWebkitTransformStyle:
888 case CSSPropertyWebkitUserDrag:
889 case CSSPropertyWebkitUserModify:
890 case CSSPropertyWebkitUserSelect:
891 case CSSPropertyWebkitWrapFlow:
892 case CSSPropertyWebkitWrapThrough:
893 case CSSPropertyWebkitWritingMode:
894 case CSSPropertyWhiteSpace:
895 case CSSPropertyWordBreak:
896 case CSSPropertyWordWrap:
903 static bool parseKeywordValue(StylePropertySet* declaration, int propertyId, const String& string, bool important, CSSStyleSheet* contextStyleSheet)
905 if (string.isEmpty())
908 if (!isKeywordPropertyID(propertyId))
911 CSSParserString cssString;
912 cssString.characters = const_cast<UChar*>(string.characters());
913 cssString.length = string.length();
914 int valueID = cssValueKeywordID(cssString);
919 Document* document = contextStyleSheet->findDocument();
920 RefPtr<CSSValue> value;
921 CSSValuePool* cssValuePool = document ? document->cssValuePool().get() : 0;
922 if (valueID == CSSValueInherit)
923 value = cssValuePool ? cssValuePool->createInheritedValue() : CSSInheritedValue::create();
924 else if (valueID == CSSValueInitial)
925 value = cssValuePool ? cssValuePool->createExplicitInitialValue() : CSSInitialValue::createExplicit();
926 else if (isValidKeywordPropertyAndValue(propertyId, valueID))
927 value = cssValuePool ? cssValuePool->createIdentifierValue(valueID) : CSSPrimitiveValue::createIdentifier(valueID);
931 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
935 PassRefPtr<CSSValueList> CSSParser::parseFontFaceValue(const AtomicString& string, CSSStyleSheet* contextStyleSheet)
937 RefPtr<StylePropertySet> dummyStyle = StylePropertySet::create();
938 if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, CSSQuirksMode, contextStyleSheet))
940 return static_pointer_cast<CSSValueList>(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily));
943 bool CSSParser::parseValue(StylePropertySet* declaration, int propertyId, const String& string, bool important, CSSParserMode cssParserMode, CSSStyleSheet* contextStyleSheet)
945 if (parseSimpleLengthValue(declaration, propertyId, string, important, cssParserMode, contextStyleSheet))
947 if (parseColorValue(declaration, propertyId, string, important, cssParserMode, contextStyleSheet))
949 if (parseKeywordValue(declaration, propertyId, string, important, contextStyleSheet))
951 CSSParser parser(cssParserMode);
952 return parser.parseValue(declaration, propertyId, string, important, contextStyleSheet);
955 bool CSSParser::parseValue(StylePropertySet* declaration, int propertyId, const String& string, bool important, CSSStyleSheet* contextStyleSheet)
957 setStyleSheet(contextStyleSheet);
959 setupParser("@-webkit-value{", string, "} ");
962 m_important = important;
969 if (m_hasFontFaceOnlyValues)
970 deleteFontFaceOnlyValues();
971 if (!m_parsedProperties.isEmpty()) {
973 declaration->addParsedProperties(m_parsedProperties.data(), m_parsedProperties.size());
980 // The color will only be changed when string contains a valid CSS color, so callers
981 // can set it to a default color and ignore the boolean result.
982 bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict)
984 // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
985 if (fastParseColor(color, string, strict))
988 CSSParser parser(CSSStrictMode);
990 // In case the fast-path parser didn't understand the color, try the full parser.
991 if (!parser.parseColor(string))
994 CSSValue* value = parser.m_parsedProperties.first().value();
995 if (!value->isPrimitiveValue())
998 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
999 if (!primitiveValue->isRGBColor())
1002 color = primitiveValue->getRGBA32Value();
1006 bool CSSParser::parseColor(const String& string)
1008 // This function may be called without a stylesheet set on the parser, so we need to
1009 // make sure that we have a CSSValuePool or we'll crash below cssyyparse().
1010 ensureCSSValuePool();
1012 setupParser("@-webkit-decls{color:", string, "} ");
1016 return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor;
1019 bool CSSParser::parseSystemColor(RGBA32& color, const String& string, Document* document)
1021 if (!document || !document->page())
1024 CSSParserString cssColor;
1025 cssColor.characters = const_cast<UChar*>(string.characters());
1026 cssColor.length = string.length();
1027 int id = cssValueKeywordID(cssColor);
1031 color = document->page()->theme()->systemColor(id).rgb();
1035 void CSSParser::parseSelector(const String& string, Document* doc, CSSSelectorList& selectorList)
1037 RefPtr<CSSStyleSheet> dummyStyleSheet = CSSStyleSheet::create(doc);
1039 setStyleSheet(dummyStyleSheet.get());
1040 m_selectorListForParseSelector = &selectorList;
1042 setupParser("@-webkit-selector{", string, "}");
1046 m_selectorListForParseSelector = 0;
1048 // The style sheet will be deleted right away, so it won't outlive the document.
1049 ASSERT(dummyStyleSheet->hasOneRef());
1052 bool CSSParser::parseDeclaration(StylePropertySet* declaration, const String& string, RefPtr<CSSStyleSourceData>* styleSourceData, CSSStyleSheet* contextStyleSheet)
1054 // Length of the "@-webkit-decls{" prefix.
1055 static const unsigned prefixLength = 15;
1057 setStyleSheet(contextStyleSheet);
1059 if (styleSourceData) {
1060 m_currentRuleData = CSSRuleSourceData::create();
1061 m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
1062 m_inStyleRuleOrDeclaration = true;
1065 setupParser("@-webkit-decls{", string, "} ");
1070 if (m_hasFontFaceOnlyValues)
1071 deleteFontFaceOnlyValues();
1072 if (!m_parsedProperties.isEmpty()) {
1074 declaration->addParsedProperties(m_parsedProperties.data(), m_parsedProperties.size());
1078 if (m_currentRuleData) {
1079 m_currentRuleData->styleSourceData->styleBodyRange.start = 0;
1080 m_currentRuleData->styleSourceData->styleBodyRange.end = string.length();
1081 for (Vector<CSSPropertySourceData>::iterator it = m_currentRuleData->styleSourceData->propertyData.begin(), endIt = m_currentRuleData->styleSourceData->propertyData.end(); it != endIt; ++it) {
1082 (*it).range.start -= prefixLength;
1083 (*it).range.end -= prefixLength;
1087 if (styleSourceData) {
1088 *styleSourceData = m_currentRuleData->styleSourceData.release();
1089 m_currentRuleData = 0;
1090 m_inStyleRuleOrDeclaration = false;
1095 PassOwnPtr<MediaQuery> CSSParser::parseMediaQuery(const String& string)
1097 if (string.isEmpty())
1100 ASSERT(!m_mediaQuery);
1102 // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
1103 // instead insert one " " (which is WHITESPACE in CSSGrammar.y)
1104 setupParser("@-webkit-mediaquery ", string, "} ");
1107 return m_mediaQuery.release();
1110 void CSSParser::addProperty(int propId, PassRefPtr<CSSValue> value, bool important, bool implicit)
1112 m_parsedProperties.append(CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand || implicit));
1115 void CSSParser::rollbackLastProperties(int num)
1118 ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num));
1119 m_parsedProperties.shrink(m_parsedProperties.size() - num);
1122 void CSSParser::clearProperties()
1124 m_parsedProperties.clear();
1125 m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1126 m_hasFontFaceOnlyValues = false;
1129 void CSSParser::setStyleSheet(CSSStyleSheet* styleSheet)
1131 m_styleSheet = styleSheet;
1132 Document* document = findDocument();
1133 m_cssValuePool = document ? document->cssValuePool() : CSSValuePool::create();
1136 Document* CSSParser::findDocument() const
1140 return m_styleSheet->findDocument();
1143 bool CSSParser::validCalculationUnit(CSSParserValue* value, Units unitflags)
1145 bool mustBeNonNegative = unitflags & FNonNeg;
1147 if (!parseCalculation(value, mustBeNonNegative ? CalculationRangeNonNegative : CalculationRangeAll))
1151 switch (m_parsedCalculation->category()) {
1153 b = (unitflags & FLength);
1156 b = (unitflags & FPercent);
1157 if (b && mustBeNonNegative && m_parsedCalculation->isNegative())
1161 b = (unitflags & FNumber);
1162 if (!b && (unitflags & FInteger) && m_parsedCalculation->isInt())
1164 if (b && mustBeNonNegative && m_parsedCalculation->isNegative())
1167 case CalcPercentLength:
1168 b = (unitflags & FPercent) && (unitflags & FLength);
1170 case CalcPercentNumber:
1171 b = (unitflags & FPercent) && (unitflags & FNumber);
1177 m_parsedCalculation.release();
1181 inline bool CSSParser::shouldAcceptUnitLessValues(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode)
1183 // Qirks mode and svg presentation attributes accept unit less values.
1184 return (unitflags & (FLength | FAngle | FTime)) && (!value->fValue || cssParserMode == CSSQuirksMode || cssParserMode == SVGAttributeMode);
1187 bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode)
1189 if (isCalculation(value))
1190 return validCalculationUnit(value, unitflags);
1193 switch (value->unit) {
1194 case CSSPrimitiveValue::CSS_NUMBER:
1195 b = (unitflags & FNumber);
1196 if (!b && shouldAcceptUnitLessValues(value, unitflags, cssParserMode)) {
1197 value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX :
1198 ((unitflags & FAngle) ? CSSPrimitiveValue::CSS_DEG : CSSPrimitiveValue::CSS_MS);
1201 if (!b && (unitflags & FInteger) && value->isInt)
1204 case CSSPrimitiveValue::CSS_PERCENTAGE:
1205 b = (unitflags & FPercent);
1207 case CSSParserValue::Q_EMS:
1208 case CSSPrimitiveValue::CSS_EMS:
1209 case CSSPrimitiveValue::CSS_REMS:
1210 case CSSPrimitiveValue::CSS_EXS:
1211 case CSSPrimitiveValue::CSS_PX:
1212 case CSSPrimitiveValue::CSS_CM:
1213 case CSSPrimitiveValue::CSS_MM:
1214 case CSSPrimitiveValue::CSS_IN:
1215 case CSSPrimitiveValue::CSS_PT:
1216 case CSSPrimitiveValue::CSS_PC:
1217 case CSSPrimitiveValue::CSS_VW:
1218 case CSSPrimitiveValue::CSS_VH:
1219 case CSSPrimitiveValue::CSS_VMIN:
1220 b = (unitflags & FLength);
1222 case CSSPrimitiveValue::CSS_MS:
1223 case CSSPrimitiveValue::CSS_S:
1224 b = (unitflags & FTime);
1226 case CSSPrimitiveValue::CSS_DEG:
1227 case CSSPrimitiveValue::CSS_RAD:
1228 case CSSPrimitiveValue::CSS_GRAD:
1229 case CSSPrimitiveValue::CSS_TURN:
1230 b = (unitflags & FAngle);
1232 case CSSPrimitiveValue::CSS_HZ:
1233 case CSSPrimitiveValue::CSS_KHZ:
1234 case CSSPrimitiveValue::CSS_DIMENSION:
1238 if (b && unitflags & FNonNeg && value->fValue < 0)
1243 inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(CSSParserValue* value)
1245 if (m_parsedCalculation) {
1246 ASSERT(isCalculation(value));
1247 return CSSPrimitiveValue::create(m_parsedCalculation.release());
1250 ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1251 || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
1252 || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN));
1253 return cssValuePool()->createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit));
1256 inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveStringValue(CSSParserValue* value)
1258 ASSERT(value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT);
1259 return cssValuePool()->createValue(value->string, CSSPrimitiveValue::CSS_STRING);
1262 static int unitFromString(CSSParserValue* value)
1264 if (value->unit != CSSPrimitiveValue::CSS_IDENT || value->id)
1267 if (equal(value->string, "em"))
1268 return CSSPrimitiveValue::CSS_EMS;
1269 if (equal(value->string, "rem"))
1270 return CSSPrimitiveValue::CSS_REMS;
1271 if (equal(value->string, "ex"))
1272 return CSSPrimitiveValue::CSS_EXS;
1273 if (equal(value->string, "px"))
1274 return CSSPrimitiveValue::CSS_PX;
1275 if (equal(value->string, "cm"))
1276 return CSSPrimitiveValue::CSS_CM;
1277 if (equal(value->string, "mm"))
1278 return CSSPrimitiveValue::CSS_MM;
1279 if (equal(value->string, "in"))
1280 return CSSPrimitiveValue::CSS_IN;
1281 if (equal(value->string, "pt"))
1282 return CSSPrimitiveValue::CSS_PT;
1283 if (equal(value->string, "pc"))
1284 return CSSPrimitiveValue::CSS_PC;
1285 if (equal(value->string, "deg"))
1286 return CSSPrimitiveValue::CSS_DEG;
1287 if (equal(value->string, "rad"))
1288 return CSSPrimitiveValue::CSS_RAD;
1289 if (equal(value->string, "grad"))
1290 return CSSPrimitiveValue::CSS_GRAD;
1291 if (equal(value->string, "turn"))
1292 return CSSPrimitiveValue::CSS_TURN;
1293 if (equal(value->string, "ms"))
1294 return CSSPrimitiveValue::CSS_MS;
1295 if (equal(value->string, "s"))
1296 return CSSPrimitiveValue::CSS_S;
1297 if (equal(value->string, "Hz"))
1298 return CSSPrimitiveValue::CSS_HZ;
1299 if (equal(value->string, "kHz"))
1300 return CSSPrimitiveValue::CSS_KHZ;
1301 if (equal(value->string, "vw"))
1302 return CSSPrimitiveValue::CSS_VW;
1303 if (equal(value->string, "vh"))
1304 return CSSPrimitiveValue::CSS_VH;
1305 if (equal(value->string, "vmin"))
1306 return CSSPrimitiveValue::CSS_VMIN;
1311 void CSSParser::checkForOrphanedUnits()
1313 if (inStrictMode() || inShorthand())
1316 // The purpose of this code is to implement the WinIE quirk that allows unit types to be separated from their numeric values
1317 // 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.
1318 CSSParserValue* numericVal = 0;
1319 unsigned size = m_valueList->size();
1320 for (unsigned i = 0; i < size; i++) {
1321 CSSParserValue* value = m_valueList->valueAt(i);
1324 // Change the unit type of the numeric val to match.
1325 int unit = unitFromString(value);
1327 numericVal->unit = unit;
1330 // Now delete the bogus unit value.
1331 m_valueList->deleteValueAt(i);
1332 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).
1338 numericVal = (value->unit == CSSPrimitiveValue::CSS_NUMBER) ? value : 0;
1342 inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(int id, CSSParserValue* value)
1345 return cssValuePool()->createIdentifierValue(id);
1346 if (value->unit == CSSPrimitiveValue::CSS_STRING)
1347 return createPrimitiveStringValue(value);
1348 if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1349 return createPrimitiveNumericValue(value);
1350 if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
1351 return createPrimitiveNumericValue(value);
1352 if (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN)
1353 return createPrimitiveNumericValue(value);
1354 if (value->unit >= CSSParserValue::Q_EMS)
1355 return CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS);
1356 if (isCalculation(value))
1357 return CSSPrimitiveValue::create(m_parsedCalculation.release());
1362 bool CSSParser::parseValue(int propId, bool important)
1367 CSSParserValue* value = m_valueList->current();
1372 // Note: m_parsedCalculation is used to pass the calc value to validUnit and then cleared at the end of this function.
1373 // FIXME: This is to avoid having to pass parsedCalc to all validUnit callers.
1374 ASSERT(!m_parsedCalculation);
1378 // In quirks mode, we will look for units that have been incorrectly separated from the number they belong to
1379 // by a space. We go ahead and associate the unit with the number even though it is invalid CSS.
1380 checkForOrphanedUnits();
1382 int num = inShorthand() ? 1 : m_valueList->size();
1384 if (id == CSSValueInherit) {
1387 addProperty(propId, cssValuePool()->createInheritedValue(), important);
1390 else if (id == CSSValueInitial) {
1393 addProperty(propId, cssValuePool()->createExplicitInitialValue(), important);
1397 if (isKeywordPropertyID(propId)) {
1398 if (!isValidKeywordPropertyAndValue(propId, id))
1400 if (m_valueList->next() && !inShorthand())
1402 addProperty(propId, cssValuePool()->createIdentifierValue(id), important);
1406 bool validPrimitive = false;
1407 RefPtr<CSSValue> parsedValue;
1409 switch (static_cast<CSSPropertyID>(propId)) {
1410 /* The comment to the left defines all valid value of this properties as defined
1411 * in CSS 2, Appendix F. Property index
1414 /* All the CSS properties are not supported by the renderer at the moment.
1415 * Note that all the CSS2 Aural properties are only checked, if CSS_AURAL is defined
1416 * (see parseAuralValues). As we don't support them at all this seems reasonable.
1419 case CSSPropertySize: // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
1420 return parseSize(propId, important);
1422 case CSSPropertyQuotes: // [<string> <string>]+ | none | inherit
1424 validPrimitive = true;
1426 return parseQuotes(propId, important);
1428 case CSSPropertyUnicodeBidi: // normal | embed | (bidi-override || isolate) | plaintext | inherit
1429 if (id == CSSValueNormal
1430 || id == CSSValueEmbed
1431 || id == CSSValueWebkitPlaintext)
1432 validPrimitive = true;
1434 RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
1435 bool isValid = true;
1436 while (isValid && value) {
1437 switch (value->id) {
1438 case CSSValueBidiOverride:
1439 case CSSValueWebkitIsolate:
1440 list->append(cssValuePool()->createIdentifierValue(value->id));
1445 value = m_valueList->next();
1447 if (list->length() && isValid) {
1448 parsedValue = list.release();
1449 m_valueList->next();
1454 case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right | inherit
1455 case CSSPropertyPageBreakBefore:
1456 case CSSPropertyWebkitColumnBreakAfter:
1457 case CSSPropertyWebkitColumnBreakBefore:
1458 case CSSPropertyWebkitRegionBreakAfter:
1459 case CSSPropertyWebkitRegionBreakBefore:
1460 if (id == CSSValueAuto
1461 || id == CSSValueAlways
1462 || id == CSSValueAvoid
1463 || id == CSSValueLeft
1464 || id == CSSValueRight)
1465 validPrimitive = ((propId == CSSPropertyWebkitRegionBreakAfter) || (propId == CSSPropertyWebkitRegionBreakBefore)) ? cssRegionsEnabled() : true;
1468 case CSSPropertyPageBreakInside: // avoid | auto | inherit
1469 case CSSPropertyWebkitColumnBreakInside:
1470 case CSSPropertyWebkitRegionBreakInside:
1471 if (id == CSSValueAuto || id == CSSValueAvoid)
1472 validPrimitive = (propId == CSSPropertyWebkitRegionBreakInside) ? cssRegionsEnabled() : true;
1475 case CSSPropertyContent: // [ <string> | <uri> | <counter> | attr(X) | open-quote |
1476 // close-quote | no-open-quote | no-close-quote ]+ | inherit
1477 return parseContent(propId, important);
1479 case CSSPropertyClip: // <shape> | auto | inherit
1480 if (id == CSSValueAuto)
1481 validPrimitive = true;
1482 else if (value->unit == CSSParserValue::Function)
1483 return parseClipShape(propId, important);
1486 /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
1487 * correctly and allows optimization in WebCore::applyRule(..)
1489 case CSSPropertyOverflow: {
1490 ShorthandScope scope(this, propId);
1491 if (num != 1 || !parseValue(CSSPropertyOverflowX, important))
1493 CSSValue* value = m_parsedProperties.last().value();
1494 addProperty(CSSPropertyOverflowY, value, important);
1498 case CSSPropertyTextAlign:
1499 // left | right | center | justify | webkit_left | webkit_right | webkit_center | webkit_match_parent |
1500 // start | end | <string> | inherit
1501 if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd
1502 || value->unit == CSSPrimitiveValue::CSS_STRING)
1503 validPrimitive = true;
1506 case CSSPropertyFontWeight: // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
1507 return parseFontWeight(important);
1509 case CSSPropertyBorderSpacing: {
1511 ShorthandScope scope(this, CSSPropertyBorderSpacing);
1512 if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important))
1514 CSSValue* value = m_parsedProperties.last().value();
1515 addProperty(CSSPropertyWebkitBorderVerticalSpacing, value, important);
1518 else if (num == 2) {
1519 ShorthandScope scope(this, CSSPropertyBorderSpacing);
1520 if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important) || !parseValue(CSSPropertyWebkitBorderVerticalSpacing, important))
1526 case CSSPropertyWebkitBorderHorizontalSpacing:
1527 case CSSPropertyWebkitBorderVerticalSpacing:
1528 validPrimitive = validUnit(value, FLength | FNonNeg);
1530 case CSSPropertyOutlineColor: // <color> | invert | inherit
1531 // Outline color has "invert" as additional keyword.
1532 // Also, we want to allow the special focus color even in strict parsing mode.
1533 if (id == CSSValueInvert || id == CSSValueWebkitFocusRingColor) {
1534 validPrimitive = true;
1538 case CSSPropertyBackgroundColor: // <color> | inherit
1539 case CSSPropertyBorderTopColor: // <color> | inherit
1540 case CSSPropertyBorderRightColor:
1541 case CSSPropertyBorderBottomColor:
1542 case CSSPropertyBorderLeftColor:
1543 case CSSPropertyWebkitBorderStartColor:
1544 case CSSPropertyWebkitBorderEndColor:
1545 case CSSPropertyWebkitBorderBeforeColor:
1546 case CSSPropertyWebkitBorderAfterColor:
1547 case CSSPropertyColor: // <color> | inherit
1548 case CSSPropertyTextLineThroughColor: // CSS3 text decoration colors
1549 case CSSPropertyTextUnderlineColor:
1550 case CSSPropertyTextOverlineColor:
1551 case CSSPropertyWebkitColumnRuleColor:
1552 case CSSPropertyWebkitTextEmphasisColor:
1553 case CSSPropertyWebkitTextFillColor:
1554 case CSSPropertyWebkitTextStrokeColor:
1555 if (id == CSSValueWebkitText)
1556 validPrimitive = true; // Always allow this, even when strict parsing is on,
1557 // since we use this in our UA sheets.
1558 else if (id == CSSValueCurrentcolor)
1559 validPrimitive = true;
1560 else if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu ||
1561 (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && inQuirksMode())) {
1562 validPrimitive = true;
1564 parsedValue = parseColor();
1566 m_valueList->next();
1570 case CSSPropertyCursor: {
1571 // [<uri>,]* [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
1572 // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize |
1573 // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help |
1574 // vertical-text | cell | context-menu | alias | copy | no-drop | not-allowed | -webkit-zoom-in
1575 // -webkit-zoom-out | all-scroll | -webkit-grab | -webkit-grabbing ] ] | inherit
1576 RefPtr<CSSValueList> list;
1577 while (value && value->unit == CSSPrimitiveValue::CSS_URI) {
1579 list = CSSValueList::createCommaSeparated();
1580 String uri = value->string;
1582 value = m_valueList->next();
1583 while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) {
1584 coords.append(int(value->fValue));
1585 value = m_valueList->next();
1587 IntPoint hotSpot(-1, -1);
1588 int nrcoords = coords.size();
1589 if (nrcoords > 0 && nrcoords != 2)
1592 hotSpot = IntPoint(coords[0], coords[1]);
1594 if (!uri.isNull() && m_styleSheet) {
1595 // FIXME: The completeURL call should be done when using the CSSCursorImageValue,
1596 // not when creating it.
1597 list->append(CSSCursorImageValue::create(m_styleSheet->completeURL(uri), hotSpot));
1600 if ((inStrictMode() && !value) || (value && !(value->unit == CSSParserValue::Operator && value->iValue == ',')))
1602 value = m_valueList->next(); // comma
1605 if (!value) { // no value after url list (MSIE 5 compatibility)
1606 if (list->length() != 1)
1608 } else if (inQuirksMode() && value->id == CSSValueHand) // MSIE 5 compatibility :/
1609 list->append(cssValuePool()->createIdentifierValue(CSSValuePointer));
1610 else if (value && ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone))
1611 list->append(cssValuePool()->createIdentifierValue(value->id));
1612 m_valueList->next();
1613 parsedValue = list.release();
1617 if (inQuirksMode() && value->id == CSSValueHand) { // MSIE 5 compatibility :/
1618 id = CSSValuePointer;
1619 validPrimitive = true;
1620 } else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)
1621 validPrimitive = true;
1625 case CSSPropertyBackgroundAttachment:
1626 case CSSPropertyBackgroundClip:
1627 case CSSPropertyWebkitBackgroundClip:
1628 case CSSPropertyWebkitBackgroundComposite:
1629 case CSSPropertyBackgroundImage:
1630 case CSSPropertyBackgroundOrigin:
1631 case CSSPropertyWebkitBackgroundOrigin:
1632 case CSSPropertyBackgroundPosition:
1633 case CSSPropertyBackgroundPositionX:
1634 case CSSPropertyBackgroundPositionY:
1635 case CSSPropertyBackgroundSize:
1636 case CSSPropertyWebkitBackgroundSize:
1637 case CSSPropertyBackgroundRepeat:
1638 case CSSPropertyBackgroundRepeatX:
1639 case CSSPropertyBackgroundRepeatY:
1640 case CSSPropertyWebkitMaskAttachment:
1641 case CSSPropertyWebkitMaskClip:
1642 case CSSPropertyWebkitMaskComposite:
1643 case CSSPropertyWebkitMaskImage:
1644 case CSSPropertyWebkitMaskOrigin:
1645 case CSSPropertyWebkitMaskPosition:
1646 case CSSPropertyWebkitMaskPositionX:
1647 case CSSPropertyWebkitMaskPositionY:
1648 case CSSPropertyWebkitMaskSize:
1649 case CSSPropertyWebkitMaskRepeat:
1650 case CSSPropertyWebkitMaskRepeatX:
1651 case CSSPropertyWebkitMaskRepeatY: {
1652 RefPtr<CSSValue> val1;
1653 RefPtr<CSSValue> val2;
1654 int propId1, propId2;
1655 bool result = false;
1656 if (parseFillProperty(propId, propId1, propId2, val1, val2)) {
1657 OwnPtr<ShorthandScope> shorthandScope;
1658 if (propId == CSSPropertyBackgroundPosition ||
1659 propId == CSSPropertyBackgroundRepeat ||
1660 propId == CSSPropertyWebkitMaskPosition ||
1661 propId == CSSPropertyWebkitMaskRepeat) {
1662 shorthandScope = adoptPtr(new ShorthandScope(this, propId));
1664 addProperty(propId1, val1.release(), important);
1666 addProperty(propId2, val2.release(), important);
1669 m_implicitShorthand = false;
1672 case CSSPropertyListStyleImage: // <uri> | none | inherit
1673 case CSSPropertyBorderImageSource:
1674 case CSSPropertyWebkitMaskBoxImageSource:
1675 if (id == CSSValueNone) {
1676 parsedValue = cssValuePool()->createIdentifierValue(CSSValueNone);
1677 m_valueList->next();
1678 } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
1680 // FIXME: The completeURL call should be done when using the CSSImageValue,
1681 // not when creating it.
1682 parsedValue = CSSImageValue::create(m_styleSheet->completeURL(value->string));
1683 m_valueList->next();
1685 } else if (isGeneratedImageValue(value)) {
1686 if (parseGeneratedImage(m_valueList.get(), parsedValue))
1687 m_valueList->next();
1691 #if ENABLE(CSS_IMAGE_SET)
1692 else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "-webkit-image-set(")) {
1693 parsedValue = parseImageSet(m_valueList.get());
1696 m_valueList->next();
1701 case CSSPropertyWebkitTextStrokeWidth:
1702 case CSSPropertyOutlineWidth: // <border-width> | inherit
1703 case CSSPropertyBorderTopWidth: //// <border-width> | inherit
1704 case CSSPropertyBorderRightWidth: // Which is defined as
1705 case CSSPropertyBorderBottomWidth: // thin | medium | thick | <length>
1706 case CSSPropertyBorderLeftWidth:
1707 case CSSPropertyWebkitBorderStartWidth:
1708 case CSSPropertyWebkitBorderEndWidth:
1709 case CSSPropertyWebkitBorderBeforeWidth:
1710 case CSSPropertyWebkitBorderAfterWidth:
1711 case CSSPropertyWebkitColumnRuleWidth:
1712 if (id == CSSValueThin || id == CSSValueMedium || id == CSSValueThick)
1713 validPrimitive = true;
1715 validPrimitive = validUnit(value, FLength | FNonNeg);
1718 case CSSPropertyLetterSpacing: // normal | <length> | inherit
1719 case CSSPropertyWordSpacing: // normal | <length> | inherit
1720 if (id == CSSValueNormal)
1721 validPrimitive = true;
1723 validPrimitive = validUnit(value, FLength);
1726 case CSSPropertyTextIndent: // <length> | <percentage> | inherit
1727 validPrimitive = (!id && validUnit(value, FLength | FPercent));
1730 case CSSPropertyPaddingTop: //// <padding-width> | inherit
1731 case CSSPropertyPaddingRight: // Which is defined as
1732 case CSSPropertyPaddingBottom: // <length> | <percentage>
1733 case CSSPropertyPaddingLeft: ////
1734 case CSSPropertyWebkitPaddingStart:
1735 case CSSPropertyWebkitPaddingEnd:
1736 case CSSPropertyWebkitPaddingBefore:
1737 case CSSPropertyWebkitPaddingAfter:
1738 validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg));
1741 case CSSPropertyMaxHeight: // <length> | <percentage> | none | inherit
1742 case CSSPropertyMaxWidth: // <length> | <percentage> | none | inherit
1743 case CSSPropertyWebkitMaxLogicalWidth:
1744 case CSSPropertyWebkitMaxLogicalHeight:
1745 if (id == CSSValueNone) {
1746 validPrimitive = true;
1750 case CSSPropertyMinHeight: // <length> | <percentage> | inherit
1751 case CSSPropertyMinWidth: // <length> | <percentage> | inherit
1752 case CSSPropertyWebkitMinLogicalWidth:
1753 case CSSPropertyWebkitMinLogicalHeight:
1754 if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
1755 validPrimitive = true;
1757 validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg));
1760 case CSSPropertyFontSize:
1761 // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
1762 if (id >= CSSValueXxSmall && id <= CSSValueLarger)
1763 validPrimitive = true;
1765 validPrimitive = (validUnit(value, FLength | FPercent | FNonNeg));
1768 case CSSPropertyFontVariant: // normal | small-caps | inherit
1769 return parseFontVariant(important);
1771 case CSSPropertyVerticalAlign:
1772 // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
1773 // <percentage> | <length> | inherit
1775 if (id >= CSSValueBaseline && id <= CSSValueWebkitBaselineMiddle)
1776 validPrimitive = true;
1778 validPrimitive = (!id && validUnit(value, FLength | FPercent));
1781 case CSSPropertyHeight: // <length> | <percentage> | auto | inherit
1782 case CSSPropertyWidth: // <length> | <percentage> | auto | inherit
1783 case CSSPropertyWebkitLogicalWidth:
1784 case CSSPropertyWebkitLogicalHeight:
1785 if (id == CSSValueAuto || id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
1786 validPrimitive = true;
1787 else if (!id && validUnit(value, FLength | FPercent | FNonNeg))
1788 // ### handle multilength case where we allow relative units
1789 validPrimitive = true;
1790 else if (value->unit == CSSParserValue::Function)
1791 return parseFlex(propId, important);
1794 case CSSPropertyBottom: // <length> | <percentage> | auto | inherit
1795 case CSSPropertyLeft: // <length> | <percentage> | auto | inherit
1796 case CSSPropertyRight: // <length> | <percentage> | auto | inherit
1797 case CSSPropertyTop: // <length> | <percentage> | auto | inherit
1798 case CSSPropertyMarginTop: //// <margin-width> | inherit
1799 case CSSPropertyMarginRight: // Which is defined as
1800 case CSSPropertyMarginBottom: // <length> | <percentage> | auto | inherit
1801 case CSSPropertyMarginLeft: ////
1802 case CSSPropertyWebkitMarginStart:
1803 case CSSPropertyWebkitMarginEnd:
1804 case CSSPropertyWebkitMarginBefore:
1805 case CSSPropertyWebkitMarginAfter:
1806 if (id == CSSValueAuto)
1807 validPrimitive = true;
1809 validPrimitive = (!id && validUnit(value, FLength | FPercent));
1812 case CSSPropertyZIndex: // auto | <integer> | inherit
1813 if (id == CSSValueAuto) {
1814 validPrimitive = true;
1818 case CSSPropertyOrphans: // <integer> | inherit
1819 case CSSPropertyWidows: // <integer> | inherit
1820 // ### not supported later on
1821 validPrimitive = (!id && validUnit(value, FInteger, CSSQuirksMode));
1824 case CSSPropertyLineHeight: // normal | <number> | <length> | <percentage> | inherit
1825 if (id == CSSValueNormal)
1826 validPrimitive = true;
1828 validPrimitive = (!id && validUnit(value, FNumber | FLength | FPercent | FNonNeg));
1830 case CSSPropertyCounterIncrement: // [ <identifier> <integer>? ]+ | none | inherit
1831 if (id != CSSValueNone)
1832 return parseCounter(propId, 1, important);
1833 validPrimitive = true;
1835 case CSSPropertyCounterReset: // [ <identifier> <integer>? ]+ | none | inherit
1836 if (id != CSSValueNone)
1837 return parseCounter(propId, 0, important);
1838 validPrimitive = true;
1840 case CSSPropertyFontFamily:
1841 // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
1843 parsedValue = parseFontFamily();
1847 case CSSPropertyTextDecoration:
1848 case CSSPropertyWebkitTextDecorationsInEffect:
1849 // none | [ underline || overline || line-through || blink ] | inherit
1850 if (id == CSSValueNone) {
1851 validPrimitive = true;
1853 RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
1854 bool isValid = true;
1855 while (isValid && value) {
1856 switch (value->id) {
1859 case CSSValueUnderline:
1860 case CSSValueOverline:
1861 case CSSValueLineThrough:
1862 list->append(cssValuePool()->createIdentifierValue(value->id));
1867 value = m_valueList->next();
1869 if (list->length() && isValid) {
1870 parsedValue = list.release();
1871 m_valueList->next();
1876 case CSSPropertyZoom: // normal | reset | document | <number> | <percentage> | inherit
1877 if (id == CSSValueNormal || id == CSSValueReset || id == CSSValueDocument)
1878 validPrimitive = true;
1880 validPrimitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg, CSSStrictMode));
1883 case CSSPropertySrc: // Only used within @font-face, so cannot use inherit | initial or be !important. This is a list of urls or local references.
1884 return parseFontFaceSrc();
1886 case CSSPropertyUnicodeRange:
1887 return parseFontFaceUnicodeRange();
1889 /* CSS3 properties */
1891 case CSSPropertyBorderImage: {
1892 RefPtr<CSSValue> result;
1893 return parseBorderImage(propId, result, important);
1895 case CSSPropertyWebkitBorderImage:
1896 case CSSPropertyWebkitMaskBoxImage: {
1897 RefPtr<CSSValue> result;
1898 if (parseBorderImage(propId, result)) {
1899 addProperty(propId, result, important);
1904 case CSSPropertyBorderImageOutset:
1905 case CSSPropertyWebkitMaskBoxImageOutset: {
1906 RefPtr<CSSPrimitiveValue> result;
1907 if (parseBorderImageOutset(result)) {
1908 addProperty(propId, result, important);
1913 case CSSPropertyBorderImageRepeat:
1914 case CSSPropertyWebkitMaskBoxImageRepeat: {
1915 RefPtr<CSSValue> result;
1916 if (parseBorderImageRepeat(result)) {
1917 addProperty(propId, result, important);
1922 case CSSPropertyBorderImageSlice:
1923 case CSSPropertyWebkitMaskBoxImageSlice: {
1924 RefPtr<CSSBorderImageSliceValue> result;
1925 if (parseBorderImageSlice(propId, result)) {
1926 addProperty(propId, result, important);
1931 case CSSPropertyBorderImageWidth:
1932 case CSSPropertyWebkitMaskBoxImageWidth: {
1933 RefPtr<CSSPrimitiveValue> result;
1934 if (parseBorderImageWidth(result)) {
1935 addProperty(propId, result, important);
1940 case CSSPropertyBorderTopRightRadius:
1941 case CSSPropertyBorderTopLeftRadius:
1942 case CSSPropertyBorderBottomLeftRadius:
1943 case CSSPropertyBorderBottomRightRadius: {
1944 if (num != 1 && num != 2)
1946 validPrimitive = validUnit(value, FLength | FPercent | FNonNeg);
1947 if (!validPrimitive)
1949 RefPtr<CSSPrimitiveValue> parsedValue1 = createPrimitiveNumericValue(value);
1950 RefPtr<CSSPrimitiveValue> parsedValue2;
1952 value = m_valueList->next();
1953 validPrimitive = validUnit(value, FLength | FPercent | FNonNeg);
1954 if (!validPrimitive)
1956 parsedValue2 = createPrimitiveNumericValue(value);
1958 parsedValue2 = parsedValue1;
1960 RefPtr<Pair> pair = Pair::create(parsedValue1.release(), parsedValue2.release());
1961 RefPtr<CSSPrimitiveValue> val = cssValuePool()->createValue(pair.release());
1962 addProperty(propId, val.release(), important);
1965 case CSSPropertyWebkitAspectRatio:
1966 return parseAspectRatio(important);
1967 case CSSPropertyBorderRadius:
1968 case CSSPropertyWebkitBorderRadius:
1969 return parseBorderRadius(propId, important);
1970 case CSSPropertyOutlineOffset:
1971 validPrimitive = validUnit(value, FLength | FPercent);
1973 case CSSPropertyTextShadow: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
1974 case CSSPropertyBoxShadow:
1975 case CSSPropertyWebkitBoxShadow:
1976 if (id == CSSValueNone)
1977 validPrimitive = true;
1979 RefPtr<CSSValueList> shadowValueList = parseShadow(m_valueList.get(), propId);
1980 if (shadowValueList) {
1981 addProperty(propId, shadowValueList.release(), important);
1982 m_valueList->next();
1988 case CSSPropertyWebkitBoxReflect:
1989 if (id == CSSValueNone)
1990 validPrimitive = true;
1992 return parseReflect(propId, important);
1994 case CSSPropertyOpacity:
1995 validPrimitive = validUnit(value, FNumber);
1997 case CSSPropertyWebkitBoxFlex:
1998 validPrimitive = validUnit(value, FNumber);
2000 case CSSPropertyWebkitBoxFlexGroup:
2001 case CSSPropertyWebkitBoxOrdinalGroup:
2002 validPrimitive = validUnit(value, FInteger | FNonNeg, CSSStrictMode);
2004 #if ENABLE(CSS_FILTERS)
2005 case CSSPropertyWebkitFilter:
2006 if (id == CSSValueNone)
2007 validPrimitive = true;
2009 RefPtr<CSSValue> val = parseFilter();
2011 addProperty(propId, val, important);
2018 case CSSPropertyWebkitFlexOrder:
2019 if (validUnit(value, FInteger, CSSStrictMode)) {
2020 // 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.
2021 parsedValue = cssValuePool()->createValue(max(static_cast<double>(std::numeric_limits<int>::min() + 2), value->fValue),
2022 static_cast<CSSPrimitiveValue::UnitTypes>(value->unit));
2023 m_valueList->next();
2026 case CSSPropertyWebkitMarquee:
2027 return parseShorthand(propId, webkitMarqueeShorthand(), important);
2028 case CSSPropertyWebkitMarqueeIncrement:
2029 if (id == CSSValueSmall || id == CSSValueLarge || id == CSSValueMedium)
2030 validPrimitive = true;
2032 validPrimitive = validUnit(value, FLength | FPercent);
2034 case CSSPropertyWebkitMarqueeRepetition:
2035 if (id == CSSValueInfinite)
2036 validPrimitive = true;
2038 validPrimitive = validUnit(value, FInteger | FNonNeg);
2040 case CSSPropertyWebkitMarqueeSpeed:
2041 if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast)
2042 validPrimitive = true;
2044 validPrimitive = validUnit(value, FTime | FInteger | FNonNeg);
2046 case CSSPropertyWebkitFlowInto:
2047 if (!cssRegionsEnabled())
2049 return parseFlowThread(propId, important);
2050 case CSSPropertyWebkitFlowFrom:
2051 if (!cssRegionsEnabled())
2053 return parseRegionThread(propId, important);
2054 case CSSPropertyWebkitRegionOverflow:
2055 if (cssRegionsEnabled() && (id == CSSValueAuto || id == CSSValueBreak))
2056 validPrimitive = true;
2058 case CSSPropertyWebkitTransform:
2059 if (id == CSSValueNone)
2060 validPrimitive = true;
2062 PassRefPtr<CSSValue> val = parseTransform();
2064 addProperty(propId, val, important);
2070 case CSSPropertyWebkitTransformOrigin:
2071 case CSSPropertyWebkitTransformOriginX:
2072 case CSSPropertyWebkitTransformOriginY:
2073 case CSSPropertyWebkitTransformOriginZ: {
2074 RefPtr<CSSValue> val1;
2075 RefPtr<CSSValue> val2;
2076 RefPtr<CSSValue> val3;
2077 int propId1, propId2, propId3;
2078 if (parseTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) {
2079 addProperty(propId1, val1.release(), important);
2081 addProperty(propId2, val2.release(), important);
2083 addProperty(propId3, val3.release(), important);
2088 case CSSPropertyWebkitPerspective:
2089 if (id == CSSValueNone)
2090 validPrimitive = true;
2092 // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property.
2093 if (validUnit(value, FNumber | FLength | FNonNeg)) {
2094 RefPtr<CSSValue> val = createPrimitiveNumericValue(value);
2096 addProperty(propId, val.release(), important);
2103 case CSSPropertyWebkitPerspectiveOrigin:
2104 case CSSPropertyWebkitPerspectiveOriginX:
2105 case CSSPropertyWebkitPerspectiveOriginY: {
2106 RefPtr<CSSValue> val1;
2107 RefPtr<CSSValue> val2;
2108 int propId1, propId2;
2109 if (parsePerspectiveOrigin(propId, propId1, propId2, val1, val2)) {
2110 addProperty(propId1, val1.release(), important);
2112 addProperty(propId2, val2.release(), important);
2117 case CSSPropertyWebkitAnimationDelay:
2118 case CSSPropertyWebkitAnimationDirection:
2119 case CSSPropertyWebkitAnimationDuration:
2120 case CSSPropertyWebkitAnimationFillMode:
2121 case CSSPropertyWebkitAnimationName:
2122 case CSSPropertyWebkitAnimationPlayState:
2123 case CSSPropertyWebkitAnimationIterationCount:
2124 case CSSPropertyWebkitAnimationTimingFunction:
2125 case CSSPropertyWebkitTransitionDelay:
2126 case CSSPropertyWebkitTransitionDuration:
2127 case CSSPropertyWebkitTransitionTimingFunction:
2128 case CSSPropertyWebkitTransitionProperty: {
2129 RefPtr<CSSValue> val;
2130 if (parseAnimationProperty(propId, val)) {
2131 addProperty(propId, val.release(), important);
2136 #if ENABLE(CSS_GRID_LAYOUT)
2137 case CSSPropertyWebkitGridColumns:
2138 case CSSPropertyWebkitGridRows:
2139 return parseGridTrackList(propId, important);
2141 case CSSPropertyWebkitGridColumn:
2142 case CSSPropertyWebkitGridRow:
2143 validPrimitive = id == CSSValueAuto || validUnit(value, FInteger);
2146 case CSSPropertyWebkitMarginCollapse: {
2148 ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2149 if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important))
2151 CSSValue* value = m_parsedProperties.last().value();
2152 addProperty(webkitMarginCollapseShorthand().properties()[1], value, important);
2155 else if (num == 2) {
2156 ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2157 if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important) || !parseValue(webkitMarginCollapseShorthand().properties()[1], important))
2163 case CSSPropertyTextLineThroughWidth:
2164 case CSSPropertyTextOverlineWidth:
2165 case CSSPropertyTextUnderlineWidth:
2166 if (id == CSSValueAuto || id == CSSValueNormal || id == CSSValueThin ||
2167 id == CSSValueMedium || id == CSSValueThick)
2168 validPrimitive = true;
2170 validPrimitive = !id && validUnit(value, FNumber | FLength | FPercent);
2172 case CSSPropertyWebkitColumnCount:
2173 if (id == CSSValueAuto)
2174 validPrimitive = true;
2176 validPrimitive = !id && validUnit(value, FInteger | FNonNeg, CSSQuirksMode);
2178 case CSSPropertyWebkitColumnGap: // normal | <length>
2179 if (id == CSSValueNormal)
2180 validPrimitive = true;
2182 validPrimitive = validUnit(value, FLength | FNonNeg);
2184 case CSSPropertyWebkitColumnAxis:
2185 if (id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto)
2186 validPrimitive = true;
2188 case CSSPropertyWebkitColumnSpan: // all | 1
2189 if (id == CSSValueAll)
2190 validPrimitive = true;
2192 validPrimitive = validUnit(value, FNumber | FNonNeg) && value->fValue == 1;
2194 case CSSPropertyWebkitColumnWidth: // auto | <length>
2195 if (id == CSSValueAuto)
2196 validPrimitive = true;
2197 else // Always parse this property in strict mode, since it would be ambiguous otherwise when used in the 'columns' shorthand property.
2198 validPrimitive = validUnit(value, FLength, CSSStrictMode);
2200 // End of CSS3 properties
2202 // Apple specific properties. These will never be standardized and are purely to
2203 // support custom WebKit-based Apple applications.
2204 case CSSPropertyWebkitLineClamp:
2205 // When specifying number of lines, don't allow 0 as a valid value
2206 // When specifying either type of unit, require non-negative integers
2207 validPrimitive = (!id && (value->unit == CSSPrimitiveValue::CSS_PERCENTAGE || value->fValue) && validUnit(value, FInteger | FPercent | FNonNeg, CSSQuirksMode));
2210 case CSSPropertyWebkitFontSizeDelta: // <length>
2211 validPrimitive = validUnit(value, FLength);
2214 case CSSPropertyWebkitHighlight:
2215 if (id == CSSValueNone || value->unit == CSSPrimitiveValue::CSS_STRING)
2216 validPrimitive = true;
2219 case CSSPropertyWebkitHyphenateCharacter:
2220 if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
2221 validPrimitive = true;
2224 case CSSPropertyWebkitHyphenateLimitBefore:
2225 case CSSPropertyWebkitHyphenateLimitAfter:
2226 if (id == CSSValueAuto || validUnit(value, FInteger | FNonNeg, CSSStrictMode))
2227 validPrimitive = true;
2230 case CSSPropertyWebkitHyphenateLimitLines:
2231 if (id == CSSValueNoLimit || validUnit(value, FInteger | FNonNeg, CSSStrictMode))
2232 validPrimitive = true;
2235 case CSSPropertyWebkitLineGrid:
2236 if (id == CSSValueNone)
2237 validPrimitive = true;
2238 else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
2239 String lineGridValue = String(value->string);
2240 if (!lineGridValue.isEmpty()) {
2241 addProperty(propId, cssValuePool()->createValue(lineGridValue, CSSPrimitiveValue::CSS_STRING), important);
2246 case CSSPropertyWebkitLocale:
2247 if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
2248 validPrimitive = true;
2251 #if ENABLE(DASHBOARD_SUPPORT)
2252 case CSSPropertyWebkitDashboardRegion: // <dashboard-region> | <dashboard-region>
2253 if (value->unit == CSSParserValue::Function || id == CSSValueNone)
2254 return parseDashboardRegions(propId, important);
2257 // End Apple-specific properties
2259 #if ENABLE(TOUCH_EVENTS)
2260 case CSSPropertyWebkitTapHighlightColor:
2261 if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu
2262 || (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && inQuirksMode())) {
2263 validPrimitive = true;
2265 parsedValue = parseColor();
2267 m_valueList->next();
2272 /* shorthand properties */
2273 case CSSPropertyBackground: {
2274 // Position must come before color in this array because a plain old "0" is a legal color
2275 // in quirks mode but it's usually the X coordinate of a position.
2276 // FIXME: Add CSSPropertyBackgroundSize to the shorthand.
2277 const CSSPropertyID properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat,
2278 CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyBackgroundOrigin,
2279 CSSPropertyBackgroundClip, CSSPropertyBackgroundColor };
2280 return parseFillShorthand(propId, properties, 7, important);
2282 case CSSPropertyWebkitMask: {
2283 const CSSPropertyID properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
2284 CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition,
2285 CSSPropertyWebkitMaskOrigin, CSSPropertyWebkitMaskClip };
2286 return parseFillShorthand(propId, properties, 6, important);
2288 case CSSPropertyBorder:
2289 // [ 'border-width' || 'border-style' || <color> ] | inherit
2291 if (parseShorthand(propId, borderAbridgedShorthand(), important)) {
2292 // The CSS3 Borders and Backgrounds specification says that border also resets border-image. It's as
2293 // though a value of none was specified for the image.
2294 addProperty(CSSPropertyBorderImage, cssValuePool()->createImplicitInitialValue(), important);
2299 case CSSPropertyBorderTop:
2300 // [ 'border-top-width' || 'border-style' || <color> ] | inherit
2301 return parseShorthand(propId, borderTopShorthand(), important);
2302 case CSSPropertyBorderRight:
2303 // [ 'border-right-width' || 'border-style' || <color> ] | inherit
2304 return parseShorthand(propId, borderRightShorthand(), important);
2305 case CSSPropertyBorderBottom:
2306 // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
2307 return parseShorthand(propId, borderBottomShorthand(), important);
2308 case CSSPropertyBorderLeft:
2309 // [ 'border-left-width' || 'border-style' || <color> ] | inherit
2310 return parseShorthand(propId, borderLeftShorthand(), important);
2311 case CSSPropertyWebkitBorderStart:
2312 return parseShorthand(propId, webkitBorderStartShorthand(), important);
2313 case CSSPropertyWebkitBorderEnd:
2314 return parseShorthand(propId, webkitBorderEndShorthand(), important);
2315 case CSSPropertyWebkitBorderBefore:
2316 return parseShorthand(propId, webkitBorderBeforeShorthand(), important);
2317 case CSSPropertyWebkitBorderAfter:
2318 return parseShorthand(propId, webkitBorderAfterShorthand(), important);
2319 case CSSPropertyOutline:
2320 // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
2321 return parseShorthand(propId, outlineShorthand(), important);
2322 case CSSPropertyBorderColor:
2323 // <color>{1,4} | inherit
2324 return parse4Values(propId, borderColorShorthand().properties(), important);
2325 case CSSPropertyBorderWidth:
2326 // <border-width>{1,4} | inherit
2327 return parse4Values(propId, borderWidthShorthand().properties(), important);
2328 case CSSPropertyBorderStyle:
2329 // <border-style>{1,4} | inherit
2330 return parse4Values(propId, borderStyleShorthand().properties(), important);
2331 case CSSPropertyMargin:
2332 // <margin-width>{1,4} | inherit
2333 return parse4Values(propId, marginShorthand().properties(), important);
2334 case CSSPropertyPadding:
2335 // <padding-width>{1,4} | inherit
2336 return parse4Values(propId, paddingShorthand().properties(), important);
2337 case CSSPropertyWebkitFlexFlow:
2338 return parseShorthand(propId, webkitFlexFlowShorthand(), important);
2339 case CSSPropertyFont:
2340 // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
2341 // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
2342 if (id >= CSSValueCaption && id <= CSSValueStatusBar)
2343 validPrimitive = true;
2345 return parseFont(important);
2347 case CSSPropertyListStyle:
2348 return parseShorthand(propId, listStyleShorthand(), important);
2349 case CSSPropertyWebkitColumns:
2350 return parseShorthand(propId, webkitColumnsShorthand(), important);
2351 case CSSPropertyWebkitColumnRule:
2352 return parseShorthand(propId, webkitColumnRuleShorthand(), important);
2353 case CSSPropertyWebkitTextStroke:
2354 return parseShorthand(propId, webkitTextStrokeShorthand(), important);
2355 case CSSPropertyWebkitAnimation:
2356 return parseAnimationShorthand(important);
2357 case CSSPropertyWebkitTransition:
2358 return parseTransitionShorthand(important);
2359 case CSSPropertyInvalid:
2361 case CSSPropertyPage:
2362 return parsePage(propId, important);
2363 case CSSPropertyFontStretch:
2364 case CSSPropertyTextLineThrough:
2365 case CSSPropertyTextOverline:
2366 case CSSPropertyTextUnderline:
2368 // CSS Text Layout Module Level 3: Vertical writing support
2369 case CSSPropertyWebkitTextEmphasis:
2370 return parseShorthand(propId, webkitTextEmphasisShorthand(), important);
2372 case CSSPropertyWebkitTextEmphasisStyle:
2373 return parseTextEmphasisStyle(important);
2375 case CSSPropertyWebkitTextOrientation:
2376 // FIXME: For now just support upright and vertical-right.
2377 if (id == CSSValueVerticalRight || id == CSSValueUpright)
2378 validPrimitive = true;
2381 case CSSPropertyWebkitLineBoxContain:
2382 if (id == CSSValueNone)
2383 validPrimitive = true;
2385 return parseLineBoxContain(important);
2387 case CSSPropertyWebkitFontFeatureSettings:
2388 if (id == CSSValueNormal)
2389 validPrimitive = true;
2391 return parseFontFeatureSettings(important);
2394 case CSSPropertyWebkitFontVariantLigatures:
2395 if (id == CSSValueNormal)
2396 validPrimitive = true;
2398 return parseFontVariantLigatures(important);
2401 case CSSPropertyWebkitShapeInside:
2402 case CSSPropertyWebkitShapeOutside:
2403 if (id == CSSValueAuto)
2404 validPrimitive = true;
2405 else if (value->unit == CSSParserValue::Function)
2406 return parseExclusionShape((propId == CSSPropertyWebkitShapeInside), important);
2408 case CSSPropertyWebkitWrapMargin:
2409 case CSSPropertyWebkitWrapPadding:
2410 validPrimitive = (!id && validUnit(value, FLength | FNonNeg));
2412 case CSSPropertyWebkitWrap:
2413 return parseShorthand(propId, webkitWrapShorthand(), important);
2414 case CSSPropertyBorderBottomStyle:
2415 case CSSPropertyBorderCollapse:
2416 case CSSPropertyBorderLeftStyle:
2417 case CSSPropertyBorderRightStyle:
2418 case CSSPropertyBorderTopStyle:
2419 case CSSPropertyBoxSizing:
2420 case CSSPropertyCaptionSide:
2421 case CSSPropertyClear:
2422 case CSSPropertyDirection:
2423 case CSSPropertyDisplay:
2424 case CSSPropertyEmptyCells:
2425 case CSSPropertyFloat:
2426 case CSSPropertyFontStyle:
2427 case CSSPropertyImageRendering:
2428 case CSSPropertyListStylePosition:
2429 case CSSPropertyListStyleType:
2430 case CSSPropertyOutlineStyle:
2431 case CSSPropertyOverflowX:
2432 case CSSPropertyOverflowY:
2433 case CSSPropertyPointerEvents:
2434 case CSSPropertyPosition:
2435 case CSSPropertyResize:
2436 case CSSPropertySpeak:
2437 case CSSPropertyTableLayout:
2438 case CSSPropertyTextLineThroughMode:
2439 case CSSPropertyTextLineThroughStyle:
2440 case CSSPropertyTextOverflow:
2441 case CSSPropertyTextOverlineMode:
2442 case CSSPropertyTextOverlineStyle:
2443 case CSSPropertyTextRendering:
2444 case CSSPropertyTextTransform:
2445 case CSSPropertyTextUnderlineMode:
2446 case CSSPropertyTextUnderlineStyle:
2447 case CSSPropertyVisibility:
2448 case CSSPropertyWebkitAppearance:
2449 case CSSPropertyWebkitBackfaceVisibility:
2450 case CSSPropertyWebkitBorderAfterStyle:
2451 case CSSPropertyWebkitBorderBeforeStyle:
2452 case CSSPropertyWebkitBorderEndStyle:
2453 case CSSPropertyWebkitBorderFit:
2454 case CSSPropertyWebkitBorderStartStyle:
2455 case CSSPropertyWebkitBoxAlign:
2456 case CSSPropertyWebkitBoxDirection:
2457 case CSSPropertyWebkitBoxLines:
2458 case CSSPropertyWebkitBoxOrient:
2459 case CSSPropertyWebkitBoxPack:
2460 case CSSPropertyWebkitColorCorrection:
2461 case CSSPropertyWebkitColumnRuleStyle:
2462 case CSSPropertyWebkitFlexAlign:
2463 case CSSPropertyWebkitFlexDirection:
2464 case CSSPropertyWebkitFlexItemAlign:
2465 case CSSPropertyWebkitFlexLinePack:
2466 case CSSPropertyWebkitFlexPack:
2467 case CSSPropertyWebkitFlexWrap:
2468 case CSSPropertyWebkitFontKerning:
2469 case CSSPropertyWebkitFontSmoothing:
2470 case CSSPropertyWebkitHyphens:
2471 case CSSPropertyWebkitLineAlign:
2472 case CSSPropertyWebkitLineBreak:
2473 case CSSPropertyWebkitLineSnap:
2474 case CSSPropertyWebkitMarginAfterCollapse:
2475 case CSSPropertyWebkitMarginBeforeCollapse:
2476 case CSSPropertyWebkitMarginBottomCollapse:
2477 case CSSPropertyWebkitMarginTopCollapse:
2478 case CSSPropertyWebkitMarqueeDirection:
2479 case CSSPropertyWebkitMarqueeStyle:
2480 case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
2481 case CSSPropertyWebkitNbspMode:
2482 #if ENABLE(OVERFLOW_SCROLLING)
2483 case CSSPropertyWebkitOverflowScrolling:
2485 case CSSPropertyWebkitPrintColorAdjust:
2486 case CSSPropertyWebkitRtlOrdering:
2487 case CSSPropertyWebkitTextCombine:
2488 case CSSPropertyWebkitTextEmphasisPosition:
2489 case CSSPropertyWebkitTextSecurity:
2490 case CSSPropertyWebkitTextSizeAdjust:
2491 case CSSPropertyWebkitTransformStyle:
2492 case CSSPropertyWebkitUserDrag:
2493 case CSSPropertyWebkitUserModify:
2494 case CSSPropertyWebkitUserSelect:
2495 case CSSPropertyWebkitWrapFlow:
2496 case CSSPropertyWebkitWrapThrough:
2497 case CSSPropertyWebkitWritingMode:
2498 case CSSPropertyWhiteSpace:
2499 case CSSPropertyWordBreak:
2500 case CSSPropertyWordWrap:
2501 // These properties should be handled before in isValidKeywordPropertyAndValue().
2502 ASSERT_NOT_REACHED();
2506 return parseSVGValue(propId, important);
2510 if (validPrimitive) {
2511 parsedValue = parseValidPrimitive(id, value);
2512 m_valueList->next();
2514 ASSERT(!m_parsedCalculation);
2516 if (!m_valueList->current() || inShorthand()) {
2517 addProperty(propId, parsedValue.release(), important);
2524 void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
2527 if (lval->isValueList())
2528 static_cast<CSSValueList*>(lval.get())->append(rval);
2530 PassRefPtr<CSSValue> oldlVal(lval.release());
2531 PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2532 list->append(oldlVal);
2541 static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue, CSSValuePool* cssValuePool)
2543 if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox
2544 || parserValue->id == CSSValueContentBox || parserValue->id == CSSValueWebkitText) {
2545 cssValue = cssValuePool->createIdentifierValue(parserValue->id);
2551 const int cMaxFillProperties = 9;
2553 bool CSSParser::parseFillShorthand(int propId, const CSSPropertyID* properties, int numProperties, bool important)
2555 ASSERT(numProperties <= cMaxFillProperties);
2556 if (numProperties > cMaxFillProperties)
2559 ShorthandScope scope(this, propId);
2561 bool parsedProperty[cMaxFillProperties] = { false };
2562 RefPtr<CSSValue> values[cMaxFillProperties];
2563 RefPtr<CSSValue> clipValue;
2564 RefPtr<CSSValue> positionYValue;
2565 RefPtr<CSSValue> repeatYValue;
2566 bool foundClip = false;
2569 while (m_valueList->current()) {
2570 CSSParserValue* val = m_valueList->current();
2571 if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2572 // We hit the end. Fill in all remaining values with the initial value.
2573 m_valueList->next();
2574 for (i = 0; i < numProperties; ++i) {
2575 if (properties[i] == CSSPropertyBackgroundColor && parsedProperty[i])
2576 // Color is not allowed except as the last item in a list for backgrounds.
2577 // Reject the entire property.
2580 if (!parsedProperty[i] && properties[i] != CSSPropertyBackgroundColor) {
2581 addFillValue(values[i], cssValuePool()->createImplicitInitialValue());
2582 if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2583 addFillValue(positionYValue, cssValuePool()->createImplicitInitialValue());
2584 if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2585 addFillValue(repeatYValue, cssValuePool()->createImplicitInitialValue());
2586 if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
2587 // If background-origin wasn't present, then reset background-clip also.
2588 addFillValue(clipValue, cssValuePool()->createImplicitInitialValue());
2591 parsedProperty[i] = false;
2593 if (!m_valueList->current())
2598 for (i = 0; !found && i < numProperties; ++i) {
2599 if (!parsedProperty[i]) {
2600 RefPtr<CSSValue> val1;
2601 RefPtr<CSSValue> val2;
2602 int propId1, propId2;
2603 CSSParserValue* parserValue = m_valueList->current();
2604 if (parseFillProperty(properties[i], propId1, propId2, val1, val2)) {
2605 parsedProperty[i] = found = true;
2606 addFillValue(values[i], val1.release());
2607 if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2608 addFillValue(positionYValue, val2.release());
2609 if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2610 addFillValue(repeatYValue, val2.release());
2611 if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
2612 // Reparse the value as a clip, and see if we succeed.
2613 if (parseBackgroundClip(parserValue, val1, cssValuePool()))
2614 addFillValue(clipValue, val1.release()); // The property parsed successfully.
2616 addFillValue(clipValue, cssValuePool()->createImplicitInitialValue()); // Some value was used for origin that is not supported by clip. Just reset clip instead.
2618 if (properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) {
2620 addFillValue(clipValue, val1.release());
2627 // if we didn't find at least one match, this is an
2628 // invalid shorthand and we have to ignore it
2633 // Now add all of the properties we found.
2634 for (i = 0; i < numProperties; i++) {
2635 // Fill in any remaining properties with the initial value.
2636 if (!parsedProperty[i]) {
2637 addFillValue(values[i], cssValuePool()->createImplicitInitialValue());
2638 if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2639 addFillValue(positionYValue, cssValuePool()->createImplicitInitialValue());
2640 if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2641 addFillValue(repeatYValue, cssValuePool()->createImplicitInitialValue());
2642 if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin)) {
2643 // If background-origin wasn't present, then reset background-clip also.
2644 addFillValue(clipValue, cssValuePool()->createImplicitInitialValue());
2647 if (properties[i] == CSSPropertyBackgroundPosition) {
2648 addProperty(CSSPropertyBackgroundPositionX, values[i].release(), important);
2649 // it's OK to call positionYValue.release() since we only see CSSPropertyBackgroundPosition once
2650 addProperty(CSSPropertyBackgroundPositionY, positionYValue.release(), important);
2651 } else if (properties[i] == CSSPropertyWebkitMaskPosition) {
2652 addProperty(CSSPropertyWebkitMaskPositionX, values[i].release(), important);
2653 // it's OK to call positionYValue.release() since we only see CSSPropertyWebkitMaskPosition once
2654 addProperty(CSSPropertyWebkitMaskPositionY, positionYValue.release(), important);
2655 } else if (properties[i] == CSSPropertyBackgroundRepeat) {
2656 addProperty(CSSPropertyBackgroundRepeatX, values[i].release(), important);
2657 // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2658 addProperty(CSSPropertyBackgroundRepeatY, repeatYValue.release(), important);
2659 } else if (properties[i] == CSSPropertyWebkitMaskRepeat) {
2660 addProperty(CSSPropertyWebkitMaskRepeatX, values[i].release(), important);
2661 // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2662 addProperty(CSSPropertyWebkitMaskRepeatY, repeatYValue.release(), important);
2663 } else if ((properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) && !foundClip)
2664 // Value is already set while updating origin
2667 addProperty(properties[i], values[i].release(), important);
2669 // Add in clip values when we hit the corresponding origin property.
2670 if (properties[i] == CSSPropertyBackgroundOrigin && !foundClip)
2671 addProperty(CSSPropertyBackgroundClip, clipValue.release(), important);
2672 else if (properties[i] == CSSPropertyWebkitMaskOrigin && !foundClip)
2673 addProperty(CSSPropertyWebkitMaskClip, clipValue.release(), important);
2679 void CSSParser::addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
2682 if (lval->isValueList())
2683 static_cast<CSSValueList*>(lval.get())->append(rval);
2685 PassRefPtr<CSSValue> oldVal(lval.release());
2686 PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2687 list->append(oldVal);
2696 bool CSSParser::parseAnimationShorthand(bool important)
2698 const unsigned numProperties = webkitAnimationShorthand().length();
2699 ShorthandScope scope(this, CSSPropertyWebkitAnimation);
2701 bool parsedProperty[] = { false, false, false, false, false, false, false };
2702 RefPtr<CSSValue> values[7];
2705 unsigned initialParsedPropertyIndex = 0;
2706 while (m_valueList->current()) {
2707 CSSParserValue* val = m_valueList->current();
2708 if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2709 // We hit the end. Fill in all remaining values with the initial value.
2710 initialParsedPropertyIndex = 0;
2711 m_valueList->next();
2712 for (i = 0; i < numProperties; ++i) {
2713 if (!parsedProperty[i])
2714 addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
2715 parsedProperty[i] = false;
2717 if (!m_valueList->current())
2722 for (i = initialParsedPropertyIndex; !found && i < numProperties; ++i) {
2723 if (!parsedProperty[i]) {
2724 RefPtr<CSSValue> val;
2725 if (parseAnimationProperty(webkitAnimationShorthand().properties()[i], val)) {
2726 parsedProperty[i] = found = true;
2727 initialParsedPropertyIndex = 1;
2728 addAnimationValue(values[i], val.release());
2733 // if we didn't find at least one match, this is an
2734 // invalid shorthand and we have to ignore it
2739 // Fill in any remaining properties with the initial value.
2740 for (i = 0; i < numProperties; ++i) {
2741 if (!parsedProperty[i])
2742 addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
2745 // Now add all of the properties we found.
2746 for (i = 0; i < numProperties; i++)
2747 addProperty(webkitAnimationShorthand().properties()[i], values[i].release(), important);
2752 bool CSSParser::parseTransitionShorthand(bool important)
2754 const unsigned numProperties = webkitTransitionShorthand().length();
2756 ShorthandScope scope(this, CSSPropertyWebkitTransition);
2758 bool parsedProperty[] = { false, false, false, false };
2759 RefPtr<CSSValue> values[4];
2762 while (m_valueList->current()) {
2763 CSSParserValue* val = m_valueList->current();
2764 if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2765 // We hit the end. Fill in all remaining values with the initial value.
2766 m_valueList->next();
2767 for (i = 0; i < numProperties; ++i) {
2768 if (!parsedProperty[i])
2769 addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
2770 parsedProperty[i] = false;
2772 if (!m_valueList->current())
2777 for (i = 0; !found && i < numProperties; ++i) {
2778 if (!parsedProperty[i]) {
2779 RefPtr<CSSValue> val;
2780 if (parseAnimationProperty(webkitTransitionShorthand().properties()[i], val)) {
2781 parsedProperty[i] = found = true;
2782 addAnimationValue(values[i], val.release());
2787 // if we didn't find at least one match, this is an
2788 // invalid shorthand and we have to ignore it
2793 // Fill in any remaining properties with the initial value.
2794 for (i = 0; i < numProperties; ++i) {
2795 if (!parsedProperty[i])
2796 addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
2799 // Now add all of the properties we found.
2800 for (i = 0; i < numProperties; i++)
2801 addProperty(webkitTransitionShorthand().properties()[i], values[i].release(), important);
2806 bool CSSParser::parseShorthand(int propId, const StylePropertyShorthand& shorthand, bool important)
2808 // We try to match as many properties as possible
2809 // We set up an array of booleans to mark which property has been found,
2810 // and we try to search for properties until it makes no longer any sense.
2811 ShorthandScope scope(this, propId);
2814 unsigned propertiesParsed = 0;
2815 bool propertyFound[6]= { false, false, false, false, false, false }; // 6 is enough size.
2817 while (m_valueList->current()) {
2819 for (unsigned propIndex = 0; !found && propIndex < shorthand.length(); ++propIndex) {
2820 if (!propertyFound[propIndex] && parseValue(shorthand.properties()[propIndex], important)) {
2821 propertyFound[propIndex] = found = true;
2826 // if we didn't find at least one match, this is an
2827 // invalid shorthand and we have to ignore it
2832 if (propertiesParsed == shorthand.length())
2835 // Fill in any remaining properties with the initial value.
2836 ImplicitScope implicitScope(this, PropertyImplicit);
2837 const StylePropertyShorthand* const* const propertiesForInitialization = shorthand.propertiesForInitialization();
2838 for (unsigned i = 0; i < shorthand.length(); ++i) {
2839 if (propertyFound[i])
2842 if (propertiesForInitialization) {
2843 const StylePropertyShorthand& initProperties = *(propertiesForInitialization[i]);
2844 for (unsigned propIndex = 0; propIndex < initProperties.length(); ++propIndex)
2845 addProperty(initProperties.properties()[propIndex], cssValuePool()->createImplicitInitialValue(), important);
2847 addProperty(shorthand.properties()[i], cssValuePool()->createImplicitInitialValue(), important);
2853 bool CSSParser::parse4Values(int propId, const CSSPropertyID *properties, bool important)
2855 /* From the CSS 2 specs, 8.3
2856 * If there is only one value, it applies to all sides. If there are two values, the top and
2857 * bottom margins are set to the first value and the right and left margins are set to the second.
2858 * If there are three values, the top is set to the first value, the left and right are set to the
2859 * second, and the bottom is set to the third. If there are four values, they apply to the top,
2860 * right, bottom, and left, respectively.
2863 int num = inShorthand() ? 1 : m_valueList->size();
2865 ShorthandScope scope(this, propId);
2867 // the order is top, right, bottom, left
2870 if (!parseValue(properties[0], important))
2872 CSSValue *value = m_parsedProperties.last().value();
2873 ImplicitScope implicitScope(this, PropertyImplicit);
2874 addProperty(properties[1], value, important);
2875 addProperty(properties[2], value, important);
2876 addProperty(properties[3], value, important);
2880 if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
2882 CSSValue *value = m_parsedProperties[m_parsedProperties.size() - 2].value();
2883 ImplicitScope implicitScope(this, PropertyImplicit);
2884 addProperty(properties[2], value, important);
2885 value = m_parsedProperties[m_parsedProperties.size() - 2].value();
2886 addProperty(properties[3], value, important);
2890 if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
2892 CSSValue *value = m_parsedProperties[m_parsedProperties.size() - 2].value();
2893 ImplicitScope implicitScope(this, PropertyImplicit);
2894 addProperty(properties[3], value, important);
2898 if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
2899 !parseValue(properties[2], important) || !parseValue(properties[3], important))
2911 // auto | <identifier>
2912 bool CSSParser::parsePage(int propId, bool important)
2914 ASSERT(propId == CSSPropertyPage);
2916 if (m_valueList->size() != 1)
2919 CSSParserValue* value = m_valueList->current();
2923 if (value->id == CSSValueAuto) {
2924 addProperty(propId, cssValuePool()->createIdentifierValue(value->id), important);
2926 } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) {
2927 addProperty(propId, createPrimitiveStringValue(value), important);
2933 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
2934 bool CSSParser::parseSize(int propId, bool important)
2936 ASSERT(propId == CSSPropertySize);
2938 if (m_valueList->size() > 2)
2941 CSSParserValue* value = m_valueList->current();
2945 RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
2948 SizeParameterType paramType = parseSizeParameter(parsedValues.get(), value, None);
2949 if (paramType == None)
2952 // Second parameter, if any.
2953 value = m_valueList->next();
2955 paramType = parseSizeParameter(parsedValues.get(), value, paramType);
2956 if (paramType == None)
2960 addProperty(propId, parsedValues.release(), important);
2964 CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType)
2966 switch (value->id) {
2968 if (prevParamType == None) {
2969 parsedValues->append(cssValuePool()->createIdentifierValue(value->id));
2973 case CSSValueLandscape:
2974 case CSSValuePortrait:
2975 if (prevParamType == None || prevParamType == PageSize) {
2976 parsedValues->append(cssValuePool()->createIdentifierValue(value->id));
2985 case CSSValueLedger:
2987 case CSSValueLetter:
2988 if (prevParamType == None || prevParamType == Orientation) {
2989 // Normalize to Page Size then Orientation order by prepending.
2990 // This is not specified by the CSS3 Paged Media specification, but for simpler processing later (CSSStyleSelector::applyPageSizeProperty).
2991 parsedValues->prepend(cssValuePool()->createIdentifierValue(value->id));
2996 if (validUnit(value, FLength | FNonNeg) && (prevParamType == None || prevParamType == Length)) {
2997 parsedValues->append(createPrimitiveNumericValue(value));
3006 // [ <string> <string> ]+ | inherit | none
3007 // inherit and none are handled in parseValue.
3008 bool CSSParser::parseQuotes(int propId, bool important)
3010 RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3011 while (CSSParserValue* val = m_valueList->current()) {
3012 RefPtr<CSSValue> parsedValue;
3013 if (val->unit == CSSPrimitiveValue::CSS_STRING)
3014 parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING);
3017 values->append(parsedValue.release());
3018 m_valueList->next();
3020 if (values->length()) {
3021 addProperty(propId, values.release(), important);
3022 m_valueList->next();
3028 // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
3029 // in CSS 2.1 this got somewhat reduced:
3030 // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
3031 bool CSSParser::parseContent(int propId, bool important)
3033 RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3035 while (CSSParserValue* val = m_valueList->current()) {
3036 RefPtr<CSSValue> parsedValue;
3037 if (val->unit == CSSPrimitiveValue::CSS_URI && m_styleSheet) {
3039 // FIXME: The completeURL call should be done when using the CSSImageValue,
3040 // not when creating it.
3041 parsedValue = CSSImageValue::create(m_styleSheet->completeURL(val->string));
3042 } else if (val->unit == CSSParserValue::Function) {
3043 // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) | -webkit-gradient(...)
3044 CSSParserValueList* args = val->function->args.get();
3047 if (equalIgnoringCase(val->function->name, "attr(")) {
3048 parsedValue = parseAttr(args);
3051 } else if (equalIgnoringCase(val->function->name, "counter(")) {
3052 parsedValue = parseCounterContent(args, false);
3055 } else if (equalIgnoringCase(val->function->name, "counters(")) {
3056 parsedValue = parseCounterContent(args, true);
3059 #if ENABLE(CSS_IMAGE_SET)
3060 } else if (equalIgnoringCase(val->function->name, "-webkit-image-set(")) {
3061 parsedValue = parseImageSet(m_valueList.get());
3065 } else if (isGeneratedImageValue(val)) {
3066 if (!parseGeneratedImage(m_valueList.get(), parsedValue))
3070 } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
3076 // FIXME: These are not yet implemented (http://bugs.webkit.org/show_bug.cgi?id=6503).
3080 case CSSValueOpenQuote:
3081 case CSSValueCloseQuote:
3082 case CSSValueNoOpenQuote:
3083 case CSSValueNoCloseQuote:
3085 case CSSValueNormal:
3086 parsedValue = cssValuePool()->createIdentifierValue(val->id);
3088 } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
3089 parsedValue = createPrimitiveStringValue(val);
3093 values->append(parsedValue.release());
3094 m_valueList->next();
3097 if (values->length()) {
3098 addProperty(propId, values.release(), important);
3099 m_valueList->next();
3106 PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args)
3108 if (args->size() != 1)
3111 CSSParserValue* a = args->current();
3113 if (a->unit != CSSPrimitiveValue::CSS_IDENT)
3116 String attrName = a->string;
3117 // CSS allows identifiers with "-" at the start, like "-webkit-mask-image".
3118 // But HTML attribute names can't have those characters, and we should not
3119 // even parse them inside attr().
3120 if (attrName[0] == '-')
3123 Document* document = findDocument();
3124 if (document && document->isHTMLDocument())
3125 attrName = attrName.lower();
3127 return cssValuePool()->createValue(attrName, CSSPrimitiveValue::CSS_ATTR);
3130 PassRefPtr<CSSValue> CSSParser::parseBackgroundColor()
3132 int id = m_valueList->current()->id;
3133 if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor ||
3134 (id >= CSSValueGrey && id < CSSValueWebkitText && inQuirksMode()))
3135 return cssValuePool()->createIdentifierValue(id);
3136 return parseColor();
3139 bool CSSParser::parseFillImage(CSSParserValueList* valueList, RefPtr<CSSValue>& value)
3141 if (valueList->current()->id == CSSValueNone) {
3142 value = cssValuePool()->createIdentifierValue(CSSValueNone);
3145 if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
3146 // FIXME: The completeURL call should be done when using the CSSImageValue,
3147 // not when creating it.
3149 value = CSSImageValue::create(m_styleSheet->completeURL(valueList->current()->string));
3153 if (isGeneratedImageValue(valueList->current()))
3154 return parseGeneratedImage(valueList, value);
3156 #if ENABLE(CSS_IMAGE_SET)
3157 if (valueList->current()->unit == CSSParserValue::Function && equalIgnoringCase(valueList->current()->function->name, "-webkit-image-set(")) {
3158 value = parseImageSet(m_valueList.get());
3167 PassRefPtr<CSSValue> CSSParser::parseFillPositionX(CSSParserValueList* valueList)
3169 int id = valueList->current()->id;
3170 if (id == CSSValueLeft || id == CSSValueRight || id == CSSValueCenter) {
3172 if (id == CSSValueRight)
3174 else if (id == CSSValueCenter)
3176 return cssValuePool()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3178 if (validUnit(valueList->current(), FPercent | FLength))
3179 return createPrimitiveNumericValue(valueList->current());
3183 PassRefPtr<CSSValue> CSSParser::parseFillPositionY(CSSParserValueList* valueList)
3185 int id = valueList->current()->id;
3186 if (id == CSSValueTop || id == CSSValueBottom || id == CSSValueCenter) {
3188 if (id == CSSValueBottom)
3190 else if (id == CSSValueCenter)
3192 return cssValuePool()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3194 if (validUnit(valueList->current(), FPercent | FLength))
3195 return createPrimitiveNumericValue(valueList->current());
3199 PassRefPtr<CSSValue> CSSParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag)
3201 int id = valueList->current()->id;
3202 if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
3204 if (id == CSSValueLeft || id == CSSValueRight) {
3205 if (cumulativeFlags & XFillPosition)
3207 cumulativeFlags |= XFillPosition;
3208 individualFlag = XFillPosition;
3209 if (id == CSSValueRight)
3212 else if (id == CSSValueTop || id == CSSValueBottom) {
3213 if (cumulativeFlags & YFillPosition)
3215 cumulativeFlags |= YFillPosition;
3216 individualFlag = YFillPosition;
3217 if (id == CSSValueBottom)
3219 } else if (id == CSSValueCenter) {
3220 // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
3222 cumulativeFlags |= AmbiguousFillPosition;
3223 individualFlag = AmbiguousFillPosition;
3225 return cssValuePool()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3227 if (validUnit(valueList->current(), FPercent | FLength)) {
3228 if (!cumulativeFlags) {
3229 cumulativeFlags |= XFillPosition;
3230 individualFlag = XFillPosition;
3231 } else if (cumulativeFlags & (XFillPosition | AmbiguousFillPosition)) {
3232 cumulativeFlags |= YFillPosition;
3233 individualFlag = YFillPosition;
3235 if (m_parsedCalculation)
3236 m_parsedCalculation.release();
3239 return createPrimitiveNumericValue(valueList->current());
3244 void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
3246 CSSParserValue* value = valueList->current();
3248 // Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length.
3249 unsigned cumulativeFlags = 0;
3250 FillPositionFlag value1Flag = InvalidFillPosition;
3251 FillPositionFlag value2Flag = InvalidFillPosition;
3252 value1 = parseFillPositionComponent(valueList, cumulativeFlags, value1Flag);
3256 // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
3257 // can assume that any other values belong to the rest of the shorthand). If we're not parsing a shorthand, though, the
3258 // value was explicitly specified for our property.
3259 value = valueList->next();
3261 // First check for the comma. If so, we are finished parsing this value or value pair.
3262 if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
3266 value2 = parseFillPositionComponent(valueList, cumulativeFlags, value2Flag);
3270 if (!inShorthand()) {
3278 // Only one value was specified. If that value was not a keyword, then it sets the x position, and the y position
3279 // is simply 50%. This is our default.
3280 // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
3281 // For left/right/center, the default of 50% in the y is still correct.
3282 value2 = cssValuePool()->createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
3284 if (value1Flag == YFillPosition || value2Flag == XFillPosition)
3285 value1.swap(value2);
3288 void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
3290 CSSParserValue* value = m_valueList->current();
3292 int id = m_valueList->current()->id;
3293 if (id == CSSValueRepeatX) {
3294 m_implicitShorthand = true;
3295 value1 = cssValuePool()->createIdentifierValue(CSSValueRepeat);
3296 value2 = cssValuePool()->createIdentifierValue(CSSValueNoRepeat);
3297 m_valueList->next();
3300 if (id == CSSValueRepeatY) {
3301 m_implicitShorthand = true;
3302 value1 = cssValuePool()->createIdentifierValue(CSSValueNoRepeat);
3303 value2 = cssValuePool()->createIdentifierValue(CSSValueRepeat);
3304 m_valueList->next();
3307 if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)
3308 value1 = cssValuePool()->createIdentifierValue(id);
3314 value = m_valueList->next();
3316 // First check for the comma. If so, we are finished parsing this value or value pair.
3317 if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
3321 id = m_valueList->current()->id;
3323 if (value && (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)) {
3324 value2 = cssValuePool()->createIdentifierValue(id);
3325 m_valueList->next();
3327 // If only one value was specified, value2 is the same as value1.
3328 m_implicitShorthand = true;
3329 value2 = cssValuePool()->createIdentifierValue(static_cast<CSSPrimitiveValue*>(value1.get())->getIdent());
3333 PassRefPtr<CSSValue> CSSParser::parseFillSize(int propId, bool& allowComma)
3336 CSSParserValue* value = m_valueList->current();
3338 if (value->id == CSSValueContain || value->id == CSSValueCover)
3339 return cssValuePool()->createIdentifierValue(value->id);
3341 RefPtr<CSSPrimitiveValue> parsedValue1;
3343 if (value->id == CSSValueAuto)
3344 parsedValue1 = cssValuePool()->createIdentifierValue(CSSValueAuto);
3346 if (!validUnit(value, FLength | FPercent))
3348 parsedValue1 = createPrimitiveNumericValue(value);
3351 CSSPropertyID property = static_cast<CSSPropertyID>(propId);
3352 RefPtr<CSSPrimitiveValue> parsedValue2;
3353 if ((value = m_valueList->next())) {
3354 if (value->unit == CSSParserValue::Operator && value->iValue == ',')
3356 else if (value->id != CSSValueAuto) {
3357 if (!validUnit(value, FLength | FPercent))
3359 parsedValue2 = createPrimitiveNumericValue(value);
3361 } else if (!parsedValue2 && property == CSSPropertyWebkitBackgroundSize) {
3362 // For backwards compatibility we set the second value to the first if it is omitted.
3363 // We only need to do this for -webkit-background-size. It should be safe to let masks match
3364 // the real property.
3365 parsedValue2 = parsedValue1;
3369 return parsedValue1;
3370 return cssValuePool()->createValue(Pair::create(parsedValue1.release(), parsedValue2.release()));