• 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 CSSPropertyTextRendering:   // auto | optimizeSpeed | optimizeLegibility | geometricPrecision | inherit
136         if (id == CSSValueAuto || id == CSSValueOptimizespeed || id == CSSValueOptimizelegibility ||
137        id == CSSValueGeometricprecision)
138             valid_primitive = true;
139         break;
140 
141     case CSSPropertyImageRendering:  // auto | optimizeSpeed |
142     case CSSPropertyColorRendering:  // optimizeQuality | inherit
143         if (id == CSSValueAuto || id == CSSValueOptimizespeed ||
144             id == CSSValueOptimizequality)
145             valid_primitive = true;
146         break;
147 
148     case CSSPropertyColorProfile: // auto | sRGB | <name> | <uri> inherit
149         if (id == CSSValueAuto || id == CSSValueSrgb)
150             valid_primitive = true;
151         break;
152 
153     case CSSPropertyColorInterpolation:   // auto | sRGB | linearRGB | inherit
154     case CSSPropertyColorInterpolationFilters:
155         if (id == CSSValueAuto || id == CSSValueSrgb || id == CSSValueLinearrgb)
156             valid_primitive = true;
157         break;
158 
159     /* Start of supported CSS properties with validation. This is needed for parseShortHand to work
160      * correctly and allows optimization in applyRule(..)
161      */
162 
163     case CSSPropertyTextAnchor:    // start | middle | end | inherit
164         if (id == CSSValueStart || id == CSSValueMiddle || id == CSSValueEnd)
165             valid_primitive = true;
166         break;
167 
168     case CSSPropertyGlyphOrientationVertical: // auto | <angle> | inherit
169         if (id == CSSValueAuto) {
170             valid_primitive = true;
171             break;
172         }
173     /* fallthrough intentional */
174     case CSSPropertyGlyphOrientationHorizontal: // <angle> (restricted to _deg_ per SVG 1.1 spec) | inherit
175         if (value->unit == CSSPrimitiveValue::CSS_DEG || value->unit == CSSPrimitiveValue::CSS_NUMBER) {
176             parsedValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_DEG);
177 
178             if (parsedValue)
179                 m_valueList->next();
180         }
181         break;
182 
183     case CSSPropertyFill:                 // <paint> | inherit
184     case CSSPropertyStroke:               // <paint> | inherit
185         {
186             if (id == CSSValueNone)
187                 parsedValue = SVGPaint::create(SVGPaint::SVG_PAINTTYPE_NONE);
188             else if (id == CSSValueCurrentcolor)
189                 parsedValue = SVGPaint::create(SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR);
190             else if (value->unit == CSSPrimitiveValue::CSS_URI) {
191                 RGBA32 c = Color::transparent;
192                 if (m_valueList->next() && parseColorFromValue(m_valueList->current(), c, true)) {
193                     parsedValue = SVGPaint::create(value->string, c);
194                 } else
195                     parsedValue = SVGPaint::create(SVGPaint::SVG_PAINTTYPE_URI, value->string);
196             } else
197                 parsedValue = parseSVGPaint();
198 
199             if (parsedValue)
200                 m_valueList->next();
201         }
202         break;
203 
204     case CSSPropertyColor:                // <color> | inherit
205         if ((id >= CSSValueAqua && id <= CSSValueWindowtext) ||
206            (id >= CSSValueAliceblue && id <= CSSValueYellowgreen))
207             parsedValue = SVGColor::create(value->string);
208         else
209             parsedValue = parseSVGColor();
210 
211         if (parsedValue)
212             m_valueList->next();
213         break;
214 
215     case CSSPropertyStopColor: // TODO : icccolor
216     case CSSPropertyFloodColor:
217     case CSSPropertyLightingColor:
218         if ((id >= CSSValueAqua && id <= CSSValueWindowtext) ||
219            (id >= CSSValueAliceblue && id <= CSSValueYellowgreen))
220             parsedValue = SVGColor::create(value->string);
221         else if (id == CSSValueCurrentcolor)
222             parsedValue = SVGColor::createCurrentColor();
223         else // TODO : svgcolor (iccColor)
224             parsedValue = parseSVGColor();
225 
226         if (parsedValue)
227             m_valueList->next();
228 
229         break;
230 
231     case CSSPropertyWritingMode:
232     // lr-tb | rl_tb | tb-rl | lr | rl | tb | inherit
233         if (id >= CSSValueLrTb && id <= CSSValueTb)
234             valid_primitive = true;
235         break;
236 
237     case CSSPropertyStrokeWidth:         // <length> | inherit
238     case CSSPropertyStrokeDashoffset:
239         valid_primitive = validUnit(value, FLength | FPercent, false);
240         break;
241     case CSSPropertyStrokeDasharray:     // none | <dasharray> | inherit
242         if (id == CSSValueNone)
243             valid_primitive = true;
244         else
245             parsedValue = parseSVGStrokeDasharray();
246 
247         break;
248 
249     case CSSPropertyKerning:              // auto | normal | <length> | inherit
250         if (id == CSSValueAuto || id == CSSValueNormal)
251             valid_primitive = true;
252         else
253             valid_primitive = validUnit(value, FLength, false);
254         break;
255 
256     case CSSPropertyClipPath:    // <uri> | none | inherit
257     case CSSPropertyFilter:
258         if (id == CSSValueNone)
259             valid_primitive = true;
260         else if (value->unit == CSSPrimitiveValue::CSS_URI) {
261             parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
262             if (parsedValue)
263                 m_valueList->next();
264         }
265         break;
266 
267     /* shorthand properties */
268     case CSSPropertyMarker:
269     {
270         ShorthandScope scope(this, propId);
271         m_implicitShorthand = true;
272         if (!parseValue(CSSPropertyMarkerStart, important))
273             return false;
274         if (m_valueList->current()) {
275             rollbackLastProperties(1);
276             return false;
277         }
278         CSSValue* value = m_parsedProperties[m_numParsedProperties - 1]->value();
279         addProperty(CSSPropertyMarkerMid, value, important);
280         addProperty(CSSPropertyMarkerEnd, value, important);
281         m_implicitShorthand = false;
282         return true;
283     }
284     default:
285         // If you crash here, it's because you added a css property and are not handling it
286         // in either this switch statement or the one in CSSParser::parseValue
287         ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propId);
288         return false;
289     }
290 
291     if (valid_primitive) {
292         if (id != 0)
293             parsedValue = CSSPrimitiveValue::createIdentifier(id);
294         else if (value->unit == CSSPrimitiveValue::CSS_STRING)
295             parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
296         else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
297             parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
298         else if (value->unit >= CSSParserValue::Q_EMS)
299             parsedValue = CSSQuirkPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_EMS);
300         m_valueList->next();
301     }
302     if (!parsedValue || (m_valueList->current() && !inShorthand()))
303         return false;
304 
305     addProperty(propId, parsedValue.release(), important);
306     return true;
307 }
308 
parseSVGStrokeDasharray()309 PassRefPtr<CSSValue> CSSParser::parseSVGStrokeDasharray()
310 {
311     RefPtr<CSSValueList> ret = CSSValueList::createCommaSeparated();
312     CSSParserValue* value = m_valueList->current();
313     bool valid_primitive = true;
314     while (value) {
315         valid_primitive = validUnit(value, FLength | FPercent |FNonNeg, false);
316         if (!valid_primitive)
317             break;
318         if (value->id != 0)
319             ret->append(CSSPrimitiveValue::createIdentifier(value->id));
320         else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
321             ret->append(CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit));
322         value = m_valueList->next();
323         if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
324             value = m_valueList->next();
325     }
326     if (!valid_primitive)
327         return 0;
328     return ret.release();
329 }
330 
parseSVGPaint()331 PassRefPtr<CSSValue> CSSParser::parseSVGPaint()
332 {
333     RGBA32 c = Color::transparent;
334     if (!parseColorFromValue(m_valueList->current(), c, true))
335         return SVGPaint::create();
336     return SVGPaint::create(Color(c));
337 }
338 
parseSVGColor()339 PassRefPtr<CSSValue> CSSParser::parseSVGColor()
340 {
341     RGBA32 c = Color::transparent;
342     if (!parseColorFromValue(m_valueList->current(), c, true))
343         return 0;
344     return SVGColor::create(Color(c));
345 }
346 
347 }
348 
349 #endif // ENABLE(SVG)
350 
351 // vim:ts=4:noet
352