1 /*
2 Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
4
5 This file is part of the KDE project
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21 */
22
23 #include "config.h"
24
25 #if ENABLE(SVG)
26 #include "SVGPathElement.h"
27
28 #include "MappedAttribute.h"
29 #include "RenderPath.h"
30 #include "SVGNames.h"
31 #include "SVGParserUtilities.h"
32 #include "SVGPathSegArc.h"
33 #include "SVGPathSegClosePath.h"
34 #include "SVGPathSegCurvetoCubic.h"
35 #include "SVGPathSegCurvetoCubicSmooth.h"
36 #include "SVGPathSegCurvetoQuadratic.h"
37 #include "SVGPathSegCurvetoQuadraticSmooth.h"
38 #include "SVGPathSegLineto.h"
39 #include "SVGPathSegLinetoHorizontal.h"
40 #include "SVGPathSegLinetoVertical.h"
41 #include "SVGPathSegList.h"
42 #include "SVGPathSegMoveto.h"
43 #include "SVGSVGElement.h"
44
45 namespace WebCore {
46
SVGPathElement(const QualifiedName & tagName,Document * doc)47 SVGPathElement::SVGPathElement(const QualifiedName& tagName, Document* doc)
48 : SVGStyledTransformableElement(tagName, doc)
49 , SVGTests()
50 , SVGLangSpace()
51 , SVGExternalResourcesRequired()
52 , m_pathLength(this, SVGNames::pathLengthAttr, 0.0f)
53 {
54 }
55
~SVGPathElement()56 SVGPathElement::~SVGPathElement()
57 {
58 }
59
getTotalLength()60 float SVGPathElement::getTotalLength()
61 {
62 // FIXME: this may wish to use the pathSegList instead of the pathdata if that's cheaper to build (or cached)
63 return toPathData().length();
64 }
65
getPointAtLength(float length)66 FloatPoint SVGPathElement::getPointAtLength(float length)
67 {
68 // FIXME: this may wish to use the pathSegList instead of the pathdata if that's cheaper to build (or cached)
69 bool ok = false;
70 return toPathData().pointAtLength(length, ok);
71 }
72
getPathSegAtLength(float length)73 unsigned long SVGPathElement::getPathSegAtLength(float length)
74 {
75 return pathSegList()->getPathSegAtLength(length);
76 }
77
createSVGPathSegClosePath()78 PassRefPtr<SVGPathSegClosePath> SVGPathElement::createSVGPathSegClosePath()
79 {
80 return SVGPathSegClosePath::create();
81 }
82
createSVGPathSegMovetoAbs(float x,float y)83 PassRefPtr<SVGPathSegMovetoAbs> SVGPathElement::createSVGPathSegMovetoAbs(float x, float y)
84 {
85 return SVGPathSegMovetoAbs::create(x, y);
86 }
87
createSVGPathSegMovetoRel(float x,float y)88 PassRefPtr<SVGPathSegMovetoRel> SVGPathElement::createSVGPathSegMovetoRel(float x, float y)
89 {
90 return SVGPathSegMovetoRel::create(x, y);
91 }
92
createSVGPathSegLinetoAbs(float x,float y)93 PassRefPtr<SVGPathSegLinetoAbs> SVGPathElement::createSVGPathSegLinetoAbs(float x, float y)
94 {
95 return SVGPathSegLinetoAbs::create(x, y);
96 }
97
createSVGPathSegLinetoRel(float x,float y)98 PassRefPtr<SVGPathSegLinetoRel> SVGPathElement::createSVGPathSegLinetoRel(float x, float y)
99 {
100 return SVGPathSegLinetoRel::create(x, y);
101 }
102
createSVGPathSegCurvetoCubicAbs(float x,float y,float x1,float y1,float x2,float y2)103 PassRefPtr<SVGPathSegCurvetoCubicAbs> SVGPathElement::createSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1, float x2, float y2)
104 {
105 return SVGPathSegCurvetoCubicAbs::create(x, y, x1, y1, x2, y2);
106 }
107
createSVGPathSegCurvetoCubicRel(float x,float y,float x1,float y1,float x2,float y2)108 PassRefPtr<SVGPathSegCurvetoCubicRel> SVGPathElement::createSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1, float x2, float y2)
109 {
110 return SVGPathSegCurvetoCubicRel::create(x, y, x1, y1, x2, y2);
111 }
112
createSVGPathSegCurvetoQuadraticAbs(float x,float y,float x1,float y1)113 PassRefPtr<SVGPathSegCurvetoQuadraticAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1)
114 {
115 return SVGPathSegCurvetoQuadraticAbs::create(x, y, x1, y1);
116 }
117
createSVGPathSegCurvetoQuadraticRel(float x,float y,float x1,float y1)118 PassRefPtr<SVGPathSegCurvetoQuadraticRel> SVGPathElement::createSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1)
119 {
120 return SVGPathSegCurvetoQuadraticRel::create(x, y, x1, y1);
121 }
122
createSVGPathSegArcAbs(float x,float y,float r1,float r2,float angle,bool largeArcFlag,bool sweepFlag)123 PassRefPtr<SVGPathSegArcAbs> SVGPathElement::createSVGPathSegArcAbs(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
124 {
125 return SVGPathSegArcAbs::create(x, y, r1, r2, angle, largeArcFlag, sweepFlag);
126 }
127
createSVGPathSegArcRel(float x,float y,float r1,float r2,float angle,bool largeArcFlag,bool sweepFlag)128 PassRefPtr<SVGPathSegArcRel> SVGPathElement::createSVGPathSegArcRel(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
129 {
130 return SVGPathSegArcRel::create(x, y, r1, r2, angle, largeArcFlag, sweepFlag);
131 }
132
createSVGPathSegLinetoHorizontalAbs(float x)133 PassRefPtr<SVGPathSegLinetoHorizontalAbs> SVGPathElement::createSVGPathSegLinetoHorizontalAbs(float x)
134 {
135 return SVGPathSegLinetoHorizontalAbs::create(x);
136 }
137
createSVGPathSegLinetoHorizontalRel(float x)138 PassRefPtr<SVGPathSegLinetoHorizontalRel> SVGPathElement::createSVGPathSegLinetoHorizontalRel(float x)
139 {
140 return SVGPathSegLinetoHorizontalRel::create(x);
141 }
142
createSVGPathSegLinetoVerticalAbs(float y)143 PassRefPtr<SVGPathSegLinetoVerticalAbs> SVGPathElement::createSVGPathSegLinetoVerticalAbs(float y)
144 {
145 return SVGPathSegLinetoVerticalAbs::create(y);
146 }
147
createSVGPathSegLinetoVerticalRel(float y)148 PassRefPtr<SVGPathSegLinetoVerticalRel> SVGPathElement::createSVGPathSegLinetoVerticalRel(float y)
149 {
150 return SVGPathSegLinetoVerticalRel::create(y);
151 }
152
createSVGPathSegCurvetoCubicSmoothAbs(float x,float y,float x2,float y2)153 PassRefPtr<SVGPathSegCurvetoCubicSmoothAbs> SVGPathElement::createSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2)
154 {
155 return SVGPathSegCurvetoCubicSmoothAbs::create(x, y, x2, y2);
156 }
157
createSVGPathSegCurvetoCubicSmoothRel(float x,float y,float x2,float y2)158 PassRefPtr<SVGPathSegCurvetoCubicSmoothRel> SVGPathElement::createSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2)
159 {
160 return SVGPathSegCurvetoCubicSmoothRel::create(x, y, x2, y2);
161 }
162
createSVGPathSegCurvetoQuadraticSmoothAbs(float x,float y)163 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y)
164 {
165 return SVGPathSegCurvetoQuadraticSmoothAbs::create(x, y);
166 }
167
createSVGPathSegCurvetoQuadraticSmoothRel(float x,float y)168 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothRel> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothRel(float x, float y)
169 {
170 return SVGPathSegCurvetoQuadraticSmoothRel::create(x, y);
171 }
172
parseMappedAttribute(MappedAttribute * attr)173 void SVGPathElement::parseMappedAttribute(MappedAttribute* attr)
174 {
175 if (attr->name() == SVGNames::dAttr) {
176 ExceptionCode ec;
177 pathSegList()->clear(ec);
178 if (!pathSegListFromSVGData(pathSegList(), attr->value(), true))
179 document()->accessSVGExtensions()->reportError("Problem parsing d=\"" + attr->value() + "\"");
180 } else if (attr->name() == SVGNames::pathLengthAttr) {
181 setPathLengthBaseValue(attr->value().toFloat());
182 if (pathLengthBaseValue() < 0.0f)
183 document()->accessSVGExtensions()->reportError("A negative value for path attribute <pathLength> is not allowed");
184 } else {
185 if (SVGTests::parseMappedAttribute(attr))
186 return;
187 if (SVGLangSpace::parseMappedAttribute(attr))
188 return;
189 if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
190 return;
191 SVGStyledTransformableElement::parseMappedAttribute(attr);
192 }
193 }
194
svgAttributeChanged(const QualifiedName & attrName)195 void SVGPathElement::svgAttributeChanged(const QualifiedName& attrName)
196 {
197 SVGStyledTransformableElement::svgAttributeChanged(attrName);
198
199 if (!renderer())
200 return;
201
202 if (attrName == SVGNames::dAttr || attrName == SVGNames::pathLengthAttr ||
203 SVGTests::isKnownAttribute(attrName) ||
204 SVGLangSpace::isKnownAttribute(attrName) ||
205 SVGExternalResourcesRequired::isKnownAttribute(attrName) ||
206 SVGStyledTransformableElement::isKnownAttribute(attrName))
207 renderer()->setNeedsLayout(true);
208 }
209
pathSegList() const210 SVGPathSegList* SVGPathElement::pathSegList() const
211 {
212 if (!m_pathSegList)
213 m_pathSegList = SVGPathSegList::create(SVGNames::dAttr);
214
215 return m_pathSegList.get();
216 }
217
normalizedPathSegList() const218 SVGPathSegList* SVGPathElement::normalizedPathSegList() const
219 {
220 // TODO
221 return 0;
222 }
223
animatedPathSegList() const224 SVGPathSegList* SVGPathElement::animatedPathSegList() const
225 {
226 // TODO
227 return 0;
228 }
229
animatedNormalizedPathSegList() const230 SVGPathSegList* SVGPathElement::animatedNormalizedPathSegList() const
231 {
232 // TODO
233 return 0;
234 }
235
toPathData() const236 Path SVGPathElement::toPathData() const
237 {
238 return pathSegList()->toPathData();
239 }
240
241 }
242
243 #endif // ENABLE(SVG)
244