blob: a8fa2528904285a496d96706d4d581510e4553da [file] [log] [blame]
/*
* 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;