Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: Source/core/svg/SVGPathStringSource.cpp

Issue 1023993002: Rework the SVGPathSource interface (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Blender fixups. Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/svg/SVGPathStringSource.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 2 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
3 * Copyright (C) 2013 Apple Inc. All rights reserved. 3 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * 4 *
5 * This library is free software; you can redistribute it and/or 5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public 6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either 7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version. 8 * version 2 of the License, or (at your option) any later version.
9 * 9 *
10 * This library is distributed in the hope that it will be useful, 10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details. 13 * Library General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU Library General Public License 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 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, 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA. 18 * Boston, MA 02110-1301, USA.
19 */ 19 */
20 20
21 #include "config.h" 21 #include "config.h"
22
23 #include "core/svg/SVGPathStringSource.h" 22 #include "core/svg/SVGPathStringSource.h"
24 23
25 #include "core/svg/SVGParserUtilities.h" 24 #include "core/svg/SVGParserUtilities.h"
26 #include "platform/geometry/FloatPoint.h" 25 #include "platform/geometry/FloatPoint.h"
27 26
28 namespace blink { 27 namespace blink {
29 28
30 SVGPathStringSource::SVGPathStringSource(const String& string) 29 SVGPathStringSource::SVGPathStringSource(const String& string)
31 : m_string(string) 30 : m_string(string)
32 , m_is8BitSource(string.is8Bit()) 31 , m_is8BitSource(string.is8Bit())
32 , m_seenError(false)
33 , m_previousCommand(PathSegUnknown)
33 { 34 {
34 ASSERT(!string.isEmpty()); 35 ASSERT(!string.isEmpty());
35 36
36 if (m_is8BitSource) { 37 if (m_is8BitSource) {
37 m_current.m_character8 = string.characters8(); 38 m_current.m_character8 = string.characters8();
38 m_end.m_character8 = m_current.m_character8 + string.length(); 39 m_end.m_character8 = m_current.m_character8 + string.length();
39 } else { 40 } else {
40 m_current.m_character16 = string.characters16(); 41 m_current.m_character16 = string.characters16();
41 m_end.m_character16 = m_current.m_character16 + string.length(); 42 m_end.m_character16 = m_current.m_character16 + string.length();
42 } 43 }
44 eatWhitespace();
43 } 45 }
44 46
45 bool SVGPathStringSource::hasMoreData() const 47 bool SVGPathStringSource::hasMoreData() const
46 { 48 {
47 if (m_is8BitSource) 49 if (m_is8BitSource)
48 return m_current.m_character8 < m_end.m_character8; 50 return m_current.m_character8 < m_end.m_character8;
49 return m_current.m_character16 < m_end.m_character16; 51 return m_current.m_character16 < m_end.m_character16;
50 } 52 }
51 53
52 bool SVGPathStringSource::moveToNextToken() 54 void SVGPathStringSource::eatWhitespace()
53 { 55 {
54 if (m_is8BitSource) 56 if (m_is8BitSource)
55 return skipOptionalSVGSpaces(m_current.m_character8, m_end.m_character8) ; 57 skipOptionalSVGSpaces(m_current.m_character8, m_end.m_character8);
56 return skipOptionalSVGSpaces(m_current.m_character16, m_end.m_character16); 58 else
59 skipOptionalSVGSpaces(m_current.m_character16, m_end.m_character16);
57 } 60 }
58 61
59 template <typename CharacterType> 62 static SVGPathSegType parseSVGSegmentTypeHelper(unsigned lookahead)
60 static bool parseSVGSegmentTypeHelper(const CharacterType*& current, SVGPathSegT ype& pathSegType)
61 { 63 {
62 switch (*(current++)) { 64 switch (lookahead) {
63 case 'Z': 65 case 'Z':
64 case 'z': 66 case 'z':
65 pathSegType = PathSegClosePath; 67 return PathSegClosePath;
66 break;
67 case 'M': 68 case 'M':
68 pathSegType = PathSegMoveToAbs; 69 return PathSegMoveToAbs;
69 break;
70 case 'm': 70 case 'm':
71 pathSegType = PathSegMoveToRel; 71 return PathSegMoveToRel;
72 break;
73 case 'L': 72 case 'L':
74 pathSegType = PathSegLineToAbs; 73 return PathSegLineToAbs;
75 break;
76 case 'l': 74 case 'l':
77 pathSegType = PathSegLineToRel; 75 return PathSegLineToRel;
78 break;
79 case 'C': 76 case 'C':
80 pathSegType = PathSegCurveToCubicAbs; 77 return PathSegCurveToCubicAbs;
81 break;
82 case 'c': 78 case 'c':
83 pathSegType = PathSegCurveToCubicRel; 79 return PathSegCurveToCubicRel;
84 break;
85 case 'Q': 80 case 'Q':
86 pathSegType = PathSegCurveToQuadraticAbs; 81 return PathSegCurveToQuadraticAbs;
87 break;
88 case 'q': 82 case 'q':
89 pathSegType = PathSegCurveToQuadraticRel; 83 return PathSegCurveToQuadraticRel;
90 break;
91 case 'A': 84 case 'A':
92 pathSegType = PathSegArcAbs; 85 return PathSegArcAbs;
93 break;
94 case 'a': 86 case 'a':
95 pathSegType = PathSegArcRel; 87 return PathSegArcRel;
96 break;
97 case 'H': 88 case 'H':
98 pathSegType = PathSegLineToHorizontalAbs; 89 return PathSegLineToHorizontalAbs;
99 break;
100 case 'h': 90 case 'h':
101 pathSegType = PathSegLineToHorizontalRel; 91 return PathSegLineToHorizontalRel;
102 break;
103 case 'V': 92 case 'V':
104 pathSegType = PathSegLineToVerticalAbs; 93 return PathSegLineToVerticalAbs;
105 break;
106 case 'v': 94 case 'v':
107 pathSegType = PathSegLineToVerticalRel; 95 return PathSegLineToVerticalRel;
108 break;
109 case 'S': 96 case 'S':
110 pathSegType = PathSegCurveToCubicSmoothAbs; 97 return PathSegCurveToCubicSmoothAbs;
111 break;
112 case 's': 98 case 's':
113 pathSegType = PathSegCurveToCubicSmoothRel; 99 return PathSegCurveToCubicSmoothRel;
114 break;
115 case 'T': 100 case 'T':
116 pathSegType = PathSegCurveToQuadraticSmoothAbs; 101 return PathSegCurveToQuadraticSmoothAbs;
117 break;
118 case 't': 102 case 't':
119 pathSegType = PathSegCurveToQuadraticSmoothRel; 103 return PathSegCurveToQuadraticSmoothRel;
120 break;
121 default: 104 default:
122 pathSegType = PathSegUnknown; 105 return PathSegUnknown;
123 } 106 }
124 return true;
125 } 107 }
126 108
127 bool SVGPathStringSource::parseSVGSegmentType(SVGPathSegType& pathSegType) 109 static bool nextCommandHelper(unsigned lookahead, SVGPathSegType previousCommand , SVGPathSegType& nextCommand)
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>
135 static bool nextCommandHelper(const CharacterType*& current, SVGPathSegType prev iousCommand, SVGPathSegType& nextCommand)
136 { 110 {
137 // Check for remaining coordinates in the current command. 111 // Check for remaining coordinates in the current command.
138 if ((*current == '+' || *current == '-' || *current == '.' || (*current >= ' 0' && *current <= '9')) 112 if ((lookahead == '+' || lookahead == '-' || lookahead == '.' || (lookahead >= '0' && lookahead <= '9'))
139 && previousCommand != PathSegClosePath) { 113 && previousCommand != PathSegClosePath) {
140 if (previousCommand == PathSegMoveToAbs) { 114 if (previousCommand == PathSegMoveToAbs) {
141 nextCommand = PathSegLineToAbs; 115 nextCommand = PathSegLineToAbs;
142 return true; 116 return true;
143 } 117 }
144 if (previousCommand == PathSegMoveToRel) { 118 if (previousCommand == PathSegMoveToRel) {
145 nextCommand = PathSegLineToRel; 119 nextCommand = PathSegLineToRel;
146 return true; 120 return true;
147 } 121 }
148 nextCommand = previousCommand; 122 nextCommand = previousCommand;
149 return true; 123 return true;
150 } 124 }
151
152 return false; 125 return false;
153 } 126 }
154 127
155 SVGPathSegType SVGPathStringSource::nextCommand(SVGPathSegType previousCommand) 128 float SVGPathStringSource::parseNumberWithError()
156 { 129 {
157 SVGPathSegType nextCommand; 130 float numberValue = 0;
158 if (m_is8BitSource) { 131 if (m_is8BitSource)
159 if (nextCommandHelper(m_current.m_character8, previousCommand, nextComma nd)) 132 m_seenError |= !parseNumber(m_current.m_character8, m_end.m_character8, numberValue);
160 return nextCommand; 133 else
134 m_seenError |= !parseNumber(m_current.m_character16, m_end.m_character16 , numberValue);
135 return numberValue;
136 }
137
138 bool SVGPathStringSource::parseArcFlagWithError()
139 {
140 bool flagValue = false;
141 if (m_is8BitSource)
142 m_seenError |= !parseArcFlag(m_current.m_character8, m_end.m_character8, flagValue);
143 else
144 m_seenError |= !parseArcFlag(m_current.m_character16, m_end.m_character1 6, flagValue);
145 return flagValue;
146 }
147
148 SVGPathSegType SVGPathStringSource::peekSegmentType()
149 {
150 ASSERT(hasMoreData());
151 // This won't work in all cases because of the state required to "detect" im plicit commands.
152 unsigned lookahead = m_is8BitSource ? *m_current.m_character8 : *m_current.m _character16;
153 return parseSVGSegmentTypeHelper(lookahead);
154 }
155
156 PathSegmentData SVGPathStringSource::parseSegment()
157 {
158 ASSERT(hasMoreData());
159 PathSegmentData segment;
160 unsigned lookahead = m_is8BitSource ? *m_current.m_character8 : *m_current.m _character16;
161 SVGPathSegType command = parseSVGSegmentTypeHelper(lookahead);
162 if (command == PathSegUnknown) {
163 // Possibly an implicit command. Not allowed if this is the first comman d.
164 if (m_previousCommand == PathSegUnknown)
165 return segment;
166 if (!nextCommandHelper(lookahead, m_previousCommand, command))
167 return segment;
161 } else { 168 } else {
162 if (nextCommandHelper(m_current.m_character16, previousCommand, nextComm and)) 169 // Valid explicit command.
163 return nextCommand; 170 if (m_is8BitSource)
171 m_current.m_character8++;
172 else
173 m_current.m_character16++;
164 } 174 }
165 175
166 parseSVGSegmentType(nextCommand); 176 segment.command = m_previousCommand = command;
167 return nextCommand;
168 }
169 177
170 bool SVGPathStringSource::parseMoveToSegment(FloatPoint& targetPoint) 178 ASSERT(!m_seenError);
171 {
172 if (m_is8BitSource)
173 return parseFloatPoint(m_current.m_character8, m_end.m_character8, targe tPoint);
174 return parseFloatPoint(m_current.m_character16, m_end.m_character16, targetP oint);
175 }
176 179
177 bool SVGPathStringSource::parseLineToSegment(FloatPoint& targetPoint) 180 switch (segment.command) {
178 { 181 case PathSegCurveToCubicRel:
179 if (m_is8BitSource) 182 case PathSegCurveToCubicAbs:
180 return parseFloatPoint(m_current.m_character8, m_end.m_character8, targe tPoint); 183 segment.point1.setX(parseNumberWithError());
181 return parseFloatPoint(m_current.m_character16, m_end.m_character16, targetP oint); 184 segment.point1.setY(parseNumberWithError());
182 } 185 /* fall through */
186 case PathSegCurveToCubicSmoothRel:
187 case PathSegCurveToCubicSmoothAbs:
188 segment.point2.setX(parseNumberWithError());
189 segment.point2.setY(parseNumberWithError());
190 /* fall through */
191 case PathSegMoveToRel:
192 case PathSegMoveToAbs:
193 case PathSegLineToRel:
194 case PathSegLineToAbs:
195 case PathSegCurveToQuadraticSmoothRel:
196 case PathSegCurveToQuadraticSmoothAbs:
197 segment.targetPoint.setX(parseNumberWithError());
198 segment.targetPoint.setY(parseNumberWithError());
199 break;
200 case PathSegLineToHorizontalRel:
201 case PathSegLineToHorizontalAbs:
202 segment.targetPoint.setX(parseNumberWithError());
203 break;
204 case PathSegLineToVerticalRel:
205 case PathSegLineToVerticalAbs:
206 segment.targetPoint.setY(parseNumberWithError());
207 break;
208 case PathSegClosePath:
209 eatWhitespace();
210 break;
211 case PathSegCurveToQuadraticRel:
212 case PathSegCurveToQuadraticAbs:
213 segment.point1.setX(parseNumberWithError());
214 segment.point1.setY(parseNumberWithError());
215 segment.targetPoint.setX(parseNumberWithError());
216 segment.targetPoint.setY(parseNumberWithError());
217 break;
218 case PathSegArcRel:
219 case PathSegArcAbs:
220 segment.point1.setX(parseNumberWithError()); // rx
221 segment.point1.setY(parseNumberWithError()); // ry
222 segment.point2.setX(parseNumberWithError()); // angle
223 segment.arcLarge = parseArcFlagWithError();
224 segment.arcSweep = parseArcFlagWithError();
225 segment.targetPoint.setX(parseNumberWithError());
226 segment.targetPoint.setY(parseNumberWithError());
227 break;
228 case PathSegUnknown:
229 ASSERT_NOT_REACHED();
230 }
183 231
184 bool SVGPathStringSource::parseLineToHorizontalSegment(float& x) 232 if (UNLIKELY(m_seenError))
185 { 233 segment.command = PathSegUnknown;
186 if (m_is8BitSource) 234 return segment;
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
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
198 bool SVGPathStringSource::parseCurveToCubicSegment(FloatPoint& point1, FloatPoin t& point2, FloatPoint& targetPoint)
199 {
200 if (m_is8BitSource)
201 return parseFloatPoint3(m_current.m_character8, m_end.m_character8, poin t1, point2, targetPoint);
202 return parseFloatPoint3(m_current.m_character16, m_end.m_character16, point1 , point2, targetPoint);
203 }
204
205 bool SVGPathStringSource::parseCurveToCubicSmoothSegment(FloatPoint& point1, Flo atPoint& targetPoint)
206 {
207 if (m_is8BitSource)
208 return parseFloatPoint2(m_current.m_character8, m_end.m_character8, poin t1, targetPoint);
209 return parseFloatPoint2(m_current.m_character16, m_end.m_character16, point1 , targetPoint);
210 }
211
212 bool SVGPathStringSource::parseCurveToQuadraticSegment(FloatPoint& point2, Float Point& targetPoint)
213 {
214 if (m_is8BitSource)
215 return parseFloatPoint2(m_current.m_character8, m_end.m_character8, poin t2, targetPoint);
216 return parseFloatPoint2(m_current.m_character16, m_end.m_character16, point2 , targetPoint);
217 }
218
219 bool SVGPathStringSource::parseCurveToQuadraticSmoothSegment(FloatPoint& targetP oint)
220 {
221 if (m_is8BitSource)
222 return parseFloatPoint(m_current.m_character8, m_end.m_character8, targe tPoint);
223 return parseFloatPoint(m_current.m_character16, m_end.m_character16, targetP oint);
224 }
225
226 template <typename CharacterType>
227 static bool parseArcToSegmentHelper(const CharacterType*& current, const Charact erType* end, float& rx, float& ry, float& angle, bool& largeArc, bool& sweep, Fl oatPoint& 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
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_character 8, rx, ry, angle, largeArc, sweep, targetPoint);
247 return parseArcToSegmentHelper(m_current.m_character16, m_end.m_character16, rx, ry, angle, largeArc, sweep, targetPoint);
248 } 235 }
249 236
250 } // namespace blink 237 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/svg/SVGPathStringSource.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698