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 19 matching lines...) Expand all Loading... | |
| 30 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF | 30 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF |
| 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 "core/dom/ExceptionCode.h" | 38 #include "core/dom/ExceptionCode.h" |
| 39 #include "core/platform/graphics/FloatRect.h" | 39 #include "core/platform/graphics/FloatRect.h" |
| 40 #include "core/platform/graphics/transforms/AffineTransform.h" | |
| 40 #include <wtf/MathExtras.h> | 41 #include <wtf/MathExtras.h> |
| 41 | 42 |
| 42 namespace WebCore { | 43 namespace WebCore { |
| 43 | 44 |
| 44 void CanvasPathMethods::closePath() | 45 void CanvasPathMethods::closePath() |
| 45 { | 46 { |
| 46 if (m_path.isEmpty()) | 47 if (m_path.isEmpty()) |
| 47 return; | 48 return; |
| 48 | 49 |
| 49 FloatRect boundRect = m_path.boundingRect(); | 50 FloatRect boundRect = m_path.boundingRect(); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 m_path.moveTo(p1); | 127 m_path.moveTo(p1); |
| 127 else if (p1 == m_path.currentPoint() || p1 == p2 || !r) | 128 else if (p1 == m_path.currentPoint() || p1 == p2 || !r) |
| 128 lineTo(x1, y1); | 129 lineTo(x1, y1); |
| 129 else | 130 else |
| 130 m_path.addArcTo(p1, p2, r); | 131 m_path.addArcTo(p1, p2, r); |
| 131 } | 132 } |
| 132 | 133 |
| 133 static float adjustEndAngle(float startAngle, float endAngle, bool anticlockwise ) | 134 static float adjustEndAngle(float startAngle, float endAngle, bool anticlockwise ) |
| 134 { | 135 { |
| 135 float twoPi = 2 * piFloat; | 136 float twoPi = 2 * piFloat; |
| 137 float newEndAngle = endAngle; | |
| 136 /* http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-el ement.html#dom-context-2d-arc | 138 /* http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-el ement.html#dom-context-2d-arc |
| 137 * If the anticlockwise argument is false and endAngle-startAngle is equal t o or greater than 2π, or, | 139 * If the anticlockwise argument is false and endAngle-startAngle is equal t o or greater than 2π, or, |
| 138 * if the anticlockwise argument is true and startAngle-endAngle is equal to or greater than 2π, | 140 * if the anticlockwise argument is true and startAngle-endAngle is equal to or greater than 2π, |
| 139 * then the arc is the whole circumference of this ellipse. | 141 * then the arc is the whole circumference of this ellipse. |
| 140 */ | 142 */ |
| 141 if (!anticlockwise && endAngle - startAngle >= twoPi) | 143 if (!anticlockwise && endAngle - startAngle >= twoPi) |
| 142 return startAngle + twoPi + fmodf(endAngle - startAngle, twoPi); | 144 newEndAngle = startAngle + twoPi + fmodf(endAngle - startAngle, twoPi); |
| 143 if (anticlockwise && startAngle - endAngle >= twoPi) | 145 else if (anticlockwise && startAngle - endAngle >= twoPi) |
| 144 return startAngle - twoPi - fmodf(startAngle - endAngle, twoPi); | 146 newEndAngle = startAngle - twoPi - fmodf(startAngle - endAngle, twoPi); |
| 145 | 147 |
| 146 /* | 148 /* |
| 147 * Otherwise, the arc is the path along the circumference of this ellipse fr om the start point to the end point, | 149 * Otherwise, the arc is the path along the circumference of this ellipse fr om the start point to the end point, |
| 148 * going anti-clockwise if the anticlockwise argument is true, and clockwise otherwise. | 150 * going anti-clockwise if the anticlockwise argument is true, and clockwise otherwise. |
| 149 * Since the points are on the ellipse, as opposed to being simply angles fr om zero, | 151 * Since the points are on the ellipse, as opposed to being simply angles fr om zero, |
| 150 * the arc can never cover an angle greater than 2π radians. | 152 * the arc can never cover an angle greater than 2π radians. |
| 151 */ | 153 */ |
| 152 if (!anticlockwise && startAngle > endAngle) | 154 else if (!anticlockwise && startAngle > endAngle) |
| 153 return startAngle + (twoPi - fmodf(startAngle - endAngle, twoPi)); | 155 newEndAngle = startAngle + (twoPi - fmodf(startAngle - endAngle, twoPi)) ; |
| 154 if (anticlockwise && startAngle < endAngle) | 156 else if (anticlockwise && startAngle < endAngle) |
| 155 return startAngle - (twoPi - fmodf(endAngle - startAngle, twoPi)); | 157 newEndAngle = startAngle - (twoPi - fmodf(endAngle - startAngle, twoPi)) ; |
| 156 | 158 |
| 157 return endAngle; | 159 ASSERT(std::abs(newEndAngle - startAngle) < 4 * piFloat); |
| 160 return newEndAngle; | |
| 158 } | 161 } |
| 159 | 162 |
| 160 void CanvasPathMethods::arc(float x, float y, float radius, float startAngle, fl oat endAngle, bool anticlockwise, ExceptionCode& ec) | 163 void CanvasPathMethods::arc(float x, float y, float radius, float startAngle, fl oat endAngle, bool anticlockwise, ExceptionCode& ec) |
| 161 { | 164 { |
| 162 ec = 0; | 165 ec = 0; |
| 163 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radius) || !std ::isfinite(startAngle) || !std::isfinite(endAngle)) | 166 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radius) || !std ::isfinite(startAngle) || !std::isfinite(endAngle)) |
| 164 return; | 167 return; |
| 165 | 168 |
| 166 if (radius < 0) { | 169 if (radius < 0) { |
| 167 ec = IndexSizeError; | 170 ec = IndexSizeError; |
| 168 return; | 171 return; |
| 169 } | 172 } |
| 170 | 173 |
| 171 if (!isTransformInvertible()) | 174 if (!isTransformInvertible()) |
| 172 return; | 175 return; |
| 173 | 176 |
| 174 if (!radius || startAngle == endAngle) { | 177 if (!radius || startAngle == endAngle) { |
| 175 // The arc is empty but we still need to draw the connecting line. | 178 // The arc is empty but we still need to draw the connecting line. |
| 176 lineTo(x + radius * cosf(startAngle), y + radius * sinf(startAngle)); | 179 lineTo(x + radius * cosf(startAngle), y + radius * sinf(startAngle)); |
| 177 return; | 180 return; |
| 178 } | 181 } |
| 179 | 182 |
| 180 float adjustedEndAngle = adjustEndAngle(startAngle, endAngle, anticlockwise) ; | 183 float adjustedEndAngle = adjustEndAngle(startAngle, endAngle, anticlockwise) ; |
| 181 m_path.addArc(FloatPoint(x, y), radius, startAngle, adjustedEndAngle, anticl ockwise); | 184 m_path.addArc(FloatPoint(x, y), radius, startAngle, adjustedEndAngle, anticl ockwise); |
| 182 } | 185 } |
| 183 | 186 |
| 187 inline static void lineToFloatPoint(CanvasPathMethods* path, const FloatPoint& p ) | |
| 188 { | |
| 189 path->lineTo(p.x(), p.y()); | |
| 190 } | |
| 191 | |
| 192 inline static FloatPoint getPointOnEllipse(float radiusX, float radiusY, float t heta) | |
| 193 { | |
| 194 return FloatPoint(radiusX * cosf(theta), radiusY * sinf(theta)); | |
| 195 } | |
| 196 | |
| 197 inline static void canonicalizeAngle(float* startAngle, float* endAngle) | |
| 198 { | |
| 199 // Make 0 <= startAngle < 2*PI | |
| 200 float twoPi = 2 * piFloat; | |
| 201 float newStartAngle = *startAngle; | |
| 202 if (newStartAngle < 0) | |
| 203 newStartAngle = twoPi + fmodf(newStartAngle, -twoPi); | |
| 204 else | |
| 205 newStartAngle = fmodf(newStartAngle, twoPi); | |
| 206 | |
| 207 float delta = newStartAngle - *startAngle; | |
| 208 *startAngle = newStartAngle; | |
| 209 *endAngle = *endAngle + delta; | |
| 210 } | |
| 211 | |
| 212 static void degenerateEllipse(CanvasPathMethods* path, float x, float y, float r adiusX, float radiusY, float rotation, float startAngle, float endAngle, bool an ticlockwise) | |
| 213 { | |
| 214 ASSERT(std::abs(endAngle - startAngle) < 4 * piFloat); | |
| 215 | |
| 216 FloatPoint center(x, y); | |
| 217 AffineTransform rotationMatrix; | |
| 218 rotationMatrix.rotate(rad2deg(rotation)); | |
| 219 lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEllipse(ra diusX, radiusY, startAngle))); | |
| 220 if ((!radiusX && !radiusY) || startAngle == endAngle) | |
| 221 return; | |
| 222 | |
| 223 canonicalizeAngle(&startAngle, &endAngle); | |
|
alph
2013/07/10 13:38:04
It seems that canonicalizeAngle should depend on a
dshwang
2013/07/10 14:19:57
canonicalizeAngle() is independent from whether an
alph
2013/07/10 15:22:30
Sorry, missed that.
| |
| 224 ASSERT(std::abs(endAngle - startAngle) < 4 * piFloat); | |
| 225 | |
| 226 float halfPiFloat = piFloat * 0.5; | |
| 227 if (!anticlockwise) { | |
| 228 for (float angle = startAngle - fmodf(startAngle, halfPiFloat) + halfPiF loat; angle < endAngle; angle += halfPiFloat) | |
| 229 lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEl lipse(radiusX, radiusY, angle))); | |
| 230 } else { | |
| 231 for (float angle = startAngle - fmodf(startAngle, halfPiFloat); angle > endAngle; angle -= halfPiFloat) | |
| 232 lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEl lipse(radiusX, radiusY, angle))); | |
| 233 } | |
| 234 | |
| 235 lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEllipse(ra diusX, radiusY, endAngle))); | |
| 236 } | |
| 237 | |
| 238 void CanvasPathMethods::ellipse(float x, float y, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise, ExceptionC ode& ec) | |
| 239 { | |
| 240 ec = 0; | |
| 241 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radiusX) || !st d::isfinite(radiusY) || !std::isfinite(rotation) || !std::isfinite(startAngle) | | !std::isfinite(endAngle)) | |
| 242 return; | |
| 243 | |
| 244 if (radiusX < 0 || radiusY < 0) { | |
| 245 ec = IndexSizeError; | |
| 246 return; | |
| 247 } | |
| 248 | |
| 249 if (!isTransformInvertible()) | |
| 250 return; | |
| 251 | |
| 252 float adjustedEndAngle = adjustEndAngle(startAngle, endAngle, anticlockwise) ; | |
| 253 if (!radiusX || !radiusY || startAngle == adjustedEndAngle) { | |
| 254 // The ellipse is empty but we still need to draw the connecting line to start point. | |
| 255 degenerateEllipse(this, x, y, radiusX, radiusY, rotation, startAngle, ad justedEndAngle, anticlockwise); | |
| 256 return; | |
| 257 } | |
| 258 | |
| 259 m_path.addEllipse(FloatPoint(x, y), radiusX, radiusY, rotation, startAngle, adjustedEndAngle, anticlockwise); | |
| 260 } | |
| 261 | |
| 184 void CanvasPathMethods::rect(float x, float y, float width, float height) | 262 void CanvasPathMethods::rect(float x, float y, float width, float height) |
| 185 { | 263 { |
| 186 if (!isTransformInvertible()) | 264 if (!isTransformInvertible()) |
| 187 return; | 265 return; |
| 188 | 266 |
| 189 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(width) || !std: :isfinite(height)) | 267 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(width) || !std: :isfinite(height)) |
| 190 return; | 268 return; |
| 191 | 269 |
| 192 if (!width && !height) { | 270 if (!width && !height) { |
| 193 m_path.moveTo(FloatPoint(x, y)); | 271 m_path.moveTo(FloatPoint(x, y)); |
| 194 return; | 272 return; |
| 195 } | 273 } |
| 196 | 274 |
| 197 m_path.addRect(FloatRect(x, y, width, height)); | 275 m_path.addRect(FloatRect(x, y, width, height)); |
| 198 } | 276 } |
| 199 } | 277 } |
| OLD | NEW |