Apply SVG styles paint-order, stroke-linejoin, and stroke-linecap on DOM text.
[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 "CSSValueList.h"
27 #include "Document.h"
28 #include "Element.h"
29 #include "RenderStyle.h"
30
31 namespace WebCore {
32
33 static RefPtr<CSSPrimitiveValue> glyphOrientationToCSSPrimitiveValue(EGlyphOrientation orientation)
34 {
35     switch (orientation) {
36         case GO_0DEG:
37             return CSSPrimitiveValue::create(0.0f, CSSPrimitiveValue::CSS_DEG);
38         case GO_90DEG:
39             return CSSPrimitiveValue::create(90.0f, CSSPrimitiveValue::CSS_DEG);
40         case GO_180DEG:
41             return CSSPrimitiveValue::create(180.0f, CSSPrimitiveValue::CSS_DEG);
42         case GO_270DEG:
43             return CSSPrimitiveValue::create(270.0f, CSSPrimitiveValue::CSS_DEG);
44         default:
45             return nullptr;
46     }
47 }
48
49 static RefPtr<CSSValue> strokeDashArrayToCSSValueList(const Vector<SVGLengthValue>& dashes)
50 {
51     if (dashes.isEmpty())
52         return CSSPrimitiveValue::createIdentifier(CSSValueNone);
53
54     auto list = CSSValueList::createCommaSeparated();
55     for (auto& length : dashes)
56         list->append(SVGLengthValue::toCSSPrimitiveValue(length));
57
58     return WTFMove(list);
59 }
60
61 RefPtr<CSSValue> ComputedStyleExtractor::adjustSVGPaintForCurrentColor(SVGPaintType paintType, const String& url, const Color& color, const Color& currentColor) const
62 {
63     if (paintType >= SVG_PAINTTYPE_URI_NONE) {
64         RefPtr<CSSValueList> values = CSSValueList::createSpaceSeparated();
65         values->append(CSSPrimitiveValue::create(url, CSSPrimitiveValue::UnitType::CSS_URI));
66         if (paintType == SVG_PAINTTYPE_URI_NONE)
67             values->append(CSSPrimitiveValue::createIdentifier(CSSValueNone));
68         else if (paintType == SVG_PAINTTYPE_URI_CURRENTCOLOR)
69             values->append(CSSPrimitiveValue::create(currentColor));
70         else if (paintType == SVG_PAINTTYPE_URI_RGBCOLOR)
71             values->append(CSSPrimitiveValue::create(color));
72         return values;
73     }
74     if (paintType == SVG_PAINTTYPE_NONE)
75         return CSSPrimitiveValue::createIdentifier(CSSValueNone);
76     if (paintType == SVG_PAINTTYPE_CURRENTCOLOR)
77         return CSSPrimitiveValue::create(currentColor);
78     
79     return CSSPrimitiveValue::create(color);
80 }
81
82 RefPtr<CSSValue> ComputedStyleExtractor::svgPropertyValue(CSSPropertyID propertyID, EUpdateLayout updateLayout)
83 {
84     if (!m_element)
85         return nullptr;
86
87     // Make sure our layout is up to date before we allow a query on these attributes.
88     if (updateLayout)
89         m_element->document().updateLayout();
90
91     auto* style = m_element->computedStyle();
92     if (!style)
93         return nullptr;
94
95     const SVGRenderStyle& svgStyle = style->svgStyle();
96
97     switch (propertyID) {
98         case CSSPropertyClipRule:
99             return CSSPrimitiveValue::create(svgStyle.clipRule());
100         case CSSPropertyFloodOpacity:
101             return CSSPrimitiveValue::create(svgStyle.floodOpacity(), CSSPrimitiveValue::CSS_NUMBER);
102         case CSSPropertyStopOpacity:
103             return CSSPrimitiveValue::create(svgStyle.stopOpacity(), CSSPrimitiveValue::CSS_NUMBER);
104         case CSSPropertyColorInterpolation:
105             return CSSPrimitiveValue::create(svgStyle.colorInterpolation());
106         case CSSPropertyColorInterpolationFilters:
107             return CSSPrimitiveValue::create(svgStyle.colorInterpolationFilters());
108         case CSSPropertyFillOpacity:
109             return CSSPrimitiveValue::create(svgStyle.fillOpacity(), CSSPrimitiveValue::CSS_NUMBER);
110         case CSSPropertyFillRule:
111             return CSSPrimitiveValue::create(svgStyle.fillRule());
112         case CSSPropertyColorRendering:
113             return CSSPrimitiveValue::create(svgStyle.colorRendering());
114         case CSSPropertyShapeRendering:
115             return CSSPrimitiveValue::create(svgStyle.shapeRendering());
116         case CSSPropertyStrokeMiterlimit:
117             return CSSPrimitiveValue::create(svgStyle.strokeMiterLimit(), CSSPrimitiveValue::CSS_NUMBER);
118         case CSSPropertyStrokeOpacity:
119             return CSSPrimitiveValue::create(svgStyle.strokeOpacity(), CSSPrimitiveValue::CSS_NUMBER);
120         case CSSPropertyAlignmentBaseline:
121             return CSSPrimitiveValue::create(svgStyle.alignmentBaseline());
122         case CSSPropertyDominantBaseline:
123             return CSSPrimitiveValue::create(svgStyle.dominantBaseline());
124         case CSSPropertyTextAnchor:
125             return CSSPrimitiveValue::create(svgStyle.textAnchor());
126         case CSSPropertyClipPath:
127             if (!svgStyle.clipperResource().isEmpty())
128                 return CSSPrimitiveValue::create(svgStyle.clipperResource(), CSSPrimitiveValue::CSS_URI);
129             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
130         case CSSPropertyMask:
131             if (!svgStyle.maskerResource().isEmpty())
132                 return CSSPrimitiveValue::create(svgStyle.maskerResource(), CSSPrimitiveValue::CSS_URI);
133             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
134         case CSSPropertyFloodColor:
135             return currentColorOrValidColor(style, svgStyle.floodColor());
136         case CSSPropertyLightingColor:
137             return currentColorOrValidColor(style, svgStyle.lightingColor());
138         case CSSPropertyStopColor:
139             return currentColorOrValidColor(style, svgStyle.stopColor());
140         case CSSPropertyFill:
141             return adjustSVGPaintForCurrentColor(svgStyle.fillPaintType(), svgStyle.fillPaintUri(), svgStyle.fillPaintColor(), style->color());
142         case CSSPropertyKerning:
143             return SVGLengthValue::toCSSPrimitiveValue(svgStyle.kerning());
144         case CSSPropertyMarkerEnd:
145             if (!svgStyle.markerEndResource().isEmpty())
146                 return CSSPrimitiveValue::create(svgStyle.markerEndResource(), CSSPrimitiveValue::CSS_URI);
147             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
148         case CSSPropertyMarkerMid:
149             if (!svgStyle.markerMidResource().isEmpty())
150                 return CSSPrimitiveValue::create(svgStyle.markerMidResource(), CSSPrimitiveValue::CSS_URI);
151             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
152         case CSSPropertyMarkerStart:
153             if (!svgStyle.markerStartResource().isEmpty())
154                 return CSSPrimitiveValue::create(svgStyle.markerStartResource(), CSSPrimitiveValue::CSS_URI);
155             return CSSPrimitiveValue::createIdentifier(CSSValueNone);
156         case CSSPropertyStroke:
157             return adjustSVGPaintForCurrentColor(svgStyle.strokePaintType(), svgStyle.strokePaintUri(), svgStyle.strokePaintColor(), style->color());
158         case CSSPropertyStrokeDasharray:
159             return strokeDashArrayToCSSValueList(svgStyle.strokeDashArray());
160         case CSSPropertyBaselineShift: {
161             switch (svgStyle.baselineShift()) {
162                 case BS_BASELINE:
163                     return CSSPrimitiveValue::createIdentifier(CSSValueBaseline);
164                 case BS_SUPER:
165                     return CSSPrimitiveValue::createIdentifier(CSSValueSuper);
166                 case BS_SUB:
167                     return CSSPrimitiveValue::createIdentifier(CSSValueSub);
168                 case BS_LENGTH:
169                     return SVGLengthValue::toCSSPrimitiveValue(svgStyle.baselineShiftValue());
170             }
171             ASSERT_NOT_REACHED();
172             return nullptr;
173         }
174         case CSSPropertyBufferedRendering:
175             return CSSPrimitiveValue::create(svgStyle.bufferedRendering());
176         case CSSPropertyGlyphOrientationHorizontal:
177             return glyphOrientationToCSSPrimitiveValue(svgStyle.glyphOrientationHorizontal());
178         case CSSPropertyGlyphOrientationVertical: {
179             if (RefPtr<CSSPrimitiveValue> value = glyphOrientationToCSSPrimitiveValue(svgStyle.glyphOrientationVertical()))
180                 return value;
181
182             if (svgStyle.glyphOrientationVertical() == GO_AUTO)
183                 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
184
185             return nullptr;
186         }
187         case CSSPropertyWebkitSvgShadow:
188             return valueForShadow(svgStyle.shadow(), propertyID, *style);
189         case CSSPropertyVectorEffect:
190             return CSSPrimitiveValue::create(svgStyle.vectorEffect());
191         case CSSPropertyMaskType:
192             return CSSPrimitiveValue::create(svgStyle.maskType());
193         case CSSPropertyMarker:
194         case CSSPropertyEnableBackground:
195         case CSSPropertyColorProfile:
196             // the above properties are not yet implemented in the engine
197             break;
198     default:
199         // If you crash here, it's because you added a css property and are not handling it
200         // in either this switch statement or the one in CSSComputedStyleDelcaration::getPropertyCSSValue
201         ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propertyID);
202     }
203     LOG_ERROR("unimplemented propertyID: %d", propertyID);
204     return nullptr;
205 }
206
207 }