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