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.
32 #include "CSSStyleSelector.h"
34 #include "CSSPrimitiveValueMappings.h"
35 #include "CSSPropertyNames.h"
36 #include "CSSValueList.h"
38 #include "ShadowValue.h"
42 #include "SVGRenderStyle.h"
43 #include "SVGRenderStyleDefs.h"
44 #include "SVGStyledElement.h"
45 #include "SVGURIReference.h"
47 #include <wtf/MathExtras.h>
49 #define HANDLE_INHERIT(prop, Prop) \
52 svgstyle->set##Prop(m_parentStyle->svgStyle()->prop());\
56 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
57 HANDLE_INHERIT(prop, Prop) \
59 svgstyle->set##Prop(SVGRenderStyle::initial##Prop());
63 static float roundToNearestGlyphOrientationAngle(float angle)
65 angle = fabsf(fmodf(angle, 360.0f));
67 if (angle <= 45.0f || angle > 315.0f)
69 else if (angle > 45.0f && angle <= 135.0f)
71 else if (angle > 135.0f && angle <= 225.0f)
77 static int angleToGlyphOrientation(float angle)
79 angle = roundToNearestGlyphOrientationAngle(angle);
83 else if (angle == 90.0f)
85 else if (angle == 180.0f)
87 else if (angle == 270.0f)
93 static Color colorFromSVGColorCSSValue(CSSValue* value, const Color& fgColor)
95 ASSERT(value->isSVGColor());
96 SVGColor* c = static_cast<SVGColor*>(value);
98 if (c->colorType() == SVGColor::SVG_COLORTYPE_CURRENTCOLOR)
105 void CSSStyleSelector::applySVGProperty(int id, CSSValue* value)
108 CSSPrimitiveValue* primitiveValue = 0;
109 if (value->isPrimitiveValue())
110 primitiveValue = static_cast<CSSPrimitiveValue*>(value);
112 SVGRenderStyle* svgstyle = m_style->accessSVGStyle();
113 unsigned short valueType = value->cssValueType();
115 bool isInherit = m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT;
116 bool isInitial = valueType == CSSPrimitiveValue::CSS_INITIAL || (!m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT);
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.
124 // ident only properties
125 case CSSPropertyAlignmentBaseline:
127 HANDLE_INHERIT_AND_INITIAL(alignmentBaseline, AlignmentBaseline)
131 svgstyle->setAlignmentBaseline(*primitiveValue);
134 case CSSPropertyBaselineShift:
136 HANDLE_INHERIT_AND_INITIAL(baselineShift, BaselineShift);
140 if (primitiveValue->getIdent()) {
141 switch (primitiveValue->getIdent()) {
142 case CSSValueBaseline:
143 svgstyle->setBaselineShift(BS_BASELINE);
146 svgstyle->setBaselineShift(BS_SUB);
149 svgstyle->setBaselineShift(BS_SUPER);
155 svgstyle->setBaselineShift(BS_LENGTH);
156 svgstyle->setBaselineShiftValue(SVGLength::fromCSSPrimitiveValue(primitiveValue));
161 case CSSPropertyKerning:
163 HANDLE_INHERIT_AND_INITIAL(kerning, Kerning);
164 svgstyle->setKerning(SVGLength::fromCSSPrimitiveValue(primitiveValue));
167 case CSSPropertyDominantBaseline:
169 HANDLE_INHERIT_AND_INITIAL(dominantBaseline, DominantBaseline)
171 svgstyle->setDominantBaseline(*primitiveValue);
174 case CSSPropertyColorInterpolation:
176 HANDLE_INHERIT_AND_INITIAL(colorInterpolation, ColorInterpolation)
178 svgstyle->setColorInterpolation(*primitiveValue);
181 case CSSPropertyColorInterpolationFilters:
183 HANDLE_INHERIT_AND_INITIAL(colorInterpolationFilters, ColorInterpolationFilters)
185 svgstyle->setColorInterpolationFilters(*primitiveValue);
188 case CSSPropertyColorRendering:
190 HANDLE_INHERIT_AND_INITIAL(colorRendering, ColorRendering)
192 svgstyle->setColorRendering(*primitiveValue);
195 case CSSPropertyClipRule:
197 HANDLE_INHERIT_AND_INITIAL(clipRule, ClipRule)
199 svgstyle->setClipRule(*primitiveValue);
202 case CSSPropertyFillRule:
204 HANDLE_INHERIT_AND_INITIAL(fillRule, FillRule)
206 svgstyle->setFillRule(*primitiveValue);
209 case CSSPropertyStrokeLinejoin:
211 HANDLE_INHERIT_AND_INITIAL(joinStyle, JoinStyle)
213 svgstyle->setJoinStyle(*primitiveValue);
216 case CSSPropertyImageRendering:
218 HANDLE_INHERIT_AND_INITIAL(imageRendering, ImageRendering)
220 svgstyle->setImageRendering(*primitiveValue);
223 case CSSPropertyShapeRendering:
225 HANDLE_INHERIT_AND_INITIAL(shapeRendering, ShapeRendering)
227 svgstyle->setShapeRendering(*primitiveValue);
230 // end of ident only properties
231 case CSSPropertyFill:
233 HANDLE_INHERIT_AND_INITIAL(fillPaint, FillPaint)
234 if (value->isSVGPaint())
235 svgstyle->setFillPaint(static_cast<SVGPaint*>(value));
238 case CSSPropertyStroke:
240 HANDLE_INHERIT_AND_INITIAL(strokePaint, StrokePaint)
241 if (value->isSVGPaint())
242 svgstyle->setStrokePaint(static_cast<SVGPaint*>(value));
246 case CSSPropertyStrokeWidth:
248 HANDLE_INHERIT_AND_INITIAL(strokeWidth, StrokeWidth)
250 svgstyle->setStrokeWidth(SVGLength::fromCSSPrimitiveValue(primitiveValue));
253 case CSSPropertyStrokeDasharray:
255 HANDLE_INHERIT_AND_INITIAL(strokeDashArray, StrokeDashArray)
256 if (!value->isValueList())
259 CSSValueList* dashes = static_cast<CSSValueList*>(value);
261 Vector<SVGLength> array;
262 size_t length = dashes->length();
263 for (size_t i = 0; i < length; ++i) {
264 CSSPrimitiveValue* dash = static_cast<CSSPrimitiveValue*>(dashes->itemWithoutBoundsCheck(i));
268 array.append(SVGLength::fromCSSPrimitiveValue(dash));
271 svgstyle->setStrokeDashArray(array);
274 case CSSPropertyStrokeDashoffset:
276 HANDLE_INHERIT_AND_INITIAL(strokeDashOffset, StrokeDashOffset)
278 svgstyle->setStrokeDashOffset(SVGLength::fromCSSPrimitiveValue(primitiveValue));
281 case CSSPropertyFillOpacity:
283 HANDLE_INHERIT_AND_INITIAL(fillOpacity, FillOpacity)
288 int type = primitiveValue->primitiveType();
289 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
290 f = primitiveValue->getFloatValue() / 100.0f;
291 else if (type == CSSPrimitiveValue::CSS_NUMBER)
292 f = primitiveValue->getFloatValue();
296 svgstyle->setFillOpacity(f);
299 case CSSPropertyStrokeOpacity:
301 HANDLE_INHERIT_AND_INITIAL(strokeOpacity, StrokeOpacity)
306 int type = primitiveValue->primitiveType();
307 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
308 f = primitiveValue->getFloatValue() / 100.0f;
309 else if (type == CSSPrimitiveValue::CSS_NUMBER)
310 f = primitiveValue->getFloatValue();
314 svgstyle->setStrokeOpacity(f);
317 case CSSPropertyStopOpacity:
319 HANDLE_INHERIT_AND_INITIAL(stopOpacity, StopOpacity)
324 int type = primitiveValue->primitiveType();
325 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
326 f = primitiveValue->getFloatValue() / 100.0f;
327 else if (type == CSSPrimitiveValue::CSS_NUMBER)
328 f = primitiveValue->getFloatValue();
332 svgstyle->setStopOpacity(f);
335 case CSSPropertyMarkerStart:
337 HANDLE_INHERIT_AND_INITIAL(markerStartResource, MarkerStartResource)
342 int type = primitiveValue->primitiveType();
343 if (type == CSSPrimitiveValue::CSS_URI)
344 s = primitiveValue->getStringValue();
348 svgstyle->setMarkerStartResource(SVGURIReference::getTarget(s));
351 case CSSPropertyMarkerMid:
353 HANDLE_INHERIT_AND_INITIAL(markerMidResource, MarkerMidResource)
358 int type = primitiveValue->primitiveType();
359 if (type == CSSPrimitiveValue::CSS_URI)
360 s = primitiveValue->getStringValue();
364 svgstyle->setMarkerMidResource(SVGURIReference::getTarget(s));
367 case CSSPropertyMarkerEnd:
369 HANDLE_INHERIT_AND_INITIAL(markerEndResource, MarkerEndResource)
374 int type = primitiveValue->primitiveType();
375 if (type == CSSPrimitiveValue::CSS_URI)
376 s = primitiveValue->getStringValue();
380 svgstyle->setMarkerEndResource(SVGURIReference::getTarget(s));
383 case CSSPropertyStrokeLinecap:
385 HANDLE_INHERIT_AND_INITIAL(capStyle, CapStyle)
387 svgstyle->setCapStyle(*primitiveValue);
390 case CSSPropertyStrokeMiterlimit:
392 HANDLE_INHERIT_AND_INITIAL(strokeMiterLimit, StrokeMiterLimit)
397 int type = primitiveValue->primitiveType();
398 if (type == CSSPrimitiveValue::CSS_NUMBER)
399 f = primitiveValue->getFloatValue();
403 svgstyle->setStrokeMiterLimit(f);
406 case CSSPropertyFilter:
408 HANDLE_INHERIT_AND_INITIAL(filterResource, FilterResource)
413 int type = primitiveValue->primitiveType();
414 if (type == CSSPrimitiveValue::CSS_URI)
415 s = primitiveValue->getStringValue();
419 svgstyle->setFilterResource(SVGURIReference::getTarget(s));
422 case CSSPropertyMask:
424 HANDLE_INHERIT_AND_INITIAL(maskerResource, MaskerResource)
429 int type = primitiveValue->primitiveType();
430 if (type == CSSPrimitiveValue::CSS_URI)
431 s = primitiveValue->getStringValue();
435 svgstyle->setMaskerResource(SVGURIReference::getTarget(s));
438 case CSSPropertyClipPath:
440 HANDLE_INHERIT_AND_INITIAL(clipperResource, ClipperResource)
445 int type = primitiveValue->primitiveType();
446 if (type == CSSPrimitiveValue::CSS_URI)
447 s = primitiveValue->getStringValue();
451 svgstyle->setClipperResource(SVGURIReference::getTarget(s));
454 case CSSPropertyTextAnchor:
456 HANDLE_INHERIT_AND_INITIAL(textAnchor, TextAnchor)
458 svgstyle->setTextAnchor(*primitiveValue);
461 case CSSPropertyWritingMode:
463 HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode)
465 svgstyle->setWritingMode(*primitiveValue);
468 case CSSPropertyStopColor:
470 HANDLE_INHERIT_AND_INITIAL(stopColor, StopColor);
471 svgstyle->setStopColor(colorFromSVGColorCSSValue(value, m_style->color()));
474 case CSSPropertyLightingColor:
476 HANDLE_INHERIT_AND_INITIAL(lightingColor, LightingColor);
477 svgstyle->setLightingColor(colorFromSVGColorCSSValue(value, m_style->color()));
480 case CSSPropertyFloodOpacity:
482 HANDLE_INHERIT_AND_INITIAL(floodOpacity, FloodOpacity)
487 int type = primitiveValue->primitiveType();
488 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
489 f = primitiveValue->getFloatValue() / 100.0f;
490 else if (type == CSSPrimitiveValue::CSS_NUMBER)
491 f = primitiveValue->getFloatValue();
495 svgstyle->setFloodOpacity(f);
498 case CSSPropertyFloodColor:
501 svgstyle->setFloodColor(SVGRenderStyle::initialFloodColor());
504 svgstyle->setFloodColor(colorFromSVGColorCSSValue(value, m_style->color()));
507 case CSSPropertyGlyphOrientationHorizontal:
509 HANDLE_INHERIT_AND_INITIAL(glyphOrientationHorizontal, GlyphOrientationHorizontal)
513 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) {
514 int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue());
515 ASSERT(orientation != -1);
517 svgstyle->setGlyphOrientationHorizontal((EGlyphOrientation) orientation);
522 case CSSPropertyGlyphOrientationVertical:
524 HANDLE_INHERIT_AND_INITIAL(glyphOrientationVertical, GlyphOrientationVertical)
528 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) {
529 int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue());
530 ASSERT(orientation != -1);
532 svgstyle->setGlyphOrientationVertical((EGlyphOrientation) orientation);
533 } else if (primitiveValue->getIdent() == CSSValueAuto)
534 svgstyle->setGlyphOrientationVertical(GO_AUTO);
538 case CSSPropertyEnableBackground:
539 // Silently ignoring this property for now
540 // http://bugs.webkit.org/show_bug.cgi?id=6022
542 case CSSPropertyWebkitSvgShadow: {
544 return svgstyle->setShadow(m_parentStyle->svgStyle()->shadow() ? new ShadowData(*m_parentStyle->svgStyle()->shadow()) : 0);
545 if (isInitial || primitiveValue) // initial | none
546 return svgstyle->setShadow(0);
548 if (!value->isValueList())
551 CSSValueList *list = static_cast<CSSValueList*>(value);
552 ASSERT(list->length() == 1);
553 ShadowValue* item = static_cast<ShadowValue*>(list->itemWithoutBoundsCheck(0));
554 int x = item->x->computeLengthInt(style(), m_rootElementStyle);
555 int y = item->y->computeLengthInt(style(), m_rootElementStyle);
556 int blur = item->blur ? item->blur->computeLengthInt(style(), m_rootElementStyle) : 0;
559 color = getColorFromPrimitiveValue(item->color.get());
561 // -webkit-svg-shadow does should not have a spread or style
562 ASSERT(!item->spread);
563 ASSERT(!item->style);
565 ShadowData* shadowData = new ShadowData(x, y, blur, 0, Normal, color.isValid() ? color : Color::transparent);
566 svgstyle->setShadow(shadowData);
569 case CSSPropertyVectorEffect: {
570 HANDLE_INHERIT_AND_INITIAL(vectorEffect, VectorEffect)
574 svgstyle->setVectorEffect(*primitiveValue);
578 // If you crash here, it's because you added a css property and are not handling it
579 // in either this switch statement or the one in CSSStyleSelector::applyProperty
580 ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", id);