Home | History | Annotate | Download | only in css
      1 /*
      2  * Copyright (C) 2003 Lars Knoll (knoll (at) kde.org)
      3  * Copyright (C) 2005 Allan Sandfeld Jensen (kde (at) carewolf.com)
      4  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
      5  * Copyright (C) 2007 Nicholas Shanks <webkit (at) nickshanks.com>
      6  * Copyright (C) 2008 Eric Seidel <eric (at) webkit.org>
      7  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      8  *
      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.
     13  *
     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.
     18  *
     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.
     23  */
     24 
     25 #include "config.h"
     26 #include "CSSParser.h"
     27 
     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 "CSSLineBoxContainValue.h"
     40 #include "CSSMediaRule.h"
     41 #include "CSSMutableStyleDeclaration.h"
     42 #include "CSSPageRule.h"
     43 #include "CSSPrimitiveValue.h"
     44 #include "CSSPrimitiveValueCache.h"
     45 #include "CSSProperty.h"
     46 #include "CSSPropertyNames.h"
     47 #include "CSSPropertySourceData.h"
     48 #include "CSSQuirkPrimitiveValue.h"
     49 #include "CSSReflectValue.h"
     50 #include "CSSRuleList.h"
     51 #include "CSSSelector.h"
     52 #include "CSSStyleRule.h"
     53 #include "CSSStyleSheet.h"
     54 #include "CSSTimingFunctionValue.h"
     55 #include "CSSUnicodeRangeValue.h"
     56 #include "CSSValueKeywords.h"
     57 #include "CSSValueList.h"
     58 #include "Counter.h"
     59 #include "Document.h"
     60 #include "FloatConversion.h"
     61 #include "FontFamilyValue.h"
     62 #include "FontValue.h"
     63 #include "HTMLParserIdioms.h"
     64 #include "HashTools.h"
     65 #include "MediaList.h"
     66 #include "MediaQueryExp.h"
     67 #include "Page.h"
     68 #include "Pair.h"
     69 #include "Rect.h"
     70 #include "RenderTheme.h"
     71 #include "ShadowValue.h"
     72 #include "WebKitCSSKeyframeRule.h"
     73 #include "WebKitCSSKeyframesRule.h"
     74 #include "WebKitCSSTransformValue.h"
     75 #include <limits.h>
     76 #include <wtf/HexNumber.h>
     77 #include <wtf/dtoa.h>
     78 #include <wtf/text/StringBuffer.h>
     79 
     80 #if ENABLE(DASHBOARD_SUPPORT)
     81 #include "DashboardRegion.h"
     82 #endif
     83 
     84 #define YYDEBUG 0
     85 
     86 #if YYDEBUG > 0
     87 extern int cssyydebug;
     88 #endif
     89 
     90 extern int cssyyparse(WebCore::CSSParser*);
     91 
     92 using namespace std;
     93 using namespace WTF;
     94 
     95 namespace WebCore {
     96 
     97 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
     98 static const double MAX_SCALE = 1000000;
     99 
    100 static bool equal(const CSSParserString& a, const char* b)
    101 {
    102     for (int i = 0; i < a.length; ++i) {
    103         if (!b[i])
    104             return false;
    105         if (a.characters[i] != b[i])
    106             return false;
    107     }
    108     return !b[a.length];
    109 }
    110 
    111 static bool equalIgnoringCase(const CSSParserString& a, const char* b)
    112 {
    113     for (int i = 0; i < a.length; ++i) {
    114         if (!b[i])
    115             return false;
    116         ASSERT(!isASCIIUpper(b[i]));
    117         if (toASCIILower(a.characters[i]) != b[i])
    118             return false;
    119     }
    120     return !b[a.length];
    121 }
    122 
    123 static bool hasPrefix(const char* string, unsigned length, const char* prefix)
    124 {
    125     for (unsigned i = 0; i < length; ++i) {
    126         if (!prefix[i])
    127             return true;
    128         if (string[i] != prefix[i])
    129             return false;
    130     }
    131     return false;
    132 }
    133 
    134 CSSParser::CSSParser(bool strictParsing)
    135     : m_strict(strictParsing)
    136     , m_important(false)
    137     , m_id(0)
    138     , m_styleSheet(0)
    139     , m_valueList(0)
    140     , m_parsedProperties(static_cast<CSSProperty**>(fastMalloc(32 * sizeof(CSSProperty*))))
    141     , m_numParsedProperties(0)
    142     , m_maxParsedProperties(32)
    143     , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
    144     , m_inParseShorthand(0)
    145     , m_currentShorthand(0)
    146     , m_implicitShorthand(false)
    147     , m_hasFontFaceOnlyValues(false)
    148     , m_hadSyntacticallyValidCSSRule(false)
    149     , m_defaultNamespace(starAtom)
    150     , m_inStyleRuleOrDeclaration(false)
    151     , m_selectorListRange(0, 0)
    152     , m_ruleBodyRange(0, 0)
    153     , m_propertyRange(UINT_MAX, UINT_MAX)
    154     , m_ruleRangeMap(0)
    155     , m_currentRuleData(0)
    156     , m_data(0)
    157     , yy_start(1)
    158     , m_lineNumber(0)
    159     , m_lastSelectorLineNumber(0)
    160     , m_allowImportRules(true)
    161     , m_allowNamespaceDeclarations(true)
    162 {
    163 #if YYDEBUG > 0
    164     cssyydebug = 1;
    165 #endif
    166     CSSPropertySourceData::init();
    167 }
    168 
    169 CSSParser::~CSSParser()
    170 {
    171     clearProperties();
    172     fastFree(m_parsedProperties);
    173 
    174     delete m_valueList;
    175 
    176     fastFree(m_data);
    177 
    178     fastDeleteAllValues(m_floatingSelectors);
    179     deleteAllValues(m_floatingSelectorVectors);
    180     deleteAllValues(m_floatingValueLists);
    181     deleteAllValues(m_floatingFunctions);
    182 }
    183 
    184 void CSSParserString::lower()
    185 {
    186     // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
    187     // that can potentially change the length of the string rather than the character
    188     // by character kind. If we don't need Unicode lowercasing, it would be good to
    189     // simplify this function.
    190 
    191     if (charactersAreAllASCII(characters, length)) {
    192         // Fast case for all-ASCII.
    193         for (int i = 0; i < length; i++)
    194             characters[i] = toASCIILower(characters[i]);
    195     } else {
    196         for (int i = 0; i < length; i++)
    197             characters[i] = Unicode::toLower(characters[i]);
    198     }
    199 }
    200 
    201 void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix)
    202 {
    203     int length = string.length() + strlen(prefix) + strlen(suffix) + 2;
    204 
    205     fastFree(m_data);
    206     m_data = static_cast<UChar*>(fastMalloc(length * sizeof(UChar)));
    207     for (unsigned i = 0; i < strlen(prefix); i++)
    208         m_data[i] = prefix[i];
    209 
    210     memcpy(m_data + strlen(prefix), string.characters(), string.length() * sizeof(UChar));
    211 
    212     unsigned start = strlen(prefix) + string.length();
    213     unsigned end = start + strlen(suffix);
    214     for (unsigned i = start; i < end; i++)
    215         m_data[i] = suffix[i - start];
    216 
    217     m_data[length - 1] = 0;
    218     m_data[length - 2] = 0;
    219 
    220     yy_hold_char = 0;
    221     yyleng = 0;
    222     yytext = yy_c_buf_p = m_data;
    223     yy_hold_char = *yy_c_buf_p;
    224     resetRuleBodyMarks();
    225 }
    226 
    227 void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string, int startLineNumber, StyleRuleRangeMap* ruleRangeMap)
    228 {
    229     setStyleSheet(sheet);
    230     m_defaultNamespace = starAtom; // Reset the default namespace.
    231     m_ruleRangeMap = ruleRangeMap;
    232     if (ruleRangeMap) {
    233         m_currentRuleData = CSSRuleSourceData::create();
    234         m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
    235     }
    236 
    237     m_lineNumber = startLineNumber;
    238     setupParser("", string, "");
    239     cssyyparse(this);
    240     m_ruleRangeMap = 0;
    241     m_currentRuleData = 0;
    242     m_rule = 0;
    243 }
    244 
    245 PassRefPtr<CSSRule> CSSParser::parseRule(CSSStyleSheet* sheet, const String& string)
    246 {
    247     setStyleSheet(sheet);
    248     m_allowNamespaceDeclarations = false;
    249     setupParser("@-webkit-rule{", string, "} ");
    250     cssyyparse(this);
    251     return m_rule.release();
    252 }
    253 
    254 PassRefPtr<CSSRule> CSSParser::parseKeyframeRule(CSSStyleSheet *sheet, const String &string)
    255 {
    256     setStyleSheet(sheet);
    257     setupParser("@-webkit-keyframe-rule{ ", string, "} ");
    258     cssyyparse(this);
    259     return m_keyframe.release();
    260 }
    261 
    262 static inline bool isColorPropertyID(int propertyId)
    263 {
    264     switch (propertyId) {
    265     case CSSPropertyColor:
    266     case CSSPropertyBackgroundColor:
    267     case CSSPropertyBorderBottomColor:
    268     case CSSPropertyBorderLeftColor:
    269     case CSSPropertyBorderRightColor:
    270     case CSSPropertyBorderTopColor:
    271     case CSSPropertyOutlineColor:
    272     case CSSPropertyTextLineThroughColor:
    273     case CSSPropertyTextOverlineColor:
    274     case CSSPropertyTextUnderlineColor:
    275     case CSSPropertyWebkitBorderAfterColor:
    276     case CSSPropertyWebkitBorderBeforeColor:
    277     case CSSPropertyWebkitBorderEndColor:
    278     case CSSPropertyWebkitBorderStartColor:
    279     case CSSPropertyWebkitColumnRuleColor:
    280     case CSSPropertyWebkitTextEmphasisColor:
    281     case CSSPropertyWebkitTextFillColor:
    282     case CSSPropertyWebkitTextStrokeColor:
    283         return true;
    284     default:
    285         return false;
    286     }
    287 }
    288 
    289 static bool parseColorValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict)
    290 {
    291     if (!string.length())
    292         return false;
    293     if (!isColorPropertyID(propertyId))
    294         return false;
    295     CSSParserString cssString;
    296     cssString.characters = const_cast<UChar*>(string.characters());
    297     cssString.length = string.length();
    298     int valueID = cssValueKeywordID(cssString);
    299     bool validPrimitive = false;
    300     if (valueID == CSSValueWebkitText)
    301         validPrimitive = true;
    302     else if (valueID == CSSValueCurrentcolor)
    303         validPrimitive = true;
    304     else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
    305              || (valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText && !strict)) {
    306         validPrimitive = true;
    307     }
    308 
    309     CSSStyleSheet* stylesheet = static_cast<CSSStyleSheet*>(declaration->stylesheet());
    310     if (!stylesheet || !stylesheet->document())
    311         return false;
    312     if (validPrimitive) {
    313         CSSProperty property(propertyId, stylesheet->document()->cssPrimitiveValueCache()->createIdentifierValue(valueID), important);
    314         declaration->addParsedProperty(property);
    315         return true;
    316     }
    317     RGBA32 color;
    318     if (!CSSParser::parseColor(string, color, strict && string[0] != '#'))
    319         return false;
    320     CSSProperty property(propertyId, stylesheet->document()->cssPrimitiveValueCache()->createColorValue(color), important);
    321     declaration->addParsedProperty(property);
    322     return true;
    323 }
    324 
    325 static inline bool isSimpleLengthPropertyID(int propertyId, bool& acceptsNegativeNumbers)
    326 {
    327     switch (propertyId) {
    328     case CSSPropertyFontSize:
    329     case CSSPropertyHeight:
    330     case CSSPropertyWidth:
    331     case CSSPropertyMinHeight:
    332     case CSSPropertyMinWidth:
    333     case CSSPropertyPaddingBottom:
    334     case CSSPropertyPaddingLeft:
    335     case CSSPropertyPaddingRight:
    336     case CSSPropertyPaddingTop:
    337     case CSSPropertyWebkitLogicalWidth:
    338     case CSSPropertyWebkitLogicalHeight:
    339     case CSSPropertyWebkitMinLogicalWidth:
    340     case CSSPropertyWebkitMinLogicalHeight:
    341     case CSSPropertyWebkitPaddingAfter:
    342     case CSSPropertyWebkitPaddingBefore:
    343     case CSSPropertyWebkitPaddingEnd:
    344     case CSSPropertyWebkitPaddingStart:
    345         acceptsNegativeNumbers = false;
    346         return true;
    347     case CSSPropertyBottom:
    348     case CSSPropertyLeft:
    349     case CSSPropertyMarginBottom:
    350     case CSSPropertyMarginLeft:
    351     case CSSPropertyMarginRight:
    352     case CSSPropertyMarginTop:
    353     case CSSPropertyRight:
    354     case CSSPropertyTextIndent:
    355     case CSSPropertyTop:
    356     case CSSPropertyWebkitMarginAfter:
    357     case CSSPropertyWebkitMarginBefore:
    358     case CSSPropertyWebkitMarginEnd:
    359     case CSSPropertyWebkitMarginStart:
    360         acceptsNegativeNumbers = true;
    361         return true;
    362     default:
    363         return false;
    364     }
    365 }
    366 
    367 static bool parseSimpleLengthValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict)
    368 {
    369     const UChar* characters = string.characters();
    370     unsigned length = string.length();
    371     if (!characters || !length)
    372         return false;
    373     bool acceptsNegativeNumbers;
    374     if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
    375         return false;
    376 
    377     CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
    378     if (length > 2 && characters[length - 2] == 'p' && characters[length - 1] == 'x') {
    379         length -= 2;
    380         unit = CSSPrimitiveValue::CSS_PX;
    381     } else if (length > 1 && characters[length - 1] == '%') {
    382         length -= 1;
    383         unit = CSSPrimitiveValue::CSS_PERCENTAGE;
    384     }
    385 
    386     // We rely on charactersToDouble for validation as well. The function
    387     // will set "ok" to "false" if the entire passed-in character range does
    388     // not represent a double.
    389     bool ok;
    390     double number = charactersToDouble(characters, length, &ok);
    391     if (!ok)
    392         return false;
    393     if (unit == CSSPrimitiveValue::CSS_NUMBER) {
    394         if (number && strict)
    395             return false;
    396         unit = CSSPrimitiveValue::CSS_PX;
    397     }
    398     if (number < 0 && !acceptsNegativeNumbers)
    399         return false;
    400 
    401     CSSStyleSheet* stylesheet = static_cast<CSSStyleSheet*>(declaration->stylesheet());
    402     if (!stylesheet || !stylesheet->document())
    403         return false;
    404     CSSProperty property(propertyId, stylesheet->document()->cssPrimitiveValueCache()->createValue(number, unit), important);
    405     declaration->addParsedProperty(property);
    406     return true;
    407 }
    408 
    409 bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict)
    410 {
    411     if (parseSimpleLengthValue(declaration, propertyId, string, important, strict))
    412         return true;
    413     if (parseColorValue(declaration, propertyId, string, important, strict))
    414         return true;
    415     CSSParser parser(strict);
    416     return parser.parseValue(declaration, propertyId, string, important);
    417 }
    418 
    419 bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important)
    420 {
    421     ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet());
    422     setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet()));
    423 
    424     setupParser("@-webkit-value{", string, "} ");
    425 
    426     m_id = propertyId;
    427     m_important = important;
    428 
    429     cssyyparse(this);
    430 
    431     m_rule = 0;
    432 
    433     bool ok = false;
    434     if (m_hasFontFaceOnlyValues)
    435         deleteFontFaceOnlyValues();
    436     if (m_numParsedProperties) {
    437         ok = true;
    438         declaration->addParsedProperties(m_parsedProperties, m_numParsedProperties);
    439         clearProperties();
    440     }
    441 
    442     return ok;
    443 }
    444 
    445 // color will only be changed when string contains a valid css color, making it
    446 // possible to set up a default color.
    447 bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict)
    448 {
    449     // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
    450     if (parseColor(string, color, strict))
    451         return true;
    452 
    453     CSSParser parser(true);
    454     RefPtr<CSSMutableStyleDeclaration> dummyStyleDeclaration = CSSMutableStyleDeclaration::create();
    455 
    456     // Now try to create a color from rgba() syntax.
    457     if (!parser.parseColor(dummyStyleDeclaration.get(), string))
    458         return false;
    459 
    460     CSSValue* value = parser.m_parsedProperties[0]->value();
    461     if (value->cssValueType() != CSSValue::CSS_PRIMITIVE_VALUE)
    462         return false;
    463 
    464     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
    465     if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_RGBCOLOR)
    466         return false;
    467 
    468     color = primitiveValue->getRGBA32Value();
    469     return true;
    470 }
    471 
    472 bool CSSParser::parseColor(CSSMutableStyleDeclaration* declaration, const String& string)
    473 {
    474     ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet());
    475     setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet()));
    476 
    477     setupParser("@-webkit-decls{color:", string, "} ");
    478     cssyyparse(this);
    479     m_rule = 0;
    480 
    481     return (m_numParsedProperties && m_parsedProperties[0]->m_id == CSSPropertyColor);
    482 }
    483 
    484 bool CSSParser::parseSystemColor(RGBA32& color, const String& string, Document* document)
    485 {
    486     if (!document || !document->page())
    487         return false;
    488 
    489     CSSParserString cssColor;
    490     cssColor.characters = const_cast<UChar*>(string.characters());
    491     cssColor.length = string.length();
    492     int id = cssValueKeywordID(cssColor);
    493     if (id <= 0)
    494         return false;
    495 
    496     color = document->page()->theme()->systemColor(id).rgb();
    497     return true;
    498 }
    499 
    500 void CSSParser::parseSelector(const String& string, Document* doc, CSSSelectorList& selectorList)
    501 {
    502     RefPtr<CSSStyleSheet> dummyStyleSheet = CSSStyleSheet::create(doc);
    503 
    504     setStyleSheet(dummyStyleSheet.get());
    505     m_selectorListForParseSelector = &selectorList;
    506 
    507     setupParser("@-webkit-selector{", string, "}");
    508 
    509     cssyyparse(this);
    510 
    511     m_selectorListForParseSelector = 0;
    512 
    513     // The style sheet will be deleted right away, so it won't outlive the document.
    514     ASSERT(dummyStyleSheet->hasOneRef());
    515 }
    516 
    517 bool CSSParser::parseDeclaration(CSSMutableStyleDeclaration* declaration, const String& string, RefPtr<CSSStyleSourceData>* styleSourceData)
    518 {
    519     // Length of the "@-webkit-decls{" prefix.
    520     static const unsigned prefixLength = 15;
    521 
    522     ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet());
    523     setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet()));
    524     if (styleSourceData) {
    525         m_currentRuleData = CSSRuleSourceData::create();
    526         m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
    527         m_inStyleRuleOrDeclaration = true;
    528     }
    529 
    530     setupParser("@-webkit-decls{", string, "} ");
    531     cssyyparse(this);
    532     m_rule = 0;
    533 
    534     bool ok = false;
    535     if (m_hasFontFaceOnlyValues)
    536         deleteFontFaceOnlyValues();
    537     if (m_numParsedProperties) {
    538         ok = true;
    539         declaration->addParsedProperties(m_parsedProperties, m_numParsedProperties);
    540         clearProperties();
    541     }
    542 
    543     if (m_currentRuleData) {
    544         m_currentRuleData->styleSourceData->styleBodyRange.start = 0;
    545         m_currentRuleData->styleSourceData->styleBodyRange.end = string.length();
    546         for (Vector<CSSPropertySourceData>::iterator it = m_currentRuleData->styleSourceData->propertyData.begin(), endIt = m_currentRuleData->styleSourceData->propertyData.end(); it != endIt; ++it) {
    547             (*it).range.start -= prefixLength;
    548             (*it).range.end -= prefixLength;
    549         }
    550     }
    551 
    552     if (styleSourceData) {
    553         *styleSourceData = m_currentRuleData->styleSourceData.release();
    554         m_currentRuleData = 0;
    555         m_inStyleRuleOrDeclaration = false;
    556     }
    557     return ok;
    558 }
    559 
    560 bool CSSParser::parseMediaQuery(MediaList* queries, const String& string)
    561 {
    562     if (string.isEmpty())
    563         return true;
    564 
    565     ASSERT(!m_mediaQuery);
    566 
    567     // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
    568     // instead insert one " " (which is WHITESPACE in CSSGrammar.y)
    569     setupParser("@-webkit-mediaquery ", string, "} ");
    570     cssyyparse(this);
    571 
    572     bool ok = false;
    573     if (m_mediaQuery) {
    574         ok = true;
    575         queries->appendMediaQuery(m_mediaQuery.release());
    576     }
    577 
    578     return ok;
    579 }
    580 
    581 
    582 void CSSParser::addProperty(int propId, PassRefPtr<CSSValue> value, bool important)
    583 {
    584     OwnPtr<CSSProperty> prop(new CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand));
    585     if (m_numParsedProperties >= m_maxParsedProperties) {
    586         m_maxParsedProperties += 32;
    587         if (m_maxParsedProperties > UINT_MAX / sizeof(CSSProperty*))
    588             return;
    589         m_parsedProperties = static_cast<CSSProperty**>(fastRealloc(m_parsedProperties,
    590             m_maxParsedProperties * sizeof(CSSProperty*)));
    591     }
    592     m_parsedProperties[m_numParsedProperties++] = prop.leakPtr();
    593 }
    594 
    595 void CSSParser::rollbackLastProperties(int num)
    596 {
    597     ASSERT(num >= 0);
    598     ASSERT(m_numParsedProperties >= static_cast<unsigned>(num));
    599 
    600     for (int i = 0; i < num; ++i)
    601         delete m_parsedProperties[--m_numParsedProperties];
    602 }
    603 
    604 void CSSParser::clearProperties()
    605 {
    606     for (unsigned i = 0; i < m_numParsedProperties; i++)
    607         delete m_parsedProperties[i];
    608     m_numParsedProperties = 0;
    609     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
    610     m_hasFontFaceOnlyValues = false;
    611 }
    612 
    613 void CSSParser::setStyleSheet(CSSStyleSheet* styleSheet)
    614 {
    615     m_styleSheet = styleSheet;
    616     m_primitiveValueCache = document() ? document()->cssPrimitiveValueCache() : CSSPrimitiveValueCache::create();
    617 }
    618 
    619 Document* CSSParser::document() const
    620 {
    621     StyleBase* root = m_styleSheet;
    622     while (root && root->parent())
    623         root = root->parent();
    624     if (!root)
    625         return 0;
    626     if (!root->isCSSStyleSheet())
    627         return 0;
    628     return static_cast<CSSStyleSheet*>(root)->document();
    629 }
    630 
    631 bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, bool strict)
    632 {
    633     bool b = false;
    634     switch (value->unit) {
    635     case CSSPrimitiveValue::CSS_NUMBER:
    636         b = (unitflags & FNumber);
    637         if (!b && ((unitflags & (FLength | FAngle | FTime)) && (value->fValue == 0 || !strict))) {
    638             value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX :
    639                           ((unitflags & FAngle) ? CSSPrimitiveValue::CSS_DEG : CSSPrimitiveValue::CSS_MS);
    640             b = true;
    641         }
    642         if (!b && (unitflags & FInteger) && value->isInt)
    643             b = true;
    644         break;
    645     case CSSPrimitiveValue::CSS_PERCENTAGE:
    646         b = (unitflags & FPercent);
    647         break;
    648     case CSSParserValue::Q_EMS:
    649     case CSSPrimitiveValue::CSS_EMS:
    650     case CSSPrimitiveValue::CSS_REMS:
    651     case CSSPrimitiveValue::CSS_EXS:
    652     case CSSPrimitiveValue::CSS_PX:
    653     case CSSPrimitiveValue::CSS_CM:
    654     case CSSPrimitiveValue::CSS_MM:
    655     case CSSPrimitiveValue::CSS_IN:
    656     case CSSPrimitiveValue::CSS_PT:
    657     case CSSPrimitiveValue::CSS_PC:
    658         b = (unitflags & FLength);
    659         break;
    660     case CSSPrimitiveValue::CSS_MS:
    661     case CSSPrimitiveValue::CSS_S:
    662         b = (unitflags & FTime);
    663         break;
    664     case CSSPrimitiveValue::CSS_DEG:
    665     case CSSPrimitiveValue::CSS_RAD:
    666     case CSSPrimitiveValue::CSS_GRAD:
    667     case CSSPrimitiveValue::CSS_TURN:
    668         b = (unitflags & FAngle);
    669         break;
    670     case CSSPrimitiveValue::CSS_HZ:
    671     case CSSPrimitiveValue::CSS_KHZ:
    672     case CSSPrimitiveValue::CSS_DIMENSION:
    673     default:
    674         break;
    675     }
    676     if (b && unitflags & FNonNeg && value->fValue < 0)
    677         b = false;
    678     return b;
    679 }
    680 
    681 static int unitFromString(CSSParserValue* value)
    682 {
    683     if (value->unit != CSSPrimitiveValue::CSS_IDENT || value->id)
    684         return 0;
    685 
    686     if (equal(value->string, "em"))
    687         return CSSPrimitiveValue::CSS_EMS;
    688     if (equal(value->string, "rem"))
    689         return CSSPrimitiveValue::CSS_REMS;
    690     if (equal(value->string, "ex"))
    691         return CSSPrimitiveValue::CSS_EXS;
    692     if (equal(value->string, "px"))
    693         return CSSPrimitiveValue::CSS_PX;
    694     if (equal(value->string, "cm"))
    695         return CSSPrimitiveValue::CSS_CM;
    696     if (equal(value->string, "mm"))
    697         return CSSPrimitiveValue::CSS_MM;
    698     if (equal(value->string, "in"))
    699         return CSSPrimitiveValue::CSS_IN;
    700     if (equal(value->string, "pt"))
    701         return CSSPrimitiveValue::CSS_PT;
    702     if (equal(value->string, "pc"))
    703         return CSSPrimitiveValue::CSS_PC;
    704     if (equal(value->string, "deg"))
    705         return CSSPrimitiveValue::CSS_DEG;
    706     if (equal(value->string, "rad"))
    707         return CSSPrimitiveValue::CSS_RAD;
    708     if (equal(value->string, "grad"))
    709         return CSSPrimitiveValue::CSS_GRAD;
    710     if (equal(value->string, "turn"))
    711         return CSSPrimitiveValue::CSS_TURN;
    712     if (equal(value->string, "ms"))
    713         return CSSPrimitiveValue::CSS_MS;
    714     if (equal(value->string, "s"))
    715         return CSSPrimitiveValue::CSS_S;
    716     if (equal(value->string, "Hz"))
    717         return CSSPrimitiveValue::CSS_HZ;
    718     if (equal(value->string, "kHz"))
    719         return CSSPrimitiveValue::CSS_KHZ;
    720 
    721     return 0;
    722 }
    723 
    724 void CSSParser::checkForOrphanedUnits()
    725 {
    726     if (m_strict || inShorthand())
    727         return;
    728 
    729     // The purpose of this code is to implement the WinIE quirk that allows unit types to be separated from their numeric values
    730     // 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.
    731     CSSParserValue* numericVal = 0;
    732     unsigned size = m_valueList->size();
    733     for (unsigned i = 0; i < size; i++) {
    734         CSSParserValue* value = m_valueList->valueAt(i);
    735 
    736         if (numericVal) {
    737             // Change the unit type of the numeric val to match.
    738             int unit = unitFromString(value);
    739             if (unit) {
    740                 numericVal->unit = unit;
    741                 numericVal = 0;
    742 
    743                 // Now delete the bogus unit value.
    744                 m_valueList->deleteValueAt(i);
    745                 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).
    746                 size--;
    747                 continue;
    748             }
    749         }
    750 
    751         numericVal = (value->unit == CSSPrimitiveValue::CSS_NUMBER) ? value : 0;
    752     }
    753 }
    754 
    755 bool CSSParser::parseValue(int propId, bool important)
    756 {
    757     if (!m_valueList)
    758         return false;
    759 
    760     CSSParserValue* value = m_valueList->current();
    761 
    762     if (!value)
    763         return false;
    764 
    765     int id = value->id;
    766 
    767     // In quirks mode, we will look for units that have been incorrectly separated from the number they belong to
    768     // by a space.  We go ahead and associate the unit with the number even though it is invalid CSS.
    769     checkForOrphanedUnits();
    770 
    771     int num = inShorthand() ? 1 : m_valueList->size();
    772 
    773     if (id == CSSValueInherit) {
    774         if (num != 1)
    775             return false;
    776         addProperty(propId, CSSInheritedValue::create(), important);
    777         return true;
    778     }
    779     else if (id == CSSValueInitial) {
    780         if (num != 1)
    781             return false;
    782         addProperty(propId, CSSInitialValue::createExplicit(), important);
    783         return true;
    784     }
    785 
    786     bool validPrimitive = false;
    787     RefPtr<CSSValue> parsedValue;
    788 
    789     switch (static_cast<CSSPropertyID>(propId)) {
    790         /* The comment to the left defines all valid value of this properties as defined
    791          * in CSS 2, Appendix F. Property index
    792          */
    793 
    794         /* All the CSS properties are not supported by the renderer at the moment.
    795          * Note that all the CSS2 Aural properties are only checked, if CSS_AURAL is defined
    796          * (see parseAuralValues). As we don't support them at all this seems reasonable.
    797          */
    798 
    799     case CSSPropertySize:                 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
    800         return parseSize(propId, important);
    801 
    802     case CSSPropertyQuotes:               // [<string> <string>]+ | none | inherit
    803         if (id)
    804             validPrimitive = true;
    805         else
    806             return parseQuotes(propId, important);
    807         break;
    808     case CSSPropertyUnicodeBidi: // normal | embed | bidi-override | isolate | inherit
    809         if (id == CSSValueNormal
    810             || id == CSSValueEmbed
    811             || id == CSSValueBidiOverride
    812             || id == CSSValueWebkitIsolate)
    813             validPrimitive = true;
    814         break;
    815 
    816     case CSSPropertyPosition:             // static | relative | absolute | fixed | inherit
    817         if (id == CSSValueStatic ||
    818              id == CSSValueRelative ||
    819              id == CSSValueAbsolute ||
    820              id == CSSValueFixed)
    821             validPrimitive = true;
    822         break;
    823 
    824     case CSSPropertyPageBreakAfter:     // auto | always | avoid | left | right | inherit
    825     case CSSPropertyPageBreakBefore:
    826     case CSSPropertyWebkitColumnBreakAfter:
    827     case CSSPropertyWebkitColumnBreakBefore:
    828         if (id == CSSValueAuto ||
    829              id == CSSValueAlways ||
    830              id == CSSValueAvoid ||
    831              id == CSSValueLeft ||
    832              id == CSSValueRight)
    833             validPrimitive = true;
    834         break;
    835 
    836     case CSSPropertyPageBreakInside:    // avoid | auto | inherit
    837     case CSSPropertyWebkitColumnBreakInside:
    838         if (id == CSSValueAuto || id == CSSValueAvoid)
    839             validPrimitive = true;
    840         break;
    841 
    842     case CSSPropertyEmptyCells:          // show | hide | inherit
    843         if (id == CSSValueShow ||
    844              id == CSSValueHide)
    845             validPrimitive = true;
    846         break;
    847 
    848     case CSSPropertyContent:              // [ <string> | <uri> | <counter> | attr(X) | open-quote |
    849         // close-quote | no-open-quote | no-close-quote ]+ | inherit
    850         return parseContent(propId, important);
    851 
    852     case CSSPropertyWhiteSpace:          // normal | pre | nowrap | inherit
    853         if (id == CSSValueNormal ||
    854             id == CSSValuePre ||
    855             id == CSSValuePreWrap ||
    856             id == CSSValuePreLine ||
    857             id == CSSValueNowrap)
    858             validPrimitive = true;
    859         break;
    860 
    861     case CSSPropertyClip:                 // <shape> | auto | inherit
    862         if (id == CSSValueAuto)
    863             validPrimitive = true;
    864         else if (value->unit == CSSParserValue::Function)
    865             return parseShape(propId, important);
    866         break;
    867 
    868     /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
    869      * correctly and allows optimization in WebCore::applyRule(..)
    870      */
    871     case CSSPropertyCaptionSide:         // top | bottom | left | right | inherit
    872         if (id == CSSValueLeft || id == CSSValueRight ||
    873             id == CSSValueTop || id == CSSValueBottom)
    874             validPrimitive = true;
    875         break;
    876 
    877     case CSSPropertyBorderCollapse:      // collapse | separate | inherit
    878         if (id == CSSValueCollapse || id == CSSValueSeparate)
    879             validPrimitive = true;
    880         break;
    881 
    882     case CSSPropertyVisibility:           // visible | hidden | collapse | inherit
    883         if (id == CSSValueVisible || id == CSSValueHidden || id == CSSValueCollapse)
    884             validPrimitive = true;
    885         break;
    886 
    887     case CSSPropertyOverflow: {
    888         ShorthandScope scope(this, propId);
    889         if (num != 1 || !parseValue(CSSPropertyOverflowX, important))
    890             return false;
    891         CSSValue* value = m_parsedProperties[m_numParsedProperties - 1]->value();
    892         addProperty(CSSPropertyOverflowY, value, important);
    893         return true;
    894     }
    895     case CSSPropertyOverflowX:
    896     case CSSPropertyOverflowY:           // visible | hidden | scroll | auto | marquee | overlay | inherit
    897         if (id == CSSValueVisible || id == CSSValueHidden || id == CSSValueScroll || id == CSSValueAuto ||
    898             id == CSSValueOverlay || id == CSSValueWebkitMarquee)
    899             validPrimitive = true;
    900         break;
    901 
    902     case CSSPropertyListStylePosition:  // inside | outside | inherit
    903         if (id == CSSValueInside || id == CSSValueOutside)
    904             validPrimitive = true;
    905         break;
    906 
    907     case CSSPropertyListStyleType:
    908         // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
    909         // for the list of supported list-style-types.
    910         if ((id >= CSSValueDisc && id <= CSSValueKatakanaIroha) || id == CSSValueNone)
    911             validPrimitive = true;
    912         break;
    913 
    914     case CSSPropertyDisplay:
    915         // inline | block | list-item | run-in | inline-block | table |
    916         // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
    917         // table-column-group | table-column | table-cell | table-caption | box | inline-box | none | inherit
    918 #if ENABLE(WCSS)
    919         if ((id >= CSSValueInline && id <= CSSValueWapMarquee) || id == CSSValueNone)
    920 #else
    921         if ((id >= CSSValueInline && id <= CSSValueWebkitInlineBox) || id == CSSValueNone)
    922 #endif
    923             validPrimitive = true;
    924         break;
    925 
    926     case CSSPropertyDirection:            // ltr | rtl | inherit
    927         if (id == CSSValueLtr || id == CSSValueRtl)
    928             validPrimitive = true;
    929         break;
    930 
    931     case CSSPropertyTextTransform:       // capitalize | uppercase | lowercase | none | inherit
    932         if ((id >= CSSValueCapitalize && id <= CSSValueLowercase) || id == CSSValueNone)
    933             validPrimitive = true;
    934         break;
    935 
    936     case CSSPropertyFloat:                // left | right | none | inherit + center for buggy CSS
    937         if (id == CSSValueLeft || id == CSSValueRight ||
    938              id == CSSValueNone || id == CSSValueCenter)
    939             validPrimitive = true;
    940         break;
    941 
    942     case CSSPropertyClear:                // none | left | right | both | inherit
    943         if (id == CSSValueNone || id == CSSValueLeft ||
    944              id == CSSValueRight|| id == CSSValueBoth)
    945             validPrimitive = true;
    946         break;
    947 
    948     case CSSPropertyTextAlign:
    949         // left | right | center | justify | webkit_left | webkit_right | webkit_center | webkit_match_parent |
    950         // start | end | <string> | inherit
    951         if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd
    952              || value->unit == CSSPrimitiveValue::CSS_STRING)
    953             validPrimitive = true;
    954         break;
    955 
    956     case CSSPropertyOutlineStyle:        // (<border-style> except hidden) | auto | inherit
    957         if (id == CSSValueAuto || id == CSSValueNone || (id >= CSSValueInset && id <= CSSValueDouble))
    958             validPrimitive = true;
    959         break;
    960 
    961     case CSSPropertyBorderTopStyle:     //// <border-style> | inherit
    962     case CSSPropertyBorderRightStyle:   //   Defined as:    none | hidden | dotted | dashed |
    963     case CSSPropertyBorderBottomStyle:  //   solid | double | groove | ridge | inset | outset
    964     case CSSPropertyBorderLeftStyle:
    965     case CSSPropertyWebkitBorderStartStyle:
    966     case CSSPropertyWebkitBorderEndStyle:
    967     case CSSPropertyWebkitBorderBeforeStyle:
    968     case CSSPropertyWebkitBorderAfterStyle:
    969     case CSSPropertyWebkitColumnRuleStyle:
    970         if (id >= CSSValueNone && id <= CSSValueDouble)
    971             validPrimitive = true;
    972         break;
    973 
    974     case CSSPropertyFontWeight:  // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
    975         return parseFontWeight(important);
    976 
    977     case CSSPropertyBorderSpacing: {
    978         const int properties[2] = { CSSPropertyWebkitBorderHorizontalSpacing,
    979                                     CSSPropertyWebkitBorderVerticalSpacing };
    980         if (num == 1) {
    981             ShorthandScope scope(this, CSSPropertyBorderSpacing);
    982             if (!parseValue(properties[0], important))
    983                 return false;
    984             CSSValue* value = m_parsedProperties[m_numParsedProperties-1]->value();
    985             addProperty(properties[1], value, important);
    986             return true;
    987         }
    988         else if (num == 2) {
    989             ShorthandScope scope(this, CSSPropertyBorderSpacing);
    990             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
    991                 return false;
    992             return true;
    993         }
    994         return false;
    995     }
    996     case CSSPropertyWebkitBorderHorizontalSpacing:
    997     case CSSPropertyWebkitBorderVerticalSpacing:
    998         validPrimitive = validUnit(value, FLength | FNonNeg, m_strict);
    999         break;
   1000     case CSSPropertyOutlineColor:        // <color> | invert | inherit
   1001         // Outline color has "invert" as additional keyword.
   1002         // Also, we want to allow the special focus color even in strict parsing mode.
   1003         if (id == CSSValueInvert || id == CSSValueWebkitFocusRingColor) {
   1004             validPrimitive = true;
   1005             break;
   1006         }
   1007         /* nobreak */
   1008     case CSSPropertyBackgroundColor: // <color> | inherit
   1009     case CSSPropertyBorderTopColor: // <color> | inherit
   1010     case CSSPropertyBorderRightColor:
   1011     case CSSPropertyBorderBottomColor:
   1012     case CSSPropertyBorderLeftColor:
   1013     case CSSPropertyWebkitBorderStartColor:
   1014     case CSSPropertyWebkitBorderEndColor:
   1015     case CSSPropertyWebkitBorderBeforeColor:
   1016     case CSSPropertyWebkitBorderAfterColor:
   1017     case CSSPropertyColor: // <color> | inherit
   1018     case CSSPropertyTextLineThroughColor: // CSS3 text decoration colors
   1019     case CSSPropertyTextUnderlineColor:
   1020     case CSSPropertyTextOverlineColor:
   1021     case CSSPropertyWebkitColumnRuleColor:
   1022     case CSSPropertyWebkitTextEmphasisColor:
   1023     case CSSPropertyWebkitTextFillColor:
   1024     case CSSPropertyWebkitTextStrokeColor:
   1025         if (id == CSSValueWebkitText)
   1026             validPrimitive = true; // Always allow this, even when strict parsing is on,
   1027                                     // since we use this in our UA sheets.
   1028         else if (id == CSSValueCurrentcolor)
   1029             validPrimitive = true;
   1030         else if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu ||
   1031              (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && !m_strict)) {
   1032             validPrimitive = true;
   1033         } else {
   1034             parsedValue = parseColor();
   1035             if (parsedValue)
   1036                 m_valueList->next();
   1037         }
   1038         break;
   1039 
   1040     case CSSPropertyCursor: {
   1041         // [<uri>,]*  [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
   1042         // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize |
   1043         // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help |
   1044         // vertical-text | cell | context-menu | alias | copy | no-drop | not-allowed | -webkit-zoom-in
   1045         // -webkit-zoom-out | all-scroll | -webkit-grab | -webkit-grabbing ] ] | inherit
   1046         RefPtr<CSSValueList> list;
   1047         while (value && value->unit == CSSPrimitiveValue::CSS_URI) {
   1048             if (!list)
   1049                 list = CSSValueList::createCommaSeparated();
   1050             String uri = value->string;
   1051             Vector<int> coords;
   1052             value = m_valueList->next();
   1053             while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) {
   1054                 coords.append(int(value->fValue));
   1055                 value = m_valueList->next();
   1056             }
   1057             IntPoint hotSpot(-1, -1);
   1058             int nrcoords = coords.size();
   1059             if (nrcoords > 0 && nrcoords != 2)
   1060                 return false;
   1061             if (nrcoords == 2)
   1062                 hotSpot = IntPoint(coords[0], coords[1]);
   1063 
   1064             if (!uri.isNull() && m_styleSheet) {
   1065                 // FIXME: The completeURL call should be done when using the CSSCursorImageValue,
   1066                 // not when creating it.
   1067                 list->append(CSSCursorImageValue::create(m_styleSheet->completeURL(uri), hotSpot));
   1068             }
   1069 
   1070             if ((m_strict && !value) || (value && !(value->unit == CSSParserValue::Operator && value->iValue == ',')))
   1071                 return false;
   1072             value = m_valueList->next(); // comma
   1073         }
   1074         if (list) {
   1075             if (!value) { // no value after url list (MSIE 5 compatibility)
   1076                 if (list->length() != 1)
   1077                     return false;
   1078             } else if (!m_strict && value->id == CSSValueHand) // MSIE 5 compatibility :/
   1079                 list->append(primitiveValueCache()->createIdentifierValue(CSSValuePointer));
   1080             else if (value && ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone))
   1081                 list->append(primitiveValueCache()->createIdentifierValue(value->id));
   1082             m_valueList->next();
   1083             parsedValue = list.release();
   1084             break;
   1085         }
   1086         id = value->id;
   1087         if (!m_strict && value->id == CSSValueHand) { // MSIE 5 compatibility :/
   1088             id = CSSValuePointer;
   1089             validPrimitive = true;
   1090         } else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)
   1091             validPrimitive = true;
   1092         break;
   1093     }
   1094 
   1095     case CSSPropertyBackgroundAttachment:
   1096     case CSSPropertyBackgroundClip:
   1097     case CSSPropertyWebkitBackgroundClip:
   1098     case CSSPropertyWebkitBackgroundComposite:
   1099     case CSSPropertyBackgroundImage:
   1100     case CSSPropertyBackgroundOrigin:
   1101     case CSSPropertyWebkitBackgroundOrigin:
   1102     case CSSPropertyBackgroundPosition:
   1103     case CSSPropertyBackgroundPositionX:
   1104     case CSSPropertyBackgroundPositionY:
   1105     case CSSPropertyBackgroundSize:
   1106     case CSSPropertyWebkitBackgroundSize:
   1107     case CSSPropertyBackgroundRepeat:
   1108     case CSSPropertyBackgroundRepeatX:
   1109     case CSSPropertyBackgroundRepeatY:
   1110     case CSSPropertyWebkitMaskAttachment:
   1111     case CSSPropertyWebkitMaskClip:
   1112     case CSSPropertyWebkitMaskComposite:
   1113     case CSSPropertyWebkitMaskImage:
   1114     case CSSPropertyWebkitMaskOrigin:
   1115     case CSSPropertyWebkitMaskPosition:
   1116     case CSSPropertyWebkitMaskPositionX:
   1117     case CSSPropertyWebkitMaskPositionY:
   1118     case CSSPropertyWebkitMaskSize:
   1119     case CSSPropertyWebkitMaskRepeat:
   1120     case CSSPropertyWebkitMaskRepeatX:
   1121     case CSSPropertyWebkitMaskRepeatY: {
   1122         RefPtr<CSSValue> val1;
   1123         RefPtr<CSSValue> val2;
   1124         int propId1, propId2;
   1125         bool result = false;
   1126         if (parseFillProperty(propId, propId1, propId2, val1, val2)) {
   1127             OwnPtr<ShorthandScope> shorthandScope;
   1128             if (propId == CSSPropertyBackgroundPosition ||
   1129                 propId == CSSPropertyBackgroundRepeat ||
   1130                 propId == CSSPropertyWebkitMaskPosition ||
   1131                 propId == CSSPropertyWebkitMaskRepeat) {
   1132                 shorthandScope.set(new ShorthandScope(this, propId));
   1133             }
   1134             addProperty(propId1, val1.release(), important);
   1135             if (val2)
   1136                 addProperty(propId2, val2.release(), important);
   1137             result = true;
   1138         }
   1139         m_implicitShorthand = false;
   1140         return result;
   1141     }
   1142     case CSSPropertyListStyleImage:     // <uri> | none | inherit
   1143         if (id == CSSValueNone) {
   1144             parsedValue = CSSImageValue::create();
   1145             m_valueList->next();
   1146         } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
   1147             if (m_styleSheet) {
   1148                 // FIXME: The completeURL call should be done when using the CSSImageValue,
   1149                 // not when creating it.
   1150                 parsedValue = CSSImageValue::create(m_styleSheet->completeURL(value->string));
   1151                 m_valueList->next();
   1152             }
   1153         } else if (isGeneratedImageValue(value)) {
   1154             if (parseGeneratedImage(parsedValue))
   1155                 m_valueList->next();
   1156             else
   1157                 return false;
   1158         }
   1159         break;
   1160 
   1161     case CSSPropertyWebkitTextStrokeWidth:
   1162     case CSSPropertyOutlineWidth:        // <border-width> | inherit
   1163     case CSSPropertyBorderTopWidth:     //// <border-width> | inherit
   1164     case CSSPropertyBorderRightWidth:   //   Which is defined as
   1165     case CSSPropertyBorderBottomWidth:  //   thin | medium | thick | <length>
   1166     case CSSPropertyBorderLeftWidth:
   1167     case CSSPropertyWebkitBorderStartWidth:
   1168     case CSSPropertyWebkitBorderEndWidth:
   1169     case CSSPropertyWebkitBorderBeforeWidth:
   1170     case CSSPropertyWebkitBorderAfterWidth:
   1171     case CSSPropertyWebkitColumnRuleWidth:
   1172         if (id == CSSValueThin || id == CSSValueMedium || id == CSSValueThick)
   1173             validPrimitive = true;
   1174         else
   1175             validPrimitive = validUnit(value, FLength | FNonNeg, m_strict);
   1176         break;
   1177 
   1178     case CSSPropertyLetterSpacing:       // normal | <length> | inherit
   1179     case CSSPropertyWordSpacing:         // normal | <length> | inherit
   1180         if (id == CSSValueNormal)
   1181             validPrimitive = true;
   1182         else
   1183             validPrimitive = validUnit(value, FLength, m_strict);
   1184         break;
   1185 
   1186     case CSSPropertyWordBreak:          // normal | break-all | break-word (this is a custom extension)
   1187         if (id == CSSValueNormal || id == CSSValueBreakAll || id == CSSValueBreakWord)
   1188             validPrimitive = true;
   1189         break;
   1190 
   1191     case CSSPropertyWordWrap:           // normal | break-word
   1192         if (id == CSSValueNormal || id == CSSValueBreakWord)
   1193             validPrimitive = true;
   1194         break;
   1195     case CSSPropertySpeak:           // none | normal | spell-out | digits | literal-punctuation | no-punctuation | inherit
   1196         if (id == CSSValueNone || id == CSSValueNormal || id == CSSValueSpellOut || id == CSSValueDigits
   1197             || id == CSSValueLiteralPunctuation || id == CSSValueNoPunctuation)
   1198             validPrimitive = true;
   1199         break;
   1200 
   1201     case CSSPropertyTextIndent:          // <length> | <percentage> | inherit
   1202         validPrimitive = (!id && validUnit(value, FLength | FPercent, m_strict));
   1203         break;
   1204 
   1205     case CSSPropertyPaddingTop:          //// <padding-width> | inherit
   1206     case CSSPropertyPaddingRight:        //   Which is defined as
   1207     case CSSPropertyPaddingBottom:       //   <length> | <percentage>
   1208     case CSSPropertyPaddingLeft:         ////
   1209     case CSSPropertyWebkitPaddingStart:
   1210     case CSSPropertyWebkitPaddingEnd:
   1211     case CSSPropertyWebkitPaddingBefore:
   1212     case CSSPropertyWebkitPaddingAfter:
   1213         validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg, m_strict));
   1214         break;
   1215 
   1216     case CSSPropertyMaxHeight:           // <length> | <percentage> | none | inherit
   1217     case CSSPropertyMaxWidth:            // <length> | <percentage> | none | inherit
   1218     case CSSPropertyWebkitMaxLogicalWidth:
   1219     case CSSPropertyWebkitMaxLogicalHeight:
   1220         if (id == CSSValueNone || id == CSSValueIntrinsic || id == CSSValueMinIntrinsic) {
   1221             validPrimitive = true;
   1222             break;
   1223         }
   1224         /* nobreak */
   1225     case CSSPropertyMinHeight:           // <length> | <percentage> | inherit
   1226     case CSSPropertyMinWidth:            // <length> | <percentage> | inherit
   1227     case CSSPropertyWebkitMinLogicalWidth:
   1228     case CSSPropertyWebkitMinLogicalHeight:
   1229         if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
   1230             validPrimitive = true;
   1231         else
   1232             validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg, m_strict));
   1233         break;
   1234 
   1235     case CSSPropertyFontSize:
   1236         // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
   1237         if (id >= CSSValueXxSmall && id <= CSSValueLarger)
   1238             validPrimitive = true;
   1239         else
   1240             validPrimitive = (validUnit(value, FLength | FPercent | FNonNeg, m_strict));
   1241         break;
   1242 
   1243     case CSSPropertyFontStyle:           // normal | italic | oblique | inherit
   1244         return parseFontStyle(important);
   1245 
   1246     case CSSPropertyFontVariant:         // normal | small-caps | inherit
   1247         return parseFontVariant(important);
   1248 
   1249     case CSSPropertyVerticalAlign:
   1250         // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
   1251         // <percentage> | <length> | inherit
   1252 
   1253         if (id >= CSSValueBaseline && id <= CSSValueWebkitBaselineMiddle)
   1254             validPrimitive = true;
   1255         else
   1256             validPrimitive = (!id && validUnit(value, FLength | FPercent, m_strict));
   1257         break;
   1258 
   1259     case CSSPropertyHeight:               // <length> | <percentage> | auto | inherit
   1260     case CSSPropertyWidth:                // <length> | <percentage> | auto | inherit
   1261     case CSSPropertyWebkitLogicalWidth:
   1262     case CSSPropertyWebkitLogicalHeight:
   1263         if (id == CSSValueAuto || id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
   1264             validPrimitive = true;
   1265         else
   1266             // ### handle multilength case where we allow relative units
   1267             validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg, m_strict));
   1268         break;
   1269 
   1270     case CSSPropertyBottom:               // <length> | <percentage> | auto | inherit
   1271     case CSSPropertyLeft:                 // <length> | <percentage> | auto | inherit
   1272     case CSSPropertyRight:                // <length> | <percentage> | auto | inherit
   1273     case CSSPropertyTop:                  // <length> | <percentage> | auto | inherit
   1274     case CSSPropertyMarginTop:           //// <margin-width> | inherit
   1275     case CSSPropertyMarginRight:         //   Which is defined as
   1276     case CSSPropertyMarginBottom:        //   <length> | <percentage> | auto | inherit
   1277     case CSSPropertyMarginLeft:          ////
   1278     case CSSPropertyWebkitMarginStart:
   1279     case CSSPropertyWebkitMarginEnd:
   1280     case CSSPropertyWebkitMarginBefore:
   1281     case CSSPropertyWebkitMarginAfter:
   1282         if (id == CSSValueAuto)
   1283             validPrimitive = true;
   1284         else
   1285             validPrimitive = (!id && validUnit(value, FLength | FPercent, m_strict));
   1286         break;
   1287 
   1288     case CSSPropertyZIndex:              // auto | <integer> | inherit
   1289         if (id == CSSValueAuto) {
   1290             validPrimitive = true;
   1291             break;
   1292         }
   1293         /* nobreak */
   1294     case CSSPropertyOrphans:              // <integer> | inherit
   1295     case CSSPropertyWidows:               // <integer> | inherit
   1296         // ### not supported later on
   1297         validPrimitive = (!id && validUnit(value, FInteger, false));
   1298         break;
   1299 
   1300     case CSSPropertyLineHeight:          // normal | <number> | <length> | <percentage> | inherit
   1301         if (id == CSSValueNormal)
   1302             validPrimitive = true;
   1303         else
   1304             validPrimitive = (!id && validUnit(value, FNumber | FLength | FPercent | FNonNeg, m_strict));
   1305         break;
   1306     case CSSPropertyCounterIncrement:    // [ <identifier> <integer>? ]+ | none | inherit
   1307         if (id != CSSValueNone)
   1308             return parseCounter(propId, 1, important);
   1309         validPrimitive = true;
   1310         break;
   1311      case CSSPropertyCounterReset:        // [ <identifier> <integer>? ]+ | none | inherit
   1312         if (id != CSSValueNone)
   1313             return parseCounter(propId, 0, important);
   1314         validPrimitive = true;
   1315         break;
   1316     case CSSPropertyFontFamily:
   1317         // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
   1318     {
   1319         parsedValue = parseFontFamily();
   1320         break;
   1321     }
   1322 
   1323     case CSSPropertyTextDecoration:
   1324     case CSSPropertyWebkitTextDecorationsInEffect:
   1325         // none | [ underline || overline || line-through || blink ] | inherit
   1326         if (id == CSSValueNone) {
   1327             validPrimitive = true;
   1328         } else {
   1329             RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
   1330             bool isValid = true;
   1331             while (isValid && value) {
   1332                 switch (value->id) {
   1333                 case CSSValueBlink:
   1334                     break;
   1335                 case CSSValueUnderline:
   1336                 case CSSValueOverline:
   1337                 case CSSValueLineThrough:
   1338                     list->append(primitiveValueCache()->createIdentifierValue(value->id));
   1339                     break;
   1340                 default:
   1341                     isValid = false;
   1342                 }
   1343                 value = m_valueList->next();
   1344             }
   1345             if (list->length() && isValid) {
   1346                 parsedValue = list.release();
   1347                 m_valueList->next();
   1348             }
   1349         }
   1350         break;
   1351 
   1352     case CSSPropertyZoom:          // normal | reset | document | <number> | <percentage> | inherit
   1353         if (id == CSSValueNormal || id == CSSValueReset || id == CSSValueDocument)
   1354             validPrimitive = true;
   1355         else
   1356             validPrimitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg, true));
   1357         break;
   1358 
   1359     case CSSPropertyTableLayout:         // auto | fixed | inherit
   1360         if (id == CSSValueAuto || id == CSSValueFixed)
   1361             validPrimitive = true;
   1362         break;
   1363 
   1364     case CSSPropertySrc:  // Only used within @font-face, so cannot use inherit | initial or be !important.  This is a list of urls or local references.
   1365         return parseFontFaceSrc();
   1366 
   1367     case CSSPropertyUnicodeRange:
   1368         return parseFontFaceUnicodeRange();
   1369 
   1370     /* CSS3 properties */
   1371     case CSSPropertyWebkitAppearance:
   1372         if ((id >= CSSValueCheckbox && id <= CSSValueTextarea) || id == CSSValueNone)
   1373             validPrimitive = true;
   1374         break;
   1375 
   1376     case CSSPropertyWebkitBorderImage:
   1377     case CSSPropertyWebkitMaskBoxImage:
   1378         if (id == CSSValueNone)
   1379             validPrimitive = true;
   1380         else {
   1381             RefPtr<CSSValue> result;
   1382             if (parseBorderImage(propId, important, result)) {
   1383                 addProperty(propId, result, important);
   1384                 return true;
   1385             }
   1386         }
   1387         break;
   1388     case CSSPropertyBorderTopRightRadius:
   1389     case CSSPropertyBorderTopLeftRadius:
   1390     case CSSPropertyBorderBottomLeftRadius:
   1391     case CSSPropertyBorderBottomRightRadius: {
   1392         if (num != 1 && num != 2)
   1393             return false;
   1394         validPrimitive = validUnit(value, FLength | FPercent, m_strict);
   1395         if (!validPrimitive)
   1396             return false;
   1397         RefPtr<CSSPrimitiveValue> parsedValue1 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
   1398         RefPtr<CSSPrimitiveValue> parsedValue2;
   1399         if (num == 2) {
   1400             value = m_valueList->next();
   1401             validPrimitive = validUnit(value, FLength | FPercent, m_strict);
   1402             if (!validPrimitive)
   1403                 return false;
   1404             parsedValue2 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
   1405         } else
   1406             parsedValue2 = parsedValue1;
   1407 
   1408         RefPtr<Pair> pair = Pair::create(parsedValue1.release(), parsedValue2.release());
   1409         RefPtr<CSSPrimitiveValue> val = primitiveValueCache()->createValue(pair.release());
   1410         addProperty(propId, val.release(), important);
   1411         return true;
   1412     }
   1413     case CSSPropertyBorderRadius:
   1414     case CSSPropertyWebkitBorderRadius:
   1415         return parseBorderRadius(propId, important);
   1416     case CSSPropertyOutlineOffset:
   1417         validPrimitive = validUnit(value, FLength | FPercent, m_strict);
   1418         break;
   1419     case CSSPropertyTextShadow: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
   1420     case CSSPropertyBoxShadow:
   1421     case CSSPropertyWebkitBoxShadow:
   1422         if (id == CSSValueNone)
   1423             validPrimitive = true;
   1424         else
   1425             return parseShadow(propId, important);
   1426         break;
   1427     case CSSPropertyWebkitBoxReflect:
   1428         if (id == CSSValueNone)
   1429             validPrimitive = true;
   1430         else
   1431             return parseReflect(propId, important);
   1432         break;
   1433     case CSSPropertyOpacity:
   1434         validPrimitive = validUnit(value, FNumber, m_strict);
   1435         break;
   1436     case CSSPropertyWebkitBoxAlign:
   1437         if (id == CSSValueStretch || id == CSSValueStart || id == CSSValueEnd ||
   1438             id == CSSValueCenter || id == CSSValueBaseline)
   1439             validPrimitive = true;
   1440         break;
   1441     case CSSPropertyWebkitBoxDirection:
   1442         if (id == CSSValueNormal || id == CSSValueReverse)
   1443             validPrimitive = true;
   1444         break;
   1445     case CSSPropertyWebkitBoxLines:
   1446         if (id == CSSValueSingle || id == CSSValueMultiple)
   1447             validPrimitive = true;
   1448         break;
   1449     case CSSPropertyWebkitBoxOrient:
   1450         if (id == CSSValueHorizontal || id == CSSValueVertical ||
   1451             id == CSSValueInlineAxis || id == CSSValueBlockAxis)
   1452             validPrimitive = true;
   1453         break;
   1454     case CSSPropertyWebkitBoxPack:
   1455         if (id == CSSValueStart || id == CSSValueEnd ||
   1456             id == CSSValueCenter || id == CSSValueJustify)
   1457             validPrimitive = true;
   1458         break;
   1459     case CSSPropertyWebkitBoxFlex:
   1460         validPrimitive = validUnit(value, FNumber, m_strict);
   1461         break;
   1462     case CSSPropertyWebkitBoxFlexGroup:
   1463     case CSSPropertyWebkitBoxOrdinalGroup:
   1464         validPrimitive = validUnit(value, FInteger | FNonNeg, true);
   1465         break;
   1466     case CSSPropertyBoxSizing:
   1467         validPrimitive = id == CSSValueBorderBox || id == CSSValueContentBox;
   1468         break;
   1469     case CSSPropertyWebkitColorCorrection:
   1470         validPrimitive = id == CSSValueSrgb || id == CSSValueDefault;
   1471         break;
   1472     case CSSPropertyWebkitMarquee: {
   1473         const int properties[5] = { CSSPropertyWebkitMarqueeDirection, CSSPropertyWebkitMarqueeIncrement,
   1474                                     CSSPropertyWebkitMarqueeRepetition,
   1475                                     CSSPropertyWebkitMarqueeStyle, CSSPropertyWebkitMarqueeSpeed };
   1476         return parseShorthand(propId, properties, 5, important);
   1477     }
   1478     case CSSPropertyWebkitMarqueeDirection:
   1479         if (id == CSSValueForwards || id == CSSValueBackwards || id == CSSValueAhead ||
   1480             id == CSSValueReverse || id == CSSValueLeft || id == CSSValueRight || id == CSSValueDown ||
   1481             id == CSSValueUp || id == CSSValueAuto)
   1482             validPrimitive = true;
   1483         break;
   1484     case CSSPropertyWebkitMarqueeIncrement:
   1485         if (id == CSSValueSmall || id == CSSValueLarge || id == CSSValueMedium)
   1486             validPrimitive = true;
   1487         else
   1488             validPrimitive = validUnit(value, FLength | FPercent, m_strict);
   1489         break;
   1490     case CSSPropertyWebkitMarqueeStyle:
   1491         if (id == CSSValueNone || id == CSSValueSlide || id == CSSValueScroll || id == CSSValueAlternate)
   1492             validPrimitive = true;
   1493         break;
   1494     case CSSPropertyWebkitMarqueeRepetition:
   1495         if (id == CSSValueInfinite)
   1496             validPrimitive = true;
   1497         else
   1498             validPrimitive = validUnit(value, FInteger | FNonNeg, m_strict);
   1499         break;
   1500     case CSSPropertyWebkitMarqueeSpeed:
   1501         if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast)
   1502             validPrimitive = true;
   1503         else
   1504             validPrimitive = validUnit(value, FTime | FInteger | FNonNeg, m_strict);
   1505         break;
   1506 #if ENABLE(WCSS)
   1507     case CSSPropertyWapMarqueeDir:
   1508         if (id == CSSValueLtr || id == CSSValueRtl)
   1509             validPrimitive = true;
   1510         break;
   1511     case CSSPropertyWapMarqueeStyle:
   1512         if (id == CSSValueNone || id == CSSValueSlide || id == CSSValueScroll || id == CSSValueAlternate)
   1513             validPrimitive = true;
   1514         break;
   1515     case CSSPropertyWapMarqueeLoop:
   1516         if (id == CSSValueInfinite)
   1517             validPrimitive = true;
   1518         else
   1519             validPrimitive = validUnit(value, FInteger | FNonNeg, m_strict);
   1520         break;
   1521     case CSSPropertyWapMarqueeSpeed:
   1522         if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast)
   1523             validPrimitive = true;
   1524         else
   1525             validPrimitive = validUnit(value, FTime | FInteger | FNonNeg, m_strict);
   1526         break;
   1527 #endif
   1528     case CSSPropertyWebkitUserDrag: // auto | none | element
   1529         if (id == CSSValueAuto || id == CSSValueNone || id == CSSValueElement)
   1530             validPrimitive = true;
   1531         break;
   1532     case CSSPropertyWebkitUserModify: // read-only | read-write
   1533         if (id == CSSValueReadOnly || id == CSSValueReadWrite || id == CSSValueReadWritePlaintextOnly)
   1534             validPrimitive = true;
   1535         break;
   1536     case CSSPropertyWebkitUserSelect: // auto | none | text
   1537         if (id == CSSValueAuto || id == CSSValueNone || id == CSSValueText)
   1538             validPrimitive = true;
   1539         break;
   1540     case CSSPropertyTextOverflow: // clip | ellipsis
   1541         if (id == CSSValueClip || id == CSSValueEllipsis)
   1542             validPrimitive = true;
   1543         break;
   1544     case CSSPropertyWebkitTransform:
   1545         if (id == CSSValueNone)
   1546             validPrimitive = true;
   1547         else {
   1548             PassRefPtr<CSSValue> val = parseTransform();
   1549             if (val) {
   1550                 addProperty(propId, val, important);
   1551                 return true;
   1552             }
   1553             return false;
   1554         }
   1555         break;
   1556     case CSSPropertyWebkitTransformOrigin:
   1557     case CSSPropertyWebkitTransformOriginX:
   1558     case CSSPropertyWebkitTransformOriginY:
   1559     case CSSPropertyWebkitTransformOriginZ: {
   1560         RefPtr<CSSValue> val1;
   1561         RefPtr<CSSValue> val2;
   1562         RefPtr<CSSValue> val3;
   1563         int propId1, propId2, propId3;
   1564         if (parseTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) {
   1565             addProperty(propId1, val1.release(), important);
   1566             if (val2)
   1567                 addProperty(propId2, val2.release(), important);
   1568             if (val3)
   1569                 addProperty(propId3, val3.release(), important);
   1570             return true;
   1571         }
   1572         return false;
   1573     }
   1574     case CSSPropertyWebkitTransformStyle:
   1575         if (value->id == CSSValueFlat || value->id == CSSValuePreserve3d)
   1576             validPrimitive = true;
   1577         break;
   1578     case CSSPropertyWebkitBackfaceVisibility:
   1579         if (value->id == CSSValueVisible || value->id == CSSValueHidden)
   1580             validPrimitive = true;
   1581         break;
   1582     case CSSPropertyWebkitPerspective:
   1583         if (id == CSSValueNone)
   1584             validPrimitive = true;
   1585         else {
   1586             // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property.
   1587             if (validUnit(value, FNumber | FLength | FNonNeg, m_strict)) {
   1588                 RefPtr<CSSValue> val = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
   1589                 if (val) {
   1590                     addProperty(propId, val.release(), important);
   1591                     return true;
   1592                 }
   1593                 return false;
   1594             }
   1595         }
   1596         break;
   1597     case CSSPropertyWebkitPerspectiveOrigin:
   1598     case CSSPropertyWebkitPerspectiveOriginX:
   1599     case CSSPropertyWebkitPerspectiveOriginY: {
   1600         RefPtr<CSSValue> val1;
   1601         RefPtr<CSSValue> val2;
   1602         int propId1, propId2;
   1603         if (parsePerspectiveOrigin(propId, propId1, propId2, val1, val2)) {
   1604             addProperty(propId1, val1.release(), important);
   1605             if (val2)
   1606                 addProperty(propId2, val2.release(), important);
   1607             return true;
   1608         }
   1609         return false;
   1610     }
   1611     case CSSPropertyWebkitAnimationDelay:
   1612     case CSSPropertyWebkitAnimationDirection:
   1613     case CSSPropertyWebkitAnimationDuration:
   1614     case CSSPropertyWebkitAnimationFillMode:
   1615     case CSSPropertyWebkitAnimationName:
   1616     case CSSPropertyWebkitAnimationPlayState:
   1617     case CSSPropertyWebkitAnimationIterationCount:
   1618     case CSSPropertyWebkitAnimationTimingFunction:
   1619     case CSSPropertyWebkitTransitionDelay:
   1620     case CSSPropertyWebkitTransitionDuration:
   1621     case CSSPropertyWebkitTransitionTimingFunction:
   1622     case CSSPropertyWebkitTransitionProperty: {
   1623         RefPtr<CSSValue> val;
   1624         if (parseAnimationProperty(propId, val)) {
   1625             addProperty(propId, val.release(), important);
   1626             return true;
   1627         }
   1628         return false;
   1629     }
   1630     case CSSPropertyWebkitMarginCollapse: {
   1631         const int properties[2] = { CSSPropertyWebkitMarginBeforeCollapse,
   1632             CSSPropertyWebkitMarginAfterCollapse };
   1633         if (num == 1) {
   1634             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
   1635             if (!parseValue(properties[0], important))
   1636                 return false;
   1637             CSSValue* value = m_parsedProperties[m_numParsedProperties-1]->value();
   1638             addProperty(properties[1], value, important);
   1639             return true;
   1640         }
   1641         else if (num == 2) {
   1642             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
   1643             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
   1644                 return false;
   1645             return true;
   1646         }
   1647         return false;
   1648     }
   1649     case CSSPropertyWebkitMarginBeforeCollapse:
   1650     case CSSPropertyWebkitMarginAfterCollapse:
   1651     case CSSPropertyWebkitMarginTopCollapse:
   1652     case CSSPropertyWebkitMarginBottomCollapse:
   1653         if (id == CSSValueCollapse || id == CSSValueSeparate || id == CSSValueDiscard)
   1654             validPrimitive = true;
   1655         break;
   1656     case CSSPropertyTextLineThroughMode:
   1657     case CSSPropertyTextOverlineMode:
   1658     case CSSPropertyTextUnderlineMode:
   1659         if (id == CSSValueContinuous || id == CSSValueSkipWhiteSpace)
   1660             validPrimitive = true;
   1661         break;
   1662     case CSSPropertyTextLineThroughStyle:
   1663     case CSSPropertyTextOverlineStyle:
   1664     case CSSPropertyTextUnderlineStyle:
   1665         if (id == CSSValueNone || id == CSSValueSolid || id == CSSValueDouble ||
   1666             id == CSSValueDashed || id == CSSValueDotDash || id == CSSValueDotDotDash ||
   1667             id == CSSValueWave)
   1668             validPrimitive = true;
   1669         break;
   1670     case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
   1671         if (id == CSSValueAuto || id == CSSValueOptimizespeed || id == CSSValueOptimizelegibility
   1672             || id == CSSValueGeometricprecision)
   1673             validPrimitive = true;
   1674         break;
   1675     case CSSPropertyTextLineThroughWidth:
   1676     case CSSPropertyTextOverlineWidth:
   1677     case CSSPropertyTextUnderlineWidth:
   1678         if (id == CSSValueAuto || id == CSSValueNormal || id == CSSValueThin ||
   1679             id == CSSValueMedium || id == CSSValueThick)
   1680             validPrimitive = true;
   1681         else
   1682             validPrimitive = !id && validUnit(value, FNumber | FLength | FPercent, m_strict);
   1683         break;
   1684     case CSSPropertyResize: // none | both | horizontal | vertical | auto
   1685         if (id == CSSValueNone || id == CSSValueBoth || id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto)
   1686             validPrimitive = true;
   1687         break;
   1688     case CSSPropertyWebkitColumnCount:
   1689         if (id == CSSValueAuto)
   1690             validPrimitive = true;
   1691         else
   1692             validPrimitive = !id && validUnit(value, FInteger | FNonNeg, false);
   1693         break;
   1694     case CSSPropertyWebkitColumnGap:         // normal | <length>
   1695         if (id == CSSValueNormal)
   1696             validPrimitive = true;
   1697         else
   1698             validPrimitive = validUnit(value, FLength | FNonNeg, m_strict);
   1699         break;
   1700     case CSSPropertyWebkitColumnSpan:        // all | 1
   1701         if (id == CSSValueAll)
   1702             validPrimitive = true;
   1703         else
   1704             validPrimitive = validUnit(value, FNumber | FNonNeg, m_strict) && value->fValue == 1;
   1705         break;
   1706     case CSSPropertyWebkitColumnWidth:         // auto | <length>
   1707         if (id == CSSValueAuto)
   1708             validPrimitive = true;
   1709         else // Always parse this property in strict mode, since it would be ambiguous otherwise when used in the 'columns' shorthand property.
   1710             validPrimitive = validUnit(value, FLength, true);
   1711         break;
   1712     case CSSPropertyPointerEvents:
   1713         // none | visiblePainted | visibleFill | visibleStroke | visible |
   1714         // painted | fill | stroke | auto | all | inherit
   1715         if (id == CSSValueVisible || id == CSSValueNone || id == CSSValueAll || id == CSSValueAuto ||
   1716             (id >= CSSValueVisiblepainted && id <= CSSValueStroke))
   1717             validPrimitive = true;
   1718         break;
   1719 
   1720     // End of CSS3 properties
   1721 
   1722     // Apple specific properties.  These will never be standardized and are purely to
   1723     // support custom WebKit-based Apple applications.
   1724     case CSSPropertyWebkitLineClamp:
   1725         // When specifying number of lines, don't allow 0 as a valid value
   1726         // When specifying either type of unit, require non-negative integers
   1727         validPrimitive = (!id && (value->unit == CSSPrimitiveValue::CSS_PERCENTAGE || value->fValue) && validUnit(value, FInteger | FPercent | FNonNeg, false));
   1728         break;
   1729     case CSSPropertyWebkitTextSizeAdjust:
   1730         if (id == CSSValueAuto || id == CSSValueNone)
   1731             validPrimitive = true;
   1732         break;
   1733     case CSSPropertyWebkitRtlOrdering:
   1734         if (id == CSSValueLogical || id == CSSValueVisual)
   1735             validPrimitive = true;
   1736         break;
   1737 
   1738     case CSSPropertyWebkitFontSizeDelta:           // <length>
   1739         validPrimitive = validUnit(value, FLength, m_strict);
   1740         break;
   1741 
   1742     case CSSPropertyWebkitNbspMode:     // normal | space
   1743         if (id == CSSValueNormal || id == CSSValueSpace)
   1744             validPrimitive = true;
   1745         break;
   1746 
   1747     case CSSPropertyWebkitLineBreak:   // normal | after-white-space
   1748         if (id == CSSValueNormal || id == CSSValueAfterWhiteSpace)
   1749             validPrimitive = true;
   1750         break;
   1751 
   1752     case CSSPropertyWebkitMatchNearestMailBlockquoteColor:   // normal | match
   1753         if (id == CSSValueNormal || id == CSSValueMatch)
   1754             validPrimitive = true;
   1755         break;
   1756 
   1757     case CSSPropertyWebkitHighlight:
   1758         if (id == CSSValueNone || value->unit == CSSPrimitiveValue::CSS_STRING)
   1759             validPrimitive = true;
   1760         break;
   1761 
   1762     case CSSPropertyWebkitHyphens:
   1763         if (id == CSSValueNone || id == CSSValueManual || id == CSSValueAuto)
   1764             validPrimitive = true;
   1765         break;
   1766 
   1767     case CSSPropertyWebkitHyphenateCharacter:
   1768         if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
   1769             validPrimitive = true;
   1770         break;
   1771 
   1772     case CSSPropertyWebkitHyphenateLimitBefore:
   1773     case CSSPropertyWebkitHyphenateLimitAfter:
   1774         if (id == CSSValueAuto || validUnit(value, FInteger | FNonNeg, true))
   1775             validPrimitive = true;
   1776         break;
   1777 
   1778     case CSSPropertyWebkitLocale:
   1779         if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
   1780             validPrimitive = true;
   1781         break;
   1782 
   1783     case CSSPropertyWebkitBorderFit:
   1784         if (id == CSSValueBorder || id == CSSValueLines)
   1785             validPrimitive = true;
   1786         break;
   1787 
   1788     case CSSPropertyWebkitTextSecurity:
   1789         // disc | circle | square | none | inherit
   1790         if (id == CSSValueDisc || id == CSSValueCircle || id == CSSValueSquare|| id == CSSValueNone)
   1791             validPrimitive = true;
   1792         break;
   1793 
   1794     case CSSPropertyWebkitFontSmoothing:
   1795         if (id == CSSValueAuto || id == CSSValueNone
   1796             || id == CSSValueAntialiased || id == CSSValueSubpixelAntialiased)
   1797             validPrimitive = true;
   1798         break;
   1799 
   1800 #if ENABLE(DASHBOARD_SUPPORT)
   1801     case CSSPropertyWebkitDashboardRegion: // <dashboard-region> | <dashboard-region>
   1802         if (value->unit == CSSParserValue::Function || id == CSSValueNone)
   1803             return parseDashboardRegions(propId, important);
   1804         break;
   1805 #endif
   1806     // End Apple-specific properties
   1807 
   1808         /* shorthand properties */
   1809     case CSSPropertyBackground: {
   1810         // Position must come before color in this array because a plain old "0" is a legal color
   1811         // in quirks mode but it's usually the X coordinate of a position.
   1812         // FIXME: Add CSSPropertyBackgroundSize to the shorthand.
   1813         const int properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat,
   1814                                    CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyBackgroundOrigin,
   1815                                    CSSPropertyBackgroundClip, CSSPropertyBackgroundColor };
   1816         return parseFillShorthand(propId, properties, 7, important);
   1817     }
   1818     case CSSPropertyWebkitMask: {
   1819         const int properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
   1820                                    CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition,
   1821                                    CSSPropertyWebkitMaskOrigin, CSSPropertyWebkitMaskClip };
   1822         return parseFillShorthand(propId, properties, 6, important);
   1823     }
   1824     case CSSPropertyBorder:
   1825         // [ 'border-width' || 'border-style' || <color> ] | inherit
   1826     {
   1827         const int properties[3] = { CSSPropertyBorderWidth, CSSPropertyBorderStyle,
   1828                                     CSSPropertyBorderColor };
   1829         return parseShorthand(propId, properties, 3, important);
   1830     }
   1831     case CSSPropertyBorderTop:
   1832         // [ 'border-top-width' || 'border-style' || <color> ] | inherit
   1833     {
   1834         const int properties[3] = { CSSPropertyBorderTopWidth, CSSPropertyBorderTopStyle,
   1835                                     CSSPropertyBorderTopColor};
   1836         return parseShorthand(propId, properties, 3, important);
   1837     }
   1838     case CSSPropertyBorderRight:
   1839         // [ 'border-right-width' || 'border-style' || <color> ] | inherit
   1840     {
   1841         const int properties[3] = { CSSPropertyBorderRightWidth, CSSPropertyBorderRightStyle,
   1842                                     CSSPropertyBorderRightColor };
   1843         return parseShorthand(propId, properties, 3, important);
   1844     }
   1845     case CSSPropertyBorderBottom:
   1846         // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
   1847     {
   1848         const int properties[3] = { CSSPropertyBorderBottomWidth, CSSPropertyBorderBottomStyle,
   1849                                     CSSPropertyBorderBottomColor };
   1850         return parseShorthand(propId, properties, 3, important);
   1851     }
   1852     case CSSPropertyBorderLeft:
   1853         // [ 'border-left-width' || 'border-style' || <color> ] | inherit
   1854     {
   1855         const int properties[3] = { CSSPropertyBorderLeftWidth, CSSPropertyBorderLeftStyle,
   1856                                     CSSPropertyBorderLeftColor };
   1857         return parseShorthand(propId, properties, 3, important);
   1858     }
   1859     case CSSPropertyWebkitBorderStart:
   1860     {
   1861         const int properties[3] = { CSSPropertyWebkitBorderStartWidth, CSSPropertyWebkitBorderStartStyle,
   1862             CSSPropertyWebkitBorderStartColor };
   1863         return parseShorthand(propId, properties, 3, important);
   1864     }
   1865     case CSSPropertyWebkitBorderEnd:
   1866     {
   1867         const int properties[3] = { CSSPropertyWebkitBorderEndWidth, CSSPropertyWebkitBorderEndStyle,
   1868             CSSPropertyWebkitBorderEndColor };
   1869         return parseShorthand(propId, properties, 3, important);
   1870     }
   1871     case CSSPropertyWebkitBorderBefore:
   1872     {
   1873         const int properties[3] = { CSSPropertyWebkitBorderBeforeWidth, CSSPropertyWebkitBorderBeforeStyle,
   1874             CSSPropertyWebkitBorderBeforeColor };
   1875         return parseShorthand(propId, properties, 3, important);
   1876     }
   1877     case CSSPropertyWebkitBorderAfter:
   1878     {
   1879         const int properties[3] = { CSSPropertyWebkitBorderAfterWidth, CSSPropertyWebkitBorderAfterStyle,
   1880             CSSPropertyWebkitBorderAfterColor };
   1881         return parseShorthand(propId, properties, 3, important);
   1882     }
   1883     case CSSPropertyOutline:
   1884         // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
   1885     {
   1886         const int properties[3] = { CSSPropertyOutlineWidth, CSSPropertyOutlineStyle,
   1887                                     CSSPropertyOutlineColor };
   1888         return parseShorthand(propId, properties, 3, important);
   1889     }
   1890     case CSSPropertyBorderColor:
   1891         // <color>{1,4} | inherit
   1892     {
   1893         const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor,
   1894                                     CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
   1895         return parse4Values(propId, properties, important);
   1896     }
   1897     case CSSPropertyBorderWidth:
   1898         // <border-width>{1,4} | inherit
   1899     {
   1900         const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth,
   1901                                     CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
   1902         return parse4Values(propId, properties, important);
   1903     }
   1904     case CSSPropertyBorderStyle:
   1905         // <border-style>{1,4} | inherit
   1906     {
   1907         const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle,
   1908                                     CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
   1909         return parse4Values(propId, properties, important);
   1910     }
   1911     case CSSPropertyMargin:
   1912         // <margin-width>{1,4} | inherit
   1913     {
   1914         const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight,
   1915                                     CSSPropertyMarginBottom, CSSPropertyMarginLeft };
   1916         return parse4Values(propId, properties, important);
   1917     }
   1918     case CSSPropertyPadding:
   1919         // <padding-width>{1,4} | inherit
   1920     {
   1921         const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight,
   1922                                     CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
   1923         return parse4Values(propId, properties, important);
   1924     }
   1925     case CSSPropertyFont:
   1926         // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
   1927         // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
   1928         if (id >= CSSValueCaption && id <= CSSValueStatusBar)
   1929             validPrimitive = true;
   1930         else
   1931             return parseFont(important);
   1932         break;
   1933     case CSSPropertyListStyle:
   1934     {
   1935         const int properties[3] = { CSSPropertyListStyleType, CSSPropertyListStylePosition,
   1936                                     CSSPropertyListStyleImage };
   1937         return parseShorthand(propId, properties, 3, important);
   1938     }
   1939     case CSSPropertyWebkitColumns: {
   1940         const int properties[2] = { CSSPropertyWebkitColumnWidth, CSSPropertyWebkitColumnCount };
   1941         return parseShorthand(propId, properties, 2, important);
   1942     }
   1943     case CSSPropertyWebkitColumnRule: {
   1944         const int properties[3] = { CSSPropertyWebkitColumnRuleWidth, CSSPropertyWebkitColumnRuleStyle,
   1945                                     CSSPropertyWebkitColumnRuleColor };
   1946         return parseShorthand(propId, properties, 3, important);
   1947     }
   1948     case CSSPropertyWebkitTextStroke: {
   1949         const int properties[2] = { CSSPropertyWebkitTextStrokeWidth, CSSPropertyWebkitTextStrokeColor };
   1950         return parseShorthand(propId, properties, 2, important);
   1951     }
   1952     case CSSPropertyWebkitAnimation:
   1953         return parseAnimationShorthand(important);
   1954     case CSSPropertyWebkitTransition:
   1955         return parseTransitionShorthand(important);
   1956     case CSSPropertyInvalid:
   1957         return false;
   1958     case CSSPropertyPage:
   1959         return parsePage(propId, important);
   1960     case CSSPropertyFontStretch:
   1961     case CSSPropertyTextLineThrough:
   1962     case CSSPropertyTextOverline:
   1963     case CSSPropertyTextUnderline:
   1964         return false;
   1965 #if ENABLE(WCSS)
   1966     case CSSPropertyWapInputFormat:
   1967         validPrimitive = true;
   1968         break;
   1969     case CSSPropertyWapInputRequired:
   1970         parsedValue = parseWCSSInputProperty();
   1971         break;
   1972 #endif
   1973 
   1974     // CSS Text Layout Module Level 3: Vertical writing support
   1975     case CSSPropertyWebkitWritingMode:
   1976         if (id >= CSSValueHorizontalTb && id <= CSSValueHorizontalBt)
   1977             validPrimitive = true;
   1978         break;
   1979 
   1980     case CSSPropertyWebkitTextCombine:
   1981         if (id == CSSValueNone || id == CSSValueHorizontal)
   1982             validPrimitive = true;
   1983         break;
   1984 
   1985     case CSSPropertyWebkitTextEmphasis: {
   1986         const int properties[] = { CSSPropertyWebkitTextEmphasisStyle, CSSPropertyWebkitTextEmphasisColor };
   1987         return parseShorthand(propId, properties, WTF_ARRAY_LENGTH(properties), important);
   1988     }
   1989 
   1990     case CSSPropertyWebkitTextEmphasisPosition:
   1991         if (id == CSSValueOver || id == CSSValueUnder)
   1992             validPrimitive = true;
   1993         break;
   1994 
   1995     case CSSPropertyWebkitTextEmphasisStyle:
   1996         return parseTextEmphasisStyle(important);
   1997 
   1998     case CSSPropertyWebkitTextOrientation:
   1999         // FIXME: For now just support upright and vertical-right.
   2000         if (id == CSSValueVerticalRight || id == CSSValueUpright)
   2001             validPrimitive = true;
   2002         break;
   2003 
   2004     case CSSPropertyWebkitLineBoxContain:
   2005         if (id == CSSValueNone)
   2006             validPrimitive = true;
   2007         else
   2008             return parseLineBoxContain(important);
   2009         break;
   2010 
   2011 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
   2012     case CSSPropertyWebkitTapHighlightColor:
   2013         parsedValue = parseColor();
   2014         if (parsedValue)
   2015             m_valueList->next();
   2016         break;
   2017 #endif
   2018 
   2019 #if ENABLE(SVG)
   2020     default:
   2021         return parseSVGValue(propId, important);
   2022 #endif
   2023     }
   2024 
   2025     if (validPrimitive) {
   2026         if (id != 0)
   2027             parsedValue = primitiveValueCache()->createIdentifierValue(id);
   2028         else if (value->unit == CSSPrimitiveValue::CSS_STRING)
   2029             parsedValue = primitiveValueCache()->createValue(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
   2030         else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
   2031             parsedValue = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
   2032         else if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
   2033             parsedValue = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
   2034         else if (value->unit >= CSSParserValue::Q_EMS)
   2035             parsedValue = CSSQuirkPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_EMS);
   2036         m_valueList->next();
   2037     }
   2038     if (parsedValue) {
   2039         if (!m_valueList->current() || inShorthand()) {
   2040             addProperty(propId, parsedValue.release(), important);
   2041             return true;
   2042         }
   2043     }
   2044     return false;
   2045 }
   2046 
   2047 #if ENABLE(WCSS)
   2048 PassRefPtr<CSSValue> CSSParser::parseWCSSInputProperty()
   2049 {
   2050     RefPtr<CSSValue> parsedValue = 0;
   2051     CSSParserValue* value = m_valueList->current();
   2052     String inputProperty;
   2053     if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT)
   2054         inputProperty = String(value->string);
   2055 
   2056     if (!inputProperty.isEmpty())
   2057        parsedValue = primitiveValueCache()->createValue(inputProperty, CSSPrimitiveValue::CSS_STRING);
   2058 
   2059     while (m_valueList->next()) {
   2060     // pass all other values, if any. If we don't do this,
   2061     // the parser will think that it's not done and won't process this property
   2062     }
   2063 
   2064     return parsedValue;
   2065 }
   2066 #endif
   2067 
   2068 void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
   2069 {
   2070     if (lval) {
   2071         if (lval->isValueList())
   2072             static_cast<CSSValueList*>(lval.get())->append(rval);
   2073         else {
   2074             PassRefPtr<CSSValue> oldlVal(lval.release());
   2075             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
   2076             list->append(oldlVal);
   2077             list->append(rval);
   2078             lval = list;
   2079         }
   2080     }
   2081     else
   2082         lval = rval;
   2083 }
   2084 
   2085 static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue, CSSPrimitiveValueCache* primitiveValueCache)
   2086 {
   2087     if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox
   2088         || parserValue->id == CSSValueContentBox || parserValue->id == CSSValueWebkitText) {
   2089         cssValue = primitiveValueCache->createIdentifierValue(parserValue->id);
   2090         return true;
   2091     }
   2092     return false;
   2093 }
   2094 
   2095 const int cMaxFillProperties = 9;
   2096 
   2097 bool CSSParser::parseFillShorthand(int propId, const int* properties, int numProperties, bool important)
   2098 {
   2099     ASSERT(numProperties <= cMaxFillProperties);
   2100     if (numProperties > cMaxFillProperties)
   2101         return false;
   2102 
   2103     ShorthandScope scope(this, propId);
   2104 
   2105     bool parsedProperty[cMaxFillProperties] = { false };
   2106     RefPtr<CSSValue> values[cMaxFillProperties];
   2107     RefPtr<CSSValue> clipValue;
   2108     RefPtr<CSSValue> positionYValue;
   2109     RefPtr<CSSValue> repeatYValue;
   2110     bool foundClip = false;
   2111     int i;
   2112 
   2113     while (m_valueList->current()) {
   2114         CSSParserValue* val = m_valueList->current();
   2115         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
   2116             // We hit the end.  Fill in all remaining values with the initial value.
   2117             m_valueList->next();
   2118             for (i = 0; i < numProperties; ++i) {
   2119                 if (properties[i] == CSSPropertyBackgroundColor && parsedProperty[i])
   2120                     // Color is not allowed except as the last item in a list for backgrounds.
   2121                     // Reject the entire property.
   2122                     return false;
   2123 
   2124                 if (!parsedProperty[i] && properties[i] != CSSPropertyBackgroundColor) {
   2125                     addFillValue(values[i], CSSInitialValue::createImplicit());
   2126                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
   2127                         addFillValue(positionYValue, CSSInitialValue::createImplicit());
   2128                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
   2129                         addFillValue(repeatYValue, CSSInitialValue::createImplicit());
   2130                     if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
   2131                         // If background-origin wasn't present, then reset background-clip also.
   2132                         addFillValue(clipValue, CSSInitialValue::createImplicit());
   2133                     }
   2134                 }
   2135                 parsedProperty[i] = false;
   2136             }
   2137             if (!m_valueList->current())
   2138                 break;
   2139         }
   2140 
   2141         bool found = false;
   2142         for (i = 0; !found && i < numProperties; ++i) {
   2143             if (!parsedProperty[i]) {
   2144                 RefPtr<CSSValue> val1;
   2145                 RefPtr<CSSValue> val2;
   2146                 int propId1, propId2;
   2147                 CSSParserValue* parserValue = m_valueList->current();
   2148                 if (parseFillProperty(properties[i], propId1, propId2, val1, val2)) {
   2149                     parsedProperty[i] = found = true;
   2150                     addFillValue(values[i], val1.release());
   2151                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
   2152                         addFillValue(positionYValue, val2.release());
   2153                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
   2154                         addFillValue(repeatYValue, val2.release());
   2155                     if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
   2156                         // Reparse the value as a clip, and see if we succeed.
   2157                         if (parseBackgroundClip(parserValue, val1, primitiveValueCache()))
   2158                             addFillValue(clipValue, val1.release()); // The property parsed successfully.
   2159                         else
   2160                             addFillValue(clipValue, CSSInitialValue::createImplicit()); // Some value was used for origin that is not supported by clip. Just reset clip instead.
   2161                     }
   2162                     if (properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) {
   2163                         // Update clipValue
   2164                         addFillValue(clipValue, val1.release());
   2165                         foundClip = true;
   2166                     }
   2167                 }
   2168             }
   2169         }
   2170 
   2171         // if we didn't find at least one match, this is an
   2172         // invalid shorthand and we have to ignore it
   2173         if (!found)
   2174             return false;
   2175     }
   2176 
   2177     // Fill in any remaining properties with the initial value.
   2178     for (i = 0; i < numProperties; ++i) {
   2179         if (!parsedProperty[i]) {
   2180             addFillValue(values[i], CSSInitialValue::createImplicit());
   2181             if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
   2182                 addFillValue(positionYValue, CSSInitialValue::createImplicit());
   2183             if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
   2184                 addFillValue(repeatYValue, CSSInitialValue::createImplicit());
   2185             if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
   2186                 // If background-origin wasn't present, then reset background-clip also.
   2187                 addFillValue(clipValue, CSSInitialValue::createImplicit());
   2188             }
   2189         }
   2190     }
   2191 
   2192     // Now add all of the properties we found.
   2193     for (i = 0; i < numProperties; i++) {
   2194         if (properties[i] == CSSPropertyBackgroundPosition) {
   2195             addProperty(CSSPropertyBackgroundPositionX, values[i].release(), important);
   2196             // it's OK to call positionYValue.release() since we only see CSSPropertyBackgroundPosition once
   2197             addProperty(CSSPropertyBackgroundPositionY, positionYValue.release(), important);
   2198         } else if (properties[i] == CSSPropertyWebkitMaskPosition) {
   2199             addProperty(CSSPropertyWebkitMaskPositionX, values[i].release(), important);
   2200             // it's OK to call positionYValue.release() since we only see CSSPropertyWebkitMaskPosition once
   2201             addProperty(CSSPropertyWebkitMaskPositionY, positionYValue.release(), important);
   2202         } else if (properties[i] == CSSPropertyBackgroundRepeat) {
   2203             addProperty(CSSPropertyBackgroundRepeatX, values[i].release(), important);
   2204             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
   2205             addProperty(CSSPropertyBackgroundRepeatY, repeatYValue.release(), important);
   2206         } else if (properties[i] == CSSPropertyWebkitMaskRepeat) {
   2207             addProperty(CSSPropertyWebkitMaskRepeatX, values[i].release(), important);
   2208             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
   2209             addProperty(CSSPropertyWebkitMaskRepeatY, repeatYValue.release(), important);
   2210         } else if ((properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) && !foundClip)
   2211             // Value is already set while updating origin
   2212             continue;
   2213         else
   2214             addProperty(properties[i], values[i].release(), important);
   2215 
   2216         // Add in clip values when we hit the corresponding origin property.
   2217         if (properties[i] == CSSPropertyBackgroundOrigin && !foundClip)
   2218             addProperty(CSSPropertyBackgroundClip, clipValue.release(), important);
   2219         else if (properties[i] == CSSPropertyWebkitMaskOrigin && !foundClip)
   2220             addProperty(CSSPropertyWebkitMaskClip, clipValue.release(), important);
   2221     }
   2222 
   2223     return true;
   2224 }
   2225 
   2226 void CSSParser::addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
   2227 {
   2228     if (lval) {
   2229         if (lval->isValueList())
   2230             static_cast<CSSValueList*>(lval.get())->append(rval);
   2231         else {
   2232             PassRefPtr<CSSValue> oldVal(lval.release());
   2233             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
   2234             list->append(oldVal);
   2235             list->append(rval);
   2236             lval = list;
   2237         }
   2238     }
   2239     else
   2240         lval = rval;
   2241 }
   2242 
   2243 bool CSSParser::parseAnimationShorthand(bool important)
   2244 {
   2245     const int properties[] = {  CSSPropertyWebkitAnimationName,
   2246                                 CSSPropertyWebkitAnimationDuration,
   2247                                 CSSPropertyWebkitAnimationTimingFunction,
   2248                                 CSSPropertyWebkitAnimationDelay,
   2249                                 CSSPropertyWebkitAnimationIterationCount,
   2250                                 CSSPropertyWebkitAnimationDirection,
   2251                                 CSSPropertyWebkitAnimationFillMode };
   2252     const int numProperties = WTF_ARRAY_LENGTH(properties);
   2253 
   2254     ShorthandScope scope(this, CSSPropertyWebkitAnimation);
   2255 
   2256     bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
   2257     RefPtr<CSSValue> values[numProperties];
   2258 
   2259     int i;
   2260     while (m_valueList->current()) {
   2261         CSSParserValue* val = m_valueList->current();
   2262         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
   2263             // We hit the end.  Fill in all remaining values with the initial value.
   2264             m_valueList->next();
   2265             for (i = 0; i < numProperties; ++i) {
   2266                 if (!parsedProperty[i])
   2267                     addAnimationValue(values[i], CSSInitialValue::createImplicit());
   2268                 parsedProperty[i] = false;
   2269             }
   2270             if (!m_valueList->current())
   2271                 break;
   2272         }
   2273 
   2274         bool found = false;
   2275         for (i = 0; !found && i < numProperties; ++i) {
   2276             if (!parsedProperty[i]) {
   2277                 RefPtr<CSSValue> val;
   2278                 if (parseAnimationProperty(properties[i], val)) {
   2279                     parsedProperty[i] = found = true;
   2280                     addAnimationValue(values[i], val.release());
   2281                 }
   2282             }
   2283         }
   2284 
   2285         // if we didn't find at least one match, this is an
   2286         // invalid shorthand and we have to ignore it
   2287         if (!found)
   2288             return false;
   2289     }
   2290 
   2291     // Fill in any remaining properties with the initial value.
   2292     for (i = 0; i < numProperties; ++i) {
   2293         if (!parsedProperty[i])
   2294             addAnimationValue(values[i], CSSInitialValue::createImplicit());
   2295     }
   2296 
   2297     // Now add all of the properties we found.
   2298     for (i = 0; i < numProperties; i++)
   2299         addProperty(properties[i], values[i].release(), important);
   2300 
   2301     return true;
   2302 }
   2303 
   2304 bool CSSParser::parseTransitionShorthand(bool important)
   2305 {
   2306     const int properties[] = { CSSPropertyWebkitTransitionProperty,
   2307                                CSSPropertyWebkitTransitionDuration,
   2308                                CSSPropertyWebkitTransitionTimingFunction,
   2309                                CSSPropertyWebkitTransitionDelay };
   2310     const int numProperties = WTF_ARRAY_LENGTH(properties);
   2311 
   2312     ShorthandScope scope(this, CSSPropertyWebkitTransition);
   2313 
   2314     bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
   2315     RefPtr<CSSValue> values[numProperties];
   2316 
   2317     int i;
   2318     while (m_valueList->current()) {
   2319         CSSParserValue* val = m_valueList->current();
   2320         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
   2321             // We hit the end.  Fill in all remaining values with the initial value.
   2322             m_valueList->next();
   2323             for (i = 0; i < numProperties; ++i) {
   2324                 if (!parsedProperty[i])
   2325                     addAnimationValue(values[i], CSSInitialValue::createImplicit());
   2326                 parsedProperty[i] = false;
   2327             }
   2328             if (!m_valueList->current())
   2329                 break;
   2330         }
   2331 
   2332         bool found = false;
   2333         for (i = 0; !found && i < numProperties; ++i) {
   2334             if (!parsedProperty[i]) {
   2335                 RefPtr<CSSValue> val;
   2336                 if (parseAnimationProperty(properties[i], val)) {
   2337                     parsedProperty[i] = found = true;
   2338                     addAnimationValue(values[i], val.release());
   2339                 }
   2340             }
   2341         }
   2342 
   2343         // if we didn't find at least one match, this is an
   2344         // invalid shorthand and we have to ignore it
   2345         if (!found)
   2346             return false;
   2347     }
   2348 
   2349     // Fill in any remaining properties with the initial value.
   2350     for (i = 0; i < numProperties; ++i) {
   2351         if (!parsedProperty[i])
   2352             addAnimationValue(values[i], CSSInitialValue::createImplicit());
   2353     }
   2354 
   2355     // Now add all of the properties we found.
   2356     for (i = 0; i < numProperties; i++)
   2357         addProperty(properties[i], values[i].release(), important);
   2358 
   2359     return true;
   2360 }
   2361 
   2362 bool CSSParser::parseShorthand(int propId, const int *properties, int numProperties, bool important)
   2363 {
   2364     // We try to match as many properties as possible
   2365     // We set up an array of booleans to mark which property has been found,
   2366     // and we try to search for properties until it makes no longer any sense.
   2367     ShorthandScope scope(this, propId);
   2368 
   2369     bool found = false;
   2370     bool fnd[6]; // Trust me ;)
   2371     for (int i = 0; i < numProperties; i++)
   2372         fnd[i] = false;
   2373 
   2374     while (m_valueList->current()) {
   2375         found = false;
   2376         for (int propIndex = 0; !found && propIndex < numProperties; ++propIndex) {
   2377             if (!fnd[propIndex]) {
   2378                 if (parseValue(properties[propIndex], important))
   2379                     fnd[propIndex] = found = true;
   2380             }
   2381         }
   2382 
   2383         // if we didn't find at least one match, this is an
   2384         // invalid shorthand and we have to ignore it
   2385         if (!found)
   2386             return false;
   2387     }
   2388 
   2389     // Fill in any remaining properties with the initial value.
   2390     m_implicitShorthand = true;
   2391     for (int i = 0; i < numProperties; ++i) {
   2392         if (!fnd[i])
   2393             addProperty(properties[i], CSSInitialValue::createImplicit(), important);
   2394     }
   2395     m_implicitShorthand = false;
   2396 
   2397     return true;
   2398 }
   2399 
   2400 bool CSSParser::parse4Values(int propId, const int *properties,  bool important)
   2401 {
   2402     /* From the CSS 2 specs, 8.3
   2403      * If there is only one value, it applies to all sides. If there are two values, the top and
   2404      * bottom margins are set to the first value and the right and left margins are set to the second.
   2405      * If there are three values, the top is set to the first value, the left and right are set to the
   2406      * second, and the bottom is set to the third. If there are four values, they apply to the top,
   2407      * right, bottom, and left, respectively.
   2408      */
   2409 
   2410     int num = inShorthand() ? 1 : m_valueList->size();
   2411 
   2412     ShorthandScope scope(this, propId);
   2413 
   2414     // the order is top, right, bottom, left
   2415     switch (num) {
   2416         case 1: {
   2417             if (!parseValue(properties[0], important))
   2418                 return false;
   2419             CSSValue *value = m_parsedProperties[m_numParsedProperties-1]->value();
   2420             m_implicitShorthand = true;
   2421             addProperty(properties[1], value, important);
   2422             addProperty(properties[2], value, important);
   2423             addProperty(properties[3], value, important);
   2424             m_implicitShorthand = false;
   2425             break;
   2426         }
   2427         case 2: {
   2428             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
   2429                 return false;
   2430             CSSValue *value = m_parsedProperties[m_numParsedProperties-2]->value();
   2431             m_implicitShorthand = true;
   2432             addProperty(properties[2], value, important);
   2433             value = m_parsedProperties[m_numParsedProperties-2]->value();
   2434             addProperty(properties[3], value, important);
   2435             m_implicitShorthand = false;
   2436             break;
   2437         }
   2438         case 3: {
   2439             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
   2440                 return false;
   2441             CSSValue *value = m_parsedProperties[m_numParsedProperties-2]->value();
   2442             m_implicitShorthand = true;
   2443             addProperty(properties[3], value, important);
   2444             m_implicitShorthand = false;
   2445             break;
   2446         }
   2447         case 4: {
   2448             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
   2449                 !parseValue(properties[2], important) || !parseValue(properties[3], important))
   2450                 return false;
   2451             break;
   2452         }
   2453         default: {
   2454             return false;
   2455         }
   2456     }
   2457 
   2458     return true;
   2459 }
   2460 
   2461 // auto | <identifier>
   2462 bool CSSParser::parsePage(int propId, bool important)
   2463 {
   2464     ASSERT(propId == CSSPropertyPage);
   2465 
   2466     if (m_valueList->size() != 1)
   2467         return false;
   2468 
   2469     CSSParserValue* value = m_valueList->current();
   2470     if (!value)
   2471         return false;
   2472 
   2473     if (value->id == CSSValueAuto) {
   2474         addProperty(propId, primitiveValueCache()->createIdentifierValue(value->id), important);
   2475         return true;
   2476     } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) {
   2477         addProperty(propId, primitiveValueCache()->createValue(value->string, CSSPrimitiveValue::CSS_STRING), important);
   2478         return true;
   2479     }
   2480     return false;
   2481 }
   2482 
   2483 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
   2484 bool CSSParser::parseSize(int propId, bool important)
   2485 {
   2486     ASSERT(propId == CSSPropertySize);
   2487 
   2488     if (m_valueList->size() > 2)
   2489         return false;
   2490 
   2491     CSSParserValue* value = m_valueList->current();
   2492     if (!value)
   2493         return false;
   2494 
   2495     RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
   2496 
   2497     // First parameter.
   2498     SizeParameterType paramType = parseSizeParameter(parsedValues.get(), value, None);
   2499     if (paramType == None)
   2500         return false;
   2501 
   2502     // Second parameter, if any.
   2503     value = m_valueList->next();
   2504     if (value) {
   2505         paramType = parseSizeParameter(parsedValues.get(), value, paramType);
   2506         if (paramType == None)
   2507             return false;
   2508     }
   2509 
   2510     addProperty(propId, parsedValues.release(), important);
   2511     return true;
   2512 }
   2513 
   2514 CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType)
   2515 {
   2516     switch (value->id) {
   2517     case CSSValueAuto:
   2518         if (prevParamType == None) {
   2519             parsedValues->append(primitiveValueCache()->createIdentifierValue(value->id));
   2520             return Auto;
   2521         }
   2522         return None;
   2523     case CSSValueLandscape:
   2524     case CSSValuePortrait:
   2525         if (prevParamType == None || prevParamType == PageSize) {
   2526             parsedValues->append(primitiveValueCache()->createIdentifierValue(value->id));
   2527             return Orientation;
   2528         }
   2529         return None;
   2530     case CSSValueA3:
   2531     case CSSValueA4:
   2532     case CSSValueA5:
   2533     case CSSValueB4:
   2534     case CSSValueB5:
   2535     case CSSValueLedger:
   2536     case CSSValueLegal:
   2537     case CSSValueLetter:
   2538         if (prevParamType == None || prevParamType == Orientation) {
   2539             // Normalize to Page Size then Orientation order by prepending.
   2540             // This is not specified by the CSS3 Paged Media specification, but for simpler processing later (CSSStyleSelector::applyPageSizeProperty).
   2541             parsedValues->prepend(primitiveValueCache()->createIdentifierValue(value->id));
   2542             return PageSize;
   2543         }
   2544         return None;
   2545     case 0:
   2546         if (validUnit(value, FLength | FNonNeg, m_strict) && (prevParamType == None || prevParamType == Length)) {
   2547             parsedValues->append(primitiveValueCache()->createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)));
   2548             return Length;
   2549         }
   2550         return None;
   2551     default:
   2552         return None;
   2553     }
   2554 }
   2555 
   2556 // [ <string> <string> ]+ | inherit | none
   2557 // inherit and none are handled in parseValue.
   2558 bool CSSParser::parseQuotes(int propId, bool important)
   2559 {
   2560     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
   2561     while (CSSParserValue* val = m_valueList->current()) {
   2562         RefPtr<CSSValue> parsedValue;
   2563         if (val->unit == CSSPrimitiveValue::CSS_STRING)
   2564             parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING);
   2565         else
   2566             break;
   2567         values->append(parsedValue.release());
   2568         m_valueList->next();
   2569     }
   2570     if (values->length()) {
   2571         addProperty(propId, values.release(), important);
   2572         m_valueList->next();
   2573         return true;
   2574     }
   2575     return false;
   2576 }
   2577 
   2578 // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
   2579 // in CSS 2.1 this got somewhat reduced:
   2580 // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
   2581 bool CSSParser::parseContent(int propId, bool important)
   2582 {
   2583     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
   2584 
   2585     while (CSSParserValue* val = m_valueList->current()) {
   2586         RefPtr<CSSValue> parsedValue;
   2587         if (val->unit == CSSPrimitiveValue::CSS_URI && m_styleSheet) {
   2588             // url
   2589             // FIXME: The completeURL call should be done when using the CSSImageValue,
   2590             // not when creating it.
   2591             parsedValue = CSSImageValue::create(m_styleSheet->completeURL(val->string));
   2592         } else if (val->unit == CSSParserValue::Function) {
   2593             // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) | -webkit-gradient(...)
   2594             CSSParserValueList* args = val->function->args.get();
   2595             if (!args)
   2596                 return false;
   2597             if (equalIgnoringCase(val->function->name, "attr(")) {
   2598                 parsedValue = parseAttr(args);
   2599                 if (!parsedValue)
   2600                     return false;
   2601             } else if (equalIgnoringCase(val->function->name, "counter(")) {
   2602                 parsedValue = parseCounterContent(args, false);
   2603                 if (!parsedValue)
   2604                     return false;
   2605             } else if (equalIgnoringCase(val->function->name, "counters(")) {
   2606                 parsedValue = parseCounterContent(args, true);
   2607                 if (!parsedValue)
   2608                     return false;
   2609             } else if (isGeneratedImageValue(val)) {
   2610                 if (!parseGeneratedImage(parsedValue))
   2611                     return false;
   2612             } else
   2613                 return false;
   2614         } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
   2615             // open-quote
   2616             // close-quote
   2617             // no-open-quote
   2618             // no-close-quote
   2619             // inherit
   2620             // FIXME: These are not yet implemented (http://bugs.webkit.org/show_bug.cgi?id=6503).
   2621             // none
   2622             // normal
   2623             switch (val->id) {
   2624             case CSSValueOpenQuote:
   2625             case CSSValueCloseQuote:
   2626             case CSSValueNoOpenQuote:
   2627             case CSSValueNoCloseQuote:
   2628             case CSSValueNone:
   2629             case CSSValueNormal:
   2630                 parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
   2631             }
   2632         } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
   2633             parsedValue = primitiveValueCache()->createValue(val->string, CSSPrimitiveValue::CSS_STRING);
   2634         }
   2635         if (!parsedValue)
   2636             break;
   2637         values->append(parsedValue.release());
   2638         m_valueList->next();
   2639     }
   2640 
   2641     if (values->length()) {
   2642         addProperty(propId, values.release(), important);
   2643         m_valueList->next();
   2644         return true;
   2645     }
   2646 
   2647     return false;
   2648 }
   2649 
   2650 PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args)
   2651 {
   2652     if (args->size() != 1)
   2653         return 0;
   2654 
   2655     CSSParserValue* a = args->current();
   2656 
   2657     if (a->unit != CSSPrimitiveValue::CSS_IDENT)
   2658         return 0;
   2659 
   2660     String attrName = a->string;
   2661     // CSS allows identifiers with "-" at the start, like "-webkit-mask-image".
   2662     // But HTML attribute names can't have those characters, and we should not
   2663     // even parse them inside attr().
   2664     if (attrName[0] == '-')
   2665         return 0;
   2666 
   2667     if (document() && document()->isHTMLDocument())
   2668         attrName = attrName.lower();
   2669 
   2670     return primitiveValueCache()->createValue(attrName, CSSPrimitiveValue::CSS_ATTR);
   2671 }
   2672 
   2673 PassRefPtr<CSSValue> CSSParser::parseBackgroundColor()
   2674 {
   2675     int id = m_valueList->current()->id;
   2676     if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor ||
   2677         (id >= CSSValueGrey && id < CSSValueWebkitText && !m_strict))
   2678        return primitiveValueCache()->createIdentifierValue(id);
   2679     return parseColor();
   2680 }
   2681 
   2682 bool CSSParser::parseFillImage(RefPtr<CSSValue>& value)
   2683 {
   2684     if (m_valueList->current()->id == CSSValueNone) {
   2685         value = CSSImageValue::create();
   2686         return true;
   2687     }
   2688     if (m_valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
   2689         // FIXME: The completeURL call should be done when using the CSSImageValue,
   2690         // not when creating it.
   2691         if (m_styleSheet)
   2692             value = CSSImageValue::create(m_styleSheet->completeURL(m_valueList->current()->string));
   2693         return true;
   2694     }
   2695 
   2696     if (isGeneratedImageValue(m_valueList->current()))
   2697         return parseGeneratedImage(value);
   2698 
   2699     return false;
   2700 }
   2701 
   2702 PassRefPtr<CSSValue> CSSParser::parseFillPositionX(CSSParserValueList* valueList)
   2703 {
   2704     int id = valueList->current()->id;
   2705     if (id == CSSValueLeft || id == CSSValueRight || id == CSSValueCenter) {
   2706         int percent = 0;
   2707         if (id == CSSValueRight)
   2708             percent = 100;
   2709         else if (id == CSSValueCenter)
   2710             percent = 50;
   2711         return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
   2712     }
   2713     if (validUnit(valueList->current(), FPercent | FLength, m_strict))
   2714         return primitiveValueCache()->createValue(valueList->current()->fValue,
   2715                                                   (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
   2716     return 0;
   2717 }
   2718 
   2719 PassRefPtr<CSSValue> CSSParser::parseFillPositionY(CSSParserValueList* valueList)
   2720 {
   2721     int id = valueList->current()->id;
   2722     if (id == CSSValueTop || id == CSSValueBottom || id == CSSValueCenter) {
   2723         int percent = 0;
   2724         if (id == CSSValueBottom)
   2725             percent = 100;
   2726         else if (id == CSSValueCenter)
   2727             percent = 50;
   2728         return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
   2729     }
   2730     if (validUnit(valueList->current(), FPercent | FLength, m_strict))
   2731         return primitiveValueCache()->createValue(valueList->current()->fValue,
   2732                                                   (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
   2733     return 0;
   2734 }
   2735 
   2736 PassRefPtr<CSSValue> CSSParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag)
   2737 {
   2738     int id = valueList->current()->id;
   2739     if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
   2740         int percent = 0;
   2741         if (id == CSSValueLeft || id == CSSValueRight) {
   2742             if (cumulativeFlags & XFillPosition)
   2743                 return 0;
   2744             cumulativeFlags |= XFillPosition;
   2745             individualFlag = XFillPosition;
   2746             if (id == CSSValueRight)
   2747                 percent = 100;
   2748         }
   2749         else if (id == CSSValueTop || id == CSSValueBottom) {
   2750             if (cumulativeFlags & YFillPosition)
   2751                 return 0;
   2752             cumulativeFlags |= YFillPosition;
   2753             individualFlag = YFillPosition;
   2754             if (id == CSSValueBottom)
   2755                 percent = 100;
   2756         } else if (id == CSSValueCenter) {
   2757             // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
   2758             percent = 50;
   2759             cumulativeFlags |= AmbiguousFillPosition;
   2760             individualFlag = AmbiguousFillPosition;
   2761         }
   2762         return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
   2763     }
   2764     if (validUnit(valueList->current(), FPercent | FLength, m_strict)) {
   2765         if (!cumulativeFlags) {
   2766             cumulativeFlags |= XFillPosition;
   2767             individualFlag = XFillPosition;
   2768         } else if (cumulativeFlags & (XFillPosition | AmbiguousFillPosition)) {
   2769             cumulativeFlags |= YFillPosition;
   2770             individualFlag = YFillPosition;
   2771         } else
   2772             return 0;
   2773         return primitiveValueCache()->createValue(valueList->current()->fValue,
   2774                                                   (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
   2775     }
   2776     return 0;
   2777 }
   2778 
   2779 void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
   2780 {
   2781     CSSParserValue* value = valueList->current();
   2782 
   2783     // Parse the first value.  We're just making sure that it is one of the valid keywords or a percentage/length.
   2784     unsigned cumulativeFlags = 0;
   2785     FillPositionFlag value1Flag = InvalidFillPosition;
   2786     FillPositionFlag value2Flag = InvalidFillPosition;
   2787     value1 = parseFillPositionComponent(valueList, cumulativeFlags, value1Flag);
   2788     if (!value1)
   2789         return;
   2790 
   2791     // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
   2792     // can assume that any other values belong to the rest of the shorthand).  If we're not parsing a shorthand, though, the
   2793     // value was explicitly specified for our property.
   2794     value = valueList->next();
   2795 
   2796     // First check for the comma.  If so, we are finished parsing this value or value pair.
   2797     if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
   2798         value = 0;
   2799 
   2800     if (value) {
   2801         value2 = parseFillPositionComponent(valueList, cumulativeFlags, value2Flag);
   2802         if (value2)
   2803             valueList->next();
   2804         else {
   2805             if (!inShorthand()) {
   2806                 value1.clear();
   2807                 return;
   2808             }
   2809         }
   2810     }
   2811 
   2812     if (!value2)
   2813         // Only one value was specified.  If that value was not a keyword, then it sets the x position, and the y position
   2814         // is simply 50%.  This is our default.
   2815         // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
   2816         // For left/right/center, the default of 50% in the y is still correct.
   2817         value2 = primitiveValueCache()->createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
   2818 
   2819     if (value1Flag == YFillPosition || value2Flag == XFillPosition)
   2820         value1.swap(value2);
   2821 }
   2822 
   2823 void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
   2824 {
   2825     CSSParserValue* value = m_valueList->current();
   2826 
   2827     int id = m_valueList->current()->id;
   2828     if (id == CSSValueRepeatX) {
   2829         m_implicitShorthand = true;
   2830         value1 = primitiveValueCache()->createIdentifierValue(CSSValueRepeat);
   2831         value2 = primitiveValueCache()->createIdentifierValue(CSSValueNoRepeat);
   2832         m_valueList->next();
   2833         return;
   2834     }
   2835     if (id == CSSValueRepeatY) {
   2836         m_implicitShorthand = true;
   2837         value1 = primitiveValueCache()->createIdentifierValue(CSSValueNoRepeat);
   2838         value2 = primitiveValueCache()->createIdentifierValue(CSSValueRepeat);
   2839         m_valueList->next();
   2840         return;
   2841     }
   2842     if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)
   2843         value1 = primitiveValueCache()->createIdentifierValue(id);
   2844     else {
   2845         value1 = 0;
   2846         return;
   2847     }
   2848 
   2849     value = m_valueList->next();
   2850 
   2851     // First check for the comma.  If so, we are finished parsing this value or value pair.
   2852     if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
   2853         value = 0;
   2854 
   2855     if (value)
   2856         id = m_valueList->current()->id;
   2857 
   2858     if (value && (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)) {
   2859         value2 = primitiveValueCache()->createIdentifierValue(id);
   2860         m_valueList->next();
   2861     } else {
   2862         // If only one value was specified, value2 is the same as value1.
   2863         m_implicitShorthand = true;
   2864         value2 = primitiveValueCache()->createIdentifierValue(static_cast<CSSPrimitiveValue*>(value1.get())->getIdent());
   2865     }
   2866 }
   2867 
   2868 PassRefPtr<CSSValue> CSSParser::parseFillSize(int propId, bool& allowComma)
   2869 {
   2870     allowComma = true;
   2871     CSSParserValue* value = m_valueList->current();
   2872 
   2873     if (value->id == CSSValueContain || value->id == CSSValueCover)
   2874         return primitiveValueCache()->createIdentifierValue(value->id);
   2875 
   2876     RefPtr<CSSPrimitiveValue> parsedValue1;
   2877 
   2878     if (value->id == CSSValueAuto)
   2879         parsedValue1 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN);
   2880     else {
   2881         if (!validUnit(value, FLength | FPercent, m_strict))
   2882             return 0;
   2883         parsedValue1 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
   2884     }
   2885 
   2886     CSSPropertyID property = static_cast<CSSPropertyID>(propId);
   2887     RefPtr<CSSPrimitiveValue> parsedValue2;
   2888     if ((value = m_valueList->next())) {
   2889         if (value->id == CSSValueAuto)
   2890             parsedValue2 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN);
   2891         else if (value->unit == CSSParserValue::Operator && value->iValue == ',')
   2892             allowComma = false;
   2893         else {
   2894             if (!validUnit(value, FLength | FPercent, m_strict))
   2895                 return 0;
   2896             parsedValue2 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
   2897         }
   2898     }
   2899     if (!parsedValue2) {
   2900         if (property == CSSPropertyWebkitBackgroundSize || property == CSSPropertyWebkitMaskSize)
   2901             parsedValue2 = parsedValue1;
   2902         else
   2903             parsedValue2 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN);
   2904     }
   2905 
   2906     return primitiveValueCache()->createValue(Pair::create(parsedValue1.release(), parsedValue2.release()));
   2907 }
   2908 
   2909 bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2,
   2910                                   RefPtr<CSSValue>& retValue1, RefPtr<CSSValue>& retValue2)
   2911 {
   2912     RefPtr<CSSValueList> values;
   2913     RefPtr<CSSValueList> values2;
   2914     CSSParserValue* val;
   2915     RefPtr<CSSValue> value;
   2916     RefPtr<CSSValue> value2;
   2917 
   2918     bool allowComma = false;
   2919 
   2920     retValue1 = retValue2 = 0;
   2921     propId1 = propId;
   2922     propId2 = propId;
   2923     if (propId == CSSPropertyBackgroundPosition) {
   2924         propId1 = CSSPropertyBackgroundPositionX;
   2925         propId2 = CSSPropertyBackgroundPositionY;
   2926     } else if (propId == CSSPropertyWebkitMaskPosition) {
   2927         propId1 = CSSPropertyWebkitMaskPositionX;
   2928         propId2 = CSSPropertyWebkitMaskPositionY;
   2929     } else if (propId == CSSPropertyBackgroundRepeat) {
   2930         propId1 = CSSPropertyBackgroundRepeatX;
   2931         propId2 = CSSPropertyBackgroundRepeatY;
   2932     } else if (propId == CSSPropertyWebkitMaskRepeat) {
   2933         propId1 = CSSPropertyWebkitMaskRepeatX;
   2934         propId2 = CSSPropertyWebkitMaskRepeatY;
   2935     }
   2936 
   2937     while ((val = m_valueList->current())) {
   2938         RefPtr<CSSValue> currValue;
   2939         RefPtr<CSSValue> currValue2;
   2940 
   2941         if (allowComma) {
   2942             if (val->unit != CSSParserValue::Operator || val->iValue != ',')
   2943                 return false;
   2944             m_valueList->next();
   2945             allowComma = false;
   2946         } else {
   2947             allowComma = true;
   2948             switch (propId) {
   2949                 case CSSPropertyBackgroundColor:
   2950                     currValue = parseBackgroundColor();
   2951                     if (currValue)
   2952                         m_valueList->next();
   2953                     break;
   2954                 case CSSPropertyBackgroundAttachment:
   2955                 case CSSPropertyWebkitMaskAttachment:
   2956                     if (val->id == CSSValueScroll || val->id == CSSValueFixed || val->id == CSSValueLocal) {
   2957                         currValue = primitiveValueCache()->createIdentifierValue(val->id);
   2958                         m_valueList->next();
   2959                     }
   2960                     break;
   2961                 case CSSPropertyBackgroundImage:
   2962                 case CSSPropertyWebkitMaskImage:
   2963                     if (parseFillImage(currValue))
   2964                         m_valueList->next();
   2965                     break;
   2966                 case CSSPropertyWebkitBackgroundClip:
   2967                 case CSSPropertyWebkitBackgroundOrigin:
   2968                 case CSSPropertyWebkitMaskClip:
   2969                 case CSSPropertyWebkitMaskOrigin:
   2970                     // The first three values here are deprecated and do not apply to the version of the property that has
   2971                     // the -webkit- prefix removed.
   2972                     if (val->id == CSSValueBorder || val->id == CSSValuePadding || val->id == CSSValueContent ||
   2973                         val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox ||
   2974                         ((propId == CSSPropertyWebkitBackgroundClip || propId == CSSPropertyWebkitMaskClip) &&
   2975                          (val->id == CSSValueText || val->id == CSSValueWebkitText))) {
   2976                         currValue = primitiveValueCache()->createIdentifierValue(val->id);
   2977                         m_valueList->next();
   2978                     }
   2979                     break;
   2980                 case CSSPropertyBackgroundClip:
   2981                     if (parseBackgroundClip(val, currValue, primitiveValueCache()))
   2982                         m_valueList->next();
   2983                     break;
   2984                 case CSSPropertyBackgroundOrigin:
   2985                     if (val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox) {
   2986                         currValue = primitiveValueCache()->createIdentifierValue(val->id);
   2987                         m_valueList->next();
   2988                     }
   2989                     break;
   2990                 case CSSPropertyBackgroundPosition:
   2991                 case CSSPropertyWebkitMaskPosition:
   2992                     parseFillPosition(m_valueList, currValue, currValue2);
   2993                     // parseFillPosition advances the m_valueList pointer
   2994                     break;
   2995                 case CSSPropertyBackgroundPositionX:
   2996                 case CSSPropertyWebkitMaskPositionX: {
   2997                     currValue = parseFillPositionX(m_valueList);
   2998                     if (currValue)
   2999                         m_valueList->next();
   3000                     break;
   3001                 }
   3002                 case CSSPropertyBackgroundPositionY:
   3003                 case CSSPropertyWebkitMaskPositionY: {
   3004                     currValue = parseFillPositionY(m_valueList);
   3005                     if (currValue)
   3006                         m_valueList->next();
   3007                     break;
   3008                 }
   3009                 case CSSPropertyWebkitBackgroundComposite:
   3010                 case CSSPropertyWebkitMaskComposite:
   3011                     if ((val->id >= CSSValueClear && val->id <= CSSValuePlusLighter) || val->id == CSSValueHighlight) {
   3012                         currValue = primitiveValueCache()->createIdentifierValue(val->id);
   3013                         m_valueList->next();
   3014                     }
   3015                     break;
   3016                 case CSSPropertyBackgroundRepeat:
   3017                 case CSSPropertyWebkitMaskRepeat:
   3018                     parseFillRepeat(currValue, currValue2);
   3019                     // parseFillRepeat advances the m_valueList pointer
   3020                     break;
   3021                 case CSSPropertyBackgroundSize:
   3022                 case CSSPropertyWebkitBackgroundSize:
   3023                 case CSSPropertyWebkitMaskSize: {
   3024                     currValue = parseFillSize(propId, allowComma);
   3025                     if (currValue)
   3026                         m_valueList->next();
   3027                     break;
   3028                 }
   3029             }
   3030             if (!currValue)
   3031                 return false;
   3032 
   3033             if (value && !values) {
   3034                 values = CSSValueList::createCommaSeparated();
   3035                 values->append(value.release());
   3036             }
   3037 
   3038             if (value2 && !values2) {
   3039                 values2 = CSSValueList::createCommaSeparated();
   3040                 values2->append(value2.release());
   3041             }
   3042 
   3043             if (values)
   3044                 values->append(currValue.release());
   3045             else
   3046                 value = currValue.release();
   3047             if (currValue2) {
   3048                 if (values2)
   3049                     values2->append(currValue2.release());
   3050                 else
   3051                     value2 = currValue2.release();
   3052             }
   3053         }
   3054 
   3055         // When parsing any fill shorthand property, we let it handle building up the lists for all
   3056         // properties.
   3057         if (inShorthand())
   3058             break;
   3059     }
   3060 
   3061     if (values && values->length()) {
   3062         retValue1 = values.release();
   3063         if (values2 && values2->length())
   3064             retValue2 = values2.release();
   3065         return true;
   3066     }
   3067     if (value) {
   3068         retValue1 = value.release();
   3069         retValue2 = value2.release();
   3070         return true;
   3071     }
   3072     return false;
   3073 }
   3074 
   3075 PassRefPtr<CSSValue> CSSParser::parseAnimationDelay()
   3076 {
   3077     CSSParserValue* value = m_valueList->current();
   3078     if (validUnit(value, FTime, m_strict))
   3079         return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
   3080     return 0;
   3081 }
   3082 
   3083 PassRefPtr<CSSValue> CSSParser::parseAnimationDirection()
   3084 {
   3085     CSSParserValue* value = m_valueList->current();
   3086     if (value->id == CSSValueNormal || value->id == CSSValueAlternate)
   3087         return primitiveValueCache()->createIdentifierValue(value->id);
   3088     return 0;
   3089 }
   3090 
   3091 PassRefPtr<CSSValue> CSSParser::parseAnimationDuration()
   3092 {
   3093     CSSParserValue* value = m_valueList->current();
   3094     if (validUnit(value, FTime | FNonNeg, m_strict))
   3095         return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
   3096     return 0;
   3097 }
   3098 
   3099 PassRefPtr<CSSValue> CSSParser::parseAnimationFillMode()
   3100 {
   3101     CSSParserValue* value = m_valueList->current();
   3102     if (value->id == CSSValueNone || value->id == CSSValueForwards || value->id == CSSValueBackwards || value->id == CSSValueBoth)
   3103         return primitiveValueCache()->createIdentifierValue(value->id);
   3104     return 0;
   3105 }
   3106 
   3107 PassRefPtr<CSSValue> CSSParser::parseAnimationIterationCount()
   3108 {
   3109     CSSParserValue* value = m_valueList->current();
   3110     if (value->id == CSSValueInfinite)
   3111         return primitiveValueCache()->createIdentifierValue(value->id);
   3112     if (validUnit(value, FInteger | FNonNeg, m_strict))
   3113         return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
   3114     return 0;
   3115 }
   3116 
   3117 PassRefPtr<CSSValue> CSSParser::parseAnimationName()
   3118 {
   3119     CSSParserValue* value = m_valueList->current();
   3120     if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT) {
   3121         if (value->id == CSSValueNone || (value->unit == CSSPrimitiveValue::CSS_STRING && equalIgnoringCase(value->string, "none"))) {
   3122             return primitiveValueCache()->createIdentifierValue(CSSValueNone);
   3123         } else {
   3124             return primitiveValueCache()->createValue(value->string, CSSPrimitiveValue::CSS_STRING);
   3125         }
   3126     }
   3127     return 0;
   3128 }
   3129 
   3130 PassRefPtr<CSSValue> CSSParser::parseAnimationPlayState()
   3131 {
   3132     CSSParserValue* value = m_valueList->current();
   3133     if (value->id == CSSValueRunning || value->id == CSSValuePaused)
   3134         return primitiveValueCache()->createIdentifierValue(value->id);
   3135     return 0;
   3136 }
   3137 
   3138 PassRefPtr<CSSValue> CSSParser::parseAnimationProperty()
   3139 {
   3140     CSSParserValue* value = m_valueList->current();
   3141     if (value->unit != CSSPrimitiveValue::CSS_IDENT)
   3142         return 0;
   3143     int result = cssPropertyID(value->string);
   3144     if (result)
   3145         return primitiveValueCache()->createIdentifierValue(result);
   3146     if (equalIgnoringCase(value->string, "all"))
   3147         return primitiveValueCache()->createIdentifierValue(CSSValueAll);
   3148     if (equalIgnoringCase(value->string, "none"))
   3149         return primitiveValueCache()->createIdentifierValue(CSSValueNone);
   3150     return 0;
   3151 }
   3152 
   3153 bool CSSParser::parseTransformOriginShorthand(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3)
   3154 {
   3155     parseFillPosition(m_valueList, value1, value2);
   3156 
   3157     // now get z
   3158     if (m_valueList->current()) {
   3159         if (validUnit(m_valueList->current(), FLength, m_strict)) {
   3160             value3 = primitiveValueCache()->createValue(m_valueList->current()->fValue,
   3161                                              (CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit);
   3162             m_valueList->next();
   3163             return true;
   3164         }
   3165         return false;
   3166     }
   3167     return true;
   3168 }
   3169 
   3170 bool CSSParser::parseCubicBezierTimingFunctionValue(CSSParserValueList*& args, double& result)
   3171 {
   3172     CSSParserValue* v = args->current();
   3173     if (!validUnit(v, FNumber, m_strict))
   3174         return false;
   3175     result = v->fValue;
   3176     if (result < 0 || result > 1.0)
   3177         return false;
   3178     v = args->next();
   3179     if (!v)
   3180         // The last number in the function has no comma after it, so we're done.
   3181         return true;
   3182     if (v->unit != CSSParserValue::Operator && v->iValue != ',')
   3183         return false;
   3184     v = args->next();
   3185     return true;
   3186 }
   3187 
   3188 PassRefPtr<CSSValue> CSSParser::parseAnimationTimingFunction()
   3189 {
   3190     CSSParserValue* value = m_valueList->current();
   3191     if (value->id == CSSValueEase || value->id == CSSValueLinear || value->id == CSSValueEaseIn || value->id == CSSValueEaseOut
   3192         || value->id == CSSValueEaseInOut || value->id == CSSValueStepStart || value->id == CSSValueStepEnd)
   3193         return primitiveValueCache()->createIdentifierValue(value->id);
   3194 
   3195     // We must be a function.
   3196     if (value->unit != CSSParserValue::Function)
   3197         return 0;
   3198 
   3199     CSSParserValueList* args = value->function->args.get();
   3200 
   3201     if (equalIgnoringCase(value->function->name, "steps(")) {
   3202         // For steps, 1 or 2 params must be specified (comma-separated)
   3203         if (!args || (args->size() != 1 && args->size() != 3))
   3204             return 0;
   3205 
   3206         // There are two values.
   3207         int numSteps;
   3208         bool stepAtStart = false;
   3209 
   3210         CSSParserValue* v = args->current();
   3211         if (!validUnit(v, FInteger, m_strict))
   3212             return 0;
   3213         numSteps = (int) min(v->fValue, (double)INT_MAX);
   3214         if (numSteps < 1)
   3215             return 0;
   3216         v = args->next();
   3217 
   3218         if (v) {
   3219             // There is a comma so we need to parse the second value
   3220             if (v->unit != CSSParserValue::Operator && v->iValue != ',')
   3221                 return 0;
   3222             v = args->next();
   3223             if (v->id != CSSValueStart && v->id != CSSValueEnd)
   3224                 return 0;
   3225             stepAtStart = v->id == CSSValueStart;
   3226         }
   3227 
   3228         return CSSStepsTimingFunctionValue::create(numSteps, stepAtStart);
   3229     }
   3230 
   3231     if (equalIgnoringCase(value->function->name, "cubic-bezier(")) {
   3232         // For cubic bezier, 4 values must be specified.
   3233         if (!args || args->size() != 7)
   3234             return 0;
   3235 
   3236         // There are two points specified.  The values must be between 0 and 1.
   3237         double x1, y1, x2, y2;
   3238 
   3239         if (!parseCubicBezierTimingFunctionValue(args, x1))
   3240             return 0;
   3241         if (!parseCubicBezierTimingFunctionValue(args, y1))
   3242             return 0;
   3243         if (!parseCubicBezierTimingFunctionValue(args, x2))
   3244             return 0;
   3245         if (!parseCubicBezierTimingFunctionValue(args, y2))
   3246             return 0;
   3247 
   3248         return CSSCubicBezierTimingFunctionValue::create(x1, y1, x2, y2);
   3249     }
   3250 
   3251     return 0;
   3252 }
   3253 
   3254 bool CSSParser::parseAnimationProperty(int propId, RefPtr<CSSValue>& result)
   3255 {
   3256     RefPtr<CSSValueList> values;
   3257     CSSParserValue* val;
   3258     RefPtr<CSSValue> value;
   3259     bool allowComma = false;
   3260 
   3261     result = 0;
   3262 
   3263     while ((val = m_valueList->current())) {
   3264         RefPtr<CSSValue> currValue;
   3265         if (allowComma) {
   3266             if (val->unit != CSSParserValue::Operator || val->iValue != ',')
   3267                 return false;
   3268             m_valueList->next();
   3269             allowComma = false;
   3270         }
   3271         else {
   3272             switch (propId) {
   3273                 case CSSPropertyWebkitAnimationDelay:
   3274                 case CSSPropertyWebkitTransitionDelay:
   3275                     currValue = parseAnimationDelay();
   3276                     if (currValue)
   3277                         m_valueList->next();
   3278                     break;
   3279                 case CSSPropertyWebkitAnimationDirection:
   3280                     currValue = parseAnimationDirection();
   3281                     if (currValue)
   3282                         m_valueList->next();
   3283                     break;
   3284                 case CSSPropertyWebkitAnimationDuration:
   3285                 case CSSPropertyWebkitTransitionDuration:
   3286                     currValue = parseAnimationDuration();
   3287                     if (currValue)
   3288                         m_valueList->next();
   3289                     break;
   3290                 case CSSPropertyWebkitAnimationFillMode:
   3291                     currValue = parseAnimationFillMode();
   3292                     if (currValue)
   3293                         m_valueList->next();
   3294                     break;
   3295                 case CSSPropertyWebkitAnimationIterationCount:
   3296                     currValue = parseAnimationIterationCount();
   3297                     if (currValue)
   3298                         m_valueList->next();
   3299                     break;
   3300                 case CSSPropertyWebkitAnimationName:
   3301                     currValue = parseAnimationName();
   3302                     if (currValue)
   3303                         m_valueList->next();
   3304                     break;
   3305                 case CSSPropertyWebkitAnimationPlayState:
   3306                     currValue = parseAnimationPlayState();
   3307                     if (currValue)
   3308                         m_valueList->next();
   3309                     break;
   3310                 case CSSPropertyWebkitTransitionProperty:
   3311                     currValue = parseAnimationProperty();
   3312                     if (currValue)
   3313                         m_valueList->next();
   3314                     break;
   3315                 case CSSPropertyWebkitAnimationTimingFunction:
   3316                 case CSSPropertyWebkitTransitionTimingFunction:
   3317                     currValue = parseAnimationTimingFunction();
   3318                     if (currValue)
   3319                         m_valueList->next();
   3320                     break;
   3321             }
   3322 
   3323             if (!currValue)
   3324                 return false;
   3325 
   3326             if (value && !values) {
   3327                 values = CSSValueList::createCommaSeparated();
   3328                 values->append(value.release());
   3329             }
   3330 
   3331             if (values)
   3332                 values->append(currValue.release());
   3333             else
   3334                 value = currValue.release();
   3335 
   3336             allowComma = true;
   3337         }
   3338 
   3339         // When parsing the 'transition' shorthand property, we let it handle building up the lists for all
   3340         // properties.
   3341         if (inShorthand())
   3342             break;
   3343     }
   3344 
   3345     if (values && values->length()) {
   3346         result = values.release();
   3347         return true;
   3348     }
   3349     if (value) {
   3350         result = value.release();
   3351         return true;
   3352     }
   3353     return false;
   3354 }
   3355 
   3356 
   3357 
   3358 #if ENABLE(DASHBOARD_SUPPORT)
   3359 
   3360 #define DASHBOARD_REGION_NUM_PARAMETERS  6
   3361 #define DASHBOARD_REGION_SHORT_NUM_PARAMETERS  2
   3362 
   3363 static CSSParserValue* skipCommaInDashboardRegion(CSSParserValueList *args)
   3364 {
   3365     if (args->size() == (DASHBOARD_REGION_NUM_PARAMETERS*2-1) ||
   3366          args->size() == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
   3367         CSSParserValue* current = args->current();
   3368         if (current->unit == CSSParserValue::Operator && current->iValue == ',')
   3369             return args->next();
   3370     }
   3371     return args->current();
   3372 }
   3373 
   3374 bool CSSParser::parseDashboardRegions(int propId, bool important)
   3375 {
   3376     bool valid = true;
   3377 
   3378     CSSParserValue* value = m_valueList->current();
   3379 
   3380     if (value->id == CSSValueNone) {
   3381         if (m_valueList->next())
   3382             return false;
   3383         addProperty(propId, primitiveValueCache()->createIdentifierValue(value->id), important);
   3384         return valid;
   3385     }
   3386 
   3387     RefPtr<DashboardRegion> firstRegion = DashboardRegion::create();
   3388     DashboardRegion* region = 0;
   3389 
   3390     while (value) {
   3391         if (region == 0) {
   3392             region = firstRegion.get();
   3393         } else {
   3394             RefPtr<DashboardRegion> nextRegion = DashboardRegion::create();
   3395             region->m_next = nextRegion;
   3396             region = nextRegion.get();
   3397         }
   3398 
   3399         if (value->unit != CSSParserValue::Function) {
   3400             valid = false;
   3401             break;
   3402         }
   3403 
   3404         // Commas count as values, so allow:
   3405         // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
   3406         // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
   3407         // also allow
   3408         // dashboard-region(label, type) or dashboard-region(label type)
   3409         // dashboard-region(label, type) or dashboard-region(label type)
   3410         CSSParserValueList* args = value->function->args.get();
   3411         if (!equalIgnoringCase(value->function->name, "dashboard-region(") || !args) {
   3412             valid = false;
   3413             break;
   3414         }
   3415 
   3416         int numArgs = args->size();
   3417         if ((numArgs != DASHBOARD_REGION_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_NUM_PARAMETERS*2-1)) &&
   3418             (numArgs != DASHBOARD_REGION_SHORT_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1))) {
   3419             valid = false;
   3420             break;
   3421         }
   3422 
   3423         // First arg is a label.
   3424         CSSParserValue* arg = args->current();
   3425         if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
   3426             valid = false;
   3427             break;
   3428         }
   3429 
   3430         region->m_label = arg->string;
   3431 
   3432         // Second arg is a type.
   3433         arg = args->next();
   3434         arg = skipCommaInDashboardRegion(args);
   3435         if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
   3436             valid = false;
   3437             break;
   3438         }
   3439 
   3440         if (equalIgnoringCase(arg->string, "circle"))
   3441             region->m_isCircle = true;
   3442         else if (equalIgnoringCase(arg->string, "rectangle"))
   3443             region->m_isRectangle = true;
   3444         else {
   3445             valid = false;
   3446             break;
   3447         }
   3448 
   3449         region->m_geometryType = arg->string;
   3450 
   3451         if (numArgs == DASHBOARD_REGION_SHORT_NUM_PARAMETERS || numArgs == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
   3452             // This originally used CSSValueInvalid by accident. It might be more logical to use something else.
   3453             RefPtr<CSSPrimitiveValue> amount = primitiveValueCache()->createIdentifierValue(CSSValueInvalid);
   3454 
   3455             region->setTop(amount);
   3456             region->setRight(amount);
   3457             region->setBottom(amount);
   3458             region->setLeft(amount);
   3459         } else {
   3460             // Next four arguments must be offset numbers
   3461             int i;
   3462             for (i = 0; i < 4; i++) {
   3463                 arg = args->next();
   3464                 arg = skipCommaInDashboardRegion(args);
   3465 
   3466                 valid = arg->id == CSSValueAuto || validUnit(arg, FLength, m_strict);
   3467                 if (!valid)
   3468                     break;
   3469 
   3470                 RefPtr<CSSPrimitiveValue> amount = arg->id == CSSValueAuto ?
   3471                     primitiveValueCache()->createIdentifierValue(CSSValueAuto) :
   3472                     primitiveValueCache()->createValue(arg->fValue, (CSSPrimitiveValue::UnitTypes) arg->unit);
   3473 
   3474                 if (i == 0)
   3475                     region->setTop(amount);
   3476                 else if (i == 1)
   3477                     region->setRight(amount);
   3478                 else if (i == 2)
   3479                     region->setBottom(amount);
   3480                 else
   3481                     region->setLeft(amount);
   3482             }
   3483         }
   3484 
   3485         if (args->next())
   3486             return false;
   3487 
   3488         value = m_valueList->next();
   3489     }
   3490 
   3491     if (valid)
   3492         addProperty(propId, primitiveValueCache()->createValue(firstRegion.release()), important);
   3493 
   3494     return valid;
   3495 }
   3496 
   3497 #endif /* ENABLE(DASHBOARD_SUPPORT) */
   3498 
   3499 PassRefPtr<CSSValue> CSSParser::parseCounterContent(CSSParserValueList* args, bool counters)
   3500 {
   3501     unsigned numArgs = args->size();
   3502     if (counters && numArgs != 3 && numArgs != 5)
   3503         return 0;
   3504     if (!counters && numArgs != 1 && numArgs != 3)
   3505         return 0;
   3506 
   3507     CSSParserValue* i = args->current();
   3508     if (i->unit != CSSPrimitiveValue::CSS_IDENT)
   3509         return 0;
   3510     RefPtr<CSSPrimitiveValue> identifier = primitiveValueCache()->createValue(i->string, CSSPrimitiveValue::CSS_STRING);
   3511 
   3512     RefPtr<CSSPrimitiveValue> separator;
   3513     if (!counters)
   3514         separator = primitiveValueCache()->createValue(String(), CSSPrimitiveValue::CSS_STRING);
   3515     else {
   3516         i = args->next();
   3517         if (i->unit != CSSParserValue::Operator || i->iValue != ',')
   3518             return 0;
   3519 
   3520         i = args->next();
   3521         if (i->unit != CSSPrimitiveValue::CSS_STRING)
   3522             return 0;
   3523 
   3524         separator = primitiveValueCache()->createValue(i->string, (CSSPrimitiveValue::UnitTypes) i->unit);
   3525     }
   3526 
   3527     RefPtr<CSSPrimitiveValue> listStyle;
   3528     i = args->next();
   3529     if (!i) // Make the list style default decimal
   3530         listStyle = primitiveValueCache()->createValue(CSSValueDecimal - CSSValueDisc, CSSPrimitiveValue::CSS_NUMBER);
   3531     else {
   3532         if (i->unit != CSSParserValue::Operator || i->iValue != ',')
   3533             return 0;
   3534 
   3535         i = args->next();
   3536         if (i->unit != CSSPrimitiveValue::CSS_IDENT)
   3537             return 0;
   3538 
   3539         short ls = 0;
   3540         if (i->id == CSSValueNone)
   3541             ls = CSSValueKatakanaIroha - CSSValueDisc + 1;
   3542         else if (i->id >= CSSValueDisc && i->id <= CSSValueKatakanaIroha)
   3543             ls = i->id - CSSValueDisc;
   3544         else
   3545             return 0;
   3546 
   3547         listStyle = primitiveValueCache()->createValue(ls, (CSSPrimitiveValue::UnitTypes) i->unit);
   3548     }
   3549 
   3550     return primitiveValueCache()->createValue(Counter::create(identifier.release(), listStyle.release(), separator.release()));
   3551 }
   3552 
   3553 bool CSSParser::parseShape(int propId, bool important)
   3554 {
   3555     CSSParserValue* value = m_valueList->current();
   3556     CSSParserValueList* args = value->function->args.get();
   3557 
   3558     if (!equalIgnoringCase(value->function->name, "rect(") || !args)
   3559         return false;
   3560 
   3561     // rect(t, r, b, l) || rect(t r b l)
   3562     if (args->size() != 4 && args->size() != 7)
   3563         return false;
   3564     RefPtr<Rect> rect = Rect::create();
   3565     bool valid = true;
   3566     int i = 0;
   3567     CSSParserValue* a = args->current();
   3568     while (a) {
   3569         valid = a->id == CSSValueAuto || validUnit(a, FLength, m_strict);
   3570         if (!valid)
   3571             break;
   3572         RefPtr<CSSPrimitiveValue> length = a->id == CSSValueAuto ?
   3573             primitiveValueCache()->createIdentifierValue(CSSValueAuto) :
   3574             primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit);
   3575         if (i == 0)
   3576             rect->setTop(length);
   3577         else if (i == 1)
   3578             rect->setRight(length);
   3579         else if (i == 2)
   3580             rect->setBottom(length);
   3581         else
   3582             rect->setLeft(length);
   3583         a = args->next();
   3584         if (a && args->size() == 7) {
   3585             if (a->unit == CSSParserValue::Operator && a->iValue == ',') {
   3586                 a = args->next();
   3587             } else {
   3588                 valid = false;
   3589                 break;
   3590             }
   3591         }
   3592         i++;
   3593     }
   3594     if (valid) {
   3595         addProperty(propId, primitiveValueCache()->createValue(rect.release()), important);
   3596         m_valueList->next();
   3597         return true;
   3598     }
   3599     return false;
   3600 }
   3601 
   3602 // [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family'
   3603 bool CSSParser::parseFont(bool important)
   3604 {
   3605     bool valid = true;
   3606     CSSParserValue *value = m_valueList->current();
   3607     RefPtr<FontValue> font = FontValue::create();
   3608     // optional font-style, font-variant and font-weight
   3609     while (value) {
   3610         int id = value->id;
   3611         if (id) {
   3612             if (id == CSSValueNormal) {
   3613                 // do nothing, it's the inital value for all three
   3614             } else if (id == CSSValueItalic || id == CSSValueOblique) {
   3615                 if (font->style)
   3616                     return false;
   3617                 font->style = primitiveValueCache()->createIdentifierValue(id);
   3618             } else if (id == CSSValueSmallCaps) {
   3619                 if (font->variant)
   3620                     return false;
   3621                 font->variant = primitiveValueCache()->createIdentifierValue(id);
   3622             } else if (id >= CSSValueBold && id <= CSSValueLighter) {
   3623                 if (font->weight)
   3624                     return false;
   3625                 font->weight = primitiveValueCache()->createIdentifierValue(id);
   3626             } else {
   3627                 valid = false;
   3628             }
   3629         } else if (!font->weight && validUnit(value, FInteger | FNonNeg, true)) {
   3630             int weight = (int)value->fValue;
   3631             int val = 0;
   3632             if (weight == 100)
   3633                 val = CSSValue100;
   3634             else if (weight == 200)
   3635                 val = CSSValue200;
   3636             else if (weight == 300)
   3637                 val = CSSValue300;
   3638             else if (weight == 400)
   3639                 val = CSSValue400;
   3640             else if (weight == 500)
   3641                 val = CSSValue500;
   3642             else if (weight == 600)
   3643                 val = CSSValue600;
   3644             else if (weight == 700)
   3645                 val = CSSValue700;
   3646             else if (weight == 800)
   3647                 val = CSSValue800;
   3648             else if (weight == 900)
   3649                 val = CSSValue900;
   3650 
   3651             if (val)
   3652                 font->weight = primitiveValueCache()->createIdentifierValue(val);
   3653             else
   3654                 valid = false;
   3655         } else {
   3656             valid = false;
   3657         }
   3658         if (!valid)
   3659             break;
   3660         value = m_valueList->next();
   3661     }
   3662     if (!value)
   3663         return false;
   3664 
   3665     // set undefined values to default
   3666     if (!font->style)
   3667         font->style = primitiveValueCache()->createIdentifierValue(CSSValueNormal);
   3668     if (!font->variant)
   3669         font->variant = primitiveValueCache()->createIdentifierValue(CSSValueNormal);
   3670     if (!font->weight)
   3671         font->weight = primitiveValueCache()->createIdentifierValue(CSSValueNormal);
   3672 
   3673     // now a font size _must_ come
   3674     // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
   3675     if (value->id >= CSSValueXxSmall && value->id <= CSSValueLarger)
   3676         font->size = primitiveValueCache()->createIdentifierValue(value->id);
   3677     else if (validUnit(value, FLength | FPercent | FNonNeg, m_strict))
   3678         font->size = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
   3679     value = m_valueList->next();
   3680     if (!font->size || !value)
   3681         return false;
   3682 
   3683     if (value->unit == CSSParserValue::Operator && value->iValue == '/') {
   3684         // line-height
   3685         value = m_valueList->next();
   3686         if (!value)
   3687             return false;
   3688         if (value->id == CSSValueNormal) {
   3689             // default value, nothing to do
   3690         } else if (validUnit(value, FNumber | FLength | FPercent | FNonNeg, m_strict))
   3691             font->lineHeight = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
   3692         else
   3693             return false;
   3694         value = m_valueList->next();
   3695         if (!value)
   3696             return false;
   3697     }
   3698 
   3699     if (!font->lineHeight)
   3700         font->lineHeight = primitiveValueCache()->createIdentifierValue(CSSValueNormal);
   3701 
   3702     // font family must come now
   3703     font->family = parseFontFamily();
   3704 
   3705     if (m_valueList->current() || !font->family)
   3706         return false;
   3707 
   3708     addProperty(CSSPropertyFont, font.release(), important);
   3709     return true;
   3710 }
   3711 
   3712 PassRefPtr<CSSValueList> CSSParser::parseFontFamily()
   3713 {
   3714     RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
   3715     CSSParserValue* value = m_valueList->current();
   3716 
   3717     FontFamilyValue* currFamily = 0;
   3718     while (value) {
   3719         CSSParserValue* nextValue = m_valueList->next();
   3720         bool nextValBreaksFont = !nextValue ||
   3721                                  (nextValue->unit == CSSParserValue::Operator && nextValue->iValue == ',');
   3722         bool nextValIsFontName = nextValue &&
   3723             ((nextValue->id >= CSSValueSerif && nextValue->id <= CSSValueWebkitBody) ||
   3724             (nextValue->unit == CSSPrimitiveValue::CSS_STRING || nextValue->unit == CSSPrimitiveValue::CSS_IDENT));
   3725 
   3726         if (value->id >= CSSValueSerif && value->id <= CSSValueWebkitBody) {
   3727             if (currFamily)
   3728                 currFamily->appendSpaceSeparated(value->string.characters, value->string.length);
   3729             else if (nextValBreaksFont || !nextValIsFontName)
   3730                 list->append(primitiveValueCache()->createIdentifierValue(value->id));
   3731             else {
   3732                 RefPtr<FontFamilyValue> newFamily = FontFamilyValue::create(value->string);
   3733                 currFamily = newFamily.get();
   3734                 list->append(newFamily.release());
   3735             }
   3736         } else if (value->unit == CSSPrimitiveValue::CSS_STRING) {
   3737             // Strings never share in a family name.
   3738             currFamily = 0;
   3739             list->append(FontFamilyValue::create(value->string));
   3740         } else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
   3741             if (currFamily)
   3742                 currFamily->appendSpaceSeparated(value->string.characters, value->string.length);
   3743             else if (nextValBreaksFont || !nextValIsFontName)
   3744                 list->append(FontFamilyValue::create(value->string));
   3745             else {
   3746                 RefPtr<FontFamilyValue> newFamily = FontFamilyValue::create(value->string);
   3747                 currFamily = newFamily.get();
   3748                 list->append(newFamily.release());
   3749             }
   3750         } else {
   3751             break;
   3752         }
   3753 
   3754         if (!nextValue)
   3755             break;
   3756 
   3757         if (nextValBreaksFont) {
   3758             value = m_valueList->next();
   3759             currFamily = 0;
   3760         }
   3761         else if (nextValIsFontName)
   3762             value = nextValue;
   3763         else
   3764             break;
   3765     }
   3766     if (!list->length())
   3767         list = 0;
   3768     return list.release();
   3769 }
   3770 
   3771 bool CSSParser::parseFontStyle(bool important)
   3772 {
   3773     RefPtr<CSSValueList> values;
   3774     if (m_valueList->size() > 1)
   3775         values = CSSValueList::createCommaSeparated();
   3776     CSSParserValue* val;
   3777     bool expectComma = false;
   3778     while ((val = m_valueList->current())) {
   3779         RefPtr<CSSPrimitiveValue> parsedValue;
   3780         if (!expectComma) {
   3781             expectComma = true;
   3782             if (val->id == CSSValueNormal || val->id == CSSValueItalic || val->id == CSSValueOblique)
   3783                 parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
   3784             else if (val->id == CSSValueAll && !values) {
   3785                 // 'all' is only allowed in @font-face and with no other values. Make a value list to
   3786                 // indicate that we are in the @font-face case.
   3787                 values = CSSValueList::createCommaSeparated();
   3788                 parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
   3789             }
   3790         } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
   3791             expectComma = false;
   3792             m_valueList->next();
   3793             continue;
   3794         }
   3795 
   3796         if (!parsedValue)
   3797             return false;
   3798 
   3799         m_valueList->next();
   3800 
   3801         if (values)
   3802             values->append(parsedValue.release());
   3803         else {
   3804             addProperty(CSSPropertyFontStyle, parsedValue.release(), important);
   3805             return true;
   3806         }
   3807     }
   3808 
   3809     if (values && values->length()) {
   3810         m_hasFontFaceOnlyValues = true;
   3811         addProperty(CSSPropertyFontStyle, values.release(), important);
   3812         return true;
   3813     }
   3814 
   3815     return false;
   3816 }
   3817 
   3818 bool CSSParser::parseFontVariant(bool important)
   3819 {
   3820     RefPtr<CSSValueList> values;
   3821     if (m_valueList->size() > 1)
   3822         values = CSSValueList::createCommaSeparated();
   3823     CSSParserValue* val;
   3824     bool expectComma = false;
   3825     while ((val = m_valueList->current())) {
   3826         RefPtr<CSSPrimitiveValue> parsedValue;
   3827         if (!expectComma) {
   3828             expectComma = true;
   3829             if (val->id == CSSValueNormal || val->id == CSSValueSmallCaps)
   3830                 parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
   3831             else if (val->id == CSSValueAll && !values) {
   3832                 // 'all' is only allowed in @font-face and with no other values. Make a value list to
   3833                 // indicate that we are in the @font-face case.
   3834                 values = CSSValueList::createCommaSeparated();
   3835                 parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
   3836             }
   3837         } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
   3838             expectComma = false;
   3839             m_valueList->next();
   3840             continue;
   3841         }
   3842 
   3843         if (!parsedValue)
   3844             return false;
   3845 
   3846         m_valueList->next();
   3847 
   3848         if (values)
   3849             values->append(parsedValue.release());
   3850         else {
   3851             addProperty(CSSPropertyFontVariant, parsedValue.release(), important);
   3852             return true;
   3853         }
   3854     }
   3855 
   3856     if (values && values->length()) {
   3857         m_hasFontFaceOnlyValues = true;
   3858         addProperty(CSSPropertyFontVariant, values.release(), important);
   3859         return true;
   3860     }
   3861 
   3862     return false;
   3863 }
   3864 
   3865 bool CSSParser::parseFontWeight(bool important)
   3866 {
   3867     RefPtr<CSSValueList> values;
   3868     if (m_valueList->size() > 1)
   3869         values = CSSValueList::createCommaSeparated();
   3870     CSSParserValue* val;
   3871     bool expectComma = false;
   3872     while ((val = m_valueList->current())) {
   3873         RefPtr<CSSPrimitiveValue> parsedValue;
   3874         if (!expectComma) {
   3875             expectComma = true;
   3876             if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
   3877                 if (val->id >= CSSValueNormal && val->id <= CSSValue900)
   3878                     parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
   3879                 else if (val->id == CSSValueAll && !values) {
   3880                     // 'all' is only allowed in @font-face and with no other values. Make a value list to
   3881                     // indicate that we are in the @font-face case.
   3882                     values = CSSValueList::createCommaSeparated();
   3883                     parsedValue = primitiveValueCache()->createIdentifierValue(val->id);
   3884                 }
   3885             } else if (validUnit(val, FInteger | FNonNeg, false)) {
   3886                 int weight = static_cast<int>(val->fValue);
   3887                 if (!(weight % 100) && weight >= 100 && weight <= 900)
   3888                     parsedValue = primitiveValueCache()->createIdentifierValue(CSSValue100 + weight / 100 - 1);
   3889             }
   3890         } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
   3891             expectComma = false;
   3892             m_valueList->next();
   3893             continue;
   3894         }
   3895 
   3896         if (!parsedValue)
   3897             return false;
   3898 
   3899         m_valueList->next();
   3900 
   3901         if (values)
   3902             values->append(parsedValue.release());
   3903         else {
   3904             addProperty(CSSPropertyFontWeight, parsedValue.release(), important);
   3905             return true;
   3906         }
   3907     }
   3908 
   3909     if (values && values->length()) {
   3910         m_hasFontFaceOnlyValues = true;
   3911         addProperty(CSSPropertyFontWeight, values.release(), important);
   3912         return true;
   3913     }
   3914 
   3915     return false;
   3916 }
   3917 
   3918 static bool isValidFormatFunction(CSSParserValue* val)
   3919 {
   3920     CSSParserValueList* args = val->function->args.get();
   3921     return equalIgnoringCase(val->function->name, "format(") && (args->current()->unit == CSSPrimitiveValue::CSS_STRING || args->current()->unit == CSSPrimitiveValue::CSS_IDENT);
   3922 }
   3923 
   3924 bool CSSParser::parseFontFaceSrc()
   3925 {
   3926     RefPtr<CSSValueList> values(CSSValueList::createCommaSeparated());
   3927     CSSParserValue* val;
   3928     bool expectComma = false;
   3929     bool allowFormat = false;
   3930     bool failed = false;
   3931     RefPtr<CSSFontFaceSrcValue> uriValue;
   3932     while ((val = m_valueList->current())) {
   3933         RefPtr<CSSFontFaceSrcValue> parsedValue;
   3934         if (val->unit == CSSPrimitiveValue::CSS_URI && !expectComma && m_styleSheet) {
   3935             // FIXME: The completeURL call should be done when using the CSSFontFaceSrcValue,
   3936             // not when creating it.
   3937             parsedValue = CSSFontFaceSrcValue::create(m_styleSheet->completeURL(val->string));
   3938             uriValue = parsedValue;
   3939             allowFormat = true;
   3940             expectComma = true;
   3941         } else if (val->unit == CSSParserValue::Function) {
   3942             // There are two allowed functions: local() and format().
   3943             CSSParserValueList* args = val->function->args.get();
   3944             if (args && args->size() == 1) {
   3945                 if (equalIgnoringCase(val->function->name, "local(") && !expectComma && (args->current()->unit == CSSPrimitiveValue::CSS_STRING || args->current()->unit == CSSPrimitiveValue::CSS_IDENT)) {
   3946                     expectComma = true;
   3947                     allowFormat = false;
   3948                     CSSParserValue* a = args->current();
   3949                     uriValue.clear();
   3950                     parsedValue = CSSFontFaceSrcValue::createLocal(a->string);
   3951                 } else if (allowFormat && uriValue && isValidFormatFunction(val)) {
   3952                     expectComma = true;
   3953                     allowFormat = false;
   3954                     uriValue->setFormat(args->current()->string);
   3955                     uriValue.clear();
   3956                     m_valueList->next();
   3957                     continue;
   3958                 }
   3959             }
   3960         } else if (val->unit == CSSParserValue::Operator && val->iValue == ',' && expectComma) {
   3961             expectComma = false;
   3962             allowFormat = false;
   3963             uriValue.clear();
   3964             m_valueList->next();
   3965             continue;
   3966         }
   3967 
   3968         if (parsedValue)
   3969             values->append(parsedValue.release());
   3970         else {
   3971             failed = true;
   3972             break;
   3973         }
   3974         m_valueList->next();
   3975     }
   3976 
   3977     if (values->length() && !failed) {
   3978         addProperty(CSSPropertySrc, values.release(), m_important);
   3979         m_valueList->next();
   3980         return true;
   3981     }
   3982 
   3983     return false;
   3984 }
   3985 
   3986 bool CSSParser::parseFontFaceUnicodeRange()
   3987 {
   3988     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
   3989     bool failed = false;
   3990     bool operatorExpected = false;
   3991     for (; m_valueList->current(); m_valueList->next(), operatorExpected = !operatorExpected) {
   3992         if (operatorExpected) {
   3993             if (m_valueList->current()->unit == CSSParserValue::Operator && m_valueList->current()->iValue == ',')
   3994                 continue;
   3995             failed = true;
   3996             break;
   3997         }
   3998         if (m_valueList->current()->unit != CSSPrimitiveValue::CSS_UNICODE_RANGE) {
   3999             failed = true;
   4000             break;
   4001         }
   4002 
   4003         String rangeString = m_valueList->current()->string;
   4004         UChar32 from = 0;
   4005         UChar32 to = 0;
   4006         unsigned length = rangeString.length();
   4007 
   4008         if (length < 3) {
   4009             failed = true;
   4010             break;
   4011         }
   4012 
   4013         unsigned i = 2;
   4014         while (i < length) {
   4015             UChar c = rangeString[i];
   4016             if (c == '-' || c == '?')
   4017                 break;
   4018             from *= 16;
   4019             if (c >= '0' && c <= '9')
   4020                 from += c - '0';
   4021             else if (c >= 'A' && c <= 'F')
   4022                 from += 10 + c - 'A';
   4023             else if (c >= 'a' && c <= 'f')
   4024                 from += 10 + c - 'a';
   4025             else {
   4026                 failed = true;
   4027                 break;
   4028             }
   4029             i++;
   4030         }
   4031         if (failed)
   4032             break;
   4033 
   4034         if (i == length)
   4035             to = from;
   4036         else if (rangeString[i] == '?') {
   4037             unsigned span = 1;
   4038             while (i < length && rangeString[i] == '?') {
   4039                 span *= 16;
   4040                 from *= 16;
   4041                 i++;
   4042             }
   4043             if (i < length)
   4044                 failed = true;
   4045             to = from + span - 1;
   4046         } else {
   4047             if (length < i + 2) {
   4048                 failed = true;
   4049                 break;
   4050             }
   4051             i++;
   4052             while (i < length) {
   4053                 UChar c = rangeString[i];
   4054                 to *= 16;
   4055                 if (c >= '0' && c <= '9')
   4056                     to += c - '0';
   4057                 else if (c >= 'A' && c <= 'F')
   4058                     to += 10 + c - 'A';
   4059                 else if (c >= 'a' && c <= 'f')
   4060                     to += 10 + c - 'a';
   4061                 else {
   4062                     failed = true;
   4063                     break;
   4064                 }
   4065                 i++;
   4066             }
   4067             if (failed)
   4068                 break;
   4069         }
   4070         if (from <= to)
   4071             values->append(CSSUnicodeRangeValue::create(from, to));
   4072     }
   4073     if (failed || !values->length())
   4074         return false;
   4075     addProperty(CSSPropertyUnicodeRange, values.release(), m_important);
   4076     return true;
   4077 }
   4078 
   4079 // Returns the number of characters which form a valid double
   4080 // and are terminated by the given terminator character
   4081 static int checkForValidDouble(const UChar* string, const UChar* end, const char terminator)
   4082 {
   4083     int length = end - string;
   4084     if (length < 1)
   4085         return 0;
   4086 
   4087     bool decimalMarkSeen = false;
   4088     int processedLength = 0;
   4089 
   4090     for (int i = 0; i < length; ++i) {
   4091         if (string[i] == terminator) {
   4092             processedLength = i;
   4093             break;
   4094         }
   4095         if (!isASCIIDigit(string[i])) {
   4096             if (!decimalMarkSeen && string[i] == '.')
   4097                 decimalMarkSeen = true;
   4098             else
   4099                 return 0;
   4100         }
   4101     }
   4102 
   4103     if (decimalMarkSeen && processedLength == 1)
   4104         return 0;
   4105 
   4106     return processedLength;
   4107 }
   4108 
   4109 // Returns the number of characters consumed for parsing a valid double
   4110 // terminated by the given terminator character
   4111 static int parseDouble(const UChar* string, const UChar* end, const char terminator, double& value)
   4112 {
   4113     int length = checkForValidDouble(string, end, terminator);
   4114     if (!length)
   4115         return 0;
   4116 
   4117     int position = 0;
   4118     double localValue = 0;
   4119 
   4120     // The consumed characters here are guaranteed to be
   4121     // ASCII digits with or without a decimal mark
   4122     for (; position < length; ++position) {
   4123         if (string[position] == '.')
   4124             break;
   4125         localValue = localValue * 10 + string[position] - '0';
   4126     }
   4127 
   4128     if (++position == length) {
   4129         value = localValue;
   4130         return length;
   4131     }
   4132 
   4133     double fraction = 0;
   4134     double scale = 1;
   4135 
   4136     while (position < length && scale < MAX_SCALE) {
   4137         fraction = fraction * 10 + string[position++] - '0';
   4138         scale *= 10;
   4139     }
   4140 
   4141     value = localValue + fraction / scale;
   4142     return length;
   4143 }
   4144 
   4145 static bool parseColorIntOrPercentage(const UChar*& string, const UChar* end, const char terminator, CSSPrimitiveValue::UnitTypes& expect, int& value)
   4146 {
   4147     const UChar* current = string;
   4148     double localValue = 0;
   4149     bool negative = false;
   4150     while (current != end && isHTMLSpace(*current))
   4151         current++;
   4152     if (current != end && *current == '-') {
   4153         negative = true;
   4154         current++;
   4155     }
   4156     if (current == end || !isASCIIDigit(*current))
   4157         return false;
   4158     while (current != end && isASCIIDigit(*current)) {
   4159         double newValue = localValue * 10 + *current++ - '0';
   4160         if (newValue >= 255) {
   4161             // Clamp values at 255.
   4162             localValue = 255;
   4163             while (current != end && isASCIIDigit(*current))
   4164                 ++current;
   4165             break;
   4166         }
   4167         localValue = newValue;
   4168     }
   4169 
   4170     if (current == end)
   4171         return false;
   4172 
   4173     if (expect == CSSPrimitiveValue::CSS_NUMBER && (*current == '.' || *current == '%'))
   4174         return false;
   4175 
   4176     if (*current == '.') {
   4177         // We already parsed the integral part, try to parse
   4178         // the fraction part of the percentage value.
   4179         double percentage = 0;
   4180         int numCharactersParsed = parseDouble(current, end, '%', percentage);
   4181         if (!numCharactersParsed)
   4182             return false;
   4183         current += numCharactersParsed;
   4184         if (*current != '%')
   4185             return false;
   4186         localValue += percentage;
   4187     }
   4188 
   4189     if (expect == CSSPrimitiveValue::CSS_PERCENTAGE && *current != '%')
   4190         return false;
   4191 
   4192     if (*current == '%') {
   4193         expect = CSSPrimitiveValue::CSS_PERCENTAGE;
   4194         localValue = localValue / 100.0 * 256.0;
   4195         // Clamp values at 255 for percentages over 100%
   4196         if (localValue > 255)
   4197             localValue = 255;
   4198         current++;
   4199     } else
   4200         expect = CSSPrimitiveValue::CSS_NUMBER;
   4201 
   4202     while (current != end && isHTMLSpace(*current))
   4203         current++;
   4204     if (current == end || *current++ != terminator)
   4205         return false;
   4206     // Clamp negative values at zero.
   4207     value = negative ? 0 : static_cast<int>(localValue);
   4208     string = current;
   4209     return true;
   4210 }
   4211 
   4212 static inline bool isTenthAlpha(const UChar* string, const int length)
   4213 {
   4214     // "0.X"
   4215     if (length == 3 && string[0] == '0' && string[1] == '.' && isASCIIDigit(string[2]))
   4216         return true;
   4217 
   4218     // ".X"
   4219     if (length == 2 && string[0] == '.' && isASCIIDigit(string[1]))
   4220         return true;
   4221 
   4222     return false;
   4223 }
   4224 
   4225 static inline bool parseAlphaValue(const UChar*& string, const UChar* end, const char terminator, int& value)
   4226 {
   4227     while (string != end && isHTMLSpace(*string))
   4228         string++;
   4229 
   4230     bool negative = false;
   4231 
   4232     if (string != end && *string == '-') {
   4233         negative = true;
   4234         string++;
   4235     }
   4236 
   4237     value = 0;
   4238 
   4239     int length = end - string;
   4240     if (length < 2)
   4241         return false;
   4242 
   4243     if (string[length - 1] != terminator)
   4244         return false;
   4245 
   4246     if (string[0] != '0' && string[0] != '1' && string[0] != '.') {
   4247         if (checkForValidDouble(string, end, terminator)) {
   4248             value = negative ? 0 : 255;
   4249             string = end;
   4250             return true;
   4251         }
   4252         return false;
   4253     }
   4254 
   4255     if (length == 2 && string[0] != '.') {
   4256         value = !negative && string[0] == '1' ? 255 : 0;
   4257         string = end;
   4258         return true;
   4259     }
   4260 
   4261     if (isTenthAlpha(string, length - 1)) {
   4262         static const int tenthAlphaValues[] = { 0, 25, 51, 76, 102, 127, 153, 179, 204, 230 };
   4263         value = negative ? 0 : tenthAlphaValues[string[length - 2] - '0'];
   4264         string = end;
   4265         return true;
   4266     }
   4267 
   4268     double alpha = 0;
   4269     if (!parseDouble(string, end, terminator, alpha))
   4270         return false;
   4271     value = negative ? 0 : static_cast<int>(alpha * nextafter(256.0, 0.0));
   4272     string = end;
   4273     return true;
   4274 }
   4275 
   4276 static inline bool mightBeRGBA(const UChar* characters, unsigned length)
   4277 {
   4278     if (length < 5)
   4279         return false;
   4280     return characters[4] == '('
   4281         && (characters[0] | 0x20) == 'r'
   4282         && (characters[1] | 0x20) == 'g'
   4283         && (characters[2] | 0x20) == 'b'
   4284         && (characters[3] | 0x20) == 'a';
   4285 }
   4286 
   4287 static inline bool mightBeRGB(const UChar* characters, unsigned length)
   4288 {
   4289     if (length < 4)
   4290         return false;
   4291     return characters[3] == '('
   4292         && (characters[0] | 0x20) == 'r'
   4293         && (characters[1] | 0x20) == 'g'
   4294         && (characters[2] | 0x20) == 'b';
   4295 }
   4296 
   4297 bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict)
   4298 {
   4299     const UChar* characters = name.characters();
   4300     unsigned length = name.length();
   4301     CSSPrimitiveValue::UnitTypes expect = CSSPrimitiveValue::CSS_UNKNOWN;
   4302 
   4303     if (!strict && length >= 3) {
   4304         if (name[0] == '#') {
   4305             if (Color::parseHexColor(characters + 1, length - 1, rgb))
   4306                 return true;
   4307         } else {
   4308             if (Color::parseHexColor(characters, length, rgb))
   4309                 return true;
   4310         }
   4311     }
   4312 
   4313     // Try rgba() syntax.
   4314     if (mightBeRGBA(characters, length)) {
   4315         const UChar* current = characters + 5;
   4316         const UChar* end = characters + length;
   4317         int red;
   4318         int green;
   4319         int blue;
   4320         int alpha;
   4321 
   4322         if (!parseColorIntOrPercentage(current, end, ',', expect, red))
   4323             return false;
   4324         if (!parseColorIntOrPercentage(current, end, ',', expect, green))
   4325             return false;
   4326         if (!parseColorIntOrPercentage(current, end, ',', expect, blue))
   4327             return false;
   4328         if (!parseAlphaValue(current, end, ')', alpha))
   4329             return false;
   4330         if (current != end)
   4331             return false;
   4332         rgb = makeRGBA(red, green, blue, alpha);
   4333         return true;
   4334     }
   4335 
   4336     // Try rgb() syntax.
   4337     if (mightBeRGB(characters, length)) {
   4338         const UChar* current = characters + 4;
   4339         const UChar* end = characters + length;
   4340         int red;
   4341         int green;
   4342         int blue;
   4343         if (!parseColorIntOrPercentage(current, end, ',', expect, red))
   4344             return false;
   4345         if (!parseColorIntOrPercentage(current, end, ',', expect, green))
   4346             return false;
   4347         if (!parseColorIntOrPercentage(current, end, ')', expect, blue))
   4348             return false;
   4349         if (current != end)
   4350             return false;
   4351         rgb = makeRGB(red, green, blue);
   4352         return true;
   4353     }
   4354 
   4355     // Try named colors.
   4356     Color tc;
   4357     tc.setNamedColor(name);
   4358     if (tc.isValid()) {
   4359         rgb = tc.rgb();
   4360         return true;
   4361     }
   4362     return false;
   4363 }
   4364 
   4365 static inline int colorIntFromValue(CSSParserValue* v)
   4366 {
   4367     if (v->fValue <= 0.0)
   4368         return 0;
   4369 
   4370     if (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE) {
   4371         if (v->fValue >= 100.0)
   4372             return 255;
   4373         return static_cast<int>(v->fValue * 256.0 / 100.0);
   4374     }
   4375 
   4376     if (v->fValue >= 255.0)
   4377         return 255;
   4378 
   4379     return static_cast<int>(v->fValue);
   4380 }
   4381 
   4382 bool CSSParser::parseColorParameters(CSSParserValue* value, int* colorArray, bool parseAlpha)
   4383 {
   4384     CSSParserValueList* args = value->function->args.get();
   4385     CSSParserValue* v = args->current();
   4386     Units unitType = FUnknown;
   4387     // Get the first value and its type
   4388     if (validUnit(v, FInteger, true))
   4389         unitType = FInteger;
   4390     else if (validUnit(v, FPercent, true))
   4391         unitType = FPercent;
   4392     else
   4393         return false;
   4394     colorArray[0] = colorIntFromValue(v);
   4395     for (int i = 1; i < 3; i++) {
   4396         v = args->next();
   4397         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
   4398             return false;
   4399         v = args->next();
   4400         if (!validUnit(v, unitType, true))
   4401             return false;
   4402         colorArray[i] = colorIntFromValue(v);
   4403     }
   4404     if (parseAlpha) {
   4405         v = args->next();
   4406         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
   4407             return false;
   4408         v = args->next();
   4409         if (!validUnit(v, FNumber, true))
   4410             return false;
   4411         // Convert the floating pointer number of alpha to an integer in the range [0, 256),
   4412         // with an equal distribution across all 256 values.
   4413         colorArray[3] = static_cast<int>(max(0.0, min(1.0, v->fValue)) * nextafter(256.0, 0.0));
   4414     }
   4415     return true;
   4416 }
   4417 
   4418 // The CSS3 specification defines the format of a HSL color as
   4419 // hsl(<number>, <percent>, <percent>)
   4420 // and with alpha, the format is
   4421 // hsla(<number>, <percent>, <percent>, <number>)
   4422 // The first value, HUE, is in an angle with a value between 0 and 360
   4423 bool CSSParser::parseHSLParameters(CSSParserValue* value, double* colorArray, bool parseAlpha)
   4424 {
   4425     CSSParserValueList* args = value->function->args.get();
   4426     CSSParserValue* v = args->current();
   4427     // Get the first value
   4428     if (!validUnit(v, FNumber, true))
   4429         return false;
   4430     // normalize the Hue value and change it to be between 0 and 1.0
   4431     colorArray[0] = (((static_cast<int>(v->fValue) % 360) + 360) % 360) / 360.0;
   4432     for (int i = 1; i < 3; i++) {
   4433         v = args->next();
   4434         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
   4435             return false;
   4436         v = args->next();
   4437         if (!validUnit(v, FPercent, true))
   4438             return false;
   4439         colorArray[i] = max(0.0, min(100.0, v->fValue)) / 100.0; // needs to be value between 0 and 1.0
   4440     }
   4441     if (parseAlpha) {
   4442         v = args->next();
   4443         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
   4444             return false;
   4445         v = args->next();
   4446         if (!validUnit(v, FNumber, true))
   4447             return false;
   4448         colorArray[3] = max(0.0, min(1.0, v->fValue));
   4449     }
   4450     return true;
   4451 }
   4452 
   4453 PassRefPtr<CSSPrimitiveValue> CSSParser::parseColor(CSSParserValue* value)
   4454 {
   4455     RGBA32 c = Color::transparent;
   4456     if (!parseColorFromValue(value ? value : m_valueList->current(), c))
   4457         return 0;
   4458     return primitiveValueCache()->createColorValue(c);
   4459 }
   4460 
   4461 bool CSSParser::parseColorFromValue(CSSParserValue* value, RGBA32& c)
   4462 {
   4463     if (!m_strict && value->unit == CSSPrimitiveValue::CSS_NUMBER &&
   4464         value->fValue >= 0. && value->fValue < 1000000.) {
   4465         String str = String::format("%06d", (int)(value->fValue+.5));
   4466         if (!CSSParser::parseColor(str, c, m_strict))
   4467             return false;
   4468     } else if (value->unit == CSSPrimitiveValue::CSS_PARSER_HEXCOLOR ||
   4469                 value->unit == CSSPrimitiveValue::CSS_IDENT ||
   4470                 (!m_strict && value->unit == CSSPrimitiveValue::CSS_DIMENSION)) {
   4471         if (!CSSParser::parseColor(value->string, c, m_strict && value->unit == CSSPrimitiveValue::CSS_IDENT))
   4472             return false;
   4473     } else if (value->unit == CSSParserValue::Function &&
   4474                 value->function->args != 0 &&
   4475                 value->function->args->size() == 5 /* rgb + two commas */ &&
   4476                 equalIgnoringCase(value->function->name, "rgb(")) {
   4477         int colorValues[3];
   4478         if (!parseColorParameters(value, colorValues, false))
   4479             return false;
   4480         c = makeRGB(colorValues[0], colorValues[1], colorValues[2]);
   4481     } else {
   4482         if (value->unit == CSSParserValue::Function &&
   4483                 value->function->args != 0 &&
   4484                 value->function->args->size() == 7 /* rgba + three commas */ &&
   4485                 equalIgnoringCase(value->function->name, "rgba(")) {
   4486             int colorValues[4];
   4487             if (!parseColorParameters(value, colorValues, true))
   4488                 return false;
   4489             c = makeRGBA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
   4490         } else if (value->unit == CSSParserValue::Function &&
   4491                     value->function->args != 0 &&
   4492                     value->function->args->size() == 5 /* hsl + two commas */ &&
   4493                     equalIgnoringCase(value->function->name, "hsl(")) {
   4494             double colorValues[3];
   4495             if (!parseHSLParameters(value, colorValues, false))
   4496                 return false;
   4497             c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], 1.0);
   4498         } else if (value->unit == CSSParserValue::Function &&
   4499                     value->function->args != 0 &&
   4500                     value->function->args->size() == 7 /* hsla + three commas */ &&
   4501                     equalIgnoringCase(value->function->name, "hsla(")) {
   4502             double colorValues[4];
   4503             if (!parseHSLParameters(value, colorValues, true))
   4504                 return false;
   4505             c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
   4506         } else
   4507             return false;
   4508     }
   4509 
   4510     return true;
   4511 }
   4512 
   4513 // This class tracks parsing state for shadow values.  If it goes out of scope (e.g., due to an early return)
   4514 // without the allowBreak bit being set, then it will clean up all of the objects and destroy them.
   4515 struct ShadowParseContext {
   4516     ShadowParseContext(CSSPropertyID prop, CSSPrimitiveValueCache* primitiveValueCache)
   4517         : property(prop)
   4518         , m_primitiveValueCache(primitiveValueCache)
   4519         , allowX(true)
   4520         , allowY(false)
   4521         , allowBlur(false)
   4522         , allowSpread(false)
   4523         , allowColor(true)
   4524         , allowStyle(prop == CSSPropertyWebkitBoxShadow || prop == CSSPropertyBoxShadow)
   4525         , allowBreak(true)
   4526     {
   4527     }
   4528 
   4529     bool allowLength() { return allowX || allowY || allowBlur || allowSpread; }
   4530 
   4531     void commitValue()
   4532     {
   4533         // Handle the ,, case gracefully by doing nothing.
   4534         if (x || y || blur || spread || color || style) {
   4535             if (!values)
   4536                 values = CSSValueList::createCommaSeparated();
   4537 
   4538             // Construct the current shadow value and add it to the list.
   4539             values->append(ShadowValue::create(x.release(), y.release(), blur.release(), spread.release(), style.release(), color.release()));
   4540         }
   4541 
   4542         // Now reset for the next shadow value.
   4543         x = 0;
   4544         y = 0;
   4545         blur = 0;
   4546         spread = 0;
   4547         style = 0;
   4548         color = 0;
   4549 
   4550         allowX = true;
   4551         allowColor = true;
   4552         allowBreak = true;
   4553         allowY = false;
   4554         allowBlur = false;
   4555         allowSpread = false;
   4556         allowStyle = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
   4557     }
   4558 
   4559     void commitLength(CSSParserValue* v)
   4560     {
   4561         RefPtr<CSSPrimitiveValue> val = m_primitiveValueCache->createValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit);
   4562 
   4563         if (allowX) {
   4564             x = val.release();
   4565             allowX = false;
   4566             allowY = true;
   4567             allowColor = false;
   4568             allowStyle = false;
   4569             allowBreak = false;
   4570         } else if (allowY) {
   4571             y = val.release();
   4572             allowY = false;
   4573             allowBlur = true;
   4574             allowColor = true;
   4575             allowStyle = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
   4576             allowBreak = true;
   4577         } else if (allowBlur) {
   4578             blur = val.release();
   4579             allowBlur = false;
   4580             allowSpread = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
   4581         } else if (allowSpread) {
   4582             spread = val.release();
   4583             allowSpread = false;
   4584         }
   4585     }
   4586 
   4587     void commitColor(PassRefPtr<CSSPrimitiveValue> val)
   4588     {
   4589         color = val;
   4590         allowColor = false;
   4591         if (allowX) {
   4592             allowStyle = false;
   4593             allowBreak = false;
   4594         } else {
   4595             allowBlur = false;
   4596             allowSpread = false;
   4597             allowStyle = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
   4598         }
   4599     }
   4600 
   4601     void commitStyle(CSSParserValue* v)
   4602     {
   4603         style = m_primitiveValueCache->createIdentifierValue(v->id);
   4604         allowStyle = false;
   4605         if (allowX)
   4606             allowBreak = false;
   4607         else {
   4608             allowBlur = false;
   4609             allowSpread = false;
   4610             allowColor = false;
   4611         }
   4612     }
   4613 
   4614     CSSPropertyID property;
   4615     CSSPrimitiveValueCache* m_primitiveValueCache;
   4616 
   4617     RefPtr<CSSValueList> values;
   4618     RefPtr<CSSPrimitiveValue> x;
   4619     RefPtr<CSSPrimitiveValue> y;
   4620     RefPtr<CSSPrimitiveValue> blur;
   4621     RefPtr<CSSPrimitiveValue> spread;
   4622     RefPtr<CSSPrimitiveValue> style;
   4623     RefPtr<CSSPrimitiveValue> color;
   4624 
   4625     bool allowX;
   4626     bool allowY;
   4627     bool allowBlur;
   4628     bool allowSpread;
   4629     bool allowColor;
   4630     bool allowStyle; // inset or not.
   4631     bool allowBreak;
   4632 };
   4633 
   4634 bool CSSParser::parseShadow(int propId, bool important)
   4635 {
   4636     ShadowParseContext context(static_cast<CSSPropertyID>(propId), primitiveValueCache());
   4637     CSSParserValue* val;
   4638     while ((val = m_valueList->current())) {
   4639         // Check for a comma break first.
   4640         if (val->unit == CSSParserValue::Operator) {
   4641             if (val->iValue != ',' || !context.allowBreak)
   4642                 // Other operators aren't legal or we aren't done with the current shadow
   4643                 // value.  Treat as invalid.
   4644                 return false;
   4645 #if ENABLE(SVG)
   4646             // -webkit-svg-shadow does not support multiple values.
   4647             if (static_cast<CSSPropertyID>(propId) == CSSPropertyWebkitSvgShadow)
   4648                 return false;
   4649 #endif
   4650             // The value is good.  Commit it.
   4651             context.commitValue();
   4652         } else if (validUnit(val, FLength, true)) {
   4653             // We required a length and didn't get one. Invalid.
   4654             if (!context.allowLength())
   4655                 return false;
   4656 
   4657             // A length is allowed here.  Construct the value and add it.
   4658             context.commitLength(val);
   4659         } else if (val->id == CSSValueInset) {
   4660             if (!context.allowStyle)
   4661                 return false;
   4662 
   4663             context.commitStyle(val);
   4664         } else {
   4665             // The only other type of value that's ok is a color value.
   4666             RefPtr<CSSPrimitiveValue> parsedColor;
   4667             bool isColor = ((val->id >= CSSValueAqua && val->id <= CSSValueWindowtext) || val->id == CSSValueMenu ||
   4668                             (val->id >= CSSValueWebkitFocusRingColor && val->id <= CSSValueWebkitText && !m_strict));
   4669             if (isColor) {
   4670                 if (!context.allowColor)
   4671                     return false;
   4672                 parsedColor = primitiveValueCache()->createIdentifierValue(val->id);
   4673             }
   4674 
   4675             if (!parsedColor)
   4676                 // It's not built-in. Try to parse it as a color.
   4677                 parsedColor = parseColor(val);
   4678 
   4679             if (!parsedColor || !context.allowColor)
   4680                 return false; // This value is not a color or length and is invalid or
   4681                               // it is a color, but a color isn't allowed at this point.
   4682 
   4683             context.commitColor(parsedColor.release());
   4684         }
   4685 
   4686         m_valueList->next();
   4687     }
   4688 
   4689     if (context.allowBreak) {
   4690         context.commitValue();
   4691         if (context.values->length()) {
   4692             addProperty(propId, context.values.release(), important);
   4693             m_valueList->next();
   4694             return true;
   4695         }
   4696     }
   4697 
   4698     return false;
   4699 }
   4700 
   4701 bool CSSParser::parseReflect(int propId, bool important)
   4702 {
   4703     // box-reflect: <direction> <offset> <mask>
   4704 
   4705     // Direction comes first.
   4706     CSSParserValue* val = m_valueList->current();
   4707     CSSReflectionDirection direction;
   4708     switch (val->id) {
   4709         case CSSValueAbove:
   4710             direction = ReflectionAbove;
   4711             break;
   4712         case CSSValueBelow:
   4713             direction = ReflectionBelow;
   4714             break;
   4715         case CSSValueLeft:
   4716             direction = ReflectionLeft;
   4717             break;
   4718         case CSSValueRight:
   4719             direction = ReflectionRight;
   4720             break;
   4721         default:
   4722             return false;
   4723     }
   4724 
   4725     // The offset comes next.
   4726     val = m_valueList->next();
   4727     RefPtr<CSSPrimitiveValue> offset;
   4728     if (!val)
   4729         offset = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_PX);
   4730     else {
   4731         if (!validUnit(val, FLength | FPercent, m_strict))
   4732             return false;
   4733         offset = primitiveValueCache()->createValue(val->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(val->unit));
   4734     }
   4735 
   4736     // Now for the mask.
   4737     RefPtr<CSSValue> mask;
   4738     val = m_valueList->next();
   4739     if (val) {
   4740         if (!parseBorderImage(propId, important, mask))
   4741             return false;
   4742     }
   4743 
   4744     RefPtr<CSSReflectValue> reflectValue = CSSReflectValue::create(direction, offset.release(), mask.release());
   4745     addProperty(propId, reflectValue.release(), important);
   4746     m_valueList->next();
   4747     return true;
   4748 }
   4749 
   4750 struct BorderImageParseContext {
   4751     BorderImageParseContext(CSSPrimitiveValueCache* primitiveValueCache)
   4752     : m_primitiveValueCache(primitiveValueCache)
   4753     , m_allowBreak(false)
   4754     , m_allowNumber(false)
   4755     , m_allowSlash(false)
   4756     , m_allowWidth(false)
   4757     , m_allowRule(false)
   4758     , m_borderTop(0)
   4759     , m_borderRight(0)
   4760     , m_borderBottom(0)
   4761     , m_borderLeft(0)
   4762     , m_horizontalRule(0)
   4763     , m_verticalRule(0)
   4764     {}
   4765 
   4766     bool allowBreak() const { return m_allowBreak; }
   4767     bool allowNumber() const { return m_allowNumber; }
   4768     bool allowSlash() const { return m_allowSlash; }
   4769     bool allowWidth() const { return m_allowWidth; }
   4770     bool allowRule() const { return m_allowRule; }
   4771 
   4772     void commitImage(PassRefPtr<CSSValue> image) { m_image = image; m_allowNumber = true; }
   4773     void commitNumber(CSSParserValue* v)
   4774     {
   4775         PassRefPtr<CSSPrimitiveValue> val = m_primitiveValueCache->createValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit);
   4776         if (!m_top)
   4777             m_top = val;
   4778         else if (!m_right)
   4779             m_right = val;
   4780         else if (!m_bottom)
   4781             m_bottom = val;
   4782         else {
   4783             ASSERT(!m_left);
   4784             m_left = val;
   4785         }
   4786 
   4787         m_allowBreak = m_allowSlash = m_allowRule = true;
   4788         m_allowNumber = !m_left;
   4789     }
   4790     void commitSlash() { m_allowBreak = m_allowSlash = m_allowNumber = false; m_allowWidth = true; }
   4791     void commitWidth(CSSParserValue* val)
   4792     {
   4793         if (!m_borderTop)
   4794             m_borderTop = val;
   4795         else if (!m_borderRight)
   4796             m_borderRight = val;
   4797         else if (!m_borderBottom)
   4798             m_borderBottom = val;
   4799         else {
   4800             ASSERT(!m_borderLeft);
   4801             m_borderLeft = val;
   4802         }
   4803 
   4804         m_allowBreak = m_allowRule = true;
   4805         m_allowWidth = !m_borderLeft;
   4806     }
   4807     void commitRule(int keyword)
   4808     {
   4809         if (!m_horizontalRule)
   4810             m_horizontalRule = keyword;
   4811         else if (!m_verticalRule)
   4812             m_verticalRule = keyword;
   4813         m_allowRule = !m_verticalRule;
   4814     }
   4815     PassRefPtr<CSSValue> commitBorderImage(CSSParser* p, bool important)
   4816     {
   4817         // We need to clone and repeat values for any omissions.
   4818         if (!m_right) {
   4819             m_right = m_primitiveValueCache->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
   4820             m_bottom = m_primitiveValueCache->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
   4821             m_left = m_primitiveValueCache->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
   4822         }
   4823         if (!m_bottom) {
   4824             m_bottom = m_primitiveValueCache->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
   4825             m_left = m_primitiveValueCache->createValue(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType());
   4826         }
   4827         if (!m_left)
   4828              m_left = m_primitiveValueCache->createValue(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType());
   4829 
   4830         // Now build a rect value to hold all four of our primitive values.
   4831         RefPtr<Rect> rect = Rect::create();
   4832         rect->setTop(m_top);
   4833         rect->setRight(m_right);
   4834         rect->setBottom(m_bottom);
   4835         rect->setLeft(m_left);
   4836 
   4837         // Fill in STRETCH as the default if it wasn't specified.
   4838         if (!m_horizontalRule)
   4839             m_horizontalRule = CSSValueStretch;
   4840 
   4841         // The vertical rule should match the horizontal rule if unspecified.
   4842         if (!m_verticalRule)
   4843             m_verticalRule = m_horizontalRule;
   4844 
   4845         // Now we have to deal with the border widths.  The best way to deal with these is to actually put these values into a value
   4846         // list and then make our parsing machinery do the parsing.
   4847         if (m_borderTop) {
   4848             CSSParserValueList newList;
   4849             newList.addValue(*m_borderTop);
   4850             if (m_borderRight)
   4851                 newList.addValue(*m_borderRight);
   4852             if (m_borderBottom)
   4853                 newList.addValue(*m_borderBottom);
   4854             if (m_borderLeft)
   4855                 newList.addValue(*m_borderLeft);
   4856             CSSParserValueList* oldList = p->m_valueList;
   4857             p->m_valueList = &newList;
   4858             p->parseValue(CSSPropertyBorderWidth, important);
   4859             p->m_valueList = oldList;
   4860         }
   4861 
   4862         // Make our new border image value now.
   4863         return CSSBorderImageValue::create(m_image, rect.release(), m_horizontalRule, m_verticalRule);
   4864     }
   4865 
   4866     CSSPrimitiveValueCache* m_primitiveValueCache;
   4867 
   4868     bool m_allowBreak;
   4869     bool m_allowNumber;
   4870     bool m_allowSlash;
   4871     bool m_allowWidth;
   4872     bool m_allowRule;
   4873 
   4874     RefPtr<CSSValue> m_image;
   4875 
   4876     RefPtr<CSSPrimitiveValue> m_top;
   4877     RefPtr<CSSPrimitiveValue> m_right;
   4878     RefPtr<CSSPrimitiveValue> m_bottom;
   4879     RefPtr<CSSPrimitiveValue> m_left;
   4880 
   4881     CSSParserValue* m_borderTop;
   4882     CSSParserValue* m_borderRight;
   4883     CSSParserValue* m_borderBottom;
   4884     CSSParserValue* m_borderLeft;
   4885 
   4886     int m_horizontalRule;
   4887     int m_verticalRule;
   4888 };
   4889 
   4890 bool CSSParser::parseBorderImage(int propId, bool important, RefPtr<CSSValue>& result)
   4891 {
   4892     // Look for an image initially.  If the first value is not a URI, then we're done.
   4893     BorderImageParseContext context(primitiveValueCache());
   4894     CSSParserValue* val = m_valueList->current();
   4895     if (val->unit == CSSPrimitiveValue::CSS_URI && m_styleSheet) {
   4896         // FIXME: The completeURL call should be done when using the CSSImageValue,
   4897         // not when creating it.
   4898         context.commitImage(CSSImageValue::create(m_styleSheet->completeURL(val->string)));
   4899     } else if (isGeneratedImageValue(val)) {
   4900         RefPtr<CSSValue> value;
   4901         if (parseGeneratedImage(value))
   4902             context.commitImage(value);
   4903         else
   4904             return false;
   4905     } else
   4906         return false;
   4907 
   4908     while ((val = m_valueList->next())) {
   4909         if (context.allowNumber() && validUnit(val, FInteger | FNonNeg | FPercent, true)) {
   4910             context.commitNumber(val);
   4911         } else if (propId == CSSPropertyWebkitBorderImage && context.allowSlash() && val->unit == CSSParserValue::Operator && val->iValue == '/') {
   4912             context.commitSlash();
   4913         } else if (context.allowWidth() &&
   4914             (val->id == CSSValueThin || val->id == CSSValueMedium || val->id == CSSValueThick || validUnit(val, FLength, m_strict))) {
   4915             context.commitWidth(val);
   4916         } else if (context.allowRule() &&
   4917             (val->id == CSSValueStretch || val->id == CSSValueRound || val->id == CSSValueRepeat)) {
   4918             context.commitRule(val->id);
   4919         } else {
   4920             // Something invalid was encountered.
   4921             return false;
   4922         }
   4923     }
   4924 
   4925     if (context.allowNumber() && propId != CSSPropertyWebkitBorderImage) {
   4926         // Allow the slices to be omitted for images that don't fit to a border.  We just set the slices to be 0.
   4927         context.m_top = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_NUMBER);
   4928         context.m_allowBreak = true;
   4929     }
   4930 
   4931     if (context.allowBreak()) {
   4932         // Need to fully commit as a single value.
   4933         result = context.commitBorderImage(this, important);
   4934         return true;
   4935     }
   4936 
   4937     return false;
   4938 }
   4939 
   4940 static void completeBorderRadii(RefPtr<CSSPrimitiveValue> radii[4])
   4941 {
   4942     if (radii[3])
   4943         return;
   4944     if (!radii[2]) {
   4945         if (!radii[1])
   4946             radii[1] = radii[0];
   4947         radii[2] = radii[0];
   4948     }
   4949     radii[3] = radii[1];
   4950 }
   4951 
   4952 bool CSSParser::parseBorderRadius(int propId, bool important)
   4953 {
   4954     unsigned num = m_valueList->size();
   4955     if (num > 9)
   4956         return false;
   4957 
   4958     ShorthandScope scope(this, propId);
   4959     RefPtr<CSSPrimitiveValue> radii[2][4];
   4960 
   4961     unsigned indexAfterSlash = 0;
   4962     for (unsigned i = 0; i < num; ++i) {
   4963         CSSParserValue* value = m_valueList->valueAt(i);
   4964         if (value->unit == CSSParserValue::Operator) {
   4965             if (value->iValue != '/')
   4966                 return false;
   4967 
   4968             if (!i || indexAfterSlash || i + 1 == num || num > i + 5)
   4969                 return false;
   4970 
   4971             indexAfterSlash = i + 1;
   4972             completeBorderRadii(radii[0]);
   4973             continue;
   4974         }
   4975 
   4976         if (i - indexAfterSlash >= 4)
   4977             return false;
   4978 
   4979         if (!validUnit(value, FLength | FPercent, m_strict))
   4980             return false;
   4981 
   4982         RefPtr<CSSPrimitiveValue> radius = primitiveValueCache()->createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit));
   4983 
   4984         if (!indexAfterSlash) {
   4985             radii[0][i] = radius;
   4986 
   4987             // Legacy syntax: -webkit-border-radius: l1 l2; is equivalent to border-radius: l1 / l2;
   4988             if (num == 2 && propId == CSSPropertyWebkitBorderRadius) {
   4989                 indexAfterSlash = 1;
   4990                 completeBorderRadii(radii[0]);
   4991             }
   4992         } else
   4993             radii[1][i - indexAfterSlash] = radius.release();
   4994     }
   4995 
   4996     if (!indexAfterSlash) {
   4997         completeBorderRadii(radii[0]);
   4998         for (unsigned i = 0; i < 4; ++i)
   4999             radii[1][i] = radii[0][i];
   5000     } else
   5001         completeBorderRadii(radii[1]);
   5002 
   5003     m_implicitShorthand = true;
   5004     addProperty(CSSPropertyBorderTopLeftRadius, primitiveValueCache()->createValue(Pair::create(radii[0][0].release(), radii[1][0].release())), important);
   5005     addProperty(CSSPropertyBorderTopRightRadius, primitiveValueCache()->createValue(Pair::create(radii[0][1].release(), radii[1][1].release())), important);
   5006     addProperty(CSSPropertyBorderBottomRightRadius, primitiveValueCache()->createValue(Pair::create(radii[0][2].release(), radii[1][2].release())), important);
   5007     addProperty(CSSPropertyBorderBottomLeftRadius, primitiveValueCache()->createValue(Pair::create(radii[0][3].release(), radii[1][3].release())), important);
   5008     m_implicitShorthand = false;
   5009     return true;
   5010 }
   5011 
   5012 bool CSSParser::parseCounter(int propId, int defaultValue, bool important)
   5013 {
   5014     enum { ID, VAL } state = ID;
   5015 
   5016     RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
   5017     RefPtr<CSSPrimitiveValue> counterName;
   5018 
   5019     while (true) {
   5020         CSSParserValue* val = m_valueList->current();
   5021         switch (state) {
   5022             case ID:
   5023                 if (val && val->unit == CSSPrimitiveValue::CSS_IDENT) {
   5024                     counterName = primitiveValueCache()->createValue(val->string, CSSPrimitiveValue::CSS_STRING);
   5025                     state = VAL;
   5026                     m_valueList->next();
   5027                     continue;
   5028                 }
   5029                 break;
   5030             case VAL: {
   5031                 int i = defaultValue;
   5032                 if (val && val->unit == CSSPrimitiveValue::CSS_NUMBER) {
   5033                     i = clampToInteger(val->fValue);
   5034                     m_valueList->next();
   5035                 }
   5036 
   5037                 list->append(primitiveValueCache()->createValue(Pair::create(counterName.release(),
   5038                     primitiveValueCache()->createValue(i, CSSPrimitiveValue::CSS_NUMBER))));
   5039                 state = ID;
   5040                 continue;
   5041             }
   5042         }
   5043         break;
   5044     }
   5045 
   5046     if (list->length() > 0) {
   5047         addProperty(propId, list.release(), important);
   5048         return true;
   5049     }
   5050 
   5051     return false;
   5052 }
   5053 
   5054 // This should go away once we drop support for -webkit-gradient
   5055 static PassRefPtr<CSSPrimitiveValue> parseDeprecatedGradientPoint(CSSParserValue* a, bool horizontal, CSSPrimitiveValueCache* primitiveValueCache)
   5056 {
   5057     RefPtr<CSSPrimitiveValue> result;
   5058     if (a->unit == CSSPrimitiveValue::CSS_IDENT) {
   5059         if ((equalIgnoringCase(a->string, "left") && horizontal) ||
   5060             (equalIgnoringCase(a->string, "top") && !horizontal))
   5061             result = primitiveValueCache->createValue(0., CSSPrimitiveValue::CSS_PERCENTAGE);
   5062         else if ((equalIgnoringCase(a->string, "right") && horizontal) ||
   5063                  (equalIgnoringCase(a->string, "bottom") && !horizontal))
   5064             result = primitiveValueCache->createValue(100., CSSPrimitiveValue::CSS_PERCENTAGE);
   5065         else if (equalIgnoringCase(a->string, "center"))
   5066             result = primitiveValueCache->createValue(50., CSSPrimitiveValue::CSS_PERCENTAGE);
   5067     } else if (a->unit == CSSPrimitiveValue::CSS_NUMBER || a->unit == CSSPrimitiveValue::CSS_PERCENTAGE)
   5068         result = primitiveValueCache->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit);
   5069     return result;
   5070 }
   5071 
   5072 static bool parseDeprecatedGradientColorStop(CSSParser* p, CSSParserValue* a, CSSGradientColorStop& stop)
   5073 {
   5074     if (a->unit != CSSParserValue::Function)
   5075         return false;
   5076 
   5077     if (!equalIgnoringCase(a->function->name, "from(") &&
   5078         !equalIgnoringCase(a->function->name, "to(") &&
   5079         !equalIgnoringCase(a->function->name, "color-stop("))
   5080         return false;
   5081 
   5082     CSSParserValueList* args = a->function->args.get();
   5083     if (!args)
   5084         return false;
   5085 
   5086     if (equalIgnoringCase(a->function->name, "from(") ||
   5087         equalIgnoringCase(a->function->name, "to(")) {
   5088         // The "from" and "to" stops expect 1 argument.
   5089         if (args->size() != 1)
   5090             return false;
   5091 
   5092         if (equalIgnoringCase(a->function->name, "from("))
   5093             stop.m_position = p->primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_NUMBER);
   5094         else
   5095             stop.m_position = p->primitiveValueCache()->createValue(1, CSSPrimitiveValue::CSS_NUMBER);
   5096 
   5097         int id = args->current()->id;
   5098         if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu)
   5099             stop.m_color = p->primitiveValueCache()->createIdentifierValue(id);
   5100         else
   5101             stop.m_color = p->parseColor(args->current());
   5102         if (!stop.m_color)
   5103             return false;
   5104     }
   5105 
   5106     // The "color-stop" function expects 3 arguments.
   5107     if (equalIgnoringCase(a->function->name, "color-stop(")) {
   5108         if (args->size() != 3)
   5109             return false;
   5110 
   5111         CSSParserValue* stopArg = args->current();
   5112         if (stopArg->unit == CSSPrimitiveValue::CSS_PERCENTAGE)
   5113             stop.m_position = p->primitiveValueCache()->createValue(stopArg->fValue / 100, CSSPrimitiveValue::CSS_NUMBER);
   5114         else if (stopArg->unit == CSSPrimitiveValue::CSS_NUMBER)
   5115             stop.m_position = p->primitiveValueCache()->createValue(stopArg->fValue, CSSPrimitiveValue::CSS_NUMBER);
   5116         else
   5117             return false;
   5118 
   5119         stopArg = args->next();
   5120         if (stopArg->unit != CSSParserValue::Operator || stopArg->iValue != ',')
   5121             return false;
   5122 
   5123         stopArg = args->next();
   5124         int id = stopArg->id;
   5125         if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu)
   5126             stop.m_color = p->primitiveValueCache()->createIdentifierValue(id);
   5127         else
   5128             stop.m_color = p->parseColor(stopArg);
   5129         if (!stop.m_color)
   5130             return false;
   5131     }
   5132 
   5133     return true;
   5134 }
   5135 
   5136 bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient)
   5137 {
   5138     // Walk the arguments.
   5139     CSSParserValueList* args = m_valueList->current()->function->args.get();
   5140     if (!args || args->size() == 0)
   5141         return false;
   5142 
   5143     // The first argument is the gradient type.  It is an identifier.
   5144     CSSGradientType gradientType;
   5145     CSSParserValue* a = args->current();
   5146     if (!a || a->unit != CSSPrimitiveValue::CSS_IDENT)
   5147         return false;
   5148     if (equalIgnoringCase(a->string, "linear"))
   5149         gradientType = CSSLinearGradient;
   5150     else if (equalIgnoringCase(a->string, "radial"))
   5151         gradientType = CSSRadialGradient;
   5152     else
   5153         return false;
   5154 
   5155     RefPtr<CSSGradientValue> result;
   5156     switch (gradientType) {
   5157         case CSSLinearGradient:
   5158             result = CSSLinearGradientValue::create(NonRepeating, true);
   5159             break;
   5160         case CSSRadialGradient:
   5161             result = CSSRadialGradientValue::create(NonRepeating, true);
   5162             break;
   5163     }
   5164 
   5165     // Comma.
   5166     a = args->next();
   5167     if (!a || a->unit != CSSParserValue::Operator || a->iValue != ',')
   5168         return false;
   5169 
   5170     // Next comes the starting point for the gradient as an x y pair.  There is no
   5171     // comma between the x and the y values.
   5172     // First X.  It can be left, right, number or percent.
   5173     a = args->next();
   5174     if (!a)
   5175         return false;
   5176     RefPtr<CSSPrimitiveValue> point = parseDeprecatedGradientPoint(a, true, primitiveValueCache());
   5177     if (!point)
   5178         return false;
   5179     result->setFirstX(point.release());
   5180 
   5181     // First Y.  It can be top, bottom, number or percent.
   5182     a = args->next();
   5183     if (!a)
   5184         return false;
   5185     point = parseDeprecatedGradientPoint(a, false, primitiveValueCache());
   5186     if (!point)
   5187         return false;
   5188     result->setFirstY(point.release());
   5189 
   5190     // Comma after the first point.
   5191     a = args->next();
   5192     if (!a || a->unit != CSSParserValue::Operator || a->iValue != ',')
   5193         return false;
   5194 
   5195     // For radial gradients only, we now expect a numeric radius.
   5196     if (gradientType == CSSRadialGradient) {
   5197         a = args->next();
   5198         if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER)
   5199             return false;
   5200         static_cast<CSSRadialGradientValue*>(result.get())->setFirstRadius(primitiveValueCache()->createValue(a->fValue, CSSPrimitiveValue::CSS_NUMBER));
   5201 
   5202         // Comma after the first radius.
   5203         a = args->next();
   5204         if (!a || a->unit != CSSParserValue::Operator || a->iValue != ',')
   5205             return false;
   5206     }
   5207 
   5208     // Next is the ending point for the gradient as an x, y pair.
   5209     // Second X.  It can be left, right, number or percent.
   5210     a = args->next();
   5211     if (!a)
   5212         return false;
   5213     point = parseDeprecatedGradientPoint(a, true, primitiveValueCache());
   5214     if (!point)
   5215         return false;
   5216     result->setSecondX(point.release());
   5217 
   5218     // Second Y.  It can be top, bottom, number or percent.
   5219     a = args->next();
   5220     if (!a)
   5221         return false;
   5222     point = parseDeprecatedGradientPoint(a, false, primitiveValueCache());
   5223     if (!point)
   5224         return false;
   5225     result->setSecondY(point.release());
   5226 
   5227     // For radial gradients only, we now expect the second radius.
   5228     if (gradientType == CSSRadialGradient) {
   5229         // Comma after the second point.
   5230         a = args->next();
   5231         if (!a || a->unit != CSSParserValue::Operator || a->iValue != ',')
   5232             return false;
   5233 
   5234         a = args->next();
   5235         if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER)
   5236             return false;
   5237         static_cast<CSSRadialGradientValue*>(result.get())->setSecondRadius(primitiveValueCache()->createValue(a->fValue, CSSPrimitiveValue::CSS_NUMBER));
   5238     }
   5239 
   5240     // We now will accept any number of stops (0 or more).
   5241     a = args->next();
   5242     while (a) {
   5243         // Look for the comma before the next stop.
   5244         if (a->unit != CSSParserValue::Operator || a->iValue != ',')
   5245             return false;
   5246 
   5247         // Now examine the stop itself.
   5248         a = args->next();
   5249         if (!a)
   5250             return false;
   5251 
   5252         // The function name needs to be one of "from", "to", or "color-stop."
   5253         CSSGradientColorStop stop;
   5254         if (!parseDeprecatedGradientColorStop(this, a, stop))
   5255             return false;
   5256         result->addStop(stop);
   5257 
   5258         // Advance
   5259         a = args->next();
   5260     }
   5261 
   5262     gradient = result.release();
   5263     return true;
   5264 }
   5265 
   5266 static PassRefPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, bool& isHorizontal, CSSPrimitiveValueCache* primitiveValueCache)
   5267 {
   5268     if (a->unit != CSSPrimitiveValue::CSS_IDENT)
   5269         return 0;
   5270 
   5271     switch (a->id) {
   5272         case CSSValueLeft:
   5273         case CSSValueRight:
   5274             isHorizontal = true;
   5275             break;
   5276         case CSSValueTop:
   5277         case CSSValueBottom:
   5278             isHorizontal = false;
   5279             break;
   5280         default:
   5281             return 0;
   5282     }
   5283     return primitiveValueCache->createIdentifierValue(a->id);
   5284 }
   5285 
   5286 static PassRefPtr<CSSPrimitiveValue> parseGradientColorOrKeyword(CSSParser* p, CSSParserValue* value)
   5287 {
   5288     int id = value->id;
   5289     if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu)
   5290         return p->primitiveValueCache()->createIdentifierValue(id);
   5291 
   5292     return p->parseColor(value);
   5293 }
   5294 
   5295 bool CSSParser::parseLinearGradient(RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating)
   5296 {
   5297     RefPtr<CSSLinearGradientValue> result = CSSLinearGradientValue::create(repeating);
   5298 
   5299     // Walk the arguments.
   5300     CSSParserValueList* args = m_valueList->current()->function->args.get();
   5301     if (!args || !args->size())
   5302         return false;
   5303 
   5304     CSSParserValue* a = args->current();
   5305     if (!a)
   5306         return false;
   5307 
   5308     bool expectComma = false;
   5309     // Look for angle.
   5310     if (validUnit(a, FAngle, true)) {
   5311         result->setAngle(primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit));
   5312 
   5313         a = args->next();
   5314         expectComma = true;
   5315     } else {
   5316         // Look one or two optional keywords that indicate a side or corner.
   5317         RefPtr<CSSPrimitiveValue> startX, startY;
   5318 
   5319         RefPtr<CSSPrimitiveValue> location;
   5320         bool isHorizontal = false;
   5321         if ((location = valueFromSideKeyword(a, isHorizontal, primitiveValueCache()))) {
   5322             if (isHorizontal)
   5323                 startX = location;
   5324             else
   5325                 startY = location;
   5326 
   5327             a = args->next();
   5328             if (a) {
   5329                 if ((location = valueFromSideKeyword(a, isHorizontal, primitiveValueCache()))) {
   5330                     if (isHorizontal) {
   5331                         if (startX)
   5332                             return false;
   5333                         startX = location;
   5334                     } else {
   5335                         if (startY)
   5336                             return false;
   5337                         startY = location;
   5338                     }
   5339 
   5340                     a = args->next();
   5341                 }
   5342             }
   5343 
   5344             expectComma = true;
   5345         }
   5346 
   5347         if (!startX && !startY)
   5348             startY = primitiveValueCache()->createIdentifierValue(CSSValueTop);
   5349 
   5350         result->setFirstX(startX.release());
   5351         result->setFirstY(startY.release());
   5352     }
   5353 
   5354     if (!parseGradientColorStops(args, result.get(), expectComma))
   5355         return false;
   5356 
   5357     Vector<CSSGradientColorStop>& stops = result->stops();
   5358     if (stops.isEmpty())
   5359         return false;
   5360 
   5361     gradient = result.release();
   5362     return true;
   5363 }
   5364 
   5365 bool CSSParser::parseRadialGradient(RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating)
   5366 {
   5367     RefPtr<CSSRadialGradientValue> result = CSSRadialGradientValue::create(repeating);
   5368 
   5369     // Walk the arguments.
   5370     CSSParserValueList* args = m_valueList->current()->function->args.get();
   5371     if (!args || !args->size())
   5372         return false;
   5373 
   5374     CSSParserValue* a = args->current();
   5375     if (!a)
   5376         return false;
   5377 
   5378     bool expectComma = false;
   5379 
   5380     // Optional background-position
   5381     RefPtr<CSSValue> centerX;
   5382     RefPtr<CSSValue> centerY;
   5383     // parseFillPosition advances the args next pointer.
   5384     parseFillPosition(args, centerX, centerY);
   5385     a = args->current();
   5386     if (!a)
   5387         return false;
   5388 
   5389     if (centerX || centerY) {
   5390         // Comma
   5391         if (a->unit != CSSParserValue::Operator || a->iValue != ',')
   5392             return false;
   5393 
   5394         a = args->next();
   5395         if (!a)
   5396             return false;
   5397     }
   5398 
   5399     ASSERT(!centerX || centerX->isPrimitiveValue());
   5400     ASSERT(!centerY || centerY->isPrimitiveValue());
   5401 
   5402     result->setFirstX(static_cast<CSSPrimitiveValue*>(centerX.get()));
   5403     result->setSecondX(static_cast<CSSPrimitiveValue*>(centerX.get()));
   5404     // CSS3 radial gradients always share the same start and end point.
   5405     result->setFirstY(static_cast<CSSPrimitiveValue*>(centerY.get()));
   5406     result->setSecondY(static_cast<CSSPrimitiveValue*>(centerY.get()));
   5407 
   5408     RefPtr<CSSPrimitiveValue> shapeValue;
   5409     RefPtr<CSSPrimitiveValue> sizeValue;
   5410 
   5411     // Optional shape and/or size in any order.
   5412     for (int i = 0; i < 2; ++i) {
   5413         if (a->unit != CSSPrimitiveValue::CSS_IDENT)
   5414             break;
   5415 
   5416         bool foundValue = false;
   5417         switch (a->id) {
   5418         case CSSValueCircle:
   5419         case CSSValueEllipse:
   5420             shapeValue = primitiveValueCache()->createIdentifierValue(a->id);
   5421             foundValue = true;
   5422             break;
   5423         case CSSValueClosestSide:
   5424         case CSSValueClosestCorner:
   5425         case CSSValueFarthestSide:
   5426         case CSSValueFarthestCorner:
   5427         case CSSValueContain:
   5428         case CSSValueCover:
   5429             sizeValue = primitiveValueCache()->createIdentifierValue(a->id);
   5430             foundValue = true;
   5431             break;
   5432         }
   5433 
   5434         if (foundValue) {
   5435             a = args->next();
   5436             if (!a)
   5437                 return false;
   5438 
   5439             expectComma = true;
   5440         }
   5441     }
   5442 
   5443     result->setShape(shapeValue);
   5444     result->setSizingBehavior(sizeValue);
   5445 
   5446     // Or, two lengths or percentages
   5447     RefPtr<CSSPrimitiveValue> horizontalSize;
   5448     RefPtr<CSSPrimitiveValue> verticalSize;
   5449 
   5450     if (!shapeValue && !sizeValue) {
   5451         if (validUnit(a, FLength | FPercent, m_strict)) {
   5452             horizontalSize = primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit);
   5453             a = args->next();
   5454             if (!a)
   5455                 return false;
   5456 
   5457             expectComma = true;
   5458         }
   5459 
   5460         if (validUnit(a, FLength | FPercent, m_strict)) {
   5461             verticalSize = primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit);
   5462 
   5463             a = args->next();
   5464             if (!a)
   5465                 return false;
   5466             expectComma = true;
   5467         }
   5468     }
   5469 
   5470     // Must have neither or both.
   5471     if (!horizontalSize != !verticalSize)
   5472         return false;
   5473 
   5474     result->setEndHorizontalSize(horizontalSize);
   5475     result->setEndVerticalSize(verticalSize);
   5476 
   5477     if (!parseGradientColorStops(args, result.get(), expectComma))
   5478         return false;
   5479 
   5480     gradient = result.release();
   5481     return true;
   5482 }
   5483 
   5484 bool CSSParser::parseGradientColorStops(CSSParserValueList* valueList, CSSGradientValue* gradient, bool expectComma)
   5485 {
   5486     CSSParserValue* a = valueList->current();
   5487 
   5488     // Now look for color stops.
   5489     while (a) {
   5490         // Look for the comma before the next stop.
   5491         if (expectComma) {
   5492             if (a->unit != CSSParserValue::Operator || a->iValue != ',')
   5493                 return false;
   5494 
   5495             a = valueList->next();
   5496             if (!a)
   5497                 return false;
   5498         }
   5499 
   5500         // <color-stop> = <color> [ <percentage> | <length> ]?
   5501         CSSGradientColorStop stop;
   5502         stop.m_color = parseGradientColorOrKeyword(this, a);
   5503         if (!stop.m_color)
   5504             return false;
   5505 
   5506         a = valueList->next();
   5507         if (a) {
   5508             if (validUnit(a, FLength | FPercent, m_strict)) {
   5509                 stop.m_position = primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit);
   5510                 a = valueList->next();
   5511             }
   5512         }
   5513 
   5514         gradient->addStop(stop);
   5515         expectComma = true;
   5516     }
   5517 
   5518     // Must have 2 or more stops to be valid.
   5519     return gradient->stops().size() > 1;
   5520 }
   5521 
   5522 bool CSSParser::isGeneratedImageValue(CSSParserValue* val) const
   5523 {
   5524     if (val->unit != CSSParserValue::Function)
   5525         return false;
   5526 
   5527     return equalIgnoringCase(val->function->name, "-webkit-gradient(")
   5528         || equalIgnoringCase(val->function->name, "-webkit-linear-gradient(")
   5529         || equalIgnoringCase(val->function->name, "-webkit-repeating-linear-gradient(")
   5530         || equalIgnoringCase(val->function->name, "-webkit-radial-gradient(")
   5531         || equalIgnoringCase(val->function->name, "-webkit-repeating-radial-gradient(")
   5532         || equalIgnoringCase(val->function->name, "-webkit-canvas(");
   5533 }
   5534 
   5535 bool CSSParser::parseGeneratedImage(RefPtr<CSSValue>& value)
   5536 {
   5537     CSSParserValue* val = m_valueList->current();
   5538 
   5539     if (val->unit != CSSParserValue::Function)
   5540         return false;
   5541 
   5542     if (equalIgnoringCase(val->function->name, "-webkit-gradient("))
   5543         return parseDeprecatedGradient(value);
   5544 
   5545     if (equalIgnoringCase(val->function->name, "-webkit-linear-gradient("))
   5546         return parseLinearGradient(value, NonRepeating);
   5547 
   5548     if (equalIgnoringCase(val->function->name, "-webkit-repeating-linear-gradient("))
   5549         return parseLinearGradient(value, Repeating);
   5550 
   5551     if (equalIgnoringCase(val->function->name, "-webkit-radial-gradient("))
   5552         return parseRadialGradient(value, NonRepeating);
   5553 
   5554     if (equalIgnoringCase(val->function->name, "-webkit-repeating-radial-gradient("))
   5555         return parseRadialGradient(value, Repeating);
   5556 
   5557     if (equalIgnoringCase(val->function->name, "-webkit-canvas("))
   5558         return parseCanvas(value);
   5559 
   5560     return false;
   5561 }
   5562 
   5563 bool CSSParser::parseCanvas(RefPtr<CSSValue>& canvas)
   5564 {
   5565     RefPtr<CSSCanvasValue> result = CSSCanvasValue::create();
   5566 
   5567     // Walk the arguments.
   5568     CSSParserValueList* args = m_valueList->current()->function->args.get();
   5569     if (!args || args->size() != 1)
   5570         return false;
   5571 
   5572     // The first argument is the canvas name.  It is an identifier.
   5573     CSSParserValue* a = args->current();
   5574     if (!a || a->unit != CSSPrimitiveValue::CSS_IDENT)
   5575         return false;
   5576     result->setName(a->string);
   5577     canvas = result;
   5578     return true;
   5579 }
   5580 
   5581 class TransformOperationInfo {
   5582 public:
   5583     TransformOperationInfo(const CSSParserString& name)
   5584     : m_type(WebKitCSSTransformValue::UnknownTransformOperation)
   5585     , m_argCount(1)
   5586     , m_allowSingleArgument(false)
   5587     , m_unit(CSSParser::FUnknown)
   5588     {
   5589         if (equalIgnoringCase(name, "scale(") || equalIgnoringCase(name, "scalex(") || equalIgnoringCase(name, "scaley(") || equalIgnoringCase(name, "scalez(")) {
   5590             m_unit = CSSParser::FNumber;
   5591             if (equalIgnoringCase(name, "scale("))
   5592                 m_type = WebKitCSSTransformValue::ScaleTransformOperation;
   5593             else if (equalIgnoringCase(name, "scalex("))
   5594                 m_type = WebKitCSSTransformValue::ScaleXTransformOperation;
   5595             else if (equalIgnoringCase(name, "scaley("))
   5596                 m_type = WebKitCSSTransformValue::ScaleYTransformOperation;
   5597             else
   5598                 m_type = WebKitCSSTransformValue::ScaleZTransformOperation;
   5599         } else if (equalIgnoringCase(name, "scale3d(")) {
   5600             m_type = WebKitCSSTransformValue::Scale3DTransformOperation;
   5601             m_argCount = 5;
   5602             m_unit = CSSParser::FNumber;
   5603         } else if (equalIgnoringCase(name, "rotate(")) {
   5604             m_type = WebKitCSSTransformValue::RotateTransformOperation;
   5605             m_unit = CSSParser::FAngle;
   5606         } else if (equalIgnoringCase(name, "rotatex(") ||
   5607                    equalIgnoringCase(name, "rotatey(") ||
   5608                    equalIgnoringCase(name, "rotatez(")) {
   5609             m_unit = CSSParser::FAngle;
   5610             if (equalIgnoringCase(name, "rotatex("))
   5611                 m_type = WebKitCSSTransformValue::RotateXTransformOperation;
   5612             else if (equalIgnoringCase(name, "rotatey("))
   5613                 m_type = WebKitCSSTransformValue::RotateYTransformOperation;
   5614             else
   5615                 m_type = WebKitCSSTransformValue::RotateZTransformOperation;
   5616         } else if (equalIgnoringCase(name, "rotate3d(")) {
   5617             m_type = WebKitCSSTransformValue::Rotate3DTransformOperation;
   5618             m_argCount = 7;
   5619             m_unit = CSSParser::FNumber;
   5620         } else if (equalIgnoringCase(name, "skew(") || equalIgnoringCase(name, "skewx(") || equalIgnoringCase(name, "skewy(")) {
   5621             m_unit = CSSParser::FAngle;
   5622             if (equalIgnoringCase(name, "skew("))
   5623                 m_type = WebKitCSSTransformValue::SkewTransformOperation;
   5624             else if (equalIgnoringCase(name, "skewx("))
   5625                 m_type = WebKitCSSTransformValue::SkewXTransformOperation;
   5626             else
   5627                 m_type = WebKitCSSTransformValue::SkewYTransformOperation;
   5628         } else if (equalIgnoringCase(name, "translate(") || equalIgnoringCase(name, "translatex(") || equalIgnoringCase(name, "translatey(") || equalIgnoringCase(name, "translatez(")) {
   5629             m_unit = CSSParser::FLength | CSSParser::FPercent;
   5630             if (equalIgnoringCase(name, "translate("))
   5631                 m_type = WebKitCSSTransformValue::TranslateTransformOperation;
   5632             else if (equalIgnoringCase(name, "translatex("))
   5633                 m_type = WebKitCSSTransformValue::TranslateXTransformOperation;
   5634             else if (equalIgnoringCase(name, "translatey("))
   5635                 m_type = WebKitCSSTransformValue::TranslateYTransformOperation;
   5636             else
   5637                 m_type = WebKitCSSTransformValue::TranslateZTransformOperation;
   5638         } else if (equalIgnoringCase(name, "translate3d(")) {
   5639             m_type = WebKitCSSTransformValue::Translate3DTransformOperation;
   5640             m_argCount = 5;
   5641             m_unit = CSSParser::FLength | CSSParser::FPercent;
   5642         } else if (equalIgnoringCase(name, "matrix(")) {
   5643             m_type = WebKitCSSTransformValue::MatrixTransformOperation;
   5644             m_argCount = 11;
   5645             m_unit = CSSParser::FNumber;
   5646         } else if (equalIgnoringCase(name, "matrix3d(")) {
   5647             m_type = WebKitCSSTransformValue::Matrix3DTransformOperation;
   5648             m_argCount = 31;
   5649             m_unit = CSSParser::FNumber;
   5650         } else if (equalIgnoringCase(name, "perspective(")) {
   5651             m_type = WebKitCSSTransformValue::PerspectiveTransformOperation;
   5652             m_unit = CSSParser::FNumber;
   5653         }
   5654 
   5655         if (equalIgnoringCase(name, "scale(") || equalIgnoringCase(name, "skew(") || equalIgnoringCase(name, "translate(")) {
   5656             m_allowSingleArgument = true;
   5657             m_argCount = 3;
   5658         }
   5659     }
   5660 
   5661     WebKitCSSTransformValue::TransformOperationType type() const { return m_type; }
   5662     unsigned argCount() const { return m_argCount; }
   5663     CSSParser::Units unit() const { return m_unit; }
   5664 
   5665     bool unknown() const { return m_type == WebKitCSSTransformValue::UnknownTransformOperation; }
   5666     bool hasCorrectArgCount(unsigned argCount) { return m_argCount == argCount || (m_allowSingleArgument && argCount == 1); }
   5667 
   5668 private:
   5669     WebKitCSSTransformValue::TransformOperationType m_type;
   5670     unsigned m_argCount;
   5671     bool m_allowSingleArgument;
   5672     CSSParser::Units m_unit;
   5673 };
   5674 
   5675 PassRefPtr<CSSValueList> CSSParser::parseTransform()
   5676 {
   5677     if (!m_valueList)
   5678         return 0;
   5679 
   5680     // The transform is a list of functional primitives that specify transform operations.
   5681     // We collect a list of WebKitCSSTransformValues, where each value specifies a single operation.
   5682     RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
   5683     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
   5684         if (value->unit != CSSParserValue::Function || !value->function)
   5685             return 0;
   5686 
   5687         // Every primitive requires at least one argument.
   5688         CSSParserValueList* args = value->function->args.get();
   5689         if (!args)
   5690             return 0;
   5691 
   5692         // See if the specified primitive is one we understand.
   5693         TransformOperationInfo info(value->function->name);
   5694         if (info.unknown())
   5695             return 0;
   5696 
   5697         if (!info.hasCorrectArgCount(args->size()))
   5698             return 0;
   5699 
   5700         // Create the new WebKitCSSTransformValue for this operation and add it to our list.
   5701         RefPtr<WebKitCSSTransformValue> transformValue = WebKitCSSTransformValue::create(info.type());
   5702         list->append(transformValue);
   5703 
   5704         // Snag our values.
   5705         CSSParserValue* a = args->current();
   5706         unsigned argNumber = 0;
   5707         while (a) {
   5708             CSSParser::Units unit = info.unit();
   5709 
   5710             if (info.type() == WebKitCSSTransformValue::Rotate3DTransformOperation && argNumber == 3) {
   5711                 // 4th param of rotate3d() is an angle rather than a bare number, validate it as such
   5712                 if (!validUnit(a, FAngle, true))
   5713                     return 0;
   5714             } else if (info.type() == WebKitCSSTransformValue::Translate3DTransformOperation && argNumber == 2) {
   5715                 // 3rd param of translate3d() cannot be a percentage
   5716                 if (!validUnit(a, FLength, true))
   5717                     return 0;
   5718             } else if (info.type() == WebKitCSSTransformValue::TranslateZTransformOperation && argNumber == 0) {
   5719                 // 1st param of translateZ() cannot be a percentage
   5720                 if (!validUnit(a, FLength, true))
   5721                     return 0;
   5722             } else if (info.type() == WebKitCSSTransformValue::PerspectiveTransformOperation && argNumber == 0) {
   5723                 // 1st param of perspective() must be a non-negative number (deprecated) or length.
   5724                 if (!validUnit(a, FNumber | FLength | FNonNeg, true))
   5725                     return 0;
   5726             } else if (!validUnit(a, unit, true))
   5727                 return 0;
   5728 
   5729             // Add the value to the current transform operation.
   5730             transformValue->append(primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit));
   5731 
   5732             a = args->next();
   5733             if (!a)
   5734                 break;
   5735             if (a->unit != CSSParserValue::Operator || a->iValue != ',')
   5736                 return 0;
   5737             a = args->next();
   5738 
   5739             argNumber++;
   5740         }
   5741     }
   5742 
   5743     return list.release();
   5744 }
   5745 
   5746 bool CSSParser::parseTransformOrigin(int propId, int& propId1, int& propId2, int& propId3, RefPtr<CSSValue>& value, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3)
   5747 {
   5748     propId1 = propId;
   5749     propId2 = propId;
   5750     propId3 = propId;
   5751     if (propId == CSSPropertyWebkitTransformOrigin) {
   5752         propId1 = CSSPropertyWebkitTransformOriginX;
   5753         propId2 = CSSPropertyWebkitTransformOriginY;
   5754         propId3 = CSSPropertyWebkitTransformOriginZ;
   5755     }
   5756 
   5757     switch (propId) {
   5758         case CSSPropertyWebkitTransformOrigin:
   5759             if (!parseTransformOriginShorthand(value, value2, value3))
   5760                 return false;
   5761             // parseTransformOriginShorthand advances the m_valueList pointer
   5762             break;
   5763         case CSSPropertyWebkitTransformOriginX: {
   5764             value = parseFillPositionX(m_valueList);
   5765             if (value)
   5766                 m_valueList->next();
   5767             break;
   5768         }
   5769         case CSSPropertyWebkitTransformOriginY: {
   5770             value = parseFillPositionY(m_valueList);
   5771             if (value)
   5772                 m_valueList->next();
   5773             break;
   5774         }
   5775         case CSSPropertyWebkitTransformOriginZ: {
   5776             if (validUnit(m_valueList->current(), FLength, m_strict))
   5777                 value = primitiveValueCache()->createValue(m_valueList->current()->fValue, (CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit);
   5778             if (value)
   5779                 m_valueList->next();
   5780             break;
   5781         }
   5782     }
   5783 
   5784     return value;
   5785 }
   5786 
   5787 bool CSSParser::parsePerspectiveOrigin(int propId, int& propId1, int& propId2, RefPtr<CSSValue>& value, RefPtr<CSSValue>& value2)
   5788 {
   5789     propId1 = propId;
   5790     propId2 = propId;
   5791     if (propId == CSSPropertyWebkitPerspectiveOrigin) {
   5792         propId1 = CSSPropertyWebkitPerspectiveOriginX;
   5793         propId2 = CSSPropertyWebkitPerspectiveOriginY;
   5794     }
   5795 
   5796     switch (propId) {
   5797         case CSSPropertyWebkitPerspectiveOrigin:
   5798             parseFillPosition(m_valueList, value, value2);
   5799             break;
   5800         case CSSPropertyWebkitPerspectiveOriginX: {
   5801             value = parseFillPositionX(m_valueList);
   5802             if (value)
   5803                 m_valueList->next();
   5804             break;
   5805         }
   5806         case CSSPropertyWebkitPerspectiveOriginY: {
   5807             value = parseFillPositionY(m_valueList);
   5808             if (value)
   5809                 m_valueList->next();
   5810             break;
   5811         }
   5812     }
   5813 
   5814     return value;
   5815 }
   5816 
   5817 bool CSSParser::parseTextEmphasisStyle(bool important)
   5818 {
   5819     unsigned valueListSize = m_valueList->size();
   5820 
   5821     RefPtr<CSSPrimitiveValue> fill;
   5822     RefPtr<CSSPrimitiveValue> shape;
   5823 
   5824     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
   5825         if (value->unit == CSSPrimitiveValue::CSS_STRING) {
   5826             if (fill || shape || (valueListSize != 1 && !inShorthand()))
   5827                 return false;
   5828             addProperty(CSSPropertyWebkitTextEmphasisStyle, primitiveValueCache()->createValue(value->string, CSSPrimitiveValue::CSS_STRING), important);
   5829             m_valueList->next();
   5830             return true;
   5831         }
   5832 
   5833         if (value->id == CSSValueNone) {
   5834             if (fill || shape || (valueListSize != 1 && !inShorthand()))
   5835                 return false;
   5836             addProperty(CSSPropertyWebkitTextEmphasisStyle, primitiveValueCache()->createIdentifierValue(CSSValueNone), important);
   5837             m_valueList->next();
   5838             return true;
   5839         }
   5840 
   5841         if (value->id == CSSValueOpen || value->id == CSSValueFilled) {
   5842             if (fill)
   5843                 return false;
   5844             fill = primitiveValueCache()->createIdentifierValue(value->id);
   5845         } else if (value->id == CSSValueDot || value->id == CSSValueCircle || value->id == CSSValueDoubleCircle || value->id == CSSValueTriangle || value->id == CSSValueSesame) {
   5846             if (shape)
   5847                 return false;
   5848             shape = primitiveValueCache()->createIdentifierValue(value->id);
   5849         } else if (!inShorthand())
   5850             return false;
   5851         else
   5852             break;
   5853     }
   5854 
   5855     if (fill && shape) {
   5856         RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
   5857         parsedValues->append(fill.release());
   5858         parsedValues->append(shape.release());
   5859         addProperty(CSSPropertyWebkitTextEmphasisStyle, parsedValues.release(), important);
   5860         return true;
   5861     }
   5862     if (fill) {
   5863         addProperty(CSSPropertyWebkitTextEmphasisStyle, fill.release(), important);
   5864         return true;
   5865     }
   5866     if (shape) {
   5867         addProperty(CSSPropertyWebkitTextEmphasisStyle, shape.release(), important);
   5868         return true;
   5869     }
   5870 
   5871     return false;
   5872 }
   5873 
   5874 bool CSSParser::parseLineBoxContain(bool important)
   5875 {
   5876     LineBoxContain lineBoxContain = LineBoxContainNone;
   5877 
   5878     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
   5879         if (value->id == CSSValueBlock) {
   5880             if (lineBoxContain & LineBoxContainBlock)
   5881                 return false;
   5882             lineBoxContain |= LineBoxContainBlock;
   5883         } else if (value->id == CSSValueInline) {
   5884             if (lineBoxContain & LineBoxContainInline)
   5885                 return false;
   5886             lineBoxContain |= LineBoxContainInline;
   5887         } else if (value->id == CSSValueFont) {
   5888             if (lineBoxContain & LineBoxContainFont)
   5889                 return false;
   5890             lineBoxContain |= LineBoxContainFont;
   5891         } else if (value->id == CSSValueGlyphs) {
   5892             if (lineBoxContain & LineBoxContainGlyphs)
   5893                 return false;
   5894             lineBoxContain |= LineBoxContainGlyphs;
   5895         } else if (value->id == CSSValueReplaced) {
   5896             if (lineBoxContain & LineBoxContainReplaced)
   5897                 return false;
   5898             lineBoxContain |= LineBoxContainReplaced;
   5899         } else if (value->id == CSSValueInlineBox) {
   5900             if (lineBoxContain & LineBoxContainInlineBox)
   5901                 return false;
   5902             lineBoxContain |= LineBoxContainInlineBox;
   5903         } else
   5904             return false;
   5905     }
   5906 
   5907     if (!lineBoxContain)
   5908         return false;
   5909 
   5910     addProperty(CSSPropertyWebkitLineBoxContain, CSSLineBoxContainValue::create(lineBoxContain), important);
   5911     return true;
   5912 }
   5913 
   5914 static inline int yyerror(const char*) { return 1; }
   5915 
   5916 #define END_TOKEN 0
   5917 
   5918 #include "CSSGrammar.h"
   5919 
   5920 int CSSParser::lex(void* yylvalWithoutType)
   5921 {
   5922     YYSTYPE* yylval = static_cast<YYSTYPE*>(yylvalWithoutType);
   5923     int length;
   5924 
   5925     lex();
   5926 
   5927     UChar* t = text(&length);
   5928 
   5929     switch (token()) {
   5930     case WHITESPACE:
   5931     case SGML_CD:
   5932     case INCLUDES:
   5933     case DASHMATCH:
   5934         break;
   5935 
   5936     case URI:
   5937     case STRING:
   5938     case IDENT:
   5939     case NTH:
   5940     case HEX:
   5941     case IDSEL:
   5942     case DIMEN:
   5943     case UNICODERANGE:
   5944     case FUNCTION:
   5945     case ANYFUNCTION:
   5946     case NOTFUNCTION:
   5947     case CALCFUNCTION:
   5948     case MINFUNCTION:
   5949     case MAXFUNCTION:
   5950         yylval->string.characters = t;
   5951         yylval->string.length = length;
   5952         break;
   5953 
   5954     case IMPORT_SYM:
   5955     case PAGE_SYM:
   5956     case MEDIA_SYM:
   5957     case FONT_FACE_SYM:
   5958     case CHARSET_SYM:
   5959     case NAMESPACE_SYM:
   5960     case WEBKIT_KEYFRAMES_SYM:
   5961 
   5962     case IMPORTANT_SYM:
   5963         break;
   5964 
   5965     case QEMS:
   5966         length--;
   5967     case GRADS:
   5968     case TURNS:
   5969         length--;
   5970     case DEGS:
   5971     case RADS:
   5972     case KHERTZ:
   5973     case REMS:
   5974         length--;
   5975     case MSECS:
   5976     case HERTZ:
   5977     case EMS:
   5978     case EXS:
   5979     case PXS:
   5980     case CMS:
   5981     case MMS:
   5982     case INS:
   5983     case PTS:
   5984     case PCS:
   5985         length--;
   5986     case SECS:
   5987     case PERCENTAGE:
   5988         length--;
   5989     case FLOATTOKEN:
   5990     case INTEGER:
   5991         yylval->number = charactersToDouble(t, length);
   5992         break;
   5993 
   5994     default:
   5995         break;
   5996     }
   5997 
   5998     return token();
   5999 }
   6000 
   6001 void CSSParser::recheckAtKeyword(const UChar* str, int len)
   6002 {
   6003     String ruleName(str, len);
   6004     if (equalIgnoringCase(ruleName, "@import"))
   6005         yyTok = IMPORT_SYM;
   6006     else if (equalIgnoringCase(ruleName, "@page"))
   6007         yyTok = PAGE_SYM;
   6008     else if (equalIgnoringCase(ruleName, "@media"))
   6009         yyTok = MEDIA_SYM;
   6010     else if (equalIgnoringCase(ruleName, "@font-face"))
   6011         yyTok = FONT_FACE_SYM;
   6012     else if (equalIgnoringCase(ruleName, "@charset"))
   6013         yyTok = CHARSET_SYM;
   6014     else if (equalIgnoringCase(ruleName, "@namespace"))
   6015         yyTok = NAMESPACE_SYM;
   6016     else if (equalIgnoringCase(ruleName, "@-webkit-keyframes"))
   6017         yyTok = WEBKIT_KEYFRAMES_SYM;
   6018     else if (equalIgnoringCase(ruleName, "@-webkit-mediaquery"))
   6019         yyTok = WEBKIT_MEDIAQUERY_SYM;
   6020 }
   6021 
   6022 UChar* CSSParser::text(int *length)
   6023 {
   6024     UChar* start = yytext;
   6025     int l = yyleng;
   6026     switch (yyTok) {
   6027     case STRING:
   6028         l--;
   6029         /* nobreak */
   6030     case HEX:
   6031     case IDSEL:
   6032         start++;
   6033         l--;
   6034         break;
   6035     case URI:
   6036         // "url("{w}{string}{w}")"
   6037         // "url("{w}{url}{w}")"
   6038         // strip "url(" and ")"
   6039         start += 4;
   6040         l -= 5;
   6041         // strip {w}
   6042         while (l && isHTMLSpace(*start)) {
   6043             ++start;
   6044             --l;
   6045         }
   6046         while (l && isHTMLSpace(start[l - 1]))
   6047             --l;
   6048         if (l && (*start == '"' || *start == '\'')) {
   6049             ASSERT(l >= 2 && start[l - 1] == *start);
   6050             ++start;
   6051             l -= 2;
   6052         }
   6053         break;
   6054     default:
   6055         break;
   6056     }
   6057 
   6058     // process escapes
   6059     UChar* out = start;
   6060     UChar* escape = 0;
   6061 
   6062     bool sawEscape = false;
   6063 
   6064     for (int i = 0; i < l; i++) {
   6065         UChar* current = start + i;
   6066         if (escape == current - 1) {
   6067             if (isASCIIHexDigit(*current))
   6068                 continue;
   6069             if (yyTok == STRING &&
   6070                  (*current == '\n' || *current == '\r' || *current == '\f')) {
   6071                 // ### handle \r\n case
   6072                 if (*current != '\r')
   6073                     escape = 0;
   6074                 continue;
   6075             }
   6076             // in all other cases copy the char to output
   6077             // ###
   6078             *out++ = *current;
   6079             escape = 0;
   6080             continue;
   6081         }
   6082         if (escape == current - 2 && yyTok == STRING &&
   6083              *(current-1) == '\r' && *current == '\n') {
   6084             escape = 0;
   6085             continue;
   6086         }
   6087         if (escape > current - 7 && isASCIIHexDigit(*current))
   6088             continue;
   6089         if (escape) {
   6090             // add escaped char
   6091             unsigned uc = 0;
   6092             escape++;
   6093             while (escape < current) {
   6094                 uc *= 16;
   6095                 uc += toASCIIHexValue(*escape);
   6096                 escape++;
   6097             }
   6098             // can't handle chars outside ucs2
   6099             if (uc > 0xffff)
   6100                 uc = 0xfffd;
   6101             *out++ = uc;
   6102             escape = 0;
   6103             if (isHTMLSpace(*current))
   6104                 continue;
   6105         }
   6106         if (!escape && *current == '\\') {
   6107             escape = current;
   6108             sawEscape = true;
   6109             continue;
   6110         }
   6111         *out++ = *current;
   6112     }
   6113     if (escape) {
   6114         // add escaped char
   6115         unsigned uc = 0;
   6116         escape++;
   6117         while (escape < start+l) {
   6118             uc *= 16;
   6119             uc += toASCIIHexValue(*escape);
   6120             escape++;
   6121         }
   6122         // can't handle chars outside ucs2
   6123         if (uc > 0xffff)
   6124             uc = 0xfffd;
   6125         *out++ = uc;
   6126     }
   6127 
   6128     *length = out - start;
   6129 
   6130     // If we have an unrecognized @-keyword, and if we handled any escapes at all, then
   6131     // we should attempt to adjust yyTok to the correct type.
   6132     if (yyTok == ATKEYWORD && sawEscape)
   6133         recheckAtKeyword(start, *length);
   6134 
   6135     return start;
   6136 }
   6137 
   6138 void CSSParser::countLines()
   6139 {
   6140     for (UChar* current = yytext; current < yytext + yyleng; ++current) {
   6141         if (*current == '\n')
   6142             ++m_lineNumber;
   6143     }
   6144 }
   6145 
   6146 CSSParserSelector* CSSParser::createFloatingSelector()
   6147 {
   6148     CSSParserSelector* selector = new CSSParserSelector;
   6149     m_floatingSelectors.add(selector);
   6150     return selector;
   6151 }
   6152 
   6153 PassOwnPtr<CSSParserSelector> CSSParser::sinkFloatingSelector(CSSParserSelector* selector)
   6154 {
   6155     if (selector) {
   6156         ASSERT(m_floatingSelectors.contains(selector));
   6157         m_floatingSelectors.remove(selector);
   6158     }
   6159     return adoptPtr(selector);
   6160 }
   6161 
   6162 Vector<OwnPtr<CSSParserSelector> >* CSSParser::createFloatingSelectorVector()
   6163 {
   6164     Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >;
   6165     m_floatingSelectorVectors.add(selectorVector);
   6166     return selectorVector;
   6167 }
   6168 
   6169 PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > CSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector)
   6170 {
   6171     if (selectorVector) {
   6172         ASSERT(m_floatingSelectorVectors.contains(selectorVector));
   6173         m_floatingSelectorVectors.remove(selectorVector);
   6174     }
   6175     return adoptPtr(selectorVector);
   6176 }
   6177 
   6178 CSSParserValueList* CSSParser::createFloatingValueList()
   6179 {
   6180     CSSParserValueList* list = new CSSParserValueList;
   6181     m_floatingValueLists.add(list);
   6182     return list;
   6183 }
   6184 
   6185 CSSParserValueList* CSSParser::sinkFloatingValueList(CSSParserValueList* list)
   6186 {
   6187     if (list) {
   6188         ASSERT(m_floatingValueLists.contains(list));
   6189         m_floatingValueLists.remove(list);
   6190     }
   6191     return list;
   6192 }
   6193 
   6194 CSSParserFunction* CSSParser::createFloatingFunction()
   6195 {
   6196     CSSParserFunction* function = new CSSParserFunction;
   6197     m_floatingFunctions.add(function);
   6198     return function;
   6199 }
   6200 
   6201 CSSParserFunction* CSSParser::sinkFloatingFunction(CSSParserFunction* function)
   6202 {
   6203     if (function) {
   6204         ASSERT(m_floatingFunctions.contains(function));
   6205         m_floatingFunctions.remove(function);
   6206     }
   6207     return function;
   6208 }
   6209 
   6210 CSSParserValue& CSSParser::sinkFloatingValue(CSSParserValue& value)
   6211 {
   6212     if (value.unit == CSSParserValue::Function) {
   6213         ASSERT(m_floatingFunctions.contains(value.function));
   6214         m_floatingFunctions.remove(value.function);
   6215     }
   6216     return value;
   6217 }
   6218 
   6219 MediaQueryExp* CSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values)
   6220 {
   6221     m_floatingMediaQueryExp = MediaQueryExp::create(mediaFeature, values);
   6222     return m_floatingMediaQueryExp.get();
   6223 }
   6224 
   6225 PassOwnPtr<MediaQueryExp> CSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression)
   6226 {
   6227     ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp);
   6228     return m_floatingMediaQueryExp.release();
   6229 }
   6230 
   6231 Vector<OwnPtr<MediaQueryExp> >* CSSParser::createFloatingMediaQueryExpList()
   6232 {
   6233     m_floatingMediaQueryExpList = adoptPtr(new Vector<OwnPtr<MediaQueryExp> >);
   6234     return m_floatingMediaQueryExpList.get();
   6235 }
   6236 
   6237 PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > CSSParser::sinkFloatingMediaQueryExpList(Vector<OwnPtr<MediaQueryExp> >* list)
   6238 {
   6239     ASSERT_UNUSED(list, list == m_floatingMediaQueryExpList);
   6240     return m_floatingMediaQueryExpList.release();
   6241 }
   6242 
   6243 MediaQuery* CSSParser::createFloatingMediaQuery(MediaQuery::Restrictor restrictor, const String& mediaType, PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > expressions)
   6244 {
   6245     m_floatingMediaQuery = adoptPtr(new MediaQuery(restrictor, mediaType, expressions));
   6246     return m_floatingMediaQuery.get();
   6247 }
   6248 
   6249 MediaQuery* CSSParser::createFloatingMediaQuery(PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > expressions)
   6250 {
   6251     return createFloatingMediaQuery(MediaQuery::None, "all", expressions);
   6252 }
   6253 
   6254 PassOwnPtr<MediaQuery> CSSParser::sinkFloatingMediaQuery(MediaQuery* query)
   6255 {
   6256     ASSERT_UNUSED(query, query == m_floatingMediaQuery);
   6257     return m_floatingMediaQuery.release();
   6258 }
   6259 
   6260 MediaList* CSSParser::createMediaList()
   6261 {
   6262     RefPtr<MediaList> list = MediaList::create();
   6263     MediaList* result = list.get();
   6264     m_parsedStyleObjects.append(list.release());
   6265     return result;
   6266 }
   6267 
   6268 CSSRule* CSSParser::createCharsetRule(const CSSParserString& charset)
   6269 {
   6270     if (!m_styleSheet)
   6271         return 0;
   6272     RefPtr<CSSCharsetRule> rule = CSSCharsetRule::create(m_styleSheet, charset);
   6273     CSSCharsetRule* result = rule.get();
   6274     m_parsedStyleObjects.append(rule.release());
   6275     return result;
   6276 }
   6277 
   6278 CSSRule* CSSParser::createImportRule(const CSSParserString& url, MediaList* media)
   6279 {
   6280     if (!media || !m_styleSheet || !m_allowImportRules)
   6281         return 0;
   6282     RefPtr<CSSImportRule> rule = CSSImportRule::create(m_styleSheet, url, media);
   6283     CSSImportRule* result = rule.get();
   6284     m_parsedStyleObjects.append(rule.release());
   6285     return result;
   6286 }
   6287 
   6288 CSSRule* CSSParser::createMediaRule(MediaList* media, CSSRuleList* rules)
   6289 {
   6290     if (!media || !rules || !m_styleSheet)
   6291         return 0;
   6292     m_allowImportRules = m_allowNamespaceDeclarations = false;
   6293     RefPtr<CSSMediaRule> rule = CSSMediaRule::create(m_styleSheet, media, rules);
   6294     CSSMediaRule* result = rule.get();
   6295     m_parsedStyleObjects.append(rule.release());
   6296     return result;
   6297 }
   6298 
   6299 CSSRuleList* CSSParser::createRuleList()
   6300 {
   6301     RefPtr<CSSRuleList> list = CSSRuleList::create();
   6302     CSSRuleList* listPtr = list.get();
   6303 
   6304     m_parsedRuleLists.append(list.release());
   6305     return listPtr;
   6306 }
   6307 
   6308 WebKitCSSKeyframesRule* CSSParser::createKeyframesRule()
   6309 {
   6310     m_allowImportRules = m_allowNamespaceDeclarations = false;
   6311     RefPtr<WebKitCSSKeyframesRule> rule = WebKitCSSKeyframesRule::create(m_styleSheet);
   6312     WebKitCSSKeyframesRule* rulePtr = rule.get();
   6313     m_parsedStyleObjects.append(rule.release());
   6314     return rulePtr;
   6315 }
   6316 
   6317 CSSRule* CSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors)
   6318 {
   6319     CSSStyleRule* result = 0;
   6320     markRuleBodyEnd();
   6321     if (selectors) {
   6322         m_allowImportRules = m_allowNamespaceDeclarations = false;
   6323         RefPtr<CSSStyleRule> rule = CSSStyleRule::create(m_styleSheet, m_lastSelectorLineNumber);
   6324         rule->adoptSelectorVector(*selectors);
   6325         if (m_hasFontFaceOnlyValues)
   6326             deleteFontFaceOnlyValues();
   6327         rule->setDeclaration(CSSMutableStyleDeclaration::create(rule.get(), m_parsedProperties, m_numParsedProperties));
   6328         result = rule.get();
   6329         m_parsedStyleObjects.append(rule.release());
   6330         if (m_ruleRangeMap) {
   6331             ASSERT(m_currentRuleData);
   6332             m_currentRuleData->styleSourceData->styleBodyRange = m_ruleBodyRange;
   6333             m_currentRuleData->selectorListRange = m_selectorListRange;
   6334             m_ruleRangeMap->set(result, m_currentRuleData.release());
   6335             m_currentRuleData = CSSRuleSourceData::create();
   6336             m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
   6337             m_inStyleRuleOrDeclaration = false;
   6338         }
   6339     }
   6340     resetSelectorListMarks();
   6341     resetRuleBodyMarks();
   6342     clearProperties();
   6343     return result;
   6344 }
   6345 
   6346 CSSRule* CSSParser::createFontFaceRule()
   6347 {
   6348     m_allowImportRules = m_allowNamespaceDeclarations = false;
   6349     for (unsigned i = 0; i < m_numParsedProperties; ++i) {
   6350         CSSProperty* property = m_parsedProperties[i];
   6351         int id = property->id();
   6352         if ((id == CSSPropertyFontWeight || id == CSSPropertyFontStyle || id == CSSPropertyFontVariant) && property->value()->isPrimitiveValue()) {
   6353             RefPtr<CSSValue> value = property->m_value.release();
   6354             property->m_value = CSSValueList::createCommaSeparated();
   6355             static_cast<CSSValueList*>(property->value())->append(value.release());
   6356         } else if (id == CSSPropertyFontFamily && (!property->value()->isValueList() || static_cast<CSSValueList*>(property->value())->length() != 1)) {
   6357             // Unlike font-family property, font-family descriptor in @font-face rule
   6358             // has to be a value list with exactly one family name. It cannot have a
   6359             // have 'initial' value and cannot 'inherit' from parent.
   6360             // See http://dev.w3.org/csswg/css3-fonts/#font-family-desc
   6361             clearProperties();
   6362             return 0;
   6363         }
   6364     }
   6365     RefPtr<CSSFontFaceRule> rule = CSSFontFaceRule::create(m_styleSheet);
   6366     rule->setDeclaration(CSSMutableStyleDeclaration::create(rule.get(), m_parsedProperties, m_numParsedProperties));
   6367     clearProperties();
   6368     CSSFontFaceRule* result = rule.get();
   6369     m_parsedStyleObjects.append(rule.release());
   6370     return result;
   6371 }
   6372 
   6373 void CSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri)
   6374 {
   6375     if (!m_styleSheet || !m_allowNamespaceDeclarations)
   6376         return;
   6377     m_allowImportRules = false;
   6378     m_styleSheet->addNamespace(this, prefix, uri);
   6379 }
   6380 
   6381 void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers)
   6382 {
   6383     AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
   6384     QualifiedName tag = QualifiedName(namespacePrefix, elementName, determinedNamespace);
   6385     if (!specifiers->isUnknownPseudoElement()) {
   6386         specifiers->setTag(tag);
   6387         return;
   6388     }
   6389 
   6390     specifiers->setRelation(CSSSelector::ShadowDescendant);
   6391     if (CSSParserSelector* history = specifiers->tagHistory()) {
   6392         history->setTag(tag);
   6393         return;
   6394     }
   6395 
   6396     // No need to create an extra element name selector if we are matching any element
   6397     // in any namespace.
   6398     if (elementName == starAtom && m_defaultNamespace == starAtom)
   6399         return;
   6400 
   6401     CSSParserSelector* elementNameSelector = new CSSParserSelector;
   6402     elementNameSelector->setTag(tag);
   6403     specifiers->setTagHistory(elementNameSelector);
   6404 }
   6405 
   6406 
   6407 CSSRule* CSSParser::createPageRule(PassOwnPtr<CSSParserSelector> pageSelector)
   6408 {
   6409     // FIXME: Margin at-rules are ignored.
   6410     m_allowImportRules = m_allowNamespaceDeclarations = false;
   6411     CSSPageRule* pageRule = 0;
   6412     if (pageSelector) {
   6413         RefPtr<CSSPageRule> rule = CSSPageRule::create(m_styleSheet, m_lastSelectorLineNumber);
   6414         Vector<OwnPtr<CSSParserSelector> > selectorVector;
   6415         selectorVector.append(pageSelector);
   6416         rule->adoptSelectorVector(selectorVector);
   6417         rule->setDeclaration(CSSMutableStyleDeclaration::create(rule.get(), m_parsedProperties, m_numParsedProperties));
   6418         pageRule = rule.get();
   6419         m_parsedStyleObjects.append(rule.release());
   6420     }
   6421     clearProperties();
   6422     return pageRule;
   6423 }
   6424 
   6425 CSSRule* CSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */)
   6426 {
   6427     // FIXME: Implement margin at-rule here, using:
   6428     //        - marginBox: margin box
   6429     //        - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_numParsedProperties) are for this at-rule.
   6430     // Don't forget to also update the action for page symbol in CSSGrammar.y such that margin at-rule data is cleared if page_selector is invalid.
   6431 
   6432     endDeclarationsForMarginBox();
   6433     return 0; // until this method is implemented.
   6434 }
   6435 
   6436 void CSSParser::startDeclarationsForMarginBox()
   6437 {
   6438     m_numParsedPropertiesBeforeMarginBox = m_numParsedProperties;
   6439 }
   6440 
   6441 void CSSParser::endDeclarationsForMarginBox()
   6442 {
   6443     ASSERT(m_numParsedPropertiesBeforeMarginBox != INVALID_NUM_PARSED_PROPERTIES);
   6444     rollbackLastProperties(m_numParsedProperties - m_numParsedPropertiesBeforeMarginBox);
   6445     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
   6446 }
   6447 
   6448 void CSSParser::deleteFontFaceOnlyValues()
   6449 {
   6450     ASSERT(m_hasFontFaceOnlyValues);
   6451     int deletedProperties = 0;
   6452 
   6453     for (unsigned i = 0; i < m_numParsedProperties; ++i) {
   6454         CSSProperty* property = m_parsedProperties[i];
   6455         int id = property->id();
   6456         if ((id == CSSPropertyFontWeight || id == CSSPropertyFontStyle || id == CSSPropertyFontVariant) && property->value()->isValueList()) {
   6457             delete property;
   6458             deletedProperties++;
   6459         } else if (deletedProperties)
   6460             m_parsedProperties[i - deletedProperties] = m_parsedProperties[i];
   6461     }
   6462 
   6463     m_numParsedProperties -= deletedProperties;
   6464 }
   6465 
   6466 WebKitCSSKeyframeRule* CSSParser::createKeyframeRule(CSSParserValueList* keys)
   6467 {
   6468     // Create a key string from the passed keys
   6469     String keyString;
   6470     for (unsigned i = 0; i < keys->size(); ++i) {
   6471         float key = (float) keys->valueAt(i)->fValue;
   6472         if (i != 0)
   6473             keyString += ",";
   6474         keyString += String::number(key);
   6475         keyString += "%";
   6476     }
   6477 
   6478     RefPtr<WebKitCSSKeyframeRule> keyframe = WebKitCSSKeyframeRule::create(m_styleSheet);
   6479     keyframe->setKeyText(keyString);
   6480     keyframe->setDeclaration(CSSMutableStyleDeclaration::create(0, m_parsedProperties, m_numParsedProperties));
   6481 
   6482     clearProperties();
   6483 
   6484     WebKitCSSKeyframeRule* keyframePtr = keyframe.get();
   6485     m_parsedStyleObjects.append(keyframe.release());
   6486     return keyframePtr;
   6487 }
   6488 
   6489 void CSSParser::invalidBlockHit()
   6490 {
   6491     if (m_styleSheet && !m_hadSyntacticallyValidCSSRule)
   6492         m_styleSheet->setHasSyntacticallyValidCSSHeader(false);
   6493 }
   6494 
   6495 void CSSParser::updateLastSelectorLineAndPosition()
   6496 {
   6497     m_lastSelectorLineNumber = m_lineNumber;
   6498     markRuleBodyStart();
   6499 }
   6500 
   6501 void CSSParser::markSelectorListStart()
   6502 {
   6503     m_selectorListRange.start = yytext - m_data;
   6504 }
   6505 
   6506 void CSSParser::markSelectorListEnd()
   6507 {
   6508     if (!m_currentRuleData)
   6509         return;
   6510     UChar* listEnd = yytext;
   6511     while (listEnd > m_data + 1) {
   6512         if (isHTMLSpace(*(listEnd - 1)))
   6513             --listEnd;
   6514         else
   6515             break;
   6516     }
   6517     m_selectorListRange.end = listEnd - m_data;
   6518 }
   6519 
   6520 void CSSParser::markRuleBodyStart()
   6521 {
   6522     unsigned offset = yytext - m_data;
   6523     if (*yytext == '{')
   6524         ++offset; // Skip the rule body opening brace.
   6525     if (offset > m_ruleBodyRange.start)
   6526         m_ruleBodyRange.start = offset;
   6527     m_inStyleRuleOrDeclaration = true;
   6528 }
   6529 
   6530 void CSSParser::markRuleBodyEnd()
   6531 {
   6532     unsigned offset = yytext - m_data;
   6533     if (offset > m_ruleBodyRange.end)
   6534         m_ruleBodyRange.end = offset;
   6535 }
   6536 
   6537 void CSSParser::markPropertyStart()
   6538 {
   6539     if (!m_inStyleRuleOrDeclaration)
   6540         return;
   6541     m_propertyRange.start = yytext - m_data;
   6542 }
   6543 
   6544 void CSSParser::markPropertyEnd(bool isImportantFound, bool isPropertyParsed)
   6545 {
   6546     if (!m_inStyleRuleOrDeclaration)
   6547         return;
   6548     unsigned offset = yytext - m_data;
   6549     if (*yytext == ';') // Include semicolon into the property text.
   6550         ++offset;
   6551     m_propertyRange.end = offset;
   6552     if (m_propertyRange.start != UINT_MAX && m_currentRuleData) {
   6553         // This stuff is only executed when the style data retrieval is requested by client.
   6554         const unsigned start = m_propertyRange.start;
   6555         const unsigned end = m_propertyRange.end;
   6556         ASSERT(start < end);
   6557         String propertyString = String(m_data + start, end - start).stripWhiteSpace();
   6558         if (propertyString.endsWith(";", true))
   6559             propertyString = propertyString.left(propertyString.length() - 1);
   6560         Vector<String> propertyComponents;
   6561         size_t colonIndex = propertyString.find(":");
   6562         ASSERT(colonIndex != notFound);
   6563 
   6564         String name = propertyString.left(colonIndex).stripWhiteSpace();
   6565         String value = propertyString.substring(colonIndex + 1, propertyString.length()).stripWhiteSpace();
   6566         // The property range is relative to the declaration start offset.
   6567         m_currentRuleData->styleSourceData->propertyData.append(
   6568             CSSPropertySourceData(name, value, isImportantFound, isPropertyParsed, SourceRange(start - m_ruleBodyRange.start, end - m_ruleBodyRange.start)));
   6569     }
   6570     resetPropertyMarks();
   6571 }
   6572 
   6573 static int cssPropertyID(const UChar* propertyName, unsigned length)
   6574 {
   6575     if (!length)
   6576         return 0;
   6577     if (length > maxCSSPropertyNameLength)
   6578         return 0;
   6579 
   6580     char buffer[maxCSSPropertyNameLength + 1 + 1]; // 1 to turn "apple"/"khtml" into "webkit", 1 for null character
   6581 
   6582     for (unsigned i = 0; i != length; ++i) {
   6583         UChar c = propertyName[i];
   6584         if (c == 0 || c >= 0x7F)
   6585             return 0; // illegal character
   6586         buffer[i] = toASCIILower(c);
   6587     }
   6588     buffer[length] = '\0';
   6589 
   6590     const char* name = buffer;
   6591     if (buffer[0] == '-') {
   6592         // If the prefix is -apple- or -khtml-, change it to -webkit-.
   6593         // This makes the string one character longer.
   6594         if (hasPrefix(buffer, length, "-apple-") || hasPrefix(buffer, length, "-khtml-")) {
   6595             memmove(buffer + 7, buffer + 6, length + 1 - 6);
   6596             memcpy(buffer, "-webkit", 7);
   6597             ++length;
   6598         }
   6599 
   6600         if (hasPrefix(buffer, length, "-webkit")) {
   6601             if (!strcmp(buffer, "-webkit-box-sizing")) {
   6602                 // -webkit-box-sizing worked in Safari 4 and earlier.
   6603                 const char* const boxSizing = "box-sizing";
   6604                 name = boxSizing;
   6605                 length = strlen(boxSizing);
   6606             } else if (!strcmp(buffer, "-webkit-opacity")) {
   6607                 // Honor -webkit-opacity as a synonym for opacity.
   6608                 // This was the only syntax that worked in Safari 1.1, and may be in use on some websites and widgets.
   6609                 const char* const opacity = "opacity";
   6610                 name = opacity;
   6611                 length = strlen(opacity);
   6612 #if PLATFORM(IOS)
   6613             } else if (!strcmp(buffer, "-webkit-hyphenate-locale")) {
   6614                 // Worked in iOS 4.2.
   6615                 const char* const webkitLocale = "-webkit-locale";
   6616                 name = webkitLocale;
   6617                 length = strlen(webkitLocale);
   6618 #endif
   6619             } else if (hasPrefix(buffer + 7, length - 7, "-border-")) {
   6620                 // -webkit-border-*-*-radius worked in Safari 4 and earlier. -webkit-border-radius syntax
   6621                 // differs from border-radius, so it is remains as a distinct property.
   6622                 if (!strcmp(buffer + 15, "top-left-radius")
   6623                         || !strcmp(buffer + 15, "top-right-radius")
   6624                         || !strcmp(buffer + 15, "bottom-right-radius")
   6625                         || !strcmp(buffer + 15, "bottom-left-radius")) {
   6626                     name = buffer + 8;
   6627                     length -= 8;
   6628                 }
   6629             }
   6630         }
   6631     }
   6632 
   6633     const Property* hashTableEntry = findProperty(name, length);
   6634     return hashTableEntry ? hashTableEntry->id : 0;
   6635 }
   6636 
   6637 int cssPropertyID(const String& string)
   6638 {
   6639     return cssPropertyID(string.characters(), string.length());
   6640 }
   6641 
   6642 int cssPropertyID(const CSSParserString& string)
   6643 {
   6644     return cssPropertyID(string.characters, string.length);
   6645 }
   6646 
   6647 int cssValueKeywordID(const CSSParserString& string)
   6648 {
   6649     unsigned length = string.length;
   6650     if (!length)
   6651         return 0;
   6652     if (length > maxCSSValueKeywordLength)
   6653         return 0;
   6654 
   6655     char buffer[maxCSSValueKeywordLength + 1 + 1]; // 1 to turn "apple"/"khtml" into "webkit", 1 for null character
   6656 
   6657     for (unsigned i = 0; i != length; ++i) {
   6658         UChar c = string.characters[i];
   6659         if (c == 0 || c >= 0x7F)
   6660             return 0; // illegal character
   6661         buffer[i] = WTF::toASCIILower(c);
   6662     }
   6663     buffer[length] = '\0';
   6664 
   6665     if (buffer[0] == '-') {
   6666         // If the prefix is -apple- or -khtml-, change it to -webkit-.
   6667         // This makes the string one character longer.
   6668         if (hasPrefix(buffer, length, "-apple-") || hasPrefix(buffer, length, "-khtml-")) {
   6669             memmove(buffer + 7, buffer + 6, length + 1 - 6);
   6670             memcpy(buffer, "-webkit", 7);
   6671             ++length;
   6672         }
   6673     }
   6674 
   6675     const Value* hashTableEntry = findValue(buffer, length);
   6676     return hashTableEntry ? hashTableEntry->id : 0;
   6677 }
   6678 
   6679 // "ident" from the CSS tokenizer, minus backslash-escape sequences
   6680 static bool isCSSTokenizerIdentifier(const String& string)
   6681 {
   6682     const UChar* p = string.characters();
   6683     const UChar* end = p + string.length();
   6684 
   6685     // -?
   6686     if (p != end && p[0] == '-')
   6687         ++p;
   6688 
   6689     // {nmstart}
   6690     if (p == end || !(p[0] == '_' || p[0] >= 128 || isASCIIAlpha(p[0])))
   6691         return false;
   6692     ++p;
   6693 
   6694     // {nmchar}*
   6695     for (; p != end; ++p) {
   6696         if (!(p[0] == '_' || p[0] == '-' || p[0] >= 128 || isASCIIAlphanumeric(p[0])))
   6697             return false;
   6698     }
   6699 
   6700     return true;
   6701 }
   6702 
   6703 // "url" from the CSS tokenizer, minus backslash-escape sequences
   6704 static bool isCSSTokenizerURL(const String& string)
   6705 {
   6706     const UChar* p = string.characters();
   6707     const UChar* end = p + string.length();
   6708 
   6709     for (; p != end; ++p) {
   6710         UChar c = p[0];
   6711         switch (c) {
   6712             case '!':
   6713             case '#':
   6714             case '$':
   6715             case '%':
   6716             case '&':
   6717                 break;
   6718             default:
   6719                 if (c < '*')
   6720                     return false;
   6721                 if (c <= '~')
   6722                     break;
   6723                 if (c < 128)
   6724                     return false;
   6725         }
   6726     }
   6727 
   6728     return true;
   6729 }
   6730 
   6731 // We use single quotes for now because markup.cpp uses double quotes.
   6732 String quoteCSSString(const String& string)
   6733 {
   6734     // For efficiency, we first pre-calculate the length of the quoted string, then we build the actual one.
   6735     // Please see below for the actual logic.
   6736     unsigned quotedStringSize = 2; // Two quotes surrounding the entire string.
   6737     bool afterEscape = false;
   6738     for (unsigned i = 0; i < string.length(); ++i) {
   6739         UChar ch = string[i];
   6740         if (ch == '\\' || ch == '\'') {
   6741             quotedStringSize += 2;
   6742             afterEscape = false;
   6743         } else if (ch < 0x20 || ch == 0x7F) {
   6744             quotedStringSize += 2 + (ch >= 0x10);
   6745             afterEscape = true;
   6746         } else {
   6747             quotedStringSize += 1 + (afterEscape && (isASCIIHexDigit(ch) || ch == ' '));
   6748             afterEscape = false;
   6749         }
   6750     }
   6751 
   6752     StringBuffer buffer(quotedStringSize);
   6753     unsigned index = 0;
   6754     buffer[index++] = '\'';
   6755     afterEscape = false;
   6756     for (unsigned i = 0; i < string.length(); ++i) {
   6757         UChar ch = string[i];
   6758         if (ch == '\\' || ch == '\'') {
   6759             buffer[index++] = '\\';
   6760             buffer[index++] = ch;
   6761             afterEscape = false;
   6762         } else if (ch < 0x20 || ch == 0x7F) { // Control characters.
   6763             buffer[index++] = '\\';
   6764             placeByteAsHexCompressIfPossible(ch, buffer, index, Lowercase);
   6765             afterEscape = true;
   6766         } else {
   6767             // Space character may be required to separate backslash-escape sequence and normal characters.
   6768             if (afterEscape && (isASCIIHexDigit(ch) || ch == ' '))
   6769                 buffer[index++] = ' ';
   6770             buffer[index++] = ch;
   6771             afterEscape = false;
   6772         }
   6773     }
   6774     buffer[index++] = '\'';
   6775 
   6776     ASSERT(quotedStringSize == index);
   6777     return String::adopt(buffer);
   6778 }
   6779 
   6780 String quoteCSSStringIfNeeded(const String& string)
   6781 {
   6782     return isCSSTokenizerIdentifier(string) ? string : quoteCSSString(string);
   6783 }
   6784 
   6785 String quoteCSSURLIfNeeded(const String& string)
   6786 {
   6787     return isCSSTokenizerURL(string) ? string : quoteCSSString(string);
   6788 }
   6789 
   6790 bool isValidNthToken(const CSSParserString& token)
   6791 {
   6792     // The tokenizer checks for the construct of an+b.
   6793     // nth can also accept "odd" or "even" but should not accept any other token.
   6794     return equalIgnoringCase(token, "odd") || equalIgnoringCase(token, "even");
   6795 }
   6796 
   6797 #define YY_DECL int CSSParser::lex()
   6798 #define yyconst const
   6799 typedef int yy_state_type;
   6800 typedef unsigned YY_CHAR;
   6801 // The following line makes sure we treat non-Latin-1 Unicode characters correctly.
   6802 #define YY_SC_TO_UI(c) (c > 0xff ? 0xff : c)
   6803 #define YY_DO_BEFORE_ACTION \
   6804         yytext = yy_bp; \
   6805         yyleng = (int) (yy_cp - yy_bp); \
   6806         yy_hold_char = *yy_cp; \
   6807         *yy_cp = 0; \
   6808         yy_c_buf_p = yy_cp;
   6809 #define YY_BREAK break;
   6810 #define ECHO
   6811 #define YY_RULE_SETUP
   6812 #define INITIAL 0
   6813 #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
   6814 #define yyterminate() yyTok = END_TOKEN; return yyTok
   6815 #define YY_FATAL_ERROR(a)
   6816 // The following line is needed to build the tokenizer with a condition stack.
   6817 // The macro is used in the tokenizer grammar with lines containing
   6818 // BEGIN(mediaqueries) and BEGIN(initial). yy_start acts as index to
   6819 // tokenizer transition table, and 'mediaqueries' and 'initial' are
   6820 // offset multipliers that specify which transitions are active
   6821 // in the tokenizer during in each condition (tokenizer state).
   6822 #define BEGIN yy_start = 1 + 2 *
   6823 
   6824 #include "tokenizer.cpp"
   6825 
   6826 }
   6827