Rubber-stamped by Brady Eidson.
[webbrowser.git] / WebCore / css / SVGCSSStyleSelector.cpp
blob6d131dff95e326e8357ff0eb7ad24e6d44658d6f
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>
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)
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.
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.
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.
29 #include "config.h"
31 #if ENABLE(SVG)
32 #include "CSSStyleSelector.h"
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>
49 #define HANDLE_INHERIT(prop, Prop) \
50 if (isInherit) \
52 svgstyle->set##Prop(m_parentStyle->svgStyle()->prop());\
53 return;\
56 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
57 HANDLE_INHERIT(prop, Prop) \
58 else if (isInitial) \
59 svgstyle->set##Prop(SVGRenderStyle::initial##Prop());
62 namespace WebCore {
64 static float roundToNearestGlyphOrientationAngle(float angle)
66 angle = fabsf(fmodf(angle, 360.0f));
68 if (angle <= 45.0f || angle > 315.0f)
69 return 0.0f;
70 else if (angle > 45.0f && angle <= 135.0f)
71 return 90.0f;
72 else if (angle > 135.0f && angle <= 225.0f)
73 return 180.0f;
75 return 270.0f;
78 static int angleToGlyphOrientation(float angle)
80 angle = roundToNearestGlyphOrientationAngle(angle);
82 if (angle == 0.0f)
83 return GO_0DEG;
84 else if (angle == 90.0f)
85 return GO_90DEG;
86 else if (angle == 180.0f)
87 return GO_180DEG;
88 else if (angle == 270.0f)
89 return GO_270DEG;
91 return -1;
94 static Color colorFromSVGColorCSSValue(CSSValue* value, RenderStyle* style)
96 ASSERT(value->isSVGColor());
97 SVGColor* c = static_cast<SVGColor*>(value);
98 Color color;
99 if (c->colorType() == SVGColor::SVG_COLORTYPE_CURRENTCOLOR)
100 color = style->color();
101 else
102 color = c->color();
103 return color;
106 void CSSStyleSelector::applySVGProperty(int id, CSSValue* value)
108 ASSERT(value);
109 CSSPrimitiveValue* primitiveValue = 0;
110 if (value->isPrimitiveValue())
111 primitiveValue = static_cast<CSSPrimitiveValue*>(value);
113 SVGRenderStyle* svgstyle = m_style->accessSVGStyle();
114 unsigned short valueType = value->cssValueType();
116 bool isInherit = m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT;
117 bool isInitial = valueType == CSSPrimitiveValue::CSS_INITIAL || (!m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT);
119 // What follows is a list that maps the CSS properties into their
120 // corresponding front-end RenderStyle values. Shorthands(e.g. border,
121 // background) occur in this list as well and are only hit when mapping
122 // "inherit" or "initial" into front-end values.
123 switch (id)
125 // ident only properties
126 case CSSPropertyAlignmentBaseline:
128 HANDLE_INHERIT_AND_INITIAL(alignmentBaseline, AlignmentBaseline)
129 if (!primitiveValue)
130 break;
132 svgstyle->setAlignmentBaseline(*primitiveValue);
133 break;
135 case CSSPropertyBaselineShift:
137 HANDLE_INHERIT_AND_INITIAL(baselineShift, BaselineShift);
138 if (!primitiveValue)
139 break;
141 if (primitiveValue->getIdent()) {
142 switch (primitiveValue->getIdent()) {
143 case CSSValueBaseline:
144 svgstyle->setBaselineShift(BS_BASELINE);
145 break;
146 case CSSValueSub:
147 svgstyle->setBaselineShift(BS_SUB);
148 break;
149 case CSSValueSuper:
150 svgstyle->setBaselineShift(BS_SUPER);
151 break;
152 default:
153 break;
155 } else {
156 svgstyle->setBaselineShift(BS_LENGTH);
157 svgstyle->setBaselineShiftValue(primitiveValue);
160 break;
162 case CSSPropertyKerning:
164 HANDLE_INHERIT_AND_INITIAL(kerning, Kerning);
165 svgstyle->setKerning(primitiveValue);
166 break;
168 case CSSPropertyDominantBaseline:
170 HANDLE_INHERIT_AND_INITIAL(dominantBaseline, DominantBaseline)
171 if (primitiveValue)
172 svgstyle->setDominantBaseline(*primitiveValue);
173 break;
175 case CSSPropertyColorInterpolation:
177 HANDLE_INHERIT_AND_INITIAL(colorInterpolation, ColorInterpolation)
178 if (primitiveValue)
179 svgstyle->setColorInterpolation(*primitiveValue);
180 break;
182 case CSSPropertyColorInterpolationFilters:
184 HANDLE_INHERIT_AND_INITIAL(colorInterpolationFilters, ColorInterpolationFilters)
185 if (primitiveValue)
186 svgstyle->setColorInterpolationFilters(*primitiveValue);
187 break;
189 case CSSPropertyColorRendering:
191 HANDLE_INHERIT_AND_INITIAL(colorRendering, ColorRendering)
192 if (primitiveValue)
193 svgstyle->setColorRendering(*primitiveValue);
194 break;
196 case CSSPropertyClipRule:
198 HANDLE_INHERIT_AND_INITIAL(clipRule, ClipRule)
199 if (primitiveValue)
200 svgstyle->setClipRule(*primitiveValue);
201 break;
203 case CSSPropertyFillRule:
205 HANDLE_INHERIT_AND_INITIAL(fillRule, FillRule)
206 if (primitiveValue)
207 svgstyle->setFillRule(*primitiveValue);
208 break;
210 case CSSPropertyStrokeLinejoin:
212 HANDLE_INHERIT_AND_INITIAL(joinStyle, JoinStyle)
213 if (primitiveValue)
214 svgstyle->setJoinStyle(*primitiveValue);
215 break;
217 case CSSPropertyImageRendering:
219 HANDLE_INHERIT_AND_INITIAL(imageRendering, ImageRendering)
220 if (primitiveValue)
221 svgstyle->setImageRendering(*primitiveValue);
222 break;
224 case CSSPropertyShapeRendering:
226 HANDLE_INHERIT_AND_INITIAL(shapeRendering, ShapeRendering)
227 if (primitiveValue)
228 svgstyle->setShapeRendering(*primitiveValue);
229 break;
231 // end of ident only properties
232 case CSSPropertyFill:
234 HANDLE_INHERIT_AND_INITIAL(fillPaint, FillPaint)
235 if (value->isSVGPaint())
236 svgstyle->setFillPaint(static_cast<SVGPaint*>(value));
237 break;
239 case CSSPropertyStroke:
241 HANDLE_INHERIT_AND_INITIAL(strokePaint, StrokePaint)
242 if (value->isSVGPaint())
243 svgstyle->setStrokePaint(static_cast<SVGPaint*>(value));
245 break;
247 case CSSPropertyStrokeWidth:
249 HANDLE_INHERIT_AND_INITIAL(strokeWidth, StrokeWidth)
250 if (primitiveValue)
251 svgstyle->setStrokeWidth(primitiveValue);
252 break;
254 case CSSPropertyStrokeDasharray:
256 HANDLE_INHERIT_AND_INITIAL(strokeDashArray, StrokeDashArray)
257 if (value->isValueList())
258 svgstyle->setStrokeDashArray(static_cast<CSSValueList*>(value));
259 break;
261 case CSSPropertyStrokeDashoffset:
263 HANDLE_INHERIT_AND_INITIAL(strokeDashOffset, StrokeDashOffset)
264 if (primitiveValue)
265 svgstyle->setStrokeDashOffset(primitiveValue);
266 break;
268 case CSSPropertyFillOpacity:
270 HANDLE_INHERIT_AND_INITIAL(fillOpacity, FillOpacity)
271 if (!primitiveValue)
272 return;
274 float f = 0.0f;
275 int type = primitiveValue->primitiveType();
276 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
277 f = primitiveValue->getFloatValue() / 100.0f;
278 else if (type == CSSPrimitiveValue::CSS_NUMBER)
279 f = primitiveValue->getFloatValue();
280 else
281 return;
283 svgstyle->setFillOpacity(f);
284 break;
286 case CSSPropertyStrokeOpacity:
288 HANDLE_INHERIT_AND_INITIAL(strokeOpacity, StrokeOpacity)
289 if (!primitiveValue)
290 return;
292 float f = 0.0f;
293 int type = primitiveValue->primitiveType();
294 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
295 f = primitiveValue->getFloatValue() / 100.0f;
296 else if (type == CSSPrimitiveValue::CSS_NUMBER)
297 f = primitiveValue->getFloatValue();
298 else
299 return;
301 svgstyle->setStrokeOpacity(f);
302 break;
304 case CSSPropertyStopOpacity:
306 HANDLE_INHERIT_AND_INITIAL(stopOpacity, StopOpacity)
307 if (!primitiveValue)
308 return;
310 float f = 0.0f;
311 int type = primitiveValue->primitiveType();
312 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
313 f = primitiveValue->getFloatValue() / 100.0f;
314 else if (type == CSSPrimitiveValue::CSS_NUMBER)
315 f = primitiveValue->getFloatValue();
316 else
317 return;
319 svgstyle->setStopOpacity(f);
320 break;
322 case CSSPropertyMarkerStart:
324 HANDLE_INHERIT_AND_INITIAL(startMarker, StartMarker)
325 if (!primitiveValue)
326 return;
328 String s;
329 int type = primitiveValue->primitiveType();
330 if (type == CSSPrimitiveValue::CSS_URI)
331 s = primitiveValue->getStringValue();
332 else
333 return;
335 svgstyle->setStartMarker(SVGURIReference::getTarget(s));
336 break;
338 case CSSPropertyMarkerMid:
340 HANDLE_INHERIT_AND_INITIAL(midMarker, MidMarker)
341 if (!primitiveValue)
342 return;
344 String s;
345 int type = primitiveValue->primitiveType();
346 if (type == CSSPrimitiveValue::CSS_URI)
347 s = primitiveValue->getStringValue();
348 else
349 return;
351 svgstyle->setMidMarker(SVGURIReference::getTarget(s));
352 break;
354 case CSSPropertyMarkerEnd:
356 HANDLE_INHERIT_AND_INITIAL(endMarker, EndMarker)
357 if (!primitiveValue)
358 return;
360 String s;
361 int type = primitiveValue->primitiveType();
362 if (type == CSSPrimitiveValue::CSS_URI)
363 s = primitiveValue->getStringValue();
364 else
365 return;
367 svgstyle->setEndMarker(SVGURIReference::getTarget(s));
368 break;
370 case CSSPropertyStrokeLinecap:
372 HANDLE_INHERIT_AND_INITIAL(capStyle, CapStyle)
373 if (primitiveValue)
374 svgstyle->setCapStyle(*primitiveValue);
375 break;
377 case CSSPropertyStrokeMiterlimit:
379 HANDLE_INHERIT_AND_INITIAL(strokeMiterLimit, StrokeMiterLimit)
380 if (!primitiveValue)
381 return;
383 float f = 0.0f;
384 int type = primitiveValue->primitiveType();
385 if (type == CSSPrimitiveValue::CSS_NUMBER)
386 f = primitiveValue->getFloatValue();
387 else
388 return;
390 svgstyle->setStrokeMiterLimit(f);
391 break;
393 case CSSPropertyFilter:
395 HANDLE_INHERIT_AND_INITIAL(filter, Filter)
396 if (!primitiveValue)
397 return;
399 String s;
400 int type = primitiveValue->primitiveType();
401 if (type == CSSPrimitiveValue::CSS_URI)
402 s = primitiveValue->getStringValue();
403 else
404 return;
405 svgstyle->setFilter(SVGURIReference::getTarget(s));
406 break;
408 case CSSPropertyMask:
410 HANDLE_INHERIT_AND_INITIAL(maskElement, MaskElement)
411 if (!primitiveValue)
412 return;
414 String s;
415 int type = primitiveValue->primitiveType();
416 if (type == CSSPrimitiveValue::CSS_URI)
417 s = primitiveValue->getStringValue();
418 else
419 return;
421 svgstyle->setMaskElement(SVGURIReference::getTarget(s));
422 break;
424 case CSSPropertyClipPath:
426 HANDLE_INHERIT_AND_INITIAL(clipPath, ClipPath)
427 if (!primitiveValue)
428 return;
430 String s;
431 int type = primitiveValue->primitiveType();
432 if (type == CSSPrimitiveValue::CSS_URI)
433 s = primitiveValue->getStringValue();
434 else
435 return;
437 svgstyle->setClipPath(SVGURIReference::getTarget(s));
438 break;
440 case CSSPropertyTextAnchor:
442 HANDLE_INHERIT_AND_INITIAL(textAnchor, TextAnchor)
443 if (primitiveValue)
444 svgstyle->setTextAnchor(*primitiveValue);
445 break;
447 case CSSPropertyWritingMode:
449 HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode)
450 if (primitiveValue)
451 svgstyle->setWritingMode(*primitiveValue);
452 break;
454 case CSSPropertyStopColor:
456 HANDLE_INHERIT_AND_INITIAL(stopColor, StopColor);
457 svgstyle->setStopColor(colorFromSVGColorCSSValue(value, m_style.get()));
458 break;
460 case CSSPropertyLightingColor:
462 HANDLE_INHERIT_AND_INITIAL(lightingColor, LightingColor);
463 svgstyle->setLightingColor(colorFromSVGColorCSSValue(value, m_style.get()));
464 break;
466 case CSSPropertyFloodOpacity:
468 HANDLE_INHERIT_AND_INITIAL(floodOpacity, FloodOpacity)
469 if (!primitiveValue)
470 return;
472 float f = 0.0f;
473 int type = primitiveValue->primitiveType();
474 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
475 f = primitiveValue->getFloatValue() / 100.0f;
476 else if (type == CSSPrimitiveValue::CSS_NUMBER)
477 f = primitiveValue->getFloatValue();
478 else
479 return;
481 svgstyle->setFloodOpacity(f);
482 break;
484 case CSSPropertyFloodColor:
486 if (isInitial) {
487 svgstyle->setFloodColor(SVGRenderStyle::initialFloodColor());
488 return;
490 svgstyle->setFloodColor(colorFromSVGColorCSSValue(value, m_style.get()));
491 break;
493 case CSSPropertyGlyphOrientationHorizontal:
495 HANDLE_INHERIT_AND_INITIAL(glyphOrientationHorizontal, GlyphOrientationHorizontal)
496 if (!primitiveValue)
497 return;
499 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) {
500 int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue());
501 ASSERT(orientation != -1);
503 svgstyle->setGlyphOrientationHorizontal((EGlyphOrientation) orientation);
506 break;
508 case CSSPropertyGlyphOrientationVertical:
510 HANDLE_INHERIT_AND_INITIAL(glyphOrientationVertical, GlyphOrientationVertical)
511 if (!primitiveValue)
512 return;
514 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) {
515 int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue());
516 ASSERT(orientation != -1);
518 svgstyle->setGlyphOrientationVertical((EGlyphOrientation) orientation);
519 } else if (primitiveValue->getIdent() == CSSValueAuto)
520 svgstyle->setGlyphOrientationVertical(GO_AUTO);
522 break;
524 case CSSPropertyEnableBackground:
525 // Silently ignoring this property for now
526 // http://bugs.webkit.org/show_bug.cgi?id=6022
527 break;
528 case CSSPropertyWebkitShadow: {
529 if (isInherit)
530 return svgstyle->setShadow(m_parentStyle->svgStyle()->shadow() ? new ShadowData(*m_parentStyle->svgStyle()->shadow()) : 0);
531 if (isInitial || primitiveValue) // initial | none
532 return svgstyle->setShadow(0);
534 if (!value->isValueList())
535 return;
537 float zoomFactor = m_style->effectiveZoom();
539 CSSValueList *list = static_cast<CSSValueList*>(value);
540 ASSERT(list->length() == 1);
541 ShadowValue* item = static_cast<ShadowValue*>(list->itemWithoutBoundsCheck(0));
542 int x = item->x->computeLengthInt(style(), m_rootElementStyle, zoomFactor);
543 int y = item->y->computeLengthInt(style(), m_rootElementStyle, zoomFactor);
544 int blur = item->blur ? item->blur->computeLengthInt(style(), m_rootElementStyle, zoomFactor) : 0;
545 Color color;
546 if (item->color)
547 color = getColorFromPrimitiveValue(item->color.get());
549 // -webkit-shadow does should not have a spread or style
550 ASSERT(!item->spread);
551 ASSERT(!item->style);
553 ShadowData* shadowData = new ShadowData(x, y, blur, 0, Normal, color.isValid() ? color : Color::transparent);
554 svgstyle->setShadow(shadowData);
555 return;
557 default:
558 // If you crash here, it's because you added a css property and are not handling it
559 // in either this switch statement or the one in CSSStyleSelector::applyProperty
560 ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", id);
561 return;
567 // vim:ts=4:noet
568 #endif // ENABLE(SVG)