1 /*
2 Copyright (C) 2005 Apple Computer, Inc.
3 Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
4 2004, 2005, 2008 Rob Buis <buis@kde.org>
5 Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
6
7 Based on khtml css code by:
8 Copyright(C) 1999-2003 Lars Knoll(knoll@kde.org)
9 (C) 2003 Apple Computer, Inc.
10 (C) 2004 Allan Sandfeld Jensen(kde@carewolf.com)
11 (C) 2004 Germain Garand(germain@ebooksfrance.org)
12
13 This file is part of the KDE project
14
15 This library is free software; you can redistribute it and/or
16 modify it under the terms of the GNU Library General Public
17 License as published by the Free Software Foundation; either
18 version 2 of the License, or (at your option) any later version.
19
20 This library is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Library General Public License for more details.
24
25 You should have received a copy of the GNU Library General Public License
26 along with this library; see the file COPYING.LIB. If not, write to
27 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28 Boston, MA 02110-1301, USA.
29 */
30
31 #include "config.h"
32
33 #if ENABLE(SVG)
34 #include "CSSStyleSelector.h"
35
36 #include "CSSPrimitiveValueMappings.h"
37 #include "CSSPropertyNames.h"
38 #include "CSSValueList.h"
39 #include "Document.h"
40 #include "SVGColor.h"
41 #include "SVGNames.h"
42 #include "SVGPaint.h"
43 #include "SVGRenderStyle.h"
44 #include "SVGRenderStyleDefs.h"
45 #include "SVGStyledElement.h"
46 #include "SVGURIReference.h"
47 #include <stdlib.h>
48 #include <wtf/MathExtras.h>
49
50 #define HANDLE_INHERIT(prop, Prop) \
51 if (isInherit) \
52 {\
53 svgstyle->set##Prop(m_parentStyle->svgStyle()->prop());\
54 return;\
55 }
56
57 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
58 HANDLE_INHERIT(prop, Prop) \
59 else if (isInitial) \
60 svgstyle->set##Prop(SVGRenderStyle::initial##Prop());
61
62
63 namespace WebCore {
64
roundToNearestGlyphOrientationAngle(float angle)65 static float roundToNearestGlyphOrientationAngle(float angle)
66 {
67 angle = fabsf(fmodf(angle, 360.0f));
68
69 if (angle <= 45.0f || angle > 315.0f)
70 return 0.0f;
71 else if (angle > 45.0f && angle <= 135.0f)
72 return 90.0f;
73 else if (angle > 135.0f && angle <= 225.0f)
74 return 180.0f;
75
76 return 270.0f;
77 }
78
angleToGlyphOrientation(float angle)79 static int angleToGlyphOrientation(float angle)
80 {
81 angle = roundToNearestGlyphOrientationAngle(angle);
82
83 if (angle == 0.0f)
84 return GO_0DEG;
85 else if (angle == 90.0f)
86 return GO_90DEG;
87 else if (angle == 180.0f)
88 return GO_180DEG;
89 else if (angle == 270.0f)
90 return GO_270DEG;
91
92 return -1;
93 }
94
colorFromSVGColorCSSValue(CSSValue * value,RenderStyle * style)95 static Color colorFromSVGColorCSSValue(CSSValue* value, RenderStyle* style)
96 {
97 ASSERT(value->isSVGColor());
98 SVGColor* c = static_cast<SVGColor*>(value);
99 Color color;
100 if (c->colorType() == SVGColor::SVG_COLORTYPE_CURRENTCOLOR)
101 color = style->color();
102 else
103 color = c->color();
104 return color;
105 }
106
applySVGProperty(int id,CSSValue * value)107 void CSSStyleSelector::applySVGProperty(int id, CSSValue* value)
108 {
109 ASSERT(value);
110 CSSPrimitiveValue* primitiveValue = 0;
111 if (value->isPrimitiveValue())
112 primitiveValue = static_cast<CSSPrimitiveValue*>(value);
113
114 SVGRenderStyle* svgstyle = m_style->accessSVGStyle();
115 unsigned short valueType = value->cssValueType();
116
117 bool isInherit = m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT;
118 bool isInitial = valueType == CSSPrimitiveValue::CSS_INITIAL || (!m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT);
119
120 // What follows is a list that maps the CSS properties into their
121 // corresponding front-end RenderStyle values. Shorthands(e.g. border,
122 // background) occur in this list as well and are only hit when mapping
123 // "inherit" or "initial" into front-end values.
124 switch (id)
125 {
126 // ident only properties
127 case CSSPropertyAlignmentBaseline:
128 {
129 HANDLE_INHERIT_AND_INITIAL(alignmentBaseline, AlignmentBaseline)
130 if (!primitiveValue)
131 break;
132
133 svgstyle->setAlignmentBaseline(*primitiveValue);
134 break;
135 }
136 case CSSPropertyBaselineShift:
137 {
138 HANDLE_INHERIT_AND_INITIAL(baselineShift, BaselineShift);
139 if (!primitiveValue)
140 break;
141
142 if (primitiveValue->getIdent()) {
143 switch (primitiveValue->getIdent()) {
144 case CSSValueBaseline:
145 svgstyle->setBaselineShift(BS_BASELINE);
146 break;
147 case CSSValueSub:
148 svgstyle->setBaselineShift(BS_SUB);
149 break;
150 case CSSValueSuper:
151 svgstyle->setBaselineShift(BS_SUPER);
152 break;
153 default:
154 break;
155 }
156 } else {
157 svgstyle->setBaselineShift(BS_LENGTH);
158 svgstyle->setBaselineShiftValue(primitiveValue);
159 }
160
161 break;
162 }
163 case CSSPropertyKerning:
164 {
165 HANDLE_INHERIT_AND_INITIAL(kerning, Kerning);
166 svgstyle->setKerning(primitiveValue);
167 break;
168 }
169 case CSSPropertyDominantBaseline:
170 {
171 HANDLE_INHERIT_AND_INITIAL(dominantBaseline, DominantBaseline)
172 if (primitiveValue)
173 svgstyle->setDominantBaseline(*primitiveValue);
174 break;
175 }
176 case CSSPropertyColorInterpolation:
177 {
178 HANDLE_INHERIT_AND_INITIAL(colorInterpolation, ColorInterpolation)
179 if (primitiveValue)
180 svgstyle->setColorInterpolation(*primitiveValue);
181 break;
182 }
183 case CSSPropertyColorInterpolationFilters:
184 {
185 HANDLE_INHERIT_AND_INITIAL(colorInterpolationFilters, ColorInterpolationFilters)
186 if (primitiveValue)
187 svgstyle->setColorInterpolationFilters(*primitiveValue);
188 break;
189 }
190 case CSSPropertyColorRendering:
191 {
192 HANDLE_INHERIT_AND_INITIAL(colorRendering, ColorRendering)
193 if (primitiveValue)
194 svgstyle->setColorRendering(*primitiveValue);
195 break;
196 }
197 case CSSPropertyClipRule:
198 {
199 HANDLE_INHERIT_AND_INITIAL(clipRule, ClipRule)
200 if (primitiveValue)
201 svgstyle->setClipRule(*primitiveValue);
202 break;
203 }
204 case CSSPropertyFillRule:
205 {
206 HANDLE_INHERIT_AND_INITIAL(fillRule, FillRule)
207 if (primitiveValue)
208 svgstyle->setFillRule(*primitiveValue);
209 break;
210 }
211 case CSSPropertyStrokeLinejoin:
212 {
213 HANDLE_INHERIT_AND_INITIAL(joinStyle, JoinStyle)
214 if (primitiveValue)
215 svgstyle->setJoinStyle(*primitiveValue);
216 break;
217 }
218 case CSSPropertyImageRendering:
219 {
220 HANDLE_INHERIT_AND_INITIAL(imageRendering, ImageRendering)
221 if (primitiveValue)
222 svgstyle->setImageRendering(*primitiveValue);
223 break;
224 }
225 case CSSPropertyShapeRendering:
226 {
227 HANDLE_INHERIT_AND_INITIAL(shapeRendering, ShapeRendering)
228 if (primitiveValue)
229 svgstyle->setShapeRendering(*primitiveValue);
230 break;
231 }
232 case CSSPropertyTextRendering:
233 {
234 HANDLE_INHERIT_AND_INITIAL(textRendering, TextRendering)
235 if (primitiveValue)
236 svgstyle->setTextRendering(*primitiveValue);
237 break;
238 }
239 // end of ident only properties
240 case CSSPropertyFill:
241 {
242 HANDLE_INHERIT_AND_INITIAL(fillPaint, FillPaint)
243 if (value->isSVGPaint())
244 svgstyle->setFillPaint(static_cast<SVGPaint*>(value));
245 break;
246 }
247 case CSSPropertyStroke:
248 {
249 HANDLE_INHERIT_AND_INITIAL(strokePaint, StrokePaint)
250 if (value->isSVGPaint())
251 svgstyle->setStrokePaint(static_cast<SVGPaint*>(value));
252
253 break;
254 }
255 case CSSPropertyStrokeWidth:
256 {
257 HANDLE_INHERIT_AND_INITIAL(strokeWidth, StrokeWidth)
258 if (primitiveValue)
259 svgstyle->setStrokeWidth(primitiveValue);
260 break;
261 }
262 case CSSPropertyStrokeDasharray:
263 {
264 HANDLE_INHERIT_AND_INITIAL(strokeDashArray, StrokeDashArray)
265 if (value->isValueList())
266 svgstyle->setStrokeDashArray(static_cast<CSSValueList*>(value));
267 break;
268 }
269 case CSSPropertyStrokeDashoffset:
270 {
271 HANDLE_INHERIT_AND_INITIAL(strokeDashOffset, StrokeDashOffset)
272 if (primitiveValue)
273 svgstyle->setStrokeDashOffset(primitiveValue);
274 break;
275 }
276 case CSSPropertyFillOpacity:
277 {
278 HANDLE_INHERIT_AND_INITIAL(fillOpacity, FillOpacity)
279 if (!primitiveValue)
280 return;
281
282 float f = 0.0f;
283 int type = primitiveValue->primitiveType();
284 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
285 f = primitiveValue->getFloatValue() / 100.0f;
286 else if (type == CSSPrimitiveValue::CSS_NUMBER)
287 f = primitiveValue->getFloatValue();
288 else
289 return;
290
291 svgstyle->setFillOpacity(f);
292 break;
293 }
294 case CSSPropertyStrokeOpacity:
295 {
296 HANDLE_INHERIT_AND_INITIAL(strokeOpacity, StrokeOpacity)
297 if (!primitiveValue)
298 return;
299
300 float f = 0.0f;
301 int type = primitiveValue->primitiveType();
302 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
303 f = primitiveValue->getFloatValue() / 100.0f;
304 else if (type == CSSPrimitiveValue::CSS_NUMBER)
305 f = primitiveValue->getFloatValue();
306 else
307 return;
308
309 svgstyle->setStrokeOpacity(f);
310 break;
311 }
312 case CSSPropertyStopOpacity:
313 {
314 HANDLE_INHERIT_AND_INITIAL(stopOpacity, StopOpacity)
315 if (!primitiveValue)
316 return;
317
318 float f = 0.0f;
319 int type = primitiveValue->primitiveType();
320 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
321 f = primitiveValue->getFloatValue() / 100.0f;
322 else if (type == CSSPrimitiveValue::CSS_NUMBER)
323 f = primitiveValue->getFloatValue();
324 else
325 return;
326
327 svgstyle->setStopOpacity(f);
328 break;
329 }
330 case CSSPropertyMarkerStart:
331 {
332 HANDLE_INHERIT_AND_INITIAL(startMarker, StartMarker)
333 if (!primitiveValue)
334 return;
335
336 String s;
337 int type = primitiveValue->primitiveType();
338 if (type == CSSPrimitiveValue::CSS_URI)
339 s = primitiveValue->getStringValue();
340 else
341 return;
342
343 svgstyle->setStartMarker(SVGURIReference::getTarget(s));
344 break;
345 }
346 case CSSPropertyMarkerMid:
347 {
348 HANDLE_INHERIT_AND_INITIAL(midMarker, MidMarker)
349 if (!primitiveValue)
350 return;
351
352 String s;
353 int type = primitiveValue->primitiveType();
354 if (type == CSSPrimitiveValue::CSS_URI)
355 s = primitiveValue->getStringValue();
356 else
357 return;
358
359 svgstyle->setMidMarker(SVGURIReference::getTarget(s));
360 break;
361 }
362 case CSSPropertyMarkerEnd:
363 {
364 HANDLE_INHERIT_AND_INITIAL(endMarker, EndMarker)
365 if (!primitiveValue)
366 return;
367
368 String s;
369 int type = primitiveValue->primitiveType();
370 if (type == CSSPrimitiveValue::CSS_URI)
371 s = primitiveValue->getStringValue();
372 else
373 return;
374
375 svgstyle->setEndMarker(SVGURIReference::getTarget(s));
376 break;
377 }
378 case CSSPropertyStrokeLinecap:
379 {
380 HANDLE_INHERIT_AND_INITIAL(capStyle, CapStyle)
381 if (primitiveValue)
382 svgstyle->setCapStyle(*primitiveValue);
383 break;
384 }
385 case CSSPropertyStrokeMiterlimit:
386 {
387 HANDLE_INHERIT_AND_INITIAL(strokeMiterLimit, StrokeMiterLimit)
388 if (!primitiveValue)
389 return;
390
391 float f = 0.0f;
392 int type = primitiveValue->primitiveType();
393 if (type == CSSPrimitiveValue::CSS_NUMBER)
394 f = primitiveValue->getFloatValue();
395 else
396 return;
397
398 svgstyle->setStrokeMiterLimit(f);
399 break;
400 }
401 case CSSPropertyFilter:
402 {
403 HANDLE_INHERIT_AND_INITIAL(filter, Filter)
404 if (!primitiveValue)
405 return;
406
407 String s;
408 int type = primitiveValue->primitiveType();
409 if (type == CSSPrimitiveValue::CSS_URI)
410 s = primitiveValue->getStringValue();
411 else
412 return;
413 svgstyle->setFilter(SVGURIReference::getTarget(s));
414 break;
415 }
416 case CSSPropertyMask:
417 {
418 HANDLE_INHERIT_AND_INITIAL(maskElement, MaskElement)
419 if (!primitiveValue)
420 return;
421
422 String s;
423 int type = primitiveValue->primitiveType();
424 if (type == CSSPrimitiveValue::CSS_URI)
425 s = primitiveValue->getStringValue();
426 else
427 return;
428
429 svgstyle->setMaskElement(SVGURIReference::getTarget(s));
430 break;
431 }
432 case CSSPropertyClipPath:
433 {
434 HANDLE_INHERIT_AND_INITIAL(clipPath, ClipPath)
435 if (!primitiveValue)
436 return;
437
438 String s;
439 int type = primitiveValue->primitiveType();
440 if (type == CSSPrimitiveValue::CSS_URI)
441 s = primitiveValue->getStringValue();
442 else
443 return;
444
445 svgstyle->setClipPath(SVGURIReference::getTarget(s));
446 break;
447 }
448 case CSSPropertyTextAnchor:
449 {
450 HANDLE_INHERIT_AND_INITIAL(textAnchor, TextAnchor)
451 if (primitiveValue)
452 svgstyle->setTextAnchor(*primitiveValue);
453 break;
454 }
455 case CSSPropertyWritingMode:
456 {
457 HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode)
458 if (primitiveValue)
459 svgstyle->setWritingMode(*primitiveValue);
460 break;
461 }
462 case CSSPropertyStopColor:
463 {
464 HANDLE_INHERIT_AND_INITIAL(stopColor, StopColor);
465 svgstyle->setStopColor(colorFromSVGColorCSSValue(value, m_style.get()));
466 break;
467 }
468 case CSSPropertyLightingColor:
469 {
470 HANDLE_INHERIT_AND_INITIAL(lightingColor, LightingColor);
471 svgstyle->setLightingColor(colorFromSVGColorCSSValue(value, m_style.get()));
472 break;
473 }
474 case CSSPropertyFloodOpacity:
475 {
476 HANDLE_INHERIT_AND_INITIAL(floodOpacity, FloodOpacity)
477 if (!primitiveValue)
478 return;
479
480 float f = 0.0f;
481 int type = primitiveValue->primitiveType();
482 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
483 f = primitiveValue->getFloatValue() / 100.0f;
484 else if (type == CSSPrimitiveValue::CSS_NUMBER)
485 f = primitiveValue->getFloatValue();
486 else
487 return;
488
489 svgstyle->setFloodOpacity(f);
490 break;
491 }
492 case CSSPropertyFloodColor:
493 {
494 if (isInitial) {
495 svgstyle->setFloodColor(SVGRenderStyle::initialFloodColor());
496 return;
497 }
498 svgstyle->setFloodColor(colorFromSVGColorCSSValue(value, m_style.get()));
499 break;
500 }
501 case CSSPropertyGlyphOrientationHorizontal:
502 {
503 HANDLE_INHERIT_AND_INITIAL(glyphOrientationHorizontal, GlyphOrientationHorizontal)
504 if (!primitiveValue)
505 return;
506
507 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) {
508 int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue());
509 ASSERT(orientation != -1);
510
511 svgstyle->setGlyphOrientationHorizontal((EGlyphOrientation) orientation);
512 }
513
514 break;
515 }
516 case CSSPropertyGlyphOrientationVertical:
517 {
518 HANDLE_INHERIT_AND_INITIAL(glyphOrientationVertical, GlyphOrientationVertical)
519 if (!primitiveValue)
520 return;
521
522 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) {
523 int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue());
524 ASSERT(orientation != -1);
525
526 svgstyle->setGlyphOrientationVertical((EGlyphOrientation) orientation);
527 } else if (primitiveValue->getIdent() == CSSValueAuto)
528 svgstyle->setGlyphOrientationVertical(GO_AUTO);
529
530 break;
531 }
532 case CSSPropertyEnableBackground:
533 // Silently ignoring this property for now
534 // http://bugs.webkit.org/show_bug.cgi?id=6022
535 break;
536 default:
537 // If you crash here, it's because you added a css property and are not handling it
538 // in either this switch statement or the one in CSSStyleSelector::applyProperty
539 ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", id);
540 return;
541 }
542 }
543
544 }
545
546 // vim:ts=4:noet
547 #endif // ENABLE(SVG)
548