• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
3  * Copyright (C) 2013 Apple Inc. All rights reserved.
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 
23 #include "core/svg/SVGPathStringSource.h"
24 
25 #include "core/svg/SVGParserUtilities.h"
26 #include "platform/geometry/FloatPoint.h"
27 
28 namespace WebCore {
29 
SVGPathStringSource(const String & string)30 SVGPathStringSource::SVGPathStringSource(const String& string)
31     : m_string(string)
32     , m_is8BitSource(string.is8Bit())
33 {
34     ASSERT(!string.isEmpty());
35 
36     if (m_is8BitSource) {
37         m_current.m_character8 = string.characters8();
38         m_end.m_character8 = m_current.m_character8 + string.length();
39     } else {
40         m_current.m_character16 = string.characters16();
41         m_end.m_character16 = m_current.m_character16 + string.length();
42     }
43 }
44 
hasMoreData() const45 bool SVGPathStringSource::hasMoreData() const
46 {
47     if (m_is8BitSource)
48         return m_current.m_character8 < m_end.m_character8;
49     return m_current.m_character16 < m_end.m_character16;
50 }
51 
moveToNextToken()52 bool SVGPathStringSource::moveToNextToken()
53 {
54     if (m_is8BitSource)
55         return skipOptionalSVGSpaces(m_current.m_character8, m_end.m_character8);
56     return skipOptionalSVGSpaces(m_current.m_character16, m_end.m_character16);
57 }
58 
59 template <typename CharacterType>
parseSVGSegmentTypeHelper(const CharacterType * & current,SVGPathSegType & pathSegType)60 static bool parseSVGSegmentTypeHelper(const CharacterType*& current, SVGPathSegType& pathSegType)
61 {
62     switch (*(current++)) {
63     case 'Z':
64     case 'z':
65         pathSegType = PathSegClosePath;
66         break;
67     case 'M':
68         pathSegType = PathSegMoveToAbs;
69         break;
70     case 'm':
71         pathSegType = PathSegMoveToRel;
72         break;
73     case 'L':
74         pathSegType = PathSegLineToAbs;
75         break;
76     case 'l':
77         pathSegType = PathSegLineToRel;
78         break;
79     case 'C':
80         pathSegType = PathSegCurveToCubicAbs;
81         break;
82     case 'c':
83         pathSegType = PathSegCurveToCubicRel;
84         break;
85     case 'Q':
86         pathSegType = PathSegCurveToQuadraticAbs;
87         break;
88     case 'q':
89         pathSegType = PathSegCurveToQuadraticRel;
90         break;
91     case 'A':
92         pathSegType = PathSegArcAbs;
93         break;
94     case 'a':
95         pathSegType = PathSegArcRel;
96         break;
97     case 'H':
98         pathSegType = PathSegLineToHorizontalAbs;
99         break;
100     case 'h':
101         pathSegType = PathSegLineToHorizontalRel;
102         break;
103     case 'V':
104         pathSegType = PathSegLineToVerticalAbs;
105         break;
106     case 'v':
107         pathSegType = PathSegLineToVerticalRel;
108         break;
109     case 'S':
110         pathSegType = PathSegCurveToCubicSmoothAbs;
111         break;
112     case 's':
113         pathSegType = PathSegCurveToCubicSmoothRel;
114         break;
115     case 'T':
116         pathSegType = PathSegCurveToQuadraticSmoothAbs;
117         break;
118     case 't':
119         pathSegType = PathSegCurveToQuadraticSmoothRel;
120         break;
121     default:
122         pathSegType = PathSegUnknown;
123     }
124     return true;
125 }
126 
parseSVGSegmentType(SVGPathSegType & pathSegType)127 bool SVGPathStringSource::parseSVGSegmentType(SVGPathSegType& pathSegType)
128 {
129     if (m_is8BitSource)
130         return parseSVGSegmentTypeHelper(m_current.m_character8, pathSegType);
131     return parseSVGSegmentTypeHelper(m_current.m_character16, pathSegType);
132 }
133 
134 template <typename CharacterType>
nextCommandHelper(const CharacterType * & current,SVGPathSegType previousCommand,SVGPathSegType & nextCommand)135 static bool nextCommandHelper(const CharacterType*& current, SVGPathSegType previousCommand, SVGPathSegType& nextCommand)
136 {
137     // Check for remaining coordinates in the current command.
138     if ((*current == '+' || *current == '-' || *current == '.' || (*current >= '0' && *current <= '9'))
139         && previousCommand != PathSegClosePath) {
140         if (previousCommand == PathSegMoveToAbs) {
141             nextCommand = PathSegLineToAbs;
142             return true;
143         }
144         if (previousCommand == PathSegMoveToRel) {
145             nextCommand = PathSegLineToRel;
146             return true;
147         }
148         nextCommand = previousCommand;
149         return true;
150     }
151 
152     return false;
153 }
154 
nextCommand(SVGPathSegType previousCommand)155 SVGPathSegType SVGPathStringSource::nextCommand(SVGPathSegType previousCommand)
156 {
157     SVGPathSegType nextCommand;
158     if (m_is8BitSource) {
159         if (nextCommandHelper(m_current.m_character8, previousCommand, nextCommand))
160             return nextCommand;
161     } else {
162         if (nextCommandHelper(m_current.m_character16, previousCommand, nextCommand))
163             return nextCommand;
164     }
165 
166     parseSVGSegmentType(nextCommand);
167     return nextCommand;
168 }
169 
parseMoveToSegment(FloatPoint & targetPoint)170 bool SVGPathStringSource::parseMoveToSegment(FloatPoint& targetPoint)
171 {
172     if (m_is8BitSource)
173         return parseFloatPoint(m_current.m_character8, m_end.m_character8, targetPoint);
174     return parseFloatPoint(m_current.m_character16, m_end.m_character16, targetPoint);
175 }
176 
parseLineToSegment(FloatPoint & targetPoint)177 bool SVGPathStringSource::parseLineToSegment(FloatPoint& targetPoint)
178 {
179     if (m_is8BitSource)
180         return parseFloatPoint(m_current.m_character8, m_end.m_character8, targetPoint);
181     return parseFloatPoint(m_current.m_character16, m_end.m_character16, targetPoint);
182 }
183 
parseLineToHorizontalSegment(float & x)184 bool SVGPathStringSource::parseLineToHorizontalSegment(float& x)
185 {
186     if (m_is8BitSource)
187         return parseNumber(m_current.m_character8, m_end.m_character8, x);
188     return parseNumber(m_current.m_character16, m_end.m_character16, x);
189 }
190 
parseLineToVerticalSegment(float & y)191 bool SVGPathStringSource::parseLineToVerticalSegment(float& y)
192 {
193     if (m_is8BitSource)
194         return parseNumber(m_current.m_character8, m_end.m_character8, y);
195     return parseNumber(m_current.m_character16, m_end.m_character16, y);
196 }
197 
parseCurveToCubicSegment(FloatPoint & point1,FloatPoint & point2,FloatPoint & targetPoint)198 bool SVGPathStringSource::parseCurveToCubicSegment(FloatPoint& point1, FloatPoint& point2, FloatPoint& targetPoint)
199 {
200     if (m_is8BitSource)
201         return parseFloatPoint3(m_current.m_character8, m_end.m_character8, point1, point2, targetPoint);
202     return parseFloatPoint3(m_current.m_character16, m_end.m_character16, point1, point2, targetPoint);
203 }
204 
parseCurveToCubicSmoothSegment(FloatPoint & point1,FloatPoint & targetPoint)205 bool SVGPathStringSource::parseCurveToCubicSmoothSegment(FloatPoint& point1, FloatPoint& targetPoint)
206 {
207     if (m_is8BitSource)
208         return parseFloatPoint2(m_current.m_character8, m_end.m_character8, point1, targetPoint);
209     return parseFloatPoint2(m_current.m_character16, m_end.m_character16, point1, targetPoint);
210 }
211 
parseCurveToQuadraticSegment(FloatPoint & point2,FloatPoint & targetPoint)212 bool SVGPathStringSource::parseCurveToQuadraticSegment(FloatPoint& point2, FloatPoint& targetPoint)
213 {
214     if (m_is8BitSource)
215         return parseFloatPoint2(m_current.m_character8, m_end.m_character8, point2, targetPoint);
216     return parseFloatPoint2(m_current.m_character16, m_end.m_character16, point2, targetPoint);
217 }
218 
parseCurveToQuadraticSmoothSegment(FloatPoint & targetPoint)219 bool SVGPathStringSource::parseCurveToQuadraticSmoothSegment(FloatPoint& targetPoint)
220 {
221     if (m_is8BitSource)
222         return parseFloatPoint(m_current.m_character8, m_end.m_character8, targetPoint);
223     return parseFloatPoint(m_current.m_character16, m_end.m_character16, targetPoint);
224 }
225 
226 template <typename CharacterType>
parseArcToSegmentHelper(const CharacterType * & current,const CharacterType * end,float & rx,float & ry,float & angle,bool & largeArc,bool & sweep,FloatPoint & targetPoint)227 static bool parseArcToSegmentHelper(const CharacterType*& current, const CharacterType* end, float& rx, float& ry, float& angle, bool& largeArc, bool& sweep, FloatPoint& targetPoint)
228 {
229     float toX;
230     float toY;
231     if (!parseNumber(current, end, rx)
232         || !parseNumber(current, end, ry)
233         || !parseNumber(current, end, angle)
234         || !parseArcFlag(current, end, largeArc)
235         || !parseArcFlag(current, end, sweep)
236         || !parseNumber(current, end, toX)
237         || !parseNumber(current, end, toY))
238         return false;
239     targetPoint = FloatPoint(toX, toY);
240     return true;
241 }
242 
parseArcToSegment(float & rx,float & ry,float & angle,bool & largeArc,bool & sweep,FloatPoint & targetPoint)243 bool SVGPathStringSource::parseArcToSegment(float& rx, float& ry, float& angle, bool& largeArc, bool& sweep, FloatPoint& targetPoint)
244 {
245     if (m_is8BitSource)
246         return parseArcToSegmentHelper(m_current.m_character8, m_end.m_character8, rx, ry, angle, largeArc, sweep, targetPoint);
247     return parseArcToSegmentHelper(m_current.m_character16, m_end.m_character16, rx, ry, angle, largeArc, sweep, targetPoint);
248 }
249 
250 } // namespace blink
251