2010-08-10 Dirk Schulze <krit@webkit.org>
[WebKit-https.git] / WebCore / svg / SVGPathStringSource.cpp
1 /*
2  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21
22 #if ENABLE(SVG)
23 #include "SVGPathStringSource.h"
24
25 #include "SVGParserUtilities.h"
26
27 namespace WebCore {
28
29 SVGPathStringSource::SVGPathStringSource(const String& string)
30     : m_string(string)
31     , m_current(string.characters())
32     , m_end(m_current + string.length())
33 {
34     ASSERT(!string.isEmpty());
35 }
36
37 SVGPathStringSource::~SVGPathStringSource()
38 {
39 }
40
41 bool SVGPathStringSource::hasMoreData() const
42 {
43     return m_current < m_end;
44 }
45
46 bool SVGPathStringSource::moveToNextToken()
47 {
48     return skipOptionalSpaces(m_current, m_end);
49 }
50
51 bool SVGPathStringSource::parseSVGSegmentType(SVGPathSegType& pathSegType)
52 {
53     switch (*(m_current++)) {
54     case 'Z':
55     case 'z':
56         pathSegType = PathSegClosePath;
57         break;
58     case 'M':
59         pathSegType = PathSegMoveToAbs;
60         break;
61     case 'm':
62         pathSegType = PathSegMoveToRel;
63         break;
64     case 'L':
65         pathSegType = PathSegLineToAbs;
66         break;
67     case 'l':
68         pathSegType = PathSegLineToRel;
69         break;
70     case 'C':
71         pathSegType = PathSegCurveToCubicAbs;
72         break;
73     case 'c':
74         pathSegType = PathSegCurveToCubicRel;
75         break;
76     case 'Q':
77         pathSegType = PathSegCurveToQuadraticAbs;
78         break;
79     case 'q':
80         pathSegType = PathSegCurveToQuadraticRel;
81         break;
82     case 'A':
83         pathSegType = PathSegArcAbs;
84         break;
85     case 'a':
86         pathSegType = PathSegArcRel;
87         break;
88     case 'H':
89         pathSegType = PathSegLineToHorizontalAbs;
90         break;
91     case 'h':
92         pathSegType = PathSegLineToHorizontalRel;
93         break;
94     case 'V':
95         pathSegType = PathSegLineToVerticalAbs;
96         break;
97     case 'v':
98         pathSegType = PathSegLineToVerticalRel;
99         break;
100     case 'S':
101         pathSegType = PathSegCurveToCubicSmoothAbs;
102         break;
103     case 's':
104         pathSegType = PathSegCurveToCubicSmoothRel;
105         break;
106     case 'T':
107         pathSegType = PathSegCurveToQuadraticSmoothAbs;
108         break;
109     case 't':
110         pathSegType = PathSegCurveToQuadraticSmoothRel;
111         break;
112     default:
113         pathSegType = PathSegUnknown;
114     }
115     return true;
116 }
117
118 SVGPathSegType SVGPathStringSource::nextCommand(SVGPathSegType previousCommand)
119 {
120     // Check for remaining coordinates in the current command.
121     if ((*m_current == '+' || *m_current == '-' || *m_current == '.' || (*m_current >= '0' && *m_current <= '9'))
122         && previousCommand != PathSegClosePath) {
123         if (previousCommand == PathSegMoveToAbs)
124             return PathSegLineToAbs;
125         if (previousCommand == PathSegMoveToRel)
126             return PathSegLineToRel;
127         return previousCommand;
128     }
129     SVGPathSegType nextCommand;
130     parseSVGSegmentType(nextCommand);
131     return nextCommand;
132 }
133
134 bool SVGPathStringSource::parseMoveToSegment(FloatPoint& targetPoint)
135 {
136     float toX;
137     float toY;
138     if (!parseNumber(m_current, m_end, toX) || !parseNumber(m_current, m_end, toY))
139         return false;
140     targetPoint = FloatPoint(toX, toY);
141     return true;
142 }
143
144 bool SVGPathStringSource::parseLineToSegment(FloatPoint& targetPoint)
145 {
146     float toX;
147     float toY;
148     if (!parseNumber(m_current, m_end, toX) || !parseNumber(m_current, m_end, toY))
149         return false;
150     targetPoint = FloatPoint(toX, toY);
151     return true;
152 }
153
154 bool SVGPathStringSource::parseLineToHorizontalSegment(float& x)
155 {
156     return parseNumber(m_current, m_end, x);
157 }
158
159 bool SVGPathStringSource::parseLineToVerticalSegment(float& y)
160 {
161     return parseNumber(m_current, m_end, y);
162 }
163
164 bool SVGPathStringSource::parseCurveToCubicSegment(FloatPoint& point1, FloatPoint& point2, FloatPoint& targetPoint)
165 {
166     float x1;
167     float y1;
168     float x2;
169     float y2;
170     float toX;
171     float toY;
172     if (!parseNumber(m_current, m_end, x1)
173         || !parseNumber(m_current, m_end, y1)
174         || !parseNumber(m_current, m_end, x2)
175         || !parseNumber(m_current, m_end, y2)
176         || !parseNumber(m_current, m_end, toX)
177         || !parseNumber(m_current, m_end, toY))
178         return false;
179     point1 = FloatPoint(x1, y1);
180     point2 = FloatPoint(x2, y2);
181     targetPoint = FloatPoint(toX, toY);
182     return true;
183 }
184
185 bool SVGPathStringSource::parseCurveToCubicSmoothSegment(FloatPoint& point1, FloatPoint& targetPoint)
186 {
187     float x1;
188     float y1;
189     float toX;
190     float toY;
191     if (!parseNumber(m_current, m_end, x1)
192         || !parseNumber(m_current, m_end, y1)
193         || !parseNumber(m_current, m_end, toX)
194         || !parseNumber(m_current, m_end, toY))
195         return false;
196     point1 = FloatPoint(x1, y1);
197     targetPoint = FloatPoint(toX, toY);
198     return true;
199 }
200
201 bool SVGPathStringSource::parseCurveToQuadraticSegment(FloatPoint& point2, FloatPoint& targetPoint)
202 {
203     float x2;
204     float y2;
205     float toX;
206     float toY;
207     if (!parseNumber(m_current, m_end, x2)
208         || !parseNumber(m_current, m_end, y2)
209         || !parseNumber(m_current, m_end, toX)
210         || !parseNumber(m_current, m_end, toY))
211         return false;
212     point2 = FloatPoint(x2, y2);
213     targetPoint = FloatPoint(toX, toY);
214     return true;
215 }
216
217 bool SVGPathStringSource::parseCurveToQuadraticSmoothSegment(FloatPoint& targetPoint)
218 {
219     float toX;
220     float toY;
221     if (!parseNumber(m_current, m_end, toX)
222         || !parseNumber(m_current, m_end, toY))
223         return false;
224     targetPoint = FloatPoint(toX, toY);
225     return true;
226 }
227
228 bool SVGPathStringSource::parseArcToSegment(float& rx, float& ry, float& angle, bool& largeArc, bool& sweep, FloatPoint& targetPoint)
229 {
230     float toX;
231     float toY;
232     if (!parseNumber(m_current, m_end, rx)
233         || !parseNumber(m_current, m_end, ry)
234         || !parseNumber(m_current, m_end, angle)
235         || !parseArcFlag(m_current, m_end, largeArc)
236         || !parseArcFlag(m_current, m_end, sweep)
237         || !parseNumber(m_current, m_end, toX)
238         || !parseNumber(m_current, m_end, toY))
239         return false;
240     targetPoint = FloatPoint(toX, toY);
241     return true;
242 }
243
244
245 }
246
247 #endif // ENABLE(SVG)