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 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 "SVGPathElement.h"
25
26 #include "MappedAttribute.h"
27 #include "RenderPath.h"
28 #include "SVGNames.h"
29 #include "SVGParserUtilities.h"
30 #include "SVGPathSegArc.h"
31 #include "SVGPathSegClosePath.h"
32 #include "SVGPathSegCurvetoCubic.h"
33 #include "SVGPathSegCurvetoCubicSmooth.h"
34 #include "SVGPathSegCurvetoQuadratic.h"
35 #include "SVGPathSegCurvetoQuadraticSmooth.h"
36 #include "SVGPathSegLineto.h"
37 #include "SVGPathSegLinetoHorizontal.h"
38 #include "SVGPathSegLinetoVertical.h"
39 #include "SVGPathSegList.h"
40 #include "SVGPathSegMoveto.h"
41 #include "SVGSVGElement.h"
42
43 namespace WebCore {
44
SVGPathElement(const QualifiedName & tagName,Document * doc)45 SVGPathElement::SVGPathElement(const QualifiedName& tagName, Document* doc)
46 : SVGStyledTransformableElement(tagName, doc)
47 , SVGTests()
48 , SVGLangSpace()
49 , SVGExternalResourcesRequired()
50 {
51 }
52
~SVGPathElement()53 SVGPathElement::~SVGPathElement()
54 {
55 }
56
getTotalLength()57 float SVGPathElement::getTotalLength()
58 {
59 // FIXME: this may wish to use the pathSegList instead of the pathdata if that's cheaper to build (or cached)
60 return toPathData().length();
61 }
62
getPointAtLength(float length)63 FloatPoint SVGPathElement::getPointAtLength(float length)
64 {
65 // FIXME: this may wish to use the pathSegList instead of the pathdata if that's cheaper to build (or cached)
66 bool ok = false;
67 return toPathData().pointAtLength(length, ok);
68 }
69
getPathSegAtLength(float length,ExceptionCode & ec)70 unsigned long SVGPathElement::getPathSegAtLength(float length, ExceptionCode& ec)
71 {
72 return pathSegList()->getPathSegAtLength(length, ec);
73 }
74
createSVGPathSegClosePath()75 PassRefPtr<SVGPathSegClosePath> SVGPathElement::createSVGPathSegClosePath()
76 {
77 return SVGPathSegClosePath::create();
78 }
79
createSVGPathSegMovetoAbs(float x,float y)80 PassRefPtr<SVGPathSegMovetoAbs> SVGPathElement::createSVGPathSegMovetoAbs(float x, float y)
81 {
82 return SVGPathSegMovetoAbs::create(x, y);
83 }
84
createSVGPathSegMovetoRel(float x,float y)85 PassRefPtr<SVGPathSegMovetoRel> SVGPathElement::createSVGPathSegMovetoRel(float x, float y)
86 {
87 return SVGPathSegMovetoRel::create(x, y);
88 }
89
createSVGPathSegLinetoAbs(float x,float y)90 PassRefPtr<SVGPathSegLinetoAbs> SVGPathElement::createSVGPathSegLinetoAbs(float x, float y)
91 {
92 return SVGPathSegLinetoAbs::create(x, y);
93 }
94
createSVGPathSegLinetoRel(float x,float y)95 PassRefPtr<SVGPathSegLinetoRel> SVGPathElement::createSVGPathSegLinetoRel(float x, float y)
96 {
97 return SVGPathSegLinetoRel::create(x, y);
98 }
99
createSVGPathSegCurvetoCubicAbs(float x,float y,float x1,float y1,float x2,float y2)100 PassRefPtr<SVGPathSegCurvetoCubicAbs> SVGPathElement::createSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1, float x2, float y2)
101 {
102 return SVGPathSegCurvetoCubicAbs::create(x, y, x1, y1, x2, y2);
103 }
104
createSVGPathSegCurvetoCubicRel(float x,float y,float x1,float y1,float x2,float y2)105 PassRefPtr<SVGPathSegCurvetoCubicRel> SVGPathElement::createSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1, float x2, float y2)
106 {
107 return SVGPathSegCurvetoCubicRel::create(x, y, x1, y1, x2, y2);
108 }
109
createSVGPathSegCurvetoQuadraticAbs(float x,float y,float x1,float y1)110 PassRefPtr<SVGPathSegCurvetoQuadraticAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1)
111 {
112 return SVGPathSegCurvetoQuadraticAbs::create(x, y, x1, y1);
113 }
114
createSVGPathSegCurvetoQuadraticRel(float x,float y,float x1,float y1)115 PassRefPtr<SVGPathSegCurvetoQuadraticRel> SVGPathElement::createSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1)
116 {
117 return SVGPathSegCurvetoQuadraticRel::create(x, y, x1, y1);
118 }
119
createSVGPathSegArcAbs(float x,float y,float r1,float r2,float angle,bool largeArcFlag,bool sweepFlag)120 PassRefPtr<SVGPathSegArcAbs> SVGPathElement::createSVGPathSegArcAbs(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
121 {
122 return SVGPathSegArcAbs::create(x, y, r1, r2, angle, largeArcFlag, sweepFlag);
123 }
124
createSVGPathSegArcRel(float x,float y,float r1,float r2,float angle,bool largeArcFlag,bool sweepFlag)125 PassRefPtr<SVGPathSegArcRel> SVGPathElement::createSVGPathSegArcRel(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
126 {
127 return SVGPathSegArcRel::create(x, y, r1, r2, angle, largeArcFlag, sweepFlag);
128 }
129
createSVGPathSegLinetoHorizontalAbs(float x)130 PassRefPtr<SVGPathSegLinetoHorizontalAbs> SVGPathElement::createSVGPathSegLinetoHorizontalAbs(float x)
131 {
132 return SVGPathSegLinetoHorizontalAbs::create(x);
133 }
134
createSVGPathSegLinetoHorizontalRel(float x)135 PassRefPtr<SVGPathSegLinetoHorizontalRel> SVGPathElement::createSVGPathSegLinetoHorizontalRel(float x)
136 {
137 return SVGPathSegLinetoHorizontalRel::create(x);
138 }
139
createSVGPathSegLinetoVerticalAbs(float y)140 PassRefPtr<SVGPathSegLinetoVerticalAbs> SVGPathElement::createSVGPathSegLinetoVerticalAbs(float y)
141 {
142 return SVGPathSegLinetoVerticalAbs::create(y);
143 }
144
createSVGPathSegLinetoVerticalRel(float y)145 PassRefPtr<SVGPathSegLinetoVerticalRel> SVGPathElement::createSVGPathSegLinetoVerticalRel(float y)
146 {
147 return SVGPathSegLinetoVerticalRel::create(y);
148 }
149
createSVGPathSegCurvetoCubicSmoothAbs(float x,float y,float x2,float y2)150 PassRefPtr<SVGPathSegCurvetoCubicSmoothAbs> SVGPathElement::createSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2)
151 {
152 return SVGPathSegCurvetoCubicSmoothAbs::create(x, y, x2, y2);
153 }
154
createSVGPathSegCurvetoCubicSmoothRel(float x,float y,float x2,float y2)155 PassRefPtr<SVGPathSegCurvetoCubicSmoothRel> SVGPathElement::createSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2)
156 {
157 return SVGPathSegCurvetoCubicSmoothRel::create(x, y, x2, y2);
158 }
159
createSVGPathSegCurvetoQuadraticSmoothAbs(float x,float y)160 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y)
161 {
162 return SVGPathSegCurvetoQuadraticSmoothAbs::create(x, y);
163 }
164
createSVGPathSegCurvetoQuadraticSmoothRel(float x,float y)165 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothRel> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothRel(float x, float y)
166 {
167 return SVGPathSegCurvetoQuadraticSmoothRel::create(x, y);
168 }
169
parseMappedAttribute(MappedAttribute * attr)170 void SVGPathElement::parseMappedAttribute(MappedAttribute* attr)
171 {
172 if (attr->name() == SVGNames::dAttr) {
173 ExceptionCode ec;
174 pathSegList()->clear(ec);
175 if (!pathSegListFromSVGData(pathSegList(), attr->value(), true))
176 document()->accessSVGExtensions()->reportError("Problem parsing d=\"" + attr->value() + "\"");
177 } else if (attr->name() == SVGNames::pathLengthAttr) {
178 setPathLengthBaseValue(attr->value().toFloat());
179 if (pathLengthBaseValue() < 0.0f)
180 document()->accessSVGExtensions()->reportError("A negative value for path attribute <pathLength> is not allowed");
181 } else {
182 if (SVGTests::parseMappedAttribute(attr))
183 return;
184 if (SVGLangSpace::parseMappedAttribute(attr))
185 return;
186 if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
187 return;
188 SVGStyledTransformableElement::parseMappedAttribute(attr);
189 }
190 }
191
svgAttributeChanged(const QualifiedName & attrName)192 void SVGPathElement::svgAttributeChanged(const QualifiedName& attrName)
193 {
194 SVGStyledTransformableElement::svgAttributeChanged(attrName);
195
196 if (!renderer())
197 return;
198
199 if (attrName == SVGNames::dAttr || attrName == SVGNames::pathLengthAttr ||
200 SVGTests::isKnownAttribute(attrName) ||
201 SVGLangSpace::isKnownAttribute(attrName) ||
202 SVGExternalResourcesRequired::isKnownAttribute(attrName) ||
203 SVGStyledTransformableElement::isKnownAttribute(attrName))
204 renderer()->setNeedsLayout(true);
205 }
206
synchronizeProperty(const QualifiedName & attrName)207 void SVGPathElement::synchronizeProperty(const QualifiedName& attrName)
208 {
209 SVGStyledTransformableElement::synchronizeProperty(attrName);
210
211 if (attrName == anyQName()) {
212 synchronizePathLength();
213 synchronizeExternalResourcesRequired();
214 return;
215 }
216
217 if (attrName == SVGNames::pathLengthAttr)
218 synchronizePathLength();
219 else if (SVGExternalResourcesRequired::isKnownAttribute(attrName))
220 synchronizeExternalResourcesRequired();
221 }
222
pathSegList() const223 SVGPathSegList* SVGPathElement::pathSegList() const
224 {
225 if (!m_pathSegList)
226 m_pathSegList = SVGPathSegList::create(SVGNames::dAttr);
227
228 return m_pathSegList.get();
229 }
230
normalizedPathSegList() const231 SVGPathSegList* SVGPathElement::normalizedPathSegList() const
232 {
233 // TODO
234 return 0;
235 }
236
animatedPathSegList() const237 SVGPathSegList* SVGPathElement::animatedPathSegList() const
238 {
239 // TODO
240 return 0;
241 }
242
animatedNormalizedPathSegList() const243 SVGPathSegList* SVGPathElement::animatedNormalizedPathSegList() const
244 {
245 // TODO
246 return 0;
247 }
248
toPathData() const249 Path SVGPathElement::toPathData() const
250 {
251 return pathSegList()->toPathData();
252 }
253
254 }
255
256 #endif // ENABLE(SVG)
257