8780c44a4eef9e68d32790ec09d11018c8cfb563
[WebKit-https.git] / Source / WebCore / css / SVGCSSComputedStyleDeclaration.cpp
1 /*
2     Copyright (C) 2007 Eric Seidel <eric@webkit.org>
3     Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Library General Public
7     License as published by the Free Software Foundation; either
8     version 2 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Library General Public License for more details.
14
15     You should have received a copy of the GNU Library General Public License
16     along with this library; see the file COPYING.LIB.  If not, write to
17     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18     Boston, MA 02110-1301, USA.
19  */
20
21 #include "config.h"
22 #include "CSSComputedStyleDeclaration.h"
23
24 #include "CSSPrimitiveValueMappings.h"
25 #include "CSSPropertyNames.h"
26 #include "Document.h"
27 #include "Element.h"
28 #include "RenderStyle.h"
29 #include "SVGPaint.h"
30
31 namespace WebCore {
32
33 static Ref<CSSValue> paintOrder(PaintOrder paintOrder)
34 {
35     Ref<CSSValueList> paintOrderList = CSSValueList::createSpaceSeparated();
36     Ref<CSSValue> fill = CSSPrimitiveValue::createIdentifier(CSSValueFill);
37     Ref<CSSValue> stroke = CSSPrimitiveValue::createIdentifier(CSSValueStroke);
38     Ref<CSSValue> markers = CSSPrimitiveValue::createIdentifier(CSSValueMarkers);
39
40     switch (paintOrder) {
41     case PaintOrderNormal:
42         return CSSPrimitiveValue::createIdentifier(CSSValueNormal);
43     case PaintOrderFill:
44         paintOrderList->append(WTFMove(fill));
45         break;
46     case PaintOrderFillMarkers:
47         paintOrderList->append(WTFMove(fill));
48         paintOrderList->append(WTFMove(markers));
49         break;
50     case PaintOrderStroke:
51         paintOrderList->append(WTFMove(stroke));
52         break;
53     case PaintOrderStrokeMarkers:
54         paintOrderList->append(WTFMove(stroke));
55         paintOrderList->append(WTFMove(markers));
56         break;
57     case PaintOrderMarkers:
58         paintOrderList->append(WTFMove(markers));
59         break;
60     case PaintOrderMarkersStroke:
61         paintOrderList->append(WTFMove(markers));
62         paintOrderList->append(WTFMove(stroke));
63         break;
64     }
65     return WTFMove(paintOrderList);
66 }
67
68 static RefPtr<CSSPrimitiveValue> glyphOrientationToCSSPrimitiveValue(EGlyphOrientation orientation)
69 {
70     switch (orientation) {
71         case GO_0DEG:
72             return CSSPrimitiveValue::create(0.0f, CSSPrimitiveValue::CSS_DEG);
73         case GO_90DEG:
74             return CSSPrimitiveValue::create(90.0f, CSSPrimitiveValue::CSS_DEG);
75         case GO_180DEG:
76             return CSSPrimitiveValue::create(180.0f, CSSPrimitiveValue::CSS_DEG);
77         case GO_270DEG:
78             return CSSPrimitiveValue::create(270.0f, CSSPrimitiveValue::CSS_DEG);
79         default:
80             return nullptr;
81     }
82 }
83
84 static RefPtr<CSSValue> strokeDashArrayToCSSValueList(const Vector<SVGLength>& dashes)
85 {
86     if (dashes.isEmpty())
87         return CSSPrimitiveValue::createIdentifier(CSSValueNone);
88
89     RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
90     const Vector<SVGLength>::const_iterator end = dashes.end();
91     for (Vector<SVGLength>::const_iterator it = dashes.begin(); it != end; ++it)
92         list->append(SVGLength::toCSSPrimitiveValue(*it));
93
94     return list;
95 }
96
97 RefPtr<SVGPaint> ComputedStyleExtractor::adjustSVGPaintForCurrentColor(RefPtr<SVGPaint>&& paint, const RenderStyle* style) const
98 {
99     if (paint->paintType() == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR || paint->paintType() == SVGPaint::SVG_PAINTTYPE_URI_CURRENTCOLOR)
100         paint->setColor(style->color());
101     return WTFMove(paint);
102 }
103
104 RefPtr<CSSValue> ComputedStyleExtractor::svgPropertyValue(CSSPropertyID propertyID, EUpdateLayout updateLayout)
105 {
106     if (!m_element)
107         return nullptr;
108
109     // Make sure our layout is up to date before we allow a query on these attributes.
110     if (updateLayout)
111         m_element->document().updateLayout();
112
113     auto* style = m_element->computedStyle();
114     if (!style)
115         return nullptr;
116
117     const SVGRenderStyle& svgStyle = style->svgStyle();
118
119     switch (propertyID) {
120         case CSSPropertyClipRule:
121             return CSSPrimitiveValue::create(svgStyle.clipRule());
122         case CSSPropertyFloodOpacity:
123             return CSSPrimitiveValue::create(svgStyle.floodOpacity(), CSSPrimitiveValue::CSS_NUMBER);
124         case CSSPropertyStopOpacity:
125             return CSSPrimitiveValue::create(svgStyle.stopOpacity(), CSSPrimitiveValue::CSS_NUMBER);
126         case CSSPropertyColorInterpolation:
127             return CSSPrimitiveValue::create(svgStyle.colorInterpolation());
128         case CSSPropertyColorInterpolationFilters:
129             return CSSPrimitiveValue::create(svgStyle.colorInterpolationFilters());
130         case CSSPropertyFillOpacity:
131             return CSSPrimitiveValue::create(svgStyle.fillOpacity(), CSSPrimitiveValue::CSS_NUMBER);
132         case CSSPropertyFillRule:
133             return CSSPrimitiveValue::create(svgStyle.fillRule());
134         case CSSPropertyColorRendering:
135             return CSSPrimitiveValue::create(svgStyle.colorRendering());
136         case CSSPropertyShapeRendering:
137             return CSSPrimitiveValue::create(svgStyle.shapeRendering());
138         case CSSPropertyStrokeLinecap:
139             return CSSPrimitiveValue::create(svgStyle.capStyle());
140         case CSSPropertyStrokeLinejoin:
141             return CSSPrimitiveValue::create(svgStyle.joinStyle());
142         case CSSPropertyStrokeMiterlimit:
143             return CSSPrimitiveValue::create(svgStyle.strokeMiterLimit(), CSSPrimitiveValue::CSS_NUMBER);
144         case CSSPropertyStrokeOpacity:
145             return CSSPrimitiveValue::create(svgStyle.strokeOpacity(), CSSPrimitiveValue::CSS_NUMBER);
146         case CSSPropertyAlignmentBaseline:
147             return CSSPrimitiveValue::create(svgStyle.alignmentBaseline());
148         case CSSPropertyDominantBaseline:
149             return CSSPrimitiveValue::create(svgStyle.dominantBaseline());
150         case CSSPropertyTextAnchor:
151             return CSSPrimitiveValue::create(svgStyle.textAnchor());
152         case CSSPropertyWritingMode:
153             return CSSPrimitiveValue::create(svgStyle.writingMode());
154         case CSSPropertyClipPath:
155             if (!svgStyle.clipperResource().isEmpty())
156                 return CSSPrimitiveValue::create(svgStyle.clipperResource(), CSSPrimitiveValue::CSS_URI);
157             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
158         case CSSPropertyMask:
159             if (!svgStyle.maskerResource().isEmpty())
160                 return CSSPrimitiveValue::create(svgStyle.maskerResource(), CSSPrimitiveValue::CSS_URI);
161             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
162         case CSSPropertyFloodColor:
163             return currentColorOrValidColor(style, svgStyle.floodColor());
164         case CSSPropertyLightingColor:
165             return currentColorOrValidColor(style, svgStyle.lightingColor());
166         case CSSPropertyStopColor:
167             return currentColorOrValidColor(style, svgStyle.stopColor());
168         case CSSPropertyFill:
169             return adjustSVGPaintForCurrentColor(SVGPaint::create(svgStyle.fillPaintType(), svgStyle.fillPaintUri(), svgStyle.fillPaintColor()), style);
170         case CSSPropertyKerning:
171             return SVGLength::toCSSPrimitiveValue(svgStyle.kerning());
172         case CSSPropertyMarkerEnd:
173             if (!svgStyle.markerEndResource().isEmpty())
174                 return CSSPrimitiveValue::create(svgStyle.markerEndResource(), CSSPrimitiveValue::CSS_URI);
175             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
176         case CSSPropertyMarkerMid:
177             if (!svgStyle.markerMidResource().isEmpty())
178                 return CSSPrimitiveValue::create(svgStyle.markerMidResource(), CSSPrimitiveValue::CSS_URI);
179             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
180         case CSSPropertyMarkerStart:
181             if (!svgStyle.markerStartResource().isEmpty())
182                 return CSSPrimitiveValue::create(svgStyle.markerStartResource(), CSSPrimitiveValue::CSS_URI);
183             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
184         case CSSPropertyStroke:
185             return adjustSVGPaintForCurrentColor(SVGPaint::create(svgStyle.strokePaintType(), svgStyle.strokePaintUri(), svgStyle.strokePaintColor()), style);
186         case CSSPropertyStrokeDasharray:
187             return strokeDashArrayToCSSValueList(svgStyle.strokeDashArray());
188         case CSSPropertyBaselineShift: {
189             switch (svgStyle.baselineShift()) {
190                 case BS_BASELINE:
191                     return CSSPrimitiveValue::createIdentifier(CSSValueBaseline);
192                 case BS_SUPER:
193                     return CSSPrimitiveValue::createIdentifier(CSSValueSuper);
194                 case BS_SUB:
195                     return CSSPrimitiveValue::createIdentifier(CSSValueSub);
196                 case BS_LENGTH:
197                     return SVGLength::toCSSPrimitiveValue(svgStyle.baselineShiftValue());
198             }
199             ASSERT_NOT_REACHED();
200             return nullptr;
201         }
202         case CSSPropertyBufferedRendering:
203             return CSSPrimitiveValue::create(svgStyle.bufferedRendering());
204         case CSSPropertyGlyphOrientationHorizontal:
205             return glyphOrientationToCSSPrimitiveValue(svgStyle.glyphOrientationHorizontal());
206         case CSSPropertyGlyphOrientationVertical: {
207             if (RefPtr<CSSPrimitiveValue> value = glyphOrientationToCSSPrimitiveValue(svgStyle.glyphOrientationVertical()))
208                 return value;
209
210             if (svgStyle.glyphOrientationVertical() == GO_AUTO)
211                 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
212
213             return nullptr;
214         }
215         case CSSPropertyWebkitSvgShadow:
216             return valueForShadow(svgStyle.shadow(), propertyID, *style);
217         case CSSPropertyVectorEffect:
218             return CSSPrimitiveValue::create(svgStyle.vectorEffect());
219         case CSSPropertyMaskType:
220             return CSSPrimitiveValue::create(svgStyle.maskType());
221         case CSSPropertyPaintOrder:
222             return paintOrder(svgStyle.paintOrder());
223         case CSSPropertyMarker:
224         case CSSPropertyEnableBackground:
225         case CSSPropertyColorProfile:
226             // the above properties are not yet implemented in the engine
227             break;
228     default:
229         // If you crash here, it's because you added a css property and are not handling it
230         // in either this switch statement or the one in CSSComputedStyleDelcaration::getPropertyCSSValue
231         ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propertyID);
232     }
233     LOG_ERROR("unimplemented propertyID: %d", propertyID);
234     return nullptr;
235 }
236
237 }