Unreviewed, rolling out r156253.
[WebKit-https.git] / Source / WebCore / css / SVGCSSStyleSelector.cpp
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 "StyleResolver.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 "SVGElement.h"
41 #include "SVGNames.h"
42 #include "SVGPaint.h"
43 #include "SVGRenderStyle.h"
44 #include "SVGRenderStyleDefs.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(state.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
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
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
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
105 void StyleResolver::applySVGProperty(CSSPropertyID id, CSSValue* value)
106 {
107     ASSERT(value);
108     CSSPrimitiveValue* primitiveValue = 0;
109     if (value->isPrimitiveValue())
110         primitiveValue = static_cast<CSSPrimitiveValue*>(value);
111
112     const State& state = m_state;
113     SVGRenderStyle* svgstyle = state.style()->accessSVGStyle();
114
115     bool isInherit = state.parentNode() && value->isInheritedValue();
116     bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue());
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->getValueID()) {
141                 switch (primitiveValue->getValueID()) {
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 CSSPropertyColorProfile:
190         {
191             // Not implemented.
192             break;
193         }
194         case CSSPropertyColorRendering:
195         {
196             HANDLE_INHERIT_AND_INITIAL(colorRendering, ColorRendering)
197             if (primitiveValue)
198                 svgstyle->setColorRendering(*primitiveValue);
199             break;
200         }
201         case CSSPropertyClipRule:
202         {
203             HANDLE_INHERIT_AND_INITIAL(clipRule, ClipRule)
204             if (primitiveValue)
205                 svgstyle->setClipRule(*primitiveValue);
206             break;
207         }
208         case CSSPropertyFillRule:
209         {
210             HANDLE_INHERIT_AND_INITIAL(fillRule, FillRule)
211             if (primitiveValue)
212                 svgstyle->setFillRule(*primitiveValue);
213             break;
214         }
215         case CSSPropertyStrokeLinejoin:
216         {
217             HANDLE_INHERIT_AND_INITIAL(joinStyle, JoinStyle)
218             if (primitiveValue)
219                 svgstyle->setJoinStyle(*primitiveValue);
220             break;
221         }
222         case CSSPropertyShapeRendering:
223         {
224             HANDLE_INHERIT_AND_INITIAL(shapeRendering, ShapeRendering)
225             if (primitiveValue)
226                 svgstyle->setShapeRendering(*primitiveValue);
227             break;
228         }
229         // end of ident only properties
230         case CSSPropertyFill:
231         {
232             if (isInherit) {
233                 const SVGRenderStyle* svgParentStyle = state.parentStyle()->svgStyle();
234                 svgstyle->setFillPaint(svgParentStyle->fillPaintType(), svgParentStyle->fillPaintColor(), svgParentStyle->fillPaintUri(), applyPropertyToRegularStyle(), applyPropertyToVisitedLinkStyle());
235                 return;
236             }
237             if (isInitial) {
238                 svgstyle->setFillPaint(SVGRenderStyle::initialFillPaintType(), SVGRenderStyle::initialFillPaintColor(), SVGRenderStyle::initialFillPaintUri(), applyPropertyToRegularStyle(), applyPropertyToVisitedLinkStyle());
239                 return;
240             }
241             if (value->isSVGPaint()) {
242                 SVGPaint* svgPaint = static_cast<SVGPaint*>(value);
243                 svgstyle->setFillPaint(svgPaint->paintType(), colorFromSVGColorCSSValue(svgPaint, state.style()->color()), svgPaint->uri(), applyPropertyToRegularStyle(), applyPropertyToVisitedLinkStyle());
244             }
245             break;
246         }
247         case CSSPropertyStroke:
248         {
249             if (isInherit) {
250                 const SVGRenderStyle* svgParentStyle = state.parentStyle()->svgStyle();
251                 svgstyle->setStrokePaint(svgParentStyle->strokePaintType(), svgParentStyle->strokePaintColor(), svgParentStyle->strokePaintUri(), applyPropertyToRegularStyle(), applyPropertyToVisitedLinkStyle());
252                 return;
253             }
254             if (isInitial) {
255                 svgstyle->setStrokePaint(SVGRenderStyle::initialStrokePaintType(), SVGRenderStyle::initialStrokePaintColor(), SVGRenderStyle::initialStrokePaintUri(), applyPropertyToRegularStyle(), applyPropertyToVisitedLinkStyle());
256                 return;
257             }
258             if (value->isSVGPaint()) {
259                 SVGPaint* svgPaint = static_cast<SVGPaint*>(value);
260                 svgstyle->setStrokePaint(svgPaint->paintType(), colorFromSVGColorCSSValue(svgPaint, state.style()->color()), svgPaint->uri(), applyPropertyToRegularStyle(), applyPropertyToVisitedLinkStyle());
261             }
262             break;
263         }
264         case CSSPropertyStrokeWidth:
265         {
266             HANDLE_INHERIT_AND_INITIAL(strokeWidth, StrokeWidth)
267             if (primitiveValue)
268                 svgstyle->setStrokeWidth(SVGLength::fromCSSPrimitiveValue(primitiveValue));
269             break;
270         }
271         case CSSPropertyStrokeDasharray:
272         {
273             HANDLE_INHERIT_AND_INITIAL(strokeDashArray, StrokeDashArray)
274             if (!value->isValueList()) {
275                 svgstyle->setStrokeDashArray(SVGRenderStyle::initialStrokeDashArray());
276                 break;
277             }
278
279             CSSValueList* dashes = static_cast<CSSValueList*>(value);
280
281             Vector<SVGLength> array;
282             size_t length = dashes->length();
283             for (size_t i = 0; i < length; ++i) {
284                 CSSValue* currValue = dashes->itemWithoutBoundsCheck(i);
285                 if (!currValue->isPrimitiveValue())
286                     continue;
287
288                 CSSPrimitiveValue* dash = static_cast<CSSPrimitiveValue*>(dashes->itemWithoutBoundsCheck(i));
289                 array.append(SVGLength::fromCSSPrimitiveValue(dash));
290             }
291
292             svgstyle->setStrokeDashArray(array);
293             break;
294         }
295         case CSSPropertyStrokeDashoffset:
296         {
297             HANDLE_INHERIT_AND_INITIAL(strokeDashOffset, StrokeDashOffset)
298             if (primitiveValue)
299                 svgstyle->setStrokeDashOffset(SVGLength::fromCSSPrimitiveValue(primitiveValue));
300             break;
301         }
302         case CSSPropertyFillOpacity:
303         {
304             HANDLE_INHERIT_AND_INITIAL(fillOpacity, FillOpacity)
305             if (!primitiveValue)
306                 return;
307
308             float f = 0.0f;
309             int type = primitiveValue->primitiveType();
310             if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
311                 f = primitiveValue->getFloatValue() / 100.0f;
312             else if (type == CSSPrimitiveValue::CSS_NUMBER)
313                 f = primitiveValue->getFloatValue();
314             else
315                 return;
316
317             svgstyle->setFillOpacity(f);
318             break;
319         }
320         case CSSPropertyStrokeOpacity:
321         {
322             HANDLE_INHERIT_AND_INITIAL(strokeOpacity, StrokeOpacity)
323             if (!primitiveValue)
324                 return;
325
326             float f = 0.0f;
327             int type = primitiveValue->primitiveType();
328             if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
329                 f = primitiveValue->getFloatValue() / 100.0f;
330             else if (type == CSSPrimitiveValue::CSS_NUMBER)
331                 f = primitiveValue->getFloatValue();
332             else
333                 return;
334
335             svgstyle->setStrokeOpacity(f);
336             break;
337         }
338         case CSSPropertyStopOpacity:
339         {
340             HANDLE_INHERIT_AND_INITIAL(stopOpacity, StopOpacity)
341             if (!primitiveValue)
342                 return;
343
344             float f = 0.0f;
345             int type = primitiveValue->primitiveType();
346             if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
347                 f = primitiveValue->getFloatValue() / 100.0f;
348             else if (type == CSSPrimitiveValue::CSS_NUMBER)
349                 f = primitiveValue->getFloatValue();
350             else
351                 return;
352
353             svgstyle->setStopOpacity(f);
354             break;
355         }
356         case CSSPropertyMarkerStart:
357         {
358             HANDLE_INHERIT_AND_INITIAL(markerStartResource, MarkerStartResource)
359             if (!primitiveValue)
360                 return;
361
362             String s;
363             int type = primitiveValue->primitiveType();
364             if (type == CSSPrimitiveValue::CSS_URI)
365                 s = primitiveValue->getStringValue();
366
367             svgstyle->setMarkerStartResource(SVGURIReference::fragmentIdentifierFromIRIString(s, &state.document()));
368             break;
369         }
370         case CSSPropertyMarkerMid:
371         {
372             HANDLE_INHERIT_AND_INITIAL(markerMidResource, MarkerMidResource)
373             if (!primitiveValue)
374                 return;
375
376             String s;
377             int type = primitiveValue->primitiveType();
378             if (type == CSSPrimitiveValue::CSS_URI)
379                 s = primitiveValue->getStringValue();
380
381             svgstyle->setMarkerMidResource(SVGURIReference::fragmentIdentifierFromIRIString(s, &state.document()));
382             break;
383         }
384         case CSSPropertyMarkerEnd:
385         {
386             HANDLE_INHERIT_AND_INITIAL(markerEndResource, MarkerEndResource)
387             if (!primitiveValue)
388                 return;
389
390             String s;
391             int type = primitiveValue->primitiveType();
392             if (type == CSSPrimitiveValue::CSS_URI)
393                 s = primitiveValue->getStringValue();
394
395             svgstyle->setMarkerEndResource(SVGURIReference::fragmentIdentifierFromIRIString(s, &state.document()));
396             break;
397         }
398         case CSSPropertyStrokeLinecap:
399         {
400             HANDLE_INHERIT_AND_INITIAL(capStyle, CapStyle)
401             if (primitiveValue)
402                 svgstyle->setCapStyle(*primitiveValue);
403             break;
404         }
405         case CSSPropertyStrokeMiterlimit:
406         {
407             HANDLE_INHERIT_AND_INITIAL(strokeMiterLimit, StrokeMiterLimit)
408             if (!primitiveValue)
409                 return;
410
411             float f = 0.0f;
412             int type = primitiveValue->primitiveType();
413             if (type == CSSPrimitiveValue::CSS_NUMBER)
414                 f = primitiveValue->getFloatValue();
415             else
416                 return;
417
418             svgstyle->setStrokeMiterLimit(f);
419             break;
420         }
421         case CSSPropertyFilter:
422         {
423             HANDLE_INHERIT_AND_INITIAL(filterResource, FilterResource)
424             if (!primitiveValue)
425                 return;
426
427             String s;
428             int type = primitiveValue->primitiveType();
429             if (type == CSSPrimitiveValue::CSS_URI)
430                 s = primitiveValue->getStringValue();
431
432             svgstyle->setFilterResource(SVGURIReference::fragmentIdentifierFromIRIString(s, &state.document()));
433             break;
434         }
435         case CSSPropertyMask:
436         {
437             HANDLE_INHERIT_AND_INITIAL(maskerResource, MaskerResource)
438             if (!primitiveValue)
439                 return;
440
441             String s;
442             int type = primitiveValue->primitiveType();
443             if (type == CSSPrimitiveValue::CSS_URI)
444                 s = primitiveValue->getStringValue();
445
446             svgstyle->setMaskerResource(SVGURIReference::fragmentIdentifierFromIRIString(s, &state.document()));
447             break;
448         }
449         case CSSPropertyClipPath:
450         {
451             HANDLE_INHERIT_AND_INITIAL(clipperResource, ClipperResource)
452             if (!primitiveValue)
453                 return;
454
455             String s;
456             int type = primitiveValue->primitiveType();
457             if (type == CSSPrimitiveValue::CSS_URI)
458                 s = primitiveValue->getStringValue();
459
460             svgstyle->setClipperResource(SVGURIReference::fragmentIdentifierFromIRIString(s, &state.document()));
461             break;
462         }
463         case CSSPropertyTextAnchor:
464         {
465             HANDLE_INHERIT_AND_INITIAL(textAnchor, TextAnchor)
466             if (primitiveValue)
467                 svgstyle->setTextAnchor(*primitiveValue);
468             break;
469         }
470         case CSSPropertyWritingMode:
471         {
472             HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode)
473             if (primitiveValue)
474                 svgstyle->setWritingMode(*primitiveValue);
475             break;
476         }
477         case CSSPropertyStopColor:
478         {
479             HANDLE_INHERIT_AND_INITIAL(stopColor, StopColor);
480             if (value->isSVGColor())
481                 svgstyle->setStopColor(colorFromSVGColorCSSValue(static_cast<SVGColor*>(value), state.style()->color()));
482             break;
483         }
484        case CSSPropertyLightingColor:
485         {
486             HANDLE_INHERIT_AND_INITIAL(lightingColor, LightingColor);
487             if (value->isSVGColor())
488                 svgstyle->setLightingColor(colorFromSVGColorCSSValue(static_cast<SVGColor*>(value), state.style()->color()));
489             break;
490         }
491         case CSSPropertyFloodOpacity:
492         {
493             HANDLE_INHERIT_AND_INITIAL(floodOpacity, FloodOpacity)
494             if (!primitiveValue)
495                 return;
496
497             float f = 0.0f;
498             int type = primitiveValue->primitiveType();
499             if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
500                 f = primitiveValue->getFloatValue() / 100.0f;
501             else if (type == CSSPrimitiveValue::CSS_NUMBER)
502                 f = primitiveValue->getFloatValue();
503             else
504                 return;
505
506             svgstyle->setFloodOpacity(f);
507             break;
508         }
509         case CSSPropertyFloodColor:
510         {
511             HANDLE_INHERIT_AND_INITIAL(floodColor, FloodColor);
512             if (value->isSVGColor())
513                 svgstyle->setFloodColor(colorFromSVGColorCSSValue(static_cast<SVGColor*>(value), state.style()->color()));
514             break;
515         }
516         case CSSPropertyGlyphOrientationHorizontal:
517         {
518             HANDLE_INHERIT_AND_INITIAL(glyphOrientationHorizontal, GlyphOrientationHorizontal)
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->setGlyphOrientationHorizontal((EGlyphOrientation) orientation);
527             }
528
529             break;
530         }
531         case CSSPropertyGlyphOrientationVertical:
532         {
533             HANDLE_INHERIT_AND_INITIAL(glyphOrientationVertical, GlyphOrientationVertical)
534             if (!primitiveValue)
535                 return;
536
537             if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) {
538                 int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue());
539                 ASSERT(orientation != -1);
540
541                 svgstyle->setGlyphOrientationVertical((EGlyphOrientation) orientation);
542             } else if (primitiveValue->getValueID() == CSSValueAuto)
543                 svgstyle->setGlyphOrientationVertical(GO_AUTO);
544
545             break;
546         }
547         case CSSPropertyEnableBackground:
548             // Silently ignoring this property for now
549             // http://bugs.webkit.org/show_bug.cgi?id=6022
550             break;
551         case CSSPropertyWebkitSvgShadow: {
552             if (isInherit)
553                 return svgstyle->setShadow(adoptPtr(state.parentStyle()->svgStyle()->shadow() ? new ShadowData(*state.parentStyle()->svgStyle()->shadow()) : 0));
554             if (isInitial || primitiveValue) // initial | none
555                 return svgstyle->setShadow(nullptr);
556
557             if (!value->isValueList())
558                 return;
559
560             CSSValueList *list = static_cast<CSSValueList*>(value);
561             if (!list->length())
562                 return;
563
564             CSSValue* firstValue = list->itemWithoutBoundsCheck(0);
565             if (!firstValue->isShadowValue())
566                 return;
567             ShadowValue* item = static_cast<ShadowValue*>(firstValue);
568             IntPoint location(item->x->computeLength<int>(state.style(), state.rootElementStyle()),
569                 item->y->computeLength<int>(state.style(), state.rootElementStyle()));
570             int blur = item->blur ? item->blur->computeLength<int>(state.style(), state.rootElementStyle()) : 0;
571             Color color;
572             if (item->color)
573                 color = colorFromPrimitiveValue(item->color.get());
574
575             // -webkit-svg-shadow does should not have a spread or style
576             ASSERT(!item->spread);
577             ASSERT(!item->style);
578
579             OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(location, blur, 0, Normal, false, color.isValid() ? color : Color::transparent));
580             svgstyle->setShadow(shadowData.release());
581             return;
582         }
583         case CSSPropertyVectorEffect: {
584             HANDLE_INHERIT_AND_INITIAL(vectorEffect, VectorEffect)
585             if (!primitiveValue)
586                 break;
587
588             svgstyle->setVectorEffect(*primitiveValue);
589             break;
590         }
591         case CSSPropertyBufferedRendering: {
592             HANDLE_INHERIT_AND_INITIAL(bufferedRendering, BufferedRendering)
593             if (!primitiveValue)
594                 break;
595
596             svgstyle->setBufferedRendering(*primitiveValue);
597             break;
598         }
599         case CSSPropertyMaskType: {
600             HANDLE_INHERIT_AND_INITIAL(maskType, MaskType)
601             if (!primitiveValue)
602                 break;
603
604             svgstyle->setMaskType(*primitiveValue);
605             break;
606         }
607         default:
608             // If you crash here, it's because you added a css property and are not handling it
609             // in either this switch statement or the one in StyleResolver::applyProperty
610             ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", id);
611             return;
612     }
613 }
614
615 }
616
617 #endif