• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Copyright (C) 2008 Eric Seidel <eric@webkit.org>
3     Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
4                   2004, 2005, 2007 Rob Buis <buis@kde.org>
5     Copyright (C) 2005, 2006 Apple Computer, Inc.
6 
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Library General Public
9     License as published by the Free Software Foundation; either
10     version 2 of the License, or (at your option) any later version.
11 
12     This library is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15     Library General Public License for more details.
16 
17     You should have received a copy of the GNU Library General Public License
18     along with this library; see the file COPYING.LIB.  If not, write to
19     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20     Boston, MA 02110-1301, USA.
21 */
22 
23 #include "config.h"
24 
25 #if ENABLE(SVG)
26 #include "CSSInheritedValue.h"
27 #include "CSSInitialValue.h"
28 #include "CSSParser.h"
29 #include "CSSProperty.h"
30 #include "CSSPropertyNames.h"
31 #include "CSSQuirkPrimitiveValue.h"
32 #include "CSSValueKeywords.h"
33 #include "CSSValueList.h"
34 #include "SVGPaint.h"
35 
36 using namespace std;
37 
38 namespace WebCore {
39 
parseSVGValue(int propId,bool important)40 bool CSSParser::parseSVGValue(int propId, bool important)
41 {
42     CSSParserValue* value = m_valueList->current();
43     if (!value)
44         return false;
45 
46     int id = value->id;
47 
48     bool valid_primitive = false;
49     RefPtr<CSSValue> parsedValue;
50 
51     switch (propId) {
52     /* The comment to the right defines all valid value of these
53      * properties as defined in SVG 1.1, Appendix N. Property index */
54     case CSSPropertyAlignmentBaseline:
55     // auto | baseline | before-edge | text-before-edge | middle |
56     // central | after-edge | text-after-edge | ideographic | alphabetic |
57     // hanging | mathematical | inherit
58         if (id == CSSValueAuto || id == CSSValueBaseline || id == CSSValueMiddle ||
59           (id >= CSSValueBeforeEdge && id <= CSSValueMathematical))
60             valid_primitive = true;
61         break;
62 
63     case CSSPropertyBaselineShift:
64     // baseline | super | sub | <percentage> | <length> | inherit
65         if (id == CSSValueBaseline || id == CSSValueSub ||
66            id >= CSSValueSuper)
67             valid_primitive = true;
68         else
69             valid_primitive = validUnit(value, FLength|FPercent, false);
70         break;
71 
72     case CSSPropertyDominantBaseline:
73     // auto | use-script | no-change | reset-size | ideographic |
74     // alphabetic | hanging | mathematical | central | middle |
75     // text-after-edge | text-before-edge | inherit
76         if (id == CSSValueAuto || id == CSSValueMiddle ||
77           (id >= CSSValueUseScript && id <= CSSValueResetSize) ||
78           (id >= CSSValueCentral && id <= CSSValueMathematical))
79             valid_primitive = true;
80         break;
81 
82     case CSSPropertyEnableBackground:
83     // accumulate | new [x] [y] [width] [height] | inherit
84         if (id == CSSValueAccumulate) // TODO : new
85             valid_primitive = true;
86         break;
87 
88     case CSSPropertyMarkerStart:
89     case CSSPropertyMarkerMid:
90     case CSSPropertyMarkerEnd:
91     case CSSPropertyMask:
92         if (id == CSSValueNone)
93             valid_primitive = true;
94         else if (value->unit == CSSPrimitiveValue::CSS_URI) {
95             parsedValue = CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_URI);
96             if (parsedValue)
97                 m_valueList->next();
98         }
99         break;
100 
101     case CSSPropertyClipRule:            // nonzero | evenodd | inherit
102     case CSSPropertyFillRule:
103         if (id == CSSValueNonzero || id == CSSValueEvenodd)
104             valid_primitive = true;
105         break;
106 
107     case CSSPropertyStrokeMiterlimit:   // <miterlimit> | inherit
108         valid_primitive = validUnit(value, FNumber|FNonNeg, false);
109         break;
110 
111     case CSSPropertyStrokeLinejoin:   // miter | round | bevel | inherit
112         if (id == CSSValueMiter || id == CSSValueRound || id == CSSValueBevel)
113             valid_primitive = true;
114         break;
115 
116     case CSSPropertyStrokeLinecap:    // butt | round | square | inherit
117         if (id == CSSValueButt || id == CSSValueRound || id == CSSValueSquare)
118             valid_primitive = true;
119         break;
120 
121     case CSSPropertyStrokeOpacity:   // <opacity-value> | inherit
122     case CSSPropertyFillOpacity:
123     case CSSPropertyStopOpacity:
124     case CSSPropertyFloodOpacity:
125         valid_primitive = (!id && validUnit(value, FNumber|FPercent, false));
126         break;
127 
128     case CSSPropertyShapeRendering:
129     // auto | optimizeSpeed | crispEdges | geometricPrecision | inherit
130         if (id == CSSValueAuto || id == CSSValueOptimizespeed ||
131             id == CSSValueCrispedges || id == CSSValueGeometricprecision)
132             valid_primitive = true;
133         break;
134 
135     case CSSPropertyImageRendering:  // auto | optimizeSpeed |
136     case CSSPropertyColorRendering:  // optimizeQuality | inherit
137         if (id == CSSValueAuto || id == CSSValueOptimizespeed ||
138             id == CSSValueOptimizequality)
139             valid_primitive = true;
140         break;
141 
142     case CSSPropertyColorProfile: // auto | sRGB | <name> | <uri> inherit
143         if (id == CSSValueAuto || id == CSSValueSrgb)
144             valid_primitive = true;
145         break;
146 
147     case CSSPropertyColorInterpolation:   // auto | sRGB | linearRGB | inherit
148     case CSSPropertyColorInterpolationFilters:
149         if (id == CSSValueAuto || id == CSSValueSrgb || id == CSSValueLinearrgb)
150             valid_primitive = true;
151         break;
152 
153     /* Start of supported CSS properties with validation. This is needed for parseShortHand to work
154      * correctly and allows optimization in applyRule(..)
155      */
156 
157     case CSSPropertyTextAnchor:    // start | middle | end | inherit
158         if (id == CSSValueStart || id == CSSValueMiddle || id == CSSValueEnd)
159             valid_primitive = true;
160         break;
161 
162     case CSSPropertyGlyphOrientationVertical: // auto | <angle> | inherit
163         if (id == CSSValueAuto) {
164             valid_primitive = true;
165             break;
166         }
167     /* fallthrough intentional */
168     case CSSPropertyGlyphOrientationHorizontal: // <angle> (restricted to _deg_ per SVG 1.1 spec) | inherit
169         if (value->unit == CSSPrimitiveValue::CSS_DEG || value->unit == CSSPrimitiveValue::CSS_NUMBER) {
170             parsedValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_DEG);
171 
172             if (parsedValue)
173                 m_valueList->next();
174         }
175         break;
176 
177     case CSSPropertyFill:                 // <paint> | inherit
178     case CSSPropertyStroke:               // <paint> | inherit
179         {
180             if (id == CSSValueNone)
181                 parsedValue = SVGPaint::create(SVGPaint::SVG_PAINTTYPE_NONE);
182             else if (id == CSSValueCurrentcolor)
183                 parsedValue = SVGPaint::create(SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR);
184             else if (value->unit == CSSPrimitiveValue::CSS_URI) {
185                 RGBA32 c = Color::transparent;
186                 if (m_valueList->next() && parseColorFromValue(m_valueList->current(), c, true)) {
187                     parsedValue = SVGPaint::create(value->string, c);
188                 } else
189                     parsedValue = SVGPaint::create(SVGPaint::SVG_PAINTTYPE_URI, value->string);
190             } else
191                 parsedValue = parseSVGPaint();
192 
193             if (parsedValue)
194                 m_valueList->next();
195         }
196         break;
197 
198     case CSSPropertyColor:                // <color> | inherit
199         if ((id >= CSSValueAqua && id <= CSSValueWindowtext) ||
200            (id >= CSSValueAliceblue && id <= CSSValueYellowgreen))
201             parsedValue = SVGColor::create(value->string);
202         else
203             parsedValue = parseSVGColor();
204 
205         if (parsedValue)
206             m_valueList->next();
207         break;
208 
209     case CSSPropertyStopColor: // TODO : icccolor
210     case CSSPropertyFloodColor:
211     case CSSPropertyLightingColor:
212         if ((id >= CSSValueAqua && id <= CSSValueWindowtext) ||
213            (id >= CSSValueAliceblue && id <= CSSValueYellowgreen))
214             parsedValue = SVGColor::create(value->string);
215         else if (id == CSSValueCurrentcolor)
216             parsedValue = SVGColor::createCurrentColor();
217         else // TODO : svgcolor (iccColor)
218             parsedValue = parseSVGColor();
219 
220         if (parsedValue)
221             m_valueList->next();
222 
223         break;
224 
225     case CSSPropertyWritingMode:
226     // lr-tb | rl_tb | tb-rl | lr | rl | tb | inherit
227         if (id >= CSSValueLrTb && id <= CSSValueTb)
228             valid_primitive = true;
229         break;
230 
231     case CSSPropertyStrokeWidth:         // <length> | inherit
232     case CSSPropertyStrokeDashoffset:
233         valid_primitive = validUnit(value, FLength | FPercent, false);
234         break;
235     case CSSPropertyStrokeDasharray:     // none | <dasharray> | inherit
236         if (id == CSSValueNone)
237             valid_primitive = true;
238         else
239             parsedValue = parseSVGStrokeDasharray();
240 
241         break;
242 
243     case CSSPropertyKerning:              // auto | normal | <length> | inherit
244         if (id == CSSValueAuto || id == CSSValueNormal)
245             valid_primitive = true;
246         else
247             valid_primitive = validUnit(value, FLength, false);
248         break;
249 
250     case CSSPropertyClipPath:    // <uri> | none | inherit
251     case CSSPropertyFilter:
252         if (id == CSSValueNone)
253             valid_primitive = true;
254         else if (value->unit == CSSPrimitiveValue::CSS_URI) {
255             parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
256             if (parsedValue)
257                 m_valueList->next();
258         }
259         break;
260     case CSSPropertyWebkitSvgShadow:
261         if (id == CSSValueNone)
262             valid_primitive = true;
263         else
264             return parseShadow(propId, important);
265 
266     /* shorthand properties */
267     case CSSPropertyMarker:
268     {
269         ShorthandScope scope(this, propId);
270         m_implicitShorthand = true;
271         if (!parseValue(CSSPropertyMarkerStart, important))
272             return false;
273         if (m_valueList->current()) {
274             rollbackLastProperties(1);
275             return false;
276         }
277         CSSValue* value = m_parsedProperties[m_numParsedProperties - 1]->value();
278         addProperty(CSSPropertyMarkerMid, value, important);
279         addProperty(CSSPropertyMarkerEnd, value, important);
280         m_implicitShorthand = false;
281         return true;
282     }
283     default:
284         // If you crash here, it's because you added a css property and are not handling it
285         // in either this switch statement or the one in CSSParser::parseValue
286         ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propId);
287         return false;
288     }
289 
290     if (valid_primitive) {
291         if (id != 0)
292             parsedValue = CSSPrimitiveValue::createIdentifier(id);
293         else if (value->unit == CSSPrimitiveValue::CSS_STRING)
294             parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
295         else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
296             parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
297         else if (value->unit >= CSSParserValue::Q_EMS)
298             parsedValue = CSSQuirkPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_EMS);
299         m_valueList->next();
300     }
301     if (!parsedValue || (m_valueList->current() && !inShorthand()))
302         return false;
303 
304     addProperty(propId, parsedValue.release(), important);
305     return true;
306 }
307 
parseSVGStrokeDasharray()308 PassRefPtr<CSSValue> CSSParser::parseSVGStrokeDasharray()
309 {
310     RefPtr<CSSValueList> ret = CSSValueList::createCommaSeparated();
311     CSSParserValue* value = m_valueList->current();
312     bool valid_primitive = true;
313     while (value) {
314         valid_primitive = validUnit(value, FLength | FPercent |FNonNeg, false);
315         if (!valid_primitive)
316             break;
317         if (value->id != 0)
318             ret->append(CSSPrimitiveValue::createIdentifier(value->id));
319         else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
320             ret->append(CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit));
321         value = m_valueList->next();
322         if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
323             value = m_valueList->next();
324     }
325     if (!valid_primitive)
326         return 0;
327     return ret.release();
328 }
329 
parseSVGPaint()330 PassRefPtr<CSSValue> CSSParser::parseSVGPaint()
331 {
332     RGBA32 c = Color::transparent;
333     if (!parseColorFromValue(m_valueList->current(), c, true))
334         return SVGPaint::create();
335     return SVGPaint::create(Color(c));
336 }
337 
parseSVGColor()338 PassRefPtr<CSSValue> CSSParser::parseSVGColor()
339 {
340     RGBA32 c = Color::transparent;
341     if (!parseColorFromValue(m_valueList->current(), c, true))
342         return 0;
343     return SVGColor::create(Color(c));
344 }
345 
346 }
347 
348 #endif // ENABLE(SVG)
349 
350 // vim:ts=4:noet
351