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 |
11 * version 2 of the License, or (at your option) any later version. | 11 * version 2 of the License, or (at your option) any later version. |
12 * | 12 * |
13 * This library is distributed in the hope that it will be useful, | 13 * This library is distributed in the hope that it will be useful, |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 * Library General Public License for more details. | 16 * Library General Public License for more details. |
17 * | 17 * |
18 * You should have received a copy of the GNU Library General Public License | 18 * You should have received a copy of the GNU Library General Public License |
19 * along with this library; see the file COPYING.LIB. If not, write to | 19 * along with this library; see the file COPYING.LIB. If not, write to |
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
21 * Boston, MA 02110-1301, USA. | 21 * Boston, MA 02110-1301, USA. |
22 */ | 22 */ |
23 | 23 |
24 #include "core/svg/SVGPathBuilder.h" | 24 #include "core/svg/SVGPathBuilder.h" |
25 | 25 |
26 #include "core/svg/SVGPathData.h" | |
27 #include "platform/graphics/Path.h" | 26 #include "platform/graphics/Path.h" |
28 | 27 |
29 namespace blink { | 28 namespace blink { |
30 | 29 |
| 30 FloatPoint SVGPathBuilder::smoothControl(bool isCompatibleSegment) const |
| 31 { |
| 32 // The control point is assumed to be the reflection of the control point on |
| 33 // the previous command relative to the current point. If there is no previo
us |
| 34 // command or if the previous command was not a [quad/cubic], assume the con
trol |
| 35 // point is coincident with the current point. |
| 36 // [https://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands] |
| 37 // [https://www.w3.org/TR/SVG/paths.html#PathDataQuadraticBezierCommands] |
| 38 FloatPoint controlPoint = m_currentPoint; |
| 39 if (isCompatibleSegment) |
| 40 controlPoint += m_currentPoint - m_lastControlPoint; |
| 41 |
| 42 return controlPoint; |
| 43 } |
| 44 |
| 45 void SVGPathBuilder::emitClose() |
| 46 { |
| 47 m_path.closeSubpath(); |
| 48 |
| 49 // At the end of the [closepath] command, the new current |
| 50 // point is set to the initial point of the current subpath. |
| 51 // [https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand] |
| 52 m_currentPoint = m_subpathPoint; |
| 53 } |
| 54 |
| 55 void SVGPathBuilder::emitMoveTo(const FloatPoint& p) |
| 56 { |
| 57 m_path.moveTo(p); |
| 58 |
| 59 // If a "closepath" is followed immediately by a "moveto", then |
| 60 // the "moveto" identifies the start point of the next subpath. |
| 61 // [https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand] |
| 62 if (m_lastCommand == PathSegClosePath) |
| 63 m_subpathPoint = p; |
| 64 |
| 65 m_currentPoint = p; |
| 66 } |
| 67 |
| 68 void SVGPathBuilder::emitLineTo(const FloatPoint& p) |
| 69 { |
| 70 m_path.addLineTo(p); |
| 71 m_currentPoint = p; |
| 72 } |
| 73 |
| 74 void SVGPathBuilder::emitQuadTo(const FloatPoint& c0, const FloatPoint& p) |
| 75 { |
| 76 m_path.addQuadCurveTo(c0, p); |
| 77 m_lastControlPoint = c0; |
| 78 m_currentPoint = p; |
| 79 } |
| 80 |
| 81 void SVGPathBuilder::emitSmoothQuadTo(const FloatPoint& p) |
| 82 { |
| 83 bool lastWasQuadratic = m_lastCommand == PathSegCurveToQuadraticAbs |
| 84 || m_lastCommand == PathSegCurveToQuadraticRel |
| 85 || m_lastCommand == PathSegCurveToQuadraticSmoothAbs |
| 86 || m_lastCommand == PathSegCurveToQuadraticSmoothRel; |
| 87 |
| 88 emitQuadTo(smoothControl(lastWasQuadratic), p); |
| 89 } |
| 90 |
| 91 void SVGPathBuilder::emitCubicTo(const FloatPoint& c0, const FloatPoint& c1, con
st FloatPoint& p) |
| 92 { |
| 93 m_path.addBezierCurveTo(c0, c1, p); |
| 94 m_lastControlPoint = c1; |
| 95 m_currentPoint = p; |
| 96 } |
| 97 |
| 98 void SVGPathBuilder::emitSmoothCubicTo(const FloatPoint& c1, const FloatPoint& p
) |
| 99 { |
| 100 bool lastWasCubic = m_lastCommand == PathSegCurveToCubicAbs |
| 101 || m_lastCommand == PathSegCurveToCubicRel |
| 102 || m_lastCommand == PathSegCurveToCubicSmoothAbs |
| 103 || m_lastCommand == PathSegCurveToCubicSmoothRel; |
| 104 |
| 105 emitCubicTo(smoothControl(lastWasCubic), c1, p); |
| 106 } |
| 107 |
| 108 void SVGPathBuilder::emitArcTo(const FloatPoint& p, const FloatSize& r, float ro
tate, |
| 109 bool largeArc, bool sweep) |
| 110 { |
| 111 m_path.addArcTo(p, r, rotate, largeArc, sweep); |
| 112 m_currentPoint = p; |
| 113 } |
| 114 |
31 void SVGPathBuilder::emitSegment(const PathSegmentData& segment) | 115 void SVGPathBuilder::emitSegment(const PathSegmentData& segment) |
32 { | 116 { |
33 switch (segment.command) { | 117 switch (segment.command) { |
| 118 case PathSegClosePath: |
| 119 emitClose(); |
| 120 break; |
34 case PathSegMoveToAbs: | 121 case PathSegMoveToAbs: |
35 m_path.moveTo(segment.targetPoint); | 122 emitMoveTo( |
| 123 segment.targetPoint); |
| 124 break; |
| 125 case PathSegMoveToRel: |
| 126 emitMoveTo( |
| 127 m_currentPoint + segment.targetPoint); |
36 break; | 128 break; |
37 case PathSegLineToAbs: | 129 case PathSegLineToAbs: |
38 m_path.addLineTo(segment.targetPoint); | 130 emitLineTo( |
| 131 segment.targetPoint); |
39 break; | 132 break; |
40 case PathSegClosePath: | 133 case PathSegLineToRel: |
41 m_path.closeSubpath(); | 134 emitLineTo( |
| 135 m_currentPoint + segment.targetPoint); |
| 136 break; |
| 137 case PathSegLineToHorizontalAbs: |
| 138 emitLineTo( |
| 139 FloatPoint(segment.targetPoint.x(), m_currentPoint.y())); |
| 140 break; |
| 141 case PathSegLineToHorizontalRel: |
| 142 emitLineTo( |
| 143 m_currentPoint + FloatSize(segment.targetPoint.x(), 0)); |
| 144 break; |
| 145 case PathSegLineToVerticalAbs: |
| 146 emitLineTo( |
| 147 FloatPoint(m_currentPoint.x(), segment.targetPoint.y())); |
| 148 break; |
| 149 case PathSegLineToVerticalRel: |
| 150 emitLineTo( |
| 151 m_currentPoint + FloatSize(0, segment.targetPoint.y())); |
| 152 break; |
| 153 case PathSegCurveToQuadraticAbs: |
| 154 emitQuadTo( |
| 155 segment.point1, |
| 156 segment.targetPoint); |
| 157 break; |
| 158 case PathSegCurveToQuadraticRel: |
| 159 emitQuadTo( |
| 160 m_currentPoint + segment.point1, |
| 161 m_currentPoint + segment.targetPoint); |
| 162 break; |
| 163 case PathSegCurveToQuadraticSmoothAbs: |
| 164 emitSmoothQuadTo( |
| 165 segment.targetPoint); |
| 166 break; |
| 167 case PathSegCurveToQuadraticSmoothRel: |
| 168 emitSmoothQuadTo( |
| 169 m_currentPoint + segment.targetPoint); |
42 break; | 170 break; |
43 case PathSegCurveToCubicAbs: | 171 case PathSegCurveToCubicAbs: |
44 m_path.addBezierCurveTo(segment.point1, segment.point2, segment.targetPo
int); | 172 emitCubicTo( |
| 173 segment.point1, |
| 174 segment.point2, |
| 175 segment.targetPoint); |
| 176 break; |
| 177 case PathSegCurveToCubicRel: |
| 178 emitCubicTo( |
| 179 m_currentPoint + segment.point1, |
| 180 m_currentPoint + segment.point2, |
| 181 m_currentPoint + segment.targetPoint); |
| 182 break; |
| 183 case PathSegCurveToCubicSmoothAbs: |
| 184 emitSmoothCubicTo( |
| 185 segment.point2, |
| 186 segment.targetPoint); |
| 187 break; |
| 188 case PathSegCurveToCubicSmoothRel: |
| 189 emitSmoothCubicTo( |
| 190 m_currentPoint + segment.point2, |
| 191 m_currentPoint + segment.targetPoint); |
| 192 break; |
| 193 case PathSegArcAbs: |
| 194 emitArcTo( |
| 195 segment.targetPoint, |
| 196 toFloatSize(segment.arcRadii()), |
| 197 segment.arcAngle(), |
| 198 segment.largeArcFlag(), |
| 199 segment.sweepFlag()); |
| 200 break; |
| 201 case PathSegArcRel: |
| 202 emitArcTo( |
| 203 m_currentPoint + segment.targetPoint, |
| 204 toFloatSize(segment.arcRadii()), |
| 205 segment.arcAngle(), |
| 206 segment.largeArcFlag(), |
| 207 segment.sweepFlag()); |
45 break; | 208 break; |
46 default: | 209 default: |
47 ASSERT_NOT_REACHED(); | 210 ASSERT_NOT_REACHED(); |
48 } | 211 } |
| 212 |
| 213 m_lastCommand = segment.command; |
49 } | 214 } |
50 | 215 |
51 } | 216 } |
OLD | NEW |