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 |