(function() { var arcToSegmentsCache = { }, segmentToBezierCache = { }, _join = Array.prototype.join, argsString; // Generous contribution by Raph Levien, from libsvg-0.1.0.tar.gz function arcToSegments(x, y, rx, ry, large, sweep, rotateX, ox, oy) { argsString = _join.call(arguments); if (arcToSegmentsCache[argsString]) { return arcToSegmentsCache[argsString]; } var coords = getXYCoords(rotateX, rx, ry, ox, oy, x, y); var d = (coords.x1-coords.x0) * (coords.x1-coords.x0) + (coords.y1-coords.y0) * (coords.y1-coords.y0); var sfactor_sq = 1 / d - 0.25; if (sfactor_sq < 0) sfactor_sq = 0; var sfactor = Math.sqrt(sfactor_sq); if (sweep === large) sfactor = -sfactor; var xc = 0.5 * (coords.x0 + coords.x1) - sfactor * (coords.y1-coords.y0); var yc = 0.5 * (coords.y0 + coords.y1) + sfactor * (coords.x1-coords.x0); var th0 = Math.atan2(coords.y0-yc, coords.x0-xc); var th1 = Math.atan2(coords.y1-yc, coords.x1-xc); var th_arc = th1-th0; if (th_arc < 0 && sweep === 1) { th_arc += 2*Math.PI; } else if (th_arc > 0 && sweep === 0) { th_arc -= 2 * Math.PI; } var segments = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001))); var result = []; for (var i=0; i 1) { pl = Math.sqrt(pl); rx *= pl; ry *= pl; } var a00 = cos_th / rx; var a01 = sin_th / rx; var a10 = (-sin_th) / ry; var a11 = (cos_th) / ry; return { x0: a00 * ox + a01 * oy, y0: a10 * ox + a11 * oy, x1: a00 * x + a01 * y, y1: a10 * x + a11 * y, sin_th: sin_th, cos_th: cos_th }; } function segmentToBezier(cx, cy, th0, th1, rx, ry, sin_th, cos_th) { argsString = _join.call(arguments); if (segmentToBezierCache[argsString]) { return segmentToBezierCache[argsString]; } var a00 = cos_th * rx; var a01 = -sin_th * ry; var a10 = sin_th * rx; var a11 = cos_th * ry; var th_half = 0.5 * (th1 - th0); var t = (8/3) * Math.sin(th_half * 0.5) * Math.sin(th_half * 0.5) / Math.sin(th_half); var x1 = cx + Math.cos(th0) - t * Math.sin(th0); var y1 = cy + Math.sin(th0) + t * Math.cos(th0); var x3 = cx + Math.cos(th1); var y3 = cy + Math.sin(th1); var x2 = x3 + t * Math.sin(th1); var y2 = y3 - t * Math.cos(th1); segmentToBezierCache[argsString] = [ a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, a00 * x3 + a01 * y3, a10 * x3 + a11 * y3 ]; return segmentToBezierCache[argsString]; } /** * Draws arc * @param {CanvasRenderingContext2D} ctx * @param {Number} x * @param {Number} y * @param {Array} coords */ fabric.util.drawArc = function(ctx, x, y, coords) { var rx = coords[0]; var ry = coords[1]; var rot = coords[2]; var large = coords[3]; var sweep = coords[4]; var ex = coords[5]; var ey = coords[6]; var segs = arcToSegments(ex, ey, rx, ry, large, sweep, rot, x, y); for (var i=0; i