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.Circle) {
 10     fabric.warn('fabric.Circle is already defined.');
 11     return;
 12   }
 13 
 14   /** 
 15    * @class Circle
 16    * @extends fabric.Object
 17    */
 18   fabric.Circle = fabric.util.createClass(fabric.Object, /** @scope fabric.Circle.prototype */ {
 19     
 20     /** @property */
 21     type: 'circle',
 22     
 23     /**
 24      * Constructor
 25      * @method initialize
 26      * @param {Object} [options] Options object
 27      * @return {fabric.Circle} thisArg
 28      */
 29     initialize: function(options) {
 30       options = options || { };
 31       
 32       this.set('radius', options.radius || 0);
 33       this.callSuper('initialize', options);
 34       
 35       var radiusBy2ByScale = this.get('radius') * 2 * this.get('scaleX');
 36       this.set('width', radiusBy2ByScale).set('height', radiusBy2ByScale);
 37     },
 38     
 39     /**
 40      * Returns object representation of an instance
 41      * @method toObject
 42      * @return {Object} object representation of an instance
 43      */
 44     toObject: function() {
 45       return extend(this.callSuper('toObject'), {
 46         radius: this.get('radius')
 47       });
 48     },
 49     
 50     /**
 51      * @private
 52      * @method _render
 53      * @param ctx {CanvasRenderingContext2D} context to render on
 54      */
 55     _render: function(ctx, noTransform) {
 56       ctx.beginPath();
 57       ctx.arc(noTransform ? this.left : 0, noTransform ? this.top : 0, this.radius, 0, piBy2, false);
 58       ctx.closePath();
 59       if (this.fill) {
 60         ctx.fill();
 61       }
 62       if (this.stroke) {
 63         ctx.stroke();
 64       }
 65     },
 66     
 67     
 68     /**
 69      * Returns complexity of an instance
 70      * @method complexity
 71      * @return {Number} complexity of this instance
 72      */
 73     complexity: function() {
 74       return 1;
 75     }
 76   });
 77   
 78   /**
 79    * List of attribute names to account for when parsing SVG element (used by `fabric.Circle.fromElement`)
 80    * @static
 81    * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement
 82    */
 83   fabric.Circle.ATTRIBUTE_NAMES = 'cx cy r fill fill-opacity stroke stroke-width transform'.split(' ');
 84   
 85   /**
 86    * Returns fabric.Circle instance from an SVG element
 87    * @static
 88    * @method fabric.Circle.fromElement
 89    * @param element {SVGElement} element to parse
 90    * @param options {Object} options object
 91    * @throws {Error} If value of `r` attribute is missing or invalid
 92    * @return {Object} instance of fabric.Circle
 93    */
 94   fabric.Circle.fromElement = function(element, options) {
 95     options || (options = { });
 96     var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES);
 97     if (!isValidRadius(parsedAttributes)) {
 98       throw Error('value of `r` attribute is required and can not be negative');
 99     }
100     if ('left' in parsedAttributes) {
101       parsedAttributes.left -= (options.width / 2) || 0;
102     }
103     if ('top' in parsedAttributes) {
104       parsedAttributes.top -= (options.height / 2) || 0;
105     }
106     return new fabric.Circle(extend(parsedAttributes, options));
107   };
108   
109   /**
110    * @private
111    */
112   function isValidRadius(attributes) {
113     return (('radius' in attributes) && (attributes.radius > 0));
114   }
115   
116   /**
117    * Returns fabric.Circle instance from an object representation
118    * @static
119    * @method fabric.Circle.fromObject
120    * @param {Object} object Object to create an instance from
121    * @return {Object} Instance of fabric.Circle
122    */
123   fabric.Circle.fromObject = function(object) {
124     return new fabric.Circle(object);
125   }
126 })();