diff options
Diffstat (limited to 'Source/WebCore/css/SVGCSSParser.cpp')
-rw-r--r-- | Source/WebCore/css/SVGCSSParser.cpp | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/Source/WebCore/css/SVGCSSParser.cpp b/Source/WebCore/css/SVGCSSParser.cpp new file mode 100644 index 0000000..3c42d40 --- /dev/null +++ b/Source/WebCore/css/SVGCSSParser.cpp @@ -0,0 +1,358 @@ +/* + Copyright (C) 2008 Eric Seidel <eric@webkit.org> + Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> + 2004, 2005, 2007, 2010 Rob Buis <buis@kde.org> + Copyright (C) 2005, 2006 Apple Computer, Inc. + + 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" + +#if ENABLE(SVG) +#include "CSSInheritedValue.h" +#include "CSSInitialValue.h" +#include "CSSParser.h" +#include "CSSProperty.h" +#include "CSSPropertyNames.h" +#include "CSSQuirkPrimitiveValue.h" +#include "CSSValueKeywords.h" +#include "CSSValueList.h" +#include "RenderTheme.h" +#include "SVGPaint.h" + +using namespace std; + +namespace WebCore { + +bool CSSParser::parseSVGValue(int propId, bool important) +{ + CSSParserValue* value = m_valueList->current(); + if (!value) + return false; + + int id = value->id; + + bool valid_primitive = false; + RefPtr<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)) + valid_primitive = true; + break; + + case CSSPropertyBaselineShift: + // baseline | super | sub | <percentage> | <length> | inherit + if (id == CSSValueBaseline || id == CSSValueSub || + id >= CSSValueSuper) + valid_primitive = true; + else + valid_primitive = validUnit(value, FLength|FPercent, false); + 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)) + valid_primitive = true; + break; + + case CSSPropertyEnableBackground: + // accumulate | new [x] [y] [width] [height] | inherit + if (id == CSSValueAccumulate) // TODO : new + valid_primitive = true; + break; + + case CSSPropertyMarkerStart: + case CSSPropertyMarkerMid: + case CSSPropertyMarkerEnd: + case CSSPropertyMask: + if (id == CSSValueNone) + valid_primitive = 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) + valid_primitive = true; + break; + + case CSSPropertyStrokeMiterlimit: // <miterlimit> | inherit + valid_primitive = validUnit(value, FNumber|FNonNeg, false); + break; + + case CSSPropertyStrokeLinejoin: // miter | round | bevel | inherit + if (id == CSSValueMiter || id == CSSValueRound || id == CSSValueBevel) + valid_primitive = true; + break; + + case CSSPropertyStrokeLinecap: // butt | round | square | inherit + if (id == CSSValueButt || id == CSSValueRound || id == CSSValueSquare) + valid_primitive = true; + break; + + case CSSPropertyStrokeOpacity: // <opacity-value> | inherit + case CSSPropertyFillOpacity: + case CSSPropertyStopOpacity: + case CSSPropertyFloodOpacity: + valid_primitive = (!id && validUnit(value, FNumber|FPercent, false)); + break; + + case CSSPropertyShapeRendering: + // auto | optimizeSpeed | crispEdges | geometricPrecision | inherit + if (id == CSSValueAuto || id == CSSValueOptimizespeed || + id == CSSValueCrispedges || id == CSSValueGeometricprecision) + valid_primitive = true; + break; + + case CSSPropertyImageRendering: // auto | optimizeSpeed | + case CSSPropertyColorRendering: // optimizeQuality | inherit + if (id == CSSValueAuto || id == CSSValueOptimizespeed || + id == CSSValueOptimizequality) + valid_primitive = true; + break; + + case CSSPropertyColorProfile: // auto | sRGB | <name> | <uri> inherit + if (id == CSSValueAuto || id == CSSValueSrgb) + valid_primitive = true; + break; + + case CSSPropertyColorInterpolation: // auto | sRGB | linearRGB | inherit + case CSSPropertyColorInterpolationFilters: + if (id == CSSValueAuto || id == CSSValueSrgb || id == CSSValueLinearrgb) + valid_primitive = 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) + valid_primitive = true; + break; + + case CSSPropertyGlyphOrientationVertical: // auto | <angle> | inherit + if (id == CSSValueAuto) { + valid_primitive = 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::create(SVGPaint::SVG_PAINTTYPE_NONE); + else if (id == CSSValueCurrentcolor) + parsedValue = SVGPaint::create(SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR); + else if ((id >= CSSValueActiveborder && id <= CSSValueWindowtext) || id == CSSValueMenu) + parsedValue = SVGPaint::create(RenderTheme::defaultTheme()->systemColor(id)); + else if (value->unit == CSSPrimitiveValue::CSS_URI) { + RGBA32 c = Color::transparent; + if (m_valueList->next() && parseColorFromValue(m_valueList->current(), c)) { + parsedValue = SVGPaint::create(value->string, c); + } else + parsedValue = SVGPaint::create(SVGPaint::SVG_PAINTTYPE_URI, value->string); + } else + parsedValue = parseSVGPaint(); + + if (parsedValue) + m_valueList->next(); + } + break; + + case CSSPropertyColor: // <color> | inherit + if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || + (id >= CSSValueAliceblue && id <= CSSValueYellowgreen)) + parsedValue = SVGColor::create(value->string); + else + parsedValue = parseSVGColor(); + + if (parsedValue) + m_valueList->next(); + break; + + case CSSPropertyStopColor: // TODO : icccolor + case CSSPropertyFloodColor: + case CSSPropertyLightingColor: + if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || + (id >= CSSValueAliceblue && id <= CSSValueYellowgreen)) + parsedValue = SVGColor::create(value->string); + else if (id == CSSValueCurrentcolor) + parsedValue = SVGColor::createCurrentColor(); + else // TODO : svgcolor (iccColor) + parsedValue = parseSVGColor(); + + if (parsedValue) + m_valueList->next(); + + break; + + case CSSPropertyVectorEffect: // none | non-scaling-stroke | inherit + if (id == CSSValueNone || id == CSSValueNonScalingStroke) + valid_primitive = 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) + valid_primitive = true; + break; + + case CSSPropertyStrokeWidth: // <length> | inherit + case CSSPropertyStrokeDashoffset: + valid_primitive = validUnit(value, FLength | FPercent, false); + break; + case CSSPropertyStrokeDasharray: // none | <dasharray> | inherit + if (id == CSSValueNone) + valid_primitive = true; + else + parsedValue = parseSVGStrokeDasharray(); + + break; + + case CSSPropertyKerning: // auto | normal | <length> | inherit + if (id == CSSValueAuto || id == CSSValueNormal) + valid_primitive = true; + else + valid_primitive = validUnit(value, FLength, false); + break; + + case CSSPropertyClipPath: // <uri> | none | inherit + case CSSPropertyFilter: + if (id == CSSValueNone) + valid_primitive = true; + else if (value->unit == CSSPrimitiveValue::CSS_URI) { + parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit); + if (parsedValue) + m_valueList->next(); + } + break; + case CSSPropertyWebkitSvgShadow: + if (id == CSSValueNone) + valid_primitive = true; + else + return parseShadow(propId, important); + + /* shorthand properties */ + case CSSPropertyMarker: + { + ShorthandScope scope(this, propId); + m_implicitShorthand = true; + if (!parseValue(CSSPropertyMarkerStart, important)) + return false; + if (m_valueList->current()) { + rollbackLastProperties(1); + return false; + } + CSSValue* value = m_parsedProperties[m_numParsedProperties - 1]->value(); + addProperty(CSSPropertyMarkerMid, value, important); + addProperty(CSSPropertyMarkerEnd, value, important); + m_implicitShorthand = false; + 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 CSSParser::parseValue + ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propId); + return false; + } + + if (valid_primitive) { + if (id != 0) + 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 = CSSQuirkPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_EMS); + m_valueList->next(); + } + if (!parsedValue || (m_valueList->current() && !inShorthand())) + return false; + + addProperty(propId, parsedValue.release(), important); + return true; +} + +PassRefPtr<CSSValue> CSSParser::parseSVGStrokeDasharray() +{ + RefPtr<CSSValueList> ret = CSSValueList::createCommaSeparated(); + CSSParserValue* value = m_valueList->current(); + bool valid_primitive = true; + while (value) { + valid_primitive = validUnit(value, FLength | FPercent |FNonNeg, false); + if (!valid_primitive) + break; + if (value->id != 0) + 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 (!valid_primitive) + return 0; + return ret.release(); +} + +PassRefPtr<CSSValue> CSSParser::parseSVGPaint() +{ + RGBA32 c = Color::transparent; + if (!parseColorFromValue(m_valueList->current(), c)) + return SVGPaint::create(); + return SVGPaint::create(Color(c)); +} + +PassRefPtr<CSSValue> CSSParser::parseSVGColor() +{ + RGBA32 c = Color::transparent; + if (!parseColorFromValue(m_valueList->current(), c)) + return 0; + return SVGColor::create(Color(c)); +} + +} + +#endif // ENABLE(SVG) + +// vim:ts=4:noet |