1 //= require "object.class"
  2 
  3 (function(){
  4   
  5   var fabric = this.fabric || (this.fabric = { }),
  6       piBy2   = Math.PI * 2,
  7       extend = fabric.util.object.extend;
  8   
  9   if (fabric.Ellipse) {
 10     fabric.warn('fabric.Ellipse is already defined.');
 11     return;
 12   }
 13   
 14   /** 
 15    * @class Ellipse
 16    * @extends fabric.Object
 17    */
 18   fabric.Ellipse = fabric.util.createClass(fabric.Object, /** @scope fabric.Ellipse.prototype */ {
 19     
 20     /** @property */
 21     type: 'ellipse',
 22     
 23     /**
 24      * Constructor
 25      * @method initialize
 26      * @param {Object} [options] Options object
 27      * @return {Object} thisArg
 28      */
 29     initialize: function(options) {
 30       options = options || { };
 31       
 32       this.callSuper('initialize', options);
 33       
 34       this.set('rx', options.rx || 0);
 35       this.set('ry', options.ry || 0);
 36       
 37       this.set('width', this.get('rx') * 2);
 38       this.set('height', this.get('ry') * 2);
 39     },
 40     
 41     /**
 42      * Returns object representation of an instance
 43      * @method toObject
 44      * @return {Object} object representation of an instance
 45      */
 46     toObject: function() {
 47       return extend(this.callSuper('toObject'), {
 48         rx: this.get('rx'),
 49         ry: this.get('ry')
 50       });
 51     },
 52     
 53     /**
 54      * @method render
 55      * @param ctx {CanvasRenderingContext2D} context to render on
 56      * @param noTransform {Boolean} context is not transformed when set to true
 57      */
 58     render: function(ctx, noTransform) {
 59       // do not use `get` for perf. reasons
 60       if (this.rx === 0 || this.ry === 0) return;
 61       return this.callSuper('render', ctx, noTransform);
 62     },
 63     
 64     /**
 65      * @private
 66      * @method _render
 67      * @param ctx {CanvasRenderingContext2D} context to render on
 68      */
 69     _render: function(ctx, noTransform) {
 70       ctx.beginPath();
 71       ctx.save();
 72       ctx.transform(1, 0, 0, this.ry/this.rx, 0, 0);
 73       ctx.arc(noTransform ? this.left : 0, noTransform ? this.top : 0, this.rx, 0, piBy2, false);
 74       ctx.restore();
 75       if (this.stroke) {
 76         ctx.stroke();
 77       }
 78       if (this.fill) {
 79         ctx.fill();
 80       }
 81     },
 82     
 83     /**
 84      * @method complexity
 85      * @return {Number} complexity
 86      */
 87     complexity: function() {
 88       return 1;
 89     }
 90   });
 91   
 92   fabric.Ellipse.ATTRIBUTE_NAMES = 'cx cy rx ry fill fill-opacity stroke stroke-width transform'.split(' ');
 93   
 94   /**
 95    * Returns fabric.Ellipse instance from an SVG element
 96    * @static
 97    * @method fabric.Ellipse.fromElement
 98    * @param {SVGElement} element Element to parse
 99    * @param {Object} [options] Options object
100    * @return {fabric.Ellipse}
101    */
102   fabric.Ellipse.fromElement = function(element, options) {
103     options || (options = { });
104     var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES);
105     if ('left' in parsedAttributes) {
106       parsedAttributes.left -= (options.width / 2) || 0;
107     }
108     if ('top' in parsedAttributes) {
109       parsedAttributes.top -= (options.height / 2) || 0;
110     }
111     return new fabric.Ellipse(extend(parsedAttributes, options));
112   };
113   
114   /**
115    * Returns fabric.Ellipse instance from an object representation
116    * @static
117    * @method fabric.Ellipse.fromObject
118    * @param {Object} object Object to create an instance from
119    * @return {fabric.Ellipse}
120    */
121   fabric.Ellipse.fromObject = function(object) {
122     return new fabric.Ellipse(object);
123   }
124 })();