Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: Source/core/html/canvas/CanvasPathMethods.cpp

Issue 14298022: Add support for new canvas ellipse method. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Make canvas-ellipse-360-winding.html for virtual/gpu pass. Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « Source/core/html/canvas/CanvasPathMethods.h ('k') | Source/core/html/canvas/CanvasRenderingContext2D.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698