Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies) |
| 4 * Copyright (C) 2007 Alp Toker <alp@atoker.com> | 4 * Copyright (C) 2007 Alp Toker <alp@atoker.com> |
| 5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> | 5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> |
| 6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> | 6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> |
| 7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. |
| 8 * Copyright (C) 2012 Intel Corporation. All rights reserved. | 8 * Copyright (C) 2012 Intel Corporation. All rights reserved. |
| 9 * Copyright (C) 2012, 2013 Adobe Systems Incorporated. All rights reserved. | 9 * Copyright (C) 2012, 2013 Adobe Systems Incorporated. All rights reserved. |
| 10 * | 10 * |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 123 FloatPoint p2 = FloatPoint(x2, y2); | 123 FloatPoint p2 = FloatPoint(x2, y2); |
| 124 | 124 |
| 125 if (!m_path.hasCurrentPoint()) | 125 if (!m_path.hasCurrentPoint()) |
| 126 m_path.moveTo(p1); | 126 m_path.moveTo(p1); |
| 127 else if (p1 == m_path.currentPoint() || p1 == p2 || !r) | 127 else if (p1 == m_path.currentPoint() || p1 == p2 || !r) |
| 128 lineTo(x1, y1); | 128 lineTo(x1, y1); |
| 129 else | 129 else |
| 130 m_path.addArcTo(p1, p2, r); | 130 m_path.addArcTo(p1, p2, r); |
| 131 } | 131 } |
| 132 | 132 |
| 133 void CanvasPathMethods::arc(float x, float y, float r, float sa, float ea, bool anticlockwise, ExceptionCode& ec) | 133 static float adjustEndAngle(float startAngle, float endAngle, bool anticlockwise ) |
| 134 { | |
| 135 // If 'startAngle' and 'endAngle' differ by more than 2Pi, just add a circle starting/ending at 'startAngle'. | |
| 136 if (anticlockwise && startAngle - endAngle >= 2 * piFloat) | |
| 137 return startAngle - 2 * piFloat; | |
| 138 if (!anticlockwise && endAngle - startAngle >= 2 * piFloat) | |
| 139 return startAngle + 2 * piFloat; | |
| 140 return endAngle; | |
| 141 } | |
| 142 | |
| 143 void CanvasPathMethods::arc(float x, float y, float radius, float startAngle, fl oat endAngle, bool anticlockwise, ExceptionCode& ec) | |
| 134 { | 144 { |
| 135 ec = 0; | 145 ec = 0; |
| 136 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(r) || !std::isf inite(sa) || !std::isfinite(ea)) | 146 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radius) || !std ::isfinite(startAngle) || !std::isfinite(endAngle)) |
| 137 return; | 147 return; |
| 138 | 148 |
| 139 if (r < 0) { | 149 if (radius < 0) { |
| 140 ec = INDEX_SIZE_ERR; | 150 ec = INDEX_SIZE_ERR; |
| 141 return; | 151 return; |
| 142 } | 152 } |
| 143 | 153 |
| 144 if (!r || sa == ea) { | 154 if (!radius || startAngle == endAngle) { |
| 145 // The arc is empty but we still need to draw the connecting line. | 155 // The arc is empty but we still need to draw the connecting line. |
| 146 lineTo(x + r * cosf(sa), y + r * sinf(sa)); | 156 lineTo(x + radius * cosf(startAngle), y + radius * sinf(startAngle)); |
| 147 return; | 157 return; |
| 148 } | 158 } |
| 149 | 159 |
| 150 if (!isTransformInvertible()) | 160 if (!isTransformInvertible()) |
| 151 return; | 161 return; |
| 152 | 162 |
| 153 // If 'sa' and 'ea' differ by more than 2Pi, just add a circle starting/endi ng at 'sa'. | 163 float adjustedEndAngle = adjustEndAngle(startAngle, endAngle, anticlockwise) ; |
| 154 if (anticlockwise && sa - ea >= 2 * piFloat) { | 164 m_path.addArc(FloatPoint(x, y), radius, startAngle, adjustedEndAngle, anticl ockwise); |
| 155 m_path.addArc(FloatPoint(x, y), r, sa, sa - 2 * piFloat, anticlockwise); | 165 } |
| 166 | |
| 167 inline static void lineTo(CanvasPathMethods* path, const FloatPoint& p) | |
| 168 { | |
| 169 path->lineTo(p.x(), p.y()); | |
| 170 } | |
| 171 | |
| 172 inline static FloatPoint ellipsePoint(float radiusX, float radiusY, float theta) | |
| 173 { | |
| 174 return FloatPoint(radiusX * cosf(theta), radiusY * sinf(theta)); | |
| 175 } | |
| 176 | |
| 177 static void degenerateEllipse(CanvasPathMethods* path, float x, float y, float r adiusX, float radiusY, float rotation, float startAngle, float endAngle, bool an ticlockwise) | |
| 178 { | |
| 179 FloatPoint center(x, y); | |
| 180 AffineTransform rotationMatrix; | |
| 181 rotationMatrix.rotate(rad2deg(rotation)); | |
| 182 lineTo(path, center + rotationMatrix.mapPoint(ellipsePoint(radiusX, radiusY, startAngle))); | |
| 183 if ((!radiusX && !radiusY) || startAngle == endAngle) | |
| 156 return; | 184 return; |
| 185 | |
| 186 float sweep = endAngle - startAngle; | |
| 187 if (anticlockwise) | |
| 188 sweep = startAngle - endAngle; | |
| 189 | |
| 190 if (sweep < 0) | |
| 191 sweep = std::fmod(-sweep, piFloat * 2); | |
|
alph
2013/07/09 17:18:18
I'm not sure how to map negative sweep. Unfortunat
dshwang
2013/07/09 17:40:53
The spec said
"
If the anticlockwise argument is f
| |
| 192 | |
| 193 FloatPoint endPoint(center + rotationMatrix.mapPoint(ellipsePoint(radiusX, r adiusY, endAngle))); | |
| 194 if (sweep <= piFloat * 0.5) { | |
| 195 lineTo(path, endPoint); | |
|
alph
2013/07/09 17:18:18
It now looks much better. But unfortunately this s
dshwang
2013/07/09 17:40:53
Good idea! I buy it. I'll change.
On the other ha
alph
2013/07/09 18:16:11
Just though that it's probably better to have two
| |
| 196 } else if (sweep <= piFloat) { | |
| 197 lineTo(path, center + rotationMatrix.mapPoint(ellipsePoint(radiusX, radi usY, piFloat * 0.5))); | |
| 198 lineTo(path, endPoint); | |
| 199 } else if (sweep <= piFloat * 1.5) { | |
| 200 lineTo(path, center + rotationMatrix.mapPoint(ellipsePoint(radiusX, radi usY, piFloat * 0.5))); | |
| 201 lineTo(path, center + rotationMatrix.mapPoint(ellipsePoint(radiusX, radi usY, piFloat))); | |
| 202 lineTo(path, endPoint); | |
| 203 } else if (sweep <= piFloat * 2) { | |
| 204 lineTo(path, center + rotationMatrix.mapPoint(ellipsePoint(radiusX, radi usY, piFloat * 0.5))); | |
| 205 lineTo(path, center + rotationMatrix.mapPoint(ellipsePoint(radiusX, radi usY, piFloat))); | |
| 206 lineTo(path, center + rotationMatrix.mapPoint(ellipsePoint(radiusX, radi usY, piFloat * 1.5))); | |
| 207 lineTo(path, endPoint); | |
| 208 } else { // sweep > piFloat * 2 | |
| 209 lineTo(path, center + rotationMatrix.mapPoint(ellipsePoint(radiusX, radi usY, piFloat * 0.5))); | |
| 210 lineTo(path, center + rotationMatrix.mapPoint(ellipsePoint(radiusX, radi usY, piFloat))); | |
| 211 lineTo(path, center + rotationMatrix.mapPoint(ellipsePoint(radiusX, radi usY, piFloat * 1.5))); | |
| 212 lineTo(path, center + rotationMatrix.mapPoint(ellipsePoint(radiusX, radi usY, piFloat * 2))); | |
| 213 lineTo(path, endPoint); | |
| 157 } | 214 } |
| 158 if (!anticlockwise && ea - sa >= 2 * piFloat) { | 215 } |
| 159 m_path.addArc(FloatPoint(x, y), r, sa, sa + 2 * piFloat, anticlockwise); | 216 |
| 217 void CanvasPathMethods::ellipse(float x, float y, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise, ExceptionC ode& ec) | |
| 218 { | |
| 219 ec = 0; | |
| 220 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radiusX) || !st d::isfinite(radiusY) || !std::isfinite(rotation) || !std::isfinite(startAngle) | | !std::isfinite(endAngle)) | |
| 221 return; | |
| 222 | |
| 223 if (radiusX < 0 || radiusY < 0) { | |
| 224 ec = INDEX_SIZE_ERR; | |
| 160 return; | 225 return; |
| 161 } | 226 } |
| 162 | 227 |
| 163 m_path.addArc(FloatPoint(x, y), r, sa, ea, anticlockwise); | 228 if (!radiusX || !radiusY || startAngle == endAngle) { |
| 229 // The ellipse is empty but we still need to draw the connecting line to start point. | |
| 230 degenerateEllipse(this, x, y, radiusX, radiusY, rotation, startAngle, en dAngle, anticlockwise); | |
| 231 // we can do as follows instead of using degenerateEllipse | |
| 232 /* | |
| 233 if ((!radiusX && !radiusY) || startAngle == endAngle) { | |
| 234 AffineTransform rotationMatrix; | |
| 235 rotationMatrix.rotate(rad2deg(rotation)); | |
| 236 lineTo(path, FloatPoint(x, y) + rotationMatrix.mapPoint(ellipsePoint (radiusX, radiusY, startAngle))); | |
| 237 } else { | |
| 238 ASSERT(startAngle != endAngle); | |
| 239 if (!radiusX) | |
| 240 radiusX = 0.0001; | |
| 241 if (!radiusY) | |
| 242 radiusY = 0.0001; | |
| 243 } | |
| 244 */ | |
|
dshwang
2013/07/09 16:37:22
Which do you think right: degenerateEllipse() or a
alph
2013/07/09 17:18:18
This way degenerateEllipse looks much better. I'd
dshwang
2013/07/09 17:40:53
Good choice :)
| |
| 245 return; | |
| 246 } | |
| 247 | |
| 248 if (!isTransformInvertible()) | |
| 249 return; | |
| 250 | |
| 251 float adjustedEndAngle = adjustEndAngle(startAngle, endAngle, anticlockwise) ; | |
| 252 m_path.addEllipse(FloatPoint(x, y), radiusX, radiusY, rotation, startAngle, adjustedEndAngle, anticlockwise); | |
| 164 } | 253 } |
| 165 | 254 |
| 166 void CanvasPathMethods::rect(float x, float y, float width, float height) | 255 void CanvasPathMethods::rect(float x, float y, float width, float height) |
| 167 { | 256 { |
| 168 if (!isTransformInvertible()) | 257 if (!isTransformInvertible()) |
| 169 return; | 258 return; |
| 170 | 259 |
| 171 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(width) || !std: :isfinite(height)) | 260 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(width) || !std: :isfinite(height)) |
| 172 return; | 261 return; |
| 173 | 262 |
| 174 if (!width && !height) { | 263 if (!width && !height) { |
| 175 m_path.moveTo(FloatPoint(x, y)); | 264 m_path.moveTo(FloatPoint(x, y)); |
| 176 return; | 265 return; |
| 177 } | 266 } |
| 178 | 267 |
| 179 m_path.addRect(FloatRect(x, y, width, height)); | 268 m_path.addRect(FloatRect(x, y, width, height)); |
| 180 } | 269 } |
| 181 } | 270 } |
| OLD | NEW |