docs: function arcToSegments(x, y, rx, ry, large, sweep, rotateX, ox, oy) {
      argsStr = join.call(arguments);
      if (arcToSegmentsCache[argsStr]) {
        return arcToSegmentsCache[argsStr];
      }
  
      var th = rotateX * (Math.PI/180);
      var sin_th = Math.sin(th);
      var cos_th = Math.cos(th);
      rx = Math.abs(rx);
      ry = Math.abs(ry);
      var px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5;
      var py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5;
      var pl = (px*px) / (rx*rx) + (py*py) / (ry*ry);
      if (pl > 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;
      var x0 = a00 * ox + a01 * oy;
      var y0 = a10 * ox + a11 * oy;
      var x1 = a00 * x + a01 * y;
      var y1 = a10 * x + a11 * y;
  
      var d = (x1-x0) * (x1-x0) + (y1-y0) * (y1-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 * (x0 + x1) - sfactor * (y1-y0);
      var yc = 0.5 * (y0 + y1) + sfactor * (x1-x0);
  
      var th0 = Math.atan2(y0-yc, x0-xc);
      var th1 = Math.atan2(y1-yc, 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<segments; i++) {
        var th2 = th0 + i * th_arc / segments;
        var th3 = th0 + (i+1) * th_arc / segments;
        result[i] = [xc, yc, th2, th3, rx, ry, sin_th, cos_th];
      }
  
      return (arcToSegmentsCache[argsStr] = result);
    }