OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2002, 2003 The Karbon Developers | 2 * Copyright (C) 2002, 2003 The Karbon Developers |
3 * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org> | 3 * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org> |
4 * Copyright (C) 2006, 2007 Rob Buis <buis@kde.org> | 4 * Copyright (C) 2006, 2007 Rob Buis <buis@kde.org> |
5 * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. | 5 * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. |
6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 18 matching lines...) Expand all Loading... |
29 #include "wtf/MathExtras.h" | 29 #include "wtf/MathExtras.h" |
30 | 30 |
31 namespace blink { | 31 namespace blink { |
32 | 32 |
33 DEFINE_TRACE(SVGPathParser) | 33 DEFINE_TRACE(SVGPathParser) |
34 { | 34 { |
35 visitor->trace(m_source); | 35 visitor->trace(m_source); |
36 visitor->trace(m_consumer); | 36 visitor->trace(m_consumer); |
37 } | 37 } |
38 | 38 |
39 void SVGPathParser::parseClosePathSegment() | 39 bool SVGPathParser::initialCommandIsMoveTo() |
40 { | 40 { |
41 // Reset m_currentPoint for the next path. | 41 // If the path is empty it is still valid, so return true. |
42 if (m_pathParsingMode == NormalizedParsing) | 42 if (!m_source->hasMoreData()) |
43 m_currentPoint = m_subPathPoint; | 43 return true; |
44 m_consumer->closePath(); | 44 |
| 45 SVGPathSegType command = m_source->peekSegmentType(); |
| 46 // Path must start with moveTo. |
| 47 return command == PathSegMoveToAbs || command == PathSegMoveToRel; |
45 } | 48 } |
46 | 49 |
47 bool SVGPathParser::parseMoveToSegment() | 50 void SVGPathParser::emitMoveToSegment(PathSegmentData& segment) |
48 { | 51 { |
49 FloatPoint targetPoint; | |
50 if (!m_source->parseMoveToSegment(targetPoint)) | |
51 return false; | |
52 | |
53 if (m_pathParsingMode == UnalteredParsing) { | 52 if (m_pathParsingMode == UnalteredParsing) { |
54 m_consumer->moveTo(targetPoint, m_mode); | 53 m_consumer->moveTo(segment.targetPoint, m_mode); |
55 return true; | 54 return; |
56 } | 55 } |
57 if (m_mode == RelativeCoordinates) | 56 if (m_mode == RelativeCoordinates) |
58 m_currentPoint += targetPoint; | 57 m_currentPoint += segment.targetPoint; |
59 else | 58 else |
60 m_currentPoint = targetPoint; | 59 m_currentPoint = segment.targetPoint; |
61 m_subPathPoint = m_currentPoint; | 60 m_subPathPoint = m_currentPoint; |
62 m_consumer->moveTo(m_currentPoint, AbsoluteCoordinates); | 61 m_consumer->moveTo(m_currentPoint, AbsoluteCoordinates); |
63 return true; | |
64 } | 62 } |
65 | 63 |
66 bool SVGPathParser::parseLineToSegment() | 64 void SVGPathParser::emitLineToSegment(PathSegmentData& segment) |
67 { | 65 { |
68 FloatPoint targetPoint; | |
69 if (!m_source->parseLineToSegment(targetPoint)) | |
70 return false; | |
71 | |
72 if (m_pathParsingMode == UnalteredParsing) { | 66 if (m_pathParsingMode == UnalteredParsing) { |
73 m_consumer->lineTo(targetPoint, m_mode); | 67 m_consumer->lineTo(segment.targetPoint, m_mode); |
74 return true; | 68 return; |
75 } | 69 } |
76 if (m_mode == RelativeCoordinates) | 70 if (m_mode == RelativeCoordinates) |
77 m_currentPoint += targetPoint; | 71 m_currentPoint += segment.targetPoint; |
78 else | 72 else |
79 m_currentPoint = targetPoint; | 73 m_currentPoint = segment.targetPoint; |
80 m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); | 74 m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); |
81 return true; | |
82 } | 75 } |
83 | 76 |
84 bool SVGPathParser::parseLineToHorizontalSegment() | 77 void SVGPathParser::emitLineToHorizontalSegment(PathSegmentData& segment) |
85 { | 78 { |
86 float toX; | |
87 if (!m_source->parseLineToHorizontalSegment(toX)) | |
88 return false; | |
89 | |
90 if (m_pathParsingMode == UnalteredParsing) { | 79 if (m_pathParsingMode == UnalteredParsing) { |
91 m_consumer->lineToHorizontal(toX, m_mode); | 80 m_consumer->lineToHorizontal(segment.targetPoint.x(), m_mode); |
92 return true; | 81 return; |
93 } | 82 } |
94 if (m_mode == RelativeCoordinates) | 83 if (m_mode == RelativeCoordinates) |
95 m_currentPoint.move(toX, 0); | 84 m_currentPoint += segment.targetPoint; |
96 else | 85 else |
97 m_currentPoint.setX(toX); | 86 m_currentPoint.setX(segment.targetPoint.x()); |
98 m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); | 87 m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); |
99 return true; | |
100 } | 88 } |
101 | 89 |
102 bool SVGPathParser::parseLineToVerticalSegment() | 90 void SVGPathParser::emitLineToVerticalSegment(PathSegmentData& segment) |
103 { | 91 { |
104 float toY; | |
105 if (!m_source->parseLineToVerticalSegment(toY)) | |
106 return false; | |
107 | |
108 if (m_pathParsingMode == UnalteredParsing) { | 92 if (m_pathParsingMode == UnalteredParsing) { |
109 m_consumer->lineToVertical(toY, m_mode); | 93 m_consumer->lineToVertical(segment.targetPoint.y(), m_mode); |
110 return true; | 94 return; |
111 } | 95 } |
112 if (m_mode == RelativeCoordinates) | 96 if (m_mode == RelativeCoordinates) |
113 m_currentPoint.move(0, toY); | 97 m_currentPoint += segment.targetPoint; |
114 else | 98 else |
115 m_currentPoint.setY(toY); | 99 m_currentPoint.setY(segment.targetPoint.y()); |
116 m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); | 100 m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); |
117 return true; | |
118 } | 101 } |
119 | 102 |
120 bool SVGPathParser::parseCurveToCubicSegment() | 103 void SVGPathParser::emitCurveToCubicSegment(PathSegmentData& segment) |
121 { | 104 { |
122 FloatPoint point1; | |
123 FloatPoint point2; | |
124 FloatPoint targetPoint; | |
125 if (!m_source->parseCurveToCubicSegment(point1, point2, targetPoint)) | |
126 return false; | |
127 | |
128 if (m_pathParsingMode == UnalteredParsing) { | 105 if (m_pathParsingMode == UnalteredParsing) { |
129 m_consumer->curveToCubic(point1, point2, targetPoint, m_mode); | 106 m_consumer->curveToCubic(segment.point1, segment.point2, segment.targetP
oint, m_mode); |
130 return true; | 107 return; |
131 } | 108 } |
132 if (m_mode == RelativeCoordinates) { | 109 if (m_mode == RelativeCoordinates) { |
133 point1 += m_currentPoint; | 110 segment.point1 += m_currentPoint; |
134 point2 += m_currentPoint; | 111 segment.point2 += m_currentPoint; |
135 targetPoint += m_currentPoint; | 112 segment.targetPoint += m_currentPoint; |
136 } | 113 } |
137 m_consumer->curveToCubic(point1, point2, targetPoint, AbsoluteCoordinates); | 114 m_consumer->curveToCubic(segment.point1, segment.point2, segment.targetPoint
, AbsoluteCoordinates); |
138 | 115 |
139 m_controlPoint = point2; | 116 m_controlPoint = segment.point2; |
140 m_currentPoint = targetPoint; | 117 m_currentPoint = segment.targetPoint; |
141 return true; | |
142 } | 118 } |
143 | 119 |
144 static FloatPoint reflectedPoint(const FloatPoint& reflectIn, const FloatPoint&
pointToReflect) | 120 static FloatPoint reflectedPoint(const FloatPoint& reflectIn, const FloatPoint&
pointToReflect) |
145 { | 121 { |
146 return FloatPoint(2 * reflectIn.x() - pointToReflect.x(), 2 * reflectIn.y()
- pointToReflect.y()); | 122 return FloatPoint(2 * reflectIn.x() - pointToReflect.x(), 2 * reflectIn.y()
- pointToReflect.y()); |
147 } | 123 } |
148 | 124 |
149 bool SVGPathParser::parseCurveToCubicSmoothSegment() | 125 void SVGPathParser::emitCurveToCubicSmoothSegment(PathSegmentData& segment) |
150 { | 126 { |
151 FloatPoint point2; | |
152 FloatPoint targetPoint; | |
153 if (!m_source->parseCurveToCubicSmoothSegment(point2, targetPoint)) | |
154 return false; | |
155 | |
156 if (m_pathParsingMode == UnalteredParsing) { | 127 if (m_pathParsingMode == UnalteredParsing) { |
157 m_consumer->curveToCubicSmooth(point2, targetPoint, m_mode); | 128 m_consumer->curveToCubicSmooth(segment.point2, segment.targetPoint, m_mo
de); |
158 return true; | 129 return; |
159 } | 130 } |
160 if (m_lastCommand != PathSegCurveToCubicAbs | 131 if (m_lastCommand != PathSegCurveToCubicAbs |
161 && m_lastCommand != PathSegCurveToCubicRel | 132 && m_lastCommand != PathSegCurveToCubicRel |
162 && m_lastCommand != PathSegCurveToCubicSmoothAbs | 133 && m_lastCommand != PathSegCurveToCubicSmoothAbs |
163 && m_lastCommand != PathSegCurveToCubicSmoothRel) | 134 && m_lastCommand != PathSegCurveToCubicSmoothRel) |
164 m_controlPoint = m_currentPoint; | 135 m_controlPoint = m_currentPoint; |
165 | 136 |
166 FloatPoint point1 = reflectedPoint(m_currentPoint, m_controlPoint); | 137 FloatPoint point1 = reflectedPoint(m_currentPoint, m_controlPoint); |
167 if (m_mode == RelativeCoordinates) { | 138 if (m_mode == RelativeCoordinates) { |
168 point2 += m_currentPoint; | 139 segment.point2 += m_currentPoint; |
169 targetPoint += m_currentPoint; | 140 segment.targetPoint += m_currentPoint; |
170 } | 141 } |
171 | 142 |
172 m_consumer->curveToCubic(point1, point2, targetPoint, AbsoluteCoordinates); | 143 m_consumer->curveToCubic(point1, segment.point2, segment.targetPoint, Absolu
teCoordinates); |
173 | 144 |
174 m_controlPoint = point2; | 145 m_controlPoint = segment.point2; |
175 m_currentPoint = targetPoint; | 146 m_currentPoint = segment.targetPoint; |
176 return true; | |
177 } | 147 } |
178 | 148 |
179 // Blend the points with a ratio (1/3):(2/3). | 149 // Blend the points with a ratio (1/3):(2/3). |
180 static FloatPoint blendPoints(const FloatPoint& p1, const FloatPoint& p2) | 150 static FloatPoint blendPoints(const FloatPoint& p1, const FloatPoint& p2) |
181 { | 151 { |
182 const float oneOverThree = 1 / 3.f; | 152 const float oneOverThree = 1 / 3.f; |
183 return FloatPoint((p1.x() + 2 * p2.x()) * oneOverThree, (p1.y() + 2 * p2.y()
) * oneOverThree); | 153 return FloatPoint((p1.x() + 2 * p2.x()) * oneOverThree, (p1.y() + 2 * p2.y()
) * oneOverThree); |
184 } | 154 } |
185 | 155 |
186 bool SVGPathParser::parseCurveToQuadraticSegment() | 156 void SVGPathParser::emitCurveToQuadraticSegment(PathSegmentData& segment) |
187 { | 157 { |
188 FloatPoint point1; | |
189 FloatPoint targetPoint; | |
190 if (!m_source->parseCurveToQuadraticSegment(point1, targetPoint)) | |
191 return false; | |
192 | |
193 if (m_pathParsingMode == UnalteredParsing) { | 158 if (m_pathParsingMode == UnalteredParsing) { |
194 m_consumer->curveToQuadratic(point1, targetPoint, m_mode); | 159 m_consumer->curveToQuadratic(segment.point1, segment.targetPoint, m_mode
); |
195 return true; | 160 return; |
196 } | 161 } |
197 m_controlPoint = point1; | 162 m_controlPoint = segment.point1; |
198 | 163 |
199 if (m_mode == RelativeCoordinates) { | 164 if (m_mode == RelativeCoordinates) { |
200 m_controlPoint += m_currentPoint; | 165 m_controlPoint += m_currentPoint; |
201 targetPoint += m_currentPoint; | 166 segment.targetPoint += m_currentPoint; |
202 } | 167 } |
203 point1 = blendPoints(m_currentPoint, m_controlPoint); | 168 segment.point1 = blendPoints(m_currentPoint, m_controlPoint); |
204 FloatPoint point2 = blendPoints(targetPoint, m_controlPoint); | 169 FloatPoint point2 = blendPoints(segment.targetPoint, m_controlPoint); |
205 | 170 |
206 m_consumer->curveToCubic(point1, point2, targetPoint, AbsoluteCoordinates); | 171 m_consumer->curveToCubic(segment.point1, point2, segment.targetPoint, Absolu
teCoordinates); |
207 | 172 |
208 m_currentPoint = targetPoint; | 173 m_currentPoint = segment.targetPoint; |
209 return true; | |
210 } | 174 } |
211 | 175 |
212 bool SVGPathParser::parseCurveToQuadraticSmoothSegment() | 176 void SVGPathParser::emitCurveToQuadraticSmoothSegment(PathSegmentData& segment) |
213 { | 177 { |
214 FloatPoint targetPoint; | |
215 if (!m_source->parseCurveToQuadraticSmoothSegment(targetPoint)) | |
216 return false; | |
217 | |
218 if (m_pathParsingMode == UnalteredParsing) { | 178 if (m_pathParsingMode == UnalteredParsing) { |
219 m_consumer->curveToQuadraticSmooth(targetPoint, m_mode); | 179 m_consumer->curveToQuadraticSmooth(segment.targetPoint, m_mode); |
220 return true; | 180 return; |
221 } | 181 } |
222 if (m_lastCommand != PathSegCurveToQuadraticAbs | 182 if (m_lastCommand != PathSegCurveToQuadraticAbs |
223 && m_lastCommand != PathSegCurveToQuadraticRel | 183 && m_lastCommand != PathSegCurveToQuadraticRel |
224 && m_lastCommand != PathSegCurveToQuadraticSmoothAbs | 184 && m_lastCommand != PathSegCurveToQuadraticSmoothAbs |
225 && m_lastCommand != PathSegCurveToQuadraticSmoothRel) | 185 && m_lastCommand != PathSegCurveToQuadraticSmoothRel) |
226 m_controlPoint = m_currentPoint; | 186 m_controlPoint = m_currentPoint; |
227 | 187 |
228 if (m_mode == RelativeCoordinates) | 188 if (m_mode == RelativeCoordinates) |
229 targetPoint += m_currentPoint; | 189 segment.targetPoint += m_currentPoint; |
230 | 190 |
231 m_controlPoint = reflectedPoint(m_currentPoint, m_controlPoint); | 191 m_controlPoint = reflectedPoint(m_currentPoint, m_controlPoint); |
232 FloatPoint point1 = blendPoints(m_currentPoint, m_controlPoint); | 192 FloatPoint point1 = blendPoints(m_currentPoint, m_controlPoint); |
233 FloatPoint point2 = blendPoints(targetPoint, m_controlPoint); | 193 FloatPoint point2 = blendPoints(segment.targetPoint, m_controlPoint); |
234 | 194 |
235 m_consumer->curveToCubic(point1, point2, targetPoint, AbsoluteCoordinates); | 195 m_consumer->curveToCubic(point1, point2, segment.targetPoint, AbsoluteCoordi
nates); |
236 | 196 |
237 m_currentPoint = targetPoint; | 197 m_currentPoint = segment.targetPoint; |
238 return true; | |
239 } | 198 } |
240 | 199 |
241 bool SVGPathParser::parseArcToSegment() | 200 void SVGPathParser::emitArcToSegment(PathSegmentData& segment) |
242 { | 201 { |
243 float rx; | |
244 float ry; | |
245 float angle; | |
246 bool largeArc; | |
247 bool sweep; | |
248 FloatPoint targetPoint; | |
249 if (!m_source->parseArcToSegment(rx, ry, angle, largeArc, sweep, targetPoint
)) | |
250 return false; | |
251 | |
252 if (m_pathParsingMode == UnalteredParsing) { | 202 if (m_pathParsingMode == UnalteredParsing) { |
253 m_consumer->arcTo(rx, ry, angle, largeArc, sweep, targetPoint, m_mode); | 203 m_consumer->arcTo(segment.arcRadii().x(), segment.arcRadii().y(), segmen
t.arcAngle(), segment.arcLarge, segment.arcSweep, segment.targetPoint, m_mode); |
254 return true; | 204 return; |
255 } | 205 } |
256 | 206 |
257 // If rx = 0 or ry = 0 then this arc is treated as a straight line segment (
a "lineto") joining the endpoints. | 207 // If rx = 0 or ry = 0 then this arc is treated as a straight line segment (
a "lineto") joining the endpoints. |
258 // http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters | 208 // http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters |
259 // If the current point and target point for the arc are identical, it shoul
d be treated as a zero length | 209 // If the current point and target point for the arc are identical, it shoul
d be treated as a zero length |
260 // path. This ensures continuity in animations. | 210 // path. This ensures continuity in animations. |
261 rx = fabsf(rx); | 211 float rx = fabsf(segment.arcRadii().x()); |
262 ry = fabsf(ry); | 212 float ry = fabsf(segment.arcRadii().y()); |
263 | 213 |
264 if (m_mode == RelativeCoordinates) | 214 if (m_mode == RelativeCoordinates) |
265 targetPoint += m_currentPoint; | 215 segment.targetPoint += m_currentPoint; |
266 | 216 |
267 if (!rx || !ry || targetPoint == m_currentPoint) { | 217 if (!rx || !ry || segment.targetPoint == m_currentPoint) { |
268 m_consumer->lineTo(targetPoint, AbsoluteCoordinates); | 218 m_consumer->lineTo(segment.targetPoint, AbsoluteCoordinates); |
269 m_currentPoint = targetPoint; | 219 m_currentPoint = segment.targetPoint; |
270 return true; | 220 return; |
271 } | 221 } |
272 | 222 |
| 223 float angle = segment.arcAngle(); |
273 FloatPoint point1 = m_currentPoint; | 224 FloatPoint point1 = m_currentPoint; |
274 m_currentPoint = targetPoint; | 225 m_currentPoint = segment.targetPoint; |
275 return decomposeArcToCubic(angle, rx, ry, point1, targetPoint, largeArc, swe
ep); | 226 if (!decomposeArcToCubic(angle, rx, ry, point1, segment.targetPoint, segment
.arcLarge, segment.arcSweep)) |
| 227 m_consumer->lineTo(segment.targetPoint, AbsoluteCoordinates); |
276 } | 228 } |
277 | 229 |
278 bool SVGPathParser::parsePathDataFromSource(PathParsingMode pathParsingMode, boo
l checkForInitialMoveTo) | 230 bool SVGPathParser::parsePathDataFromSource(PathParsingMode pathParsingMode, boo
l checkForInitialMoveTo) |
279 { | 231 { |
280 ASSERT(m_source); | 232 ASSERT(m_source); |
281 ASSERT(m_consumer); | 233 ASSERT(m_consumer); |
282 | 234 |
283 m_pathParsingMode = pathParsingMode; | 235 m_pathParsingMode = pathParsingMode; |
284 | 236 |
285 m_controlPoint = FloatPoint(); | 237 m_controlPoint = FloatPoint(); |
286 m_currentPoint = FloatPoint(); | 238 m_currentPoint = FloatPoint(); |
287 m_subPathPoint = FloatPoint(); | 239 m_subPathPoint = FloatPoint(); |
288 | 240 |
289 // Skip any leading spaces. | 241 if (checkForInitialMoveTo && !initialCommandIsMoveTo()) |
290 if (!m_source->moveToNextToken()) | |
291 return true; | |
292 | |
293 SVGPathSegType command; | |
294 m_source->parseSVGSegmentType(command); | |
295 m_lastCommand = PathSegUnknown; | |
296 | |
297 // Path must start with moveto. | |
298 if (checkForInitialMoveTo && command != PathSegMoveToAbs && command != PathS
egMoveToRel) | |
299 return false; | 242 return false; |
300 | 243 |
301 while (true) { | 244 m_lastCommand = PathSegUnknown; |
302 // Skip spaces between command and first coordinate. | 245 while (m_source->hasMoreData()) { |
303 m_source->moveToNextToken(); | 246 PathSegmentData segment = m_source->parseSegment(); |
| 247 if (segment.command == PathSegUnknown) |
| 248 return false; |
| 249 |
304 m_mode = AbsoluteCoordinates; | 250 m_mode = AbsoluteCoordinates; |
305 switch (command) { | 251 |
| 252 switch (segment.command) { |
306 case PathSegMoveToRel: | 253 case PathSegMoveToRel: |
307 m_mode = RelativeCoordinates; | 254 m_mode = RelativeCoordinates; |
308 case PathSegMoveToAbs: | 255 case PathSegMoveToAbs: |
309 if (!parseMoveToSegment()) | 256 emitMoveToSegment(segment); |
310 return false; | |
311 break; | 257 break; |
312 case PathSegLineToRel: | 258 case PathSegLineToRel: |
313 m_mode = RelativeCoordinates; | 259 m_mode = RelativeCoordinates; |
314 case PathSegLineToAbs: | 260 case PathSegLineToAbs: |
315 if (!parseLineToSegment()) | 261 emitLineToSegment(segment); |
316 return false; | |
317 break; | 262 break; |
318 case PathSegLineToHorizontalRel: | 263 case PathSegLineToHorizontalRel: |
319 m_mode = RelativeCoordinates; | 264 m_mode = RelativeCoordinates; |
320 case PathSegLineToHorizontalAbs: | 265 case PathSegLineToHorizontalAbs: |
321 if (!parseLineToHorizontalSegment()) | 266 emitLineToHorizontalSegment(segment); |
322 return false; | |
323 break; | 267 break; |
324 case PathSegLineToVerticalRel: | 268 case PathSegLineToVerticalRel: |
325 m_mode = RelativeCoordinates; | 269 m_mode = RelativeCoordinates; |
326 case PathSegLineToVerticalAbs: | 270 case PathSegLineToVerticalAbs: |
327 if (!parseLineToVerticalSegment()) | 271 emitLineToVerticalSegment(segment); |
328 return false; | |
329 break; | 272 break; |
330 case PathSegClosePath: | 273 case PathSegClosePath: |
331 parseClosePathSegment(); | 274 m_consumer->closePath(); |
| 275 // Reset m_currentPoint for the next path. |
| 276 if (m_pathParsingMode == NormalizedParsing) |
| 277 m_currentPoint = m_subPathPoint; |
332 break; | 278 break; |
333 case PathSegCurveToCubicRel: | 279 case PathSegCurveToCubicRel: |
334 m_mode = RelativeCoordinates; | 280 m_mode = RelativeCoordinates; |
335 case PathSegCurveToCubicAbs: | 281 case PathSegCurveToCubicAbs: |
336 if (!parseCurveToCubicSegment()) | 282 emitCurveToCubicSegment(segment); |
337 return false; | |
338 break; | 283 break; |
339 case PathSegCurveToCubicSmoothRel: | 284 case PathSegCurveToCubicSmoothRel: |
340 m_mode = RelativeCoordinates; | 285 m_mode = RelativeCoordinates; |
341 case PathSegCurveToCubicSmoothAbs: | 286 case PathSegCurveToCubicSmoothAbs: |
342 if (!parseCurveToCubicSmoothSegment()) | 287 emitCurveToCubicSmoothSegment(segment); |
343 return false; | |
344 break; | 288 break; |
345 case PathSegCurveToQuadraticRel: | 289 case PathSegCurveToQuadraticRel: |
346 m_mode = RelativeCoordinates; | 290 m_mode = RelativeCoordinates; |
347 case PathSegCurveToQuadraticAbs: | 291 case PathSegCurveToQuadraticAbs: |
348 if (!parseCurveToQuadraticSegment()) | 292 emitCurveToQuadraticSegment(segment); |
349 return false; | |
350 break; | 293 break; |
351 case PathSegCurveToQuadraticSmoothRel: | 294 case PathSegCurveToQuadraticSmoothRel: |
352 m_mode = RelativeCoordinates; | 295 m_mode = RelativeCoordinates; |
353 case PathSegCurveToQuadraticSmoothAbs: | 296 case PathSegCurveToQuadraticSmoothAbs: |
354 if (!parseCurveToQuadraticSmoothSegment()) | 297 emitCurveToQuadraticSmoothSegment(segment); |
355 return false; | |
356 break; | 298 break; |
357 case PathSegArcRel: | 299 case PathSegArcRel: |
358 m_mode = RelativeCoordinates; | 300 m_mode = RelativeCoordinates; |
359 case PathSegArcAbs: | 301 case PathSegArcAbs: |
360 if (!parseArcToSegment()) | 302 emitArcToSegment(segment); |
361 return false; | |
362 break; | 303 break; |
363 default: | 304 default: |
364 return false; | 305 ASSERT_NOT_REACHED(); |
365 } | 306 } |
366 if (!m_consumer->continueConsuming()) | 307 if (!m_consumer->continueConsuming()) |
367 return true; | 308 return true; |
368 | 309 |
369 m_lastCommand = command; | 310 m_lastCommand = segment.command; |
370 | |
371 if (!m_source->hasMoreData()) | |
372 return true; | |
373 | |
374 command = m_source->nextCommand(command); | |
375 | 311 |
376 if (m_lastCommand != PathSegCurveToCubicAbs | 312 if (m_lastCommand != PathSegCurveToCubicAbs |
377 && m_lastCommand != PathSegCurveToCubicRel | 313 && m_lastCommand != PathSegCurveToCubicRel |
378 && m_lastCommand != PathSegCurveToCubicSmoothAbs | 314 && m_lastCommand != PathSegCurveToCubicSmoothAbs |
379 && m_lastCommand != PathSegCurveToCubicSmoothRel | 315 && m_lastCommand != PathSegCurveToCubicSmoothRel |
380 && m_lastCommand != PathSegCurveToQuadraticAbs | 316 && m_lastCommand != PathSegCurveToQuadraticAbs |
381 && m_lastCommand != PathSegCurveToQuadraticRel | 317 && m_lastCommand != PathSegCurveToQuadraticRel |
382 && m_lastCommand != PathSegCurveToQuadraticSmoothAbs | 318 && m_lastCommand != PathSegCurveToQuadraticSmoothAbs |
383 && m_lastCommand != PathSegCurveToQuadraticSmoothRel) | 319 && m_lastCommand != PathSegCurveToQuadraticSmoothRel) |
384 m_controlPoint = m_currentPoint; | 320 m_controlPoint = m_currentPoint; |
385 | 321 |
386 m_consumer->incrementPathSegmentCount(); | 322 if (m_source->hasMoreData()) |
| 323 m_consumer->incrementPathSegmentCount(); |
387 } | 324 } |
388 | 325 return true; |
389 return false; | |
390 } | 326 } |
391 | 327 |
392 // This works by converting the SVG arc to "simple" beziers. | 328 // This works by converting the SVG arc to "simple" beziers. |
393 // Partly adapted from Niko's code in kdelibs/kdecore/svgicons. | 329 // Partly adapted from Niko's code in kdelibs/kdecore/svgicons. |
394 // See also SVG implementation notes: http://www.w3.org/TR/SVG/implnote.html#Arc
ConversionEndpointToCenter | 330 // See also SVG implementation notes: http://www.w3.org/TR/SVG/implnote.html#Arc
ConversionEndpointToCenter |
395 bool SVGPathParser::decomposeArcToCubic(float angle, float rx, float ry, const F
loatPoint& start, const FloatPoint& end, bool largeArcFlag, bool sweepFlag) | 331 bool SVGPathParser::decomposeArcToCubic(float angle, float rx, float ry, const F
loatPoint& start, const FloatPoint& end, bool largeArcFlag, bool sweepFlag) |
396 { | 332 { |
397 FloatSize midPointDistance = start - end; | 333 FloatSize midPointDistance = start - end; |
398 midPointDistance.scale(0.5f); | 334 midPointDistance.scale(0.5f); |
399 | 335 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 point2 = targetPoint; | 405 point2 = targetPoint; |
470 point2.move(t * sinEndTheta, -t * cosEndTheta); | 406 point2.move(t * sinEndTheta, -t * cosEndTheta); |
471 | 407 |
472 m_consumer->curveToCubic(pointTransform.mapPoint(point1), pointTransform
.mapPoint(point2), | 408 m_consumer->curveToCubic(pointTransform.mapPoint(point1), pointTransform
.mapPoint(point2), |
473 pointTransform.mapPoint(targetPoint), AbsoluteC
oordinates); | 409 pointTransform.mapPoint(targetPoint), AbsoluteC
oordinates); |
474 } | 410 } |
475 return true; | 411 return true; |
476 } | 412 } |
477 | 413 |
478 } | 414 } |
OLD | NEW |