1 //= require "object.class"
  2 
  3 (function(global) {
  4   
  5   "use strict";
  6   
  7   var fabric = global.fabric || (global.fabric = { });
  8   
  9   if (fabric.Rect) {
 10     console.warn('fabric.Rect is already defined');
 11     return;
 12   }
 13   
 14   /** 
 15    * @class Rect
 16    * @extends fabric.Object
 17    */
 18   fabric.Rect = fabric.util.createClass(fabric.Object, /** @scope fabric.Rect.prototype */ {
 19     
 20     /**
 21      * @property
 22      * @type String
 23      */
 24     type: 'rect',
 25     
 26     /**
 27      * @property
 28      * @type Object
 29      */
 30     options: {
 31       rx: 0,
 32       ry: 0
 33     },
 34     
 35     /**
 36      * Constructor
 37      * @method initialize
 38      * @param options {Object} options object
 39      * @return {Object} thisArg
 40      */
 41     initialize: function(options) {
 42       this.callSuper('initialize', options);
 43       this._initRxRy();
 44     },
 45     
 46     /**
 47      * @private
 48      * @method _initRxRy
 49      */
 50     _initRxRy: function() {
 51       if (this.options.rx && !this.options.ry) {
 52         this.options.ry = this.options.rx;
 53       }
 54       else if (this.options.ry && !this.options.rx) {
 55         this.options.rx = this.options.ry;
 56       }
 57     },
 58     
 59     /**
 60      * @private
 61      * @method _render
 62      * @param ctx {CanvasRenderingContext2D} context to render on
 63      */
 64     _render: function(ctx) {   
 65       var rx = this.options.rx || 0,
 66           ry = this.options.ry || 0,
 67           x = -this.width / 2,
 68           y = -this.height / 2,
 69           w = this.width,
 70           h = this.height;
 71       
 72       ctx.beginPath();
 73       ctx.moveTo(x+rx, y);
 74       ctx.lineTo(x+w-rx, y);
 75       ctx.bezierCurveTo(x+w, y, x+w, y+ry, x+w, y+ry);
 76       ctx.lineTo(x+w, y+h-ry);
 77       ctx.bezierCurveTo(x+w,y+h,x+w-rx,y+h,x+w-rx,y+h);
 78       ctx.lineTo(x+rx,y+h);
 79       ctx.bezierCurveTo(x,y+h,x,y+h-ry,x,y+h-ry);
 80       ctx.lineTo(x,y+ry);
 81       ctx.bezierCurveTo(x,y,x+rx,y,x+rx,y);
 82       ctx.closePath();
 83       
 84       if (this.fill) {
 85         ctx.fill();
 86       }
 87       if (this.stroke) {
 88         ctx.stroke();
 89       }
 90     },
 91     
 92     // since our coordinate system differs from that of SVG
 93     _normalizeLeftTopProperties: function(parsedAttributes) {
 94       if (parsedAttributes.left) {
 95         this.set('left', parsedAttributes.left + this.getWidth() / 2);
 96       }
 97       if (parsedAttributes.top) {
 98         this.set('top', parsedAttributes.top + this.getHeight() / 2);
 99       }
100       return this;
101     },
102     
103     /**
104      * @method complexity
105      * @return {Number} complexity
106      */
107     complexity: function() {
108       return 1;
109     }
110   });
111   
112   // TODO (kangax): implement rounded rectangles (both parsing and rendering)
113   
114   /**
115    * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`)
116    * @static
117    */
118   fabric.Rect.ATTRIBUTE_NAMES = 'x y width height rx ry fill fill-opacity stroke stroke-width transform'.split(' ');
119   
120   /**
121    * @private
122    */
123   function _setDefaultLeftTopValues(attributes) {
124     attributes.left = attributes.left || 0;
125     attributes.top  = attributes.top  || 0;
126     return attributes;
127   }
128   
129   /**
130    * Returns fabric.Rect instance from an SVG element
131    * @static
132    * @method fabric.Rect.fromElement
133    * @param element {SVGElement} element to parse
134    * @param options {Object} options object
135    * @return {fabric.Rect} instance of fabric.Rect
136    */
137   fabric.Rect.fromElement = function(element, options) {
138     if (!element) {
139       return null;
140     }
141     
142     var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);
143     parsedAttributes = _setDefaultLeftTopValues(parsedAttributes);
144     
145     var rect = new fabric.Rect(fabric.util.object.extend(options || { }, parsedAttributes));
146     rect._normalizeLeftTopProperties(parsedAttributes);
147     
148     return rect;
149   };
150   
151   /**
152    * Returns fabric.Rect instance from an object representation
153    * @static
154    * @method fabric.Rect.fromObject
155    * @param object {Object} object to create an instance from
156    * @return {Object} instance of fabric.Rect
157    */
158   fabric.Rect.fromObject = function(object) {
159     return new fabric.Rect(object);
160   };
161 })(this);