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 library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Library General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Library General Public License for more details.
22
23 You should have received a copy of the GNU Library General Public License
24 along with this library; see the file COPYING.LIB. If not, write to
25 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26 Boston, MA 02110-1301, USA.
27 */
28
29 #include "config.h"
30
31 #if ENABLE(SVG)
32 #include "CSSStyleSelector.h"
33
34 #include "CSSPrimitiveValueMappings.h"
35 #include "CSSPropertyNames.h"
36 #include "CSSValueList.h"
37 #include "Document.h"
38 #include "ShadowValue.h"
39 #include "SVGColor.h"
40 #include "SVGNames.h"
41 #include "SVGPaint.h"
42 #include "SVGRenderStyle.h"
43 #include "SVGRenderStyleDefs.h"
44 #include "SVGStyledElement.h"
45 #include "SVGURIReference.h"
46 #include <stdlib.h>
47 #include <wtf/MathExtras.h>
48
49 #define HANDLE_INHERIT(prop, Prop) \
50 if (isInherit) \
51 { \
52 svgstyle->set##Prop(m_parentStyle->svgStyle()->prop()); \
53 return; \
54 }
55
56 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
57 HANDLE_INHERIT(prop, Prop) \
58 if (isInitial) { \
59 svgstyle->set##Prop(SVGRenderStyle::initial##Prop()); \
60 return; \
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(SVGColor * svgColor,const Color & fgColor)95 static Color colorFromSVGColorCSSValue(SVGColor* svgColor, const Color& fgColor)
96 {
97 Color color;
98 if (svgColor->colorType() == SVGColor::SVG_COLORTYPE_CURRENTCOLOR)
99 color = fgColor;
100 else
101 color = svgColor->color();
102 return color;
103 }
104
applySVGProperty(int id,CSSValue * value)105 void CSSStyleSelector::applySVGProperty(int id, CSSValue* value)
106 {
107 ASSERT(value);
108 CSSPrimitiveValue* primitiveValue = 0;
109 if (value->isPrimitiveValue())
110 primitiveValue = static_cast<CSSPrimitiveValue*>(value);
111
112 SVGRenderStyle* svgstyle = m_style->accessSVGStyle();
113 unsigned short valueType = value->cssValueType();
114
115 bool isInherit = m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT;
116 bool isInitial = valueType == CSSPrimitiveValue::CSS_INITIAL || (!m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT);
117
118 // What follows is a list that maps the CSS properties into their
119 // corresponding front-end RenderStyle values. Shorthands(e.g. border,
120 // background) occur in this list as well and are only hit when mapping
121 // "inherit" or "initial" into front-end values.
122 switch (id)
123 {
124 // ident only properties
125 case CSSPropertyAlignmentBaseline:
126 {
127 HANDLE_INHERIT_AND_INITIAL(alignmentBaseline, AlignmentBaseline)
128 if (!primitiveValue)
129 break;
130
131 svgstyle->setAlignmentBaseline(*primitiveValue);
132 break;
133 }
134 case CSSPropertyBaselineShift:
135 {
136 HANDLE_INHERIT_AND_INITIAL(baselineShift, BaselineShift);
137 if (!primitiveValue)
138 break;
139
140 if (primitiveValue->getIdent()) {
141 switch (primitiveValue->getIdent()) {
142 case CSSValueBaseline:
143 svgstyle->setBaselineShift(BS_BASELINE);
144 break;
145 case CSSValueSub:
146 svgstyle->setBaselineShift(BS_SUB);
147 break;
148 case CSSValueSuper:
149 svgstyle->setBaselineShift(BS_SUPER);
150 break;
151 default:
152 break;
153 }
154 } else {
155 svgstyle->setBaselineShift(BS_LENGTH);
156 svgstyle->setBaselineShiftValue(SVGLength::fromCSSPrimitiveValue(primitiveValue));
157 }
158
159 break;
160 }
161 case CSSPropertyKerning:
162 {
163 HANDLE_INHERIT_AND_INITIAL(kerning, Kerning);
164 if (primitiveValue)
165 svgstyle->setKerning(SVGLength::fromCSSPrimitiveValue(primitiveValue));
166 break;
167 }
168 case CSSPropertyDominantBaseline:
169 {
170 HANDLE_INHERIT_AND_INITIAL(dominantBaseline, DominantBaseline)
171 if (primitiveValue)
172 svgstyle->setDominantBaseline(*primitiveValue);
173 break;
174 }
175 case CSSPropertyColorInterpolation:
176 {
177 HANDLE_INHERIT_AND_INITIAL(colorInterpolation, ColorInterpolation)
178 if (primitiveValue)
179 svgstyle->setColorInterpolation(*primitiveValue);
180 break;
181 }
182 case CSSPropertyColorInterpolationFilters:
183 {
184 HANDLE_INHERIT_AND_INITIAL(colorInterpolationFilters, ColorInterpolationFilters)
185 if (primitiveValue)
186 svgstyle->setColorInterpolationFilters(*primitiveValue);
187 break;
188 }
189 case CSSPropertyColorRendering:
190 {
191 HANDLE_INHERIT_AND_INITIAL(colorRendering, ColorRendering)
192 if (primitiveValue)
193 svgstyle->setColorRendering(*primitiveValue);
194 break;
195 }
196 case CSSPropertyClipRule:
197 {
198 HANDLE_INHERIT_AND_INITIAL(clipRule, ClipRule)
199 if (primitiveValue)
200 svgstyle->setClipRule(*primitiveValue);
201 break;
202 }
203 case CSSPropertyFillRule:
204 {
205 HANDLE_INHERIT_AND_INITIAL(fillRule, FillRule)
206 if (primitiveValue)
207 svgstyle->setFillRule(*primitiveValue);
208 break;
209 }
210 case CSSPropertyStrokeLinejoin:
211 {
212 HANDLE_INHERIT_AND_INITIAL(joinStyle, JoinStyle)
213 if (primitiveValue)
214 svgstyle->setJoinStyle(*primitiveValue);
215 break;
216 }
217 case CSSPropertyImageRendering:
218 {
219 HANDLE_INHERIT_AND_INITIAL(imageRendering, ImageRendering)
220 if (primitiveValue)
221 svgstyle->setImageRendering(*primitiveValue);
222 break;
223 }
224 case CSSPropertyShapeRendering:
225 {
226 HANDLE_INHERIT_AND_INITIAL(shapeRendering, ShapeRendering)
227 if (primitiveValue)
228 svgstyle->setShapeRendering(*primitiveValue);
229 break;
230 }
231 // end of ident only properties
232 case CSSPropertyFill:
233 {
234 HANDLE_INHERIT_AND_INITIAL(fillPaint, FillPaint)
235 if (value->isSVGPaint())
236 svgstyle->setFillPaint(static_cast<SVGPaint*>(value));
237 break;
238 }
239 case CSSPropertyStroke:
240 {
241 HANDLE_INHERIT_AND_INITIAL(strokePaint, StrokePaint)
242 if (value->isSVGPaint())
243 svgstyle->setStrokePaint(static_cast<SVGPaint*>(value));
244
245 break;
246 }
247 case CSSPropertyStrokeWidth:
248 {
249 HANDLE_INHERIT_AND_INITIAL(strokeWidth, StrokeWidth)
250 if (primitiveValue)
251 svgstyle->setStrokeWidth(SVGLength::fromCSSPrimitiveValue(primitiveValue));
252 break;
253 }
254 case CSSPropertyStrokeDasharray:
255 {
256 HANDLE_INHERIT_AND_INITIAL(strokeDashArray, StrokeDashArray)
257 if (!value->isValueList())
258 break;
259
260 CSSValueList* dashes = static_cast<CSSValueList*>(value);
261
262 Vector<SVGLength> array;
263 size_t length = dashes->length();
264 for (size_t i = 0; i < length; ++i) {
265 CSSValue* currValue = dashes->itemWithoutBoundsCheck(i);
266 if (!currValue->isPrimitiveValue())
267 continue;
268
269 CSSPrimitiveValue* dash = static_cast<CSSPrimitiveValue*>(dashes->itemWithoutBoundsCheck(i));
270 array.append(SVGLength::fromCSSPrimitiveValue(dash));
271 }
272
273 svgstyle->setStrokeDashArray(array);
274 break;
275 }
276 case CSSPropertyStrokeDashoffset:
277 {
278 HANDLE_INHERIT_AND_INITIAL(strokeDashOffset, StrokeDashOffset)
279 if (primitiveValue)
280 svgstyle->setStrokeDashOffset(SVGLength::fromCSSPrimitiveValue(primitiveValue));
281 break;
282 }
283 case CSSPropertyFillOpacity:
284 {
285 HANDLE_INHERIT_AND_INITIAL(fillOpacity, FillOpacity)
286 if (!primitiveValue)
287 return;
288
289 float f = 0.0f;
290 int type = primitiveValue->primitiveType();
291 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
292 f = primitiveValue->getFloatValue() / 100.0f;
293 else if (type == CSSPrimitiveValue::CSS_NUMBER)
294 f = primitiveValue->getFloatValue();
295 else
296 return;
297
298 svgstyle->setFillOpacity(f);
299 break;
300 }
301 case CSSPropertyStrokeOpacity:
302 {
303 HANDLE_INHERIT_AND_INITIAL(strokeOpacity, StrokeOpacity)
304 if (!primitiveValue)
305 return;
306
307 float f = 0.0f;
308 int type = primitiveValue->primitiveType();
309 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
310 f = primitiveValue->getFloatValue() / 100.0f;
311 else if (type == CSSPrimitiveValue::CSS_NUMBER)
312 f = primitiveValue->getFloatValue();
313 else
314 return;
315
316 svgstyle->setStrokeOpacity(f);
317 break;
318 }
319 case CSSPropertyStopOpacity:
320 {
321 HANDLE_INHERIT_AND_INITIAL(stopOpacity, StopOpacity)
322 if (!primitiveValue)
323 return;
324
325 float f = 0.0f;
326 int type = primitiveValue->primitiveType();
327 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
328 f = primitiveValue->getFloatValue() / 100.0f;
329 else if (type == CSSPrimitiveValue::CSS_NUMBER)
330 f = primitiveValue->getFloatValue();
331 else
332 return;
333
334 svgstyle->setStopOpacity(f);
335 break;
336 }
337 case CSSPropertyMarkerStart:
338 {
339 HANDLE_INHERIT_AND_INITIAL(markerStartResource, MarkerStartResource)
340 if (!primitiveValue)
341 return;
342
343 String s;
344 int type = primitiveValue->primitiveType();
345 if (type == CSSPrimitiveValue::CSS_URI)
346 s = primitiveValue->getStringValue();
347 else
348 return;
349
350 svgstyle->setMarkerStartResource(SVGURIReference::getTarget(s));
351 break;
352 }
353 case CSSPropertyMarkerMid:
354 {
355 HANDLE_INHERIT_AND_INITIAL(markerMidResource, MarkerMidResource)
356 if (!primitiveValue)
357 return;
358
359 String s;
360 int type = primitiveValue->primitiveType();
361 if (type == CSSPrimitiveValue::CSS_URI)
362 s = primitiveValue->getStringValue();
363 else
364 return;
365
366 svgstyle->setMarkerMidResource(SVGURIReference::getTarget(s));
367 break;
368 }
369 case CSSPropertyMarkerEnd:
370 {
371 HANDLE_INHERIT_AND_INITIAL(markerEndResource, MarkerEndResource)
372 if (!primitiveValue)
373 return;
374
375 String s;
376 int type = primitiveValue->primitiveType();
377 if (type == CSSPrimitiveValue::CSS_URI)
378 s = primitiveValue->getStringValue();
379 else
380 return;
381
382 svgstyle->setMarkerEndResource(SVGURIReference::getTarget(s));
383 break;
384 }
385 case CSSPropertyStrokeLinecap:
386 {
387 HANDLE_INHERIT_AND_INITIAL(capStyle, CapStyle)
388 if (primitiveValue)
389 svgstyle->setCapStyle(*primitiveValue);
390 break;
391 }
392 case CSSPropertyStrokeMiterlimit:
393 {
394 HANDLE_INHERIT_AND_INITIAL(strokeMiterLimit, StrokeMiterLimit)
395 if (!primitiveValue)
396 return;
397
398 float f = 0.0f;
399 int type = primitiveValue->primitiveType();
400 if (type == CSSPrimitiveValue::CSS_NUMBER)
401 f = primitiveValue->getFloatValue();
402 else
403 return;
404
405 svgstyle->setStrokeMiterLimit(f);
406 break;
407 }
408 case CSSPropertyFilter:
409 {
410 HANDLE_INHERIT_AND_INITIAL(filterResource, FilterResource)
411 if (!primitiveValue)
412 return;
413
414 String s;
415 int type = primitiveValue->primitiveType();
416 if (type == CSSPrimitiveValue::CSS_URI)
417 s = primitiveValue->getStringValue();
418 else
419 return;
420
421 svgstyle->setFilterResource(SVGURIReference::getTarget(s));
422 break;
423 }
424 case CSSPropertyMask:
425 {
426 HANDLE_INHERIT_AND_INITIAL(maskerResource, MaskerResource)
427 if (!primitiveValue)
428 return;
429
430 String s;
431 int type = primitiveValue->primitiveType();
432 if (type == CSSPrimitiveValue::CSS_URI)
433 s = primitiveValue->getStringValue();
434 else
435 return;
436
437 svgstyle->setMaskerResource(SVGURIReference::getTarget(s));
438 break;
439 }
440 case CSSPropertyClipPath:
441 {
442 HANDLE_INHERIT_AND_INITIAL(clipperResource, ClipperResource)
443 if (!primitiveValue)
444 return;
445
446 String s;
447 int type = primitiveValue->primitiveType();
448 if (type == CSSPrimitiveValue::CSS_URI)
449 s = primitiveValue->getStringValue();
450 else
451 return;
452
453 svgstyle->setClipperResource(SVGURIReference::getTarget(s));
454 break;
455 }
456 case CSSPropertyTextAnchor:
457 {
458 HANDLE_INHERIT_AND_INITIAL(textAnchor, TextAnchor)
459 if (primitiveValue)
460 svgstyle->setTextAnchor(*primitiveValue);
461 break;
462 }
463 case CSSPropertyWritingMode:
464 {
465 HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode)
466 if (primitiveValue)
467 svgstyle->setWritingMode(*primitiveValue);
468 break;
469 }
470 case CSSPropertyStopColor:
471 {
472 HANDLE_INHERIT_AND_INITIAL(stopColor, StopColor);
473 if (value->isSVGColor())
474 svgstyle->setStopColor(colorFromSVGColorCSSValue(static_cast<SVGColor*>(value), m_style->color()));
475 break;
476 }
477 case CSSPropertyLightingColor:
478 {
479 HANDLE_INHERIT_AND_INITIAL(lightingColor, LightingColor);
480 if (value->isSVGColor())
481 svgstyle->setLightingColor(colorFromSVGColorCSSValue(static_cast<SVGColor*>(value), m_style->color()));
482 break;
483 }
484 case CSSPropertyFloodOpacity:
485 {
486 HANDLE_INHERIT_AND_INITIAL(floodOpacity, FloodOpacity)
487 if (!primitiveValue)
488 return;
489
490 float f = 0.0f;
491 int type = primitiveValue->primitiveType();
492 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
493 f = primitiveValue->getFloatValue() / 100.0f;
494 else if (type == CSSPrimitiveValue::CSS_NUMBER)
495 f = primitiveValue->getFloatValue();
496 else
497 return;
498
499 svgstyle->setFloodOpacity(f);
500 break;
501 }
502 case CSSPropertyFloodColor:
503 {
504 HANDLE_INHERIT_AND_INITIAL(floodColor, FloodColor);
505 if (value->isSVGColor())
506 svgstyle->setFloodColor(colorFromSVGColorCSSValue(static_cast<SVGColor*>(value), m_style->color()));
507 break;
508 }
509 case CSSPropertyGlyphOrientationHorizontal:
510 {
511 HANDLE_INHERIT_AND_INITIAL(glyphOrientationHorizontal, GlyphOrientationHorizontal)
512 if (!primitiveValue)
513 return;
514
515 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) {
516 int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue());
517 ASSERT(orientation != -1);
518
519 svgstyle->setGlyphOrientationHorizontal((EGlyphOrientation) orientation);
520 }
521
522 break;
523 }
524 case CSSPropertyGlyphOrientationVertical:
525 {
526 HANDLE_INHERIT_AND_INITIAL(glyphOrientationVertical, GlyphOrientationVertical)
527 if (!primitiveValue)
528 return;
529
530 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) {
531 int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue());
532 ASSERT(orientation != -1);
533
534 svgstyle->setGlyphOrientationVertical((EGlyphOrientation) orientation);
535 } else if (primitiveValue->getIdent() == CSSValueAuto)
536 svgstyle->setGlyphOrientationVertical(GO_AUTO);
537
538 break;
539 }
540 case CSSPropertyEnableBackground:
541 // Silently ignoring this property for now
542 // http://bugs.webkit.org/show_bug.cgi?id=6022
543 break;
544 case CSSPropertyWebkitSvgShadow: {
545 if (isInherit)
546 return svgstyle->setShadow(m_parentStyle->svgStyle()->shadow() ? new ShadowData(*m_parentStyle->svgStyle()->shadow()) : 0);
547 if (isInitial || primitiveValue) // initial | none
548 return svgstyle->setShadow(0);
549
550 if (!value->isValueList())
551 return;
552
553 CSSValueList *list = static_cast<CSSValueList*>(value);
554 if (!list->length())
555 return;
556
557 CSSValue* firstValue = list->itemWithoutBoundsCheck(0);
558 if (!firstValue->isShadowValue())
559 return;
560 ShadowValue* item = static_cast<ShadowValue*>(firstValue);
561 int x = item->x->computeLengthInt(style(), m_rootElementStyle);
562 int y = item->y->computeLengthInt(style(), m_rootElementStyle);
563 int blur = item->blur ? item->blur->computeLengthInt(style(), m_rootElementStyle) : 0;
564 Color color;
565 if (item->color)
566 color = getColorFromPrimitiveValue(item->color.get());
567
568 // -webkit-svg-shadow does should not have a spread or style
569 ASSERT(!item->spread);
570 ASSERT(!item->style);
571
572 ShadowData* shadowData = new ShadowData(x, y, blur, 0, Normal, false, color.isValid() ? color : Color::transparent);
573 svgstyle->setShadow(shadowData);
574 return;
575 }
576 case CSSPropertyVectorEffect: {
577 HANDLE_INHERIT_AND_INITIAL(vectorEffect, VectorEffect)
578 if (!primitiveValue)
579 break;
580
581 svgstyle->setVectorEffect(*primitiveValue);
582 break;
583 }
584 default:
585 // If you crash here, it's because you added a css property and are not handling it
586 // in either this switch statement or the one in CSSStyleSelector::applyProperty
587 ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", id);
588 return;
589 }
590 }
591
592 }
593
594 #endif
595