| /* |
| * Copyright (C) 2003 Lars Knoll (knoll@kde.org) |
| * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) |
| * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. |
| * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> |
| * Copyright (C) 2008 Eric Seidel <eric@webkit.org> |
| * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) |
| * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. |
| * Copyright (C) 2012 Intel Corporation. All rights reserved. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| |
| #include "config.h" |
| #include "CSSParser.h" |
| |
| #include "CSSAspectRatioValue.h" |
| #include "CSSBasicShapes.h" |
| #include "CSSBorderImage.h" |
| #include "CSSCanvasValue.h" |
| #include "CSSCrossfadeValue.h" |
| #include "CSSCursorImageValue.h" |
| #include "CSSFontFaceRule.h" |
| #include "CSSFontFaceSrcValue.h" |
| #include "CSSFunctionValue.h" |
| #include "CSSGradientValue.h" |
| #include "CSSImageValue.h" |
| #include "CSSInheritedValue.h" |
| #include "CSSInitialValue.h" |
| #include "CSSLineBoxContainValue.h" |
| #include "CSSMediaRule.h" |
| #include "CSSPageRule.h" |
| #include "CSSPrimitiveValue.h" |
| #include "CSSPropertySourceData.h" |
| #include "CSSReflectValue.h" |
| #include "CSSSelector.h" |
| #include "CSSStyleSheet.h" |
| #include "CSSTimingFunctionValue.h" |
| #include "CSSUnicodeRangeValue.h" |
| #include "CSSValueKeywords.h" |
| #include "CSSValueList.h" |
| #include "CSSValuePool.h" |
| #if ENABLE(CSS_VARIABLES) |
| #include "CSSVariableValue.h" |
| #endif |
| #include "Counter.h" |
| #include "Document.h" |
| #include "FloatConversion.h" |
| #include "FontFeatureValue.h" |
| #include "FontValue.h" |
| #include "HTMLParserIdioms.h" |
| #include "HashTools.h" |
| #include "HistogramSupport.h" |
| #include "MediaList.h" |
| #include "MediaQueryExp.h" |
| #include "Page.h" |
| #include "PageConsole.h" |
| #include "Pair.h" |
| #include "Rect.h" |
| #include "RenderTheme.h" |
| #include "RuntimeEnabledFeatures.h" |
| #include "SVGParserUtilities.h" |
| #include "Settings.h" |
| #include "ShadowValue.h" |
| #include "StylePropertySet.h" |
| #include "StylePropertyShorthand.h" |
| #include "StyleRule.h" |
| #include "StyleRuleImport.h" |
| #include "StyleSheetContents.h" |
| #include "TextEncoding.h" |
| #include "WebKitCSSKeyframeRule.h" |
| #include "WebKitCSSKeyframesRule.h" |
| #include "WebKitCSSRegionRule.h" |
| #include "WebKitCSSTransformValue.h" |
| #include <limits.h> |
| #include <wtf/BitArray.h> |
| #include <wtf/HexNumber.h> |
| #include <wtf/dtoa.h> |
| #include <wtf/text/StringBuffer.h> |
| #include <wtf/text/StringBuilder.h> |
| #include <wtf/text/StringImpl.h> |
| |
| #if ENABLE(CSS_IMAGE_SET) |
| #include "CSSImageSetValue.h" |
| #endif |
| |
| #if ENABLE(CSS_FILTERS) |
| #include "WebKitCSSFilterValue.h" |
| #if ENABLE(SVG) |
| #include "WebKitCSSSVGDocumentValue.h" |
| #endif |
| #endif |
| |
| #if ENABLE(CSS_SHADERS) |
| #include "WebKitCSSArrayFunctionValue.h" |
| #include "WebKitCSSMatFunctionValue.h" |
| #include "WebKitCSSMixFunctionValue.h" |
| #include "WebKitCSSShaderValue.h" |
| #endif |
| |
| #if ENABLE(DASHBOARD_SUPPORT) |
| #include "DashboardRegion.h" |
| #endif |
| |
| #define YYDEBUG 0 |
| |
| #if YYDEBUG > 0 |
| extern int cssyydebug; |
| #endif |
| |
| extern int cssyyparse(WebCore::CSSParser*); |
| |
| using namespace std; |
| using namespace WTF; |
| |
| namespace { |
| |
| enum PropertyType { |
| PropertyExplicit, |
| PropertyImplicit |
| }; |
| |
| class ImplicitScope { |
| WTF_MAKE_NONCOPYABLE(ImplicitScope); |
| public: |
| ImplicitScope(WebCore::CSSParser* parser, PropertyType propertyType) |
| : m_parser(parser) |
| { |
| m_parser->m_implicitShorthand = propertyType == PropertyImplicit; |
| } |
| |
| ~ImplicitScope() |
| { |
| m_parser->m_implicitShorthand = false; |
| } |
| |
| private: |
| WebCore::CSSParser* m_parser; |
| }; |
| |
| } // namespace |
| |
| namespace WebCore { |
| |
| static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX; |
| static const double MAX_SCALE = 1000000; |
| |
| template <unsigned N> |
| static bool equal(const CSSParserString& a, const char (&b)[N]) |
| { |
| unsigned length = N - 1; // Ignore the trailing null character |
| if (a.length() != length) |
| return false; |
| |
| return a.is8Bit() ? WTF::equal(a.characters8(), reinterpret_cast<const LChar*>(b), length) : WTF::equal(a.characters16(), reinterpret_cast<const LChar*>(b), length); |
| } |
| |
| template <unsigned N> |
| static bool equalIgnoringCase(const CSSParserString& a, const char (&b)[N]) |
| { |
| unsigned length = N - 1; // Ignore the trailing null character |
| if (a.length() != length) |
| return false; |
| |
| return a.is8Bit() ? WTF::equalIgnoringCase(b, a.characters8(), length) : WTF::equalIgnoringCase(b, a.characters16(), length); |
| } |
| |
| template <unsigned N> |
| static bool equalIgnoringCase(CSSParserValue* value, const char (&b)[N]) |
| { |
| ASSERT(value->unit == CSSPrimitiveValue::CSS_IDENT || value->unit == CSSPrimitiveValue::CSS_STRING); |
| return equalIgnoringCase(value->string, b); |
| } |
| |
| static bool hasPrefix(const char* string, unsigned length, const char* prefix) |
| { |
| for (unsigned i = 0; i < length; ++i) { |
| if (!prefix[i]) |
| return true; |
| if (string[i] != prefix[i]) |
| return false; |
| } |
| return false; |
| } |
| |
| static PassRefPtr<CSSPrimitiveValue> createPrimitiveValuePair(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second) |
| { |
| return cssValuePool().createValue(Pair::create(first, second)); |
| } |
| |
| class AnimationParseContext { |
| public: |
| AnimationParseContext() |
| : m_animationPropertyKeywordAllowed(true) |
| , m_firstAnimationCommitted(false) |
| , m_hasSeenAnimationPropertyKeyword(false) |
| { |
| } |
| |
| void commitFirstAnimation() |
| { |
| m_firstAnimationCommitted = true; |
| } |
| |
| bool hasCommittedFirstAnimation() const |
| { |
| return m_firstAnimationCommitted; |
| } |
| |
| void commitAnimationPropertyKeyword() |
| { |
| m_animationPropertyKeywordAllowed = false; |
| } |
| |
| bool animationPropertyKeywordAllowed() const |
| { |
| return m_animationPropertyKeywordAllowed; |
| } |
| |
| bool hasSeenAnimationPropertyKeyword() const |
| { |
| return m_hasSeenAnimationPropertyKeyword; |
| } |
| |
| void sawAnimationPropertyKeyword() |
| { |
| m_hasSeenAnimationPropertyKeyword = true; |
| } |
| |
| private: |
| bool m_animationPropertyKeywordAllowed; |
| bool m_firstAnimationCommitted; |
| bool m_hasSeenAnimationPropertyKeyword; |
| }; |
| |
| const CSSParserContext& strictCSSParserContext() |
| { |
| DEFINE_STATIC_LOCAL(CSSParserContext, strictContext, (CSSStrictMode)); |
| return strictContext; |
| } |
| |
| CSSParserContext::CSSParserContext(CSSParserMode mode, const KURL& baseURL) |
| : baseURL(baseURL) |
| , mode(mode) |
| , isHTMLDocument(false) |
| , isCSSCustomFilterEnabled(false) |
| , isCSSStickyPositionEnabled(false) |
| , isCSSRegionsEnabled(false) |
| , isCSSCompositingEnabled(false) |
| , isCSSGridLayoutEnabled(false) |
| #if ENABLE(CSS_VARIABLES) |
| , isCSSVariablesEnabled(false) |
| #endif |
| , needsSiteSpecificQuirks(false) |
| , enforcesCSSMIMETypeInNoQuirksMode(true) |
| , useLegacyBackgroundSizeShorthandBehavior(false) |
| { |
| } |
| |
| CSSParserContext::CSSParserContext(Document* document, const KURL& baseURL, const String& charset) |
| : baseURL(baseURL.isNull() ? document->baseURL() : baseURL) |
| , charset(charset) |
| , mode(document->inQuirksMode() ? CSSQuirksMode : CSSStrictMode) |
| , isHTMLDocument(document->isHTMLDocument()) |
| , isCSSCustomFilterEnabled(document->settings() ? document->settings()->isCSSCustomFilterEnabled() : false) |
| , isCSSStickyPositionEnabled(document->cssStickyPositionEnabled()) |
| , isCSSRegionsEnabled(document->cssRegionsEnabled()) |
| , isCSSCompositingEnabled(document->cssCompositingEnabled()) |
| , isCSSGridLayoutEnabled(document->cssGridLayoutEnabled()) |
| #if ENABLE(CSS_VARIABLES) |
| , isCSSVariablesEnabled(document->settings() ? document->settings()->cssVariablesEnabled() : false) |
| #endif |
| , needsSiteSpecificQuirks(document->settings() ? document->settings()->needsSiteSpecificQuirks() : false) |
| , enforcesCSSMIMETypeInNoQuirksMode(!document->settings() || document->settings()->enforceCSSMIMETypeInNoQuirksMode()) |
| , useLegacyBackgroundSizeShorthandBehavior(document->settings() ? document->settings()->useLegacyBackgroundSizeShorthandBehavior() : false) |
| { |
| } |
| |
| bool operator==(const CSSParserContext& a, const CSSParserContext& b) |
| { |
| return a.baseURL == b.baseURL |
| && a.charset == b.charset |
| && a.mode == b.mode |
| && a.isHTMLDocument == b.isHTMLDocument |
| && a.isCSSCustomFilterEnabled == b.isCSSCustomFilterEnabled |
| && a.isCSSStickyPositionEnabled == b.isCSSStickyPositionEnabled |
| && a.isCSSRegionsEnabled == b.isCSSRegionsEnabled |
| && a.isCSSCompositingEnabled == b.isCSSCompositingEnabled |
| && a.isCSSGridLayoutEnabled == b.isCSSGridLayoutEnabled |
| #if ENABLE(CSS_VARIABLES) |
| && a.isCSSVariablesEnabled == b.isCSSVariablesEnabled |
| #endif |
| && a.needsSiteSpecificQuirks == b.needsSiteSpecificQuirks |
| && a.enforcesCSSMIMETypeInNoQuirksMode == b.enforcesCSSMIMETypeInNoQuirksMode |
| && a.useLegacyBackgroundSizeShorthandBehavior == b.useLegacyBackgroundSizeShorthandBehavior; |
| } |
| |
| CSSParser::CSSParser(const CSSParserContext& context) |
| : m_context(context) |
| , m_important(false) |
| , m_id(CSSPropertyInvalid) |
| , m_styleSheet(0) |
| #if ENABLE(CSS3_CONDITIONAL_RULES) |
| , m_supportsCondition(false) |
| #endif |
| , m_selectorListForParseSelector(0) |
| , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES) |
| , m_inParseShorthand(0) |
| , m_currentShorthand(CSSPropertyInvalid) |
| , m_implicitShorthand(false) |
| , m_hasFontFaceOnlyValues(false) |
| , m_hadSyntacticallyValidCSSRule(false) |
| , m_logErrors(false) |
| #if ENABLE(CSS_SHADERS) |
| , m_inFilterRule(false) |
| #endif |
| , m_defaultNamespace(starAtom) |
| , m_parsedTextPrefixLength(0) |
| , m_propertyRange(UINT_MAX, UINT_MAX) |
| , m_ruleSourceDataResult(0) |
| , m_parsingMode(NormalMode) |
| , m_is8BitSource(false) |
| , m_currentCharacter8(0) |
| , m_currentCharacter16(0) |
| , m_length(0) |
| , m_token(0) |
| , m_lineNumber(0) |
| , m_tokenStartLineNumber(0) |
| , m_lastSelectorLineNumber(0) |
| , m_allowImportRules(true) |
| , m_allowNamespaceDeclarations(true) |
| #if ENABLE(CSS_DEVICE_ADAPTATION) |
| , m_inViewport(false) |
| #endif |
| { |
| #if YYDEBUG > 0 |
| cssyydebug = 1; |
| #endif |
| m_tokenStart.ptr8 = 0; |
| CSSPropertySourceData::init(); |
| } |
| |
| CSSParser::~CSSParser() |
| { |
| clearProperties(); |
| |
| deleteAllValues(m_floatingSelectors); |
| deleteAllValues(m_floatingSelectorVectors); |
| deleteAllValues(m_floatingValueLists); |
| deleteAllValues(m_floatingFunctions); |
| } |
| |
| template <typename CharacterType> |
| ALWAYS_INLINE static void makeLower(const CharacterType* input, CharacterType* output, unsigned length) |
| { |
| // FIXME: If we need Unicode lowercasing here, then we probably want the real kind |
| // that can potentially change the length of the string rather than the character |
| // by character kind. If we don't need Unicode lowercasing, it would be good to |
| // simplify this function. |
| |
| if (charactersAreAllASCII(input, length)) { |
| // Fast case for all-ASCII. |
| for (unsigned i = 0; i < length; i++) |
| output[i] = toASCIILower(input[i]); |
| } else { |
| for (unsigned i = 0; i < length; i++) |
| output[i] = Unicode::toLower(input[i]); |
| } |
| } |
| |
| void CSSParserString::lower() |
| { |
| if (is8Bit()) { |
| makeLower(characters8(), characters8(), length()); |
| return; |
| } |
| |
| makeLower(characters16(), characters16(), length()); |
| } |
| |
| AtomicString CSSParserString::lowerSubstring(unsigned position, unsigned length) const |
| { |
| ASSERT(m_length >= position + length); |
| |
| RefPtr<StringImpl> result; |
| |
| if (is8Bit()) { |
| LChar* buffer; |
| result = StringImpl::createUninitialized(length, buffer); |
| makeLower(characters8() + position, buffer, length); |
| } else { |
| UChar* buffer = 0; |
| result = StringImpl::createUninitialized(length, buffer); |
| makeLower(characters16() + position, buffer, length); |
| } |
| |
| return AtomicString(result); |
| } |
| |
| void CSSParser::setupParser(const char* prefix, unsigned prefixLength, const String& string, const char* suffix, unsigned suffixLength) |
| { |
| m_parsedTextPrefixLength = prefixLength; |
| unsigned stringLength = string.length(); |
| unsigned length = stringLength + m_parsedTextPrefixLength + suffixLength + 1; |
| m_length = length; |
| |
| if (!stringLength || string.is8Bit()) { |
| m_dataStart8 = adoptArrayPtr(new LChar[length]); |
| for (unsigned i = 0; i < m_parsedTextPrefixLength; i++) |
| m_dataStart8[i] = prefix[i]; |
| |
| if (stringLength) |
| memcpy(m_dataStart8.get() + m_parsedTextPrefixLength, string.characters8(), stringLength * sizeof(LChar)); |
| |
| unsigned start = m_parsedTextPrefixLength + stringLength; |
| unsigned end = start + suffixLength; |
| for (unsigned i = start; i < end; i++) |
| m_dataStart8[i] = suffix[i - start]; |
| |
| m_dataStart8[length - 1] = 0; |
| |
| m_is8BitSource = true; |
| m_currentCharacter8 = m_dataStart8.get(); |
| m_currentCharacter16 = 0; |
| setTokenStart<LChar>(m_currentCharacter8); |
| m_lexFunc = &CSSParser::realLex<LChar>; |
| return; |
| } |
| |
| m_dataStart16 = adoptArrayPtr(new UChar[length]); |
| for (unsigned i = 0; i < m_parsedTextPrefixLength; i++) |
| m_dataStart16[i] = prefix[i]; |
| |
| memcpy(m_dataStart16.get() + m_parsedTextPrefixLength, string.characters(), stringLength * sizeof(UChar)); |
| |
| unsigned start = m_parsedTextPrefixLength + stringLength; |
| unsigned end = start + suffixLength; |
| for (unsigned i = start; i < end; i++) |
| m_dataStart16[i] = suffix[i - start]; |
| |
| m_dataStart16[length - 1] = 0; |
| |
| m_is8BitSource = false; |
| m_currentCharacter8 = 0; |
| m_currentCharacter16 = m_dataStart16.get(); |
| setTokenStart<UChar>(m_currentCharacter16); |
| m_lexFunc = &CSSParser::realLex<UChar>; |
| } |
| |
| void CSSParser::parseSheet(StyleSheetContents* sheet, const String& string, int startLineNumber, RuleSourceDataList* ruleSourceDataResult, bool logErrors) |
| { |
| setStyleSheet(sheet); |
| m_defaultNamespace = starAtom; // Reset the default namespace. |
| if (ruleSourceDataResult) |
| m_currentRuleDataStack = adoptPtr(new RuleSourceDataList()); |
| m_ruleSourceDataResult = ruleSourceDataResult; |
| |
| m_logErrors = logErrors && sheet->singleOwnerDocument() && !sheet->baseURL().isEmpty() && sheet->singleOwnerDocument()->page(); |
| m_lineNumber = startLineNumber; |
| setupParser("", string, ""); |
| cssyyparse(this); |
| sheet->shrinkToFit(); |
| m_currentRuleDataStack.clear(); |
| m_ruleSourceDataResult = 0; |
| m_rule = 0; |
| m_logErrors = false; |
| } |
| |
| PassRefPtr<StyleRuleBase> CSSParser::parseRule(StyleSheetContents* sheet, const String& string) |
| { |
| setStyleSheet(sheet); |
| m_allowNamespaceDeclarations = false; |
| setupParser("@-webkit-rule{", string, "} "); |
| cssyyparse(this); |
| return m_rule.release(); |
| } |
| |
| PassRefPtr<StyleKeyframe> CSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string) |
| { |
| setStyleSheet(sheet); |
| setupParser("@-webkit-keyframe-rule{ ", string, "} "); |
| cssyyparse(this); |
| return m_keyframe.release(); |
| } |
| |
| #if ENABLE(CSS3_CONDITIONAL_RULES) |
| bool CSSParser::parseSupportsCondition(const String& string) |
| { |
| m_supportsCondition = false; |
| setupParser("@-webkit-supports-condition{ ", string, "} "); |
| cssyyparse(this); |
| return m_supportsCondition; |
| } |
| #endif |
| |
| static inline bool isColorPropertyID(CSSPropertyID 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: |
| #if ENABLE(CSS3_TEXT) |
| case CSSPropertyWebkitTextDecorationColor: |
| #endif // CSS3_TEXT |
| case CSSPropertyWebkitTextEmphasisColor: |
| case CSSPropertyWebkitTextFillColor: |
| case CSSPropertyWebkitTextStrokeColor: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| static bool parseColorValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode) |
| { |
| ASSERT(!string.isEmpty()); |
| bool strict = isStrictParserMode(cssParserMode); |
| if (!isColorPropertyID(propertyId)) |
| return false; |
| CSSParserString cssString; |
| cssString.init(string); |
| 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; |
| } |
| |
| if (validPrimitive) { |
| RefPtr<CSSValue> value = cssValuePool().createIdentifierValue(valueID); |
| declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)); |
| return true; |
| } |
| RGBA32 color; |
| if (!CSSParser::fastParseColor(color, string, strict && string[0] != '#')) |
| return false; |
| RefPtr<CSSValue> value = cssValuePool().createColorValue(color); |
| declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)); |
| return true; |
| } |
| |
| static inline bool isSimpleLengthPropertyID(CSSPropertyID 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; |
| #if ENABLE(CSS_EXCLUSIONS) |
| case CSSPropertyWebkitShapeMargin: |
| case CSSPropertyWebkitShapePadding: |
| acceptsNegativeNumbers = false; |
| return RuntimeEnabledFeatures::cssExclusionsEnabled(); |
| #endif |
| case CSSPropertyBottom: |
| case CSSPropertyLeft: |
| case CSSPropertyMarginBottom: |
| case CSSPropertyMarginLeft: |
| case CSSPropertyMarginRight: |
| case CSSPropertyMarginTop: |
| case CSSPropertyRight: |
| case CSSPropertyTop: |
| case CSSPropertyWebkitMarginAfter: |
| case CSSPropertyWebkitMarginBefore: |
| case CSSPropertyWebkitMarginEnd: |
| case CSSPropertyWebkitMarginStart: |
| acceptsNegativeNumbers = true; |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| template <typename CharacterType> |
| static inline bool parseSimpleLength(const CharacterType* characters, unsigned& length, CSSPrimitiveValue::UnitTypes& unit, double& number) |
| { |
| if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == '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; |
| number = charactersToDouble(characters, length, &ok); |
| return ok; |
| } |
| |
| static bool parseSimpleLengthValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode) |
| { |
| ASSERT(!string.isEmpty()); |
| bool acceptsNegativeNumbers; |
| if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers)) |
| return false; |
| |
| unsigned length = string.length(); |
| double number; |
| CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER; |
| |
| if (string.is8Bit()) { |
| if (!parseSimpleLength(string.characters8(), length, unit, number)) |
| return false; |
| } else { |
| if (!parseSimpleLength(string.characters16(), length, unit, number)) |
| return false; |
| } |
| |
| if (unit == CSSPrimitiveValue::CSS_NUMBER) { |
| if (number && isStrictParserMode(cssParserMode)) |
| return false; |
| unit = CSSPrimitiveValue::CSS_PX; |
| } |
| if (number < 0 && !acceptsNegativeNumbers) |
| return false; |
| |
| RefPtr<CSSValue> value = cssValuePool().createValue(number, unit); |
| declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)); |
| return true; |
| } |
| |
| static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int valueID, const CSSParserContext& parserContext) |
| { |
| if (!valueID) |
| return false; |
| |
| switch (propertyId) { |
| case CSSPropertyBorderCollapse: // collapse | separate | inherit |
| if (valueID == CSSValueCollapse || valueID == CSSValueSeparate) |
| return true; |
| break; |
| case CSSPropertyBorderTopStyle: // <border-style> | inherit |
| case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed | |
| case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset |
| case CSSPropertyBorderLeftStyle: |
| case CSSPropertyWebkitBorderAfterStyle: |
| case CSSPropertyWebkitBorderBeforeStyle: |
| case CSSPropertyWebkitBorderEndStyle: |
| case CSSPropertyWebkitBorderStartStyle: |
| case CSSPropertyWebkitColumnRuleStyle: |
| if (valueID >= CSSValueNone && valueID <= CSSValueDouble) |
| return true; |
| break; |
| case CSSPropertyBoxSizing: |
| if (valueID == CSSValueBorderBox || valueID == CSSValueContentBox) |
| return true; |
| break; |
| case CSSPropertyCaptionSide: // top | bottom | left | right | inherit |
| if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom) |
| return true; |
| break; |
| case CSSPropertyClear: // none | left | right | both | inherit |
| if (valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth) |
| return true; |
| break; |
| case CSSPropertyDirection: // ltr | rtl | inherit |
| if (valueID == CSSValueLtr || valueID == CSSValueRtl) |
| return true; |
| break; |
| case CSSPropertyDisplay: |
| // inline | block | list-item | run-in | inline-block | table | |
| // inline-table | table-row-group | table-header-group | table-footer-group | table-row | |
| // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none | inherit |
| // -webkit-flex | -webkit-inline-flex | -webkit-grid | -webkit-inline-grid |
| if ((valueID >= CSSValueInline && valueID <= CSSValueWebkitInlineFlex) || valueID == CSSValueNone) |
| return true; |
| if (parserContext.isCSSGridLayoutEnabled && (valueID == CSSValueWebkitGrid || valueID == CSSValueWebkitInlineGrid)) |
| return true; |
| break; |
| |
| case CSSPropertyEmptyCells: // show | hide | inherit |
| if (valueID == CSSValueShow || valueID == CSSValueHide) |
| return true; |
| break; |
| case CSSPropertyFloat: // left | right | none | center (for buggy CSS, maps to none) |
| if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter) |
| return true; |
| break; |
| case CSSPropertyFontStyle: // normal | italic | oblique | inherit |
| if (valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique) |
| return true; |
| break; |
| case CSSPropertyImageRendering: // auto | optimizeSpeed | optimizeQuality | -webkit-crisp-edges | -webkit-optimize-contrast |
| if (valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizequality |
| || valueID == CSSValueWebkitCrispEdges || valueID == CSSValueWebkitOptimizeContrast) |
| return true; |
| break; |
| case CSSPropertyListStylePosition: // inside | outside | inherit |
| if (valueID == CSSValueInside || valueID == CSSValueOutside) |
| return true; |
| break; |
| case CSSPropertyListStyleType: |
| // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in |
| // for the list of supported list-style-types. |
| if ((valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone) |
| return true; |
| break; |
| case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto | inherit |
| if (valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble)) |
| return true; |
| break; |
| case CSSPropertyOverflowWrap: // normal | break-word |
| case CSSPropertyWordWrap: |
| if (valueID == CSSValueNormal || valueID == CSSValueBreakWord) |
| return true; |
| break; |
| case CSSPropertyOverflowX: // visible | hidden | scroll | auto | marquee | overlay | inherit |
| if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitMarquee) |
| return true; |
| break; |
| case CSSPropertyOverflowY: // visible | hidden | scroll | auto | marquee | overlay | inherit | -webkit-paged-x | -webkit-paged-y |
| if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitMarquee || valueID == CSSValueWebkitPagedX || valueID == CSSValueWebkitPagedY) |
| return true; |
| break; |
| case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right | inherit |
| case CSSPropertyPageBreakBefore: |
| case CSSPropertyWebkitColumnBreakAfter: |
| case CSSPropertyWebkitColumnBreakBefore: |
| if (valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight) |
| return true; |
| break; |
| case CSSPropertyPageBreakInside: // avoid | auto | inherit |
| case CSSPropertyWebkitColumnBreakInside: |
| if (valueID == CSSValueAuto || valueID == CSSValueAvoid) |
| return true; |
| break; |
| case CSSPropertyPointerEvents: |
| // none | visiblePainted | visibleFill | visibleStroke | visible | |
| // painted | fill | stroke | auto | all | inherit |
| if (valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueStroke)) |
| return true; |
| break; |
| case CSSPropertyPosition: // static | relative | absolute | fixed | sticky | inherit |
| if (valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed |
| #if ENABLE(CSS_STICKY_POSITION) |
| || (parserContext.isCSSStickyPositionEnabled && valueID == CSSValueWebkitSticky) |
| #endif |
| ) |
| return true; |
| break; |
| case CSSPropertyResize: // none | both | horizontal | vertical | auto |
| if (valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto) |
| return true; |
| break; |
| case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation | inherit |
| if (valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation) |
| return true; |
| break; |
| case CSSPropertyTableLayout: // auto | fixed | inherit |
| if (valueID == CSSValueAuto || valueID == CSSValueFixed) |
| return true; |
| break; |
| case CSSPropertyTextLineThroughMode: |
| case CSSPropertyTextOverlineMode: |
| case CSSPropertyTextUnderlineMode: |
| if (valueID == CSSValueContinuous || valueID == CSSValueSkipWhiteSpace) |
| return true; |
| break; |
| case CSSPropertyTextLineThroughStyle: |
| case CSSPropertyTextOverlineStyle: |
| case CSSPropertyTextUnderlineStyle: |
| if (valueID == CSSValueNone || valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDashed || valueID == CSSValueDotDash || valueID == CSSValueDotDotDash || valueID == CSSValueWave) |
| return true; |
| break; |
| case CSSPropertyTextOverflow: // clip | ellipsis |
| if (valueID == CSSValueClip || valueID == CSSValueEllipsis) |
| return true; |
| break; |
| case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision |
| if (valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision) |
| return true; |
| break; |
| case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none | inherit |
| if ((valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone) |
| return true; |
| break; |
| case CSSPropertyVisibility: // visible | hidden | collapse | inherit |
| if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse) |
| return true; |
| break; |
| case CSSPropertyWebkitAppearance: |
| if ((valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone) |
| return true; |
| break; |
| case CSSPropertyWebkitBackfaceVisibility: |
| if (valueID == CSSValueVisible || valueID == CSSValueHidden) |
| return true; |
| break; |
| #if ENABLE(CSS_COMPOSITING) |
| case CSSPropertyWebkitBlendMode: |
| if (parserContext.isCSSCompositingEnabled && (valueID == CSSValueNormal || valueID == CSSValueMultiply || valueID == CSSValueScreen |
| || valueID == CSSValueOverlay || valueID == CSSValueDarken || valueID == CSSValueLighten || valueID == CSSValueColorDodge |
| || valueID == CSSValueColorBurn || valueID == CSSValueHardLight || valueID == CSSValueSoftLight || valueID == CSSValueDifference |
| || valueID == CSSValueExclusion || valueID == CSSValueHue || valueID == CSSValueSaturation || valueID == CSSValueColor |
| || valueID == CSSValueLuminosity)) |
| return true; |
| break; |
| #endif |
| case CSSPropertyWebkitBorderFit: |
| if (valueID == CSSValueBorder || valueID == CSSValueLines) |
| return true; |
| break; |
| case CSSPropertyWebkitBoxAlign: |
| if (valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline) |
| return true; |
| break; |
| #if ENABLE(CSS_BOX_DECORATION_BREAK) |
| case CSSPropertyWebkitBoxDecorationBreak: |
| if (valueID == CSSValueClone || valueID == CSSValueSlice) |
| return true; |
| break; |
| #endif |
| case CSSPropertyWebkitBoxDirection: |
| if (valueID == CSSValueNormal || valueID == CSSValueReverse) |
| return true; |
| break; |
| case CSSPropertyWebkitBoxLines: |
| if (valueID == CSSValueSingle || valueID == CSSValueMultiple) |
| return true; |
| break; |
| case CSSPropertyWebkitBoxOrient: |
| if (valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis) |
| return true; |
| break; |
| case CSSPropertyWebkitBoxPack: |
| if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify) |
| return true; |
| break; |
| case CSSPropertyWebkitColorCorrection: |
| if (valueID == CSSValueSrgb || valueID == CSSValueDefault) |
| return true; |
| break; |
| case CSSPropertyWebkitAlignContent: |
| if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch) |
| return true; |
| break; |
| case CSSPropertyWebkitAlignItems: |
| if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch) |
| return true; |
| break; |
| case CSSPropertyWebkitAlignSelf: |
| if (valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch) |
| return true; |
| break; |
| case CSSPropertyWebkitFlexDirection: |
| if (valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse) |
| return true; |
| break; |
| case CSSPropertyWebkitFlexWrap: |
| if (valueID == CSSValueNowrap || valueID == CSSValueWrap || valueID == CSSValueWrapReverse) |
| return true; |
| break; |
| case CSSPropertyWebkitJustifyContent: |
| if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround) |
| return true; |
| break; |
| case CSSPropertyWebkitFontKerning: |
| if (valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone) |
| return true; |
| break; |
| case CSSPropertyWebkitFontSmoothing: |
| if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased) |
| return true; |
| break; |
| case CSSPropertyWebkitHyphens: |
| if (valueID == CSSValueNone || valueID == CSSValueManual || valueID == CSSValueAuto) |
| return true; |
| break; |
| case CSSPropertyWebkitGridAutoFlow: |
| if (valueID == CSSValueNone || valueID == CSSValueRow || valueID == CSSValueColumn) |
| return true; |
| break; |
| case CSSPropertyWebkitLineAlign: |
| if (valueID == CSSValueNone || valueID == CSSValueEdges) |
| return true; |
| break; |
| case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space |
| if (valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace) |
| return true; |
| break; |
| case CSSPropertyWebkitLineSnap: |
| if (valueID == CSSValueNone || valueID == CSSValueBaseline || valueID == CSSValueContain) |
| return true; |
| break; |
| case CSSPropertyWebkitMarginAfterCollapse: |
| case CSSPropertyWebkitMarginBeforeCollapse: |
| case CSSPropertyWebkitMarginBottomCollapse: |
| case CSSPropertyWebkitMarginTopCollapse: |
| if (valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard) |
| return true; |
| break; |
| case CSSPropertyWebkitMarqueeDirection: |
| if (valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown |
| || valueID == CSSValueUp || valueID == CSSValueAuto) |
| return true; |
| break; |
| case CSSPropertyWebkitMarqueeStyle: |
| if (valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate) |
| return true; |
| break; |
| case CSSPropertyWebkitNbspMode: // normal | space |
| if (valueID == CSSValueNormal || valueID == CSSValueSpace) |
| return true; |
| break; |
| #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING) |
| case CSSPropertyWebkitOverflowScrolling: |
| if (valueID == CSSValueAuto || valueID == CSSValueTouch) |
| return true; |
| break; |
| #endif |
| case CSSPropertyWebkitPrintColorAdjust: |
| if (valueID == CSSValueExact || valueID == CSSValueEconomy) |
| return true; |
| break; |
| #if ENABLE(CSS_REGIONS) |
| case CSSPropertyWebkitRegionBreakAfter: |
| case CSSPropertyWebkitRegionBreakBefore: |
| if (parserContext.isCSSRegionsEnabled && (valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight)) |
| return true; |
| break; |
| case CSSPropertyWebkitRegionBreakInside: |
| if (parserContext.isCSSRegionsEnabled && (valueID == CSSValueAuto || valueID == CSSValueAvoid)) |
| return true; |
| break; |
| case CSSPropertyWebkitRegionOverflow: |
| if (parserContext.isCSSRegionsEnabled && (valueID == CSSValueAuto || valueID == CSSValueBreak)) |
| return true; |
| break; |
| #endif |
| case CSSPropertyWebkitRtlOrdering: |
| if (valueID == CSSValueLogical || valueID == CSSValueVisual) |
| return true; |
| break; |
| |
| case CSSPropertyWebkitRubyPosition: |
| if (valueID == CSSValueBefore || valueID == CSSValueAfter) |
| return true; |
| break; |
| |
| #if ENABLE(CSS3_TEXT) |
| case CSSPropertyWebkitTextAlignLast: |
| // auto | start | end | left | right | center | justify |
| if ((valueID >= CSSValueLeft && valueID <= CSSValueJustify) || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueAuto) |
| return true; |
| break; |
| #endif // CSS3_TEXT |
| case CSSPropertyWebkitTextCombine: |
| if (valueID == CSSValueNone || valueID == CSSValueHorizontal) |
| return true; |
| break; |
| case CSSPropertyWebkitTextEmphasisPosition: |
| if (valueID == CSSValueOver || valueID == CSSValueUnder) |
| return true; |
| break; |
| #if ENABLE(CSS3_TEXT) |
| case CSSPropertyWebkitTextJustify: |
| // auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida |
| if ((valueID >= CSSValueInterWord && valueID <= CSSValueKashida) || valueID == CSSValueAuto || valueID == CSSValueNone) |
| return true; |
| break; |
| #endif // CSS3_TEXT |
| case CSSPropertyWebkitTextSecurity: |
| // disc | circle | square | none | inherit |
| if (valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone) |
| return true; |
| break; |
| case CSSPropertyWebkitTransformStyle: |
| if (valueID == CSSValueFlat || valueID == CSSValuePreserve3d) |
| return true; |
| break; |
| case CSSPropertyWebkitUserDrag: // auto | none | element |
| if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement) |
| return true; |
| break; |
| case CSSPropertyWebkitUserModify: // read-only | read-write |
| if (valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly) |
| return true; |
| break; |
| case CSSPropertyWebkitUserSelect: // auto | none | text | all |
| if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText || valueID == CSSValueAll) |
| return true; |
| break; |
| #if ENABLE(CSS_EXCLUSIONS) |
| case CSSPropertyWebkitWrapFlow: |
| if (!RuntimeEnabledFeatures::cssExclusionsEnabled()) |
| return false; |
| if (valueID == CSSValueAuto || valueID == CSSValueBoth || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueMaximum || valueID == CSSValueClear) |
| return true; |
| break; |
| case CSSPropertyWebkitWrapThrough: |
| if (!RuntimeEnabledFeatures::cssExclusionsEnabled()) |
| return false; |
| if (valueID == CSSValueWrap || valueID == CSSValueNone) |
| return true; |
| break; |
| #endif |
| case CSSPropertyWebkitWritingMode: |
| if (valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt) |
| return true; |
| break; |
| case CSSPropertyWhiteSpace: // normal | pre | nowrap | inherit |
| if (valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap) |
| return true; |
| break; |
| case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension) |
| if (valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord) |
| return true; |
| break; |
| default: |
| ASSERT_NOT_REACHED(); |
| return false; |
| } |
| return false; |
| } |
| |
| static inline bool isKeywordPropertyID(CSSPropertyID propertyId) |
| { |
| switch (propertyId) { |
| case CSSPropertyBorderBottomStyle: |
| case CSSPropertyBorderCollapse: |
| case CSSPropertyBorderLeftStyle: |
| case CSSPropertyBorderRightStyle: |
| case CSSPropertyBorderTopStyle: |
| case CSSPropertyBoxSizing: |
| case CSSPropertyCaptionSide: |
| case CSSPropertyClear: |
| case CSSPropertyDirection: |
| case CSSPropertyDisplay: |
| case CSSPropertyEmptyCells: |
| case CSSPropertyFloat: |
| case CSSPropertyFontStyle: |
| case CSSPropertyImageRendering: |
| case CSSPropertyListStylePosition: |
| case CSSPropertyListStyleType: |
| case CSSPropertyOutlineStyle: |
| case CSSPropertyOverflowWrap: |
| case CSSPropertyOverflowX: |
| case CSSPropertyOverflowY: |
| case CSSPropertyPageBreakAfter: |
| case CSSPropertyPageBreakBefore: |
| case CSSPropertyPageBreakInside: |
| case CSSPropertyPointerEvents: |
| case CSSPropertyPosition: |
| case CSSPropertyResize: |
| case CSSPropertySpeak: |
| case CSSPropertyTableLayout: |
| case CSSPropertyTextLineThroughMode: |
| case CSSPropertyTextLineThroughStyle: |
| case CSSPropertyTextOverflow: |
| case CSSPropertyTextOverlineMode: |
| case CSSPropertyTextOverlineStyle: |
| case CSSPropertyTextRendering: |
| case CSSPropertyTextTransform: |
| case CSSPropertyTextUnderlineMode: |
| case CSSPropertyTextUnderlineStyle: |
| case CSSPropertyVisibility: |
| case CSSPropertyWebkitAppearance: |
| #if ENABLE(CSS_COMPOSITING) |
| case CSSPropertyWebkitBlendMode: |
| #endif |
| case CSSPropertyWebkitBackfaceVisibility: |
| case CSSPropertyWebkitBorderAfterStyle: |
| case CSSPropertyWebkitBorderBeforeStyle: |
| case CSSPropertyWebkitBorderEndStyle: |
| case CSSPropertyWebkitBorderFit: |
| case CSSPropertyWebkitBorderStartStyle: |
| case CSSPropertyWebkitBoxAlign: |
| #if ENABLE(CSS_BOX_DECORATION_BREAK) |
| case CSSPropertyWebkitBoxDecorationBreak: |
| #endif |
| case CSSPropertyWebkitBoxDirection: |
| case CSSPropertyWebkitBoxLines: |
| case CSSPropertyWebkitBoxOrient: |
| case CSSPropertyWebkitBoxPack: |
| case CSSPropertyWebkitColorCorrection: |
| case CSSPropertyWebkitColumnBreakAfter: |
| case CSSPropertyWebkitColumnBreakBefore: |
| case CSSPropertyWebkitColumnBreakInside: |
| case CSSPropertyWebkitColumnRuleStyle: |
| case CSSPropertyWebkitAlignContent: |
| case CSSPropertyWebkitAlignItems: |
| case CSSPropertyWebkitAlignSelf: |
| case CSSPropertyWebkitFlexDirection: |
| case CSSPropertyWebkitFlexWrap: |
| case CSSPropertyWebkitJustifyContent: |
| case CSSPropertyWebkitFontKerning: |
| case CSSPropertyWebkitFontSmoothing: |
| case CSSPropertyWebkitHyphens: |
| case CSSPropertyWebkitGridAutoFlow: |
| case CSSPropertyWebkitLineAlign: |
| case CSSPropertyWebkitLineBreak: |
| case CSSPropertyWebkitLineSnap: |
| case CSSPropertyWebkitMarginAfterCollapse: |
| case CSSPropertyWebkitMarginBeforeCollapse: |
| case CSSPropertyWebkitMarginBottomCollapse: |
| case CSSPropertyWebkitMarginTopCollapse: |
| case CSSPropertyWebkitMarqueeDirection: |
| case CSSPropertyWebkitMarqueeStyle: |
| case CSSPropertyWebkitNbspMode: |
| #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING) |
| case CSSPropertyWebkitOverflowScrolling: |
| #endif |
| case CSSPropertyWebkitPrintColorAdjust: |
| #if ENABLE(CSS_REGIONS) |
| case CSSPropertyWebkitRegionBreakAfter: |
| case CSSPropertyWebkitRegionBreakBefore: |
| case CSSPropertyWebkitRegionBreakInside: |
| case CSSPropertyWebkitRegionOverflow: |
| #endif |
| case CSSPropertyWebkitRtlOrdering: |
| case CSSPropertyWebkitRubyPosition: |
| #if ENABLE(CSS3_TEXT) |
| case CSSPropertyWebkitTextAlignLast: |
| #endif // CSS3_TEXT |
| case CSSPropertyWebkitTextCombine: |
| case CSSPropertyWebkitTextEmphasisPosition: |
| #if ENABLE(CSS3_TEXT) |
| case CSSPropertyWebkitTextJustify: |
| #endif // CSS3_TEXT |
| case CSSPropertyWebkitTextSecurity: |
| case CSSPropertyWebkitTransformStyle: |
| case CSSPropertyWebkitUserDrag: |
| case CSSPropertyWebkitUserModify: |
| case CSSPropertyWebkitUserSelect: |
| #if ENABLE(CSS_EXCLUSIONS) |
| case CSSPropertyWebkitWrapFlow: |
| case CSSPropertyWebkitWrapThrough: |
| #endif |
| case CSSPropertyWebkitWritingMode: |
| case CSSPropertyWhiteSpace: |
| case CSSPropertyWordBreak: |
| case CSSPropertyWordWrap: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| static bool parseKeywordValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext) |
| { |
| ASSERT(!string.isEmpty()); |
| |
| if (!isKeywordPropertyID(propertyId)) { |
| // All properties accept the values of "initial" and "inherit". |
| String lowerCaseString = string.lower(); |
| if (lowerCaseString != "initial" && lowerCaseString != "inherit") |
| return false; |
| |
| // Parse initial/inherit shorthands using the CSSParser. |
| if (shorthandForProperty(propertyId).length()) |
| return false; |
| } |
| |
| CSSParserString cssString; |
| cssString.init(string); |
| int valueID = cssValueKeywordID(cssString); |
| |
| if (!valueID) |
| return false; |
| |
| RefPtr<CSSValue> value; |
| if (valueID == CSSValueInherit) |
| value = cssValuePool().createInheritedValue(); |
| else if (valueID == CSSValueInitial) |
| value = cssValuePool().createExplicitInitialValue(); |
| else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext)) |
| value = cssValuePool().createIdentifierValue(valueID); |
| else |
| return false; |
| |
| declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)); |
| return true; |
| } |
| |
| template <typename CharacterType> |
| static bool parseTransformArguments(WebKitCSSTransformValue* transformValue, CharacterType* characters, unsigned length, unsigned start, unsigned expectedCount) |
| { |
| while (expectedCount) { |
| size_t end = WTF::find(characters, length, expectedCount == 1 ? ')' : ',', start); |
| if (end == notFound || (expectedCount == 1 && end != length - 1)) |
| return false; |
| unsigned argumentLength = end - start; |
| CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER; |
| double number; |
| if (!parseSimpleLength(characters + start, argumentLength, unit, number)) |
| return false; |
| if (unit != CSSPrimitiveValue::CSS_PX && (number || unit != CSSPrimitiveValue::CSS_NUMBER)) |
| return false; |
| transformValue->append(cssValuePool().createValue(number, unit)); |
| start = end + 1; |
| --expectedCount; |
| } |
| return true; |
| } |
| |
| static bool parseTranslateTransformValue(MutableStylePropertySet* properties, CSSPropertyID propertyID, const String& string, bool important) |
| { |
| if (propertyID != CSSPropertyWebkitTransform) |
| return false; |
| static const unsigned shortestValidTransformStringLength = 12; |
| static const unsigned likelyMultipartTransformStringLengthCutoff = 32; |
| if (string.length() < shortestValidTransformStringLength || string.length() > likelyMultipartTransformStringLengthCutoff) |
| return false; |
| if (!string.startsWith("translate", false)) |
| return false; |
| UChar c9 = toASCIILower(string[9]); |
| UChar c10 = toASCIILower(string[10]); |
| |
| WebKitCSSTransformValue::TransformOperationType transformType; |
| unsigned expectedArgumentCount = 1; |
| unsigned argumentStart = 11; |
| if (c9 == 'x' && c10 == '(') |
| transformType = WebKitCSSTransformValue::TranslateXTransformOperation; |
| else if (c9 == 'y' && c10 == '(') |
| transformType = WebKitCSSTransformValue::TranslateYTransformOperation; |
| else if (c9 == 'z' && c10 == '(') |
| transformType = WebKitCSSTransformValue::TranslateZTransformOperation; |
| else if (c9 == '(') { |
| transformType = WebKitCSSTransformValue::TranslateTransformOperation; |
| expectedArgumentCount = 2; |
| argumentStart = 10; |
| } else if (c9 == '3' && c10 == 'd' && string[11] == '(') { |
| transformType = WebKitCSSTransformValue::Translate3DTransformOperation; |
| expectedArgumentCount = 3; |
| argumentStart = 12; |
| } else |
| return false; |
| |
| RefPtr<WebKitCSSTransformValue> transformValue = WebKitCSSTransformValue::create(transformType); |
| bool success; |
| if (string.is8Bit()) |
| success = parseTransformArguments(transformValue.get(), string.characters8(), string.length(), argumentStart, expectedArgumentCount); |
| else |
| success = parseTransformArguments(transformValue.get(), string.characters16(), string.length(), argumentStart, expectedArgumentCount); |
| if (!success) |
| return false; |
| RefPtr<CSSValueList> result = CSSValueList::createSpaceSeparated(); |
| result->append(transformValue.release()); |
| properties->addParsedProperty(CSSProperty(CSSPropertyWebkitTransform, result.release(), important)); |
| return true; |
| } |
| |
| PassRefPtr<CSSValueList> CSSParser::parseFontFaceValue(const AtomicString& string) |
| { |
| if (string.isEmpty()) |
| return 0; |
| RefPtr<MutableStylePropertySet> dummyStyle = MutableStylePropertySet::create(); |
| if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, CSSQuirksMode, 0)) |
| return 0; |
| return static_pointer_cast<CSSValueList>(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily)); |
| } |
| |
| #if ENABLE(CSS_VARIABLES) |
| bool CSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, Document* document) |
| { |
| ASSERT(!string.isEmpty()); |
| |
| CSSParserContext context(document); |
| |
| if (parseSimpleLengthValue(declaration, propertyID, string, important, context.mode)) |
| return true; |
| if (parseColorValue(declaration, propertyID, string, important, context.mode)) |
| return true; |
| if (parseKeywordValue(declaration, propertyID, string, important, context)) |
| return true; |
| |
| CSSParser parser(context); |
| return parser.parseValue(declaration, propertyID, string, important, static_cast<StyleSheetContents*>(0)); |
| } |
| #endif |
| |
| bool CSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, StyleSheetContents* contextStyleSheet) |
| { |
| ASSERT(!string.isEmpty()); |
| if (parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode)) |
| return true; |
| if (parseColorValue(declaration, propertyID, string, important, cssParserMode)) |
| return true; |
| |
| CSSParserContext context(cssParserMode); |
| if (contextStyleSheet) { |
| context = contextStyleSheet->parserContext(); |
| context.mode = cssParserMode; |
| } |
| |
| if (parseKeywordValue(declaration, propertyID, string, important, context)) |
| return true; |
| if (parseTranslateTransformValue(declaration, propertyID, string, important)) |
| return true; |
| |
| CSSParser parser(context); |
| return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet); |
| } |
| |
| bool CSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, StyleSheetContents* contextStyleSheet) |
| { |
| setStyleSheet(contextStyleSheet); |
| |
| setupParser("@-webkit-value{", string, "} "); |
| |
| m_id = propertyID; |
| m_important = important; |
| |
| cssyyparse(this); |
| |
| m_rule = 0; |
| |
| bool ok = false; |
| if (m_hasFontFaceOnlyValues) |
| deleteFontFaceOnlyValues(); |
| if (!m_parsedProperties.isEmpty()) { |
| ok = true; |
| declaration->addParsedProperties(m_parsedProperties); |
| clearProperties(); |
| } |
| |
| return ok; |
| } |
| |
| // The color will only be changed when string contains a valid CSS color, so callers |
| // can set it to a default color and ignore the boolean result. |
| bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict) |
| { |
| // First try creating a color specified by name, rgba(), rgb() or "#" syntax. |
| if (fastParseColor(color, string, strict)) |
| return true; |
| |
| CSSParser parser(CSSStrictMode); |
| |
| // In case the fast-path parser didn't understand the color, try the full parser. |
| if (!parser.parseColor(string)) |
| return false; |
| |
| CSSValue* value = parser.m_parsedProperties.first().value(); |
| if (!value->isPrimitiveValue()) |
| return false; |
| |
| CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
| if (!primitiveValue->isRGBColor()) |
| return false; |
| |
| color = primitiveValue->getRGBA32Value(); |
| return true; |
| } |
| |
| bool CSSParser::parseColor(const String& string) |
| { |
| setupParser("@-webkit-decls{color:", string, "} "); |
| cssyyparse(this); |
| m_rule = 0; |
| |
| return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor; |
| } |
| |
| bool CSSParser::parseSystemColor(RGBA32& color, const String& string, Document* document) |
| { |
| if (!document || !document->page()) |
| return false; |
| |
| CSSParserString cssColor; |
| cssColor.init(string); |
| int id = cssValueKeywordID(cssColor); |
| if (id <= 0) |
| return false; |
| |
| color = document->page()->theme()->systemColor(id).rgb(); |
| return true; |
| } |
| |
| void CSSParser::parseSelector(const String& string, CSSSelectorList& selectorList) |
| { |
| m_selectorListForParseSelector = &selectorList; |
| |
| setupParser("@-webkit-selector{", string, "}"); |
| |
| cssyyparse(this); |
| |
| m_selectorListForParseSelector = 0; |
| } |
| |
| PassRefPtr<ImmutableStylePropertySet> CSSParser::parseInlineStyleDeclaration(const String& string, Element* element) |
| { |
| CSSParserContext context = element->document()->elementSheet()->contents()->parserContext(); |
| context.mode = strictToCSSParserMode(element->isHTMLElement() && !element->document()->inQuirksMode()); |
| return CSSParser(context).parseDeclaration(string, element->document()->elementSheet()->contents()); |
| } |
| |
| PassRefPtr<ImmutableStylePropertySet> CSSParser::parseDeclaration(const String& string, StyleSheetContents* contextStyleSheet) |
| { |
| setStyleSheet(contextStyleSheet); |
| |
| setupParser("@-webkit-decls{", string, "} "); |
| cssyyparse(this); |
| m_rule = 0; |
| |
| if (m_hasFontFaceOnlyValues) |
| deleteFontFaceOnlyValues(); |
| |
| RefPtr<ImmutableStylePropertySet> style = createStylePropertySet(); |
| clearProperties(); |
| return style.release(); |
| } |
| |
| |
| bool CSSParser::parseDeclaration(MutableStylePropertySet* declaration, const String& string, PassRefPtr<CSSRuleSourceData> prpRuleSourceData, StyleSheetContents* contextStyleSheet) |
| { |
| // Length of the "@-webkit-decls{" prefix. |
| static const unsigned prefixLength = 15; |
| |
| setStyleSheet(contextStyleSheet); |
| |
| RefPtr<CSSRuleSourceData> ruleSourceData = prpRuleSourceData; |
| if (ruleSourceData) { |
| m_currentRuleDataStack = adoptPtr(new RuleSourceDataList()); |
| m_currentRuleDataStack->append(ruleSourceData); |
| } |
| |
| setupParser("@-webkit-decls{", string, "} "); |
| cssyyparse(this); |
| m_rule = 0; |
| |
| bool ok = false; |
| if (m_hasFontFaceOnlyValues) |
| deleteFontFaceOnlyValues(); |
| if (!m_parsedProperties.isEmpty()) { |
| ok = true; |
| declaration->addParsedProperties(m_parsedProperties); |
| clearProperties(); |
| } |
| |
| if (ruleSourceData) { |
| ASSERT(m_currentRuleDataStack->size() == 1); |
| ruleSourceData->ruleBodyRange.start = 0; |
| ruleSourceData->ruleBodyRange.end = string.length(); |
| for (size_t i = 0, size = ruleSourceData->styleSourceData->propertyData.size(); i < size; ++i) { |
| CSSPropertySourceData& propertyData = ruleSourceData->styleSourceData->propertyData.at(i); |
| propertyData.range.start -= prefixLength; |
| propertyData.range.end -= prefixLength; |
| } |
| |
| fixUnparsedPropertyRanges(ruleSourceData.get()); |
| m_currentRuleDataStack.clear(); |
| } |
| |
| return ok; |
| } |
| |
| PassOwnPtr<MediaQuery> CSSParser::parseMediaQuery(const String& string) |
| { |
| if (string.isEmpty()) |
| return nullptr; |
| |
| ASSERT(!m_mediaQuery); |
| |
| // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token. |
| // instead insert one " " (which is WHITESPACE in CSSGrammar.y) |
| setupParser("@-webkit-mediaquery ", string, "} "); |
| cssyyparse(this); |
| |
| return m_mediaQuery.release(); |
| } |
| |
| #if ENABLE(CSS_VARIABLES) |
| static inline void filterProperties(bool important, const CSSParser::ParsedPropertyVector& input, Vector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties, HashSet<AtomicString>& seenVariables) |
| #else |
| static inline void filterProperties(bool important, const CSSParser::ParsedPropertyVector& input, Vector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties) |
| #endif |
| { |
| // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found. |
| for (int i = input.size() - 1; i >= 0; --i) { |
| const CSSProperty& property = input[i]; |
| if (property.isImportant() != important) |
| continue; |
| #if ENABLE(CSS_VARIABLES) |
| if (property.id() == CSSPropertyVariable) { |
| const AtomicString& name = static_cast<CSSVariableValue*>(property.value())->name(); |
| if (seenVariables.contains(name)) |
| continue; |
| seenVariables.add(name); |
| output[--unusedEntries] = property; |
| continue; |
| } |
| #endif |
| const unsigned propertyIDIndex = property.id() - firstCSSProperty; |
| if (seenProperties.get(propertyIDIndex)) |
| continue; |
| seenProperties.set(propertyIDIndex); |
| output[--unusedEntries] = property; |
| } |
| } |
| |
| PassRefPtr<ImmutableStylePropertySet> CSSParser::createStylePropertySet() |
| { |
| BitArray<numCSSProperties> seenProperties; |
| size_t unusedEntries = m_parsedProperties.size(); |
| Vector<CSSProperty, 256> results(unusedEntries); |
| |
| // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found. |
| #if ENABLE(CSS_VARIABLES) |
| HashSet<AtomicString> seenVariables; |
| filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties, seenVariables); |
| filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties, seenVariables); |
| #else |
| filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties); |
| filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties); |
| #endif |
| if (unusedEntries) |
| results.remove(0, unusedEntries); |
| |
| return ImmutableStylePropertySet::create(results.data(), results.size(), m_context.mode); |
| } |
| |
| void CSSParser::addPropertyWithPrefixingVariant(CSSPropertyID propId, PassRefPtr<CSSValue> value, bool important, bool implicit) |
| { |
| RefPtr<CSSValue> val = value.get(); |
| addProperty(propId, value, important, implicit); |
| |
| CSSPropertyID prefixingVariant = prefixingVariantForPropertyId(propId); |
| if (prefixingVariant == propId) |
| return; |
| addProperty(prefixingVariant, val.release(), important, implicit); |
| } |
| |
| void CSSParser::addProperty(CSSPropertyID propId, PassRefPtr<CSSValue> value, bool important, bool implicit) |
| { |
| m_parsedProperties.append(CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand || implicit)); |
| } |
| |
| void CSSParser::rollbackLastProperties(int num) |
| { |
| ASSERT(num >= 0); |
| ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num)); |
| m_parsedProperties.shrink(m_parsedProperties.size() - num); |
| } |
| |
| void CSSParser::clearProperties() |
| { |
| m_parsedProperties.clear(); |
| m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES; |
| m_hasFontFaceOnlyValues = false; |
| } |
| |
| KURL CSSParser::completeURL(const CSSParserContext& context, const String& url) |
| { |
| if (url.isNull()) |
| return KURL(); |
| if (context.charset.isEmpty()) |
| return KURL(context.baseURL, url); |
| return KURL(context.baseURL, url, context.charset); |
| } |
| |
| KURL CSSParser::completeURL(const String& url) const |
| { |
| return completeURL(m_context, url); |
| } |
| |
| bool CSSParser::validCalculationUnit(CSSParserValue* value, Units unitflags, ReleaseParsedCalcValueCondition releaseCalc) |
| { |
| bool mustBeNonNegative = unitflags & FNonNeg; |
| |
| if (!parseCalculation(value, mustBeNonNegative ? CalculationRangeNonNegative : CalculationRangeAll)) |
| return false; |
| |
| bool b = false; |
| switch (m_parsedCalculation->category()) { |
| case CalcLength: |
| b = (unitflags & FLength); |
| break; |
| case CalcPercent: |
| b = (unitflags & FPercent); |
| if (b && mustBeNonNegative && m_parsedCalculation->isNegative()) |
| b = false; |
| break; |
| case CalcNumber: |
| b = (unitflags & FNumber); |
| if (!b && (unitflags & FInteger) && m_parsedCalculation->isInt()) |
| b = true; |
| if (b && mustBeNonNegative && m_parsedCalculation->isNegative()) |
| b = false; |
| break; |
| case CalcPercentLength: |
| b = (unitflags & FPercent) && (unitflags & FLength); |
| break; |
| case CalcPercentNumber: |
| b = (unitflags & FPercent) && (unitflags & FNumber); |
| break; |
| #if ENABLE(CSS_VARIABLES) |
| case CalcVariable: |
| b = true; |
| break; |
| #endif |
| case CalcOther: |
| break; |
| } |
| if (!b || releaseCalc == ReleaseParsedCalcValue) |
| m_parsedCalculation.release(); |
| return b; |
| } |
| |
| inline bool CSSParser::shouldAcceptUnitLessValues(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode) |
| { |
| // Qirks mode and svg presentation attributes accept unit less values. |
| return (unitflags & (FLength | FAngle | FTime)) && (!value->fValue || cssParserMode == CSSQuirksMode || cssParserMode == SVGAttributeMode); |
| } |
| |
| bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode, ReleaseParsedCalcValueCondition releaseCalc) |
| { |
| if (isCalculation(value)) |
| return validCalculationUnit(value, unitflags, releaseCalc); |
| |
| bool b = false; |
| switch (value->unit) { |
| #if ENABLE(CSS_VARIABLES) |
| case CSSPrimitiveValue::CSS_VARIABLE_NAME: |
| // Variables are checked at the point they are dereferenced because unit type is not available here. |
| b = true; |
| break; |
| #endif |
| case CSSPrimitiveValue::CSS_NUMBER: |
| b = (unitflags & FNumber); |
| if (!b && shouldAcceptUnitLessValues(value, unitflags, cssParserMode)) { |
| value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX : |
| ((unitflags & FAngle) ? CSSPrimitiveValue::CSS_DEG : CSSPrimitiveValue::CSS_MS); |
| b = true; |
| } |
| if (!b && (unitflags & FInteger) && value->isInt) |
| b = true; |
| if (!b && (unitflags & FPositiveInteger) && value->isInt && value->fValue > 0) |
| b = true; |
| break; |
| case CSSPrimitiveValue::CSS_PERCENTAGE: |
| b = (unitflags & FPercent); |
| break; |
| case CSSParserValue::Q_EMS: |
| case CSSPrimitiveValue::CSS_EMS: |
| case CSSPrimitiveValue::CSS_REMS: |
| case CSSPrimitiveValue::CSS_CHS: |
| case CSSPrimitiveValue::CSS_EXS: |
| case CSSPrimitiveValue::CSS_PX: |
| case CSSPrimitiveValue::CSS_CM: |
| case CSSPrimitiveValue::CSS_MM: |
| case CSSPrimitiveValue::CSS_IN: |
| case CSSPrimitiveValue::CSS_PT: |
| case CSSPrimitiveValue::CSS_PC: |
| case CSSPrimitiveValue::CSS_VW: |
| case CSSPrimitiveValue::CSS_VH: |
| case CSSPrimitiveValue::CSS_VMIN: |
| case CSSPrimitiveValue::CSS_VMAX: |
| b = (unitflags & FLength); |
| break; |
| case CSSPrimitiveValue::CSS_MS: |
| case CSSPrimitiveValue::CSS_S: |
| b = (unitflags & FTime); |
| break; |
| case CSSPrimitiveValue::CSS_DEG: |
| case CSSPrimitiveValue::CSS_RAD: |
| case CSSPrimitiveValue::CSS_GRAD: |
| case CSSPrimitiveValue::CSS_TURN: |
| b = (unitflags & FAngle); |
| break; |
| #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) |
| case CSSPrimitiveValue::CSS_DPPX: |
| case CSSPrimitiveValue::CSS_DPI: |
| case CSSPrimitiveValue::CSS_DPCM: |
| b = (unitflags & FResolution); |
| break; |
| #endif |
| case CSSPrimitiveValue::CSS_HZ: |
| case CSSPrimitiveValue::CSS_KHZ: |
| case CSSPrimitiveValue::CSS_DIMENSION: |
| default: |
| break; |
| } |
| if (b && unitflags & FNonNeg && value->fValue < 0) |
| b = false; |
| return b; |
| } |
| |
| inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(CSSParserValue* value) |
| { |
| #if ENABLE(CSS_VARIABLES) |
| if (value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME) |
| return createPrimitiveVariableNameValue(value); |
| #endif |
| |
| if (m_parsedCalculation) { |
| ASSERT(isCalculation(value)); |
| return CSSPrimitiveValue::create(m_parsedCalculation.release()); |
| } |
| |
| #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) |
| ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) |
| || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_CHS) |
| || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMAX) |
| || (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM)); |
| #else |
| ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) |
| || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_CHS) |
| || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMAX)); |
| #endif |
| return cssValuePool().createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)); |
| } |
| |
| inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveStringValue(CSSParserValue* value) |
| { |
| ASSERT(value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT); |
| return cssValuePool().createValue(value->string, CSSPrimitiveValue::CSS_STRING); |
| } |
| |
| #if ENABLE(CSS_VARIABLES) |
| inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveVariableNameValue(CSSParserValue* value) |
| { |
| ASSERT(value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME); |
| AtomicString variableName = String(value->string).lower(); |
| return CSSPrimitiveValue::create(variableName, CSSPrimitiveValue::CSS_VARIABLE_NAME); |
| } |
| #endif |
| |
| static inline bool isComma(CSSParserValue* value) |
| { |
| return value && value->unit == CSSParserValue::Operator && value->iValue == ','; |
| } |
| |
| static inline bool isForwardSlashOperator(CSSParserValue* value) |
| { |
| ASSERT(value); |
| return value->unit == CSSParserValue::Operator && value->iValue == '/'; |
| } |
| |
| bool CSSParser::validWidth(CSSParserValue* value) |
| { |
| int id = value->id; |
| if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic || id == CSSValueWebkitMinContent || id == CSSValueWebkitMaxContent || id == CSSValueWebkitFillAvailable || id == CSSValueWebkitFitContent) |
| return true; |
| return !id && validUnit(value, FLength | FPercent | FNonNeg); |
| } |
| |
| // FIXME: Combine this with validWidth when we support fit-content, et al, for heights. |
| bool CSSParser::validHeight(CSSParserValue* value) |
| { |
| int id = value->id; |
| if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic) |
| return true; |
| return !id && validUnit(value, FLength | FPercent | FNonNeg); |
| } |
| |
| inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(int identifier, CSSParserValue* value) |
| { |
| if (identifier) |
| return cssValuePool().createIdentifierValue(identifier); |
| if (value->unit == CSSPrimitiveValue::CSS_STRING) |
| return createPrimitiveStringValue(value); |
| if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) |
| return createPrimitiveNumericValue(value); |
| if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_CHS) |
| return createPrimitiveNumericValue(value); |
| if (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMAX) |
| return createPrimitiveNumericValue(value); |
| #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) |
| if (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM) |
| return createPrimitiveNumericValue(value); |
| #endif |
| #if ENABLE(CSS_VARIABLES) |
| if (value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME) |
| return createPrimitiveVariableNameValue(value); |
| #endif |
| if (value->unit >= CSSParserValue::Q_EMS) |
| return CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS); |
| if (isCalculation(value)) |
| return CSSPrimitiveValue::create(m_parsedCalculation.release()); |
| |
| return 0; |
| } |
| |
| void CSSParser::addExpandedPropertyForValue(CSSPropertyID propId, PassRefPtr<CSSValue> prpValue, bool important) |
| { |
| const StylePropertyShorthand& shorthand = shorthandForProperty(propId); |
| unsigned shorthandLength = shorthand.length(); |
| if (!shorthandLength) { |
| addProperty(propId, prpValue, important); |
| return; |
| } |
| |
| RefPtr<CSSValue> value = prpValue; |
| ShorthandScope scope(this, propId); |
| const CSSPropertyID* longhands = shorthand.properties(); |
| for (unsigned i = 0; i < shorthandLength; ++i) |
| addProperty(longhands[i], value, important); |
| } |
| |
| bool CSSParser::parseValue(CSSPropertyID propId, bool important) |
| { |
| if (!m_valueList) |
| return false; |
| |
| CSSParserValue* value = m_valueList->current(); |
| |
| if (!value) |
| return false; |
| |
| // Note: m_parsedCalculation is used to pass the calc value to validUnit and then cleared at the end of this function. |
| // FIXME: This is to avoid having to pass parsedCalc to all validUnit callers. |
| ASSERT(!m_parsedCalculation); |
| |
| int id = value->id; |
| |
| int num = inShorthand() ? 1 : m_valueList->size(); |
| |
| if (id == CSSValueInherit) { |
| if (num != 1) |
| return false; |
| addExpandedPropertyForValue(propId, cssValuePool().createInheritedValue(), important); |
| return true; |
| } |
| else if (id == CSSValueInitial) { |
| if (num != 1) |
| return false; |
| addExpandedPropertyForValue(propId, cssValuePool().createExplicitInitialValue(), important); |
| return true; |
| } |
| |
| #if ENABLE(CSS_VARIABLES) |
| if (!id && value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME && num == 1) { |
| addProperty(propId, createPrimitiveVariableNameValue(value), important); |
| m_valueList->next(); |
| return true; |
| } |
| ASSERT(propId != CSSPropertyVariable); |
| #endif |
| |
| if (isKeywordPropertyID(propId)) { |
| if (!isValidKeywordPropertyAndValue(propId, id, m_context)) |
| return false; |
| if (m_valueList->next() && !inShorthand()) |
| return false; |
| addProperty(propId, cssValuePool().createIdentifierValue(id), important); |
| return true; |
| } |
| |
| #if ENABLE(CSS_DEVICE_ADAPTATION) |
| if (inViewport()) |
| return parseViewportProperty(propId, important); |
| #endif |
| |
| bool validPrimitive = false; |
| RefPtr<CSSValue> parsedValue; |
| |
| switch (propId) { |
| case CSSPropertySize: // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ] |
| return parseSize(propId, important); |
| |
| case CSSPropertyQuotes: // [<string> <string>]+ | none | inherit |
| if (id) |
| validPrimitive = true; |
| else |
| return parseQuotes(propId, important); |
| break; |
| case CSSPropertyUnicodeBidi: // normal | embed | bidi-override | isolate | isolate-override | plaintext | inherit |
| if (id == CSSValueNormal |
| || id == CSSValueEmbed |
| || id == CSSValueBidiOverride |
| || id == CSSValueWebkitIsolate |
| || id == CSSValueWebkitIsolateOverride |
| || id == CSSValueWebkitPlaintext) |
| validPrimitive = true; |
| break; |
| |
| case CSSPropertyContent: // [ <string> | <uri> | <counter> | attr(X) | open-quote | |
| // close-quote | no-open-quote | no-close-quote ]+ | inherit |
| return parseContent(propId, important); |
| |
| case CSSPropertyClip: // <shape> | auto | inherit |
| if (id == CSSValueAuto) |
| validPrimitive = true; |
| else if (value->unit == CSSParserValue::Function) |
| return parseClipShape(propId, important); |
| break; |
| |
| /* Start of supported CSS properties with validation. This is needed for parseShorthand to work |
| * correctly and allows optimization in WebCore::applyRule(..) |
| */ |
| case CSSPropertyOverflow: { |
| ShorthandScope scope(this, propId); |
| if (num != 1 || !parseValue(CSSPropertyOverflowY, important)) |
| return false; |
| |
| RefPtr<CSSValue> overflowXValue; |
| |
| // FIXME: -webkit-paged-x or -webkit-paged-y only apply to overflow-y. If this value has been |
| // set using the shorthand, then for now overflow-x will default to auto, but once we implement |
| // pagination controls, it should default to hidden. If the overflow-y value is anything but |
| // paged-x or paged-y, then overflow-x and overflow-y should have the same value. |
| if (id == CSSValueWebkitPagedX || id == CSSValueWebkitPagedY) |
| overflowXValue = cssValuePool().createIdentifierValue(CSSValueAuto); |
| else |
| overflowXValue = m_parsedProperties.last().value(); |
| addProperty(CSSPropertyOverflowX, overflowXValue.release(), important); |
| return true; |
| } |
| |
| case CSSPropertyTextAlign: |
| // left | right | center | justify | -webkit-left | -webkit-right | -webkit-center | -webkit-match-parent |
| // | start | end | <string> | inherit | -webkit-auto (converted to start) |
| if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd |
| || value->unit == CSSPrimitiveValue::CSS_STRING) |
| validPrimitive = true; |
| break; |
| |
| case CSSPropertyFontWeight: { // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit |
| if (m_valueList->size() != 1) |
| return false; |
| return parseFontWeight(important); |
| } |
| case CSSPropertyBorderSpacing: { |
| if (num == 1) { |
| ShorthandScope scope(this, CSSPropertyBorderSpacing); |
| if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important)) |
| return false; |
| CSSValue* value = m_parsedProperties.last().value(); |
| addProperty(CSSPropertyWebkitBorderVerticalSpacing, value, important); |
| return true; |
| } |
| else if (num == 2) { |
| ShorthandScope scope(this, CSSPropertyBorderSpacing); |
| if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important) || !parseValue(CSSPropertyWebkitBorderVerticalSpacing, important)) |
| return false; |
| return true; |
| } |
| return false; |
| } |
| case CSSPropertyWebkitBorderHorizontalSpacing: |
| case CSSPropertyWebkitBorderVerticalSpacing: |
| validPrimitive = validUnit(value, FLength | FNonNeg); |
| break; |
| case CSSPropertyOutlineColor: // <color> | invert | inherit |
| // Outline color has "invert" as additional keyword. |
| // Also, we want to allow the special focus color even in strict parsing mode. |
| if (id == CSSValueInvert || id == CSSValueWebkitFocusRingColor) { |
| validPrimitive = true; |
| break; |
| } |
| /* nobreak */ |
| case CSSPropertyBackgroundColor: // <color> | inherit |
| case CSSPropertyBorderTopColor: // <color> | inherit |
| case CSSPropertyBorderRightColor: |
| case CSSPropertyBorderBottomColor: |
| case CSSPropertyBorderLeftColor: |
| case CSSPropertyWebkitBorderStartColor: |
| case CSSPropertyWebkitBorderEndColor: |
| case CSSPropertyWebkitBorderBeforeColor: |
| case CSSPropertyWebkitBorderAfterColor: |
| case CSSPropertyColor: // <color> | inherit |
| case CSSPropertyTextLineThroughColor: // CSS3 text decoration colors |
| case CSSPropertyTextUnderlineColor: |
| case CSSPropertyTextOverlineColor: |
| case CSSPropertyWebkitColumnRuleColor: |
| #if ENABLE(CSS3_TEXT) |
| case CSSPropertyWebkitTextDecorationColor: |
| #endif // CSS3_TEXT |
| case CSSPropertyWebkitTextEmphasisColor: |
| case CSSPropertyWebkitTextFillColor: |
| case CSSPropertyWebkitTextStrokeColor: |
| if (id == CSSValueWebkitText) |
| validPrimitive = true; // Always allow this, even when strict parsing is on, |
| // since we use this in our UA sheets. |
| else if (id == CSSValueCurrentcolor) |
| validPrimitive = true; |
| else if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || |
| (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && inQuirksMode())) { |
| validPrimitive = true; |
| } else { |
| parsedValue = parseColor(); |
| if (parsedValue) |
| m_valueList->next(); |
| } |
| break; |
| |
| case CSSPropertyCursor: { |
| // Grammar defined by CSS3 UI and modified by CSS4 images: |
| // [ [<image> [<x> <y>]?,]* |
| // [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize | |
| // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize | |
| // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help | |
| // vertical-text | cell | context-menu | alias | copy | no-drop | not-allowed | -webkit-zoom-in |
| // -webkit-zoom-out | all-scroll | -webkit-grab | -webkit-grabbing ] ] | inherit |
| RefPtr<CSSValueList> list; |
| while (value) { |
| RefPtr<CSSValue> image = 0; |
| if (value->unit == CSSPrimitiveValue::CSS_URI) { |
| String uri = value->string; |
| if (!uri.isNull()) |
| image = CSSImageValue::create(completeURL(uri)); |
| #if ENABLE(CSS_IMAGE_SET) && ENABLE(MOUSE_CURSOR_SCALE) |
| } else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "-webkit-image-set(")) { |
| image = parseImageSet(m_valueList.get()); |
| if (!image) |
| break; |
| #endif |
| } else |
| break; |
| |
| Vector<int> coords; |
| value = m_valueList->next(); |
| while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) { |
| coords.append(int(value->fValue)); |
| value = m_valueList->next(); |
| } |
| bool hasHotSpot = false; |
| IntPoint hotSpot(-1, -1); |
| int nrcoords = coords.size(); |
| if (nrcoords > 0 && nrcoords != 2) |
| return false; |
| if (nrcoords == 2) { |
| hasHotSpot = true; |
| hotSpot = IntPoint(coords[0], coords[1]); |
| } |
| |
| if (!list) |
| list = CSSValueList::createCommaSeparated(); |
| |
| if (image) |
| list->append(CSSCursorImageValue::create(image, hasHotSpot, hotSpot)); |
| |
| if ((inStrictMode() && !value) || (value && !(value->unit == CSSParserValue::Operator && value->iValue == ','))) |
| return false; |
| value = m_valueList->next(); // comma |
| } |
| if (list) { |
| if (!value) { // no value after url list (MSIE 5 compatibility) |
| if (list->length() != 1) |
| return false; |
| } else if (inQuirksMode() && value->id == CSSValueHand) // MSIE 5 compatibility :/ |
| list->append(cssValuePool().createIdentifierValue(CSSValuePointer)); |
| else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone) |
| list->append(cssValuePool().createIdentifierValue(value->id)); |
| m_valueList->next(); |
| parsedValue = list.release(); |
| break; |
| } else if (value) { |
| id = value->id; |
| if (inQuirksMode() && value->id == CSSValueHand) { // MSIE 5 compatibility :/ |
| id = CSSValuePointer; |
| validPrimitive = true; |
| } else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone) |
| validPrimitive = true; |
| } else { |
| ASSERT_NOT_REACHED(); |
| return false; |
| } |
| break; |
| } |
| |
| #if ENABLE(CURSOR_VISIBILITY) |
| case CSSPropertyWebkitCursorVisibility: |
| if (id == CSSValueAuto || id == CSSValueAutoHide) |
| validPrimitive = true; |
| break; |
| #endif |
| |
| case CSSPropertyBackgroundAttachment: |
| case CSSPropertyBackgroundClip: |
| case CSSPropertyWebkitBackgroundClip: |
| case CSSPropertyWebkitBackgroundComposite: |
| case CSSPropertyBackgroundImage: |
| case CSSPropertyBackgroundOrigin: |
| case CSSPropertyWebkitBackgroundOrigin: |
| case CSSPropertyBackgroundPosition: |
| case CSSPropertyBackgroundPositionX: |
| case CSSPropertyBackgroundPositionY: |
| case CSSPropertyBackgroundSize: |
| case CSSPropertyWebkitBackgroundSize: |
| case CSSPropertyBackgroundRepeat: |
| case CSSPropertyBackgroundRepeatX: |
| case CSSPropertyBackgroundRepeatY: |
| case CSSPropertyWebkitMaskClip: |
| case CSSPropertyWebkitMaskComposite: |
| case CSSPropertyWebkitMaskImage: |
| case CSSPropertyWebkitMaskOrigin: |
| case CSSPropertyWebkitMaskPosition: |
| case CSSPropertyWebkitMaskPositionX: |
| case CSSPropertyWebkitMaskPositionY: |
| case CSSPropertyWebkitMaskSize: |
| case CSSPropertyWebkitMaskRepeat: |
| case CSSPropertyWebkitMaskRepeatX: |
| case CSSPropertyWebkitMaskRepeatY: |
| #if ENABLE(CSS_COMPOSITING) |
| case CSSPropertyWebkitBackgroundBlendMode: |
| #endif |
| { |
| RefPtr<CSSValue> val1; |
| RefPtr<CSSValue> val2; |
| CSSPropertyID propId1, propId2; |
| bool result = false; |
| if (parseFillProperty(propId, propId1, propId2, val1, val2)) { |
| OwnPtr<ShorthandScope> shorthandScope; |
| if (propId == CSSPropertyBackgroundPosition || |
| propId == CSSPropertyBackgroundRepeat || |
| propId == CSSPropertyWebkitMaskPosition || |
| propId == CSSPropertyWebkitMaskRepeat) { |
| shorthandScope = adoptPtr(new ShorthandScope(this, propId)); |
| } |
| addProperty(propId1, val1.release(), important); |
| if (val2) |
| addProperty(propId2, val2.release(), important); |
| result = true; |
| } |
| m_implicitShorthand = false; |
| return result; |
| } |
| case CSSPropertyListStyleImage: // <uri> | none | inherit |
| case CSSPropertyBorderImageSource: |
| case CSSPropertyWebkitMaskBoxImageSource: |
| if (id == CSSValueNone) { |
| parsedValue = cssValuePool().createIdentifierValue(CSSValueNone); |
| m_valueList->next(); |
| } else if (value->unit == CSSPrimitiveValue::CSS_URI) { |
| parsedValue = CSSImageValue::create(completeURL(value->string)); |
| m_valueList->next(); |
| } else if (isGeneratedImageValue(value)) { |
| if (parseGeneratedImage(m_valueList.get(), parsedValue)) |
| m_valueList->next(); |
| else |
| return false; |
| } |
| #if ENABLE(CSS_IMAGE_SET) |
| else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "-webkit-image-set(")) { |
| parsedValue = parseImageSet(m_valueList.get()); |
| if (!parsedValue) |
| return false; |
| m_valueList->next(); |
| } |
| #endif |
| break; |
| |
| case CSSPropertyWebkitTextStrokeWidth: |
| case CSSPropertyOutlineWidth: // <border-width> | inherit |
| case CSSPropertyBorderTopWidth: //// <border-width> | inherit |
| case CSSPropertyBorderRightWidth: // Which is defined as |
| case CSSPropertyBorderBottomWidth: // thin | medium | thick | <length> |
| case CSSPropertyBorderLeftWidth: |
| case CSSPropertyWebkitBorderStartWidth: |
| case CSSPropertyWebkitBorderEndWidth: |
| case CSSPropertyWebkitBorderBeforeWidth: |
| case CSSPropertyWebkitBorderAfterWidth: |
| case CSSPropertyWebkitColumnRuleWidth: |
| if (id == CSSValueThin || id == CSSValueMedium || id == CSSValueThick) |
| validPrimitive = true; |
| else |
| validPrimitive = validUnit(value, FLength | FNonNeg); |
| break; |
| |
| case CSSPropertyLetterSpacing: // normal | <length> | inherit |
| case CSSPropertyWordSpacing: // normal | <length> | inherit |
| if (id == CSSValueNormal) |
| validPrimitive = true; |
| else |
| validPrimitive = validUnit(value, FLength); |
| break; |
| |
| case CSSPropertyTextIndent: |
| parsedValue = parseTextIndent(); |
| break; |
| |
| case CSSPropertyPaddingTop: //// <padding-width> | inherit |
| case CSSPropertyPaddingRight: // Which is defined as |
| case CSSPropertyPaddingBottom: // <length> | <percentage> |
| case CSSPropertyPaddingLeft: //// |
| case CSSPropertyWebkitPaddingStart: |
| case CSSPropertyWebkitPaddingEnd: |
| case CSSPropertyWebkitPaddingBefore: |
| case CSSPropertyWebkitPaddingAfter: |
| validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg)); |
| break; |
| |
| case CSSPropertyMaxWidth: |
| case CSSPropertyWebkitMaxLogicalWidth: |
| validPrimitive = (id == CSSValueNone || validWidth(value)); |
| break; |
| |
| case CSSPropertyMinWidth: |
| case CSSPropertyWebkitMinLogicalWidth: |
| validPrimitive = validWidth(value); |
| break; |
| |
| case CSSPropertyWidth: |
| case CSSPropertyWebkitLogicalWidth: |
| validPrimitive = (id == CSSValueAuto || validWidth(value)); |
| break; |
| |
| case CSSPropertyMaxHeight: |
| case CSSPropertyWebkitMaxLogicalHeight: |
| validPrimitive = (id == CSSValueNone || validHeight(value)); |
| break; |
| |
| case CSSPropertyMinHeight: |
| case CSSPropertyWebkitMinLogicalHeight: |
| validPrimitive = validHeight(value); |
| break; |
| |
| case CSSPropertyHeight: |
| case CSSPropertyWebkitLogicalHeight: |
| validPrimitive = (id == CSSValueAuto || validHeight(value)); |
| break; |
| |
| case CSSPropertyFontSize: |
| return parseFontSize(important); |
| |
| case CSSPropertyFontVariant: // normal | small-caps | inherit |
| return parseFontVariant(important); |
| |
| case CSSPropertyVerticalAlign: |
| // baseline | sub | super | top | text-top | middle | bottom | text-bottom | |
| // <percentage> | <length> | inherit |
| |
| if (id >= CSSValueBaseline && id <= CSSValueWebkitBaselineMiddle) |
| validPrimitive = true; |
| else |
| validPrimitive = (!id && validUnit(value, FLength | FPercent)); |
| break; |
| |
| case CSSPropertyBottom: // <length> | <percentage> | auto | inherit |
| case CSSPropertyLeft: // <length> | <percentage> | auto | inherit |
| case CSSPropertyRight: // <length> | <percentage> | auto | inherit |
| case CSSPropertyTop: // <length> | <percentage> | auto | inherit |
| case CSSPropertyMarginTop: //// <margin-width> | inherit |
| case CSSPropertyMarginRight: // Which is defined as |
| case CSSPropertyMarginBottom: // <length> | <percentage> | auto | inherit |
| case CSSPropertyMarginLeft: //// |
| case CSSPropertyWebkitMarginStart: |
| case CSSPropertyWebkitMarginEnd: |
| case CSSPropertyWebkitMarginBefore: |
| case CSSPropertyWebkitMarginAfter: |
| if (id == CSSValueAuto) |
| validPrimitive = true; |
| else |
| validPrimitive = (!id && validUnit(value, FLength | FPercent)); |
| break; |
| |
| case CSSPropertyZIndex: // auto | <integer> | inherit |
| if (id == CSSValueAuto) { |
| validPrimitive = true; |
| break; |
| } |
| /* nobreak */ |
| case CSSPropertyOrphans: // <integer> | inherit | auto (We've added support for auto for backwards compatibility) |
| case CSSPropertyWidows: // <integer> | inherit | auto (Ditto) |
| if (id == CSSValueAuto) |
| validPrimitive = true; |
| else |
| validPrimitive = (!id && validUnit(value, FInteger, CSSQuirksMode)); |
| break; |
| |
| case CSSPropertyLineHeight: |
| return parseLineHeight(important); |
| case CSSPropertyCounterIncrement: // [ <identifier> <integer>? ]+ | none | inherit |
| if (id != CSSValueNone) |
| return parseCounter(propId, 1, important); |
| validPrimitive = true; |
| break; |
| case CSSPropertyCounterReset: // [ <identifier> <integer>? ]+ | none | inherit |
| if (id != CSSValueNone) |
| return parseCounter(propId, 0, important); |
| validPrimitive = true; |
| break; |
| case CSSPropertyFontFamily: |
| // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit |
| { |
| parsedValue = parseFontFamily(); |
| break; |
| } |
| |
| case CSSPropertyTextDecoration: |
| case CSSPropertyWebkitTextDecorationsInEffect: |
| #if ENABLE(CSS3_TEXT) |
| case CSSPropertyWebkitTextDecorationLine: |
| #endif // CSS3_TEXT |
| // none | [ underline || overline || line-through || blink ] | inherit |
| return parseTextDecoration(propId, important); |
| |
| #if ENABLE(CSS3_TEXT) |
| case CSSPropertyWebkitTextDecorationStyle: |
| // solid | double | dotted | dashed | wavy |
| if (id == CSSValueSolid || id == CSSValueDouble || id == CSSValueDotted || id == CSSValueDashed || id == CSSValueWavy) |
| validPrimitive = true; |
| break; |
| |
| case CSSPropertyWebkitTextUnderlinePosition: |
| // auto | alphabetic | under |
| return parseTextUnderlinePosition(important); |
| #endif // CSS3_TEXT |
| |
| case CSSPropertyZoom: // normal | reset | document | <number> | <percentage> | inherit |
| if (id == CSSValueNormal || id == CSSValueReset || id == CSSValueDocument) |
| validPrimitive = true; |
| else |
| validPrimitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg, CSSStrictMode)); |
| break; |
| |
| case CSSPropertySrc: // Only used within @font-face and @-webkit-filter, so cannot use inherit | initial or be !important. This is a list of urls or local references. |
| #if ENABLE(CSS_SHADERS) |
| if (m_inFilterRule) |
| return parseFilterRuleSrc(); |
| #endif |
| return parseFontFaceSrc(); |
| |
| #if ENABLE(CSS_SHADERS) |
| case CSSPropertyMix: |
| // The mix property is just supported inside of an @filter rule. |
| if (!m_inFilterRule) |
| return false; |
| return parseFilterRuleMix(); |
| case CSSPropertyParameters: |
| // The parameters property is just supported inside of an @filter rule. |
| if (!m_inFilterRule) |
| return false; |
| return parseFilterRuleParameters(); |
| #endif |
| |
| case CSSPropertyUnicodeRange: |
| return parseFontFaceUnicodeRange(); |
| |
| /* CSS3 properties */ |
| |
| case CSSPropertyBorderImage: { |
| RefPtr<CSSValue> result; |
| return parseBorderImage(propId, result, important); |
| } |
| case CSSPropertyWebkitBorderImage: |
| case CSSPropertyWebkitMaskBoxImage: { |
| RefPtr<CSSValue> result; |
| if (parseBorderImage(propId, result)) { |
| addProperty(propId, result, important); |
| return true; |
| } |
| break; |
| } |
| case CSSPropertyBorderImageOutset: |
| case CSSPropertyWebkitMaskBoxImageOutset: { |
| RefPtr<CSSPrimitiveValue> result; |
| if (parseBorderImageOutset(result)) { |
| addProperty(propId, result, important); |
| return true; |
| } |
| break; |
| } |
| case CSSPropertyBorderImageRepeat: |
| case CSSPropertyWebkitMaskBoxImageRepeat: { |
| RefPtr<CSSValue> result; |
| if (parseBorderImageRepeat(result)) { |
| addProperty(propId, result, important); |
| return true; |
| } |
| break; |
| } |
| case CSSPropertyBorderImageSlice: |
| case CSSPropertyWebkitMaskBoxImageSlice: { |
| RefPtr<CSSBorderImageSliceValue> result; |
| if (parseBorderImageSlice(propId, result)) { |
| addProperty(propId, result, important); |
| return true; |
| } |
| break; |
| } |
| case CSSPropertyBorderImageWidth: |
| case CSSPropertyWebkitMaskBoxImageWidth: { |
| RefPtr<CSSPrimitiveValue> result; |
| if (parseBorderImageWidth(result)) { |
| addProperty(propId, result, important); |
| return true; |
| } |
| break; |
| } |
| case CSSPropertyBorderTopRightRadius: |
| case CSSPropertyBorderTopLeftRadius: |
| case CSSPropertyBorderBottomLeftRadius: |
| case CSSPropertyBorderBottomRightRadius: { |
| if (num != 1 && num != 2) |
| return false; |
| validPrimitive = validUnit(value, FLength | FPercent | FNonNeg); |
| if (!validPrimitive) |
| return false; |
| RefPtr<CSSPrimitiveValue> parsedValue1 = createPrimitiveNumericValue(value); |
| RefPtr<CSSPrimitiveValue> parsedValue2; |
| if (num == 2) { |
| value = m_valueList->next(); |
| validPrimitive = validUnit(value, FLength | FPercent | FNonNeg); |
| if (!validPrimitive) |
| return false; |
| parsedValue2 = createPrimitiveNumericValue(value); |
| } else |
| parsedValue2 = parsedValue1; |
| |
| addProperty(propId, createPrimitiveValuePair(parsedValue1.release(), parsedValue2.release()), important); |
| return true; |
| } |
| case CSSPropertyTabSize: |
| validPrimitive = validUnit(value, FInteger | FNonNeg); |
| break; |
| case CSSPropertyWebkitAspectRatio: |
| return parseAspectRatio(important); |
| case CSSPropertyBorderRadius: |
| case CSSPropertyWebkitBorderRadius: |
| return parseBorderRadius(propId, important); |
| case CSSPropertyOutlineOffset: |
| validPrimitive = validUnit(value, FLength | FPercent); |
| break; |
| case CSSPropertyTextShadow: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3 |
| case CSSPropertyBoxShadow: |
| case CSSPropertyWebkitBoxShadow: |
| if (id == CSSValueNone) |
| validPrimitive = true; |
| else { |
| RefPtr<CSSValueList> shadowValueList = parseShadow(m_valueList.get(), propId); |
| if (shadowValueList) { |
| addProperty(propId, shadowValueList.release(), important); |
| m_valueList->next(); |
| return true; |
| } |
| return false; |
| } |
| break; |
| case CSSPropertyWebkitBoxReflect: |
| if (id == CSSValueNone) |
| validPrimitive = true; |
| else |
| return parseReflect(propId, important); |
| break; |
| case CSSPropertyOpacity: |
| validPrimitive = validUnit(value, FNumber); |
| break; |
| case CSSPropertyWebkitBoxFlex: |
| validPrimitive = validUnit(value, FNumber); |
| break; |
| case CSSPropertyWebkitBoxFlexGroup: |
| validPrimitive = validUnit(value, FInteger | FNonNeg, CSSStrictMode); |
| break; |
| case CSSPropertyWebkitBoxOrdinalGroup: |
| validPrimitive = validUnit(value, FInteger | FNonNeg, CSSStrictMode) && value->fValue; |
| break; |
| #if ENABLE(CSS_FILTERS) |
| case CSSPropertyWebkitFilter: |
| if (id == CSSValueNone) |
| validPrimitive = true; |
| else { |
| RefPtr<CSSValue> val = parseFilter(); |
| if (val) { |
| addProperty(propId, val, important); |
| return true; |
| } |
| return false; |
| } |
| break; |
| #endif |
| #if ENABLE(CSS_COMPOSITING) |
| case CSSPropertyWebkitBlendMode: |
| if (cssCompositingEnabled()) |
| validPrimitive = true; |
| break; |
| #endif |
| case CSSPropertyWebkitFlex: { |
| ShorthandScope scope(this, propId); |
| if (id == CSSValueNone) { |
| addProperty(CSSPropertyWebkitFlexGrow, cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER), important); |
| addProperty(CSSPropertyWebkitFlexShrink, cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER), important); |
| addProperty(CSSPropertyWebkitFlexBasis, cssValuePool().createIdentifierValue(CSSValueAuto), important); |
| return true; |
| } |
| return parseFlex(m_valueList.get(), important); |
| } |
| case CSSPropertyWebkitFlexBasis: |
| // FIXME: Support intrinsic dimensions too. |
| if (id == CSSValueAuto) |
| validPrimitive = true; |
| else |
| validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg)); |
| break; |
| case CSSPropertyWebkitFlexGrow: |
| case CSSPropertyWebkitFlexShrink: |
| validPrimitive = validUnit(value, FNumber | FNonNeg); |
| break; |
| case CSSPropertyWebkitOrder: |
| if (validUnit(value, FInteger, CSSStrictMode)) { |
| // We restrict the smallest value to int min + 2 because we use int min and int min + 1 as special values in a hash set. |
| parsedValue = cssValuePool().createValue(max(static_cast<double>(std::numeric_limits<int>::min() + 2), value->fValue), |
| static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)); |
| m_valueList->next(); |
| } |
| break; |
| case CSSPropertyWebkitMarquee: |
| return parseShorthand(propId, webkitMarqueeShorthand(), important); |
| case CSSPropertyWebkitMarqueeIncrement: |
| if (id == CSSValueSmall || id == CSSValueLarge || id == CSSValueMedium) |
| validPrimitive = true; |
| else |
| validPrimitive = validUnit(value, FLength | FPercent); |
| break; |
| case CSSPropertyWebkitMarqueeRepetition: |
| if (id == CSSValueInfinite) |
| validPrimitive = true; |
| else |
| validPrimitive = validUnit(value, FInteger | FNonNeg); |
| break; |
| case CSSPropertyWebkitMarqueeSpeed: |
| if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast) |
| validPrimitive = true; |
| else |
| validPrimitive = validUnit(value, FTime | FInteger | FNonNeg); |
| break; |
| #if ENABLE(CSS_REGIONS) |
| case CSSPropertyWebkitFlowInto: |
| if (!cssRegionsEnabled()) |
| return false; |
| return parseFlowThread(propId, important); |
| case CSSPropertyWebkitFlowFrom: |
| if (!cssRegionsEnabled()) |
| return false; |
| return parseRegionThread(propId, important); |
| #endif |
| case CSSPropertyWebkitTransform: |
| if (id == CSSValueNone) |
| validPrimitive = true; |
| else { |
| RefPtr<CSSValue> transformValue = parseTransform(); |
| if (transformValue) { |
| addProperty(propId, transformValue.release(), important); |
| return true; |
| } |
| return false; |
| } |
| break; |
| case CSSPropertyWebkitTransformOrigin: |
| case CSSPropertyWebkitTransformOriginX: |
| case CSSPropertyWebkitTransformOriginY: |
| case CSSPropertyWebkitTransformOriginZ: { |
| RefPtr<CSSValue> val1; |
| RefPtr<CSSValue> val2; |
| RefPtr<CSSValue> val3; |
| CSSPropertyID propId1, propId2, propId3; |
| if (parseTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) { |
| addProperty(propId1, val1.release(), important); |
| if (val2) |
| addProperty(propId2, val2.release(), important); |
| if (val3) |
| addProperty(propId3, val3.release(), important); |
| return true; |
| } |
| return false; |
| } |
| case CSSPropertyWebkitPerspective: |
| if (id == CSSValueNone) |
| validPrimitive = true; |
| else { |
| // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property. |
| if (validUnit(value, FNumber | FLength | FNonNeg)) { |
| RefPtr<CSSValue> val = createPrimitiveNumericValue(value); |
| if (val) { |
| addProperty(propId, val.release(), important); |
| return true; |
| } |
| return false; |
| } |
| } |
| break; |
| case CSSPropertyWebkitPerspectiveOrigin: |
| case CSSPropertyWebkitPerspectiveOriginX: |
| case CSSPropertyWebkitPerspectiveOriginY: { |
| RefPtr<CSSValue> val1; |
| RefPtr<CSSValue> val2; |
| CSSPropertyID propId1, propId2; |
| if (parsePerspectiveOrigin(propId, propId1, propId2, val1, val2)) { |
| addProperty(propId1, val1.release(), important); |
| if (val2) |
| addProperty(propId2, val2.release(), important); |
| return true; |
| } |
| return false; |
| } |
| case CSSPropertyWebkitAnimationDelay: |
| case CSSPropertyWebkitAnimationDirection: |
| case CSSPropertyWebkitAnimationDuration: |
| case CSSPropertyWebkitAnimationFillMode: |
| case CSSPropertyWebkitAnimationName: |
| case CSSPropertyWebkitAnimationPlayState: |
| case CSSPropertyWebkitAnimationIterationCount: |
| case CSSPropertyWebkitAnimationTimingFunction: |
| case CSSPropertyTransitionDelay: |
| case CSSPropertyTransitionDuration: |
| case CSSPropertyTransitionTimingFunction: |
| case CSSPropertyTransitionProperty: |
| case CSSPropertyWebkitTransitionDelay: |
| case CSSPropertyWebkitTransitionDuration: |
| case CSSPropertyWebkitTransitionTimingFunction: |
| case CSSPropertyWebkitTransitionProperty: { |
| RefPtr<CSSValue> val; |
| AnimationParseContext context; |
| if (parseAnimationProperty(propId, val, context)) { |
| addPropertyWithPrefixingVariant(propId, val.release(), important); |
| return true; |
| } |
| return false; |
| } |
| |
| case CSSPropertyWebkitGridAutoColumns: |
| case CSSPropertyWebkitGridAutoRows: |
| if (!cssGridLayoutEnabled()) |
| return false; |
| parsedValue = parseGridTrackSize(); |
| break; |
| |
| case CSSPropertyWebkitGridColumns: |
| case CSSPropertyWebkitGridRows: |
| if (!cssGridLayoutEnabled()) |
| return false; |
| return parseGridTrackList(propId, important); |
| |
| case CSSPropertyWebkitGridStart: |
| case CSSPropertyWebkitGridEnd: |
| case CSSPropertyWebkitGridBefore: |
| case CSSPropertyWebkitGridAfter: |
| if (!cssGridLayoutEnabled()) |
| return false; |
| |
| validPrimitive = id == CSSValueAuto || (validUnit(value, FInteger) && value->fValue); |
| break; |
| |
| case CSSPropertyWebkitGridColumn: |
| case CSSPropertyWebkitGridRow: { |
| if (!cssGridLayoutEnabled()) |
| return false; |
| |
| return parseGridItemPositionShorthand(propId, important); |
| } |
| |
| case CSSPropertyWebkitMarginCollapse: { |
| if (num == 1) { |
| ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse); |
| if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important)) |
| return false; |
| CSSValue* value = m_parsedProperties.last().value(); |
| addProperty(webkitMarginCollapseShorthand().properties()[1], value, important); |
| return true; |
| } |
| else if (num == 2) { |
| ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse); |
| if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important) || !parseValue(webkitMarginCollapseShorthand().properties()[1], important)) |
| return false; |
| return true; |
| } |
| return false; |
| } |
| case CSSPropertyTextLineThroughWidth: |
| case CSSPropertyTextOverlineWidth: |
| case CSSPropertyTextUnderlineWidth: |
| if (id == CSSValueAuto || id == CSSValueNormal || id == CSSValueThin || |
| id == CSSValueMedium || id == CSSValueThick) |
| validPrimitive = true; |
|
|