1 /*
2 Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3 2004, 2005, 2007 Rob Buis <buis@kde.org>
4 Copyright (C) 2005, 2006 Apple Computer, Inc.
5
6 This file is part of the KDE project
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22 */
23
24 #include "cssparser.h"
25 #include "cssproperties.h"
26 #include "cssvalues.h"
27
28 #include "css/css_valueimpl.h"
29 #include "css/css_svgvalueimpl.h"
30
31 using namespace std;
32
33 namespace DOM
34 {
35
parseSVGValue(int propId,bool important)36 bool CSSParser::parseSVGValue(int propId, bool important)
37 {
38 Value *value = valueList->current();
39 if (!value) {
40 return false;
41 }
42
43 int id = value->id;
44
45 bool valid_primitive = false;
46 CSSValueImpl *parsedValue = nullptr;
47
48 switch (propId) {
49 /* The comment to the right defines all valid value of these
50 * properties as defined in SVG 1.1, Appendix N. Property index */
51 case CSS_PROP_ALIGNMENT_BASELINE:
52 // auto | baseline | before-edge | text-before-edge | middle |
53 // central | after-edge | text-after-edge | ideographic | alphabetic |
54 // hanging | mathematical | inherit
55 if (id == CSS_VAL_AUTO || id == CSS_VAL_BASELINE || id == CSS_VAL_MIDDLE ||
56 (id >= CSS_VAL_BEFORE_EDGE && id <= CSS_VAL_MATHEMATICAL)) {
57 valid_primitive = true;
58 }
59 break;
60
61 case CSS_PROP_BASELINE_SHIFT:
62 // baseline | super | sub | <percentage> | <length> | inherit
63 if (id == CSS_VAL_BASELINE || id == CSS_VAL_SUB || id >= CSS_VAL_SUPER) {
64 valid_primitive = true;
65 } else {
66 valid_primitive = validUnit(value, FLength | FPercent, false);
67 }
68 break;
69
70 case CSS_PROP_DOMINANT_BASELINE:
71 // auto | use-script | no-change | reset-size | ideographic |
72 // alphabetic | hanging | mathematical | central | middle |
73 // text-after-edge | text-before-edge | inherit
74 if (id == CSS_VAL_AUTO || id == CSS_VAL_MIDDLE ||
75 (id >= CSS_VAL_USE_SCRIPT && id <= CSS_VAL_RESET_SIZE) ||
76 (id >= CSS_VAL_CENTRAL && id <= CSS_VAL_MATHEMATICAL)) {
77 valid_primitive = true;
78 }
79 break;
80
81 case CSS_PROP_ENABLE_BACKGROUND:
82 // accumulate | new [x] [y] [width] [height] | inherit
83 if (id == CSS_VAL_ACCUMULATE) { // ### TODO: new
84 valid_primitive = true;
85 }
86 break;
87
88 case CSS_PROP_MARKER_START:
89 case CSS_PROP_MARKER_MID:
90 case CSS_PROP_MARKER_END:
91 case CSS_PROP_MASK:
92 if (id == CSS_VAL_NONE) {
93 valid_primitive = true;
94 } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
95 parsedValue = new CSSPrimitiveValueImpl(domString(value->string), CSSPrimitiveValue::CSS_URI);
96 if (parsedValue) {
97 valueList->next();
98 }
99 }
100 break;
101
102 case CSS_PROP_CLIP_RULE: // nonzero | evenodd | inherit
103 case CSS_PROP_FILL_RULE:
104 if (id == CSS_VAL_NONZERO || id == CSS_VAL_EVENODD) {
105 valid_primitive = true;
106 }
107 break;
108
109 case CSS_PROP_STROKE_MITERLIMIT: // <miterlimit> | inherit
110 valid_primitive = validUnit(value, FNumber | FNonNeg, false);
111 break;
112
113 case CSS_PROP_STROKE_LINEJOIN: // miter | round | bevel | inherit
114 if (id == CSS_VAL_MITER || id == CSS_VAL_ROUND || id == CSS_VAL_BEVEL) {
115 valid_primitive = true;
116 }
117 break;
118
119 case CSS_PROP_STROKE_LINECAP: // butt | round | square | inherit
120 if (id == CSS_VAL_BUTT || id == CSS_VAL_ROUND || id == CSS_VAL_SQUARE) {
121 valid_primitive = true;
122 }
123 break;
124
125 case CSS_PROP_STROKE_OPACITY: // <opacity-value> | inherit
126 case CSS_PROP_FILL_OPACITY:
127 case CSS_PROP_STOP_OPACITY:
128 case CSS_PROP_FLOOD_OPACITY:
129 valid_primitive = (!id && validUnit(value, FNumber | FPercent, false));
130 break;
131
132 case CSS_PROP_SHAPE_RENDERING:
133 // auto | optimizeSpeed | crispEdges | geometricPrecision | inherit
134 if (id == CSS_VAL_AUTO || id == CSS_VAL_OPTIMIZESPEED ||
135 id == CSS_VAL_CRISPEDGES || id == CSS_VAL_GEOMETRICPRECISION) {
136 valid_primitive = true;
137 }
138 break;
139
140 case CSS_PROP_TEXT_RENDERING: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision | inherit
141 if (id == CSS_VAL_AUTO || id == CSS_VAL_OPTIMIZESPEED || id == CSS_VAL_OPTIMIZELEGIBILITY ||
142 id == CSS_VAL_GEOMETRICPRECISION) {
143 valid_primitive = true;
144 }
145 break;
146
147 case CSS_PROP_IMAGE_RENDERING: // auto | optimizeSpeed |
148 case CSS_PROP_COLOR_RENDERING: // optimizeQuality | inherit
149 if (id == CSS_VAL_AUTO || id == CSS_VAL_OPTIMIZESPEED ||
150 id == CSS_VAL_OPTIMIZEQUALITY) {
151 valid_primitive = true;
152 }
153 break;
154
155 case CSS_PROP_COLOR_PROFILE: // auto | sRGB | <name> | <uri> inherit
156 if (id == CSS_VAL_AUTO || id == CSS_VAL_SRGB) {
157 valid_primitive = true;
158 }
159 break;
160
161 case CSS_PROP_COLOR_INTERPOLATION: // auto | sRGB | linearRGB | inherit
162 case CSS_PROP_COLOR_INTERPOLATION_FILTERS:
163 if (id == CSS_VAL_AUTO || id == CSS_VAL_SRGB || id == CSS_VAL_LINEARRGB) {
164 valid_primitive = true;
165 }
166 break;
167
168 case CSS_PROP_POINTER_EVENTS:
169 // visiblePainted | visibleFill | visibleStroke | visible |
170 // painted | fill | stroke | all | none | inherit
171 if (id == CSS_VAL_VISIBLE || id == CSS_VAL_NONE ||
172 (id >= CSS_VAL_VISIBLEPAINTED && id <= CSS_VAL_ALL)) {
173 valid_primitive = true;
174 }
175 break;
176
177 case CSS_PROP_TEXT_ANCHOR: // start | middle | end | inherit
178 if (id == CSS_VAL_START || id == CSS_VAL_MIDDLE || id == CSS_VAL_END) {
179 valid_primitive = true;
180 }
181 break;
182
183 case CSS_PROP_GLYPH_ORIENTATION_VERTICAL: // auto | <angle> | inherit
184 if (id == CSS_VAL_AUTO) {
185 valid_primitive = true;
186 break;
187 }
188 /* fallthrough intentional */
189 case CSS_PROP_GLYPH_ORIENTATION_HORIZONTAL: // <angle> (restricted to _deg_ per SVG 1.1 spec) | inherit
190 if (value->unit == CSSPrimitiveValue::CSS_DEG || value->unit == CSSPrimitiveValue::CSS_NUMBER) {
191 parsedValue = new CSSPrimitiveValueImpl(value->fValue, CSSPrimitiveValue::CSS_DEG);
192
193 if (parsedValue) {
194 valueList->next();
195 }
196 }
197 break;
198
199 case CSS_PROP_FILL: // <paint> | inherit
200 case CSS_PROP_STROKE: { // <paint> | inherit
201 if (id == CSS_VAL_NONE) {
202 parsedValue = new SVGPaintImpl(SVGPaintImpl::SVG_PAINTTYPE_NONE);
203 } else if (id == CSS_VAL_CURRENTCOLOR) {
204 parsedValue = new SVGPaintImpl(SVGPaintImpl::SVG_PAINTTYPE_CURRENTCOLOR);
205 } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
206 CSSPrimitiveValueImpl *val;
207 if (valueList->next() && (val = parseColorFromValue(valueList->current()/*, c, true*/))) {
208 parsedValue = new SVGPaintImpl(domString(value->string), val->getRGBColorValue());
209 delete val;
210 } else {
211 parsedValue = new SVGPaintImpl(SVGPaintImpl::SVG_PAINTTYPE_URI, domString(value->string));
212 }
213 } else {
214 parsedValue = parseSVGPaint();
215 }
216
217 if (parsedValue) {
218 valueList->next();
219 }
220 }
221 break;
222
223 /*case CSS_PROP_Color: // <color> | inherit
224 if ((id >= CSS_VAL_Aqua && id <= CSS_VAL_Windowtext) ||
225 (id >= CSS_VAL_Aliceblue && id <= CSS_VAL_Yellowgreen))
226 parsedValue = new SVGColor(value->string);
227 else
228 parsedValue = parseSVGColor();
229
230 if (parsedValue)
231 valueList->next();
232 break;*/
233
234 case CSS_PROP_STOP_COLOR: // TODO : icccolor
235 case CSS_PROP_FLOOD_COLOR:
236 case CSS_PROP_LIGHTING_COLOR:
237 if ((id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT)/* ||
238 (id >= CSS_VAL_Aliceblue && id <= CSS_VAL_Yellowgreen)*/) {
239 parsedValue = new SVGColorImpl(domString(value->string));
240 } else if (id == CSS_VAL_CURRENTCOLOR) {
241 parsedValue = new SVGColorImpl(SVGColorImpl::SVG_COLORTYPE_CURRENTCOLOR);
242 } else { // TODO : svgcolor (iccColor)
243 parsedValue = parseSVGColor();
244 }
245
246 if (parsedValue) {
247 valueList->next();
248 }
249
250 break;
251
252 case CSS_PROP_WRITING_MODE:
253 // lr-tb | rl_tb | tb-rl | lr | rl | tb | inherit
254 if (id >= CSS_VAL_LR_TB && id <= CSS_VAL_TB) {
255 valid_primitive = true;
256 }
257 break;
258
259 case CSS_PROP_STROKE_WIDTH: // <length> | inherit
260 case CSS_PROP_STROKE_DASHOFFSET:
261 valid_primitive = validUnit(value, FLength | FPercent, false);
262 break;
263
264 case CSS_PROP_STROKE_DASHARRAY: // none | <dasharray> | inherit
265 if (id == CSS_VAL_NONE) {
266 valid_primitive = true;
267 } else {
268 parsedValue = parseSVGStrokeDasharray();
269 }
270
271 break;
272
273 case CSS_PROP_KERNING: // auto | normal | <length> | inherit
274 if (id == CSS_VAL_AUTO || id == CSS_VAL_NORMAL) {
275 valid_primitive = true;
276 } else {
277 valid_primitive = validUnit(value, FLength, false);
278 }
279 break;
280
281 case CSS_PROP_CLIP_PATH: // <uri> | none | inherit
282 case CSS_PROP_FILTER:
283 if (id == CSS_VAL_NONE) {
284 valid_primitive = true;
285 } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
286 parsedValue = new CSSPrimitiveValueImpl(domString(value->string), (CSSPrimitiveValue::UnitTypes) value->unit);
287 if (parsedValue) {
288 valueList->next();
289 }
290 }
291 break;
292
293 /* shorthand properties */
294 case CSS_PROP_MARKER: {
295 const int properties[3] = { CSS_PROP_MARKER_START, CSS_PROP_MARKER_MID,
296 CSS_PROP_MARKER_END
297 };
298 return parseShortHand(propId, properties, 3, important);
299
300 }
301 default:
302 // If you crash here, it's because you added a css property and are not handling it
303 // in either this switch statement or the one in CSSParser::parseValue
304 //ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propId);
305 //return false;
306 break;
307 }
308
309 if (valid_primitive) {
310 if (id != 0) {
311 parsedValue = new CSSPrimitiveValueImpl(id);
312 } else if (value->unit == CSSPrimitiveValue::CSS_STRING) {
313 parsedValue = new CSSPrimitiveValueImpl(domString(value->string), (CSSPrimitiveValue::UnitTypes)value->unit);
314 } else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) {
315 parsedValue = new CSSPrimitiveValueImpl(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
316 } else if (value->unit >= Value::Q_EMS) {
317 parsedValue = new CSSQuirkPrimitiveValueImpl(value->fValue, CSSPrimitiveValue::CSS_EMS);
318 }
319 valueList->next();
320 }
321 if (!parsedValue || (valueList->current() && !inShorthand())) {
322 delete parsedValue;
323 return false;
324 }
325
326 addProperty(propId, parsedValue, important);
327 return true;
328 }
329
parseSVGStrokeDasharray()330 CSSValueImpl *CSSParser::parseSVGStrokeDasharray()
331 {
332 CSSValueListImpl *ret = new CSSValueListImpl(CSSValueListImpl::Comma);
333 Value *value = valueList->current();
334 bool valid_primitive = true;
335 while (value) {
336 valid_primitive = validUnit(value, FLength | FPercent | FNonNeg, false);
337 if (!valid_primitive) {
338 break;
339 }
340 if (value->id != 0) {
341 ret->append(new CSSPrimitiveValueImpl(value->id));
342 } else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) {
343 ret->append(new CSSPrimitiveValueImpl(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit));
344 }
345 value = valueList->next();
346 if (value && value->unit == Value::Operator && value->iValue == ',') {
347 value = valueList->next();
348 }
349 }
350 if (!valid_primitive) {
351 delete ret;
352 ret = nullptr;
353 }
354
355 return ret;
356 }
357
parseSVGPaint()358 CSSValueImpl *CSSParser::parseSVGPaint()
359 {
360 CSSPrimitiveValueImpl *val;
361
362 if (!(val = parseColorFromValue(valueList->current()/*, c, true*/))) {
363 return new SVGPaintImpl();
364 }
365
366 SVGPaintImpl *paint = new SVGPaintImpl(QColor(val->getRGBColorValue()));
367 delete val;
368 return paint;
369 }
370
parseSVGColor()371 CSSValueImpl *CSSParser::parseSVGColor()
372 {
373 CSSPrimitiveValueImpl *val;
374 if (!(val = parseColorFromValue(valueList->current()/*, c, true*/))) {
375 return nullptr;
376 }
377 SVGColorImpl *color = new SVGColorImpl(QColor(val->getRGBColorValue()));
378 delete val;
379 return color;
380 }
381
382 }
383
384