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
SVGPathStringSource(const String & string)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
hasMoreData() const37 bool SVGPathStringSource::hasMoreData() const
38 {
39 return m_current < m_end;
40 }
41
moveToNextToken()42 bool SVGPathStringSource::moveToNextToken()
43 {
44 return skipOptionalSpaces(m_current, m_end);
45 }
46
parseSVGSegmentType(SVGPathSegType & pathSegType)47 bool SVGPathStringSource::parseSVGSegmentType(SVGPathSegType& pathSegType)
48 {
49 switch (*(m_current++)) {
50 case 'Z':
51 case 'z':
52 pathSegType = PathSegClosePath;
53 break;
54 case 'M':
55 pathSegType = PathSegMoveToAbs;
56 break;
57 case 'm':
58 pathSegType = PathSegMoveToRel;
59 break;
60 case 'L':
61 pathSegType = PathSegLineToAbs;
62 break;
63 case 'l':
64 pathSegType = PathSegLineToRel;
65 break;
66 case 'C':
67 pathSegType = PathSegCurveToCubicAbs;
68 break;
69 case 'c':
70 pathSegType = PathSegCurveToCubicRel;
71 break;
72 case 'Q':
73 pathSegType = PathSegCurveToQuadraticAbs;
74 break;
75 case 'q':
76 pathSegType = PathSegCurveToQuadraticRel;
77 break;
78 case 'A':
79 pathSegType = PathSegArcAbs;
80 break;
81 case 'a':
82 pathSegType = PathSegArcRel;
83 break;
84 case 'H':
85 pathSegType = PathSegLineToHorizontalAbs;
86 break;
87 case 'h':
88 pathSegType = PathSegLineToHorizontalRel;
89 break;
90 case 'V':
91 pathSegType = PathSegLineToVerticalAbs;
92 break;
93 case 'v':
94 pathSegType = PathSegLineToVerticalRel;
95 break;
96 case 'S':
97 pathSegType = PathSegCurveToCubicSmoothAbs;
98 break;
99 case 's':
100 pathSegType = PathSegCurveToCubicSmoothRel;
101 break;
102 case 'T':
103 pathSegType = PathSegCurveToQuadraticSmoothAbs;
104 break;
105 case 't':
106 pathSegType = PathSegCurveToQuadraticSmoothRel;
107 break;
108 default:
109 pathSegType = PathSegUnknown;
110 }
111 return true;
112 }
113
nextCommand(SVGPathSegType previousCommand)114 SVGPathSegType SVGPathStringSource::nextCommand(SVGPathSegType previousCommand)
115 {
116 // Check for remaining coordinates in the current command.
117 if ((*m_current == '+' || *m_current == '-' || *m_current == '.' || (*m_current >= '0' && *m_current <= '9'))
118 && previousCommand != PathSegClosePath) {
119 if (previousCommand == PathSegMoveToAbs)
120 return PathSegLineToAbs;
121 if (previousCommand == PathSegMoveToRel)
122 return PathSegLineToRel;
123 return previousCommand;
124 }
125 SVGPathSegType nextCommand;
126 parseSVGSegmentType(nextCommand);
127 return nextCommand;
128 }
129
parseMoveToSegment(FloatPoint & targetPoint)130 bool SVGPathStringSource::parseMoveToSegment(FloatPoint& targetPoint)
131 {
132 float toX;
133 float toY;
134 if (!parseNumber(m_current, m_end, toX) || !parseNumber(m_current, m_end, toY))
135 return false;
136 targetPoint = FloatPoint(toX, toY);
137 return true;
138 }
139
parseLineToSegment(FloatPoint & targetPoint)140 bool SVGPathStringSource::parseLineToSegment(FloatPoint& targetPoint)
141 {
142 float toX;
143 float toY;
144 if (!parseNumber(m_current, m_end, toX) || !parseNumber(m_current, m_end, toY))
145 return false;
146 targetPoint = FloatPoint(toX, toY);
147 return true;
148 }
149
parseLineToHorizontalSegment(float & x)150 bool SVGPathStringSource::parseLineToHorizontalSegment(float& x)
151 {
152 return parseNumber(m_current, m_end, x);
153 }
154
parseLineToVerticalSegment(float & y)155 bool SVGPathStringSource::parseLineToVerticalSegment(float& y)
156 {
157 return parseNumber(m_current, m_end, y);
158 }
159
parseCurveToCubicSegment(FloatPoint & point1,FloatPoint & point2,FloatPoint & targetPoint)160 bool SVGPathStringSource::parseCurveToCubicSegment(FloatPoint& point1, FloatPoint& point2, FloatPoint& targetPoint)
161 {
162 float x1;
163 float y1;
164 float x2;
165 float y2;
166 float toX;
167 float toY;
168 if (!parseNumber(m_current, m_end, x1)
169 || !parseNumber(m_current, m_end, y1)
170 || !parseNumber(m_current, m_end, x2)
171 || !parseNumber(m_current, m_end, y2)
172 || !parseNumber(m_current, m_end, toX)
173 || !parseNumber(m_current, m_end, toY))
174 return false;
175 point1 = FloatPoint(x1, y1);
176 point2 = FloatPoint(x2, y2);
177 targetPoint = FloatPoint(toX, toY);
178 return true;
179 }
180
parseCurveToCubicSmoothSegment(FloatPoint & point1,FloatPoint & targetPoint)181 bool SVGPathStringSource::parseCurveToCubicSmoothSegment(FloatPoint& point1, FloatPoint& targetPoint)
182 {
183 float x1;
184 float y1;
185 float toX;
186 float toY;
187 if (!parseNumber(m_current, m_end, x1)
188 || !parseNumber(m_current, m_end, y1)
189 || !parseNumber(m_current, m_end, toX)
190 || !parseNumber(m_current, m_end, toY))
191 return false;
192 point1 = FloatPoint(x1, y1);
193 targetPoint = FloatPoint(toX, toY);
194 return true;
195 }
196
parseCurveToQuadraticSegment(FloatPoint & point2,FloatPoint & targetPoint)197 bool SVGPathStringSource::parseCurveToQuadraticSegment(FloatPoint& point2, FloatPoint& targetPoint)
198 {
199 float x2;
200 float y2;
201 float toX;
202 float toY;
203 if (!parseNumber(m_current, m_end, x2)
204 || !parseNumber(m_current, m_end, y2)
205 || !parseNumber(m_current, m_end, toX)
206 || !parseNumber(m_current, m_end, toY))
207 return false;
208 point2 = FloatPoint(x2, y2);
209 targetPoint = FloatPoint(toX, toY);
210 return true;
211 }
212
parseCurveToQuadraticSmoothSegment(FloatPoint & targetPoint)213 bool SVGPathStringSource::parseCurveToQuadraticSmoothSegment(FloatPoint& targetPoint)
214 {
215 float toX;
216 float toY;
217 if (!parseNumber(m_current, m_end, toX)
218 || !parseNumber(m_current, m_end, toY))
219 return false;
220 targetPoint = FloatPoint(toX, toY);
221 return true;
222 }
223
parseArcToSegment(float & rx,float & ry,float & angle,bool & largeArc,bool & sweep,FloatPoint & targetPoint)224 bool SVGPathStringSource::parseArcToSegment(float& rx, float& ry, float& angle, bool& largeArc, bool& sweep, FloatPoint& targetPoint)
225 {
226 float toX;
227 float toY;
228 if (!parseNumber(m_current, m_end, rx)
229 || !parseNumber(m_current, m_end, ry)
230 || !parseNumber(m_current, m_end, angle)
231 || !parseArcFlag(m_current, m_end, largeArc)
232 || !parseArcFlag(m_current, m_end, sweep)
233 || !parseNumber(m_current, m_end, toX)
234 || !parseNumber(m_current, m_end, toY))
235 return false;
236 targetPoint = FloatPoint(toX, toY);
237 return true;
238 }
239
240
241 }
242
243 #endif // ENABLE(SVG)
244