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 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/)
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
26 #include "CSSParser.h"
28 #include "CSSBorderImageValue.h"
29 #include "CSSCanvasValue.h"
30 #include "CSSCharsetRule.h"
31 #include "CSSCursorImageValue.h"
32 #include "CSSFontFaceRule.h"
33 #include "CSSFontFaceSrcValue.h"
34 #include "CSSGradientValue.h"
35 #include "CSSImageValue.h"
36 #include "CSSImportRule.h"
37 #include "CSSInheritedValue.h"
38 #include "CSSInitialValue.h"
39 #include "CSSMediaRule.h"
40 #include "CSSMutableStyleDeclaration.h"
41 #include "CSSPageRule.h"
42 #include "CSSPrimitiveValue.h"
43 #include "CSSPrimitiveValueCache.h"
44 #include "CSSProperty.h"
45 #include "CSSPropertyNames.h"
46 #include "CSSPropertySourceData.h"
47 #include "CSSQuirkPrimitiveValue.h"
48 #include "CSSReflectValue.h"
49 #include "CSSRuleList.h"
50 #include "CSSSelector.h"
51 #include "CSSStyleRule.h"
52 #include "CSSStyleSheet.h"
53 #include "CSSTimingFunctionValue.h"
54 #include "CSSUnicodeRangeValue.h"
55 #include "CSSValueKeywords.h"
56 #include "CSSValueList.h"
59 #include "FloatConversion.h"
60 #include "FontFamilyValue.h"
61 #include "FontValue.h"
62 #include "HTMLParserIdioms.h"
63 #include "HashTools.h"
64 #include "MediaList.h"
65 #include "MediaQueryExp.h"
69 #include "RenderTheme.h"
70 #include "ShadowValue.h"
71 #include "WebKitCSSKeyframeRule.h"
72 #include "WebKitCSSKeyframesRule.h"
73 #include "WebKitCSSTransformValue.h"
76 #include <wtf/text/StringBuffer.h>
78 #if ENABLE(DASHBOARD_SUPPORT)
79 #include "DashboardRegion.h"
85 extern int cssyydebug;
88 extern int cssyyparse(void* parser);
95 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
97 static bool equal(const CSSParserString& a, const char* b)
99 for (int i = 0; i < a.length; ++i) {
102 if (a.characters[i] != b[i])
108 static bool equalIgnoringCase(const CSSParserString& a, const char* b)
110 for (int i = 0; i < a.length; ++i) {
113 ASSERT(!isASCIIUpper(b[i]));
114 if (toASCIILower(a.characters[i]) != b[i])
120 static bool hasPrefix(const char* string, unsigned length, const char* prefix)
122 for (unsigned i = 0; i < length; ++i) {
125 if (string[i] != prefix[i])
131 CSSParser::CSSParser(bool strictParsing)
132 : m_strict(strictParsing)
137 , m_parsedProperties(static_cast<CSSProperty**>(fastMalloc(32 * sizeof(CSSProperty*))))
138 , m_numParsedProperties(0)
139 , m_maxParsedProperties(32)
140 , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
141 , m_inParseShorthand(0)
142 , m_currentShorthand(0)
143 , m_implicitShorthand(false)
144 , m_hasFontFaceOnlyValues(false)
145 , m_hadSyntacticallyValidCSSRule(false)
146 , m_defaultNamespace(starAtom)
147 , m_inStyleRuleOrDeclaration(false)
148 , m_selectorListRange(0, 0)
149 , m_ruleBodyRange(0, 0)
150 , m_propertyRange(UINT_MAX, UINT_MAX)
152 , m_currentRuleData(0)
156 , m_lastSelectorLineNumber(0)
157 , m_allowImportRules(true)
158 , m_allowNamespaceDeclarations(true)
163 CSSPropertySourceData::init();
166 CSSParser::~CSSParser()
169 fastFree(m_parsedProperties);
175 fastDeleteAllValues(m_floatingSelectors);
176 deleteAllValues(m_floatingValueLists);
177 deleteAllValues(m_floatingFunctions);
180 void CSSParserString::lower()
182 // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
183 // that can potentially change the length of the string rather than the character
184 // by character kind. If we don't need Unicode lowercasing, it would be good to
185 // simplify this function.
187 if (charactersAreAllASCII(characters, length)) {
188 // Fast case for all-ASCII.
189 for (int i = 0; i < length; i++)
190 characters[i] = toASCIILower(characters[i]);
192 for (int i = 0; i < length; i++)
193 characters[i] = Unicode::toLower(characters[i]);
197 void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix)
199 int length = string.length() + strlen(prefix) + strlen(suffix) + 2;
202 m_data = static_cast<UChar*>(fastMalloc(length * sizeof(UChar)));
203 for (unsigned i = 0; i < strlen(prefix); i++)
204 m_data[i] = prefix[i];
206 memcpy(m_data + strlen(prefix), string.characters(), string.length() * sizeof(UChar));
208 unsigned start = strlen(prefix) + string.length();
209 unsigned end = start + strlen(suffix);
210 for (unsigned i = start; i < end; i++)
211 m_data[i] = suffix[i - start];
213 m_data[length - 1] = 0;
214 m_data[length - 2] = 0;
218 yytext = yy_c_buf_p = m_data;
219 yy_hold_char = *yy_c_buf_p;
220 resetRuleBodyMarks();
223 void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string, int startLineNumber, StyleRuleRangeMap* ruleRangeMap)
225 setStyleSheet(sheet);
226 m_defaultNamespace = starAtom; // Reset the default namespace.
227 m_ruleRangeMap = ruleRangeMap;
229 m_currentRuleData = CSSRuleSourceData::create();
230 m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
233 m_lineNumber = startLineNumber;
234 setupParser("", string, "");
237 m_currentRuleData = 0;
241 PassRefPtr<CSSRule> CSSParser::parseRule(CSSStyleSheet* sheet, const String& string)
243 setStyleSheet(sheet);
244 m_allowNamespaceDeclarations = false;
245 setupParser("@-webkit-rule{", string, "} ");
247 return m_rule.release();
250 PassRefPtr<CSSRule> CSSParser::parseKeyframeRule(CSSStyleSheet *sheet, const String &string)
252 setStyleSheet(sheet);
253 setupParser("@-webkit-keyframe-rule{ ", string, "} ");
255 return m_keyframe.release();
258 bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int id, const String& string, bool important)
260 ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet());
261 setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet()));
263 setupParser("@-webkit-value{", string, "} ");
266 m_important = important;
273 if (m_hasFontFaceOnlyValues)
274 deleteFontFaceOnlyValues();
275 if (m_numParsedProperties) {
277 declaration->addParsedProperties(m_parsedProperties, m_numParsedProperties);
284 // color will only be changed when string contains a valid css color, making it
285 // possible to set up a default color.
286 bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict)
288 // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
289 if (parseColor(string, color, strict))
292 CSSParser parser(true);
293 RefPtr<CSSMutableStyleDeclaration> dummyStyleDeclaration = CSSMutableStyleDeclaration::create();
295 // Now try to create a color from rgba() syntax.
296 if (!parser.parseColor(dummyStyleDeclaration.get(), string))
299 CSSValue* value = parser.m_parsedProperties[0]->value();
300 if (value->cssValueType() != CSSValue::CSS_PRIMITIVE_VALUE)
303 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
304 if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_RGBCOLOR)
307 color = primitiveValue->getRGBA32Value();
311 bool CSSParser::parseColor(CSSMutableStyleDeclaration* declaration, const String& string)
313 ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet());
314 setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet()));
316 setupParser("@-webkit-decls{color:", string, "} ");
320 return (m_numParsedProperties && m_parsedProperties[0]->m_id == CSSPropertyColor);
323 bool CSSParser::parseSystemColor(RGBA32& color, const String& string, Document* document)
325 if (!document || !document->page())
328 CSSParserString cssColor;
329 cssColor.characters = const_cast<UChar*>(string.characters());
330 cssColor.length = string.length();
331 int id = cssValueKeywordID(cssColor);
335 color = document->page()->theme()->systemColor(id).rgb();
339 void CSSParser::parseSelector(const String& string, Document* doc, CSSSelectorList& selectorList)
341 RefPtr<CSSStyleSheet> dummyStyleSheet = CSSStyleSheet::create(doc);
343 setStyleSheet(dummyStyleSheet.get());
344 m_selectorListForParseSelector = &selectorList;
346 setupParser("@-webkit-selector{", string, "}");
350 m_selectorListForParseSelector = 0;
352 // The style sheet will be deleted right away, so it won't outlive the document.
353 ASSERT(dummyStyleSheet->hasOneRef());
356 bool CSSParser::parseDeclaration(CSSMutableStyleDeclaration* declaration, const String& string, RefPtr<CSSStyleSourceData>* styleSourceData)
358 // Length of the "@-webkit-decls{" prefix.
359 static const unsigned prefixLength = 15;
361 ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet());
362 setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet()));
363 if (styleSourceData) {
364 m_currentRuleData = CSSRuleSourceData::create();
365 m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
366 m_inStyleRuleOrDeclaration = true;
369 setupParser("@-webkit-decls{", string, "} ");
374 if (m_hasFontFaceOnlyValues)
375 deleteFontFaceOnlyValues();
376 if (m_numParsedProperties) {
378 declaration->addParsedProperties(m_parsedProperties, m_numParsedProperties);
382 if (m_currentRuleData) {
383 m_currentRuleData->styleSourceData->styleBodyRange.start = 0;
384 m_currentRuleData->styleSourceData->styleBodyRange.end = string.length();
385 for (Vector<CSSPropertySourceData>::iterator it = m_currentRuleData->styleSourceData->propertyData.begin(), endIt = m_currentRuleData->styleSourceData->propertyData.end(); it != endIt; ++it) {
386 (*it).range.start -= prefixLength;
387 (*it).range.end -= prefixLength;
391 if (styleSourceData) {
392 *styleSourceData = m_currentRuleData->styleSourceData.release();
393 m_currentRuleData = 0;
394 m_inStyleRuleOrDeclaration = false;
399 bool CSSParser::parseMediaQuery(MediaList* queries, const String& string)
401 if (string.isEmpty())
404 ASSERT(!m_mediaQuery);
406 // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
407 // instead insert one " " (which is WHITESPACE in CSSGrammar.y)
408 setupParser("@-webkit-mediaquery ", string, "} ");
414 queries->appendMediaQuery(m_mediaQuery.release());
421 void CSSParser::addProperty(int propId, PassRefPtr<CSSValue> value, bool important)
423 OwnPtr<CSSProperty> prop(new CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand));
424 if (m_numParsedProperties >= m_maxParsedProperties) {
425 m_maxParsedProperties += 32;
426 if (m_maxParsedProperties > UINT_MAX / sizeof(CSSProperty*))
428 m_parsedProperties = static_cast<CSSProperty**>(fastRealloc(m_parsedProperties,
429 m_maxParsedProperties * sizeof(CSSProperty*)));
431 m_parsedProperties[m_numParsedProperties++] = prop.leakPtr();
434 void CSSParser::rollbackLastProperties(int num)
437 ASSERT(m_numParsedProperties >= static_cast<unsigned>(num));
439 for (int i = 0; i < num; ++i)
440 delete m_parsedProperties[--m_numParsedProperties];
443 void CSSParser::clearProperties()
445 for (unsigned i = 0; i < m_numParsedProperties; i++)
446 delete m_parsedProperties[i];
447 m_numParsedProperties = 0;
448 m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
449 m_hasFontFaceOnlyValues = false;
452 void CSSParser::setStyleSheet(CSSStyleSheet* styleSheet)
454 m_styleSheet = styleSheet;
455 m_primitiveValueCache = document() ? document()->cssPrimitiveValueCache() : CSSPrimitiveValueCache::create();
458 Document* CSSParser::document() const
460 StyleBase* root = m_styleSheet;
461 while (root && root->parent())
462 root = root->parent();
465 if (!root->isCSSStyleSheet())
467 return static_cast<CSSStyleSheet*>(root)->document();
470 bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, bool strict)
473 switch (value->unit) {
474 case CSSPrimitiveValue::CSS_NUMBER:
475 b = (unitflags & FNumber);
476 if (!b && ((unitflags & (FLength | FAngle | FTime)) && (value->fValue == 0 || !strict))) {
477 value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX :
478 ((unitflags & FAngle) ? CSSPrimitiveValue::CSS_DEG : CSSPrimitiveValue::CSS_MS);
481 if (!b && (unitflags & FInteger) && value->isInt)
484 case CSSPrimitiveValue::CSS_PERCENTAGE:
485 b = (unitflags & FPercent);
487 case CSSParserValue::Q_EMS:
488 case CSSPrimitiveValue::CSS_EMS:
489 case CSSPrimitiveValue::CSS_REMS:
490 case CSSPrimitiveValue::CSS_EXS:
491 case CSSPrimitiveValue::CSS_PX:
492 case CSSPrimitiveValue::CSS_CM:
493 case CSSPrimitiveValue::CSS_MM:
494 case CSSPrimitiveValue::CSS_IN:
495 case CSSPrimitiveValue::CSS_PT:
496 case CSSPrimitiveValue::CSS_PC:
497 b = (unitflags & FLength);
499 case CSSPrimitiveValue::CSS_MS:
500 case CSSPrimitiveValue::CSS_S:
501 b = (unitflags & FTime);
503 case CSSPrimitiveValue::CSS_DEG:
504 case CSSPrimitiveValue::CSS_RAD:
505 case CSSPrimitiveValue::CSS_GRAD:
506 case CSSPrimitiveValue::CSS_TURN:
507 b = (unitflags & FAngle);
509 case CSSPrimitiveValue::CSS_HZ:
510 case CSSPrimitiveValue::CSS_KHZ:
511 case CSSPrimitiveValue::CSS_DIMENSION:
515 if (b && unitflags & FNonNeg && value->fValue < 0)
520 static int unitFromString(CSSParserValue* value)
522 if (value->unit != CSSPrimitiveValue::CSS_IDENT || value->id)
525 if (equal(value->string, "em"))
526 return CSSPrimitiveValue::CSS_EMS;
527 if (equal(value->string, "rem"))
528 return CSSPrimitiveValue::CSS_REMS;
529 if (equal(value->string, "ex"))
530 return CSSPrimitiveValue::CSS_EXS;
531 if (equal(value->string, "px"))
532 return CSSPrimitiveValue::CSS_PX;
533 if (equal(value->string, "cm"))
534 return CSSPrimitiveValue::CSS_CM;
535 if (equal(value->string, "mm"))
536 return CSSPrimitiveValue::CSS_MM;
537 if (equal(value->string, "in"))
538 return CSSPrimitiveValue::CSS_IN;
539 if (equal(value->string, "pt"))
540 return CSSPrimitiveValue::CSS_PT;
541 if (equal(value->string, "pc"))
542 return CSSPrimitiveValue::CSS_PC;
543 if (equal(value->string, "deg"))
544 return CSSPrimitiveValue::CSS_DEG;
545 if (equal(value->string, "rad"))
546 return CSSPrimitiveValue::CSS_RAD;
547 if (equal(value->string, "grad"))
548 return CSSPrimitiveValue::CSS_GRAD;
549 if (equal(value->string, "turn"))
550 return CSSPrimitiveValue::CSS_TURN;
551 if (equal(value->string, "ms"))
552 return CSSPrimitiveValue::CSS_MS;
553 if (equal(value->string, "s"))
554 return CSSPrimitiveValue::CSS_S;
555 if (equal(value->string, "Hz"))
556 return CSSPrimitiveValue::CSS_HZ;
557 if (equal(value->string, "kHz"))
558 return CSSPrimitiveValue::CSS_KHZ;
563 void CSSParser::checkForOrphanedUnits()
565 if (m_strict || inShorthand())
568 // The purpose of this code is to implement the WinIE quirk that allows unit types to be separated from their numeric values
569 // 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.
570 CSSParserValue* numericVal = 0;
571 unsigned size = m_valueList->size();
572 for (unsigned i = 0; i < size; i++) {
573 CSSParserValue* value = m_valueList->valueAt(i);
576 // Change the unit type of the numeric val to match.
577 int unit = unitFromString(value);
579 numericVal->unit = unit;
582 // Now delete the bogus unit value.
583 m_valueList->deleteValueAt(i);
584 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).
590 numericVal = (value->unit == CSSPrimitiveValue::CSS_NUMBER) ? value : 0;
594 bool CSSParser::parseValue(int propId, bool important)
599 CSSParserValue* value = m_valueList->current();
606 // In quirks mode, we will look for units that have been incorrectly separated from the number they belong to
607 // by a space. We go ahead and associate the unit with the number even though it is invalid CSS.
608 checkForOrphanedUnits();
610 int num = inShorthand() ? 1 : m_valueList->size();
612 if (id == CSSValueInherit) {
615 addProperty(propId, CSSInheritedValue::create(), important);
618 else if (id == CSSValueInitial) {
621 addProperty(propId, CSSInitialValue::createExplicit(), important);
625 bool validPrimitive = false;
626 RefPtr<CSSValue> parsedValue;
628 switch (static_cast<CSSPropertyID>(propId)) {
629 /* The comment to the left defines all valid value of this properties as defined
630 * in CSS 2, Appendix F. Property index
633 /* All the CSS properties are not supported by the renderer at the moment.
634 * Note that all the CSS2 Aural properties are only checked, if CSS_AURAL is defined
635 * (see parseAuralValues). As we don't support them at all this seems reasonable.
638 case CSSPropertySize: // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
639 return parseSize(propId, important);
641 case CSSPropertyQuotes: // [<string> <string>]+ | none | inherit
643 validPrimitive = true;
645 return parseQuotes(propId, important);
647 case CSSPropertyUnicodeBidi: // normal | embed | bidi-override | inherit
648 if (id == CSSValueNormal ||
649 id == CSSValueEmbed ||
650 id == CSSValueBidiOverride)
651 validPrimitive = true;
654 case CSSPropertyPosition: // static | relative | absolute | fixed | inherit
655 if (id == CSSValueStatic ||
656 id == CSSValueRelative ||
657 id == CSSValueAbsolute ||
659 validPrimitive = true;
662 case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right | inherit
663 case CSSPropertyPageBreakBefore:
664 case CSSPropertyWebkitColumnBreakAfter:
665 case CSSPropertyWebkitColumnBreakBefore:
666 if (id == CSSValueAuto ||
667 id == CSSValueAlways ||
668 id == CSSValueAvoid ||
669 id == CSSValueLeft ||
671 validPrimitive = true;
674 case CSSPropertyPageBreakInside: // avoid | auto | inherit
675 case CSSPropertyWebkitColumnBreakInside:
676 if (id == CSSValueAuto || id == CSSValueAvoid)
677 validPrimitive = true;
680 case CSSPropertyEmptyCells: // show | hide | inherit
681 if (id == CSSValueShow ||
683 validPrimitive = true;
686 case CSSPropertyContent: // [ <string> | <uri> | <counter> | attr(X) | open-quote |
687 // close-quote | no-open-quote | no-close-quote ]+ | inherit
688 return parseContent(propId, important);
690 case CSSPropertyWhiteSpace: // normal | pre | nowrap | inherit
691 if (id == CSSValueNormal ||
693 id == CSSValuePreWrap ||
694 id == CSSValuePreLine ||
695 id == CSSValueNowrap)
696 validPrimitive = true;
699 case CSSPropertyClip: // <shape> | auto | inherit
700 if (id == CSSValueAuto)
701 validPrimitive = true;
702 else if (value->unit == CSSParserValue::Function)
703 return parseShape(propId, important);
706 /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
707 * correctly and allows optimization in WebCore::applyRule(..)
709 case CSSPropertyCaptionSide: // top | bottom | left | right | inherit
710 if (id == CSSValueLeft || id == CSSValueRight ||
711 id == CSSValueTop || id == CSSValueBottom)
712 validPrimitive = true;
715 case CSSPropertyBorderCollapse: // collapse | separate | inherit
716 if (id == CSSValueCollapse || id == CSSValueSeparate)
717 validPrimitive = true;
720 case CSSPropertyVisibility: // visible | hidden | collapse | inherit
721 if (id == CSSValueVisible || id == CSSValueHidden || id == CSSValueCollapse)
722 validPrimitive = true;
725 case CSSPropertyOverflow: {
726 ShorthandScope scope(this, propId);
727 if (num != 1 || !parseValue(CSSPropertyOverflowX, important))
729 CSSValue* value = m_parsedProperties[m_numParsedProperties - 1]->value();
730 addProperty(CSSPropertyOverflowY, value, important);
733 case CSSPropertyOverflowX:
734 case CSSPropertyOverflowY: // visible | hidden | scroll | auto | marquee | overlay | inherit
735 if (id == CSSValueVisible || id == CSSValueHidden || id == CSSValueScroll || id == CSSValueAuto ||
736 id == CSSValueOverlay || id == CSSValueWebkitMarquee)
737 validPrimitive = true;
740 case CSSPropertyListStylePosition: // inside | outside | inherit
741 if (id == CSSValueInside || id == CSSValueOutside)
742 validPrimitive = true;
745 case CSSPropertyListStyleType:
746 // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
747 // for the list of supported list-style-types.
748 if ((id >= CSSValueDisc && id <= CSSValueKatakanaIroha) || id == CSSValueNone)
749 validPrimitive = true;
752 case CSSPropertyDisplay:
753 // inline | block | list-item | run-in | inline-block | table |
754 // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
755 // table-column-group | table-column | table-cell | table-caption | box | inline-box | none | inherit
757 if ((id >= CSSValueInline && id <= CSSValueWapMarquee) || id == CSSValueNone)
759 if ((id >= CSSValueInline && id <= CSSValueWebkitInlineBox) || id == CSSValueNone)
761 validPrimitive = true;
764 case CSSPropertyDirection: // ltr | rtl | inherit
765 if (id == CSSValueLtr || id == CSSValueRtl)
766 validPrimitive = true;
769 case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none | inherit
770 if ((id >= CSSValueCapitalize && id <= CSSValueLowercase) || id == CSSValueNone)
771 validPrimitive = true;
774 case CSSPropertyFloat: // left | right | none | inherit + center for buggy CSS
775 if (id == CSSValueLeft || id == CSSValueRight ||
776 id == CSSValueNone || id == CSSValueCenter)
777 validPrimitive = true;
780 case CSSPropertyClear: // none | left | right | both | inherit
781 if (id == CSSValueNone || id == CSSValueLeft ||
782 id == CSSValueRight|| id == CSSValueBoth)
783 validPrimitive = true;
786 case CSSPropertyTextAlign:
787 // left | right | center | justify | webkit_left | webkit_right | webkit_center | start | end | <string> | inherit
788 if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitCenter) || id == CSSValueStart || id == CSSValueEnd ||
789 value->unit == CSSPrimitiveValue::CSS_STRING)
790 validPrimitive = true;
793 case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto | inherit
794 if (id == CSSValueAuto || id == CSSValueNone || (id >= CSSValueInset && id <= CSSValueDouble))
795 validPrimitive = true;
798 case CSSPropertyBorderTopStyle: //// <border-style> | inherit
799 case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
800 case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
801 case CSSPropertyBorderLeftStyle:
802 case CSSPropertyWebkitBorderStartStyle:
803 case CSSPropertyWebkitBorderEndStyle:
804 case CSSPropertyWebkitBorderBeforeStyle:
805 case CSSPropertyWebkitBorderAfterStyle:
806 case CSSPropertyWebkitColumnRuleStyle:
807 if (id >= CSSValueNone && id <= CSSValueDouble)
808 validPrimitive = true;
811 case CSSPropertyFontWeight: // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
812 return parseFontWeight(important);
814 case CSSPropertyBorderSpacing: {
815 const int properties[2] = { CSSPropertyWebkitBorderHorizontalSpacing,
816 CSSPropertyWebkitBorderVerticalSpacing };
818 ShorthandScope scope(this, CSSPropertyBorderSpacing);
819 if (!parseValue(properties[0], important))
821 CSSValue* value = m_parsedProperties[m_numParsedProperties-1]->value();
822 addProperty(properties[1], value, important);
826 ShorthandScope scope(this, CSSPropertyBorderSpacing);
827 if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
833 case CSSPropertyWebkitBorderHorizontalSpacing:
834 case CSSPropertyWebkitBorderVerticalSpacing:
835 validPrimitive = validUnit(value, FLength | FNonNeg, m_strict);
837 case CSSPropertyOutlineColor: // <color> | invert | inherit
838 // Outline color has "invert" as additional keyword.
839 // Also, we want to allow the special focus color even in strict parsing mode.
840 if (id == CSSValueInvert || id == CSSValueWebkitFocusRingColor) {
841 validPrimitive = true;
845 case CSSPropertyBackgroundColor: // <color> | inherit
846 case CSSPropertyBorderTopColor: // <color> | inherit
847 case CSSPropertyBorderRightColor:
848 case CSSPropertyBorderBottomColor:
849 case CSSPropertyBorderLeftColor:
850 case CSSPropertyWebkitBorderStartColor:
851 case CSSPropertyWebkitBorderEndColor:
852 case CSSPropertyWebkitBorderBeforeColor:
853 case CSSPropertyWebkitBorderAfterColor:
854 case CSSPropertyColor: // <color> | inherit
855 case CSSPropertyTextLineThroughColor: // CSS3 text decoration colors
856 case CSSPropertyTextUnderlineColor:
857 case CSSPropertyTextOverlineColor:
858 case CSSPropertyWebkitColumnRuleColor:
859 case CSSPropertyWebkitTextEmphasisColor:
860 case CSSPropertyWebkitTextFillColor:
861 case CSSPropertyWebkitTextStrokeColor:
862 if (id == CSSValueWebkitText)
863 validPrimitive = true; // Always allow this, even when strict parsing is on,
864 // since we use this in our UA sheets.
865 else if (id == CSSValueCurrentcolor)
866 validPrimitive = true;
867 else if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu ||
868 (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && !m_strict)) {
869 validPrimitive = true;
871 parsedValue = parseColor();
877 case CSSPropertyCursor: {
878 // [<uri>,]* [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
879 // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize |
880 // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help |
881 // vertical-text | cell | context-menu | alias | copy | no-drop | not-allowed | -webkit-zoom-in
882 // -webkit-zoom-out | all-scroll | -webkit-grab | -webkit-grabbing ] ] | inherit
883 RefPtr<CSSValueList> list;
884 while (value && value->unit == CSSPrimitiveValue::CSS_URI) {
886 list = CSSValueList::createCommaSeparated();
887 String uri = value->string;
889 value = m_valueList->next();
890 while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) {
891 coords.append(int(value->fValue));
892 value = m_valueList->next();
894 IntPoint hotSpot(-1, -1);
895 int nrcoords = coords.size();
896 if (nrcoords > 0 && nrcoords != 2)
899 hotSpot = IntPoint(coords[0], coords[1]);
901 if (!uri.isNull() && m_styleSheet) {
902 // FIXME: The completeURL call should be done when using the CSSCursorImageValue,
903 // not when creating it.
904 list->append(CSSCursorImageValue::create(m_styleSheet->completeURL(uri), hotSpot));
907 if ((m_strict && !value) || (value && !(value->unit == CSSParserValue::Operator && value->iValue == ',')))
909 value = m_valueList->next(); // comma
912 if (!value) { // no value after url list (MSIE 5 compatibility)
913 if (list->length() != 1)
915 } else if (!m_strict && value->id == CSSValueHand) // MSIE 5 compatibility :/
916 list->append(primitiveValueCache()->createIdentifierValue(CSSValuePointer));
917 else if (value && ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone))
918 list->append(primitiveValueCache()->createIdentifierValue(value->id));
920 parsedValue = list.release();
924 if (!m_strict && value->id == CSSValueHand) { // MSIE 5 compatibility :/
925 id = CSSValuePointer;
926 validPrimitive = true;
927 } else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)
928 validPrimitive = true;
932 case CSSPropertyBackgroundAttachment:
933 case CSSPropertyBackgroundClip:
934 case CSSPropertyWebkitBackgroundClip:
935 case CSSPropertyWebkitBackgroundComposite:
936 case CSSPropertyBackgroundImage:
937 case CSSPropertyBackgroundOrigin:
938 case CSSPropertyWebkitBackgroundOrigin:
939 case CSSPropertyBackgroundPosition:
940 case CSSPropertyBackgroundPositionX:
941 case CSSPropertyBackgroundPositionY:
942 case CSSPropertyBackgroundSize:
943 case CSSPropertyWebkitBackgroundSize:
944 case CSSPropertyBackgroundRepeat:
945 case CSSPropertyBackgroundRepeatX:
946 case CSSPropertyBackgroundRepeatY:
947 case CSSPropertyWebkitMaskAttachment:
948 case CSSPropertyWebkitMaskClip:
949 case CSSPropertyWebkitMaskComposite:
950 case CSSPropertyWebkitMaskImage:
951 case CSSPropertyWebkitMaskOrigin:
952 case CSSPropertyWebkitMaskPosition:
953 case CSSPropertyWebkitMaskPositionX:
954 case CSSPropertyWebkitMaskPositionY:
955 case CSSPropertyWebkitMaskSize:
956 case CSSPropertyWebkitMaskRepeat:
957 case CSSPropertyWebkitMaskRepeatX:
958 case CSSPropertyWebkitMaskRepeatY: {
959 RefPtr<CSSValue> val1;
960 RefPtr<CSSValue> val2;
961 int propId1, propId2;
963 if (parseFillProperty(propId, propId1, propId2, val1, val2)) {
964 OwnPtr<ShorthandScope> shorthandScope;
965 if (propId == CSSPropertyBackgroundPosition ||
966 propId == CSSPropertyBackgroundRepeat ||
967 propId == CSSPropertyWebkitMaskPosition ||
968 propId == CSSPropertyWebkitMaskRepeat) {
969 shorthandScope.set(new ShorthandScope(this, propId));
971 addProperty(propId1, val1.release(), important);
973 addProperty(propId2, val2.release(), important);
976 m_implicitShorthand = false;
979 case CSSPropertyListStyleImage: // <uri> | none | inherit
980 if (id == CSSValueNone) {
981 parsedValue = CSSImageValue::create();
983 } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
985 // FIXME: The completeURL call should be done when using the CSSImageValue,
986 // not when creating it.
987 parsedValue = CSSImageValue::create(m_styleSheet->completeURL(value->string));
990 } else if (isGeneratedImageValue(value)) {
991 if (parseGeneratedImage(parsedValue))
998 case CSSPropertyWebkitTextStrokeWidth:
999 case CSSPropertyOutlineWidth: // <border-width> | inherit
1000 case CSSPropertyBorderTopWidth: //// <border-width> | inherit
1001 case CSSPropertyBorderRightWidth: // Which is defined as
1002 case CSSPropertyBorderBottomWidth: // thin | medium | thick | <length>
1003 case CSSPropertyBorderLeftWidth:
1004 case CSSPropertyWebkitBorderStartWidth:
1005 case CSSPropertyWebkitBorderEndWidth:
1006 case CSSPropertyWebkitBorderBeforeWidth:
1007 case CSSPropertyWebkitBorderAfterWidth:
1008 case CSSPropertyWebkitColumnRuleWidth:
1009 if (id == CSSValueThin || id == CSSValueMedium || id == CSSValueThick)
1010 validPrimitive = true;
1012 validPrimitive = validUnit(value, FLength | FNonNeg, m_strict);
1015 case CSSPropertyLetterSpacing: // normal | <length> | inherit
1016 case CSSPropertyWordSpacing: // normal | <length> | inherit
1017 if (id == CSSValueNormal)
1018 validPrimitive = true;
1020 validPrimitive = validUnit(value, FLength, m_strict);
1023 case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
1024 if (id == CSSValueNormal || id == CSSValueBreakAll || id == CSSValueBreakWord)
1025 validPrimitive = true;
1028 case CSSPropertyWordWrap: // normal | break-word
1029 if (id == CSSValueNormal || id == CSSValueBreakWord)
1030 validPrimitive = true;
1032 case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation | inherit
1033 if (id == CSSValueNone || id == CSSValueNormal || id == CSSValueSpellOut || id == CSSValueDigits
1034 || id == CSSValueLiteralPunctuation || id == CSSValueNoPunctuation)
1035 validPrimitive = true;
1038 case CSSPropertyTextIndent: // <length> | <percentage> | inherit
1039 validPrimitive = (!id && validUnit(value, FLength | FPercent, m_strict));
1042 case CSSPropertyPaddingTop: //// <padding-width> | inherit
1043 case CSSPropertyPaddingRight: // Which is defined as
1044 case CSSPropertyPaddingBottom: // <length> | <percentage>
1045 case CSSPropertyPaddingLeft: ////
1046 case CSSPropertyWebkitPaddingStart:
1047 case CSSPropertyWebkitPaddingEnd:
1048 case CSSPropertyWebkitPaddingBefore:
1049 case CSSPropertyWebkitPaddingAfter:
1050 validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg, m_strict));
1053 case CSSPropertyMaxHeight: // <length> | <percentage> | none | inherit
1054 case CSSPropertyMaxWidth: // <length> | <percentage> | none | inherit
1055 case CSSPropertyWebkitMaxLogicalWidth:
1056 case CSSPropertyWebkitMaxLogicalHeight:
1057 if (id == CSSValueNone || id == CSSValueIntrinsic || id == CSSValueMinIntrinsic) {
1058 validPrimitive = true;
1062 case CSSPropertyMinHeight: // <length> | <percentage> | inherit
1063 case CSSPropertyMinWidth: // <length> | <percentage> | inherit
1064 case CSSPropertyWebkitMinLogicalWidth:
1065 case CSSPropertyWebkitMinLogicalHeight:
1066 if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
1067 validPrimitive = true;
1069 validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg, m_strict));
1072 case CSSPropertyFontSize:
1073 // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
1074 if (id >= CSSValueXxSmall && id <= CSSValueLarger)
1075 validPrimitive = true;
1077 validPrimitive = (validUnit(value, FLength | FPercent | FNonNeg, m_strict));
1080 case CSSPropertyFontStyle: // normal | italic | oblique | inherit
1081 return parseFontStyle(important);
1083 case CSSPropertyFontVariant: // normal | small-caps | inherit
1084 return parseFontVariant(important);
1086 case CSSPropertyVerticalAlign:
1087 // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
1088 // <percentage> | <length> | inherit
1090 if (id >= CSSValueBaseline && id <= CSSValueWebkitBaselineMiddle)
1091 validPrimitive = true;
1093 validPrimitive = (!id && validUnit(value, FLength | FPercent, m_strict));
1096 case CSSPropertyHeight: // <length> | <percentage> | auto | inherit
1097 case CSSPropertyWidth: // <length> | <percentage> | auto | inherit
1098 case CSSPropertyWebkitLogicalWidth:
1099 case CSSPropertyWebkitLogicalHeight:
1100 if (id == CSSValueAuto || id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
1101 validPrimitive = true;
1103 // ### handle multilength case where we allow relative units
1104 validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg, m_strict));
1107 case CSSPropertyBottom: // <length> | <percentage> | auto | inherit
1108 case CSSPropertyLeft: // <length> | <percentage> | auto | inherit
1109 case CSSPropertyRight: // <length> | <percentage> | auto | inherit
1110 case CSSPropertyTop: // <length> | <percentage> | auto | inherit
1111 case CSSPropertyMarginTop: //// <margin-width> | inherit
1112 case CSSPropertyMarginRight: // Which is defined as
1113 case CSSPropertyMarginBottom: // <length> | <percentage> | auto | inherit
1114 case CSSPropertyMarginLeft: ////
1115 case CSSPropertyWebkitMarginStart:
1116 case CSSPropertyWebkitMarginEnd:
1117 case CSSPropertyWebkitMarginBefore:
1118 case CSSPropertyWebkitMarginAfter:
1119 if (id == CSSValueAuto)
1120 validPrimitive = true;
1122 validPrimitive = (!id && validUnit(value, FLength | FPercent, m_strict));
1125 case CSSPropertyZIndex: // auto | <integer> | inherit
1126 if (id == CSSValueAuto) {
1127 validPrimitive = true;
1131 case CSSPropertyOrphans: // <integer> | inherit
1132 case CSSPropertyWidows: // <integer> | inherit
1133 // ### not supported later on
1134 validPrimitive = (!id && validUnit(value, FInteger, false));
1137 case CSSPropertyLineHeight: // normal | <number> | <length> | <percentage> | inherit
1138 if (id == CSSValueNormal)
1139 validPrimitive = true;
1141 validPrimitive = (!id && validUnit(value, FNumber | FLength | FPercent | FNonNeg, m_strict));
1143 case CSSPropertyCounterIncrement: // [ <identifier> <integer>? ]+ | none | inherit
1144 if (id != CSSValueNone)
1145 return parseCounter(propId, 1, important);
1146 validPrimitive = true;
1148 case CSSPropertyCounterReset: // [ <identifier> <integer>? ]+ | none | inherit
1149 if (id != CSSValueNone)
1150 return parseCounter(propId, 0, important);
1151 validPrimitive = true;
1153 case CSSPropertyFontFamily:
1154 // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
1156 parsedValue = parseFontFamily();
1160 case CSSPropertyTextDecoration:
1161 case CSSPropertyWebkitTextDecorationsInEffect:
1162 // none | [ underline || overline || line-through || blink ] | inherit
1163 if (id == CSSValueNone) {
1164 validPrimitive = true;
1166 RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
1167 bool isValid = true;
1168 while (isValid && value) {
1169 switch (value->id) {
1172 case CSSValueUnderline:
1173 case CSSValueOverline:
1174 case CSSValueLineThrough:
1175 list->append(primitiveValueCache()->createIdentifierValue(value->id));
1180 value = m_valueList->next();
1182 if (list->length() && isValid) {
1183 parsedValue = list.release();
1184 m_valueList->next();
1189 case CSSPropertyZoom: // normal | reset | document | <number> | <percentage> | inherit
1190 if (id == CSSValueNormal || id == CSSValueReset || id == CSSValueDocument)
1191 validPrimitive = true;
1193 validPrimitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg, true));
1196 case CSSPropertyTableLayout: // auto | fixed | inherit
1197 if (id == CSSValueAuto || id == CSSValueFixed)
1198 validPrimitive = true;
1201 case CSSPropertySrc: // Only used within @font-face, so cannot use inherit | initial or be !important. This is a list of urls or local references.
1202 return parseFontFaceSrc();
1204 case CSSPropertyUnicodeRange:
1205 return parseFontFaceUnicodeRange();
1207 /* CSS3 properties */
1208 case CSSPropertyWebkitAppearance:
1209 if ((id >= CSSValueCheckbox && id <= CSSValueTextarea) || id == CSSValueNone)
1210 validPrimitive = true;
1213 case CSSPropertyWebkitBorderImage:
1214 case CSSPropertyWebkitMaskBoxImage:
1215 if (id == CSSValueNone)
1216 validPrimitive = true;
1218 RefPtr<CSSValue> result;
1219 if (parseBorderImage(propId, important, result)) {
1220 addProperty(propId, result, important);
1225 case CSSPropertyBorderTopRightRadius:
1226 case CSSPropertyBorderTopLeftRadius:
1227 case CSSPropertyBorderBottomLeftRadius:
1228 case CSSPropertyBorderBottomRightRadius: {
1229 if (num != 1 && num != 2)
1231 validPrimitive = validUnit(value, FLength | FPercent, m_strict);
1232 if (!validPrimitive)
1234 RefPtr<CSSPrimitiveValue> parsedValue1 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
1235 RefPtr<CSSPrimitiveValue> parsedValue2;
1237 value = m_valueList->next();
1238 validPrimitive = validUnit(value, FLength | FPercent, m_strict);
1239 if (!validPrimitive)
1241 parsedValue2 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
1243 parsedValue2 = parsedValue1;
1245 RefPtr<Pair> pair = Pair::create(parsedValue1.release(), parsedValue2.release());
1246 RefPtr<CSSPrimitiveValue> val = primitiveValueCache()->createValue(pair.release());
1247 addProperty(propId, val.release(), important);
1250 case CSSPropertyBorderRadius:
1251 case CSSPropertyWebkitBorderRadius:
1252 return parseBorderRadius(propId, important);
1253 case CSSPropertyOutlineOffset:
1254 validPrimitive = validUnit(value, FLength | FPercent, m_strict);
1256 case CSSPropertyTextShadow: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
1257 case CSSPropertyBoxShadow:
1258 case CSSPropertyWebkitBoxShadow:
1259 if (id == CSSValueNone)
1260 validPrimitive = true;
1262 return parseShadow(propId, important);
1264 case CSSPropertyWebkitBoxReflect:
1265 if (id == CSSValueNone)
1266 validPrimitive = true;
1268 return parseReflect(propId, important);
1270 case CSSPropertyOpacity:
1271 validPrimitive = validUnit(value, FNumber, m_strict);
1273 case CSSPropertyWebkitBoxAlign:
1274 if (id == CSSValueStretch || id == CSSValueStart || id == CSSValueEnd ||
1275 id == CSSValueCenter || id == CSSValueBaseline)
1276 validPrimitive = true;
1278 case CSSPropertyWebkitBoxDirection:
1279 if (id == CSSValueNormal || id == CSSValueReverse)
1280 validPrimitive = true;
1282 case CSSPropertyWebkitBoxLines:
1283 if (id == CSSValueSingle || id == CSSValueMultiple)
1284 validPrimitive = true;
1286 case CSSPropertyWebkitBoxOrient:
1287 if (id == CSSValueHorizontal || id == CSSValueVertical ||
1288 id == CSSValueInlineAxis || id == CSSValueBlockAxis)
1289 validPrimitive = true;
1291 case CSSPropertyWebkitBoxPack:
1292 if (id == CSSValueStart || id == CSSValueEnd ||
1293 id == CSSValueCenter || id == CSSValueJustify)
1294 validPrimitive = true;
1296 case CSSPropertyWebkitBoxFlex:
1297 validPrimitive = validUnit(value, FNumber, m_strict);
1299 case CSSPropertyWebkitBoxFlexGroup:
1300 case CSSPropertyWebkitBoxOrdinalGroup:
1301 validPrimitive = validUnit(value, FInteger | FNonNeg, true);
1303 case CSSPropertyBoxSizing:
1304 validPrimitive = id == CSSValueBorderBox || id == CSSValueContentBox;
1306 case CSSPropertyWebkitColorCorrection:
1307 validPrimitive = id == CSSValueSrgb || id == CSSValueDefault;
1309 case CSSPropertyWebkitMarquee: {
1310 const int properties[5] = { CSSPropertyWebkitMarqueeDirection, CSSPropertyWebkitMarqueeIncrement,
1311 CSSPropertyWebkitMarqueeRepetition,
1312 CSSPropertyWebkitMarqueeStyle, CSSPropertyWebkitMarqueeSpeed };
1313 return parseShorthand(propId, properties, 5, important);
1315 case CSSPropertyWebkitMarqueeDirection:
1316 if (id == CSSValueForwards || id == CSSValueBackwards || id == CSSValueAhead ||
1317 id == CSSValueReverse || id == CSSValueLeft || id == CSSValueRight || id == CSSValueDown ||
1318 id == CSSValueUp || id == CSSValueAuto)
1319 validPrimitive = true;
1321 case CSSPropertyWebkitMarqueeIncrement:
1322 if (id == CSSValueSmall || id == CSSValueLarge || id == CSSValueMedium)
1323 validPrimitive = true;
1325 validPrimitive = validUnit(value, FLength | FPercent, m_strict);
1327 case CSSPropertyWebkitMarqueeStyle:
1328 if (id == CSSValueNone || id == CSSValueSlide || id == CSSValueScroll || id == CSSValueAlternate)
1329 validPrimitive = true;
1331 case CSSPropertyWebkitMarqueeRepetition:
1332 if (id == CSSValueInfinite)
1333 validPrimitive = true;
1335 validPrimitive = validUnit(value, FInteger | FNonNeg, m_strict);
1337 case CSSPropertyWebkitMarqueeSpeed:
1338 if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast)
1339 validPrimitive = true;
1341 validPrimitive = validUnit(value, FTime | FInteger | FNonNeg, m_strict);
1344 case CSSPropertyWapMarqueeDir:
1345 if (id == CSSValueLtr || id == CSSValueRtl)
1346 validPrimitive = true;
1348 case CSSPropertyWapMarqueeStyle:
1349 if (id == CSSValueNone || id == CSSValueSlide || id == CSSValueScroll || id == CSSValueAlternate)
1350 validPrimitive = true;
1352 case CSSPropertyWapMarqueeLoop:
1353 if (id == CSSValueInfinite)
1354 validPrimitive = true;
1356 validPrimitive = validUnit(value, FInteger | FNonNeg, m_strict);
1358 case CSSPropertyWapMarqueeSpeed:
1359 if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast)
1360 validPrimitive = true;
1362 validPrimitive = validUnit(value, FTime | FInteger | FNonNeg, m_strict);
1365 case CSSPropertyWebkitUserDrag: // auto | none | element
1366 if (id == CSSValueAuto || id == CSSValueNone || id == CSSValueElement)
1367 validPrimitive = true;
1369 case CSSPropertyWebkitUserModify: // read-only | read-write
1370 if (id == CSSValueReadOnly || id == CSSValueReadWrite || id == CSSValueReadWritePlaintextOnly)
1371 validPrimitive = true;
1373 case CSSPropertyWebkitUserSelect: // auto | none | text
1374 if (id == CSSValueAuto || id == CSSValueNone || id == CSSValueText)
1375 validPrimitive = true;
1377 case CSSPropertyTextOverflow: // clip | ellipsis
1378 if (id == CSSValueClip || id == CSSValueEllipsis)
1379 validPrimitive = true;
1381 case CSSPropertyWebkitTransform:
1382 if (id == CSSValueNone)
1383 validPrimitive = true;
1385 PassRefPtr<CSSValue> val = parseTransform();
1387 addProperty(propId, val, important);
1393 case CSSPropertyWebkitTransformOrigin:
1394 case CSSPropertyWebkitTransformOriginX:
1395 case CSSPropertyWebkitTransformOriginY:
1396 case CSSPropertyWebkitTransformOriginZ: {
1397 RefPtr<CSSValue> val1;
1398 RefPtr<CSSValue> val2;
1399 RefPtr<CSSValue> val3;
1400 int propId1, propId2, propId3;
1401 if (parseTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) {
1402 addProperty(propId1, val1.release(), important);
1404 addProperty(propId2, val2.release(), important);
1406 addProperty(propId3, val3.release(), important);
1411 case CSSPropertyWebkitTransformStyle:
1412 if (value->id == CSSValueFlat || value->id == CSSValuePreserve3d)
1413 validPrimitive = true;
1415 case CSSPropertyWebkitBackfaceVisibility:
1416 if (value->id == CSSValueVisible || value->id == CSSValueHidden)
1417 validPrimitive = true;
1419 case CSSPropertyWebkitPerspective:
1420 if (id == CSSValueNone)
1421 validPrimitive = true;
1423 // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property.
1424 if (validUnit(value, FNumber | FLength | FNonNeg, m_strict)) {
1425 RefPtr<CSSValue> val = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
1427 addProperty(propId, val.release(), important);
1434 case CSSPropertyWebkitPerspectiveOrigin:
1435 case CSSPropertyWebkitPerspectiveOriginX:
1436 case CSSPropertyWebkitPerspectiveOriginY: {
1437 RefPtr<CSSValue> val1;
1438 RefPtr<CSSValue> val2;
1439 int propId1, propId2;
1440 if (parsePerspectiveOrigin(propId, propId1, propId2, val1, val2)) {
1441 addProperty(propId1, val1.release(), important);
1443 addProperty(propId2, val2.release(), important);
1448 case CSSPropertyWebkitAnimationDelay:
1449 case CSSPropertyWebkitAnimationDirection:
1450 case CSSPropertyWebkitAnimationDuration:
1451 case CSSPropertyWebkitAnimationFillMode:
1452 case CSSPropertyWebkitAnimationName:
1453 case CSSPropertyWebkitAnimationPlayState:
1454 case CSSPropertyWebkitAnimationIterationCount:
1455 case CSSPropertyWebkitAnimationTimingFunction:
1456 case CSSPropertyWebkitTransitionDelay:
1457 case CSSPropertyWebkitTransitionDuration:
1458 case CSSPropertyWebkitTransitionTimingFunction:
1459 case CSSPropertyWebkitTransitionProperty: {
1460 RefPtr<CSSValue> val;
1461 if (parseAnimationProperty(propId, val)) {
1462 addProperty(propId, val.release(), important);
1467 case CSSPropertyWebkitMarginCollapse: {
1468 const int properties[2] = { CSSPropertyWebkitMarginBeforeCollapse,
1469 CSSPropertyWebkitMarginAfterCollapse };
1471 ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
1472 if (!parseValue(properties[0], important))
1474 CSSValue* value = m_parsedProperties[m_numParsedProperties-1]->value();
1475 addProperty(properties[1], value, important);
1478 else if (num == 2) {
1479 ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
1480 if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
1486 case CSSPropertyWebkitMarginBeforeCollapse:
1487 case CSSPropertyWebkitMarginAfterCollapse:
1488 case CSSPropertyWebkitMarginTopCollapse:
1489 case CSSPropertyWebkitMarginBottomCollapse:
1490 if (id == CSSValueCollapse || id == CSSValueSeparate || id == CSSValueDiscard)
1491 validPrimitive = true;
1493 case CSSPropertyTextLineThroughMode:
1494 case CSSPropertyTextOverlineMode:
1495 case CSSPropertyTextUnderlineMode:
1496 if (id == CSSValueContinuous || id == CSSValueSkipWhiteSpace)
1497 validPrimitive = true;
1499 case CSSPropertyTextLineThroughStyle:
1500 case CSSPropertyTextOverlineStyle:
1501 case CSSPropertyTextUnderlineStyle:
1502 if (id == CSSValueNone || id == CSSValueSolid || id == CSSValueDouble ||
1503 id == CSSValueDashed || id == CSSValueDotDash || id == CSSValueDotDotDash ||
1505 validPrimitive = true;
1507 case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
1508 if (id == CSSValueAuto || id == CSSValueOptimizespeed || id == CSSValueOptimizelegibility
1509 || id == CSSValueGeometricprecision)
1510 validPrimitive = true;
1512 case CSSPropertyTextLineThroughWidth:
1513 case CSSPropertyTextOverlineWidth:
1514 case CSSPropertyTextUnderlineWidth:
1515 if (id == CSSValueAuto || id == CSSValueNormal || id == CSSValueThin ||
1516 id == CSSValueMedium || id == CSSValueThick)
1517 validPrimitive = true;
1519 validPrimitive = !id && validUnit(value, FNumber | FLength | FPercent, m_strict);
1521 case CSSPropertyResize: // none | both | horizontal | vertical | auto
1522 if (id == CSSValueNone || id == CSSValueBoth || id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto)
1523 validPrimitive = true;
1525 case CSSPropertyWebkitColumnCount:
1526 if (id == CSSValueAuto)
1527 validPrimitive = true;
1529 validPrimitive = !id && validUnit(value, FInteger | FNonNeg, false);
1531 case CSSPropertyWebkitColumnGap: // normal | <length>
1532 if (id == CSSValueNormal)
1533 validPrimitive = true;
1535 validPrimitive = validUnit(value, FLength | FNonNeg, m_strict);
1537 case CSSPropertyWebkitColumnSpan: // all | 1
1538 if (id == CSSValueAll)
1539 validPrimitive = true;
1541 validPrimitive = validUnit(value, FNumber | FNonNeg, m_strict) && value->fValue == 1;
1543 case CSSPropertyWebkitColumnWidth: // auto | <length>
1544 if (id == CSSValueAuto)
1545 validPrimitive = true;
1546 else // Always parse this property in strict mode, since it would be ambiguous otherwise when used in the 'columns' shorthand property.
1547 validPrimitive = validUnit(value, FLength, true);
1549 case CSSPropertyPointerEvents:
1550 // none | visiblePainted | visibleFill | visibleStroke | visible |
1551 // painted | fill | stroke | auto | all | inherit
1552 if (id == CSSValueVisible || id == CSSValueNone || id == CSSValueAll || id == CSSValueAuto ||
1553 (id >= CSSValueVisiblepainted && id <= CSSValueStroke))
1554 validPrimitive = true;
1557 // End of CSS3 properties
1559 // Apple specific properties. These will never be standardized and are purely to
1560 // support custom WebKit-based Apple applications.
1561 case CSSPropertyWebkitLineClamp:
1562 // When specifying number of lines, don't allow 0 as a valid value
1563 // When specifying either type of unit, require non-negative integers
1564 validPrimitive = (!id && (value->unit == CSSPrimitiveValue::CSS_PERCENTAGE || value->fValue) && validUnit(value, FInteger | FPercent | FNonNeg, false));
1566 case CSSPropertyWebkitTextSizeAdjust:
1567 if (id == CSSValueAuto || id == CSSValueNone)
1568 validPrimitive = true;
1570 case CSSPropertyWebkitRtlOrdering:
1571 if (id == CSSValueLogical || id == CSSValueVisual)
1572 validPrimitive = true;
1575 case CSSPropertyWebkitFontSizeDelta: // <length>
1576 validPrimitive = validUnit(value, FLength, m_strict);
1579 case CSSPropertyWebkitNbspMode: // normal | space
1580 if (id == CSSValueNormal || id == CSSValueSpace)
1581 validPrimitive = true;
1584 case CSSPropertyWebkitLineBreak: // normal | after-white-space
1585 if (id == CSSValueNormal || id == CSSValueAfterWhiteSpace)
1586 validPrimitive = true;
1589 case CSSPropertyWebkitMatchNearestMailBlockquoteColor: // normal | match
1590 if (id == CSSValueNormal || id == CSSValueMatch)
1591 validPrimitive = true;
1594 case CSSPropertyWebkitHighlight:
1595 if (id == CSSValueNone || value->unit == CSSPrimitiveValue::CSS_STRING)
1596 validPrimitive = true;
1599 case CSSPropertyWebkitHyphens:
1600 if (id == CSSValueNone || id == CSSValueManual || id == CSSValueAuto)
1601 validPrimitive = true;
1604 case CSSPropertyWebkitHyphenateCharacter:
1605 if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
1606 validPrimitive = true;
1609 case CSSPropertyWebkitHyphenateLimitBefore:
1610 case CSSPropertyWebkitHyphenateLimitAfter:
1611 if (id == CSSValueAuto || validUnit(value, FInteger | FNonNeg, true))
1612 validPrimitive = true;
1615 case CSSPropertyWebkitLocale:
1616 if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
1617 validPrimitive = true;
1620 case CSSPropertyWebkitBorderFit:
1621 if (id == CSSValueBorder || id == CSSValueLines)
1622 validPrimitive = true;
1625 case CSSPropertyWebkitTextSecurity:
1626 // disc | circle | square | none | inherit
1627 if (id == CSSValueDisc || id == CSSValueCircle || id == CSSValueSquare|| id == CSSValueNone)
1628 validPrimitive = true;
1631 case CSSPropertyWebkitFontSmoothing:
1632 if (id == CSSValueAuto || id == CSSValueNone
1633 || id == CSSValueAntialiased || id == CSSValueSubpixelAntialiased)
1634 validPrimitive = true;
1637 #if ENABLE(DASHBOARD_SUPPORT)
1638 case CSSPropertyWebkitDashboardRegion: // <dashboard-region> | <dashboard-region>
1639 if (value->unit == CSSParserValue::Function || id == CSSValueNone)
1640 return parseDashboardRegions(propId, important);
1643 // End Apple-specific properties
1645 /* shorthand properties */
1646 case CSSPropertyBackground: {
1647 // Position must come before color in this array because a plain old "0" is a legal color
1648 // in quirks mode but it's usually the X coordinate of a position.
1649 // FIXME: Add CSSPropertyBackgroundSize to the shorthand.
1650 const int properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat,
1651 CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyBackgroundOrigin,
1652 CSSPropertyBackgroundClip, CSSPropertyBackgroundColor };
1653 return parseFillShorthand(propId, properties, 7, important);
1655 case CSSPropertyWebkitMask: {
1656 const int properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
1657 CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition,
1658 CSSPropertyWebkitMaskOrigin, CSSPropertyWebkitMaskClip };
1659 return parseFillShorthand(propId, properties, 6, important);
1661 case CSSPropertyBorder:
1662 // [ 'border-width' || 'border-style' || <color> ] | inherit
1664 const int properties[3] = { CSSPropertyBorderWidth, CSSPropertyBorderStyle,
1665 CSSPropertyBorderColor };
1666 return parseShorthand(propId, properties, 3, important);
1668 case CSSPropertyBorderTop:
1669 // [ 'border-top-width' || 'border-style' || <color> ] | inherit
1671 const int properties[3] = { CSSPropertyBorderTopWidth, CSSPropertyBorderTopStyle,
1672 CSSPropertyBorderTopColor};
1673 return parseShorthand(propId, properties, 3, important);
1675 case CSSPropertyBorderRight:
1676 // [ 'border-right-width' || 'border-style' || <color> ] | inherit
1678 const int properties[3] = { CSSPropertyBorderRightWidth, CSSPropertyBorderRightStyle,
1679 CSSPropertyBorderRightColor };
1680 return parseShorthand(propId, properties, 3, important);
1682 case CSSPropertyBorderBottom:
1683 // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
1685 const int properties[3] = { CSSPropertyBorderBottomWidth, CSSPropertyBorderBottomStyle,
1686 CSSPropertyBorderBottomColor };
1687 return parseShorthand(propId, properties, 3, important);
1689 case CSSPropertyBorderLeft:
1690 // [ 'border-left-width' || 'border-style' || <color> ] | inherit
1692 const int properties[3] = { CSSPropertyBorderLeftWidth, CSSPropertyBorderLeftStyle,
1693 CSSPropertyBorderLeftColor };
1694 return parseShorthand(propId, properties, 3, important);
1696 case CSSPropertyWebkitBorderStart:
1698 const int properties[3] = { CSSPropertyWebkitBorderStartWidth, CSSPropertyWebkitBorderStartStyle,
1699 CSSPropertyWebkitBorderStartColor };
1700 return parseShorthand(propId, properties, 3, important);
1702 case CSSPropertyWebkitBorderEnd:
1704 const int properties[3] = { CSSPropertyWebkitBorderEndWidth, CSSPropertyWebkitBorderEndStyle,
1705 CSSPropertyWebkitBorderEndColor };
1706 return parseShorthand(propId, properties, 3, important);
1708 case CSSPropertyWebkitBorderBefore:
1710 const int properties[3] = { CSSPropertyWebkitBorderBeforeWidth, CSSPropertyWebkitBorderBeforeStyle,
1711 CSSPropertyWebkitBorderBeforeColor };
1712 return parseShorthand(propId, properties, 3, important);
1714 case CSSPropertyWebkitBorderAfter:
1716 const int properties[3] = { CSSPropertyWebkitBorderAfterWidth, CSSPropertyWebkitBorderAfterStyle,
1717 CSSPropertyWebkitBorderAfterColor };
1718 return parseShorthand(propId, properties, 3, important);
1720 case CSSPropertyOutline:
1721 // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
1723 const int properties[3] = { CSSPropertyOutlineWidth, CSSPropertyOutlineStyle,
1724 CSSPropertyOutlineColor };
1725 return parseShorthand(propId, properties, 3, important);
1727 case CSSPropertyBorderColor:
1728 // <color>{1,4} | inherit
1730 const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor,
1731 CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
1732 return parse4Values(propId, properties, important);
1734 case CSSPropertyBorderWidth:
1735 // <border-width>{1,4} | inherit
1737 const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth,
1738 CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
1739 return parse4Values(propId, properties, important);
1741 case CSSPropertyBorderStyle:
1742 // <border-style>{1,4} | inherit
1744 const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle,
1745 CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
1746 return parse4Values(propId, properties, important);
1748 case CSSPropertyMargin:
1749 // <margin-width>{1,4} | inherit
1751 const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight,
1752 CSSPropertyMarginBottom, CSSPropertyMarginLeft };
1753 return parse4Values(propId, properties, important);
1755 case CSSPropertyPadding:
1756 // <padding-width>{1,4} | inherit
1758 const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight,
1759 CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
1760 return parse4Values(propId, properties, important);
1762 case CSSPropertyFont:
1763 // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
1764 // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
1765 if (id >= CSSValueCaption && id <= CSSValueStatusBar)
1766 validPrimitive = true;
1768 return parseFont(important);
1770 case CSSPropertyListStyle:
1772 const int properties[3] = { CSSPropertyListStyleType, CSSPropertyListStylePosition,
1773 CSSPropertyListStyleImage };
1774 return parseShorthand(propId, properties, 3, important);
1776 case CSSPropertyWebkitColumns: {
1777 const int properties[2] = { CSSPropertyWebkitColumnWidth, CSSPropertyWebkitColumnCount };
1778 return parseShorthand(propId, properties, 2, important);
1780 case CSSPropertyWebkitColumnRule: {
1781 const int properties[3] = { CSSPropertyWebkitColumnRuleWidth, CSSPropertyWebkitColumnRuleStyle,
1782 CSSPropertyWebkitColumnRuleColor };
1783 return parseShorthand(propId, properties, 3, important);
1785 case CSSPropertyWebkitTextStroke: {
1786 const int properties[2] = { CSSPropertyWebkitTextStrokeWidth, CSSPropertyWebkitTextStrokeColor };
1787 return parseShorthand(propId, properties, 2, important);
1789 case CSSPropertyWebkitAnimation:
1790 return parseAnimationShorthand(important);
1791 case CSSPropertyWebkitTransition:
1792 return parseTransitionShorthand(important);
1793 case CSSPropertyInvalid:
1795 case CSSPropertyPage:
1796 return parsePage(propId, important);
1797 case CSSPropertyFontStretch:
1798 case CSSPropertyTextLineThrough:
1799 case CSSPropertyTextOverline:
1800 case CSSPropertyTextUnderline:
1803 case CSSPropertyWapInputFormat:
1804 validPrimitive = true;
1806 case CSSPropertyWapInputRequired:
1807 parsedValue = parseWCSSInputProperty();
1811 // CSS Text Layout Module Level 3: Vertical writing support
1812 case CSSPropertyWebkitWritingMode:
1813 if (id >= CSSValueHorizontalTb && id <= CSSValueHorizontalBt)
1814 validPrimitive = true;
1817 case CSSPropertyWebkitTextCombine:
1818 if (id == CSSValueNone || id == CSSValueHorizontal)
1819 validPrimitive = true;
1822 case CSSPropertyWebkitTextEmphasis: {
1823 const int properties[] = { CSSPropertyWebkitTextEmphasisStyle, CSSPropertyWebkitTextEmphasisColor };
1824 return parseShorthand(propId, properties, WTF_ARRAY_LENGTH(properties), important);
1827 case CSSPropertyWebkitTextEmphasisPosition:
1828 if (id == CSSValueOver || id == CSSValueUnder)
1829 validPrimitive = true;
1832 case CSSPropertyWebkitTextEmphasisStyle:
1833 return parseTextEmphasisStyle(important);
1837 return parseSVGValue(propId, important);
1841 if (validPrimitive) {
1843 parsedValue = primitiveValueCache()->createIdentifierValue(id);
1844 else if (value->unit == CSSPrimitiveValue::CSS_STRING)
1845 parsedValue = primitiveValueCache()->createValue(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
1846 else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1847 parsedValue = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
1848 else if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
1849 parsedValue = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
1850 else if (value->unit >= CSSParserValue::Q_EMS)
1851 parsedValue = CSSQuirkPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_EMS);
1852 m_valueList->next();
1855 if (!m_valueList->current() || inShorthand()) {
1856 addProperty(propId, parsedValue.release(), important);
1864 PassRefPtr<CSSValue> CSSParser::parseWCSSInputProperty()
1866 RefPtr<CSSValue> parsedValue = 0;
1867 CSSParserValue* value = m_valueList->current();
1868 String inputProperty;
1869 if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT)
1870 inputProperty = String(value->string);
1872 if (!inputProperty.isEmpty())
1873 parsedValue = primitiveValueCache()->createValue(inputProperty, CSSPrimitiveValue::CSS_STRING);
1875 while (m_valueList->next()) {
1876 // pass all other values, if any. If we don't do this,
1877 // the parser will think that it's not done and won't process this property
1884 void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
1887 if (lval->isValueList())
1888 static_cast<CSSValueList*>(lval.get())->append(rval);
1890 PassRefPtr<CSSValue> oldlVal(lval.release());
1891 PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
1892 list->append(oldlVal);
1901 static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue, CSSPrimitiveValueCache* primitiveValueCache)
1903 if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox
1904 || parserValue->id == CSSValueContentBox || parserValue->id == CSSValueWebkitText) {
1905 cssValue = primitiveValueCache->createIdentifierValue(parserValue->id);
1911 const int cMaxFillProperties = 9;
1913 bool CSSParser::parseFillShorthand(int propId, const int* properties, int numProperties, bool important)
1915 ASSERT(numProperties <= cMaxFillProperties);
1916 if (numProperties > cMaxFillProperties)
1919 ShorthandScope scope(this, propId);
1921 bool parsedProperty[cMaxFillProperties] = { false };
1922 RefPtr<CSSValue> values[cMaxFillProperties];
1923 RefPtr<CSSValue> clipValue;
1924 RefPtr<CSSValue> positionYValue;
1925 RefPtr<CSSValue> repeatYValue;
1926 bool foundClip = false;
1929 while (m_valueList->current()) {
1930 CSSParserValue* val = m_valueList->current();
1931 if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
1932 // We hit the end. Fill in all remaining values with the initial value.
1933 m_valueList->next();
1934 for (i = 0; i < numProperties; ++i) {
1935 if (properties[i] == CSSPropertyBackgroundColor && parsedProperty[i])
1936 // Color is not allowed except as the last item in a list for backgrounds.
1937 // Reject the entire property.
1940 if (!parsedProperty[i] && properties[i] != CSSPropertyBackgroundColor) {
1941 addFillValue(values[i], CSSInitialValue::createImplicit());
1942 if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
1943 addFillValue(positionYValue, CSSInitialValue::createImplicit());
1944 if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
1945 addFillValue(repeatYValue, CSSInitialValue::createImplicit());
1946 if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
1947 // If background-origin wasn't present, then reset background-clip also.
1948 addFillValue(clipValue, CSSInitialValue::createImplicit());
1951 parsedProperty[i] = false;
1953 if (!m_valueList->current())
1958 for (i = 0; !found && i < numProperties; ++i) {
1959 if (!parsedProperty[i]) {
1960 RefPtr<CSSValue> val1;
1961 RefPtr<CSSValue> val2;
1962 int propId1, propId2;
1963 CSSParserValue* parserValue = m_valueList->current();
1964 if (parseFillProperty(properties[i], propId1, propId2, val1, val2)) {
1965 parsedProperty[i] = found = true;
1966 addFillValue(values[i], val1.release());
1967 if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
1968 addFillValue(positionYValue, val2.release());
1969 if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
1970 addFillValue(repeatYValue, val2.release());
1971 if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
1972 // Reparse the value as a clip, and see if we succeed.
1973 if (parseBackgroundClip(parserValue, val1, primitiveValueCache()))
1974 addFillValue(clipValue, val1.release()); // The property parsed successfully.
1976 addFillValue(clipValue, CSSInitialValue::createImplicit()); // Some value was used for origin that is not supported by clip. Just reset clip instead.
1978 if (properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) {
1980 addFillValue(clipValue, val1.release());
1987 // if we didn't find at least one match, this is an
1988 // invalid shorthand and we have to ignore it
1993 // Fill in any remaining properties with the initial value.
1994 for (i = 0; i < numProperties; ++i) {
1995 if (!parsedProperty[i]) {
1996 addFillValue(values[i], CSSInitialValue::createImplicit());
1997 if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
1998 addFillValue(positionYValue, CSSInitialValue::createImplicit());
1999 if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2000 addFillValue(repeatYValue, CSSInitialValue::createImplicit());
2001 if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
2002 // If background-origin wasn't present, then reset background-clip also.
2003 addFillValue(clipValue, CSSInitialValue::createImplicit());
2008 // Now add all of the properties we found.
2009 for (i = 0; i < numProperties; i++) {
2010 if (properties[i] == CSSPropertyBackgroundPosition) {
2011 addProperty(CSSPropertyBackgroundPositionX, values[i].release(), important);
2012 // it's OK to call positionYValue.release() since we only see CSSPropertyBackgroundPosition once
2013 addProperty(CSSPropertyBackgroundPositionY, positionYValue.release(), important);
2014 } else if (properties[i] == CSSPropertyWebkitMaskPosition) {
2015 addProperty(CSSPropertyWebkitMaskPositionX, values[i].release(), important);
2016 // it's OK to call positionYValue.release() since we only see CSSPropertyWebkitMaskPosition once
2017 addProperty(CSSPropertyWebkitMaskPositionY, positionYValue.release(), important);
2018 } else if (properties[i] == CSSPropertyBackgroundRepeat) {
2019 addProperty(CSSPropertyBackgroundRepeatX, values[i].release(), important);
2020 // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2021 addProperty(CSSPropertyBackgroundRepeatY, repeatYValue.release(), important);
2022 } else if (properties[i] == CSSPropertyWebkitMaskRepeat) {
2023 addProperty(CSSPropertyWebkitMaskRepeatX, values[i].release(), important);
2024 // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2025 addProperty(CSSPropertyWebkitMaskRepeatY, repeatYValue.release(), important);
2026 } else if ((properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) && !foundClip)
2027 // Value is already set while updating origin
2030 addProperty(properties[i], values[i].release(), important);
2032 // Add in clip values when we hit the corresponding origin property.
2033 if (properties[i] == CSSPropertyBackgroundOrigin && !foundClip)
2034 addProperty(CSSPropertyBackgroundClip, clipValue.release(), important);
2035 else if (properties[i] == CSSPropertyWebkitMaskOrigin && !foundClip)
2036 addProperty(CSSPropertyWebkitMaskClip, clipValue.release(), important);
2042 void CSSParser::addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
2045 if (lval->isValueList())
2046 static_cast<CSSValueList*>(lval.get())->append(rval);
2048 PassRefPtr<CSSValue> oldVal(lval.release());
2049 PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2050 list->append(oldVal);
2059 bool CSSParser::parseAnimationShorthand(bool important)
2061 const int properties[] = { CSSPropertyWebkitAnimationName,
2062 CSSPropertyWebkitAnimationDuration,
2063 CSSPropertyWebkitAnimationTimingFunction,
2064 CSSPropertyWebkitAnimationDelay,
2065 CSSPropertyWebkitAnimationIterationCount,
2066 CSSPropertyWebkitAnimationDirection,
2067 CSSPropertyWebkitAnimationFillMode };
2068 const int numProperties = WTF_ARRAY_LENGTH(properties);
2070 ShorthandScope scope(this, CSSPropertyWebkitAnimation);
2072 bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
2073 RefPtr<CSSValue> values[numProperties];
2076 while (m_valueList->current()) {
2077 CSSParserValue* val = m_valueList->current();
2078 if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2079 // We hit the end. Fill in all remaining values with the initial value.
2080 m_valueList->next();
2081 for (i = 0; i < numProperties; ++i) {
2082 if (!parsedProperty[i])
2083 addAnimationValue(values[i], CSSInitialValue::createImplicit());
2084 parsedProperty[i] = false;
2086 if (!m_valueList->current())
2091 for (i = 0; !found && i < numProperties; ++i) {
2092 if (!parsedProperty[i]) {
2093 RefPtr<CSSValue> val;
2094 if (parseAnimationProperty(properties[i], val)) {
2095 parsedProperty[i] = found = true;
2096 addAnimationValue(values[i], val.release());
2101 // if we didn't find at least one match, this is an
2102 // invalid shorthand and we have to ignore it
2107 // Fill in any remaining properties with the initial value.
2108 for (i = 0; i < numProperties; ++i) {
2109 if (!parsedProperty[i])
2110 addAnimationValue(values[i], CSSInitialValue::createImplicit());
2113 // Now add all of the properties we found.
2114 for (i = 0; i < numProperties; i++)
2115 addProperty(properties[i], values[i].release(), important);
2120 bool CSSParser::parseTransitionShorthand(bool important)
2122 const int properties[] = { CSSPropertyWebkitTransitionProperty,
2123 CSSPropertyWebkitTransitionDuration,
2124 CSSPropertyWebkitTransitionTimingFunction,
2125 CSSPropertyWebkitTransitionDelay };
2126 const int numProperties = WTF_ARRAY_LENGTH(properties);
2128 ShorthandScope scope(this, CSSPropertyWebkitTransition);
2130 bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
2131 RefPtr<CSSValue> values[numProperties];
2134 while (m_valueList->current()) {
2135 CSSParserValue* val = m_valueList->current();
2136 if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2137 // We hit the end. Fill in all remaining values with the initial value.
2138 m_valueList->next();
2139 for (i = 0; i < numProperties; ++i) {
2140 if (!parsedProperty[i])
2141 addAnimationValue(values[i], CSSInitialValue::createImplicit());
2142 parsedProperty[i] = false;
2144 if (!m_valueList->current())
2149 for (i = 0; !found && i < numProperties; ++i) {
2150 if (!parsedProperty[i]) {
2151 RefPtr<CSSValue> val;
2152 if (parseAnimationProperty(properties[i], val)) {
2153 parsedProperty[i] = found = true;
2154 addAnimationValue(values[i], val.release());
2159 // if we didn't find at least one match, this is an
2160 // invalid shorthand and we have to ignore it
2165 // Fill in any remaining properties with the initial value.
2166 for (i = 0; i < numProperties; ++i) {
2167 if (!parsedProperty[i])
2168 addAnimationValue(values[i], CSSInitialValue::createImplicit());
2171 // Now add all of the properties we found.
2172 for (i = 0; i < numProperties; i++)
2173 addProperty(properties[i], values[i].release(), important);
2178 bool CSSParser::parseShorthand(int propId, const int *properties, int numProperties, bool important)
2180 // We try to match as many properties as possible
2181 // We set up an array of booleans to mark which property has been found,
2182 // and we try to search for properties until it makes no longer any sense.
2183 ShorthandScope scope(this, propId);
2186 bool fnd[6]; // Trust me ;)
2187 for (int i = 0; i < numProperties; i++)
2190 while (m_valueList->current()) {
2192 for (int propIndex = 0; !found && propIndex < numProperties; ++propIndex) {
2193 if (!fnd[propIndex]) {
2194 if (parseValue(properties[propIndex], important))
2195 fnd[propIndex] = found = true;
2199 // if we didn't find at least one match, this is an
2200 // invalid shorthand and we have to ignore it
2205 // Fill in any remaining properties with the initial value.
2206 m_implicitShorthand = true;
2207 for (int i = 0; i < numProperties; ++i) {
2209 addProperty(properties[i], CSSInitialValue::createImplicit(), important);
2211 m_implicitShorthand = false;
2216 bool CSSParser::parse4Values(int propId, const int *properties, bool important)
2218 /* From the CSS 2 specs, 8.3
2219 * If there is only one value, it applies to all sides. If there are two values, the top and
2220 * bottom margins are set to the first value and the right and left margins are set to the second.
2221 * If there are three values, the top is set to the first value, the left and right are set to the
2222 * second, and the bottom is set to the third. If there are four values, they apply to the top,
2223 * right, bottom, and left, respectively.
2226 int num = inShorthand() ? 1 : m_valueList->size();
2228 ShorthandScope scope(this, propId);
2230 // the order is top, right, bottom, left
2233 if (!parseValue(properties[0], important))
2235 CSSValue *value = m_parsedProperties[m_numParsedProperties-1]->value();
2236 m_implicitShorthand = true;
2237 addProperty(properties[1], value, important);
2238 addProperty(properties[2], value, important);
2239 addProperty(properties[3], value, important);
2240 m_implicitShorthand = false;
2244 if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
2246 CSSValue *value = m_parsedProperties[m_numParsedProperties-2]->value();
2247 m_implicitShorthand = true;
2248 addProperty(properties[2], value, important);
2249 value = m_parsedProperties[m_numParsedProperties-2]->value();
2250 addProperty(properties[3], value, important);
2251 m_implicitShorthand = false;
2255 if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
2257 CSSValue *value = m_parsedProperties[m_numParsedProperties-2]->value();
2258 m_implicitShorthand = true;
2259 addProperty(properties[3], value, important);
2260 m_implicitShorthand = false;
2264 if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
2265 !parseValue(properties[2], important) || !parseValue(properties[3], important))
2277 // auto | <identifier>
2278 bool CSSParser::parsePage(int propId, bool important)
2280 ASSERT(propId == CSSPropertyPage);
2282 if (m_valueList->size() != 1)
2285 CSSParserValue* value = m_valueList->current();
2289 if (value->id == CSSValueAuto) {
2290 addProperty(propId, primitiveValueCache()->createIdentifierValue(value->id), important);
2292 } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) {
2293 addProperty(propId, primitiveValueCache()->createValue(value->string, CSSPrimitiveValue::CSS_STRING), important);
2299 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
2300 bool CSSParser::parseSize(int propId, bool important)
2302 ASSERT(propId == CSSPropertySize);
2304 if (m_valueList->size() > 2)
2307 CSSParserValue* value = m_valueList->current();
2311 RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
2314 SizeParameterType paramType = parseSizeParameter(parsedValues.get(), value, None);
2315 if (paramType == None)
2318 // Second parameter, if any.
2319 value = m_valueList->next();
2321 paramType = parseSizeParameter(parsedValues.get(), value, paramType);
2322 if (paramType == None)
2326 addProperty(propId, parsedValues.release(), important);
2330 CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType)
2332 switch (value->id) {
2334 if (prevParamType == None) {
2335 parsedValues->append(primitiveValueCache()->createIdentifierValue(value->id));
2339 case CSSValueLandscape:
2340 case CSSValuePortrait:
2341 if (prevParamType == None || prevParamType == PageSize) {
2342 parsedValues->append(primitiveValueCache()->createIdentifierValue(value->id));
2351 case CSSValueLedger:
2353 case CSSValueLetter:
2354 if (prevParamType == None || prevParamType == Orientation) {
2355 // Normalize to Page Size then Orientation order by prepending.
2356 // This is not specified by the CSS3 Paged Media specification, but for simpler processing later (CSSStyleSelector::applyPageSizeProperty).
2357 parsedValues->prepend(primitiveValueCache()->createIdentifierValue(value->id));
2362 if (validUnit(value, FLength | FNonNeg, m_strict) && (prevParamType == None || prevParamType == Length)) {
2363 parsedValues->append(primitiveValueCache()->createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)));
2372 // [ <string> <string> ]+ | inherit | none
2373 // inherit and none are handled in parseValue.
2374 bool CSSParser::parseQuotes(int propId, bool important)
2376 RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
2377 while (CSSParserValue* val = m_valueList->current()) {
2378 RefPtr<CSSValue> parsedValue;
2379 if (val->unit == CSSPrimitiveValue::CSS_STRING)
2380 parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING);
2383 values->append(parsedValue.release());
2384 m_valueList->next();
2386 if (values->length()) {
2387 addProperty(propId, values.release(), important);
2388 m_valueList->next();
2394 // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
2395 // in CSS 2.1 this got somewhat reduced:
2396 // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
2397 bool CSSParser::parseContent(int propId, bool important)
2399 RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
2401 while (CSSParserValue* val = m_valueList->current()) {
2402 RefPtr<CSSValue> parsedValue;
2403 if (val->unit == CSSPrimitiveValue::CSS_URI && m_styleSheet) {
2405 // FIXME: The completeURL call should be done when using the CSSImageValue,
2406 // not when creating it.
2407 parsedValue = CSSImageValue::create(m_styleSheet->completeURL(val->string));
2408 } else if (val->unit == CSSParserValue::Function) {
2409 // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) | -webkit-gradient(...)
2410 CSSParserValueList* args = val->function->args.get();
2413 if (equalIgnoringCase(val->function->name, "attr(")) {
2414 parsedValue = parseAttr(args);
2417 } else if (equalIgnoringCase(val->function->name, "counter(")) {
2418 parsedValue = parseCounterContent(args, false);
2421 } else if (equalIgnoringCase(val->function->name, "counters(")) {
2422 parsedValue = parseCounterContent(args, true);
2425 } else if (isGeneratedImageValue(val)) {
2426 if (!parseGeneratedImage(parsedValue))
2430 } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
2436 // FIXME: These are not yet implemented (http://bugs.webkit.org/show_bug.cgi?id=6503).
2440 case CSSValueOpenQuote:
2441 case CSSValueCloseQuote:
2442 case CSSValueNoOpenQuote:
2443 case CSSValueNoCloseQuote:
2445 case CSSValueNormal:
2446 parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
2448 } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
2449 parsedValue = primitiveValueCache()->createValue(val->string, CSSPrimitiveValue::CSS_STRING);
2453 values->append(parsedValue.release());
2454 m_valueList->next();
2457 if (values->length()) {
2458 addProperty(propId, values.release(), important);
2459 m_valueList->next();
2466 PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args)
2468 if (args->size() != 1)
2471 CSSParserValue* a = args->current();
2473 if (a->unit != CSSPrimitiveValue::CSS_IDENT)
2476 String attrName = a->string;
2477 // CSS allows identifiers with "-" at the start, like "-webkit-mask-image".
2478 // But HTML attribute names can't have those characters, and we should not
2479 // even parse them inside attr().
2480 if (attrName[0] == '-')
2483 if (document() && document()->isHTMLDocument())
2484 attrName = attrName.lower();
2486 return primitiveValueCache()->createValue(attrName, CSSPrimitiveValue::CSS_ATTR);
2489 PassRefPtr<CSSValue> CSSParser::parseBackgroundColor()
2491 int id = m_valueList->current()->id;
2492 if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor ||
2493 (id >= CSSValueGrey && id < CSSValueWebkitText && !m_strict))
2494 return primitiveValueCache()->createIdentifierValue(id);
2495 return parseColor();
2498 bool CSSParser::parseFillImage(RefPtr<CSSValue>& value)
2500 if (m_valueList->current()->id == CSSValueNone) {
2501 value = CSSImageValue::create();
2504 if (m_valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
2505 // FIXME: The completeURL call should be done when using the CSSImageValue,
2506 // not when creating it.
2508 value = CSSImageValue::create(m_styleSheet->completeURL(m_valueList->current()->string));
2512 if (isGeneratedImageValue(m_valueList->current()))
2513 return parseGeneratedImage(value);
2518 PassRefPtr<CSSValue> CSSParser::parseFillPositionXY(CSSParserValueList* valueList, bool& xFound, bool& yFound)
2520 int id = valueList->current()->id;
2521 if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
2523 if (id == CSSValueLeft || id == CSSValueRight) {
2527 if (id == CSSValueRight)
2530 else if (id == CSSValueTop || id == CSSValueBottom) {
2534 if (id == CSSValueBottom)
2537 else if (id == CSSValueCenter)
2538 // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
2540 return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
2542 if (validUnit(valueList->current(), FPercent | FLength, m_strict))
2543 return primitiveValueCache()->createValue(valueList->current()->fValue,
2544 (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
2549 void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
2551 CSSParserValue* value = valueList->current();
2553 // Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length.
2554 bool value1IsX = false, value1IsY = false;
2555 value1 = parseFillPositionXY(valueList, value1IsX, value1IsY);
2559 // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
2560 // can assume that any other values belong to the rest of the shorthand). If we're not parsing a shorthand, though, the
2561 // value was explicitly specified for our property.
2562 value = valueList->next();
2564 // First check for the comma. If so, we are finished parsing this value or value pair.
2565 if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
2568 bool value2IsX = false, value2IsY = false;
2570 value2 = parseFillPositionXY(valueList, value2IsX, value2IsY);
2574 if (!inShorthand()) {
2582 // Only one value was specified. If that value was not a keyword, then it sets the x position, and the y position
2583 // is simply 50%. This is our default.
2584 // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
2585 // For left/right/center, the default of 50% in the y is still correct.
2586 value2 = primitiveValueCache()->createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
2588 if (value1IsY || value2IsX)
2589 value1.swap(value2);
2592 void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
2594 CSSParserValue* value = m_valueList->current();
2596 int id = m_valueList->current()->id;
2597 if (id == CSSValueRepeatX) {
2598 m_implicitShorthand = true;
2599 value1 = primitiveValueCache()->createIdentifierValue(CSSValueRepeat);
2600 value2 = primitiveValueCache()->createIdentifierValue(CSSValueNoRepeat);
2601 m_valueList->next();
2604 if (id == CSSValueRepeatY) {
2605 m_implicitShorthand = true;
2606 value1 = primitiveValueCache()->createIdentifierValue(CSSValueNoRepeat);
2607 value2 = primitiveValueCache()->createIdentifierValue(CSSValueRepeat);
2608 m_valueList->next();
2611 if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)
2612 value1 = primitiveValueCache()->createIdentifierValue(id);
2618 value = m_valueList->next();
2620 // First check for the comma. If so, we are finished parsing this value or value pair.
2621 if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
2625 id = m_valueList->current()->id;
2627 if (value && (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)) {
2628 value2 = primitiveValueCache()->createIdentifierValue(id);
2629 m_valueList->next();
2631 // If only one value was specified, value2 is the same as value1.
2632 m_implicitShorthand = true;
2633 value2 = primitiveValueCache()->createIdentifierValue(static_cast<CSSPrimitiveValue*>(value1.get())->getIdent());
2637 PassRefPtr<CSSValue> CSSParser::parseFillSize(int propId, bool& allowComma)
2640 CSSParserValue* value = m_valueList->current();
2642 if (value->id == CSSValueContain || value->id == CSSValueCover)
2643 return primitiveValueCache()->createIdentifierValue(value->id);
2645 RefPtr<CSSPrimitiveValue> parsedValue1;
2647 if (value->id == CSSValueAuto)
2648 parsedValue1 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN);
2650 if (!validUnit(value, FLength | FPercent, m_strict))
2652 parsedValue1 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2655 CSSPropertyID property = static_cast<CSSPropertyID>(propId);
2656 RefPtr<CSSPrimitiveValue> parsedValue2;
2657 if ((value = m_valueList->next())) {
2658 if (value->id == CSSValueAuto)
2659 parsedValue2 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN);
2660 else if (value->unit == CSSParserValue::Operator && value->iValue == ',')
2663 if (!validUnit(value, FLength | FPercent, m_strict))
2665 parsedValue2 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2668 if (!parsedValue2) {
2669 if (property == CSSPropertyWebkitBackgroundSize || property == CSSPropertyWebkitMaskSize)
2670 parsedValue2 = parsedValue1;
2672 parsedValue2 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN);
2675 return primitiveValueCache()->createValue(Pair::create(parsedValue1.release(), parsedValue2.release()));
2678 bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2,
2679 RefPtr<CSSValue>& retValue1, RefPtr<CSSValue>& retValue2)
2681 RefPtr<CSSValueList> values;
2682 RefPtr<CSSValueList> values2;
2683 CSSParserValue* val;
2684 RefPtr<CSSValue> value;
2685 RefPtr<CSSValue> value2;
2687 bool allowComma = false;
2689 retValue1 = retValue2 = 0;
2692 if (propId == CSSPropertyBackgroundPosition) {
2693 propId1 = CSSPropertyBackgroundPositionX;
2694 propId2 = CSSPropertyBackgroundPositionY;
2695 } else if (propId == CSSPropertyWebkitMaskPosition) {
2696 propId1 = CSSPropertyWebkitMaskPositionX;
2697 propId2 = CSSPropertyWebkitMaskPositionY;
2698 } else if (propId == CSSPropertyBackgroundRepeat) {
2699 propId1 = CSSPropertyBackgroundRepeatX;
2700 propId2 = CSSPropertyBackgroundRepeatY;
2701 } else if (propId == CSSPropertyWebkitMaskRepeat) {
2702 propId1 = CSSPropertyWebkitMaskRepeatX;
2703 propId2 = CSSPropertyWebkitMaskRepeatY;
2706 while ((val = m_valueList->current())) {
2707 RefPtr<CSSValue> currValue;
2708 RefPtr<CSSValue> currValue2;
2711 if (val->unit != CSSParserValue::Operator || val->iValue != ',')
2713 m_valueList->next();
2718 case CSSPropertyBackgroundColor:
2719 currValue = parseBackgroundColor();
2721 m_valueList->next();
2723 case CSSPropertyBackgroundAttachment:
2724 case CSSPropertyWebkitMaskAttachment:
2725 if (val->id == CSSValueScroll || val->id == CSSValueFixed || val->id == CSSValueLocal) {
2726 currValue = primitiveValueCache()->createIdentifierValue(val->id);
2727 m_valueList->next();
2730 case CSSPropertyBackgroundImage:
2731 case CSSPropertyWebkitMaskImage:
2732 if (parseFillImage(currValue))
2733 m_valueList->next();
2735 case CSSPropertyWebkitBackgroundClip:
2736 case CSSPropertyWebkitBackgroundOrigin:
2737 case CSSPropertyWebkitMaskClip:
2738 case CSSPropertyWebkitMaskOrigin:
2739 // The first three values here are deprecated and do not apply to the version of the property that has
2740 // the -webkit- prefix removed.
2741 if (val->id == CSSValueBorder || val->id == CSSValuePadding || val->id == CSSValueContent ||
2742 val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox ||
2743 ((propId == CSSPropertyWebkitBackgroundClip || propId == CSSPropertyWebkitMaskClip) &&
2744 (val->id == CSSValueText || val->id == CSSValueWebkitText))) {
2745 currValue = primitiveValueCache()->createIdentifierValue(val->id);
2746 m_valueList->next();
2749 case CSSPropertyBackgroundClip:
2750 if (parseBackgroundClip(val, currValue, primitiveValueCache()))
2751 m_valueList->next();
2753 case CSSPropertyBackgroundOrigin:
2754 if (val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox) {
2755 currValue = primitiveValueCache()->createIdentifierValue(val->id);
2756 m_valueList->next();
2759 case CSSPropertyBackgroundPosition:
2760 case CSSPropertyWebkitMaskPosition:
2761 parseFillPosition(m_valueList, currValue, currValue2);
2762 // parseFillPosition advances the m_valueList pointer
2764 case CSSPropertyBackgroundPositionX:
2765 case CSSPropertyWebkitMaskPositionX: {
2766 bool xFound = false, yFound = true;
2767 currValue = parseFillPositionXY(m_valueList, xFound, yFound);
2769 m_valueList->next();
2772 case CSSPropertyBackgroundPositionY:
2773 case CSSPropertyWebkitMaskPositionY: {
2774 bool xFound = true, yFound = false;
2775 currValue = parseFillPositionXY(m_valueList, xFound, yFound);
2777 m_valueList->next();
2780 case CSSPropertyWebkitBackgroundComposite:
2781 case CSSPropertyWebkitMaskComposite:
2782 if ((val->id >= CSSValueClear && val->id <= CSSValuePlusLighter) || val->id == CSSValueHighlight) {
2783 currValue = primitiveValueCache()->createIdentifierValue(val->id);
2784 m_valueList->next();
2787 case CSSPropertyBackgroundRepeat:
2788 case CSSPropertyWebkitMaskRepeat:
2789 parseFillRepeat(currValue, currValue2);
2790 // parseFillRepeat advances the m_valueList pointer
2792 case CSSPropertyBackgroundSize:
2793 case CSSPropertyWebkitBackgroundSize:
2794 case CSSPropertyWebkitMaskSize: {
2795 currValue = parseFillSize(propId, allowComma);
2797 m_valueList->next();
2804 if (value && !values) {
2805 values = CSSValueList::createCommaSeparated();
2806 values->append(value.release());
2809 if (value2 && !values2) {
2810 values2 = CSSValueList::createCommaSeparated();
2811 values2->append(value2.release());
2815 values->append(currValue.release());
2817 value = currValue.release();
2820 values2->append(currValue2.release());
2822 value2 = currValue2.release();
2826 // When parsing any fill shorthand property, we let it handle building up the lists for all
2832 if (values && values->length()) {
2833 retValue1 = values.release();
2834 if (values2 && values2->length())
2835 retValue2 = values2.release();
2839 retValue1 = value.release();
2840 retValue2 = value2.release();
2846 PassRefPtr<CSSValue> CSSParser::parseAnimationDelay()
2848 CSSParserValue* value = m_valueList->current();
2849 if (validUnit(value, FTime, m_strict))
2850 return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2854 PassRefPtr<CSSValue> CSSParser::parseAnimationDirection()
2856 CSSParserValue* value = m_valueList->current();
2857 if (value->id == CSSValueNormal || value->id == CSSValueAlternate)
2858 return primitiveValueCache()->createIdentifierValue(value->id);
2862 PassRefPtr<CSSValue> CSSParser::parseAnimationDuration()
2864 CSSParserValue* value = m_valueList->current();
2865 if (validUnit(value, FTime | FNonNeg, m_strict))
2866 return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2870 PassRefPtr<CSSValue> CSSParser::parseAnimationFillMode()
2872 CSSParserValue* value = m_valueList->current();
2873 if (value->id == CSSValueNone || value->id == CSSValueForwards || value->id == CSSValueBackwards || value->id == CSSValueBoth)
2874 return primitiveValueCache()->createIdentifierValue(value->id);
2878 PassRefPtr<CSSValue> CSSParser::parseAnimationIterationCount()
2880 CSSParserValue* value = m_valueList->current();
2881 if (value->id == CSSValueInfinite)
2882 return primitiveValueCache()->createIdentifierValue(value->id);
2883 if (validUnit(value, FInteger | FNonNeg, m_strict))
2884 return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2888 PassRefPtr<CSSValue> CSSParser::parseAnimationName()
2890 CSSParserValue* value = m_valueList->current();
2891 if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT) {
2892 if (value->id == CSSValueNone || (value->unit == CSSPrimitiveValue::CSS_STRING && equalIgnoringCase(value->string, "none"))) {
2893 return primitiveValueCache()->createIdentifierValue(CSSValueNone);
2895 return primitiveValueCache()->createValue(value->string, CSSPrimitiveValue::CSS_STRING);
2901 PassRefPtr<CSSValue> CSSParser::parseAnimationPlayState()
2903 CSSParserValue* value = m_valueList->current();
2904 if (value->id == CSSValueRunning || value->id == CSSValuePaused)
2905 return primitiveValueCache()->createIdentifierValue(value->id);
2909 PassRefPtr<CSSValue> CSSParser::parseAnimationProperty()
2911 CSSParserValue* value = m_valueList->current();
2912 if (value->unit != CSSPrimitiveValue::CSS_IDENT)
2914 int result = cssPropertyID(value->string);
2916 return primitiveValueCache()->createIdentifierValue(result);
2917 if (equalIgnoringCase(value->string, "all"))
2918 return primitiveValueCache()->createIdentifierValue(CSSValueAll);
2919 if (equalIgnoringCase(value->string, "none"))
2920 return primitiveValueCache()->createIdentifierValue(CSSValueNone);
2924 bool CSSParser::parseTransformOriginShorthand(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3)
2926 parseFillPosition(m_valueList, value1, value2);
2929 if (m_valueList->current()) {
2930 if (validUnit(m_valueList->current(), FLength, m_strict)) {
2931 value3 = primitiveValueCache()->createValue(m_valueList->current()->fValue,
2932 (CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit);
2933 m_valueList->next();
2941 bool CSSParser::parseCubicBezierTimingFunctionValue(CSSParserValueList*& args, double& result)
2943 CSSParserValue* v = args->current();
2944 if (!validUnit(v, FNumber, m_strict))
2947 if (result < 0 || result > 1.0)
2951 // The last number in the function has no comma after it, so we're done.
2953 if (v->unit != CSSParserValue::Operator && v->iValue != ',')
2959 PassRefPtr<CSSValue> CSSParser::parseAnimationTimingFunction()
2961 CSSParserValue* value = m_valueList->current();
2962 if (value->id == CSSValueEase || value->id == CSSValueLinear || value->id == CSSValueEaseIn || value->id == CSSValueEaseOut
2963 || value->id == CSSValueEaseInOut || value->id == CSSValueStepStart || value->id == CSSValueStepEnd)
2964 return primitiveValueCache()->createIdentifierValue(value->id);
2966 // We must be a function.
2967 if (value->unit != CSSParserValue::Function)
2970 CSSParserValueList* args = value->function->args.get();
2972 if (equalIgnoringCase(value->function->name, "steps(")) {
2973 // For steps, 1 or 2 params must be specified (comma-separated)
2974 if (!args || (args->size() != 1 && args->size() != 3))
2977 // There are two values.
2979 bool stepAtStart = false;
2981 CSSParserValue* v = args->current();
2982 if (!validUnit(v, FInteger, m_strict))
2984 numSteps = (int) min(v->fValue, (double)INT_MAX);
2990 // There is a comma so we need to parse the second value
2991 if (v->unit != CSSParserValue::Operator && v->iValue != ',')
2994 if (v->id != CSSValueStart && v->id != CSSValueEnd)
2996 stepAtStart = v->id == CSSValueStart;
2999 return CSSStepsTimingFunctionValue::create(numSteps, stepAtStart);
3002 if (equalIgnoringCase(value->function->name, "cubic-bezier(")) {
3003 // For cubic bezier, 4 values must be specified.
3004 if (!args || args->size() != 7)
3007 // There are two points specified. The values must be between 0 and 1.
3008 double x1, y1, x2, y2;
3010 if (!parseCubicBezierTimingFunctionValue(args, x1))
3012 if (!parseCubicBezierTimingFunctionValue(args, y1))
3014 if (!parseCubicBezierTimingFunctionValue(args, x2))
3016 if (!parseCubicBezierTimingFunctionValue(args, y2))
3019 return CSSCubicBezierTimingFunctionValue::create(x1, y1, x2, y2);
3025 bool CSSParser::parseAnimationProperty(int propId, RefPtr<CSSValue>& result)
3027 RefPtr<CSSValueList> values;
3028 CSSParserValue* val;
3029 RefPtr<CSSValue> value;
3030 bool allowComma = false;
3034 while ((val = m_valueList->current())) {
3035 RefPtr<CSSValue> currValue;
3037 if (val->unit != CSSParserValue::Operator || val->iValue != ',')
3039 m_valueList->next();
3044 case CSSPropertyWebkitAnimationDelay:
3045 case CSSPropertyWebkitTransitionDelay:
3046 currValue = parseAnimationDelay();
3048 m_valueList->next();
3050 case CSSPropertyWebkitAnimationDirection:
3051 currValue = parseAnimationDirection();
3053 m_valueList->next();
3055 case CSSPropertyWebkitAnimationDuration:
3056 case CSSPropertyWebkitTransitionDuration:
3057 currValue = parseAnimationDuration();
3059 m_valueList->next();
3061 case CSSPropertyWebkitAnimationFillMode:
3062 currValue = parseAnimationFillMode();
3064 m_valueList->next();
3066 case CSSPropertyWebkitAnimationIterationCount:
3067 currValue = parseAnimationIterationCount();
3069 m_valueList->next();
3071 case CSSPropertyWebkitAnimationName:
3072 currValue = parseAnimationName();
3074 m_valueList->next();
3076 case CSSPropertyWebkitAnimationPlayState:
3077 currValue = parseAnimationPlayState();
3079 m_valueList->next();
3081 case CSSPropertyWebkitTransitionProperty:
3082 currValue = parseAnimationProperty();
3084 m_valueList->next();
3086 case CSSPropertyWebkitAnimationTimingFunction:
3087 case CSSPropertyWebkitTransitionTimingFunction:
3088 currValue = parseAnimationTimingFunction();
3090 m_valueList->next();
3097 if (value && !values) {
3098 values = CSSValueList::createCommaSeparated();
3099 values->append(value.release());
3103 values->append(currValue.release());
3105 value = currValue.release();
3110 // When parsing the 'transition' shorthand property, we let it handle building up the lists for all
3116 if (values && values->length()) {
3117 result = values.release();
3121 result = value.release();
3129 #if ENABLE(DASHBOARD_SUPPORT)
3131 #define DASHBOARD_REGION_NUM_PARAMETERS 6
3132 #define DASHBOARD_REGION_SHORT_NUM_PARAMETERS 2
3134 static CSSParserValue* skipCommaInDashboardRegion(CSSParserValueList *args)
3136 if (args->size() == (DASHBOARD_REGION_NUM_PARAMETERS*2-1) ||
3137 args->size() == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
3138 CSSParserValue* current = args->current();
3139 if (current->unit == CSSParserValue::Operator && current->iValue == ',')
3140 return args->next();
3142 return args->current();
3145 bool CSSParser::parseDashboardRegions(int propId, bool important)
3149 CSSParserValue* value = m_valueList->current();
3151 if (value->id == CSSValueNone) {
3152 if (m_valueList->next())
3154 addProperty(propId, primitiveValueCache()->createIdentifierValue(value->id), important);
3158 RefPtr<DashboardRegion> firstRegion = DashboardRegion::create();
3159 DashboardRegion* region = 0;
3163 region = firstRegion.get();
3165 RefPtr<DashboardRegion> nextRegion = DashboardRegion::create();
3166 region->m_next = nextRegion;
3167 region = nextRegion.get();
3170 if (value->unit != CSSParserValue::Function) {
3175 // Commas count as values, so allow:
3176 // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
3177 // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
3179 // dashboard-region(label, type) or dashboard-region(label type)
3180 // dashboard-region(label, type) or dashboard-region(label type)
3181 CSSParserValueList* args = value->function->args.get();
3182 if (!equalIgnoringCase(value->function->name, "dashboard-region(") || !args) {
3187 int numArgs = args->size();
3188 if ((numArgs != DASHBOARD_REGION_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_NUM_PARAMETERS*2-1)) &&
3189 (numArgs != DASHBOARD_REGION_SHORT_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1))) {
3194 // First arg is a label.
3195 CSSParserValue* arg = args->current();
3196 if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
3201 region->m_label = arg->string;
3203 // Second arg is a type.
3205 arg = skipCommaInDashboardRegion(args);
3206 if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
3211 if (equalIgnoringCase(arg->string, "circle"))
3212 region->m_isCircle = true;
3213 else if (equalIgnoringCase(arg->string, "rectangle"))
3214 region->m_isRectangle = true;
3220 region->m_geometryType = arg->string;
3222 if (numArgs == DASHBOARD_REGION_SHORT_NUM_PARAMETERS || numArgs == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
3223 // This originally used CSSValueInvalid by accident. It might be more logical to use something else.
3224 RefPtr<CSSPrimitiveValue> amount = primitiveValueCache()->createIdentifierValue(CSSValueInvalid);
3226 region->setTop(amount);
3227 region->setRight(amount);
3228 region->setBottom(amount);
3229 region->setLeft(amount);
3231 // Next four arguments must be offset numbers
3233 for (i = 0; i < 4; i++) {
3235 arg = skipCommaInDashboardRegion(args);
3237 valid = arg->id == CSSValueAuto || validUnit(arg, FLength, m_strict);
3241 RefPtr<CSSPrimitiveValue> amount = arg->id == CSSValueAuto ?
3242 primitiveValueCache()->createIdentifierValue(CSSValueAuto) :
3243 primitiveValueCache()->createValue(arg->fValue, (CSSPrimitiveValue::UnitTypes) arg->unit);
3246 region->setTop(amount);
3248 region->setRight(amount);
3250 region->setBottom(amount);
3252 region->setLeft(amount);
3259 value = m_valueList->next();
3263 addProperty(propId, primitiveValueCache()->createValue(firstRegion.release()), important);
3268 #endif /* ENABLE(DASHBOARD_SUPPORT) */
3270 PassRefPtr<CSSValue> CSSParser::parseCounterContent(CSSParserValueList* args, bool counters)
3272 unsigned numArgs = args->size();
3273 if (counters && numArgs != 3 && numArgs != 5)
3275 if (!counters && numArgs != 1 && numArgs != 3)
3278 CSSParserValue* i = args->current();
3279 if (i->unit != CSSPrimitiveValue::CSS_IDENT)
3281 RefPtr<CSSPrimitiveValue> identifier = primitiveValueCache()->createValue(i->string, CSSPrimitiveValue::CSS_STRING);
3283 RefPtr<CSSPrimitiveValue> separator;
3285 separator = primitiveValueCache()->createValue(String(), CSSPrimitiveValue::CSS_STRING);
3288 if (i->unit != CSSParserValue::Operator || i->iValue != ',')
3292 if (i->unit != CSSPrimitiveValue::CSS_STRING)
3295 separator = primitiveValueCache()->createValue(i->string, (CSSPrimitiveValue::UnitTypes) i->unit);
3298 RefPtr<CSSPrimitiveValue> listStyle;
3300 if (!i) // Make the list style default decimal
3301 listStyle = primitiveValueCache()->createValue(CSSValueDecimal - CSSValueDisc, CSSPrimitiveValue::CSS_NUMBER);
3303 if (i->unit != CSSParserValue::Operator || i->iValue != ',')
3307 if (i->unit != CSSPrimitiveValue::CSS_IDENT)
3311 if (i->id == CSSValueNone)
3312 ls = CSSValueKatakanaIroha - CSSValueDisc + 1;
3313 else if (i->id >= CSSValueDisc && i->id <= CSSValueKatakanaIroha)
3314 ls = i->id - CSSValueDisc;
3318 listStyle = primitiveValueCache()->createValue(ls, (CSSPrimitiveValue::UnitTypes) i->unit);
3321 return primitiveValueCache()->createValue(Counter::create(identifier.release(), listStyle.release(), separator.release()));
3324 bool CSSParser::parseShape(int propId, bool important)
3326 CSSParserValue* value = m_valueList->current();
3327 CSSParserValueList* args = value->function->args.get();
3329 if (!equalIgnoringCase(value->function->name, "rect(") || !args)
3332 // rect(t, r, b, l) || rect(t r b l)
3333 if (args->size() != 4 && args->size() != 7)
3335 RefPtr<Rect> rect = Rect::create();
3338 CSSParserValue* a = args->current();
3340 valid = a->id == CSSValueAuto || validUnit(a, FLength, m_strict);
3343 RefPtr<CSSPrimitiveValue> length = a->id == CSSValueAuto ?
3344 primitiveValueCache()->createIdentifierValue(CSSValueAuto) :
3345 primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit);
3347 rect->setTop(length);
3349 rect->setRight(length);
3351 rect->setBottom(length);
3353 rect->setLeft(length);
3355 if (a && args->size() == 7) {
3356 if (a->unit == CSSParserValue::Operator && a->iValue == ',') {
3366 addProperty(propId, primitiveValueCache()->createValue(rect.release()), important);
3367 m_valueList->next();
3373 // [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family'
3374 bool CSSParser::parseFont(bool important)
3377 CSSParserValue *value = m_valueList->current();
3378 RefPtr<FontValue> font = FontValue::create();
3379 // optional font-style, font-variant and font-weight
3383 if (id == CSSValueNormal) {
3384 // do nothing, it's the inital value for all three
3385 } else if (id == CSSValueItalic || id == CSSValueOblique) {
3388 font->style = primitiveValueCache()->createIdentifierValue(id);
3389 } else if (id == CSSValueSmallCaps) {
3392 font->variant = primitiveValueCache()->createIdentifierValue(id);
3393 } else if (id >= CSSValueBold && id <= CSSValueLighter) {
3396 font->weight = primitiveValueCache()->createIdentifierValue(id);
3400 } else if (!font->weight && validUnit(value, FInteger | FNonNeg, true)) {
3401 int weight = (int)value->fValue;
3405 else if (weight == 200)
3407 else if (weight == 300)
3409 else if (weight == 400)
3411 else if (weight == 500)
3413 else if (weight == 600)
3415 else if (weight == 700)
3417 else if (weight == 800)
3419 else if (weight == 900)
3423 font->weight = primitiveValueCache()->createIdentifierValue(val);
3431 value = m_valueList->next();
3436 // set undefined values to default
3438 font->style = primitiveValueCache()->createIdentifierValue(CSSValueNormal);
3440 font->variant = primitiveValueCache()->createIdentifierValue(CSSValueNormal);
3442 font->weight = primitiveValueCache()->createIdentifierValue(CSSValueNormal);
3444 // now a font size _must_ come
3445 // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
3446 if (value->id >= CSSValueXxSmall && value->id <= CSSValueLarger)
3447 font->size = primitiveValueCache()->createIdentifierValue(value->id);
3448 else if (validUnit(value, FLength | FPercent | FNonNeg, m_strict))
3449 font->size = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
3450 value = m_valueList->next();
3451 if (!font->size || !value)
3454 if (value->unit == CSSParserValue::Operator && value->iValue == '/') {
3456 value = m_valueList->next();
3459 if (value->id == CSSValueNormal) {
3460 // default value, nothing to do
3461 } else if (validUnit(value, FNumber | FLength | FPercent | FNonNeg, m_strict))
3462 font->lineHeight = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
3465 value = m_valueList->next();
3470 if (!font->lineHeight)
3471 font->lineHeight = primitiveValueCache()->createIdentifierValue(CSSValueNormal);
3473 // font family must come now
3474 font->family = parseFontFamily();
3476 if (m_valueList->current() || !font->family)
3479 addProperty(CSSPropertyFont, font.release(), important);
3483 PassRefPtr<CSSValueList> CSSParser::parseFontFamily()
3485 RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
3486 CSSParserValue* value = m_valueList->current();
3488 FontFamilyValue* currFamily = 0;
3490 CSSParserValue* nextValue = m_valueList->next();
3491 bool nextValBreaksFont = !nextValue ||
3492 (nextValue->unit == CSSParserValue::Operator && nextValue->iValue == ',');
3493 bool nextValIsFontName = nextValue &&
3494 ((nextValue->id >= CSSValueSerif && nextValue->id <= CSSValueWebkitBody) ||
3495 (nextValue->unit == CSSPrimitiveValue::CSS_STRING || nextValue->unit == CSSPrimitiveValue::CSS_IDENT));
3497 if (value->id >= CSSValueSerif && value->id <= CSSValueWebkitBody) {
3499 currFamily->appendSpaceSeparated(value->string.characters, value->string.length);
3500 else if (nextValBreaksFont || !nextValIsFontName)
3501 list->append(primitiveValueCache()->createIdentifierValue(value->id));
3503 RefPtr<FontFamilyValue> newFamily = FontFamilyValue::create(value->string);
3504 currFamily = newFamily.get();
3505 list->append(newFamily.release());
3507 } else if (value->unit == CSSPrimitiveValue::CSS_STRING) {
3508 // Strings never share in a family name.
3510 list->append(FontFamilyValue::create(value->string));
3511 } else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
3513 currFamily->appendSpaceSeparated(value->string.characters, value->string.length);
3514 else if (nextValBreaksFont || !nextValIsFontName)
3515 list->append(FontFamilyValue::create(value->string));
3517 RefPtr<FontFamilyValue> newFamily = FontFamilyValue::create(value->string);
3518 currFamily = newFamily.get();
3519 list->append(newFamily.release());
3528 if (nextValBreaksFont) {
3529 value = m_valueList->next();
3532 else if (nextValIsFontName)
3537 if (!list->length())
3539 return list.release();
3542 bool CSSParser::parseFontStyle(bool important)
3544 RefPtr<CSSValueList> values;
3545 if (m_valueList->size() > 1)
3546 values = CSSValueList::createCommaSeparated();
3547 CSSParserValue* val;
3548 bool expectComma = false;
3549 while ((val = m_valueList->current())) {
3550 RefPtr<CSSPrimitiveValue> parsedValue;
3553 if (val->id == CSSValueNormal || val->id == CSSValueItalic || val->id == CSSValueOblique)
3554 parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
3555 else if (val->id == CSSValueAll && !values) {
3556 // 'all' is only allowed in @font-face and with no other values. Make a value list to
3557 // indicate that we are in the @font-face case.
3558 values = CSSValueList::createCommaSeparated();
3559 parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
3561 } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3562 expectComma = false;
3563 m_valueList->next();
3570 m_valueList->next();
3573 values->append(parsedValue.release());
3575 addProperty(CSSPropertyFontStyle, parsedValue.release(), important);
3580 if (values && values->length()) {
3581 m_hasFontFaceOnlyValues = true;
3582 addProperty(CSSPropertyFontStyle, values.release(), important);
3589 bool CSSParser::parseFontVariant(bool important)
3591 RefPtr<CSSValueList> values;
3592 if (m_valueList->size() > 1)
3593 values = CSSValueList::createCommaSeparated();
3594 CSSParserValue* val;
3595 bool expectComma = false;
3596 while ((val = m_valueList->current())) {
3597 RefPtr<CSSPrimitiveValue> parsedValue;
3600 if (val->id == CSSValueNormal || val->id == CSSValueSmallCaps)
3601 parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
3602 else if (val->id == CSSValueAll && !values) {
3603 // 'all' is only allowed in @font-face and with no other values. Make a value list to
3604 // indicate that we are in the @font-face case.
3605 values = CSSValueList::createCommaSeparated();
3606 parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
3608 } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3609 expectComma = false;
3610 m_valueList->next();
3617 m_valueList->next();
3620 values->append(parsedValue.release());
3622 addProperty(CSSPropertyFontVariant, parsedValue.release(), important);
3627 if (values && values->length()) {
3628 m_hasFontFaceOnlyValues = true;
3629 addProperty(CSSPropertyFontVariant, values.release(), important);
3636 bool CSSParser::parseFontWeight(bool important)
3638 RefPtr<CSSValueList> values;
3639 if (m_valueList->size() > 1)
3640 values = CSSValueList::createCommaSeparated();
3641 CSSParserValue* val;
3642 bool expectComma = false;
3643 while ((val = m_valueList->current())) {
3644 RefPtr<CSSPrimitiveValue> parsedValue;
3647 if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
3648 if (val->id >= CSSValueNormal && val->id <= CSSValue900)
3649 parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
3650 else if (val->id == CSSValueAll && !values) {
3651 // 'all' is only allowed in @font-face and with no other values. Make a value list to
3652 // indicate that we are in the @font-face case.
3653 values = CSSValueList::createCommaSeparated();
3654 parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
3656 } else if (validUnit(val, FInteger | FNonNeg, false)) {
3657 int weight = static_cast<int>(val->fValue);
3658 if (!(weight % 100) && weight >= 100 && weight <= 900)
3659 parsedValue = primitiveValueCache()->createIdentifierValue(CSSValue100 + weight / 100 - 1);
3661 } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3662 expectComma = false;
3663 m_valueList->next();
3670 m_valueList->next();
3673 values->append(parsedValue.release());
3675 addProperty(CSSPropertyFontWeight, parsedValue.release(), important);
3680 if (values && values->length()) {
3681 m_hasFontFaceOnlyValues = true;
3682 addProperty(CSSPropertyFontWeight, values.release(), important);
3689 static bool isValidFormatFunction(CSSParserValue* val)
3691 CSSParserValueList* args = val->function->args.get();
3692 return equalIgnoringCase(val->function->name, "format(") && (args->current()->unit == CSSPrimitiveValue::CSS_STRING || args->current()->unit == CSSPrimitiveValue::CSS_IDENT);
3695 bool CSSParser::parseFontFaceSrc()
3697 RefPtr<CSSValueList> values(CSSValueList::createCommaSeparated());
3698 CSSParserValue* val;
3699 bool expectComma = false;
3700 bool allowFormat = false;
3701 bool failed = false;
3702 RefPtr<CSSFontFaceSrcValue> uriValue;
3703 while ((val = m_valueList->current())) {
3704 RefPtr<CSSFontFaceSrcValue> parsedValue;
3705 if (val->unit == CSSPrimitiveValue::CSS_URI && !expectComma && m_styleSheet) {
3706 // FIXME: The completeURL call should be done when using the CSSFontFaceSrcValue,
3707 // not when creating it.
3708 parsedValue = CSSFontFaceSrcValue::create(m_styleSheet->completeURL(val->string));
3709 uriValue = parsedValue;
3712 } else if (val->unit == CSSParserValue::Function) {
3713 // There are two allowed functions: local() and format().
3714 CSSParserValueList* args = val->function->args.get();
3715 if (args && args->size() == 1) {
3716 if (equalIgnoringCase(val->function->name, "local(") && !expectComma && (args->current()->unit == CSSPrimitiveValue::CSS_STRING || args->current()->unit == CSSPrimitiveValue::CSS_IDENT)) {
3718 allowFormat = false;
3719 CSSParserValue* a = args->current();
3721 parsedValue = CSSFontFaceSrcValue::createLocal(a->string);
3722 } else if (allowFormat && uriValue && isValidFormatFunction(val)) {
3724 allowFormat = false;
3725 uriValue->setFormat(args->current()->string);
3727 m_valueList->next();
3731 } else if (val->unit == CSSParserValue::Operator && val->iValue == ',' && expectComma) {
3732 expectComma = false;
3733 allowFormat = false;
3735 m_valueList->next();
3740 values->append(parsedValue.release());
3745 m_valueList->next();
3748 if (values->length() && !failed) {
3749 addProperty(CSSPropertySrc, values.release(), m_important);
3750 m_valueList->next();
3757 bool CSSParser::parseFontFaceUnicodeRange()
3759 RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3760 bool failed = false;
3761 bool operatorExpected = false;
3762 for (; m_valueList->current(); m_valueList->next(), operatorExpected = !operatorExpected) {
3763 if (operatorExpected) {
3764 if (m_valueList->current()->unit == CSSParserValue::Operator && m_valueList->current()->iValue == ',')
3769 if (m_valueList->current()->unit != CSSPrimitiveValue::CSS_UNICODE_RANGE) {
3774 String rangeString = m_valueList->current()->string;
3777 unsigned length = rangeString.length();
3785 while (i < length) {
3786 UChar c = rangeString[i];
3787 if (c == '-' || c == '?')
3790 if (c >= '0' && c <= '9')
3792 else if (c >= 'A' && c <= 'F')
3793 from += 10 + c - 'A';
3794 else if (c >= 'a' && c <= 'f')
3795 from += 10 + c - 'a';
3807 else if (rangeString[i] == '?') {
3809 while (i < length && rangeString[i] == '?') {
3816 to = from + span - 1;
3818 if (length < i + 2) {
3823 while (i < length) {
3824 UChar c = rangeString[i];
3826 if (c >= '0' && c <= '9')
3828 else if (c >= 'A' && c <= 'F')
3830 else if (c >= 'a' && c <= 'f')
3842 values->append(CSSUnicodeRangeValue::create(from, to));
3844 if (failed || !values->length())
3846 addProperty(CSSPropertyUnicodeRange, values.release(), m_important);
3850 static inline bool parseColorInt(const UChar*& string, const UChar* end, UChar terminator, int& value)
3852 const UChar* current = string;
3854 bool negative = false;
3855 while (current != end && isHTMLSpace(*current))
3857 if (current != end && *current == '-') {
3861 if (current == end || !isASCIIDigit(*current))