2 Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
3 2004, 2005 Rob Buis <buis@kde.org>
4 Copyright (C) 2005, 2006 Apple Computer, Inc.
6 This file is part of the KDE project
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.
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.
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., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.
30 #include "CSSInheritedValue.h"
31 #include "CSSInitialValue.h"
32 #include "cssparser.h"
33 #include "CSSPropertyNames.h"
34 #include "CSSQuirkPrimitiveValue.h"
35 #include "CSSValueKeywords.h"
36 #include "CSSValueList.h"
37 #include "ksvgcssproperties.c"
38 #include "ksvgcssvalues.c"
44 typedef Value KDOMCSSValue;
45 typedef ValueList KDOMCSSValueList;
47 bool CSSParser::parseSVGValue(int propId, bool important)
52 KDOMCSSValue *value = valueList->current();
58 int num = inShorthand() ? 1 : valueList->size();
60 if (id == CSS_VAL_INHERIT) {
63 addProperty(propId, new CSSInheritedValue(), important);
65 } else if (id == CSS_VAL_INITIAL) {
68 addProperty(propId, new CSSInitialValue(), important);
72 bool valid_primitive = false;
73 CSSValue *parsedValue = 0;
77 /* The comment to the right defines all valid value of these
78 * properties as defined in SVG 1.1, Appendix N. Property index */
79 case SVGCSS_PROP_ALIGNMENT_BASELINE:
80 // auto | baseline | before-edge | text-before-edge | middle |
81 // central | after-edge | text-after-edge | ideographic | alphabetic |
82 // hanging | mathematical | inherit
83 if (id == CSS_VAL_AUTO || id == CSS_VAL_BASELINE || id == CSS_VAL_MIDDLE ||
84 (id >= SVGCSS_VAL_BEFORE_EDGE && id <= SVGCSS_VAL_MATHEMATICAL))
85 valid_primitive = true;
88 case SVGCSS_PROP_BASELINE_SHIFT:
89 // baseline | super | sub | <percentage> | <length> | inherit
90 if (id == CSS_VAL_BASELINE || id == CSS_VAL_SUB ||
92 valid_primitive = true;
94 valid_primitive = validUnit(value, FLength|FPercent, false);
97 case SVGCSS_PROP_DOMINANT_BASELINE:
98 // auto | use-script | no-change | reset-size | ideographic |
99 // alphabetic | hanging | mathematical | central | middle |
100 // text-after-edge | text-before-edge | inherit
101 if (id == CSS_VAL_AUTO || id == CSS_VAL_MIDDLE ||
102 (id >= SVGCSS_VAL_USE_SCRIPT && id <= SVGCSS_VAL_RESET_SIZE) ||
103 (id >= SVGCSS_VAL_CENTRAL && id <= SVGCSS_VAL_MATHEMATICAL))
104 valid_primitive = true;
107 case SVGCSS_PROP_ENABLE_BACKGROUND:
108 // accumulate | new [x] [y] [width] [height] | inherit
109 if (id == SVGCSS_VAL_ACCUMULATE) // TODO : new
110 valid_primitive = true;
113 case SVGCSS_PROP_MARKER_START:
114 case SVGCSS_PROP_MARKER_MID:
115 case SVGCSS_PROP_MARKER_END:
116 case SVGCSS_PROP_MASK:
117 if (id == CSS_VAL_NONE)
118 valid_primitive = true;
119 else if (value->unit == CSSPrimitiveValue::CSS_URI)
121 parsedValue = new CSSPrimitiveValue(domString(value->string), CSSPrimitiveValue::CSS_URI);
127 case SVGCSS_PROP_CLIP_RULE: // nonzero | evenodd | inherit
128 case SVGCSS_PROP_FILL_RULE:
129 if (id == SVGCSS_VAL_NONZERO || id == SVGCSS_VAL_EVENODD)
130 valid_primitive = true;
133 case SVGCSS_PROP_STROKE_MITERLIMIT: // <miterlimit> | inherit
134 valid_primitive = validUnit(value, FInteger|FNonNeg, false);
137 case SVGCSS_PROP_STROKE_LINEJOIN: // miter | round | bevel | inherit
138 if (id == SVGCSS_VAL_MITER || id == CSS_VAL_ROUND || id == SVGCSS_VAL_BEVEL)
139 valid_primitive = true;
142 case SVGCSS_PROP_STROKE_LINECAP: // butt | round | square | inherit
143 if (id == SVGCSS_VAL_BUTT || id == CSS_VAL_ROUND || id == CSS_VAL_SQUARE)
144 valid_primitive = true;
147 case SVGCSS_PROP_STROKE_OPACITY: // <opacity-value> | inherit
148 case SVGCSS_PROP_FILL_OPACITY:
149 case SVGCSS_PROP_STOP_OPACITY:
150 case SVGCSS_PROP_FLOOD_OPACITY:
151 valid_primitive = (!id && validUnit(value, FNumber|FPercent, false));
154 case SVGCSS_PROP_SHAPE_RENDERING:
155 // auto | optimizeSpeed | crispEdges | geometricPrecision | inherit
156 if (id == CSS_VAL_AUTO || id == SVGCSS_VAL_OPTIMIZESPEED ||
157 id == SVGCSS_VAL_CRISPEDGES || id == SVGCSS_VAL_GEOMETRICPRECISION)
158 valid_primitive = true;
161 case SVGCSS_PROP_TEXT_RENDERING: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision | inherit
162 if (id == CSS_VAL_AUTO || id == SVGCSS_VAL_OPTIMIZESPEED || id == SVGCSS_VAL_OPTIMIZELEGIBILITY ||
163 id == SVGCSS_VAL_GEOMETRICPRECISION)
164 valid_primitive = true;
167 case SVGCSS_PROP_IMAGE_RENDERING: // auto | optimizeSpeed |
168 case SVGCSS_PROP_COLOR_RENDERING: // optimizeQuality | inherit
169 if (id == CSS_VAL_AUTO || id == SVGCSS_VAL_OPTIMIZESPEED ||
170 id == SVGCSS_VAL_OPTIMIZEQUALITY)
171 valid_primitive = true;
174 case SVGCSS_PROP_COLOR_PROFILE: // auto | sRGB | <name> | <uri> inherit
175 if (id == CSS_VAL_AUTO || id == SVGCSS_VAL_SRGB)
176 valid_primitive = true;
179 case SVGCSS_PROP_COLOR_INTERPOLATION: // auto | sRGB | linearRGB | inherit
180 case SVGCSS_PROP_COLOR_INTERPOLATION_FILTERS:
181 if (id == CSS_VAL_AUTO || id == SVGCSS_VAL_SRGB || id == SVGCSS_VAL_LINEARRGB)
182 valid_primitive = true;
185 /* Start of supported CSS properties with validation. This is needed for parseShortHand to work
186 * correctly and allows optimization in applyRule(..)
189 case SVGCSS_PROP_POINTER_EVENTS:
190 // visiblePainted | visibleFill | visibleStroke | visible |
191 // painted | fill | stroke || all | inherit
192 if (id == CSS_VAL_VISIBLE ||
193 (id >= SVGCSS_VAL_VISIBLEPAINTED && id <= SVGCSS_VAL_ALL))
194 valid_primitive = true;
197 case SVGCSS_PROP_TEXT_ANCHOR: // start | middle | end | inherit
198 if (id == CSS_VAL_START || id == CSS_VAL_MIDDLE || id == CSS_VAL_END)
199 valid_primitive = true;
202 case SVGCSS_PROP_GLYPH_ORIENTATION_VERTICAL: // auto | <angle> | inherit
203 if (id == CSS_VAL_AUTO)
205 valid_primitive = true;
208 /* fallthrough intentional */
209 case SVGCSS_PROP_GLYPH_ORIENTATION_HORIZONTAL: // <angle> | inherit
210 if (value->unit == CSSPrimitiveValue::CSS_DEG)
211 parsedValue = new CSSPrimitiveValue(value->fValue, CSSPrimitiveValue::CSS_DEG);
212 else if (value->unit == CSSPrimitiveValue::CSS_GRAD)
213 parsedValue = new CSSPrimitiveValue(value->fValue, CSSPrimitiveValue::CSS_GRAD);
214 else if (value->unit == CSSPrimitiveValue::CSS_RAD)
215 parsedValue = new CSSPrimitiveValue(value->fValue, CSSPrimitiveValue::CSS_RAD);
218 case SVGCSS_PROP_FILL: // <paint> | inherit
219 case SVGCSS_PROP_STROKE: // <paint> | inherit
221 if (id == CSS_VAL_NONE)
222 parsedValue = new SVGPaint(SVG_PAINTTYPE_NONE);
223 else if (id == SVGCSS_VAL_CURRENTCOLOR)
224 parsedValue = new SVGPaint(SVG_PAINTTYPE_CURRENTCOLOR);
225 else if (value->unit == CSSPrimitiveValue::CSS_URI)
226 parsedValue = new SVGPaint(SVG_PAINTTYPE_URI, domString(value->string).impl());
228 parsedValue = parseSVGPaint();
235 case CSS_PROP_COLOR: // <color> | inherit
236 if ((id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT) ||
237 (id >= SVGCSS_VAL_ALICEBLUE && id <= SVGCSS_VAL_YELLOWGREEN))
238 parsedValue = new SVGColor(domString(value->string).impl());
240 parsedValue = parseSVGColor();
246 case SVGCSS_PROP_STOP_COLOR: // TODO : icccolor
247 case SVGCSS_PROP_FLOOD_COLOR:
248 case SVGCSS_PROP_LIGHTING_COLOR:
249 if ((id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT) ||
250 (id >= SVGCSS_VAL_ALICEBLUE && id <= SVGCSS_VAL_YELLOWGREEN))
251 parsedValue = new SVGColor(domString(value->string).impl());
252 else if (id == SVGCSS_VAL_CURRENTCOLOR)
253 parsedValue = new SVGColor(SVGColor::SVG_COLORTYPE_CURRENTCOLOR);
254 else // TODO : svgcolor (iccColor)
255 parsedValue = parseSVGColor();
262 case SVGCSS_PROP_WRITING_MODE:
263 // lr-tb | rl_tb | tb-rl | lr | rl | tb | inherit
264 if (id >= SVGCSS_VAL_LR_TB && id <= SVGCSS_VAL_TB)
265 valid_primitive = true;
268 case SVGCSS_PROP_STROKE_WIDTH: // <length> | inherit
269 case SVGCSS_PROP_STROKE_DASHOFFSET:
270 valid_primitive = validUnit(value, FLength | FPercent, false);
272 case SVGCSS_PROP_STROKE_DASHARRAY: // none | <dasharray> | inherit
273 if (id == CSS_VAL_NONE)
274 valid_primitive = true;
276 parsedValue = parseSVGStrokeDasharray();
280 case SVGCSS_PROP_KERNING: // auto | normal | <length> | inherit
281 if (id == CSS_VAL_AUTO)
282 valid_primitive = true;
284 valid_primitive = validUnit(value, FLength, false);
287 case SVGCSS_PROP_CLIP_PATH: // <uri> | none | inherit
288 case SVGCSS_PROP_FILTER:
289 if (id == CSS_VAL_NONE)
290 valid_primitive = true;
291 else if (value->unit == CSSPrimitiveValue::CSS_URI)
293 parsedValue = new CSSPrimitiveValue(domString(value->string), (CSSPrimitiveValue::UnitTypes) value->unit);
299 /* shorthand properties */
300 case SVGCSS_PROP_MARKER:
302 const int properties[3] = { SVGCSS_PROP_MARKER_START,
303 SVGCSS_PROP_MARKER_MID,
304 SVGCSS_PROP_MARKER_END };
305 return parseShorthand(propId, properties, 3, important);
314 parsedValue = new CSSPrimitiveValue(id);
315 else if (value->unit == CSSPrimitiveValue::CSS_STRING)
316 parsedValue = new CSSPrimitiveValue(domString(value->string), (CSSPrimitiveValue::UnitTypes) value->unit);
317 else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
318 parsedValue = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
319 else if (value->unit >= KDOMCSSValue::Q_EMS)
320 parsedValue = new CSSQuirkPrimitiveValue(value->fValue, CSSPrimitiveValue::CSS_EMS);
324 if (!valueList->current() || inShorthand()) {
325 addProperty(propId, parsedValue, important);
333 CSSValue* CSSParser::parseSVGStrokeDasharray()
335 CSSValueList* ret = new CSSValueList;
336 KDOMCSSValue* value = valueList->current();
337 bool valid_primitive = true;
338 while(valid_primitive && value) {
339 valid_primitive = validUnit(value, FLength | FPercent |FNonNeg, false);
341 ret->append(new CSSPrimitiveValue(value->id));
342 else if (value->unit == CSSPrimitiveValue::CSS_STRING)
343 ret->append(new CSSPrimitiveValue(domString(value->string), (CSSPrimitiveValue::UnitTypes) value->unit));
344 else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
345 ret->append(new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit));
346 value = valueList->next();
347 if (value && value->unit == KDOMCSSValue::Operator && value->iValue == ',')
348 value = valueList->next();
350 if (!valid_primitive) {
358 CSSValue *CSSParser::parseSVGPaint()
360 KDOMCSSValue *value = valueList->current();
361 if (!strict && value->unit == CSSPrimitiveValue::CSS_NUMBER &&
362 value->fValue >= 0. && value->fValue < 1000000.) {
363 String str = String::sprintf("%06d", (int)(value->fValue+.5));
364 return new SVGPaint(SVG_PAINTTYPE_RGBCOLOR, 0, str.impl());
365 } else if (value->unit == CSSPrimitiveValue::CSS_RGBCOLOR) {
366 String str = "#" + domString(value->string);
367 return new SVGPaint(SVG_PAINTTYPE_RGBCOLOR, 0, str.impl());
368 } else if (value->unit == CSSPrimitiveValue::CSS_IDENT ||
369 (!strict && value->unit == CSSPrimitiveValue::CSS_DIMENSION))
370 return new SVGPaint(SVG_PAINTTYPE_RGBCOLOR, 0, domString(value->string).impl());
371 else if (value->unit == KDOMCSSValue::Function && value->function->args != 0 &&
372 domString(value->function->name).lower() == "rgb(")
374 KDOMCSSValueList *args = value->function->args;
375 KDOMCSSValue *v = args->current();
376 if (!validUnit(v, FInteger|FPercent, true))
378 int r = (int) (v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.));
380 if (v->unit != KDOMCSSValue::Operator && v->iValue != ',')
383 if (!validUnit(v, FInteger|FPercent, true))
385 int g = (int) (v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.));
387 if (v->unit != KDOMCSSValue::Operator && v->iValue != ',')
390 if (!validUnit(v, FInteger|FPercent, true))
392 int b = (int) (v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.));
393 r = max(0, min(255, r));
394 g = max(0, min(255, g));
395 b = max(0, min(255, b));
397 return new SVGPaint(SVG_PAINTTYPE_RGBCOLOR, 0, String::sprintf("rgb(%d, %d, %d)", r, g, b).impl());
402 return new SVGPaint();
405 CSSValue *CSSParser::parseSVGColor()
407 KDOMCSSValue *value = valueList->current();
408 if (!strict && value->unit == CSSPrimitiveValue::CSS_NUMBER && value->fValue >= 0. && value->fValue < 1000000.)
409 return new SVGColor(String::sprintf("%06d", (int)(value->fValue+.5)).impl());
410 else if (value->unit == CSSPrimitiveValue::CSS_RGBCOLOR) {
411 String str = "#" + domString(value->string);
412 return new SVGColor(str.impl());
413 } else if (value->unit == CSSPrimitiveValue::CSS_IDENT || (!strict && value->unit == CSSPrimitiveValue::CSS_DIMENSION))
414 return new SVGColor(domString(value->string).impl());
415 else if (value->unit == KDOMCSSValue::Function && value->function->args != 0 && domString(value->function->name).lower() == "rgb(") {
416 KDOMCSSValueList *args = value->function->args;
417 KDOMCSSValue *v = args->current();
418 if (!validUnit(v, FInteger|FPercent, true))
420 int r = (int) (v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.));
422 if (v->unit != Value::Operator && v->iValue != ',')
425 if (!validUnit(v, FInteger|FPercent, true))
427 int g = (int) (v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.));
429 if (v->unit != Value::Operator && v->iValue != ',')
432 if (!validUnit(v, FInteger|FPercent, true))
434 int b = (int) (v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.));
435 r = max(0, min(255, r));
436 g = max(0, min(255, g));
437 b = max(0, min(255, b));
439 return new SVGColor(String::sprintf("rgb(%d, %d, %d)", r, g, b).impl());
444 return new SVGPaint();
449 #endif // SVG_SUPPORT