Update To 11.40.268.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/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"
48
49 namespace blink {
50
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))
55 {
56     addToPropertyMap(m_pathLength);
57     addToPropertyMap(m_pathSegList);
58 }
59
60 DEFINE_NODE_FACTORY(SVGPathElement)
61
62 float SVGPathElement::getTotalLength()
63 {
64     float totalLength = 0;
65     getTotalLengthOfSVGPathByteStream(pathByteStream(), totalLength);
66     return totalLength;
67 }
68
69 PassRefPtr<SVGPointTearOff> SVGPathElement::getPointAtLength(float length)
70 {
71     FloatPoint point;
72     getPointAtLengthOfSVGPathByteStream(pathByteStream(), length, point);
73     return SVGPointTearOff::create(SVGPoint::create(point), 0, PropertyIsNotAnimVal);
74 }
75
76 unsigned SVGPathElement::getPathSegAtLength(float length)
77 {
78     unsigned pathSeg = 0;
79     getSVGPathSegAtLengthFromSVGPathByteStream(pathByteStream(), length, pathSeg);
80     return pathSeg;
81 }
82
83 PassRefPtr<SVGPathSegClosePath> SVGPathElement::createSVGPathSegClosePath()
84 {
85     return SVGPathSegClosePath::create(0);
86 }
87
88 PassRefPtr<SVGPathSegMovetoAbs> SVGPathElement::createSVGPathSegMovetoAbs(float x, float y)
89 {
90     return SVGPathSegMovetoAbs::create(0, x, y);
91 }
92
93 PassRefPtr<SVGPathSegMovetoRel> SVGPathElement::createSVGPathSegMovetoRel(float x, float y)
94 {
95     return SVGPathSegMovetoRel::create(0, x, y);
96 }
97
98 PassRefPtr<SVGPathSegLinetoAbs> SVGPathElement::createSVGPathSegLinetoAbs(float x, float y)
99 {
100     return SVGPathSegLinetoAbs::create(0, x, y);
101 }
102
103 PassRefPtr<SVGPathSegLinetoRel> SVGPathElement::createSVGPathSegLinetoRel(float x, float y)
104 {
105     return SVGPathSegLinetoRel::create(0, x, y);
106 }
107
108 PassRefPtr<SVGPathSegCurvetoCubicAbs> SVGPathElement::createSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1, float x2, float y2)
109 {
110     return SVGPathSegCurvetoCubicAbs::create(0, x, y, x1, y1, x2, y2);
111 }
112
113 PassRefPtr<SVGPathSegCurvetoCubicRel> SVGPathElement::createSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1, float x2, float y2)
114 {
115     return SVGPathSegCurvetoCubicRel::create(0, x, y, x1, y1, x2, y2);
116 }
117
118 PassRefPtr<SVGPathSegCurvetoQuadraticAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1)
119 {
120     return SVGPathSegCurvetoQuadraticAbs::create(0, x, y, x1, y1);
121 }
122
123 PassRefPtr<SVGPathSegCurvetoQuadraticRel> SVGPathElement::createSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1)
124 {
125     return SVGPathSegCurvetoQuadraticRel::create(0, x, y, x1, y1);
126 }
127
128 PassRefPtr<SVGPathSegArcAbs> SVGPathElement::createSVGPathSegArcAbs(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
129 {
130     return SVGPathSegArcAbs::create(0, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
131 }
132
133 PassRefPtr<SVGPathSegArcRel> SVGPathElement::createSVGPathSegArcRel(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
134 {
135     return SVGPathSegArcRel::create(0, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
136 }
137
138 PassRefPtr<SVGPathSegLinetoHorizontalAbs> SVGPathElement::createSVGPathSegLinetoHorizontalAbs(float x)
139 {
140     return SVGPathSegLinetoHorizontalAbs::create(0, x);
141 }
142
143 PassRefPtr<SVGPathSegLinetoHorizontalRel> SVGPathElement::createSVGPathSegLinetoHorizontalRel(float x)
144 {
145     return SVGPathSegLinetoHorizontalRel::create(0, x);
146 }
147
148 PassRefPtr<SVGPathSegLinetoVerticalAbs> SVGPathElement::createSVGPathSegLinetoVerticalAbs(float y)
149 {
150     return SVGPathSegLinetoVerticalAbs::create(0, y);
151 }
152
153 PassRefPtr<SVGPathSegLinetoVerticalRel> SVGPathElement::createSVGPathSegLinetoVerticalRel(float y)
154 {
155     return SVGPathSegLinetoVerticalRel::create(0, y);
156 }
157
158 PassRefPtr<SVGPathSegCurvetoCubicSmoothAbs> SVGPathElement::createSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2)
159 {
160     return SVGPathSegCurvetoCubicSmoothAbs::create(0, x, y, x2, y2);
161 }
162
163 PassRefPtr<SVGPathSegCurvetoCubicSmoothRel> SVGPathElement::createSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2)
164 {
165     return SVGPathSegCurvetoCubicSmoothRel::create(0, x, y, x2, y2);
166 }
167
168 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y)
169 {
170     return SVGPathSegCurvetoQuadraticSmoothAbs::create(0, x, y);
171 }
172
173 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothRel> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothRel(float x, float y)
174 {
175     return SVGPathSegCurvetoQuadraticSmoothRel::create(0, x, y);
176 }
177
178 bool SVGPathElement::isSupportedAttribute(const QualifiedName& attrName)
179 {
180     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
181     if (supportedAttributes.isEmpty()) {
182         supportedAttributes.add(SVGNames::dAttr);
183         supportedAttributes.add(SVGNames::pathLengthAttr);
184     }
185     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
186 }
187
188 void SVGPathElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
189 {
190     if (!isSupportedAttribute(name)) {
191         SVGGeometryElement::parseAttribute(name, value);
192         return;
193     }
194
195     SVGParsingError parseError = NoError;
196
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");
203     } else {
204         ASSERT_NOT_REACHED();
205     }
206
207     reportAttributeParsingError(parseError, name, value);
208 }
209
210 void SVGPathElement::svgAttributeChanged(const QualifiedName& attrName)
211 {
212     if (!isSupportedAttribute(attrName)) {
213         SVGGeometryElement::svgAttributeChanged(attrName);
214         return;
215     }
216
217     SVGElement::InvalidationGuard invalidationGuard(this);
218
219     RenderSVGShape* renderer = toRenderSVGShape(this->renderer());
220
221     if (attrName == SVGNames::dAttr) {
222         if (renderer)
223             renderer->setNeedsShapeUpdate();
224
225         invalidateMPathDependencies();
226     }
227
228     if (renderer)
229         markForLayoutAndParentResourceInvalidation(renderer);
230 }
231
232 void SVGPathElement::invalidateMPathDependencies()
233 {
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();
241         }
242     }
243 }
244
245 Node::InsertionNotificationRequest SVGPathElement::insertedInto(ContainerNode* rootParent)
246 {
247     SVGGeometryElement::insertedInto(rootParent);
248     invalidateMPathDependencies();
249     return InsertionDone;
250 }
251
252 void SVGPathElement::removedFrom(ContainerNode* rootParent)
253 {
254     SVGGeometryElement::removedFrom(rootParent);
255     invalidateMPathDependencies();
256 }
257
258 void SVGPathElement::pathSegListChanged(ListModification listModification)
259 {
260     m_pathSegList->baseValue()->clearByteStream();
261
262     invalidateSVGAttributes();
263
264     RenderSVGShape* renderer = toRenderSVGShape(this->renderer());
265     if (!renderer)
266         return;
267
268     renderer->setNeedsShapeUpdate();
269     markForLayoutAndParentResourceInvalidation(renderer);
270 }
271
272 FloatRect SVGPathElement::getBBox()
273 {
274     // By default, getBBox() returns objectBoundingBox but that will include
275     // markers so we override it to return just the path's bounding rect.
276
277     document().updateLayoutIgnorePendingStylesheets();
278
279     // FIXME: Eventually we should support getBBox for detached elements.
280     if (!renderer())
281         return FloatRect();
282
283     RenderSVGShape* renderer = toRenderSVGShape(this->renderer());
284     return renderer->path().boundingRect();
285 }
286
287 } // namespace blink