2 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
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.
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.
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.
22 #include "core/svg/SVGPathElement.h"
24 #include "core/rendering/svg/RenderSVGPath.h"
25 #include "core/svg/SVGDocumentExtensions.h"
26 #include "core/svg/SVGMPathElement.h"
27 #include "core/svg/SVGPathSegArcAbs.h"
28 #include "core/svg/SVGPathSegArcRel.h"
29 #include "core/svg/SVGPathSegClosePath.h"
30 #include "core/svg/SVGPathSegCurvetoCubicAbs.h"
31 #include "core/svg/SVGPathSegCurvetoCubicRel.h"
32 #include "core/svg/SVGPathSegCurvetoCubicSmoothAbs.h"
33 #include "core/svg/SVGPathSegCurvetoCubicSmoothRel.h"
34 #include "core/svg/SVGPathSegCurvetoQuadraticAbs.h"
35 #include "core/svg/SVGPathSegCurvetoQuadraticRel.h"
36 #include "core/svg/SVGPathSegCurvetoQuadraticSmoothAbs.h"
37 #include "core/svg/SVGPathSegCurvetoQuadraticSmoothRel.h"
38 #include "core/svg/SVGPathSegLinetoAbs.h"
39 #include "core/svg/SVGPathSegLinetoHorizontalAbs.h"
40 #include "core/svg/SVGPathSegLinetoHorizontalRel.h"
41 #include "core/svg/SVGPathSegLinetoRel.h"
42 #include "core/svg/SVGPathSegLinetoVerticalAbs.h"
43 #include "core/svg/SVGPathSegLinetoVerticalRel.h"
44 #include "core/svg/SVGPathSegMovetoAbs.h"
45 #include "core/svg/SVGPathSegMovetoRel.h"
46 #include "core/svg/SVGPathUtilities.h"
47 #include "core/svg/SVGPointTearOff.h"
51 inline SVGPathElement::SVGPathElement(Document& document)
52 : SVGGeometryElement(SVGNames::pathTag, document)
53 , m_pathLength(SVGAnimatedNumber::create(this, SVGNames::pathLengthAttr, SVGNumber::create()))
54 , m_pathSegList(SVGAnimatedPath::create(this, SVGNames::dAttr))
56 addToPropertyMap(m_pathLength);
57 addToPropertyMap(m_pathSegList);
60 DEFINE_NODE_FACTORY(SVGPathElement)
62 float SVGPathElement::getTotalLength()
64 float totalLength = 0;
65 getTotalLengthOfSVGPathByteStream(pathByteStream(), totalLength);
69 PassRefPtr<SVGPointTearOff> SVGPathElement::getPointAtLength(float length)
72 getPointAtLengthOfSVGPathByteStream(pathByteStream(), length, point);
73 return SVGPointTearOff::create(SVGPoint::create(point), 0, PropertyIsNotAnimVal);
76 unsigned SVGPathElement::getPathSegAtLength(float length)
79 getSVGPathSegAtLengthFromSVGPathByteStream(pathByteStream(), length, pathSeg);
83 PassRefPtr<SVGPathSegClosePath> SVGPathElement::createSVGPathSegClosePath()
85 return SVGPathSegClosePath::create(0);
88 PassRefPtr<SVGPathSegMovetoAbs> SVGPathElement::createSVGPathSegMovetoAbs(float x, float y)
90 return SVGPathSegMovetoAbs::create(0, x, y);
93 PassRefPtr<SVGPathSegMovetoRel> SVGPathElement::createSVGPathSegMovetoRel(float x, float y)
95 return SVGPathSegMovetoRel::create(0, x, y);
98 PassRefPtr<SVGPathSegLinetoAbs> SVGPathElement::createSVGPathSegLinetoAbs(float x, float y)
100 return SVGPathSegLinetoAbs::create(0, x, y);
103 PassRefPtr<SVGPathSegLinetoRel> SVGPathElement::createSVGPathSegLinetoRel(float x, float y)
105 return SVGPathSegLinetoRel::create(0, x, y);
108 PassRefPtr<SVGPathSegCurvetoCubicAbs> SVGPathElement::createSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1, float x2, float y2)
110 return SVGPathSegCurvetoCubicAbs::create(0, x, y, x1, y1, x2, y2);
113 PassRefPtr<SVGPathSegCurvetoCubicRel> SVGPathElement::createSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1, float x2, float y2)
115 return SVGPathSegCurvetoCubicRel::create(0, x, y, x1, y1, x2, y2);
118 PassRefPtr<SVGPathSegCurvetoQuadraticAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1)
120 return SVGPathSegCurvetoQuadraticAbs::create(0, x, y, x1, y1);
123 PassRefPtr<SVGPathSegCurvetoQuadraticRel> SVGPathElement::createSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1)
125 return SVGPathSegCurvetoQuadraticRel::create(0, x, y, x1, y1);
128 PassRefPtr<SVGPathSegArcAbs> SVGPathElement::createSVGPathSegArcAbs(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
130 return SVGPathSegArcAbs::create(0, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
133 PassRefPtr<SVGPathSegArcRel> SVGPathElement::createSVGPathSegArcRel(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
135 return SVGPathSegArcRel::create(0, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
138 PassRefPtr<SVGPathSegLinetoHorizontalAbs> SVGPathElement::createSVGPathSegLinetoHorizontalAbs(float x)
140 return SVGPathSegLinetoHorizontalAbs::create(0, x);
143 PassRefPtr<SVGPathSegLinetoHorizontalRel> SVGPathElement::createSVGPathSegLinetoHorizontalRel(float x)
145 return SVGPathSegLinetoHorizontalRel::create(0, x);
148 PassRefPtr<SVGPathSegLinetoVerticalAbs> SVGPathElement::createSVGPathSegLinetoVerticalAbs(float y)
150 return SVGPathSegLinetoVerticalAbs::create(0, y);
153 PassRefPtr<SVGPathSegLinetoVerticalRel> SVGPathElement::createSVGPathSegLinetoVerticalRel(float y)
155 return SVGPathSegLinetoVerticalRel::create(0, y);
158 PassRefPtr<SVGPathSegCurvetoCubicSmoothAbs> SVGPathElement::createSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2)
160 return SVGPathSegCurvetoCubicSmoothAbs::create(0, x, y, x2, y2);
163 PassRefPtr<SVGPathSegCurvetoCubicSmoothRel> SVGPathElement::createSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2)
165 return SVGPathSegCurvetoCubicSmoothRel::create(0, x, y, x2, y2);
168 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y)
170 return SVGPathSegCurvetoQuadraticSmoothAbs::create(0, x, y);
173 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothRel> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothRel(float x, float y)
175 return SVGPathSegCurvetoQuadraticSmoothRel::create(0, x, y);
178 bool SVGPathElement::isSupportedAttribute(const QualifiedName& attrName)
180 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
181 if (supportedAttributes.isEmpty()) {
182 supportedAttributes.add(SVGNames::dAttr);
183 supportedAttributes.add(SVGNames::pathLengthAttr);
185 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
188 void SVGPathElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
190 if (!isSupportedAttribute(name)) {
191 SVGGeometryElement::parseAttribute(name, value);
195 SVGParsingError parseError = NoError;
197 if (name == SVGNames::dAttr) {
198 m_pathSegList->setBaseValueAsString(value, parseError);
199 } else if (name == SVGNames::pathLengthAttr) {
200 m_pathLength->setBaseValueAsString(value, parseError);
201 if (parseError == NoError && m_pathLength->baseValue()->value() < 0)
202 document().accessSVGExtensions().reportError("A negative value for path attribute <pathLength> is not allowed");
204 ASSERT_NOT_REACHED();
207 reportAttributeParsingError(parseError, name, value);
210 void SVGPathElement::svgAttributeChanged(const QualifiedName& attrName)
212 if (!isSupportedAttribute(attrName)) {
213 SVGGeometryElement::svgAttributeChanged(attrName);
217 SVGElement::InvalidationGuard invalidationGuard(this);
219 RenderSVGShape* renderer = toRenderSVGShape(this->renderer());
221 if (attrName == SVGNames::dAttr) {
223 renderer->setNeedsShapeUpdate();
225 invalidateMPathDependencies();
229 markForLayoutAndParentResourceInvalidation(renderer);
232 void SVGPathElement::invalidateMPathDependencies()
234 // <mpath> can only reference <path> but this dependency is not handled in
235 // markForLayoutAndParentResourceInvalidation so we update any mpath dependencies manually.
236 if (SVGElementSet* dependencies = setOfIncomingReferences()) {
237 SVGElementSet::iterator end = dependencies->end();
238 for (SVGElementSet::iterator it = dependencies->begin(); it != end; ++it) {
239 if (isSVGMPathElement(**it))
240 toSVGMPathElement(*it)->targetPathChanged();
245 Node::InsertionNotificationRequest SVGPathElement::insertedInto(ContainerNode* rootParent)
247 SVGGeometryElement::insertedInto(rootParent);
248 invalidateMPathDependencies();
249 return InsertionDone;
252 void SVGPathElement::removedFrom(ContainerNode* rootParent)
254 SVGGeometryElement::removedFrom(rootParent);
255 invalidateMPathDependencies();
258 void SVGPathElement::pathSegListChanged(ListModification listModification)
260 m_pathSegList->baseValue()->clearByteStream();
262 invalidateSVGAttributes();
264 RenderSVGShape* renderer = toRenderSVGShape(this->renderer());
268 renderer->setNeedsShapeUpdate();
269 markForLayoutAndParentResourceInvalidation(renderer);
272 FloatRect SVGPathElement::getBBox()
274 // By default, getBBox() returns objectBoundingBox but that will include
275 // markers so we override it to return just the path's bounding rect.
277 document().updateLayoutIgnorePendingStylesheets();
279 // FIXME: Eventually we should support getBBox for detached elements.
283 RenderSVGShape* renderer = toRenderSVGShape(this->renderer());
284 return renderer->path().boundingRect();