| 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 |