diff options
Diffstat (limited to 'Source/WebCore/css/CSSParser.cpp')
-rw-r--r-- | Source/WebCore/css/CSSParser.cpp | 890 |
1 files changed, 656 insertions, 234 deletions
diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp index 55175a2..b7030b2 100644 --- a/Source/WebCore/css/CSSParser.cpp +++ b/Source/WebCore/css/CSSParser.cpp @@ -36,10 +36,12 @@ #include "CSSImportRule.h" #include "CSSInheritedValue.h" #include "CSSInitialValue.h" +#include "CSSLineBoxContainValue.h" #include "CSSMediaRule.h" #include "CSSMutableStyleDeclaration.h" #include "CSSPageRule.h" #include "CSSPrimitiveValue.h" +#include "CSSPrimitiveValueCache.h" #include "CSSProperty.h" #include "CSSPropertyNames.h" #include "CSSPropertySourceData.h" @@ -71,6 +73,7 @@ #include "WebKitCSSKeyframesRule.h" #include "WebKitCSSTransformValue.h" #include <limits.h> +#include <wtf/HexNumber.h> #include <wtf/dtoa.h> #include <wtf/text/StringBuffer.h> @@ -96,6 +99,7 @@ using namespace WTF; namespace WebCore { static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX; +static const double MAX_SCALE = 1000000; static bool equal(const CSSParserString& a, const char* b) { @@ -176,6 +180,7 @@ CSSParser::~CSSParser() fastFree(m_data); fastDeleteAllValues(m_floatingSelectors); + deleteAllValues(m_floatingSelectorVectors); deleteAllValues(m_floatingValueLists); deleteAllValues(m_floatingFunctions); } @@ -228,7 +233,7 @@ void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string, int start #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); #endif - m_styleSheet = sheet; + setStyleSheet(sheet); m_defaultNamespace = starAtom; // Reset the default namespace. m_ruleRangeMap = ruleRangeMap; if (ruleRangeMap) { @@ -252,7 +257,7 @@ PassRefPtr<CSSRule> CSSParser::parseRule(CSSStyleSheet* sheet, const String& str #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); #endif - m_styleSheet = sheet; + setStyleSheet(sheet); m_allowNamespaceDeclarations = false; setupParser("@-webkit-rule{", string, "} "); cssyyparse(this); @@ -267,7 +272,7 @@ PassRefPtr<CSSRule> CSSParser::parseKeyframeRule(CSSStyleSheet *sheet, const Str #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); #endif - m_styleSheet = sheet; + setStyleSheet(sheet); setupParser("@-webkit-keyframe-rule{ ", string, "} "); cssyyparse(this); #ifdef ANDROID_INSTRUMENT @@ -276,17 +281,174 @@ PassRefPtr<CSSRule> CSSParser::parseKeyframeRule(CSSStyleSheet *sheet, const Str return m_keyframe.release(); } -bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int id, const String& string, bool important) +static inline bool isColorPropertyID(int propertyId) +{ + switch (propertyId) { + case CSSPropertyColor: + case CSSPropertyBackgroundColor: + case CSSPropertyBorderBottomColor: + case CSSPropertyBorderLeftColor: + case CSSPropertyBorderRightColor: + case CSSPropertyBorderTopColor: + case CSSPropertyOutlineColor: + case CSSPropertyTextLineThroughColor: + case CSSPropertyTextOverlineColor: + case CSSPropertyTextUnderlineColor: + case CSSPropertyWebkitBorderAfterColor: + case CSSPropertyWebkitBorderBeforeColor: + case CSSPropertyWebkitBorderEndColor: + case CSSPropertyWebkitBorderStartColor: + case CSSPropertyWebkitColumnRuleColor: + case CSSPropertyWebkitTextEmphasisColor: + case CSSPropertyWebkitTextFillColor: + case CSSPropertyWebkitTextStrokeColor: + return true; + default: + return false; + } +} + +static bool parseColorValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict) +{ + if (!string.length()) + return false; + if (!isColorPropertyID(propertyId)) + return false; + CSSParserString cssString; + cssString.characters = const_cast<UChar*>(string.characters()); + cssString.length = string.length(); + int valueID = cssValueKeywordID(cssString); + bool validPrimitive = false; + if (valueID == CSSValueWebkitText) + validPrimitive = true; + else if (valueID == CSSValueCurrentcolor) + validPrimitive = true; + else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu + || (valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText && !strict)) { + validPrimitive = true; + } + + CSSStyleSheet* stylesheet = static_cast<CSSStyleSheet*>(declaration->stylesheet()); + if (!stylesheet || !stylesheet->document()) + return false; + if (validPrimitive) { + CSSProperty property(propertyId, stylesheet->document()->cssPrimitiveValueCache()->createIdentifierValue(valueID), important); + declaration->addParsedProperty(property); + return true; + } + RGBA32 color; + if (!CSSParser::parseColor(string, color, strict && string[0] != '#')) + return false; + CSSProperty property(propertyId, stylesheet->document()->cssPrimitiveValueCache()->createColorValue(color), important); + declaration->addParsedProperty(property); + return true; +} + +static inline bool isSimpleLengthPropertyID(int propertyId, bool& acceptsNegativeNumbers) +{ + switch (propertyId) { + case CSSPropertyFontSize: + case CSSPropertyHeight: + case CSSPropertyWidth: + case CSSPropertyMinHeight: + case CSSPropertyMinWidth: + case CSSPropertyPaddingBottom: + case CSSPropertyPaddingLeft: + case CSSPropertyPaddingRight: + case CSSPropertyPaddingTop: + case CSSPropertyWebkitLogicalWidth: + case CSSPropertyWebkitLogicalHeight: + case CSSPropertyWebkitMinLogicalWidth: + case CSSPropertyWebkitMinLogicalHeight: + case CSSPropertyWebkitPaddingAfter: + case CSSPropertyWebkitPaddingBefore: + case CSSPropertyWebkitPaddingEnd: + case CSSPropertyWebkitPaddingStart: + acceptsNegativeNumbers = false; + return true; + case CSSPropertyBottom: + case CSSPropertyLeft: + case CSSPropertyMarginBottom: + case CSSPropertyMarginLeft: + case CSSPropertyMarginRight: + case CSSPropertyMarginTop: + case CSSPropertyRight: + case CSSPropertyTextIndent: + case CSSPropertyTop: + case CSSPropertyWebkitMarginAfter: + case CSSPropertyWebkitMarginBefore: + case CSSPropertyWebkitMarginEnd: + case CSSPropertyWebkitMarginStart: + acceptsNegativeNumbers = true; + return true; + default: + return false; + } +} + +static bool parseSimpleLengthValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict) +{ + const UChar* characters = string.characters(); + unsigned length = string.length(); + if (!characters || !length) + return false; + bool acceptsNegativeNumbers; + if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers)) + return false; + + CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER; + if (length > 2 && characters[length - 2] == 'p' && characters[length - 1] == 'x') { + length -= 2; + unit = CSSPrimitiveValue::CSS_PX; + } else if (length > 1 && characters[length - 1] == '%') { + length -= 1; + unit = CSSPrimitiveValue::CSS_PERCENTAGE; + } + + // We rely on charactersToDouble for validation as well. The function + // will set "ok" to "false" if the entire passed-in character range does + // not represent a double. + bool ok; + double number = charactersToDouble(characters, length, &ok); + if (!ok) + return false; + if (unit == CSSPrimitiveValue::CSS_NUMBER) { + if (number && strict) + return false; + unit = CSSPrimitiveValue::CSS_PX; + } + if (number < 0 && !acceptsNegativeNumbers) + return false; + + CSSStyleSheet* stylesheet = static_cast<CSSStyleSheet*>(declaration->stylesheet()); + if (!stylesheet || !stylesheet->document()) + return false; + CSSProperty property(propertyId, stylesheet->document()->cssPrimitiveValueCache()->createValue(number, unit), important); + declaration->addParsedProperty(property); + return true; +} + +bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict) +{ + if (parseSimpleLengthValue(declaration, propertyId, string, important, strict)) + return true; + if (parseColorValue(declaration, propertyId, string, important, strict)) + return true; + CSSParser parser(strict); + return parser.parseValue(declaration, propertyId, string, important); +} + +bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important) { #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); #endif ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet()); - m_styleSheet = static_cast<CSSStyleSheet*>(declaration->stylesheet()); + setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet())); setupParser("@-webkit-value{", string, "} "); - m_id = id; + m_id = propertyId; m_important = important; cssyyparse(this); @@ -341,7 +503,7 @@ bool CSSParser::parseColor(CSSMutableStyleDeclaration* declaration, const String android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); #endif ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet()); - m_styleSheet = static_cast<CSSStyleSheet*>(declaration->stylesheet()); + setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet())); setupParser("@-webkit-decls{color:", string, "} "); cssyyparse(this); @@ -376,7 +538,7 @@ void CSSParser::parseSelector(const String& string, Document* doc, CSSSelectorLi #endif RefPtr<CSSStyleSheet> dummyStyleSheet = CSSStyleSheet::create(doc); - m_styleSheet = dummyStyleSheet.get(); + setStyleSheet(dummyStyleSheet.get()); m_selectorListForParseSelector = &selectorList; setupParser("@-webkit-selector{", string, "}"); @@ -403,7 +565,7 @@ bool CSSParser::parseDeclaration(CSSMutableStyleDeclaration* declaration, const static const unsigned prefixLength = 15; ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet()); - m_styleSheet = static_cast<CSSStyleSheet*>(declaration->stylesheet()); + setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet())); if (styleSourceData) { m_currentRuleData = CSSRuleSourceData::create(); m_currentRuleData->styleSourceData = CSSStyleSourceData::create(); @@ -501,6 +663,12 @@ void CSSParser::clearProperties() m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES; m_hasFontFaceOnlyValues = false; } + +void CSSParser::setStyleSheet(CSSStyleSheet* styleSheet) +{ + m_styleSheet = styleSheet; + m_primitiveValueCache = document() ? document()->cssPrimitiveValueCache() : CSSPrimitiveValueCache::create(); +} Document* CSSParser::document() const { @@ -688,11 +856,14 @@ bool CSSParser::parseValue(int propId, bool important) case CSSPropertyQuotes: // [<string> <string>]+ | none | inherit if (id) validPrimitive = true; + else + return parseQuotes(propId, important); break; - case CSSPropertyUnicodeBidi: // normal | embed | bidi-override | inherit - if (id == CSSValueNormal || - id == CSSValueEmbed || - id == CSSValueBidiOverride) + case CSSPropertyUnicodeBidi: // normal | embed | bidi-override | isolate | inherit + if (id == CSSValueNormal + || id == CSSValueEmbed + || id == CSSValueBidiOverride + || id == CSSValueWebkitIsolate) validPrimitive = true; break; @@ -829,9 +1000,10 @@ bool CSSParser::parseValue(int propId, bool important) break; case CSSPropertyTextAlign: - // left | right | center | justify | webkit_left | webkit_right | webkit_center | start | end | <string> | inherit - if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitCenter) || id == CSSValueStart || id == CSSValueEnd || - value->unit == CSSPrimitiveValue::CSS_STRING) + // left | right | center | justify | webkit_left | webkit_right | webkit_center | webkit_match_parent | + // start | end | <string> | inherit + if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd + || value->unit == CSSPrimitiveValue::CSS_STRING) validPrimitive = true; break; @@ -958,9 +1130,9 @@ bool CSSParser::parseValue(int propId, bool important) if (list->length() != 1) return false; } else if (!m_strict && value->id == CSSValueHand) // MSIE 5 compatibility :/ - list->append(CSSPrimitiveValue::createIdentifier(CSSValuePointer)); + list->append(primitiveValueCache()->createIdentifierValue(CSSValuePointer)); else if (value && ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)) - list->append(CSSPrimitiveValue::createIdentifier(value->id)); + list->append(primitiveValueCache()->createIdentifierValue(value->id)); m_valueList->next(); parsedValue = list.release(); break; @@ -1217,7 +1389,7 @@ bool CSSParser::parseValue(int propId, bool important) case CSSValueUnderline: case CSSValueOverline: case CSSValueLineThrough: - list->append(CSSPrimitiveValue::createIdentifier(value->id)); + list->append(primitiveValueCache()->createIdentifierValue(value->id)); break; default: isValid = false; @@ -1276,19 +1448,19 @@ bool CSSParser::parseValue(int propId, bool important) validPrimitive = validUnit(value, FLength | FPercent, m_strict); if (!validPrimitive) return false; - RefPtr<CSSPrimitiveValue> parsedValue1 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + RefPtr<CSSPrimitiveValue> parsedValue1 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); RefPtr<CSSPrimitiveValue> parsedValue2; if (num == 2) { value = m_valueList->next(); validPrimitive = validUnit(value, FLength | FPercent, m_strict); if (!validPrimitive) return false; - parsedValue2 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + parsedValue2 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); } else parsedValue2 = parsedValue1; RefPtr<Pair> pair = Pair::create(parsedValue1.release(), parsedValue2.release()); - RefPtr<CSSPrimitiveValue> val = CSSPrimitiveValue::create(pair.release()); + RefPtr<CSSPrimitiveValue> val = primitiveValueCache()->createValue(pair.release()); addProperty(propId, val.release(), important); return true; } @@ -1467,7 +1639,7 @@ bool CSSParser::parseValue(int propId, bool important) else { // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property. if (validUnit(value, FNumber | FLength | FNonNeg, m_strict)) { - RefPtr<CSSValue> val = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + RefPtr<CSSValue> val = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); if (val) { addProperty(propId, val.release(), important); return true; @@ -1651,7 +1823,13 @@ bool CSSParser::parseValue(int propId, bool important) validPrimitive = true; break; - case CSSPropertyWebkitHyphenateLocale: + case CSSPropertyWebkitHyphenateLimitBefore: + case CSSPropertyWebkitHyphenateLimitAfter: + if (id == CSSValueAuto || validUnit(value, FInteger | FNonNeg, true)) + validPrimitive = true; + break; + + case CSSPropertyWebkitLocale: if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING) validPrimitive = true; break; @@ -1872,6 +2050,19 @@ bool CSSParser::parseValue(int propId, bool important) case CSSPropertyWebkitTextEmphasisStyle: return parseTextEmphasisStyle(important); + case CSSPropertyWebkitTextOrientation: + // FIXME: For now just support upright and vertical-right. + if (id == CSSValueVerticalRight || id == CSSValueUpright) + validPrimitive = true; + break; + + case CSSPropertyWebkitLineBoxContain: + if (id == CSSValueNone) + validPrimitive = true; + else + return parseLineBoxContain(important); + break; + #ifdef ANDROID_CSS_RING case CSSPropertyWebkitRing: { @@ -1918,13 +2109,13 @@ bool CSSParser::parseValue(int propId, bool important) if (validPrimitive) { if (id != 0) - parsedValue = CSSPrimitiveValue::createIdentifier(id); + parsedValue = primitiveValueCache()->createIdentifierValue(id); else if (value->unit == CSSPrimitiveValue::CSS_STRING) - parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit); + parsedValue = primitiveValueCache()->createValue(value->string, (CSSPrimitiveValue::UnitTypes) value->unit); else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) - parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + parsedValue = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); else if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS) - parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + parsedValue = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); else if (value->unit >= CSSParserValue::Q_EMS) parsedValue = CSSQuirkPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_EMS); m_valueList->next(); @@ -1948,7 +2139,7 @@ PassRefPtr<CSSValue> CSSParser::parseWCSSInputProperty() inputProperty = String(value->string); if (!inputProperty.isEmpty()) - parsedValue = CSSPrimitiveValue::create(inputProperty, CSSPrimitiveValue::CSS_STRING); + parsedValue = primitiveValueCache()->createValue(inputProperty, CSSPrimitiveValue::CSS_STRING); while (m_valueList->next()) { // pass all other values, if any. If we don't do this, @@ -1976,11 +2167,11 @@ void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval) lval = rval; } -static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue) +static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue, CSSPrimitiveValueCache* primitiveValueCache) { if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox || parserValue->id == CSSValueContentBox || parserValue->id == CSSValueWebkitText) { - cssValue = CSSPrimitiveValue::createIdentifier(parserValue->id); + cssValue = primitiveValueCache->createIdentifierValue(parserValue->id); return true; } return false; @@ -2048,7 +2239,7 @@ bool CSSParser::parseFillShorthand(int propId, const int* properties, int numPro addFillValue(repeatYValue, val2.release()); if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) { // Reparse the value as a clip, and see if we succeed. - if (parseBackgroundClip(parserValue, val1)) + if (parseBackgroundClip(parserValue, val1, primitiveValueCache())) addFillValue(clipValue, val1.release()); // The property parsed successfully. else addFillValue(clipValue, CSSInitialValue::createImplicit()); // Some value was used for origin that is not supported by clip. Just reset clip instead. @@ -2365,10 +2556,10 @@ bool CSSParser::parsePage(int propId, bool important) return false; if (value->id == CSSValueAuto) { - addProperty(propId, CSSPrimitiveValue::createIdentifier(value->id), important); + addProperty(propId, primitiveValueCache()->createIdentifierValue(value->id), important); return true; } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) { - addProperty(propId, CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_STRING), important); + addProperty(propId, primitiveValueCache()->createValue(value->string, CSSPrimitiveValue::CSS_STRING), important); return true; } return false; @@ -2410,14 +2601,14 @@ CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedV switch (value->id) { case CSSValueAuto: if (prevParamType == None) { - parsedValues->append(CSSPrimitiveValue::createIdentifier(value->id)); + parsedValues->append(primitiveValueCache()->createIdentifierValue(value->id)); return Auto; } return None; case CSSValueLandscape: case CSSValuePortrait: if (prevParamType == None || prevParamType == PageSize) { - parsedValues->append(CSSPrimitiveValue::createIdentifier(value->id)); + parsedValues->append(primitiveValueCache()->createIdentifierValue(value->id)); return Orientation; } return None; @@ -2432,13 +2623,13 @@ CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedV if (prevParamType == None || prevParamType == Orientation) { // Normalize to Page Size then Orientation order by prepending. // This is not specified by the CSS3 Paged Media specification, but for simpler processing later (CSSStyleSelector::applyPageSizeProperty). - parsedValues->prepend(CSSPrimitiveValue::createIdentifier(value->id)); + parsedValues->prepend(primitiveValueCache()->createIdentifierValue(value->id)); return PageSize; } return None; case 0: if (validUnit(value, FLength | FNonNeg, m_strict) && (prevParamType == None || prevParamType == Length)) { - parsedValues->append(CSSPrimitiveValue::create(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit))); + parsedValues->append(primitiveValueCache()->createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit))); return Length; } return None; @@ -2447,6 +2638,28 @@ CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedV } } +// [ <string> <string> ]+ | inherit | none +// inherit and none are handled in parseValue. +bool CSSParser::parseQuotes(int propId, bool important) +{ + RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated(); + while (CSSParserValue* val = m_valueList->current()) { + RefPtr<CSSValue> parsedValue; + if (val->unit == CSSPrimitiveValue::CSS_STRING) + parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING); + else + break; + values->append(parsedValue.release()); + m_valueList->next(); + } + if (values->length()) { + addProperty(propId, values.release(), important); + m_valueList->next(); + return true; + } + return false; +} + // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit // in CSS 2.1 this got somewhat reduced: // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit @@ -2499,10 +2712,10 @@ bool CSSParser::parseContent(int propId, bool important) case CSSValueNoCloseQuote: case CSSValueNone: case CSSValueNormal: - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); } } else if (val->unit == CSSPrimitiveValue::CSS_STRING) { - parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING); + parsedValue = primitiveValueCache()->createValue(val->string, CSSPrimitiveValue::CSS_STRING); } if (!parsedValue) break; @@ -2539,7 +2752,7 @@ PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args) if (document() && document()->isHTMLDocument()) attrName = attrName.lower(); - return CSSPrimitiveValue::create(attrName, CSSPrimitiveValue::CSS_ATTR); + return primitiveValueCache()->createValue(attrName, CSSPrimitiveValue::CSS_ATTR); } PassRefPtr<CSSValue> CSSParser::parseBackgroundColor() @@ -2547,7 +2760,7 @@ PassRefPtr<CSSValue> CSSParser::parseBackgroundColor() int id = m_valueList->current()->id; if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor || (id >= CSSValueGrey && id < CSSValueWebkitText && !m_strict)) - return CSSPrimitiveValue::createIdentifier(id); + return primitiveValueCache()->createIdentifierValue(id); return parseColor(); } @@ -2571,34 +2784,80 @@ bool CSSParser::parseFillImage(RefPtr<CSSValue>& value) return false; } -PassRefPtr<CSSValue> CSSParser::parseFillPositionXY(CSSParserValueList* valueList, bool& xFound, bool& yFound) +PassRefPtr<CSSValue> CSSParser::parseFillPositionX(CSSParserValueList* valueList) +{ + int id = valueList->current()->id; + if (id == CSSValueLeft || id == CSSValueRight || id == CSSValueCenter) { + int percent = 0; + if (id == CSSValueRight) + percent = 100; + else if (id == CSSValueCenter) + percent = 50; + return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE); + } + if (validUnit(valueList->current(), FPercent | FLength, m_strict)) + return primitiveValueCache()->createValue(valueList->current()->fValue, + (CSSPrimitiveValue::UnitTypes)valueList->current()->unit); + return 0; +} + +PassRefPtr<CSSValue> CSSParser::parseFillPositionY(CSSParserValueList* valueList) +{ + int id = valueList->current()->id; + if (id == CSSValueTop || id == CSSValueBottom || id == CSSValueCenter) { + int percent = 0; + if (id == CSSValueBottom) + percent = 100; + else if (id == CSSValueCenter) + percent = 50; + return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE); + } + if (validUnit(valueList->current(), FPercent | FLength, m_strict)) + return primitiveValueCache()->createValue(valueList->current()->fValue, + (CSSPrimitiveValue::UnitTypes)valueList->current()->unit); + return 0; +} + +PassRefPtr<CSSValue> CSSParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag) { int id = valueList->current()->id; if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) { int percent = 0; if (id == CSSValueLeft || id == CSSValueRight) { - if (xFound) + if (cumulativeFlags & XFillPosition) return 0; - xFound = true; + cumulativeFlags |= XFillPosition; + individualFlag = XFillPosition; if (id == CSSValueRight) percent = 100; } else if (id == CSSValueTop || id == CSSValueBottom) { - if (yFound) + if (cumulativeFlags & YFillPosition) return 0; - yFound = true; + cumulativeFlags |= YFillPosition; + individualFlag = YFillPosition; if (id == CSSValueBottom) percent = 100; - } - else if (id == CSSValueCenter) + } else if (id == CSSValueCenter) { // Center is ambiguous, so we're not sure which position we've found yet, an x or a y. percent = 50; - return CSSPrimitiveValue::create(percent, CSSPrimitiveValue::CSS_PERCENTAGE); + cumulativeFlags |= AmbiguousFillPosition; + individualFlag = AmbiguousFillPosition; + } + return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE); + } + if (validUnit(valueList->current(), FPercent | FLength, m_strict)) { + if (!cumulativeFlags) { + cumulativeFlags |= XFillPosition; + individualFlag = XFillPosition; + } else if (cumulativeFlags & (XFillPosition | AmbiguousFillPosition)) { + cumulativeFlags |= YFillPosition; + individualFlag = YFillPosition; + } else + return 0; + return primitiveValueCache()->createValue(valueList->current()->fValue, + (CSSPrimitiveValue::UnitTypes)valueList->current()->unit); } - if (validUnit(valueList->current(), FPercent | FLength, m_strict)) - return CSSPrimitiveValue::create(valueList->current()->fValue, - (CSSPrimitiveValue::UnitTypes)valueList->current()->unit); - return 0; } @@ -2607,8 +2866,10 @@ void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue CSSParserValue* value = valueList->current(); // Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length. - bool value1IsX = false, value1IsY = false; - value1 = parseFillPositionXY(valueList, value1IsX, value1IsY); + unsigned cumulativeFlags = 0; + FillPositionFlag value1Flag = InvalidFillPosition; + FillPositionFlag value2Flag = InvalidFillPosition; + value1 = parseFillPositionComponent(valueList, cumulativeFlags, value1Flag); if (!value1) return; @@ -2621,9 +2882,8 @@ void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue if (value && value->unit == CSSParserValue::Operator && value->iValue == ',') value = 0; - bool value2IsX = false, value2IsY = false; if (value) { - value2 = parseFillPositionXY(valueList, value2IsX, value2IsY); + value2 = parseFillPositionComponent(valueList, cumulativeFlags, value2Flag); if (value2) valueList->next(); else { @@ -2639,9 +2899,9 @@ void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue // is simply 50%. This is our default. // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center). // For left/right/center, the default of 50% in the y is still correct. - value2 = CSSPrimitiveValue::create(50, CSSPrimitiveValue::CSS_PERCENTAGE); + value2 = primitiveValueCache()->createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE); - if (value1IsY || value2IsX) + if (value1Flag == YFillPosition || value2Flag == XFillPosition) value1.swap(value2); } @@ -2652,20 +2912,20 @@ void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& valu int id = m_valueList->current()->id; if (id == CSSValueRepeatX) { m_implicitShorthand = true; - value1 = CSSPrimitiveValue::createIdentifier(CSSValueRepeat); - value2 = CSSPrimitiveValue::createIdentifier(CSSValueNoRepeat); + value1 = primitiveValueCache()->createIdentifierValue(CSSValueRepeat); + value2 = primitiveValueCache()->createIdentifierValue(CSSValueNoRepeat); m_valueList->next(); return; } if (id == CSSValueRepeatY) { m_implicitShorthand = true; - value1 = CSSPrimitiveValue::createIdentifier(CSSValueNoRepeat); - value2 = CSSPrimitiveValue::createIdentifier(CSSValueRepeat); + value1 = primitiveValueCache()->createIdentifierValue(CSSValueNoRepeat); + value2 = primitiveValueCache()->createIdentifierValue(CSSValueRepeat); m_valueList->next(); return; } if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace) - value1 = CSSPrimitiveValue::createIdentifier(id); + value1 = primitiveValueCache()->createIdentifierValue(id); else { value1 = 0; return; @@ -2681,12 +2941,12 @@ void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& valu id = m_valueList->current()->id; if (value && (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)) { - value2 = CSSPrimitiveValue::createIdentifier(id); + value2 = primitiveValueCache()->createIdentifierValue(id); m_valueList->next(); } else { // If only one value was specified, value2 is the same as value1. m_implicitShorthand = true; - value2 = CSSPrimitiveValue::createIdentifier(static_cast<CSSPrimitiveValue*>(value1.get())->getIdent()); + value2 = primitiveValueCache()->createIdentifierValue(static_cast<CSSPrimitiveValue*>(value1.get())->getIdent()); } } @@ -2696,39 +2956,39 @@ PassRefPtr<CSSValue> CSSParser::parseFillSize(int propId, bool& allowComma) CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueContain || value->id == CSSValueCover) - return CSSPrimitiveValue::createIdentifier(value->id); + return primitiveValueCache()->createIdentifierValue(value->id); RefPtr<CSSPrimitiveValue> parsedValue1; if (value->id == CSSValueAuto) - parsedValue1 = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_UNKNOWN); + parsedValue1 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN); else { if (!validUnit(value, FLength | FPercent, m_strict)) return 0; - parsedValue1 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + parsedValue1 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); } CSSPropertyID property = static_cast<CSSPropertyID>(propId); RefPtr<CSSPrimitiveValue> parsedValue2; if ((value = m_valueList->next())) { if (value->id == CSSValueAuto) - parsedValue2 = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_UNKNOWN); + parsedValue2 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN); else if (value->unit == CSSParserValue::Operator && value->iValue == ',') allowComma = false; else { if (!validUnit(value, FLength | FPercent, m_strict)) return 0; - parsedValue2 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + parsedValue2 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); } } if (!parsedValue2) { if (property == CSSPropertyWebkitBackgroundSize || property == CSSPropertyWebkitMaskSize) parsedValue2 = parsedValue1; else - parsedValue2 = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_UNKNOWN); + parsedValue2 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN); } - return CSSPrimitiveValue::create(Pair::create(parsedValue1.release(), parsedValue2.release())); + return primitiveValueCache()->createValue(Pair::create(parsedValue1.release(), parsedValue2.release())); } bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2, @@ -2779,7 +3039,7 @@ bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2, case CSSPropertyBackgroundAttachment: case CSSPropertyWebkitMaskAttachment: if (val->id == CSSValueScroll || val->id == CSSValueFixed || val->id == CSSValueLocal) { - currValue = CSSPrimitiveValue::createIdentifier(val->id); + currValue = primitiveValueCache()->createIdentifierValue(val->id); m_valueList->next(); } break; @@ -2798,17 +3058,17 @@ bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2, val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox || ((propId == CSSPropertyWebkitBackgroundClip || propId == CSSPropertyWebkitMaskClip) && (val->id == CSSValueText || val->id == CSSValueWebkitText))) { - currValue = CSSPrimitiveValue::createIdentifier(val->id); + currValue = primitiveValueCache()->createIdentifierValue(val->id); m_valueList->next(); } break; case CSSPropertyBackgroundClip: - if (parseBackgroundClip(val, currValue)) + if (parseBackgroundClip(val, currValue, primitiveValueCache())) m_valueList->next(); break; case CSSPropertyBackgroundOrigin: if (val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox) { - currValue = CSSPrimitiveValue::createIdentifier(val->id); + currValue = primitiveValueCache()->createIdentifierValue(val->id); m_valueList->next(); } break; @@ -2819,16 +3079,14 @@ bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2, break; case CSSPropertyBackgroundPositionX: case CSSPropertyWebkitMaskPositionX: { - bool xFound = false, yFound = true; - currValue = parseFillPositionXY(m_valueList, xFound, yFound); + currValue = parseFillPositionX(m_valueList); if (currValue) m_valueList->next(); break; } case CSSPropertyBackgroundPositionY: case CSSPropertyWebkitMaskPositionY: { - bool xFound = true, yFound = false; - currValue = parseFillPositionXY(m_valueList, xFound, yFound); + currValue = parseFillPositionY(m_valueList); if (currValue) m_valueList->next(); break; @@ -2836,7 +3094,7 @@ bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2, case CSSPropertyWebkitBackgroundComposite: case CSSPropertyWebkitMaskComposite: if ((val->id >= CSSValueClear && val->id <= CSSValuePlusLighter) || val->id == CSSValueHighlight) { - currValue = CSSPrimitiveValue::createIdentifier(val->id); + currValue = primitiveValueCache()->createIdentifierValue(val->id); m_valueList->next(); } break; @@ -2903,7 +3161,7 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationDelay() { CSSParserValue* value = m_valueList->current(); if (validUnit(value, FTime, m_strict)) - return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); return 0; } @@ -2911,7 +3169,7 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationDirection() { CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueNormal || value->id == CSSValueAlternate) - return CSSPrimitiveValue::createIdentifier(value->id); + return primitiveValueCache()->createIdentifierValue(value->id); return 0; } @@ -2919,7 +3177,7 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationDuration() { CSSParserValue* value = m_valueList->current(); if (validUnit(value, FTime | FNonNeg, m_strict)) - return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); return 0; } @@ -2927,7 +3185,7 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationFillMode() { CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueNone || value->id == CSSValueForwards || value->id == CSSValueBackwards || value->id == CSSValueBoth) - return CSSPrimitiveValue::createIdentifier(value->id); + return primitiveValueCache()->createIdentifierValue(value->id); return 0; } @@ -2935,9 +3193,9 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationIterationCount() { CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueInfinite) - return CSSPrimitiveValue::createIdentifier(value->id); + return primitiveValueCache()->createIdentifierValue(value->id); if (validUnit(value, FInteger | FNonNeg, m_strict)) - return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); return 0; } @@ -2946,9 +3204,9 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationName() CSSParserValue* value = m_valueList->current(); if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT) { if (value->id == CSSValueNone || (value->unit == CSSPrimitiveValue::CSS_STRING && equalIgnoringCase(value->string, "none"))) { - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache()->createIdentifierValue(CSSValueNone); } else { - return CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_STRING); + return primitiveValueCache()->createValue(value->string, CSSPrimitiveValue::CSS_STRING); } } return 0; @@ -2958,7 +3216,7 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationPlayState() { CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueRunning || value->id == CSSValuePaused) - return CSSPrimitiveValue::createIdentifier(value->id); + return primitiveValueCache()->createIdentifierValue(value->id); return 0; } @@ -2969,11 +3227,11 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationProperty() return 0; int result = cssPropertyID(value->string); if (result) - return CSSPrimitiveValue::createIdentifier(result); + return primitiveValueCache()->createIdentifierValue(result); if (equalIgnoringCase(value->string, "all")) - return CSSPrimitiveValue::createIdentifier(CSSValueAll); + return primitiveValueCache()->createIdentifierValue(CSSValueAll); if (equalIgnoringCase(value->string, "none")) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache()->createIdentifierValue(CSSValueNone); return 0; } @@ -2984,7 +3242,7 @@ bool CSSParser::parseTransformOriginShorthand(RefPtr<CSSValue>& value1, RefPtr<C // now get z if (m_valueList->current()) { if (validUnit(m_valueList->current(), FLength, m_strict)) { - value3 = CSSPrimitiveValue::create(m_valueList->current()->fValue, + value3 = primitiveValueCache()->createValue(m_valueList->current()->fValue, (CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit); m_valueList->next(); return true; @@ -3017,7 +3275,7 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationTimingFunction() CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueEase || value->id == CSSValueLinear || value->id == CSSValueEaseIn || value->id == CSSValueEaseOut || value->id == CSSValueEaseInOut || value->id == CSSValueStepStart || value->id == CSSValueStepEnd) - return CSSPrimitiveValue::createIdentifier(value->id); + return primitiveValueCache()->createIdentifierValue(value->id); // We must be a function. if (value->unit != CSSParserValue::Function) @@ -3207,7 +3465,7 @@ bool CSSParser::parseDashboardRegions(int propId, bool important) if (value->id == CSSValueNone) { if (m_valueList->next()) return false; - addProperty(propId, CSSPrimitiveValue::createIdentifier(value->id), important); + addProperty(propId, primitiveValueCache()->createIdentifierValue(value->id), important); return valid; } @@ -3277,7 +3535,7 @@ bool CSSParser::parseDashboardRegions(int propId, bool important) if (numArgs == DASHBOARD_REGION_SHORT_NUM_PARAMETERS || numArgs == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) { // This originally used CSSValueInvalid by accident. It might be more logical to use something else. - RefPtr<CSSPrimitiveValue> amount = CSSPrimitiveValue::createIdentifier(CSSValueInvalid); + RefPtr<CSSPrimitiveValue> amount = primitiveValueCache()->createIdentifierValue(CSSValueInvalid); region->setTop(amount); region->setRight(amount); @@ -3295,8 +3553,8 @@ bool CSSParser::parseDashboardRegions(int propId, bool important) break; RefPtr<CSSPrimitiveValue> amount = arg->id == CSSValueAuto ? - CSSPrimitiveValue::createIdentifier(CSSValueAuto) : - CSSPrimitiveValue::create(arg->fValue, (CSSPrimitiveValue::UnitTypes) arg->unit); + primitiveValueCache()->createIdentifierValue(CSSValueAuto) : + primitiveValueCache()->createValue(arg->fValue, (CSSPrimitiveValue::UnitTypes) arg->unit); if (i == 0) region->setTop(amount); @@ -3316,7 +3574,7 @@ bool CSSParser::parseDashboardRegions(int propId, bool important) } if (valid) - addProperty(propId, CSSPrimitiveValue::create(firstRegion.release()), important); + addProperty(propId, primitiveValueCache()->createValue(firstRegion.release()), important); return valid; } @@ -3334,11 +3592,11 @@ PassRefPtr<CSSValue> CSSParser::parseCounterContent(CSSParserValueList* args, bo CSSParserValue* i = args->current(); if (i->unit != CSSPrimitiveValue::CSS_IDENT) return 0; - RefPtr<CSSPrimitiveValue> identifier = CSSPrimitiveValue::create(i->string, CSSPrimitiveValue::CSS_STRING); + RefPtr<CSSPrimitiveValue> identifier = primitiveValueCache()->createValue(i->string, CSSPrimitiveValue::CSS_STRING); RefPtr<CSSPrimitiveValue> separator; if (!counters) - separator = CSSPrimitiveValue::create(String(), CSSPrimitiveValue::CSS_STRING); + separator = primitiveValueCache()->createValue(String(), CSSPrimitiveValue::CSS_STRING); else { i = args->next(); if (i->unit != CSSParserValue::Operator || i->iValue != ',') @@ -3348,13 +3606,13 @@ PassRefPtr<CSSValue> CSSParser::parseCounterContent(CSSParserValueList* args, bo if (i->unit != CSSPrimitiveValue::CSS_STRING) return 0; - separator = CSSPrimitiveValue::create(i->string, (CSSPrimitiveValue::UnitTypes) i->unit); + separator = primitiveValueCache()->createValue(i->string, (CSSPrimitiveValue::UnitTypes) i->unit); } RefPtr<CSSPrimitiveValue> listStyle; i = args->next(); if (!i) // Make the list style default decimal - listStyle = CSSPrimitiveValue::create(CSSValueDecimal - CSSValueDisc, CSSPrimitiveValue::CSS_NUMBER); + listStyle = primitiveValueCache()->createValue(CSSValueDecimal - CSSValueDisc, CSSPrimitiveValue::CSS_NUMBER); else { if (i->unit != CSSParserValue::Operator || i->iValue != ',') return 0; @@ -3371,10 +3629,10 @@ PassRefPtr<CSSValue> CSSParser::parseCounterContent(CSSParserValueList* args, bo else return 0; - listStyle = CSSPrimitiveValue::create(ls, (CSSPrimitiveValue::UnitTypes) i->unit); + listStyle = primitiveValueCache()->createValue(ls, (CSSPrimitiveValue::UnitTypes) i->unit); } - return CSSPrimitiveValue::create(Counter::create(identifier.release(), listStyle.release(), separator.release())); + return primitiveValueCache()->createValue(Counter::create(identifier.release(), listStyle.release(), separator.release())); } bool CSSParser::parseShape(int propId, bool important) @@ -3397,8 +3655,8 @@ bool CSSParser::parseShape(int propId, bool important) if (!valid) break; RefPtr<CSSPrimitiveValue> length = a->id == CSSValueAuto ? - CSSPrimitiveValue::createIdentifier(CSSValueAuto) : - CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit); + primitiveValueCache()->createIdentifierValue(CSSValueAuto) : + primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit); if (i == 0) rect->setTop(length); else if (i == 1) @@ -3419,7 +3677,7 @@ bool CSSParser::parseShape(int propId, bool important) i++; } if (valid) { - addProperty(propId, CSSPrimitiveValue::create(rect.release()), important); + addProperty(propId, primitiveValueCache()->createValue(rect.release()), important); m_valueList->next(); return true; } @@ -3441,15 +3699,15 @@ bool CSSParser::parseFont(bool important) } else if (id == CSSValueItalic || id == CSSValueOblique) { if (font->style) return false; - font->style = CSSPrimitiveValue::createIdentifier(id); + font->style = primitiveValueCache()->createIdentifierValue(id); } else if (id == CSSValueSmallCaps) { if (font->variant) return false; - font->variant = CSSPrimitiveValue::createIdentifier(id); + font->variant = primitiveValueCache()->createIdentifierValue(id); } else if (id >= CSSValueBold && id <= CSSValueLighter) { if (font->weight) return false; - font->weight = CSSPrimitiveValue::createIdentifier(id); + font->weight = primitiveValueCache()->createIdentifierValue(id); } else { valid = false; } @@ -3476,7 +3734,7 @@ bool CSSParser::parseFont(bool important) val = CSSValue900; if (val) - font->weight = CSSPrimitiveValue::createIdentifier(val); + font->weight = primitiveValueCache()->createIdentifierValue(val); else valid = false; } else { @@ -3491,18 +3749,18 @@ bool CSSParser::parseFont(bool important) // set undefined values to default if (!font->style) - font->style = CSSPrimitiveValue::createIdentifier(CSSValueNormal); + font->style = primitiveValueCache()->createIdentifierValue(CSSValueNormal); if (!font->variant) - font->variant = CSSPrimitiveValue::createIdentifier(CSSValueNormal); + font->variant = primitiveValueCache()->createIdentifierValue(CSSValueNormal); if (!font->weight) - font->weight = CSSPrimitiveValue::createIdentifier(CSSValueNormal); + font->weight = primitiveValueCache()->createIdentifierValue(CSSValueNormal); // now a font size _must_ come // <absolute-size> | <relative-size> | <length> | <percentage> | inherit if (value->id >= CSSValueXxSmall && value->id <= CSSValueLarger) - font->size = CSSPrimitiveValue::createIdentifier(value->id); + font->size = primitiveValueCache()->createIdentifierValue(value->id); else if (validUnit(value, FLength | FPercent | FNonNeg, m_strict)) - font->size = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + font->size = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); value = m_valueList->next(); if (!font->size || !value) return false; @@ -3515,7 +3773,7 @@ bool CSSParser::parseFont(bool important) if (value->id == CSSValueNormal) { // default value, nothing to do } else if (validUnit(value, FNumber | FLength | FPercent | FNonNeg, m_strict)) - font->lineHeight = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + font->lineHeight = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); else return false; value = m_valueList->next(); @@ -3524,7 +3782,7 @@ bool CSSParser::parseFont(bool important) } if (!font->lineHeight) - font->lineHeight = CSSPrimitiveValue::createIdentifier(CSSValueNormal); + font->lineHeight = primitiveValueCache()->createIdentifierValue(CSSValueNormal); // font family must come now font->family = parseFontFamily(); @@ -3554,7 +3812,7 @@ PassRefPtr<CSSValueList> CSSParser::parseFontFamily() if (currFamily) currFamily->appendSpaceSeparated(value->string.characters, value->string.length); else if (nextValBreaksFont || !nextValIsFontName) - list->append(CSSPrimitiveValue::createIdentifier(value->id)); + list->append(primitiveValueCache()->createIdentifierValue(value->id)); else { RefPtr<FontFamilyValue> newFamily = FontFamilyValue::create(value->string); currFamily = newFamily.get(); @@ -3607,12 +3865,12 @@ bool CSSParser::parseFontStyle(bool important) if (!expectComma) { expectComma = true; if (val->id == CSSValueNormal || val->id == CSSValueItalic || val->id == CSSValueOblique) - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); else if (val->id == CSSValueAll && !values) { // 'all' is only allowed in @font-face and with no other values. Make a value list to // indicate that we are in the @font-face case. values = CSSValueList::createCommaSeparated(); - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); } } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') { expectComma = false; @@ -3654,12 +3912,12 @@ bool CSSParser::parseFontVariant(bool important) if (!expectComma) { expectComma = true; if (val->id == CSSValueNormal || val->id == CSSValueSmallCaps) - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); else if (val->id == CSSValueAll && !values) { // 'all' is only allowed in @font-face and with no other values. Make a value list to // indicate that we are in the @font-face case. values = CSSValueList::createCommaSeparated(); - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); } } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') { expectComma = false; @@ -3702,17 +3960,17 @@ bool CSSParser::parseFontWeight(bool important) expectComma = true; if (val->unit == CSSPrimitiveValue::CSS_IDENT) { if (val->id >= CSSValueNormal && val->id <= CSSValue900) - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); else if (val->id == CSSValueAll && !values) { // 'all' is only allowed in @font-face and with no other values. Make a value list to // indicate that we are in the @font-face case. values = CSSValueList::createCommaSeparated(); - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); } } else if (validUnit(val, FInteger | FNonNeg, false)) { int weight = static_cast<int>(val->fValue); if (!(weight % 100) && weight >= 100 && weight <= 900) - parsedValue = CSSPrimitiveValue::createIdentifier(CSSValue100 + weight / 100 - 1); + parsedValue = primitiveValueCache()->createIdentifierValue(CSSValue100 + weight / 100 - 1); } } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') { expectComma = false; @@ -3903,10 +4161,76 @@ bool CSSParser::parseFontFaceUnicodeRange() return true; } -static inline bool parseColorInt(const UChar*& string, const UChar* end, UChar terminator, int& value) +// Returns the number of characters which form a valid double +// and are terminated by the given terminator character +static int checkForValidDouble(const UChar* string, const UChar* end, const char terminator) +{ + int length = end - string; + if (length < 1) + return 0; + + bool decimalMarkSeen = false; + int processedLength = 0; + + for (int i = 0; i < length; ++i) { + if (string[i] == terminator) { + processedLength = i; + break; + } + if (!isASCIIDigit(string[i])) { + if (!decimalMarkSeen && string[i] == '.') + decimalMarkSeen = true; + else + return 0; + } + } + + if (decimalMarkSeen && processedLength == 1) + return 0; + + return processedLength; +} + +// Returns the number of characters consumed for parsing a valid double +// terminated by the given terminator character +static int parseDouble(const UChar* string, const UChar* end, const char terminator, double& value) +{ + int length = checkForValidDouble(string, end, terminator); + if (!length) + return 0; + + int position = 0; + double localValue = 0; + + // The consumed characters here are guaranteed to be + // ASCII digits with or without a decimal mark + for (; position < length; ++position) { + if (string[position] == '.') + break; + localValue = localValue * 10 + string[position] - '0'; + } + + if (++position == length) { + value = localValue; + return length; + } + + double fraction = 0; + double scale = 1; + + while (position < length && scale < MAX_SCALE) { + fraction = fraction * 10 + string[position++] - '0'; + scale *= 10; + } + + value = localValue + fraction / scale; + return length; +} + +static bool parseColorIntOrPercentage(const UChar*& string, const UChar* end, const char terminator, CSSPrimitiveValue::UnitTypes& expect, int& value) { const UChar* current = string; - int localValue = 0; + double localValue = 0; bool negative = false; while (current != end && isHTMLSpace(*current)) current++; @@ -3917,7 +4241,7 @@ static inline bool parseColorInt(const UChar*& string, const UChar* end, UChar t if (current == end || !isASCIIDigit(*current)) return false; while (current != end && isASCIIDigit(*current)) { - int newValue = localValue * 10 + *current++ - '0'; + double newValue = localValue * 10 + *current++ - '0'; if (newValue >= 255) { // Clamp values at 255. localValue = 255; @@ -3927,12 +4251,42 @@ static inline bool parseColorInt(const UChar*& string, const UChar* end, UChar t } localValue = newValue; } + + if (expect == CSSPrimitiveValue::CSS_NUMBER && (*current == '.' || *current == '%')) + return false; + + if (*current == '.') { + // We already parsed the integral part, try to parse + // the fraction part of the percentage value. + double percentage = 0; + int numCharactersParsed = parseDouble(current, end, '%', percentage); + if (!numCharactersParsed) + return false; + current += numCharactersParsed; + if (*current != '%') + return false; + localValue += percentage; + } + + if (expect == CSSPrimitiveValue::CSS_PERCENTAGE && *current != '%') + return false; + + if (*current == '%') { + expect = CSSPrimitiveValue::CSS_PERCENTAGE; + localValue = localValue / 100.0 * 256.0; + // Clamp values at 255 for percentages over 100% + if (localValue > 255) + localValue = 255; + current++; + } else + expect = CSSPrimitiveValue::CSS_NUMBER; + while (current != end && isHTMLSpace(*current)) current++; if (current == end || *current++ != terminator) return false; // Clamp negative values at zero. - value = negative ? 0 : localValue; + value = negative ? 0 : static_cast<int>(localValue); string = current; return true; } @@ -3950,48 +4304,55 @@ static inline bool isTenthAlpha(const UChar* string, const int length) return false; } -static inline bool parseAlphaValue(const UChar*& string, const UChar* end, UChar terminator, int& value) +static inline bool parseAlphaValue(const UChar*& string, const UChar* end, const char terminator, int& value) { while (string != end && isHTMLSpace(*string)) string++; + bool negative = false; + + if (string != end && *string == '-') { + negative = true; + string++; + } + value = 0; int length = end - string; if (length < 2) return false; - if (string[0] != '0' && string[0] != '1' && string[0] != '.') + if (string[length - 1] != terminator) return false; - if (string[length - 1] != terminator) + if (string[0] != '0' && string[0] != '1' && string[0] != '.') { + if (checkForValidDouble(string, end, terminator)) { + value = negative ? 0 : 255; + string = end; + return true; + } return false; + } if (length == 2 && string[0] != '.') { - value = string[0] == '1' ? 255 : 0; + value = !negative && string[0] == '1' ? 255 : 0; string = end; return true; } if (isTenthAlpha(string, length - 1)) { static const int tenthAlphaValues[] = { 0, 25, 51, 76, 102, 127, 153, 179, 204, 230 }; - value = tenthAlphaValues[string[length - 2] - '0']; + value = negative ? 0 : tenthAlphaValues[string[length - 2] - '0']; string = end; return true; } - Vector<char, 8> bytes(length + 1); - for (int i = 0; i < length; ++i) { - if (!isASCIIDigit(string[i]) && string[i] != '.' && string[i] != terminator) - return false; - bytes[i] = string[i]; - } - bytes[length] = '\0'; - char* foundTerminator; - double d = WTF::strtod(bytes.data(), &foundTerminator); - value = static_cast<int>(d * nextafter(256.0, 0.0)); - string += (foundTerminator - bytes.data()) + 1; - return *foundTerminator == terminator; + double alpha = 0; + if (!parseDouble(string, end, terminator, alpha)) + return false; + value = negative ? 0 : static_cast<int>(alpha * nextafter(256.0, 0.0)); + string = end; + return true; } static inline bool mightBeRGBA(const UChar* characters, unsigned length) @@ -4019,6 +4380,7 @@ bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict) { const UChar* characters = name.characters(); unsigned length = name.length(); + CSSPrimitiveValue::UnitTypes expect = CSSPrimitiveValue::CSS_UNKNOWN; if (!strict && length >= 3) { if (name[0] == '#') { @@ -4038,11 +4400,12 @@ bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict) int green; int blue; int alpha; - if (!parseColorInt(current, end, ',', red)) + + if (!parseColorIntOrPercentage(current, end, ',', expect, red)) return false; - if (!parseColorInt(current, end, ',', green)) + if (!parseColorIntOrPercentage(current, end, ',', expect, green)) return false; - if (!parseColorInt(current, end, ',', blue)) + if (!parseColorIntOrPercentage(current, end, ',', expect, blue)) return false; if (!parseAlphaValue(current, end, ')', alpha)) return false; @@ -4059,11 +4422,11 @@ bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict) int red; int green; int blue; - if (!parseColorInt(current, end, ',', red)) + if (!parseColorIntOrPercentage(current, end, ',', expect, red)) return false; - if (!parseColorInt(current, end, ',', green)) + if (!parseColorIntOrPercentage(current, end, ',', expect, green)) return false; - if (!parseColorInt(current, end, ')', blue)) + if (!parseColorIntOrPercentage(current, end, ')', expect, blue)) return false; if (current != end) return false; @@ -4174,7 +4537,7 @@ PassRefPtr<CSSPrimitiveValue> CSSParser::parseColor(CSSParserValue* value) RGBA32 c = Color::transparent; if (!parseColorFromValue(value ? value : m_valueList->current(), c)) return 0; - return CSSPrimitiveValue::createColor(c); + return primitiveValueCache()->createColorValue(c); } bool CSSParser::parseColorFromValue(CSSParserValue* value, RGBA32& c) @@ -4232,8 +4595,9 @@ bool CSSParser::parseColorFromValue(CSSParserValue* value, RGBA32& c) // This class tracks parsing state for shadow values. If it goes out of scope (e.g., due to an early return) // without the allowBreak bit being set, then it will clean up all of the objects and destroy them. struct ShadowParseContext { - ShadowParseContext(CSSPropertyID prop) + ShadowParseContext(CSSPropertyID prop, CSSPrimitiveValueCache* primitiveValueCache) : property(prop) + , m_primitiveValueCache(primitiveValueCache) , allowX(true) , allowY(false) , allowBlur(false) @@ -4276,7 +4640,7 @@ struct ShadowParseContext { void commitLength(CSSParserValue* v) { - RefPtr<CSSPrimitiveValue> val = CSSPrimitiveValue::create(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); + RefPtr<CSSPrimitiveValue> val = m_primitiveValueCache->createValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); if (allowX) { x = val.release(); @@ -4318,7 +4682,7 @@ struct ShadowParseContext { void commitStyle(CSSParserValue* v) { - style = CSSPrimitiveValue::createIdentifier(v->id); + style = m_primitiveValueCache->createIdentifierValue(v->id); allowStyle = false; if (allowX) allowBreak = false; @@ -4330,6 +4694,7 @@ struct ShadowParseContext { } CSSPropertyID property; + CSSPrimitiveValueCache* m_primitiveValueCache; RefPtr<CSSValueList> values; RefPtr<CSSPrimitiveValue> x; @@ -4350,7 +4715,7 @@ struct ShadowParseContext { bool CSSParser::parseShadow(int propId, bool important) { - ShadowParseContext context(static_cast<CSSPropertyID>(propId)); + ShadowParseContext context(static_cast<CSSPropertyID>(propId), primitiveValueCache()); CSSParserValue* val; while ((val = m_valueList->current())) { // Check for a comma break first. @@ -4386,7 +4751,7 @@ bool CSSParser::parseShadow(int propId, bool important) if (isColor) { if (!context.allowColor) return false; - parsedColor = CSSPrimitiveValue::createIdentifier(val->id); + parsedColor = primitiveValueCache()->createIdentifierValue(val->id); } if (!parsedColor) @@ -4443,11 +4808,11 @@ bool CSSParser::parseReflect(int propId, bool important) val = m_valueList->next(); RefPtr<CSSPrimitiveValue> offset; if (!val) - offset = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_PX); + offset = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_PX); else { if (!validUnit(val, FLength | FPercent, m_strict)) return false; - offset = CSSPrimitiveValue::create(val->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(val->unit)); + offset = primitiveValueCache()->createValue(val->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(val->unit)); } // Now for the mask. @@ -4465,8 +4830,9 @@ bool CSSParser::parseReflect(int propId, bool important) } struct BorderImageParseContext { - BorderImageParseContext() - : m_allowBreak(false) + BorderImageParseContext(CSSPrimitiveValueCache* primitiveValueCache) + : m_primitiveValueCache(primitiveValueCache) + , m_allowBreak(false) , m_allowNumber(false) , m_allowSlash(false) , m_allowWidth(false) @@ -4488,7 +4854,7 @@ struct BorderImageParseContext { void commitImage(PassRefPtr<CSSValue> image) { m_image = image; m_allowNumber = true; } void commitNumber(CSSParserValue* v) { - PassRefPtr<CSSPrimitiveValue> val = CSSPrimitiveValue::create(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); + PassRefPtr<CSSPrimitiveValue> val = m_primitiveValueCache->createValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); if (!m_top) m_top = val; else if (!m_right) @@ -4532,16 +4898,16 @@ struct BorderImageParseContext { { // We need to clone and repeat values for any omissions. if (!m_right) { - m_right = CSSPrimitiveValue::create(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); - m_bottom = CSSPrimitiveValue::create(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); - m_left = CSSPrimitiveValue::create(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + m_right = m_primitiveValueCache->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + m_bottom = m_primitiveValueCache->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + m_left = m_primitiveValueCache->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); } if (!m_bottom) { - m_bottom = CSSPrimitiveValue::create(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); - m_left = CSSPrimitiveValue::create(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType()); + m_bottom = m_primitiveValueCache->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + m_left = m_primitiveValueCache->createValue(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType()); } if (!m_left) - m_left = CSSPrimitiveValue::create(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType()); + m_left = m_primitiveValueCache->createValue(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType()); // Now build a rect value to hold all four of our primitive values. RefPtr<Rect> rect = Rect::create(); @@ -4578,6 +4944,8 @@ struct BorderImageParseContext { // Make our new border image value now. return CSSBorderImageValue::create(m_image, rect.release(), m_horizontalRule, m_verticalRule); } + + CSSPrimitiveValueCache* m_primitiveValueCache; bool m_allowBreak; bool m_allowNumber; @@ -4604,7 +4972,7 @@ struct BorderImageParseContext { bool CSSParser::parseBorderImage(int propId, bool important, RefPtr<CSSValue>& result) { // Look for an image initially. If the first value is not a URI, then we're done. - BorderImageParseContext context; + BorderImageParseContext context(primitiveValueCache()); CSSParserValue* val = m_valueList->current(); if (val->unit == CSSPrimitiveValue::CSS_URI && m_styleSheet) { // FIXME: The completeURL call should be done when using the CSSImageValue, @@ -4638,7 +5006,7 @@ bool CSSParser::parseBorderImage(int propId, bool important, RefPtr<CSSValue>& r if (context.allowNumber() && propId != CSSPropertyWebkitBorderImage) { // Allow the slices to be omitted for images that don't fit to a border. We just set the slices to be 0. - context.m_top = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_NUMBER); + context.m_top = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_NUMBER); context.m_allowBreak = true; } @@ -4693,7 +5061,7 @@ bool CSSParser::parseBorderRadius(int propId, bool important) if (!validUnit(value, FLength | FPercent, m_strict)) return false; - RefPtr<CSSPrimitiveValue> radius = CSSPrimitiveValue::create(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)); + RefPtr<CSSPrimitiveValue> radius = primitiveValueCache()->createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)); if (!indexAfterSlash) { radii[0][i] = radius; @@ -4715,10 +5083,10 @@ bool CSSParser::parseBorderRadius(int propId, bool important) completeBorderRadii(radii[1]); m_implicitShorthand = true; - addProperty(CSSPropertyBorderTopLeftRadius, CSSPrimitiveValue::create(Pair::create(radii[0][0].release(), radii[1][0].release())), important); - addProperty(CSSPropertyBorderTopRightRadius, CSSPrimitiveValue::create(Pair::create(radii[0][1].release(), radii[1][1].release())), important); - addProperty(CSSPropertyBorderBottomRightRadius, CSSPrimitiveValue::create(Pair::create(radii[0][2].release(), radii[1][2].release())), important); - addProperty(CSSPropertyBorderBottomLeftRadius, CSSPrimitiveValue::create(Pair::create(radii[0][3].release(), radii[1][3].release())), important); + addProperty(CSSPropertyBorderTopLeftRadius, primitiveValueCache()->createValue(Pair::create(radii[0][0].release(), radii[1][0].release())), important); + addProperty(CSSPropertyBorderTopRightRadius, primitiveValueCache()->createValue(Pair::create(radii[0][1].release(), radii[1][1].release())), important); + addProperty(CSSPropertyBorderBottomRightRadius, primitiveValueCache()->createValue(Pair::create(radii[0][2].release(), radii[1][2].release())), important); + addProperty(CSSPropertyBorderBottomLeftRadius, primitiveValueCache()->createValue(Pair::create(radii[0][3].release(), radii[1][3].release())), important); m_implicitShorthand = false; return true; } @@ -4735,7 +5103,7 @@ bool CSSParser::parseCounter(int propId, int defaultValue, bool important) switch (state) { case ID: if (val && val->unit == CSSPrimitiveValue::CSS_IDENT) { - counterName = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING); + counterName = primitiveValueCache()->createValue(val->string, CSSPrimitiveValue::CSS_STRING); state = VAL; m_valueList->next(); continue; @@ -4748,8 +5116,8 @@ bool CSSParser::parseCounter(int propId, int defaultValue, bool important) m_valueList->next(); } - list->append(CSSPrimitiveValue::create(Pair::create(counterName.release(), - CSSPrimitiveValue::create(i, CSSPrimitiveValue::CSS_NUMBER)))); + list->append(primitiveValueCache()->createValue(Pair::create(counterName.release(), + primitiveValueCache()->createValue(i, CSSPrimitiveValue::CSS_NUMBER)))); state = ID; continue; } @@ -4766,20 +5134,20 @@ bool CSSParser::parseCounter(int propId, int defaultValue, bool important) } // This should go away once we drop support for -webkit-gradient -static PassRefPtr<CSSPrimitiveValue> parseDeprecatedGradientPoint(CSSParserValue* a, bool horizontal) +static PassRefPtr<CSSPrimitiveValue> parseDeprecatedGradientPoint(CSSParserValue* a, bool horizontal, CSSPrimitiveValueCache* primitiveValueCache) { RefPtr<CSSPrimitiveValue> result; if (a->unit == CSSPrimitiveValue::CSS_IDENT) { if ((equalIgnoringCase(a->string, "left") && horizontal) || (equalIgnoringCase(a->string, "top") && !horizontal)) - result = CSSPrimitiveValue::create(0., CSSPrimitiveValue::CSS_PERCENTAGE); + result = primitiveValueCache->createValue(0., CSSPrimitiveValue::CSS_PERCENTAGE); else if ((equalIgnoringCase(a->string, "right") && horizontal) || (equalIgnoringCase(a->string, "bottom") && !horizontal)) - result = CSSPrimitiveValue::create(100., CSSPrimitiveValue::CSS_PERCENTAGE); + result = primitiveValueCache->createValue(100., CSSPrimitiveValue::CSS_PERCENTAGE); else if (equalIgnoringCase(a->string, "center")) - result = CSSPrimitiveValue::create(50., CSSPrimitiveValue::CSS_PERCENTAGE); + result = primitiveValueCache->createValue(50., CSSPrimitiveValue::CSS_PERCENTAGE); } else if (a->unit == CSSPrimitiveValue::CSS_NUMBER || a->unit == CSSPrimitiveValue::CSS_PERCENTAGE) - result = CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit); + result = primitiveValueCache->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit); return result; } @@ -4804,13 +5172,13 @@ static bool parseDeprecatedGradientColorStop(CSSParser* p, CSSParserValue* a, CS return false; if (equalIgnoringCase(a->function->name, "from(")) - stop.m_position = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_NUMBER); + stop.m_position = p->primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_NUMBER); else - stop.m_position = CSSPrimitiveValue::create(1, CSSPrimitiveValue::CSS_NUMBER); + stop.m_position = p->primitiveValueCache()->createValue(1, CSSPrimitiveValue::CSS_NUMBER); int id = args->current()->id; if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu) - stop.m_color = CSSPrimitiveValue::createIdentifier(id); + stop.m_color = p->primitiveValueCache()->createIdentifierValue(id); else stop.m_color = p->parseColor(args->current()); if (!stop.m_color) @@ -4824,9 +5192,9 @@ static bool parseDeprecatedGradientColorStop(CSSParser* p, CSSParserValue* a, CS CSSParserValue* stopArg = args->current(); if (stopArg->unit == CSSPrimitiveValue::CSS_PERCENTAGE) - stop.m_position = CSSPrimitiveValue::create(stopArg->fValue / 100, CSSPrimitiveValue::CSS_NUMBER); + stop.m_position = p->primitiveValueCache()->createValue(stopArg->fValue / 100, CSSPrimitiveValue::CSS_NUMBER); else if (stopArg->unit == CSSPrimitiveValue::CSS_NUMBER) - stop.m_position = CSSPrimitiveValue::create(stopArg->fValue, CSSPrimitiveValue::CSS_NUMBER); + stop.m_position = p->primitiveValueCache()->createValue(stopArg->fValue, CSSPrimitiveValue::CSS_NUMBER); else return false; @@ -4837,7 +5205,7 @@ static bool parseDeprecatedGradientColorStop(CSSParser* p, CSSParserValue* a, CS stopArg = args->next(); int id = stopArg->id; if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu) - stop.m_color = CSSPrimitiveValue::createIdentifier(id); + stop.m_color = p->primitiveValueCache()->createIdentifierValue(id); else stop.m_color = p->parseColor(stopArg); if (!stop.m_color) @@ -4887,7 +5255,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) a = args->next(); if (!a) return false; - RefPtr<CSSPrimitiveValue> point = parseDeprecatedGradientPoint(a, true); + RefPtr<CSSPrimitiveValue> point = parseDeprecatedGradientPoint(a, true, primitiveValueCache()); if (!point) return false; result->setFirstX(point.release()); @@ -4896,7 +5264,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) a = args->next(); if (!a) return false; - point = parseDeprecatedGradientPoint(a, false); + point = parseDeprecatedGradientPoint(a, false, primitiveValueCache()); if (!point) return false; result->setFirstY(point.release()); @@ -4911,7 +5279,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) a = args->next(); if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER) return false; - static_cast<CSSRadialGradientValue*>(result.get())->setFirstRadius(CSSPrimitiveValue::create(a->fValue, CSSPrimitiveValue::CSS_NUMBER)); + static_cast<CSSRadialGradientValue*>(result.get())->setFirstRadius(primitiveValueCache()->createValue(a->fValue, CSSPrimitiveValue::CSS_NUMBER)); // Comma after the first radius. a = args->next(); @@ -4924,7 +5292,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) a = args->next(); if (!a) return false; - point = parseDeprecatedGradientPoint(a, true); + point = parseDeprecatedGradientPoint(a, true, primitiveValueCache()); if (!point) return false; result->setSecondX(point.release()); @@ -4933,7 +5301,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) a = args->next(); if (!a) return false; - point = parseDeprecatedGradientPoint(a, false); + point = parseDeprecatedGradientPoint(a, false, primitiveValueCache()); if (!point) return false; result->setSecondY(point.release()); @@ -4948,7 +5316,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) a = args->next(); if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER) return false; - static_cast<CSSRadialGradientValue*>(result.get())->setSecondRadius(CSSPrimitiveValue::create(a->fValue, CSSPrimitiveValue::CSS_NUMBER)); + static_cast<CSSRadialGradientValue*>(result.get())->setSecondRadius(primitiveValueCache()->createValue(a->fValue, CSSPrimitiveValue::CSS_NUMBER)); } // We now will accept any number of stops (0 or more). @@ -4977,7 +5345,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) return true; } -static PassRefPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, bool& isHorizontal) +static PassRefPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, bool& isHorizontal, CSSPrimitiveValueCache* primitiveValueCache) { if (a->unit != CSSPrimitiveValue::CSS_IDENT) return 0; @@ -4994,14 +5362,14 @@ static PassRefPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, boo default: return 0; } - return CSSPrimitiveValue::createIdentifier(a->id); + return primitiveValueCache->createIdentifierValue(a->id); } static PassRefPtr<CSSPrimitiveValue> parseGradientColorOrKeyword(CSSParser* p, CSSParserValue* value) { int id = value->id; if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu) - return CSSPrimitiveValue::createIdentifier(id); + return p->primitiveValueCache()->createIdentifierValue(id); return p->parseColor(value); } @@ -5022,7 +5390,7 @@ bool CSSParser::parseLinearGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea bool expectComma = false; // Look for angle. if (validUnit(a, FAngle, true)) { - result->setAngle(CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit)); + result->setAngle(primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit)); a = args->next(); expectComma = true; @@ -5032,7 +5400,7 @@ bool CSSParser::parseLinearGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea RefPtr<CSSPrimitiveValue> location; bool isHorizontal = false; - if ((location = valueFromSideKeyword(a, isHorizontal))) { + if ((location = valueFromSideKeyword(a, isHorizontal, primitiveValueCache()))) { if (isHorizontal) startX = location; else @@ -5040,7 +5408,7 @@ bool CSSParser::parseLinearGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea a = args->next(); if (a) { - if ((location = valueFromSideKeyword(a, isHorizontal))) { + if ((location = valueFromSideKeyword(a, isHorizontal, primitiveValueCache()))) { if (isHorizontal) { if (startX) return false; @@ -5059,7 +5427,7 @@ bool CSSParser::parseLinearGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea } if (!startX && !startY) - startY = CSSPrimitiveValue::createIdentifier(CSSValueTop); + startY = primitiveValueCache()->createIdentifierValue(CSSValueTop); result->setFirstX(startX.release()); result->setFirstY(startY.release()); @@ -5129,7 +5497,7 @@ bool CSSParser::parseRadialGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea switch (a->id) { case CSSValueCircle: case CSSValueEllipse: - shapeValue = CSSPrimitiveValue::createIdentifier(a->id); + shapeValue = primitiveValueCache()->createIdentifierValue(a->id); foundValue = true; break; case CSSValueClosestSide: @@ -5138,7 +5506,7 @@ bool CSSParser::parseRadialGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea case CSSValueFarthestCorner: case CSSValueContain: case CSSValueCover: - sizeValue = CSSPrimitiveValue::createIdentifier(a->id); + sizeValue = primitiveValueCache()->createIdentifierValue(a->id); foundValue = true; break; } @@ -5161,7 +5529,7 @@ bool CSSParser::parseRadialGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea if (!shapeValue && !sizeValue) { if (validUnit(a, FLength | FPercent, m_strict)) { - horizontalSize = CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit); + horizontalSize = primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit); a = args->next(); if (!a) return false; @@ -5170,7 +5538,7 @@ bool CSSParser::parseRadialGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea } if (validUnit(a, FLength | FPercent, m_strict)) { - verticalSize = CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit); + verticalSize = primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit); a = args->next(); if (!a) @@ -5218,7 +5586,7 @@ bool CSSParser::parseGradientColorStops(CSSParserValueList* valueList, CSSGradie a = valueList->next(); if (a) { if (validUnit(a, FLength | FPercent, m_strict)) { - stop.m_position = CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit); + stop.m_position = primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit); a = valueList->next(); } } @@ -5439,7 +5807,7 @@ PassRefPtr<CSSValueList> CSSParser::parseTransform() return 0; // Add the value to the current transform operation. - transformValue->append(CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit)); + transformValue->append(primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit)); a = args->next(); if (!a) @@ -5473,22 +5841,20 @@ bool CSSParser::parseTransformOrigin(int propId, int& propId1, int& propId2, int // parseTransformOriginShorthand advances the m_valueList pointer break; case CSSPropertyWebkitTransformOriginX: { - bool xFound = false, yFound = true; - value = parseFillPositionXY(m_valueList, xFound, yFound); + value = parseFillPositionX(m_valueList); if (value) m_valueList->next(); break; } case CSSPropertyWebkitTransformOriginY: { - bool xFound = true, yFound = false; - value = parseFillPositionXY(m_valueList, xFound, yFound); + value = parseFillPositionY(m_valueList); if (value) m_valueList->next(); break; } case CSSPropertyWebkitTransformOriginZ: { if (validUnit(m_valueList->current(), FLength, m_strict)) - value = CSSPrimitiveValue::create(m_valueList->current()->fValue, (CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit); + value = primitiveValueCache()->createValue(m_valueList->current()->fValue, (CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit); if (value) m_valueList->next(); break; @@ -5512,15 +5878,13 @@ bool CSSParser::parsePerspectiveOrigin(int propId, int& propId1, int& propId2, R parseFillPosition(m_valueList, value, value2); break; case CSSPropertyWebkitPerspectiveOriginX: { - bool xFound = false, yFound = true; - value = parseFillPositionXY(m_valueList, xFound, yFound); + value = parseFillPositionX(m_valueList); if (value) m_valueList->next(); break; } case CSSPropertyWebkitPerspectiveOriginY: { - bool xFound = true, yFound = false; - value = parseFillPositionXY(m_valueList, xFound, yFound); + value = parseFillPositionY(m_valueList); if (value) m_valueList->next(); break; @@ -5541,7 +5905,7 @@ bool CSSParser::parseTextEmphasisStyle(bool important) if (value->unit == CSSPrimitiveValue::CSS_STRING) { if (fill || shape || (valueListSize != 1 && !inShorthand())) return false; - addProperty(CSSPropertyWebkitTextEmphasisStyle, CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_STRING), important); + addProperty(CSSPropertyWebkitTextEmphasisStyle, primitiveValueCache()->createValue(value->string, CSSPrimitiveValue::CSS_STRING), important); m_valueList->next(); return true; } @@ -5549,7 +5913,7 @@ bool CSSParser::parseTextEmphasisStyle(bool important) if (value->id == CSSValueNone) { if (fill || shape || (valueListSize != 1 && !inShorthand())) return false; - addProperty(CSSPropertyWebkitTextEmphasisStyle, CSSPrimitiveValue::createIdentifier(CSSValueNone), important); + addProperty(CSSPropertyWebkitTextEmphasisStyle, primitiveValueCache()->createIdentifierValue(CSSValueNone), important); m_valueList->next(); return true; } @@ -5557,11 +5921,11 @@ bool CSSParser::parseTextEmphasisStyle(bool important) if (value->id == CSSValueOpen || value->id == CSSValueFilled) { if (fill) return false; - fill = CSSPrimitiveValue::createIdentifier(value->id); + fill = primitiveValueCache()->createIdentifierValue(value->id); } else if (value->id == CSSValueDot || value->id == CSSValueCircle || value->id == CSSValueDoubleCircle || value->id == CSSValueTriangle || value->id == CSSValueSesame) { if (shape) return false; - shape = CSSPrimitiveValue::createIdentifier(value->id); + shape = primitiveValueCache()->createIdentifierValue(value->id); } else if (!inShorthand()) return false; else @@ -5587,6 +5951,46 @@ bool CSSParser::parseTextEmphasisStyle(bool important) return false; } +bool CSSParser::parseLineBoxContain(bool important) +{ + LineBoxContain lineBoxContain = LineBoxContainNone; + + for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) { + if (value->id == CSSValueBlock) { + if (lineBoxContain & LineBoxContainBlock) + return false; + lineBoxContain |= LineBoxContainBlock; + } else if (value->id == CSSValueInline) { + if (lineBoxContain & LineBoxContainInline) + return false; + lineBoxContain |= LineBoxContainInline; + } else if (value->id == CSSValueFont) { + if (lineBoxContain & LineBoxContainFont) + return false; + lineBoxContain |= LineBoxContainFont; + } else if (value->id == CSSValueGlyphs) { + if (lineBoxContain & LineBoxContainGlyphs) + return false; + lineBoxContain |= LineBoxContainGlyphs; + } else if (value->id == CSSValueReplaced) { + if (lineBoxContain & LineBoxContainReplaced) + return false; + lineBoxContain |= LineBoxContainReplaced; + } else if (value->id == CSSValueInlineBox) { + if (lineBoxContain & LineBoxContainInlineBox) + return false; + lineBoxContain |= LineBoxContainInlineBox; + } else + return false; + } + + if (!lineBoxContain) + return false; + + addProperty(CSSPropertyWebkitLineBoxContain, CSSLineBoxContainValue::create(lineBoxContain), important); + return true; +} + static inline int yyerror(const char*) { return 1; } #define END_TOKEN 0 @@ -5618,6 +6022,7 @@ int CSSParser::lex(void* yylvalWithoutType) case DIMEN: case UNICODERANGE: case FUNCTION: + case ANYFUNCTION: case NOTFUNCTION: yylval->string.characters = t; yylval->string.length = length; @@ -5831,6 +6236,22 @@ PassOwnPtr<CSSParserSelector> CSSParser::sinkFloatingSelector(CSSParserSelector* return adoptPtr(selector); } +Vector<OwnPtr<CSSParserSelector> >* CSSParser::createFloatingSelectorVector() +{ + Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >; + m_floatingSelectorVectors.add(selectorVector); + return selectorVector; +} + +PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > CSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector) +{ + if (selectorVector) { + ASSERT(m_floatingSelectorVectors.contains(selectorVector)); + m_floatingSelectorVectors.remove(selectorVector); + } + return adoptPtr(selectorVector); +} + CSSParserValueList* CSSParser::createFloatingValueList() { CSSParserValueList* list = new CSSParserValueList; @@ -6041,9 +6462,6 @@ void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePre return; } - if (Document* doc = document()) - doc->setUsesDescendantRules(true); - specifiers->setRelation(CSSSelector::ShadowDescendant); if (CSSParserSelector* history = specifiers->tagHistory()) { history->setTag(tag); @@ -6266,6 +6684,13 @@ static int cssPropertyID(const UChar* propertyName, unsigned length) const char* const opacity = "opacity"; name = opacity; length = strlen(opacity); +#if PLATFORM(IOS) + } else if (!strcmp(buffer, "-webkit-hyphenate-locale")) { + // Worked in iOS 4.2. + const char* const webkitLocale = "-webkit-locale"; + name = webkitLocale; + length = strlen(webkitLocale); +#endif } else if (hasPrefix(buffer + 7, length - 7, "-border-")) { // -webkit-border-*-*-radius worked in Safari 4 and earlier. -webkit-border-radius syntax // differs from border-radius, so it is remains as a distinct property. @@ -6410,11 +6835,8 @@ String quoteCSSString(const String& string) buffer[index++] = ch; afterEscape = false; } else if (ch < 0x20 || ch == 0x7F) { // Control characters. - static const char hexDigits[17] = "0123456789abcdef"; buffer[index++] = '\\'; - if (ch >= 0x10) - buffer[index++] = hexDigits[ch >> 4]; - buffer[index++] = hexDigits[ch & 0xF]; + placeByteAsHexCompressIfPossible(ch, buffer, index, Lowercase); afterEscape = true; } else { // Space character may be required to separate backslash-escape sequence and normal characters. |