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 20 matching lines...) Expand all Loading... |
31 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 31 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 * SUCH DAMAGE. | 32 * SUCH DAMAGE. |
33 */ | 33 */ |
34 | 34 |
35 #include "config.h" | 35 #include "config.h" |
36 #include "core/html/canvas/CanvasPathMethods.h" | 36 #include "core/html/canvas/CanvasPathMethods.h" |
37 | 37 |
38 #include "bindings/v8/ExceptionState.h" | 38 #include "bindings/v8/ExceptionState.h" |
39 #include "core/dom/ExceptionCode.h" | 39 #include "core/dom/ExceptionCode.h" |
40 #include "core/platform/graphics/FloatRect.h" | 40 #include "core/platform/graphics/FloatRect.h" |
| 41 #include "core/platform/graphics/transforms/AffineTransform.h" |
41 #include "wtf/MathExtras.h" | 42 #include "wtf/MathExtras.h" |
42 | 43 |
43 namespace WebCore { | 44 namespace WebCore { |
44 | 45 |
45 void CanvasPathMethods::closePath() | 46 void CanvasPathMethods::closePath() |
46 { | 47 { |
47 if (m_path.isEmpty()) | 48 if (m_path.isEmpty()) |
48 return; | 49 return; |
49 | 50 |
50 FloatRect boundRect = m_path.boundingRect(); | 51 FloatRect boundRect = m_path.boundingRect(); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 if (!radius || startAngle == endAngle) { | 180 if (!radius || startAngle == endAngle) { |
180 // The arc is empty but we still need to draw the connecting line. | 181 // The arc is empty but we still need to draw the connecting line. |
181 lineTo(x + radius * cosf(startAngle), y + radius * sinf(startAngle)); | 182 lineTo(x + radius * cosf(startAngle), y + radius * sinf(startAngle)); |
182 return; | 183 return; |
183 } | 184 } |
184 | 185 |
185 float adjustedEndAngle = adjustEndAngle(startAngle, endAngle, anticlockwise)
; | 186 float adjustedEndAngle = adjustEndAngle(startAngle, endAngle, anticlockwise)
; |
186 m_path.addArc(FloatPoint(x, y), radius, startAngle, adjustedEndAngle, anticl
ockwise); | 187 m_path.addArc(FloatPoint(x, y), radius, startAngle, adjustedEndAngle, anticl
ockwise); |
187 } | 188 } |
188 | 189 |
| 190 inline static void lineToFloatPoint(CanvasPathMethods* path, const FloatPoint& p
) |
| 191 { |
| 192 path->lineTo(p.x(), p.y()); |
| 193 } |
| 194 |
| 195 inline static FloatPoint getPointOnEllipse(float radiusX, float radiusY, float t
heta) |
| 196 { |
| 197 return FloatPoint(radiusX * cosf(theta), radiusY * sinf(theta)); |
| 198 } |
| 199 |
| 200 inline static void canonicalizeAngle(float* startAngle, float* endAngle) |
| 201 { |
| 202 // Make 0 <= startAngle < 2*PI |
| 203 float twoPi = 2 * piFloat; |
| 204 float newStartAngle = *startAngle; |
| 205 if (newStartAngle < 0) |
| 206 newStartAngle = twoPi + fmodf(newStartAngle, -twoPi); |
| 207 else |
| 208 newStartAngle = fmodf(newStartAngle, twoPi); |
| 209 |
| 210 float delta = newStartAngle - *startAngle; |
| 211 *startAngle = newStartAngle; |
| 212 *endAngle = *endAngle + delta; |
| 213 } |
| 214 |
| 215 /* |
| 216 * degenerateEllipse() handles a degenerated ellipse using several lines. |
| 217 * |
| 218 * Let's see a following example: line to ellipse to line. |
| 219 * _--^\ |
| 220 * ( ) |
| 221 * -----( ) |
| 222 * ) |
| 223 * /-------- |
| 224 * |
| 225 * If radiusX becomes zero, the ellipse of the example is degenerated. |
| 226 * _ |
| 227 * // P |
| 228 * // |
| 229 * -----// |
| 230 * / |
| 231 * /-------- |
| 232 * |
| 233 * To draw the above example, need to get P that is a local maximum point. |
| 234 * Angles for P are 0.5Pi and 1.5Pi in the ellipse coordinates. |
| 235 * |
| 236 * If radiusY becomes zero, the result is as follows. |
| 237 * -----__ |
| 238 * --_ |
| 239 * ---------- |
| 240 * ``P |
| 241 * Angles for P are 0 and Pi in the ellipse coordinates. |
| 242 * |
| 243 * To handle both cases, degenerateEllipse() lines to start angle, local maximum
points(every 0.5Pi), and end angle. |
| 244 * NOTE: Before ellipse() calls this function, adjustEndAngle() is called, so en
dAngle - startAngle must be less than 4Pi. |
| 245 */ |
| 246 static void degenerateEllipse(CanvasPathMethods* path, float x, float y, float r
adiusX, float radiusY, float rotation, float startAngle, float endAngle, bool an
ticlockwise) |
| 247 { |
| 248 ASSERT(std::abs(endAngle - startAngle) < 4 * piFloat); |
| 249 |
| 250 FloatPoint center(x, y); |
| 251 AffineTransform rotationMatrix; |
| 252 rotationMatrix.rotate(rad2deg(rotation)); |
| 253 // First, if the object's path has any subpaths, then the method must add a
straight line from the last point in the subpath to the start point of the arc. |
| 254 lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEllipse(ra
diusX, radiusY, startAngle))); |
| 255 if ((!radiusX && !radiusY) || startAngle == endAngle) |
| 256 return; |
| 257 |
| 258 canonicalizeAngle(&startAngle, &endAngle); |
| 259 ASSERT(std::abs(endAngle - startAngle) < 4 * piFloat); |
| 260 |
| 261 float halfPiFloat = piFloat * 0.5; |
| 262 if (!anticlockwise) { |
| 263 // startAngle - fmodf(startAngle, halfPiFloat) + halfPiFloat is the one
of (0, 0.5Pi, Pi, 1.5Pi, 2Pi) |
| 264 // that is the closest to startAngle on the clockwise direction. |
| 265 for (float angle = startAngle - fmodf(startAngle, halfPiFloat) + halfPiF
loat; angle < endAngle; angle += halfPiFloat) |
| 266 lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEl
lipse(radiusX, radiusY, angle))); |
| 267 } else { |
| 268 for (float angle = startAngle - fmodf(startAngle, halfPiFloat); angle >
endAngle; angle -= halfPiFloat) |
| 269 lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEl
lipse(radiusX, radiusY, angle))); |
| 270 } |
| 271 |
| 272 lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEllipse(ra
diusX, radiusY, endAngle))); |
| 273 } |
| 274 |
| 275 void CanvasPathMethods::ellipse(float x, float y, float radiusX, float radiusY,
float rotation, float startAngle, float endAngle, bool anticlockwise, ExceptionS
tate& es) |
| 276 { |
| 277 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radiusX) || !st
d::isfinite(radiusY) || !std::isfinite(rotation) || !std::isfinite(startAngle) |
| !std::isfinite(endAngle)) |
| 278 return; |
| 279 |
| 280 if (radiusX < 0 || radiusY < 0) { |
| 281 es.throwDOMException(IndexSizeError); |
| 282 return; |
| 283 } |
| 284 |
| 285 if (!isTransformInvertible()) |
| 286 return; |
| 287 |
| 288 float adjustedEndAngle = adjustEndAngle(startAngle, endAngle, anticlockwise)
; |
| 289 if (!radiusX || !radiusY || startAngle == adjustedEndAngle) { |
| 290 // The ellipse is empty but we still need to draw the connecting line to
start point. |
| 291 degenerateEllipse(this, x, y, radiusX, radiusY, rotation, startAngle, ad
justedEndAngle, anticlockwise); |
| 292 return; |
| 293 } |
| 294 |
| 295 m_path.addEllipse(FloatPoint(x, y), radiusX, radiusY, rotation, startAngle,
adjustedEndAngle, anticlockwise); |
| 296 } |
| 297 |
189 void CanvasPathMethods::rect(float x, float y, float width, float height) | 298 void CanvasPathMethods::rect(float x, float y, float width, float height) |
190 { | 299 { |
191 if (!isTransformInvertible()) | 300 if (!isTransformInvertible()) |
192 return; | 301 return; |
193 | 302 |
194 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(width) || !std:
:isfinite(height)) | 303 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(width) || !std:
:isfinite(height)) |
195 return; | 304 return; |
196 | 305 |
197 if (!width && !height) { | 306 if (!width && !height) { |
198 m_path.moveTo(FloatPoint(x, y)); | 307 m_path.moveTo(FloatPoint(x, y)); |
199 return; | 308 return; |
200 } | 309 } |
201 | 310 |
202 m_path.addRect(FloatRect(x, y, width, height)); | 311 m_path.addRect(FloatRect(x, y, width, height)); |
203 } | 312 } |
204 } | 313 } |
OLD | NEW |