Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / svg / SVGPathElement.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 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 #include "core/svg/SVGPathElement.h"
23
24 #include "core/rendering/svg/RenderSVGPath.h"
25 #include "core/rendering/svg/RenderSVGResource.h"
26 #include "core/svg/SVGDocumentExtensions.h"
27 #include "core/svg/SVGMPathElement.h"
28 #include "core/svg/SVGPathSegArcAbs.h"
29 #include "core/svg/SVGPathSegArcRel.h"
30 #include "core/svg/SVGPathSegClosePath.h"
31 #include "core/svg/SVGPathSegCurvetoCubicAbs.h"
32 #include "core/svg/SVGPathSegCurvetoCubicRel.h"
33 #include "core/svg/SVGPathSegCurvetoCubicSmoothAbs.h"
34 #include "core/svg/SVGPathSegCurvetoCubicSmoothRel.h"
35 #include "core/svg/SVGPathSegCurvetoQuadraticAbs.h"
36 #include "core/svg/SVGPathSegCurvetoQuadraticRel.h"
37 #include "core/svg/SVGPathSegCurvetoQuadraticSmoothAbs.h"
38 #include "core/svg/SVGPathSegCurvetoQuadraticSmoothRel.h"
39 #include "core/svg/SVGPathSegLinetoAbs.h"
40 #include "core/svg/SVGPathSegLinetoHorizontalAbs.h"
41 #include "core/svg/SVGPathSegLinetoHorizontalRel.h"
42 #include "core/svg/SVGPathSegLinetoRel.h"
43 #include "core/svg/SVGPathSegLinetoVerticalAbs.h"
44 #include "core/svg/SVGPathSegLinetoVerticalRel.h"
45 #include "core/svg/SVGPathSegMovetoAbs.h"
46 #include "core/svg/SVGPathSegMovetoRel.h"
47 #include "core/svg/SVGPathUtilities.h"
48 #include "core/svg/SVGPointTearOff.h"
49
50 namespace blink {
51
52 inline SVGPathElement::SVGPathElement(Document& document)
53     : SVGGeometryElement(SVGNames::pathTag, document)
54     , m_pathLength(SVGAnimatedNumber::create(this, SVGNames::pathLengthAttr, SVGNumber::create()))
55     , m_pathSegList(SVGAnimatedPath::create(this, SVGNames::dAttr))
56 {
57     addToPropertyMap(m_pathLength);
58     addToPropertyMap(m_pathSegList);
59 }
60
61 DEFINE_NODE_FACTORY(SVGPathElement)
62
63 float SVGPathElement::getTotalLength()
64 {
65     float totalLength = 0;
66     getTotalLengthOfSVGPathByteStream(pathByteStream(), totalLength);
67     return totalLength;
68 }
69
70 PassRefPtr<SVGPointTearOff> SVGPathElement::getPointAtLength(float length)
71 {
72     FloatPoint point;
73     getPointAtLengthOfSVGPathByteStream(pathByteStream(), length, point);
74     return SVGPointTearOff::create(SVGPoint::create(point), 0, PropertyIsNotAnimVal);
75 }
76
77 unsigned SVGPathElement::getPathSegAtLength(float length)
78 {
79     unsigned pathSeg = 0;
80     getSVGPathSegAtLengthFromSVGPathByteStream(pathByteStream(), length, pathSeg);
81     return pathSeg;
82 }
83
84 PassRefPtr<SVGPathSegClosePath> SVGPathElement::createSVGPathSegClosePath()
85 {
86     return SVGPathSegClosePath::create(0);
87 }
88
89 PassRefPtr<SVGPathSegMovetoAbs> SVGPathElement::createSVGPathSegMovetoAbs(float x, float y)
90 {
91     return SVGPathSegMovetoAbs::create(0, x, y);
92 }
93
94 PassRefPtr<SVGPathSegMovetoRel> SVGPathElement::createSVGPathSegMovetoRel(float x, float y)
95 {
96     return SVGPathSegMovetoRel::create(0, x, y);
97 }
98
99 PassRefPtr<SVGPathSegLinetoAbs> SVGPathElement::createSVGPathSegLinetoAbs(float x, float y)
100 {
101     return SVGPathSegLinetoAbs::create(0, x, y);
102 }
103
104 PassRefPtr<SVGPathSegLinetoRel> SVGPathElement::createSVGPathSegLinetoRel(float x, float y)
105 {
106     return SVGPathSegLinetoRel::create(0, x, y);
107 }
108
109 PassRefPtr<SVGPathSegCurvetoCubicAbs> SVGPathElement::createSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1, float x2, float y2)
110 {
111     return SVGPathSegCurvetoCubicAbs::create(0, x, y, x1, y1, x2, y2);
112 }
113
114 PassRefPtr<SVGPathSegCurvetoCubicRel> SVGPathElement::createSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1, float x2, float y2)
115 {
116     return SVGPathSegCurvetoCubicRel::create(0, x, y, x1, y1, x2, y2);
117 }
118
119 PassRefPtr<SVGPathSegCurvetoQuadraticAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1)
120 {
121     return SVGPathSegCurvetoQuadraticAbs::create(0, x, y, x1, y1);
122 }
123
124 PassRefPtr<SVGPathSegCurvetoQuadraticRel> SVGPathElement::createSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1)
125 {
126     return SVGPathSegCurvetoQuadraticRel::create(0, x, y, x1, y1);
127 }
128
129 PassRefPtr<SVGPathSegArcAbs> SVGPathElement::createSVGPathSegArcAbs(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
130 {
131     return SVGPathSegArcAbs::create(0, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
132 }
133
134 PassRefPtr<SVGPathSegArcRel> SVGPathElement::createSVGPathSegArcRel(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
135 {
136     return SVGPathSegArcRel::create(0, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
137 }
138
139 PassRefPtr<SVGPathSegLinetoHorizontalAbs> SVGPathElement::createSVGPathSegLinetoHorizontalAbs(float x)
140 {
141     return SVGPathSegLinetoHorizontalAbs::create(0, x);
142 }
143
144 PassRefPtr<SVGPathSegLinetoHorizontalRel> SVGPathElement::createSVGPathSegLinetoHorizontalRel(float x)
145 {
146     return SVGPathSegLinetoHorizontalRel::create(0, x);
147 }
148
149 PassRefPtr<SVGPathSegLinetoVerticalAbs> SVGPathElement::createSVGPathSegLinetoVerticalAbs(float y)
150 {
151     return SVGPathSegLinetoVerticalAbs::create(0, y);
152 }
153
154 PassRefPtr<SVGPathSegLinetoVerticalRel> SVGPathElement::createSVGPathSegLinetoVerticalRel(float y)
155 {
156     return SVGPathSegLinetoVerticalRel::create(0, y);
157 }
158
159 PassRefPtr<SVGPathSegCurvetoCubicSmoothAbs> SVGPathElement::createSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2)
160 {
161     return SVGPathSegCurvetoCubicSmoothAbs::create(0, x, y, x2, y2);
162 }
163
164 PassRefPtr<SVGPathSegCurvetoCubicSmoothRel> SVGPathElement::createSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2)
165 {
166     return SVGPathSegCurvetoCubicSmoothRel::create(0, x, y, x2, y2);
167 }
168
169 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y)
170 {
171     return SVGPathSegCurvetoQuadraticSmoothAbs::create(0, x, y);
172 }
173
174 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothRel> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothRel(float x, float y)
175 {
176     return SVGPathSegCurvetoQuadraticSmoothRel::create(0, x, y);
177 }
178
179 bool SVGPathElement::isSupportedAttribute(const QualifiedName& attrName)
180 {
181     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
182     if (supportedAttributes.isEmpty()) {
183         supportedAttributes.add(SVGNames::dAttr);
184         supportedAttributes.add(SVGNames::pathLengthAttr);
185     }
186     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
187 }
188
189 void SVGPathElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
190 {
191     if (!isSupportedAttribute(name)) {
192         SVGGeometryElement::parseAttribute(name, value);
193         return;
194     }
195
196     SVGParsingError parseError = NoError;
197
198     if (name == SVGNames::dAttr) {
199         m_pathSegList->setBaseValueAsString(value, parseError);
200     } else if (name == SVGNames::pathLengthAttr) {
201         m_pathLength->setBaseValueAsString(value, parseError);
202         if (parseError == NoError && m_pathLength->baseValue()->value() < 0)
203             document().accessSVGExtensions().reportError("A negative value for path attribute <pathLength> is not allowed");
204     } else {
205         ASSERT_NOT_REACHED();
206     }
207
208     reportAttributeParsingError(parseError, name, value);
209 }
210
211 void SVGPathElement::svgAttributeChanged(const QualifiedName& attrName)
212 {
213     if (!isSupportedAttribute(attrName)) {
214         SVGGeometryElement::svgAttributeChanged(attrName);
215         return;
216     }
217
218     SVGElement::InvalidationGuard invalidationGuard(this);
219
220     RenderSVGShape* renderer = toRenderSVGShape(this->renderer());
221
222     if (attrName == SVGNames::dAttr) {
223         if (renderer)
224             renderer->setNeedsShapeUpdate();
225
226         invalidateMPathDependencies();
227     }
228
229     if (renderer)
230         RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
231 }
232
233 void SVGPathElement::invalidateMPathDependencies()
234 {
235     // <mpath> can only reference <path> but this dependency is not handled in
236     // markForLayoutAndParentResourceInvalidation so we update any mpath dependencies manually.
237     if (SVGElementSet* dependencies = setOfIncomingReferences()) {
238         SVGElementSet::iterator end = dependencies->end();
239         for (SVGElementSet::iterator it = dependencies->begin(); it != end; ++it) {
240             if (isSVGMPathElement(**it))
241                 toSVGMPathElement(*it)->targetPathChanged();
242         }
243     }
244 }
245
246 Node::InsertionNotificationRequest SVGPathElement::insertedInto(ContainerNode* rootParent)
247 {
248     SVGGeometryElement::insertedInto(rootParent);
249     invalidateMPathDependencies();
250     return InsertionDone;
251 }
252
253 void SVGPathElement::removedFrom(ContainerNode* rootParent)
254 {
255     SVGGeometryElement::removedFrom(rootParent);
256     invalidateMPathDependencies();
257 }
258
259 void SVGPathElement::pathSegListChanged(ListModification listModification)
260 {
261     m_pathSegList->baseValue()->clearByteStream();
262
263     invalidateSVGAttributes();
264
265     RenderSVGShape* renderer = toRenderSVGShape(this->renderer());
266     if (!renderer)
267         return;
268
269     renderer->setNeedsShapeUpdate();
270     RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
271 }
272
273 FloatRect SVGPathElement::getBBox()
274 {
275     // By default, getBBox() returns objectBoundingBox but that will include
276     // markers so we override it to return just the path's bounding rect.
277
278     document().updateLayoutIgnorePendingStylesheets();
279
280     // FIXME: Eventually we should support getBBox for detached elements.
281     if (!renderer())
282         return FloatRect();
283
284     RenderSVGShape* renderer = toRenderSVGShape(this->renderer());
285     return renderer->path().boundingRect();
286 }
287
288 } // namespace blink