| Index: Source/core/css/parser/CSSPropertyParser.cpp
|
| diff --git a/Source/core/css/parser/CSSPropertyParser.cpp b/Source/core/css/parser/CSSPropertyParser.cpp
|
| index 9f52c8fd6c92ffb915d29f0c53cbe011dd75e8c4..bfaf825dee4ff8c22f1e4ea829f89763626ca3b9 100644
|
| --- a/Source/core/css/parser/CSSPropertyParser.cpp
|
| +++ b/Source/core/css/parser/CSSPropertyParser.cpp
|
| @@ -26,6 +26,11 @@
|
|
|
| #include "config.h"
|
| #include "core/css/parser/CSSPropertyParser.h"
|
| +#include "RuntimeEnabledFeatures.h"
|
| +#include "core/rendering/RenderTheme.h"
|
| +#include "core/svg/SVGPaint.h"
|
| +
|
| +using namespace std;
|
|
|
| namespace WebCore {
|
|
|
| @@ -48,4 +53,394 @@ CSSPropertyParser::~CSSPropertyParser()
|
| {
|
| }
|
|
|
| +bool CSSPropertyParser::isSystemColor(int id)
|
| +{
|
| + return (id >= CSSValueActiveborder && id <= CSSValueWindowtext) || id == CSSValueMenu;
|
| +}
|
| +
|
| +bool CSSPropertyParser::parseSVGValue(CSSPropertyID propId, bool important)
|
| +{
|
| + CSSParserValue* value = m_valueList->current();
|
| + if (!value)
|
| + return false;
|
| +
|
| + CSSValueID id = value->id;
|
| +
|
| + bool validPrimitive = false;
|
| + RefPtrWillBeRawPtr<CSSValue> parsedValue;
|
| +
|
| + switch (propId) {
|
| + /* The comment to the right defines all valid value of these
|
| + * properties as defined in SVG 1.1, Appendix N. Property index */
|
| + case CSSPropertyAlignmentBaseline:
|
| + // auto | baseline | before-edge | text-before-edge | middle |
|
| + // central | after-edge | text-after-edge | ideographic | alphabetic |
|
| + // hanging | mathematical | inherit
|
| + if (id == CSSValueAuto || id == CSSValueBaseline || id == CSSValueMiddle
|
| + || (id >= CSSValueBeforeEdge && id <= CSSValueMathematical))
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + case CSSPropertyBaselineShift:
|
| + // baseline | super | sub | <percentage> | <length> | inherit
|
| + if (id == CSSValueBaseline || id == CSSValueSub
|
| + || id >= CSSValueSuper)
|
| + validPrimitive = true;
|
| + else
|
| + validPrimitive = validUnit(value, FLength | FPercent, SVGAttributeMode);
|
| + break;
|
| +
|
| + case CSSPropertyDominantBaseline:
|
| + // auto | use-script | no-change | reset-size | ideographic |
|
| + // alphabetic | hanging | mathematical | central | middle |
|
| + // text-after-edge | text-before-edge | inherit
|
| + if (id == CSSValueAuto || id == CSSValueMiddle
|
| + || (id >= CSSValueUseScript && id <= CSSValueResetSize)
|
| + || (id >= CSSValueCentral && id <= CSSValueMathematical))
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + case CSSPropertyEnableBackground:
|
| + // accumulate | new [x] [y] [width] [height] | inherit
|
| + if (id == CSSValueAccumulate) // TODO : new
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + case CSSPropertyMarkerStart:
|
| + case CSSPropertyMarkerMid:
|
| + case CSSPropertyMarkerEnd:
|
| + case CSSPropertyMask:
|
| + if (id == CSSValueNone) {
|
| + validPrimitive = true;
|
| + } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
|
| + parsedValue = CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_URI);
|
| + if (parsedValue)
|
| + m_valueList->next();
|
| + }
|
| + break;
|
| +
|
| + case CSSPropertyClipRule: // nonzero | evenodd | inherit
|
| + case CSSPropertyFillRule:
|
| + if (id == CSSValueNonzero || id == CSSValueEvenodd)
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + case CSSPropertyStrokeMiterlimit: // <miterlimit> | inherit
|
| + validPrimitive = validUnit(value, FNumber | FNonNeg, SVGAttributeMode);
|
| + break;
|
| +
|
| + case CSSPropertyStrokeLinejoin: // miter | round | bevel | inherit
|
| + if (id == CSSValueMiter || id == CSSValueRound || id == CSSValueBevel)
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + case CSSPropertyStrokeLinecap: // butt | round | square | inherit
|
| + if (id == CSSValueButt || id == CSSValueRound || id == CSSValueSquare)
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + case CSSPropertyStrokeOpacity: // <opacity-value> | inherit
|
| + case CSSPropertyFillOpacity:
|
| + case CSSPropertyStopOpacity:
|
| + case CSSPropertyFloodOpacity:
|
| + validPrimitive = (!id && validUnit(value, FNumber | FPercent, SVGAttributeMode));
|
| + break;
|
| +
|
| + case CSSPropertyShapeRendering:
|
| + // auto | optimizeSpeed | crispEdges | geometricPrecision | inherit
|
| + if (id == CSSValueAuto || id == CSSValueOptimizespeed
|
| + || id == CSSValueCrispedges || id == CSSValueGeometricprecision)
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + case CSSPropertyImageRendering: // auto | optimizeSpeed |
|
| + case CSSPropertyColorRendering: // optimizeQuality | inherit
|
| + if (id == CSSValueAuto || id == CSSValueOptimizespeed
|
| + || id == CSSValueOptimizequality)
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + case CSSPropertyBufferedRendering: // auto | dynamic | static
|
| + if (id == CSSValueAuto || id == CSSValueDynamic || id == CSSValueStatic)
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + case CSSPropertyColorProfile: // auto | sRGB | <name> | <uri> inherit
|
| + if (id == CSSValueAuto || id == CSSValueSrgb)
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + case CSSPropertyColorInterpolation: // auto | sRGB | linearRGB | inherit
|
| + case CSSPropertyColorInterpolationFilters:
|
| + if (id == CSSValueAuto || id == CSSValueSrgb || id == CSSValueLinearrgb)
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + /* Start of supported CSS properties with validation. This is needed for parseShortHand to work
|
| + * correctly and allows optimization in applyRule(..)
|
| + */
|
| +
|
| + case CSSPropertyTextAnchor: // start | middle | end | inherit
|
| + if (id == CSSValueStart || id == CSSValueMiddle || id == CSSValueEnd)
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + case CSSPropertyGlyphOrientationVertical: // auto | <angle> | inherit
|
| + if (id == CSSValueAuto) {
|
| + validPrimitive = true;
|
| + break;
|
| + }
|
| + /* fallthrough intentional */
|
| + case CSSPropertyGlyphOrientationHorizontal: // <angle> (restricted to _deg_ per SVG 1.1 spec) | inherit
|
| + if (value->unit == CSSPrimitiveValue::CSS_DEG || value->unit == CSSPrimitiveValue::CSS_NUMBER) {
|
| + parsedValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_DEG);
|
| +
|
| + if (parsedValue)
|
| + m_valueList->next();
|
| + }
|
| + break;
|
| +
|
| + case CSSPropertyFill: // <paint> | inherit
|
| + case CSSPropertyStroke: // <paint> | inherit
|
| + {
|
| + if (id == CSSValueNone) {
|
| + parsedValue = SVGPaint::createNone();
|
| + } else if (id == CSSValueCurrentcolor) {
|
| + parsedValue = SVGPaint::createCurrentColor();
|
| + } else if (isSystemColor(id)) {
|
| + parsedValue = SVGPaint::createColor(RenderTheme::theme().systemColor(id));
|
| + } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
|
| + RGBA32 c = Color::transparent;
|
| + if (m_valueList->next()) {
|
| + if (parseColorFromValue(m_valueList->current(), c))
|
| + parsedValue = SVGPaint::createURIAndColor(value->string, c);
|
| + else if (m_valueList->current()->id == CSSValueNone)
|
| + parsedValue = SVGPaint::createURIAndNone(value->string);
|
| + else if (m_valueList->current()->id == CSSValueCurrentcolor)
|
| + parsedValue = SVGPaint::createURIAndCurrentColor(value->string);
|
| + }
|
| + if (!parsedValue)
|
| + parsedValue = SVGPaint::createURI(value->string);
|
| + } else {
|
| + parsedValue = parseSVGPaint();
|
| + }
|
| +
|
| + if (parsedValue)
|
| + m_valueList->next();
|
| + }
|
| + break;
|
| +
|
| + case CSSPropertyStopColor: // TODO : icccolor
|
| + case CSSPropertyFloodColor:
|
| + case CSSPropertyLightingColor:
|
| + if (isSystemColor(id))
|
| + parsedValue = SVGColor::createFromColor(RenderTheme::theme().systemColor(id));
|
| + else if ((id >= CSSValueAqua && id <= CSSValueTransparent)
|
| + || (id >= CSSValueAliceblue && id <= CSSValueYellowgreen) || id == CSSValueGrey)
|
| + parsedValue = SVGColor::createFromString(value->string);
|
| + else if (id == CSSValueCurrentcolor)
|
| + parsedValue = SVGColor::createCurrentColor();
|
| + else // TODO : svgcolor (iccColor)
|
| + parsedValue = parseSVGColor();
|
| +
|
| + if (parsedValue)
|
| + m_valueList->next();
|
| +
|
| + break;
|
| +
|
| + case CSSPropertyPaintOrder:
|
| + if (!RuntimeEnabledFeatures::svgPaintOrderEnabled())
|
| + return false;
|
| +
|
| + if (m_valueList->size() == 1 && id == CSSValueNormal)
|
| + validPrimitive = true;
|
| + else if ((parsedValue = parsePaintOrder()))
|
| + m_valueList->next();
|
| + break;
|
| +
|
| + case CSSPropertyVectorEffect: // none | non-scaling-stroke | inherit
|
| + if (id == CSSValueNone || id == CSSValueNonScalingStroke)
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + case CSSPropertyWritingMode:
|
| + // lr-tb | rl_tb | tb-rl | lr | rl | tb | inherit
|
| + if (id == CSSValueLrTb || id == CSSValueRlTb || id == CSSValueTbRl || id == CSSValueLr || id == CSSValueRl || id == CSSValueTb)
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + case CSSPropertyStrokeWidth: // <length> | inherit
|
| + case CSSPropertyStrokeDashoffset:
|
| + validPrimitive = validUnit(value, FLength | FPercent, SVGAttributeMode);
|
| + break;
|
| + case CSSPropertyStrokeDasharray: // none | <dasharray> | inherit
|
| + if (id == CSSValueNone)
|
| + validPrimitive = true;
|
| + else
|
| + parsedValue = parseSVGStrokeDasharray();
|
| +
|
| + break;
|
| +
|
| + case CSSPropertyKerning: // auto | normal | <length> | inherit
|
| + if (id == CSSValueAuto || id == CSSValueNormal)
|
| + validPrimitive = true;
|
| + else
|
| + validPrimitive = validUnit(value, FLength, SVGAttributeMode);
|
| + break;
|
| +
|
| + case CSSPropertyClipPath: // <uri> | none | inherit
|
| + case CSSPropertyFilter:
|
| + if (id == CSSValueNone) {
|
| + validPrimitive = true;
|
| + } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
|
| + parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
|
| + if (parsedValue)
|
| + m_valueList->next();
|
| + }
|
| + break;
|
| + case CSSPropertyMaskType: // luminance | alpha | inherit
|
| + if (id == CSSValueLuminance || id == CSSValueAlpha)
|
| + validPrimitive = true;
|
| + break;
|
| +
|
| + /* shorthand properties */
|
| + case CSSPropertyMarker: {
|
| + ShorthandScope scope(this, propId);
|
| + CSSPropertyParser::ImplicitScope implicitScope(this, PropertyImplicit);
|
| + if (!parseValue(CSSPropertyMarkerStart, important))
|
| + return false;
|
| + if (m_valueList->current()) {
|
| + rollbackLastProperties(1);
|
| + return false;
|
| + }
|
| + CSSValue* value = m_parsedProperties.last().value();
|
| + addProperty(CSSPropertyMarkerMid, value, important);
|
| + addProperty(CSSPropertyMarkerEnd, value, important);
|
| + return true;
|
| + }
|
| + default:
|
| + // If you crash here, it's because you added a css property and are not handling it
|
| + // in either this switch statement or the one in CSSPropertyParser::parseValue
|
| + ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propId);
|
| + return false;
|
| + }
|
| +
|
| + if (validPrimitive) {
|
| + if (id)
|
| + parsedValue = CSSPrimitiveValue::createIdentifier(id);
|
| + else if (value->unit == CSSPrimitiveValue::CSS_STRING)
|
| + parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
|
| + else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
|
| + parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
|
| + else if (value->unit >= CSSParserValue::Q_EMS)
|
| + parsedValue = CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS);
|
| + if (isCalculation(value)) {
|
| + // FIXME calc() http://webkit.org/b/16662 : actually create a CSSPrimitiveValue here, ie
|
| + // parsedValue = CSSPrimitiveValue::create(m_parsedCalculation.release());
|
| + m_parsedCalculation.release();
|
| + parsedValue = nullptr;
|
| + }
|
| + m_valueList->next();
|
| + }
|
| + if (!parsedValue || (m_valueList->current() && !inShorthand()))
|
| + return false;
|
| +
|
| + addProperty(propId, parsedValue.release(), important);
|
| + return true;
|
| +}
|
| +
|
| +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSVGStrokeDasharray()
|
| +{
|
| + RefPtrWillBeRawPtr<CSSValueList> ret = CSSValueList::createCommaSeparated();
|
| + CSSParserValue* value = m_valueList->current();
|
| + bool validPrimitive = true;
|
| + while (value) {
|
| + validPrimitive = validUnit(value, FLength | FPercent | FNonNeg, SVGAttributeMode);
|
| + if (!validPrimitive)
|
| + break;
|
| + if (value->id)
|
| + ret->append(CSSPrimitiveValue::createIdentifier(value->id));
|
| + else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
|
| + ret->append(CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit));
|
| + value = m_valueList->next();
|
| + if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
|
| + value = m_valueList->next();
|
| + }
|
| + if (!validPrimitive)
|
| + return nullptr;
|
| + return ret.release();
|
| +}
|
| +
|
| +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSVGPaint()
|
| +{
|
| + RGBA32 c = Color::transparent;
|
| + if (!parseColorFromValue(m_valueList->current(), c))
|
| + return SVGPaint::createUnknown();
|
| + return SVGPaint::createColor(Color(c));
|
| +}
|
| +
|
| +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSVGColor()
|
| +{
|
| + RGBA32 c = Color::transparent;
|
| + if (!parseColorFromValue(m_valueList->current(), c))
|
| + return nullptr;
|
| + return SVGColor::createFromColor(Color(c));
|
| +}
|
| +
|
| +// normal | [ fill || stroke || markers ]
|
| +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parsePaintOrder() const
|
| +{
|
| + if (m_valueList->size() > 3)
|
| + return nullptr;
|
| +
|
| + CSSParserValue* value = m_valueList->current();
|
| + if (!value)
|
| + return nullptr;
|
| +
|
| + RefPtrWillBeRawPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
|
| +
|
| + // The default paint-order is: Fill, Stroke, Markers.
|
| + bool seenFill = false, seenStroke = false, seenMarkers = false;
|
| +
|
| + do {
|
| + switch (value->id) {
|
| + case CSSValueNormal:
|
| + // normal inside [fill || stroke || markers] not valid
|
| + return nullptr;
|
| + case CSSValueFill:
|
| + if (seenFill)
|
| + return nullptr;
|
| +
|
| + seenFill = true;
|
| + break;
|
| + case CSSValueStroke:
|
| + if (seenStroke)
|
| + return nullptr;
|
| +
|
| + seenStroke = true;
|
| + break;
|
| + case CSSValueMarkers:
|
| + if (seenMarkers)
|
| + return nullptr;
|
| +
|
| + seenMarkers = true;
|
| + break;
|
| + default:
|
| + return nullptr;
|
| + }
|
| +
|
| + parsedValues->append(CSSPrimitiveValue::createIdentifier(value->id));
|
| + } while ((value = m_valueList->next()));
|
| +
|
| + // fill out the rest of the paint order
|
| + if (!seenFill)
|
| + parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueFill));
|
| + if (!seenStroke)
|
| + parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke));
|
| + if (!seenMarkers)
|
| + parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
|
| +
|
| + return parsedValues.release();
|
| +}
|
| +
|
| } // namespace WebCore
|
|
|