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