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