• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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