| 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 29 matching lines...) Expand all Loading... |
| 40 { | 40 { |
| 41 // If the path is empty it is still valid, so return true. | 41 // If the path is empty it is still valid, so return true. |
| 42 if (!m_source->hasMoreData()) | 42 if (!m_source->hasMoreData()) |
| 43 return true; | 43 return true; |
| 44 | 44 |
| 45 SVGPathSegType command = m_source->peekSegmentType(); | 45 SVGPathSegType command = m_source->peekSegmentType(); |
| 46 // Path must start with moveTo. | 46 // Path must start with moveTo. |
| 47 return command == PathSegMoveToAbs || command == PathSegMoveToRel; | 47 return command == PathSegMoveToAbs || command == PathSegMoveToRel; |
| 48 } | 48 } |
| 49 | 49 |
| 50 void SVGPathParser::emitMoveToSegment(PathSegmentData& segment) | |
| 51 { | |
| 52 if (m_mode == RelativeCoordinates) | |
| 53 m_currentPoint += segment.targetPoint; | |
| 54 else | |
| 55 m_currentPoint = segment.targetPoint; | |
| 56 m_subPathPoint = m_currentPoint; | |
| 57 m_consumer->moveTo(m_currentPoint, AbsoluteCoordinates); | |
| 58 } | |
| 59 | 50 |
| 60 void SVGPathParser::emitLineToSegment(PathSegmentData& segment) | 51 class NormalizingConsumer { |
| 61 { | 52 STACK_ALLOCATED(); |
| 62 if (m_mode == RelativeCoordinates) | 53 public: |
| 63 m_currentPoint += segment.targetPoint; | 54 NormalizingConsumer(SVGPathConsumer* consumer) |
| 64 else | 55 : m_consumer(consumer) |
| 65 m_currentPoint = segment.targetPoint; | 56 , m_lastCommand(PathSegUnknown) |
| 66 m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); | 57 { |
| 67 } | 58 ASSERT(m_consumer); |
| 59 } |
| 68 | 60 |
| 69 void SVGPathParser::emitLineToHorizontalSegment(PathSegmentData& segment) | 61 void emitSegment(PathSegmentData&); |
| 70 { | |
| 71 if (m_mode == RelativeCoordinates) | |
| 72 m_currentPoint += segment.targetPoint; | |
| 73 else | |
| 74 m_currentPoint.setX(segment.targetPoint.x()); | |
| 75 m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); | |
| 76 } | |
| 77 | 62 |
| 78 void SVGPathParser::emitLineToVerticalSegment(PathSegmentData& segment) | 63 private: |
| 79 { | 64 bool decomposeArcToCubic(const FloatPoint& currentPoint, const PathSegmentDa
ta&); |
| 80 if (m_mode == RelativeCoordinates) | |
| 81 m_currentPoint += segment.targetPoint; | |
| 82 else | |
| 83 m_currentPoint.setY(segment.targetPoint.y()); | |
| 84 m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); | |
| 85 } | |
| 86 | 65 |
| 87 void SVGPathParser::emitCurveToCubicSegment(PathSegmentData& segment) | 66 RawPtrWillBeMember<SVGPathConsumer> m_consumer; |
| 88 { | 67 FloatPoint m_controlPoint; |
| 89 if (m_mode == RelativeCoordinates) { | 68 FloatPoint m_currentPoint; |
| 90 segment.point1 += m_currentPoint; | 69 FloatPoint m_subPathPoint; |
| 91 segment.point2 += m_currentPoint; | 70 SVGPathSegType m_lastCommand; |
| 92 segment.targetPoint += m_currentPoint; | 71 }; |
| 93 } | |
| 94 m_consumer->curveToCubic(segment.point1, segment.point2, segment.targetPoint
, AbsoluteCoordinates); | |
| 95 | |
| 96 m_controlPoint = segment.point2; | |
| 97 m_currentPoint = segment.targetPoint; | |
| 98 } | |
| 99 | 72 |
| 100 static FloatPoint reflectedPoint(const FloatPoint& reflectIn, const FloatPoint&
pointToReflect) | 73 static FloatPoint reflectedPoint(const FloatPoint& reflectIn, const FloatPoint&
pointToReflect) |
| 101 { | 74 { |
| 102 return FloatPoint(2 * reflectIn.x() - pointToReflect.x(), 2 * reflectIn.y()
- pointToReflect.y()); | 75 return FloatPoint(2 * reflectIn.x() - pointToReflect.x(), 2 * reflectIn.y()
- pointToReflect.y()); |
| 103 } | 76 } |
| 104 | 77 |
| 105 void SVGPathParser::emitCurveToCubicSmoothSegment(PathSegmentData& segment) | |
| 106 { | |
| 107 if (m_lastCommand != PathSegCurveToCubicAbs | |
| 108 && m_lastCommand != PathSegCurveToCubicRel | |
| 109 && m_lastCommand != PathSegCurveToCubicSmoothAbs | |
| 110 && m_lastCommand != PathSegCurveToCubicSmoothRel) | |
| 111 m_controlPoint = m_currentPoint; | |
| 112 | |
| 113 FloatPoint point1 = reflectedPoint(m_currentPoint, m_controlPoint); | |
| 114 if (m_mode == RelativeCoordinates) { | |
| 115 segment.point2 += m_currentPoint; | |
| 116 segment.targetPoint += m_currentPoint; | |
| 117 } | |
| 118 | |
| 119 m_consumer->curveToCubic(point1, segment.point2, segment.targetPoint, Absolu
teCoordinates); | |
| 120 | |
| 121 m_controlPoint = segment.point2; | |
| 122 m_currentPoint = segment.targetPoint; | |
| 123 } | |
| 124 | |
| 125 // Blend the points with a ratio (1/3):(2/3). | 78 // Blend the points with a ratio (1/3):(2/3). |
| 126 static FloatPoint blendPoints(const FloatPoint& p1, const FloatPoint& p2) | 79 static FloatPoint blendPoints(const FloatPoint& p1, const FloatPoint& p2) |
| 127 { | 80 { |
| 128 const float oneOverThree = 1 / 3.f; | 81 const float oneOverThree = 1 / 3.f; |
| 129 return FloatPoint((p1.x() + 2 * p2.x()) * oneOverThree, (p1.y() + 2 * p2.y()
) * oneOverThree); | 82 return FloatPoint((p1.x() + 2 * p2.x()) * oneOverThree, (p1.y() + 2 * p2.y()
) * oneOverThree); |
| 130 } | 83 } |
| 131 | 84 |
| 132 void SVGPathParser::emitCurveToQuadraticSegment(PathSegmentData& segment) | 85 static inline bool isCubicCommand(SVGPathSegType command) |
| 133 { | 86 { |
| 134 m_controlPoint = segment.point1; | 87 return command == PathSegCurveToCubicAbs |
| 88 || command == PathSegCurveToCubicRel |
| 89 || command == PathSegCurveToCubicSmoothAbs |
| 90 || command == PathSegCurveToCubicSmoothRel; |
| 91 } |
| 135 | 92 |
| 136 if (m_mode == RelativeCoordinates) { | 93 static inline bool isQuadraticCommand(SVGPathSegType command) |
| 137 m_controlPoint += m_currentPoint; | 94 { |
| 95 return command == PathSegCurveToQuadraticAbs |
| 96 || command == PathSegCurveToQuadraticRel |
| 97 || command == PathSegCurveToQuadraticSmoothAbs |
| 98 || command == PathSegCurveToQuadraticSmoothRel; |
| 99 } |
| 100 |
| 101 void NormalizingConsumer::emitSegment(PathSegmentData& segment) |
| 102 { |
| 103 SVGPathSegType originalCommand = segment.command; |
| 104 |
| 105 // Convert relative points to absolute points. |
| 106 switch (segment.command) { |
| 107 case PathSegCurveToQuadraticRel: |
| 108 segment.point1 += m_currentPoint; |
| 138 segment.targetPoint += m_currentPoint; | 109 segment.targetPoint += m_currentPoint; |
| 110 break; |
| 111 case PathSegCurveToCubicRel: |
| 112 segment.point1 += m_currentPoint; |
| 113 /* fall through */ |
| 114 case PathSegCurveToCubicSmoothRel: |
| 115 segment.point2 += m_currentPoint; |
| 116 /* fall through */ |
| 117 case PathSegMoveToRel: |
| 118 case PathSegLineToRel: |
| 119 case PathSegLineToHorizontalRel: |
| 120 case PathSegLineToVerticalRel: |
| 121 case PathSegCurveToQuadraticSmoothRel: |
| 122 case PathSegArcRel: |
| 123 segment.targetPoint += m_currentPoint; |
| 124 break; |
| 125 case PathSegLineToHorizontalAbs: |
| 126 segment.targetPoint.setY(m_currentPoint.y()); |
| 127 break; |
| 128 case PathSegLineToVerticalAbs: |
| 129 segment.targetPoint.setX(m_currentPoint.x()); |
| 130 break; |
| 131 case PathSegClosePath: |
| 132 // Reset m_currentPoint for the next path. |
| 133 segment.targetPoint = m_subPathPoint; |
| 134 break; |
| 135 default: |
| 136 break; |
| 139 } | 137 } |
| 140 segment.point1 = blendPoints(m_currentPoint, m_controlPoint); | |
| 141 FloatPoint point2 = blendPoints(segment.targetPoint, m_controlPoint); | |
| 142 | 138 |
| 143 m_consumer->curveToCubic(segment.point1, point2, segment.targetPoint, Absolu
teCoordinates); | 139 // Update command verb, handle smooth segments and convert quadratic curve |
| 140 // segments to cubics. |
| 141 switch (segment.command) { |
| 142 case PathSegMoveToRel: |
| 143 case PathSegMoveToAbs: |
| 144 m_subPathPoint = segment.targetPoint; |
| 145 segment.command = PathSegMoveToAbs; |
| 146 break; |
| 147 case PathSegLineToRel: |
| 148 case PathSegLineToAbs: |
| 149 case PathSegLineToHorizontalRel: |
| 150 case PathSegLineToHorizontalAbs: |
| 151 case PathSegLineToVerticalRel: |
| 152 case PathSegLineToVerticalAbs: |
| 153 segment.command = PathSegLineToAbs; |
| 154 break; |
| 155 case PathSegClosePath: |
| 156 break; |
| 157 case PathSegCurveToCubicSmoothRel: |
| 158 case PathSegCurveToCubicSmoothAbs: |
| 159 if (!isCubicCommand(m_lastCommand)) |
| 160 segment.point1 = m_currentPoint; |
| 161 else |
| 162 segment.point1 = reflectedPoint(m_currentPoint, m_controlPoint); |
| 163 /* fall through */ |
| 164 case PathSegCurveToCubicRel: |
| 165 case PathSegCurveToCubicAbs: |
| 166 m_controlPoint = segment.point2; |
| 167 segment.command = PathSegCurveToCubicAbs; |
| 168 break; |
| 169 case PathSegCurveToQuadraticSmoothRel: |
| 170 case PathSegCurveToQuadraticSmoothAbs: |
| 171 if (!isQuadraticCommand(m_lastCommand)) |
| 172 segment.point1 = m_currentPoint; |
| 173 else |
| 174 segment.point1 = reflectedPoint(m_currentPoint, m_controlPoint); |
| 175 /* fall through */ |
| 176 case PathSegCurveToQuadraticRel: |
| 177 case PathSegCurveToQuadraticAbs: |
| 178 // Save the unmodified control point. |
| 179 m_controlPoint = segment.point1; |
| 180 segment.point1 = blendPoints(m_currentPoint, m_controlPoint); |
| 181 segment.point2 = blendPoints(segment.targetPoint, m_controlPoint); |
| 182 segment.command = PathSegCurveToCubicAbs; |
| 183 break; |
| 184 case PathSegArcRel: |
| 185 case PathSegArcAbs: |
| 186 if (!decomposeArcToCubic(m_currentPoint, segment)) { |
| 187 // On failure, emit a line segment to the target point. |
| 188 segment.command = PathSegLineToAbs; |
| 189 } else { |
| 190 // decomposeArcToCubic() has already emitted the normalized |
| 191 // segments, so set command to PathSegArcAbs, to skip any further |
| 192 // emit. |
| 193 segment.command = PathSegArcAbs; |
| 194 } |
| 195 break; |
| 196 default: |
| 197 ASSERT_NOT_REACHED(); |
| 198 } |
| 199 |
| 200 switch (segment.command) { |
| 201 case PathSegMoveToAbs: |
| 202 m_consumer->moveTo(segment.targetPoint, AbsoluteCoordinates); |
| 203 break; |
| 204 case PathSegLineToAbs: |
| 205 m_consumer->lineTo(segment.targetPoint, AbsoluteCoordinates); |
| 206 break; |
| 207 case PathSegClosePath: |
| 208 m_consumer->closePath(); |
| 209 break; |
| 210 case PathSegCurveToCubicAbs: |
| 211 m_consumer->curveToCubic(segment.point1, segment.point2, segment.targetP
oint, AbsoluteCoordinates); |
| 212 break; |
| 213 case PathSegArcAbs: |
| 214 break; |
| 215 default: |
| 216 ASSERT_NOT_REACHED(); |
| 217 } |
| 144 | 218 |
| 145 m_currentPoint = segment.targetPoint; | 219 m_currentPoint = segment.targetPoint; |
| 146 } | |
| 147 | 220 |
| 148 void SVGPathParser::emitCurveToQuadraticSmoothSegment(PathSegmentData& segment) | 221 if (!isCubicCommand(originalCommand) && !isQuadraticCommand(originalCommand)
) |
| 149 { | |
| 150 if (m_lastCommand != PathSegCurveToQuadraticAbs | |
| 151 && m_lastCommand != PathSegCurveToQuadraticRel | |
| 152 && m_lastCommand != PathSegCurveToQuadraticSmoothAbs | |
| 153 && m_lastCommand != PathSegCurveToQuadraticSmoothRel) | |
| 154 m_controlPoint = m_currentPoint; | 222 m_controlPoint = m_currentPoint; |
| 155 | 223 |
| 156 if (m_mode == RelativeCoordinates) | 224 m_lastCommand = originalCommand; |
| 157 segment.targetPoint += m_currentPoint; | |
| 158 | |
| 159 m_controlPoint = reflectedPoint(m_currentPoint, m_controlPoint); | |
| 160 FloatPoint point1 = blendPoints(m_currentPoint, m_controlPoint); | |
| 161 FloatPoint point2 = blendPoints(segment.targetPoint, m_controlPoint); | |
| 162 | |
| 163 m_consumer->curveToCubic(point1, point2, segment.targetPoint, AbsoluteCoordi
nates); | |
| 164 | |
| 165 m_currentPoint = segment.targetPoint; | |
| 166 } | |
| 167 | |
| 168 void SVGPathParser::emitArcToSegment(PathSegmentData& segment) | |
| 169 { | |
| 170 if (m_mode == RelativeCoordinates) | |
| 171 segment.targetPoint += m_currentPoint; | |
| 172 | |
| 173 if (!decomposeArcToCubic(m_currentPoint, segment)) | |
| 174 m_consumer->lineTo(segment.targetPoint, AbsoluteCoordinates); | |
| 175 m_currentPoint = segment.targetPoint; | |
| 176 } | 225 } |
| 177 | 226 |
| 178 bool SVGPathParser::parsePathDataFromSource(PathParsingMode pathParsingMode, boo
l checkForInitialMoveTo) | 227 bool SVGPathParser::parsePathDataFromSource(PathParsingMode pathParsingMode, boo
l checkForInitialMoveTo) |
| 179 { | 228 { |
| 180 ASSERT(m_source); | 229 ASSERT(m_source); |
| 181 ASSERT(m_consumer); | 230 ASSERT(m_consumer); |
| 182 | 231 |
| 183 m_controlPoint = FloatPoint(); | |
| 184 m_currentPoint = FloatPoint(); | |
| 185 m_subPathPoint = FloatPoint(); | |
| 186 | |
| 187 if (checkForInitialMoveTo && !initialCommandIsMoveTo()) | 232 if (checkForInitialMoveTo && !initialCommandIsMoveTo()) |
| 188 return false; | 233 return false; |
| 189 | 234 |
| 190 m_lastCommand = PathSegUnknown; | 235 NormalizingConsumer normalizer(m_consumer); |
| 236 |
| 191 while (m_source->hasMoreData()) { | 237 while (m_source->hasMoreData()) { |
| 192 PathSegmentData segment = m_source->parseSegment(); | 238 PathSegmentData segment = m_source->parseSegment(); |
| 193 if (segment.command == PathSegUnknown) | 239 if (segment.command == PathSegUnknown) |
| 194 return false; | 240 return false; |
| 195 | 241 |
| 196 if (pathParsingMode == NormalizedParsing) { | 242 if (pathParsingMode == NormalizedParsing) { |
| 197 m_mode = AbsoluteCoordinates; | 243 normalizer.emitSegment(segment); |
| 198 | |
| 199 switch (segment.command) { | |
| 200 case PathSegMoveToRel: | |
| 201 m_mode = RelativeCoordinates; | |
| 202 case PathSegMoveToAbs: | |
| 203 emitMoveToSegment(segment); | |
| 204 break; | |
| 205 case PathSegLineToRel: | |
| 206 m_mode = RelativeCoordinates; | |
| 207 case PathSegLineToAbs: | |
| 208 emitLineToSegment(segment); | |
| 209 break; | |
| 210 case PathSegLineToHorizontalRel: | |
| 211 m_mode = RelativeCoordinates; | |
| 212 case PathSegLineToHorizontalAbs: | |
| 213 emitLineToHorizontalSegment(segment); | |
| 214 break; | |
| 215 case PathSegLineToVerticalRel: | |
| 216 m_mode = RelativeCoordinates; | |
| 217 case PathSegLineToVerticalAbs: | |
| 218 emitLineToVerticalSegment(segment); | |
| 219 break; | |
| 220 case PathSegClosePath: | |
| 221 m_consumer->closePath(); | |
| 222 // Reset m_currentPoint for the next path. | |
| 223 m_currentPoint = m_subPathPoint; | |
| 224 break; | |
| 225 case PathSegCurveToCubicRel: | |
| 226 m_mode = RelativeCoordinates; | |
| 227 case PathSegCurveToCubicAbs: | |
| 228 emitCurveToCubicSegment(segment); | |
| 229 break; | |
| 230 case PathSegCurveToCubicSmoothRel: | |
| 231 m_mode = RelativeCoordinates; | |
| 232 case PathSegCurveToCubicSmoothAbs: | |
| 233 emitCurveToCubicSmoothSegment(segment); | |
| 234 break; | |
| 235 case PathSegCurveToQuadraticRel: | |
| 236 m_mode = RelativeCoordinates; | |
| 237 case PathSegCurveToQuadraticAbs: | |
| 238 emitCurveToQuadraticSegment(segment); | |
| 239 break; | |
| 240 case PathSegCurveToQuadraticSmoothRel: | |
| 241 m_mode = RelativeCoordinates; | |
| 242 case PathSegCurveToQuadraticSmoothAbs: | |
| 243 emitCurveToQuadraticSmoothSegment(segment); | |
| 244 break; | |
| 245 case PathSegArcRel: | |
| 246 m_mode = RelativeCoordinates; | |
| 247 case PathSegArcAbs: | |
| 248 emitArcToSegment(segment); | |
| 249 break; | |
| 250 default: | |
| 251 ASSERT_NOT_REACHED(); | |
| 252 } | |
| 253 } else { | 244 } else { |
| 254 PathCoordinateMode mode = AbsoluteCoordinates; | 245 PathCoordinateMode mode = AbsoluteCoordinates; |
| 255 | 246 |
| 256 switch (segment.command) { | 247 switch (segment.command) { |
| 257 case PathSegMoveToRel: | 248 case PathSegMoveToRel: |
| 258 mode = RelativeCoordinates; | 249 mode = RelativeCoordinates; |
| 259 case PathSegMoveToAbs: | 250 case PathSegMoveToAbs: |
| 260 m_consumer->moveTo(segment.targetPoint, mode); | 251 m_consumer->moveTo(segment.targetPoint, mode); |
| 261 break; | 252 break; |
| 262 case PathSegLineToRel: | 253 case PathSegLineToRel: |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 m_consumer->arcTo(segment.arcRadii().x(), segment.arcRadii().y()
, segment.arcAngle(), segment.arcLarge, segment.arcSweep, segment.targetPoint, m
ode); | 294 m_consumer->arcTo(segment.arcRadii().x(), segment.arcRadii().y()
, segment.arcAngle(), segment.arcLarge, segment.arcSweep, segment.targetPoint, m
ode); |
| 304 break; | 295 break; |
| 305 default: | 296 default: |
| 306 ASSERT_NOT_REACHED(); | 297 ASSERT_NOT_REACHED(); |
| 307 } | 298 } |
| 308 } | 299 } |
| 309 | 300 |
| 310 if (!m_consumer->continueConsuming()) | 301 if (!m_consumer->continueConsuming()) |
| 311 return true; | 302 return true; |
| 312 | 303 |
| 313 m_lastCommand = segment.command; | |
| 314 | |
| 315 if (m_lastCommand != PathSegCurveToCubicAbs | |
| 316 && m_lastCommand != PathSegCurveToCubicRel | |
| 317 && m_lastCommand != PathSegCurveToCubicSmoothAbs | |
| 318 && m_lastCommand != PathSegCurveToCubicSmoothRel | |
| 319 && m_lastCommand != PathSegCurveToQuadraticAbs | |
| 320 && m_lastCommand != PathSegCurveToQuadraticRel | |
| 321 && m_lastCommand != PathSegCurveToQuadraticSmoothAbs | |
| 322 && m_lastCommand != PathSegCurveToQuadraticSmoothRel) | |
| 323 m_controlPoint = m_currentPoint; | |
| 324 | |
| 325 if (m_source->hasMoreData()) | 304 if (m_source->hasMoreData()) |
| 326 m_consumer->incrementPathSegmentCount(); | 305 m_consumer->incrementPathSegmentCount(); |
| 327 } | 306 } |
| 328 return true; | 307 return true; |
| 329 } | 308 } |
| 330 | 309 |
| 331 // This works by converting the SVG arc to "simple" beziers. | 310 // This works by converting the SVG arc to "simple" beziers. |
| 332 // Partly adapted from Niko's code in kdelibs/kdecore/svgicons. | 311 // Partly adapted from Niko's code in kdelibs/kdecore/svgicons. |
| 333 // See also SVG implementation notes: http://www.w3.org/TR/SVG/implnote.html#Arc
ConversionEndpointToCenter | 312 // See also SVG implementation notes: http://www.w3.org/TR/SVG/implnote.html#Arc
ConversionEndpointToCenter |
| 334 bool SVGPathParser::decomposeArcToCubic(const FloatPoint& currentPoint, const Pa
thSegmentData& arcSegment) | 313 bool NormalizingConsumer::decomposeArcToCubic(const FloatPoint& currentPoint, co
nst PathSegmentData& arcSegment) |
| 335 { | 314 { |
| 336 // If rx = 0 or ry = 0 then this arc is treated as a straight line segment (
a "lineto") joining the endpoints. | 315 // If rx = 0 or ry = 0 then this arc is treated as a straight line segment (
a "lineto") joining the endpoints. |
| 337 // http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters | 316 // http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters |
| 338 float rx = fabsf(arcSegment.arcRadii().x()); | 317 float rx = fabsf(arcSegment.arcRadii().x()); |
| 339 float ry = fabsf(arcSegment.arcRadii().y()); | 318 float ry = fabsf(arcSegment.arcRadii().y()); |
| 340 if (!rx || !ry) | 319 if (!rx || !ry) |
| 341 return false; | 320 return false; |
| 342 | 321 |
| 343 // If the current point and target point for the arc are identical, it shoul
d be treated as a zero length | 322 // If the current point and target point for the arc are identical, it shoul
d be treated as a zero length |
| 344 // path. This ensures continuity in animations. | 323 // path. This ensures continuity in animations. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 422 point2 = targetPoint; | 401 point2 = targetPoint; |
| 423 point2.move(t * sinEndTheta, -t * cosEndTheta); | 402 point2.move(t * sinEndTheta, -t * cosEndTheta); |
| 424 | 403 |
| 425 m_consumer->curveToCubic(pointTransform.mapPoint(point1), pointTransform
.mapPoint(point2), | 404 m_consumer->curveToCubic(pointTransform.mapPoint(point1), pointTransform
.mapPoint(point2), |
| 426 pointTransform.mapPoint(targetPoint), AbsoluteC
oordinates); | 405 pointTransform.mapPoint(targetPoint), AbsoluteC
oordinates); |
| 427 } | 406 } |
| 428 return true; | 407 return true; |
| 429 } | 408 } |
| 430 | 409 |
| 431 } | 410 } |
| OLD | NEW |