28cd9b1fc703cb8b2a3d470dd76aa3e3.json 2.66 MB
{"ast":null,"code":"/* build: `node build.js modules=ALL exclude=gestures,accessors requirejs minifier=uglifyjs` */\n\n/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */\nvar fabric = fabric || {\n  version: '4.2.0'\n};\n\nif (typeof exports !== 'undefined') {\n  exports.fabric = fabric;\n}\n/* _AMD_START_ */\nelse if (typeof define === 'function' && define.amd) {\n    define([], function () {\n      return fabric;\n    });\n  }\n/* _AMD_END_ */\n\n\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\n  if (document instanceof (typeof HTMLDocument !== 'undefined' ? HTMLDocument : Document)) {\n    fabric.document = document;\n  } else {\n    fabric.document = document.implementation.createHTMLDocument('');\n  }\n\n  fabric.window = window;\n} else {\n  // assume we're running under node.js when document/window are not present\n  var jsdom = require('jsdom');\n\n  var virtualWindow = new jsdom.JSDOM(decodeURIComponent('%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E'), {\n    features: {\n      FetchExternalResources: ['img']\n    },\n    resources: 'usable'\n  }).window;\n  fabric.document = virtualWindow.document;\n  fabric.jsdomImplForWrapper = require('jsdom/lib/jsdom/living/generated/utils').implForWrapper;\n  fabric.nodeCanvas = require('jsdom/lib/jsdom/utils').Canvas;\n  fabric.window = virtualWindow;\n  DOMParser = fabric.window.DOMParser;\n}\n/**\n * True when in environment that supports touch events\n * @type boolean\n */\n\n\nfabric.isTouchSupported = 'ontouchstart' in fabric.window || 'ontouchstart' in fabric.document || fabric.window && fabric.window.navigator && fabric.window.navigator.maxTouchPoints > 0;\n/**\n * True when in environment that's probably Node.js\n * @type boolean\n */\n\nfabric.isLikelyNode = typeof Buffer !== 'undefined' && typeof window === 'undefined';\n/* _FROM_SVG_START_ */\n\n/**\n * Attributes parsed from all SVG elements\n * @type array\n */\n\nfabric.SHARED_ATTRIBUTES = ['display', 'transform', 'fill', 'fill-opacity', 'fill-rule', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-linecap', 'stroke-dashoffset', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'id', 'paint-order', 'vector-effect', 'instantiated_by_use', 'clip-path'];\n/* _FROM_SVG_END_ */\n\n/**\n * Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion.\n */\n\nfabric.DPI = 96;\nfabric.reNum = '(?:[-+]?(?:\\\\d+|\\\\d*\\\\.\\\\d+)(?:[eE][-+]?\\\\d+)?)';\nfabric.commaWsp = '(?:\\\\s+,?\\\\s*|,\\\\s*)';\nfabric.rePathCommand = /([-+]?((\\d+\\.\\d+)|((\\d+)|(\\.\\d+)))(?:[eE][-+]?\\d+)?)/ig;\nfabric.reNonWord = /[ \\n\\.,;!\\?\\-]/;\nfabric.fontPaths = {};\nfabric.iMatrix = [1, 0, 0, 1, 0, 0];\nfabric.svgNS = 'http://www.w3.org/2000/svg';\n/**\n * Pixel limit for cache canvases. 1Mpx , 4Mpx should be fine.\n * @since 1.7.14\n * @type Number\n * @default\n */\n\nfabric.perfLimitSizeTotal = 2097152;\n/**\n * Pixel limit for cache canvases width or height. IE fixes the maximum at 5000\n * @since 1.7.14\n * @type Number\n * @default\n */\n\nfabric.maxCacheSideLimit = 4096;\n/**\n * Lowest pixel limit for cache canvases, set at 256PX\n * @since 1.7.14\n * @type Number\n * @default\n */\n\nfabric.minCacheSideLimit = 256;\n/**\n * Cache Object for widths of chars in text rendering.\n */\n\nfabric.charWidthsCache = {};\n/**\n * if webgl is enabled and available, textureSize will determine the size\n * of the canvas backend\n * @since 2.0.0\n * @type Number\n * @default\n */\n\nfabric.textureSize = 2048;\n/**\n * When 'true', style information is not retained when copy/pasting text, making\n * pasted text use destination style.\n * Defaults to 'false'.\n * @type Boolean\n * @default\n */\n\nfabric.disableStyleCopyPaste = false;\n/**\n * Enable webgl for filtering picture is available\n * A filtering backend will be initialized, this will both take memory and\n * time since a default 2048x2048 canvas will be created for the gl context\n * @since 2.0.0\n * @type Boolean\n * @default\n */\n\nfabric.enableGLFiltering = true;\n/**\n * Device Pixel Ratio\n * @see https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/SettingUptheCanvas.html\n */\n\nfabric.devicePixelRatio = fabric.window.devicePixelRatio || fabric.window.webkitDevicePixelRatio || fabric.window.mozDevicePixelRatio || 1;\n/**\n * Browser-specific constant to adjust CanvasRenderingContext2D.shadowBlur value,\n * which is unitless and not rendered equally across browsers.\n *\n * Values that work quite well (as of October 2017) are:\n * - Chrome: 1.5\n * - Edge: 1.75\n * - Firefox: 0.9\n * - Safari: 0.95\n *\n * @since 2.0.0\n * @type Number\n * @default 1\n */\n\nfabric.browserShadowBlurConstant = 1;\n/**\n * This object contains the result of arc to beizer conversion for faster retrieving if the same arc needs to be converted again.\n * It was an internal variable, is accessible since version 2.3.4\n */\n\nfabric.arcToSegmentsCache = {};\n/**\n * This object keeps the results of the boundsOfCurve calculation mapped by the joined arguments necessary to calculate it.\n * It does speed up calculation, if you parse and add always the same paths, but in case of heavy usage of freedrawing\n * you do not get any speed benefit and you get a big object in memory.\n * The object was a private variable before, while now is appended to the lib so that you have access to it and you\n * can eventually clear it.\n * It was an internal variable, is accessible since version 2.3.4\n */\n\nfabric.boundsOfCurveCache = {};\n/**\n * If disabled boundsOfCurveCache is not used. For apps that make heavy usage of pencil drawing probably disabling it is better\n * @default true\n */\n\nfabric.cachesBoundsOfCurve = true;\n/**\n * Skip performance testing of setupGLContext and force the use of putImageData that seems to be the one that works best on\n * Chrome + old hardware. if your users are experiencing empty images after filtering you may try to force this to true\n * this has to be set before instantiating the filtering backend ( before filtering the first image )\n * @type Boolean\n * @default false\n */\n\nfabric.forceGLPutImageData = false;\n\nfabric.initFilterBackend = function () {\n  if (fabric.enableGLFiltering && fabric.isWebglSupported && fabric.isWebglSupported(fabric.textureSize)) {\n    console.log('max texture size: ' + fabric.maxTextureSize);\n    return new fabric.WebglFilterBackend({\n      tileSize: fabric.textureSize\n    });\n  } else if (fabric.Canvas2dFilterBackend) {\n    return new fabric.Canvas2dFilterBackend();\n  }\n};\n\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\n  // ensure globality even if entire library were function wrapped (as in Meteor.js packaging system)\n  window.fabric = fabric;\n}\n\n(function () {\n  /**\n   * @private\n   * @param {String} eventName\n   * @param {Function} handler\n   */\n  function _removeEventListener(eventName, handler) {\n    if (!this.__eventListeners[eventName]) {\n      return;\n    }\n\n    var eventListener = this.__eventListeners[eventName];\n\n    if (handler) {\n      eventListener[eventListener.indexOf(handler)] = false;\n    } else {\n      fabric.util.array.fill(eventListener, false);\n    }\n  }\n  /**\n   * Observes specified event\n   * @memberOf fabric.Observable\n   * @alias on\n   * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n   * @param {Function} handler Function that receives a notification when an event of the specified type occurs\n   * @return {Self} thisArg\n   * @chainable\n   */\n\n\n  function on(eventName, handler) {\n    if (!this.__eventListeners) {\n      this.__eventListeners = {};\n    } // one object with key/value pairs was passed\n\n\n    if (arguments.length === 1) {\n      for (var prop in eventName) {\n        this.on(prop, eventName[prop]);\n      }\n    } else {\n      if (!this.__eventListeners[eventName]) {\n        this.__eventListeners[eventName] = [];\n      }\n\n      this.__eventListeners[eventName].push(handler);\n    }\n\n    return this;\n  }\n  /**\n   * Stops event observing for a particular event handler. Calling this method\n   * without arguments removes all handlers for all events\n   * @memberOf fabric.Observable\n   * @alias off\n   * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n   * @param {Function} handler Function to be deleted from EventListeners\n   * @return {Self} thisArg\n   * @chainable\n   */\n\n\n  function off(eventName, handler) {\n    if (!this.__eventListeners) {\n      return this;\n    } // remove all key/value pairs (event name -> event handler)\n\n\n    if (arguments.length === 0) {\n      for (eventName in this.__eventListeners) {\n        _removeEventListener.call(this, eventName);\n      }\n    } // one object with key/value pairs was passed\n    else if (arguments.length === 1 && typeof arguments[0] === 'object') {\n        for (var prop in eventName) {\n          _removeEventListener.call(this, prop, eventName[prop]);\n        }\n      } else {\n        _removeEventListener.call(this, eventName, handler);\n      }\n\n    return this;\n  }\n  /**\n   * Fires event with an optional options object\n   * @memberOf fabric.Observable\n   * @param {String} eventName Event name to fire\n   * @param {Object} [options] Options object\n   * @return {Self} thisArg\n   * @chainable\n   */\n\n\n  function fire(eventName, options) {\n    if (!this.__eventListeners) {\n      return this;\n    }\n\n    var listenersForEvent = this.__eventListeners[eventName];\n\n    if (!listenersForEvent) {\n      return this;\n    }\n\n    for (var i = 0, len = listenersForEvent.length; i < len; i++) {\n      listenersForEvent[i] && listenersForEvent[i].call(this, options || {});\n    }\n\n    this.__eventListeners[eventName] = listenersForEvent.filter(function (value) {\n      return value !== false;\n    });\n    return this;\n  }\n  /**\n   * @namespace fabric.Observable\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#events}\n   * @see {@link http://fabricjs.com/events|Events demo}\n   */\n\n\n  fabric.Observable = {\n    fire: fire,\n    on: on,\n    off: off\n  };\n})();\n/**\n * @namespace fabric.Collection\n */\n\n\nfabric.Collection = {\n  _objects: [],\n\n  /**\n   * Adds objects to collection, Canvas or Group, then renders canvas\n   * (if `renderOnAddRemove` is not `false`).\n   * in case of Group no changes to bounding box are made.\n   * Objects should be instances of (or inherit from) fabric.Object\n   * Use of this function is highly discouraged for groups.\n   * you can add a bunch of objects with the add method but then you NEED\n   * to run a addWithUpdate call for the Group class or position/bbox will be wrong.\n   * @param {...fabric.Object} object Zero or more fabric instances\n   * @return {Self} thisArg\n   * @chainable\n   */\n  add: function () {\n    this._objects.push.apply(this._objects, arguments);\n\n    if (this._onObjectAdded) {\n      for (var i = 0, length = arguments.length; i < length; i++) {\n        this._onObjectAdded(arguments[i]);\n      }\n    }\n\n    this.renderOnAddRemove && this.requestRenderAll();\n    return this;\n  },\n\n  /**\n   * Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`)\n   * An object should be an instance of (or inherit from) fabric.Object\n   * Use of this function is highly discouraged for groups.\n   * you can add a bunch of objects with the insertAt method but then you NEED\n   * to run a addWithUpdate call for the Group class or position/bbox will be wrong.\n   * @param {Object} object Object to insert\n   * @param {Number} index Index to insert object at\n   * @param {Boolean} nonSplicing When `true`, no splicing (shifting) of objects occurs\n   * @return {Self} thisArg\n   * @chainable\n   */\n  insertAt: function (object, index, nonSplicing) {\n    var objects = this._objects;\n\n    if (nonSplicing) {\n      objects[index] = object;\n    } else {\n      objects.splice(index, 0, object);\n    }\n\n    this._onObjectAdded && this._onObjectAdded(object);\n    this.renderOnAddRemove && this.requestRenderAll();\n    return this;\n  },\n\n  /**\n   * Removes objects from a collection, then renders canvas (if `renderOnAddRemove` is not `false`)\n   * @param {...fabric.Object} object Zero or more fabric instances\n   * @return {Self} thisArg\n   * @chainable\n   */\n  remove: function () {\n    var objects = this._objects,\n        index,\n        somethingRemoved = false;\n\n    for (var i = 0, length = arguments.length; i < length; i++) {\n      index = objects.indexOf(arguments[i]); // only call onObjectRemoved if an object was actually removed\n\n      if (index !== -1) {\n        somethingRemoved = true;\n        objects.splice(index, 1);\n        this._onObjectRemoved && this._onObjectRemoved(arguments[i]);\n      }\n    }\n\n    this.renderOnAddRemove && somethingRemoved && this.requestRenderAll();\n    return this;\n  },\n\n  /**\n   * Executes given function for each object in this group\n   * @param {Function} callback\n   *                   Callback invoked with current object as first argument,\n   *                   index - as second and an array of all objects - as third.\n   *                   Callback is invoked in a context of Global Object (e.g. `window`)\n   *                   when no `context` argument is given\n   *\n   * @param {Object} context Context (aka thisObject)\n   * @return {Self} thisArg\n   * @chainable\n   */\n  forEachObject: function (callback, context) {\n    var objects = this.getObjects();\n\n    for (var i = 0, len = objects.length; i < len; i++) {\n      callback.call(context, objects[i], i, objects);\n    }\n\n    return this;\n  },\n\n  /**\n   * Returns an array of children objects of this instance\n   * Type parameter introduced in 1.3.10\n   * since 2.3.5 this method return always a COPY of the array;\n   * @param {String} [type] When specified, only objects of this type are returned\n   * @return {Array}\n   */\n  getObjects: function (type) {\n    if (typeof type === 'undefined') {\n      return this._objects.concat();\n    }\n\n    return this._objects.filter(function (o) {\n      return o.type === type;\n    });\n  },\n\n  /**\n   * Returns object at specified index\n   * @param {Number} index\n   * @return {Self} thisArg\n   */\n  item: function (index) {\n    return this._objects[index];\n  },\n\n  /**\n   * Returns true if collection contains no objects\n   * @return {Boolean} true if collection is empty\n   */\n  isEmpty: function () {\n    return this._objects.length === 0;\n  },\n\n  /**\n   * Returns a size of a collection (i.e: length of an array containing its objects)\n   * @return {Number} Collection size\n   */\n  size: function () {\n    return this._objects.length;\n  },\n\n  /**\n   * Returns true if collection contains an object\n   * @param {Object} object Object to check against\n   * @return {Boolean} `true` if collection contains an object\n   */\n  contains: function (object) {\n    return this._objects.indexOf(object) > -1;\n  },\n\n  /**\n   * Returns number representation of a collection complexity\n   * @return {Number} complexity\n   */\n  complexity: function () {\n    return this._objects.reduce(function (memo, current) {\n      memo += current.complexity ? current.complexity() : 0;\n      return memo;\n    }, 0);\n  }\n};\n/**\n * @namespace fabric.CommonMethods\n */\n\nfabric.CommonMethods = {\n  /**\n   * Sets object's properties from options\n   * @param {Object} [options] Options object\n   */\n  _setOptions: function (options) {\n    for (var prop in options) {\n      this.set(prop, options[prop]);\n    }\n  },\n\n  /**\n   * @private\n   * @param {Object} [filler] Options object\n   * @param {String} [property] property to set the Gradient to\n   */\n  _initGradient: function (filler, property) {\n    if (filler && filler.colorStops && !(filler instanceof fabric.Gradient)) {\n      this.set(property, new fabric.Gradient(filler));\n    }\n  },\n\n  /**\n   * @private\n   * @param {Object} [filler] Options object\n   * @param {String} [property] property to set the Pattern to\n   * @param {Function} [callback] callback to invoke after pattern load\n   */\n  _initPattern: function (filler, property, callback) {\n    if (filler && filler.source && !(filler instanceof fabric.Pattern)) {\n      this.set(property, new fabric.Pattern(filler, callback));\n    } else {\n      callback && callback();\n    }\n  },\n\n  /**\n   * @private\n   */\n  _setObject: function (obj) {\n    for (var prop in obj) {\n      this._set(prop, obj[prop]);\n    }\n  },\n\n  /**\n   * Sets property to a given value. When changing position/dimension -related properties (left, top, scale, angle, etc.) `set` does not update position of object's borders/controls. If you need to update those, call `setCoords()`.\n   * @param {String|Object} key Property name or object (if object, iterate over the object properties)\n   * @param {Object|Function} value Property value (if function, the value is passed into it and its return value is used as a new one)\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  set: function (key, value) {\n    if (typeof key === 'object') {\n      this._setObject(key);\n    } else {\n      this._set(key, value);\n    }\n\n    return this;\n  },\n  _set: function (key, value) {\n    this[key] = value;\n  },\n\n  /**\n   * Toggles specified property from `true` to `false` or from `false` to `true`\n   * @param {String} property Property to toggle\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  toggle: function (property) {\n    var value = this.get(property);\n\n    if (typeof value === 'boolean') {\n      this.set(property, !value);\n    }\n\n    return this;\n  },\n\n  /**\n   * Basic getter\n   * @param {String} property Property name\n   * @return {*} value of a property\n   */\n  get: function (property) {\n    return this[property];\n  }\n};\n\n(function (global) {\n  var sqrt = Math.sqrt,\n      atan2 = Math.atan2,\n      pow = Math.pow,\n      PiBy180 = Math.PI / 180,\n      PiBy2 = Math.PI / 2;\n  /**\n   * @namespace fabric.util\n   */\n\n  fabric.util = {\n    /**\n     * Calculate the cos of an angle, avoiding returning floats for known results\n     * @static\n     * @memberOf fabric.util\n     * @param {Number} angle the angle in radians or in degree\n     * @return {Number}\n     */\n    cos: function (angle) {\n      if (angle === 0) {\n        return 1;\n      }\n\n      if (angle < 0) {\n        // cos(a) = cos(-a)\n        angle = -angle;\n      }\n\n      var angleSlice = angle / PiBy2;\n\n      switch (angleSlice) {\n        case 1:\n        case 3:\n          return 0;\n\n        case 2:\n          return -1;\n      }\n\n      return Math.cos(angle);\n    },\n\n    /**\n     * Calculate the sin of an angle, avoiding returning floats for known results\n     * @static\n     * @memberOf fabric.util\n     * @param {Number} angle the angle in radians or in degree\n     * @return {Number}\n     */\n    sin: function (angle) {\n      if (angle === 0) {\n        return 0;\n      }\n\n      var angleSlice = angle / PiBy2,\n          sign = 1;\n\n      if (angle < 0) {\n        // sin(-a) = -sin(a)\n        sign = -1;\n      }\n\n      switch (angleSlice) {\n        case 1:\n          return sign;\n\n        case 2:\n          return 0;\n\n        case 3:\n          return -sign;\n      }\n\n      return Math.sin(angle);\n    },\n\n    /**\n     * Removes value from an array.\n     * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf`\n     * @static\n     * @memberOf fabric.util\n     * @param {Array} array\n     * @param {*} value\n     * @return {Array} original array\n     */\n    removeFromArray: function (array, value) {\n      var idx = array.indexOf(value);\n\n      if (idx !== -1) {\n        array.splice(idx, 1);\n      }\n\n      return array;\n    },\n\n    /**\n     * Returns random number between 2 specified ones.\n     * @static\n     * @memberOf fabric.util\n     * @param {Number} min lower limit\n     * @param {Number} max upper limit\n     * @return {Number} random value (between min and max)\n     */\n    getRandomInt: function (min, max) {\n      return Math.floor(Math.random() * (max - min + 1)) + min;\n    },\n\n    /**\n     * Transforms degrees to radians.\n     * @static\n     * @memberOf fabric.util\n     * @param {Number} degrees value in degrees\n     * @return {Number} value in radians\n     */\n    degreesToRadians: function (degrees) {\n      return degrees * PiBy180;\n    },\n\n    /**\n     * Transforms radians to degrees.\n     * @static\n     * @memberOf fabric.util\n     * @param {Number} radians value in radians\n     * @return {Number} value in degrees\n     */\n    radiansToDegrees: function (radians) {\n      return radians / PiBy180;\n    },\n\n    /**\n     * Rotates `point` around `origin` with `radians`\n     * @static\n     * @memberOf fabric.util\n     * @param {fabric.Point} point The point to rotate\n     * @param {fabric.Point} origin The origin of the rotation\n     * @param {Number} radians The radians of the angle for the rotation\n     * @return {fabric.Point} The new rotated point\n     */\n    rotatePoint: function (point, origin, radians) {\n      point.subtractEquals(origin);\n      var v = fabric.util.rotateVector(point, radians);\n      return new fabric.Point(v.x, v.y).addEquals(origin);\n    },\n\n    /**\n     * Rotates `vector` with `radians`\n     * @static\n     * @memberOf fabric.util\n     * @param {Object} vector The vector to rotate (x and y)\n     * @param {Number} radians The radians of the angle for the rotation\n     * @return {Object} The new rotated point\n     */\n    rotateVector: function (vector, radians) {\n      var sin = fabric.util.sin(radians),\n          cos = fabric.util.cos(radians),\n          rx = vector.x * cos - vector.y * sin,\n          ry = vector.x * sin + vector.y * cos;\n      return {\n        x: rx,\n        y: ry\n      };\n    },\n\n    /**\n     * Apply transform t to point p\n     * @static\n     * @memberOf fabric.util\n     * @param  {fabric.Point} p The point to transform\n     * @param  {Array} t The transform\n     * @param  {Boolean} [ignoreOffset] Indicates that the offset should not be applied\n     * @return {fabric.Point} The transformed point\n     */\n    transformPoint: function (p, t, ignoreOffset) {\n      if (ignoreOffset) {\n        return new fabric.Point(t[0] * p.x + t[2] * p.y, t[1] * p.x + t[3] * p.y);\n      }\n\n      return new fabric.Point(t[0] * p.x + t[2] * p.y + t[4], t[1] * p.x + t[3] * p.y + t[5]);\n    },\n\n    /**\n     * Returns coordinates of points's bounding rectangle (left, top, width, height)\n     * @param {Array} points 4 points array\n     * @param {Array} [transform] an array of 6 numbers representing a 2x3 transform matrix\n     * @return {Object} Object with left, top, width, height properties\n     */\n    makeBoundingBoxFromPoints: function (points, transform) {\n      if (transform) {\n        for (var i = 0; i < points.length; i++) {\n          points[i] = fabric.util.transformPoint(points[i], transform);\n        }\n      }\n\n      var xPoints = [points[0].x, points[1].x, points[2].x, points[3].x],\n          minX = fabric.util.array.min(xPoints),\n          maxX = fabric.util.array.max(xPoints),\n          width = maxX - minX,\n          yPoints = [points[0].y, points[1].y, points[2].y, points[3].y],\n          minY = fabric.util.array.min(yPoints),\n          maxY = fabric.util.array.max(yPoints),\n          height = maxY - minY;\n      return {\n        left: minX,\n        top: minY,\n        width: width,\n        height: height\n      };\n    },\n\n    /**\n     * Invert transformation t\n     * @static\n     * @memberOf fabric.util\n     * @param {Array} t The transform\n     * @return {Array} The inverted transform\n     */\n    invertTransform: function (t) {\n      var a = 1 / (t[0] * t[3] - t[1] * t[2]),\n          r = [a * t[3], -a * t[1], -a * t[2], a * t[0]],\n          o = fabric.util.transformPoint({\n        x: t[4],\n        y: t[5]\n      }, r, true);\n      r[4] = -o.x;\n      r[5] = -o.y;\n      return r;\n    },\n\n    /**\n     * A wrapper around Number#toFixed, which contrary to native method returns number, not string.\n     * @static\n     * @memberOf fabric.util\n     * @param {Number|String} number number to operate on\n     * @param {Number} fractionDigits number of fraction digits to \"leave\"\n     * @return {Number}\n     */\n    toFixed: function (number, fractionDigits) {\n      return parseFloat(Number(number).toFixed(fractionDigits));\n    },\n\n    /**\n     * Converts from attribute value to pixel value if applicable.\n     * Returns converted pixels or original value not converted.\n     * @param {Number|String} value number to operate on\n     * @param {Number} fontSize\n     * @return {Number|String}\n     */\n    parseUnit: function (value, fontSize) {\n      var unit = /\\D{0,2}$/.exec(value),\n          number = parseFloat(value);\n\n      if (!fontSize) {\n        fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;\n      }\n\n      switch (unit[0]) {\n        case 'mm':\n          return number * fabric.DPI / 25.4;\n\n        case 'cm':\n          return number * fabric.DPI / 2.54;\n\n        case 'in':\n          return number * fabric.DPI;\n\n        case 'pt':\n          return number * fabric.DPI / 72;\n        // or * 4 / 3\n\n        case 'pc':\n          return number * fabric.DPI / 72 * 12;\n        // or * 16\n\n        case 'em':\n          return number * fontSize;\n\n        default:\n          return number;\n      }\n    },\n\n    /**\n     * Function which always returns `false`.\n     * @static\n     * @memberOf fabric.util\n     * @return {Boolean}\n     */\n    falseFunction: function () {\n      return false;\n    },\n\n    /**\n     * Returns klass \"Class\" object of given namespace\n     * @memberOf fabric.util\n     * @param {String} type Type of object (eg. 'circle')\n     * @param {String} namespace Namespace to get klass \"Class\" object from\n     * @return {Object} klass \"Class\"\n     */\n    getKlass: function (type, namespace) {\n      // capitalize first letter only\n      type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1));\n      return fabric.util.resolveNamespace(namespace)[type];\n    },\n\n    /**\n     * Returns array of attributes for given svg that fabric parses\n     * @memberOf fabric.util\n     * @param {String} type Type of svg element (eg. 'circle')\n     * @return {Array} string names of supported attributes\n     */\n    getSvgAttributes: function (type) {\n      var attributes = ['instantiated_by_use', 'style', 'id', 'class'];\n\n      switch (type) {\n        case 'linearGradient':\n          attributes = attributes.concat(['x1', 'y1', 'x2', 'y2', 'gradientUnits', 'gradientTransform']);\n          break;\n\n        case 'radialGradient':\n          attributes = attributes.concat(['gradientUnits', 'gradientTransform', 'cx', 'cy', 'r', 'fx', 'fy', 'fr']);\n          break;\n\n        case 'stop':\n          attributes = attributes.concat(['offset', 'stop-color', 'stop-opacity']);\n          break;\n      }\n\n      return attributes;\n    },\n\n    /**\n     * Returns object of given namespace\n     * @memberOf fabric.util\n     * @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric'\n     * @return {Object} Object for given namespace (default fabric)\n     */\n    resolveNamespace: function (namespace) {\n      if (!namespace) {\n        return fabric;\n      }\n\n      var parts = namespace.split('.'),\n          len = parts.length,\n          i,\n          obj = global || fabric.window;\n\n      for (i = 0; i < len; ++i) {\n        obj = obj[parts[i]];\n      }\n\n      return obj;\n    },\n\n    /**\n     * Loads image element from given url and passes it to a callback\n     * @memberOf fabric.util\n     * @param {String} url URL representing an image\n     * @param {Function} callback Callback; invoked with loaded image\n     * @param {*} [context] Context to invoke callback in\n     * @param {Object} [crossOrigin] crossOrigin value to set image element to\n     */\n    loadImage: function (url, callback, context, crossOrigin) {\n      if (!url) {\n        callback && callback.call(context, url);\n        return;\n      }\n\n      var img = fabric.util.createImage();\n      /** @ignore */\n\n      var onLoadCallback = function () {\n        callback && callback.call(context, img, false);\n        img = img.onload = img.onerror = null;\n      };\n\n      img.onload = onLoadCallback;\n      /** @ignore */\n\n      img.onerror = function () {\n        fabric.log('Error loading ' + img.src);\n        callback && callback.call(context, null, true);\n        img = img.onload = img.onerror = null;\n      }; // data-urls appear to be buggy with crossOrigin\n      // https://github.com/kangax/fabric.js/commit/d0abb90f1cd5c5ef9d2a94d3fb21a22330da3e0a#commitcomment-4513767\n      // see https://code.google.com/p/chromium/issues/detail?id=315152\n      //     https://bugzilla.mozilla.org/show_bug.cgi?id=935069\n      // crossOrigin null is the same as not set.\n\n\n      if (url.indexOf('data') !== 0 && crossOrigin !== undefined && crossOrigin !== null) {\n        img.crossOrigin = crossOrigin;\n      } // IE10 / IE11-Fix: SVG contents from data: URI\n      // will only be available if the IMG is present\n      // in the DOM (and visible)\n\n\n      if (url.substring(0, 14) === 'data:image/svg') {\n        img.onload = null;\n        fabric.util.loadImageInDom(img, onLoadCallback);\n      }\n\n      img.src = url;\n    },\n\n    /**\n     * Attaches SVG image with data: URL to the dom\n     * @memberOf fabric.util\n     * @param {Object} img Image object with data:image/svg src\n     * @param {Function} callback Callback; invoked with loaded image\n     * @return {Object} DOM element (div containing the SVG image)\n     */\n    loadImageInDom: function (img, onLoadCallback) {\n      var div = fabric.document.createElement('div');\n      div.style.width = div.style.height = '1px';\n      div.style.left = div.style.top = '-100%';\n      div.style.position = 'absolute';\n      div.appendChild(img);\n      fabric.document.querySelector('body').appendChild(div);\n      /**\n       * Wrap in function to:\n       *   1. Call existing callback\n       *   2. Cleanup DOM\n       */\n\n      img.onload = function () {\n        onLoadCallback();\n        div.parentNode.removeChild(div);\n        div = null;\n      };\n    },\n\n    /**\n     * Creates corresponding fabric instances from their object representations\n     * @static\n     * @memberOf fabric.util\n     * @param {Array} objects Objects to enliven\n     * @param {Function} callback Callback to invoke when all objects are created\n     * @param {String} namespace Namespace to get klass \"Class\" object from\n     * @param {Function} reviver Method for further parsing of object elements,\n     * called after each fabric object created.\n     */\n    enlivenObjects: function (objects, callback, namespace, reviver) {\n      objects = objects || [];\n      var enlivenedObjects = [],\n          numLoadedObjects = 0,\n          numTotalObjects = objects.length;\n\n      function onLoaded() {\n        if (++numLoadedObjects === numTotalObjects) {\n          callback && callback(enlivenedObjects.filter(function (obj) {\n            // filter out undefined objects (objects that gave error)\n            return obj;\n          }));\n        }\n      }\n\n      if (!numTotalObjects) {\n        callback && callback(enlivenedObjects);\n        return;\n      }\n\n      objects.forEach(function (o, index) {\n        // if sparse array\n        if (!o || !o.type) {\n          onLoaded();\n          return;\n        }\n\n        var klass = fabric.util.getKlass(o.type, namespace);\n        klass.fromObject(o, function (obj, error) {\n          error || (enlivenedObjects[index] = obj);\n          reviver && reviver(o, obj, error);\n          onLoaded();\n        });\n      });\n    },\n\n    /**\n     * Create and wait for loading of patterns\n     * @static\n     * @memberOf fabric.util\n     * @param {Array} patterns Objects to enliven\n     * @param {Function} callback Callback to invoke when all objects are created\n     * called after each fabric object created.\n     */\n    enlivenPatterns: function (patterns, callback) {\n      patterns = patterns || [];\n\n      function onLoaded() {\n        if (++numLoadedPatterns === numPatterns) {\n          callback && callback(enlivenedPatterns);\n        }\n      }\n\n      var enlivenedPatterns = [],\n          numLoadedPatterns = 0,\n          numPatterns = patterns.length;\n\n      if (!numPatterns) {\n        callback && callback(enlivenedPatterns);\n        return;\n      }\n\n      patterns.forEach(function (p, index) {\n        if (p && p.source) {\n          new fabric.Pattern(p, function (pattern) {\n            enlivenedPatterns[index] = pattern;\n            onLoaded();\n          });\n        } else {\n          enlivenedPatterns[index] = p;\n          onLoaded();\n        }\n      });\n    },\n\n    /**\n     * Groups SVG elements (usually those retrieved from SVG document)\n     * @static\n     * @memberOf fabric.util\n     * @param {Array} elements SVG elements to group\n     * @param {Object} [options] Options object\n     * @param {String} path Value to set sourcePath to\n     * @return {fabric.Object|fabric.Group}\n     */\n    groupSVGElements: function (elements, options, path) {\n      var object;\n\n      if (elements && elements.length === 1) {\n        return elements[0];\n      }\n\n      if (options) {\n        if (options.width && options.height) {\n          options.centerPoint = {\n            x: options.width / 2,\n            y: options.height / 2\n          };\n        } else {\n          delete options.width;\n          delete options.height;\n        }\n      }\n\n      object = new fabric.Group(elements, options);\n\n      if (typeof path !== 'undefined') {\n        object.sourcePath = path;\n      }\n\n      return object;\n    },\n\n    /**\n     * Populates an object with properties of another object\n     * @static\n     * @memberOf fabric.util\n     * @param {Object} source Source object\n     * @param {Object} destination Destination object\n     * @return {Array} properties Properties names to include\n     */\n    populateWithProperties: function (source, destination, properties) {\n      if (properties && Object.prototype.toString.call(properties) === '[object Array]') {\n        for (var i = 0, len = properties.length; i < len; i++) {\n          if (properties[i] in source) {\n            destination[properties[i]] = source[properties[i]];\n          }\n        }\n      }\n    },\n\n    /**\n     * Draws a dashed line between two points\n     *\n     * This method is used to draw dashed line around selection area.\n     * See <a href=\"http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas\">dotted stroke in canvas</a>\n     *\n     * @param {CanvasRenderingContext2D} ctx context\n     * @param {Number} x  start x coordinate\n     * @param {Number} y start y coordinate\n     * @param {Number} x2 end x coordinate\n     * @param {Number} y2 end y coordinate\n     * @param {Array} da dash array pattern\n     */\n    drawDashedLine: function (ctx, x, y, x2, y2, da) {\n      var dx = x2 - x,\n          dy = y2 - y,\n          len = sqrt(dx * dx + dy * dy),\n          rot = atan2(dy, dx),\n          dc = da.length,\n          di = 0,\n          draw = true;\n      ctx.save();\n      ctx.translate(x, y);\n      ctx.moveTo(0, 0);\n      ctx.rotate(rot);\n      x = 0;\n\n      while (len > x) {\n        x += da[di++ % dc];\n\n        if (x > len) {\n          x = len;\n        }\n\n        ctx[draw ? 'lineTo' : 'moveTo'](x, 0);\n        draw = !draw;\n      }\n\n      ctx.restore();\n    },\n\n    /**\n     * Creates canvas element\n     * @static\n     * @memberOf fabric.util\n     * @return {CanvasElement} initialized canvas element\n     */\n    createCanvasElement: function () {\n      return fabric.document.createElement('canvas');\n    },\n\n    /**\n     * Creates a canvas element that is a copy of another and is also painted\n     * @param {CanvasElement} canvas to copy size and content of\n     * @static\n     * @memberOf fabric.util\n     * @return {CanvasElement} initialized canvas element\n     */\n    copyCanvasElement: function (canvas) {\n      var newCanvas = fabric.util.createCanvasElement();\n      newCanvas.width = canvas.width;\n      newCanvas.height = canvas.height;\n      newCanvas.getContext('2d').drawImage(canvas, 0, 0);\n      return newCanvas;\n    },\n\n    /**\n     * since 2.6.0 moved from canvas instance to utility.\n     * @param {CanvasElement} canvasEl to copy size and content of\n     * @param {String} format 'jpeg' or 'png', in some browsers 'webp' is ok too\n     * @param {Number} quality <= 1 and > 0\n     * @static\n     * @memberOf fabric.util\n     * @return {String} data url\n     */\n    toDataURL: function (canvasEl, format, quality) {\n      return canvasEl.toDataURL('image/' + format, quality);\n    },\n\n    /**\n     * Creates image element (works on client and node)\n     * @static\n     * @memberOf fabric.util\n     * @return {HTMLImageElement} HTML image element\n     */\n    createImage: function () {\n      return fabric.document.createElement('img');\n    },\n\n    /**\n     * Multiply matrix A by matrix B to nest transformations\n     * @static\n     * @memberOf fabric.util\n     * @param  {Array} a First transformMatrix\n     * @param  {Array} b Second transformMatrix\n     * @param  {Boolean} is2x2 flag to multiply matrices as 2x2 matrices\n     * @return {Array} The product of the two transform matrices\n     */\n    multiplyTransformMatrices: function (a, b, is2x2) {\n      // Matrix multiply a * b\n      return [a[0] * b[0] + a[2] * b[1], a[1] * b[0] + a[3] * b[1], a[0] * b[2] + a[2] * b[3], a[1] * b[2] + a[3] * b[3], is2x2 ? 0 : a[0] * b[4] + a[2] * b[5] + a[4], is2x2 ? 0 : a[1] * b[4] + a[3] * b[5] + a[5]];\n    },\n\n    /**\n     * Decomposes standard 2x3 matrix into transform components\n     * @static\n     * @memberOf fabric.util\n     * @param  {Array} a transformMatrix\n     * @return {Object} Components of transform\n     */\n    qrDecompose: function (a) {\n      var angle = atan2(a[1], a[0]),\n          denom = pow(a[0], 2) + pow(a[1], 2),\n          scaleX = sqrt(denom),\n          scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX,\n          skewX = atan2(a[0] * a[2] + a[1] * a[3], denom);\n      return {\n        angle: angle / PiBy180,\n        scaleX: scaleX,\n        scaleY: scaleY,\n        skewX: skewX / PiBy180,\n        skewY: 0,\n        translateX: a[4],\n        translateY: a[5]\n      };\n    },\n\n    /**\n     * Returns a transform matrix starting from an object of the same kind of\n     * the one returned from qrDecompose, useful also if you want to calculate some\n     * transformations from an object that is not enlived yet\n     * @static\n     * @memberOf fabric.util\n     * @param  {Object} options\n     * @param  {Number} [options.angle] angle in degrees\n     * @return {Number[]} transform matrix\n     */\n    calcRotateMatrix: function (options) {\n      if (!options.angle) {\n        return fabric.iMatrix.concat();\n      }\n\n      var theta = fabric.util.degreesToRadians(options.angle),\n          cos = fabric.util.cos(theta),\n          sin = fabric.util.sin(theta);\n      return [cos, sin, -sin, cos, 0, 0];\n    },\n\n    /**\n     * Returns a transform matrix starting from an object of the same kind of\n     * the one returned from qrDecompose, useful also if you want to calculate some\n     * transformations from an object that is not enlived yet.\n     * is called DimensionsTransformMatrix because those properties are the one that influence\n     * the size of the resulting box of the object.\n     * @static\n     * @memberOf fabric.util\n     * @param  {Object} options\n     * @param  {Number} [options.scaleX]\n     * @param  {Number} [options.scaleY]\n     * @param  {Boolean} [options.flipX]\n     * @param  {Boolean} [options.flipY]\n     * @param  {Number} [options.skewX]\n     * @param  {Number} [options.skewX]\n     * @return {Number[]} transform matrix\n     */\n    calcDimensionsMatrix: function (options) {\n      var scaleX = typeof options.scaleX === 'undefined' ? 1 : options.scaleX,\n          scaleY = typeof options.scaleY === 'undefined' ? 1 : options.scaleY,\n          scaleMatrix = [options.flipX ? -scaleX : scaleX, 0, 0, options.flipY ? -scaleY : scaleY, 0, 0],\n          multiply = fabric.util.multiplyTransformMatrices,\n          degreesToRadians = fabric.util.degreesToRadians;\n\n      if (options.skewX) {\n        scaleMatrix = multiply(scaleMatrix, [1, 0, Math.tan(degreesToRadians(options.skewX)), 1], true);\n      }\n\n      if (options.skewY) {\n        scaleMatrix = multiply(scaleMatrix, [1, Math.tan(degreesToRadians(options.skewY)), 0, 1], true);\n      }\n\n      return scaleMatrix;\n    },\n\n    /**\n     * Returns a transform matrix starting from an object of the same kind of\n     * the one returned from qrDecompose, useful also if you want to calculate some\n     * transformations from an object that is not enlived yet\n     * @static\n     * @memberOf fabric.util\n     * @param  {Object} options\n     * @param  {Number} [options.angle]\n     * @param  {Number} [options.scaleX]\n     * @param  {Number} [options.scaleY]\n     * @param  {Boolean} [options.flipX]\n     * @param  {Boolean} [options.flipY]\n     * @param  {Number} [options.skewX]\n     * @param  {Number} [options.skewX]\n     * @param  {Number} [options.translateX]\n     * @param  {Number} [options.translateY]\n     * @return {Number[]} transform matrix\n     */\n    composeMatrix: function (options) {\n      var matrix = [1, 0, 0, 1, options.translateX || 0, options.translateY || 0],\n          multiply = fabric.util.multiplyTransformMatrices;\n\n      if (options.angle) {\n        matrix = multiply(matrix, fabric.util.calcRotateMatrix(options));\n      }\n\n      if (options.scaleX !== 1 || options.scaleY !== 1 || options.skewX || options.skewY || options.flipX || options.flipY) {\n        matrix = multiply(matrix, fabric.util.calcDimensionsMatrix(options));\n      }\n\n      return matrix;\n    },\n\n    /**\n     * reset an object transform state to neutral. Top and left are not accounted for\n     * @static\n     * @memberOf fabric.util\n     * @param  {fabric.Object} target object to transform\n     */\n    resetObjectTransform: function (target) {\n      target.scaleX = 1;\n      target.scaleY = 1;\n      target.skewX = 0;\n      target.skewY = 0;\n      target.flipX = false;\n      target.flipY = false;\n      target.rotate(0);\n    },\n\n    /**\n     * Extract Object transform values\n     * @static\n     * @memberOf fabric.util\n     * @param  {fabric.Object} target object to read from\n     * @return {Object} Components of transform\n     */\n    saveObjectTransform: function (target) {\n      return {\n        scaleX: target.scaleX,\n        scaleY: target.scaleY,\n        skewX: target.skewX,\n        skewY: target.skewY,\n        angle: target.angle,\n        left: target.left,\n        flipX: target.flipX,\n        flipY: target.flipY,\n        top: target.top\n      };\n    },\n\n    /**\n     * Returns true if context has transparent pixel\n     * at specified location (taking tolerance into account)\n     * @param {CanvasRenderingContext2D} ctx context\n     * @param {Number} x x coordinate\n     * @param {Number} y y coordinate\n     * @param {Number} tolerance Tolerance\n     */\n    isTransparent: function (ctx, x, y, tolerance) {\n      // If tolerance is > 0 adjust start coords to take into account.\n      // If moves off Canvas fix to 0\n      if (tolerance > 0) {\n        if (x > tolerance) {\n          x -= tolerance;\n        } else {\n          x = 0;\n        }\n\n        if (y > tolerance) {\n          y -= tolerance;\n        } else {\n          y = 0;\n        }\n      }\n\n      var _isTransparent = true,\n          i,\n          temp,\n          imageData = ctx.getImageData(x, y, tolerance * 2 || 1, tolerance * 2 || 1),\n          l = imageData.data.length; // Split image data - for tolerance > 1, pixelDataSize = 4;\n\n      for (i = 3; i < l; i += 4) {\n        temp = imageData.data[i];\n        _isTransparent = temp <= 0;\n\n        if (_isTransparent === false) {\n          break; // Stop if colour found\n        }\n      }\n\n      imageData = null;\n      return _isTransparent;\n    },\n\n    /**\n     * Parse preserveAspectRatio attribute from element\n     * @param {string} attribute to be parsed\n     * @return {Object} an object containing align and meetOrSlice attribute\n     */\n    parsePreserveAspectRatioAttribute: function (attribute) {\n      var meetOrSlice = 'meet',\n          alignX = 'Mid',\n          alignY = 'Mid',\n          aspectRatioAttrs = attribute.split(' '),\n          align;\n\n      if (aspectRatioAttrs && aspectRatioAttrs.length) {\n        meetOrSlice = aspectRatioAttrs.pop();\n\n        if (meetOrSlice !== 'meet' && meetOrSlice !== 'slice') {\n          align = meetOrSlice;\n          meetOrSlice = 'meet';\n        } else if (aspectRatioAttrs.length) {\n          align = aspectRatioAttrs.pop();\n        }\n      } //divide align in alignX and alignY\n\n\n      alignX = align !== 'none' ? align.slice(1, 4) : 'none';\n      alignY = align !== 'none' ? align.slice(5, 8) : 'none';\n      return {\n        meetOrSlice: meetOrSlice,\n        alignX: alignX,\n        alignY: alignY\n      };\n    },\n\n    /**\n     * Clear char widths cache for the given font family or all the cache if no\n     * fontFamily is specified.\n     * Use it if you know you are loading fonts in a lazy way and you are not waiting\n     * for custom fonts to load properly when adding text objects to the canvas.\n     * If a text object is added when its own font is not loaded yet, you will get wrong\n     * measurement and so wrong bounding boxes.\n     * After the font cache is cleared, either change the textObject text content or call\n     * initDimensions() to trigger a recalculation\n     * @memberOf fabric.util\n     * @param {String} [fontFamily] font family to clear\n     */\n    clearFabricFontCache: function (fontFamily) {\n      fontFamily = (fontFamily || '').toLowerCase();\n\n      if (!fontFamily) {\n        fabric.charWidthsCache = {};\n      } else if (fabric.charWidthsCache[fontFamily]) {\n        delete fabric.charWidthsCache[fontFamily];\n      }\n    },\n\n    /**\n     * Given current aspect ratio, determines the max width and height that can\n     * respect the total allowed area for the cache.\n     * @memberOf fabric.util\n     * @param {Number} ar aspect ratio\n     * @param {Number} maximumArea Maximum area you want to achieve\n     * @return {Object.x} Limited dimensions by X\n     * @return {Object.y} Limited dimensions by Y\n     */\n    limitDimsByArea: function (ar, maximumArea) {\n      var roughWidth = Math.sqrt(maximumArea * ar),\n          perfLimitSizeY = Math.floor(maximumArea / roughWidth);\n      return {\n        x: Math.floor(roughWidth),\n        y: perfLimitSizeY\n      };\n    },\n    capValue: function (min, value, max) {\n      return Math.max(min, Math.min(value, max));\n    },\n\n    /**\n     * Finds the scale for the object source to fit inside the object destination,\n     * keeping aspect ratio intact.\n     * respect the total allowed area for the cache.\n     * @memberOf fabric.util\n     * @param {Object | fabric.Object} source\n     * @param {Number} source.height natural unscaled height of the object\n     * @param {Number} source.width natural unscaled width of the object\n     * @param {Object | fabric.Object} destination\n     * @param {Number} destination.height natural unscaled height of the object\n     * @param {Number} destination.width natural unscaled width of the object\n     * @return {Number} scale factor to apply to source to fit into destination\n     */\n    findScaleToFit: function (source, destination) {\n      return Math.min(destination.width / source.width, destination.height / source.height);\n    },\n\n    /**\n     * Finds the scale for the object source to cover entirely the object destination,\n     * keeping aspect ratio intact.\n     * respect the total allowed area for the cache.\n     * @memberOf fabric.util\n     * @param {Object | fabric.Object} source\n     * @param {Number} source.height natural unscaled height of the object\n     * @param {Number} source.width natural unscaled width of the object\n     * @param {Object | fabric.Object} destination\n     * @param {Number} destination.height natural unscaled height of the object\n     * @param {Number} destination.width natural unscaled width of the object\n     * @return {Number} scale factor to apply to source to cover destination\n     */\n    findScaleToCover: function (source, destination) {\n      return Math.max(destination.width / source.width, destination.height / source.height);\n    },\n\n    /**\n     * given an array of 6 number returns something like `\"matrix(...numbers)\"`\n     * @memberOf fabric.util\n     * @param {Array} trasnform an array with 6 numbers\n     * @return {String} transform matrix for svg\n     * @return {Object.y} Limited dimensions by Y\n     */\n    matrixToSVG: function (transform) {\n      return 'matrix(' + transform.map(function (value) {\n        return fabric.util.toFixed(value, fabric.Object.NUM_FRACTION_DIGITS);\n      }).join(' ') + ')';\n    },\n\n    /**\n     * given a width and height, return the size of the bounding box\n     * that can contains the box with width/height with applied transform\n     * described in options.\n     * Use to calculate the boxes around objects for controls.\n     * @memberOf fabric.util\n     * @param {Number} width\n     * @param {Number} height\n     * @param {Object} options\n     * @param {Number} options.scaleX\n     * @param {Number} options.scaleY\n     * @param {Number} options.skewX\n     * @param {Number} options.skewY\n     * @return {Object.x} width of containing\n     * @return {Object.y} height of containing\n     */\n    sizeAfterTransform: function (width, height, options) {\n      var dimX = width / 2,\n          dimY = height / 2,\n          points = [{\n        x: -dimX,\n        y: -dimY\n      }, {\n        x: dimX,\n        y: -dimY\n      }, {\n        x: -dimX,\n        y: dimY\n      }, {\n        x: dimX,\n        y: dimY\n      }],\n          transformMatrix = fabric.util.calcDimensionsMatrix(options),\n          bbox = fabric.util.makeBoundingBoxFromPoints(points, transformMatrix);\n      return {\n        x: bbox.width,\n        y: bbox.height\n      };\n    }\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function () {\n  var _join = Array.prototype.join,\n      commandLengths = {\n    m: 2,\n    l: 2,\n    h: 1,\n    v: 1,\n    c: 6,\n    s: 4,\n    q: 4,\n    t: 2,\n    a: 7\n  },\n      repeatedCommands = {\n    m: 'l',\n    M: 'L'\n  };\n\n  function segmentToBezier(th2, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY) {\n    var costh2 = fabric.util.cos(th2),\n        sinth2 = fabric.util.sin(th2),\n        costh3 = fabric.util.cos(th3),\n        sinth3 = fabric.util.sin(th3),\n        toX = cosTh * rx * costh3 - sinTh * ry * sinth3 + cx1,\n        toY = sinTh * rx * costh3 + cosTh * ry * sinth3 + cy1,\n        cp1X = fromX + mT * (-cosTh * rx * sinth2 - sinTh * ry * costh2),\n        cp1Y = fromY + mT * (-sinTh * rx * sinth2 + cosTh * ry * costh2),\n        cp2X = toX + mT * (cosTh * rx * sinth3 + sinTh * ry * costh3),\n        cp2Y = toY + mT * (sinTh * rx * sinth3 - cosTh * ry * costh3);\n    return ['C', cp1X, cp1Y, cp2X, cp2Y, toX, toY];\n  }\n  /* Adapted from http://dxr.mozilla.org/mozilla-central/source/content/svg/content/src/nsSVGPathDataParser.cpp\n   * by Andrea Bogazzi code is under MPL. if you don't have a copy of the license you can take it here\n   * http://mozilla.org/MPL/2.0/\n   */\n\n\n  function arcToSegments(toX, toY, rx, ry, large, sweep, rotateX) {\n    var PI = Math.PI,\n        th = rotateX * PI / 180,\n        sinTh = fabric.util.sin(th),\n        cosTh = fabric.util.cos(th),\n        fromX = 0,\n        fromY = 0;\n    rx = Math.abs(rx);\n    ry = Math.abs(ry);\n    var px = -cosTh * toX * 0.5 - sinTh * toY * 0.5,\n        py = -cosTh * toY * 0.5 + sinTh * toX * 0.5,\n        rx2 = rx * rx,\n        ry2 = ry * ry,\n        py2 = py * py,\n        px2 = px * px,\n        pl = rx2 * ry2 - rx2 * py2 - ry2 * px2,\n        root = 0;\n\n    if (pl < 0) {\n      var s = Math.sqrt(1 - pl / (rx2 * ry2));\n      rx *= s;\n      ry *= s;\n    } else {\n      root = (large === sweep ? -1.0 : 1.0) * Math.sqrt(pl / (rx2 * py2 + ry2 * px2));\n    }\n\n    var cx = root * rx * py / ry,\n        cy = -root * ry * px / rx,\n        cx1 = cosTh * cx - sinTh * cy + toX * 0.5,\n        cy1 = sinTh * cx + cosTh * cy + toY * 0.5,\n        mTheta = calcVectorAngle(1, 0, (px - cx) / rx, (py - cy) / ry),\n        dtheta = calcVectorAngle((px - cx) / rx, (py - cy) / ry, (-px - cx) / rx, (-py - cy) / ry);\n\n    if (sweep === 0 && dtheta > 0) {\n      dtheta -= 2 * PI;\n    } else if (sweep === 1 && dtheta < 0) {\n      dtheta += 2 * PI;\n    } // Convert into cubic bezier segments <= 90deg\n\n\n    var segments = Math.ceil(Math.abs(dtheta / PI * 2)),\n        result = [],\n        mDelta = dtheta / segments,\n        mT = 8 / 3 * Math.sin(mDelta / 4) * Math.sin(mDelta / 4) / Math.sin(mDelta / 2),\n        th3 = mTheta + mDelta;\n\n    for (var i = 0; i < segments; i++) {\n      result[i] = segmentToBezier(mTheta, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY);\n      fromX = result[i][5];\n      fromY = result[i][6];\n      mTheta = th3;\n      th3 += mDelta;\n    }\n\n    return result;\n  }\n  /*\n   * Private\n   */\n\n\n  function calcVectorAngle(ux, uy, vx, vy) {\n    var ta = Math.atan2(uy, ux),\n        tb = Math.atan2(vy, vx);\n\n    if (tb >= ta) {\n      return tb - ta;\n    } else {\n      return 2 * Math.PI - (ta - tb);\n    }\n  }\n  /**\n   * Calculate bounding box of a beziercurve\n   * @param {Number} x0 starting point\n   * @param {Number} y0\n   * @param {Number} x1 first control point\n   * @param {Number} y1\n   * @param {Number} x2 secondo control point\n   * @param {Number} y2\n   * @param {Number} x3 end of beizer\n   * @param {Number} y3\n   */\n  // taken from http://jsbin.com/ivomiq/56/edit  no credits available for that.\n  // TODO: can we normalize this with the starting points set at 0 and then translated the bbox?\n\n\n  function getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3) {\n    var argsString;\n\n    if (fabric.cachesBoundsOfCurve) {\n      argsString = _join.call(arguments);\n\n      if (fabric.boundsOfCurveCache[argsString]) {\n        return fabric.boundsOfCurveCache[argsString];\n      }\n    }\n\n    var sqrt = Math.sqrt,\n        min = Math.min,\n        max = Math.max,\n        abs = Math.abs,\n        tvalues = [],\n        bounds = [[], []],\n        a,\n        b,\n        c,\n        t,\n        t1,\n        t2,\n        b2ac,\n        sqrtb2ac;\n    b = 6 * x0 - 12 * x1 + 6 * x2;\n    a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;\n    c = 3 * x1 - 3 * x0;\n\n    for (var i = 0; i < 2; ++i) {\n      if (i > 0) {\n        b = 6 * y0 - 12 * y1 + 6 * y2;\n        a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;\n        c = 3 * y1 - 3 * y0;\n      }\n\n      if (abs(a) < 1e-12) {\n        if (abs(b) < 1e-12) {\n          continue;\n        }\n\n        t = -c / b;\n\n        if (0 < t && t < 1) {\n          tvalues.push(t);\n        }\n\n        continue;\n      }\n\n      b2ac = b * b - 4 * c * a;\n\n      if (b2ac < 0) {\n        continue;\n      }\n\n      sqrtb2ac = sqrt(b2ac);\n      t1 = (-b + sqrtb2ac) / (2 * a);\n\n      if (0 < t1 && t1 < 1) {\n        tvalues.push(t1);\n      }\n\n      t2 = (-b - sqrtb2ac) / (2 * a);\n\n      if (0 < t2 && t2 < 1) {\n        tvalues.push(t2);\n      }\n    }\n\n    var x,\n        y,\n        j = tvalues.length,\n        jlen = j,\n        mt;\n\n    while (j--) {\n      t = tvalues[j];\n      mt = 1 - t;\n      x = mt * mt * mt * x0 + 3 * mt * mt * t * x1 + 3 * mt * t * t * x2 + t * t * t * x3;\n      bounds[0][j] = x;\n      y = mt * mt * mt * y0 + 3 * mt * mt * t * y1 + 3 * mt * t * t * y2 + t * t * t * y3;\n      bounds[1][j] = y;\n    }\n\n    bounds[0][jlen] = x0;\n    bounds[1][jlen] = y0;\n    bounds[0][jlen + 1] = x3;\n    bounds[1][jlen + 1] = y3;\n    var result = [{\n      x: min.apply(null, bounds[0]),\n      y: min.apply(null, bounds[1])\n    }, {\n      x: max.apply(null, bounds[0]),\n      y: max.apply(null, bounds[1])\n    }];\n\n    if (fabric.cachesBoundsOfCurve) {\n      fabric.boundsOfCurveCache[argsString] = result;\n    }\n\n    return result;\n  }\n  /**\n   * Converts arc to a bunch of beizer curves\n   * @param {Number} fx starting point x\n   * @param {Number} fy starting point y\n   * @param {Array} coords Arc command\n   */\n\n\n  function fromArcToBeizers(fx, fy, coords) {\n    var rx = coords[1],\n        ry = coords[2],\n        rot = coords[3],\n        large = coords[4],\n        sweep = coords[5],\n        tx = coords[6],\n        ty = coords[7],\n        segsNorm = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);\n\n    for (var i = 0, len = segsNorm.length; i < len; i++) {\n      segsNorm[i][1] += fx;\n      segsNorm[i][2] += fy;\n      segsNorm[i][3] += fx;\n      segsNorm[i][4] += fy;\n      segsNorm[i][5] += fx;\n      segsNorm[i][6] += fy;\n    }\n\n    return segsNorm;\n  }\n\n  ;\n\n  function makePathSimpler(path) {\n    // x and y represent the last point of the path. the previous command point.\n    // we add them to each relative command to make it an absolute comment.\n    // we also swap the v V h H with L, because are easier to transform.\n    var x = 0,\n        y = 0,\n        len = path.length,\n        // x1 and y1 represent the last point of the subpath. the subpath is started with\n    // m or M command. When a z or Z command is drawn, x and y need to be resetted to\n    // the last x1 and y1.\n    x1 = 0,\n        y1 = 0,\n        current,\n        i,\n        converted,\n        // previous will host the letter of the previous command, to handle S and T.\n    // controlX and controlY will host the previous reflected control point\n    destinationPath = [],\n        previous,\n        controlX,\n        controlY;\n\n    for (i = 0; i < len; ++i) {\n      converted = false;\n      current = path[i].slice(0);\n\n      switch (current[0]) {\n        // first letter\n        case 'l':\n          // lineto, relative\n          current[0] = 'L';\n          current[1] += x;\n          current[2] += y;\n        // falls through\n\n        case 'L':\n          x = current[1];\n          y = current[2];\n          break;\n\n        case 'h':\n          // horizontal lineto, relative\n          current[1] += x;\n        // falls through\n\n        case 'H':\n          current[0] = 'L';\n          current[2] = y;\n          x = current[1];\n          break;\n\n        case 'v':\n          // vertical lineto, relative\n          current[1] += y;\n        // falls through\n\n        case 'V':\n          current[0] = 'L';\n          y = current[1];\n          current[1] = x;\n          current[2] = y;\n          break;\n\n        case 'm':\n          // moveTo, relative\n          current[0] = 'M';\n          current[1] += x;\n          current[2] += y;\n        // falls through\n\n        case 'M':\n          x = current[1];\n          y = current[2];\n          x1 = current[1];\n          y1 = current[2];\n          break;\n\n        case 'c':\n          // bezierCurveTo, relative\n          current[0] = 'C';\n          current[1] += x;\n          current[2] += y;\n          current[3] += x;\n          current[4] += y;\n          current[5] += x;\n          current[6] += y;\n        // falls through\n\n        case 'C':\n          controlX = current[3];\n          controlY = current[4];\n          x = current[5];\n          y = current[6];\n          break;\n\n        case 's':\n          // shorthand cubic bezierCurveTo, relative\n          current[0] = 'S';\n          current[1] += x;\n          current[2] += y;\n          current[3] += x;\n          current[4] += y;\n        // falls through\n\n        case 'S':\n          // would be sScC but since we are swapping sSc for C, we check just that.\n          if (previous === 'C') {\n            // calculate reflection of previous control points\n            controlX = 2 * x - controlX;\n            controlY = 2 * y - controlY;\n          } else {\n            // If there is no previous command or if the previous command was not a C, c, S, or s,\n            // the control point is coincident with the current point\n            controlX = x;\n            controlY = y;\n          }\n\n          x = current[3];\n          y = current[4];\n          current[0] = 'C';\n          current[5] = current[3];\n          current[6] = current[4];\n          current[3] = current[1];\n          current[4] = current[2];\n          current[1] = controlX;\n          current[2] = controlY; // current[3] and current[4] are NOW the second control point.\n          // we keep it for the next reflection.\n\n          controlX = current[3];\n          controlY = current[4];\n          break;\n\n        case 'q':\n          // quadraticCurveTo, relative\n          current[0] = 'Q';\n          current[1] += x;\n          current[2] += y;\n          current[3] += x;\n          current[4] += y;\n        // falls through\n\n        case 'Q':\n          controlX = current[1];\n          controlY = current[2];\n          x = current[3];\n          y = current[4];\n          break;\n\n        case 't':\n          // shorthand quadraticCurveTo, relative\n          current[0] = 'T';\n          current[1] += x;\n          current[2] += y;\n        // falls through\n\n        case 'T':\n          if (previous === 'Q') {\n            // calculate reflection of previous control point\n            controlX = 2 * x - controlX;\n            controlY = 2 * y - controlY;\n          } else {\n            // If there is no previous command or if the previous command was not a Q, q, T or t,\n            // assume the control point is coincident with the current point\n            controlX = x;\n            controlY = y;\n          }\n\n          current[0] = 'Q';\n          x = current[1];\n          y = current[2];\n          current[1] = controlX;\n          current[2] = controlY;\n          current[3] = x;\n          current[4] = y;\n          break;\n\n        case 'a':\n          current[0] = 'A';\n          current[6] += x;\n          current[7] += y;\n        // falls through\n\n        case 'A':\n          converted = true;\n          destinationPath = destinationPath.concat(fromArcToBeizers(x, y, current));\n          x = current[6];\n          y = current[7];\n          break;\n\n        case 'z':\n        case 'Z':\n          x = x1;\n          y = y1;\n          break;\n\n        default:\n      }\n\n      if (!converted) {\n        destinationPath.push(current);\n      }\n\n      previous = current[0];\n    }\n\n    return destinationPath;\n  }\n\n  ;\n  /**\n   * Calc length from point x1,y1 to x2,y2\n   * @param {Number} x1 starting point x\n   * @param {Number} y1 starting point y\n   * @param {Number} x2 starting point x\n   * @param {Number} y2 starting point y\n   * @return {Number} length of segment\n   */\n\n  function calcLineLength(x1, y1, x2, y2) {\n    return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));\n  } // functions for the Cubic beizer\n  // taken from: https://github.com/konvajs/konva/blob/7.0.5/src/shapes/Path.ts#L350\n\n\n  function CB1(t) {\n    return t * t * t;\n  }\n\n  function CB2(t) {\n    return 3 * t * t * (1 - t);\n  }\n\n  function CB3(t) {\n    return 3 * t * (1 - t) * (1 - t);\n  }\n\n  function CB4(t) {\n    return (1 - t) * (1 - t) * (1 - t);\n  }\n\n  function getPointOnCubicBezierIterator(p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y) {\n    return function (pct) {\n      var c1 = CB1(pct),\n          c2 = CB2(pct),\n          c3 = CB3(pct),\n          c4 = CB4(pct);\n      return {\n        x: p4x * c1 + p3x * c2 + p2x * c3 + p1x * c4,\n        y: p4y * c1 + p3y * c2 + p2y * c3 + p1y * c4\n      };\n    };\n  }\n\n  function QB1(t) {\n    return t * t;\n  }\n\n  function QB2(t) {\n    return 2 * t * (1 - t);\n  }\n\n  function QB3(t) {\n    return (1 - t) * (1 - t);\n  }\n\n  function getPointOnQuadraticBezierIterator(p1x, p1y, p2x, p2y, p3x, p3y) {\n    return function (pct) {\n      var c1 = QB1(pct),\n          c2 = QB2(pct),\n          c3 = QB3(pct);\n      return {\n        x: p3x * c1 + p2x * c2 + p1x * c3,\n        y: p3y * c1 + p2y * c2 + p1y * c3\n      };\n    };\n  }\n\n  function pathIterator(iterator, x1, y1) {\n    var tempP = {\n      x: x1,\n      y: y1\n    },\n        p,\n        tmpLen = 0,\n        perc;\n\n    for (perc = 0.01; perc <= 1; perc += 0.01) {\n      p = iterator(perc);\n      tmpLen += calcLineLength(tempP.x, tempP.y, p.x, p.y);\n      tempP = p;\n    }\n\n    return tmpLen;\n  } //measures the length of a pre-simplified path\n\n\n  function getPathSegmentsInfo(path) {\n    var totalLength = 0,\n        len = path.length,\n        current,\n        //x2 and y2 are the coords of segment start\n    //x1 and y1 are the coords of the current point\n    x1 = 0,\n        y1 = 0,\n        x2 = 0,\n        y2 = 0,\n        info = [],\n        iterator,\n        tempInfo;\n\n    for (var i = 0; i < len; i++) {\n      current = path[i];\n      tempInfo = {\n        x: x1,\n        y: y1,\n        command: current[0]\n      };\n\n      switch (current[0]) {\n        //first letter\n        case 'M':\n          tempInfo.length = 0;\n          x2 = x1 = current[1];\n          y2 = y1 = current[2];\n          break;\n\n        case 'L':\n          tempInfo.length = calcLineLength(x1, y1, current[1], current[2]);\n          x1 = current[1];\n          y1 = current[2];\n          break;\n\n        case 'C':\n          iterator = getPointOnCubicBezierIterator(x1, y1, current[1], current[2], current[3], current[4], current[5], current[6]);\n          tempInfo.length = pathIterator(iterator, x1, y1);\n          x1 = current[5];\n          y1 = current[6];\n          break;\n\n        case 'Q':\n          iterator = getPointOnQuadraticBezierIterator(x1, y1, current[1], current[2], current[3], current[4]);\n          tempInfo.length = pathIterator(iterator, x1, y1);\n          x1 = current[3];\n          y1 = current[4];\n          break;\n\n        case 'Z':\n        case 'z':\n          // we add those in order to ease calculations later\n          tempInfo.destX = x2;\n          tempInfo.destY = y2;\n          tempInfo.length = calcLineLength(x1, y1, x2, y2);\n          x1 = x2;\n          y1 = y2;\n          break;\n      }\n\n      totalLength += tempInfo.length;\n      info.push(tempInfo);\n    }\n\n    info.push({\n      length: totalLength,\n      x: x1,\n      y: y1\n    });\n    return info;\n  }\n\n  function getPointOnPath(path, perc, infos) {\n    if (!infos) {\n      infos = getPathSegmentsInfo(path);\n    }\n\n    var distance = infos[infos.length - 1] * perc,\n        i = 0;\n\n    while (distance - infos[i] > 0 && i < infos.length) {\n      distance -= infos[i];\n      i++;\n    }\n\n    var segInfo = infos[i],\n        segPercent = distance / segInfo.length,\n        command = segInfo.length,\n        segment = path[i];\n\n    switch (command) {\n      case 'Z':\n      case 'z':\n        return new fabric.Point(segInfo.x, segInfo.y).lerp(new fabric.Point(segInfo.destX, segInfo.destY), segPercent);\n        break;\n\n      case 'L':\n        return new fabric.Point(segInfo.x, segInfo.y).lerp(new fabric.Point(segment[1], segment[2]), segPercent);\n        break;\n\n      case 'C':\n        return getPointOnCubicBezierIterator(segInfo.x, segInfo.y, segment[1], segment[2], segment[3], segment[4], segment[5], segment[6])(segPercent);\n        break;\n\n      case 'Q':\n        return getPointOnQuadraticBezierIterator(segInfo.x, segInfo.y, segment[1], segment[2], segment[3], segment[4])(segPercent);\n        break;\n    }\n  }\n\n  function parsePath(pathString) {\n    var result = [],\n        coords = [],\n        currentPath,\n        parsed,\n        re = fabric.rePathCommand,\n        rNumber = '[-+]?(?:\\\\d*\\\\.\\\\d+|\\\\d+\\\\.?)(?:[eE][-+]?\\\\d+)?\\\\s*',\n        rNumberCommaWsp = '(' + rNumber + ')' + fabric.commaWsp,\n        rFlagCommaWsp = '([01])' + fabric.commaWsp + '?',\n        rArcSeq = rNumberCommaWsp + '?' + rNumberCommaWsp + '?' + rNumberCommaWsp + rFlagCommaWsp + rFlagCommaWsp + rNumberCommaWsp + '?(' + rNumber + ')',\n        regArcArgumentSequence = new RegExp(rArcSeq, 'g'),\n        match,\n        coordsStr,\n        // one of commands (m,M,l,L,q,Q,c,C,etc.) followed by non-command characters (i.e. command values)\n    path;\n\n    if (!pathString || !pathString.match) {\n      return result;\n    }\n\n    path = pathString.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi);\n\n    for (var i = 0, coordsParsed, len = path.length; i < len; i++) {\n      currentPath = path[i];\n      coordsStr = currentPath.slice(1).trim();\n      coords.length = 0;\n      var command = currentPath.charAt(0);\n      coordsParsed = [command];\n\n      if (command.toLowerCase() === 'a') {\n        // arcs have special flags that apparently don't require spaces so handle special\n        for (var args; args = regArcArgumentSequence.exec(coordsStr);) {\n          for (var j = 1; j < args.length; j++) {\n            coords.push(args[j]);\n          }\n        }\n      } else {\n        while (match = re.exec(coordsStr)) {\n          coords.push(match[0]);\n        }\n      }\n\n      for (var j = 0, jlen = coords.length; j < jlen; j++) {\n        parsed = parseFloat(coords[j]);\n\n        if (!isNaN(parsed)) {\n          coordsParsed.push(parsed);\n        }\n      }\n\n      var commandLength = commandLengths[command.toLowerCase()],\n          repeatedCommand = repeatedCommands[command] || command;\n\n      if (coordsParsed.length - 1 > commandLength) {\n        for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) {\n          result.push([command].concat(coordsParsed.slice(k, k + commandLength)));\n          command = repeatedCommand;\n        }\n      } else {\n        result.push(coordsParsed);\n      }\n    }\n\n    return result;\n  }\n\n  ;\n  /**\n   * Calculate bounding box of a elliptic-arc\n   * @deprecated\n   * @param {Number} fx start point of arc\n   * @param {Number} fy\n   * @param {Number} rx horizontal radius\n   * @param {Number} ry vertical radius\n   * @param {Number} rot angle of horizontal axis\n   * @param {Number} large 1 or 0, whatever the arc is the big or the small on the 2 points\n   * @param {Number} sweep 1 or 0, 1 clockwise or counterclockwise direction\n   * @param {Number} tx end point of arc\n   * @param {Number} ty\n   */\n\n  function getBoundsOfArc(fx, fy, rx, ry, rot, large, sweep, tx, ty) {\n    var fromX = 0,\n        fromY = 0,\n        bound,\n        bounds = [],\n        segs = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);\n\n    for (var i = 0, len = segs.length; i < len; i++) {\n      bound = getBoundsOfCurve(fromX, fromY, segs[i][1], segs[i][2], segs[i][3], segs[i][4], segs[i][5], segs[i][6]);\n      bounds.push({\n        x: bound[0].x + fx,\n        y: bound[0].y + fy\n      });\n      bounds.push({\n        x: bound[1].x + fx,\n        y: bound[1].y + fy\n      });\n      fromX = segs[i][5];\n      fromY = segs[i][6];\n    }\n\n    return bounds;\n  }\n\n  ;\n  /**\n   * Draws arc\n   * @param {CanvasRenderingContext2D} ctx\n   * @param {Number} fx\n   * @param {Number} fy\n   * @param {Array} coords coords of the arc, without the front 'A/a'\n   */\n\n  function drawArc(ctx, fx, fy, coords) {\n    coords = coords.slice(0).unshift('X'); // command A or a does not matter\n\n    var beizers = fromArcToBeizers(fx, fy, coords);\n    beizers.forEach(function (beizer) {\n      ctx.bezierCurveTo.apply(ctx, beizer.slice(1));\n    });\n  }\n\n  ;\n  fabric.util.parsePath = parsePath;\n  fabric.util.makePathSimpler = makePathSimpler;\n  fabric.util.getPathSegmentsInfo = getPathSegmentsInfo;\n  fabric.util.fromArcToBeizers = fromArcToBeizers;\n  fabric.util.getBoundsOfCurve = getBoundsOfCurve;\n  fabric.util.getPointOnPath = getPointOnPath; // kept because we do not want to make breaking changes.\n  // but useless and deprecated.\n\n  fabric.util.getBoundsOfArc = getBoundsOfArc;\n  fabric.util.drawArc = drawArc;\n})();\n\n(function () {\n  var slice = Array.prototype.slice;\n  /**\n   * Invokes method on all items in a given array\n   * @memberOf fabric.util.array\n   * @param {Array} array Array to iterate over\n   * @param {String} method Name of a method to invoke\n   * @return {Array}\n   */\n\n  function invoke(array, method) {\n    var args = slice.call(arguments, 2),\n        result = [];\n\n    for (var i = 0, len = array.length; i < len; i++) {\n      result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]);\n    }\n\n    return result;\n  }\n  /**\n   * Finds maximum value in array (not necessarily \"first\" one)\n   * @memberOf fabric.util.array\n   * @param {Array} array Array to iterate over\n   * @param {String} byProperty\n   * @return {*}\n   */\n\n\n  function max(array, byProperty) {\n    return find(array, byProperty, function (value1, value2) {\n      return value1 >= value2;\n    });\n  }\n  /**\n   * Finds minimum value in array (not necessarily \"first\" one)\n   * @memberOf fabric.util.array\n   * @param {Array} array Array to iterate over\n   * @param {String} byProperty\n   * @return {*}\n   */\n\n\n  function min(array, byProperty) {\n    return find(array, byProperty, function (value1, value2) {\n      return value1 < value2;\n    });\n  }\n  /**\n   * @private\n   */\n\n\n  function fill(array, value) {\n    var k = array.length;\n\n    while (k--) {\n      array[k] = value;\n    }\n\n    return array;\n  }\n  /**\n   * @private\n   */\n\n\n  function find(array, byProperty, condition) {\n    if (!array || array.length === 0) {\n      return;\n    }\n\n    var i = array.length - 1,\n        result = byProperty ? array[i][byProperty] : array[i];\n\n    if (byProperty) {\n      while (i--) {\n        if (condition(array[i][byProperty], result)) {\n          result = array[i][byProperty];\n        }\n      }\n    } else {\n      while (i--) {\n        if (condition(array[i], result)) {\n          result = array[i];\n        }\n      }\n    }\n\n    return result;\n  }\n  /**\n   * @namespace fabric.util.array\n   */\n\n\n  fabric.util.array = {\n    fill: fill,\n    invoke: invoke,\n    min: min,\n    max: max\n  };\n})();\n\n(function () {\n  /**\n   * Copies all enumerable properties of one js object to another\n   * this does not and cannot compete with generic utils.\n   * Does not clone or extend fabric.Object subclasses.\n   * This is mostly for internal use and has extra handling for fabricJS objects\n   * it skips the canvas and group properties in deep cloning.\n   * @memberOf fabric.util.object\n   * @param {Object} destination Where to copy to\n   * @param {Object} source Where to copy from\n   * @return {Object}\n   */\n  function extend(destination, source, deep) {\n    // JScript DontEnum bug is not taken care of\n    // the deep clone is for internal use, is not meant to avoid\n    // javascript traps or cloning html element or self referenced objects.\n    if (deep) {\n      if (!fabric.isLikelyNode && source instanceof Element) {\n        // avoid cloning deep images, canvases,\n        destination = source;\n      } else if (source instanceof Array) {\n        destination = [];\n\n        for (var i = 0, len = source.length; i < len; i++) {\n          destination[i] = extend({}, source[i], deep);\n        }\n      } else if (source && typeof source === 'object') {\n        for (var property in source) {\n          if (property === 'canvas' || property === 'group') {\n            // we do not want to clone this props at all.\n            // we want to keep the keys in the copy\n            destination[property] = null;\n          } else if (source.hasOwnProperty(property)) {\n            destination[property] = extend({}, source[property], deep);\n          }\n        }\n      } else {\n        // this sounds odd for an extend but is ok for recursive use\n        destination = source;\n      }\n    } else {\n      for (var property in source) {\n        destination[property] = source[property];\n      }\n    }\n\n    return destination;\n  }\n  /**\n   * Creates an empty object and copies all enumerable properties of another object to it\n   * @memberOf fabric.util.object\n   * TODO: this function return an empty object if you try to clone null\n   * @param {Object} object Object to clone\n   * @return {Object}\n   */\n\n\n  function clone(object, deep) {\n    return extend({}, object, deep);\n  }\n  /** @namespace fabric.util.object */\n\n\n  fabric.util.object = {\n    extend: extend,\n    clone: clone\n  };\n  fabric.util.object.extend(fabric.util, fabric.Observable);\n})();\n\n(function () {\n  /**\n   * Camelizes a string\n   * @memberOf fabric.util.string\n   * @param {String} string String to camelize\n   * @return {String} Camelized version of a string\n   */\n  function camelize(string) {\n    return string.replace(/-+(.)?/g, function (match, character) {\n      return character ? character.toUpperCase() : '';\n    });\n  }\n  /**\n   * Capitalizes a string\n   * @memberOf fabric.util.string\n   * @param {String} string String to capitalize\n   * @param {Boolean} [firstLetterOnly] If true only first letter is capitalized\n   * and other letters stay untouched, if false first letter is capitalized\n   * and other letters are converted to lowercase.\n   * @return {String} Capitalized version of a string\n   */\n\n\n  function capitalize(string, firstLetterOnly) {\n    return string.charAt(0).toUpperCase() + (firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase());\n  }\n  /**\n   * Escapes XML in a string\n   * @memberOf fabric.util.string\n   * @param {String} string String to escape\n   * @return {String} Escaped version of a string\n   */\n\n\n  function escapeXml(string) {\n    return string.replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/'/g, '&apos;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n  }\n  /**\n   * Divide a string in the user perceived single units\n   * @memberOf fabric.util.string\n   * @param {String} textstring String to escape\n   * @return {Array} array containing the graphemes\n   */\n\n\n  function graphemeSplit(textstring) {\n    var i = 0,\n        chr,\n        graphemes = [];\n\n    for (i = 0, chr; i < textstring.length; i++) {\n      if ((chr = getWholeChar(textstring, i)) === false) {\n        continue;\n      }\n\n      graphemes.push(chr);\n    }\n\n    return graphemes;\n  } // taken from mdn in the charAt doc page.\n\n\n  function getWholeChar(str, i) {\n    var code = str.charCodeAt(i);\n\n    if (isNaN(code)) {\n      return ''; // Position not found\n    }\n\n    if (code < 0xD800 || code > 0xDFFF) {\n      return str.charAt(i);\n    } // High surrogate (could change last hex to 0xDB7F to treat high private\n    // surrogates as single characters)\n\n\n    if (0xD800 <= code && code <= 0xDBFF) {\n      if (str.length <= i + 1) {\n        throw 'High surrogate without following low surrogate';\n      }\n\n      var next = str.charCodeAt(i + 1);\n\n      if (0xDC00 > next || next > 0xDFFF) {\n        throw 'High surrogate without following low surrogate';\n      }\n\n      return str.charAt(i) + str.charAt(i + 1);\n    } // Low surrogate (0xDC00 <= code && code <= 0xDFFF)\n\n\n    if (i === 0) {\n      throw 'Low surrogate without preceding high surrogate';\n    }\n\n    var prev = str.charCodeAt(i - 1); // (could change last hex to 0xDB7F to treat high private\n    // surrogates as single characters)\n\n    if (0xD800 > prev || prev > 0xDBFF) {\n      throw 'Low surrogate without preceding high surrogate';\n    } // We can pass over low surrogates now as the second component\n    // in a pair which we have already processed\n\n\n    return false;\n  }\n  /**\n   * String utilities\n   * @namespace fabric.util.string\n   */\n\n\n  fabric.util.string = {\n    camelize: camelize,\n    capitalize: capitalize,\n    escapeXml: escapeXml,\n    graphemeSplit: graphemeSplit\n  };\n})();\n\n(function () {\n  var slice = Array.prototype.slice,\n      emptyFunction = function () {},\n      IS_DONTENUM_BUGGY = function () {\n    for (var p in {\n      toString: 1\n    }) {\n      if (p === 'toString') {\n        return false;\n      }\n    }\n\n    return true;\n  }(),\n\n  /** @ignore */\n  addMethods = function (klass, source, parent) {\n    for (var property in source) {\n      if (property in klass.prototype && typeof klass.prototype[property] === 'function' && (source[property] + '').indexOf('callSuper') > -1) {\n        klass.prototype[property] = function (property) {\n          return function () {\n            var superclass = this.constructor.superclass;\n            this.constructor.superclass = parent;\n            var returnValue = source[property].apply(this, arguments);\n            this.constructor.superclass = superclass;\n\n            if (property !== 'initialize') {\n              return returnValue;\n            }\n          };\n        }(property);\n      } else {\n        klass.prototype[property] = source[property];\n      }\n\n      if (IS_DONTENUM_BUGGY) {\n        if (source.toString !== Object.prototype.toString) {\n          klass.prototype.toString = source.toString;\n        }\n\n        if (source.valueOf !== Object.prototype.valueOf) {\n          klass.prototype.valueOf = source.valueOf;\n        }\n      }\n    }\n  };\n\n  function Subclass() {}\n\n  function callSuper(methodName) {\n    var parentMethod = null,\n        _this = this; // climb prototype chain to find method not equal to callee's method\n\n\n    while (_this.constructor.superclass) {\n      var superClassMethod = _this.constructor.superclass.prototype[methodName];\n\n      if (_this[methodName] !== superClassMethod) {\n        parentMethod = superClassMethod;\n        break;\n      } // eslint-disable-next-line\n\n\n      _this = _this.constructor.superclass.prototype;\n    }\n\n    if (!parentMethod) {\n      return console.log('tried to callSuper ' + methodName + ', method not found in prototype chain', this);\n    }\n\n    return arguments.length > 1 ? parentMethod.apply(this, slice.call(arguments, 1)) : parentMethod.call(this);\n  }\n  /**\n   * Helper for creation of \"classes\".\n   * @memberOf fabric.util\n   * @param {Function} [parent] optional \"Class\" to inherit from\n   * @param {Object} [properties] Properties shared by all instances of this class\n   *                  (be careful modifying objects defined here as this would affect all instances)\n   */\n\n\n  function createClass() {\n    var parent = null,\n        properties = slice.call(arguments, 0);\n\n    if (typeof properties[0] === 'function') {\n      parent = properties.shift();\n    }\n\n    function klass() {\n      this.initialize.apply(this, arguments);\n    }\n\n    klass.superclass = parent;\n    klass.subclasses = [];\n\n    if (parent) {\n      Subclass.prototype = parent.prototype;\n      klass.prototype = new Subclass();\n      parent.subclasses.push(klass);\n    }\n\n    for (var i = 0, length = properties.length; i < length; i++) {\n      addMethods(klass, properties[i], parent);\n    }\n\n    if (!klass.prototype.initialize) {\n      klass.prototype.initialize = emptyFunction;\n    }\n\n    klass.prototype.constructor = klass;\n    klass.prototype.callSuper = callSuper;\n    return klass;\n  }\n\n  fabric.util.createClass = createClass;\n})();\n\n(function () {\n  // since ie11 can use addEventListener but they do not support options, i need to check\n  var couldUseAttachEvent = !!fabric.document.createElement('div').attachEvent,\n      touchEvents = ['touchstart', 'touchmove', 'touchend'];\n  /**\n   * Adds an event listener to an element\n   * @function\n   * @memberOf fabric.util\n   * @param {HTMLElement} element\n   * @param {String} eventName\n   * @param {Function} handler\n   */\n\n  fabric.util.addListener = function (element, eventName, handler, options) {\n    element && element.addEventListener(eventName, handler, couldUseAttachEvent ? false : options);\n  };\n  /**\n   * Removes an event listener from an element\n   * @function\n   * @memberOf fabric.util\n   * @param {HTMLElement} element\n   * @param {String} eventName\n   * @param {Function} handler\n   */\n\n\n  fabric.util.removeListener = function (element, eventName, handler, options) {\n    element && element.removeEventListener(eventName, handler, couldUseAttachEvent ? false : options);\n  };\n\n  function getTouchInfo(event) {\n    var touchProp = event.changedTouches;\n\n    if (touchProp && touchProp[0]) {\n      return touchProp[0];\n    }\n\n    return event;\n  }\n\n  fabric.util.getPointer = function (event) {\n    var element = event.target,\n        scroll = fabric.util.getScrollLeftTop(element),\n        _evt = getTouchInfo(event);\n\n    return {\n      x: _evt.clientX + scroll.left,\n      y: _evt.clientY + scroll.top\n    };\n  };\n\n  fabric.util.isTouchEvent = function (event) {\n    return touchEvents.indexOf(event.type) > -1 || event.pointerType === 'touch';\n  };\n})();\n\n(function () {\n  /**\n   * Cross-browser wrapper for setting element's style\n   * @memberOf fabric.util\n   * @param {HTMLElement} element\n   * @param {Object} styles\n   * @return {HTMLElement} Element that was passed as a first argument\n   */\n  function setStyle(element, styles) {\n    var elementStyle = element.style;\n\n    if (!elementStyle) {\n      return element;\n    }\n\n    if (typeof styles === 'string') {\n      element.style.cssText += ';' + styles;\n      return styles.indexOf('opacity') > -1 ? setOpacity(element, styles.match(/opacity:\\s*(\\d?\\.?\\d*)/)[1]) : element;\n    }\n\n    for (var property in styles) {\n      if (property === 'opacity') {\n        setOpacity(element, styles[property]);\n      } else {\n        var normalizedProperty = property === 'float' || property === 'cssFloat' ? typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat' : property;\n        elementStyle[normalizedProperty] = styles[property];\n      }\n    }\n\n    return element;\n  }\n\n  var parseEl = fabric.document.createElement('div'),\n      supportsOpacity = typeof parseEl.style.opacity === 'string',\n      supportsFilters = typeof parseEl.style.filter === 'string',\n      reOpacity = /alpha\\s*\\(\\s*opacity\\s*=\\s*([^\\)]+)\\)/,\n\n  /** @ignore */\n  setOpacity = function (element) {\n    return element;\n  };\n\n  if (supportsOpacity) {\n    /** @ignore */\n    setOpacity = function (element, value) {\n      element.style.opacity = value;\n      return element;\n    };\n  } else if (supportsFilters) {\n    /** @ignore */\n    setOpacity = function (element, value) {\n      var es = element.style;\n\n      if (element.currentStyle && !element.currentStyle.hasLayout) {\n        es.zoom = 1;\n      }\n\n      if (reOpacity.test(es.filter)) {\n        value = value >= 0.9999 ? '' : 'alpha(opacity=' + value * 100 + ')';\n        es.filter = es.filter.replace(reOpacity, value);\n      } else {\n        es.filter += ' alpha(opacity=' + value * 100 + ')';\n      }\n\n      return element;\n    };\n  }\n\n  fabric.util.setStyle = setStyle;\n})();\n\n(function () {\n  var _slice = Array.prototype.slice;\n  /**\n   * Takes id and returns an element with that id (if one exists in a document)\n   * @memberOf fabric.util\n   * @param {String|HTMLElement} id\n   * @return {HTMLElement|null}\n   */\n\n  function getById(id) {\n    return typeof id === 'string' ? fabric.document.getElementById(id) : id;\n  }\n\n  var sliceCanConvertNodelists,\n\n  /**\n   * Converts an array-like object (e.g. arguments or NodeList) to an array\n   * @memberOf fabric.util\n   * @param {Object} arrayLike\n   * @return {Array}\n   */\n  toArray = function (arrayLike) {\n    return _slice.call(arrayLike, 0);\n  };\n\n  try {\n    sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array;\n  } catch (err) {}\n\n  if (!sliceCanConvertNodelists) {\n    toArray = function (arrayLike) {\n      var arr = new Array(arrayLike.length),\n          i = arrayLike.length;\n\n      while (i--) {\n        arr[i] = arrayLike[i];\n      }\n\n      return arr;\n    };\n  }\n  /**\n   * Creates specified element with specified attributes\n   * @memberOf fabric.util\n   * @param {String} tagName Type of an element to create\n   * @param {Object} [attributes] Attributes to set on an element\n   * @return {HTMLElement} Newly created element\n   */\n\n\n  function makeElement(tagName, attributes) {\n    var el = fabric.document.createElement(tagName);\n\n    for (var prop in attributes) {\n      if (prop === 'class') {\n        el.className = attributes[prop];\n      } else if (prop === 'for') {\n        el.htmlFor = attributes[prop];\n      } else {\n        el.setAttribute(prop, attributes[prop]);\n      }\n    }\n\n    return el;\n  }\n  /**\n   * Adds class to an element\n   * @memberOf fabric.util\n   * @param {HTMLElement} element Element to add class to\n   * @param {String} className Class to add to an element\n   */\n\n\n  function addClass(element, className) {\n    if (element && (' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) {\n      element.className += (element.className ? ' ' : '') + className;\n    }\n  }\n  /**\n   * Wraps element with another element\n   * @memberOf fabric.util\n   * @param {HTMLElement} element Element to wrap\n   * @param {HTMLElement|String} wrapper Element to wrap with\n   * @param {Object} [attributes] Attributes to set on a wrapper\n   * @return {HTMLElement} wrapper\n   */\n\n\n  function wrapElement(element, wrapper, attributes) {\n    if (typeof wrapper === 'string') {\n      wrapper = makeElement(wrapper, attributes);\n    }\n\n    if (element.parentNode) {\n      element.parentNode.replaceChild(wrapper, element);\n    }\n\n    wrapper.appendChild(element);\n    return wrapper;\n  }\n  /**\n   * Returns element scroll offsets\n   * @memberOf fabric.util\n   * @param {HTMLElement} element Element to operate on\n   * @return {Object} Object with left/top values\n   */\n\n\n  function getScrollLeftTop(element) {\n    var left = 0,\n        top = 0,\n        docElement = fabric.document.documentElement,\n        body = fabric.document.body || {\n      scrollLeft: 0,\n      scrollTop: 0\n    }; // While loop checks (and then sets element to) .parentNode OR .host\n    //  to account for ShadowDOM. We still want to traverse up out of ShadowDOM,\n    //  but the .parentNode of a root ShadowDOM node will always be null, instead\n    //  it should be accessed through .host. See http://stackoverflow.com/a/24765528/4383938\n\n    while (element && (element.parentNode || element.host)) {\n      // Set element to element parent, or 'host' in case of ShadowDOM\n      element = element.parentNode || element.host;\n\n      if (element === fabric.document) {\n        left = body.scrollLeft || docElement.scrollLeft || 0;\n        top = body.scrollTop || docElement.scrollTop || 0;\n      } else {\n        left += element.scrollLeft || 0;\n        top += element.scrollTop || 0;\n      }\n\n      if (element.nodeType === 1 && element.style.position === 'fixed') {\n        break;\n      }\n    }\n\n    return {\n      left: left,\n      top: top\n    };\n  }\n  /**\n   * Returns offset for a given element\n   * @function\n   * @memberOf fabric.util\n   * @param {HTMLElement} element Element to get offset for\n   * @return {Object} Object with \"left\" and \"top\" properties\n   */\n\n\n  function getElementOffset(element) {\n    var docElem,\n        doc = element && element.ownerDocument,\n        box = {\n      left: 0,\n      top: 0\n    },\n        offset = {\n      left: 0,\n      top: 0\n    },\n        scrollLeftTop,\n        offsetAttributes = {\n      borderLeftWidth: 'left',\n      borderTopWidth: 'top',\n      paddingLeft: 'left',\n      paddingTop: 'top'\n    };\n\n    if (!doc) {\n      return offset;\n    }\n\n    for (var attr in offsetAttributes) {\n      offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0;\n    }\n\n    docElem = doc.documentElement;\n\n    if (typeof element.getBoundingClientRect !== 'undefined') {\n      box = element.getBoundingClientRect();\n    }\n\n    scrollLeftTop = getScrollLeftTop(element);\n    return {\n      left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left,\n      top: box.top + scrollLeftTop.top - (docElem.clientTop || 0) + offset.top\n    };\n  }\n  /**\n   * Returns style attribute value of a given element\n   * @memberOf fabric.util\n   * @param {HTMLElement} element Element to get style attribute for\n   * @param {String} attr Style attribute to get for element\n   * @return {String} Style attribute value of the given element.\n   */\n\n\n  var getElementStyle;\n\n  if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) {\n    getElementStyle = function (element, attr) {\n      var style = fabric.document.defaultView.getComputedStyle(element, null);\n      return style ? style[attr] : undefined;\n    };\n  } else {\n    getElementStyle = function (element, attr) {\n      var value = element.style[attr];\n\n      if (!value && element.currentStyle) {\n        value = element.currentStyle[attr];\n      }\n\n      return value;\n    };\n  }\n\n  (function () {\n    var style = fabric.document.documentElement.style,\n        selectProp = 'userSelect' in style ? 'userSelect' : 'MozUserSelect' in style ? 'MozUserSelect' : 'WebkitUserSelect' in style ? 'WebkitUserSelect' : 'KhtmlUserSelect' in style ? 'KhtmlUserSelect' : '';\n    /**\n     * Makes element unselectable\n     * @memberOf fabric.util\n     * @param {HTMLElement} element Element to make unselectable\n     * @return {HTMLElement} Element that was passed in\n     */\n\n    function makeElementUnselectable(element) {\n      if (typeof element.onselectstart !== 'undefined') {\n        element.onselectstart = fabric.util.falseFunction;\n      }\n\n      if (selectProp) {\n        element.style[selectProp] = 'none';\n      } else if (typeof element.unselectable === 'string') {\n        element.unselectable = 'on';\n      }\n\n      return element;\n    }\n    /**\n     * Makes element selectable\n     * @memberOf fabric.util\n     * @param {HTMLElement} element Element to make selectable\n     * @return {HTMLElement} Element that was passed in\n     */\n\n\n    function makeElementSelectable(element) {\n      if (typeof element.onselectstart !== 'undefined') {\n        element.onselectstart = null;\n      }\n\n      if (selectProp) {\n        element.style[selectProp] = '';\n      } else if (typeof element.unselectable === 'string') {\n        element.unselectable = '';\n      }\n\n      return element;\n    }\n\n    fabric.util.makeElementUnselectable = makeElementUnselectable;\n    fabric.util.makeElementSelectable = makeElementSelectable;\n  })();\n\n  function getNodeCanvas(element) {\n    var impl = fabric.jsdomImplForWrapper(element);\n    return impl._canvas || impl._image;\n  }\n\n  ;\n\n  function cleanUpJsdomNode(element) {\n    if (!fabric.isLikelyNode) {\n      return;\n    }\n\n    var impl = fabric.jsdomImplForWrapper(element);\n\n    if (impl) {\n      impl._image = null;\n      impl._canvas = null; // unsure if necessary\n\n      impl._currentSrc = null;\n      impl._attributes = null;\n      impl._classList = null;\n    }\n  }\n\n  function setImageSmoothing(ctx, value) {\n    ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled || ctx.webkitImageSmoothingEnabled || ctx.mozImageSmoothingEnabled || ctx.msImageSmoothingEnabled || ctx.oImageSmoothingEnabled;\n    ctx.imageSmoothingEnabled = value;\n  }\n  /**\n   * setImageSmoothing sets the context imageSmoothingEnabled property.\n   * Used by canvas and by ImageObject.\n   * @memberOf fabric.util\n   * @since 4.0.0\n   * @param {HTMLRenderingContext2D} ctx to set on\n   * @param {Boolean} value true or false\n   */\n\n\n  fabric.util.setImageSmoothing = setImageSmoothing;\n  fabric.util.getById = getById;\n  fabric.util.toArray = toArray;\n  fabric.util.addClass = addClass;\n  fabric.util.makeElement = makeElement;\n  fabric.util.wrapElement = wrapElement;\n  fabric.util.getScrollLeftTop = getScrollLeftTop;\n  fabric.util.getElementOffset = getElementOffset;\n  fabric.util.getNodeCanvas = getNodeCanvas;\n  fabric.util.cleanUpJsdomNode = cleanUpJsdomNode;\n})();\n\n(function () {\n  function addParamToUrl(url, param) {\n    return url + (/\\?/.test(url) ? '&' : '?') + param;\n  }\n\n  function emptyFn() {}\n  /**\n   * Cross-browser abstraction for sending XMLHttpRequest\n   * @memberOf fabric.util\n   * @param {String} url URL to send XMLHttpRequest to\n   * @param {Object} [options] Options object\n   * @param {String} [options.method=\"GET\"]\n   * @param {String} [options.parameters] parameters to append to url in GET or in body\n   * @param {String} [options.body] body to send with POST or PUT request\n   * @param {Function} options.onComplete Callback to invoke when request is completed\n   * @return {XMLHttpRequest} request\n   */\n\n\n  function request(url, options) {\n    options || (options = {});\n\n    var method = options.method ? options.method.toUpperCase() : 'GET',\n        onComplete = options.onComplete || function () {},\n        xhr = new fabric.window.XMLHttpRequest(),\n        body = options.body || options.parameters;\n    /** @ignore */\n\n\n    xhr.onreadystatechange = function () {\n      if (xhr.readyState === 4) {\n        onComplete(xhr);\n        xhr.onreadystatechange = emptyFn;\n      }\n    };\n\n    if (method === 'GET') {\n      body = null;\n\n      if (typeof options.parameters === 'string') {\n        url = addParamToUrl(url, options.parameters);\n      }\n    }\n\n    xhr.open(method, url, true);\n\n    if (method === 'POST' || method === 'PUT') {\n      xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\n    }\n\n    xhr.send(body);\n    return xhr;\n  }\n\n  fabric.util.request = request;\n})();\n/**\n * Wrapper around `console.log` (when available)\n * @param {*} [values] Values to log\n */\n\n\nfabric.log = console.log;\n/**\n * Wrapper around `console.warn` (when available)\n * @param {*} [values] Values to log as a warning\n */\n\nfabric.warn = console.warn;\n\n(function () {\n  function noop() {\n    return false;\n  }\n\n  function defaultEasing(t, b, c, d) {\n    return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;\n  }\n  /**\n   * Changes value from one to another within certain period of time, invoking callbacks as value is being changed.\n   * @memberOf fabric.util\n   * @param {Object} [options] Animation options\n   * @param {Function} [options.onChange] Callback; invoked on every value change\n   * @param {Function} [options.onComplete] Callback; invoked when value change is completed\n   * @param {Number} [options.startValue=0] Starting value\n   * @param {Number} [options.endValue=100] Ending value\n   * @param {Number} [options.byValue=100] Value to modify the property by\n   * @param {Function} [options.easing] Easing function\n   * @param {Number} [options.duration=500] Duration of change (in ms)\n   * @param {Function} [options.abort] Additional function with logic. If returns true, onComplete is called.\n   */\n\n\n  function animate(options) {\n    requestAnimFrame(function (timestamp) {\n      options || (options = {});\n      var start = timestamp || +new Date(),\n          duration = options.duration || 500,\n          finish = start + duration,\n          time,\n          onChange = options.onChange || noop,\n          abort = options.abort || noop,\n          onComplete = options.onComplete || noop,\n          easing = options.easing || defaultEasing,\n          startValue = 'startValue' in options ? options.startValue : 0,\n          endValue = 'endValue' in options ? options.endValue : 100,\n          byValue = options.byValue || endValue - startValue;\n      options.onStart && options.onStart();\n\n      (function tick(ticktime) {\n        // TODO: move abort call after calculation\n        // and pass (current,valuePerc, timePerc) as arguments\n        time = ticktime || +new Date();\n        var currentTime = time > finish ? duration : time - start,\n            timePerc = currentTime / duration,\n            current = easing(currentTime, startValue, byValue, duration),\n            valuePerc = Math.abs((current - startValue) / byValue);\n\n        if (abort()) {\n          onComplete(endValue, 1, 1);\n          return;\n        }\n\n        if (time > finish) {\n          onChange(endValue, 1, 1);\n          onComplete(endValue, 1, 1);\n          return;\n        } else {\n          onChange(current, valuePerc, timePerc);\n          requestAnimFrame(tick);\n        }\n      })(start);\n    });\n  }\n\n  var _requestAnimFrame = fabric.window.requestAnimationFrame || fabric.window.webkitRequestAnimationFrame || fabric.window.mozRequestAnimationFrame || fabric.window.oRequestAnimationFrame || fabric.window.msRequestAnimationFrame || function (callback) {\n    return fabric.window.setTimeout(callback, 1000 / 60);\n  };\n\n  var _cancelAnimFrame = fabric.window.cancelAnimationFrame || fabric.window.clearTimeout;\n  /**\n   * requestAnimationFrame polyfill based on http://paulirish.com/2011/requestanimationframe-for-smart-animating/\n   * In order to get a precise start time, `requestAnimFrame` should be called as an entry into the method\n   * @memberOf fabric.util\n   * @param {Function} callback Callback to invoke\n   * @param {DOMElement} element optional Element to associate with animation\n   */\n\n\n  function requestAnimFrame() {\n    return _requestAnimFrame.apply(fabric.window, arguments);\n  }\n\n  function cancelAnimFrame() {\n    return _cancelAnimFrame.apply(fabric.window, arguments);\n  }\n\n  fabric.util.animate = animate;\n  fabric.util.requestAnimFrame = requestAnimFrame;\n  fabric.util.cancelAnimFrame = cancelAnimFrame;\n})();\n\n(function () {\n  // Calculate an in-between color. Returns a \"rgba()\" string.\n  // Credit: Edwin Martin <edwin@bitstorm.org>\n  //         http://www.bitstorm.org/jquery/color-animation/jquery.animate-colors.js\n  function calculateColor(begin, end, pos) {\n    var color = 'rgba(' + parseInt(begin[0] + pos * (end[0] - begin[0]), 10) + ',' + parseInt(begin[1] + pos * (end[1] - begin[1]), 10) + ',' + parseInt(begin[2] + pos * (end[2] - begin[2]), 10);\n    color += ',' + (begin && end ? parseFloat(begin[3] + pos * (end[3] - begin[3])) : 1);\n    color += ')';\n    return color;\n  }\n  /**\n   * Changes the color from one to another within certain period of time, invoking callbacks as value is being changed.\n   * @memberOf fabric.util\n   * @param {String} fromColor The starting color in hex or rgb(a) format.\n   * @param {String} toColor The starting color in hex or rgb(a) format.\n   * @param {Number} [duration] Duration of change (in ms).\n   * @param {Object} [options] Animation options\n   * @param {Function} [options.onChange] Callback; invoked on every value change\n   * @param {Function} [options.onComplete] Callback; invoked when value change is completed\n   * @param {Function} [options.colorEasing] Easing function. Note that this function only take two arguments (currentTime, duration). Thus the regular animation easing functions cannot be used.\n   * @param {Function} [options.abort] Additional function with logic. If returns true, onComplete is called.\n   */\n\n\n  function animateColor(fromColor, toColor, duration, options) {\n    var startColor = new fabric.Color(fromColor).getSource(),\n        endColor = new fabric.Color(toColor).getSource(),\n        originalOnComplete = options.onComplete,\n        originalOnChange = options.onChange;\n    options = options || {};\n    fabric.util.animate(fabric.util.object.extend(options, {\n      duration: duration || 500,\n      startValue: startColor,\n      endValue: endColor,\n      byValue: endColor,\n      easing: function (currentTime, startValue, byValue, duration) {\n        var posValue = options.colorEasing ? options.colorEasing(currentTime, duration) : 1 - Math.cos(currentTime / duration * (Math.PI / 2));\n        return calculateColor(startValue, byValue, posValue);\n      },\n      // has to take in account for color restoring;\n      onComplete: function (current, valuePerc, timePerc) {\n        if (originalOnComplete) {\n          return originalOnComplete(calculateColor(endColor, endColor, 0), valuePerc, timePerc);\n        }\n      },\n      onChange: function (current, valuePerc, timePerc) {\n        if (originalOnChange) {\n          if (Array.isArray(current)) {\n            return originalOnChange(calculateColor(current, current, 0), valuePerc, timePerc);\n          }\n\n          originalOnChange(current, valuePerc, timePerc);\n        }\n      }\n    }));\n  }\n\n  fabric.util.animateColor = animateColor;\n})();\n\n(function () {\n  function normalize(a, c, p, s) {\n    if (a < Math.abs(c)) {\n      a = c;\n      s = p / 4;\n    } else {\n      //handle the 0/0 case:\n      if (c === 0 && a === 0) {\n        s = p / (2 * Math.PI) * Math.asin(1);\n      } else {\n        s = p / (2 * Math.PI) * Math.asin(c / a);\n      }\n    }\n\n    return {\n      a: a,\n      c: c,\n      p: p,\n      s: s\n    };\n  }\n\n  function elastic(opts, t, d) {\n    return opts.a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p);\n  }\n  /**\n   * Cubic easing out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeOutCubic(t, b, c, d) {\n    return c * ((t = t / d - 1) * t * t + 1) + b;\n  }\n  /**\n   * Cubic easing in and out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInOutCubic(t, b, c, d) {\n    t /= d / 2;\n\n    if (t < 1) {\n      return c / 2 * t * t * t + b;\n    }\n\n    return c / 2 * ((t -= 2) * t * t + 2) + b;\n  }\n  /**\n   * Quartic easing in\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInQuart(t, b, c, d) {\n    return c * (t /= d) * t * t * t + b;\n  }\n  /**\n   * Quartic easing out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeOutQuart(t, b, c, d) {\n    return -c * ((t = t / d - 1) * t * t * t - 1) + b;\n  }\n  /**\n   * Quartic easing in and out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInOutQuart(t, b, c, d) {\n    t /= d / 2;\n\n    if (t < 1) {\n      return c / 2 * t * t * t * t + b;\n    }\n\n    return -c / 2 * ((t -= 2) * t * t * t - 2) + b;\n  }\n  /**\n   * Quintic easing in\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInQuint(t, b, c, d) {\n    return c * (t /= d) * t * t * t * t + b;\n  }\n  /**\n   * Quintic easing out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeOutQuint(t, b, c, d) {\n    return c * ((t = t / d - 1) * t * t * t * t + 1) + b;\n  }\n  /**\n   * Quintic easing in and out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInOutQuint(t, b, c, d) {\n    t /= d / 2;\n\n    if (t < 1) {\n      return c / 2 * t * t * t * t * t + b;\n    }\n\n    return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;\n  }\n  /**\n   * Sinusoidal easing in\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInSine(t, b, c, d) {\n    return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;\n  }\n  /**\n   * Sinusoidal easing out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeOutSine(t, b, c, d) {\n    return c * Math.sin(t / d * (Math.PI / 2)) + b;\n  }\n  /**\n   * Sinusoidal easing in and out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInOutSine(t, b, c, d) {\n    return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;\n  }\n  /**\n   * Exponential easing in\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInExpo(t, b, c, d) {\n    return t === 0 ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;\n  }\n  /**\n   * Exponential easing out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeOutExpo(t, b, c, d) {\n    return t === d ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;\n  }\n  /**\n   * Exponential easing in and out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInOutExpo(t, b, c, d) {\n    if (t === 0) {\n      return b;\n    }\n\n    if (t === d) {\n      return b + c;\n    }\n\n    t /= d / 2;\n\n    if (t < 1) {\n      return c / 2 * Math.pow(2, 10 * (t - 1)) + b;\n    }\n\n    return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;\n  }\n  /**\n   * Circular easing in\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInCirc(t, b, c, d) {\n    return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;\n  }\n  /**\n   * Circular easing out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeOutCirc(t, b, c, d) {\n    return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;\n  }\n  /**\n   * Circular easing in and out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInOutCirc(t, b, c, d) {\n    t /= d / 2;\n\n    if (t < 1) {\n      return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;\n    }\n\n    return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;\n  }\n  /**\n   * Elastic easing in\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInElastic(t, b, c, d) {\n    var s = 1.70158,\n        p = 0,\n        a = c;\n\n    if (t === 0) {\n      return b;\n    }\n\n    t /= d;\n\n    if (t === 1) {\n      return b + c;\n    }\n\n    if (!p) {\n      p = d * 0.3;\n    }\n\n    var opts = normalize(a, c, p, s);\n    return -elastic(opts, t, d) + b;\n  }\n  /**\n   * Elastic easing out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeOutElastic(t, b, c, d) {\n    var s = 1.70158,\n        p = 0,\n        a = c;\n\n    if (t === 0) {\n      return b;\n    }\n\n    t /= d;\n\n    if (t === 1) {\n      return b + c;\n    }\n\n    if (!p) {\n      p = d * 0.3;\n    }\n\n    var opts = normalize(a, c, p, s);\n    return opts.a * Math.pow(2, -10 * t) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p) + opts.c + b;\n  }\n  /**\n   * Elastic easing in and out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInOutElastic(t, b, c, d) {\n    var s = 1.70158,\n        p = 0,\n        a = c;\n\n    if (t === 0) {\n      return b;\n    }\n\n    t /= d / 2;\n\n    if (t === 2) {\n      return b + c;\n    }\n\n    if (!p) {\n      p = d * (0.3 * 1.5);\n    }\n\n    var opts = normalize(a, c, p, s);\n\n    if (t < 1) {\n      return -0.5 * elastic(opts, t, d) + b;\n    }\n\n    return opts.a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p) * 0.5 + opts.c + b;\n  }\n  /**\n   * Backwards easing in\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInBack(t, b, c, d, s) {\n    if (s === undefined) {\n      s = 1.70158;\n    }\n\n    return c * (t /= d) * t * ((s + 1) * t - s) + b;\n  }\n  /**\n   * Backwards easing out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeOutBack(t, b, c, d, s) {\n    if (s === undefined) {\n      s = 1.70158;\n    }\n\n    return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;\n  }\n  /**\n   * Backwards easing in and out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInOutBack(t, b, c, d, s) {\n    if (s === undefined) {\n      s = 1.70158;\n    }\n\n    t /= d / 2;\n\n    if (t < 1) {\n      return c / 2 * (t * t * (((s *= 1.525) + 1) * t - s)) + b;\n    }\n\n    return c / 2 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2) + b;\n  }\n  /**\n   * Bouncing easing in\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInBounce(t, b, c, d) {\n    return c - easeOutBounce(d - t, 0, c, d) + b;\n  }\n  /**\n   * Bouncing easing out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeOutBounce(t, b, c, d) {\n    if ((t /= d) < 1 / 2.75) {\n      return c * (7.5625 * t * t) + b;\n    } else if (t < 2 / 2.75) {\n      return c * (7.5625 * (t -= 1.5 / 2.75) * t + 0.75) + b;\n    } else if (t < 2.5 / 2.75) {\n      return c * (7.5625 * (t -= 2.25 / 2.75) * t + 0.9375) + b;\n    } else {\n      return c * (7.5625 * (t -= 2.625 / 2.75) * t + 0.984375) + b;\n    }\n  }\n  /**\n   * Bouncing easing in and out\n   * @memberOf fabric.util.ease\n   */\n\n\n  function easeInOutBounce(t, b, c, d) {\n    if (t < d / 2) {\n      return easeInBounce(t * 2, 0, c, d) * 0.5 + b;\n    }\n\n    return easeOutBounce(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;\n  }\n  /**\n   * Easing functions\n   * See <a href=\"http://gizma.com/easing/\">Easing Equations by Robert Penner</a>\n   * @namespace fabric.util.ease\n   */\n\n\n  fabric.util.ease = {\n    /**\n     * Quadratic easing in\n     * @memberOf fabric.util.ease\n     */\n    easeInQuad: function (t, b, c, d) {\n      return c * (t /= d) * t + b;\n    },\n\n    /**\n     * Quadratic easing out\n     * @memberOf fabric.util.ease\n     */\n    easeOutQuad: function (t, b, c, d) {\n      return -c * (t /= d) * (t - 2) + b;\n    },\n\n    /**\n     * Quadratic easing in and out\n     * @memberOf fabric.util.ease\n     */\n    easeInOutQuad: function (t, b, c, d) {\n      t /= d / 2;\n\n      if (t < 1) {\n        return c / 2 * t * t + b;\n      }\n\n      return -c / 2 * (--t * (t - 2) - 1) + b;\n    },\n\n    /**\n     * Cubic easing in\n     * @memberOf fabric.util.ease\n     */\n    easeInCubic: function (t, b, c, d) {\n      return c * (t /= d) * t * t + b;\n    },\n    easeOutCubic: easeOutCubic,\n    easeInOutCubic: easeInOutCubic,\n    easeInQuart: easeInQuart,\n    easeOutQuart: easeOutQuart,\n    easeInOutQuart: easeInOutQuart,\n    easeInQuint: easeInQuint,\n    easeOutQuint: easeOutQuint,\n    easeInOutQuint: easeInOutQuint,\n    easeInSine: easeInSine,\n    easeOutSine: easeOutSine,\n    easeInOutSine: easeInOutSine,\n    easeInExpo: easeInExpo,\n    easeOutExpo: easeOutExpo,\n    easeInOutExpo: easeInOutExpo,\n    easeInCirc: easeInCirc,\n    easeOutCirc: easeOutCirc,\n    easeInOutCirc: easeInOutCirc,\n    easeInElastic: easeInElastic,\n    easeOutElastic: easeOutElastic,\n    easeInOutElastic: easeInOutElastic,\n    easeInBack: easeInBack,\n    easeOutBack: easeOutBack,\n    easeInOutBack: easeInOutBack,\n    easeInBounce: easeInBounce,\n    easeOutBounce: easeOutBounce,\n    easeInOutBounce: easeInOutBounce\n  };\n})();\n\n(function (global) {\n  'use strict';\n  /**\n   * @name fabric\n   * @namespace\n   */\n\n  var fabric = global.fabric || (global.fabric = {}),\n      extend = fabric.util.object.extend,\n      clone = fabric.util.object.clone,\n      toFixed = fabric.util.toFixed,\n      parseUnit = fabric.util.parseUnit,\n      multiplyTransformMatrices = fabric.util.multiplyTransformMatrices,\n      svgValidTagNames = ['path', 'circle', 'polygon', 'polyline', 'ellipse', 'rect', 'line', 'image', 'text'],\n      svgViewBoxElements = ['symbol', 'image', 'marker', 'pattern', 'view', 'svg'],\n      svgInvalidAncestors = ['pattern', 'defs', 'symbol', 'metadata', 'clipPath', 'mask', 'desc'],\n      svgValidParents = ['symbol', 'g', 'a', 'svg', 'clipPath', 'defs'],\n      attributesMap = {\n    cx: 'left',\n    x: 'left',\n    r: 'radius',\n    cy: 'top',\n    y: 'top',\n    display: 'visible',\n    visibility: 'visible',\n    transform: 'transformMatrix',\n    'fill-opacity': 'fillOpacity',\n    'fill-rule': 'fillRule',\n    'font-family': 'fontFamily',\n    'font-size': 'fontSize',\n    'font-style': 'fontStyle',\n    'font-weight': 'fontWeight',\n    'letter-spacing': 'charSpacing',\n    'paint-order': 'paintFirst',\n    'stroke-dasharray': 'strokeDashArray',\n    'stroke-dashoffset': 'strokeDashOffset',\n    'stroke-linecap': 'strokeLineCap',\n    'stroke-linejoin': 'strokeLineJoin',\n    'stroke-miterlimit': 'strokeMiterLimit',\n    'stroke-opacity': 'strokeOpacity',\n    'stroke-width': 'strokeWidth',\n    'text-decoration': 'textDecoration',\n    'text-anchor': 'textAnchor',\n    opacity: 'opacity',\n    'clip-path': 'clipPath',\n    'clip-rule': 'clipRule',\n    'vector-effect': 'strokeUniform',\n    'image-rendering': 'imageSmoothing'\n  },\n      colorAttributes = {\n    stroke: 'strokeOpacity',\n    fill: 'fillOpacity'\n  },\n      fSize = 'font-size',\n      cPath = 'clip-path';\n  fabric.svgValidTagNamesRegEx = getSvgRegex(svgValidTagNames);\n  fabric.svgViewBoxElementsRegEx = getSvgRegex(svgViewBoxElements);\n  fabric.svgInvalidAncestorsRegEx = getSvgRegex(svgInvalidAncestors);\n  fabric.svgValidParentsRegEx = getSvgRegex(svgValidParents);\n  fabric.cssRules = {};\n  fabric.gradientDefs = {};\n  fabric.clipPaths = {};\n\n  function normalizeAttr(attr) {\n    // transform attribute names\n    if (attr in attributesMap) {\n      return attributesMap[attr];\n    }\n\n    return attr;\n  }\n\n  function normalizeValue(attr, value, parentAttributes, fontSize) {\n    var isArray = Object.prototype.toString.call(value) === '[object Array]',\n        parsed;\n\n    if ((attr === 'fill' || attr === 'stroke') && value === 'none') {\n      value = '';\n    } else if (attr === 'strokeUniform') {\n      return value === 'non-scaling-stroke';\n    } else if (attr === 'strokeDashArray') {\n      if (value === 'none') {\n        value = null;\n      } else {\n        value = value.replace(/,/g, ' ').split(/\\s+/).map(parseFloat);\n      }\n    } else if (attr === 'transformMatrix') {\n      if (parentAttributes && parentAttributes.transformMatrix) {\n        value = multiplyTransformMatrices(parentAttributes.transformMatrix, fabric.parseTransformAttribute(value));\n      } else {\n        value = fabric.parseTransformAttribute(value);\n      }\n    } else if (attr === 'visible') {\n      value = value !== 'none' && value !== 'hidden'; // display=none on parent element always takes precedence over child element\n\n      if (parentAttributes && parentAttributes.visible === false) {\n        value = false;\n      }\n    } else if (attr === 'opacity') {\n      value = parseFloat(value);\n\n      if (parentAttributes && typeof parentAttributes.opacity !== 'undefined') {\n        value *= parentAttributes.opacity;\n      }\n    } else if (attr === 'textAnchor'\n    /* text-anchor */\n    ) {\n        value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center';\n      } else if (attr === 'charSpacing') {\n      // parseUnit returns px and we convert it to em\n      parsed = parseUnit(value, fontSize) / fontSize * 1000;\n    } else if (attr === 'paintFirst') {\n      var fillIndex = value.indexOf('fill');\n      var strokeIndex = value.indexOf('stroke');\n      var value = 'fill';\n\n      if (fillIndex > -1 && strokeIndex > -1 && strokeIndex < fillIndex) {\n        value = 'stroke';\n      } else if (fillIndex === -1 && strokeIndex > -1) {\n        value = 'stroke';\n      }\n    } else if (attr === 'href' || attr === 'xlink:href' || attr === 'font') {\n      return value;\n    } else if (attr === 'imageSmoothing') {\n      return value === 'optimizeQuality' ? true : false;\n    } else {\n      parsed = isArray ? value.map(parseUnit) : parseUnit(value, fontSize);\n    }\n\n    return !isArray && isNaN(parsed) ? value : parsed;\n  }\n  /**\n    * @private\n    */\n\n\n  function getSvgRegex(arr) {\n    return new RegExp('^(' + arr.join('|') + ')\\\\b', 'i');\n  }\n  /**\n   * @private\n   * @param {Object} attributes Array of attributes to parse\n   */\n\n\n  function _setStrokeFillOpacity(attributes) {\n    for (var attr in colorAttributes) {\n      if (typeof attributes[colorAttributes[attr]] === 'undefined' || attributes[attr] === '') {\n        continue;\n      }\n\n      if (typeof attributes[attr] === 'undefined') {\n        if (!fabric.Object.prototype[attr]) {\n          continue;\n        }\n\n        attributes[attr] = fabric.Object.prototype[attr];\n      }\n\n      if (attributes[attr].indexOf('url(') === 0) {\n        continue;\n      }\n\n      var color = new fabric.Color(attributes[attr]);\n      attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba();\n    }\n\n    return attributes;\n  }\n  /**\n   * @private\n   */\n\n\n  function _getMultipleNodes(doc, nodeNames) {\n    var nodeName,\n        nodeArray = [],\n        nodeList,\n        i,\n        len;\n\n    for (i = 0, len = nodeNames.length; i < len; i++) {\n      nodeName = nodeNames[i];\n      nodeList = doc.getElementsByTagName(nodeName);\n      nodeArray = nodeArray.concat(Array.prototype.slice.call(nodeList));\n    }\n\n    return nodeArray;\n  }\n  /**\n   * Parses \"transform\" attribute, returning an array of values\n   * @static\n   * @function\n   * @memberOf fabric\n   * @param {String} attributeValue String containing attribute value\n   * @return {Array} Array of 6 elements representing transformation matrix\n   */\n\n\n  fabric.parseTransformAttribute = function () {\n    function rotateMatrix(matrix, args) {\n      var cos = fabric.util.cos(args[0]),\n          sin = fabric.util.sin(args[0]),\n          x = 0,\n          y = 0;\n\n      if (args.length === 3) {\n        x = args[1];\n        y = args[2];\n      }\n\n      matrix[0] = cos;\n      matrix[1] = sin;\n      matrix[2] = -sin;\n      matrix[3] = cos;\n      matrix[4] = x - (cos * x - sin * y);\n      matrix[5] = y - (sin * x + cos * y);\n    }\n\n    function scaleMatrix(matrix, args) {\n      var multiplierX = args[0],\n          multiplierY = args.length === 2 ? args[1] : args[0];\n      matrix[0] = multiplierX;\n      matrix[3] = multiplierY;\n    }\n\n    function skewMatrix(matrix, args, pos) {\n      matrix[pos] = Math.tan(fabric.util.degreesToRadians(args[0]));\n    }\n\n    function translateMatrix(matrix, args) {\n      matrix[4] = args[0];\n\n      if (args.length === 2) {\n        matrix[5] = args[1];\n      }\n    } // identity matrix\n\n\n    var iMatrix = fabric.iMatrix,\n        // == begin transform regexp\n    number = fabric.reNum,\n        commaWsp = fabric.commaWsp,\n        skewX = '(?:(skewX)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*\\\\))',\n        skewY = '(?:(skewY)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*\\\\))',\n        rotate = '(?:(rotate)\\\\s*\\\\(\\\\s*(' + number + ')(?:' + commaWsp + '(' + number + ')' + commaWsp + '(' + number + '))?\\\\s*\\\\))',\n        scale = '(?:(scale)\\\\s*\\\\(\\\\s*(' + number + ')(?:' + commaWsp + '(' + number + '))?\\\\s*\\\\))',\n        translate = '(?:(translate)\\\\s*\\\\(\\\\s*(' + number + ')(?:' + commaWsp + '(' + number + '))?\\\\s*\\\\))',\n        matrix = '(?:(matrix)\\\\s*\\\\(\\\\s*' + '(' + number + ')' + commaWsp + '(' + number + ')' + commaWsp + '(' + number + ')' + commaWsp + '(' + number + ')' + commaWsp + '(' + number + ')' + commaWsp + '(' + number + ')' + '\\\\s*\\\\))',\n        transform = '(?:' + matrix + '|' + translate + '|' + scale + '|' + rotate + '|' + skewX + '|' + skewY + ')',\n        transforms = '(?:' + transform + '(?:' + commaWsp + '*' + transform + ')*' + ')',\n        transformList = '^\\\\s*(?:' + transforms + '?)\\\\s*$',\n        // http://www.w3.org/TR/SVG/coords.html#TransformAttribute\n    reTransformList = new RegExp(transformList),\n        // == end transform regexp\n    reTransform = new RegExp(transform, 'g');\n    return function (attributeValue) {\n      // start with identity matrix\n      var matrix = iMatrix.concat(),\n          matrices = []; // return if no argument was given or\n      // an argument does not match transform attribute regexp\n\n      if (!attributeValue || attributeValue && !reTransformList.test(attributeValue)) {\n        return matrix;\n      }\n\n      attributeValue.replace(reTransform, function (match) {\n        var m = new RegExp(transform).exec(match).filter(function (match) {\n          // match !== '' && match != null\n          return !!match;\n        }),\n            operation = m[1],\n            args = m.slice(2).map(parseFloat);\n\n        switch (operation) {\n          case 'translate':\n            translateMatrix(matrix, args);\n            break;\n\n          case 'rotate':\n            args[0] = fabric.util.degreesToRadians(args[0]);\n            rotateMatrix(matrix, args);\n            break;\n\n          case 'scale':\n            scaleMatrix(matrix, args);\n            break;\n\n          case 'skewX':\n            skewMatrix(matrix, args, 2);\n            break;\n\n          case 'skewY':\n            skewMatrix(matrix, args, 1);\n            break;\n\n          case 'matrix':\n            matrix = args;\n            break;\n        } // snapshot current matrix into matrices array\n\n\n        matrices.push(matrix.concat()); // reset\n\n        matrix = iMatrix.concat();\n      });\n      var combinedMatrix = matrices[0];\n\n      while (matrices.length > 1) {\n        matrices.shift();\n        combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]);\n      }\n\n      return combinedMatrix;\n    };\n  }();\n  /**\n   * @private\n   */\n\n\n  function parseStyleString(style, oStyle) {\n    var attr, value;\n    style.replace(/;\\s*$/, '').split(';').forEach(function (chunk) {\n      var pair = chunk.split(':');\n      attr = pair[0].trim().toLowerCase();\n      value = pair[1].trim();\n      oStyle[attr] = value;\n    });\n  }\n  /**\n   * @private\n   */\n\n\n  function parseStyleObject(style, oStyle) {\n    var attr, value;\n\n    for (var prop in style) {\n      if (typeof style[prop] === 'undefined') {\n        continue;\n      }\n\n      attr = prop.toLowerCase();\n      value = style[prop];\n      oStyle[attr] = value;\n    }\n  }\n  /**\n   * @private\n   */\n\n\n  function getGlobalStylesForElement(element, svgUid) {\n    var styles = {};\n\n    for (var rule in fabric.cssRules[svgUid]) {\n      if (elementMatchesRule(element, rule.split(' '))) {\n        for (var property in fabric.cssRules[svgUid][rule]) {\n          styles[property] = fabric.cssRules[svgUid][rule][property];\n        }\n      }\n    }\n\n    return styles;\n  }\n  /**\n   * @private\n   */\n\n\n  function elementMatchesRule(element, selectors) {\n    var firstMatching,\n        parentMatching = true; //start from rightmost selector.\n\n    firstMatching = selectorMatches(element, selectors.pop());\n\n    if (firstMatching && selectors.length) {\n      parentMatching = doesSomeParentMatch(element, selectors);\n    }\n\n    return firstMatching && parentMatching && selectors.length === 0;\n  }\n\n  function doesSomeParentMatch(element, selectors) {\n    var selector,\n        parentMatching = true;\n\n    while (element.parentNode && element.parentNode.nodeType === 1 && selectors.length) {\n      if (parentMatching) {\n        selector = selectors.pop();\n      }\n\n      element = element.parentNode;\n      parentMatching = selectorMatches(element, selector);\n    }\n\n    return selectors.length === 0;\n  }\n  /**\n   * @private\n   */\n\n\n  function selectorMatches(element, selector) {\n    var nodeName = element.nodeName,\n        classNames = element.getAttribute('class'),\n        id = element.getAttribute('id'),\n        matcher,\n        i; // i check if a selector matches slicing away part from it.\n    // if i get empty string i should match\n\n    matcher = new RegExp('^' + nodeName, 'i');\n    selector = selector.replace(matcher, '');\n\n    if (id && selector.length) {\n      matcher = new RegExp('#' + id + '(?![a-zA-Z\\\\-]+)', 'i');\n      selector = selector.replace(matcher, '');\n    }\n\n    if (classNames && selector.length) {\n      classNames = classNames.split(' ');\n\n      for (i = classNames.length; i--;) {\n        matcher = new RegExp('\\\\.' + classNames[i] + '(?![a-zA-Z\\\\-]+)', 'i');\n        selector = selector.replace(matcher, '');\n      }\n    }\n\n    return selector.length === 0;\n  }\n  /**\n   * @private\n   * to support IE8 missing getElementById on SVGdocument and on node xmlDOM\n   */\n\n\n  function elementById(doc, id) {\n    var el;\n    doc.getElementById && (el = doc.getElementById(id));\n\n    if (el) {\n      return el;\n    }\n\n    var node,\n        i,\n        len,\n        nodelist = doc.getElementsByTagName('*');\n\n    for (i = 0, len = nodelist.length; i < len; i++) {\n      node = nodelist[i];\n\n      if (id === node.getAttribute('id')) {\n        return node;\n      }\n    }\n  }\n  /**\n   * @private\n   */\n\n\n  function parseUseDirectives(doc) {\n    var nodelist = _getMultipleNodes(doc, ['use', 'svg:use']),\n        i = 0;\n\n    while (nodelist.length && i < nodelist.length) {\n      var el = nodelist[i],\n          xlink = (el.getAttribute('xlink:href') || el.getAttribute('href')).substr(1),\n          x = el.getAttribute('x') || 0,\n          y = el.getAttribute('y') || 0,\n          el2 = elementById(doc, xlink).cloneNode(true),\n          currentTrans = (el2.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')',\n          parentNode,\n          oldLength = nodelist.length,\n          attr,\n          j,\n          attrs,\n          len,\n          namespace = fabric.svgNS;\n      applyViewboxTransform(el2);\n\n      if (/^svg$/i.test(el2.nodeName)) {\n        var el3 = el2.ownerDocument.createElementNS(namespace, 'g');\n\n        for (j = 0, attrs = el2.attributes, len = attrs.length; j < len; j++) {\n          attr = attrs.item(j);\n          el3.setAttributeNS(namespace, attr.nodeName, attr.nodeValue);\n        } // el2.firstChild != null\n\n\n        while (el2.firstChild) {\n          el3.appendChild(el2.firstChild);\n        }\n\n        el2 = el3;\n      }\n\n      for (j = 0, attrs = el.attributes, len = attrs.length; j < len; j++) {\n        attr = attrs.item(j);\n\n        if (attr.nodeName === 'x' || attr.nodeName === 'y' || attr.nodeName === 'xlink:href' || attr.nodeName === 'href') {\n          continue;\n        }\n\n        if (attr.nodeName === 'transform') {\n          currentTrans = attr.nodeValue + ' ' + currentTrans;\n        } else {\n          el2.setAttribute(attr.nodeName, attr.nodeValue);\n        }\n      }\n\n      el2.setAttribute('transform', currentTrans);\n      el2.setAttribute('instantiated_by_use', '1');\n      el2.removeAttribute('id');\n      parentNode = el.parentNode;\n      parentNode.replaceChild(el2, el); // some browsers do not shorten nodelist after replaceChild (IE8)\n\n      if (nodelist.length === oldLength) {\n        i++;\n      }\n    }\n  } // http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute\n  // matches, e.g.: +14.56e-12, etc.\n\n\n  var reViewBoxAttrValue = new RegExp('^' + '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' + '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' + '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' + '\\\\s*(' + fabric.reNum + '+)\\\\s*' + '$');\n  /**\n   * Add a <g> element that envelop all child elements and makes the viewbox transformMatrix descend on all elements\n   */\n\n  function applyViewboxTransform(element) {\n    if (!fabric.svgViewBoxElementsRegEx.test(element.nodeName)) {\n      return;\n    }\n\n    var viewBoxAttr = element.getAttribute('viewBox'),\n        scaleX = 1,\n        scaleY = 1,\n        minX = 0,\n        minY = 0,\n        viewBoxWidth,\n        viewBoxHeight,\n        matrix,\n        el,\n        widthAttr = element.getAttribute('width'),\n        heightAttr = element.getAttribute('height'),\n        x = element.getAttribute('x') || 0,\n        y = element.getAttribute('y') || 0,\n        preserveAspectRatio = element.getAttribute('preserveAspectRatio') || '',\n        missingViewBox = !viewBoxAttr || !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue)),\n        missingDimAttr = !widthAttr || !heightAttr || widthAttr === '100%' || heightAttr === '100%',\n        toBeParsed = missingViewBox && missingDimAttr,\n        parsedDim = {},\n        translateMatrix = '',\n        widthDiff = 0,\n        heightDiff = 0;\n    parsedDim.width = 0;\n    parsedDim.height = 0;\n    parsedDim.toBeParsed = toBeParsed;\n\n    if (missingViewBox) {\n      if ((x || y) && element.parentNode.nodeName !== '#document') {\n        translateMatrix = ' translate(' + parseUnit(x) + ' ' + parseUnit(y) + ') ';\n        matrix = (element.getAttribute('transform') || '') + translateMatrix;\n        element.setAttribute('transform', matrix);\n        element.removeAttribute('x');\n        element.removeAttribute('y');\n      }\n    }\n\n    if (toBeParsed) {\n      return parsedDim;\n    }\n\n    if (missingViewBox) {\n      parsedDim.width = parseUnit(widthAttr);\n      parsedDim.height = parseUnit(heightAttr); // set a transform for elements that have x y and are inner(only) SVGs\n\n      return parsedDim;\n    }\n\n    minX = -parseFloat(viewBoxAttr[1]);\n    minY = -parseFloat(viewBoxAttr[2]);\n    viewBoxWidth = parseFloat(viewBoxAttr[3]);\n    viewBoxHeight = parseFloat(viewBoxAttr[4]);\n    parsedDim.minX = minX;\n    parsedDim.minY = minY;\n    parsedDim.viewBoxWidth = viewBoxWidth;\n    parsedDim.viewBoxHeight = viewBoxHeight;\n\n    if (!missingDimAttr) {\n      parsedDim.width = parseUnit(widthAttr);\n      parsedDim.height = parseUnit(heightAttr);\n      scaleX = parsedDim.width / viewBoxWidth;\n      scaleY = parsedDim.height / viewBoxHeight;\n    } else {\n      parsedDim.width = viewBoxWidth;\n      parsedDim.height = viewBoxHeight;\n    } // default is to preserve aspect ratio\n\n\n    preserveAspectRatio = fabric.util.parsePreserveAspectRatioAttribute(preserveAspectRatio);\n\n    if (preserveAspectRatio.alignX !== 'none') {\n      //translate all container for the effect of Mid, Min, Max\n      if (preserveAspectRatio.meetOrSlice === 'meet') {\n        scaleY = scaleX = scaleX > scaleY ? scaleY : scaleX; // calculate additional translation to move the viewbox\n      }\n\n      if (preserveAspectRatio.meetOrSlice === 'slice') {\n        scaleY = scaleX = scaleX > scaleY ? scaleX : scaleY; // calculate additional translation to move the viewbox\n      }\n\n      widthDiff = parsedDim.width - viewBoxWidth * scaleX;\n      heightDiff = parsedDim.height - viewBoxHeight * scaleX;\n\n      if (preserveAspectRatio.alignX === 'Mid') {\n        widthDiff /= 2;\n      }\n\n      if (preserveAspectRatio.alignY === 'Mid') {\n        heightDiff /= 2;\n      }\n\n      if (preserveAspectRatio.alignX === 'Min') {\n        widthDiff = 0;\n      }\n\n      if (preserveAspectRatio.alignY === 'Min') {\n        heightDiff = 0;\n      }\n    }\n\n    if (scaleX === 1 && scaleY === 1 && minX === 0 && minY === 0 && x === 0 && y === 0) {\n      return parsedDim;\n    }\n\n    if ((x || y) && element.parentNode.nodeName !== '#document') {\n      translateMatrix = ' translate(' + parseUnit(x) + ' ' + parseUnit(y) + ') ';\n    }\n\n    matrix = translateMatrix + ' matrix(' + scaleX + ' 0' + ' 0 ' + scaleY + ' ' + (minX * scaleX + widthDiff) + ' ' + (minY * scaleY + heightDiff) + ') '; // seems unused.\n    // parsedDim.viewboxTransform = fabric.parseTransformAttribute(matrix);\n\n    if (element.nodeName === 'svg') {\n      el = element.ownerDocument.createElementNS(fabric.svgNS, 'g'); // element.firstChild != null\n\n      while (element.firstChild) {\n        el.appendChild(element.firstChild);\n      }\n\n      element.appendChild(el);\n    } else {\n      el = element;\n      el.removeAttribute('x');\n      el.removeAttribute('y');\n      matrix = el.getAttribute('transform') + matrix;\n    }\n\n    el.setAttribute('transform', matrix);\n    return parsedDim;\n  }\n\n  function hasAncestorWithNodeName(element, nodeName) {\n    while (element && (element = element.parentNode)) {\n      if (element.nodeName && nodeName.test(element.nodeName.replace('svg:', '')) && !element.getAttribute('instantiated_by_use')) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n  /**\n   * Parses an SVG document, converts it to an array of corresponding fabric.* instances and passes them to a callback\n   * @static\n   * @function\n   * @memberOf fabric\n   * @param {SVGDocument} doc SVG document to parse\n   * @param {Function} callback Callback to call when parsing is finished;\n   * It's being passed an array of elements (parsed from a document).\n   * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n   * @param {Object} [parsingOptions] options for parsing document\n   * @param {String} [parsingOptions.crossOrigin] crossOrigin settings\n   */\n\n\n  fabric.parseSVGDocument = function (doc, callback, reviver, parsingOptions) {\n    if (!doc) {\n      return;\n    }\n\n    parseUseDirectives(doc);\n    var svgUid = fabric.Object.__uid++,\n        i,\n        len,\n        options = applyViewboxTransform(doc),\n        descendants = fabric.util.toArray(doc.getElementsByTagName('*'));\n    options.crossOrigin = parsingOptions && parsingOptions.crossOrigin;\n    options.svgUid = svgUid;\n\n    if (descendants.length === 0 && fabric.isLikelyNode) {\n      // we're likely in node, where \"o3-xml\" library fails to gEBTN(\"*\")\n      // https://github.com/ajaxorg/node-o3-xml/issues/21\n      descendants = doc.selectNodes('//*[name(.)!=\"svg\"]');\n      var arr = [];\n\n      for (i = 0, len = descendants.length; i < len; i++) {\n        arr[i] = descendants[i];\n      }\n\n      descendants = arr;\n    }\n\n    var elements = descendants.filter(function (el) {\n      applyViewboxTransform(el);\n      return fabric.svgValidTagNamesRegEx.test(el.nodeName.replace('svg:', '')) && !hasAncestorWithNodeName(el, fabric.svgInvalidAncestorsRegEx); // http://www.w3.org/TR/SVG/struct.html#DefsElement\n    });\n\n    if (!elements || elements && !elements.length) {\n      callback && callback([], {});\n      return;\n    }\n\n    var clipPaths = {};\n    descendants.filter(function (el) {\n      return el.nodeName.replace('svg:', '') === 'clipPath';\n    }).forEach(function (el) {\n      var id = el.getAttribute('id');\n      clipPaths[id] = fabric.util.toArray(el.getElementsByTagName('*')).filter(function (el) {\n        return fabric.svgValidTagNamesRegEx.test(el.nodeName.replace('svg:', ''));\n      });\n    });\n    fabric.gradientDefs[svgUid] = fabric.getGradientDefs(doc);\n    fabric.cssRules[svgUid] = fabric.getCSSRules(doc);\n    fabric.clipPaths[svgUid] = clipPaths; // Precedence of rules:   style > class > attribute\n\n    fabric.parseElements(elements, function (instances, elements) {\n      if (callback) {\n        callback(instances, options, elements, descendants);\n        delete fabric.gradientDefs[svgUid];\n        delete fabric.cssRules[svgUid];\n        delete fabric.clipPaths[svgUid];\n      }\n    }, clone(options), reviver, parsingOptions);\n  };\n\n  function recursivelyParseGradientsXlink(doc, gradient) {\n    var gradientsAttrs = ['gradientTransform', 'x1', 'x2', 'y1', 'y2', 'gradientUnits', 'cx', 'cy', 'r', 'fx', 'fy'],\n        xlinkAttr = 'xlink:href',\n        xLink = gradient.getAttribute(xlinkAttr).substr(1),\n        referencedGradient = elementById(doc, xLink);\n\n    if (referencedGradient && referencedGradient.getAttribute(xlinkAttr)) {\n      recursivelyParseGradientsXlink(doc, referencedGradient);\n    }\n\n    gradientsAttrs.forEach(function (attr) {\n      if (referencedGradient && !gradient.hasAttribute(attr) && referencedGradient.hasAttribute(attr)) {\n        gradient.setAttribute(attr, referencedGradient.getAttribute(attr));\n      }\n    });\n\n    if (!gradient.children.length) {\n      var referenceClone = referencedGradient.cloneNode(true);\n\n      while (referenceClone.firstChild) {\n        gradient.appendChild(referenceClone.firstChild);\n      }\n    }\n\n    gradient.removeAttribute(xlinkAttr);\n  }\n\n  var reFontDeclaration = new RegExp('(normal|italic)?\\\\s*(normal|small-caps)?\\\\s*' + '(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\\\\s*(' + fabric.reNum + '(?:px|cm|mm|em|pt|pc|in)*)(?:\\\\/(normal|' + fabric.reNum + '))?\\\\s+(.*)');\n  extend(fabric, {\n    /**\n     * Parses a short font declaration, building adding its properties to a style object\n     * @static\n     * @function\n     * @memberOf fabric\n     * @param {String} value font declaration\n     * @param {Object} oStyle definition\n     */\n    parseFontDeclaration: function (value, oStyle) {\n      var match = value.match(reFontDeclaration);\n\n      if (!match) {\n        return;\n      }\n\n      var fontStyle = match[1],\n          // font variant is not used\n      // fontVariant = match[2],\n      fontWeight = match[3],\n          fontSize = match[4],\n          lineHeight = match[5],\n          fontFamily = match[6];\n\n      if (fontStyle) {\n        oStyle.fontStyle = fontStyle;\n      }\n\n      if (fontWeight) {\n        oStyle.fontWeight = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight);\n      }\n\n      if (fontSize) {\n        oStyle.fontSize = parseUnit(fontSize);\n      }\n\n      if (fontFamily) {\n        oStyle.fontFamily = fontFamily;\n      }\n\n      if (lineHeight) {\n        oStyle.lineHeight = lineHeight === 'normal' ? 1 : lineHeight;\n      }\n    },\n\n    /**\n     * Parses an SVG document, returning all of the gradient declarations found in it\n     * @static\n     * @function\n     * @memberOf fabric\n     * @param {SVGDocument} doc SVG document to parse\n     * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element\n     */\n    getGradientDefs: function (doc) {\n      var tagArray = ['linearGradient', 'radialGradient', 'svg:linearGradient', 'svg:radialGradient'],\n          elList = _getMultipleNodes(doc, tagArray),\n          el,\n          j = 0,\n          gradientDefs = {};\n\n      j = elList.length;\n\n      while (j--) {\n        el = elList[j];\n\n        if (el.getAttribute('xlink:href')) {\n          recursivelyParseGradientsXlink(doc, el);\n        }\n\n        gradientDefs[el.getAttribute('id')] = el;\n      }\n\n      return gradientDefs;\n    },\n\n    /**\n     * Returns an object of attributes' name/value, given element and an array of attribute names;\n     * Parses parent \"g\" nodes recursively upwards.\n     * @static\n     * @memberOf fabric\n     * @param {DOMElement} element Element to parse\n     * @param {Array} attributes Array of attributes to parse\n     * @return {Object} object containing parsed attributes' names/values\n     */\n    parseAttributes: function (element, attributes, svgUid) {\n      if (!element) {\n        return;\n      }\n\n      var value,\n          parentAttributes = {},\n          fontSize,\n          parentFontSize;\n\n      if (typeof svgUid === 'undefined') {\n        svgUid = element.getAttribute('svgUid');\n      } // if there's a parent container (`g` or `a` or `symbol` node), parse its attributes recursively upwards\n\n\n      if (element.parentNode && fabric.svgValidParentsRegEx.test(element.parentNode.nodeName)) {\n        parentAttributes = fabric.parseAttributes(element.parentNode, attributes, svgUid);\n      }\n\n      var ownAttributes = attributes.reduce(function (memo, attr) {\n        value = element.getAttribute(attr);\n\n        if (value) {\n          // eslint-disable-line\n          memo[attr] = value;\n        }\n\n        return memo;\n      }, {}); // add values parsed from style, which take precedence over attributes\n      // (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes)\n\n      var cssAttrs = extend(getGlobalStylesForElement(element, svgUid), fabric.parseStyleAttribute(element));\n      ownAttributes = extend(ownAttributes, cssAttrs);\n\n      if (cssAttrs[cPath]) {\n        element.setAttribute(cPath, cssAttrs[cPath]);\n      }\n\n      fontSize = parentFontSize = parentAttributes.fontSize || fabric.Text.DEFAULT_SVG_FONT_SIZE;\n\n      if (ownAttributes[fSize]) {\n        // looks like the minimum should be 9px when dealing with ems. this is what looks like in browsers.\n        ownAttributes[fSize] = fontSize = parseUnit(ownAttributes[fSize], parentFontSize);\n      }\n\n      var normalizedAttr,\n          normalizedValue,\n          normalizedStyle = {};\n\n      for (var attr in ownAttributes) {\n        normalizedAttr = normalizeAttr(attr);\n        normalizedValue = normalizeValue(normalizedAttr, ownAttributes[attr], parentAttributes, fontSize);\n        normalizedStyle[normalizedAttr] = normalizedValue;\n      }\n\n      if (normalizedStyle && normalizedStyle.font) {\n        fabric.parseFontDeclaration(normalizedStyle.font, normalizedStyle);\n      }\n\n      var mergedAttrs = extend(parentAttributes, normalizedStyle);\n      return fabric.svgValidParentsRegEx.test(element.nodeName) ? mergedAttrs : _setStrokeFillOpacity(mergedAttrs);\n    },\n\n    /**\n     * Transforms an array of svg elements to corresponding fabric.* instances\n     * @static\n     * @memberOf fabric\n     * @param {Array} elements Array of elements to parse\n     * @param {Function} callback Being passed an array of fabric instances (transformed from SVG elements)\n     * @param {Object} [options] Options object\n     * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n     */\n    parseElements: function (elements, callback, options, reviver, parsingOptions) {\n      new fabric.ElementsParser(elements, callback, options, reviver, parsingOptions).parse();\n    },\n\n    /**\n     * Parses \"style\" attribute, retuning an object with values\n     * @static\n     * @memberOf fabric\n     * @param {SVGElement} element Element to parse\n     * @return {Object} Objects with values parsed from style attribute of an element\n     */\n    parseStyleAttribute: function (element) {\n      var oStyle = {},\n          style = element.getAttribute('style');\n\n      if (!style) {\n        return oStyle;\n      }\n\n      if (typeof style === 'string') {\n        parseStyleString(style, oStyle);\n      } else {\n        parseStyleObject(style, oStyle);\n      }\n\n      return oStyle;\n    },\n\n    /**\n     * Parses \"points\" attribute, returning an array of values\n     * @static\n     * @memberOf fabric\n     * @param {String} points points attribute string\n     * @return {Array} array of points\n     */\n    parsePointsAttribute: function (points) {\n      // points attribute is required and must not be empty\n      if (!points) {\n        return null;\n      } // replace commas with whitespace and remove bookending whitespace\n\n\n      points = points.replace(/,/g, ' ').trim();\n      points = points.split(/\\s+/);\n      var parsedPoints = [],\n          i,\n          len;\n\n      for (i = 0, len = points.length; i < len; i += 2) {\n        parsedPoints.push({\n          x: parseFloat(points[i]),\n          y: parseFloat(points[i + 1])\n        });\n      } // odd number of points is an error\n      // if (parsedPoints.length % 2 !== 0) {\n      //   return null;\n      // }\n\n\n      return parsedPoints;\n    },\n\n    /**\n     * Returns CSS rules for a given SVG document\n     * @static\n     * @function\n     * @memberOf fabric\n     * @param {SVGDocument} doc SVG document to parse\n     * @return {Object} CSS rules of this document\n     */\n    getCSSRules: function (doc) {\n      var styles = doc.getElementsByTagName('style'),\n          i,\n          len,\n          allRules = {},\n          rules; // very crude parsing of style contents\n\n      for (i = 0, len = styles.length; i < len; i++) {\n        // <style/> could produce `undefined`, covering this case with ''\n        var styleContents = styles[i].textContent || ''; // remove comments\n\n        styleContents = styleContents.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n\n        if (styleContents.trim() === '') {\n          continue;\n        }\n\n        rules = styleContents.match(/[^{]*\\{[\\s\\S]*?\\}/g);\n        rules = rules.map(function (rule) {\n          return rule.trim();\n        }); // eslint-disable-next-line no-loop-func\n\n        rules.forEach(function (rule) {\n          var match = rule.match(/([\\s\\S]*?)\\s*\\{([^}]*)\\}/),\n              ruleObj = {},\n              declaration = match[2].trim(),\n              propertyValuePairs = declaration.replace(/;$/, '').split(/\\s*;\\s*/);\n\n          for (i = 0, len = propertyValuePairs.length; i < len; i++) {\n            var pair = propertyValuePairs[i].split(/\\s*:\\s*/),\n                property = pair[0],\n                value = pair[1];\n            ruleObj[property] = value;\n          }\n\n          rule = match[1];\n          rule.split(',').forEach(function (_rule) {\n            _rule = _rule.replace(/^svg/i, '').trim();\n\n            if (_rule === '') {\n              return;\n            }\n\n            if (allRules[_rule]) {\n              fabric.util.object.extend(allRules[_rule], ruleObj);\n            } else {\n              allRules[_rule] = fabric.util.object.clone(ruleObj);\n            }\n          });\n        });\n      }\n\n      return allRules;\n    },\n\n    /**\n     * Takes url corresponding to an SVG document, and parses it into a set of fabric objects.\n     * Note that SVG is fetched via XMLHttpRequest, so it needs to conform to SOP (Same Origin Policy)\n     * @memberOf fabric\n     * @param {String} url\n     * @param {Function} callback\n     * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n     * @param {Object} [options] Object containing options for parsing\n     * @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources\n     */\n    loadSVGFromURL: function (url, callback, reviver, options) {\n      url = url.replace(/^\\n\\s*/, '').trim();\n      new fabric.util.request(url, {\n        method: 'get',\n        onComplete: onComplete\n      });\n\n      function onComplete(r) {\n        var xml = r.responseXML;\n\n        if (!xml || !xml.documentElement) {\n          callback && callback(null);\n          return false;\n        }\n\n        fabric.parseSVGDocument(xml.documentElement, function (results, _options, elements, allElements) {\n          callback && callback(results, _options, elements, allElements);\n        }, reviver, options);\n      }\n    },\n\n    /**\n     * Takes string corresponding to an SVG document, and parses it into a set of fabric objects\n     * @memberOf fabric\n     * @param {String} string\n     * @param {Function} callback\n     * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n     * @param {Object} [options] Object containing options for parsing\n     * @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources\n     */\n    loadSVGFromString: function (string, callback, reviver, options) {\n      var parser = new fabric.window.DOMParser(),\n          doc = parser.parseFromString(string.trim(), 'text/xml');\n      fabric.parseSVGDocument(doc.documentElement, function (results, _options, elements, allElements) {\n        callback(results, _options, elements, allElements);\n      }, reviver, options);\n    }\n  });\n})(typeof exports !== 'undefined' ? exports : this);\n\nfabric.ElementsParser = function (elements, callback, options, reviver, parsingOptions, doc) {\n  this.elements = elements;\n  this.callback = callback;\n  this.options = options;\n  this.reviver = reviver;\n  this.svgUid = options && options.svgUid || 0;\n  this.parsingOptions = parsingOptions;\n  this.regexUrl = /^url\\(['\"]?#([^'\"]+)['\"]?\\)/g;\n  this.doc = doc;\n};\n\n(function (proto) {\n  proto.parse = function () {\n    this.instances = new Array(this.elements.length);\n    this.numElements = this.elements.length;\n    this.createObjects();\n  };\n\n  proto.createObjects = function () {\n    var _this = this;\n\n    this.elements.forEach(function (element, i) {\n      element.setAttribute('svgUid', _this.svgUid);\n\n      _this.createObject(element, i);\n    });\n  };\n\n  proto.findTag = function (el) {\n    return fabric[fabric.util.string.capitalize(el.tagName.replace('svg:', ''))];\n  };\n\n  proto.createObject = function (el, index) {\n    var klass = this.findTag(el);\n\n    if (klass && klass.fromElement) {\n      try {\n        klass.fromElement(el, this.createCallback(index, el), this.options);\n      } catch (err) {\n        fabric.log(err);\n      }\n    } else {\n      this.checkIfDone();\n    }\n  };\n\n  proto.createCallback = function (index, el) {\n    var _this = this;\n\n    return function (obj) {\n      var _options;\n\n      _this.resolveGradient(obj, el, 'fill');\n\n      _this.resolveGradient(obj, el, 'stroke');\n\n      if (obj instanceof fabric.Image && obj._originalElement) {\n        _options = obj.parsePreserveAspectRatioAttribute(el);\n      }\n\n      obj._removeTransformMatrix(_options);\n\n      _this.resolveClipPath(obj, el);\n\n      _this.reviver && _this.reviver(el, obj);\n      _this.instances[index] = obj;\n\n      _this.checkIfDone();\n    };\n  };\n\n  proto.extractPropertyDefinition = function (obj, property, storage) {\n    var value = obj[property],\n        regex = this.regexUrl;\n\n    if (!regex.test(value)) {\n      return;\n    }\n\n    regex.lastIndex = 0;\n    var id = regex.exec(value)[1];\n    regex.lastIndex = 0;\n    return fabric[storage][this.svgUid][id];\n  };\n\n  proto.resolveGradient = function (obj, el, property) {\n    var gradientDef = this.extractPropertyDefinition(obj, property, 'gradientDefs');\n\n    if (gradientDef) {\n      var opacityAttr = el.getAttribute(property + '-opacity');\n      var gradient = fabric.Gradient.fromElement(gradientDef, obj, opacityAttr, this.options);\n      obj.set(property, gradient);\n    }\n  };\n\n  proto.createClipPathCallback = function (obj, container) {\n    return function (_newObj) {\n      _newObj._removeTransformMatrix();\n\n      _newObj.fillRule = _newObj.clipRule;\n      container.push(_newObj);\n    };\n  };\n\n  proto.resolveClipPath = function (obj, usingElement) {\n    var clipPath = this.extractPropertyDefinition(obj, 'clipPath', 'clipPaths'),\n        element,\n        klass,\n        objTransformInv,\n        container,\n        gTransform,\n        options;\n\n    if (clipPath) {\n      container = [];\n      objTransformInv = fabric.util.invertTransform(obj.calcTransformMatrix()); // move the clipPath tag as sibling to the real element that is using it\n\n      var clipPathTag = clipPath[0].parentNode;\n      var clipPathOwner = usingElement;\n\n      while (clipPathOwner.parentNode && clipPathOwner.getAttribute('clip-path') !== obj.clipPath) {\n        clipPathOwner = clipPathOwner.parentNode;\n      }\n\n      clipPathOwner.parentNode.appendChild(clipPathTag);\n\n      for (var i = 0; i < clipPath.length; i++) {\n        element = clipPath[i];\n        klass = this.findTag(element);\n        klass.fromElement(element, this.createClipPathCallback(obj, container), this.options);\n      }\n\n      if (container.length === 1) {\n        clipPath = container[0];\n      } else {\n        clipPath = new fabric.Group(container);\n      }\n\n      gTransform = fabric.util.multiplyTransformMatrices(objTransformInv, clipPath.calcTransformMatrix());\n\n      if (clipPath.clipPath) {\n        this.resolveClipPath(clipPath, clipPathOwner);\n      }\n\n      var options = fabric.util.qrDecompose(gTransform);\n      clipPath.flipX = false;\n      clipPath.flipY = false;\n      clipPath.set('scaleX', options.scaleX);\n      clipPath.set('scaleY', options.scaleY);\n      clipPath.angle = options.angle;\n      clipPath.skewX = options.skewX;\n      clipPath.skewY = 0;\n      clipPath.setPositionByOrigin({\n        x: options.translateX,\n        y: options.translateY\n      }, 'center', 'center');\n      obj.clipPath = clipPath;\n    } else {\n      // if clip-path does not resolve to any element, delete the property.\n      delete obj.clipPath;\n    }\n  };\n\n  proto.checkIfDone = function () {\n    if (--this.numElements === 0) {\n      this.instances = this.instances.filter(function (el) {\n        // eslint-disable-next-line no-eq-null, eqeqeq\n        return el != null;\n      });\n      this.callback(this.instances, this.elements);\n    }\n  };\n})(fabric.ElementsParser.prototype);\n\n(function (global) {\n  'use strict';\n  /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */\n\n  var fabric = global.fabric || (global.fabric = {});\n\n  if (fabric.Point) {\n    fabric.warn('fabric.Point is already defined');\n    return;\n  }\n\n  fabric.Point = Point;\n  /**\n   * Point class\n   * @class fabric.Point\n   * @memberOf fabric\n   * @constructor\n   * @param {Number} x\n   * @param {Number} y\n   * @return {fabric.Point} thisArg\n   */\n\n  function Point(x, y) {\n    this.x = x;\n    this.y = y;\n  }\n\n  Point.prototype =\n  /** @lends fabric.Point.prototype */\n  {\n    type: 'point',\n    constructor: Point,\n\n    /**\n     * Adds another point to this one and returns another one\n     * @param {fabric.Point} that\n     * @return {fabric.Point} new Point instance with added values\n     */\n    add: function (that) {\n      return new Point(this.x + that.x, this.y + that.y);\n    },\n\n    /**\n     * Adds another point to this one\n     * @param {fabric.Point} that\n     * @return {fabric.Point} thisArg\n     * @chainable\n     */\n    addEquals: function (that) {\n      this.x += that.x;\n      this.y += that.y;\n      return this;\n    },\n\n    /**\n     * Adds value to this point and returns a new one\n     * @param {Number} scalar\n     * @return {fabric.Point} new Point with added value\n     */\n    scalarAdd: function (scalar) {\n      return new Point(this.x + scalar, this.y + scalar);\n    },\n\n    /**\n     * Adds value to this point\n     * @param {Number} scalar\n     * @return {fabric.Point} thisArg\n     * @chainable\n     */\n    scalarAddEquals: function (scalar) {\n      this.x += scalar;\n      this.y += scalar;\n      return this;\n    },\n\n    /**\n     * Subtracts another point from this point and returns a new one\n     * @param {fabric.Point} that\n     * @return {fabric.Point} new Point object with subtracted values\n     */\n    subtract: function (that) {\n      return new Point(this.x - that.x, this.y - that.y);\n    },\n\n    /**\n     * Subtracts another point from this point\n     * @param {fabric.Point} that\n     * @return {fabric.Point} thisArg\n     * @chainable\n     */\n    subtractEquals: function (that) {\n      this.x -= that.x;\n      this.y -= that.y;\n      return this;\n    },\n\n    /**\n     * Subtracts value from this point and returns a new one\n     * @param {Number} scalar\n     * @return {fabric.Point}\n     */\n    scalarSubtract: function (scalar) {\n      return new Point(this.x - scalar, this.y - scalar);\n    },\n\n    /**\n     * Subtracts value from this point\n     * @param {Number} scalar\n     * @return {fabric.Point} thisArg\n     * @chainable\n     */\n    scalarSubtractEquals: function (scalar) {\n      this.x -= scalar;\n      this.y -= scalar;\n      return this;\n    },\n\n    /**\n     * Multiplies this point by a value and returns a new one\n     * TODO: rename in scalarMultiply in 2.0\n     * @param {Number} scalar\n     * @return {fabric.Point}\n     */\n    multiply: function (scalar) {\n      return new Point(this.x * scalar, this.y * scalar);\n    },\n\n    /**\n     * Multiplies this point by a value\n     * TODO: rename in scalarMultiplyEquals in 2.0\n     * @param {Number} scalar\n     * @return {fabric.Point} thisArg\n     * @chainable\n     */\n    multiplyEquals: function (scalar) {\n      this.x *= scalar;\n      this.y *= scalar;\n      return this;\n    },\n\n    /**\n     * Divides this point by a value and returns a new one\n     * TODO: rename in scalarDivide in 2.0\n     * @param {Number} scalar\n     * @return {fabric.Point}\n     */\n    divide: function (scalar) {\n      return new Point(this.x / scalar, this.y / scalar);\n    },\n\n    /**\n     * Divides this point by a value\n     * TODO: rename in scalarDivideEquals in 2.0\n     * @param {Number} scalar\n     * @return {fabric.Point} thisArg\n     * @chainable\n     */\n    divideEquals: function (scalar) {\n      this.x /= scalar;\n      this.y /= scalar;\n      return this;\n    },\n\n    /**\n     * Returns true if this point is equal to another one\n     * @param {fabric.Point} that\n     * @return {Boolean}\n     */\n    eq: function (that) {\n      return this.x === that.x && this.y === that.y;\n    },\n\n    /**\n     * Returns true if this point is less than another one\n     * @param {fabric.Point} that\n     * @return {Boolean}\n     */\n    lt: function (that) {\n      return this.x < that.x && this.y < that.y;\n    },\n\n    /**\n     * Returns true if this point is less than or equal to another one\n     * @param {fabric.Point} that\n     * @return {Boolean}\n     */\n    lte: function (that) {\n      return this.x <= that.x && this.y <= that.y;\n    },\n\n    /**\n      * Returns true if this point is greater another one\n     * @param {fabric.Point} that\n     * @return {Boolean}\n     */\n    gt: function (that) {\n      return this.x > that.x && this.y > that.y;\n    },\n\n    /**\n     * Returns true if this point is greater than or equal to another one\n     * @param {fabric.Point} that\n     * @return {Boolean}\n     */\n    gte: function (that) {\n      return this.x >= that.x && this.y >= that.y;\n    },\n\n    /**\n     * Returns new point which is the result of linear interpolation with this one and another one\n     * @param {fabric.Point} that\n     * @param {Number} t , position of interpolation, between 0 and 1 default 0.5\n     * @return {fabric.Point}\n     */\n    lerp: function (that, t) {\n      if (typeof t === 'undefined') {\n        t = 0.5;\n      }\n\n      t = Math.max(Math.min(1, t), 0);\n      return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t);\n    },\n\n    /**\n     * Returns distance from this point and another one\n     * @param {fabric.Point} that\n     * @return {Number}\n     */\n    distanceFrom: function (that) {\n      var dx = this.x - that.x,\n          dy = this.y - that.y;\n      return Math.sqrt(dx * dx + dy * dy);\n    },\n\n    /**\n     * Returns the point between this point and another one\n     * @param {fabric.Point} that\n     * @return {fabric.Point}\n     */\n    midPointFrom: function (that) {\n      return this.lerp(that);\n    },\n\n    /**\n     * Returns a new point which is the min of this and another one\n     * @param {fabric.Point} that\n     * @return {fabric.Point}\n     */\n    min: function (that) {\n      return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y));\n    },\n\n    /**\n     * Returns a new point which is the max of this and another one\n     * @param {fabric.Point} that\n     * @return {fabric.Point}\n     */\n    max: function (that) {\n      return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y));\n    },\n\n    /**\n     * Returns string representation of this point\n     * @return {String}\n     */\n    toString: function () {\n      return this.x + ',' + this.y;\n    },\n\n    /**\n     * Sets x/y of this point\n     * @param {Number} x\n     * @param {Number} y\n     * @chainable\n     */\n    setXY: function (x, y) {\n      this.x = x;\n      this.y = y;\n      return this;\n    },\n\n    /**\n     * Sets x of this point\n     * @param {Number} x\n     * @chainable\n     */\n    setX: function (x) {\n      this.x = x;\n      return this;\n    },\n\n    /**\n     * Sets y of this point\n     * @param {Number} y\n     * @chainable\n     */\n    setY: function (y) {\n      this.y = y;\n      return this;\n    },\n\n    /**\n     * Sets x/y of this point from another point\n     * @param {fabric.Point} that\n     * @chainable\n     */\n    setFromPoint: function (that) {\n      this.x = that.x;\n      this.y = that.y;\n      return this;\n    },\n\n    /**\n     * Swaps x/y of this point and another point\n     * @param {fabric.Point} that\n     */\n    swap: function (that) {\n      var x = this.x,\n          y = this.y;\n      this.x = that.x;\n      this.y = that.y;\n      that.x = x;\n      that.y = y;\n    },\n\n    /**\n     * return a cloned instance of the point\n     * @return {fabric.Point}\n     */\n    clone: function () {\n      return new Point(this.x, this.y);\n    }\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n  /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */\n\n  var fabric = global.fabric || (global.fabric = {});\n\n  if (fabric.Intersection) {\n    fabric.warn('fabric.Intersection is already defined');\n    return;\n  }\n  /**\n   * Intersection class\n   * @class fabric.Intersection\n   * @memberOf fabric\n   * @constructor\n   */\n\n\n  function Intersection(status) {\n    this.status = status;\n    this.points = [];\n  }\n\n  fabric.Intersection = Intersection;\n  fabric.Intersection.prototype =\n  /** @lends fabric.Intersection.prototype */\n  {\n    constructor: Intersection,\n\n    /**\n     * Appends a point to intersection\n     * @param {fabric.Point} point\n     * @return {fabric.Intersection} thisArg\n     * @chainable\n     */\n    appendPoint: function (point) {\n      this.points.push(point);\n      return this;\n    },\n\n    /**\n     * Appends points to intersection\n     * @param {Array} points\n     * @return {fabric.Intersection} thisArg\n     * @chainable\n     */\n    appendPoints: function (points) {\n      this.points = this.points.concat(points);\n      return this;\n    }\n  };\n  /**\n   * Checks if one line intersects another\n   * TODO: rename in intersectSegmentSegment\n   * @static\n   * @param {fabric.Point} a1\n   * @param {fabric.Point} a2\n   * @param {fabric.Point} b1\n   * @param {fabric.Point} b2\n   * @return {fabric.Intersection}\n   */\n\n  fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) {\n    var result,\n        uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x),\n        ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x),\n        uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);\n\n    if (uB !== 0) {\n      var ua = uaT / uB,\n          ub = ubT / uB;\n\n      if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {\n        result = new Intersection('Intersection');\n        result.appendPoint(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y)));\n      } else {\n        result = new Intersection();\n      }\n    } else {\n      if (uaT === 0 || ubT === 0) {\n        result = new Intersection('Coincident');\n      } else {\n        result = new Intersection('Parallel');\n      }\n    }\n\n    return result;\n  };\n  /**\n   * Checks if line intersects polygon\n   * TODO: rename in intersectSegmentPolygon\n   * fix detection of coincident\n   * @static\n   * @param {fabric.Point} a1\n   * @param {fabric.Point} a2\n   * @param {Array} points\n   * @return {fabric.Intersection}\n   */\n\n\n  fabric.Intersection.intersectLinePolygon = function (a1, a2, points) {\n    var result = new Intersection(),\n        length = points.length,\n        b1,\n        b2,\n        inter,\n        i;\n\n    for (i = 0; i < length; i++) {\n      b1 = points[i];\n      b2 = points[(i + 1) % length];\n      inter = Intersection.intersectLineLine(a1, a2, b1, b2);\n      result.appendPoints(inter.points);\n    }\n\n    if (result.points.length > 0) {\n      result.status = 'Intersection';\n    }\n\n    return result;\n  };\n  /**\n   * Checks if polygon intersects another polygon\n   * @static\n   * @param {Array} points1\n   * @param {Array} points2\n   * @return {fabric.Intersection}\n   */\n\n\n  fabric.Intersection.intersectPolygonPolygon = function (points1, points2) {\n    var result = new Intersection(),\n        length = points1.length,\n        i;\n\n    for (i = 0; i < length; i++) {\n      var a1 = points1[i],\n          a2 = points1[(i + 1) % length],\n          inter = Intersection.intersectLinePolygon(a1, a2, points2);\n      result.appendPoints(inter.points);\n    }\n\n    if (result.points.length > 0) {\n      result.status = 'Intersection';\n    }\n\n    return result;\n  };\n  /**\n   * Checks if polygon intersects rectangle\n   * @static\n   * @param {Array} points\n   * @param {fabric.Point} r1\n   * @param {fabric.Point} r2\n   * @return {fabric.Intersection}\n   */\n\n\n  fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) {\n    var min = r1.min(r2),\n        max = r1.max(r2),\n        topRight = new fabric.Point(max.x, min.y),\n        bottomLeft = new fabric.Point(min.x, max.y),\n        inter1 = Intersection.intersectLinePolygon(min, topRight, points),\n        inter2 = Intersection.intersectLinePolygon(topRight, max, points),\n        inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points),\n        inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points),\n        result = new Intersection();\n    result.appendPoints(inter1.points);\n    result.appendPoints(inter2.points);\n    result.appendPoints(inter3.points);\n    result.appendPoints(inter4.points);\n\n    if (result.points.length > 0) {\n      result.status = 'Intersection';\n    }\n\n    return result;\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {});\n\n  if (fabric.Color) {\n    fabric.warn('fabric.Color is already defined.');\n    return;\n  }\n  /**\n   * Color class\n   * The purpose of {@link fabric.Color} is to abstract and encapsulate common color operations;\n   * {@link fabric.Color} is a constructor and creates instances of {@link fabric.Color} objects.\n   *\n   * @class fabric.Color\n   * @param {String} color optional in hex or rgb(a) or hsl format or from known color list\n   * @return {fabric.Color} thisArg\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#colors}\n   */\n\n\n  function Color(color) {\n    if (!color) {\n      this.setSource([0, 0, 0, 1]);\n    } else {\n      this._tryParsingColor(color);\n    }\n  }\n\n  fabric.Color = Color;\n  fabric.Color.prototype =\n  /** @lends fabric.Color.prototype */\n  {\n    /**\n     * @private\n     * @param {String|Array} color Color value to parse\n     */\n    _tryParsingColor: function (color) {\n      var source;\n\n      if (color in Color.colorNameMap) {\n        color = Color.colorNameMap[color];\n      }\n\n      if (color === 'transparent') {\n        source = [255, 255, 255, 0];\n      }\n\n      if (!source) {\n        source = Color.sourceFromHex(color);\n      }\n\n      if (!source) {\n        source = Color.sourceFromRgb(color);\n      }\n\n      if (!source) {\n        source = Color.sourceFromHsl(color);\n      }\n\n      if (!source) {\n        //if color is not recognize let's make black as canvas does\n        source = [0, 0, 0, 1];\n      }\n\n      if (source) {\n        this.setSource(source);\n      }\n    },\n\n    /**\n     * Adapted from <a href=\"https://rawgithub.com/mjijackson/mjijackson.github.com/master/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.html\">https://github.com/mjijackson</a>\n     * @private\n     * @param {Number} r Red color value\n     * @param {Number} g Green color value\n     * @param {Number} b Blue color value\n     * @return {Array} Hsl color\n     */\n    _rgbToHsl: function (r, g, b) {\n      r /= 255;\n      g /= 255;\n      b /= 255;\n      var h,\n          s,\n          l,\n          max = fabric.util.array.max([r, g, b]),\n          min = fabric.util.array.min([r, g, b]);\n      l = (max + min) / 2;\n\n      if (max === min) {\n        h = s = 0; // achromatic\n      } else {\n        var d = max - min;\n        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n\n        switch (max) {\n          case r:\n            h = (g - b) / d + (g < b ? 6 : 0);\n            break;\n\n          case g:\n            h = (b - r) / d + 2;\n            break;\n\n          case b:\n            h = (r - g) / d + 4;\n            break;\n        }\n\n        h /= 6;\n      }\n\n      return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];\n    },\n\n    /**\n     * Returns source of this color (where source is an array representation; ex: [200, 200, 100, 1])\n     * @return {Array}\n     */\n    getSource: function () {\n      return this._source;\n    },\n\n    /**\n     * Sets source of this color (where source is an array representation; ex: [200, 200, 100, 1])\n     * @param {Array} source\n     */\n    setSource: function (source) {\n      this._source = source;\n    },\n\n    /**\n     * Returns color representation in RGB format\n     * @return {String} ex: rgb(0-255,0-255,0-255)\n     */\n    toRgb: function () {\n      var source = this.getSource();\n      return 'rgb(' + source[0] + ',' + source[1] + ',' + source[2] + ')';\n    },\n\n    /**\n     * Returns color representation in RGBA format\n     * @return {String} ex: rgba(0-255,0-255,0-255,0-1)\n     */\n    toRgba: function () {\n      var source = this.getSource();\n      return 'rgba(' + source[0] + ',' + source[1] + ',' + source[2] + ',' + source[3] + ')';\n    },\n\n    /**\n     * Returns color representation in HSL format\n     * @return {String} ex: hsl(0-360,0%-100%,0%-100%)\n     */\n    toHsl: function () {\n      var source = this.getSource(),\n          hsl = this._rgbToHsl(source[0], source[1], source[2]);\n\n      return 'hsl(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%)';\n    },\n\n    /**\n     * Returns color representation in HSLA format\n     * @return {String} ex: hsla(0-360,0%-100%,0%-100%,0-1)\n     */\n    toHsla: function () {\n      var source = this.getSource(),\n          hsl = this._rgbToHsl(source[0], source[1], source[2]);\n\n      return 'hsla(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%,' + source[3] + ')';\n    },\n\n    /**\n     * Returns color representation in HEX format\n     * @return {String} ex: FF5555\n     */\n    toHex: function () {\n      var source = this.getSource(),\n          r,\n          g,\n          b;\n      r = source[0].toString(16);\n      r = r.length === 1 ? '0' + r : r;\n      g = source[1].toString(16);\n      g = g.length === 1 ? '0' + g : g;\n      b = source[2].toString(16);\n      b = b.length === 1 ? '0' + b : b;\n      return r.toUpperCase() + g.toUpperCase() + b.toUpperCase();\n    },\n\n    /**\n     * Returns color representation in HEXA format\n     * @return {String} ex: FF5555CC\n     */\n    toHexa: function () {\n      var source = this.getSource(),\n          a;\n      a = Math.round(source[3] * 255);\n      a = a.toString(16);\n      a = a.length === 1 ? '0' + a : a;\n      return this.toHex() + a.toUpperCase();\n    },\n\n    /**\n     * Gets value of alpha channel for this color\n     * @return {Number} 0-1\n     */\n    getAlpha: function () {\n      return this.getSource()[3];\n    },\n\n    /**\n     * Sets value of alpha channel for this color\n     * @param {Number} alpha Alpha value 0-1\n     * @return {fabric.Color} thisArg\n     */\n    setAlpha: function (alpha) {\n      var source = this.getSource();\n      source[3] = alpha;\n      this.setSource(source);\n      return this;\n    },\n\n    /**\n     * Transforms color to its grayscale representation\n     * @return {fabric.Color} thisArg\n     */\n    toGrayscale: function () {\n      var source = this.getSource(),\n          average = parseInt((source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), 10),\n          currentAlpha = source[3];\n      this.setSource([average, average, average, currentAlpha]);\n      return this;\n    },\n\n    /**\n     * Transforms color to its black and white representation\n     * @param {Number} threshold\n     * @return {fabric.Color} thisArg\n     */\n    toBlackWhite: function (threshold) {\n      var source = this.getSource(),\n          average = (source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0),\n          currentAlpha = source[3];\n      threshold = threshold || 127;\n      average = Number(average) < Number(threshold) ? 0 : 255;\n      this.setSource([average, average, average, currentAlpha]);\n      return this;\n    },\n\n    /**\n     * Overlays color with another color\n     * @param {String|fabric.Color} otherColor\n     * @return {fabric.Color} thisArg\n     */\n    overlayWith: function (otherColor) {\n      if (!(otherColor instanceof Color)) {\n        otherColor = new Color(otherColor);\n      }\n\n      var result = [],\n          alpha = this.getAlpha(),\n          otherAlpha = 0.5,\n          source = this.getSource(),\n          otherSource = otherColor.getSource(),\n          i;\n\n      for (i = 0; i < 3; i++) {\n        result.push(Math.round(source[i] * (1 - otherAlpha) + otherSource[i] * otherAlpha));\n      }\n\n      result[3] = alpha;\n      this.setSource(result);\n      return this;\n    }\n  };\n  /**\n   * Regex matching color in RGB or RGBA formats (ex: rgb(0, 0, 0), rgba(255, 100, 10, 0.5), rgba( 255 , 100 , 10 , 0.5 ), rgb(1,1,1), rgba(100%, 60%, 10%, 0.5))\n   * @static\n   * @field\n   * @memberOf fabric.Color\n   */\n  // eslint-disable-next-line max-len\n\n  fabric.Color.reRGBa = /^rgba?\\(\\s*(\\d{1,3}(?:\\.\\d+)?\\%?)\\s*,\\s*(\\d{1,3}(?:\\.\\d+)?\\%?)\\s*,\\s*(\\d{1,3}(?:\\.\\d+)?\\%?)\\s*(?:\\s*,\\s*((?:\\d*\\.?\\d+)?)\\s*)?\\)$/i;\n  /**\n   * Regex matching color in HSL or HSLA formats (ex: hsl(200, 80%, 10%), hsla(300, 50%, 80%, 0.5), hsla( 300 , 50% , 80% , 0.5 ))\n   * @static\n   * @field\n   * @memberOf fabric.Color\n   */\n\n  fabric.Color.reHSLa = /^hsla?\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3}\\%)\\s*,\\s*(\\d{1,3}\\%)\\s*(?:\\s*,\\s*(\\d+(?:\\.\\d+)?)\\s*)?\\)$/i;\n  /**\n   * Regex matching color in HEX format (ex: #FF5544CC, #FF5555, 010155, aff)\n   * @static\n   * @field\n   * @memberOf fabric.Color\n   */\n\n  fabric.Color.reHex = /^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i;\n  /**\n   * Map of the 148 color names with HEX code\n   * @static\n   * @field\n   * @memberOf fabric.Color\n   * @see: https://www.w3.org/TR/css3-color/#svg-color\n   */\n\n  fabric.Color.colorNameMap = {\n    aliceblue: '#F0F8FF',\n    antiquewhite: '#FAEBD7',\n    aqua: '#00FFFF',\n    aquamarine: '#7FFFD4',\n    azure: '#F0FFFF',\n    beige: '#F5F5DC',\n    bisque: '#FFE4C4',\n    black: '#000000',\n    blanchedalmond: '#FFEBCD',\n    blue: '#0000FF',\n    blueviolet: '#8A2BE2',\n    brown: '#A52A2A',\n    burlywood: '#DEB887',\n    cadetblue: '#5F9EA0',\n    chartreuse: '#7FFF00',\n    chocolate: '#D2691E',\n    coral: '#FF7F50',\n    cornflowerblue: '#6495ED',\n    cornsilk: '#FFF8DC',\n    crimson: '#DC143C',\n    cyan: '#00FFFF',\n    darkblue: '#00008B',\n    darkcyan: '#008B8B',\n    darkgoldenrod: '#B8860B',\n    darkgray: '#A9A9A9',\n    darkgrey: '#A9A9A9',\n    darkgreen: '#006400',\n    darkkhaki: '#BDB76B',\n    darkmagenta: '#8B008B',\n    darkolivegreen: '#556B2F',\n    darkorange: '#FF8C00',\n    darkorchid: '#9932CC',\n    darkred: '#8B0000',\n    darksalmon: '#E9967A',\n    darkseagreen: '#8FBC8F',\n    darkslateblue: '#483D8B',\n    darkslategray: '#2F4F4F',\n    darkslategrey: '#2F4F4F',\n    darkturquoise: '#00CED1',\n    darkviolet: '#9400D3',\n    deeppink: '#FF1493',\n    deepskyblue: '#00BFFF',\n    dimgray: '#696969',\n    dimgrey: '#696969',\n    dodgerblue: '#1E90FF',\n    firebrick: '#B22222',\n    floralwhite: '#FFFAF0',\n    forestgreen: '#228B22',\n    fuchsia: '#FF00FF',\n    gainsboro: '#DCDCDC',\n    ghostwhite: '#F8F8FF',\n    gold: '#FFD700',\n    goldenrod: '#DAA520',\n    gray: '#808080',\n    grey: '#808080',\n    green: '#008000',\n    greenyellow: '#ADFF2F',\n    honeydew: '#F0FFF0',\n    hotpink: '#FF69B4',\n    indianred: '#CD5C5C',\n    indigo: '#4B0082',\n    ivory: '#FFFFF0',\n    khaki: '#F0E68C',\n    lavender: '#E6E6FA',\n    lavenderblush: '#FFF0F5',\n    lawngreen: '#7CFC00',\n    lemonchiffon: '#FFFACD',\n    lightblue: '#ADD8E6',\n    lightcoral: '#F08080',\n    lightcyan: '#E0FFFF',\n    lightgoldenrodyellow: '#FAFAD2',\n    lightgray: '#D3D3D3',\n    lightgrey: '#D3D3D3',\n    lightgreen: '#90EE90',\n    lightpink: '#FFB6C1',\n    lightsalmon: '#FFA07A',\n    lightseagreen: '#20B2AA',\n    lightskyblue: '#87CEFA',\n    lightslategray: '#778899',\n    lightslategrey: '#778899',\n    lightsteelblue: '#B0C4DE',\n    lightyellow: '#FFFFE0',\n    lime: '#00FF00',\n    limegreen: '#32CD32',\n    linen: '#FAF0E6',\n    magenta: '#FF00FF',\n    maroon: '#800000',\n    mediumaquamarine: '#66CDAA',\n    mediumblue: '#0000CD',\n    mediumorchid: '#BA55D3',\n    mediumpurple: '#9370DB',\n    mediumseagreen: '#3CB371',\n    mediumslateblue: '#7B68EE',\n    mediumspringgreen: '#00FA9A',\n    mediumturquoise: '#48D1CC',\n    mediumvioletred: '#C71585',\n    midnightblue: '#191970',\n    mintcream: '#F5FFFA',\n    mistyrose: '#FFE4E1',\n    moccasin: '#FFE4B5',\n    navajowhite: '#FFDEAD',\n    navy: '#000080',\n    oldlace: '#FDF5E6',\n    olive: '#808000',\n    olivedrab: '#6B8E23',\n    orange: '#FFA500',\n    orangered: '#FF4500',\n    orchid: '#DA70D6',\n    palegoldenrod: '#EEE8AA',\n    palegreen: '#98FB98',\n    paleturquoise: '#AFEEEE',\n    palevioletred: '#DB7093',\n    papayawhip: '#FFEFD5',\n    peachpuff: '#FFDAB9',\n    peru: '#CD853F',\n    pink: '#FFC0CB',\n    plum: '#DDA0DD',\n    powderblue: '#B0E0E6',\n    purple: '#800080',\n    rebeccapurple: '#663399',\n    red: '#FF0000',\n    rosybrown: '#BC8F8F',\n    royalblue: '#4169E1',\n    saddlebrown: '#8B4513',\n    salmon: '#FA8072',\n    sandybrown: '#F4A460',\n    seagreen: '#2E8B57',\n    seashell: '#FFF5EE',\n    sienna: '#A0522D',\n    silver: '#C0C0C0',\n    skyblue: '#87CEEB',\n    slateblue: '#6A5ACD',\n    slategray: '#708090',\n    slategrey: '#708090',\n    snow: '#FFFAFA',\n    springgreen: '#00FF7F',\n    steelblue: '#4682B4',\n    tan: '#D2B48C',\n    teal: '#008080',\n    thistle: '#D8BFD8',\n    tomato: '#FF6347',\n    turquoise: '#40E0D0',\n    violet: '#EE82EE',\n    wheat: '#F5DEB3',\n    white: '#FFFFFF',\n    whitesmoke: '#F5F5F5',\n    yellow: '#FFFF00',\n    yellowgreen: '#9ACD32'\n  };\n  /**\n   * @private\n   * @param {Number} p\n   * @param {Number} q\n   * @param {Number} t\n   * @return {Number}\n   */\n\n  function hue2rgb(p, q, t) {\n    if (t < 0) {\n      t += 1;\n    }\n\n    if (t > 1) {\n      t -= 1;\n    }\n\n    if (t < 1 / 6) {\n      return p + (q - p) * 6 * t;\n    }\n\n    if (t < 1 / 2) {\n      return q;\n    }\n\n    if (t < 2 / 3) {\n      return p + (q - p) * (2 / 3 - t) * 6;\n    }\n\n    return p;\n  }\n  /**\n   * Returns new color object, when given a color in RGB format\n   * @memberOf fabric.Color\n   * @param {String} color Color value ex: rgb(0-255,0-255,0-255)\n   * @return {fabric.Color}\n   */\n\n\n  fabric.Color.fromRgb = function (color) {\n    return Color.fromSource(Color.sourceFromRgb(color));\n  };\n  /**\n   * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format\n   * @memberOf fabric.Color\n   * @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%)\n   * @return {Array} source\n   */\n\n\n  fabric.Color.sourceFromRgb = function (color) {\n    var match = color.match(Color.reRGBa);\n\n    if (match) {\n      var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1),\n          g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1),\n          b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1);\n      return [parseInt(r, 10), parseInt(g, 10), parseInt(b, 10), match[4] ? parseFloat(match[4]) : 1];\n    }\n  };\n  /**\n   * Returns new color object, when given a color in RGBA format\n   * @static\n   * @function\n   * @memberOf fabric.Color\n   * @param {String} color\n   * @return {fabric.Color}\n   */\n\n\n  fabric.Color.fromRgba = Color.fromRgb;\n  /**\n   * Returns new color object, when given a color in HSL format\n   * @param {String} color Color value ex: hsl(0-260,0%-100%,0%-100%)\n   * @memberOf fabric.Color\n   * @return {fabric.Color}\n   */\n\n  fabric.Color.fromHsl = function (color) {\n    return Color.fromSource(Color.sourceFromHsl(color));\n  };\n  /**\n   * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format.\n   * Adapted from <a href=\"https://rawgithub.com/mjijackson/mjijackson.github.com/master/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.html\">https://github.com/mjijackson</a>\n   * @memberOf fabric.Color\n   * @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1)\n   * @return {Array} source\n   * @see http://http://www.w3.org/TR/css3-color/#hsl-color\n   */\n\n\n  fabric.Color.sourceFromHsl = function (color) {\n    var match = color.match(Color.reHSLa);\n\n    if (!match) {\n      return;\n    }\n\n    var h = (parseFloat(match[1]) % 360 + 360) % 360 / 360,\n        s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1),\n        l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1),\n        r,\n        g,\n        b;\n\n    if (s === 0) {\n      r = g = b = l;\n    } else {\n      var q = l <= 0.5 ? l * (s + 1) : l + s - l * s,\n          p = l * 2 - q;\n      r = hue2rgb(p, q, h + 1 / 3);\n      g = hue2rgb(p, q, h);\n      b = hue2rgb(p, q, h - 1 / 3);\n    }\n\n    return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), match[4] ? parseFloat(match[4]) : 1];\n  };\n  /**\n   * Returns new color object, when given a color in HSLA format\n   * @static\n   * @function\n   * @memberOf fabric.Color\n   * @param {String} color\n   * @return {fabric.Color}\n   */\n\n\n  fabric.Color.fromHsla = Color.fromHsl;\n  /**\n   * Returns new color object, when given a color in HEX format\n   * @static\n   * @memberOf fabric.Color\n   * @param {String} color Color value ex: FF5555\n   * @return {fabric.Color}\n   */\n\n  fabric.Color.fromHex = function (color) {\n    return Color.fromSource(Color.sourceFromHex(color));\n  };\n  /**\n   * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HEX format\n   * @static\n   * @memberOf fabric.Color\n   * @param {String} color ex: FF5555 or FF5544CC (RGBa)\n   * @return {Array} source\n   */\n\n\n  fabric.Color.sourceFromHex = function (color) {\n    if (color.match(Color.reHex)) {\n      var value = color.slice(color.indexOf('#') + 1),\n          isShortNotation = value.length === 3 || value.length === 4,\n          isRGBa = value.length === 8 || value.length === 4,\n          r = isShortNotation ? value.charAt(0) + value.charAt(0) : value.substring(0, 2),\n          g = isShortNotation ? value.charAt(1) + value.charAt(1) : value.substring(2, 4),\n          b = isShortNotation ? value.charAt(2) + value.charAt(2) : value.substring(4, 6),\n          a = isRGBa ? isShortNotation ? value.charAt(3) + value.charAt(3) : value.substring(6, 8) : 'FF';\n      return [parseInt(r, 16), parseInt(g, 16), parseInt(b, 16), parseFloat((parseInt(a, 16) / 255).toFixed(2))];\n    }\n  };\n  /**\n   * Returns new color object, when given color in array representation (ex: [200, 100, 100, 0.5])\n   * @static\n   * @memberOf fabric.Color\n   * @param {Array} source\n   * @return {fabric.Color}\n   */\n\n\n  fabric.Color.fromSource = function (source) {\n    var oColor = new Color();\n    oColor.setSource(source);\n    return oColor;\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      scaleMap = ['e', 'se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e'],\n      skewMap = ['ns', 'nesw', 'ew', 'nwse'],\n      controls = {},\n      LEFT = 'left',\n      TOP = 'top',\n      RIGHT = 'right',\n      BOTTOM = 'bottom',\n      CENTER = 'center',\n      opposite = {\n    top: BOTTOM,\n    bottom: TOP,\n    left: RIGHT,\n    right: LEFT,\n    center: CENTER\n  },\n      radiansToDegrees = fabric.util.radiansToDegrees,\n      sign = Math.sign || function (x) {\n    return (x > 0) - (x < 0) || +x;\n  };\n  /**\n   * Combine control position and object angle to find the control direction compared\n   * to the object center.\n   * @param {fabric.Object} fabricObject the fabric object for which we are rendering controls\n   * @param {fabric.Control} control the control class\n   * @return {Number} 0 - 7 a quadrant number\n   */\n\n\n  function findCornerQuadrant(fabricObject, control) {\n    var cornerAngle = fabricObject.angle + radiansToDegrees(Math.atan2(control.y, control.x)) + 360;\n    return Math.round(cornerAngle % 360 / 45);\n  }\n\n  function fireEvent(eventName, options) {\n    var target = options.transform.target,\n        canvas = target.canvas,\n        canvasOptions = fabric.util.object.clone(options);\n    canvasOptions.target = target;\n    canvas && canvas.fire('object:' + eventName, canvasOptions);\n    target.fire(eventName, options);\n  }\n  /**\n   * Inspect event and fabricObject properties to understand if the scaling action\n   * @param {Event} eventData from the user action\n   * @param {fabric.Object} fabricObject the fabric object about to scale\n   * @return {Boolean} true if scale is proportional\n   */\n\n\n  function scaleIsProportional(eventData, fabricObject) {\n    var canvas = fabricObject.canvas,\n        uniScaleKey = canvas.uniScaleKey,\n        uniformIsToggled = eventData[uniScaleKey];\n    return canvas.uniformScaling && !uniformIsToggled || !canvas.uniformScaling && uniformIsToggled;\n  }\n  /**\n   * Checks if transform is centered\n   * @param {Object} transform transform data\n   * @return {Boolean} true if transform is centered\n   */\n\n\n  function isTransformCentered(transform) {\n    return transform.originX === CENTER && transform.originY === CENTER;\n  }\n  /**\n   * Inspect fabricObject to understand if the current scaling action is allowed\n   * @param {fabric.Object} fabricObject the fabric object about to scale\n   * @param {String} by 'x' or 'y' or ''\n   * @param {Boolean} scaleProportionally true if we are trying to scale proportionally\n   * @return {Boolean} true if scaling is not allowed at current conditions\n   */\n\n\n  function scalingIsForbidden(fabricObject, by, scaleProportionally) {\n    var lockX = fabricObject.lockScalingX,\n        lockY = fabricObject.lockScalingY;\n\n    if (lockX && lockY) {\n      return true;\n    }\n\n    if (!by && (lockX || lockY) && scaleProportionally) {\n      return true;\n    }\n\n    if (lockX && by === 'x') {\n      return true;\n    }\n\n    if (lockY && by === 'y') {\n      return true;\n    }\n\n    return false;\n  }\n  /**\n   * return the correct cursor style for the scale action\n   * @param {Event} eventData the javascript event that is causing the scale\n   * @param {fabric.Control} control the control that is interested in the action\n   * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n   * @return {String} a valid css string for the cursor\n   */\n\n\n  function scaleCursorStyleHandler(eventData, control, fabricObject) {\n    var notAllowed = 'not-allowed',\n        scaleProportionally = scaleIsProportional(eventData, fabricObject),\n        by = '';\n\n    if (control.x !== 0 && control.y === 0) {\n      by = 'x';\n    } else if (control.x === 0 && control.y !== 0) {\n      by = 'y';\n    }\n\n    if (scalingIsForbidden(fabricObject, by, scaleProportionally)) {\n      return notAllowed;\n    }\n\n    var n = findCornerQuadrant(fabricObject, control);\n    return scaleMap[n] + '-resize';\n  }\n  /**\n   * return the correct cursor style for the skew action\n   * @param {Event} eventData the javascript event that is causing the scale\n   * @param {fabric.Control} control the control that is interested in the action\n   * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n   * @return {String} a valid css string for the cursor\n   */\n\n\n  function skewCursorStyleHandler(eventData, control, fabricObject) {\n    var notAllowed = 'not-allowed';\n\n    if (control.x !== 0 && fabricObject.lockSkewingY) {\n      return notAllowed;\n    }\n\n    if (control.y !== 0 && fabricObject.lockSkewingX) {\n      return notAllowed;\n    }\n\n    var n = findCornerQuadrant(fabricObject, control) % 4;\n    return skewMap[n] + '-resize';\n  }\n  /**\n   * Combine skew and scale style handlers to cover fabric standard use case\n   * @param {Event} eventData the javascript event that is causing the scale\n   * @param {fabric.Control} control the control that is interested in the action\n   * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n   * @return {String} a valid css string for the cursor\n   */\n\n\n  function scaleSkewCursorStyleHandler(eventData, control, fabricObject) {\n    if (eventData[fabricObject.canvas.altActionKey]) {\n      return controls.skewCursorStyleHandler(eventData, control, fabricObject);\n    }\n\n    return controls.scaleCursorStyleHandler(eventData, control, fabricObject);\n  }\n  /**\n   * Inspect event, control and fabricObject to return the correct action name\n   * @param {Event} eventData the javascript event that is causing the scale\n   * @param {fabric.Control} control the control that is interested in the action\n   * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n   * @return {String} an action name\n   */\n\n\n  function scaleOrSkewActionName(eventData, control, fabricObject) {\n    var isAlternative = eventData[fabricObject.canvas.altActionKey];\n\n    if (control.x === 0) {\n      // then is scaleY or skewX\n      return isAlternative ? 'skewX' : 'scaleY';\n    }\n\n    if (control.y === 0) {\n      // then is scaleY or skewX\n      return isAlternative ? 'skewY' : 'scaleX';\n    }\n  }\n  /**\n   * Find the correct style for the control that is used for rotation.\n   * this function is very simple and it just take care of not-allowed or standard cursor\n   * @param {Event} eventData the javascript event that is causing the scale\n   * @param {fabric.Control} control the control that is interested in the action\n   * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n   * @return {String} a valid css string for the cursor\n   */\n\n\n  function rotationStyleHandler(eventData, control, fabricObject) {\n    if (fabricObject.lockRotation) {\n      return 'not-allowed';\n    }\n\n    return control.cursorStyle;\n  }\n\n  function commonEventInfo(eventData, transform, x, y) {\n    return {\n      e: eventData,\n      transform: transform,\n      pointer: {\n        x: x,\n        y: y\n      }\n    };\n  }\n  /**\n   * Wrap an action handler with saving/restoring object position on the transform.\n   * this is the code that permits to objects to keep their position while transforming.\n   * @param {Function} actionHandler the function to wrap\n   * @return {Function} a function with an action handler signature\n   */\n\n\n  function wrapWithFixedAnchor(actionHandler) {\n    return function (eventData, transform, x, y) {\n      var target = transform.target,\n          centerPoint = target.getCenterPoint(),\n          constraint = target.translateToOriginPoint(centerPoint, transform.originX, transform.originY),\n          actionPerformed = actionHandler(eventData, transform, x, y);\n      target.setPositionByOrigin(constraint, transform.originX, transform.originY);\n      return actionPerformed;\n    };\n  }\n  /**\n   * Transforms a point described by x and y in a distance from the top left corner of the object\n   * bounding box.\n   * @param {Object} transform\n   * @param {String} originX\n   * @param {String} originY\n   * @param {number} x\n   * @param {number} y\n   * @return {Fabric.Point} the normalized point\n   */\n\n\n  function getLocalPoint(transform, originX, originY, x, y) {\n    var target = transform.target,\n        control = target.controls[transform.corner],\n        zoom = target.canvas.getZoom(),\n        padding = target.padding / zoom,\n        localPoint = target.toLocalPoint(new fabric.Point(x, y), originX, originY);\n\n    if (localPoint.x >= padding) {\n      localPoint.x -= padding;\n    }\n\n    if (localPoint.x <= -padding) {\n      localPoint.x += padding;\n    }\n\n    if (localPoint.y >= padding) {\n      localPoint.y -= padding;\n    }\n\n    if (localPoint.y <= padding) {\n      localPoint.y += padding;\n    }\n\n    localPoint.x -= control.offsetX;\n    localPoint.y -= control.offsetY;\n    return localPoint;\n  }\n  /**\n   * Detect if the fabric object is flipped on one side.\n   * @param {fabric.Object} target\n   * @return {Boolean} true if one flip, but not two.\n   */\n\n\n  function targetHasOneFlip(target) {\n    return target.flipX && !target.flipY || !target.flipX && target.flipY;\n  }\n  /**\n   * Utility function to compensate the scale factor when skew is applied on both axes\n   * @private\n   */\n\n\n  function compensateScaleForSkew(target, oppositeSkew, scaleToCompensate, axis, reference) {\n    if (target[oppositeSkew] !== 0) {\n      var newDim = target._getTransformedDimensions()[axis];\n\n      var newValue = reference / newDim * target[scaleToCompensate];\n      target.set(scaleToCompensate, newValue);\n    }\n  }\n  /**\n   * Action handler for skewing on the X axis\n   * @private\n   */\n\n\n  function skewObjectX(eventData, transform, x, y) {\n    var target = transform.target,\n        // find how big the object would be, if there was no skewX. takes in account scaling\n    dimNoSkew = target._getTransformedDimensions(0, target.skewY),\n        localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y),\n        // the mouse is in the center of the object, and we want it to stay there.\n    // so the object will grow twice as much as the mouse.\n    // this makes the skew growth to localPoint * 2 - dimNoSkew.\n    totalSkewSize = Math.abs(localPoint.x * 2) - dimNoSkew.x,\n        currentSkew = target.skewX,\n        newSkew;\n\n    if (totalSkewSize < 2) {\n      // let's make it easy to go back to position 0.\n      newSkew = 0;\n    } else {\n      newSkew = radiansToDegrees(Math.atan2(totalSkewSize / target.scaleX, dimNoSkew.y / target.scaleY)); // now we have to find the sign of the skew.\n      // it mostly depend on the origin of transformation.\n\n      if (transform.originX === LEFT && transform.originY === BOTTOM) {\n        newSkew = -newSkew;\n      }\n\n      if (transform.originX === RIGHT && transform.originY === TOP) {\n        newSkew = -newSkew;\n      }\n\n      if (targetHasOneFlip(target)) {\n        newSkew = -newSkew;\n      }\n    }\n\n    var hasSkewed = currentSkew !== newSkew;\n\n    if (hasSkewed) {\n      var dimBeforeSkewing = target._getTransformedDimensions().y;\n\n      target.set('skewX', newSkew);\n      compensateScaleForSkew(target, 'skewY', 'scaleY', 'y', dimBeforeSkewing);\n      fireEvent('skewing', commonEventInfo(eventData, transform, x, y));\n    }\n\n    return hasSkewed;\n  }\n  /**\n   * Action handler for skewing on the Y axis\n   * @private\n   */\n\n\n  function skewObjectY(eventData, transform, x, y) {\n    var target = transform.target,\n        // find how big the object would be, if there was no skewX. takes in account scaling\n    dimNoSkew = target._getTransformedDimensions(target.skewX, 0),\n        localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y),\n        // the mouse is in the center of the object, and we want it to stay there.\n    // so the object will grow twice as much as the mouse.\n    // this makes the skew growth to localPoint * 2 - dimNoSkew.\n    totalSkewSize = Math.abs(localPoint.y * 2) - dimNoSkew.y,\n        currentSkew = target.skewY,\n        newSkew;\n\n    if (totalSkewSize < 2) {\n      // let's make it easy to go back to position 0.\n      newSkew = 0;\n    } else {\n      newSkew = radiansToDegrees(Math.atan2(totalSkewSize / target.scaleY, dimNoSkew.x / target.scaleX)); // now we have to find the sign of the skew.\n      // it mostly depend on the origin of transformation.\n\n      if (transform.originX === LEFT && transform.originY === BOTTOM) {\n        newSkew = -newSkew;\n      }\n\n      if (transform.originX === RIGHT && transform.originY === TOP) {\n        newSkew = -newSkew;\n      }\n\n      if (targetHasOneFlip(target)) {\n        newSkew = -newSkew;\n      }\n    }\n\n    var hasSkewed = currentSkew !== newSkew;\n\n    if (hasSkewed) {\n      var dimBeforeSkewing = target._getTransformedDimensions().x;\n\n      target.set('skewY', newSkew);\n      compensateScaleForSkew(target, 'skewX', 'scaleX', 'x', dimBeforeSkewing);\n      fireEvent('skewing', commonEventInfo(eventData, transform, x, y));\n    }\n\n    return hasSkewed;\n  }\n  /**\n   * Wrapped Action handler for skewing on the Y axis, takes care of the\n   * skew direction and determine the correct transform origin for the anchor point\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n\n\n  function skewHandlerX(eventData, transform, x, y) {\n    // step1 figure out and change transform origin.\n    // if skewX > 0 and originY bottom we anchor on right\n    // if skewX > 0 and originY top we anchor on left\n    // if skewX < 0 and originY bottom we anchor on left\n    // if skewX < 0 and originY top we anchor on right\n    // if skewX is 0, we look for mouse position to understand where are we going.\n    var target = transform.target,\n        currentSkew = target.skewX,\n        originX,\n        originY = transform.originY;\n\n    if (target.lockSkewingX) {\n      return false;\n    }\n\n    if (currentSkew === 0) {\n      var localPointFromCenter = getLocalPoint(transform, CENTER, CENTER, x, y);\n\n      if (localPointFromCenter.x > 0) {\n        // we are pulling right, anchor left;\n        originX = LEFT;\n      } else {\n        // we are pulling right, anchor right\n        originX = RIGHT;\n      }\n    } else {\n      if (currentSkew > 0) {\n        originX = originY === TOP ? LEFT : RIGHT;\n      }\n\n      if (currentSkew < 0) {\n        originX = originY === TOP ? RIGHT : LEFT;\n      } // is the object flipped on one side only? swap the origin.\n\n\n      if (targetHasOneFlip(target)) {\n        originX = originX === LEFT ? RIGHT : LEFT;\n      }\n    } // once we have the origin, we find the anchor point\n\n\n    transform.originX = originX;\n    var finalHandler = wrapWithFixedAnchor(skewObjectX);\n    return finalHandler(eventData, transform, x, y);\n  }\n  /**\n   * Wrapped Action handler for skewing on the Y axis, takes care of the\n   * skew direction and determine the correct transform origin for the anchor point\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n\n\n  function skewHandlerY(eventData, transform, x, y) {\n    // step1 figure out and change transform origin.\n    // if skewY > 0 and originX left we anchor on top\n    // if skewY > 0 and originX right we anchor on bottom\n    // if skewY < 0 and originX left we anchor on bottom\n    // if skewY < 0 and originX right we anchor on top\n    // if skewY is 0, we look for mouse position to understand where are we going.\n    var target = transform.target,\n        currentSkew = target.skewY,\n        originY,\n        originX = transform.originX;\n\n    if (target.lockSkewingY) {\n      return false;\n    }\n\n    if (currentSkew === 0) {\n      var localPointFromCenter = getLocalPoint(transform, CENTER, CENTER, x, y);\n\n      if (localPointFromCenter.y > 0) {\n        // we are pulling down, anchor up;\n        originY = TOP;\n      } else {\n        // we are pulling up, anchor down\n        originY = BOTTOM;\n      }\n    } else {\n      if (currentSkew > 0) {\n        originY = originX === LEFT ? TOP : BOTTOM;\n      }\n\n      if (currentSkew < 0) {\n        originY = originX === LEFT ? BOTTOM : TOP;\n      } // is the object flipped on one side only? swap the origin.\n\n\n      if (targetHasOneFlip(target)) {\n        originY = originY === TOP ? BOTTOM : TOP;\n      }\n    } // once we have the origin, we find the anchor point\n\n\n    transform.originY = originY;\n    var finalHandler = wrapWithFixedAnchor(skewObjectY);\n    return finalHandler(eventData, transform, x, y);\n  }\n  /**\n   * Action handler for rotation and snapping, without anchor point.\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   * @private\n   */\n\n\n  function rotationWithSnapping(eventData, transform, x, y) {\n    var t = transform,\n        target = t.target,\n        pivotPoint = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY);\n\n    if (target.lockRotation) {\n      return false;\n    }\n\n    var lastAngle = Math.atan2(t.ey - pivotPoint.y, t.ex - pivotPoint.x),\n        curAngle = Math.atan2(y - pivotPoint.y, x - pivotPoint.x),\n        angle = radiansToDegrees(curAngle - lastAngle + t.theta),\n        hasRotated = true;\n\n    if (target.snapAngle > 0) {\n      var snapAngle = target.snapAngle,\n          snapThreshold = target.snapThreshold || snapAngle,\n          rightAngleLocked = Math.ceil(angle / snapAngle) * snapAngle,\n          leftAngleLocked = Math.floor(angle / snapAngle) * snapAngle;\n\n      if (Math.abs(angle - leftAngleLocked) < snapThreshold) {\n        angle = leftAngleLocked;\n      } else if (Math.abs(angle - rightAngleLocked) < snapThreshold) {\n        angle = rightAngleLocked;\n      }\n    } // normalize angle to positive value\n\n\n    if (angle < 0) {\n      angle = 360 + angle;\n    }\n\n    angle %= 360;\n    hasRotated = target.angle !== angle;\n    target.angle = angle;\n\n    if (hasRotated) {\n      fireEvent('rotating', commonEventInfo(eventData, transform, x, y));\n    }\n\n    return hasRotated;\n  }\n  /**\n   * Basic scaling logic, reused with different constrain for scaling X,Y, freely or equally.\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @param {Object} options additional information for scaling\n   * @param {String} options.by 'x', 'y', 'equally' or '' to indicate type of scaling\n   * @return {Boolean} true if some change happened\n   * @private\n   */\n\n\n  function scaleObject(eventData, transform, x, y, options) {\n    options = options || {};\n    var target = transform.target,\n        lockScalingX = target.lockScalingX,\n        lockScalingY = target.lockScalingY,\n        by = options.by,\n        newPoint,\n        scaleX,\n        scaleY,\n        dim,\n        scaleProportionally = scaleIsProportional(eventData, target),\n        forbidScaling = scalingIsForbidden(target, by, scaleProportionally),\n        signX,\n        signY,\n        gestureScale = transform.gestureScale;\n\n    if (forbidScaling) {\n      return false;\n    }\n\n    if (gestureScale) {\n      scaleX = transform.scaleX * gestureScale;\n      scaleY = transform.scaleY * gestureScale;\n    } else {\n      newPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y); // use of sign: We use sign to detect change of direction of an action. sign usually change when\n      // we cross the origin point with the mouse. So a scale flip for example. There is an issue when scaling\n      // by center and scaling using one middle control ( default: mr, mt, ml, mb), the mouse movement can easily\n      // cross many time the origin point and flip the object. so we need a way to filter out the noise.\n      // This ternary here should be ok to filter out X scaling when we want Y only and vice versa.\n\n      signX = by !== 'y' ? sign(newPoint.x) : 1;\n      signY = by !== 'x' ? sign(newPoint.y) : 1;\n\n      if (!transform.signX) {\n        transform.signX = signX;\n      }\n\n      if (!transform.signY) {\n        transform.signY = signY;\n      }\n\n      if (target.lockScalingFlip && (transform.signX !== signX || transform.signY !== signY)) {\n        return false;\n      }\n\n      dim = target._getTransformedDimensions(); // missing detection of flip and logic to switch the origin\n\n      if (scaleProportionally && !by) {\n        // uniform scaling\n        var distance = Math.abs(newPoint.x) + Math.abs(newPoint.y),\n            original = transform.original,\n            originalDistance = Math.abs(dim.x * original.scaleX / target.scaleX) + Math.abs(dim.y * original.scaleY / target.scaleY),\n            scale = distance / originalDistance,\n            hasScaled;\n        scaleX = original.scaleX * scale;\n        scaleY = original.scaleY * scale;\n      } else {\n        scaleX = Math.abs(newPoint.x * target.scaleX / dim.x);\n        scaleY = Math.abs(newPoint.y * target.scaleY / dim.y);\n      } // if we are scaling by center, we need to double the scale\n\n\n      if (isTransformCentered(transform)) {\n        scaleX *= 2;\n        scaleY *= 2;\n      }\n\n      if (transform.signX !== signX && by !== 'y') {\n        transform.originX = opposite[transform.originX];\n        scaleX *= -1;\n        transform.signX = signX;\n      }\n\n      if (transform.signY !== signY && by !== 'x') {\n        transform.originY = opposite[transform.originY];\n        scaleY *= -1;\n        transform.signY = signY;\n      }\n    } // minScale is taken are in the setter.\n\n\n    var oldScaleX = target.scaleX,\n        oldScaleY = target.scaleY;\n\n    if (!by) {\n      !lockScalingX && target.set('scaleX', scaleX);\n      !lockScalingY && target.set('scaleY', scaleY);\n    } else {\n      // forbidden cases already handled on top here.\n      by === 'x' && target.set('scaleX', scaleX);\n      by === 'y' && target.set('scaleY', scaleY);\n    }\n\n    hasScaled = oldScaleX !== target.scaleX || oldScaleY !== target.scaleY;\n\n    if (hasScaled) {\n      fireEvent('scaling', commonEventInfo(eventData, transform, x, y));\n    }\n\n    return hasScaled;\n  }\n  /**\n   * Generic scaling logic, to scale from corners either equally or freely.\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n\n\n  function scaleObjectFromCorner(eventData, transform, x, y) {\n    return scaleObject(eventData, transform, x, y);\n  }\n  /**\n   * Scaling logic for the X axis.\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n\n\n  function scaleObjectX(eventData, transform, x, y) {\n    return scaleObject(eventData, transform, x, y, {\n      by: 'x'\n    });\n  }\n  /**\n   * Scaling logic for the Y axis.\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n\n\n  function scaleObjectY(eventData, transform, x, y) {\n    return scaleObject(eventData, transform, x, y, {\n      by: 'y'\n    });\n  }\n  /**\n   * Composed action handler to either scale Y or skew X\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n\n\n  function scalingYOrSkewingX(eventData, transform, x, y) {\n    // ok some safety needed here.\n    if (eventData[transform.target.canvas.altActionKey]) {\n      return controls.skewHandlerX(eventData, transform, x, y);\n    }\n\n    return controls.scalingY(eventData, transform, x, y);\n  }\n  /**\n   * Composed action handler to either scale X or skew Y\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n\n\n  function scalingXOrSkewingY(eventData, transform, x, y) {\n    // ok some safety needed here.\n    if (eventData[transform.target.canvas.altActionKey]) {\n      return controls.skewHandlerY(eventData, transform, x, y);\n    }\n\n    return controls.scalingX(eventData, transform, x, y);\n  }\n  /**\n   * Action handler to change textbox width\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n\n\n  function changeWidth(eventData, transform, x, y) {\n    var target = transform.target,\n        localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y),\n        strokePadding = target.strokeWidth / (target.strokeUniform ? target.scaleX : 1),\n        multiplier = isTransformCentered(transform) ? 2 : 1,\n        oldWidth = target.width,\n        hasResized,\n        newWidth = Math.abs(localPoint.x * multiplier / target.scaleX) - strokePadding;\n    target.set('width', Math.max(newWidth, 0));\n    hasResized = oldWidth !== newWidth;\n\n    if (hasResized) {\n      fireEvent('resizing', commonEventInfo(eventData, transform, x, y));\n    }\n\n    return hasResized;\n  }\n  /**\n   * Action handler\n   * @private\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if the translation occurred\n   */\n\n\n  function dragHandler(eventData, transform, x, y) {\n    var target = transform.target,\n        newLeft = x - transform.offsetX,\n        newTop = y - transform.offsetY,\n        moveX = !target.get('lockMovementX') && target.left !== newLeft,\n        moveY = !target.get('lockMovementY') && target.top !== newTop;\n    moveX && target.set('left', newLeft);\n    moveY && target.set('top', newTop);\n\n    if (moveX || moveY) {\n      fireEvent('moving', commonEventInfo(eventData, transform, x, y));\n    }\n\n    return moveX || moveY;\n  }\n\n  controls.scaleCursorStyleHandler = scaleCursorStyleHandler;\n  controls.skewCursorStyleHandler = skewCursorStyleHandler;\n  controls.scaleSkewCursorStyleHandler = scaleSkewCursorStyleHandler;\n  controls.rotationWithSnapping = wrapWithFixedAnchor(rotationWithSnapping);\n  controls.scalingEqually = wrapWithFixedAnchor(scaleObjectFromCorner);\n  controls.scalingX = wrapWithFixedAnchor(scaleObjectX);\n  controls.scalingY = wrapWithFixedAnchor(scaleObjectY);\n  controls.scalingYOrSkewingX = scalingYOrSkewingX;\n  controls.scalingXOrSkewingY = scalingXOrSkewingY;\n  controls.changeWidth = wrapWithFixedAnchor(changeWidth);\n  controls.skewHandlerX = skewHandlerX;\n  controls.skewHandlerY = skewHandlerY;\n  controls.dragHandler = dragHandler;\n  controls.scaleOrSkewActionName = scaleOrSkewActionName;\n  controls.rotationStyleHandler = rotationStyleHandler;\n  controls.fireEvent = fireEvent;\n  controls.wrapWithFixedAnchor = wrapWithFixedAnchor;\n  controls.getLocalPoint = getLocalPoint;\n  fabric.controlsUtils = controls;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      degreesToRadians = fabric.util.degreesToRadians,\n      controls = fabric.controlsUtils;\n  /**\n   * Render a round control, as per fabric features.\n   * This function is written to respect object properties like transparentCorners, cornerSize\n   * cornerColor, cornerStrokeColor\n   * plus the addition of offsetY and offsetX.\n   * @param {CanvasRenderingContext2D} ctx context to render on\n   * @param {Number} left x coordinate where the control center should be\n   * @param {Number} top y coordinate where the control center should be\n   * @param {Object} styleOverride override for fabric.Object controls style\n   * @param {fabric.Object} fabricObject the fabric object for which we are rendering controls\n   */\n\n  function renderCircleControl(ctx, left, top, styleOverride, fabricObject) {\n    styleOverride = styleOverride || {};\n    var size = styleOverride.cornerSize || fabricObject.cornerSize,\n        transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ? styleOverride.transparentCorners : this.transparentCorners,\n        methodName = transparentCorners ? 'stroke' : 'fill',\n        stroke = !transparentCorners && (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor);\n    ctx.save();\n    ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor;\n    ctx.strokeStyle = styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor; // this is still wrong\n\n    ctx.lineWidth = 1;\n    ctx.beginPath();\n    ctx.arc(left, top, size / 2, 0, 2 * Math.PI, false);\n    ctx[methodName]();\n\n    if (stroke) {\n      ctx.stroke();\n    }\n\n    ctx.restore();\n  }\n  /**\n   * Render a square control, as per fabric features.\n   * This function is written to respect object properties like transparentCorners, cornerSize\n   * cornerColor, cornerStrokeColor\n   * plus the addition of offsetY and offsetX.\n   * @param {CanvasRenderingContext2D} ctx context to render on\n   * @param {Number} left x coordinate where the control center should be\n   * @param {Number} top y coordinate where the control center should be\n   * @param {Object} styleOverride override for fabric.Object controls style\n   * @param {fabric.Object} fabricObject the fabric object for which we are rendering controls\n   */\n\n\n  function renderSquareControl(ctx, left, top, styleOverride, fabricObject) {\n    styleOverride = styleOverride || {};\n    var size = styleOverride.cornerSize || fabricObject.cornerSize,\n        transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ? styleOverride.transparentCorners : fabricObject.transparentCorners,\n        methodName = transparentCorners ? 'stroke' : 'fill',\n        stroke = !transparentCorners && (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor),\n        sizeBy2 = size / 2;\n    ctx.save();\n    ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor;\n    ctx.strokeStyle = styleOverride.strokeCornerColor || fabricObject.strokeCornerColor; // this is still wrong\n\n    ctx.lineWidth = 1;\n    ctx.translate(left, top);\n    ctx.rotate(degreesToRadians(fabricObject.angle)); // this does not work, and fixed with ( && ) does not make sense.\n    // to have real transparent corners we need the controls on upperCanvas\n    // transparentCorners || ctx.clearRect(-sizeBy2, -sizeBy2, size, size);\n\n    ctx[methodName + 'Rect'](-sizeBy2, -sizeBy2, size, size);\n\n    if (stroke) {\n      ctx.strokeRect(-sizeBy2, -sizeBy2, size, size);\n    }\n\n    ctx.restore();\n  }\n\n  controls.renderCircleControl = renderCircleControl;\n  controls.renderSquareControl = renderSquareControl;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {});\n\n  function Control(options) {\n    for (var i in options) {\n      this[i] = options[i];\n    }\n  }\n\n  fabric.Control = Control;\n  fabric.Control.prototype =\n  /** @lends fabric.Control.prototype */\n  {\n    /**\n     * keep track of control visibility.\n     * mainly for backward compatibility.\n     * if you do not want to see a control, you can remove it\n     * from the controlset.\n     * @type {Boolean}\n     * @default true\n     */\n    visible: true,\n\n    /**\n     * Name of the action that the controll will likely execute.\n     * This is optional. FabricJS uses to identify what the user is doing for some\n     * extra optimizations. If you are writing a custom control and you want to know\n     * somewhere else in the code what is going on, you can use this string here.\n     * you can also provide a custom getActionName if your control run multiple actions\n     * depending on some external state.\n     * default to scale since is the most common, used on 4 corners by default\n     * @type {String}\n     * @default 'scale'\n     */\n    actionName: 'scale',\n\n    /**\n     * Drawing angle of the control.\n     * NOT used for now, but name marked as needed for internal logic\n     * example: to reuse the same drawing function for different rotated controls\n     * @type {Number}\n     * @default 0\n     */\n    angle: 0,\n\n    /**\n     * Relative position of the control. X\n     * 0,0 is the center of the Object, while -0.5 (left) or 0.5 (right) are the extremities\n     * of the bounding box.\n     * @type {Number}\n     * @default 0\n     */\n    x: 0,\n\n    /**\n     * Relative position of the control. Y\n     * 0,0 is the center of the Object, while -0.5 (top) or 0.5 (bottom) are the extremities\n     * of the bounding box.\n     * @type {Number}\n     * @default 0\n     */\n    y: 0,\n\n    /**\n     * Horizontal offset of the control from the defined position. In pixels\n     * Positive offset moves the control to the right, negative to the left.\n     * It used when you want to have position of control that does not scale with\n     * the bounding box. Example: rotation control is placed at x:0, y: 0.5 on\n     * the boundindbox, with an offset of 30 pixels vertivally. Those 30 pixels will\n     * stay 30 pixels no matter how the object is big. Another example is having 2\n     * controls in the corner, that stay in the same position when the object scale.\n     * of the bounding box.\n     * @type {Number}\n     * @default 0\n     */\n    offsetX: 0,\n\n    /**\n     * Vertical offset of the control from the defined position. In pixels\n     * Positive offset moves the control to the bottom, negative to the top.\n     * @type {Number}\n     * @default 0\n     */\n    offsetY: 0,\n\n    /**\n     * Css cursor style to display when the control is hovered.\n     * if the method `cursorStyleHandler` is provided, this property is ignored.\n     * @type {String}\n     * @default 'crosshair'\n     */\n    cursorStyle: 'crosshair',\n\n    /**\n     * If controls has an offsetY or offsetX, draw a line that connects\n     * the control to the bounding box\n     * @type {Boolean}\n     * @default false\n     */\n    withConnection: false,\n\n    /**\n     * The control actionHandler, provide one to handle action ( control being moved )\n     * @param {Event} eventData the native mouse event\n     * @param {Object} transformData properties of the current transform\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {Function}\n     */\n    actionHandler: function ()\n    /* eventData, transformData, fabricObject */\n    {},\n\n    /**\n     * The control handler for mouse down, provide one to handle mouse down on control\n     * @param {Event} eventData the native mouse event\n     * @param {Object} transformData properties of the current transform\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {Function}\n     */\n    mouseDownHandler: function ()\n    /* eventData, transformData, fabricObject */\n    {},\n\n    /**\n     * The control mouseUpHandler, provide one to handle an effect on mouse up.\n     * @param {Event} eventData the native mouse event\n     * @param {Object} transformData properties of the current transform\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {Function}\n     */\n    mouseUpHandler: function ()\n    /* eventData, transformData, fabricObject */\n    {},\n\n    /**\n     * Returns control actionHandler\n     * @param {Event} eventData the native mouse event\n     * @param {Object} transformData properties of the current transform\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {Function}\n     */\n    getActionHandler: function ()\n    /* eventData, transformData, fabricObject */\n    {\n      return this.actionHandler;\n    },\n\n    /**\n     * Returns control mouseDown handler\n     * @param {Event} eventData the native mouse event\n     * @param {Object} transformData properties of the current transform\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {Function}\n     */\n    getMouseDownHandler: function ()\n    /* eventData, fabricObject, control */\n    {\n      return this.mouseDownHandler;\n    },\n\n    /**\n     * Returns control mouseUp handler\n     * @param {Event} eventData the native mouse event\n     * @param {Object} transformData properties of the current transform\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {Function}\n     */\n    getMouseUpHandler: function ()\n    /* eventData, fabricObject, control */\n    {\n      return this.mouseUpHandler;\n    },\n\n    /**\n     * Returns control cursorStyle for css using cursorStyle. If you need a more elaborate\n     * function you can pass one in the constructor\n     * the cursorStyle property\n     * @param {Event} eventData the native mouse event\n     * @param {fabric.Control} control the current control ( likely this)\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {String}\n     */\n    cursorStyleHandler: function (eventData, control\n    /* fabricObject */\n    ) {\n      return control.cursorStyle;\n    },\n\n    /**\n     * Returns the action name. The basic implementation just return the actionName property.\n     * @param {Event} eventData the native mouse event\n     * @param {fabric.Control} control the current control ( likely this)\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {String}\n     */\n    getActionName: function (eventData, control\n    /* fabricObject */\n    ) {\n      return control.actionName;\n    },\n\n    /**\n     * Returns controls visibility\n     * @param {fabric.Object} object on which the control is displayed\n     * @param {String} controlKey key where the control is memorized on the\n     * @return {Boolean}\n     */\n    getVisibility: function (fabricObject, controlKey) {\n      var objectVisibility = fabricObject._controlsVisibility;\n\n      if (objectVisibility && typeof objectVisibility[controlKey] !== 'undefined') {\n        return objectVisibility[controlKey];\n      }\n\n      return this.visible;\n    },\n\n    /**\n     * Sets controls visibility\n     * @param {Boolean} visibility for the object\n     * @return {Void}\n     */\n    setVisibility: function (visibility\n    /* name, fabricObject */\n    ) {\n      this.visible = visibility;\n    },\n    positionHandler: function (dim, finalMatrix\n    /*, fabricObject, currentControl */\n    ) {\n      var point = fabric.util.transformPoint({\n        x: this.x * dim.x + this.offsetX,\n        y: this.y * dim.y + this.offsetY\n      }, finalMatrix);\n      return point;\n    },\n\n    /**\n    * Render function for the control.\n    * When this function runs the context is unscaled. unrotate. Just retina scaled.\n    * all the functions will have to translate to the point left,top before starting Drawing\n    * if they want to draw a control where the position is detected.\n    * left and top are the result of the positionHandler function\n    * @param {RenderingContext2D} ctx the context where the control will be drawn\n    * @param {Number} left position of the canvas where we are about to render the control.\n    * @param {Number} top position of the canvas where we are about to render the control.\n    * @param {Object} styleOverride\n    * @param {fabric.Object} fabricObject the object where the control is about to be rendered\n    */\n    render: function (ctx, left, top, styleOverride, fabricObject) {\n      styleOverride = styleOverride || {};\n\n      switch (styleOverride.cornerStyle || fabricObject.cornerStyle) {\n        case 'circle':\n          fabric.controlsUtils.renderCircleControl.call(this, ctx, left, top, styleOverride, fabricObject);\n          break;\n\n        default:\n          fabric.controlsUtils.renderSquareControl.call(this, ctx, left, top, styleOverride, fabricObject);\n      }\n    }\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function () {\n  /* _FROM_SVG_START_ */\n  function getColorStop(el, multiplier) {\n    var style = el.getAttribute('style'),\n        offset = el.getAttribute('offset') || 0,\n        color,\n        colorAlpha,\n        opacity,\n        i; // convert percents to absolute values\n\n    offset = parseFloat(offset) / (/%$/.test(offset) ? 100 : 1);\n    offset = offset < 0 ? 0 : offset > 1 ? 1 : offset;\n\n    if (style) {\n      var keyValuePairs = style.split(/\\s*;\\s*/);\n\n      if (keyValuePairs[keyValuePairs.length - 1] === '') {\n        keyValuePairs.pop();\n      }\n\n      for (i = keyValuePairs.length; i--;) {\n        var split = keyValuePairs[i].split(/\\s*:\\s*/),\n            key = split[0].trim(),\n            value = split[1].trim();\n\n        if (key === 'stop-color') {\n          color = value;\n        } else if (key === 'stop-opacity') {\n          opacity = value;\n        }\n      }\n    }\n\n    if (!color) {\n      color = el.getAttribute('stop-color') || 'rgb(0,0,0)';\n    }\n\n    if (!opacity) {\n      opacity = el.getAttribute('stop-opacity');\n    }\n\n    color = new fabric.Color(color);\n    colorAlpha = color.getAlpha();\n    opacity = isNaN(parseFloat(opacity)) ? 1 : parseFloat(opacity);\n    opacity *= colorAlpha * multiplier;\n    return {\n      offset: offset,\n      color: color.toRgb(),\n      opacity: opacity\n    };\n  }\n\n  function getLinearCoords(el) {\n    return {\n      x1: el.getAttribute('x1') || 0,\n      y1: el.getAttribute('y1') || 0,\n      x2: el.getAttribute('x2') || '100%',\n      y2: el.getAttribute('y2') || 0\n    };\n  }\n\n  function getRadialCoords(el) {\n    return {\n      x1: el.getAttribute('fx') || el.getAttribute('cx') || '50%',\n      y1: el.getAttribute('fy') || el.getAttribute('cy') || '50%',\n      r1: 0,\n      x2: el.getAttribute('cx') || '50%',\n      y2: el.getAttribute('cy') || '50%',\n      r2: el.getAttribute('r') || '50%'\n    };\n  }\n  /* _FROM_SVG_END_ */\n\n\n  var clone = fabric.util.object.clone;\n  /**\n   * Gradient class\n   * @class fabric.Gradient\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#gradients}\n   * @see {@link fabric.Gradient#initialize} for constructor definition\n   */\n\n  fabric.Gradient = fabric.util.createClass(\n  /** @lends fabric.Gradient.prototype */\n  {\n    /**\n     * Horizontal offset for aligning gradients coming from SVG when outside pathgroups\n     * @type Number\n     * @default 0\n     */\n    offsetX: 0,\n\n    /**\n     * Vertical offset for aligning gradients coming from SVG when outside pathgroups\n     * @type Number\n     * @default 0\n     */\n    offsetY: 0,\n\n    /**\n     * A transform matrix to apply to the gradient before painting.\n     * Imported from svg gradients, is not applied with the current transform in the center.\n     * Before this transform is applied, the origin point is at the top left corner of the object\n     * plus the addition of offsetY and offsetX.\n     * @type Number[]\n     * @default null\n     */\n    gradientTransform: null,\n\n    /**\n     * coordinates units for coords.\n     * If `pixels`, the number of coords are in the same unit of width / height.\n     * If set as `percentage` the coords are still a number, but 1 means 100% of width\n     * for the X and 100% of the height for the y. It can be bigger than 1 and negative.\n     * allowed values pixels or percentage.\n     * @type String\n     * @default 'pixels'\n     */\n    gradientUnits: 'pixels',\n\n    /**\n     * Gradient type linear or radial\n     * @type String\n     * @default 'pixels'\n     */\n    type: 'linear',\n\n    /**\n     * Constructor\n     * @param {Object} options Options object with type, coords, gradientUnits and colorStops\n     * @param {Object} [options.type] gradient type linear or radial\n     * @param {Object} [options.gradientUnits] gradient units\n     * @param {Object} [options.offsetX] SVG import compatibility\n     * @param {Object} [options.offsetY] SVG import compatibility\n     * @param {Object[]} options.colorStops contains the colorstops.\n     * @param {Object} options.coords contains the coords of the gradient\n     * @param {Number} [options.coords.x1] X coordiante of the first point for linear or of the focal point for radial\n     * @param {Number} [options.coords.y1] Y coordiante of the first point for linear or of the focal point for radial\n     * @param {Number} [options.coords.x2] X coordiante of the second point for linear or of the center point for radial\n     * @param {Number} [options.coords.y2] Y coordiante of the second point for linear or of the center point for radial\n     * @param {Number} [options.coords.r1] only for radial gradient, radius of the inner circle\n     * @param {Number} [options.coords.r2] only for radial gradient, radius of the external circle\n     * @return {fabric.Gradient} thisArg\n     */\n    initialize: function (options) {\n      options || (options = {});\n      options.coords || (options.coords = {});\n\n      var coords,\n          _this = this; // sets everything, then coords and colorstops get sets again\n\n\n      Object.keys(options).forEach(function (option) {\n        _this[option] = options[option];\n      });\n\n      if (this.id) {\n        this.id += '_' + fabric.Object.__uid++;\n      } else {\n        this.id = fabric.Object.__uid++;\n      }\n\n      coords = {\n        x1: options.coords.x1 || 0,\n        y1: options.coords.y1 || 0,\n        x2: options.coords.x2 || 0,\n        y2: options.coords.y2 || 0\n      };\n\n      if (this.type === 'radial') {\n        coords.r1 = options.coords.r1 || 0;\n        coords.r2 = options.coords.r2 || 0;\n      }\n\n      this.coords = coords;\n      this.colorStops = options.colorStops.slice();\n    },\n\n    /**\n     * Adds another colorStop\n     * @param {Object} colorStop Object with offset and color\n     * @return {fabric.Gradient} thisArg\n     */\n    addColorStop: function (colorStops) {\n      for (var position in colorStops) {\n        var color = new fabric.Color(colorStops[position]);\n        this.colorStops.push({\n          offset: parseFloat(position),\n          color: color.toRgb(),\n          opacity: color.getAlpha()\n        });\n      }\n\n      return this;\n    },\n\n    /**\n     * Returns object representation of a gradient\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object}\n     */\n    toObject: function (propertiesToInclude) {\n      var object = {\n        type: this.type,\n        coords: this.coords,\n        colorStops: this.colorStops,\n        offsetX: this.offsetX,\n        offsetY: this.offsetY,\n        gradientUnits: this.gradientUnits,\n        gradientTransform: this.gradientTransform ? this.gradientTransform.concat() : this.gradientTransform\n      };\n      fabric.util.populateWithProperties(this, object, propertiesToInclude);\n      return object;\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * Returns SVG representation of an gradient\n     * @param {Object} object Object to create a gradient for\n     * @return {String} SVG representation of an gradient (linear/radial)\n     */\n    toSVG: function (object, options) {\n      var coords = clone(this.coords, true),\n          i,\n          len,\n          options = options || {},\n          markup,\n          commonAttributes,\n          colorStops = clone(this.colorStops, true),\n          needsSwap = coords.r1 > coords.r2,\n          transform = this.gradientTransform ? this.gradientTransform.concat() : fabric.iMatrix.concat(),\n          offsetX = -this.offsetX,\n          offsetY = -this.offsetY,\n          withViewport = !!options.additionalTransform,\n          gradientUnits = this.gradientUnits === 'pixels' ? 'userSpaceOnUse' : 'objectBoundingBox'; // colorStops must be sorted ascending\n\n      colorStops.sort(function (a, b) {\n        return a.offset - b.offset;\n      });\n\n      if (gradientUnits === 'objectBoundingBox') {\n        offsetX /= object.width;\n        offsetY /= object.height;\n      } else {\n        offsetX += object.width / 2;\n        offsetY += object.height / 2;\n      }\n\n      if (object.type === 'path') {\n        offsetX -= object.pathOffset.x;\n        offsetY -= object.pathOffset.y;\n      }\n\n      transform[4] -= offsetX;\n      transform[5] -= offsetY;\n      commonAttributes = 'id=\"SVGID_' + this.id + '\" gradientUnits=\"' + gradientUnits + '\"';\n      commonAttributes += ' gradientTransform=\"' + (withViewport ? options.additionalTransform + ' ' : '') + fabric.util.matrixToSVG(transform) + '\" ';\n\n      if (this.type === 'linear') {\n        markup = ['<linearGradient ', commonAttributes, ' x1=\"', coords.x1, '\" y1=\"', coords.y1, '\" x2=\"', coords.x2, '\" y2=\"', coords.y2, '\">\\n'];\n      } else if (this.type === 'radial') {\n        // svg radial gradient has just 1 radius. the biggest.\n        markup = ['<radialGradient ', commonAttributes, ' cx=\"', needsSwap ? coords.x1 : coords.x2, '\" cy=\"', needsSwap ? coords.y1 : coords.y2, '\" r=\"', needsSwap ? coords.r1 : coords.r2, '\" fx=\"', needsSwap ? coords.x2 : coords.x1, '\" fy=\"', needsSwap ? coords.y2 : coords.y1, '\">\\n'];\n      }\n\n      if (this.type === 'radial') {\n        if (needsSwap) {\n          // svg goes from internal to external radius. if radius are inverted, swap color stops.\n          colorStops = colorStops.concat();\n          colorStops.reverse();\n\n          for (i = 0, len = colorStops.length; i < len; i++) {\n            colorStops[i].offset = 1 - colorStops[i].offset;\n          }\n        }\n\n        var minRadius = Math.min(coords.r1, coords.r2);\n\n        if (minRadius > 0) {\n          // i have to shift all colorStops and add new one in 0.\n          var maxRadius = Math.max(coords.r1, coords.r2),\n              percentageShift = minRadius / maxRadius;\n\n          for (i = 0, len = colorStops.length; i < len; i++) {\n            colorStops[i].offset += percentageShift * (1 - colorStops[i].offset);\n          }\n        }\n      }\n\n      for (i = 0, len = colorStops.length; i < len; i++) {\n        var colorStop = colorStops[i];\n        markup.push('<stop ', 'offset=\"', colorStop.offset * 100 + '%', '\" style=\"stop-color:', colorStop.color, typeof colorStop.opacity !== 'undefined' ? ';stop-opacity: ' + colorStop.opacity : ';', '\"/>\\n');\n      }\n\n      markup.push(this.type === 'linear' ? '</linearGradient>\\n' : '</radialGradient>\\n');\n      return markup.join('');\n    },\n\n    /* _TO_SVG_END_ */\n\n    /**\n     * Returns an instance of CanvasGradient\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @return {CanvasGradient}\n     */\n    toLive: function (ctx) {\n      var gradient,\n          coords = fabric.util.object.clone(this.coords),\n          i,\n          len;\n\n      if (!this.type) {\n        return;\n      }\n\n      if (this.type === 'linear') {\n        gradient = ctx.createLinearGradient(coords.x1, coords.y1, coords.x2, coords.y2);\n      } else if (this.type === 'radial') {\n        gradient = ctx.createRadialGradient(coords.x1, coords.y1, coords.r1, coords.x2, coords.y2, coords.r2);\n      }\n\n      for (i = 0, len = this.colorStops.length; i < len; i++) {\n        var color = this.colorStops[i].color,\n            opacity = this.colorStops[i].opacity,\n            offset = this.colorStops[i].offset;\n\n        if (typeof opacity !== 'undefined') {\n          color = new fabric.Color(color).setAlpha(opacity).toRgba();\n        }\n\n        gradient.addColorStop(offset, color);\n      }\n\n      return gradient;\n    }\n  });\n  fabric.util.object.extend(fabric.Gradient, {\n    /* _FROM_SVG_START_ */\n\n    /**\n     * Returns {@link fabric.Gradient} instance from an SVG element\n     * @static\n     * @memberOf fabric.Gradient\n     * @param {SVGGradientElement} el SVG gradient element\n     * @param {fabric.Object} instance\n     * @param {String} opacityAttr A fill-opacity or stroke-opacity attribute to multiply to each stop's opacity.\n     * @param {Object} svgOptions an object containing the size of the SVG in order to parse correctly graidents\n     * that uses gradientUnits as 'userSpaceOnUse' and percentages.\n     * @param {Object.number} viewBoxWidth width part of the viewBox attribute on svg\n     * @param {Object.number} viewBoxHeight height part of the viewBox attribute on svg\n     * @param {Object.number} width width part of the svg tag if viewBox is not specified\n     * @param {Object.number} height height part of the svg tag if viewBox is not specified\n     * @return {fabric.Gradient} Gradient instance\n     * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement\n     * @see http://www.w3.org/TR/SVG/pservers.html#RadialGradientElement\n     */\n    fromElement: function (el, instance, opacityAttr, svgOptions) {\n      /**\n       *  @example:\n       *\n       *  <linearGradient id=\"linearGrad1\">\n       *    <stop offset=\"0%\" stop-color=\"white\"/>\n       *    <stop offset=\"100%\" stop-color=\"black\"/>\n       *  </linearGradient>\n       *\n       *  OR\n       *\n       *  <linearGradient id=\"linearGrad2\">\n       *    <stop offset=\"0\" style=\"stop-color:rgb(255,255,255)\"/>\n       *    <stop offset=\"1\" style=\"stop-color:rgb(0,0,0)\"/>\n       *  </linearGradient>\n       *\n       *  OR\n       *\n       *  <radialGradient id=\"radialGrad1\">\n       *    <stop offset=\"0%\" stop-color=\"white\" stop-opacity=\"1\" />\n       *    <stop offset=\"50%\" stop-color=\"black\" stop-opacity=\"0.5\" />\n       *    <stop offset=\"100%\" stop-color=\"white\" stop-opacity=\"1\" />\n       *  </radialGradient>\n       *\n       *  OR\n       *\n       *  <radialGradient id=\"radialGrad2\">\n       *    <stop offset=\"0\" stop-color=\"rgb(255,255,255)\" />\n       *    <stop offset=\"0.5\" stop-color=\"rgb(0,0,0)\" />\n       *    <stop offset=\"1\" stop-color=\"rgb(255,255,255)\" />\n       *  </radialGradient>\n       *\n       */\n      var multiplier = parseFloat(opacityAttr) / (/%$/.test(opacityAttr) ? 100 : 1);\n      multiplier = multiplier < 0 ? 0 : multiplier > 1 ? 1 : multiplier;\n\n      if (isNaN(multiplier)) {\n        multiplier = 1;\n      }\n\n      var colorStopEls = el.getElementsByTagName('stop'),\n          type,\n          gradientUnits = el.getAttribute('gradientUnits') === 'userSpaceOnUse' ? 'pixels' : 'percentage',\n          gradientTransform = el.getAttribute('gradientTransform') || '',\n          colorStops = [],\n          coords,\n          i,\n          offsetX = 0,\n          offsetY = 0,\n          transformMatrix;\n\n      if (el.nodeName === 'linearGradient' || el.nodeName === 'LINEARGRADIENT') {\n        type = 'linear';\n        coords = getLinearCoords(el);\n      } else {\n        type = 'radial';\n        coords = getRadialCoords(el);\n      }\n\n      for (i = colorStopEls.length; i--;) {\n        colorStops.push(getColorStop(colorStopEls[i], multiplier));\n      }\n\n      transformMatrix = fabric.parseTransformAttribute(gradientTransform);\n\n      __convertPercentUnitsToValues(instance, coords, svgOptions, gradientUnits);\n\n      if (gradientUnits === 'pixels') {\n        offsetX = -instance.left;\n        offsetY = -instance.top;\n      }\n\n      var gradient = new fabric.Gradient({\n        id: el.getAttribute('id'),\n        type: type,\n        coords: coords,\n        colorStops: colorStops,\n        gradientUnits: gradientUnits,\n        gradientTransform: transformMatrix,\n        offsetX: offsetX,\n        offsetY: offsetY\n      });\n      return gradient;\n    }\n    /* _FROM_SVG_END_ */\n\n  });\n  /**\n   * @private\n   */\n\n  function __convertPercentUnitsToValues(instance, options, svgOptions, gradientUnits) {\n    var propValue, finalValue;\n    Object.keys(options).forEach(function (prop) {\n      propValue = options[prop];\n\n      if (propValue === 'Infinity') {\n        finalValue = 1;\n      } else if (propValue === '-Infinity') {\n        finalValue = 0;\n      } else {\n        finalValue = parseFloat(options[prop], 10);\n\n        if (typeof propValue === 'string' && /^(\\d+\\.\\d+)%|(\\d+)%$/.test(propValue)) {\n          finalValue *= 0.01;\n\n          if (gradientUnits === 'pixels') {\n            // then we need to fix those percentages here in svg parsing\n            if (prop === 'x1' || prop === 'x2' || prop === 'r2') {\n              finalValue *= svgOptions.viewBoxWidth || svgOptions.width;\n            }\n\n            if (prop === 'y1' || prop === 'y2') {\n              finalValue *= svgOptions.viewBoxHeight || svgOptions.height;\n            }\n          }\n        }\n      }\n\n      options[prop] = finalValue;\n    });\n  }\n})();\n\n(function () {\n  'use strict';\n\n  var toFixed = fabric.util.toFixed;\n  /**\n   * Pattern class\n   * @class fabric.Pattern\n   * @see {@link http://fabricjs.com/patterns|Pattern demo}\n   * @see {@link http://fabricjs.com/dynamic-patterns|DynamicPattern demo}\n   * @see {@link fabric.Pattern#initialize} for constructor definition\n   */\n\n  fabric.Pattern = fabric.util.createClass(\n  /** @lends fabric.Pattern.prototype */\n  {\n    /**\n     * Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat)\n     * @type String\n     * @default\n     */\n    repeat: 'repeat',\n\n    /**\n     * Pattern horizontal offset from object's left/top corner\n     * @type Number\n     * @default\n     */\n    offsetX: 0,\n\n    /**\n     * Pattern vertical offset from object's left/top corner\n     * @type Number\n     * @default\n     */\n    offsetY: 0,\n\n    /**\n     * crossOrigin value (one of \"\", \"anonymous\", \"use-credentials\")\n     * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes\n     * @type String\n     * @default\n     */\n    crossOrigin: '',\n\n    /**\n     * transform matrix to change the pattern, imported from svgs.\n     * @type Array\n     * @default\n     */\n    patternTransform: null,\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     * @param {Function} [callback] function to invoke after callback init.\n     * @return {fabric.Pattern} thisArg\n     */\n    initialize: function (options, callback) {\n      options || (options = {});\n      this.id = fabric.Object.__uid++;\n      this.setOptions(options);\n\n      if (!options.source || options.source && typeof options.source !== 'string') {\n        callback && callback(this);\n        return;\n      } else {\n        // img src string\n        var _this = this;\n\n        this.source = fabric.util.createImage();\n        fabric.util.loadImage(options.source, function (img, isError) {\n          _this.source = img;\n          callback && callback(_this, isError);\n        }, null, this.crossOrigin);\n      }\n    },\n\n    /**\n     * Returns object representation of a pattern\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} Object representation of a pattern instance\n     */\n    toObject: function (propertiesToInclude) {\n      var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n          source,\n          object; // <img> element\n\n      if (typeof this.source.src === 'string') {\n        source = this.source.src;\n      } // <canvas> element\n      else if (typeof this.source === 'object' && this.source.toDataURL) {\n          source = this.source.toDataURL();\n        }\n\n      object = {\n        type: 'pattern',\n        source: source,\n        repeat: this.repeat,\n        crossOrigin: this.crossOrigin,\n        offsetX: toFixed(this.offsetX, NUM_FRACTION_DIGITS),\n        offsetY: toFixed(this.offsetY, NUM_FRACTION_DIGITS),\n        patternTransform: this.patternTransform ? this.patternTransform.concat() : null\n      };\n      fabric.util.populateWithProperties(this, object, propertiesToInclude);\n      return object;\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * Returns SVG representation of a pattern\n     * @param {fabric.Object} object\n     * @return {String} SVG representation of a pattern\n     */\n    toSVG: function (object) {\n      var patternSource = typeof this.source === 'function' ? this.source() : this.source,\n          patternWidth = patternSource.width / object.width,\n          patternHeight = patternSource.height / object.height,\n          patternOffsetX = this.offsetX / object.width,\n          patternOffsetY = this.offsetY / object.height,\n          patternImgSrc = '';\n\n      if (this.repeat === 'repeat-x' || this.repeat === 'no-repeat') {\n        patternHeight = 1;\n\n        if (patternOffsetY) {\n          patternHeight += Math.abs(patternOffsetY);\n        }\n      }\n\n      if (this.repeat === 'repeat-y' || this.repeat === 'no-repeat') {\n        patternWidth = 1;\n\n        if (patternOffsetX) {\n          patternWidth += Math.abs(patternOffsetX);\n        }\n      }\n\n      if (patternSource.src) {\n        patternImgSrc = patternSource.src;\n      } else if (patternSource.toDataURL) {\n        patternImgSrc = patternSource.toDataURL();\n      }\n\n      return '<pattern id=\"SVGID_' + this.id + '\" x=\"' + patternOffsetX + '\" y=\"' + patternOffsetY + '\" width=\"' + patternWidth + '\" height=\"' + patternHeight + '\">\\n' + '<image x=\"0\" y=\"0\"' + ' width=\"' + patternSource.width + '\" height=\"' + patternSource.height + '\" xlink:href=\"' + patternImgSrc + '\"></image>\\n' + '</pattern>\\n';\n    },\n\n    /* _TO_SVG_END_ */\n    setOptions: function (options) {\n      for (var prop in options) {\n        this[prop] = options[prop];\n      }\n    },\n\n    /**\n     * Returns an instance of CanvasPattern\n     * @param {CanvasRenderingContext2D} ctx Context to create pattern\n     * @return {CanvasPattern}\n     */\n    toLive: function (ctx) {\n      var source = this.source; // if the image failed to load, return, and allow rest to continue loading\n\n      if (!source) {\n        return '';\n      } // if an image\n\n\n      if (typeof source.src !== 'undefined') {\n        if (!source.complete) {\n          return '';\n        }\n\n        if (source.naturalWidth === 0 || source.naturalHeight === 0) {\n          return '';\n        }\n      }\n\n      return ctx.createPattern(source, this.repeat);\n    }\n  });\n})();\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      toFixed = fabric.util.toFixed;\n\n  if (fabric.Shadow) {\n    fabric.warn('fabric.Shadow is already defined.');\n    return;\n  }\n  /**\n   * Shadow class\n   * @class fabric.Shadow\n   * @see {@link http://fabricjs.com/shadows|Shadow demo}\n   * @see {@link fabric.Shadow#initialize} for constructor definition\n   */\n\n\n  fabric.Shadow = fabric.util.createClass(\n  /** @lends fabric.Shadow.prototype */\n  {\n    /**\n     * Shadow color\n     * @type String\n     * @default\n     */\n    color: 'rgb(0,0,0)',\n\n    /**\n     * Shadow blur\n     * @type Number\n     */\n    blur: 0,\n\n    /**\n     * Shadow horizontal offset\n     * @type Number\n     * @default\n     */\n    offsetX: 0,\n\n    /**\n     * Shadow vertical offset\n     * @type Number\n     * @default\n     */\n    offsetY: 0,\n\n    /**\n     * Whether the shadow should affect stroke operations\n     * @type Boolean\n     * @default\n     */\n    affectStroke: false,\n\n    /**\n     * Indicates whether toObject should include default values\n     * @type Boolean\n     * @default\n     */\n    includeDefaultValues: true,\n\n    /**\n     * When `false`, the shadow will scale with the object.\n     * When `true`, the shadow's offsetX, offsetY, and blur will not be affected by the object's scale.\n     * default to false\n     * @type Boolean\n     * @default\n     */\n    nonScaling: false,\n\n    /**\n     * Constructor\n     * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetY properties or string (e.g. \"rgba(0,0,0,0.2) 2px 2px 10px\")\n     * @return {fabric.Shadow} thisArg\n     */\n    initialize: function (options) {\n      if (typeof options === 'string') {\n        options = this._parseShadow(options);\n      }\n\n      for (var prop in options) {\n        this[prop] = options[prop];\n      }\n\n      this.id = fabric.Object.__uid++;\n    },\n\n    /**\n     * @private\n     * @param {String} shadow Shadow value to parse\n     * @return {Object} Shadow object with color, offsetX, offsetY and blur\n     */\n    _parseShadow: function (shadow) {\n      var shadowStr = shadow.trim(),\n          offsetsAndBlur = fabric.Shadow.reOffsetsAndBlur.exec(shadowStr) || [],\n          color = shadowStr.replace(fabric.Shadow.reOffsetsAndBlur, '') || 'rgb(0,0,0)';\n      return {\n        color: color.trim(),\n        offsetX: parseInt(offsetsAndBlur[1], 10) || 0,\n        offsetY: parseInt(offsetsAndBlur[2], 10) || 0,\n        blur: parseInt(offsetsAndBlur[3], 10) || 0\n      };\n    },\n\n    /**\n     * Returns a string representation of an instance\n     * @see http://www.w3.org/TR/css-text-decor-3/#text-shadow\n     * @return {String} Returns CSS3 text-shadow declaration\n     */\n    toString: function () {\n      return [this.offsetX, this.offsetY, this.blur, this.color].join('px ');\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * Returns SVG representation of a shadow\n     * @param {fabric.Object} object\n     * @return {String} SVG representation of a shadow\n     */\n    toSVG: function (object) {\n      var fBoxX = 40,\n          fBoxY = 40,\n          NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n          offset = fabric.util.rotateVector({\n        x: this.offsetX,\n        y: this.offsetY\n      }, fabric.util.degreesToRadians(-object.angle)),\n          BLUR_BOX = 20,\n          color = new fabric.Color(this.color);\n\n      if (object.width && object.height) {\n        //http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion\n        // we add some extra space to filter box to contain the blur ( 20 )\n        fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;\n        fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;\n      }\n\n      if (object.flipX) {\n        offset.x *= -1;\n      }\n\n      if (object.flipY) {\n        offset.y *= -1;\n      }\n\n      return '<filter id=\"SVGID_' + this.id + '\" y=\"-' + fBoxY + '%\" height=\"' + (100 + 2 * fBoxY) + '%\" ' + 'x=\"-' + fBoxX + '%\" width=\"' + (100 + 2 * fBoxX) + '%\" ' + '>\\n' + '\\t<feGaussianBlur in=\"SourceAlpha\" stdDeviation=\"' + toFixed(this.blur ? this.blur / 2 : 0, NUM_FRACTION_DIGITS) + '\"></feGaussianBlur>\\n' + '\\t<feOffset dx=\"' + toFixed(offset.x, NUM_FRACTION_DIGITS) + '\" dy=\"' + toFixed(offset.y, NUM_FRACTION_DIGITS) + '\" result=\"oBlur\" ></feOffset>\\n' + '\\t<feFlood flood-color=\"' + color.toRgb() + '\" flood-opacity=\"' + color.getAlpha() + '\"/>\\n' + '\\t<feComposite in2=\"oBlur\" operator=\"in\" />\\n' + '\\t<feMerge>\\n' + '\\t\\t<feMergeNode></feMergeNode>\\n' + '\\t\\t<feMergeNode in=\"SourceGraphic\"></feMergeNode>\\n' + '\\t</feMerge>\\n' + '</filter>\\n';\n    },\n\n    /* _TO_SVG_END_ */\n\n    /**\n     * Returns object representation of a shadow\n     * @return {Object} Object representation of a shadow instance\n     */\n    toObject: function () {\n      if (this.includeDefaultValues) {\n        return {\n          color: this.color,\n          blur: this.blur,\n          offsetX: this.offsetX,\n          offsetY: this.offsetY,\n          affectStroke: this.affectStroke,\n          nonScaling: this.nonScaling\n        };\n      }\n\n      var obj = {},\n          proto = fabric.Shadow.prototype;\n      ['color', 'blur', 'offsetX', 'offsetY', 'affectStroke', 'nonScaling'].forEach(function (prop) {\n        if (this[prop] !== proto[prop]) {\n          obj[prop] = this[prop];\n        }\n      }, this);\n      return obj;\n    }\n  });\n  /**\n   * Regex matching shadow offsetX, offsetY and blur (ex: \"2px 2px 10px rgba(0,0,0,0.2)\", \"rgb(0,255,0) 2px 2px\")\n   * @static\n   * @field\n   * @memberOf fabric.Shadow\n   */\n  // eslint-disable-next-line max-len\n\n  fabric.Shadow.reOffsetsAndBlur = /(?:\\s|^)(-?\\d+(?:px)?(?:\\s?|$))?(-?\\d+(?:px)?(?:\\s?|$))?(\\d+(?:px)?)?(?:\\s?|$)(?:$|\\s)/;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function () {\n  'use strict';\n\n  if (fabric.StaticCanvas) {\n    fabric.warn('fabric.StaticCanvas is already defined.');\n    return;\n  } // aliases for faster resolution\n\n\n  var extend = fabric.util.object.extend,\n      getElementOffset = fabric.util.getElementOffset,\n      removeFromArray = fabric.util.removeFromArray,\n      toFixed = fabric.util.toFixed,\n      transformPoint = fabric.util.transformPoint,\n      invertTransform = fabric.util.invertTransform,\n      getNodeCanvas = fabric.util.getNodeCanvas,\n      createCanvasElement = fabric.util.createCanvasElement,\n      CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element');\n  /**\n   * Static canvas class\n   * @class fabric.StaticCanvas\n   * @mixes fabric.Collection\n   * @mixes fabric.Observable\n   * @see {@link http://fabricjs.com/static_canvas|StaticCanvas demo}\n   * @see {@link fabric.StaticCanvas#initialize} for constructor definition\n   * @fires before:render\n   * @fires after:render\n   * @fires canvas:cleared\n   * @fires object:added\n   * @fires object:removed\n   */\n\n  fabric.StaticCanvas = fabric.util.createClass(fabric.CommonMethods,\n  /** @lends fabric.StaticCanvas.prototype */\n  {\n    /**\n     * Constructor\n     * @param {HTMLElement | String} el &lt;canvas> element to initialize instance on\n     * @param {Object} [options] Options object\n     * @return {Object} thisArg\n     */\n    initialize: function (el, options) {\n      options || (options = {});\n      this.renderAndResetBound = this.renderAndReset.bind(this);\n      this.requestRenderAllBound = this.requestRenderAll.bind(this);\n\n      this._initStatic(el, options);\n    },\n\n    /**\n     * Background color of canvas instance.\n     * Should be set via {@link fabric.StaticCanvas#setBackgroundColor}.\n     * @type {(String|fabric.Pattern)}\n     * @default\n     */\n    backgroundColor: '',\n\n    /**\n     * Background image of canvas instance.\n     * since 2.4.0 image caching is active, please when putting an image as background, add to the\n     * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom\n     * vale. As an alternative you can disable image objectCaching\n     * @type fabric.Image\n     * @default\n     */\n    backgroundImage: null,\n\n    /**\n     * Overlay color of canvas instance.\n     * Should be set via {@link fabric.StaticCanvas#setOverlayColor}\n     * @since 1.3.9\n     * @type {(String|fabric.Pattern)}\n     * @default\n     */\n    overlayColor: '',\n\n    /**\n     * Overlay image of canvas instance.\n     * since 2.4.0 image caching is active, please when putting an image as overlay, add to the\n     * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom\n     * vale. As an alternative you can disable image objectCaching\n     * @type fabric.Image\n     * @default\n     */\n    overlayImage: null,\n\n    /**\n     * Indicates whether toObject/toDatalessObject should include default values\n     * if set to false, takes precedence over the object value.\n     * @type Boolean\n     * @default\n     */\n    includeDefaultValues: true,\n\n    /**\n     * Indicates whether objects' state should be saved\n     * @type Boolean\n     * @default\n     */\n    stateful: false,\n\n    /**\n     * Indicates whether {@link fabric.Collection.add}, {@link fabric.Collection.insertAt} and {@link fabric.Collection.remove},\n     * {@link fabric.StaticCanvas.moveTo}, {@link fabric.StaticCanvas.clear} and many more, should also re-render canvas.\n     * Disabling this option will not give a performance boost when adding/removing a lot of objects to/from canvas at once\n     * since the renders are quequed and executed one per frame.\n     * Disabling is suggested anyway and managing the renders of the app manually is not a big effort ( canvas.requestRenderAll() )\n     * Left default to true to do not break documentation and old app, fiddles.\n     * @type Boolean\n     * @default\n     */\n    renderOnAddRemove: true,\n\n    /**\n     * Indicates whether object controls (borders/controls) are rendered above overlay image\n     * @type Boolean\n     * @default\n     */\n    controlsAboveOverlay: false,\n\n    /**\n     * Indicates whether the browser can be scrolled when using a touchscreen and dragging on the canvas\n     * @type Boolean\n     * @default\n     */\n    allowTouchScrolling: false,\n\n    /**\n     * Indicates whether this canvas will use image smoothing, this is on by default in browsers\n     * @type Boolean\n     * @default\n     */\n    imageSmoothingEnabled: true,\n\n    /**\n     * The transformation (in the format of Canvas transform) which focuses the viewport\n     * @type Array\n     * @default\n     */\n    viewportTransform: fabric.iMatrix.concat(),\n\n    /**\n     * if set to false background image is not affected by viewport transform\n     * @since 1.6.3\n     * @type Boolean\n     * @default\n     */\n    backgroundVpt: true,\n\n    /**\n     * if set to false overlya image is not affected by viewport transform\n     * @since 1.6.3\n     * @type Boolean\n     * @default\n     */\n    overlayVpt: true,\n\n    /**\n     * When true, canvas is scaled by devicePixelRatio for better rendering on retina screens\n     * @type Boolean\n     * @default\n     */\n    enableRetinaScaling: true,\n\n    /**\n     * Describe canvas element extension over design\n     * properties are tl,tr,bl,br.\n     * if canvas is not zoomed/panned those points are the four corner of canvas\n     * if canvas is viewportTransformed you those points indicate the extension\n     * of canvas element in plain untrasformed coordinates\n     * The coordinates get updated with @method calcViewportBoundaries.\n     * @memberOf fabric.StaticCanvas.prototype\n     */\n    vptCoords: {},\n\n    /**\n     * Based on vptCoords and object.aCoords, skip rendering of objects that\n     * are not included in current viewport.\n     * May greatly help in applications with crowded canvas and use of zoom/pan\n     * If One of the corner of the bounding box of the object is on the canvas\n     * the objects get rendered.\n     * @memberOf fabric.StaticCanvas.prototype\n     * @type Boolean\n     * @default\n     */\n    skipOffscreen: true,\n\n    /**\n     * a fabricObject that, without stroke define a clipping area with their shape. filled in black\n     * the clipPath object gets used when the canvas has rendered, and the context is placed in the\n     * top left corner of the canvas.\n     * clipPath will clip away controls, if you do not want this to happen use controlsAboveOverlay = true\n     * @type fabric.Object\n     */\n    clipPath: undefined,\n\n    /**\n     * @private\n     * @param {HTMLElement | String} el &lt;canvas> element to initialize instance on\n     * @param {Object} [options] Options object\n     */\n    _initStatic: function (el, options) {\n      var cb = this.requestRenderAllBound;\n      this._objects = [];\n\n      this._createLowerCanvas(el);\n\n      this._initOptions(options); // only initialize retina scaling once\n\n\n      if (!this.interactive) {\n        this._initRetinaScaling();\n      }\n\n      if (options.overlayImage) {\n        this.setOverlayImage(options.overlayImage, cb);\n      }\n\n      if (options.backgroundImage) {\n        this.setBackgroundImage(options.backgroundImage, cb);\n      }\n\n      if (options.backgroundColor) {\n        this.setBackgroundColor(options.backgroundColor, cb);\n      }\n\n      if (options.overlayColor) {\n        this.setOverlayColor(options.overlayColor, cb);\n      }\n\n      this.calcOffset();\n    },\n\n    /**\n     * @private\n     */\n    _isRetinaScaling: function () {\n      return fabric.devicePixelRatio !== 1 && this.enableRetinaScaling;\n    },\n\n    /**\n     * @private\n     * @return {Number} retinaScaling if applied, otherwise 1;\n     */\n    getRetinaScaling: function () {\n      return this._isRetinaScaling() ? fabric.devicePixelRatio : 1;\n    },\n\n    /**\n     * @private\n     */\n    _initRetinaScaling: function () {\n      if (!this._isRetinaScaling()) {\n        return;\n      }\n\n      var scaleRatio = fabric.devicePixelRatio;\n\n      this.__initRetinaScaling(scaleRatio, this.lowerCanvasEl, this.contextContainer);\n\n      if (this.upperCanvasEl) {\n        this.__initRetinaScaling(scaleRatio, this.upperCanvasEl, this.contextTop);\n      }\n    },\n    __initRetinaScaling: function (scaleRatio, canvas, context) {\n      canvas.setAttribute('width', this.width * scaleRatio);\n      canvas.setAttribute('height', this.height * scaleRatio);\n      context.scale(scaleRatio, scaleRatio);\n    },\n\n    /**\n     * Calculates canvas element offset relative to the document\n     * This method is also attached as \"resize\" event handler of window\n     * @return {fabric.Canvas} instance\n     * @chainable\n     */\n    calcOffset: function () {\n      this._offset = getElementOffset(this.lowerCanvasEl);\n      return this;\n    },\n\n    /**\n     * Sets {@link fabric.StaticCanvas#overlayImage|overlay image} for this canvas\n     * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set overlay to\n     * @param {Function} callback callback to invoke when image is loaded and set as an overlay\n     * @param {Object} [options] Optional options to set for the {@link fabric.Image|overlay image}.\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     * @see {@link http://jsfiddle.net/fabricjs/MnzHT/|jsFiddle demo}\n     * @example <caption>Normal overlayImage with left/top = 0</caption>\n     * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n     *   // Needed to position overlayImage at 0/0\n     *   originX: 'left',\n     *   originY: 'top'\n     * });\n     * @example <caption>overlayImage with different properties</caption>\n     * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n     *   opacity: 0.5,\n     *   angle: 45,\n     *   left: 400,\n     *   top: 400,\n     *   originX: 'left',\n     *   originY: 'top'\n     * });\n     * @example <caption>Stretched overlayImage #1 - width/height correspond to canvas width/height</caption>\n     * fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img, isError) {\n     *    img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'});\n     *    canvas.setOverlayImage(img, canvas.renderAll.bind(canvas));\n     * });\n     * @example <caption>Stretched overlayImage #2 - width/height correspond to canvas width/height</caption>\n     * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n     *   width: canvas.width,\n     *   height: canvas.height,\n     *   // Needed to position overlayImage at 0/0\n     *   originX: 'left',\n     *   originY: 'top'\n     * });\n     * @example <caption>overlayImage loaded from cross-origin</caption>\n     * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n     *   opacity: 0.5,\n     *   angle: 45,\n     *   left: 400,\n     *   top: 400,\n     *   originX: 'left',\n     *   originY: 'top',\n     *   crossOrigin: 'anonymous'\n     * });\n     */\n    setOverlayImage: function (image, callback, options) {\n      return this.__setBgOverlayImage('overlayImage', image, callback, options);\n    },\n\n    /**\n     * Sets {@link fabric.StaticCanvas#backgroundImage|background image} for this canvas\n     * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set background to\n     * @param {Function} callback Callback to invoke when image is loaded and set as background\n     * @param {Object} [options] Optional options to set for the {@link fabric.Image|background image}.\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     * @see {@link http://jsfiddle.net/djnr8o7a/28/|jsFiddle demo}\n     * @example <caption>Normal backgroundImage with left/top = 0</caption>\n     * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n     *   // Needed to position backgroundImage at 0/0\n     *   originX: 'left',\n     *   originY: 'top'\n     * });\n     * @example <caption>backgroundImage with different properties</caption>\n     * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n     *   opacity: 0.5,\n     *   angle: 45,\n     *   left: 400,\n     *   top: 400,\n     *   originX: 'left',\n     *   originY: 'top'\n     * });\n     * @example <caption>Stretched backgroundImage #1 - width/height correspond to canvas width/height</caption>\n     * fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img, isError) {\n     *    img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'});\n     *    canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas));\n     * });\n     * @example <caption>Stretched backgroundImage #2 - width/height correspond to canvas width/height</caption>\n     * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n     *   width: canvas.width,\n     *   height: canvas.height,\n     *   // Needed to position backgroundImage at 0/0\n     *   originX: 'left',\n     *   originY: 'top'\n     * });\n     * @example <caption>backgroundImage loaded from cross-origin</caption>\n     * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n     *   opacity: 0.5,\n     *   angle: 45,\n     *   left: 400,\n     *   top: 400,\n     *   originX: 'left',\n     *   originY: 'top',\n     *   crossOrigin: 'anonymous'\n     * });\n     */\n    // TODO: fix stretched examples\n    setBackgroundImage: function (image, callback, options) {\n      return this.__setBgOverlayImage('backgroundImage', image, callback, options);\n    },\n\n    /**\n     * Sets {@link fabric.StaticCanvas#overlayColor|foreground color} for this canvas\n     * @param {(String|fabric.Pattern)} overlayColor Color or pattern to set foreground color to\n     * @param {Function} callback Callback to invoke when foreground color is set\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     * @see {@link http://jsfiddle.net/fabricjs/pB55h/|jsFiddle demo}\n     * @example <caption>Normal overlayColor - color value</caption>\n     * canvas.setOverlayColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));\n     * @example <caption>fabric.Pattern used as overlayColor</caption>\n     * canvas.setOverlayColor({\n     *   source: 'http://fabricjs.com/assets/escheresque_ste.png'\n     * }, canvas.renderAll.bind(canvas));\n     * @example <caption>fabric.Pattern used as overlayColor with repeat and offset</caption>\n     * canvas.setOverlayColor({\n     *   source: 'http://fabricjs.com/assets/escheresque_ste.png',\n     *   repeat: 'repeat',\n     *   offsetX: 200,\n     *   offsetY: 100\n     * }, canvas.renderAll.bind(canvas));\n     */\n    setOverlayColor: function (overlayColor, callback) {\n      return this.__setBgOverlayColor('overlayColor', overlayColor, callback);\n    },\n\n    /**\n     * Sets {@link fabric.StaticCanvas#backgroundColor|background color} for this canvas\n     * @param {(String|fabric.Pattern)} backgroundColor Color or pattern to set background color to\n     * @param {Function} callback Callback to invoke when background color is set\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     * @see {@link http://jsfiddle.net/fabricjs/hXzvk/|jsFiddle demo}\n     * @example <caption>Normal backgroundColor - color value</caption>\n     * canvas.setBackgroundColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));\n     * @example <caption>fabric.Pattern used as backgroundColor</caption>\n     * canvas.setBackgroundColor({\n     *   source: 'http://fabricjs.com/assets/escheresque_ste.png'\n     * }, canvas.renderAll.bind(canvas));\n     * @example <caption>fabric.Pattern used as backgroundColor with repeat and offset</caption>\n     * canvas.setBackgroundColor({\n     *   source: 'http://fabricjs.com/assets/escheresque_ste.png',\n     *   repeat: 'repeat',\n     *   offsetX: 200,\n     *   offsetY: 100\n     * }, canvas.renderAll.bind(canvas));\n     */\n    setBackgroundColor: function (backgroundColor, callback) {\n      return this.__setBgOverlayColor('backgroundColor', backgroundColor, callback);\n    },\n\n    /**\n     * @private\n     * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundImage|backgroundImage}\n     * or {@link fabric.StaticCanvas#overlayImage|overlayImage})\n     * @param {(fabric.Image|String|null)} image fabric.Image instance, URL of an image or null to set background or overlay to\n     * @param {Function} callback Callback to invoke when image is loaded and set as background or overlay. The first argument is the created image, the second argument is a flag indicating whether an error occured or not.\n     * @param {Object} [options] Optional options to set for the {@link fabric.Image|image}.\n     */\n    __setBgOverlayImage: function (property, image, callback, options) {\n      if (typeof image === 'string') {\n        fabric.util.loadImage(image, function (img, isError) {\n          if (img) {\n            var instance = new fabric.Image(img, options);\n            this[property] = instance;\n            instance.canvas = this;\n          }\n\n          callback && callback(img, isError);\n        }, this, options && options.crossOrigin);\n      } else {\n        options && image.setOptions(options);\n        this[property] = image;\n        image && (image.canvas = this);\n        callback && callback(image, false);\n      }\n\n      return this;\n    },\n\n    /**\n     * @private\n     * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundColor|backgroundColor}\n     * or {@link fabric.StaticCanvas#overlayColor|overlayColor})\n     * @param {(Object|String|null)} color Object with pattern information, color value or null\n     * @param {Function} [callback] Callback is invoked when color is set\n     */\n    __setBgOverlayColor: function (property, color, callback) {\n      this[property] = color;\n\n      this._initGradient(color, property);\n\n      this._initPattern(color, property, callback);\n\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _createCanvasElement: function () {\n      var element = createCanvasElement();\n\n      if (!element) {\n        throw CANVAS_INIT_ERROR;\n      }\n\n      if (!element.style) {\n        element.style = {};\n      }\n\n      if (typeof element.getContext === 'undefined') {\n        throw CANVAS_INIT_ERROR;\n      }\n\n      return element;\n    },\n\n    /**\n     * @private\n     * @param {Object} [options] Options object\n     */\n    _initOptions: function (options) {\n      var lowerCanvasEl = this.lowerCanvasEl;\n\n      this._setOptions(options);\n\n      this.width = this.width || parseInt(lowerCanvasEl.width, 10) || 0;\n      this.height = this.height || parseInt(lowerCanvasEl.height, 10) || 0;\n\n      if (!this.lowerCanvasEl.style) {\n        return;\n      }\n\n      lowerCanvasEl.width = this.width;\n      lowerCanvasEl.height = this.height;\n      lowerCanvasEl.style.width = this.width + 'px';\n      lowerCanvasEl.style.height = this.height + 'px';\n      this.viewportTransform = this.viewportTransform.slice();\n    },\n\n    /**\n     * Creates a bottom canvas\n     * @private\n     * @param {HTMLElement} [canvasEl]\n     */\n    _createLowerCanvas: function (canvasEl) {\n      // canvasEl === 'HTMLCanvasElement' does not work on jsdom/node\n      if (canvasEl && canvasEl.getContext) {\n        this.lowerCanvasEl = canvasEl;\n      } else {\n        this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement();\n      }\n\n      fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas');\n\n      if (this.interactive) {\n        this._applyCanvasStyle(this.lowerCanvasEl);\n      }\n\n      this.contextContainer = this.lowerCanvasEl.getContext('2d');\n    },\n\n    /**\n     * Returns canvas width (in px)\n     * @return {Number}\n     */\n    getWidth: function () {\n      return this.width;\n    },\n\n    /**\n     * Returns canvas height (in px)\n     * @return {Number}\n     */\n    getHeight: function () {\n      return this.height;\n    },\n\n    /**\n     * Sets width of this canvas instance\n     * @param {Number|String} value                         Value to set width to\n     * @param {Object}        [options]                     Options object\n     * @param {Boolean}       [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n     * @param {Boolean}       [options.cssOnly=false]       Set the given dimensions only as css dimensions\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    setWidth: function (value, options) {\n      return this.setDimensions({\n        width: value\n      }, options);\n    },\n\n    /**\n     * Sets height of this canvas instance\n     * @param {Number|String} value                         Value to set height to\n     * @param {Object}        [options]                     Options object\n     * @param {Boolean}       [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n     * @param {Boolean}       [options.cssOnly=false]       Set the given dimensions only as css dimensions\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    setHeight: function (value, options) {\n      return this.setDimensions({\n        height: value\n      }, options);\n    },\n\n    /**\n     * Sets dimensions (width, height) of this canvas instance. when options.cssOnly flag active you should also supply the unit of measure (px/%/em)\n     * @param {Object}        dimensions                    Object with width/height properties\n     * @param {Number|String} [dimensions.width]            Width of canvas element\n     * @param {Number|String} [dimensions.height]           Height of canvas element\n     * @param {Object}        [options]                     Options object\n     * @param {Boolean}       [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n     * @param {Boolean}       [options.cssOnly=false]       Set the given dimensions only as css dimensions\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    setDimensions: function (dimensions, options) {\n      var cssValue;\n      options = options || {};\n\n      for (var prop in dimensions) {\n        cssValue = dimensions[prop];\n\n        if (!options.cssOnly) {\n          this._setBackstoreDimension(prop, dimensions[prop]);\n\n          cssValue += 'px';\n          this.hasLostContext = true;\n        }\n\n        if (!options.backstoreOnly) {\n          this._setCssDimension(prop, cssValue);\n        }\n      }\n\n      if (this._isCurrentlyDrawing) {\n        this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles();\n      }\n\n      this._initRetinaScaling();\n\n      this.calcOffset();\n\n      if (!options.cssOnly) {\n        this.requestRenderAll();\n      }\n\n      return this;\n    },\n\n    /**\n     * Helper for setting width/height\n     * @private\n     * @param {String} prop property (width|height)\n     * @param {Number} value value to set property to\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    _setBackstoreDimension: function (prop, value) {\n      this.lowerCanvasEl[prop] = value;\n\n      if (this.upperCanvasEl) {\n        this.upperCanvasEl[prop] = value;\n      }\n\n      if (this.cacheCanvasEl) {\n        this.cacheCanvasEl[prop] = value;\n      }\n\n      this[prop] = value;\n      return this;\n    },\n\n    /**\n     * Helper for setting css width/height\n     * @private\n     * @param {String} prop property (width|height)\n     * @param {String} value value to set property to\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    _setCssDimension: function (prop, value) {\n      this.lowerCanvasEl.style[prop] = value;\n\n      if (this.upperCanvasEl) {\n        this.upperCanvasEl.style[prop] = value;\n      }\n\n      if (this.wrapperEl) {\n        this.wrapperEl.style[prop] = value;\n      }\n\n      return this;\n    },\n\n    /**\n     * Returns canvas zoom level\n     * @return {Number}\n     */\n    getZoom: function () {\n      return this.viewportTransform[0];\n    },\n\n    /**\n     * Sets viewport transform of this canvas instance\n     * @param {Array} vpt the transform in the form of context.transform\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    setViewportTransform: function (vpt) {\n      var activeObject = this._activeObject,\n          object,\n          i,\n          len;\n      this.viewportTransform = vpt;\n\n      for (i = 0, len = this._objects.length; i < len; i++) {\n        object = this._objects[i];\n        object.group || object.setCoords(true);\n      }\n\n      if (activeObject) {\n        activeObject.setCoords();\n      }\n\n      this.calcViewportBoundaries();\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * Sets zoom level of this canvas instance, zoom centered around point\n     * @param {fabric.Point} point to zoom with respect to\n     * @param {Number} value to set zoom to, less than 1 zooms out\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    zoomToPoint: function (point, value) {\n      // TODO: just change the scale, preserve other transformations\n      var before = point,\n          vpt = this.viewportTransform.slice(0);\n      point = transformPoint(point, invertTransform(this.viewportTransform));\n      vpt[0] = value;\n      vpt[3] = value;\n      var after = transformPoint(point, vpt);\n      vpt[4] += before.x - after.x;\n      vpt[5] += before.y - after.y;\n      return this.setViewportTransform(vpt);\n    },\n\n    /**\n     * Sets zoom level of this canvas instance\n     * @param {Number} value to set zoom to, less than 1 zooms out\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    setZoom: function (value) {\n      this.zoomToPoint(new fabric.Point(0, 0), value);\n      return this;\n    },\n\n    /**\n     * Pan viewport so as to place point at top left corner of canvas\n     * @param {fabric.Point} point to move to\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    absolutePan: function (point) {\n      var vpt = this.viewportTransform.slice(0);\n      vpt[4] = -point.x;\n      vpt[5] = -point.y;\n      return this.setViewportTransform(vpt);\n    },\n\n    /**\n     * Pans viewpoint relatively\n     * @param {fabric.Point} point (position vector) to move by\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    relativePan: function (point) {\n      return this.absolutePan(new fabric.Point(-point.x - this.viewportTransform[4], -point.y - this.viewportTransform[5]));\n    },\n\n    /**\n     * Returns &lt;canvas> element corresponding to this instance\n     * @return {HTMLCanvasElement}\n     */\n    getElement: function () {\n      return this.lowerCanvasEl;\n    },\n\n    /**\n     * @private\n     * @param {fabric.Object} obj Object that was added\n     */\n    _onObjectAdded: function (obj) {\n      this.stateful && obj.setupState();\n\n      obj._set('canvas', this);\n\n      obj.setCoords();\n      this.fire('object:added', {\n        target: obj\n      });\n      obj.fire('added');\n    },\n\n    /**\n     * @private\n     * @param {fabric.Object} obj Object that was removed\n     */\n    _onObjectRemoved: function (obj) {\n      this.fire('object:removed', {\n        target: obj\n      });\n      obj.fire('removed');\n      delete obj.canvas;\n    },\n\n    /**\n     * Clears specified context of canvas element\n     * @param {CanvasRenderingContext2D} ctx Context to clear\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    clearContext: function (ctx) {\n      ctx.clearRect(0, 0, this.width, this.height);\n      return this;\n    },\n\n    /**\n     * Returns context of canvas where objects are drawn\n     * @return {CanvasRenderingContext2D}\n     */\n    getContext: function () {\n      return this.contextContainer;\n    },\n\n    /**\n     * Clears all contexts (background, main, top) of an instance\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    clear: function () {\n      this._objects.length = 0;\n      this.backgroundImage = null;\n      this.overlayImage = null;\n      this.backgroundColor = '';\n      this.overlayColor = '';\n\n      if (this._hasITextHandlers) {\n        this.off('mouse:up', this._mouseUpITextHandler);\n        this._iTextInstances = null;\n        this._hasITextHandlers = false;\n      }\n\n      this.clearContext(this.contextContainer);\n      this.fire('canvas:cleared');\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * Renders the canvas\n     * @return {fabric.Canvas} instance\n     * @chainable\n     */\n    renderAll: function () {\n      var canvasToDrawOn = this.contextContainer;\n      this.renderCanvas(canvasToDrawOn, this._objects);\n      return this;\n    },\n\n    /**\n     * Function created to be instance bound at initialization\n     * used in requestAnimationFrame rendering\n     * Let the fabricJS call it. If you call it manually you could have more\n     * animationFrame stacking on to of each other\n     * for an imperative rendering, use canvas.renderAll\n     * @private\n     * @return {fabric.Canvas} instance\n     * @chainable\n     */\n    renderAndReset: function () {\n      this.isRendering = 0;\n      this.renderAll();\n    },\n\n    /**\n     * Append a renderAll request to next animation frame.\n     * unless one is already in progress, in that case nothing is done\n     * a boolean flag will avoid appending more.\n     * @return {fabric.Canvas} instance\n     * @chainable\n     */\n    requestRenderAll: function () {\n      if (!this.isRendering) {\n        this.isRendering = fabric.util.requestAnimFrame(this.renderAndResetBound);\n      }\n\n      return this;\n    },\n\n    /**\n     * Calculate the position of the 4 corner of canvas with current viewportTransform.\n     * helps to determinate when an object is in the current rendering viewport using\n     * object absolute coordinates ( aCoords )\n     * @return {Object} points.tl\n     * @chainable\n     */\n    calcViewportBoundaries: function () {\n      var points = {},\n          width = this.width,\n          height = this.height,\n          iVpt = invertTransform(this.viewportTransform);\n      points.tl = transformPoint({\n        x: 0,\n        y: 0\n      }, iVpt);\n      points.br = transformPoint({\n        x: width,\n        y: height\n      }, iVpt);\n      points.tr = new fabric.Point(points.br.x, points.tl.y);\n      points.bl = new fabric.Point(points.tl.x, points.br.y);\n      this.vptCoords = points;\n      return points;\n    },\n    cancelRequestedRender: function () {\n      if (this.isRendering) {\n        fabric.util.cancelAnimFrame(this.isRendering);\n        this.isRendering = 0;\n      }\n    },\n\n    /**\n     * Renders background, objects, overlay and controls.\n     * @param {CanvasRenderingContext2D} ctx\n     * @param {Array} objects to render\n     * @return {fabric.Canvas} instance\n     * @chainable\n     */\n    renderCanvas: function (ctx, objects) {\n      var v = this.viewportTransform,\n          path = this.clipPath;\n      this.cancelRequestedRender();\n      this.calcViewportBoundaries();\n      this.clearContext(ctx);\n      fabric.util.setImageSmoothing(ctx, this.imageSmoothingEnabled);\n      this.fire('before:render', {\n        ctx: ctx\n      });\n\n      this._renderBackground(ctx);\n\n      ctx.save(); //apply viewport transform once for all rendering process\n\n      ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n\n      this._renderObjects(ctx, objects);\n\n      ctx.restore();\n\n      if (!this.controlsAboveOverlay && this.interactive) {\n        this.drawControls(ctx);\n      }\n\n      if (path) {\n        path.canvas = this; // needed to setup a couple of variables\n\n        path.shouldCache();\n        path._transformDone = true;\n        path.renderCache({\n          forClipping: true\n        });\n        this.drawClipPathOnCanvas(ctx);\n      }\n\n      this._renderOverlay(ctx);\n\n      if (this.controlsAboveOverlay && this.interactive) {\n        this.drawControls(ctx);\n      }\n\n      this.fire('after:render', {\n        ctx: ctx\n      });\n    },\n\n    /**\n     * Paint the cached clipPath on the lowerCanvasEl\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    drawClipPathOnCanvas: function (ctx) {\n      var v = this.viewportTransform,\n          path = this.clipPath;\n      ctx.save();\n      ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); // DEBUG: uncomment this line, comment the following\n      // ctx.globalAlpha = 0.4;\n\n      ctx.globalCompositeOperation = 'destination-in';\n      path.transform(ctx);\n      ctx.scale(1 / path.zoomX, 1 / path.zoomY);\n      ctx.drawImage(path._cacheCanvas, -path.cacheTranslationX, -path.cacheTranslationY);\n      ctx.restore();\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Array} objects to render\n     */\n    _renderObjects: function (ctx, objects) {\n      var i, len;\n\n      for (i = 0, len = objects.length; i < len; ++i) {\n        objects[i] && objects[i].render(ctx);\n      }\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {string} property 'background' or 'overlay'\n     */\n    _renderBackgroundOrOverlay: function (ctx, property) {\n      var fill = this[property + 'Color'],\n          object = this[property + 'Image'],\n          v = this.viewportTransform,\n          needsVpt = this[property + 'Vpt'];\n\n      if (!fill && !object) {\n        return;\n      }\n\n      if (fill) {\n        ctx.save();\n        ctx.beginPath();\n        ctx.moveTo(0, 0);\n        ctx.lineTo(this.width, 0);\n        ctx.lineTo(this.width, this.height);\n        ctx.lineTo(0, this.height);\n        ctx.closePath();\n        ctx.fillStyle = fill.toLive ? fill.toLive(ctx, this) : fill;\n\n        if (needsVpt) {\n          ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n        }\n\n        ctx.transform(1, 0, 0, 1, fill.offsetX || 0, fill.offsetY || 0);\n        var m = fill.gradientTransform || fill.patternTransform;\n        m && ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\n        ctx.fill();\n        ctx.restore();\n      }\n\n      if (object) {\n        ctx.save();\n\n        if (needsVpt) {\n          ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n        }\n\n        object.render(ctx);\n        ctx.restore();\n      }\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderBackground: function (ctx) {\n      this._renderBackgroundOrOverlay(ctx, 'background');\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderOverlay: function (ctx) {\n      this._renderBackgroundOrOverlay(ctx, 'overlay');\n    },\n\n    /**\n     * Returns coordinates of a center of canvas.\n     * Returned value is an object with top and left properties\n     * @return {Object} object with \"top\" and \"left\" number values\n     */\n    getCenter: function () {\n      return {\n        top: this.height / 2,\n        left: this.width / 2\n      };\n    },\n\n    /**\n     * Centers object horizontally in the canvas\n     * @param {fabric.Object} object Object to center horizontally\n     * @return {fabric.Canvas} thisArg\n     */\n    centerObjectH: function (object) {\n      return this._centerObject(object, new fabric.Point(this.getCenter().left, object.getCenterPoint().y));\n    },\n\n    /**\n     * Centers object vertically in the canvas\n     * @param {fabric.Object} object Object to center vertically\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    centerObjectV: function (object) {\n      return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenter().top));\n    },\n\n    /**\n     * Centers object vertically and horizontally in the canvas\n     * @param {fabric.Object} object Object to center vertically and horizontally\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    centerObject: function (object) {\n      var center = this.getCenter();\n      return this._centerObject(object, new fabric.Point(center.left, center.top));\n    },\n\n    /**\n     * Centers object vertically and horizontally in the viewport\n     * @param {fabric.Object} object Object to center vertically and horizontally\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    viewportCenterObject: function (object) {\n      var vpCenter = this.getVpCenter();\n      return this._centerObject(object, vpCenter);\n    },\n\n    /**\n     * Centers object horizontally in the viewport, object.top is unchanged\n     * @param {fabric.Object} object Object to center vertically and horizontally\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    viewportCenterObjectH: function (object) {\n      var vpCenter = this.getVpCenter();\n\n      this._centerObject(object, new fabric.Point(vpCenter.x, object.getCenterPoint().y));\n\n      return this;\n    },\n\n    /**\n     * Centers object Vertically in the viewport, object.top is unchanged\n     * @param {fabric.Object} object Object to center vertically and horizontally\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    viewportCenterObjectV: function (object) {\n      var vpCenter = this.getVpCenter();\n      return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, vpCenter.y));\n    },\n\n    /**\n     * Calculate the point in canvas that correspond to the center of actual viewport.\n     * @return {fabric.Point} vpCenter, viewport center\n     * @chainable\n     */\n    getVpCenter: function () {\n      var center = this.getCenter(),\n          iVpt = invertTransform(this.viewportTransform);\n      return transformPoint({\n        x: center.left,\n        y: center.top\n      }, iVpt);\n    },\n\n    /**\n     * @private\n     * @param {fabric.Object} object Object to center\n     * @param {fabric.Point} center Center point\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    _centerObject: function (object, center) {\n      object.setPositionByOrigin(center, 'center', 'center');\n      object.setCoords();\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * Returs dataless JSON representation of canvas\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {String} json string\n     */\n    toDatalessJSON: function (propertiesToInclude) {\n      return this.toDatalessObject(propertiesToInclude);\n    },\n\n    /**\n     * Returns object representation of canvas\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function (propertiesToInclude) {\n      return this._toObjectMethod('toObject', propertiesToInclude);\n    },\n\n    /**\n     * Returns dataless object representation of canvas\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toDatalessObject: function (propertiesToInclude) {\n      return this._toObjectMethod('toDatalessObject', propertiesToInclude);\n    },\n\n    /**\n     * @private\n     */\n    _toObjectMethod: function (methodName, propertiesToInclude) {\n      var clipPath = this.clipPath,\n          data = {\n        version: fabric.version,\n        objects: this._toObjects(methodName, propertiesToInclude)\n      };\n\n      if (clipPath) {\n        data.clipPath = this._toObject(this.clipPath, methodName, propertiesToInclude);\n      }\n\n      extend(data, this.__serializeBgOverlay(methodName, propertiesToInclude));\n      fabric.util.populateWithProperties(this, data, propertiesToInclude);\n      return data;\n    },\n\n    /**\n     * @private\n     */\n    _toObjects: function (methodName, propertiesToInclude) {\n      return this._objects.filter(function (object) {\n        return !object.excludeFromExport;\n      }).map(function (instance) {\n        return this._toObject(instance, methodName, propertiesToInclude);\n      }, this);\n    },\n\n    /**\n     * @private\n     */\n    _toObject: function (instance, methodName, propertiesToInclude) {\n      var originalValue;\n\n      if (!this.includeDefaultValues) {\n        originalValue = instance.includeDefaultValues;\n        instance.includeDefaultValues = false;\n      }\n\n      var object = instance[methodName](propertiesToInclude);\n\n      if (!this.includeDefaultValues) {\n        instance.includeDefaultValues = originalValue;\n      }\n\n      return object;\n    },\n\n    /**\n     * @private\n     */\n    __serializeBgOverlay: function (methodName, propertiesToInclude) {\n      var data = {},\n          bgImage = this.backgroundImage,\n          overlay = this.overlayImage;\n\n      if (this.backgroundColor) {\n        data.background = this.backgroundColor.toObject ? this.backgroundColor.toObject(propertiesToInclude) : this.backgroundColor;\n      }\n\n      if (this.overlayColor) {\n        data.overlay = this.overlayColor.toObject ? this.overlayColor.toObject(propertiesToInclude) : this.overlayColor;\n      }\n\n      if (bgImage && !bgImage.excludeFromExport) {\n        data.backgroundImage = this._toObject(bgImage, methodName, propertiesToInclude);\n      }\n\n      if (overlay && !overlay.excludeFromExport) {\n        data.overlayImage = this._toObject(overlay, methodName, propertiesToInclude);\n      }\n\n      return data;\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * When true, getSvgTransform() will apply the StaticCanvas.viewportTransform to the SVG transformation. When true,\n     * a zoomed canvas will then produce zoomed SVG output.\n     * @type Boolean\n     * @default\n     */\n    svgViewportTransformation: true,\n\n    /**\n     * Returns SVG representation of canvas\n     * @function\n     * @param {Object} [options] Options object for SVG output\n     * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included\n     * @param {Object} [options.viewBox] SVG viewbox object\n     * @param {Number} [options.viewBox.x] x-cooridnate of viewbox\n     * @param {Number} [options.viewBox.y] y-coordinate of viewbox\n     * @param {Number} [options.viewBox.width] Width of viewbox\n     * @param {Number} [options.viewBox.height] Height of viewbox\n     * @param {String} [options.encoding=UTF-8] Encoding of SVG output\n     * @param {String} [options.width] desired width of svg with or without units\n     * @param {String} [options.height] desired height of svg with or without units\n     * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation.\n     * @return {String} SVG string\n     * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}\n     * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo}\n     * @example <caption>Normal SVG output</caption>\n     * var svg = canvas.toSVG();\n     * @example <caption>SVG output without preamble (without &lt;?xml ../>)</caption>\n     * var svg = canvas.toSVG({suppressPreamble: true});\n     * @example <caption>SVG output with viewBox attribute</caption>\n     * var svg = canvas.toSVG({\n     *   viewBox: {\n     *     x: 100,\n     *     y: 100,\n     *     width: 200,\n     *     height: 300\n     *   }\n     * });\n     * @example <caption>SVG output with different encoding (default: UTF-8)</caption>\n     * var svg = canvas.toSVG({encoding: 'ISO-8859-1'});\n     * @example <caption>Modify SVG output with reviver function</caption>\n     * var svg = canvas.toSVG(null, function(svg) {\n     *   return svg.replace('stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; ', '');\n     * });\n     */\n    toSVG: function (options, reviver) {\n      options || (options = {});\n      options.reviver = reviver;\n      var markup = [];\n\n      this._setSVGPreamble(markup, options);\n\n      this._setSVGHeader(markup, options);\n\n      if (this.clipPath) {\n        markup.push('<g clip-path=\"url(#' + this.clipPath.clipPathId + ')\" >\\n');\n      }\n\n      this._setSVGBgOverlayColor(markup, 'background');\n\n      this._setSVGBgOverlayImage(markup, 'backgroundImage', reviver);\n\n      this._setSVGObjects(markup, reviver);\n\n      if (this.clipPath) {\n        markup.push('</g>\\n');\n      }\n\n      this._setSVGBgOverlayColor(markup, 'overlay');\n\n      this._setSVGBgOverlayImage(markup, 'overlayImage', reviver);\n\n      markup.push('</svg>');\n      return markup.join('');\n    },\n\n    /**\n     * @private\n     */\n    _setSVGPreamble: function (markup, options) {\n      if (options.suppressPreamble) {\n        return;\n      }\n\n      markup.push('<?xml version=\"1.0\" encoding=\"', options.encoding || 'UTF-8', '\" standalone=\"no\" ?>\\n', '<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ', '\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\\n');\n    },\n\n    /**\n     * @private\n     */\n    _setSVGHeader: function (markup, options) {\n      var width = options.width || this.width,\n          height = options.height || this.height,\n          vpt,\n          viewBox = 'viewBox=\"0 0 ' + this.width + ' ' + this.height + '\" ',\n          NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n\n      if (options.viewBox) {\n        viewBox = 'viewBox=\"' + options.viewBox.x + ' ' + options.viewBox.y + ' ' + options.viewBox.width + ' ' + options.viewBox.height + '\" ';\n      } else {\n        if (this.svgViewportTransformation) {\n          vpt = this.viewportTransform;\n          viewBox = 'viewBox=\"' + toFixed(-vpt[4] / vpt[0], NUM_FRACTION_DIGITS) + ' ' + toFixed(-vpt[5] / vpt[3], NUM_FRACTION_DIGITS) + ' ' + toFixed(this.width / vpt[0], NUM_FRACTION_DIGITS) + ' ' + toFixed(this.height / vpt[3], NUM_FRACTION_DIGITS) + '\" ';\n        }\n      }\n\n      markup.push('<svg ', 'xmlns=\"http://www.w3.org/2000/svg\" ', 'xmlns:xlink=\"http://www.w3.org/1999/xlink\" ', 'version=\"1.1\" ', 'width=\"', width, '\" ', 'height=\"', height, '\" ', viewBox, 'xml:space=\"preserve\">\\n', '<desc>Created with Fabric.js ', fabric.version, '</desc>\\n', '<defs>\\n', this.createSVGFontFacesMarkup(), this.createSVGRefElementsMarkup(), this.createSVGClipPathMarkup(options), '</defs>\\n');\n    },\n    createSVGClipPathMarkup: function (options) {\n      var clipPath = this.clipPath;\n\n      if (clipPath) {\n        clipPath.clipPathId = 'CLIPPATH_' + fabric.Object.__uid++;\n        return '<clipPath id=\"' + clipPath.clipPathId + '\" >\\n' + this.clipPath.toClipPathSVG(options.reviver) + '</clipPath>\\n';\n      }\n\n      return '';\n    },\n\n    /**\n     * Creates markup containing SVG referenced elements like patterns, gradients etc.\n     * @return {String}\n     */\n    createSVGRefElementsMarkup: function () {\n      var _this = this,\n          markup = ['background', 'overlay'].map(function (prop) {\n        var fill = _this[prop + 'Color'];\n\n        if (fill && fill.toLive) {\n          var shouldTransform = _this[prop + 'Vpt'],\n              vpt = _this.viewportTransform,\n              object = {\n            width: _this.width / (shouldTransform ? vpt[0] : 1),\n            height: _this.height / (shouldTransform ? vpt[3] : 1)\n          };\n          return fill.toSVG(object, {\n            additionalTransform: shouldTransform ? fabric.util.matrixToSVG(vpt) : ''\n          });\n        }\n      });\n\n      return markup.join('');\n    },\n\n    /**\n     * Creates markup containing SVG font faces,\n     * font URLs for font faces must be collected by developers\n     * and are not extracted from the DOM by fabricjs\n     * @param {Array} objects Array of fabric objects\n     * @return {String}\n     */\n    createSVGFontFacesMarkup: function () {\n      var markup = '',\n          fontList = {},\n          obj,\n          fontFamily,\n          style,\n          row,\n          rowIndex,\n          _char,\n          charIndex,\n          i,\n          len,\n          fontPaths = fabric.fontPaths,\n          objects = [];\n\n      this._objects.forEach(function add(object) {\n        objects.push(object);\n\n        if (object._objects) {\n          object._objects.forEach(add);\n        }\n      });\n\n      for (i = 0, len = objects.length; i < len; i++) {\n        obj = objects[i];\n        fontFamily = obj.fontFamily;\n\n        if (obj.type.indexOf('text') === -1 || fontList[fontFamily] || !fontPaths[fontFamily]) {\n          continue;\n        }\n\n        fontList[fontFamily] = true;\n\n        if (!obj.styles) {\n          continue;\n        }\n\n        style = obj.styles;\n\n        for (rowIndex in style) {\n          row = style[rowIndex];\n\n          for (charIndex in row) {\n            _char = row[charIndex];\n            fontFamily = _char.fontFamily;\n\n            if (!fontList[fontFamily] && fontPaths[fontFamily]) {\n              fontList[fontFamily] = true;\n            }\n          }\n        }\n      }\n\n      for (var j in fontList) {\n        markup += ['\\t\\t@font-face {\\n', '\\t\\t\\tfont-family: \\'', j, '\\';\\n', '\\t\\t\\tsrc: url(\\'', fontPaths[j], '\\');\\n', '\\t\\t}\\n'].join('');\n      }\n\n      if (markup) {\n        markup = ['\\t<style type=\"text/css\">', '<![CDATA[\\n', markup, ']]>', '</style>\\n'].join('');\n      }\n\n      return markup;\n    },\n\n    /**\n     * @private\n     */\n    _setSVGObjects: function (markup, reviver) {\n      var instance,\n          i,\n          len,\n          objects = this._objects;\n\n      for (i = 0, len = objects.length; i < len; i++) {\n        instance = objects[i];\n\n        if (instance.excludeFromExport) {\n          continue;\n        }\n\n        this._setSVGObject(markup, instance, reviver);\n      }\n    },\n\n    /**\n     * @private\n     */\n    _setSVGObject: function (markup, instance, reviver) {\n      markup.push(instance.toSVG(reviver));\n    },\n\n    /**\n     * @private\n     */\n    _setSVGBgOverlayImage: function (markup, property, reviver) {\n      if (this[property] && !this[property].excludeFromExport && this[property].toSVG) {\n        markup.push(this[property].toSVG(reviver));\n      }\n    },\n\n    /**\n     * @private\n     */\n    _setSVGBgOverlayColor: function (markup, property) {\n      var filler = this[property + 'Color'],\n          vpt = this.viewportTransform,\n          finalWidth = this.width,\n          finalHeight = this.height;\n\n      if (!filler) {\n        return;\n      }\n\n      if (filler.toLive) {\n        var repeat = filler.repeat,\n            iVpt = fabric.util.invertTransform(vpt),\n            shouldInvert = this[property + 'Vpt'],\n            additionalTransform = shouldInvert ? fabric.util.matrixToSVG(iVpt) : '';\n        markup.push('<rect transform=\"' + additionalTransform + ' translate(', finalWidth / 2, ',', finalHeight / 2, ')\"', ' x=\"', filler.offsetX - finalWidth / 2, '\" y=\"', filler.offsetY - finalHeight / 2, '\" ', 'width=\"', repeat === 'repeat-y' || repeat === 'no-repeat' ? filler.source.width : finalWidth, '\" height=\"', repeat === 'repeat-x' || repeat === 'no-repeat' ? filler.source.height : finalHeight, '\" fill=\"url(#SVGID_' + filler.id + ')\"', '></rect>\\n');\n      } else {\n        markup.push('<rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" ', 'fill=\"', filler, '\"', '></rect>\\n');\n      }\n    },\n\n    /* _TO_SVG_END_ */\n\n    /**\n     * Moves an object or the objects of a multiple selection\n     * to the bottom of the stack of drawn objects\n     * @param {fabric.Object} object Object to send to back\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    sendToBack: function (object) {\n      if (!object) {\n        return this;\n      }\n\n      var activeSelection = this._activeObject,\n          i,\n          obj,\n          objs;\n\n      if (object === activeSelection && object.type === 'activeSelection') {\n        objs = activeSelection._objects;\n\n        for (i = objs.length; i--;) {\n          obj = objs[i];\n          removeFromArray(this._objects, obj);\n\n          this._objects.unshift(obj);\n        }\n      } else {\n        removeFromArray(this._objects, object);\n\n        this._objects.unshift(object);\n      }\n\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * Moves an object or the objects of a multiple selection\n     * to the top of the stack of drawn objects\n     * @param {fabric.Object} object Object to send\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    bringToFront: function (object) {\n      if (!object) {\n        return this;\n      }\n\n      var activeSelection = this._activeObject,\n          i,\n          obj,\n          objs;\n\n      if (object === activeSelection && object.type === 'activeSelection') {\n        objs = activeSelection._objects;\n\n        for (i = 0; i < objs.length; i++) {\n          obj = objs[i];\n          removeFromArray(this._objects, obj);\n\n          this._objects.push(obj);\n        }\n      } else {\n        removeFromArray(this._objects, object);\n\n        this._objects.push(object);\n      }\n\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * Moves an object or a selection down in stack of drawn objects\n     * An optional paramter, intersecting allowes to move the object in behind\n     * the first intersecting object. Where intersection is calculated with\n     * bounding box. If no intersection is found, there will not be change in the\n     * stack.\n     * @param {fabric.Object} object Object to send\n     * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    sendBackwards: function (object, intersecting) {\n      if (!object) {\n        return this;\n      }\n\n      var activeSelection = this._activeObject,\n          i,\n          obj,\n          idx,\n          newIdx,\n          objs,\n          objsMoved = 0;\n\n      if (object === activeSelection && object.type === 'activeSelection') {\n        objs = activeSelection._objects;\n\n        for (i = 0; i < objs.length; i++) {\n          obj = objs[i];\n          idx = this._objects.indexOf(obj);\n\n          if (idx > 0 + objsMoved) {\n            newIdx = idx - 1;\n            removeFromArray(this._objects, obj);\n\n            this._objects.splice(newIdx, 0, obj);\n          }\n\n          objsMoved++;\n        }\n      } else {\n        idx = this._objects.indexOf(object);\n\n        if (idx !== 0) {\n          // if object is not on the bottom of stack\n          newIdx = this._findNewLowerIndex(object, idx, intersecting);\n          removeFromArray(this._objects, object);\n\n          this._objects.splice(newIdx, 0, object);\n        }\n      }\n\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _findNewLowerIndex: function (object, idx, intersecting) {\n      var newIdx, i;\n\n      if (intersecting) {\n        newIdx = idx; // traverse down the stack looking for the nearest intersecting object\n\n        for (i = idx - 1; i >= 0; --i) {\n          var isIntersecting = object.intersectsWithObject(this._objects[i]) || object.isContainedWithinObject(this._objects[i]) || this._objects[i].isContainedWithinObject(object);\n\n          if (isIntersecting) {\n            newIdx = i;\n            break;\n          }\n        }\n      } else {\n        newIdx = idx - 1;\n      }\n\n      return newIdx;\n    },\n\n    /**\n     * Moves an object or a selection up in stack of drawn objects\n     * An optional paramter, intersecting allowes to move the object in front\n     * of the first intersecting object. Where intersection is calculated with\n     * bounding box. If no intersection is found, there will not be change in the\n     * stack.\n     * @param {fabric.Object} object Object to send\n     * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    bringForward: function (object, intersecting) {\n      if (!object) {\n        return this;\n      }\n\n      var activeSelection = this._activeObject,\n          i,\n          obj,\n          idx,\n          newIdx,\n          objs,\n          objsMoved = 0;\n\n      if (object === activeSelection && object.type === 'activeSelection') {\n        objs = activeSelection._objects;\n\n        for (i = objs.length; i--;) {\n          obj = objs[i];\n          idx = this._objects.indexOf(obj);\n\n          if (idx < this._objects.length - 1 - objsMoved) {\n            newIdx = idx + 1;\n            removeFromArray(this._objects, obj);\n\n            this._objects.splice(newIdx, 0, obj);\n          }\n\n          objsMoved++;\n        }\n      } else {\n        idx = this._objects.indexOf(object);\n\n        if (idx !== this._objects.length - 1) {\n          // if object is not on top of stack (last item in an array)\n          newIdx = this._findNewUpperIndex(object, idx, intersecting);\n          removeFromArray(this._objects, object);\n\n          this._objects.splice(newIdx, 0, object);\n        }\n      }\n\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _findNewUpperIndex: function (object, idx, intersecting) {\n      var newIdx, i, len;\n\n      if (intersecting) {\n        newIdx = idx; // traverse up the stack looking for the nearest intersecting object\n\n        for (i = idx + 1, len = this._objects.length; i < len; ++i) {\n          var isIntersecting = object.intersectsWithObject(this._objects[i]) || object.isContainedWithinObject(this._objects[i]) || this._objects[i].isContainedWithinObject(object);\n\n          if (isIntersecting) {\n            newIdx = i;\n            break;\n          }\n        }\n      } else {\n        newIdx = idx + 1;\n      }\n\n      return newIdx;\n    },\n\n    /**\n     * Moves an object to specified level in stack of drawn objects\n     * @param {fabric.Object} object Object to send\n     * @param {Number} index Position to move to\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    moveTo: function (object, index) {\n      removeFromArray(this._objects, object);\n\n      this._objects.splice(index, 0, object);\n\n      return this.renderOnAddRemove && this.requestRenderAll();\n    },\n\n    /**\n     * Clears a canvas element and dispose objects\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    dispose: function () {\n      // cancel eventually ongoing renders\n      if (this.isRendering) {\n        fabric.util.cancelAnimFrame(this.isRendering);\n        this.isRendering = 0;\n      }\n\n      this.forEachObject(function (object) {\n        object.dispose && object.dispose();\n      });\n      this._objects = [];\n\n      if (this.backgroundImage && this.backgroundImage.dispose) {\n        this.backgroundImage.dispose();\n      }\n\n      this.backgroundImage = null;\n\n      if (this.overlayImage && this.overlayImage.dispose) {\n        this.overlayImage.dispose();\n      }\n\n      this.overlayImage = null;\n      this._iTextInstances = null;\n      this.contextContainer = null;\n      fabric.util.cleanUpJsdomNode(this.lowerCanvasEl);\n      this.lowerCanvasEl = undefined;\n      return this;\n    },\n\n    /**\n     * Returns a string representation of an instance\n     * @return {String} string representation of an instance\n     */\n    toString: function () {\n      return '#<fabric.Canvas (' + this.complexity() + '): ' + '{ objects: ' + this._objects.length + ' }>';\n    }\n  });\n  extend(fabric.StaticCanvas.prototype, fabric.Observable);\n  extend(fabric.StaticCanvas.prototype, fabric.Collection);\n  extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter);\n  extend(fabric.StaticCanvas,\n  /** @lends fabric.StaticCanvas */\n  {\n    /**\n     * @static\n     * @type String\n     * @default\n     */\n    EMPTY_JSON: '{\"objects\": [], \"background\": \"white\"}',\n\n    /**\n     * Provides a way to check support of some of the canvas methods\n     * (either those of HTMLCanvasElement itself, or rendering context)\n     *\n     * @param {String} methodName Method to check support for;\n     *                            Could be one of \"setLineDash\"\n     * @return {Boolean | null} `true` if method is supported (or at least exists),\n     *                          `null` if canvas element or context can not be initialized\n     */\n    supports: function (methodName) {\n      var el = createCanvasElement();\n\n      if (!el || !el.getContext) {\n        return null;\n      }\n\n      var ctx = el.getContext('2d');\n\n      if (!ctx) {\n        return null;\n      }\n\n      switch (methodName) {\n        case 'setLineDash':\n          return typeof ctx.setLineDash !== 'undefined';\n\n        default:\n          return null;\n      }\n    }\n  });\n  /**\n   * Returns JSON representation of canvas\n   * @function\n   * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n   * @return {String} JSON string\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}\n   * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo}\n   * @example <caption>JSON without additional properties</caption>\n   * var json = canvas.toJSON();\n   * @example <caption>JSON with additional properties included</caption>\n   * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY']);\n   * @example <caption>JSON without default values</caption>\n   * canvas.includeDefaultValues = false;\n   * var json = canvas.toJSON();\n   */\n\n  fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject;\n\n  if (fabric.isLikelyNode) {\n    fabric.StaticCanvas.prototype.createPNGStream = function () {\n      var impl = getNodeCanvas(this.lowerCanvasEl);\n      return impl && impl.createPNGStream();\n    };\n\n    fabric.StaticCanvas.prototype.createJPEGStream = function (opts) {\n      var impl = getNodeCanvas(this.lowerCanvasEl);\n      return impl && impl.createJPEGStream(opts);\n    };\n  }\n})();\n/**\n * BaseBrush class\n * @class fabric.BaseBrush\n * @see {@link http://fabricjs.com/freedrawing|Freedrawing demo}\n */\n\n\nfabric.BaseBrush = fabric.util.createClass(\n/** @lends fabric.BaseBrush.prototype */\n{\n  /**\n   * Color of a brush\n   * @type String\n   * @default\n   */\n  color: 'rgb(0, 0, 0)',\n\n  /**\n   * Width of a brush, has to be a Number, no string literals\n   * @type Number\n   * @default\n   */\n  width: 1,\n\n  /**\n   * Shadow object representing shadow of this shape.\n   * <b>Backwards incompatibility note:</b> This property replaces \"shadowColor\" (String), \"shadowOffsetX\" (Number),\n   * \"shadowOffsetY\" (Number) and \"shadowBlur\" (Number) since v1.2.12\n   * @type fabric.Shadow\n   * @default\n   */\n  shadow: null,\n\n  /**\n   * Line endings style of a brush (one of \"butt\", \"round\", \"square\")\n   * @type String\n   * @default\n   */\n  strokeLineCap: 'round',\n\n  /**\n   * Corner style of a brush (one of \"bevel\", \"round\", \"miter\")\n   * @type String\n   * @default\n   */\n  strokeLineJoin: 'round',\n\n  /**\n   * Maximum miter length (used for strokeLineJoin = \"miter\") of a brush's\n   * @type Number\n   * @default\n   */\n  strokeMiterLimit: 10,\n\n  /**\n   * Stroke Dash Array.\n   * @type Array\n   * @default\n   */\n  strokeDashArray: null,\n\n  /**\n   * Sets brush styles\n   * @private\n   */\n  _setBrushStyles: function () {\n    var ctx = this.canvas.contextTop;\n    ctx.strokeStyle = this.color;\n    ctx.lineWidth = this.width;\n    ctx.lineCap = this.strokeLineCap;\n    ctx.miterLimit = this.strokeMiterLimit;\n    ctx.lineJoin = this.strokeLineJoin;\n\n    if (fabric.StaticCanvas.supports('setLineDash')) {\n      ctx.setLineDash(this.strokeDashArray || []);\n    }\n  },\n\n  /**\n   * Sets the transformation on given context\n   * @param {RenderingContext2d} ctx context to render on\n   * @private\n   */\n  _saveAndTransform: function (ctx) {\n    var v = this.canvas.viewportTransform;\n    ctx.save();\n    ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n  },\n\n  /**\n   * Sets brush shadow styles\n   * @private\n   */\n  _setShadow: function () {\n    if (!this.shadow) {\n      return;\n    }\n\n    var canvas = this.canvas,\n        shadow = this.shadow,\n        ctx = canvas.contextTop,\n        zoom = canvas.getZoom();\n\n    if (canvas && canvas._isRetinaScaling()) {\n      zoom *= fabric.devicePixelRatio;\n    }\n\n    ctx.shadowColor = shadow.color;\n    ctx.shadowBlur = shadow.blur * zoom;\n    ctx.shadowOffsetX = shadow.offsetX * zoom;\n    ctx.shadowOffsetY = shadow.offsetY * zoom;\n  },\n  needsFullRender: function () {\n    var color = new fabric.Color(this.color);\n    return color.getAlpha() < 1 || !!this.shadow;\n  },\n\n  /**\n   * Removes brush shadow styles\n   * @private\n   */\n  _resetShadow: function () {\n    var ctx = this.canvas.contextTop;\n    ctx.shadowColor = '';\n    ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;\n  }\n});\n\n(function () {\n  /**\n   * PencilBrush class\n   * @class fabric.PencilBrush\n   * @extends fabric.BaseBrush\n   */\n  fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush,\n  /** @lends fabric.PencilBrush.prototype */\n  {\n    /**\n     * Discard points that are less than `decimate` pixel distant from each other\n     * @type Number\n     * @default 0.4\n     */\n    decimate: 0.4,\n\n    /**\n     * Constructor\n     * @param {fabric.Canvas} canvas\n     * @return {fabric.PencilBrush} Instance of a pencil brush\n     */\n    initialize: function (canvas) {\n      this.canvas = canvas;\n      this._points = [];\n    },\n\n    /**\n     * Invoked inside on mouse down and mouse move\n     * @param {Object} pointer\n     */\n    _drawSegment: function (ctx, p1, p2) {\n      var midPoint = p1.midPointFrom(p2);\n      ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);\n      return midPoint;\n    },\n\n    /**\n     * Inovoked on mouse down\n     * @param {Object} pointer\n     */\n    onMouseDown: function (pointer, options) {\n      if (!this.canvas._isMainEvent(options.e)) {\n        return;\n      }\n\n      this._prepareForDrawing(pointer); // capture coordinates immediately\n      // this allows to draw dots (when movement never occurs)\n\n\n      this._captureDrawingPath(pointer);\n\n      this._render();\n    },\n\n    /**\n     * Inovoked on mouse move\n     * @param {Object} pointer\n     */\n    onMouseMove: function (pointer, options) {\n      if (!this.canvas._isMainEvent(options.e)) {\n        return;\n      }\n\n      if (this._captureDrawingPath(pointer) && this._points.length > 1) {\n        if (this.needsFullRender()) {\n          // redraw curve\n          // clear top canvas\n          this.canvas.clearContext(this.canvas.contextTop);\n\n          this._render();\n        } else {\n          var points = this._points,\n              length = points.length,\n              ctx = this.canvas.contextTop; // draw the curve update\n\n          this._saveAndTransform(ctx);\n\n          if (this.oldEnd) {\n            ctx.beginPath();\n            ctx.moveTo(this.oldEnd.x, this.oldEnd.y);\n          }\n\n          this.oldEnd = this._drawSegment(ctx, points[length - 2], points[length - 1], true);\n          ctx.stroke();\n          ctx.restore();\n        }\n      }\n    },\n\n    /**\n     * Invoked on mouse up\n     */\n    onMouseUp: function (options) {\n      if (!this.canvas._isMainEvent(options.e)) {\n        return true;\n      }\n\n      this.oldEnd = undefined;\n\n      this._finalizeAndAddPath();\n\n      return false;\n    },\n\n    /**\n     * @private\n     * @param {Object} pointer Actual mouse position related to the canvas.\n     */\n    _prepareForDrawing: function (pointer) {\n      var p = new fabric.Point(pointer.x, pointer.y);\n\n      this._reset();\n\n      this._addPoint(p);\n\n      this.canvas.contextTop.moveTo(p.x, p.y);\n    },\n\n    /**\n     * @private\n     * @param {fabric.Point} point Point to be added to points array\n     */\n    _addPoint: function (point) {\n      if (this._points.length > 1 && point.eq(this._points[this._points.length - 1])) {\n        return false;\n      }\n\n      this._points.push(point);\n\n      return true;\n    },\n\n    /**\n     * Clear points array and set contextTop canvas style.\n     * @private\n     */\n    _reset: function () {\n      this._points = [];\n\n      this._setBrushStyles();\n\n      this._setShadow();\n    },\n\n    /**\n     * @private\n     * @param {Object} pointer Actual mouse position related to the canvas.\n     */\n    _captureDrawingPath: function (pointer) {\n      var pointerPoint = new fabric.Point(pointer.x, pointer.y);\n      return this._addPoint(pointerPoint);\n    },\n\n    /**\n     * Draw a smooth path on the topCanvas using quadraticCurveTo\n     * @private\n     */\n    _render: function () {\n      var ctx = this.canvas.contextTop,\n          i,\n          len,\n          p1 = this._points[0],\n          p2 = this._points[1];\n\n      this._saveAndTransform(ctx);\n\n      ctx.beginPath(); //if we only have 2 points in the path and they are the same\n      //it means that the user only clicked the canvas without moving the mouse\n      //then we should be drawing a dot. A path isn't drawn between two identical dots\n      //that's why we set them apart a bit\n\n      if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) {\n        var width = this.width / 1000;\n        p1 = new fabric.Point(p1.x, p1.y);\n        p2 = new fabric.Point(p2.x, p2.y);\n        p1.x -= width;\n        p2.x += width;\n      }\n\n      ctx.moveTo(p1.x, p1.y);\n\n      for (i = 1, len = this._points.length; i < len; i++) {\n        // we pick the point between pi + 1 & pi + 2 as the\n        // end point and p1 as our control point.\n        this._drawSegment(ctx, p1, p2);\n\n        p1 = this._points[i];\n        p2 = this._points[i + 1];\n      } // Draw last line as a straight line while\n      // we wait for the next point to be able to calculate\n      // the bezier control point\n\n\n      ctx.lineTo(p1.x, p1.y);\n      ctx.stroke();\n      ctx.restore();\n    },\n\n    /**\n     * Converts points to SVG path\n     * @param {Array} points Array of points\n     * @return {String} SVG path\n     */\n    convertPointsToSVGPath: function (points) {\n      var path = [],\n          i,\n          width = this.width / 1000,\n          p1 = new fabric.Point(points[0].x, points[0].y),\n          p2 = new fabric.Point(points[1].x, points[1].y),\n          len = points.length,\n          multSignX = 1,\n          multSignY = 0,\n          manyPoints = len > 2;\n\n      if (manyPoints) {\n        multSignX = points[2].x < p2.x ? -1 : points[2].x === p2.x ? 0 : 1;\n        multSignY = points[2].y < p2.y ? -1 : points[2].y === p2.y ? 0 : 1;\n      }\n\n      path.push('M ', p1.x - multSignX * width, ' ', p1.y - multSignY * width, ' ');\n\n      for (i = 1; i < len; i++) {\n        if (!p1.eq(p2)) {\n          var midPoint = p1.midPointFrom(p2); // p1 is our bezier control point\n          // midpoint is our endpoint\n          // start point is p(i-1) value.\n\n          path.push('Q ', p1.x, ' ', p1.y, ' ', midPoint.x, ' ', midPoint.y, ' ');\n        }\n\n        p1 = points[i];\n\n        if (i + 1 < points.length) {\n          p2 = points[i + 1];\n        }\n      }\n\n      if (manyPoints) {\n        multSignX = p1.x > points[i - 2].x ? 1 : p1.x === points[i - 2].x ? 0 : -1;\n        multSignY = p1.y > points[i - 2].y ? 1 : p1.y === points[i - 2].y ? 0 : -1;\n      }\n\n      path.push('L ', p1.x + multSignX * width, ' ', p1.y + multSignY * width);\n      return path;\n    },\n\n    /**\n     * Creates fabric.Path object to add on canvas\n     * @param {String} pathData Path data\n     * @return {fabric.Path} Path to add on canvas\n     */\n    createPath: function (pathData) {\n      var path = new fabric.Path(pathData, {\n        fill: null,\n        stroke: this.color,\n        strokeWidth: this.width,\n        strokeLineCap: this.strokeLineCap,\n        strokeMiterLimit: this.strokeMiterLimit,\n        strokeLineJoin: this.strokeLineJoin,\n        strokeDashArray: this.strokeDashArray\n      });\n\n      if (this.shadow) {\n        this.shadow.affectStroke = true;\n        path.shadow = new fabric.Shadow(this.shadow);\n      }\n\n      return path;\n    },\n\n    /**\n     * Decimate poins array with the decimate value\n     */\n    decimatePoints: function (points, distance) {\n      if (points.length <= 2) {\n        return points;\n      }\n\n      var zoom = this.canvas.getZoom(),\n          adjustedDistance = Math.pow(distance / zoom, 2),\n          i,\n          l = points.length - 1,\n          lastPoint = points[0],\n          newPoints = [lastPoint],\n          cDistance;\n\n      for (i = 1; i < l; i++) {\n        cDistance = Math.pow(lastPoint.x - points[i].x, 2) + Math.pow(lastPoint.y - points[i].y, 2);\n\n        if (cDistance >= adjustedDistance) {\n          lastPoint = points[i];\n          newPoints.push(lastPoint);\n        }\n      }\n\n      if (newPoints.length === 1) {\n        newPoints.push(new fabric.Point(newPoints[0].x, newPoints[0].y));\n      }\n\n      return newPoints;\n    },\n\n    /**\n     * On mouseup after drawing the path on contextTop canvas\n     * we use the points captured to create an new fabric path object\n     * and add it to the fabric canvas.\n     */\n    _finalizeAndAddPath: function () {\n      var ctx = this.canvas.contextTop;\n      ctx.closePath();\n\n      if (this.decimate) {\n        this._points = this.decimatePoints(this._points, this.decimate);\n      }\n\n      var pathData = this.convertPointsToSVGPath(this._points).join('');\n\n      if (pathData === 'M 0 0 Q 0 0 0 0 L 0 0') {\n        // do not create 0 width/height paths, as they are\n        // rendered inconsistently across browsers\n        // Firefox 4, for example, renders a dot,\n        // whereas Chrome 10 renders nothing\n        this.canvas.requestRenderAll();\n        return;\n      }\n\n      var path = this.createPath(pathData);\n      this.canvas.clearContext(this.canvas.contextTop);\n      this.canvas.fire('before:path:created', {\n        path: path\n      });\n      this.canvas.add(path);\n      this.canvas.requestRenderAll();\n      path.setCoords();\n\n      this._resetShadow(); // fire event 'path' created\n\n\n      this.canvas.fire('path:created', {\n        path: path\n      });\n    }\n  });\n})();\n/**\n * CircleBrush class\n * @class fabric.CircleBrush\n */\n\n\nfabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush,\n/** @lends fabric.CircleBrush.prototype */\n{\n  /**\n   * Width of a brush\n   * @type Number\n   * @default\n   */\n  width: 10,\n\n  /**\n   * Constructor\n   * @param {fabric.Canvas} canvas\n   * @return {fabric.CircleBrush} Instance of a circle brush\n   */\n  initialize: function (canvas) {\n    this.canvas = canvas;\n    this.points = [];\n  },\n\n  /**\n   * Invoked inside on mouse down and mouse move\n   * @param {Object} pointer\n   */\n  drawDot: function (pointer) {\n    var point = this.addPoint(pointer),\n        ctx = this.canvas.contextTop;\n\n    this._saveAndTransform(ctx);\n\n    this.dot(ctx, point);\n    ctx.restore();\n  },\n  dot: function (ctx, point) {\n    ctx.fillStyle = point.fill;\n    ctx.beginPath();\n    ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false);\n    ctx.closePath();\n    ctx.fill();\n  },\n\n  /**\n   * Invoked on mouse down\n   */\n  onMouseDown: function (pointer) {\n    this.points.length = 0;\n    this.canvas.clearContext(this.canvas.contextTop);\n\n    this._setShadow();\n\n    this.drawDot(pointer);\n  },\n\n  /**\n   * Render the full state of the brush\n   * @private\n   */\n  _render: function () {\n    var ctx = this.canvas.contextTop,\n        i,\n        len,\n        points = this.points;\n\n    this._saveAndTransform(ctx);\n\n    for (i = 0, len = points.length; i < len; i++) {\n      this.dot(ctx, points[i]);\n    }\n\n    ctx.restore();\n  },\n\n  /**\n   * Invoked on mouse move\n   * @param {Object} pointer\n   */\n  onMouseMove: function (pointer) {\n    if (this.needsFullRender()) {\n      this.canvas.clearContext(this.canvas.contextTop);\n      this.addPoint(pointer);\n\n      this._render();\n    } else {\n      this.drawDot(pointer);\n    }\n  },\n\n  /**\n   * Invoked on mouse up\n   */\n  onMouseUp: function () {\n    var originalRenderOnAddRemove = this.canvas.renderOnAddRemove,\n        i,\n        len;\n    this.canvas.renderOnAddRemove = false;\n    var circles = [];\n\n    for (i = 0, len = this.points.length; i < len; i++) {\n      var point = this.points[i],\n          circle = new fabric.Circle({\n        radius: point.radius,\n        left: point.x,\n        top: point.y,\n        originX: 'center',\n        originY: 'center',\n        fill: point.fill\n      });\n      this.shadow && (circle.shadow = new fabric.Shadow(this.shadow));\n      circles.push(circle);\n    }\n\n    var group = new fabric.Group(circles);\n    group.canvas = this.canvas;\n    this.canvas.fire('before:path:created', {\n      path: group\n    });\n    this.canvas.add(group);\n    this.canvas.fire('path:created', {\n      path: group\n    });\n    this.canvas.clearContext(this.canvas.contextTop);\n\n    this._resetShadow();\n\n    this.canvas.renderOnAddRemove = originalRenderOnAddRemove;\n    this.canvas.requestRenderAll();\n  },\n\n  /**\n   * @param {Object} pointer\n   * @return {fabric.Point} Just added pointer point\n   */\n  addPoint: function (pointer) {\n    var pointerPoint = new fabric.Point(pointer.x, pointer.y),\n        circleRadius = fabric.util.getRandomInt(Math.max(0, this.width - 20), this.width + 20) / 2,\n        circleColor = new fabric.Color(this.color).setAlpha(fabric.util.getRandomInt(0, 100) / 100).toRgba();\n    pointerPoint.radius = circleRadius;\n    pointerPoint.fill = circleColor;\n    this.points.push(pointerPoint);\n    return pointerPoint;\n  }\n});\n/**\n * SprayBrush class\n * @class fabric.SprayBrush\n */\n\nfabric.SprayBrush = fabric.util.createClass(fabric.BaseBrush,\n/** @lends fabric.SprayBrush.prototype */\n{\n  /**\n   * Width of a spray\n   * @type Number\n   * @default\n   */\n  width: 10,\n\n  /**\n   * Density of a spray (number of dots per chunk)\n   * @type Number\n   * @default\n   */\n  density: 20,\n\n  /**\n   * Width of spray dots\n   * @type Number\n   * @default\n   */\n  dotWidth: 1,\n\n  /**\n   * Width variance of spray dots\n   * @type Number\n   * @default\n   */\n  dotWidthVariance: 1,\n\n  /**\n   * Whether opacity of a dot should be random\n   * @type Boolean\n   * @default\n   */\n  randomOpacity: false,\n\n  /**\n   * Whether overlapping dots (rectangles) should be removed (for performance reasons)\n   * @type Boolean\n   * @default\n   */\n  optimizeOverlapping: true,\n\n  /**\n   * Constructor\n   * @param {fabric.Canvas} canvas\n   * @return {fabric.SprayBrush} Instance of a spray brush\n   */\n  initialize: function (canvas) {\n    this.canvas = canvas;\n    this.sprayChunks = [];\n  },\n\n  /**\n   * Invoked on mouse down\n   * @param {Object} pointer\n   */\n  onMouseDown: function (pointer) {\n    this.sprayChunks.length = 0;\n    this.canvas.clearContext(this.canvas.contextTop);\n\n    this._setShadow();\n\n    this.addSprayChunk(pointer);\n    this.render(this.sprayChunkPoints);\n  },\n\n  /**\n   * Invoked on mouse move\n   * @param {Object} pointer\n   */\n  onMouseMove: function (pointer) {\n    this.addSprayChunk(pointer);\n    this.render(this.sprayChunkPoints);\n  },\n\n  /**\n   * Invoked on mouse up\n   */\n  onMouseUp: function () {\n    var originalRenderOnAddRemove = this.canvas.renderOnAddRemove;\n    this.canvas.renderOnAddRemove = false;\n    var rects = [];\n\n    for (var i = 0, ilen = this.sprayChunks.length; i < ilen; i++) {\n      var sprayChunk = this.sprayChunks[i];\n\n      for (var j = 0, jlen = sprayChunk.length; j < jlen; j++) {\n        var rect = new fabric.Rect({\n          width: sprayChunk[j].width,\n          height: sprayChunk[j].width,\n          left: sprayChunk[j].x + 1,\n          top: sprayChunk[j].y + 1,\n          originX: 'center',\n          originY: 'center',\n          fill: this.color\n        });\n        rects.push(rect);\n      }\n    }\n\n    if (this.optimizeOverlapping) {\n      rects = this._getOptimizedRects(rects);\n    }\n\n    var group = new fabric.Group(rects);\n    this.shadow && group.set('shadow', new fabric.Shadow(this.shadow));\n    this.canvas.fire('before:path:created', {\n      path: group\n    });\n    this.canvas.add(group);\n    this.canvas.fire('path:created', {\n      path: group\n    });\n    this.canvas.clearContext(this.canvas.contextTop);\n\n    this._resetShadow();\n\n    this.canvas.renderOnAddRemove = originalRenderOnAddRemove;\n    this.canvas.requestRenderAll();\n  },\n\n  /**\n   * @private\n   * @param {Array} rects\n   */\n  _getOptimizedRects: function (rects) {\n    // avoid creating duplicate rects at the same coordinates\n    var uniqueRects = {},\n        key,\n        i,\n        len;\n\n    for (i = 0, len = rects.length; i < len; i++) {\n      key = rects[i].left + '' + rects[i].top;\n\n      if (!uniqueRects[key]) {\n        uniqueRects[key] = rects[i];\n      }\n    }\n\n    var uniqueRectsArray = [];\n\n    for (key in uniqueRects) {\n      uniqueRectsArray.push(uniqueRects[key]);\n    }\n\n    return uniqueRectsArray;\n  },\n\n  /**\n   * Render new chunk of spray brush\n   */\n  render: function (sprayChunk) {\n    var ctx = this.canvas.contextTop,\n        i,\n        len;\n    ctx.fillStyle = this.color;\n\n    this._saveAndTransform(ctx);\n\n    for (i = 0, len = sprayChunk.length; i < len; i++) {\n      var point = sprayChunk[i];\n\n      if (typeof point.opacity !== 'undefined') {\n        ctx.globalAlpha = point.opacity;\n      }\n\n      ctx.fillRect(point.x, point.y, point.width, point.width);\n    }\n\n    ctx.restore();\n  },\n\n  /**\n   * Render all spray chunks\n   */\n  _render: function () {\n    var ctx = this.canvas.contextTop,\n        i,\n        ilen;\n    ctx.fillStyle = this.color;\n\n    this._saveAndTransform(ctx);\n\n    for (i = 0, ilen = this.sprayChunks.length; i < ilen; i++) {\n      this.render(this.sprayChunks[i]);\n    }\n\n    ctx.restore();\n  },\n\n  /**\n   * @param {Object} pointer\n   */\n  addSprayChunk: function (pointer) {\n    this.sprayChunkPoints = [];\n    var x,\n        y,\n        width,\n        radius = this.width / 2,\n        i;\n\n    for (i = 0; i < this.density; i++) {\n      x = fabric.util.getRandomInt(pointer.x - radius, pointer.x + radius);\n      y = fabric.util.getRandomInt(pointer.y - radius, pointer.y + radius);\n\n      if (this.dotWidthVariance) {\n        width = fabric.util.getRandomInt( // bottom clamp width to 1\n        Math.max(1, this.dotWidth - this.dotWidthVariance), this.dotWidth + this.dotWidthVariance);\n      } else {\n        width = this.dotWidth;\n      }\n\n      var point = new fabric.Point(x, y);\n      point.width = width;\n\n      if (this.randomOpacity) {\n        point.opacity = fabric.util.getRandomInt(0, 100) / 100;\n      }\n\n      this.sprayChunkPoints.push(point);\n    }\n\n    this.sprayChunks.push(this.sprayChunkPoints);\n  }\n});\n/**\n * PatternBrush class\n * @class fabric.PatternBrush\n * @extends fabric.BaseBrush\n */\n\nfabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush,\n/** @lends fabric.PatternBrush.prototype */\n{\n  getPatternSrc: function () {\n    var dotWidth = 20,\n        dotDistance = 5,\n        patternCanvas = fabric.util.createCanvasElement(),\n        patternCtx = patternCanvas.getContext('2d');\n    patternCanvas.width = patternCanvas.height = dotWidth + dotDistance;\n    patternCtx.fillStyle = this.color;\n    patternCtx.beginPath();\n    patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false);\n    patternCtx.closePath();\n    patternCtx.fill();\n    return patternCanvas;\n  },\n  getPatternSrcFunction: function () {\n    return String(this.getPatternSrc).replace('this.color', '\"' + this.color + '\"');\n  },\n\n  /**\n   * Creates \"pattern\" instance property\n   */\n  getPattern: function () {\n    return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), 'repeat');\n  },\n\n  /**\n   * Sets brush styles\n   */\n  _setBrushStyles: function () {\n    this.callSuper('_setBrushStyles');\n    this.canvas.contextTop.strokeStyle = this.getPattern();\n  },\n\n  /**\n   * Creates path\n   */\n  createPath: function (pathData) {\n    var path = this.callSuper('createPath', pathData),\n        topLeft = path._getLeftTopCoords().scalarAdd(path.strokeWidth / 2);\n\n    path.stroke = new fabric.Pattern({\n      source: this.source || this.getPatternSrcFunction(),\n      offsetX: -topLeft.x,\n      offsetY: -topLeft.y\n    });\n    return path;\n  }\n});\n\n(function () {\n  var getPointer = fabric.util.getPointer,\n      degreesToRadians = fabric.util.degreesToRadians,\n      abs = Math.abs,\n      supportLineDash = fabric.StaticCanvas.supports('setLineDash'),\n      isTouchEvent = fabric.util.isTouchEvent,\n      STROKE_OFFSET = 0.5;\n  /**\n   * Canvas class\n   * @class fabric.Canvas\n   * @extends fabric.StaticCanvas\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#canvas}\n   * @see {@link fabric.Canvas#initialize} for constructor definition\n   *\n   * @fires object:modified at the end of a transform or any change when statefull is true\n   * @fires object:rotating while an object is being rotated from the control\n   * @fires object:scaling while an object is being scaled by controls\n   * @fires object:moving while an object is being dragged\n   * @fires object:skewing while an object is being skewed from the controls\n   *\n   * @fires before:transform before a transform is is started\n   * @fires before:selection:cleared\n   * @fires selection:cleared\n   * @fires selection:updated\n   * @fires selection:created\n   *\n   * @fires path:created after a drawing operation ends and the path is added\n   * @fires mouse:down\n   * @fires mouse:move\n   * @fires mouse:up\n   * @fires mouse:down:before  on mouse down, before the inner fabric logic runs\n   * @fires mouse:move:before on mouse move, before the inner fabric logic runs\n   * @fires mouse:up:before on mouse up, before the inner fabric logic runs\n   * @fires mouse:over\n   * @fires mouse:out\n   * @fires mouse:dblclick whenever a native dbl click event fires on the canvas.\n   *\n   * @fires dragover\n   * @fires dragenter\n   * @fires dragleave\n   * @fires drop\n   * @fires after:render at the end of the render process, receives the context in the callback\n   * @fires before:render at start the render process, receives the context in the callback\n   *\n   * the following events are deprecated:\n   * @fires object:rotated at the end of a rotation transform\n   * @fires object:scaled at the end of a scale transform\n   * @fires object:moved at the end of translation transform\n   * @fires object:skewed at the end of a skew transform\n   */\n\n  fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas,\n  /** @lends fabric.Canvas.prototype */\n  {\n    /**\n     * Constructor\n     * @param {HTMLElement | String} el &lt;canvas> element to initialize instance on\n     * @param {Object} [options] Options object\n     * @return {Object} thisArg\n     */\n    initialize: function (el, options) {\n      options || (options = {});\n      this.renderAndResetBound = this.renderAndReset.bind(this);\n      this.requestRenderAllBound = this.requestRenderAll.bind(this);\n\n      this._initStatic(el, options);\n\n      this._initInteractive();\n\n      this._createCacheCanvas();\n    },\n\n    /**\n     * When true, objects can be transformed by one side (unproportionally)\n     * when dragged on the corners that normally would not do that.\n     * @type Boolean\n     * @default\n     * @since fabric 4.0 // changed name and default value\n     */\n    uniformScaling: true,\n\n    /**\n     * Indicates which key switches uniform scaling.\n     * values: 'altKey', 'shiftKey', 'ctrlKey'.\n     * If `null` or 'none' or any other string that is not a modifier key\n     * feature is disabled.\n     * totally wrong named. this sounds like `uniform scaling`\n     * if Canvas.uniformScaling is true, pressing this will set it to false\n     * and viceversa.\n     * @since 1.6.2\n     * @type String\n     * @default\n     */\n    uniScaleKey: 'shiftKey',\n\n    /**\n     * When true, objects use center point as the origin of scale transformation.\n     * <b>Backwards incompatibility note:</b> This property replaces \"centerTransform\" (Boolean).\n     * @since 1.3.4\n     * @type Boolean\n     * @default\n     */\n    centeredScaling: false,\n\n    /**\n     * When true, objects use center point as the origin of rotate transformation.\n     * <b>Backwards incompatibility note:</b> This property replaces \"centerTransform\" (Boolean).\n     * @since 1.3.4\n     * @type Boolean\n     * @default\n     */\n    centeredRotation: false,\n\n    /**\n     * Indicates which key enable centered Transform\n     * values: 'altKey', 'shiftKey', 'ctrlKey'.\n     * If `null` or 'none' or any other string that is not a modifier key\n     * feature is disabled feature disabled.\n     * @since 1.6.2\n     * @type String\n     * @default\n     */\n    centeredKey: 'altKey',\n\n    /**\n     * Indicates which key enable alternate action on corner\n     * values: 'altKey', 'shiftKey', 'ctrlKey'.\n     * If `null` or 'none' or any other string that is not a modifier key\n     * feature is disabled feature disabled.\n     * @since 1.6.2\n     * @type String\n     * @default\n     */\n    altActionKey: 'shiftKey',\n\n    /**\n     * Indicates that canvas is interactive. This property should not be changed.\n     * @type Boolean\n     * @default\n     */\n    interactive: true,\n\n    /**\n     * Indicates whether group selection should be enabled\n     * @type Boolean\n     * @default\n     */\n    selection: true,\n\n    /**\n     * Indicates which key or keys enable multiple click selection\n     * Pass value as a string or array of strings\n     * values: 'altKey', 'shiftKey', 'ctrlKey'.\n     * If `null` or empty or containing any other string that is not a modifier key\n     * feature is disabled.\n     * @since 1.6.2\n     * @type String|Array\n     * @default\n     */\n    selectionKey: 'shiftKey',\n\n    /**\n     * Indicates which key enable alternative selection\n     * in case of target overlapping with active object\n     * values: 'altKey', 'shiftKey', 'ctrlKey'.\n     * For a series of reason that come from the general expectations on how\n     * things should work, this feature works only for preserveObjectStacking true.\n     * If `null` or 'none' or any other string that is not a modifier key\n     * feature is disabled.\n     * @since 1.6.5\n     * @type null|String\n     * @default\n     */\n    altSelectionKey: null,\n\n    /**\n     * Color of selection\n     * @type String\n     * @default\n     */\n    selectionColor: 'rgba(100, 100, 255, 0.3)',\n    // blue\n\n    /**\n     * Default dash array pattern\n     * If not empty the selection border is dashed\n     * @type Array\n     */\n    selectionDashArray: [],\n\n    /**\n     * Color of the border of selection (usually slightly darker than color of selection itself)\n     * @type String\n     * @default\n     */\n    selectionBorderColor: 'rgba(255, 255, 255, 0.3)',\n\n    /**\n     * Width of a line used in object/group selection\n     * @type Number\n     * @default\n     */\n    selectionLineWidth: 1,\n\n    /**\n     * Select only shapes that are fully contained in the dragged selection rectangle.\n     * @type Boolean\n     * @default\n     */\n    selectionFullyContained: false,\n\n    /**\n     * Default cursor value used when hovering over an object on canvas\n     * @type String\n     * @default\n     */\n    hoverCursor: 'move',\n\n    /**\n     * Default cursor value used when moving an object on canvas\n     * @type String\n     * @default\n     */\n    moveCursor: 'move',\n\n    /**\n     * Default cursor value used for the entire canvas\n     * @type String\n     * @default\n     */\n    defaultCursor: 'default',\n\n    /**\n     * Cursor value used during free drawing\n     * @type String\n     * @default\n     */\n    freeDrawingCursor: 'crosshair',\n\n    /**\n     * Cursor value used for rotation point\n     * @type String\n     * @default\n     */\n    rotationCursor: 'crosshair',\n\n    /**\n     * Cursor value used for disabled elements ( corners with disabled action )\n     * @type String\n     * @since 2.0.0\n     * @default\n     */\n    notAllowedCursor: 'not-allowed',\n\n    /**\n     * Default element class that's given to wrapper (div) element of canvas\n     * @type String\n     * @default\n     */\n    containerClass: 'canvas-container',\n\n    /**\n     * When true, object detection happens on per-pixel basis rather than on per-bounding-box\n     * @type Boolean\n     * @default\n     */\n    perPixelTargetFind: false,\n\n    /**\n     * Number of pixels around target pixel to tolerate (consider active) during object detection\n     * @type Number\n     * @default\n     */\n    targetFindTolerance: 0,\n\n    /**\n     * When true, target detection is skipped. Target detection will return always undefined.\n     * click selection won't work anymore, events will fire with no targets.\n     * if something is selected before setting it to true, it will be deselected at the first click.\n     * area selection will still work. check the `selection` property too.\n     * if you deactivate both, you should look into staticCanvas.\n     * @type Boolean\n     * @default\n     */\n    skipTargetFind: false,\n\n    /**\n     * When true, mouse events on canvas (mousedown/mousemove/mouseup) result in free drawing.\n     * After mousedown, mousemove creates a shape,\n     * and then mouseup finalizes it and adds an instance of `fabric.Path` onto canvas.\n     * @tutorial {@link http://fabricjs.com/fabric-intro-part-4#free_drawing}\n     * @type Boolean\n     * @default\n     */\n    isDrawingMode: false,\n\n    /**\n     * Indicates whether objects should remain in current stack position when selected.\n     * When false objects are brought to top and rendered as part of the selection group\n     * @type Boolean\n     * @default\n     */\n    preserveObjectStacking: false,\n\n    /**\n     * Indicates the angle that an object will lock to while rotating.\n     * @type Number\n     * @since 1.6.7\n     * @default\n     */\n    snapAngle: 0,\n\n    /**\n     * Indicates the distance from the snapAngle the rotation will lock to the snapAngle.\n     * When `null`, the snapThreshold will default to the snapAngle.\n     * @type null|Number\n     * @since 1.6.7\n     * @default\n     */\n    snapThreshold: null,\n\n    /**\n     * Indicates if the right click on canvas can output the context menu or not\n     * @type Boolean\n     * @since 1.6.5\n     * @default\n     */\n    stopContextMenu: false,\n\n    /**\n     * Indicates if the canvas can fire right click events\n     * @type Boolean\n     * @since 1.6.5\n     * @default\n     */\n    fireRightClick: false,\n\n    /**\n     * Indicates if the canvas can fire middle click events\n     * @type Boolean\n     * @since 1.7.8\n     * @default\n     */\n    fireMiddleClick: false,\n\n    /**\n     * Keep track of the subTargets for Mouse Events\n     * @type fabric.Object[]\n     */\n    targets: [],\n\n    /**\n     * Keep track of the hovered target\n     * @type fabric.Object\n     * @private\n     */\n    _hoveredTarget: null,\n\n    /**\n     * hold the list of nested targets hovered\n     * @type fabric.Object[]\n     * @private\n     */\n    _hoveredTargets: [],\n\n    /**\n     * @private\n     */\n    _initInteractive: function () {\n      this._currentTransform = null;\n      this._groupSelector = null;\n\n      this._initWrapperElement();\n\n      this._createUpperCanvas();\n\n      this._initEventListeners();\n\n      this._initRetinaScaling();\n\n      this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this);\n      this.calcOffset();\n    },\n\n    /**\n     * Divides objects in two groups, one to render immediately\n     * and one to render as activeGroup.\n     * @return {Array} objects to render immediately and pushes the other in the activeGroup.\n     */\n    _chooseObjectsToRender: function () {\n      var activeObjects = this.getActiveObjects(),\n          object,\n          objsToRender,\n          activeGroupObjects;\n\n      if (activeObjects.length > 0 && !this.preserveObjectStacking) {\n        objsToRender = [];\n        activeGroupObjects = [];\n\n        for (var i = 0, length = this._objects.length; i < length; i++) {\n          object = this._objects[i];\n\n          if (activeObjects.indexOf(object) === -1) {\n            objsToRender.push(object);\n          } else {\n            activeGroupObjects.push(object);\n          }\n        }\n\n        if (activeObjects.length > 1) {\n          this._activeObject._objects = activeGroupObjects;\n        }\n\n        objsToRender.push.apply(objsToRender, activeGroupObjects);\n      } else {\n        objsToRender = this._objects;\n      }\n\n      return objsToRender;\n    },\n\n    /**\n     * Renders both the top canvas and the secondary container canvas.\n     * @return {fabric.Canvas} instance\n     * @chainable\n     */\n    renderAll: function () {\n      if (this.contextTopDirty && !this._groupSelector && !this.isDrawingMode) {\n        this.clearContext(this.contextTop);\n        this.contextTopDirty = false;\n      }\n\n      if (this.hasLostContext) {\n        this.renderTopLayer(this.contextTop);\n      }\n\n      var canvasToDrawOn = this.contextContainer;\n      this.renderCanvas(canvasToDrawOn, this._chooseObjectsToRender());\n      return this;\n    },\n    renderTopLayer: function (ctx) {\n      ctx.save();\n\n      if (this.isDrawingMode && this._isCurrentlyDrawing) {\n        this.freeDrawingBrush && this.freeDrawingBrush._render();\n        this.contextTopDirty = true;\n      } // we render the top context - last object\n\n\n      if (this.selection && this._groupSelector) {\n        this._drawSelection(ctx);\n\n        this.contextTopDirty = true;\n      }\n\n      ctx.restore();\n    },\n\n    /**\n     * Method to render only the top canvas.\n     * Also used to render the group selection box.\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    renderTop: function () {\n      var ctx = this.contextTop;\n      this.clearContext(ctx);\n      this.renderTopLayer(ctx);\n      this.fire('after:render');\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _normalizePointer: function (object, pointer) {\n      var m = object.calcTransformMatrix(),\n          invertedM = fabric.util.invertTransform(m),\n          vptPointer = this.restorePointerVpt(pointer);\n      return fabric.util.transformPoint(vptPointer, invertedM);\n    },\n\n    /**\n     * Returns true if object is transparent at a certain location\n     * @param {fabric.Object} target Object to check\n     * @param {Number} x Left coordinate\n     * @param {Number} y Top coordinate\n     * @return {Boolean}\n     */\n    isTargetTransparent: function (target, x, y) {\n      // in case the target is the activeObject, we cannot execute this optimization\n      // because we need to draw controls too.\n      if (target.shouldCache() && target._cacheCanvas && target !== this._activeObject) {\n        var normalizedPointer = this._normalizePointer(target, {\n          x: x,\n          y: y\n        }),\n            targetRelativeX = Math.max(target.cacheTranslationX + normalizedPointer.x * target.zoomX, 0),\n            targetRelativeY = Math.max(target.cacheTranslationY + normalizedPointer.y * target.zoomY, 0);\n\n        var isTransparent = fabric.util.isTransparent(target._cacheContext, Math.round(targetRelativeX), Math.round(targetRelativeY), this.targetFindTolerance);\n        return isTransparent;\n      }\n\n      var ctx = this.contextCache,\n          originalColor = target.selectionBackgroundColor,\n          v = this.viewportTransform;\n      target.selectionBackgroundColor = '';\n      this.clearContext(ctx);\n      ctx.save();\n      ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n      target.render(ctx);\n      ctx.restore();\n      target === this._activeObject && target._renderControls(ctx, {\n        hasBorders: false,\n        transparentCorners: false\n      }, {\n        hasBorders: false\n      });\n      target.selectionBackgroundColor = originalColor;\n      var isTransparent = fabric.util.isTransparent(ctx, x, y, this.targetFindTolerance);\n      return isTransparent;\n    },\n\n    /**\n     * takes an event and determins if selection key has been pressed\n     * @private\n     * @param {Event} e Event object\n     */\n    _isSelectionKeyPressed: function (e) {\n      var selectionKeyPressed = false;\n\n      if (Object.prototype.toString.call(this.selectionKey) === '[object Array]') {\n        selectionKeyPressed = !!this.selectionKey.find(function (key) {\n          return e[key] === true;\n        });\n      } else {\n        selectionKeyPressed = e[this.selectionKey];\n      }\n\n      return selectionKeyPressed;\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object\n     * @param {fabric.Object} target\n     */\n    _shouldClearSelection: function (e, target) {\n      var activeObjects = this.getActiveObjects(),\n          activeObject = this._activeObject;\n      return !target || target && activeObject && activeObjects.length > 1 && activeObjects.indexOf(target) === -1 && activeObject !== target && !this._isSelectionKeyPressed(e) || target && !target.evented || target && !target.selectable && activeObject && activeObject !== target;\n    },\n\n    /**\n     * centeredScaling from object can't override centeredScaling from canvas.\n     * this should be fixed, since object setting should take precedence over canvas.\n     * also this should be something that will be migrated in the control properties.\n     * as ability to define the origin of the transformation that the control provide.\n     * @private\n     * @param {fabric.Object} target\n     * @param {String} action\n     * @param {Boolean} altKey\n     */\n    _shouldCenterTransform: function (target, action, altKey) {\n      if (!target) {\n        return;\n      }\n\n      var centerTransform;\n\n      if (action === 'scale' || action === 'scaleX' || action === 'scaleY' || action === 'resizing') {\n        centerTransform = this.centeredScaling || target.centeredScaling;\n      } else if (action === 'rotate') {\n        centerTransform = this.centeredRotation || target.centeredRotation;\n      }\n\n      return centerTransform ? !altKey : altKey;\n    },\n\n    /**\n     * should disappear before release 4.0\n     * @private\n     */\n    _getOriginFromCorner: function (target, corner) {\n      var origin = {\n        x: target.originX,\n        y: target.originY\n      };\n\n      if (corner === 'ml' || corner === 'tl' || corner === 'bl') {\n        origin.x = 'right';\n      } else if (corner === 'mr' || corner === 'tr' || corner === 'br') {\n        origin.x = 'left';\n      }\n\n      if (corner === 'tl' || corner === 'mt' || corner === 'tr') {\n        origin.y = 'bottom';\n      } else if (corner === 'bl' || corner === 'mb' || corner === 'br') {\n        origin.y = 'top';\n      } else if (corner === 'mtr') {\n        origin.x = 'center';\n        origin.y = 'center';\n      }\n\n      return origin;\n    },\n\n    /**\n     * @private\n     * @param {Boolean} alreadySelected true if target is already selected\n     * @param {String} corner a string representing the corner ml, mr, tl ...\n     * @param {Event} e Event object\n     * @param {fabric.Object} [target] inserted back to help overriding. Unused\n     */\n    _getActionFromCorner: function (alreadySelected, corner, e, target) {\n      if (!corner || !alreadySelected) {\n        return 'drag';\n      }\n\n      var control = target.controls[corner];\n      return control.getActionName(e, control, target);\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object\n     * @param {fabric.Object} target\n     */\n    _setupCurrentTransform: function (e, target, alreadySelected) {\n      if (!target) {\n        return;\n      }\n\n      var pointer = this.getPointer(e),\n          corner = target.__corner,\n          actionHandler = alreadySelected && corner ? target.controls[corner].getActionHandler() : fabric.controlsUtils.dragHandler,\n          action = this._getActionFromCorner(alreadySelected, corner, e, target),\n          origin = this._getOriginFromCorner(target, corner),\n          altKey = e[this.centeredKey],\n          transform = {\n        target: target,\n        action: action,\n        actionHandler: actionHandler,\n        corner: corner,\n        scaleX: target.scaleX,\n        scaleY: target.scaleY,\n        skewX: target.skewX,\n        skewY: target.skewY,\n        // used by transation\n        offsetX: pointer.x - target.left,\n        offsetY: pointer.y - target.top,\n        originX: origin.x,\n        originY: origin.y,\n        ex: pointer.x,\n        ey: pointer.y,\n        lastX: pointer.x,\n        lastY: pointer.y,\n        // unsure they are useful anymore.\n        // left: target.left,\n        // top: target.top,\n        theta: degreesToRadians(target.angle),\n        // end of unsure\n        width: target.width * target.scaleX,\n        shiftKey: e.shiftKey,\n        altKey: altKey,\n        original: fabric.util.saveObjectTransform(target)\n      };\n\n      if (this._shouldCenterTransform(target, action, altKey)) {\n        transform.originX = 'center';\n        transform.originY = 'center';\n      }\n\n      transform.original.originX = origin.x;\n      transform.original.originY = origin.y;\n      this._currentTransform = transform;\n\n      this._beforeTransform(e);\n    },\n\n    /**\n     * Set the cursor type of the canvas element\n     * @param {String} value Cursor type of the canvas element.\n     * @see http://www.w3.org/TR/css3-ui/#cursor\n     */\n    setCursor: function (value) {\n      this.upperCanvasEl.style.cursor = value;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx to draw the selection on\n     */\n    _drawSelection: function (ctx) {\n      var groupSelector = this._groupSelector,\n          left = groupSelector.left,\n          top = groupSelector.top,\n          aleft = abs(left),\n          atop = abs(top);\n\n      if (this.selectionColor) {\n        ctx.fillStyle = this.selectionColor;\n        ctx.fillRect(groupSelector.ex - (left > 0 ? 0 : -left), groupSelector.ey - (top > 0 ? 0 : -top), aleft, atop);\n      }\n\n      if (!this.selectionLineWidth || !this.selectionBorderColor) {\n        return;\n      }\n\n      ctx.lineWidth = this.selectionLineWidth;\n      ctx.strokeStyle = this.selectionBorderColor; // selection border\n\n      if (this.selectionDashArray.length > 1 && !supportLineDash) {\n        var px = groupSelector.ex + STROKE_OFFSET - (left > 0 ? 0 : aleft),\n            py = groupSelector.ey + STROKE_OFFSET - (top > 0 ? 0 : atop);\n        ctx.beginPath();\n        fabric.util.drawDashedLine(ctx, px, py, px + aleft, py, this.selectionDashArray);\n        fabric.util.drawDashedLine(ctx, px, py + atop - 1, px + aleft, py + atop - 1, this.selectionDashArray);\n        fabric.util.drawDashedLine(ctx, px, py, px, py + atop, this.selectionDashArray);\n        fabric.util.drawDashedLine(ctx, px + aleft - 1, py, px + aleft - 1, py + atop, this.selectionDashArray);\n        ctx.closePath();\n        ctx.stroke();\n      } else {\n        fabric.Object.prototype._setLineDash.call(this, ctx, this.selectionDashArray);\n\n        ctx.strokeRect(groupSelector.ex + STROKE_OFFSET - (left > 0 ? 0 : aleft), groupSelector.ey + STROKE_OFFSET - (top > 0 ? 0 : atop), aleft, atop);\n      }\n    },\n\n    /**\n     * Method that determines what object we are clicking on\n     * the skipGroup parameter is for internal use, is needed for shift+click action\n     * 11/09/2018 TODO: would be cool if findTarget could discern between being a full target\n     * or the outside part of the corner.\n     * @param {Event} e mouse event\n     * @param {Boolean} skipGroup when true, activeGroup is skipped and only objects are traversed through\n     * @return {fabric.Object} the target found\n     */\n    findTarget: function (e, skipGroup) {\n      if (this.skipTargetFind) {\n        return;\n      }\n\n      var ignoreZoom = true,\n          pointer = this.getPointer(e, ignoreZoom),\n          activeObject = this._activeObject,\n          aObjects = this.getActiveObjects(),\n          activeTarget,\n          activeTargetSubs,\n          isTouch = isTouchEvent(e); // first check current group (if one exists)\n      // active group does not check sub targets like normal groups.\n      // if active group just exits.\n\n      this.targets = [];\n\n      if (aObjects.length > 1 && !skipGroup && activeObject === this._searchPossibleTargets([activeObject], pointer)) {\n        return activeObject;\n      } // if we hit the corner of an activeObject, let's return that.\n\n\n      if (aObjects.length === 1 && activeObject._findTargetCorner(pointer, isTouch)) {\n        return activeObject;\n      }\n\n      if (aObjects.length === 1 && activeObject === this._searchPossibleTargets([activeObject], pointer)) {\n        if (!this.preserveObjectStacking) {\n          return activeObject;\n        } else {\n          activeTarget = activeObject;\n          activeTargetSubs = this.targets;\n          this.targets = [];\n        }\n      }\n\n      var target = this._searchPossibleTargets(this._objects, pointer);\n\n      if (e[this.altSelectionKey] && target && activeTarget && target !== activeTarget) {\n        target = activeTarget;\n        this.targets = activeTargetSubs;\n      }\n\n      return target;\n    },\n\n    /**\n     * Checks point is inside the object.\n     * @param {Object} [pointer] x,y object of point coordinates we want to check.\n     * @param {fabric.Object} obj Object to test against\n     * @param {Object} [globalPointer] x,y object of point coordinates relative to canvas used to search per pixel target.\n     * @return {Boolean} true if point is contained within an area of given object\n     * @private\n     */\n    _checkTarget: function (pointer, obj, globalPointer) {\n      if (obj && obj.visible && obj.evented && ( // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html\n      // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html\n      obj.containsPoint(pointer) || !!obj._findTargetCorner(pointer))) {\n        if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) {\n          var isTransparent = this.isTargetTransparent(obj, globalPointer.x, globalPointer.y);\n\n          if (!isTransparent) {\n            return true;\n          }\n        } else {\n          return true;\n        }\n      }\n    },\n\n    /**\n     * Function used to search inside objects an object that contains pointer in bounding box or that contains pointerOnCanvas when painted\n     * @param {Array} [objects] objects array to look into\n     * @param {Object} [pointer] x,y object of point coordinates we want to check.\n     * @return {fabric.Object} object that contains pointer\n     * @private\n     */\n    _searchPossibleTargets: function (objects, pointer) {\n      // Cache all targets where their bounding box contains point.\n      var target,\n          i = objects.length,\n          subTarget; // Do not check for currently grouped objects, since we check the parent group itself.\n      // until we call this function specifically to search inside the activeGroup\n\n      while (i--) {\n        var objToCheck = objects[i];\n        var pointerToUse = objToCheck.group ? this._normalizePointer(objToCheck.group, pointer) : pointer;\n\n        if (this._checkTarget(pointerToUse, objToCheck, pointer)) {\n          target = objects[i];\n\n          if (target.subTargetCheck && target instanceof fabric.Group) {\n            subTarget = this._searchPossibleTargets(target._objects, pointer);\n            subTarget && this.targets.push(subTarget);\n          }\n\n          break;\n        }\n      }\n\n      return target;\n    },\n\n    /**\n     * Returns pointer coordinates without the effect of the viewport\n     * @param {Object} pointer with \"x\" and \"y\" number values\n     * @return {Object} object with \"x\" and \"y\" number values\n     */\n    restorePointerVpt: function (pointer) {\n      return fabric.util.transformPoint(pointer, fabric.util.invertTransform(this.viewportTransform));\n    },\n\n    /**\n     * Returns pointer coordinates relative to canvas.\n     * Can return coordinates with or without viewportTransform.\n     * ignoreZoom false gives back coordinates that represent\n     * the point clicked on canvas element.\n     * ignoreZoom true gives back coordinates after being processed\n     * by the viewportTransform ( sort of coordinates of what is displayed\n     * on the canvas where you are clicking.\n     * ignoreZoom true = HTMLElement coordinates relative to top,left\n     * ignoreZoom false, default = fabric space coordinates, the same used for shape position\n     * To interact with your shapes top and left you want to use ignoreZoom true\n     * most of the time, while ignoreZoom false will give you coordinates\n     * compatible with the object.oCoords system.\n     * of the time.\n     * @param {Event} e\n     * @param {Boolean} ignoreZoom\n     * @return {Object} object with \"x\" and \"y\" number values\n     */\n    getPointer: function (e, ignoreZoom) {\n      // return cached values if we are in the event processing chain\n      if (this._absolutePointer && !ignoreZoom) {\n        return this._absolutePointer;\n      }\n\n      if (this._pointer && ignoreZoom) {\n        return this._pointer;\n      }\n\n      var pointer = getPointer(e),\n          upperCanvasEl = this.upperCanvasEl,\n          bounds = upperCanvasEl.getBoundingClientRect(),\n          boundsWidth = bounds.width || 0,\n          boundsHeight = bounds.height || 0,\n          cssScale;\n\n      if (!boundsWidth || !boundsHeight) {\n        if ('top' in bounds && 'bottom' in bounds) {\n          boundsHeight = Math.abs(bounds.top - bounds.bottom);\n        }\n\n        if ('right' in bounds && 'left' in bounds) {\n          boundsWidth = Math.abs(bounds.right - bounds.left);\n        }\n      }\n\n      this.calcOffset();\n      pointer.x = pointer.x - this._offset.left;\n      pointer.y = pointer.y - this._offset.top;\n\n      if (!ignoreZoom) {\n        pointer = this.restorePointerVpt(pointer);\n      }\n\n      var retinaScaling = this.getRetinaScaling();\n\n      if (retinaScaling !== 1) {\n        pointer.x /= retinaScaling;\n        pointer.y /= retinaScaling;\n      }\n\n      if (boundsWidth === 0 || boundsHeight === 0) {\n        // If bounds are not available (i.e. not visible), do not apply scale.\n        cssScale = {\n          width: 1,\n          height: 1\n        };\n      } else {\n        cssScale = {\n          width: upperCanvasEl.width / boundsWidth,\n          height: upperCanvasEl.height / boundsHeight\n        };\n      }\n\n      return {\n        x: pointer.x * cssScale.width,\n        y: pointer.y * cssScale.height\n      };\n    },\n\n    /**\n     * @private\n     * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized\n     */\n    _createUpperCanvas: function () {\n      var lowerCanvasClass = this.lowerCanvasEl.className.replace(/\\s*lower-canvas\\s*/, ''),\n          lowerCanvasEl = this.lowerCanvasEl,\n          upperCanvasEl = this.upperCanvasEl; // there is no need to create a new upperCanvas element if we have already one.\n\n      if (upperCanvasEl) {\n        upperCanvasEl.className = '';\n      } else {\n        upperCanvasEl = this._createCanvasElement();\n        this.upperCanvasEl = upperCanvasEl;\n      }\n\n      fabric.util.addClass(upperCanvasEl, 'upper-canvas ' + lowerCanvasClass);\n      this.wrapperEl.appendChild(upperCanvasEl);\n\n      this._copyCanvasStyle(lowerCanvasEl, upperCanvasEl);\n\n      this._applyCanvasStyle(upperCanvasEl);\n\n      this.contextTop = upperCanvasEl.getContext('2d');\n    },\n\n    /**\n     * @private\n     */\n    _createCacheCanvas: function () {\n      this.cacheCanvasEl = this._createCanvasElement();\n      this.cacheCanvasEl.setAttribute('width', this.width);\n      this.cacheCanvasEl.setAttribute('height', this.height);\n      this.contextCache = this.cacheCanvasEl.getContext('2d');\n    },\n\n    /**\n     * @private\n     */\n    _initWrapperElement: function () {\n      this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', {\n        'class': this.containerClass\n      });\n      fabric.util.setStyle(this.wrapperEl, {\n        width: this.width + 'px',\n        height: this.height + 'px',\n        position: 'relative'\n      });\n      fabric.util.makeElementUnselectable(this.wrapperEl);\n    },\n\n    /**\n     * @private\n     * @param {HTMLElement} element canvas element to apply styles on\n     */\n    _applyCanvasStyle: function (element) {\n      var width = this.width || element.width,\n          height = this.height || element.height;\n      fabric.util.setStyle(element, {\n        position: 'absolute',\n        width: width + 'px',\n        height: height + 'px',\n        left: 0,\n        top: 0,\n        'touch-action': this.allowTouchScrolling ? 'manipulation' : 'none',\n        '-ms-touch-action': this.allowTouchScrolling ? 'manipulation' : 'none'\n      });\n      element.width = width;\n      element.height = height;\n      fabric.util.makeElementUnselectable(element);\n    },\n\n    /**\n     * Copy the entire inline style from one element (fromEl) to another (toEl)\n     * @private\n     * @param {Element} fromEl Element style is copied from\n     * @param {Element} toEl Element copied style is applied to\n     */\n    _copyCanvasStyle: function (fromEl, toEl) {\n      toEl.style.cssText = fromEl.style.cssText;\n    },\n\n    /**\n     * Returns context of canvas where object selection is drawn\n     * @return {CanvasRenderingContext2D}\n     */\n    getSelectionContext: function () {\n      return this.contextTop;\n    },\n\n    /**\n     * Returns &lt;canvas> element on which object selection is drawn\n     * @return {HTMLCanvasElement}\n     */\n    getSelectionElement: function () {\n      return this.upperCanvasEl;\n    },\n\n    /**\n     * Returns currently active object\n     * @return {fabric.Object} active object\n     */\n    getActiveObject: function () {\n      return this._activeObject;\n    },\n\n    /**\n     * Returns an array with the current selected objects\n     * @return {fabric.Object} active object\n     */\n    getActiveObjects: function () {\n      var active = this._activeObject;\n\n      if (active) {\n        if (active.type === 'activeSelection' && active._objects) {\n          return active._objects.slice(0);\n        } else {\n          return [active];\n        }\n      }\n\n      return [];\n    },\n\n    /**\n     * @private\n     * @param {fabric.Object} obj Object that was removed\n     */\n    _onObjectRemoved: function (obj) {\n      // removing active object should fire \"selection:cleared\" events\n      if (obj === this._activeObject) {\n        this.fire('before:selection:cleared', {\n          target: obj\n        });\n\n        this._discardActiveObject();\n\n        this.fire('selection:cleared', {\n          target: obj\n        });\n        obj.fire('deselected');\n      }\n\n      if (obj === this._hoveredTarget) {\n        this._hoveredTarget = null;\n        this._hoveredTargets = [];\n      }\n\n      this.callSuper('_onObjectRemoved', obj);\n    },\n\n    /**\n     * @private\n     * Compares the old activeObject with the current one and fires correct events\n     * @param {fabric.Object} obj old activeObject\n     */\n    _fireSelectionEvents: function (oldObjects, e) {\n      var somethingChanged = false,\n          objects = this.getActiveObjects(),\n          added = [],\n          removed = [],\n          opt = {\n        e: e\n      };\n      oldObjects.forEach(function (oldObject) {\n        if (objects.indexOf(oldObject) === -1) {\n          somethingChanged = true;\n          oldObject.fire('deselected', opt);\n          removed.push(oldObject);\n        }\n      });\n      objects.forEach(function (object) {\n        if (oldObjects.indexOf(object) === -1) {\n          somethingChanged = true;\n          object.fire('selected', opt);\n          added.push(object);\n        }\n      });\n\n      if (oldObjects.length > 0 && objects.length > 0) {\n        opt.selected = added;\n        opt.deselected = removed; // added for backward compatibility\n\n        opt.updated = added[0] || removed[0];\n        opt.target = this._activeObject;\n        somethingChanged && this.fire('selection:updated', opt);\n      } else if (objects.length > 0) {\n        opt.selected = added; // added for backward compatibility\n\n        opt.target = this._activeObject;\n        this.fire('selection:created', opt);\n      } else if (oldObjects.length > 0) {\n        opt.deselected = removed;\n        this.fire('selection:cleared', opt);\n      }\n    },\n\n    /**\n     * Sets given object as the only active object on canvas\n     * @param {fabric.Object} object Object to set as an active one\n     * @param {Event} [e] Event (passed along when firing \"object:selected\")\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    setActiveObject: function (object, e) {\n      var currentActives = this.getActiveObjects();\n\n      this._setActiveObject(object, e);\n\n      this._fireSelectionEvents(currentActives, e);\n\n      return this;\n    },\n\n    /**\n     * @private\n     * @param {Object} object to set as active\n     * @param {Event} [e] Event (passed along when firing \"object:selected\")\n     * @return {Boolean} true if the selection happened\n     */\n    _setActiveObject: function (object, e) {\n      if (this._activeObject === object) {\n        return false;\n      }\n\n      if (!this._discardActiveObject(e, object)) {\n        return false;\n      }\n\n      if (object.onSelect({\n        e: e\n      })) {\n        return false;\n      }\n\n      this._activeObject = object;\n      return true;\n    },\n\n    /**\n     * @private\n     */\n    _discardActiveObject: function (e, object) {\n      var obj = this._activeObject;\n\n      if (obj) {\n        // onDeselect return TRUE to cancel selection;\n        if (obj.onDeselect({\n          e: e,\n          object: object\n        })) {\n          return false;\n        }\n\n        this._activeObject = null;\n      }\n\n      return true;\n    },\n\n    /**\n     * Discards currently active object and fire events. If the function is called by fabric\n     * as a consequence of a mouse event, the event is passed as a parameter and\n     * sent to the fire function for the custom events. When used as a method the\n     * e param does not have any application.\n     * @param {event} e\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    discardActiveObject: function (e) {\n      var currentActives = this.getActiveObjects(),\n          activeObject = this.getActiveObject();\n\n      if (currentActives.length) {\n        this.fire('before:selection:cleared', {\n          target: activeObject,\n          e: e\n        });\n      }\n\n      this._discardActiveObject(e);\n\n      this._fireSelectionEvents(currentActives, e);\n\n      return this;\n    },\n\n    /**\n     * Clears a canvas element and removes all event listeners\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    dispose: function () {\n      var wrapper = this.wrapperEl;\n      this.removeListeners();\n      wrapper.removeChild(this.upperCanvasEl);\n      wrapper.removeChild(this.lowerCanvasEl);\n      this.contextCache = null;\n      this.contextTop = null;\n      ['upperCanvasEl', 'cacheCanvasEl'].forEach(function (element) {\n        fabric.util.cleanUpJsdomNode(this[element]);\n        this[element] = undefined;\n      }.bind(this));\n\n      if (wrapper.parentNode) {\n        wrapper.parentNode.replaceChild(this.lowerCanvasEl, this.wrapperEl);\n      }\n\n      delete this.wrapperEl;\n      fabric.StaticCanvas.prototype.dispose.call(this);\n      return this;\n    },\n\n    /**\n     * Clears all contexts (background, main, top) of an instance\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    clear: function () {\n      // this.discardActiveGroup();\n      this.discardActiveObject();\n      this.clearContext(this.contextTop);\n      return this.callSuper('clear');\n    },\n\n    /**\n     * Draws objects' controls (borders/controls)\n     * @param {CanvasRenderingContext2D} ctx Context to render controls on\n     */\n    drawControls: function (ctx) {\n      var activeObject = this._activeObject;\n\n      if (activeObject) {\n        activeObject._renderControls(ctx);\n      }\n    },\n\n    /**\n     * @private\n     */\n    _toObject: function (instance, methodName, propertiesToInclude) {\n      //If the object is part of the current selection group, it should\n      //be transformed appropriately\n      //i.e. it should be serialised as it would appear if the selection group\n      //were to be destroyed.\n      var originalProperties = this._realizeGroupTransformOnObject(instance),\n          object = this.callSuper('_toObject', instance, methodName, propertiesToInclude); //Undo the damage we did by changing all of its properties\n\n\n      this._unwindGroupTransformOnObject(instance, originalProperties);\n\n      return object;\n    },\n\n    /**\n     * Realises an object's group transformation on it\n     * @private\n     * @param {fabric.Object} [instance] the object to transform (gets mutated)\n     * @returns the original values of instance which were changed\n     */\n    _realizeGroupTransformOnObject: function (instance) {\n      if (instance.group && instance.group.type === 'activeSelection' && this._activeObject === instance.group) {\n        var layoutProps = ['angle', 'flipX', 'flipY', 'left', 'scaleX', 'scaleY', 'skewX', 'skewY', 'top']; //Copy all the positionally relevant properties across now\n\n        var originalValues = {};\n        layoutProps.forEach(function (prop) {\n          originalValues[prop] = instance[prop];\n        });\n\n        this._activeObject.realizeTransform(instance);\n\n        return originalValues;\n      } else {\n        return null;\n      }\n    },\n\n    /**\n     * Restores the changed properties of instance\n     * @private\n     * @param {fabric.Object} [instance] the object to un-transform (gets mutated)\n     * @param {Object} [originalValues] the original values of instance, as returned by _realizeGroupTransformOnObject\n     */\n    _unwindGroupTransformOnObject: function (instance, originalValues) {\n      if (originalValues) {\n        instance.set(originalValues);\n      }\n    },\n\n    /**\n     * @private\n     */\n    _setSVGObject: function (markup, instance, reviver) {\n      //If the object is in a selection group, simulate what would happen to that\n      //object when the group is deselected\n      var originalProperties = this._realizeGroupTransformOnObject(instance);\n\n      this.callSuper('_setSVGObject', markup, instance, reviver);\n\n      this._unwindGroupTransformOnObject(instance, originalProperties);\n    },\n    setViewportTransform: function (vpt) {\n      if (this.renderOnAddRemove && this._activeObject && this._activeObject.isEditing) {\n        this._activeObject.clearContextTop();\n      }\n\n      fabric.StaticCanvas.prototype.setViewportTransform.call(this, vpt);\n    }\n  }); // copying static properties manually to work around Opera's bug,\n  // where \"prototype\" property is enumerable and overrides existing prototype\n\n  for (var prop in fabric.StaticCanvas) {\n    if (prop !== 'prototype') {\n      fabric.Canvas[prop] = fabric.StaticCanvas[prop];\n    }\n  }\n})();\n\n(function () {\n  var addListener = fabric.util.addListener,\n      removeListener = fabric.util.removeListener,\n      RIGHT_CLICK = 3,\n      MIDDLE_CLICK = 2,\n      LEFT_CLICK = 1,\n      addEventOptions = {\n    passive: false\n  };\n\n  function checkClick(e, value) {\n    return e.button && e.button === value - 1;\n  }\n\n  fabric.util.object.extend(fabric.Canvas.prototype,\n  /** @lends fabric.Canvas.prototype */\n  {\n    /**\n     * Contains the id of the touch event that owns the fabric transform\n     * @type Number\n     * @private\n     */\n    mainTouchId: null,\n\n    /**\n     * Adds mouse listeners to canvas\n     * @private\n     */\n    _initEventListeners: function () {\n      // in case we initialized the class twice. This should not happen normally\n      // but in some kind of applications where the canvas element may be changed\n      // this is a workaround to having double listeners.\n      this.removeListeners();\n\n      this._bindEvents();\n\n      this.addOrRemove(addListener, 'add');\n    },\n\n    /**\n     * return an event prefix pointer or mouse.\n     * @private\n     */\n    _getEventPrefix: function () {\n      return this.enablePointerEvents ? 'pointer' : 'mouse';\n    },\n    addOrRemove: function (functor, eventjsFunctor) {\n      var canvasElement = this.upperCanvasEl,\n          eventTypePrefix = this._getEventPrefix();\n\n      functor(fabric.window, 'resize', this._onResize);\n      functor(canvasElement, eventTypePrefix + 'down', this._onMouseDown);\n      functor(canvasElement, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n      functor(canvasElement, eventTypePrefix + 'out', this._onMouseOut);\n      functor(canvasElement, eventTypePrefix + 'enter', this._onMouseEnter);\n      functor(canvasElement, 'wheel', this._onMouseWheel);\n      functor(canvasElement, 'contextmenu', this._onContextMenu);\n      functor(canvasElement, 'dblclick', this._onDoubleClick);\n      functor(canvasElement, 'dragover', this._onDragOver);\n      functor(canvasElement, 'dragenter', this._onDragEnter);\n      functor(canvasElement, 'dragleave', this._onDragLeave);\n      functor(canvasElement, 'drop', this._onDrop);\n\n      if (!this.enablePointerEvents) {\n        functor(canvasElement, 'touchstart', this._onTouchStart, addEventOptions);\n      }\n\n      if (typeof eventjs !== 'undefined' && eventjsFunctor in eventjs) {\n        eventjs[eventjsFunctor](canvasElement, 'gesture', this._onGesture);\n        eventjs[eventjsFunctor](canvasElement, 'drag', this._onDrag);\n        eventjs[eventjsFunctor](canvasElement, 'orientation', this._onOrientationChange);\n        eventjs[eventjsFunctor](canvasElement, 'shake', this._onShake);\n        eventjs[eventjsFunctor](canvasElement, 'longpress', this._onLongPress);\n      }\n    },\n\n    /**\n     * Removes all event listeners\n     */\n    removeListeners: function () {\n      this.addOrRemove(removeListener, 'remove'); // if you dispose on a mouseDown, before mouse up, you need to clean document to...\n\n      var eventTypePrefix = this._getEventPrefix();\n\n      removeListener(fabric.document, eventTypePrefix + 'up', this._onMouseUp);\n      removeListener(fabric.document, 'touchend', this._onTouchEnd, addEventOptions);\n      removeListener(fabric.document, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n      removeListener(fabric.document, 'touchmove', this._onMouseMove, addEventOptions);\n    },\n\n    /**\n     * @private\n     */\n    _bindEvents: function () {\n      if (this.eventsBound) {\n        // for any reason we pass here twice we do not want to bind events twice.\n        return;\n      }\n\n      this._onMouseDown = this._onMouseDown.bind(this);\n      this._onTouchStart = this._onTouchStart.bind(this);\n      this._onMouseMove = this._onMouseMove.bind(this);\n      this._onMouseUp = this._onMouseUp.bind(this);\n      this._onTouchEnd = this._onTouchEnd.bind(this);\n      this._onResize = this._onResize.bind(this);\n      this._onGesture = this._onGesture.bind(this);\n      this._onDrag = this._onDrag.bind(this);\n      this._onShake = this._onShake.bind(this);\n      this._onLongPress = this._onLongPress.bind(this);\n      this._onOrientationChange = this._onOrientationChange.bind(this);\n      this._onMouseWheel = this._onMouseWheel.bind(this);\n      this._onMouseOut = this._onMouseOut.bind(this);\n      this._onMouseEnter = this._onMouseEnter.bind(this);\n      this._onContextMenu = this._onContextMenu.bind(this);\n      this._onDoubleClick = this._onDoubleClick.bind(this);\n      this._onDragOver = this._onDragOver.bind(this);\n      this._onDragEnter = this._simpleEventHandler.bind(this, 'dragenter');\n      this._onDragLeave = this._simpleEventHandler.bind(this, 'dragleave');\n      this._onDrop = this._simpleEventHandler.bind(this, 'drop');\n      this.eventsBound = true;\n    },\n\n    /**\n     * @private\n     * @param {Event} [e] Event object fired on Event.js gesture\n     * @param {Event} [self] Inner Event object\n     */\n    _onGesture: function (e, self) {\n      this.__onTransformGesture && this.__onTransformGesture(e, self);\n    },\n\n    /**\n     * @private\n     * @param {Event} [e] Event object fired on Event.js drag\n     * @param {Event} [self] Inner Event object\n     */\n    _onDrag: function (e, self) {\n      this.__onDrag && this.__onDrag(e, self);\n    },\n\n    /**\n     * @private\n     * @param {Event} [e] Event object fired on wheel event\n     */\n    _onMouseWheel: function (e) {\n      this.__onMouseWheel(e);\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onMouseOut: function (e) {\n      var target = this._hoveredTarget;\n      this.fire('mouse:out', {\n        target: target,\n        e: e\n      });\n      this._hoveredTarget = null;\n      target && target.fire('mouseout', {\n        e: e\n      });\n\n      var _this = this;\n\n      this._hoveredTargets.forEach(function (_target) {\n        _this.fire('mouse:out', {\n          target: target,\n          e: e\n        });\n\n        _target && target.fire('mouseout', {\n          e: e\n        });\n      });\n\n      this._hoveredTargets = [];\n\n      if (this._iTextInstances) {\n        this._iTextInstances.forEach(function (obj) {\n          if (obj.isEditing) {\n            obj.hiddenTextarea.focus();\n          }\n        });\n      }\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mouseenter\n     */\n    _onMouseEnter: function (e) {\n      // This find target and consequent 'mouse:over' is used to\n      // clear old instances on hovered target.\n      // calling findTarget has the side effect of killing target.__corner.\n      // as a short term fix we are not firing this if we are currently transforming.\n      // as a long term fix we need to separate the action of finding a target with the\n      // side effects we added to it.\n      if (!this._currentTransform && !this.findTarget(e)) {\n        this.fire('mouse:over', {\n          target: null,\n          e: e\n        });\n        this._hoveredTarget = null;\n        this._hoveredTargets = [];\n      }\n    },\n\n    /**\n     * @private\n     * @param {Event} [e] Event object fired on Event.js orientation change\n     * @param {Event} [self] Inner Event object\n     */\n    _onOrientationChange: function (e, self) {\n      this.__onOrientationChange && this.__onOrientationChange(e, self);\n    },\n\n    /**\n     * @private\n     * @param {Event} [e] Event object fired on Event.js shake\n     * @param {Event} [self] Inner Event object\n     */\n    _onShake: function (e, self) {\n      this.__onShake && this.__onShake(e, self);\n    },\n\n    /**\n     * @private\n     * @param {Event} [e] Event object fired on Event.js shake\n     * @param {Event} [self] Inner Event object\n     */\n    _onLongPress: function (e, self) {\n      this.__onLongPress && this.__onLongPress(e, self);\n    },\n\n    /**\n     * prevent default to allow drop event to be fired\n     * @private\n     * @param {Event} [e] Event object fired on Event.js shake\n     */\n    _onDragOver: function (e) {\n      e.preventDefault();\n\n      var target = this._simpleEventHandler('dragover', e);\n\n      this._fireEnterLeaveEvents(target, e);\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onContextMenu: function (e) {\n      if (this.stopContextMenu) {\n        e.stopPropagation();\n        e.preventDefault();\n      }\n\n      return false;\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onDoubleClick: function (e) {\n      this._cacheTransformEventData(e);\n\n      this._handleEvent(e, 'dblclick');\n\n      this._resetTransformEventData(e);\n    },\n\n    /**\n     * Return a the id of an event.\n     * returns either the pointerId or the identifier or 0 for the mouse event\n     * @private\n     * @param {Event} evt Event object\n     */\n    getPointerId: function (evt) {\n      var changedTouches = evt.changedTouches;\n\n      if (changedTouches) {\n        return changedTouches[0] && changedTouches[0].identifier;\n      }\n\n      if (this.enablePointerEvents) {\n        return evt.pointerId;\n      }\n\n      return -1;\n    },\n\n    /**\n     * Determines if an event has the id of the event that is considered main\n     * @private\n     * @param {evt} event Event object\n     */\n    _isMainEvent: function (evt) {\n      if (evt.isPrimary === true) {\n        return true;\n      }\n\n      if (evt.isPrimary === false) {\n        return false;\n      }\n\n      if (evt.type === 'touchend' && evt.touches.length === 0) {\n        return true;\n      }\n\n      if (evt.changedTouches) {\n        return evt.changedTouches[0].identifier === this.mainTouchId;\n      }\n\n      return true;\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onTouchStart: function (e) {\n      e.preventDefault();\n\n      if (this.mainTouchId === null) {\n        this.mainTouchId = this.getPointerId(e);\n      }\n\n      this.__onMouseDown(e);\n\n      this._resetTransformEventData();\n\n      var canvasElement = this.upperCanvasEl,\n          eventTypePrefix = this._getEventPrefix();\n\n      addListener(fabric.document, 'touchend', this._onTouchEnd, addEventOptions);\n      addListener(fabric.document, 'touchmove', this._onMouseMove, addEventOptions); // Unbind mousedown to prevent double triggers from touch devices\n\n      removeListener(canvasElement, eventTypePrefix + 'down', this._onMouseDown);\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onMouseDown: function (e) {\n      this.__onMouseDown(e);\n\n      this._resetTransformEventData();\n\n      var canvasElement = this.upperCanvasEl,\n          eventTypePrefix = this._getEventPrefix();\n\n      removeListener(canvasElement, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n      addListener(fabric.document, eventTypePrefix + 'up', this._onMouseUp);\n      addListener(fabric.document, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onTouchEnd: function (e) {\n      if (e.touches.length > 0) {\n        // if there are still touches stop here\n        return;\n      }\n\n      this.__onMouseUp(e);\n\n      this._resetTransformEventData();\n\n      this.mainTouchId = null;\n\n      var eventTypePrefix = this._getEventPrefix();\n\n      removeListener(fabric.document, 'touchend', this._onTouchEnd, addEventOptions);\n      removeListener(fabric.document, 'touchmove', this._onMouseMove, addEventOptions);\n\n      var _this = this;\n\n      if (this._willAddMouseDown) {\n        clearTimeout(this._willAddMouseDown);\n      }\n\n      this._willAddMouseDown = setTimeout(function () {\n        // Wait 400ms before rebinding mousedown to prevent double triggers\n        // from touch devices\n        addListener(_this.upperCanvasEl, eventTypePrefix + 'down', _this._onMouseDown);\n        _this._willAddMouseDown = 0;\n      }, 400);\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mouseup\n     */\n    _onMouseUp: function (e) {\n      this.__onMouseUp(e);\n\n      this._resetTransformEventData();\n\n      var canvasElement = this.upperCanvasEl,\n          eventTypePrefix = this._getEventPrefix();\n\n      if (this._isMainEvent(e)) {\n        removeListener(fabric.document, eventTypePrefix + 'up', this._onMouseUp);\n        removeListener(fabric.document, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n        addListener(canvasElement, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n      }\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousemove\n     */\n    _onMouseMove: function (e) {\n      !this.allowTouchScrolling && e.preventDefault && e.preventDefault();\n\n      this.__onMouseMove(e);\n    },\n\n    /**\n     * @private\n     */\n    _onResize: function () {\n      this.calcOffset();\n    },\n\n    /**\n     * Decides whether the canvas should be redrawn in mouseup and mousedown events.\n     * @private\n     * @param {Object} target\n     */\n    _shouldRender: function (target) {\n      var activeObject = this._activeObject;\n\n      if (!!activeObject !== !!target || activeObject && target && activeObject !== target) {\n        // this covers: switch of target, from target to no target, selection of target\n        // multiSelection with key and mouse\n        return true;\n      } else if (activeObject && activeObject.isEditing) {\n        // if we mouse up/down over a editing textbox a cursor change,\n        // there is no need to re render\n        return false;\n      }\n\n      return false;\n    },\n\n    /**\n     * Method that defines the actions when mouse is released on canvas.\n     * The method resets the currentTransform parameters, store the image corner\n     * position in the image object and render the canvas on top.\n     * @private\n     * @param {Event} e Event object fired on mouseup\n     */\n    __onMouseUp: function (e) {\n      var target,\n          transform = this._currentTransform,\n          groupSelector = this._groupSelector,\n          shouldRender = false,\n          isClick = !groupSelector || groupSelector.left === 0 && groupSelector.top === 0;\n\n      this._cacheTransformEventData(e);\n\n      target = this._target;\n\n      this._handleEvent(e, 'up:before'); // if right/middle click just fire events and return\n      // target undefined will make the _handleEvent search the target\n\n\n      if (checkClick(e, RIGHT_CLICK)) {\n        if (this.fireRightClick) {\n          this._handleEvent(e, 'up', RIGHT_CLICK, isClick);\n        }\n\n        return;\n      }\n\n      if (checkClick(e, MIDDLE_CLICK)) {\n        if (this.fireMiddleClick) {\n          this._handleEvent(e, 'up', MIDDLE_CLICK, isClick);\n        }\n\n        this._resetTransformEventData();\n\n        return;\n      }\n\n      if (this.isDrawingMode && this._isCurrentlyDrawing) {\n        this._onMouseUpInDrawingMode(e);\n\n        return;\n      }\n\n      if (!this._isMainEvent(e)) {\n        return;\n      }\n\n      if (transform) {\n        this._finalizeCurrentTransform(e);\n\n        shouldRender = transform.actionPerformed;\n      }\n\n      if (!isClick) {\n        var targetWasActive = target === this._activeObject;\n\n        this._maybeGroupObjects(e);\n\n        if (!shouldRender) {\n          shouldRender = this._shouldRender(target) || !targetWasActive && target === this._activeObject;\n        }\n      }\n\n      if (target) {\n        var corner = target._findTargetCorner(this.getPointer(e, true), fabric.util.isTouchEvent(e));\n\n        var control = target.controls[corner],\n            mouseUpHandler = control && control.getMouseUpHandler(e, target, control);\n\n        if (mouseUpHandler) {\n          mouseUpHandler(e, target, control);\n        }\n\n        target.isMoving = false;\n      }\n\n      this._setCursorFromEvent(e, target);\n\n      this._handleEvent(e, 'up', LEFT_CLICK, isClick);\n\n      this._groupSelector = null;\n      this._currentTransform = null; // reset the target information about which corner is selected\n\n      target && (target.__corner = 0);\n\n      if (shouldRender) {\n        this.requestRenderAll();\n      } else if (!isClick) {\n        this.renderTop();\n      }\n    },\n\n    /**\n     * @private\n     * Handle event firing for target and subtargets\n     * @param {Event} e event from mouse\n     * @param {String} eventType event to fire (up, down or move)\n     * @return {Fabric.Object} target return the the target found, for internal reasons.\n     */\n    _simpleEventHandler: function (eventType, e) {\n      var target = this.findTarget(e),\n          targets = this.targets,\n          options = {\n        e: e,\n        target: target,\n        subTargets: targets\n      };\n      this.fire(eventType, options);\n      target && target.fire(eventType, options);\n\n      if (!targets) {\n        return target;\n      }\n\n      for (var i = 0; i < targets.length; i++) {\n        targets[i].fire(eventType, options);\n      }\n\n      return target;\n    },\n\n    /**\n     * @private\n     * Handle event firing for target and subtargets\n     * @param {Event} e event from mouse\n     * @param {String} eventType event to fire (up, down or move)\n     * @param {fabric.Object} targetObj receiving event\n     * @param {Number} [button] button used in the event 1 = left, 2 = middle, 3 = right\n     * @param {Boolean} isClick for left button only, indicates that the mouse up happened without move.\n     */\n    _handleEvent: function (e, eventType, button, isClick) {\n      var target = this._target,\n          targets = this.targets || [],\n          options = {\n        e: e,\n        target: target,\n        subTargets: targets,\n        button: button || LEFT_CLICK,\n        isClick: isClick || false,\n        pointer: this._pointer,\n        absolutePointer: this._absolutePointer,\n        transform: this._currentTransform\n      };\n\n      if (eventType === 'up') {\n        options.currentTarget = this.findTarget(e);\n        options.currentSubTargets = this.targets;\n      }\n\n      this.fire('mouse:' + eventType, options);\n      target && target.fire('mouse' + eventType, options);\n\n      for (var i = 0; i < targets.length; i++) {\n        targets[i].fire('mouse' + eventType, options);\n      }\n    },\n\n    /**\n     * @private\n     * @param {Event} e send the mouse event that generate the finalize down, so it can be used in the event\n     */\n    _finalizeCurrentTransform: function (e) {\n      var transform = this._currentTransform,\n          target = transform.target,\n          eventName,\n          options = {\n        e: e,\n        target: target,\n        transform: transform,\n        action: transform.action\n      };\n\n      if (target._scaling) {\n        target._scaling = false;\n      }\n\n      target.setCoords();\n\n      if (transform.actionPerformed || this.stateful && target.hasStateChanged()) {\n        if (transform.actionPerformed) {\n          // this is not friendly to the new control api.\n          // is deprecated.\n          eventName = this._addEventOptions(options, transform);\n\n          this._fire(eventName, options);\n        }\n\n        this._fire('modified', options);\n      }\n    },\n\n    /**\n     * Mutate option object in order to add by property and give back the event name.\n     * @private\n     * @deprecated since 4.2.0\n     * @param {Object} options to mutate\n     * @param {Object} transform to inspect action from\n     */\n    _addEventOptions: function (options, transform) {\n      // we can probably add more details at low cost\n      // scale change, rotation changes, translation changes\n      var eventName, by;\n\n      switch (transform.action) {\n        case 'scaleX':\n          eventName = 'scaled';\n          by = 'x';\n          break;\n\n        case 'scaleY':\n          eventName = 'scaled';\n          by = 'y';\n          break;\n\n        case 'skewX':\n          eventName = 'skewed';\n          by = 'x';\n          break;\n\n        case 'skewY':\n          eventName = 'skewed';\n          by = 'y';\n          break;\n\n        case 'scale':\n          eventName = 'scaled';\n          by = 'equally';\n          break;\n\n        case 'rotate':\n          eventName = 'rotated';\n          break;\n\n        case 'drag':\n          eventName = 'moved';\n          break;\n      }\n\n      options.by = by;\n      return eventName;\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onMouseDownInDrawingMode: function (e) {\n      this._isCurrentlyDrawing = true;\n\n      if (this.getActiveObject()) {\n        this.discardActiveObject(e).requestRenderAll();\n      }\n\n      var pointer = this.getPointer(e);\n      this.freeDrawingBrush.onMouseDown(pointer, {\n        e: e,\n        pointer: pointer\n      });\n\n      this._handleEvent(e, 'down');\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousemove\n     */\n    _onMouseMoveInDrawingMode: function (e) {\n      if (this._isCurrentlyDrawing) {\n        var pointer = this.getPointer(e);\n        this.freeDrawingBrush.onMouseMove(pointer, {\n          e: e,\n          pointer: pointer\n        });\n      }\n\n      this.setCursor(this.freeDrawingCursor);\n\n      this._handleEvent(e, 'move');\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mouseup\n     */\n    _onMouseUpInDrawingMode: function (e) {\n      var pointer = this.getPointer(e);\n      this._isCurrentlyDrawing = this.freeDrawingBrush.onMouseUp({\n        e: e,\n        pointer: pointer\n      });\n\n      this._handleEvent(e, 'up');\n    },\n\n    /**\n     * Method that defines the actions when mouse is clicked on canvas.\n     * The method inits the currentTransform parameters and renders all the\n     * canvas so the current image can be placed on the top canvas and the rest\n     * in on the container one.\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    __onMouseDown: function (e) {\n      this._cacheTransformEventData(e);\n\n      this._handleEvent(e, 'down:before');\n\n      var target = this._target; // if right click just fire events\n\n      if (checkClick(e, RIGHT_CLICK)) {\n        if (this.fireRightClick) {\n          this._handleEvent(e, 'down', RIGHT_CLICK);\n        }\n\n        return;\n      }\n\n      if (checkClick(e, MIDDLE_CLICK)) {\n        if (this.fireMiddleClick) {\n          this._handleEvent(e, 'down', MIDDLE_CLICK);\n        }\n\n        return;\n      }\n\n      if (this.isDrawingMode) {\n        this._onMouseDownInDrawingMode(e);\n\n        return;\n      }\n\n      if (!this._isMainEvent(e)) {\n        return;\n      } // ignore if some object is being transformed at this moment\n\n\n      if (this._currentTransform) {\n        return;\n      }\n\n      var pointer = this._pointer; // save pointer for check in __onMouseUp event\n\n      this._previousPointer = pointer;\n\n      var shouldRender = this._shouldRender(target),\n          shouldGroup = this._shouldGroup(e, target);\n\n      if (this._shouldClearSelection(e, target)) {\n        this.discardActiveObject(e);\n      } else if (shouldGroup) {\n        this._handleGrouping(e, target);\n\n        target = this._activeObject;\n      }\n\n      if (this.selection && (!target || !target.selectable && !target.isEditing && target !== this._activeObject)) {\n        this._groupSelector = {\n          ex: pointer.x,\n          ey: pointer.y,\n          top: 0,\n          left: 0\n        };\n      }\n\n      if (target) {\n        var alreadySelected = target === this._activeObject;\n\n        if (target.selectable) {\n          this.setActiveObject(target, e);\n        }\n\n        var corner = target._findTargetCorner(this.getPointer(e, true), fabric.util.isTouchEvent(e));\n\n        target.__corner = corner;\n\n        if (target === this._activeObject && (corner || !shouldGroup)) {\n          var control = target.controls[corner],\n              mouseDownHandler = control && control.getMouseDownHandler(e, target, control);\n\n          if (mouseDownHandler) {\n            mouseDownHandler(e, target, control);\n          }\n\n          this._setupCurrentTransform(e, target, alreadySelected);\n        }\n      }\n\n      this._handleEvent(e, 'down'); // we must renderAll so that we update the visuals\n\n\n      (shouldRender || shouldGroup) && this.requestRenderAll();\n    },\n\n    /**\n     * reset cache form common information needed during event processing\n     * @private\n     */\n    _resetTransformEventData: function () {\n      this._target = null;\n      this._pointer = null;\n      this._absolutePointer = null;\n    },\n\n    /**\n     * Cache common information needed during event processing\n     * @private\n     * @param {Event} e Event object fired on event\n     */\n    _cacheTransformEventData: function (e) {\n      // reset in order to avoid stale caching\n      this._resetTransformEventData();\n\n      this._pointer = this.getPointer(e, true);\n      this._absolutePointer = this.restorePointerVpt(this._pointer);\n      this._target = this._currentTransform ? this._currentTransform.target : this.findTarget(e) || null;\n    },\n\n    /**\n     * @private\n     */\n    _beforeTransform: function (e) {\n      var t = this._currentTransform;\n      this.stateful && t.target.saveState();\n      this.fire('before:transform', {\n        e: e,\n        transform: t\n      });\n    },\n\n    /**\n     * Method that defines the actions when mouse is hovering the canvas.\n     * The currentTransform parameter will define whether the user is rotating/scaling/translating\n     * an image or neither of them (only hovering). A group selection is also possible and would cancel\n     * all any other type of action.\n     * In case of an image transformation only the top canvas will be rendered.\n     * @private\n     * @param {Event} e Event object fired on mousemove\n     */\n    __onMouseMove: function (e) {\n      this._handleEvent(e, 'move:before');\n\n      this._cacheTransformEventData(e);\n\n      var target, pointer;\n\n      if (this.isDrawingMode) {\n        this._onMouseMoveInDrawingMode(e);\n\n        return;\n      }\n\n      if (!this._isMainEvent(e)) {\n        return;\n      }\n\n      var groupSelector = this._groupSelector; // We initially clicked in an empty area, so we draw a box for multiple selection\n\n      if (groupSelector) {\n        pointer = this._pointer;\n        groupSelector.left = pointer.x - groupSelector.ex;\n        groupSelector.top = pointer.y - groupSelector.ey;\n        this.renderTop();\n      } else if (!this._currentTransform) {\n        target = this.findTarget(e) || null;\n\n        this._setCursorFromEvent(e, target);\n\n        this._fireOverOutEvents(target, e);\n      } else {\n        this._transformObject(e);\n      }\n\n      this._handleEvent(e, 'move');\n\n      this._resetTransformEventData();\n    },\n\n    /**\n     * Manage the mouseout, mouseover events for the fabric object on the canvas\n     * @param {Fabric.Object} target the target where the target from the mousemove event\n     * @param {Event} e Event object fired on mousemove\n     * @private\n     */\n    _fireOverOutEvents: function (target, e) {\n      var _hoveredTarget = this._hoveredTarget,\n          _hoveredTargets = this._hoveredTargets,\n          targets = this.targets,\n          length = Math.max(_hoveredTargets.length, targets.length);\n      this.fireSyntheticInOutEvents(target, e, {\n        oldTarget: _hoveredTarget,\n        evtOut: 'mouseout',\n        canvasEvtOut: 'mouse:out',\n        evtIn: 'mouseover',\n        canvasEvtIn: 'mouse:over'\n      });\n\n      for (var i = 0; i < length; i++) {\n        this.fireSyntheticInOutEvents(targets[i], e, {\n          oldTarget: _hoveredTargets[i],\n          evtOut: 'mouseout',\n          evtIn: 'mouseover'\n        });\n      }\n\n      this._hoveredTarget = target;\n      this._hoveredTargets = this.targets.concat();\n    },\n\n    /**\n     * Manage the dragEnter, dragLeave events for the fabric objects on the canvas\n     * @param {Fabric.Object} target the target where the target from the onDrag event\n     * @param {Event} e Event object fired on ondrag\n     * @private\n     */\n    _fireEnterLeaveEvents: function (target, e) {\n      var _draggedoverTarget = this._draggedoverTarget,\n          _hoveredTargets = this._hoveredTargets,\n          targets = this.targets,\n          length = Math.max(_hoveredTargets.length, targets.length);\n      this.fireSyntheticInOutEvents(target, e, {\n        oldTarget: _draggedoverTarget,\n        evtOut: 'dragleave',\n        evtIn: 'dragenter'\n      });\n\n      for (var i = 0; i < length; i++) {\n        this.fireSyntheticInOutEvents(targets[i], e, {\n          oldTarget: _hoveredTargets[i],\n          evtOut: 'dragleave',\n          evtIn: 'dragenter'\n        });\n      }\n\n      this._draggedoverTarget = target;\n    },\n\n    /**\n     * Manage the synthetic in/out events for the fabric objects on the canvas\n     * @param {Fabric.Object} target the target where the target from the supported events\n     * @param {Event} e Event object fired\n     * @param {Object} config configuration for the function to work\n     * @param {String} config.targetName property on the canvas where the old target is stored\n     * @param {String} [config.canvasEvtOut] name of the event to fire at canvas level for out\n     * @param {String} config.evtOut name of the event to fire for out\n     * @param {String} [config.canvasEvtIn] name of the event to fire at canvas level for in\n     * @param {String} config.evtIn name of the event to fire for in\n     * @private\n     */\n    fireSyntheticInOutEvents: function (target, e, config) {\n      var inOpt,\n          outOpt,\n          oldTarget = config.oldTarget,\n          outFires,\n          inFires,\n          targetChanged = oldTarget !== target,\n          canvasEvtIn = config.canvasEvtIn,\n          canvasEvtOut = config.canvasEvtOut;\n\n      if (targetChanged) {\n        inOpt = {\n          e: e,\n          target: target,\n          previousTarget: oldTarget\n        };\n        outOpt = {\n          e: e,\n          target: oldTarget,\n          nextTarget: target\n        };\n      }\n\n      inFires = target && targetChanged;\n      outFires = oldTarget && targetChanged;\n\n      if (outFires) {\n        canvasEvtOut && this.fire(canvasEvtOut, outOpt);\n        oldTarget.fire(config.evtOut, outOpt);\n      }\n\n      if (inFires) {\n        canvasEvtIn && this.fire(canvasEvtIn, inOpt);\n        target.fire(config.evtIn, inOpt);\n      }\n    },\n\n    /**\n     * Method that defines actions when an Event Mouse Wheel\n     * @param {Event} e Event object fired on mouseup\n     */\n    __onMouseWheel: function (e) {\n      this._cacheTransformEventData(e);\n\n      this._handleEvent(e, 'wheel');\n\n      this._resetTransformEventData();\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event fired on mousemove\n     */\n    _transformObject: function (e) {\n      var pointer = this.getPointer(e),\n          transform = this._currentTransform;\n      transform.reset = false;\n      transform.target.isMoving = true;\n      transform.shiftKey = e.shiftKey;\n      transform.altKey = e[this.centeredKey];\n\n      this._performTransformAction(e, transform, pointer);\n\n      transform.actionPerformed && this.requestRenderAll();\n    },\n\n    /**\n     * @private\n     */\n    _performTransformAction: function (e, transform, pointer) {\n      var x = pointer.x,\n          y = pointer.y,\n          action = transform.action,\n          actionPerformed = false,\n          actionHandler = transform.actionHandler; // this object could be created from the function in the control handlers\n\n      if (actionHandler) {\n        actionPerformed = actionHandler(e, transform, x, y);\n      }\n\n      if (action === 'drag' && actionPerformed) {\n        this.setCursor(transform.target.moveCursor || this.moveCursor);\n      }\n\n      transform.actionPerformed = transform.actionPerformed || actionPerformed;\n    },\n\n    /**\n     * @private\n     */\n    _fire: fabric.controlsUtils.fireEvent,\n\n    /**\n     * Sets the cursor depending on where the canvas is being hovered.\n     * Note: very buggy in Opera\n     * @param {Event} e Event object\n     * @param {Object} target Object that the mouse is hovering, if so.\n     */\n    _setCursorFromEvent: function (e, target) {\n      if (!target) {\n        this.setCursor(this.defaultCursor);\n        return false;\n      }\n\n      var hoverCursor = target.hoverCursor || this.hoverCursor,\n          activeSelection = this._activeObject && this._activeObject.type === 'activeSelection' ? this._activeObject : null,\n          // only show proper corner when group selection is not active\n      corner = (!activeSelection || !activeSelection.contains(target)) && // here we call findTargetCorner always with undefined for the touch parameter.\n      // we assume that if you are using a cursor you do not need to interact with\n      // the bigger touch area.\n      target._findTargetCorner(this.getPointer(e, true));\n\n      if (!corner) {\n        if (target.subTargetCheck) {\n          // hoverCursor should come from top-most subTarget,\n          // so we walk the array backwards\n          this.targets.concat().reverse().map(function (_target) {\n            hoverCursor = _target.hoverCursor || hoverCursor;\n          });\n        }\n\n        this.setCursor(hoverCursor);\n      } else {\n        this.setCursor(this.getCornerCursor(corner, target, e));\n      }\n    },\n\n    /**\n     * @private\n     */\n    getCornerCursor: function (corner, target, e) {\n      var control = target.controls[corner];\n      return control.cursorStyleHandler(e, control, target);\n    }\n  });\n})();\n\n(function () {\n  var min = Math.min,\n      max = Math.max;\n  fabric.util.object.extend(fabric.Canvas.prototype,\n  /** @lends fabric.Canvas.prototype */\n  {\n    /**\n     * @private\n     * @param {Event} e Event object\n     * @param {fabric.Object} target\n     * @return {Boolean}\n     */\n    _shouldGroup: function (e, target) {\n      var activeObject = this._activeObject;\n      return activeObject && this._isSelectionKeyPressed(e) && target && target.selectable && this.selection && (activeObject !== target || activeObject.type === 'activeSelection') && !target.onSelect({\n        e: e\n      });\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object\n     * @param {fabric.Object} target\n     */\n    _handleGrouping: function (e, target) {\n      var activeObject = this._activeObject; // avoid multi select when shift click on a corner\n\n      if (activeObject.__corner) {\n        return;\n      }\n\n      if (target === activeObject) {\n        // if it's a group, find target again, using activeGroup objects\n        target = this.findTarget(e, true); // if even object is not found or we are on activeObjectCorner, bail out\n\n        if (!target || !target.selectable) {\n          return;\n        }\n      }\n\n      if (activeObject && activeObject.type === 'activeSelection') {\n        this._updateActiveSelection(target, e);\n      } else {\n        this._createActiveSelection(target, e);\n      }\n    },\n\n    /**\n     * @private\n     */\n    _updateActiveSelection: function (target, e) {\n      var activeSelection = this._activeObject,\n          currentActiveObjects = activeSelection._objects.slice(0);\n\n      if (activeSelection.contains(target)) {\n        activeSelection.removeWithUpdate(target);\n        this._hoveredTarget = target;\n        this._hoveredTargets = this.targets.concat();\n\n        if (activeSelection.size() === 1) {\n          // activate last remaining object\n          this._setActiveObject(activeSelection.item(0), e);\n        }\n      } else {\n        activeSelection.addWithUpdate(target);\n        this._hoveredTarget = activeSelection;\n        this._hoveredTargets = this.targets.concat();\n      }\n\n      this._fireSelectionEvents(currentActiveObjects, e);\n    },\n\n    /**\n     * @private\n     */\n    _createActiveSelection: function (target, e) {\n      var currentActives = this.getActiveObjects(),\n          group = this._createGroup(target);\n\n      this._hoveredTarget = group; // ISSUE 4115: should we consider subTargets here?\n      // this._hoveredTargets = [];\n      // this._hoveredTargets = this.targets.concat();\n\n      this._setActiveObject(group, e);\n\n      this._fireSelectionEvents(currentActives, e);\n    },\n\n    /**\n     * @private\n     * @param {Object} target\n     */\n    _createGroup: function (target) {\n      var objects = this._objects,\n          isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target),\n          groupObjects = isActiveLower ? [this._activeObject, target] : [target, this._activeObject];\n      this._activeObject.isEditing && this._activeObject.exitEditing();\n      return new fabric.ActiveSelection(groupObjects, {\n        canvas: this\n      });\n    },\n\n    /**\n     * @private\n     * @param {Event} e mouse event\n     */\n    _groupSelectedObjects: function (e) {\n      var group = this._collectObjects(e),\n          aGroup; // do not create group for 1 element only\n\n\n      if (group.length === 1) {\n        this.setActiveObject(group[0], e);\n      } else if (group.length > 1) {\n        aGroup = new fabric.ActiveSelection(group.reverse(), {\n          canvas: this\n        });\n        this.setActiveObject(aGroup, e);\n      }\n    },\n\n    /**\n     * @private\n     */\n    _collectObjects: function (e) {\n      var group = [],\n          currentObject,\n          x1 = this._groupSelector.ex,\n          y1 = this._groupSelector.ey,\n          x2 = x1 + this._groupSelector.left,\n          y2 = y1 + this._groupSelector.top,\n          selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)),\n          selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)),\n          allowIntersect = !this.selectionFullyContained,\n          isClick = x1 === x2 && y1 === y2; // we iterate reverse order to collect top first in case of click.\n\n      for (var i = this._objects.length; i--;) {\n        currentObject = this._objects[i];\n\n        if (!currentObject || !currentObject.selectable || !currentObject.visible) {\n          continue;\n        }\n\n        if (allowIntersect && currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2) || currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) || allowIntersect && currentObject.containsPoint(selectionX1Y1) || allowIntersect && currentObject.containsPoint(selectionX2Y2)) {\n          group.push(currentObject); // only add one object if it's a click\n\n          if (isClick) {\n            break;\n          }\n        }\n      }\n\n      if (group.length > 1) {\n        group = group.filter(function (object) {\n          return !object.onSelect({\n            e: e\n          });\n        });\n      }\n\n      return group;\n    },\n\n    /**\n     * @private\n     */\n    _maybeGroupObjects: function (e) {\n      if (this.selection && this._groupSelector) {\n        this._groupSelectedObjects(e);\n      }\n\n      this.setCursor(this.defaultCursor); // clear selection and current transformation\n\n      this._groupSelector = null;\n    }\n  });\n})();\n\n(function () {\n  fabric.util.object.extend(fabric.StaticCanvas.prototype,\n  /** @lends fabric.StaticCanvas.prototype */\n  {\n    /**\n     * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately\n     * @param {Object} [options] Options object\n     * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\n     * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\n     * @param {Number} [options.multiplier=1] Multiplier to scale by, to have consistent\n     * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n     * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n     * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n     * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n     * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 2.0.0\n     * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format\n     * @see {@link http://jsfiddle.net/fabricjs/NfZVb/|jsFiddle demo}\n     * @example <caption>Generate jpeg dataURL with lower quality</caption>\n     * var dataURL = canvas.toDataURL({\n     *   format: 'jpeg',\n     *   quality: 0.8\n     * });\n     * @example <caption>Generate cropped png dataURL (clipping of canvas)</caption>\n     * var dataURL = canvas.toDataURL({\n     *   format: 'png',\n     *   left: 100,\n     *   top: 100,\n     *   width: 200,\n     *   height: 200\n     * });\n     * @example <caption>Generate double scaled png dataURL</caption>\n     * var dataURL = canvas.toDataURL({\n     *   format: 'png',\n     *   multiplier: 2\n     * });\n     */\n    toDataURL: function (options) {\n      options || (options = {});\n      var format = options.format || 'png',\n          quality = options.quality || 1,\n          multiplier = (options.multiplier || 1) * (options.enableRetinaScaling ? this.getRetinaScaling() : 1),\n          canvasEl = this.toCanvasElement(multiplier, options);\n      return fabric.util.toDataURL(canvasEl, format, quality);\n    },\n\n    /**\n     * Create a new HTMLCanvas element painted with the current canvas content.\n     * No need to resize the actual one or repaint it.\n     * Will transfer object ownership to a new canvas, paint it, and set everything back.\n     * This is an intermediary step used to get to a dataUrl but also it is useful to\n     * create quick image copies of a canvas without passing for the dataUrl string\n     * @param {Number} [multiplier] a zoom factor.\n     * @param {Object} [cropping] Cropping informations\n     * @param {Number} [cropping.left] Cropping left offset.\n     * @param {Number} [cropping.top] Cropping top offset.\n     * @param {Number} [cropping.width] Cropping width.\n     * @param {Number} [cropping.height] Cropping height.\n     */\n    toCanvasElement: function (multiplier, cropping) {\n      multiplier = multiplier || 1;\n      cropping = cropping || {};\n      var scaledWidth = (cropping.width || this.width) * multiplier,\n          scaledHeight = (cropping.height || this.height) * multiplier,\n          zoom = this.getZoom(),\n          originalWidth = this.width,\n          originalHeight = this.height,\n          newZoom = zoom * multiplier,\n          vp = this.viewportTransform,\n          translateX = (vp[4] - (cropping.left || 0)) * multiplier,\n          translateY = (vp[5] - (cropping.top || 0)) * multiplier,\n          originalInteractive = this.interactive,\n          newVp = [newZoom, 0, 0, newZoom, translateX, translateY],\n          originalRetina = this.enableRetinaScaling,\n          canvasEl = fabric.util.createCanvasElement(),\n          originalContextTop = this.contextTop;\n      canvasEl.width = scaledWidth;\n      canvasEl.height = scaledHeight;\n      this.contextTop = null;\n      this.enableRetinaScaling = false;\n      this.interactive = false;\n      this.viewportTransform = newVp;\n      this.width = scaledWidth;\n      this.height = scaledHeight;\n      this.calcViewportBoundaries();\n      this.renderCanvas(canvasEl.getContext('2d'), this._objects);\n      this.viewportTransform = vp;\n      this.width = originalWidth;\n      this.height = originalHeight;\n      this.calcViewportBoundaries();\n      this.interactive = originalInteractive;\n      this.enableRetinaScaling = originalRetina;\n      this.contextTop = originalContextTop;\n      return canvasEl;\n    }\n  });\n})();\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype,\n/** @lends fabric.StaticCanvas.prototype */\n{\n  /**\n   * Populates canvas with data from the specified JSON.\n   * JSON format must conform to the one of {@link fabric.Canvas#toJSON}\n   * @param {String|Object} json JSON string or object\n   * @param {Function} callback Callback, invoked when json is parsed\n   *                            and corresponding objects (e.g: {@link fabric.Image})\n   *                            are initialized\n   * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created.\n   * @return {fabric.Canvas} instance\n   * @chainable\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#deserialization}\n   * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo}\n   * @example <caption>loadFromJSON</caption>\n   * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));\n   * @example <caption>loadFromJSON with reviver</caption>\n   * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas), function(o, object) {\n   *   // `o` = json object\n   *   // `object` = fabric.Object instance\n   *   // ... do some stuff ...\n   * });\n   */\n  loadFromJSON: function (json, callback, reviver) {\n    if (!json) {\n      return;\n    } // serialize if it wasn't already\n\n\n    var serialized = typeof json === 'string' ? JSON.parse(json) : fabric.util.object.clone(json);\n\n    var _this = this,\n        clipPath = serialized.clipPath,\n        renderOnAddRemove = this.renderOnAddRemove;\n\n    this.renderOnAddRemove = false;\n    delete serialized.clipPath;\n\n    this._enlivenObjects(serialized.objects, function (enlivenedObjects) {\n      _this.clear();\n\n      _this._setBgOverlay(serialized, function () {\n        if (clipPath) {\n          _this._enlivenObjects([clipPath], function (enlivenedCanvasClip) {\n            _this.clipPath = enlivenedCanvasClip[0];\n\n            _this.__setupCanvas.call(_this, serialized, enlivenedObjects, renderOnAddRemove, callback);\n          });\n        } else {\n          _this.__setupCanvas.call(_this, serialized, enlivenedObjects, renderOnAddRemove, callback);\n        }\n      });\n    }, reviver);\n\n    return this;\n  },\n\n  /**\n   * @private\n   * @param {Object} serialized Object with background and overlay information\n   * @param {Array} restored canvas objects\n   * @param {Function} cached renderOnAddRemove callback\n   * @param {Function} callback Invoked after all background and overlay images/patterns loaded\n   */\n  __setupCanvas: function (serialized, enlivenedObjects, renderOnAddRemove, callback) {\n    var _this = this;\n\n    enlivenedObjects.forEach(function (obj, index) {\n      // we splice the array just in case some custom classes restored from JSON\n      // will add more object to canvas at canvas init.\n      _this.insertAt(obj, index);\n    });\n    this.renderOnAddRemove = renderOnAddRemove; // remove parts i cannot set as options\n\n    delete serialized.objects;\n    delete serialized.backgroundImage;\n    delete serialized.overlayImage;\n    delete serialized.background;\n    delete serialized.overlay; // this._initOptions does too many things to just\n    // call it. Normally loading an Object from JSON\n    // create the Object instance. Here the Canvas is\n    // already an instance and we are just loading things over it\n\n    this._setOptions(serialized);\n\n    this.renderAll();\n    callback && callback();\n  },\n\n  /**\n   * @private\n   * @param {Object} serialized Object with background and overlay information\n   * @param {Function} callback Invoked after all background and overlay images/patterns loaded\n   */\n  _setBgOverlay: function (serialized, callback) {\n    var loaded = {\n      backgroundColor: false,\n      overlayColor: false,\n      backgroundImage: false,\n      overlayImage: false\n    };\n\n    if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background && !serialized.overlay) {\n      callback && callback();\n      return;\n    }\n\n    var cbIfLoaded = function () {\n      if (loaded.backgroundImage && loaded.overlayImage && loaded.backgroundColor && loaded.overlayColor) {\n        callback && callback();\n      }\n    };\n\n    this.__setBgOverlay('backgroundImage', serialized.backgroundImage, loaded, cbIfLoaded);\n\n    this.__setBgOverlay('overlayImage', serialized.overlayImage, loaded, cbIfLoaded);\n\n    this.__setBgOverlay('backgroundColor', serialized.background, loaded, cbIfLoaded);\n\n    this.__setBgOverlay('overlayColor', serialized.overlay, loaded, cbIfLoaded);\n  },\n\n  /**\n   * @private\n   * @param {String} property Property to set (backgroundImage, overlayImage, backgroundColor, overlayColor)\n   * @param {(Object|String)} value Value to set\n   * @param {Object} loaded Set loaded property to true if property is set\n   * @param {Object} callback Callback function to invoke after property is set\n   */\n  __setBgOverlay: function (property, value, loaded, callback) {\n    var _this = this;\n\n    if (!value) {\n      loaded[property] = true;\n      callback && callback();\n      return;\n    }\n\n    if (property === 'backgroundImage' || property === 'overlayImage') {\n      fabric.util.enlivenObjects([value], function (enlivedObject) {\n        _this[property] = enlivedObject[0];\n        loaded[property] = true;\n        callback && callback();\n      });\n    } else {\n      this['set' + fabric.util.string.capitalize(property, true)](value, function () {\n        loaded[property] = true;\n        callback && callback();\n      });\n    }\n  },\n\n  /**\n   * @private\n   * @param {Array} objects\n   * @param {Function} callback\n   * @param {Function} [reviver]\n   */\n  _enlivenObjects: function (objects, callback, reviver) {\n    if (!objects || objects.length === 0) {\n      callback && callback([]);\n      return;\n    }\n\n    fabric.util.enlivenObjects(objects, function (enlivenedObjects) {\n      callback && callback(enlivenedObjects);\n    }, null, reviver);\n  },\n\n  /**\n   * @private\n   * @param {String} format\n   * @param {Function} callback\n   */\n  _toDataURL: function (format, callback) {\n    this.clone(function (clone) {\n      callback(clone.toDataURL(format));\n    });\n  },\n\n  /**\n   * @private\n   * @param {String} format\n   * @param {Number} multiplier\n   * @param {Function} callback\n   */\n  _toDataURLWithMultiplier: function (format, multiplier, callback) {\n    this.clone(function (clone) {\n      callback(clone.toDataURLWithMultiplier(format, multiplier));\n    });\n  },\n\n  /**\n   * Clones canvas instance\n   * @param {Object} [callback] Receives cloned instance as a first argument\n   * @param {Array} [properties] Array of properties to include in the cloned canvas and children\n   */\n  clone: function (callback, properties) {\n    var data = JSON.stringify(this.toJSON(properties));\n    this.cloneWithoutData(function (clone) {\n      clone.loadFromJSON(data, function () {\n        callback && callback(clone);\n      });\n    });\n  },\n\n  /**\n   * Clones canvas instance without cloning existing data.\n   * This essentially copies canvas dimensions, clipping properties, etc.\n   * but leaves data empty (so that you can populate it with your own)\n   * @param {Object} [callback] Receives cloned instance as a first argument\n   */\n  cloneWithoutData: function (callback) {\n    var el = fabric.util.createCanvasElement();\n    el.width = this.width;\n    el.height = this.height;\n    var clone = new fabric.Canvas(el);\n\n    if (this.backgroundImage) {\n      clone.setBackgroundImage(this.backgroundImage.src, function () {\n        clone.renderAll();\n        callback && callback(clone);\n      });\n      clone.backgroundImageOpacity = this.backgroundImageOpacity;\n      clone.backgroundImageStretch = this.backgroundImageStretch;\n    } else {\n      callback && callback(clone);\n    }\n  }\n});\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      extend = fabric.util.object.extend,\n      clone = fabric.util.object.clone,\n      toFixed = fabric.util.toFixed,\n      capitalize = fabric.util.string.capitalize,\n      degreesToRadians = fabric.util.degreesToRadians,\n      supportsLineDash = fabric.StaticCanvas.supports('setLineDash'),\n      objectCaching = !fabric.isLikelyNode,\n      ALIASING_LIMIT = 2;\n\n  if (fabric.Object) {\n    return;\n  }\n  /**\n   * Root object class from which all 2d shape classes inherit from\n   * @class fabric.Object\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#objects}\n   * @see {@link fabric.Object#initialize} for constructor definition\n   *\n   * @fires added\n   * @fires removed\n   *\n   * @fires selected\n   * @fires deselected\n   * @fires modified\n   * @fires modified\n   * @fires moved\n   * @fires scaled\n   * @fires rotated\n   * @fires skewed\n   *\n   * @fires rotating\n   * @fires scaling\n   * @fires moving\n   * @fires skewing\n   *\n   * @fires mousedown\n   * @fires mouseup\n   * @fires mouseover\n   * @fires mouseout\n   * @fires mousewheel\n   * @fires mousedblclick\n   *\n   * @fires dragover\n   * @fires dragenter\n   * @fires dragleave\n   * @fires drop\n   */\n\n\n  fabric.Object = fabric.util.createClass(fabric.CommonMethods,\n  /** @lends fabric.Object.prototype */\n  {\n    /**\n     * Type of an object (rect, circle, path, etc.).\n     * Note that this property is meant to be read-only and not meant to be modified.\n     * If you modify, certain parts of Fabric (such as JSON loading) won't work correctly.\n     * @type String\n     * @default\n     */\n    type: 'object',\n\n    /**\n     * Horizontal origin of transformation of an object (one of \"left\", \"right\", \"center\")\n     * See http://jsfiddle.net/1ow02gea/244/ on how originX/originY affect objects in groups\n     * @type String\n     * @default\n     */\n    originX: 'left',\n\n    /**\n     * Vertical origin of transformation of an object (one of \"top\", \"bottom\", \"center\")\n     * See http://jsfiddle.net/1ow02gea/244/ on how originX/originY affect objects in groups\n     * @type String\n     * @default\n     */\n    originY: 'top',\n\n    /**\n     * Top position of an object. Note that by default it's relative to object top. You can change this by setting originY={top/center/bottom}\n     * @type Number\n     * @default\n     */\n    top: 0,\n\n    /**\n     * Left position of an object. Note that by default it's relative to object left. You can change this by setting originX={left/center/right}\n     * @type Number\n     * @default\n     */\n    left: 0,\n\n    /**\n     * Object width\n     * @type Number\n     * @default\n     */\n    width: 0,\n\n    /**\n     * Object height\n     * @type Number\n     * @default\n     */\n    height: 0,\n\n    /**\n     * Object scale factor (horizontal)\n     * @type Number\n     * @default\n     */\n    scaleX: 1,\n\n    /**\n     * Object scale factor (vertical)\n     * @type Number\n     * @default\n     */\n    scaleY: 1,\n\n    /**\n     * When true, an object is rendered as flipped horizontally\n     * @type Boolean\n     * @default\n     */\n    flipX: false,\n\n    /**\n     * When true, an object is rendered as flipped vertically\n     * @type Boolean\n     * @default\n     */\n    flipY: false,\n\n    /**\n     * Opacity of an object\n     * @type Number\n     * @default\n     */\n    opacity: 1,\n\n    /**\n     * Angle of rotation of an object (in degrees)\n     * @type Number\n     * @default\n     */\n    angle: 0,\n\n    /**\n     * Angle of skew on x axes of an object (in degrees)\n     * @type Number\n     * @default\n     */\n    skewX: 0,\n\n    /**\n     * Angle of skew on y axes of an object (in degrees)\n     * @type Number\n     * @default\n     */\n    skewY: 0,\n\n    /**\n     * Size of object's controlling corners (in pixels)\n     * @type Number\n     * @default\n     */\n    cornerSize: 13,\n\n    /**\n     * Size of object's controlling corners when touch interaction is detected\n     * @type Number\n     * @default\n     */\n    touchCornerSize: 24,\n\n    /**\n     * When true, object's controlling corners are rendered as transparent inside (i.e. stroke instead of fill)\n     * @type Boolean\n     * @default\n     */\n    transparentCorners: true,\n\n    /**\n     * Default cursor value used when hovering over this object on canvas\n     * @type String\n     * @default\n     */\n    hoverCursor: null,\n\n    /**\n     * Default cursor value used when moving this object on canvas\n     * @type String\n     * @default\n     */\n    moveCursor: null,\n\n    /**\n     * Padding between object and its controlling borders (in pixels)\n     * @type Number\n     * @default\n     */\n    padding: 0,\n\n    /**\n     * Color of controlling borders of an object (when it's active)\n     * @type String\n     * @default\n     */\n    borderColor: 'rgb(178,204,255)',\n\n    /**\n     * Array specifying dash pattern of an object's borders (hasBorder must be true)\n     * @since 1.6.2\n     * @type Array\n     */\n    borderDashArray: null,\n\n    /**\n     * Color of controlling corners of an object (when it's active)\n     * @type String\n     * @default\n     */\n    cornerColor: 'rgb(178,204,255)',\n\n    /**\n     * Color of controlling corners of an object (when it's active and transparentCorners false)\n     * @since 1.6.2\n     * @type String\n     * @default\n     */\n    cornerStrokeColor: null,\n\n    /**\n     * Specify style of control, 'rect' or 'circle'\n     * @since 1.6.2\n     * @type String\n     */\n    cornerStyle: 'rect',\n\n    /**\n     * Array specifying dash pattern of an object's control (hasBorder must be true)\n     * @since 1.6.2\n     * @type Array\n     */\n    cornerDashArray: null,\n\n    /**\n     * When true, this object will use center point as the origin of transformation\n     * when being scaled via the controls.\n     * <b>Backwards incompatibility note:</b> This property replaces \"centerTransform\" (Boolean).\n     * @since 1.3.4\n     * @type Boolean\n     * @default\n     */\n    centeredScaling: false,\n\n    /**\n     * When true, this object will use center point as the origin of transformation\n     * when being rotated via the controls.\n     * <b>Backwards incompatibility note:</b> This property replaces \"centerTransform\" (Boolean).\n     * @since 1.3.4\n     * @type Boolean\n     * @default\n     */\n    centeredRotation: true,\n\n    /**\n     * Color of object's fill\n     * takes css colors https://www.w3.org/TR/css-color-3/\n     * @type String\n     * @default\n     */\n    fill: 'rgb(0,0,0)',\n\n    /**\n     * Fill rule used to fill an object\n     * accepted values are nonzero, evenodd\n     * <b>Backwards incompatibility note:</b> This property was used for setting globalCompositeOperation until v1.4.12 (use `fabric.Object#globalCompositeOperation` instead)\n     * @type String\n     * @default\n     */\n    fillRule: 'nonzero',\n\n    /**\n     * Composite rule used for canvas globalCompositeOperation\n     * @type String\n     * @default\n     */\n    globalCompositeOperation: 'source-over',\n\n    /**\n     * Background color of an object.\n     * takes css colors https://www.w3.org/TR/css-color-3/\n     * @type String\n     * @default\n     */\n    backgroundColor: '',\n\n    /**\n     * Selection Background color of an object. colored layer behind the object when it is active.\n     * does not mix good with globalCompositeOperation methods.\n     * @type String\n     * @default\n     */\n    selectionBackgroundColor: '',\n\n    /**\n     * When defined, an object is rendered via stroke and this property specifies its color\n     * takes css colors https://www.w3.org/TR/css-color-3/\n     * @type String\n     * @default\n     */\n    stroke: null,\n\n    /**\n     * Width of a stroke used to render this object\n     * @type Number\n     * @default\n     */\n    strokeWidth: 1,\n\n    /**\n     * Array specifying dash pattern of an object's stroke (stroke must be defined)\n     * @type Array\n     */\n    strokeDashArray: null,\n\n    /**\n     * Line offset of an object's stroke\n     * @type Number\n     * @default\n     */\n    strokeDashOffset: 0,\n\n    /**\n     * Line endings style of an object's stroke (one of \"butt\", \"round\", \"square\")\n     * @type String\n     * @default\n     */\n    strokeLineCap: 'butt',\n\n    /**\n     * Corner style of an object's stroke (one of \"bevil\", \"round\", \"miter\")\n     * @type String\n     * @default\n     */\n    strokeLineJoin: 'miter',\n\n    /**\n     * Maximum miter length (used for strokeLineJoin = \"miter\") of an object's stroke\n     * @type Number\n     * @default\n     */\n    strokeMiterLimit: 4,\n\n    /**\n     * Shadow object representing shadow of this shape\n     * @type fabric.Shadow\n     * @default\n     */\n    shadow: null,\n\n    /**\n     * Opacity of object's controlling borders when object is active and moving\n     * @type Number\n     * @default\n     */\n    borderOpacityWhenMoving: 0.4,\n\n    /**\n     * Scale factor of object's controlling borders\n     * bigger number will make a thicker border\n     * border is 1, so this is basically a border tickness\n     * since there is no way to change the border itself.\n     * @type Number\n     * @default\n     */\n    borderScaleFactor: 1,\n\n    /**\n     * Minimum allowed scale value of an object\n     * @type Number\n     * @default\n     */\n    minScaleLimit: 0,\n\n    /**\n     * When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection).\n     * But events still fire on it.\n     * @type Boolean\n     * @default\n     */\n    selectable: true,\n\n    /**\n     * When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4\n     * @type Boolean\n     * @default\n     */\n    evented: true,\n\n    /**\n     * When set to `false`, an object is not rendered on canvas\n     * @type Boolean\n     * @default\n     */\n    visible: true,\n\n    /**\n     * When set to `false`, object's controls are not displayed and can not be used to manipulate object\n     * @type Boolean\n     * @default\n     */\n    hasControls: true,\n\n    /**\n     * When set to `false`, object's controlling borders are not rendered\n     * @type Boolean\n     * @default\n     */\n    hasBorders: true,\n\n    /**\n     * When set to `true`, objects are \"found\" on canvas on per-pixel basis rather than according to bounding box\n     * @type Boolean\n     * @default\n     */\n    perPixelTargetFind: false,\n\n    /**\n     * When `false`, default object's values are not included in its serialization\n     * @type Boolean\n     * @default\n     */\n    includeDefaultValues: true,\n\n    /**\n     * When `true`, object horizontal movement is locked\n     * @type Boolean\n     * @default\n     */\n    lockMovementX: false,\n\n    /**\n     * When `true`, object vertical movement is locked\n     * @type Boolean\n     * @default\n     */\n    lockMovementY: false,\n\n    /**\n     * When `true`, object rotation is locked\n     * @type Boolean\n     * @default\n     */\n    lockRotation: false,\n\n    /**\n     * When `true`, object horizontal scaling is locked\n     * @type Boolean\n     * @default\n     */\n    lockScalingX: false,\n\n    /**\n     * When `true`, object vertical scaling is locked\n     * @type Boolean\n     * @default\n     */\n    lockScalingY: false,\n\n    /**\n     * When `true`, object horizontal skewing is locked\n     * @type Boolean\n     * @default\n     */\n    lockSkewingX: false,\n\n    /**\n     * When `true`, object vertical skewing is locked\n     * @type Boolean\n     * @default\n     */\n    lockSkewingY: false,\n\n    /**\n     * When `true`, object cannot be flipped by scaling into negative values\n     * @type Boolean\n     * @default\n     */\n    lockScalingFlip: false,\n\n    /**\n     * When `true`, object is not exported in OBJECT/JSON\n     * @since 1.6.3\n     * @type Boolean\n     * @default\n     */\n    excludeFromExport: false,\n\n    /**\n     * When `true`, object is cached on an additional canvas.\n     * When `false`, object is not cached unless necessary ( clipPath )\n     * default to true\n     * @since 1.7.0\n     * @type Boolean\n     * @default true\n     */\n    objectCaching: objectCaching,\n\n    /**\n     * When `true`, object properties are checked for cache invalidation. In some particular\n     * situation you may want this to be disabled ( spray brush, very big, groups)\n     * or if your application does not allow you to modify properties for groups child you want\n     * to disable it for groups.\n     * default to false\n     * since 1.7.0\n     * @type Boolean\n     * @default false\n     */\n    statefullCache: false,\n\n    /**\n     * When `true`, cache does not get updated during scaling. The picture will get blocky if scaled\n     * too much and will be redrawn with correct details at the end of scaling.\n     * this setting is performance and application dependant.\n     * default to true\n     * since 1.7.0\n     * @type Boolean\n     * @default true\n     */\n    noScaleCache: true,\n\n    /**\n     * When `false`, the stoke width will scale with the object.\n     * When `true`, the stroke will always match the exact pixel size entered for stroke width.\n     * default to false\n     * @since 2.6.0\n     * @type Boolean\n     * @default false\n     * @type Boolean\n     * @default false\n     */\n    strokeUniform: false,\n\n    /**\n     * When set to `true`, object's cache will be rerendered next render call.\n     * since 1.7.0\n     * @type Boolean\n     * @default true\n     */\n    dirty: true,\n\n    /**\n     * keeps the value of the last hovered corner during mouse move.\n     * 0 is no corner, or 'mt', 'ml', 'mtr' etc..\n     * It should be private, but there is no harm in using it as\n     * a read-only property.\n     * @type number|string|any\n     * @default 0\n     */\n    __corner: 0,\n\n    /**\n     * Determines if the fill or the stroke is drawn first (one of \"fill\" or \"stroke\")\n     * @type String\n     * @default\n     */\n    paintFirst: 'fill',\n\n    /**\n     * List of properties to consider when checking if state\n     * of an object is changed (fabric.Object#hasStateChanged)\n     * as well as for history (undo/redo) purposes\n     * @type Array\n     */\n    stateProperties: ('top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' + 'stroke strokeWidth strokeDashArray strokeLineCap strokeDashOffset strokeLineJoin strokeMiterLimit ' + 'angle opacity fill globalCompositeOperation shadow visible backgroundColor ' + 'skewX skewY fillRule paintFirst clipPath strokeUniform').split(' '),\n\n    /**\n     * List of properties to consider when checking if cache needs refresh\n     * Those properties are checked by statefullCache ON ( or lazy mode if we want ) or from single\n     * calls to Object.set(key, value). If the key is in this list, the object is marked as dirty\n     * and refreshed at the next render\n     * @type Array\n     */\n    cacheProperties: ('fill stroke strokeWidth strokeDashArray width height paintFirst strokeUniform' + ' strokeLineCap strokeDashOffset strokeLineJoin strokeMiterLimit backgroundColor clipPath').split(' '),\n\n    /**\n     * List of properties to consider for animating colors.\n     * @type Array\n     */\n    colorProperties: 'fill stroke backgroundColor'.split(' '),\n\n    /**\n     * a fabricObject that, without stroke define a clipping area with their shape. filled in black\n     * the clipPath object gets used when the object has rendered, and the context is placed in the center\n     * of the object cacheCanvas.\n     * If you want 0,0 of a clipPath to align with an object center, use clipPath.originX/Y to 'center'\n     * @type fabric.Object\n     */\n    clipPath: undefined,\n\n    /**\n     * Meaningful ONLY when the object is used as clipPath.\n     * if true, the clipPath will make the object clip to the outside of the clipPath\n     * since 2.4.0\n     * @type boolean\n     * @default false\n     */\n    inverted: false,\n\n    /**\n     * Meaningful ONLY when the object is used as clipPath.\n     * if true, the clipPath will have its top and left relative to canvas, and will\n     * not be influenced by the object transform. This will make the clipPath relative\n     * to the canvas, but clipping just a particular object.\n     * WARNING this is beta, this feature may change or be renamed.\n     * since 2.4.0\n     * @type boolean\n     * @default false\n     */\n    absolutePositioned: false,\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     */\n    initialize: function (options) {\n      if (options) {\n        this.setOptions(options);\n      }\n    },\n\n    /**\n     * Create a the canvas used to keep the cached copy of the object\n     * @private\n     */\n    _createCacheCanvas: function () {\n      this._cacheProperties = {};\n      this._cacheCanvas = fabric.util.createCanvasElement();\n      this._cacheContext = this._cacheCanvas.getContext('2d');\n\n      this._updateCacheCanvas(); // if canvas gets created, is empty, so dirty.\n\n\n      this.dirty = true;\n    },\n\n    /**\n     * Limit the cache dimensions so that X * Y do not cross fabric.perfLimitSizeTotal\n     * and each side do not cross fabric.cacheSideLimit\n     * those numbers are configurable so that you can get as much detail as you want\n     * making bargain with performances.\n     * @param {Object} dims\n     * @param {Object} dims.width width of canvas\n     * @param {Object} dims.height height of canvas\n     * @param {Object} dims.zoomX zoomX zoom value to unscale the canvas before drawing cache\n     * @param {Object} dims.zoomY zoomY zoom value to unscale the canvas before drawing cache\n     * @return {Object}.width width of canvas\n     * @return {Object}.height height of canvas\n     * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\n     * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\n     */\n    _limitCacheSize: function (dims) {\n      var perfLimitSizeTotal = fabric.perfLimitSizeTotal,\n          width = dims.width,\n          height = dims.height,\n          max = fabric.maxCacheSideLimit,\n          min = fabric.minCacheSideLimit;\n\n      if (width <= max && height <= max && width * height <= perfLimitSizeTotal) {\n        if (width < min) {\n          dims.width = min;\n        }\n\n        if (height < min) {\n          dims.height = min;\n        }\n\n        return dims;\n      }\n\n      var ar = width / height,\n          limitedDims = fabric.util.limitDimsByArea(ar, perfLimitSizeTotal),\n          capValue = fabric.util.capValue,\n          x = capValue(min, limitedDims.x, max),\n          y = capValue(min, limitedDims.y, max);\n\n      if (width > x) {\n        dims.zoomX /= width / x;\n        dims.width = x;\n        dims.capped = true;\n      }\n\n      if (height > y) {\n        dims.zoomY /= height / y;\n        dims.height = y;\n        dims.capped = true;\n      }\n\n      return dims;\n    },\n\n    /**\n     * Return the dimension and the zoom level needed to create a cache canvas\n     * big enough to host the object to be cached.\n     * @private\n     * @return {Object}.x width of object to be cached\n     * @return {Object}.y height of object to be cached\n     * @return {Object}.width width of canvas\n     * @return {Object}.height height of canvas\n     * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\n     * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\n     */\n    _getCacheCanvasDimensions: function () {\n      var objectScale = this.getTotalObjectScaling(),\n          // caculate dimensions without skewing\n      dim = this._getTransformedDimensions(0, 0),\n          neededX = dim.x * objectScale.scaleX / this.scaleX,\n          neededY = dim.y * objectScale.scaleY / this.scaleY;\n\n      return {\n        // for sure this ALIASING_LIMIT is slightly creating problem\n        // in situation in which the cache canvas gets an upper limit\n        // also objectScale contains already scaleX and scaleY\n        width: neededX + ALIASING_LIMIT,\n        height: neededY + ALIASING_LIMIT,\n        zoomX: objectScale.scaleX,\n        zoomY: objectScale.scaleY,\n        x: neededX,\n        y: neededY\n      };\n    },\n\n    /**\n     * Update width and height of the canvas for cache\n     * returns true or false if canvas needed resize.\n     * @private\n     * @return {Boolean} true if the canvas has been resized\n     */\n    _updateCacheCanvas: function () {\n      var targetCanvas = this.canvas;\n\n      if (this.noScaleCache && targetCanvas && targetCanvas._currentTransform) {\n        var target = targetCanvas._currentTransform.target,\n            action = targetCanvas._currentTransform.action;\n\n        if (this === target && action.slice && action.slice(0, 5) === 'scale') {\n          return false;\n        }\n      }\n\n      var canvas = this._cacheCanvas,\n          dims = this._limitCacheSize(this._getCacheCanvasDimensions()),\n          minCacheSize = fabric.minCacheSideLimit,\n          width = dims.width,\n          height = dims.height,\n          drawingWidth,\n          drawingHeight,\n          zoomX = dims.zoomX,\n          zoomY = dims.zoomY,\n          dimensionsChanged = width !== this.cacheWidth || height !== this.cacheHeight,\n          zoomChanged = this.zoomX !== zoomX || this.zoomY !== zoomY,\n          shouldRedraw = dimensionsChanged || zoomChanged,\n          additionalWidth = 0,\n          additionalHeight = 0,\n          shouldResizeCanvas = false;\n\n      if (dimensionsChanged) {\n        var canvasWidth = this._cacheCanvas.width,\n            canvasHeight = this._cacheCanvas.height,\n            sizeGrowing = width > canvasWidth || height > canvasHeight,\n            sizeShrinking = (width < canvasWidth * 0.9 || height < canvasHeight * 0.9) && canvasWidth > minCacheSize && canvasHeight > minCacheSize;\n        shouldResizeCanvas = sizeGrowing || sizeShrinking;\n\n        if (sizeGrowing && !dims.capped && (width > minCacheSize || height > minCacheSize)) {\n          additionalWidth = width * 0.1;\n          additionalHeight = height * 0.1;\n        }\n      }\n\n      if (shouldRedraw) {\n        if (shouldResizeCanvas) {\n          canvas.width = Math.ceil(width + additionalWidth);\n          canvas.height = Math.ceil(height + additionalHeight);\n        } else {\n          this._cacheContext.setTransform(1, 0, 0, 1, 0, 0);\n\n          this._cacheContext.clearRect(0, 0, canvas.width, canvas.height);\n        }\n\n        drawingWidth = dims.x / 2;\n        drawingHeight = dims.y / 2;\n        this.cacheTranslationX = Math.round(canvas.width / 2 - drawingWidth) + drawingWidth;\n        this.cacheTranslationY = Math.round(canvas.height / 2 - drawingHeight) + drawingHeight;\n        this.cacheWidth = width;\n        this.cacheHeight = height;\n\n        this._cacheContext.translate(this.cacheTranslationX, this.cacheTranslationY);\n\n        this._cacheContext.scale(zoomX, zoomY);\n\n        this.zoomX = zoomX;\n        this.zoomY = zoomY;\n        return true;\n      }\n\n      return false;\n    },\n\n    /**\n     * Sets object's properties from options\n     * @param {Object} [options] Options object\n     */\n    setOptions: function (options) {\n      this._setOptions(options);\n\n      this._initGradient(options.fill, 'fill');\n\n      this._initGradient(options.stroke, 'stroke');\n\n      this._initPattern(options.fill, 'fill');\n\n      this._initPattern(options.stroke, 'stroke');\n    },\n\n    /**\n     * Transforms context when rendering an object\n     * @param {CanvasRenderingContext2D} ctx Context\n     */\n    transform: function (ctx) {\n      var needFullTransform = this.group && !this.group._transformDone || this.group && this.canvas && ctx === this.canvas.contextTop;\n      var m = this.calcTransformMatrix(!needFullTransform);\n      ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\n    },\n\n    /**\n     * Returns an object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function (propertiesToInclude) {\n      var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n          object = {\n        type: this.type,\n        version: fabric.version,\n        originX: this.originX,\n        originY: this.originY,\n        left: toFixed(this.left, NUM_FRACTION_DIGITS),\n        top: toFixed(this.top, NUM_FRACTION_DIGITS),\n        width: toFixed(this.width, NUM_FRACTION_DIGITS),\n        height: toFixed(this.height, NUM_FRACTION_DIGITS),\n        fill: this.fill && this.fill.toObject ? this.fill.toObject() : this.fill,\n        stroke: this.stroke && this.stroke.toObject ? this.stroke.toObject() : this.stroke,\n        strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS),\n        strokeDashArray: this.strokeDashArray ? this.strokeDashArray.concat() : this.strokeDashArray,\n        strokeLineCap: this.strokeLineCap,\n        strokeDashOffset: this.strokeDashOffset,\n        strokeLineJoin: this.strokeLineJoin,\n        // strokeUniform:            this.strokeUniform,\n        strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS),\n        scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS),\n        scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS),\n        angle: toFixed(this.angle, NUM_FRACTION_DIGITS),\n        flipX: this.flipX,\n        flipY: this.flipY,\n        opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS),\n        shadow: this.shadow && this.shadow.toObject ? this.shadow.toObject() : this.shadow,\n        visible: this.visible,\n        backgroundColor: this.backgroundColor,\n        fillRule: this.fillRule,\n        paintFirst: this.paintFirst,\n        globalCompositeOperation: this.globalCompositeOperation,\n        skewX: toFixed(this.skewX, NUM_FRACTION_DIGITS),\n        skewY: toFixed(this.skewY, NUM_FRACTION_DIGITS)\n      };\n\n      if (this.clipPath) {\n        object.clipPath = this.clipPath.toObject(propertiesToInclude);\n        object.clipPath.inverted = this.clipPath.inverted;\n        object.clipPath.absolutePositioned = this.clipPath.absolutePositioned;\n      }\n\n      fabric.util.populateWithProperties(this, object, propertiesToInclude);\n\n      if (!this.includeDefaultValues) {\n        object = this._removeDefaultValues(object);\n      }\n\n      return object;\n    },\n\n    /**\n     * Returns (dataless) object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} Object representation of an instance\n     */\n    toDatalessObject: function (propertiesToInclude) {\n      // will be overwritten by subclasses\n      return this.toObject(propertiesToInclude);\n    },\n\n    /**\n     * @private\n     * @param {Object} object\n     */\n    _removeDefaultValues: function (object) {\n      var prototype = fabric.util.getKlass(object.type).prototype,\n          stateProperties = prototype.stateProperties;\n      stateProperties.forEach(function (prop) {\n        if (prop === 'left' || prop === 'top') {\n          return;\n        }\n\n        if (object[prop] === prototype[prop]) {\n          delete object[prop];\n        }\n\n        var isArray = Object.prototype.toString.call(object[prop]) === '[object Array]' && Object.prototype.toString.call(prototype[prop]) === '[object Array]'; // basically a check for [] === []\n\n        if (isArray && object[prop].length === 0 && prototype[prop].length === 0) {\n          delete object[prop];\n        }\n      });\n      return object;\n    },\n\n    /**\n     * Returns a string representation of an instance\n     * @return {String}\n     */\n    toString: function () {\n      return '#<fabric.' + capitalize(this.type) + '>';\n    },\n\n    /**\n     * Return the object scale factor counting also the group scaling\n     * @return {Object} object with scaleX and scaleY properties\n     */\n    getObjectScaling: function () {\n      var options = fabric.util.qrDecompose(this.calcTransformMatrix());\n      return {\n        scaleX: Math.abs(options.scaleX),\n        scaleY: Math.abs(options.scaleY)\n      };\n    },\n\n    /**\n     * Return the object scale factor counting also the group scaling, zoom and retina\n     * @return {Object} object with scaleX and scaleY properties\n     */\n    getTotalObjectScaling: function () {\n      var scale = this.getObjectScaling(),\n          scaleX = scale.scaleX,\n          scaleY = scale.scaleY;\n\n      if (this.canvas) {\n        var zoom = this.canvas.getZoom();\n        var retina = this.canvas.getRetinaScaling();\n        scaleX *= zoom * retina;\n        scaleY *= zoom * retina;\n      }\n\n      return {\n        scaleX: scaleX,\n        scaleY: scaleY\n      };\n    },\n\n    /**\n     * Return the object opacity counting also the group property\n     * @return {Number}\n     */\n    getObjectOpacity: function () {\n      var opacity = this.opacity;\n\n      if (this.group) {\n        opacity *= this.group.getObjectOpacity();\n      }\n\n      return opacity;\n    },\n\n    /**\n     * @private\n     * @param {String} key\n     * @param {*} value\n     * @return {fabric.Object} thisArg\n     */\n    _set: function (key, value) {\n      var shouldConstrainValue = key === 'scaleX' || key === 'scaleY',\n          isChanged = this[key] !== value,\n          groupNeedsUpdate = false;\n\n      if (shouldConstrainValue) {\n        value = this._constrainScale(value);\n      }\n\n      if (key === 'scaleX' && value < 0) {\n        this.flipX = !this.flipX;\n        value *= -1;\n      } else if (key === 'scaleY' && value < 0) {\n        this.flipY = !this.flipY;\n        value *= -1;\n      } else if (key === 'shadow' && value && !(value instanceof fabric.Shadow)) {\n        value = new fabric.Shadow(value);\n      } else if (key === 'dirty' && this.group) {\n        this.group.set('dirty', value);\n      }\n\n      this[key] = value;\n\n      if (isChanged) {\n        groupNeedsUpdate = this.group && this.group.isOnACache();\n\n        if (this.cacheProperties.indexOf(key) > -1) {\n          this.dirty = true;\n          groupNeedsUpdate && this.group.set('dirty', true);\n        } else if (groupNeedsUpdate && this.stateProperties.indexOf(key) > -1) {\n          this.group.set('dirty', true);\n        }\n      }\n\n      return this;\n    },\n\n    /**\n     * This callback function is called by the parent group of an object every\n     * time a non-delegated property changes on the group. It is passed the key\n     * and value as parameters. Not adding in this function's signature to avoid\n     * Travis build error about unused variables.\n     */\n    setOnGroup: function () {// implemented by sub-classes, as needed.\n    },\n\n    /**\n     * Retrieves viewportTransform from Object's canvas if possible\n     * @method getViewportTransform\n     * @memberOf fabric.Object.prototype\n     * @return {Array}\n     */\n    getViewportTransform: function () {\n      if (this.canvas && this.canvas.viewportTransform) {\n        return this.canvas.viewportTransform;\n      }\n\n      return fabric.iMatrix.concat();\n    },\n\n    /*\n     * @private\n     * return if the object would be visible in rendering\n     * @memberOf fabric.Object.prototype\n     * @return {Boolean}\n     */\n    isNotVisible: function () {\n      return this.opacity === 0 || !this.width && !this.height && this.strokeWidth === 0 || !this.visible;\n    },\n\n    /**\n     * Renders an object on a specified context\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    render: function (ctx) {\n      // do not render if width/height are zeros or object is not visible\n      if (this.isNotVisible()) {\n        return;\n      }\n\n      if (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) {\n        return;\n      }\n\n      ctx.save();\n\n      this._setupCompositeOperation(ctx);\n\n      this.drawSelectionBackground(ctx);\n      this.transform(ctx);\n\n      this._setOpacity(ctx);\n\n      this._setShadow(ctx, this);\n\n      if (this.shouldCache()) {\n        this.renderCache();\n        this.drawCacheOnCanvas(ctx);\n      } else {\n        this._removeCacheCanvas();\n\n        this.dirty = false;\n        this.drawObject(ctx);\n\n        if (this.objectCaching && this.statefullCache) {\n          this.saveState({\n            propertySet: 'cacheProperties'\n          });\n        }\n      }\n\n      ctx.restore();\n    },\n    renderCache: function (options) {\n      options = options || {};\n\n      if (!this._cacheCanvas) {\n        this._createCacheCanvas();\n      }\n\n      if (this.isCacheDirty()) {\n        this.statefullCache && this.saveState({\n          propertySet: 'cacheProperties'\n        });\n        this.drawObject(this._cacheContext, options.forClipping);\n        this.dirty = false;\n      }\n    },\n\n    /**\n     * Remove cacheCanvas and its dimensions from the objects\n     */\n    _removeCacheCanvas: function () {\n      this._cacheCanvas = null;\n      this.cacheWidth = 0;\n      this.cacheHeight = 0;\n    },\n\n    /**\n     * return true if the object will draw a stroke\n     * Does not consider text styles. This is just a shortcut used at rendering time\n     * We want it to be an aproximation and be fast.\n     * wrote to avoid extra caching, it has to return true when stroke happens,\n     * can guess when it will not happen at 100% chance, does not matter if it misses\n     * some use case where the stroke is invisible.\n     * @since 3.0.0\n     * @returns Boolean\n     */\n    hasStroke: function () {\n      return this.stroke && this.stroke !== 'transparent' && this.strokeWidth !== 0;\n    },\n\n    /**\n     * return true if the object will draw a fill\n     * Does not consider text styles. This is just a shortcut used at rendering time\n     * We want it to be an aproximation and be fast.\n     * wrote to avoid extra caching, it has to return true when fill happens,\n     * can guess when it will not happen at 100% chance, does not matter if it misses\n     * some use case where the fill is invisible.\n     * @since 3.0.0\n     * @returns Boolean\n     */\n    hasFill: function () {\n      return this.fill && this.fill !== 'transparent';\n    },\n\n    /**\n     * When set to `true`, force the object to have its own cache, even if it is inside a group\n     * it may be needed when your object behave in a particular way on the cache and always needs\n     * its own isolated canvas to render correctly.\n     * Created to be overridden\n     * since 1.7.12\n     * @returns Boolean\n     */\n    needsItsOwnCache: function () {\n      if (this.paintFirst === 'stroke' && this.hasFill() && this.hasStroke() && typeof this.shadow === 'object') {\n        return true;\n      }\n\n      if (this.clipPath) {\n        return true;\n      }\n\n      return false;\n    },\n\n    /**\n     * Decide if the object should cache or not. Create its own cache level\n     * objectCaching is a global flag, wins over everything\n     * needsItsOwnCache should be used when the object drawing method requires\n     * a cache step. None of the fabric classes requires it.\n     * Generally you do not cache objects in groups because the group outside is cached.\n     * Read as: cache if is needed, or if the feature is enabled but we are not already caching.\n     * @return {Boolean}\n     */\n    shouldCache: function () {\n      this.ownCaching = this.needsItsOwnCache() || this.objectCaching && (!this.group || !this.group.isOnACache());\n      return this.ownCaching;\n    },\n\n    /**\n     * Check if this object or a child object will cast a shadow\n     * used by Group.shouldCache to know if child has a shadow recursively\n     * @return {Boolean}\n     */\n    willDrawShadow: function () {\n      return !!this.shadow && (this.shadow.offsetX !== 0 || this.shadow.offsetY !== 0);\n    },\n\n    /**\n     * Execute the drawing operation for an object clipPath\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    drawClipPathOnCache: function (ctx) {\n      var path = this.clipPath;\n      ctx.save(); // DEBUG: uncomment this line, comment the following\n      // ctx.globalAlpha = 0.4\n\n      if (path.inverted) {\n        ctx.globalCompositeOperation = 'destination-out';\n      } else {\n        ctx.globalCompositeOperation = 'destination-in';\n      } //ctx.scale(1 / 2, 1 / 2);\n\n\n      if (path.absolutePositioned) {\n        var m = fabric.util.invertTransform(this.calcTransformMatrix());\n        ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\n      }\n\n      path.transform(ctx);\n      ctx.scale(1 / path.zoomX, 1 / path.zoomY);\n      ctx.drawImage(path._cacheCanvas, -path.cacheTranslationX, -path.cacheTranslationY);\n      ctx.restore();\n    },\n\n    /**\n     * Execute the drawing operation for an object on a specified context\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    drawObject: function (ctx, forClipping) {\n      var originalFill = this.fill,\n          originalStroke = this.stroke;\n\n      if (forClipping) {\n        this.fill = 'black';\n        this.stroke = '';\n\n        this._setClippingProperties(ctx);\n      } else {\n        this._renderBackground(ctx);\n\n        this._setStrokeStyles(ctx, this);\n\n        this._setFillStyles(ctx, this);\n      }\n\n      this._render(ctx);\n\n      this._drawClipPath(ctx);\n\n      this.fill = originalFill;\n      this.stroke = originalStroke;\n    },\n    _drawClipPath: function (ctx) {\n      var path = this.clipPath;\n\n      if (!path) {\n        return;\n      } // needed to setup a couple of variables\n      // path canvas gets overridden with this one.\n      // TODO find a better solution?\n\n\n      path.canvas = this.canvas;\n      path.shouldCache();\n      path._transformDone = true;\n      path.renderCache({\n        forClipping: true\n      });\n      this.drawClipPathOnCache(ctx);\n    },\n\n    /**\n     * Paint the cached copy of the object on the target context.\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    drawCacheOnCanvas: function (ctx) {\n      ctx.scale(1 / this.zoomX, 1 / this.zoomY);\n      ctx.drawImage(this._cacheCanvas, -this.cacheTranslationX, -this.cacheTranslationY);\n    },\n\n    /**\n     * Check if cache is dirty\n     * @param {Boolean} skipCanvas skip canvas checks because this object is painted\n     * on parent canvas.\n     */\n    isCacheDirty: function (skipCanvas) {\n      if (this.isNotVisible()) {\n        return false;\n      }\n\n      if (this._cacheCanvas && !skipCanvas && this._updateCacheCanvas()) {\n        // in this case the context is already cleared.\n        return true;\n      } else {\n        if (this.dirty || this.clipPath && this.clipPath.absolutePositioned || this.statefullCache && this.hasStateChanged('cacheProperties')) {\n          if (this._cacheCanvas && !skipCanvas) {\n            var width = this.cacheWidth / this.zoomX;\n            var height = this.cacheHeight / this.zoomY;\n\n            this._cacheContext.clearRect(-width / 2, -height / 2, width, height);\n          }\n\n          return true;\n        }\n      }\n\n      return false;\n    },\n\n    /**\n     * Draws a background for the object big as its untransformed dimensions\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderBackground: function (ctx) {\n      if (!this.backgroundColor) {\n        return;\n      }\n\n      var dim = this._getNonTransformedDimensions();\n\n      ctx.fillStyle = this.backgroundColor;\n      ctx.fillRect(-dim.x / 2, -dim.y / 2, dim.x, dim.y); // if there is background color no other shadows\n      // should be casted\n\n      this._removeShadow(ctx);\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _setOpacity: function (ctx) {\n      if (this.group && !this.group._transformDone) {\n        ctx.globalAlpha = this.getObjectOpacity();\n      } else {\n        ctx.globalAlpha *= this.opacity;\n      }\n    },\n    _setStrokeStyles: function (ctx, decl) {\n      if (decl.stroke) {\n        ctx.lineWidth = decl.strokeWidth;\n        ctx.lineCap = decl.strokeLineCap;\n        ctx.lineDashOffset = decl.strokeDashOffset;\n        ctx.lineJoin = decl.strokeLineJoin;\n        ctx.miterLimit = decl.strokeMiterLimit;\n        ctx.strokeStyle = decl.stroke.toLive ? decl.stroke.toLive(ctx, this) : decl.stroke;\n      }\n    },\n    _setFillStyles: function (ctx, decl) {\n      if (decl.fill) {\n        ctx.fillStyle = decl.fill.toLive ? decl.fill.toLive(ctx, this) : decl.fill;\n      }\n    },\n    _setClippingProperties: function (ctx) {\n      ctx.globalAlpha = 1;\n      ctx.strokeStyle = 'transparent';\n      ctx.fillStyle = '#000000';\n    },\n\n    /**\n     * @private\n     * Sets line dash\n     * @param {CanvasRenderingContext2D} ctx Context to set the dash line on\n     * @param {Array} dashArray array representing dashes\n     * @param {Function} alternative function to call if browser does not support lineDash\n     */\n    _setLineDash: function (ctx, dashArray, alternative) {\n      if (!dashArray || dashArray.length === 0) {\n        return;\n      } // Spec requires the concatenation of two copies the dash list when the number of elements is odd\n\n\n      if (1 & dashArray.length) {\n        dashArray.push.apply(dashArray, dashArray);\n      }\n\n      if (supportsLineDash) {\n        ctx.setLineDash(dashArray);\n      } else {\n        alternative && alternative(ctx);\n      }\n    },\n\n    /**\n     * Renders controls and borders for the object\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Object} [styleOverride] properties to override the object style\n     */\n    _renderControls: function (ctx, styleOverride) {\n      var vpt = this.getViewportTransform(),\n          matrix = this.calcTransformMatrix(),\n          options,\n          drawBorders,\n          drawControls;\n      styleOverride = styleOverride || {};\n      drawBorders = typeof styleOverride.hasBorders !== 'undefined' ? styleOverride.hasBorders : this.hasBorders;\n      drawControls = typeof styleOverride.hasControls !== 'undefined' ? styleOverride.hasControls : this.hasControls;\n      matrix = fabric.util.multiplyTransformMatrices(vpt, matrix);\n      options = fabric.util.qrDecompose(matrix);\n      ctx.save();\n      ctx.translate(options.translateX, options.translateY);\n      ctx.lineWidth = 1 * this.borderScaleFactor;\n\n      if (!this.group) {\n        ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n      }\n\n      if (styleOverride.forActiveSelection) {\n        ctx.rotate(degreesToRadians(options.angle));\n        drawBorders && this.drawBordersInGroup(ctx, options, styleOverride);\n      } else {\n        ctx.rotate(degreesToRadians(this.angle));\n        drawBorders && this.drawBorders(ctx, styleOverride);\n      }\n\n      drawControls && this.drawControls(ctx, styleOverride);\n      ctx.restore();\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _setShadow: function (ctx) {\n      if (!this.shadow) {\n        return;\n      }\n\n      var shadow = this.shadow,\n          canvas = this.canvas,\n          scaling,\n          multX = canvas && canvas.viewportTransform[0] || 1,\n          multY = canvas && canvas.viewportTransform[3] || 1;\n\n      if (shadow.nonScaling) {\n        scaling = {\n          scaleX: 1,\n          scaleY: 1\n        };\n      } else {\n        scaling = this.getObjectScaling();\n      }\n\n      if (canvas && canvas._isRetinaScaling()) {\n        multX *= fabric.devicePixelRatio;\n        multY *= fabric.devicePixelRatio;\n      }\n\n      ctx.shadowColor = shadow.color;\n      ctx.shadowBlur = shadow.blur * fabric.browserShadowBlurConstant * (multX + multY) * (scaling.scaleX + scaling.scaleY) / 4;\n      ctx.shadowOffsetX = shadow.offsetX * multX * scaling.scaleX;\n      ctx.shadowOffsetY = shadow.offsetY * multY * scaling.scaleY;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _removeShadow: function (ctx) {\n      if (!this.shadow) {\n        return;\n      }\n\n      ctx.shadowColor = '';\n      ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Object} filler fabric.Pattern or fabric.Gradient\n     * @return {Object} offset.offsetX offset for text rendering\n     * @return {Object} offset.offsetY offset for text rendering\n     */\n    _applyPatternGradientTransform: function (ctx, filler) {\n      if (!filler || !filler.toLive) {\n        return {\n          offsetX: 0,\n          offsetY: 0\n        };\n      }\n\n      var t = filler.gradientTransform || filler.patternTransform;\n      var offsetX = -this.width / 2 + filler.offsetX || 0,\n          offsetY = -this.height / 2 + filler.offsetY || 0;\n\n      if (filler.gradientUnits === 'percentage') {\n        ctx.transform(this.width, 0, 0, this.height, offsetX, offsetY);\n      } else {\n        ctx.transform(1, 0, 0, 1, offsetX, offsetY);\n      }\n\n      if (t) {\n        ctx.transform(t[0], t[1], t[2], t[3], t[4], t[5]);\n      }\n\n      return {\n        offsetX: offsetX,\n        offsetY: offsetY\n      };\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderPaintInOrder: function (ctx) {\n      if (this.paintFirst === 'stroke') {\n        this._renderStroke(ctx);\n\n        this._renderFill(ctx);\n      } else {\n        this._renderFill(ctx);\n\n        this._renderStroke(ctx);\n      }\n    },\n\n    /**\n     * @private\n     * function that actually render something on the context.\n     * empty here to allow Obects to work on tests to benchmark fabric functionalites\n     * not related to rendering\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function ()\n    /* ctx */\n    {},\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderFill: function (ctx) {\n      if (!this.fill) {\n        return;\n      }\n\n      ctx.save();\n\n      this._applyPatternGradientTransform(ctx, this.fill);\n\n      if (this.fillRule === 'evenodd') {\n        ctx.fill('evenodd');\n      } else {\n        ctx.fill();\n      }\n\n      ctx.restore();\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderStroke: function (ctx) {\n      if (!this.stroke || this.strokeWidth === 0) {\n        return;\n      }\n\n      if (this.shadow && !this.shadow.affectStroke) {\n        this._removeShadow(ctx);\n      }\n\n      ctx.save();\n\n      if (this.strokeUniform && this.group) {\n        var scaling = this.getObjectScaling();\n        ctx.scale(1 / scaling.scaleX, 1 / scaling.scaleY);\n      } else if (this.strokeUniform) {\n        ctx.scale(1 / this.scaleX, 1 / this.scaleY);\n      }\n\n      this._setLineDash(ctx, this.strokeDashArray, this._renderDashedStroke);\n\n      if (this.stroke.toLive && this.stroke.gradientUnits === 'percentage') {\n        // need to transform gradient in a pattern.\n        // this is a slow process. If you are hitting this codepath, and the object\n        // is not using caching, you should consider switching it on.\n        // we need a canvas as big as the current object caching canvas.\n        this._applyPatternForTransformedGradient(ctx, this.stroke);\n      } else {\n        this._applyPatternGradientTransform(ctx, this.stroke);\n      }\n\n      ctx.stroke();\n      ctx.restore();\n    },\n\n    /**\n     * This function try to patch the missing gradientTransform on canvas gradients.\n     * transforming a context to transform the gradient, is going to transform the stroke too.\n     * we want to transform the gradient but not the stroke operation, so we create\n     * a transformed gradient on a pattern and then we use the pattern instead of the gradient.\n     * this method has drwabacks: is slow, is in low resolution, needs a patch for when the size\n     * is limited.\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {fabric.Gradient} filler a fabric gradient instance\n     */\n    _applyPatternForTransformedGradient: function (ctx, filler) {\n      var dims = this._limitCacheSize(this._getCacheCanvasDimensions()),\n          pCanvas = fabric.util.createCanvasElement(),\n          pCtx,\n          retinaScaling = this.canvas.getRetinaScaling(),\n          width = dims.x / this.scaleX / retinaScaling,\n          height = dims.y / this.scaleY / retinaScaling;\n\n      pCanvas.width = width;\n      pCanvas.height = height;\n      pCtx = pCanvas.getContext('2d');\n      pCtx.beginPath();\n      pCtx.moveTo(0, 0);\n      pCtx.lineTo(width, 0);\n      pCtx.lineTo(width, height);\n      pCtx.lineTo(0, height);\n      pCtx.closePath();\n      pCtx.translate(width / 2, height / 2);\n      pCtx.scale(dims.zoomX / this.scaleX / retinaScaling, dims.zoomY / this.scaleY / retinaScaling);\n\n      this._applyPatternGradientTransform(pCtx, filler);\n\n      pCtx.fillStyle = filler.toLive(ctx);\n      pCtx.fill();\n      ctx.translate(-this.width / 2 - this.strokeWidth / 2, -this.height / 2 - this.strokeWidth / 2);\n      ctx.scale(retinaScaling * this.scaleX / dims.zoomX, retinaScaling * this.scaleY / dims.zoomY);\n      ctx.strokeStyle = pCtx.createPattern(pCanvas, 'no-repeat');\n    },\n\n    /**\n     * This function is an helper for svg import. it returns the center of the object in the svg\n     * untransformed coordinates\n     * @private\n     * @return {Object} center point from element coordinates\n     */\n    _findCenterFromElement: function () {\n      return {\n        x: this.left + this.width / 2,\n        y: this.top + this.height / 2\n      };\n    },\n\n    /**\n     * This function is an helper for svg import. it decompose the transformMatrix\n     * and assign properties to object.\n     * untransformed coordinates\n     * @private\n     * @chainable\n     */\n    _assignTransformMatrixProps: function () {\n      if (this.transformMatrix) {\n        var options = fabric.util.qrDecompose(this.transformMatrix);\n        this.flipX = false;\n        this.flipY = false;\n        this.set('scaleX', options.scaleX);\n        this.set('scaleY', options.scaleY);\n        this.angle = options.angle;\n        this.skewX = options.skewX;\n        this.skewY = 0;\n      }\n    },\n\n    /**\n     * This function is an helper for svg import. it removes the transform matrix\n     * and set to object properties that fabricjs can handle\n     * @private\n     * @param {Object} preserveAspectRatioOptions\n     * @return {thisArg}\n     */\n    _removeTransformMatrix: function (preserveAspectRatioOptions) {\n      var center = this._findCenterFromElement();\n\n      if (this.transformMatrix) {\n        this._assignTransformMatrixProps();\n\n        center = fabric.util.transformPoint(center, this.transformMatrix);\n      }\n\n      this.transformMatrix = null;\n\n      if (preserveAspectRatioOptions) {\n        this.scaleX *= preserveAspectRatioOptions.scaleX;\n        this.scaleY *= preserveAspectRatioOptions.scaleY;\n        this.cropX = preserveAspectRatioOptions.cropX;\n        this.cropY = preserveAspectRatioOptions.cropY;\n        center.x += preserveAspectRatioOptions.offsetLeft;\n        center.y += preserveAspectRatioOptions.offsetTop;\n        this.width = preserveAspectRatioOptions.width;\n        this.height = preserveAspectRatioOptions.height;\n      }\n\n      this.setPositionByOrigin(center, 'center', 'center');\n    },\n\n    /**\n     * Clones an instance, using a callback method will work for every object.\n     * @param {Function} callback Callback is invoked with a clone as a first argument\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     */\n    clone: function (callback, propertiesToInclude) {\n      var objectForm = this.toObject(propertiesToInclude);\n\n      if (this.constructor.fromObject) {\n        this.constructor.fromObject(objectForm, callback);\n      } else {\n        fabric.Object._fromObject('Object', objectForm, callback);\n      }\n    },\n\n    /**\n     * Creates an instance of fabric.Image out of an object\n     * could make use of both toDataUrl or toCanvasElement.\n     * @param {Function} callback callback, invoked with an instance as a first argument\n     * @param {Object} [options] for clone as image, passed to toDataURL\n     * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\n     * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\n     * @param {Number} [options.multiplier=1] Multiplier to scale by\n     * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n     * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n     * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n     * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n     * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\n     * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\n     * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\n     * @return {fabric.Object} thisArg\n     */\n    cloneAsImage: function (callback, options) {\n      var canvasEl = this.toCanvasElement(options);\n\n      if (callback) {\n        callback(new fabric.Image(canvasEl));\n      }\n\n      return this;\n    },\n\n    /**\n     * Converts an object into a HTMLCanvas element\n     * @param {Object} options Options object\n     * @param {Number} [options.multiplier=1] Multiplier to scale by\n     * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n     * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n     * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n     * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n     * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\n     * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\n     * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\n     * @return {HTMLCanvasElement} Returns DOM element <canvas> with the fabric.Object\n     */\n    toCanvasElement: function (options) {\n      options || (options = {});\n      var utils = fabric.util,\n          origParams = utils.saveObjectTransform(this),\n          originalGroup = this.group,\n          originalShadow = this.shadow,\n          abs = Math.abs,\n          multiplier = (options.multiplier || 1) * (options.enableRetinaScaling ? fabric.devicePixelRatio : 1);\n      delete this.group;\n\n      if (options.withoutTransform) {\n        utils.resetObjectTransform(this);\n      }\n\n      if (options.withoutShadow) {\n        this.shadow = null;\n      }\n\n      var el = fabric.util.createCanvasElement(),\n          // skip canvas zoom and calculate with setCoords now.\n      boundingRect = this.getBoundingRect(true, true),\n          shadow = this.shadow,\n          scaling,\n          shadowOffset = {\n        x: 0,\n        y: 0\n      },\n          shadowBlur,\n          width,\n          height;\n\n      if (shadow) {\n        shadowBlur = shadow.blur;\n\n        if (shadow.nonScaling) {\n          scaling = {\n            scaleX: 1,\n            scaleY: 1\n          };\n        } else {\n          scaling = this.getObjectScaling();\n        } // consider non scaling shadow.\n\n\n        shadowOffset.x = 2 * Math.round(abs(shadow.offsetX) + shadowBlur) * abs(scaling.scaleX);\n        shadowOffset.y = 2 * Math.round(abs(shadow.offsetY) + shadowBlur) * abs(scaling.scaleY);\n      }\n\n      width = boundingRect.width + shadowOffset.x;\n      height = boundingRect.height + shadowOffset.y; // if the current width/height is not an integer\n      // we need to make it so.\n\n      el.width = Math.ceil(width);\n      el.height = Math.ceil(height);\n      var canvas = new fabric.StaticCanvas(el, {\n        enableRetinaScaling: false,\n        renderOnAddRemove: false,\n        skipOffscreen: false\n      });\n\n      if (options.format === 'jpeg') {\n        canvas.backgroundColor = '#fff';\n      }\n\n      this.setPositionByOrigin(new fabric.Point(canvas.width / 2, canvas.height / 2), 'center', 'center');\n      var originalCanvas = this.canvas;\n      canvas.add(this);\n      var canvasEl = canvas.toCanvasElement(multiplier || 1, options);\n      this.shadow = originalShadow;\n      this.set('canvas', originalCanvas);\n\n      if (originalGroup) {\n        this.group = originalGroup;\n      }\n\n      this.set(origParams).setCoords(); // canvas.dispose will call image.dispose that will nullify the elements\n      // since this canvas is a simple element for the process, we remove references\n      // to objects in this way in order to avoid object trashing.\n\n      canvas._objects = [];\n      canvas.dispose();\n      canvas = null;\n      return canvasEl;\n    },\n\n    /**\n     * Converts an object into a data-url-like string\n     * @param {Object} options Options object\n     * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\n     * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\n     * @param {Number} [options.multiplier=1] Multiplier to scale by\n     * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n     * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n     * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n     * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n     * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\n     * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\n     * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\n     * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format\n     */\n    toDataURL: function (options) {\n      options || (options = {});\n      return fabric.util.toDataURL(this.toCanvasElement(options), options.format || 'png', options.quality || 1);\n    },\n\n    /**\n     * Returns true if specified type is identical to the type of an instance\n     * @param {String} type Type to check against\n     * @return {Boolean}\n     */\n    isType: function (type) {\n      return this.type === type;\n    },\n\n    /**\n     * Returns complexity of an instance\n     * @return {Number} complexity of this instance (is 1 unless subclassed)\n     */\n    complexity: function () {\n      return 1;\n    },\n\n    /**\n     * Returns a JSON representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} JSON\n     */\n    toJSON: function (propertiesToInclude) {\n      // delegate, not alias\n      return this.toObject(propertiesToInclude);\n    },\n\n    /**\n     * Sets \"angle\" of an instance with centered rotation\n     * @param {Number} angle Angle value (in degrees)\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    rotate: function (angle) {\n      var shouldCenterOrigin = (this.originX !== 'center' || this.originY !== 'center') && this.centeredRotation;\n\n      if (shouldCenterOrigin) {\n        this._setOriginToCenter();\n      }\n\n      this.set('angle', angle);\n\n      if (shouldCenterOrigin) {\n        this._resetOrigin();\n      }\n\n      return this;\n    },\n\n    /**\n     * Centers object horizontally on canvas to which it was added last.\n     * You might need to call `setCoords` on an object after centering, to update controls area.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    centerH: function () {\n      this.canvas && this.canvas.centerObjectH(this);\n      return this;\n    },\n\n    /**\n     * Centers object horizontally on current viewport of canvas to which it was added last.\n     * You might need to call `setCoords` on an object after centering, to update controls area.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    viewportCenterH: function () {\n      this.canvas && this.canvas.viewportCenterObjectH(this);\n      return this;\n    },\n\n    /**\n     * Centers object vertically on canvas to which it was added last.\n     * You might need to call `setCoords` on an object after centering, to update controls area.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    centerV: function () {\n      this.canvas && this.canvas.centerObjectV(this);\n      return this;\n    },\n\n    /**\n     * Centers object vertically on current viewport of canvas to which it was added last.\n     * You might need to call `setCoords` on an object after centering, to update controls area.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    viewportCenterV: function () {\n      this.canvas && this.canvas.viewportCenterObjectV(this);\n      return this;\n    },\n\n    /**\n     * Centers object vertically and horizontally on canvas to which is was added last\n     * You might need to call `setCoords` on an object after centering, to update controls area.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    center: function () {\n      this.canvas && this.canvas.centerObject(this);\n      return this;\n    },\n\n    /**\n     * Centers object on current viewport of canvas to which it was added last.\n     * You might need to call `setCoords` on an object after centering, to update controls area.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    viewportCenter: function () {\n      this.canvas && this.canvas.viewportCenterObject(this);\n      return this;\n    },\n\n    /**\n     * Returns coordinates of a pointer relative to an object\n     * @param {Event} e Event to operate upon\n     * @param {Object} [pointer] Pointer to operate upon (instead of event)\n     * @return {Object} Coordinates of a pointer (x, y)\n     */\n    getLocalPointer: function (e, pointer) {\n      pointer = pointer || this.canvas.getPointer(e);\n\n      var pClicked = new fabric.Point(pointer.x, pointer.y),\n          objectLeftTop = this._getLeftTopCoords();\n\n      if (this.angle) {\n        pClicked = fabric.util.rotatePoint(pClicked, objectLeftTop, degreesToRadians(-this.angle));\n      }\n\n      return {\n        x: pClicked.x - objectLeftTop.x,\n        y: pClicked.y - objectLeftTop.y\n      };\n    },\n\n    /**\n     * Sets canvas globalCompositeOperation for specific object\n     * custom composition operation for the particular object can be specified using globalCompositeOperation property\n     * @param {CanvasRenderingContext2D} ctx Rendering canvas context\n     */\n    _setupCompositeOperation: function (ctx) {\n      if (this.globalCompositeOperation) {\n        ctx.globalCompositeOperation = this.globalCompositeOperation;\n      }\n    }\n  });\n  fabric.util.createAccessors && fabric.util.createAccessors(fabric.Object);\n  extend(fabric.Object.prototype, fabric.Observable);\n  /**\n   * Defines the number of fraction digits to use when serializing object values.\n   * You can use it to increase/decrease precision of such values like left, top, scaleX, scaleY, etc.\n   * @static\n   * @memberOf fabric.Object\n   * @constant\n   * @type Number\n   */\n\n  fabric.Object.NUM_FRACTION_DIGITS = 2;\n\n  fabric.Object._fromObject = function (className, object, callback, extraParam) {\n    var klass = fabric[className];\n    object = clone(object, true);\n    fabric.util.enlivenPatterns([object.fill, object.stroke], function (patterns) {\n      if (typeof patterns[0] !== 'undefined') {\n        object.fill = patterns[0];\n      }\n\n      if (typeof patterns[1] !== 'undefined') {\n        object.stroke = patterns[1];\n      }\n\n      fabric.util.enlivenObjects([object.clipPath], function (enlivedProps) {\n        object.clipPath = enlivedProps[0];\n        var instance = extraParam ? new klass(object[extraParam], object) : new klass(object);\n        callback && callback(instance);\n      });\n    });\n  };\n  /**\n   * Unique id used internally when creating SVG elements\n   * @static\n   * @memberOf fabric.Object\n   * @type Number\n   */\n\n\n  fabric.Object.__uid = 0;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function () {\n  var degreesToRadians = fabric.util.degreesToRadians,\n      originXOffset = {\n    left: -0.5,\n    center: 0,\n    right: 0.5\n  },\n      originYOffset = {\n    top: -0.5,\n    center: 0,\n    bottom: 0.5\n  };\n  fabric.util.object.extend(fabric.Object.prototype,\n  /** @lends fabric.Object.prototype */\n  {\n    /**\n     * Translates the coordinates from a set of origin to another (based on the object's dimensions)\n     * @param {fabric.Point} point The point which corresponds to the originX and originY params\n     * @param {String} fromOriginX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} fromOriginY Vertical origin: 'top', 'center' or 'bottom'\n     * @param {String} toOriginX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} toOriginY Vertical origin: 'top', 'center' or 'bottom'\n     * @return {fabric.Point}\n     */\n    translateToGivenOrigin: function (point, fromOriginX, fromOriginY, toOriginX, toOriginY) {\n      var x = point.x,\n          y = point.y,\n          offsetX,\n          offsetY,\n          dim;\n\n      if (typeof fromOriginX === 'string') {\n        fromOriginX = originXOffset[fromOriginX];\n      } else {\n        fromOriginX -= 0.5;\n      }\n\n      if (typeof toOriginX === 'string') {\n        toOriginX = originXOffset[toOriginX];\n      } else {\n        toOriginX -= 0.5;\n      }\n\n      offsetX = toOriginX - fromOriginX;\n\n      if (typeof fromOriginY === 'string') {\n        fromOriginY = originYOffset[fromOriginY];\n      } else {\n        fromOriginY -= 0.5;\n      }\n\n      if (typeof toOriginY === 'string') {\n        toOriginY = originYOffset[toOriginY];\n      } else {\n        toOriginY -= 0.5;\n      }\n\n      offsetY = toOriginY - fromOriginY;\n\n      if (offsetX || offsetY) {\n        dim = this._getTransformedDimensions();\n        x = point.x + offsetX * dim.x;\n        y = point.y + offsetY * dim.y;\n      }\n\n      return new fabric.Point(x, y);\n    },\n\n    /**\n     * Translates the coordinates from origin to center coordinates (based on the object's dimensions)\n     * @param {fabric.Point} point The point which corresponds to the originX and originY params\n     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n     * @return {fabric.Point}\n     */\n    translateToCenterPoint: function (point, originX, originY) {\n      var p = this.translateToGivenOrigin(point, originX, originY, 'center', 'center');\n\n      if (this.angle) {\n        return fabric.util.rotatePoint(p, point, degreesToRadians(this.angle));\n      }\n\n      return p;\n    },\n\n    /**\n     * Translates the coordinates from center to origin coordinates (based on the object's dimensions)\n     * @param {fabric.Point} center The point which corresponds to center of the object\n     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n     * @return {fabric.Point}\n     */\n    translateToOriginPoint: function (center, originX, originY) {\n      var p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY);\n\n      if (this.angle) {\n        return fabric.util.rotatePoint(p, center, degreesToRadians(this.angle));\n      }\n\n      return p;\n    },\n\n    /**\n     * Returns the real center coordinates of the object\n     * @return {fabric.Point}\n     */\n    getCenterPoint: function () {\n      var leftTop = new fabric.Point(this.left, this.top);\n      return this.translateToCenterPoint(leftTop, this.originX, this.originY);\n    },\n\n    /**\n     * Returns the coordinates of the object based on center coordinates\n     * @param {fabric.Point} point The point which corresponds to the originX and originY params\n     * @return {fabric.Point}\n     */\n    // getOriginPoint: function(center) {\n    //   return this.translateToOriginPoint(center, this.originX, this.originY);\n    // },\n\n    /**\n     * Returns the coordinates of the object as if it has a different origin\n     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n     * @return {fabric.Point}\n     */\n    getPointByOrigin: function (originX, originY) {\n      var center = this.getCenterPoint();\n      return this.translateToOriginPoint(center, originX, originY);\n    },\n\n    /**\n     * Returns the point in local coordinates\n     * @param {fabric.Point} point The point relative to the global coordinate system\n     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n     * @return {fabric.Point}\n     */\n    toLocalPoint: function (point, originX, originY) {\n      var center = this.getCenterPoint(),\n          p,\n          p2;\n\n      if (typeof originX !== 'undefined' && typeof originY !== 'undefined') {\n        p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY);\n      } else {\n        p = new fabric.Point(this.left, this.top);\n      }\n\n      p2 = new fabric.Point(point.x, point.y);\n\n      if (this.angle) {\n        p2 = fabric.util.rotatePoint(p2, center, -degreesToRadians(this.angle));\n      }\n\n      return p2.subtractEquals(p);\n    },\n\n    /**\n     * Returns the point in global coordinates\n     * @param {fabric.Point} The point relative to the local coordinate system\n     * @return {fabric.Point}\n     */\n    // toGlobalPoint: function(point) {\n    //   return fabric.util.rotatePoint(point, this.getCenterPoint(), degreesToRadians(this.angle)).addEquals(new fabric.Point(this.left, this.top));\n    // },\n\n    /**\n     * Sets the position of the object taking into consideration the object's origin\n     * @param {fabric.Point} pos The new position of the object\n     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n     * @return {void}\n     */\n    setPositionByOrigin: function (pos, originX, originY) {\n      var center = this.translateToCenterPoint(pos, originX, originY),\n          position = this.translateToOriginPoint(center, this.originX, this.originY);\n      this.set('left', position.x);\n      this.set('top', position.y);\n    },\n\n    /**\n     * @param {String} to One of 'left', 'center', 'right'\n     */\n    adjustPosition: function (to) {\n      var angle = degreesToRadians(this.angle),\n          hypotFull = this.getScaledWidth(),\n          xFull = fabric.util.cos(angle) * hypotFull,\n          yFull = fabric.util.sin(angle) * hypotFull,\n          offsetFrom,\n          offsetTo; //TODO: this function does not consider mixed situation like top, center.\n\n      if (typeof this.originX === 'string') {\n        offsetFrom = originXOffset[this.originX];\n      } else {\n        offsetFrom = this.originX - 0.5;\n      }\n\n      if (typeof to === 'string') {\n        offsetTo = originXOffset[to];\n      } else {\n        offsetTo = to - 0.5;\n      }\n\n      this.left += xFull * (offsetTo - offsetFrom);\n      this.top += yFull * (offsetTo - offsetFrom);\n      this.setCoords();\n      this.originX = to;\n    },\n\n    /**\n     * Sets the origin/position of the object to it's center point\n     * @private\n     * @return {void}\n     */\n    _setOriginToCenter: function () {\n      this._originalOriginX = this.originX;\n      this._originalOriginY = this.originY;\n      var center = this.getCenterPoint();\n      this.originX = 'center';\n      this.originY = 'center';\n      this.left = center.x;\n      this.top = center.y;\n    },\n\n    /**\n     * Resets the origin/position of the object to it's original origin\n     * @private\n     * @return {void}\n     */\n    _resetOrigin: function () {\n      var originPoint = this.translateToOriginPoint(this.getCenterPoint(), this._originalOriginX, this._originalOriginY);\n      this.originX = this._originalOriginX;\n      this.originY = this._originalOriginY;\n      this.left = originPoint.x;\n      this.top = originPoint.y;\n      this._originalOriginX = null;\n      this._originalOriginY = null;\n    },\n\n    /**\n     * @private\n     */\n    _getLeftTopCoords: function () {\n      return this.translateToOriginPoint(this.getCenterPoint(), 'left', 'top');\n    }\n  });\n})();\n\n(function () {\n  function arrayFromCoords(coords) {\n    return [new fabric.Point(coords.tl.x, coords.tl.y), new fabric.Point(coords.tr.x, coords.tr.y), new fabric.Point(coords.br.x, coords.br.y), new fabric.Point(coords.bl.x, coords.bl.y)];\n  }\n\n  var util = fabric.util,\n      degreesToRadians = util.degreesToRadians,\n      multiplyMatrices = util.multiplyTransformMatrices,\n      transformPoint = util.transformPoint;\n  util.object.extend(fabric.Object.prototype,\n  /** @lends fabric.Object.prototype */\n  {\n    /**\n     * Describe object's corner position in canvas element coordinates.\n     * properties are depending on control keys and padding the main controls.\n     * each property is an object with x, y and corner.\n     * The `corner` property contains in a similar manner the 4 points of the\n     * interactive area of the corner.\n     * The coordinates depends from the controls positionHandler and are used\n     * to draw and locate controls\n     * @memberOf fabric.Object.prototype\n     */\n    oCoords: null,\n\n    /**\n     * Describe object's corner position in canvas object absolute coordinates\n     * properties are tl,tr,bl,br and describe the four main corner.\n     * each property is an object with x, y, instance of Fabric.Point.\n     * The coordinates depends from this properties: width, height, scaleX, scaleY\n     * skewX, skewY, angle, strokeWidth, top, left.\n     * Those coordinates are useful to understand where an object is. They get updated\n     * with oCoords but they do not need to be updated when zoom or panning change.\n     * The coordinates get updated with @method setCoords.\n     * You can calculate them without updating with @method calcACoords();\n     * @memberOf fabric.Object.prototype\n     */\n    aCoords: null,\n\n    /**\n     * Describe object's corner position in canvas element coordinates.\n     * includes padding. Used of object detection.\n     * set and refreshed with setCoords and calcCoords.\n     * @memberOf fabric.Object.prototype\n     */\n    lineCoords: null,\n\n    /**\n     * storage for object transform matrix\n     */\n    ownMatrixCache: null,\n\n    /**\n     * storage for object full transform matrix\n     */\n    matrixCache: null,\n\n    /**\n     * custom controls interface\n     * controls are added by default_controls.js\n     */\n    controls: {},\n\n    /**\n     * return correct set of coordinates for intersection\n     * this will return either aCoords or lineCoords.\n     * @param {Boolean} absolute will return aCoords if true or lineCoords\n     * @return {Object} {tl, tr, br, bl} points\n     */\n    _getCoords: function (absolute, calculate) {\n      if (calculate) {\n        return absolute ? this.calcACoords() : this.calcLineCoords();\n      }\n\n      if (!this.aCoords || !this.lineCoords) {\n        this.setCoords(true);\n      }\n\n      return absolute ? this.aCoords : this.lineCoords;\n    },\n\n    /**\n     * return correct set of coordinates for intersection\n     * this will return either aCoords or lineCoords.\n     * The coords are returned in an array.\n     * @return {Array} [tl, tr, br, bl] of points\n     */\n    getCoords: function (absolute, calculate) {\n      return arrayFromCoords(this._getCoords(absolute, calculate));\n    },\n\n    /**\n     * Checks if object intersects with an area formed by 2 points\n     * @param {Object} pointTL top-left point of area\n     * @param {Object} pointBR bottom-right point of area\n     * @param {Boolean} [absolute] use coordinates without viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if object intersects with an area formed by 2 points\n     */\n    intersectsWithRect: function (pointTL, pointBR, absolute, calculate) {\n      var coords = this.getCoords(absolute, calculate),\n          intersection = fabric.Intersection.intersectPolygonRectangle(coords, pointTL, pointBR);\n      return intersection.status === 'Intersection';\n    },\n\n    /**\n     * Checks if object intersects with another object\n     * @param {Object} other Object to test\n     * @param {Boolean} [absolute] use coordinates without viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if object intersects with another object\n     */\n    intersectsWithObject: function (other, absolute, calculate) {\n      var intersection = fabric.Intersection.intersectPolygonPolygon(this.getCoords(absolute, calculate), other.getCoords(absolute, calculate));\n      return intersection.status === 'Intersection' || other.isContainedWithinObject(this, absolute, calculate) || this.isContainedWithinObject(other, absolute, calculate);\n    },\n\n    /**\n     * Checks if object is fully contained within area of another object\n     * @param {Object} other Object to test\n     * @param {Boolean} [absolute] use coordinates without viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if object is fully contained within area of another object\n     */\n    isContainedWithinObject: function (other, absolute, calculate) {\n      var points = this.getCoords(absolute, calculate),\n          otherCoords = absolute ? other.aCoords : other.lineCoords,\n          i = 0,\n          lines = other._getImageLines(otherCoords);\n\n      for (; i < 4; i++) {\n        if (!other.containsPoint(points[i], lines)) {\n          return false;\n        }\n      }\n\n      return true;\n    },\n\n    /**\n     * Checks if object is fully contained within area formed by 2 points\n     * @param {Object} pointTL top-left point of area\n     * @param {Object} pointBR bottom-right point of area\n     * @param {Boolean} [absolute] use coordinates without viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if object is fully contained within area formed by 2 points\n     */\n    isContainedWithinRect: function (pointTL, pointBR, absolute, calculate) {\n      var boundingRect = this.getBoundingRect(absolute, calculate);\n      return boundingRect.left >= pointTL.x && boundingRect.left + boundingRect.width <= pointBR.x && boundingRect.top >= pointTL.y && boundingRect.top + boundingRect.height <= pointBR.y;\n    },\n\n    /**\n     * Checks if point is inside the object\n     * @param {fabric.Point} point Point to check against\n     * @param {Object} [lines] object returned from @method _getImageLines\n     * @param {Boolean} [absolute] use coordinates without viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if point is inside the object\n     */\n    containsPoint: function (point, lines, absolute, calculate) {\n      var coords = this._getCoords(absolute, calculate),\n          lines = lines || this._getImageLines(coords),\n          xPoints = this._findCrossPoints(point, lines); // if xPoints is odd then point is inside the object\n\n\n      return xPoints !== 0 && xPoints % 2 === 1;\n    },\n\n    /**\n     * Checks if object is contained within the canvas with current viewportTransform\n     * the check is done stopping at first point that appears on screen\n     * @param {Boolean} [calculate] use coordinates of current position instead of .aCoords\n     * @return {Boolean} true if object is fully or partially contained within canvas\n     */\n    isOnScreen: function (calculate) {\n      if (!this.canvas) {\n        return false;\n      }\n\n      var pointTL = this.canvas.vptCoords.tl,\n          pointBR = this.canvas.vptCoords.br;\n      var points = this.getCoords(true, calculate); // if some point is on screen, the object is on screen.\n\n      if (points.some(function (point) {\n        return point.x <= pointBR.x && point.x >= pointTL.x && point.y <= pointBR.y && point.y >= pointTL.y;\n      })) {\n        return true;\n      } // no points on screen, check intersection with absolute coordinates\n\n\n      if (this.intersectsWithRect(pointTL, pointBR, true, calculate)) {\n        return true;\n      }\n\n      return this._containsCenterOfCanvas(pointTL, pointBR, calculate);\n    },\n\n    /**\n     * Checks if the object contains the midpoint between canvas extremities\n     * Does not make sense outside the context of isOnScreen and isPartiallyOnScreen\n     * @private\n     * @param {Fabric.Point} pointTL Top Left point\n     * @param {Fabric.Point} pointBR Top Right point\n     * @param {Boolean} calculate use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if the object contains the point\n     */\n    _containsCenterOfCanvas: function (pointTL, pointBR, calculate) {\n      // worst case scenario the object is so big that contains the screen\n      var centerPoint = {\n        x: (pointTL.x + pointBR.x) / 2,\n        y: (pointTL.y + pointBR.y) / 2\n      };\n\n      if (this.containsPoint(centerPoint, null, true, calculate)) {\n        return true;\n      }\n\n      return false;\n    },\n\n    /**\n     * Checks if object is partially contained within the canvas with current viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if object is partially contained within canvas\n     */\n    isPartiallyOnScreen: function (calculate) {\n      if (!this.canvas) {\n        return false;\n      }\n\n      var pointTL = this.canvas.vptCoords.tl,\n          pointBR = this.canvas.vptCoords.br;\n\n      if (this.intersectsWithRect(pointTL, pointBR, true, calculate)) {\n        return true;\n      }\n\n      var allPointsAreOutside = this.getCoords(true, calculate).every(function (point) {\n        return (point.x >= pointBR.x || point.x <= pointTL.x) && (point.y >= pointBR.y || point.y <= pointTL.y);\n      });\n      return allPointsAreOutside && this._containsCenterOfCanvas(pointTL, pointBR, calculate);\n    },\n\n    /**\n     * Method that returns an object with the object edges in it, given the coordinates of the corners\n     * @private\n     * @param {Object} oCoords Coordinates of the object corners\n     */\n    _getImageLines: function (oCoords) {\n      var lines = {\n        topline: {\n          o: oCoords.tl,\n          d: oCoords.tr\n        },\n        rightline: {\n          o: oCoords.tr,\n          d: oCoords.br\n        },\n        bottomline: {\n          o: oCoords.br,\n          d: oCoords.bl\n        },\n        leftline: {\n          o: oCoords.bl,\n          d: oCoords.tl\n        }\n      }; // // debugging\n      // if (this.canvas.contextTop) {\n      //   this.canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);\n      //   this.canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);\n      //\n      //   this.canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);\n      //   this.canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);\n      //\n      //   this.canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);\n      //   this.canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);\n      //\n      //   this.canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);\n      //   this.canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);\n      // }\n\n      return lines;\n    },\n\n    /**\n     * Helper method to determine how many cross points are between the 4 object edges\n     * and the horizontal line determined by a point on canvas\n     * @private\n     * @param {fabric.Point} point Point to check\n     * @param {Object} lines Coordinates of the object being evaluated\n     */\n    // remove yi, not used but left code here just in case.\n    _findCrossPoints: function (point, lines) {\n      var b1,\n          b2,\n          a1,\n          a2,\n          xi,\n          // yi,\n      xcount = 0,\n          iLine;\n\n      for (var lineKey in lines) {\n        iLine = lines[lineKey]; // optimisation 1: line below point. no cross\n\n        if (iLine.o.y < point.y && iLine.d.y < point.y) {\n          continue;\n        } // optimisation 2: line above point. no cross\n\n\n        if (iLine.o.y >= point.y && iLine.d.y >= point.y) {\n          continue;\n        } // optimisation 3: vertical line case\n\n\n        if (iLine.o.x === iLine.d.x && iLine.o.x >= point.x) {\n          xi = iLine.o.x; // yi = point.y;\n        } // calculate the intersection point\n        else {\n            b1 = 0;\n            b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x);\n            a1 = point.y - b1 * point.x;\n            a2 = iLine.o.y - b2 * iLine.o.x;\n            xi = -(a1 - a2) / (b1 - b2); // yi = a1 + b1 * xi;\n          } // dont count xi < point.x cases\n\n\n        if (xi >= point.x) {\n          xcount += 1;\n        } // optimisation 4: specific for square images\n\n\n        if (xcount === 2) {\n          break;\n        }\n      }\n\n      return xcount;\n    },\n\n    /**\n     * Returns coordinates of object's bounding rectangle (left, top, width, height)\n     * the box is intended as aligned to axis of canvas.\n     * @param {Boolean} [absolute] use coordinates without viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords / .aCoords\n     * @return {Object} Object with left, top, width, height properties\n     */\n    getBoundingRect: function (absolute, calculate) {\n      var coords = this.getCoords(absolute, calculate);\n      return util.makeBoundingBoxFromPoints(coords);\n    },\n\n    /**\n     * Returns width of an object's bounding box counting transformations\n     * before 2.0 it was named getWidth();\n     * @return {Number} width value\n     */\n    getScaledWidth: function () {\n      return this._getTransformedDimensions().x;\n    },\n\n    /**\n     * Returns height of an object bounding box counting transformations\n     * before 2.0 it was named getHeight();\n     * @return {Number} height value\n     */\n    getScaledHeight: function () {\n      return this._getTransformedDimensions().y;\n    },\n\n    /**\n     * Makes sure the scale is valid and modifies it if necessary\n     * @private\n     * @param {Number} value\n     * @return {Number}\n     */\n    _constrainScale: function (value) {\n      if (Math.abs(value) < this.minScaleLimit) {\n        if (value < 0) {\n          return -this.minScaleLimit;\n        } else {\n          return this.minScaleLimit;\n        }\n      } else if (value === 0) {\n        return 0.0001;\n      }\n\n      return value;\n    },\n\n    /**\n     * Scales an object (equally by x and y)\n     * @param {Number} value Scale factor\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    scale: function (value) {\n      this._set('scaleX', value);\n\n      this._set('scaleY', value);\n\n      return this.setCoords();\n    },\n\n    /**\n     * Scales an object to a given width, with respect to bounding box (scaling by x/y equally)\n     * @param {Number} value New width value\n     * @param {Boolean} absolute ignore viewport\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    scaleToWidth: function (value, absolute) {\n      // adjust to bounding rect factor so that rotated shapes would fit as well\n      var boundingRectFactor = this.getBoundingRect(absolute).width / this.getScaledWidth();\n      return this.scale(value / this.width / boundingRectFactor);\n    },\n\n    /**\n     * Scales an object to a given height, with respect to bounding box (scaling by x/y equally)\n     * @param {Number} value New height value\n     * @param {Boolean} absolute ignore viewport\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    scaleToHeight: function (value, absolute) {\n      // adjust to bounding rect factor so that rotated shapes would fit as well\n      var boundingRectFactor = this.getBoundingRect(absolute).height / this.getScaledHeight();\n      return this.scale(value / this.height / boundingRectFactor);\n    },\n\n    /**\n     * Calculates and returns the .coords of an object.\n     * unused by the library, only for the end dev.\n     * @return {Object} Object with tl, tr, br, bl ....\n     * @chainable\n     * @deprecated\n     */\n    calcCoords: function (absolute) {\n      // this is a compatibility function to avoid removing calcCoords now.\n      if (absolute) {\n        return this.calcACoords();\n      }\n\n      return this.calcOCoords();\n    },\n    calcLineCoords: function () {\n      var vpt = this.getViewportTransform(),\n          padding = this.padding,\n          angle = degreesToRadians(this.angle),\n          cos = util.cos(angle),\n          sin = util.sin(angle),\n          cosP = cos * padding,\n          sinP = sin * padding,\n          cosPSinP = cosP + sinP,\n          cosPMinusSinP = cosP - sinP,\n          aCoords = this.calcACoords();\n      var lineCoords = {\n        tl: transformPoint(aCoords.tl, vpt),\n        tr: transformPoint(aCoords.tr, vpt),\n        bl: transformPoint(aCoords.bl, vpt),\n        br: transformPoint(aCoords.br, vpt)\n      };\n\n      if (padding) {\n        lineCoords.tl.x -= cosPMinusSinP;\n        lineCoords.tl.y -= cosPSinP;\n        lineCoords.tr.x += cosPSinP;\n        lineCoords.tr.y -= cosPMinusSinP;\n        lineCoords.bl.x -= cosPSinP;\n        lineCoords.bl.y += cosPMinusSinP;\n        lineCoords.br.x += cosPMinusSinP;\n        lineCoords.br.y += cosPSinP;\n      }\n\n      return lineCoords;\n    },\n    calcOCoords: function () {\n      var rotateMatrix = this._calcRotateMatrix(),\n          translateMatrix = this._calcTranslateMatrix(),\n          vpt = this.getViewportTransform(),\n          startMatrix = multiplyMatrices(vpt, translateMatrix),\n          finalMatrix = multiplyMatrices(startMatrix, rotateMatrix),\n          finalMatrix = multiplyMatrices(finalMatrix, [1 / vpt[0], 0, 0, 1 / vpt[3], 0, 0]),\n          dim = this._calculateCurrentDimensions(),\n          coords = {};\n\n      this.forEachControl(function (control, key, fabricObject) {\n        coords[key] = control.positionHandler(dim, finalMatrix, fabricObject);\n      }); // debug code\n      // var canvas = this.canvas;\n      // setTimeout(function() {\n      //   canvas.contextTop.clearRect(0, 0, 700, 700);\n      //   canvas.contextTop.fillStyle = 'green';\n      //   Object.keys(coords).forEach(function(key) {\n      //     var control = coords[key];\n      //     canvas.contextTop.fillRect(control.x, control.y, 3, 3);\n      //   });\n      // }, 50);\n\n      return coords;\n    },\n    calcACoords: function () {\n      var rotateMatrix = this._calcRotateMatrix(),\n          translateMatrix = this._calcTranslateMatrix(),\n          finalMatrix = multiplyMatrices(translateMatrix, rotateMatrix),\n          dim = this._getTransformedDimensions(),\n          w = dim.x / 2,\n          h = dim.y / 2;\n\n      return {\n        // corners\n        tl: transformPoint({\n          x: -w,\n          y: -h\n        }, finalMatrix),\n        tr: transformPoint({\n          x: w,\n          y: -h\n        }, finalMatrix),\n        bl: transformPoint({\n          x: -w,\n          y: h\n        }, finalMatrix),\n        br: transformPoint({\n          x: w,\n          y: h\n        }, finalMatrix)\n      };\n    },\n\n    /**\n     * Sets corner position coordinates based on current angle, width and height.\n     * oCoords are used to find the corners\n     * aCoords are used to quickly find an object on the canvas\n     * lineCoords are used to quickly find object during pointer events.\n     * See {@link https://github.com/kangax/fabric.js/wiki/When-to-call-setCoords|When-to-call-setCoords}\n     * @param {Boolean} [skipCorners] skip calculation of oCoords.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    setCoords: function (skipCorners) {\n      this.aCoords = this.calcACoords(); // in case we are in a group, for how the inner group target check works,\n      // lineCoords are exactly aCoords. Since the vpt gets absorbed by the normalized pointer.\n\n      this.lineCoords = this.group ? this.aCoords : this.calcLineCoords();\n\n      if (skipCorners) {\n        return this;\n      } // set coordinates of the draggable boxes in the corners used to scale/rotate the image\n\n\n      this.oCoords = this.calcOCoords();\n      this._setCornerCoords && this._setCornerCoords();\n      return this;\n    },\n\n    /**\n     * calculate rotation matrix of an object\n     * @return {Array} rotation matrix for the object\n     */\n    _calcRotateMatrix: function () {\n      return util.calcRotateMatrix(this);\n    },\n\n    /**\n     * calculate the translation matrix for an object transform\n     * @return {Array} rotation matrix for the object\n     */\n    _calcTranslateMatrix: function () {\n      var center = this.getCenterPoint();\n      return [1, 0, 0, 1, center.x, center.y];\n    },\n    transformMatrixKey: function (skipGroup) {\n      var sep = '_',\n          prefix = '';\n\n      if (!skipGroup && this.group) {\n        prefix = this.group.transformMatrixKey(skipGroup) + sep;\n      }\n\n      ;\n      return prefix + this.top + sep + this.left + sep + this.scaleX + sep + this.scaleY + sep + this.skewX + sep + this.skewY + sep + this.angle + sep + this.originX + sep + this.originY + sep + this.width + sep + this.height + sep + this.strokeWidth + this.flipX + this.flipY;\n    },\n\n    /**\n     * calculate transform matrix that represents the current transformations from the\n     * object's properties.\n     * @param {Boolean} [skipGroup] return transform matrix for object not counting parent transformations\n     * There are some situation in which this is useful to avoid the fake rotation.\n     * @return {Array} transform matrix for the object\n     */\n    calcTransformMatrix: function (skipGroup) {\n      var matrix = this.calcOwnMatrix();\n\n      if (skipGroup || !this.group) {\n        return matrix;\n      }\n\n      var key = this.transformMatrixKey(skipGroup),\n          cache = this.matrixCache || (this.matrixCache = {});\n\n      if (cache.key === key) {\n        return cache.value;\n      }\n\n      if (this.group) {\n        matrix = multiplyMatrices(this.group.calcTransformMatrix(false), matrix);\n      }\n\n      cache.key = key;\n      cache.value = matrix;\n      return matrix;\n    },\n\n    /**\n     * calculate transform matrix that represents the current transformations from the\n     * object's properties, this matrix does not include the group transformation\n     * @return {Array} transform matrix for the object\n     */\n    calcOwnMatrix: function () {\n      var key = this.transformMatrixKey(true),\n          cache = this.ownMatrixCache || (this.ownMatrixCache = {});\n\n      if (cache.key === key) {\n        return cache.value;\n      }\n\n      var tMatrix = this._calcTranslateMatrix(),\n          options = {\n        angle: this.angle,\n        translateX: tMatrix[4],\n        translateY: tMatrix[5],\n        scaleX: this.scaleX,\n        scaleY: this.scaleY,\n        skewX: this.skewX,\n        skewY: this.skewY,\n        flipX: this.flipX,\n        flipY: this.flipY\n      };\n\n      cache.key = key;\n      cache.value = util.composeMatrix(options);\n      return cache.value;\n    },\n\n    /*\n     * Calculate object dimensions from its properties\n     * @private\n     * @deprecated since 3.4.0, please use fabric.util._calcDimensionsTransformMatrix\n     * not including or including flipX, flipY to emulate the flipping boolean\n     * @return {Object} .x width dimension\n     * @return {Object} .y height dimension\n     */\n    _calcDimensionsTransformMatrix: function (skewX, skewY, flipping) {\n      return util.calcDimensionsMatrix({\n        skewX: skewX,\n        skewY: skewY,\n        scaleX: this.scaleX * (flipping && this.flipX ? -1 : 1),\n        scaleY: this.scaleY * (flipping && this.flipY ? -1 : 1)\n      });\n    },\n\n    /*\n     * Calculate object dimensions from its properties\n     * @private\n     * @return {Object} .x width dimension\n     * @return {Object} .y height dimension\n     */\n    _getNonTransformedDimensions: function () {\n      var strokeWidth = this.strokeWidth,\n          w = this.width + strokeWidth,\n          h = this.height + strokeWidth;\n      return {\n        x: w,\n        y: h\n      };\n    },\n\n    /*\n     * Calculate object bounding box dimensions from its properties scale, skew.\n     * @param {Number} skewX, a value to override current skewX\n     * @param {Number} skewY, a value to override current skewY\n     * @private\n     * @return {Object} .x width dimension\n     * @return {Object} .y height dimension\n     */\n    _getTransformedDimensions: function (skewX, skewY) {\n      if (typeof skewX === 'undefined') {\n        skewX = this.skewX;\n      }\n\n      if (typeof skewY === 'undefined') {\n        skewY = this.skewY;\n      }\n\n      var dimensions = this._getNonTransformedDimensions(),\n          dimX,\n          dimY,\n          noSkew = skewX === 0 && skewY === 0;\n\n      if (this.strokeUniform) {\n        dimX = this.width;\n        dimY = this.height;\n      } else {\n        dimX = dimensions.x;\n        dimY = dimensions.y;\n      }\n\n      if (noSkew) {\n        return this._finalizeDimensions(dimX * this.scaleX, dimY * this.scaleY);\n      }\n\n      var bbox = util.sizeAfterTransform(dimX, dimY, {\n        scaleX: this.scaleX,\n        scaleY: this.scaleY,\n        skewX: skewX,\n        skewY: skewY\n      });\n      return this._finalizeDimensions(bbox.x, bbox.y);\n    },\n\n    /*\n     * Calculate object bounding box dimensions from its properties scale, skew.\n     * @param Number width width of the bbox\n     * @param Number height height of the bbox\n     * @private\n     * @return {Object} .x finalized width dimension\n     * @return {Object} .y finalized height dimension\n     */\n    _finalizeDimensions: function (width, height) {\n      return this.strokeUniform ? {\n        x: width + this.strokeWidth,\n        y: height + this.strokeWidth\n      } : {\n        x: width,\n        y: height\n      };\n    },\n\n    /*\n     * Calculate object dimensions for controls box, including padding and canvas zoom.\n     * and active selection\n     * private\n     */\n    _calculateCurrentDimensions: function () {\n      var vpt = this.getViewportTransform(),\n          dim = this._getTransformedDimensions(),\n          p = transformPoint(dim, vpt, true);\n\n      return p.scalarAdd(2 * this.padding);\n    }\n  });\n})();\n\nfabric.util.object.extend(fabric.Object.prototype,\n/** @lends fabric.Object.prototype */\n{\n  /**\n   * Moves an object to the bottom of the stack of drawn objects\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  sendToBack: function () {\n    if (this.group) {\n      fabric.StaticCanvas.prototype.sendToBack.call(this.group, this);\n    } else if (this.canvas) {\n      this.canvas.sendToBack(this);\n    }\n\n    return this;\n  },\n\n  /**\n   * Moves an object to the top of the stack of drawn objects\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  bringToFront: function () {\n    if (this.group) {\n      fabric.StaticCanvas.prototype.bringToFront.call(this.group, this);\n    } else if (this.canvas) {\n      this.canvas.bringToFront(this);\n    }\n\n    return this;\n  },\n\n  /**\n   * Moves an object down in stack of drawn objects\n   * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  sendBackwards: function (intersecting) {\n    if (this.group) {\n      fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting);\n    } else if (this.canvas) {\n      this.canvas.sendBackwards(this, intersecting);\n    }\n\n    return this;\n  },\n\n  /**\n   * Moves an object up in stack of drawn objects\n   * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  bringForward: function (intersecting) {\n    if (this.group) {\n      fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting);\n    } else if (this.canvas) {\n      this.canvas.bringForward(this, intersecting);\n    }\n\n    return this;\n  },\n\n  /**\n   * Moves an object to specified level in stack of drawn objects\n   * @param {Number} index New position of object\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  moveTo: function (index) {\n    if (this.group && this.group.type !== 'activeSelection') {\n      fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index);\n    } else if (this.canvas) {\n      this.canvas.moveTo(this, index);\n    }\n\n    return this;\n  }\n});\n/* _TO_SVG_START_ */\n\n(function () {\n  function getSvgColorString(prop, value) {\n    if (!value) {\n      return prop + ': none; ';\n    } else if (value.toLive) {\n      return prop + ': url(#SVGID_' + value.id + '); ';\n    } else {\n      var color = new fabric.Color(value),\n          str = prop + ': ' + color.toRgb() + '; ',\n          opacity = color.getAlpha();\n\n      if (opacity !== 1) {\n        //change the color in rgb + opacity\n        str += prop + '-opacity: ' + opacity.toString() + '; ';\n      }\n\n      return str;\n    }\n  }\n\n  var toFixed = fabric.util.toFixed;\n  fabric.util.object.extend(fabric.Object.prototype,\n  /** @lends fabric.Object.prototype */\n  {\n    /**\n     * Returns styles-string for svg-export\n     * @param {Boolean} skipShadow a boolean to skip shadow filter output\n     * @return {String}\n     */\n    getSvgStyles: function (skipShadow) {\n      var fillRule = this.fillRule ? this.fillRule : 'nonzero',\n          strokeWidth = this.strokeWidth ? this.strokeWidth : '0',\n          strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : 'none',\n          strokeDashOffset = this.strokeDashOffset ? this.strokeDashOffset : '0',\n          strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt',\n          strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter',\n          strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4',\n          opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1',\n          visibility = this.visible ? '' : ' visibility: hidden;',\n          filter = skipShadow ? '' : this.getSvgFilter(),\n          fill = getSvgColorString('fill', this.fill),\n          stroke = getSvgColorString('stroke', this.stroke);\n      return [stroke, 'stroke-width: ', strokeWidth, '; ', 'stroke-dasharray: ', strokeDashArray, '; ', 'stroke-linecap: ', strokeLineCap, '; ', 'stroke-dashoffset: ', strokeDashOffset, '; ', 'stroke-linejoin: ', strokeLineJoin, '; ', 'stroke-miterlimit: ', strokeMiterLimit, '; ', fill, 'fill-rule: ', fillRule, '; ', 'opacity: ', opacity, ';', filter, visibility].join('');\n    },\n\n    /**\n     * Returns styles-string for svg-export\n     * @param {Object} style the object from which to retrieve style properties\n     * @param {Boolean} useWhiteSpace a boolean to include an additional attribute in the style.\n     * @return {String}\n     */\n    getSvgSpanStyles: function (style, useWhiteSpace) {\n      var term = '; ';\n      var fontFamily = style.fontFamily ? 'font-family: ' + (style.fontFamily.indexOf('\\'') === -1 && style.fontFamily.indexOf('\"') === -1 ? '\\'' + style.fontFamily + '\\'' : style.fontFamily) + term : '';\n      var strokeWidth = style.strokeWidth ? 'stroke-width: ' + style.strokeWidth + term : '',\n          fontFamily = fontFamily,\n          fontSize = style.fontSize ? 'font-size: ' + style.fontSize + 'px' + term : '',\n          fontStyle = style.fontStyle ? 'font-style: ' + style.fontStyle + term : '',\n          fontWeight = style.fontWeight ? 'font-weight: ' + style.fontWeight + term : '',\n          fill = style.fill ? getSvgColorString('fill', style.fill) : '',\n          stroke = style.stroke ? getSvgColorString('stroke', style.stroke) : '',\n          textDecoration = this.getSvgTextDecoration(style),\n          deltaY = style.deltaY ? 'baseline-shift: ' + -style.deltaY + '; ' : '';\n\n      if (textDecoration) {\n        textDecoration = 'text-decoration: ' + textDecoration + term;\n      }\n\n      return [stroke, strokeWidth, fontFamily, fontSize, fontStyle, fontWeight, textDecoration, fill, deltaY, useWhiteSpace ? 'white-space: pre; ' : ''].join('');\n    },\n\n    /**\n     * Returns text-decoration property for svg-export\n     * @param {Object} style the object from which to retrieve style properties\n     * @return {String}\n     */\n    getSvgTextDecoration: function (style) {\n      return ['overline', 'underline', 'line-through'].filter(function (decoration) {\n        return style[decoration.replace('-', '')];\n      }).join(' ');\n    },\n\n    /**\n     * Returns filter for svg shadow\n     * @return {String}\n     */\n    getSvgFilter: function () {\n      return this.shadow ? 'filter: url(#SVGID_' + this.shadow.id + ');' : '';\n    },\n\n    /**\n     * Returns id attribute for svg output\n     * @return {String}\n     */\n    getSvgCommons: function () {\n      return [this.id ? 'id=\"' + this.id + '\" ' : '', this.clipPath ? 'clip-path=\"url(#' + this.clipPath.clipPathId + ')\" ' : ''].join('');\n    },\n\n    /**\n     * Returns transform-string for svg-export\n     * @param {Boolean} use the full transform or the single object one.\n     * @return {String}\n     */\n    getSvgTransform: function (full, additionalTransform) {\n      var transform = full ? this.calcTransformMatrix() : this.calcOwnMatrix(),\n          svgTransform = 'transform=\"' + fabric.util.matrixToSVG(transform);\n      return svgTransform + (additionalTransform || '') + '\" ';\n    },\n    _setSVGBg: function (textBgRects) {\n      if (this.backgroundColor) {\n        var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n        textBgRects.push('\\t\\t<rect ', this._getFillAttributes(this.backgroundColor), ' x=\"', toFixed(-this.width / 2, NUM_FRACTION_DIGITS), '\" y=\"', toFixed(-this.height / 2, NUM_FRACTION_DIGITS), '\" width=\"', toFixed(this.width, NUM_FRACTION_DIGITS), '\" height=\"', toFixed(this.height, NUM_FRACTION_DIGITS), '\"></rect>\\n');\n      }\n    },\n\n    /**\n     * Returns svg representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    toSVG: function (reviver) {\n      return this._createBaseSVGMarkup(this._toSVG(reviver), {\n        reviver: reviver\n      });\n    },\n\n    /**\n     * Returns svg clipPath representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    toClipPathSVG: function (reviver) {\n      return '\\t' + this._createBaseClipPathSVGMarkup(this._toSVG(reviver), {\n        reviver: reviver\n      });\n    },\n\n    /**\n     * @private\n     */\n    _createBaseClipPathSVGMarkup: function (objectMarkup, options) {\n      options = options || {};\n      var reviver = options.reviver,\n          additionalTransform = options.additionalTransform || '',\n          commonPieces = [this.getSvgTransform(true, additionalTransform), this.getSvgCommons()].join(''),\n          // insert commons in the markup, style and svgCommons\n      index = objectMarkup.indexOf('COMMON_PARTS');\n      objectMarkup[index] = commonPieces;\n      return reviver ? reviver(objectMarkup.join('')) : objectMarkup.join('');\n    },\n\n    /**\n     * @private\n     */\n    _createBaseSVGMarkup: function (objectMarkup, options) {\n      options = options || {};\n      var noStyle = options.noStyle,\n          reviver = options.reviver,\n          styleInfo = noStyle ? '' : 'style=\"' + this.getSvgStyles() + '\" ',\n          shadowInfo = options.withShadow ? 'style=\"' + this.getSvgFilter() + '\" ' : '',\n          clipPath = this.clipPath,\n          vectorEffect = this.strokeUniform ? 'vector-effect=\"non-scaling-stroke\" ' : '',\n          absoluteClipPath = clipPath && clipPath.absolutePositioned,\n          stroke = this.stroke,\n          fill = this.fill,\n          shadow = this.shadow,\n          commonPieces,\n          markup = [],\n          clipPathMarkup,\n          // insert commons in the markup, style and svgCommons\n      index = objectMarkup.indexOf('COMMON_PARTS'),\n          additionalTransform = options.additionalTransform;\n\n      if (clipPath) {\n        clipPath.clipPathId = 'CLIPPATH_' + fabric.Object.__uid++;\n        clipPathMarkup = '<clipPath id=\"' + clipPath.clipPathId + '\" >\\n' + clipPath.toClipPathSVG(reviver) + '</clipPath>\\n';\n      }\n\n      if (absoluteClipPath) {\n        markup.push('<g ', shadowInfo, this.getSvgCommons(), ' >\\n');\n      }\n\n      markup.push('<g ', this.getSvgTransform(false), !absoluteClipPath ? shadowInfo + this.getSvgCommons() : '', ' >\\n');\n      commonPieces = [styleInfo, vectorEffect, noStyle ? '' : this.addPaintOrder(), ' ', additionalTransform ? 'transform=\"' + additionalTransform + '\" ' : ''].join('');\n      objectMarkup[index] = commonPieces;\n\n      if (fill && fill.toLive) {\n        markup.push(fill.toSVG(this));\n      }\n\n      if (stroke && stroke.toLive) {\n        markup.push(stroke.toSVG(this));\n      }\n\n      if (shadow) {\n        markup.push(shadow.toSVG(this));\n      }\n\n      if (clipPath) {\n        markup.push(clipPathMarkup);\n      }\n\n      markup.push(objectMarkup.join(''));\n      markup.push('</g>\\n');\n      absoluteClipPath && markup.push('</g>\\n');\n      return reviver ? reviver(markup.join('')) : markup.join('');\n    },\n    addPaintOrder: function () {\n      return this.paintFirst !== 'fill' ? ' paint-order=\"' + this.paintFirst + '\" ' : '';\n    }\n  });\n})();\n/* _TO_SVG_END_ */\n\n\n(function () {\n  var extend = fabric.util.object.extend,\n      originalSet = 'stateProperties';\n  /*\n    Depends on `stateProperties`\n  */\n\n  function saveProps(origin, destination, props) {\n    var tmpObj = {},\n        deep = true;\n    props.forEach(function (prop) {\n      tmpObj[prop] = origin[prop];\n    });\n    extend(origin[destination], tmpObj, deep);\n  }\n\n  function _isEqual(origValue, currentValue, firstPass) {\n    if (origValue === currentValue) {\n      // if the objects are identical, return\n      return true;\n    } else if (Array.isArray(origValue)) {\n      if (!Array.isArray(currentValue) || origValue.length !== currentValue.length) {\n        return false;\n      }\n\n      for (var i = 0, len = origValue.length; i < len; i++) {\n        if (!_isEqual(origValue[i], currentValue[i])) {\n          return false;\n        }\n      }\n\n      return true;\n    } else if (origValue && typeof origValue === 'object') {\n      var keys = Object.keys(origValue),\n          key;\n\n      if (!currentValue || typeof currentValue !== 'object' || !firstPass && keys.length !== Object.keys(currentValue).length) {\n        return false;\n      }\n\n      for (var i = 0, len = keys.length; i < len; i++) {\n        key = keys[i]; // since clipPath is in the statefull cache list and the clipPath objects\n        // would be iterated as an object, this would lead to possible infinite recursion\n        // we do not want to compare those.\n\n        if (key === 'canvas' || key === 'group') {\n          continue;\n        }\n\n        if (!_isEqual(origValue[key], currentValue[key])) {\n          return false;\n        }\n      }\n\n      return true;\n    }\n  }\n\n  fabric.util.object.extend(fabric.Object.prototype,\n  /** @lends fabric.Object.prototype */\n  {\n    /**\n     * Returns true if object state (one of its state properties) was changed\n     * @param {String} [propertySet] optional name for the set of property we want to save\n     * @return {Boolean} true if instance' state has changed since `{@link fabric.Object#saveState}` was called\n     */\n    hasStateChanged: function (propertySet) {\n      propertySet = propertySet || originalSet;\n      var dashedPropertySet = '_' + propertySet;\n\n      if (Object.keys(this[dashedPropertySet]).length < this[propertySet].length) {\n        return true;\n      }\n\n      return !_isEqual(this[dashedPropertySet], this, true);\n    },\n\n    /**\n     * Saves state of an object\n     * @param {Object} [options] Object with additional `stateProperties` array to include when saving state\n     * @return {fabric.Object} thisArg\n     */\n    saveState: function (options) {\n      var propertySet = options && options.propertySet || originalSet,\n          destination = '_' + propertySet;\n\n      if (!this[destination]) {\n        return this.setupState(options);\n      }\n\n      saveProps(this, destination, this[propertySet]);\n\n      if (options && options.stateProperties) {\n        saveProps(this, destination, options.stateProperties);\n      }\n\n      return this;\n    },\n\n    /**\n     * Setups state of an object\n     * @param {Object} [options] Object with additional `stateProperties` array to include when saving state\n     * @return {fabric.Object} thisArg\n     */\n    setupState: function (options) {\n      options = options || {};\n      var propertySet = options.propertySet || originalSet;\n      options.propertySet = propertySet;\n      this['_' + propertySet] = {};\n      this.saveState(options);\n      return this;\n    }\n  });\n})();\n\n(function () {\n  var degreesToRadians = fabric.util.degreesToRadians;\n  fabric.util.object.extend(fabric.Object.prototype,\n  /** @lends fabric.Object.prototype */\n  {\n    /**\n     * Determines which corner has been clicked\n     * @private\n     * @param {Object} pointer The pointer indicating the mouse position\n     * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or false if nothing is found\n     */\n    _findTargetCorner: function (pointer, forTouch) {\n      // objects in group, anykind, are not self modificable,\n      // must not return an hovered corner.\n      if (!this.hasControls || this.group || !this.canvas || this.canvas._activeObject !== this) {\n        return false;\n      }\n\n      var ex = pointer.x,\n          ey = pointer.y,\n          xPoints,\n          lines,\n          keys = Object.keys(this.oCoords),\n          j = keys.length - 1,\n          i;\n      this.__corner = 0; // cycle in reverse order so we pick first the one on top\n\n      for (; j >= 0; j--) {\n        i = keys[j];\n\n        if (!this.isControlVisible(i)) {\n          continue;\n        }\n\n        lines = this._getImageLines(forTouch ? this.oCoords[i].touchCorner : this.oCoords[i].corner); // debugging\n        // this.canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);\n        // this.canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);\n        //\n        // this.canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);\n        // this.canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);\n        //\n        // this.canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);\n        // this.canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);\n        //\n        // this.canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);\n        // this.canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);\n\n        xPoints = this._findCrossPoints({\n          x: ex,\n          y: ey\n        }, lines);\n\n        if (xPoints !== 0 && xPoints % 2 === 1) {\n          this.__corner = i;\n          return i;\n        }\n      }\n\n      return false;\n    },\n\n    /**\n     * Calls a function for each control. The function gets called,\n     * with the control, the object that is calling the iterator and the control's key\n     * @param {Function} fn function to iterate over the controls over\n     */\n    forEachControl: function (fn) {\n      for (var i in this.controls) {\n        fn(this.controls[i], i, this);\n      }\n\n      ;\n    },\n\n    /**\n     * Sets the coordinates of the draggable boxes in the corners of\n     * the image used to scale/rotate it.\n     * note: if we would switch to ROUND corner area, all of this would disappear.\n     * everything would resolve to a single point and a pythagorean theorem for the distance\n     * @private\n     */\n    _setCornerCoords: function () {\n      var coords = this.oCoords,\n          newTheta = degreesToRadians(45 - this.angle),\n          cosTheta = fabric.util.cos(newTheta),\n          sinTheta = fabric.util.sin(newTheta),\n\n      /* Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, */\n\n      /* 0.707106 stands for sqrt(2)/2 */\n      cornerHypotenuse = this.cornerSize * 0.707106,\n          touchHypotenuse = this.touchCornerSize * 0.707106,\n          cosHalfOffset = cornerHypotenuse * cosTheta,\n          sinHalfOffset = cornerHypotenuse * sinTheta,\n          touchCosHalfOffset = touchHypotenuse * cosTheta,\n          touchSinHalfOffset = touchHypotenuse * sinTheta,\n          x,\n          y;\n\n      for (var control in coords) {\n        x = coords[control].x;\n        y = coords[control].y;\n        coords[control].corner = {\n          tl: {\n            x: x - sinHalfOffset,\n            y: y - cosHalfOffset\n          },\n          tr: {\n            x: x + cosHalfOffset,\n            y: y - sinHalfOffset\n          },\n          bl: {\n            x: x - cosHalfOffset,\n            y: y + sinHalfOffset\n          },\n          br: {\n            x: x + sinHalfOffset,\n            y: y + cosHalfOffset\n          }\n        };\n        coords[control].touchCorner = {\n          tl: {\n            x: x - touchSinHalfOffset,\n            y: y - touchCosHalfOffset\n          },\n          tr: {\n            x: x + touchCosHalfOffset,\n            y: y - touchSinHalfOffset\n          },\n          bl: {\n            x: x - touchCosHalfOffset,\n            y: y + touchSinHalfOffset\n          },\n          br: {\n            x: x + touchSinHalfOffset,\n            y: y + touchCosHalfOffset\n          }\n        };\n      }\n    },\n\n    /**\n     * Draws a colored layer behind the object, inside its selection borders.\n     * Requires public options: padding, selectionBackgroundColor\n     * this function is called when the context is transformed\n     * has checks to be skipped when the object is on a staticCanvas\n     * @param {CanvasRenderingContext2D} ctx Context to draw on\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    drawSelectionBackground: function (ctx) {\n      if (!this.selectionBackgroundColor || this.canvas && !this.canvas.interactive || this.canvas && this.canvas._activeObject !== this) {\n        return this;\n      }\n\n      ctx.save();\n\n      var center = this.getCenterPoint(),\n          wh = this._calculateCurrentDimensions(),\n          vpt = this.canvas.viewportTransform;\n\n      ctx.translate(center.x, center.y);\n      ctx.scale(1 / vpt[0], 1 / vpt[3]);\n      ctx.rotate(degreesToRadians(this.angle));\n      ctx.fillStyle = this.selectionBackgroundColor;\n      ctx.fillRect(-wh.x / 2, -wh.y / 2, wh.x, wh.y);\n      ctx.restore();\n      return this;\n    },\n\n    /**\n     * Draws borders of an object's bounding box.\n     * Requires public properties: width, height\n     * Requires public options: padding, borderColor\n     * @param {CanvasRenderingContext2D} ctx Context to draw on\n     * @param {Object} styleOverride object to override the object style\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    drawBorders: function (ctx, styleOverride) {\n      styleOverride = styleOverride || {};\n\n      var wh = this._calculateCurrentDimensions(),\n          strokeWidth = this.borderScaleFactor,\n          width = wh.x + strokeWidth,\n          height = wh.y + strokeWidth,\n          hasControls = typeof styleOverride.hasControls !== 'undefined' ? styleOverride.hasControls : this.hasControls,\n          shouldStroke = false;\n\n      ctx.save();\n      ctx.strokeStyle = styleOverride.borderColor || this.borderColor;\n\n      this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray, null);\n\n      ctx.strokeRect(-width / 2, -height / 2, width, height);\n\n      if (hasControls) {\n        ctx.beginPath();\n        this.forEachControl(function (control, key, fabricObject) {\n          // in this moment, the ctx is centered on the object.\n          // width and height of the above function are the size of the bbox.\n          if (control.withConnection && control.getVisibility(fabricObject, key)) {\n            // reset movement for each control\n            shouldStroke = true;\n            ctx.moveTo(control.x * width, control.y * height);\n            ctx.lineTo(control.x * width + control.offsetX, control.y * height + control.offsetY);\n          }\n        });\n\n        if (shouldStroke) {\n          ctx.stroke();\n        }\n      }\n\n      ctx.restore();\n      return this;\n    },\n\n    /**\n     * Draws borders of an object's bounding box when it is inside a group.\n     * Requires public properties: width, height\n     * Requires public options: padding, borderColor\n     * @param {CanvasRenderingContext2D} ctx Context to draw on\n     * @param {object} options object representing current object parameters\n     * @param {Object} styleOverride object to override the object style\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    drawBordersInGroup: function (ctx, options, styleOverride) {\n      styleOverride = styleOverride || {};\n      var bbox = fabric.util.sizeAfterTransform(this.width, this.height, options),\n          strokeWidth = this.strokeWidth,\n          strokeUniform = this.strokeUniform,\n          borderScaleFactor = this.borderScaleFactor,\n          width = bbox.x + strokeWidth * (strokeUniform ? this.canvas.getZoom() : options.scaleX) + borderScaleFactor,\n          height = bbox.y + strokeWidth * (strokeUniform ? this.canvas.getZoom() : options.scaleY) + borderScaleFactor;\n      ctx.save();\n\n      this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray, null);\n\n      ctx.strokeStyle = styleOverride.borderColor || this.borderColor;\n      ctx.strokeRect(-width / 2, -height / 2, width, height);\n      ctx.restore();\n      return this;\n    },\n\n    /**\n     * Draws corners of an object's bounding box.\n     * Requires public properties: width, height\n     * Requires public options: cornerSize, padding\n     * @param {CanvasRenderingContext2D} ctx Context to draw on\n     * @param {Object} styleOverride object to override the object style\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    drawControls: function (ctx, styleOverride) {\n      styleOverride = styleOverride || {};\n      ctx.save();\n      ctx.setTransform(this.canvas.getRetinaScaling(), 0, 0, this.canvas.getRetinaScaling(), 0, 0);\n      ctx.strokeStyle = ctx.fillStyle = styleOverride.cornerColor || this.cornerColor;\n\n      if (!this.transparentCorners) {\n        ctx.strokeStyle = styleOverride.cornerStrokeColor || this.cornerStrokeColor;\n      }\n\n      this._setLineDash(ctx, styleOverride.cornerDashArray || this.cornerDashArray, null);\n\n      this.setCoords();\n      this.forEachControl(function (control, key, fabricObject) {\n        if (control.getVisibility(fabricObject, key)) {\n          control.render(ctx, fabricObject.oCoords[key].x, fabricObject.oCoords[key].y, styleOverride, fabricObject);\n        }\n      });\n      ctx.restore();\n      return this;\n    },\n\n    /**\n     * Returns true if the specified control is visible, false otherwise.\n     * @param {String} controlKey The key of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'.\n     * @returns {Boolean} true if the specified control is visible, false otherwise\n     */\n    isControlVisible: function (controlKey) {\n      return this.controls[controlKey] && this.controls[controlKey].getVisibility(this, controlKey);\n    },\n\n    /**\n     * Sets the visibility of the specified control.\n     * @param {String} controlKey The key of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'.\n     * @param {Boolean} visible true to set the specified control visible, false otherwise\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    setControlVisible: function (controlKey, visible) {\n      if (!this._controlsVisibility) {\n        this._controlsVisibility = {};\n      }\n\n      this._controlsVisibility[controlKey] = visible;\n      return this;\n    },\n\n    /**\n     * Sets the visibility state of object controls.\n     * @param {Object} [options] Options object\n     * @param {Boolean} [options.bl] true to enable the bottom-left control, false to disable it\n     * @param {Boolean} [options.br] true to enable the bottom-right control, false to disable it\n     * @param {Boolean} [options.mb] true to enable the middle-bottom control, false to disable it\n     * @param {Boolean} [options.ml] true to enable the middle-left control, false to disable it\n     * @param {Boolean} [options.mr] true to enable the middle-right control, false to disable it\n     * @param {Boolean} [options.mt] true to enable the middle-top control, false to disable it\n     * @param {Boolean} [options.tl] true to enable the top-left control, false to disable it\n     * @param {Boolean} [options.tr] true to enable the top-right control, false to disable it\n     * @param {Boolean} [options.mtr] true to enable the middle-top-rotate control, false to disable it\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    setControlsVisibility: function (options) {\n      options || (options = {});\n\n      for (var p in options) {\n        this.setControlVisible(p, options[p]);\n      }\n\n      return this;\n    },\n\n    /**\n     * This callback function is called every time _discardActiveObject or _setActiveObject\n     * try to to deselect this object. If the function returns true, the process is cancelled\n     * @param {Object} [options] options sent from the upper functions\n     * @param {Event} [options.e] event if the process is generated by an event\n     */\n    onDeselect: function () {// implemented by sub-classes, as needed.\n    },\n\n    /**\n     * This callback function is called every time _discardActiveObject or _setActiveObject\n     * try to to select this object. If the function returns true, the process is cancelled\n     * @param {Object} [options] options sent from the upper functions\n     * @param {Event} [options.e] event if the process is generated by an event\n     */\n    onSelect: function () {// implemented by sub-classes, as needed.\n    }\n  });\n})();\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype,\n/** @lends fabric.StaticCanvas.prototype */\n{\n  /**\n   * Animation duration (in ms) for fx* methods\n   * @type Number\n   * @default\n   */\n  FX_DURATION: 500,\n\n  /**\n   * Centers object horizontally with animation.\n   * @param {fabric.Object} object Object to center\n   * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n   * @param {Function} [callbacks.onComplete] Invoked on completion\n   * @param {Function} [callbacks.onChange] Invoked on every step of animation\n   * @return {fabric.Canvas} thisArg\n   * @chainable\n   */\n  fxCenterObjectH: function (object, callbacks) {\n    callbacks = callbacks || {};\n\n    var empty = function () {},\n        onComplete = callbacks.onComplete || empty,\n        onChange = callbacks.onChange || empty,\n        _this = this;\n\n    fabric.util.animate({\n      startValue: object.left,\n      endValue: this.getCenter().left,\n      duration: this.FX_DURATION,\n      onChange: function (value) {\n        object.set('left', value);\n\n        _this.requestRenderAll();\n\n        onChange();\n      },\n      onComplete: function () {\n        object.setCoords();\n        onComplete();\n      }\n    });\n    return this;\n  },\n\n  /**\n   * Centers object vertically with animation.\n   * @param {fabric.Object} object Object to center\n   * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n   * @param {Function} [callbacks.onComplete] Invoked on completion\n   * @param {Function} [callbacks.onChange] Invoked on every step of animation\n   * @return {fabric.Canvas} thisArg\n   * @chainable\n   */\n  fxCenterObjectV: function (object, callbacks) {\n    callbacks = callbacks || {};\n\n    var empty = function () {},\n        onComplete = callbacks.onComplete || empty,\n        onChange = callbacks.onChange || empty,\n        _this = this;\n\n    fabric.util.animate({\n      startValue: object.top,\n      endValue: this.getCenter().top,\n      duration: this.FX_DURATION,\n      onChange: function (value) {\n        object.set('top', value);\n\n        _this.requestRenderAll();\n\n        onChange();\n      },\n      onComplete: function () {\n        object.setCoords();\n        onComplete();\n      }\n    });\n    return this;\n  },\n\n  /**\n   * Same as `fabric.Canvas#remove` but animated\n   * @param {fabric.Object} object Object to remove\n   * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n   * @param {Function} [callbacks.onComplete] Invoked on completion\n   * @param {Function} [callbacks.onChange] Invoked on every step of animation\n   * @return {fabric.Canvas} thisArg\n   * @chainable\n   */\n  fxRemove: function (object, callbacks) {\n    callbacks = callbacks || {};\n\n    var empty = function () {},\n        onComplete = callbacks.onComplete || empty,\n        onChange = callbacks.onChange || empty,\n        _this = this;\n\n    fabric.util.animate({\n      startValue: object.opacity,\n      endValue: 0,\n      duration: this.FX_DURATION,\n      onChange: function (value) {\n        object.set('opacity', value);\n\n        _this.requestRenderAll();\n\n        onChange();\n      },\n      onComplete: function () {\n        _this.remove(object);\n\n        onComplete();\n      }\n    });\n    return this;\n  }\n});\nfabric.util.object.extend(fabric.Object.prototype,\n/** @lends fabric.Object.prototype */\n{\n  /**\n   * Animates object's properties\n   * @param {String|Object} property Property to animate (if string) or properties to animate (if object)\n   * @param {Number|Object} value Value to animate property to (if string was given first) or options object\n   * @return {fabric.Object} thisArg\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#animation}\n   * @chainable\n   *\n   * As object — multiple properties\n   *\n   * object.animate({ left: ..., top: ... });\n   * object.animate({ left: ..., top: ... }, { duration: ... });\n   *\n   * As string — one property\n   *\n   * object.animate('left', ...);\n   * object.animate('left', { duration: ... });\n   *\n   */\n  animate: function () {\n    if (arguments[0] && typeof arguments[0] === 'object') {\n      var propsToAnimate = [],\n          prop,\n          skipCallbacks;\n\n      for (prop in arguments[0]) {\n        propsToAnimate.push(prop);\n      }\n\n      for (var i = 0, len = propsToAnimate.length; i < len; i++) {\n        prop = propsToAnimate[i];\n        skipCallbacks = i !== len - 1;\n\n        this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks);\n      }\n    } else {\n      this._animate.apply(this, arguments);\n    }\n\n    return this;\n  },\n\n  /**\n   * @private\n   * @param {String} property Property to animate\n   * @param {String} to Value to animate to\n   * @param {Object} [options] Options object\n   * @param {Boolean} [skipCallbacks] When true, callbacks like onchange and oncomplete are not invoked\n   */\n  _animate: function (property, to, options, skipCallbacks) {\n    var _this = this,\n        propPair;\n\n    to = to.toString();\n\n    if (!options) {\n      options = {};\n    } else {\n      options = fabric.util.object.clone(options);\n    }\n\n    if (~property.indexOf('.')) {\n      propPair = property.split('.');\n    }\n\n    var propIsColor = _this.colorProperties.indexOf(property) > -1 || propPair && _this.colorProperties.indexOf(propPair[1]) > -1;\n    var currentValue = propPair ? this.get(propPair[0])[propPair[1]] : this.get(property);\n\n    if (!('from' in options)) {\n      options.from = currentValue;\n    }\n\n    if (!propIsColor) {\n      if (~to.indexOf('=')) {\n        to = currentValue + parseFloat(to.replace('=', ''));\n      } else {\n        to = parseFloat(to);\n      }\n    }\n\n    var _options = {\n      startValue: options.from,\n      endValue: to,\n      byValue: options.by,\n      easing: options.easing,\n      duration: options.duration,\n      abort: options.abort && function () {\n        return options.abort.call(_this);\n      },\n      onChange: function (value, valueProgress, timeProgress) {\n        if (propPair) {\n          _this[propPair[0]][propPair[1]] = value;\n        } else {\n          _this.set(property, value);\n        }\n\n        if (skipCallbacks) {\n          return;\n        }\n\n        options.onChange && options.onChange(value, valueProgress, timeProgress);\n      },\n      onComplete: function (value, valueProgress, timeProgress) {\n        if (skipCallbacks) {\n          return;\n        }\n\n        _this.setCoords();\n\n        options.onComplete && options.onComplete(value, valueProgress, timeProgress);\n      }\n    };\n\n    if (propIsColor) {\n      fabric.util.animateColor(_options.startValue, _options.endValue, _options.duration, _options);\n    } else {\n      fabric.util.animate(_options);\n    }\n  }\n});\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      extend = fabric.util.object.extend,\n      clone = fabric.util.object.clone,\n      coordProps = {\n    x1: 1,\n    x2: 1,\n    y1: 1,\n    y2: 1\n  },\n      supportsLineDash = fabric.StaticCanvas.supports('setLineDash');\n\n  if (fabric.Line) {\n    fabric.warn('fabric.Line is already defined');\n    return;\n  }\n  /**\n   * Line class\n   * @class fabric.Line\n   * @extends fabric.Object\n   * @see {@link fabric.Line#initialize} for constructor definition\n   */\n\n\n  fabric.Line = fabric.util.createClass(fabric.Object,\n  /** @lends fabric.Line.prototype */\n  {\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'line',\n\n    /**\n     * x value or first line edge\n     * @type Number\n     * @default\n     */\n    x1: 0,\n\n    /**\n     * y value or first line edge\n     * @type Number\n     * @default\n     */\n    y1: 0,\n\n    /**\n     * x value or second line edge\n     * @type Number\n     * @default\n     */\n    x2: 0,\n\n    /**\n     * y value or second line edge\n     * @type Number\n     * @default\n     */\n    y2: 0,\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('x1', 'x2', 'y1', 'y2'),\n\n    /**\n     * Constructor\n     * @param {Array} [points] Array of points\n     * @param {Object} [options] Options object\n     * @return {fabric.Line} thisArg\n     */\n    initialize: function (points, options) {\n      if (!points) {\n        points = [0, 0, 0, 0];\n      }\n\n      this.callSuper('initialize', options);\n      this.set('x1', points[0]);\n      this.set('y1', points[1]);\n      this.set('x2', points[2]);\n      this.set('y2', points[3]);\n\n      this._setWidthHeight(options);\n    },\n\n    /**\n     * @private\n     * @param {Object} [options] Options\n     */\n    _setWidthHeight: function (options) {\n      options || (options = {});\n      this.width = Math.abs(this.x2 - this.x1);\n      this.height = Math.abs(this.y2 - this.y1);\n      this.left = 'left' in options ? options.left : this._getLeftToOriginX();\n      this.top = 'top' in options ? options.top : this._getTopToOriginY();\n    },\n\n    /**\n     * @private\n     * @param {String} key\n     * @param {*} value\n     */\n    _set: function (key, value) {\n      this.callSuper('_set', key, value);\n\n      if (typeof coordProps[key] !== 'undefined') {\n        this._setWidthHeight();\n      }\n\n      return this;\n    },\n\n    /**\n     * @private\n     * @return {Number} leftToOriginX Distance from left edge of canvas to originX of Line.\n     */\n    _getLeftToOriginX: makeEdgeToOriginGetter({\n      // property names\n      origin: 'originX',\n      axis1: 'x1',\n      axis2: 'x2',\n      dimension: 'width'\n    }, {\n      // possible values of origin\n      nearest: 'left',\n      center: 'center',\n      farthest: 'right'\n    }),\n\n    /**\n     * @private\n     * @return {Number} topToOriginY Distance from top edge of canvas to originY of Line.\n     */\n    _getTopToOriginY: makeEdgeToOriginGetter({\n      // property names\n      origin: 'originY',\n      axis1: 'y1',\n      axis2: 'y2',\n      dimension: 'height'\n    }, {\n      // possible values of origin\n      nearest: 'top',\n      center: 'center',\n      farthest: 'bottom'\n    }),\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function (ctx) {\n      ctx.beginPath();\n\n      if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) {\n        // move from center (of virtual box) to its left/top corner\n        // we can't assume x1, y1 is top left and x2, y2 is bottom right\n        var p = this.calcLinePoints();\n        ctx.moveTo(p.x1, p.y1);\n        ctx.lineTo(p.x2, p.y2);\n      }\n\n      ctx.lineWidth = this.strokeWidth; // TODO: test this\n      // make sure setting \"fill\" changes color of a line\n      // (by copying fillStyle to strokeStyle, since line is stroked, not filled)\n\n      var origStrokeStyle = ctx.strokeStyle;\n      ctx.strokeStyle = this.stroke || ctx.fillStyle;\n      this.stroke && this._renderStroke(ctx);\n      ctx.strokeStyle = origStrokeStyle;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderDashedStroke: function (ctx) {\n      var p = this.calcLinePoints();\n      ctx.beginPath();\n      fabric.util.drawDashedLine(ctx, p.x1, p.y1, p.x2, p.y2, this.strokeDashArray);\n      ctx.closePath();\n    },\n\n    /**\n     * This function is an helper for svg import. it returns the center of the object in the svg\n     * untransformed coordinates\n     * @private\n     * @return {Object} center point from element coordinates\n     */\n    _findCenterFromElement: function () {\n      return {\n        x: (this.x1 + this.x2) / 2,\n        y: (this.y1 + this.y2) / 2\n      };\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @methd toObject\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function (propertiesToInclude) {\n      return extend(this.callSuper('toObject', propertiesToInclude), this.calcLinePoints());\n    },\n\n    /*\n     * Calculate object dimensions from its properties\n     * @private\n     */\n    _getNonTransformedDimensions: function () {\n      var dim = this.callSuper('_getNonTransformedDimensions');\n\n      if (this.strokeLineCap === 'butt') {\n        if (this.width === 0) {\n          dim.y -= this.strokeWidth;\n        }\n\n        if (this.height === 0) {\n          dim.x -= this.strokeWidth;\n        }\n      }\n\n      return dim;\n    },\n\n    /**\n     * Recalculates line points given width and height\n     * @private\n     */\n    calcLinePoints: function () {\n      var xMult = this.x1 <= this.x2 ? -1 : 1,\n          yMult = this.y1 <= this.y2 ? -1 : 1,\n          x1 = xMult * this.width * 0.5,\n          y1 = yMult * this.height * 0.5,\n          x2 = xMult * this.width * -0.5,\n          y2 = yMult * this.height * -0.5;\n      return {\n        x1: x1,\n        x2: x2,\n        y1: y1,\n        y2: y2\n      };\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function () {\n      var p = this.calcLinePoints();\n      return ['<line ', 'COMMON_PARTS', 'x1=\"', p.x1, '\" y1=\"', p.y1, '\" x2=\"', p.x2, '\" y2=\"', p.y2, '\" />\\n'];\n    }\n    /* _TO_SVG_END_ */\n\n  });\n  /* _FROM_SVG_START_ */\n\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement})\n   * @static\n   * @memberOf fabric.Line\n   * @see http://www.w3.org/TR/SVG/shapes.html#LineElement\n   */\n\n  fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' '));\n  /**\n   * Returns fabric.Line instance from an SVG element\n   * @static\n   * @memberOf fabric.Line\n   * @param {SVGElement} element Element to parse\n   * @param {Object} [options] Options object\n   * @param {Function} [callback] callback function invoked after parsing\n   */\n\n  fabric.Line.fromElement = function (element, callback, options) {\n    options = options || {};\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES),\n        points = [parsedAttributes.x1 || 0, parsedAttributes.y1 || 0, parsedAttributes.x2 || 0, parsedAttributes.y2 || 0];\n    callback(new fabric.Line(points, extend(parsedAttributes, options)));\n  };\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns fabric.Line instance from an object representation\n   * @static\n   * @memberOf fabric.Line\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] invoked with new instance as first argument\n   */\n\n\n  fabric.Line.fromObject = function (object, callback) {\n    function _callback(instance) {\n      delete instance.points;\n      callback && callback(instance);\n    }\n\n    ;\n    var options = clone(object, true);\n    options.points = [object.x1, object.y1, object.x2, object.y2];\n\n    fabric.Object._fromObject('Line', options, _callback, 'points');\n  };\n  /**\n   * Produces a function that calculates distance from canvas edge to Line origin.\n   */\n\n\n  function makeEdgeToOriginGetter(propertyNames, originValues) {\n    var origin = propertyNames.origin,\n        axis1 = propertyNames.axis1,\n        axis2 = propertyNames.axis2,\n        dimension = propertyNames.dimension,\n        nearest = originValues.nearest,\n        center = originValues.center,\n        farthest = originValues.farthest;\n    return function () {\n      switch (this.get(origin)) {\n        case nearest:\n          return Math.min(this.get(axis1), this.get(axis2));\n\n        case center:\n          return Math.min(this.get(axis1), this.get(axis2)) + 0.5 * this.get(dimension);\n\n        case farthest:\n          return Math.max(this.get(axis1), this.get(axis2));\n      }\n    };\n  }\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      pi = Math.PI;\n\n  if (fabric.Circle) {\n    fabric.warn('fabric.Circle is already defined.');\n    return;\n  }\n  /**\n   * Circle class\n   * @class fabric.Circle\n   * @extends fabric.Object\n   * @see {@link fabric.Circle#initialize} for constructor definition\n   */\n\n\n  fabric.Circle = fabric.util.createClass(fabric.Object,\n  /** @lends fabric.Circle.prototype */\n  {\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'circle',\n\n    /**\n     * Radius of this circle\n     * @type Number\n     * @default\n     */\n    radius: 0,\n\n    /**\n     * Start angle of the circle, moving clockwise\n     * deprectated type, this should be in degree, this was an oversight.\n     * probably will change to degrees in next major version\n     * @type Number\n     * @default 0\n     */\n    startAngle: 0,\n\n    /**\n     * End angle of the circle\n     * deprectated type, this should be in degree, this was an oversight.\n     * probably will change to degrees in next major version\n     * @type Number\n     * @default 2Pi\n     */\n    endAngle: pi * 2,\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('radius', 'startAngle', 'endAngle'),\n\n    /**\n     * @private\n     * @param {String} key\n     * @param {*} value\n     * @return {fabric.Circle} thisArg\n     */\n    _set: function (key, value) {\n      this.callSuper('_set', key, value);\n\n      if (key === 'radius') {\n        this.setRadius(value);\n      }\n\n      return this;\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function (propertiesToInclude) {\n      return this.callSuper('toObject', ['radius', 'startAngle', 'endAngle'].concat(propertiesToInclude));\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function () {\n      var svgString,\n          x = 0,\n          y = 0,\n          angle = (this.endAngle - this.startAngle) % (2 * pi);\n\n      if (angle === 0) {\n        svgString = ['<circle ', 'COMMON_PARTS', 'cx=\"' + x + '\" cy=\"' + y + '\" ', 'r=\"', this.radius, '\" />\\n'];\n      } else {\n        var startX = fabric.util.cos(this.startAngle) * this.radius,\n            startY = fabric.util.sin(this.startAngle) * this.radius,\n            endX = fabric.util.cos(this.endAngle) * this.radius,\n            endY = fabric.util.sin(this.endAngle) * this.radius,\n            largeFlag = angle > pi ? '1' : '0';\n        svgString = ['<path d=\"M ' + startX + ' ' + startY, ' A ' + this.radius + ' ' + this.radius, ' 0 ', +largeFlag + ' 1', ' ' + endX + ' ' + endY, '\" ', 'COMMON_PARTS', ' />\\n'];\n      }\n\n      return svgString;\n    },\n\n    /* _TO_SVG_END_ */\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx context to render on\n     */\n    _render: function (ctx) {\n      ctx.beginPath();\n      ctx.arc(0, 0, this.radius, this.startAngle, this.endAngle, false);\n\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * Returns horizontal radius of an object (according to how an object is scaled)\n     * @return {Number}\n     */\n    getRadiusX: function () {\n      return this.get('radius') * this.get('scaleX');\n    },\n\n    /**\n     * Returns vertical radius of an object (according to how an object is scaled)\n     * @return {Number}\n     */\n    getRadiusY: function () {\n      return this.get('radius') * this.get('scaleY');\n    },\n\n    /**\n     * Sets radius of an object (and updates width accordingly)\n     * @return {fabric.Circle} thisArg\n     */\n    setRadius: function (value) {\n      this.radius = value;\n      return this.set('width', value * 2).set('height', value * 2);\n    }\n  });\n  /* _FROM_SVG_START_ */\n\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Circle.fromElement})\n   * @static\n   * @memberOf fabric.Circle\n   * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement\n   */\n\n  fabric.Circle.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy r'.split(' '));\n  /**\n   * Returns {@link fabric.Circle} instance from an SVG element\n   * @static\n   * @memberOf fabric.Circle\n   * @param {SVGElement} element Element to parse\n   * @param {Function} [callback] Options callback invoked after parsing is finished\n   * @param {Object} [options] Options object\n   * @throws {Error} If value of `r` attribute is missing or invalid\n   */\n\n  fabric.Circle.fromElement = function (element, callback) {\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES);\n\n    if (!isValidRadius(parsedAttributes)) {\n      throw new Error('value of `r` attribute is required and can not be negative');\n    }\n\n    parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.radius;\n    parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.radius;\n    callback(new fabric.Circle(parsedAttributes));\n  };\n  /**\n   * @private\n   */\n\n\n  function isValidRadius(attributes) {\n    return 'radius' in attributes && attributes.radius >= 0;\n  }\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns {@link fabric.Circle} instance from an object representation\n   * @static\n   * @memberOf fabric.Circle\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] invoked with new instance as first argument\n   * @return {Object} Instance of fabric.Circle\n   */\n\n\n  fabric.Circle.fromObject = function (object, callback) {\n    return fabric.Object._fromObject('Circle', object, callback);\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {});\n\n  if (fabric.Triangle) {\n    fabric.warn('fabric.Triangle is already defined');\n    return;\n  }\n  /**\n   * Triangle class\n   * @class fabric.Triangle\n   * @extends fabric.Object\n   * @return {fabric.Triangle} thisArg\n   * @see {@link fabric.Triangle#initialize} for constructor definition\n   */\n\n\n  fabric.Triangle = fabric.util.createClass(fabric.Object,\n  /** @lends fabric.Triangle.prototype */\n  {\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'triangle',\n\n    /**\n     * Width is set to 100 to compensate the old initialize code that was setting it to 100\n     * @type Number\n     * @default\n     */\n    width: 100,\n\n    /**\n     * Height is set to 100 to compensate the old initialize code that was setting it to 100\n     * @type Number\n     * @default\n     */\n    height: 100,\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function (ctx) {\n      var widthBy2 = this.width / 2,\n          heightBy2 = this.height / 2;\n      ctx.beginPath();\n      ctx.moveTo(-widthBy2, heightBy2);\n      ctx.lineTo(0, -heightBy2);\n      ctx.lineTo(widthBy2, heightBy2);\n      ctx.closePath();\n\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderDashedStroke: function (ctx) {\n      var widthBy2 = this.width / 2,\n          heightBy2 = this.height / 2;\n      ctx.beginPath();\n      fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray);\n      ctx.closePath();\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function () {\n      var widthBy2 = this.width / 2,\n          heightBy2 = this.height / 2,\n          points = [-widthBy2 + ' ' + heightBy2, '0 ' + -heightBy2, widthBy2 + ' ' + heightBy2].join(',');\n      return ['<polygon ', 'COMMON_PARTS', 'points=\"', points, '\" />'];\n    }\n    /* _TO_SVG_END_ */\n\n  });\n  /**\n   * Returns {@link fabric.Triangle} instance from an object representation\n   * @static\n   * @memberOf fabric.Triangle\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] invoked with new instance as first argument\n   */\n\n  fabric.Triangle.fromObject = function (object, callback) {\n    return fabric.Object._fromObject('Triangle', object, callback);\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      piBy2 = Math.PI * 2;\n\n  if (fabric.Ellipse) {\n    fabric.warn('fabric.Ellipse is already defined.');\n    return;\n  }\n  /**\n   * Ellipse class\n   * @class fabric.Ellipse\n   * @extends fabric.Object\n   * @return {fabric.Ellipse} thisArg\n   * @see {@link fabric.Ellipse#initialize} for constructor definition\n   */\n\n\n  fabric.Ellipse = fabric.util.createClass(fabric.Object,\n  /** @lends fabric.Ellipse.prototype */\n  {\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'ellipse',\n\n    /**\n     * Horizontal radius\n     * @type Number\n     * @default\n     */\n    rx: 0,\n\n    /**\n     * Vertical radius\n     * @type Number\n     * @default\n     */\n    ry: 0,\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('rx', 'ry'),\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     * @return {fabric.Ellipse} thisArg\n     */\n    initialize: function (options) {\n      this.callSuper('initialize', options);\n      this.set('rx', options && options.rx || 0);\n      this.set('ry', options && options.ry || 0);\n    },\n\n    /**\n     * @private\n     * @param {String} key\n     * @param {*} value\n     * @return {fabric.Ellipse} thisArg\n     */\n    _set: function (key, value) {\n      this.callSuper('_set', key, value);\n\n      switch (key) {\n        case 'rx':\n          this.rx = value;\n          this.set('width', value * 2);\n          break;\n\n        case 'ry':\n          this.ry = value;\n          this.set('height', value * 2);\n          break;\n      }\n\n      return this;\n    },\n\n    /**\n     * Returns horizontal radius of an object (according to how an object is scaled)\n     * @return {Number}\n     */\n    getRx: function () {\n      return this.get('rx') * this.get('scaleX');\n    },\n\n    /**\n     * Returns Vertical radius of an object (according to how an object is scaled)\n     * @return {Number}\n     */\n    getRy: function () {\n      return this.get('ry') * this.get('scaleY');\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function (propertiesToInclude) {\n      return this.callSuper('toObject', ['rx', 'ry'].concat(propertiesToInclude));\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function () {\n      return ['<ellipse ', 'COMMON_PARTS', 'cx=\"0\" cy=\"0\" ', 'rx=\"', this.rx, '\" ry=\"', this.ry, '\" />\\n'];\n    },\n\n    /* _TO_SVG_END_ */\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx context to render on\n     */\n    _render: function (ctx) {\n      ctx.beginPath();\n      ctx.save();\n      ctx.transform(1, 0, 0, this.ry / this.rx, 0, 0);\n      ctx.arc(0, 0, this.rx, 0, piBy2, false);\n      ctx.restore();\n\n      this._renderPaintInOrder(ctx);\n    }\n  });\n  /* _FROM_SVG_START_ */\n\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Ellipse.fromElement})\n   * @static\n   * @memberOf fabric.Ellipse\n   * @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement\n   */\n\n  fabric.Ellipse.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy rx ry'.split(' '));\n  /**\n   * Returns {@link fabric.Ellipse} instance from an SVG element\n   * @static\n   * @memberOf fabric.Ellipse\n   * @param {SVGElement} element Element to parse\n   * @param {Function} [callback] Options callback invoked after parsing is finished\n   * @return {fabric.Ellipse}\n   */\n\n  fabric.Ellipse.fromElement = function (element, callback) {\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES);\n    parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.rx;\n    parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.ry;\n    callback(new fabric.Ellipse(parsedAttributes));\n  };\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns {@link fabric.Ellipse} instance from an object representation\n   * @static\n   * @memberOf fabric.Ellipse\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] invoked with new instance as first argument\n   * @return {fabric.Ellipse}\n   */\n\n\n  fabric.Ellipse.fromObject = function (object, callback) {\n    return fabric.Object._fromObject('Ellipse', object, callback);\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      extend = fabric.util.object.extend;\n\n  if (fabric.Rect) {\n    fabric.warn('fabric.Rect is already defined');\n    return;\n  }\n  /**\n   * Rectangle class\n   * @class fabric.Rect\n   * @extends fabric.Object\n   * @return {fabric.Rect} thisArg\n   * @see {@link fabric.Rect#initialize} for constructor definition\n   */\n\n\n  fabric.Rect = fabric.util.createClass(fabric.Object,\n  /** @lends fabric.Rect.prototype */\n  {\n    /**\n     * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})\n     * as well as for history (undo/redo) purposes\n     * @type Array\n     */\n    stateProperties: fabric.Object.prototype.stateProperties.concat('rx', 'ry'),\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'rect',\n\n    /**\n     * Horizontal border radius\n     * @type Number\n     * @default\n     */\n    rx: 0,\n\n    /**\n     * Vertical border radius\n     * @type Number\n     * @default\n     */\n    ry: 0,\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('rx', 'ry'),\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     * @return {Object} thisArg\n     */\n    initialize: function (options) {\n      this.callSuper('initialize', options);\n\n      this._initRxRy();\n    },\n\n    /**\n     * Initializes rx/ry attributes\n     * @private\n     */\n    _initRxRy: function () {\n      if (this.rx && !this.ry) {\n        this.ry = this.rx;\n      } else if (this.ry && !this.rx) {\n        this.rx = this.ry;\n      }\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function (ctx) {\n      // 1x1 case (used in spray brush) optimization was removed because\n      // with caching and higher zoom level this makes more damage than help\n      var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0,\n          ry = this.ry ? Math.min(this.ry, this.height / 2) : 0,\n          w = this.width,\n          h = this.height,\n          x = -this.width / 2,\n          y = -this.height / 2,\n          isRounded = rx !== 0 || ry !== 0,\n\n      /* \"magic number\" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */\n      k = 1 - 0.5522847498;\n      ctx.beginPath();\n      ctx.moveTo(x + rx, y);\n      ctx.lineTo(x + w - rx, y);\n      isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry);\n      ctx.lineTo(x + w, y + h - ry);\n      isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h);\n      ctx.lineTo(x + rx, y + h);\n      isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry);\n      ctx.lineTo(x, y + ry);\n      isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y);\n      ctx.closePath();\n\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderDashedStroke: function (ctx) {\n      var x = -this.width / 2,\n          y = -this.height / 2,\n          w = this.width,\n          h = this.height;\n      ctx.beginPath();\n      fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);\n      ctx.closePath();\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function (propertiesToInclude) {\n      return this.callSuper('toObject', ['rx', 'ry'].concat(propertiesToInclude));\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function () {\n      var x = -this.width / 2,\n          y = -this.height / 2;\n      return ['<rect ', 'COMMON_PARTS', 'x=\"', x, '\" y=\"', y, '\" rx=\"', this.rx, '\" ry=\"', this.ry, '\" width=\"', this.width, '\" height=\"', this.height, '\" />\\n'];\n    }\n    /* _TO_SVG_END_ */\n\n  });\n  /* _FROM_SVG_START_ */\n\n  /**\n   * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`)\n   * @static\n   * @memberOf fabric.Rect\n   * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement\n   */\n\n  fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' '));\n  /**\n   * Returns {@link fabric.Rect} instance from an SVG element\n   * @static\n   * @memberOf fabric.Rect\n   * @param {SVGElement} element Element to parse\n   * @param {Function} callback callback function invoked after parsing\n   * @param {Object} [options] Options object\n   */\n\n  fabric.Rect.fromElement = function (element, callback, options) {\n    if (!element) {\n      return callback(null);\n    }\n\n    options = options || {};\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);\n    parsedAttributes.left = parsedAttributes.left || 0;\n    parsedAttributes.top = parsedAttributes.top || 0;\n    parsedAttributes.height = parsedAttributes.height || 0;\n    parsedAttributes.width = parsedAttributes.width || 0;\n    var rect = new fabric.Rect(extend(options ? fabric.util.object.clone(options) : {}, parsedAttributes));\n    rect.visible = rect.visible && rect.width > 0 && rect.height > 0;\n    callback(rect);\n  };\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns {@link fabric.Rect} instance from an object representation\n   * @static\n   * @memberOf fabric.Rect\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] Callback to invoke when an fabric.Rect instance is created\n   */\n\n\n  fabric.Rect.fromObject = function (object, callback) {\n    return fabric.Object._fromObject('Rect', object, callback);\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      extend = fabric.util.object.extend,\n      min = fabric.util.array.min,\n      max = fabric.util.array.max,\n      toFixed = fabric.util.toFixed;\n\n  if (fabric.Polyline) {\n    fabric.warn('fabric.Polyline is already defined');\n    return;\n  }\n  /**\n   * Polyline class\n   * @class fabric.Polyline\n   * @extends fabric.Object\n   * @see {@link fabric.Polyline#initialize} for constructor definition\n   */\n\n\n  fabric.Polyline = fabric.util.createClass(fabric.Object,\n  /** @lends fabric.Polyline.prototype */\n  {\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'polyline',\n\n    /**\n     * Points array\n     * @type Array\n     * @default\n     */\n    points: null,\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('points'),\n\n    /**\n     * Constructor\n     * @param {Array} points Array of points (where each point is an object with x and y)\n     * @param {Object} [options] Options object\n     * @return {fabric.Polyline} thisArg\n     * @example\n     * var poly = new fabric.Polyline([\n     *     { x: 10, y: 10 },\n     *     { x: 50, y: 30 },\n     *     { x: 40, y: 70 },\n     *     { x: 60, y: 50 },\n     *     { x: 100, y: 150 },\n     *     { x: 40, y: 100 }\n     *   ], {\n     *   stroke: 'red',\n     *   left: 100,\n     *   top: 100\n     * });\n     */\n    initialize: function (points, options) {\n      options = options || {};\n      this.points = points || [];\n      this.callSuper('initialize', options);\n\n      this._setPositionDimensions(options);\n    },\n    _setPositionDimensions: function (options) {\n      var calcDim = this._calcDimensions(options),\n          correctLeftTop;\n\n      this.width = calcDim.width;\n      this.height = calcDim.height;\n\n      if (!options.fromSVG) {\n        correctLeftTop = this.translateToGivenOrigin({\n          x: calcDim.left - this.strokeWidth / 2,\n          y: calcDim.top - this.strokeWidth / 2\n        }, 'left', 'top', this.originX, this.originY);\n      }\n\n      if (typeof options.left === 'undefined') {\n        this.left = options.fromSVG ? calcDim.left : correctLeftTop.x;\n      }\n\n      if (typeof options.top === 'undefined') {\n        this.top = options.fromSVG ? calcDim.top : correctLeftTop.y;\n      }\n\n      this.pathOffset = {\n        x: calcDim.left + this.width / 2,\n        y: calcDim.top + this.height / 2\n      };\n    },\n\n    /**\n     * Calculate the polygon min and max point from points array,\n     * returning an object with left, top, widht, height to measure the\n     * polygon size\n     * @return {Object} object.left X coordinate of the polygon leftmost point\n     * @return {Object} object.top Y coordinate of the polygon topmost point\n     * @return {Object} object.width distance between X coordinates of the polygon leftmost and rightmost point\n     * @return {Object} object.height distance between Y coordinates of the polygon topmost and bottommost point\n     * @private\n     */\n    _calcDimensions: function () {\n      var points = this.points,\n          minX = min(points, 'x') || 0,\n          minY = min(points, 'y') || 0,\n          maxX = max(points, 'x') || 0,\n          maxY = max(points, 'y') || 0,\n          width = maxX - minX,\n          height = maxY - minY;\n      return {\n        left: minX,\n        top: minY,\n        width: width,\n        height: height\n      };\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function (propertiesToInclude) {\n      return extend(this.callSuper('toObject', propertiesToInclude), {\n        points: this.points.concat()\n      });\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function () {\n      var points = [],\n          diffX = this.pathOffset.x,\n          diffY = this.pathOffset.y,\n          NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n\n      for (var i = 0, len = this.points.length; i < len; i++) {\n        points.push(toFixed(this.points[i].x - diffX, NUM_FRACTION_DIGITS), ',', toFixed(this.points[i].y - diffY, NUM_FRACTION_DIGITS), ' ');\n      }\n\n      return ['<' + this.type + ' ', 'COMMON_PARTS', 'points=\"', points.join(''), '\" />\\n'];\n    },\n\n    /* _TO_SVG_END_ */\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    commonRender: function (ctx) {\n      var point,\n          len = this.points.length,\n          x = this.pathOffset.x,\n          y = this.pathOffset.y;\n\n      if (!len || isNaN(this.points[len - 1].y)) {\n        // do not draw if no points or odd points\n        // NaN comes from parseFloat of a empty string in parser\n        return false;\n      }\n\n      ctx.beginPath();\n      ctx.moveTo(this.points[0].x - x, this.points[0].y - y);\n\n      for (var i = 0; i < len; i++) {\n        point = this.points[i];\n        ctx.lineTo(point.x - x, point.y - y);\n      }\n\n      return true;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function (ctx) {\n      if (!this.commonRender(ctx)) {\n        return;\n      }\n\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderDashedStroke: function (ctx) {\n      var p1, p2;\n      ctx.beginPath();\n\n      for (var i = 0, len = this.points.length; i < len; i++) {\n        p1 = this.points[i];\n        p2 = this.points[i + 1] || p1;\n        fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray);\n      }\n    },\n\n    /**\n     * Returns complexity of an instance\n     * @return {Number} complexity of this instance\n     */\n    complexity: function () {\n      return this.get('points').length;\n    }\n  });\n  /* _FROM_SVG_START_ */\n\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Polyline.fromElement})\n   * @static\n   * @memberOf fabric.Polyline\n   * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement\n   */\n\n  fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat();\n  /**\n   * Returns fabric.Polyline instance from an SVG element\n   * @static\n   * @memberOf fabric.Polyline\n   * @param {SVGElement} element Element to parser\n   * @param {Function} callback callback function invoked after parsing\n   * @param {Object} [options] Options object\n   */\n\n  fabric.Polyline.fromElementGenerator = function (_class) {\n    return function (element, callback, options) {\n      if (!element) {\n        return callback(null);\n      }\n\n      options || (options = {});\n      var points = fabric.parsePointsAttribute(element.getAttribute('points')),\n          parsedAttributes = fabric.parseAttributes(element, fabric[_class].ATTRIBUTE_NAMES);\n      parsedAttributes.fromSVG = true;\n      callback(new fabric[_class](points, extend(parsedAttributes, options)));\n    };\n  };\n\n  fabric.Polyline.fromElement = fabric.Polyline.fromElementGenerator('Polyline');\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns fabric.Polyline instance from an object representation\n   * @static\n   * @memberOf fabric.Polyline\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\n   */\n\n  fabric.Polyline.fromObject = function (object, callback) {\n    return fabric.Object._fromObject('Polyline', object, callback, 'points');\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {});\n\n  if (fabric.Polygon) {\n    fabric.warn('fabric.Polygon is already defined');\n    return;\n  }\n  /**\n   * Polygon class\n   * @class fabric.Polygon\n   * @extends fabric.Polyline\n   * @see {@link fabric.Polygon#initialize} for constructor definition\n   */\n\n\n  fabric.Polygon = fabric.util.createClass(fabric.Polyline,\n  /** @lends fabric.Polygon.prototype */\n  {\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'polygon',\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function (ctx) {\n      if (!this.commonRender(ctx)) {\n        return;\n      }\n\n      ctx.closePath();\n\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderDashedStroke: function (ctx) {\n      this.callSuper('_renderDashedStroke', ctx);\n      ctx.closePath();\n    }\n  });\n  /* _FROM_SVG_START_ */\n\n  /**\n   * List of attribute names to account for when parsing SVG element (used by `fabric.Polygon.fromElement`)\n   * @static\n   * @memberOf fabric.Polygon\n   * @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement\n   */\n\n  fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat();\n  /**\n   * Returns {@link fabric.Polygon} instance from an SVG element\n   * @static\n   * @memberOf fabric.Polygon\n   * @param {SVGElement} element Element to parse\n   * @param {Function} callback callback function invoked after parsing\n   * @param {Object} [options] Options object\n   */\n\n  fabric.Polygon.fromElement = fabric.Polyline.fromElementGenerator('Polygon');\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns fabric.Polygon instance from an object representation\n   * @static\n   * @memberOf fabric.Polygon\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\n   */\n\n  fabric.Polygon.fromObject = function (object, callback) {\n    return fabric.Object._fromObject('Polygon', object, callback, 'points');\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      min = fabric.util.array.min,\n      max = fabric.util.array.max,\n      extend = fabric.util.object.extend,\n      _toString = Object.prototype.toString,\n      toFixed = fabric.util.toFixed;\n\n  if (fabric.Path) {\n    fabric.warn('fabric.Path is already defined');\n    return;\n  }\n  /**\n   * Path class\n   * @class fabric.Path\n   * @extends fabric.Object\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#path_and_pathgroup}\n   * @see {@link fabric.Path#initialize} for constructor definition\n   */\n\n\n  fabric.Path = fabric.util.createClass(fabric.Object,\n  /** @lends fabric.Path.prototype */\n  {\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'path',\n\n    /**\n     * Array of path points\n     * @type Array\n     * @default\n     */\n    path: null,\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('path', 'fillRule'),\n    stateProperties: fabric.Object.prototype.stateProperties.concat('path'),\n\n    /**\n     * Constructor\n     * @param {Array|String} path Path data (sequence of coordinates and corresponding \"command\" tokens)\n     * @param {Object} [options] Options object\n     * @return {fabric.Path} thisArg\n     */\n    initialize: function (path, options) {\n      options = options || {};\n      this.callSuper('initialize', options);\n\n      if (!path) {\n        path = [];\n      }\n\n      var fromArray = _toString.call(path) === '[object Array]';\n      this.path = fromArray ? fabric.util.makePathSimpler(path) : fabric.util.makePathSimpler(fabric.util.parsePath(path));\n\n      if (!this.path) {\n        return;\n      }\n\n      fabric.Polyline.prototype._setPositionDimensions.call(this, options);\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx context to render path on\n     */\n    _renderPathCommands: function (ctx) {\n      var current,\n          // current instruction\n      subpathStartX = 0,\n          subpathStartY = 0,\n          x = 0,\n          // current x\n      y = 0,\n          // current y\n      controlX = 0,\n          // current control point x\n      controlY = 0,\n          // current control point y\n      l = -this.pathOffset.x,\n          t = -this.pathOffset.y;\n      ctx.beginPath();\n\n      for (var i = 0, len = this.path.length; i < len; ++i) {\n        current = this.path[i];\n\n        switch (current[0]) {\n          // first letter\n          case 'L':\n            // lineto, absolute\n            x = current[1];\n            y = current[2];\n            ctx.lineTo(x + l, y + t);\n            break;\n\n          case 'M':\n            // moveTo, absolute\n            x = current[1];\n            y = current[2];\n            subpathStartX = x;\n            subpathStartY = y;\n            ctx.moveTo(x + l, y + t);\n            break;\n\n          case 'C':\n            // bezierCurveTo, absolute\n            x = current[5];\n            y = current[6];\n            controlX = current[3];\n            controlY = current[4];\n            ctx.bezierCurveTo(current[1] + l, current[2] + t, controlX + l, controlY + t, x + l, y + t);\n            break;\n\n          case 'Q':\n            // quadraticCurveTo, absolute\n            ctx.quadraticCurveTo(current[1] + l, current[2] + t, current[3] + l, current[4] + t);\n            x = current[3];\n            y = current[4];\n            controlX = current[1];\n            controlY = current[2];\n            break;\n\n          case 'z':\n          case 'Z':\n            x = subpathStartX;\n            y = subpathStartY;\n            ctx.closePath();\n            break;\n        }\n      }\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx context to render path on\n     */\n    _render: function (ctx) {\n      this._renderPathCommands(ctx);\n\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * Returns string representation of an instance\n     * @return {String} string representation of an instance\n     */\n    toString: function () {\n      return '#<fabric.Path (' + this.complexity() + '): { \"top\": ' + this.top + ', \"left\": ' + this.left + ' }>';\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function (propertiesToInclude) {\n      return extend(this.callSuper('toObject', propertiesToInclude), {\n        path: this.path.map(function (item) {\n          return item.slice();\n        })\n      });\n    },\n\n    /**\n     * Returns dataless object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toDatalessObject: function (propertiesToInclude) {\n      var o = this.toObject(['sourcePath'].concat(propertiesToInclude));\n\n      if (o.sourcePath) {\n        delete o.path;\n      }\n\n      return o;\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function () {\n      var path = this.path.map(function (path) {\n        return path.join(' ');\n      }).join(' ');\n      return ['<path ', 'COMMON_PARTS', 'd=\"', path, '\" stroke-linecap=\"round\" ', '/>\\n'];\n    },\n    _getOffsetTransform: function () {\n      var digits = fabric.Object.NUM_FRACTION_DIGITS;\n      return ' translate(' + toFixed(-this.pathOffset.x, digits) + ', ' + toFixed(-this.pathOffset.y, digits) + ')';\n    },\n\n    /**\n     * Returns svg clipPath representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    toClipPathSVG: function (reviver) {\n      var additionalTransform = this._getOffsetTransform();\n\n      return '\\t' + this._createBaseClipPathSVGMarkup(this._toSVG(), {\n        reviver: reviver,\n        additionalTransform: additionalTransform\n      });\n    },\n\n    /**\n     * Returns svg representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    toSVG: function (reviver) {\n      var additionalTransform = this._getOffsetTransform();\n\n      return this._createBaseSVGMarkup(this._toSVG(), {\n        reviver: reviver,\n        additionalTransform: additionalTransform\n      });\n    },\n\n    /* _TO_SVG_END_ */\n\n    /**\n     * Returns number representation of an instance complexity\n     * @return {Number} complexity of this instance\n     */\n    complexity: function () {\n      return this.path.length;\n    },\n\n    /**\n     * @private\n     */\n    _calcDimensions: function () {\n      var aX = [],\n          aY = [],\n          current,\n          // current instruction\n      subpathStartX = 0,\n          subpathStartY = 0,\n          x = 0,\n          // current x\n      y = 0,\n          // current y\n      bounds;\n\n      for (var i = 0, len = this.path.length; i < len; ++i) {\n        current = this.path[i];\n\n        switch (current[0]) {\n          // first letter\n          case 'L':\n            // lineto, absolute\n            x = current[1];\n            y = current[2];\n            bounds = [];\n            break;\n\n          case 'M':\n            // moveTo, absolute\n            x = current[1];\n            y = current[2];\n            subpathStartX = x;\n            subpathStartY = y;\n            bounds = [];\n            break;\n\n          case 'C':\n            // bezierCurveTo, absolute\n            bounds = fabric.util.getBoundsOfCurve(x, y, current[1], current[2], current[3], current[4], current[5], current[6]);\n            x = current[5];\n            y = current[6];\n            break;\n\n          case 'Q':\n            // quadraticCurveTo, absolute\n            bounds = fabric.util.getBoundsOfCurve(x, y, current[1], current[2], current[1], current[2], current[3], current[4]);\n            x = current[3];\n            y = current[4];\n            break;\n\n          case 'z':\n          case 'Z':\n            x = subpathStartX;\n            y = subpathStartY;\n            break;\n        }\n\n        bounds.forEach(function (point) {\n          aX.push(point.x);\n          aY.push(point.y);\n        });\n        aX.push(x);\n        aY.push(y);\n      }\n\n      var minX = min(aX) || 0,\n          minY = min(aY) || 0,\n          maxX = max(aX) || 0,\n          maxY = max(aY) || 0,\n          deltaX = maxX - minX,\n          deltaY = maxY - minY;\n      return {\n        left: minX,\n        top: minY,\n        width: deltaX,\n        height: deltaY\n      };\n    }\n  });\n  /**\n   * Creates an instance of fabric.Path from an object\n   * @static\n   * @memberOf fabric.Path\n   * @param {Object} object\n   * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\n   */\n\n  fabric.Path.fromObject = function (object, callback) {\n    if (typeof object.sourcePath === 'string') {\n      var pathUrl = object.sourcePath;\n      fabric.loadSVGFromURL(pathUrl, function (elements) {\n        var path = elements[0];\n        path.setOptions(object);\n        callback && callback(path);\n      });\n    } else {\n      fabric.Object._fromObject('Path', object, callback, 'path');\n    }\n  };\n  /* _FROM_SVG_START_ */\n\n  /**\n   * List of attribute names to account for when parsing SVG element (used by `fabric.Path.fromElement`)\n   * @static\n   * @memberOf fabric.Path\n   * @see http://www.w3.org/TR/SVG/paths.html#PathElement\n   */\n\n\n  fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(['d']);\n  /**\n   * Creates an instance of fabric.Path from an SVG <path> element\n   * @static\n   * @memberOf fabric.Path\n   * @param {SVGElement} element to parse\n   * @param {Function} callback Callback to invoke when an fabric.Path instance is created\n   * @param {Object} [options] Options object\n   * @param {Function} [callback] Options callback invoked after parsing is finished\n   */\n\n  fabric.Path.fromElement = function (element, callback, options) {\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES);\n    parsedAttributes.fromSVG = true;\n    callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options)));\n  };\n  /* _FROM_SVG_END_ */\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      min = fabric.util.array.min,\n      max = fabric.util.array.max;\n\n  if (fabric.Group) {\n    return;\n  }\n  /**\n   * Group class\n   * @class fabric.Group\n   * @extends fabric.Object\n   * @mixes fabric.Collection\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#groups}\n   * @see {@link fabric.Group#initialize} for constructor definition\n   */\n\n\n  fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection,\n  /** @lends fabric.Group.prototype */\n  {\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'group',\n\n    /**\n     * Width of stroke\n     * @type Number\n     * @default\n     */\n    strokeWidth: 0,\n\n    /**\n     * Indicates if click, mouseover, mouseout events & hoverCursor should also check for subtargets\n     * @type Boolean\n     * @default\n     */\n    subTargetCheck: false,\n\n    /**\n     * Groups are container, do not render anything on theyr own, ence no cache properties\n     * @type Array\n     * @default\n     */\n    cacheProperties: [],\n\n    /**\n     * setOnGroup is a method used for TextBox that is no more used since 2.0.0 The behavior is still\n     * available setting this boolean to true.\n     * @type Boolean\n     * @since 2.0.0\n     * @default\n     */\n    useSetOnGroup: false,\n\n    /**\n     * Constructor\n     * @param {Object} objects Group objects\n     * @param {Object} [options] Options object\n     * @param {Boolean} [isAlreadyGrouped] if true, objects have been grouped already.\n     * @return {Object} thisArg\n     */\n    initialize: function (objects, options, isAlreadyGrouped) {\n      options = options || {};\n      this._objects = []; // if objects enclosed in a group have been grouped already,\n      // we cannot change properties of objects.\n      // Thus we need to set options to group without objects,\n\n      isAlreadyGrouped && this.callSuper('initialize', options);\n      this._objects = objects || [];\n\n      for (var i = this._objects.length; i--;) {\n        this._objects[i].group = this;\n      }\n\n      if (!isAlreadyGrouped) {\n        var center = options && options.centerPoint; // we want to set origins before calculating the bounding box.\n        // so that the topleft can be set with that in mind.\n        // if specific top and left are passed, are overwritten later\n        // with the callSuper('initialize', options)\n\n        if (options.originX !== undefined) {\n          this.originX = options.originX;\n        }\n\n        if (options.originY !== undefined) {\n          this.originY = options.originY;\n        } // if coming from svg i do not want to calc bounds.\n        // i assume width and height are passed along options\n\n\n        center || this._calcBounds();\n\n        this._updateObjectsCoords(center);\n\n        delete options.centerPoint;\n        this.callSuper('initialize', options);\n      } else {\n        this._updateObjectsACoords();\n      }\n\n      this.setCoords();\n    },\n\n    /**\n     * @private\n     */\n    _updateObjectsACoords: function () {\n      var skipControls = true;\n\n      for (var i = this._objects.length; i--;) {\n        this._objects[i].setCoords(skipControls);\n      }\n    },\n\n    /**\n     * @private\n     * @param {Boolean} [skipCoordsChange] if true, coordinates of objects enclosed in a group do not change\n     */\n    _updateObjectsCoords: function (center) {\n      var center = center || this.getCenterPoint();\n\n      for (var i = this._objects.length; i--;) {\n        this._updateObjectCoords(this._objects[i], center);\n      }\n    },\n\n    /**\n     * @private\n     * @param {Object} object\n     * @param {fabric.Point} center, current center of group.\n     */\n    _updateObjectCoords: function (object, center) {\n      var objectLeft = object.left,\n          objectTop = object.top,\n          skipControls = true;\n      object.set({\n        left: objectLeft - center.x,\n        top: objectTop - center.y\n      });\n      object.group = this;\n      object.setCoords(skipControls);\n    },\n\n    /**\n     * Returns string represenation of a group\n     * @return {String}\n     */\n    toString: function () {\n      return '#<fabric.Group: (' + this.complexity() + ')>';\n    },\n\n    /**\n     * Adds an object to a group; Then recalculates group's dimension, position.\n     * @param {Object} object\n     * @return {fabric.Group} thisArg\n     * @chainable\n     */\n    addWithUpdate: function (object) {\n      this._restoreObjectsState();\n\n      fabric.util.resetObjectTransform(this);\n\n      if (object) {\n        this._objects.push(object);\n\n        object.group = this;\n\n        object._set('canvas', this.canvas);\n      }\n\n      this._calcBounds();\n\n      this._updateObjectsCoords();\n\n      this.setCoords();\n      this.dirty = true;\n      return this;\n    },\n\n    /**\n     * Removes an object from a group; Then recalculates group's dimension, position.\n     * @param {Object} object\n     * @return {fabric.Group} thisArg\n     * @chainable\n     */\n    removeWithUpdate: function (object) {\n      this._restoreObjectsState();\n\n      fabric.util.resetObjectTransform(this);\n      this.remove(object);\n\n      this._calcBounds();\n\n      this._updateObjectsCoords();\n\n      this.setCoords();\n      this.dirty = true;\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _onObjectAdded: function (object) {\n      this.dirty = true;\n      object.group = this;\n\n      object._set('canvas', this.canvas);\n    },\n\n    /**\n     * @private\n     */\n    _onObjectRemoved: function (object) {\n      this.dirty = true;\n      delete object.group;\n    },\n\n    /**\n     * @private\n     */\n    _set: function (key, value) {\n      var i = this._objects.length;\n\n      if (this.useSetOnGroup) {\n        while (i--) {\n          this._objects[i].setOnGroup(key, value);\n        }\n      }\n\n      if (key === 'canvas') {\n        while (i--) {\n          this._objects[i]._set(key, value);\n        }\n      }\n\n      fabric.Object.prototype._set.call(this, key, value);\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function (propertiesToInclude) {\n      var _includeDefaultValues = this.includeDefaultValues;\n\n      var objsToObject = this._objects.map(function (obj) {\n        var originalDefaults = obj.includeDefaultValues;\n        obj.includeDefaultValues = _includeDefaultValues;\n\n        var _obj = obj.toObject(propertiesToInclude);\n\n        obj.includeDefaultValues = originalDefaults;\n        return _obj;\n      });\n\n      var obj = fabric.Object.prototype.toObject.call(this, propertiesToInclude);\n      obj.objects = objsToObject;\n      return obj;\n    },\n\n    /**\n     * Returns object representation of an instance, in dataless mode.\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toDatalessObject: function (propertiesToInclude) {\n      var objsToObject,\n          sourcePath = this.sourcePath;\n\n      if (sourcePath) {\n        objsToObject = sourcePath;\n      } else {\n        var _includeDefaultValues = this.includeDefaultValues;\n        objsToObject = this._objects.map(function (obj) {\n          var originalDefaults = obj.includeDefaultValues;\n          obj.includeDefaultValues = _includeDefaultValues;\n\n          var _obj = obj.toDatalessObject(propertiesToInclude);\n\n          obj.includeDefaultValues = originalDefaults;\n          return _obj;\n        });\n      }\n\n      var obj = fabric.Object.prototype.toDatalessObject.call(this, propertiesToInclude);\n      obj.objects = objsToObject;\n      return obj;\n    },\n\n    /**\n     * Renders instance on a given context\n     * @param {CanvasRenderingContext2D} ctx context to render instance on\n     */\n    render: function (ctx) {\n      this._transformDone = true;\n      this.callSuper('render', ctx);\n      this._transformDone = false;\n    },\n\n    /**\n     * Decide if the object should cache or not. Create its own cache level\n     * needsItsOwnCache should be used when the object drawing method requires\n     * a cache step. None of the fabric classes requires it.\n     * Generally you do not cache objects in groups because the group is already cached.\n     * @return {Boolean}\n     */\n    shouldCache: function () {\n      var ownCache = fabric.Object.prototype.shouldCache.call(this);\n\n      if (ownCache) {\n        for (var i = 0, len = this._objects.length; i < len; i++) {\n          if (this._objects[i].willDrawShadow()) {\n            this.ownCaching = false;\n            return false;\n          }\n        }\n      }\n\n      return ownCache;\n    },\n\n    /**\n     * Check if this object or a child object will cast a shadow\n     * @return {Boolean}\n     */\n    willDrawShadow: function () {\n      if (fabric.Object.prototype.willDrawShadow.call(this)) {\n        return true;\n      }\n\n      for (var i = 0, len = this._objects.length; i < len; i++) {\n        if (this._objects[i].willDrawShadow()) {\n          return true;\n        }\n      }\n\n      return false;\n    },\n\n    /**\n     * Check if this group or its parent group are caching, recursively up\n     * @return {Boolean}\n     */\n    isOnACache: function () {\n      return this.ownCaching || this.group && this.group.isOnACache();\n    },\n\n    /**\n     * Execute the drawing operation for an object on a specified context\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    drawObject: function (ctx) {\n      for (var i = 0, len = this._objects.length; i < len; i++) {\n        this._objects[i].render(ctx);\n      }\n\n      this._drawClipPath(ctx);\n    },\n\n    /**\n     * Check if cache is dirty\n     */\n    isCacheDirty: function (skipCanvas) {\n      if (this.callSuper('isCacheDirty', skipCanvas)) {\n        return true;\n      }\n\n      if (!this.statefullCache) {\n        return false;\n      }\n\n      for (var i = 0, len = this._objects.length; i < len; i++) {\n        if (this._objects[i].isCacheDirty(true)) {\n          if (this._cacheCanvas) {\n            // if this group has not a cache canvas there is nothing to clean\n            var x = this.cacheWidth / this.zoomX,\n                y = this.cacheHeight / this.zoomY;\n\n            this._cacheContext.clearRect(-x / 2, -y / 2, x, y);\n          }\n\n          return true;\n        }\n      }\n\n      return false;\n    },\n\n    /**\n     * Retores original state of each of group objects (original state is that which was before group was created).\n     * @private\n     * @return {fabric.Group} thisArg\n     * @chainable\n     */\n    _restoreObjectsState: function () {\n      this._objects.forEach(this._restoreObjectState, this);\n\n      return this;\n    },\n\n    /**\n     * Realises the transform from this group onto the supplied object\n     * i.e. it tells you what would happen if the supplied object was in\n     * the group, and then the group was destroyed. It mutates the supplied\n     * object.\n     * @param {fabric.Object} object\n     * @return {fabric.Object} transformedObject\n     */\n    realizeTransform: function (object) {\n      var matrix = object.calcTransformMatrix(),\n          options = fabric.util.qrDecompose(matrix),\n          center = new fabric.Point(options.translateX, options.translateY);\n      object.flipX = false;\n      object.flipY = false;\n      object.set('scaleX', options.scaleX);\n      object.set('scaleY', options.scaleY);\n      object.skewX = options.skewX;\n      object.skewY = options.skewY;\n      object.angle = options.angle;\n      object.setPositionByOrigin(center, 'center', 'center');\n      return object;\n    },\n\n    /**\n     * Restores original state of a specified object in group\n     * @private\n     * @param {fabric.Object} object\n     * @return {fabric.Group} thisArg\n     */\n    _restoreObjectState: function (object) {\n      this.realizeTransform(object);\n      delete object.group;\n      object.setCoords();\n      return this;\n    },\n\n    /**\n     * Destroys a group (restoring state of its objects)\n     * @return {fabric.Group} thisArg\n     * @chainable\n     */\n    destroy: function () {\n      // when group is destroyed objects needs to get a repaint to be eventually\n      // displayed on canvas.\n      this._objects.forEach(function (object) {\n        object.set('dirty', true);\n      });\n\n      return this._restoreObjectsState();\n    },\n\n    /**\n     * make a group an active selection, remove the group from canvas\n     * the group has to be on canvas for this to work.\n     * @return {fabric.ActiveSelection} thisArg\n     * @chainable\n     */\n    toActiveSelection: function () {\n      if (!this.canvas) {\n        return;\n      }\n\n      var objects = this._objects,\n          canvas = this.canvas;\n      this._objects = [];\n      var options = this.toObject();\n      delete options.objects;\n      var activeSelection = new fabric.ActiveSelection([]);\n      activeSelection.set(options);\n      activeSelection.type = 'activeSelection';\n      canvas.remove(this);\n      objects.forEach(function (object) {\n        object.group = activeSelection;\n        object.dirty = true;\n        canvas.add(object);\n      });\n      activeSelection.canvas = canvas;\n      activeSelection._objects = objects;\n      canvas._activeObject = activeSelection;\n      activeSelection.setCoords();\n      return activeSelection;\n    },\n\n    /**\n     * Destroys a group (restoring state of its objects)\n     * @return {fabric.Group} thisArg\n     * @chainable\n     */\n    ungroupOnCanvas: function () {\n      return this._restoreObjectsState();\n    },\n\n    /**\n     * Sets coordinates of all objects inside group\n     * @return {fabric.Group} thisArg\n     * @chainable\n     */\n    setObjectsCoords: function () {\n      var skipControls = true;\n      this.forEachObject(function (object) {\n        object.setCoords(skipControls);\n      });\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _calcBounds: function (onlyWidthHeight) {\n      var aX = [],\n          aY = [],\n          o,\n          prop,\n          props = ['tr', 'br', 'bl', 'tl'],\n          i = 0,\n          iLen = this._objects.length,\n          j,\n          jLen = props.length;\n\n      for (; i < iLen; ++i) {\n        o = this._objects[i];\n        o.aCoords = o.calcACoords();\n\n        for (j = 0; j < jLen; j++) {\n          prop = props[j];\n          aX.push(o.aCoords[prop].x);\n          aY.push(o.aCoords[prop].y);\n        }\n      }\n\n      this._getBounds(aX, aY, onlyWidthHeight);\n    },\n\n    /**\n     * @private\n     */\n    _getBounds: function (aX, aY, onlyWidthHeight) {\n      var minXY = new fabric.Point(min(aX), min(aY)),\n          maxXY = new fabric.Point(max(aX), max(aY)),\n          top = minXY.y || 0,\n          left = minXY.x || 0,\n          width = maxXY.x - minXY.x || 0,\n          height = maxXY.y - minXY.y || 0;\n      this.width = width;\n      this.height = height;\n\n      if (!onlyWidthHeight) {\n        // the bounding box always finds the topleft most corner.\n        // whatever is the group origin, we set up here the left/top position.\n        this.setPositionByOrigin({\n          x: left,\n          y: top\n        }, 'left', 'top');\n      }\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * Returns svg representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    _toSVG: function (reviver) {\n      var svgString = ['<g ', 'COMMON_PARTS', ' >\\n'];\n\n      for (var i = 0, len = this._objects.length; i < len; i++) {\n        svgString.push('\\t\\t', this._objects[i].toSVG(reviver));\n      }\n\n      svgString.push('</g>\\n');\n      return svgString;\n    },\n\n    /**\n     * Returns styles-string for svg-export, specific version for group\n     * @return {String}\n     */\n    getSvgStyles: function () {\n      var opacity = typeof this.opacity !== 'undefined' && this.opacity !== 1 ? 'opacity: ' + this.opacity + ';' : '',\n          visibility = this.visible ? '' : ' visibility: hidden;';\n      return [opacity, this.getSvgFilter(), visibility].join('');\n    },\n\n    /**\n     * Returns svg clipPath representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    toClipPathSVG: function (reviver) {\n      var svgString = [];\n\n      for (var i = 0, len = this._objects.length; i < len; i++) {\n        svgString.push('\\t', this._objects[i].toClipPathSVG(reviver));\n      }\n\n      return this._createBaseClipPathSVGMarkup(svgString, {\n        reviver: reviver\n      });\n    }\n    /* _TO_SVG_END_ */\n\n  });\n  /**\n   * Returns {@link fabric.Group} instance from an object representation\n   * @static\n   * @memberOf fabric.Group\n   * @param {Object} object Object to create a group from\n   * @param {Function} [callback] Callback to invoke when an group instance is created\n   */\n\n  fabric.Group.fromObject = function (object, callback) {\n    var objects = object.objects,\n        options = fabric.util.object.clone(object, true);\n    delete options.objects;\n\n    if (typeof objects === 'string') {\n      // it has to be an url or something went wrong.\n      fabric.loadSVGFromURL(objects, function (elements) {\n        var group = fabric.util.groupSVGElements(elements, object, objects);\n        group.set(options);\n        callback && callback(group);\n      });\n      return;\n    }\n\n    fabric.util.enlivenObjects(objects, function (enlivenedObjects) {\n      fabric.util.enlivenObjects([object.clipPath], function (enlivedClipPath) {\n        var options = fabric.util.object.clone(object, true);\n        options.clipPath = enlivedClipPath[0];\n        delete options.objects;\n        callback && callback(new fabric.Group(enlivenedObjects, options, true));\n      });\n    });\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {});\n\n  if (fabric.ActiveSelection) {\n    return;\n  }\n  /**\n   * Group class\n   * @class fabric.ActiveSelection\n   * @extends fabric.Group\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#groups}\n   * @see {@link fabric.ActiveSelection#initialize} for constructor definition\n   */\n\n\n  fabric.ActiveSelection = fabric.util.createClass(fabric.Group,\n  /** @lends fabric.ActiveSelection.prototype */\n  {\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'activeSelection',\n\n    /**\n     * Constructor\n     * @param {Object} objects ActiveSelection objects\n     * @param {Object} [options] Options object\n     * @return {Object} thisArg\n     */\n    initialize: function (objects, options) {\n      options = options || {};\n      this._objects = objects || [];\n\n      for (var i = this._objects.length; i--;) {\n        this._objects[i].group = this;\n      }\n\n      if (options.originX) {\n        this.originX = options.originX;\n      }\n\n      if (options.originY) {\n        this.originY = options.originY;\n      }\n\n      this._calcBounds();\n\n      this._updateObjectsCoords();\n\n      fabric.Object.prototype.initialize.call(this, options);\n      this.setCoords();\n    },\n\n    /**\n     * Change te activeSelection to a normal group,\n     * High level function that automatically adds it to canvas as\n     * active object. no events fired.\n     * @since 2.0.0\n     * @return {fabric.Group}\n     */\n    toGroup: function () {\n      var objects = this._objects.concat();\n\n      this._objects = [];\n      var options = fabric.Object.prototype.toObject.call(this);\n      var newGroup = new fabric.Group([]);\n      delete options.type;\n      newGroup.set(options);\n      objects.forEach(function (object) {\n        object.canvas.remove(object);\n        object.group = newGroup;\n      });\n      newGroup._objects = objects;\n\n      if (!this.canvas) {\n        return newGroup;\n      }\n\n      var canvas = this.canvas;\n      canvas.add(newGroup);\n      canvas._activeObject = newGroup;\n      newGroup.setCoords();\n      return newGroup;\n    },\n\n    /**\n     * If returns true, deselection is cancelled.\n     * @since 2.0.0\n     * @return {Boolean} [cancel]\n     */\n    onDeselect: function () {\n      this.destroy();\n      return false;\n    },\n\n    /**\n     * Returns string representation of a group\n     * @return {String}\n     */\n    toString: function () {\n      return '#<fabric.ActiveSelection: (' + this.complexity() + ')>';\n    },\n\n    /**\n     * Decide if the object should cache or not. Create its own cache level\n     * objectCaching is a global flag, wins over everything\n     * needsItsOwnCache should be used when the object drawing method requires\n     * a cache step. None of the fabric classes requires it.\n     * Generally you do not cache objects in groups because the group outside is cached.\n     * @return {Boolean}\n     */\n    shouldCache: function () {\n      return false;\n    },\n\n    /**\n     * Check if this group or its parent group are caching, recursively up\n     * @return {Boolean}\n     */\n    isOnACache: function () {\n      return false;\n    },\n\n    /**\n     * Renders controls and borders for the object\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Object} [styleOverride] properties to override the object style\n     * @param {Object} [childrenOverride] properties to override the children overrides\n     */\n    _renderControls: function (ctx, styleOverride, childrenOverride) {\n      ctx.save();\n      ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n      this.callSuper('_renderControls', ctx, styleOverride);\n      childrenOverride = childrenOverride || {};\n\n      if (typeof childrenOverride.hasControls === 'undefined') {\n        childrenOverride.hasControls = false;\n      }\n\n      childrenOverride.forActiveSelection = true;\n\n      for (var i = 0, len = this._objects.length; i < len; i++) {\n        this._objects[i]._renderControls(ctx, childrenOverride);\n      }\n\n      ctx.restore();\n    }\n  });\n  /**\n   * Returns {@link fabric.ActiveSelection} instance from an object representation\n   * @static\n   * @memberOf fabric.ActiveSelection\n   * @param {Object} object Object to create a group from\n   * @param {Function} [callback] Callback to invoke when an ActiveSelection instance is created\n   */\n\n  fabric.ActiveSelection.fromObject = function (object, callback) {\n    fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) {\n      delete object.objects;\n      callback && callback(new fabric.ActiveSelection(enlivenedObjects, object, true));\n    });\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var extend = fabric.util.object.extend;\n\n  if (!global.fabric) {\n    global.fabric = {};\n  }\n\n  if (global.fabric.Image) {\n    fabric.warn('fabric.Image is already defined.');\n    return;\n  }\n  /**\n   * Image class\n   * @class fabric.Image\n   * @extends fabric.Object\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#images}\n   * @see {@link fabric.Image#initialize} for constructor definition\n   */\n\n\n  fabric.Image = fabric.util.createClass(fabric.Object,\n  /** @lends fabric.Image.prototype */\n  {\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'image',\n\n    /**\n     * Width of a stroke.\n     * For image quality a stroke multiple of 2 gives better results.\n     * @type Number\n     * @default\n     */\n    strokeWidth: 0,\n\n    /**\n     * When calling {@link fabric.Image.getSrc}, return value from element src with `element.getAttribute('src')`.\n     * This allows for relative urls as image src.\n     * @since 2.7.0\n     * @type Boolean\n     * @default\n     */\n    srcFromAttribute: false,\n\n    /**\n     * private\n     * contains last value of scaleX to detect\n     * if the Image got resized after the last Render\n     * @type Number\n     */\n    _lastScaleX: 1,\n\n    /**\n     * private\n     * contains last value of scaleY to detect\n     * if the Image got resized after the last Render\n     * @type Number\n     */\n    _lastScaleY: 1,\n\n    /**\n     * private\n     * contains last value of scaling applied by the apply filter chain\n     * @type Number\n     */\n    _filterScalingX: 1,\n\n    /**\n     * private\n     * contains last value of scaling applied by the apply filter chain\n     * @type Number\n     */\n    _filterScalingY: 1,\n\n    /**\n     * minimum scale factor under which any resizeFilter is triggered to resize the image\n     * 0 will disable the automatic resize. 1 will trigger automatically always.\n     * number bigger than 1 are not implemented yet.\n     * @type Number\n     */\n    minimumScaleTrigger: 0.5,\n\n    /**\n     * List of properties to consider when checking if\n     * state of an object is changed ({@link fabric.Object#hasStateChanged})\n     * as well as for history (undo/redo) purposes\n     * @type Array\n     */\n    stateProperties: fabric.Object.prototype.stateProperties.concat('cropX', 'cropY'),\n\n    /**\n     * key used to retrieve the texture representing this image\n     * @since 2.0.0\n     * @type String\n     * @default\n     */\n    cacheKey: '',\n\n    /**\n     * Image crop in pixels from original image size.\n     * @since 2.0.0\n     * @type Number\n     * @default\n     */\n    cropX: 0,\n\n    /**\n     * Image crop in pixels from original image size.\n     * @since 2.0.0\n     * @type Number\n     * @default\n     */\n    cropY: 0,\n\n    /**\n     * Indicates whether this canvas will use image smoothing when painting this image.\n     * Also influence if the cacheCanvas for this image uses imageSmoothing\n     * @since 4.0.0-beta.11\n     * @type Boolean\n     * @default\n     */\n    imageSmoothing: true,\n\n    /**\n     * Constructor\n     * @param {HTMLImageElement | String} element Image element\n     * @param {Object} [options] Options object\n     * @param {function} [callback] callback function to call after eventual filters applied.\n     * @return {fabric.Image} thisArg\n     */\n    initialize: function (element, options) {\n      options || (options = {});\n      this.filters = [];\n      this.cacheKey = 'texture' + fabric.Object.__uid++;\n      this.callSuper('initialize', options);\n\n      this._initElement(element, options);\n    },\n\n    /**\n     * Returns image element which this instance if based on\n     * @return {HTMLImageElement} Image element\n     */\n    getElement: function () {\n      return this._element || {};\n    },\n\n    /**\n     * Sets image element for this instance to a specified one.\n     * If filters defined they are applied to new image.\n     * You might need to call `canvas.renderAll` and `object.setCoords` after replacing, to render new image and update controls area.\n     * @param {HTMLImageElement} element\n     * @param {Object} [options] Options object\n     * @return {fabric.Image} thisArg\n     * @chainable\n     */\n    setElement: function (element, options) {\n      this.removeTexture(this.cacheKey);\n      this.removeTexture(this.cacheKey + '_filtered');\n      this._element = element;\n      this._originalElement = element;\n\n      this._initConfig(options);\n\n      if (this.filters.length !== 0) {\n        this.applyFilters();\n      } // resizeFilters work on the already filtered copy.\n      // we need to apply resizeFilters AFTER normal filters.\n      // applyResizeFilters is run more often than normal fiters\n      // and is triggered by user interactions rather than dev code\n\n\n      if (this.resizeFilter) {\n        this.applyResizeFilters();\n      }\n\n      return this;\n    },\n\n    /**\n     * Delete a single texture if in webgl mode\n     */\n    removeTexture: function (key) {\n      var backend = fabric.filterBackend;\n\n      if (backend && backend.evictCachesForKey) {\n        backend.evictCachesForKey(key);\n      }\n    },\n\n    /**\n     * Delete textures, reference to elements and eventually JSDOM cleanup\n     */\n    dispose: function () {\n      this.removeTexture(this.cacheKey);\n      this.removeTexture(this.cacheKey + '_filtered');\n      this._cacheContext = undefined;\n      ['_originalElement', '_element', '_filteredEl', '_cacheCanvas'].forEach(function (element) {\n        fabric.util.cleanUpJsdomNode(this[element]);\n        this[element] = undefined;\n      }.bind(this));\n    },\n\n    /**\n     * Get the crossOrigin value (of the corresponding image element)\n     */\n    getCrossOrigin: function () {\n      return this._originalElement && (this._originalElement.crossOrigin || null);\n    },\n\n    /**\n     * Returns original size of an image\n     * @return {Object} Object with \"width\" and \"height\" properties\n     */\n    getOriginalSize: function () {\n      var element = this.getElement();\n      return {\n        width: element.naturalWidth || element.width,\n        height: element.naturalHeight || element.height\n      };\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _stroke: function (ctx) {\n      if (!this.stroke || this.strokeWidth === 0) {\n        return;\n      }\n\n      var w = this.width / 2,\n          h = this.height / 2;\n      ctx.beginPath();\n      ctx.moveTo(-w, -h);\n      ctx.lineTo(w, -h);\n      ctx.lineTo(w, h);\n      ctx.lineTo(-w, h);\n      ctx.lineTo(-w, -h);\n      ctx.closePath();\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderDashedStroke: function (ctx) {\n      var x = -this.width / 2,\n          y = -this.height / 2,\n          w = this.width,\n          h = this.height;\n      ctx.save();\n\n      this._setStrokeStyles(ctx, this);\n\n      ctx.beginPath();\n      fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);\n      ctx.closePath();\n      ctx.restore();\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function (propertiesToInclude) {\n      var filters = [];\n      this.filters.forEach(function (filterObj) {\n        if (filterObj) {\n          filters.push(filterObj.toObject());\n        }\n      });\n      var object = extend(this.callSuper('toObject', ['cropX', 'cropY'].concat(propertiesToInclude)), {\n        src: this.getSrc(),\n        crossOrigin: this.getCrossOrigin(),\n        filters: filters\n      });\n\n      if (this.resizeFilter) {\n        object.resizeFilter = this.resizeFilter.toObject();\n      }\n\n      return object;\n    },\n\n    /**\n     * Returns true if an image has crop applied, inspecting values of cropX,cropY,width,hight.\n     * @return {Boolean}\n     */\n    hasCrop: function () {\n      return this.cropX || this.cropY || this.width < this._element.width || this.height < this._element.height;\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function () {\n      var svgString = [],\n          imageMarkup = [],\n          strokeSvg,\n          element = this._element,\n          x = -this.width / 2,\n          y = -this.height / 2,\n          clipPath = '',\n          imageRendering = '';\n\n      if (!element) {\n        return [];\n      }\n\n      if (this.hasCrop()) {\n        var clipPathId = fabric.Object.__uid++;\n        svgString.push('<clipPath id=\"imageCrop_' + clipPathId + '\">\\n', '\\t<rect x=\"' + x + '\" y=\"' + y + '\" width=\"' + this.width + '\" height=\"' + this.height + '\" />\\n', '</clipPath>\\n');\n        clipPath = ' clip-path=\"url(#imageCrop_' + clipPathId + ')\" ';\n      }\n\n      if (!this.imageSmoothing) {\n        imageRendering = '\" image-rendering=\"optimizeSpeed';\n      }\n\n      imageMarkup.push('\\t<image ', 'COMMON_PARTS', 'xlink:href=\"', this.getSvgSrc(true), '\" x=\"', x - this.cropX, '\" y=\"', y - this.cropY, // we're essentially moving origin of transformation from top/left corner to the center of the shape\n      // by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left\n      // so that object's center aligns with container's left/top\n      '\" width=\"', element.width || element.naturalWidth, '\" height=\"', element.height || element.height, imageRendering, '\"', clipPath, '></image>\\n');\n\n      if (this.stroke || this.strokeDashArray) {\n        var origFill = this.fill;\n        this.fill = null;\n        strokeSvg = ['\\t<rect ', 'x=\"', x, '\" y=\"', y, '\" width=\"', this.width, '\" height=\"', this.height, '\" style=\"', this.getSvgStyles(), '\"/>\\n'];\n        this.fill = origFill;\n      }\n\n      if (this.paintFirst !== 'fill') {\n        svgString = svgString.concat(strokeSvg, imageMarkup);\n      } else {\n        svgString = svgString.concat(imageMarkup, strokeSvg);\n      }\n\n      return svgString;\n    },\n\n    /* _TO_SVG_END_ */\n\n    /**\n     * Returns source of an image\n     * @param {Boolean} filtered indicates if the src is needed for svg\n     * @return {String} Source of an image\n     */\n    getSrc: function (filtered) {\n      var element = filtered ? this._element : this._originalElement;\n\n      if (element) {\n        if (element.toDataURL) {\n          return element.toDataURL();\n        }\n\n        if (this.srcFromAttribute) {\n          return element.getAttribute('src');\n        } else {\n          return element.src;\n        }\n      } else {\n        return this.src || '';\n      }\n    },\n\n    /**\n     * Sets source of an image\n     * @param {String} src Source string (URL)\n     * @param {Function} [callback] Callback is invoked when image has been loaded (and all filters have been applied)\n     * @param {Object} [options] Options object\n     * @param {String} [options.crossOrigin] crossOrigin value (one of \"\", \"anonymous\", \"use-credentials\")\n     * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes\n     * @return {fabric.Image} thisArg\n     * @chainable\n     */\n    setSrc: function (src, callback, options) {\n      fabric.util.loadImage(src, function (img, isError) {\n        this.setElement(img, options);\n\n        this._setWidthHeight();\n\n        callback && callback(this, isError);\n      }, this, options && options.crossOrigin);\n      return this;\n    },\n\n    /**\n     * Returns string representation of an instance\n     * @return {String} String representation of an instance\n     */\n    toString: function () {\n      return '#<fabric.Image: { src: \"' + this.getSrc() + '\" }>';\n    },\n    applyResizeFilters: function () {\n      var filter = this.resizeFilter,\n          minimumScale = this.minimumScaleTrigger,\n          objectScale = this.getTotalObjectScaling(),\n          scaleX = objectScale.scaleX,\n          scaleY = objectScale.scaleY,\n          elementToFilter = this._filteredEl || this._originalElement;\n\n      if (this.group) {\n        this.set('dirty', true);\n      }\n\n      if (!filter || scaleX > minimumScale && scaleY > minimumScale) {\n        this._element = elementToFilter;\n        this._filterScalingX = 1;\n        this._filterScalingY = 1;\n        this._lastScaleX = scaleX;\n        this._lastScaleY = scaleY;\n        return;\n      }\n\n      if (!fabric.filterBackend) {\n        fabric.filterBackend = fabric.initFilterBackend();\n      }\n\n      var canvasEl = fabric.util.createCanvasElement(),\n          cacheKey = this._filteredEl ? this.cacheKey + '_filtered' : this.cacheKey,\n          sourceWidth = elementToFilter.width,\n          sourceHeight = elementToFilter.height;\n      canvasEl.width = sourceWidth;\n      canvasEl.height = sourceHeight;\n      this._element = canvasEl;\n      this._lastScaleX = filter.scaleX = scaleX;\n      this._lastScaleY = filter.scaleY = scaleY;\n      fabric.filterBackend.applyFilters([filter], elementToFilter, sourceWidth, sourceHeight, this._element, cacheKey);\n      this._filterScalingX = canvasEl.width / this._originalElement.width;\n      this._filterScalingY = canvasEl.height / this._originalElement.height;\n    },\n\n    /**\n     * Applies filters assigned to this image (from \"filters\" array) or from filter param\n     * @method applyFilters\n     * @param {Array} filters to be applied\n     * @param {Boolean} forResizing specify if the filter operation is a resize operation\n     * @return {thisArg} return the fabric.Image object\n     * @chainable\n     */\n    applyFilters: function (filters) {\n      filters = filters || this.filters || [];\n      filters = filters.filter(function (filter) {\n        return filter && !filter.isNeutralState();\n      });\n      this.set('dirty', true); // needs to clear out or WEBGL will not resize correctly\n\n      this.removeTexture(this.cacheKey + '_filtered');\n\n      if (filters.length === 0) {\n        this._element = this._originalElement;\n        this._filteredEl = null;\n        this._filterScalingX = 1;\n        this._filterScalingY = 1;\n        return this;\n      }\n\n      var imgElement = this._originalElement,\n          sourceWidth = imgElement.naturalWidth || imgElement.width,\n          sourceHeight = imgElement.naturalHeight || imgElement.height;\n\n      if (this._element === this._originalElement) {\n        // if the element is the same we need to create a new element\n        var canvasEl = fabric.util.createCanvasElement();\n        canvasEl.width = sourceWidth;\n        canvasEl.height = sourceHeight;\n        this._element = canvasEl;\n        this._filteredEl = canvasEl;\n      } else {\n        // clear the existing element to get new filter data\n        // also dereference the eventual resized _element\n        this._element = this._filteredEl;\n\n        this._filteredEl.getContext('2d').clearRect(0, 0, sourceWidth, sourceHeight); // we also need to resize again at next renderAll, so remove saved _lastScaleX/Y\n\n\n        this._lastScaleX = 1;\n        this._lastScaleY = 1;\n      }\n\n      if (!fabric.filterBackend) {\n        fabric.filterBackend = fabric.initFilterBackend();\n      }\n\n      fabric.filterBackend.applyFilters(filters, this._originalElement, sourceWidth, sourceHeight, this._element, this.cacheKey);\n\n      if (this._originalElement.width !== this._element.width || this._originalElement.height !== this._element.height) {\n        this._filterScalingX = this._element.width / this._originalElement.width;\n        this._filterScalingY = this._element.height / this._originalElement.height;\n      }\n\n      return this;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function (ctx) {\n      fabric.util.setImageSmoothing(ctx, this.imageSmoothing);\n\n      if (this.isMoving !== true && this.resizeFilter && this._needsResize()) {\n        this.applyResizeFilters();\n      }\n\n      this._stroke(ctx);\n\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * Paint the cached copy of the object on the target context.\n     * it will set the imageSmoothing for the draw operation\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    drawCacheOnCanvas: function (ctx) {\n      fabric.util.setImageSmoothing(ctx, this.imageSmoothing);\n      fabric.Object.prototype.drawCacheOnCanvas.call(this, ctx);\n    },\n\n    /**\n     * Decide if the object should cache or not. Create its own cache level\n     * needsItsOwnCache should be used when the object drawing method requires\n     * a cache step. None of the fabric classes requires it.\n     * Generally you do not cache objects in groups because the group outside is cached.\n     * This is the special image version where we would like to avoid caching where possible.\n     * Essentially images do not benefit from caching. They may require caching, and in that\n     * case we do it. Also caching an image usually ends in a loss of details.\n     * A full performance audit should be done.\n     * @return {Boolean}\n     */\n    shouldCache: function () {\n      return this.needsItsOwnCache();\n    },\n    _renderFill: function (ctx) {\n      var elementToDraw = this._element;\n\n      if (!elementToDraw) {\n        return;\n      }\n\n      var scaleX = this._filterScalingX,\n          scaleY = this._filterScalingY,\n          w = this.width,\n          h = this.height,\n          min = Math.min,\n          max = Math.max,\n          // crop values cannot be lesser than 0.\n      cropX = max(this.cropX, 0),\n          cropY = max(this.cropY, 0),\n          elWidth = elementToDraw.naturalWidth || elementToDraw.width,\n          elHeight = elementToDraw.naturalHeight || elementToDraw.height,\n          sX = cropX * scaleX,\n          sY = cropY * scaleY,\n          // the width height cannot exceed element width/height, starting from the crop offset.\n      sW = min(w * scaleX, elWidth - sX),\n          sH = min(h * scaleY, elHeight - sY),\n          x = -w / 2,\n          y = -h / 2,\n          maxDestW = min(w, elWidth / scaleX - cropX),\n          maxDestH = min(h, elHeight / scaleX - cropY);\n      elementToDraw && ctx.drawImage(elementToDraw, sX, sY, sW, sH, x, y, maxDestW, maxDestH);\n    },\n\n    /**\n     * needed to check if image needs resize\n     * @private\n     */\n    _needsResize: function () {\n      var scale = this.getTotalObjectScaling();\n      return scale.scaleX !== this._lastScaleX || scale.scaleY !== this._lastScaleY;\n    },\n\n    /**\n     * @private\n     */\n    _resetWidthHeight: function () {\n      this.set(this.getOriginalSize());\n    },\n\n    /**\n     * The Image class's initialization method. This method is automatically\n     * called by the constructor.\n     * @private\n     * @param {HTMLImageElement|String} element The element representing the image\n     * @param {Object} [options] Options object\n     */\n    _initElement: function (element, options) {\n      this.setElement(fabric.util.getById(element), options);\n      fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS);\n    },\n\n    /**\n     * @private\n     * @param {Object} [options] Options object\n     */\n    _initConfig: function (options) {\n      options || (options = {});\n      this.setOptions(options);\n\n      this._setWidthHeight(options);\n    },\n\n    /**\n     * @private\n     * @param {Array} filters to be initialized\n     * @param {Function} callback Callback to invoke when all fabric.Image.filters instances are created\n     */\n    _initFilters: function (filters, callback) {\n      if (filters && filters.length) {\n        fabric.util.enlivenObjects(filters, function (enlivenedObjects) {\n          callback && callback(enlivenedObjects);\n        }, 'fabric.Image.filters');\n      } else {\n        callback && callback();\n      }\n    },\n\n    /**\n     * @private\n     * Set the width and the height of the image object, using the element or the\n     * options.\n     * @param {Object} [options] Object with width/height properties\n     */\n    _setWidthHeight: function (options) {\n      options || (options = {});\n      var el = this.getElement();\n      this.width = options.width || el.naturalWidth || el.width || 0;\n      this.height = options.height || el.naturalHeight || el.height || 0;\n    },\n\n    /**\n     * Calculate offset for center and scale factor for the image in order to respect\n     * the preserveAspectRatio attribute\n     * @private\n     * @return {Object}\n     */\n    parsePreserveAspectRatioAttribute: function () {\n      var pAR = fabric.util.parsePreserveAspectRatioAttribute(this.preserveAspectRatio || ''),\n          rWidth = this._element.width,\n          rHeight = this._element.height,\n          scaleX = 1,\n          scaleY = 1,\n          offsetLeft = 0,\n          offsetTop = 0,\n          cropX = 0,\n          cropY = 0,\n          offset,\n          pWidth = this.width,\n          pHeight = this.height,\n          parsedAttributes = {\n        width: pWidth,\n        height: pHeight\n      };\n\n      if (pAR && (pAR.alignX !== 'none' || pAR.alignY !== 'none')) {\n        if (pAR.meetOrSlice === 'meet') {\n          scaleX = scaleY = fabric.util.findScaleToFit(this._element, parsedAttributes);\n          offset = (pWidth - rWidth * scaleX) / 2;\n\n          if (pAR.alignX === 'Min') {\n            offsetLeft = -offset;\n          }\n\n          if (pAR.alignX === 'Max') {\n            offsetLeft = offset;\n          }\n\n          offset = (pHeight - rHeight * scaleY) / 2;\n\n          if (pAR.alignY === 'Min') {\n            offsetTop = -offset;\n          }\n\n          if (pAR.alignY === 'Max') {\n            offsetTop = offset;\n          }\n        }\n\n        if (pAR.meetOrSlice === 'slice') {\n          scaleX = scaleY = fabric.util.findScaleToCover(this._element, parsedAttributes);\n          offset = rWidth - pWidth / scaleX;\n\n          if (pAR.alignX === 'Mid') {\n            cropX = offset / 2;\n          }\n\n          if (pAR.alignX === 'Max') {\n            cropX = offset;\n          }\n\n          offset = rHeight - pHeight / scaleY;\n\n          if (pAR.alignY === 'Mid') {\n            cropY = offset / 2;\n          }\n\n          if (pAR.alignY === 'Max') {\n            cropY = offset;\n          }\n\n          rWidth = pWidth / scaleX;\n          rHeight = pHeight / scaleY;\n        }\n      } else {\n        scaleX = pWidth / rWidth;\n        scaleY = pHeight / rHeight;\n      }\n\n      return {\n        width: rWidth,\n        height: rHeight,\n        scaleX: scaleX,\n        scaleY: scaleY,\n        offsetLeft: offsetLeft,\n        offsetTop: offsetTop,\n        cropX: cropX,\n        cropY: cropY\n      };\n    }\n  });\n  /**\n   * Default CSS class name for canvas\n   * @static\n   * @type String\n   * @default\n   */\n\n  fabric.Image.CSS_CANVAS = 'canvas-img';\n  /**\n   * Alias for getSrc\n   * @static\n   */\n\n  fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc;\n  /**\n   * Creates an instance of fabric.Image from its object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {Function} callback Callback to invoke when an image instance is created\n   */\n\n  fabric.Image.fromObject = function (_object, callback) {\n    var object = fabric.util.object.clone(_object);\n    fabric.util.loadImage(object.src, function (img, isError) {\n      if (isError) {\n        callback && callback(null, true);\n        return;\n      }\n\n      fabric.Image.prototype._initFilters.call(object, object.filters, function (filters) {\n        object.filters = filters || [];\n\n        fabric.Image.prototype._initFilters.call(object, [object.resizeFilter], function (resizeFilters) {\n          object.resizeFilter = resizeFilters[0];\n          fabric.util.enlivenObjects([object.clipPath], function (enlivedProps) {\n            object.clipPath = enlivedProps[0];\n            var image = new fabric.Image(img, object);\n            callback(image, false);\n          });\n        });\n      });\n    }, null, object.crossOrigin);\n  };\n  /**\n   * Creates an instance of fabric.Image from an URL string\n   * @static\n   * @param {String} url URL to create an image from\n   * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument). Second argument is a boolean indicating if an error occured or not.\n   * @param {Object} [imgOptions] Options object\n   */\n\n\n  fabric.Image.fromURL = function (url, callback, imgOptions) {\n    fabric.util.loadImage(url, function (img, isError) {\n      callback && callback(new fabric.Image(img, imgOptions), isError);\n    }, null, imgOptions && imgOptions.crossOrigin);\n  };\n  /* _FROM_SVG_START_ */\n\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Image.fromElement})\n   * @static\n   * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement}\n   */\n\n\n  fabric.Image.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y width height preserveAspectRatio xlink:href crossOrigin image-rendering'.split(' '));\n  /**\n   * Returns {@link fabric.Image} instance from an SVG element\n   * @static\n   * @param {SVGElement} element Element to parse\n   * @param {Object} [options] Options object\n   * @param {Function} callback Callback to execute when fabric.Image object is created\n   * @return {fabric.Image} Instance of fabric.Image\n   */\n\n  fabric.Image.fromElement = function (element, callback, options) {\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES);\n    fabric.Image.fromURL(parsedAttributes['xlink:href'], callback, extend(options ? fabric.util.object.clone(options) : {}, parsedAttributes));\n  };\n  /* _FROM_SVG_END_ */\n\n})(typeof exports !== 'undefined' ? exports : this);\n\nfabric.util.object.extend(fabric.Object.prototype,\n/** @lends fabric.Object.prototype */\n{\n  /**\n   * @private\n   * @return {Number} angle value\n   */\n  _getAngleValueForStraighten: function () {\n    var angle = this.angle % 360;\n\n    if (angle > 0) {\n      return Math.round((angle - 1) / 90) * 90;\n    }\n\n    return Math.round(angle / 90) * 90;\n  },\n\n  /**\n   * Straightens an object (rotating it from current angle to one of 0, 90, 180, 270, etc. depending on which is closer)\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  straighten: function () {\n    this.rotate(this._getAngleValueForStraighten());\n    return this;\n  },\n\n  /**\n   * Same as {@link fabric.Object.prototype.straighten} but with animation\n   * @param {Object} callbacks Object with callback functions\n   * @param {Function} [callbacks.onComplete] Invoked on completion\n   * @param {Function} [callbacks.onChange] Invoked on every step of animation\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  fxStraighten: function (callbacks) {\n    callbacks = callbacks || {};\n\n    var empty = function () {},\n        onComplete = callbacks.onComplete || empty,\n        onChange = callbacks.onChange || empty,\n        _this = this;\n\n    fabric.util.animate({\n      startValue: this.get('angle'),\n      endValue: this._getAngleValueForStraighten(),\n      duration: this.FX_DURATION,\n      onChange: function (value) {\n        _this.rotate(value);\n\n        onChange();\n      },\n      onComplete: function () {\n        _this.setCoords();\n\n        onComplete();\n      }\n    });\n    return this;\n  }\n});\nfabric.util.object.extend(fabric.StaticCanvas.prototype,\n/** @lends fabric.StaticCanvas.prototype */\n{\n  /**\n   * Straightens object, then rerenders canvas\n   * @param {fabric.Object} object Object to straighten\n   * @return {fabric.Canvas} thisArg\n   * @chainable\n   */\n  straightenObject: function (object) {\n    object.straighten();\n    this.requestRenderAll();\n    return this;\n  },\n\n  /**\n   * Same as {@link fabric.Canvas.prototype.straightenObject}, but animated\n   * @param {fabric.Object} object Object to straighten\n   * @return {fabric.Canvas} thisArg\n   * @chainable\n   */\n  fxStraightenObject: function (object) {\n    object.fxStraighten({\n      onChange: this.requestRenderAllBound\n    });\n    return this;\n  }\n});\n\n(function () {\n  'use strict';\n  /**\n   * Tests if webgl supports certain precision\n   * @param {WebGL} Canvas WebGL context to test on\n   * @param {String} Precision to test can be any of following: 'lowp', 'mediump', 'highp'\n   * @returns {Boolean} Whether the user's browser WebGL supports given precision.\n   */\n\n  function testPrecision(gl, precision) {\n    var fragmentSource = 'precision ' + precision + ' float;\\nvoid main(){}';\n    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n    gl.shaderSource(fragmentShader, fragmentSource);\n    gl.compileShader(fragmentShader);\n\n    if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\n      return false;\n    }\n\n    return true;\n  }\n  /**\n   * Indicate whether this filtering backend is supported by the user's browser.\n   * @param {Number} tileSize check if the tileSize is supported\n   * @returns {Boolean} Whether the user's browser supports WebGL.\n   */\n\n\n  fabric.isWebglSupported = function (tileSize) {\n    if (fabric.isLikelyNode) {\n      return false;\n    }\n\n    tileSize = tileSize || fabric.WebglFilterBackend.prototype.tileSize;\n    var canvas = document.createElement('canvas');\n    var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n    var isSupported = false; // eslint-disable-next-line\n\n    if (gl) {\n      fabric.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);\n      isSupported = fabric.maxTextureSize >= tileSize;\n      var precisions = ['highp', 'mediump', 'lowp'];\n\n      for (var i = 0; i < 3; i++) {\n        if (testPrecision(gl, precisions[i])) {\n          fabric.webGlPrecision = precisions[i];\n          break;\n        }\n\n        ;\n      }\n    }\n\n    this.isSupported = isSupported;\n    return isSupported;\n  };\n\n  fabric.WebglFilterBackend = WebglFilterBackend;\n  /**\n   * WebGL filter backend.\n   */\n\n  function WebglFilterBackend(options) {\n    if (options && options.tileSize) {\n      this.tileSize = options.tileSize;\n    }\n\n    this.setupGLContext(this.tileSize, this.tileSize);\n    this.captureGPUInfo();\n  }\n\n  ;\n  WebglFilterBackend.prototype =\n  /** @lends fabric.WebglFilterBackend.prototype */\n  {\n    tileSize: 2048,\n\n    /**\n     * Experimental. This object is a sort of repository of help layers used to avoid\n     * of recreating them during frequent filtering. If you are previewing a filter with\n     * a slider you problably do not want to create help layers every filter step.\n     * in this object there will be appended some canvases, created once, resized sometimes\n     * cleared never. Clearing is left to the developer.\n     **/\n    resources: {},\n\n    /**\n     * Setup a WebGL context suitable for filtering, and bind any needed event handlers.\n     */\n    setupGLContext: function (width, height) {\n      this.dispose();\n      this.createWebGLCanvas(width, height); // eslint-disable-next-line\n\n      this.aPosition = new Float32Array([0, 0, 0, 1, 1, 0, 1, 1]);\n      this.chooseFastestCopyGLTo2DMethod(width, height);\n    },\n\n    /**\n     * Pick a method to copy data from GL context to 2d canvas.  In some browsers using\n     * putImageData is faster than drawImage for that specific operation.\n     */\n    chooseFastestCopyGLTo2DMethod: function (width, height) {\n      var canMeasurePerf = typeof window.performance !== 'undefined',\n          canUseImageData;\n\n      try {\n        new ImageData(1, 1);\n        canUseImageData = true;\n      } catch (e) {\n        canUseImageData = false;\n      } // eslint-disable-next-line no-undef\n\n\n      var canUseArrayBuffer = typeof ArrayBuffer !== 'undefined'; // eslint-disable-next-line no-undef\n\n      var canUseUint8Clamped = typeof Uint8ClampedArray !== 'undefined';\n\n      if (!(canMeasurePerf && canUseImageData && canUseArrayBuffer && canUseUint8Clamped)) {\n        return;\n      }\n\n      var targetCanvas = fabric.util.createCanvasElement(); // eslint-disable-next-line no-undef\n\n      var imageBuffer = new ArrayBuffer(width * height * 4);\n\n      if (fabric.forceGLPutImageData) {\n        this.imageBuffer = imageBuffer;\n        this.copyGLTo2D = copyGLTo2DPutImageData;\n        return;\n      }\n\n      var testContext = {\n        imageBuffer: imageBuffer,\n        destinationWidth: width,\n        destinationHeight: height,\n        targetCanvas: targetCanvas\n      };\n      var startTime, drawImageTime, putImageDataTime;\n      targetCanvas.width = width;\n      targetCanvas.height = height;\n      startTime = window.performance.now();\n      copyGLTo2DDrawImage.call(testContext, this.gl, testContext);\n      drawImageTime = window.performance.now() - startTime;\n      startTime = window.performance.now();\n      copyGLTo2DPutImageData.call(testContext, this.gl, testContext);\n      putImageDataTime = window.performance.now() - startTime;\n\n      if (drawImageTime > putImageDataTime) {\n        this.imageBuffer = imageBuffer;\n        this.copyGLTo2D = copyGLTo2DPutImageData;\n      } else {\n        this.copyGLTo2D = copyGLTo2DDrawImage;\n      }\n    },\n\n    /**\n     * Create a canvas element and associated WebGL context and attaches them as\n     * class properties to the GLFilterBackend class.\n     */\n    createWebGLCanvas: function (width, height) {\n      var canvas = fabric.util.createCanvasElement();\n      canvas.width = width;\n      canvas.height = height;\n      var glOptions = {\n        alpha: true,\n        premultipliedAlpha: false,\n        depth: false,\n        stencil: false,\n        antialias: false\n      },\n          gl = canvas.getContext('webgl', glOptions);\n\n      if (!gl) {\n        gl = canvas.getContext('experimental-webgl', glOptions);\n      }\n\n      if (!gl) {\n        return;\n      }\n\n      gl.clearColor(0, 0, 0, 0); // this canvas can fire webglcontextlost and webglcontextrestored\n\n      this.canvas = canvas;\n      this.gl = gl;\n    },\n\n    /**\n     * Attempts to apply the requested filters to the source provided, drawing the filtered output\n     * to the provided target canvas.\n     *\n     * @param {Array} filters The filters to apply.\n     * @param {HTMLImageElement|HTMLCanvasElement} source The source to be filtered.\n     * @param {Number} width The width of the source input.\n     * @param {Number} height The height of the source input.\n     * @param {HTMLCanvasElement} targetCanvas The destination for filtered output to be drawn.\n     * @param {String|undefined} cacheKey A key used to cache resources related to the source. If\n     * omitted, caching will be skipped.\n     */\n    applyFilters: function (filters, source, width, height, targetCanvas, cacheKey) {\n      var gl = this.gl;\n      var cachedTexture;\n\n      if (cacheKey) {\n        cachedTexture = this.getCachedTexture(cacheKey, source);\n      }\n\n      var pipelineState = {\n        originalWidth: source.width || source.originalWidth,\n        originalHeight: source.height || source.originalHeight,\n        sourceWidth: width,\n        sourceHeight: height,\n        destinationWidth: width,\n        destinationHeight: height,\n        context: gl,\n        sourceTexture: this.createTexture(gl, width, height, !cachedTexture && source),\n        targetTexture: this.createTexture(gl, width, height),\n        originalTexture: cachedTexture || this.createTexture(gl, width, height, !cachedTexture && source),\n        passes: filters.length,\n        webgl: true,\n        aPosition: this.aPosition,\n        programCache: this.programCache,\n        pass: 0,\n        filterBackend: this,\n        targetCanvas: targetCanvas\n      };\n      var tempFbo = gl.createFramebuffer();\n      gl.bindFramebuffer(gl.FRAMEBUFFER, tempFbo);\n      filters.forEach(function (filter) {\n        filter && filter.applyTo(pipelineState);\n      });\n      resizeCanvasIfNeeded(pipelineState);\n      this.copyGLTo2D(gl, pipelineState);\n      gl.bindTexture(gl.TEXTURE_2D, null);\n      gl.deleteTexture(pipelineState.sourceTexture);\n      gl.deleteTexture(pipelineState.targetTexture);\n      gl.deleteFramebuffer(tempFbo);\n      targetCanvas.getContext('2d').setTransform(1, 0, 0, 1, 0, 0);\n      return pipelineState;\n    },\n\n    /**\n     * Detach event listeners, remove references, and clean up caches.\n     */\n    dispose: function () {\n      if (this.canvas) {\n        this.canvas = null;\n        this.gl = null;\n      }\n\n      this.clearWebGLCaches();\n    },\n\n    /**\n     * Wipe out WebGL-related caches.\n     */\n    clearWebGLCaches: function () {\n      this.programCache = {};\n      this.textureCache = {};\n    },\n\n    /**\n     * Create a WebGL texture object.\n     *\n     * Accepts specific dimensions to initialize the textuer to or a source image.\n     *\n     * @param {WebGLRenderingContext} gl The GL context to use for creating the texture.\n     * @param {Number} width The width to initialize the texture at.\n     * @param {Number} height The height to initialize the texture.\n     * @param {HTMLImageElement|HTMLCanvasElement} textureImageSource A source for the texture data.\n     * @returns {WebGLTexture}\n     */\n    createTexture: function (gl, width, height, textureImageSource) {\n      var texture = gl.createTexture();\n      gl.bindTexture(gl.TEXTURE_2D, texture);\n      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n      if (textureImageSource) {\n        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureImageSource);\n      } else {\n        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n      }\n\n      return texture;\n    },\n\n    /**\n     * Can be optionally used to get a texture from the cache array\n     *\n     * If an existing texture is not found, a new texture is created and cached.\n     *\n     * @param {String} uniqueId A cache key to use to find an existing texture.\n     * @param {HTMLImageElement|HTMLCanvasElement} textureImageSource A source to use to create the\n     * texture cache entry if one does not already exist.\n     */\n    getCachedTexture: function (uniqueId, textureImageSource) {\n      if (this.textureCache[uniqueId]) {\n        return this.textureCache[uniqueId];\n      } else {\n        var texture = this.createTexture(this.gl, textureImageSource.width, textureImageSource.height, textureImageSource);\n        this.textureCache[uniqueId] = texture;\n        return texture;\n      }\n    },\n\n    /**\n     * Clear out cached resources related to a source image that has been\n     * filtered previously.\n     *\n     * @param {String} cacheKey The cache key provided when the source image was filtered.\n     */\n    evictCachesForKey: function (cacheKey) {\n      if (this.textureCache[cacheKey]) {\n        this.gl.deleteTexture(this.textureCache[cacheKey]);\n        delete this.textureCache[cacheKey];\n      }\n    },\n    copyGLTo2D: copyGLTo2DDrawImage,\n\n    /**\n     * Attempt to extract GPU information strings from a WebGL context.\n     *\n     * Useful information when debugging or blacklisting specific GPUs.\n     *\n     * @returns {Object} A GPU info object with renderer and vendor strings.\n     */\n    captureGPUInfo: function () {\n      if (this.gpuInfo) {\n        return this.gpuInfo;\n      }\n\n      var gl = this.gl,\n          gpuInfo = {\n        renderer: '',\n        vendor: ''\n      };\n\n      if (!gl) {\n        return gpuInfo;\n      }\n\n      var ext = gl.getExtension('WEBGL_debug_renderer_info');\n\n      if (ext) {\n        var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);\n        var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);\n\n        if (renderer) {\n          gpuInfo.renderer = renderer.toLowerCase();\n        }\n\n        if (vendor) {\n          gpuInfo.vendor = vendor.toLowerCase();\n        }\n      }\n\n      this.gpuInfo = gpuInfo;\n      return gpuInfo;\n    }\n  };\n})();\n\nfunction resizeCanvasIfNeeded(pipelineState) {\n  var targetCanvas = pipelineState.targetCanvas,\n      width = targetCanvas.width,\n      height = targetCanvas.height,\n      dWidth = pipelineState.destinationWidth,\n      dHeight = pipelineState.destinationHeight;\n\n  if (width !== dWidth || height !== dHeight) {\n    targetCanvas.width = dWidth;\n    targetCanvas.height = dHeight;\n  }\n}\n/**\n * Copy an input WebGL canvas on to an output 2D canvas.\n *\n * The WebGL canvas is assumed to be upside down, with the top-left pixel of the\n * desired output image appearing in the bottom-left corner of the WebGL canvas.\n *\n * @param {WebGLRenderingContext} sourceContext The WebGL context to copy from.\n * @param {HTMLCanvasElement} targetCanvas The 2D target canvas to copy on to.\n * @param {Object} pipelineState The 2D target canvas to copy on to.\n */\n\n\nfunction copyGLTo2DDrawImage(gl, pipelineState) {\n  var glCanvas = gl.canvas,\n      targetCanvas = pipelineState.targetCanvas,\n      ctx = targetCanvas.getContext('2d');\n  ctx.translate(0, targetCanvas.height); // move it down again\n\n  ctx.scale(1, -1); // vertical flip\n  // where is my image on the big glcanvas?\n\n  var sourceY = glCanvas.height - targetCanvas.height;\n  ctx.drawImage(glCanvas, 0, sourceY, targetCanvas.width, targetCanvas.height, 0, 0, targetCanvas.width, targetCanvas.height);\n}\n/**\n * Copy an input WebGL canvas on to an output 2D canvas using 2d canvas' putImageData\n * API. Measurably faster than using ctx.drawImage in Firefox (version 54 on OSX Sierra).\n *\n * @param {WebGLRenderingContext} sourceContext The WebGL context to copy from.\n * @param {HTMLCanvasElement} targetCanvas The 2D target canvas to copy on to.\n * @param {Object} pipelineState The 2D target canvas to copy on to.\n */\n\n\nfunction copyGLTo2DPutImageData(gl, pipelineState) {\n  var targetCanvas = pipelineState.targetCanvas,\n      ctx = targetCanvas.getContext('2d'),\n      dWidth = pipelineState.destinationWidth,\n      dHeight = pipelineState.destinationHeight,\n      numBytes = dWidth * dHeight * 4; // eslint-disable-next-line no-undef\n\n  var u8 = new Uint8Array(this.imageBuffer, 0, numBytes); // eslint-disable-next-line no-undef\n\n  var u8Clamped = new Uint8ClampedArray(this.imageBuffer, 0, numBytes);\n  gl.readPixels(0, 0, dWidth, dHeight, gl.RGBA, gl.UNSIGNED_BYTE, u8);\n  var imgData = new ImageData(u8Clamped, dWidth, dHeight);\n  ctx.putImageData(imgData, 0, 0);\n}\n\n(function () {\n  'use strict';\n\n  var noop = function () {};\n\n  fabric.Canvas2dFilterBackend = Canvas2dFilterBackend;\n  /**\n   * Canvas 2D filter backend.\n   */\n\n  function Canvas2dFilterBackend() {}\n\n  ;\n  Canvas2dFilterBackend.prototype =\n  /** @lends fabric.Canvas2dFilterBackend.prototype */\n  {\n    evictCachesForKey: noop,\n    dispose: noop,\n    clearWebGLCaches: noop,\n\n    /**\n     * Experimental. This object is a sort of repository of help layers used to avoid\n     * of recreating them during frequent filtering. If you are previewing a filter with\n     * a slider you probably do not want to create help layers every filter step.\n     * in this object there will be appended some canvases, created once, resized sometimes\n     * cleared never. Clearing is left to the developer.\n     **/\n    resources: {},\n\n    /**\n     * Apply a set of filters against a source image and draw the filtered output\n     * to the provided destination canvas.\n     *\n     * @param {EnhancedFilter} filters The filter to apply.\n     * @param {HTMLImageElement|HTMLCanvasElement} sourceElement The source to be filtered.\n     * @param {Number} sourceWidth The width of the source input.\n     * @param {Number} sourceHeight The height of the source input.\n     * @param {HTMLCanvasElement} targetCanvas The destination for filtered output to be drawn.\n     */\n    applyFilters: function (filters, sourceElement, sourceWidth, sourceHeight, targetCanvas) {\n      var ctx = targetCanvas.getContext('2d');\n      ctx.drawImage(sourceElement, 0, 0, sourceWidth, sourceHeight);\n      var imageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight);\n      var originalImageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight);\n      var pipelineState = {\n        sourceWidth: sourceWidth,\n        sourceHeight: sourceHeight,\n        imageData: imageData,\n        originalEl: sourceElement,\n        originalImageData: originalImageData,\n        canvasEl: targetCanvas,\n        ctx: ctx,\n        filterBackend: this\n      };\n      filters.forEach(function (filter) {\n        filter.applyTo(pipelineState);\n      });\n\n      if (pipelineState.imageData.width !== sourceWidth || pipelineState.imageData.height !== sourceHeight) {\n        targetCanvas.width = pipelineState.imageData.width;\n        targetCanvas.height = pipelineState.imageData.height;\n      }\n\n      ctx.putImageData(pipelineState.imageData, 0, 0);\n      return pipelineState;\n    }\n  };\n})();\n/**\n * @namespace fabric.Image.filters\n * @memberOf fabric.Image\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#image_filters}\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n */\n\n\nfabric.Image = fabric.Image || {};\nfabric.Image.filters = fabric.Image.filters || {};\n/**\n * Root filter class from which all filter classes inherit from\n * @class fabric.Image.filters.BaseFilter\n * @memberOf fabric.Image.filters\n */\n\nfabric.Image.filters.BaseFilter = fabric.util.createClass(\n/** @lends fabric.Image.filters.BaseFilter.prototype */\n{\n  /**\n   * Filter type\n   * @param {String} type\n   * @default\n   */\n  type: 'BaseFilter',\n\n  /**\n   * Array of attributes to send with buffers. do not modify\n   * @private\n   */\n  vertexSource: 'attribute vec2 aPosition;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vTexCoord = aPosition;\\n' + 'gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\\n' + '}',\n  fragmentSource: 'precision highp float;\\n' + 'varying vec2 vTexCoord;\\n' + 'uniform sampler2D uTexture;\\n' + 'void main() {\\n' + 'gl_FragColor = texture2D(uTexture, vTexCoord);\\n' + '}',\n\n  /**\n   * Constructor\n   * @param {Object} [options] Options object\n   */\n  initialize: function (options) {\n    if (options) {\n      this.setOptions(options);\n    }\n  },\n\n  /**\n   * Sets filter's properties from options\n   * @param {Object} [options] Options object\n   */\n  setOptions: function (options) {\n    for (var prop in options) {\n      this[prop] = options[prop];\n    }\n  },\n\n  /**\n   * Compile this filter's shader program.\n   *\n   * @param {WebGLRenderingContext} gl The GL canvas context to use for shader compilation.\n   * @param {String} fragmentSource fragmentShader source for compilation\n   * @param {String} vertexSource vertexShader source for compilation\n   */\n  createProgram: function (gl, fragmentSource, vertexSource) {\n    fragmentSource = fragmentSource || this.fragmentSource;\n    vertexSource = vertexSource || this.vertexSource;\n\n    if (fabric.webGlPrecision !== 'highp') {\n      fragmentSource = fragmentSource.replace(/precision highp float/g, 'precision ' + fabric.webGlPrecision + ' float');\n    }\n\n    var vertexShader = gl.createShader(gl.VERTEX_SHADER);\n    gl.shaderSource(vertexShader, vertexSource);\n    gl.compileShader(vertexShader);\n\n    if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {\n      throw new Error( // eslint-disable-next-line prefer-template\n      'Vertex shader compile error for ' + this.type + ': ' + gl.getShaderInfoLog(vertexShader));\n    }\n\n    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n    gl.shaderSource(fragmentShader, fragmentSource);\n    gl.compileShader(fragmentShader);\n\n    if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\n      throw new Error( // eslint-disable-next-line prefer-template\n      'Fragment shader compile error for ' + this.type + ': ' + gl.getShaderInfoLog(fragmentShader));\n    }\n\n    var program = gl.createProgram();\n    gl.attachShader(program, vertexShader);\n    gl.attachShader(program, fragmentShader);\n    gl.linkProgram(program);\n\n    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n      throw new Error( // eslint-disable-next-line prefer-template\n      'Shader link error for \"${this.type}\" ' + gl.getProgramInfoLog(program));\n    }\n\n    var attributeLocations = this.getAttributeLocations(gl, program);\n    var uniformLocations = this.getUniformLocations(gl, program) || {};\n    uniformLocations.uStepW = gl.getUniformLocation(program, 'uStepW');\n    uniformLocations.uStepH = gl.getUniformLocation(program, 'uStepH');\n    return {\n      program: program,\n      attributeLocations: attributeLocations,\n      uniformLocations: uniformLocations\n    };\n  },\n\n  /**\n   * Return a map of attribute names to WebGLAttributeLocation objects.\n   *\n   * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n   * @param {WebGLShaderProgram} program The shader program from which to take attribute locations.\n   * @returns {Object} A map of attribute names to attribute locations.\n   */\n  getAttributeLocations: function (gl, program) {\n    return {\n      aPosition: gl.getAttribLocation(program, 'aPosition')\n    };\n  },\n\n  /**\n   * Return a map of uniform names to WebGLUniformLocation objects.\n   *\n   * Intended to be overridden by subclasses.\n   *\n   * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n   * @param {WebGLShaderProgram} program The shader program from which to take uniform locations.\n   * @returns {Object} A map of uniform names to uniform locations.\n   */\n  getUniformLocations: function ()\n  /* gl, program */\n  {\n    // in case i do not need any special uniform i need to return an empty object\n    return {};\n  },\n\n  /**\n   * Send attribute data from this filter to its shader program on the GPU.\n   *\n   * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n   * @param {Object} attributeLocations A map of shader attribute names to their locations.\n   */\n  sendAttributeData: function (gl, attributeLocations, aPositionData) {\n    var attributeLocation = attributeLocations.aPosition;\n    var buffer = gl.createBuffer();\n    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n    gl.enableVertexAttribArray(attributeLocation);\n    gl.vertexAttribPointer(attributeLocation, 2, gl.FLOAT, false, 0, 0);\n    gl.bufferData(gl.ARRAY_BUFFER, aPositionData, gl.STATIC_DRAW);\n  },\n  _setupFrameBuffer: function (options) {\n    var gl = options.context,\n        width,\n        height;\n\n    if (options.passes > 1) {\n      width = options.destinationWidth;\n      height = options.destinationHeight;\n\n      if (options.sourceWidth !== width || options.sourceHeight !== height) {\n        gl.deleteTexture(options.targetTexture);\n        options.targetTexture = options.filterBackend.createTexture(gl, width, height);\n      }\n\n      gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, options.targetTexture, 0);\n    } else {\n      // draw last filter on canvas and not to framebuffer.\n      gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n      gl.finish();\n    }\n  },\n  _swapTextures: function (options) {\n    options.passes--;\n    options.pass++;\n    var temp = options.targetTexture;\n    options.targetTexture = options.sourceTexture;\n    options.sourceTexture = temp;\n  },\n\n  /**\n   * Generic isNeutral implementation for one parameter based filters.\n   * Used only in image applyFilters to discard filters that will not have an effect\n   * on the image\n   * Other filters may need their own verison ( ColorMatrix, HueRotation, gamma, ComposedFilter )\n   * @param {Object} options\n   **/\n  isNeutralState: function ()\n  /* options */\n  {\n    var main = this.mainParameter,\n        _class = fabric.Image.filters[this.type].prototype;\n\n    if (main) {\n      if (Array.isArray(_class[main])) {\n        for (var i = _class[main].length; i--;) {\n          if (this[main][i] !== _class[main][i]) {\n            return false;\n          }\n        }\n\n        return true;\n      } else {\n        return _class[main] === this[main];\n      }\n    } else {\n      return false;\n    }\n  },\n\n  /**\n   * Apply this filter to the input image data provided.\n   *\n   * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\n   *\n   * @param {Object} options\n   * @param {Number} options.passes The number of filters remaining to be executed\n   * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n   * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n   * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n   * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n   * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n   */\n  applyTo: function (options) {\n    if (options.webgl) {\n      this._setupFrameBuffer(options);\n\n      this.applyToWebGL(options);\n\n      this._swapTextures(options);\n    } else {\n      this.applyTo2d(options);\n    }\n  },\n\n  /**\n   * Retrieves the cached shader.\n   * @param {Object} options\n   * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n   * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n   */\n  retrieveShader: function (options) {\n    if (!options.programCache.hasOwnProperty(this.type)) {\n      options.programCache[this.type] = this.createProgram(options.context);\n    }\n\n    return options.programCache[this.type];\n  },\n\n  /**\n   * Apply this filter using webgl.\n   *\n   * @param {Object} options\n   * @param {Number} options.passes The number of filters remaining to be executed\n   * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n   * @param {WebGLTexture} options.originalTexture The texture of the original input image.\n   * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n   * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n   * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n   * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n   */\n  applyToWebGL: function (options) {\n    var gl = options.context;\n    var shader = this.retrieveShader(options);\n\n    if (options.pass === 0 && options.originalTexture) {\n      gl.bindTexture(gl.TEXTURE_2D, options.originalTexture);\n    } else {\n      gl.bindTexture(gl.TEXTURE_2D, options.sourceTexture);\n    }\n\n    gl.useProgram(shader.program);\n    this.sendAttributeData(gl, shader.attributeLocations, options.aPosition);\n    gl.uniform1f(shader.uniformLocations.uStepW, 1 / options.sourceWidth);\n    gl.uniform1f(shader.uniformLocations.uStepH, 1 / options.sourceHeight);\n    this.sendUniformData(gl, shader.uniformLocations);\n    gl.viewport(0, 0, options.destinationWidth, options.destinationHeight);\n    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n  },\n  bindAdditionalTexture: function (gl, texture, textureUnit) {\n    gl.activeTexture(textureUnit);\n    gl.bindTexture(gl.TEXTURE_2D, texture); // reset active texture to 0 as usual\n\n    gl.activeTexture(gl.TEXTURE0);\n  },\n  unbindAdditionalTexture: function (gl, textureUnit) {\n    gl.activeTexture(textureUnit);\n    gl.bindTexture(gl.TEXTURE_2D, null);\n    gl.activeTexture(gl.TEXTURE0);\n  },\n  getMainParameter: function () {\n    return this[this.mainParameter];\n  },\n  setMainParameter: function (value) {\n    this[this.mainParameter] = value;\n  },\n\n  /**\n   * Send uniform data from this filter to its shader program on the GPU.\n   *\n   * Intended to be overridden by subclasses.\n   *\n   * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n   * @param {Object} uniformLocations A map of shader uniform names to their locations.\n   */\n  sendUniformData: function ()\n  /* gl, uniformLocations */\n  {// Intentionally left blank.  Override me in subclasses.\n  },\n\n  /**\n   * If needed by a 2d filter, this functions can create an helper canvas to be used\n   * remember that options.targetCanvas is available for use till end of chain.\n   */\n  createHelpLayer: function (options) {\n    if (!options.helpLayer) {\n      var helpLayer = document.createElement('canvas');\n      helpLayer.width = options.sourceWidth;\n      helpLayer.height = options.sourceHeight;\n      options.helpLayer = helpLayer;\n    }\n  },\n\n  /**\n   * Returns object representation of an instance\n   * @return {Object} Object representation of an instance\n   */\n  toObject: function () {\n    var object = {\n      type: this.type\n    },\n        mainP = this.mainParameter;\n\n    if (mainP) {\n      object[mainP] = this[mainP];\n    }\n\n    return object;\n  },\n\n  /**\n   * Returns a JSON representation of an instance\n   * @return {Object} JSON\n   */\n  toJSON: function () {\n    // delegate, not alias\n    return this.toObject();\n  }\n});\n\nfabric.Image.filters.BaseFilter.fromObject = function (object, callback) {\n  var filter = new fabric.Image.filters[object.type](object);\n  callback && callback(filter);\n  return filter;\n};\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Color Matrix filter class\n   * @class fabric.Image.filters.ColorMatrix\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.ColorMatrix#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @see {@Link http://www.webwasp.co.uk/tutorials/219/Color_Matrix_Filter.php}\n   * @see {@Link http://phoboslab.org/log/2013/11/fast-image-filters-with-webgl}\n   * @example <caption>Kodachrome filter</caption>\n   * var filter = new fabric.Image.filters.ColorMatrix({\n   *  matrix: [\n       1.1285582396593525, -0.3967382283601348, -0.03992559172921793, 0, 63.72958762196502,\n       -0.16404339962244616, 1.0835251566291304, -0.05498805115633132, 0, 24.732407896706203,\n       -0.16786010706155763, -0.5603416277695248, 1.6014850761964943, 0, 35.62982807460946,\n       0, 0, 0, 1, 0\n      ]\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n\n  filters.ColorMatrix = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.ColorMatrix.prototype */\n  {\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'ColorMatrix',\n    fragmentSource: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'varying vec2 vTexCoord;\\n' + 'uniform mat4 uColorMatrix;\\n' + 'uniform vec4 uConstants;\\n' + 'void main() {\\n' + 'vec4 color = texture2D(uTexture, vTexCoord);\\n' + 'color *= uColorMatrix;\\n' + 'color += uConstants;\\n' + 'gl_FragColor = color;\\n' + '}',\n\n    /**\n     * Colormatrix for pixels.\n     * array of 20 floats. Numbers in positions 4, 9, 14, 19 loose meaning\n     * outside the -1, 1 range.\n     * 0.0039215686 is the part of 1 that get translated to 1 in 2d\n     * @param {Array} matrix array of 20 numbers.\n     * @default\n     */\n    matrix: [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0],\n    mainParameter: 'matrix',\n\n    /**\n     * Lock the colormatrix on the color part, skipping alpha, manly for non webgl scenario\n     * to save some calculation\n     */\n    colorsOnly: true,\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     */\n    initialize: function (options) {\n      this.callSuper('initialize', options); // create a new array instead mutating the prototype with push\n\n      this.matrix = this.matrix.slice(0);\n    },\n\n    /**\n     * Apply the ColorMatrix operation to a Uint8Array representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8Array to be filtered.\n     */\n    applyTo2d: function (options) {\n      var imageData = options.imageData,\n          data = imageData.data,\n          iLen = data.length,\n          m = this.matrix,\n          r,\n          g,\n          b,\n          a,\n          i,\n          colorsOnly = this.colorsOnly;\n\n      for (i = 0; i < iLen; i += 4) {\n        r = data[i];\n        g = data[i + 1];\n        b = data[i + 2];\n\n        if (colorsOnly) {\n          data[i] = r * m[0] + g * m[1] + b * m[2] + m[4] * 255;\n          data[i + 1] = r * m[5] + g * m[6] + b * m[7] + m[9] * 255;\n          data[i + 2] = r * m[10] + g * m[11] + b * m[12] + m[14] * 255;\n        } else {\n          a = data[i + 3];\n          data[i] = r * m[0] + g * m[1] + b * m[2] + a * m[3] + m[4] * 255;\n          data[i + 1] = r * m[5] + g * m[6] + b * m[7] + a * m[8] + m[9] * 255;\n          data[i + 2] = r * m[10] + g * m[11] + b * m[12] + a * m[13] + m[14] * 255;\n          data[i + 3] = r * m[15] + g * m[16] + b * m[17] + a * m[18] + m[19] * 255;\n        }\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uColorMatrix: gl.getUniformLocation(program, 'uColorMatrix'),\n        uConstants: gl.getUniformLocation(program, 'uConstants')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      var m = this.matrix,\n          matrix = [m[0], m[1], m[2], m[3], m[5], m[6], m[7], m[8], m[10], m[11], m[12], m[13], m[15], m[16], m[17], m[18]],\n          constants = [m[4], m[9], m[14], m[19]];\n      gl.uniformMatrix4fv(uniformLocations.uColorMatrix, false, matrix);\n      gl.uniform4fv(uniformLocations.uConstants, constants);\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] function to invoke after filter creation\n   * @return {fabric.Image.filters.ColorMatrix} Instance of fabric.Image.filters.ColorMatrix\n   */\n\n  fabric.Image.filters.ColorMatrix.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Brightness filter class\n   * @class fabric.Image.filters.Brightness\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Brightness#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Brightness({\n   *   brightness: 0.05\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n\n  filters.Brightness = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.Brightness.prototype */\n  {\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Brightness',\n\n    /**\n     * Fragment source for the brightness program\n     */\n    fragmentSource: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uBrightness;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = texture2D(uTexture, vTexCoord);\\n' + 'color.rgb += uBrightness;\\n' + 'gl_FragColor = color;\\n' + '}',\n\n    /**\n     * Brightness value, from -1 to 1.\n     * translated to -255 to 255 for 2d\n     * 0.0039215686 is the part of 1 that get translated to 1 in 2d\n     * @param {Number} brightness\n     * @default\n     */\n    brightness: 0,\n\n    /**\n     * Describe the property that is the filter parameter\n     * @param {String} m\n     * @default\n     */\n    mainParameter: 'brightness',\n\n    /**\n    * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\n    *\n    * @param {Object} options\n    * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n    */\n    applyTo2d: function (options) {\n      if (this.brightness === 0) {\n        return;\n      }\n\n      var imageData = options.imageData,\n          data = imageData.data,\n          i,\n          len = data.length,\n          brightness = Math.round(this.brightness * 255);\n\n      for (i = 0; i < len; i += 4) {\n        data[i] = data[i] + brightness;\n        data[i + 1] = data[i + 1] + brightness;\n        data[i + 2] = data[i + 2] + brightness;\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uBrightness: gl.getUniformLocation(program, 'uBrightness')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      gl.uniform1f(uniformLocations.uBrightness, this.brightness);\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Brightness} Instance of fabric.Image.filters.Brightness\n   */\n\n  fabric.Image.filters.Brightness.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      extend = fabric.util.object.extend,\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Adapted from <a href=\"http://www.html5rocks.com/en/tutorials/canvas/imagefilters/\">html5rocks article</a>\n   * @class fabric.Image.filters.Convolute\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Convolute#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example <caption>Sharpen filter</caption>\n   * var filter = new fabric.Image.filters.Convolute({\n   *   matrix: [ 0, -1,  0,\n   *            -1,  5, -1,\n   *             0, -1,  0 ]\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   * @example <caption>Blur filter</caption>\n   * var filter = new fabric.Image.filters.Convolute({\n   *   matrix: [ 1/9, 1/9, 1/9,\n   *             1/9, 1/9, 1/9,\n   *             1/9, 1/9, 1/9 ]\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   * @example <caption>Emboss filter</caption>\n   * var filter = new fabric.Image.filters.Convolute({\n   *   matrix: [ 1,   1,  1,\n   *             1, 0.7, -1,\n   *            -1,  -1, -1 ]\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   * @example <caption>Emboss filter with opaqueness</caption>\n   * var filter = new fabric.Image.filters.Convolute({\n   *   opaque: true,\n   *   matrix: [ 1,   1,  1,\n   *             1, 0.7, -1,\n   *            -1,  -1, -1 ]\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   */\n\n  filters.Convolute = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.Convolute.prototype */\n  {\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Convolute',\n\n    /*\n     * Opaque value (true/false)\n     */\n    opaque: false,\n\n    /*\n     * matrix for the filter, max 9x9\n     */\n    matrix: [0, 0, 0, 0, 1, 0, 0, 0, 0],\n\n    /**\n     * Fragment source for the brightness program\n     */\n    fragmentSource: {\n      Convolute_3_1: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uMatrix[9];\\n' + 'uniform float uStepW;\\n' + 'uniform float uStepH;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = vec4(0, 0, 0, 0);\\n' + 'for (float h = 0.0; h < 3.0; h+=1.0) {\\n' + 'for (float w = 0.0; w < 3.0; w+=1.0) {\\n' + 'vec2 matrixPos = vec2(uStepW * (w - 1), uStepH * (h - 1));\\n' + 'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 3.0 + w)];\\n' + '}\\n' + '}\\n' + 'gl_FragColor = color;\\n' + '}',\n      Convolute_3_0: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uMatrix[9];\\n' + 'uniform float uStepW;\\n' + 'uniform float uStepH;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = vec4(0, 0, 0, 1);\\n' + 'for (float h = 0.0; h < 3.0; h+=1.0) {\\n' + 'for (float w = 0.0; w < 3.0; w+=1.0) {\\n' + 'vec2 matrixPos = vec2(uStepW * (w - 1.0), uStepH * (h - 1.0));\\n' + 'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 3.0 + w)];\\n' + '}\\n' + '}\\n' + 'float alpha = texture2D(uTexture, vTexCoord).a;\\n' + 'gl_FragColor = color;\\n' + 'gl_FragColor.a = alpha;\\n' + '}',\n      Convolute_5_1: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uMatrix[25];\\n' + 'uniform float uStepW;\\n' + 'uniform float uStepH;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = vec4(0, 0, 0, 0);\\n' + 'for (float h = 0.0; h < 5.0; h+=1.0) {\\n' + 'for (float w = 0.0; w < 5.0; w+=1.0) {\\n' + 'vec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\\n' + 'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 5.0 + w)];\\n' + '}\\n' + '}\\n' + 'gl_FragColor = color;\\n' + '}',\n      Convolute_5_0: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uMatrix[25];\\n' + 'uniform float uStepW;\\n' + 'uniform float uStepH;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = vec4(0, 0, 0, 1);\\n' + 'for (float h = 0.0; h < 5.0; h+=1.0) {\\n' + 'for (float w = 0.0; w < 5.0; w+=1.0) {\\n' + 'vec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\\n' + 'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 5.0 + w)];\\n' + '}\\n' + '}\\n' + 'float alpha = texture2D(uTexture, vTexCoord).a;\\n' + 'gl_FragColor = color;\\n' + 'gl_FragColor.a = alpha;\\n' + '}',\n      Convolute_7_1: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uMatrix[49];\\n' + 'uniform float uStepW;\\n' + 'uniform float uStepH;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = vec4(0, 0, 0, 0);\\n' + 'for (float h = 0.0; h < 7.0; h+=1.0) {\\n' + 'for (float w = 0.0; w < 7.0; w+=1.0) {\\n' + 'vec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\\n' + 'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 7.0 + w)];\\n' + '}\\n' + '}\\n' + 'gl_FragColor = color;\\n' + '}',\n      Convolute_7_0: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uMatrix[49];\\n' + 'uniform float uStepW;\\n' + 'uniform float uStepH;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = vec4(0, 0, 0, 1);\\n' + 'for (float h = 0.0; h < 7.0; h+=1.0) {\\n' + 'for (float w = 0.0; w < 7.0; w+=1.0) {\\n' + 'vec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\\n' + 'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 7.0 + w)];\\n' + '}\\n' + '}\\n' + 'float alpha = texture2D(uTexture, vTexCoord).a;\\n' + 'gl_FragColor = color;\\n' + 'gl_FragColor.a = alpha;\\n' + '}',\n      Convolute_9_1: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uMatrix[81];\\n' + 'uniform float uStepW;\\n' + 'uniform float uStepH;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = vec4(0, 0, 0, 0);\\n' + 'for (float h = 0.0; h < 9.0; h+=1.0) {\\n' + 'for (float w = 0.0; w < 9.0; w+=1.0) {\\n' + 'vec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\\n' + 'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 9.0 + w)];\\n' + '}\\n' + '}\\n' + 'gl_FragColor = color;\\n' + '}',\n      Convolute_9_0: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uMatrix[81];\\n' + 'uniform float uStepW;\\n' + 'uniform float uStepH;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = vec4(0, 0, 0, 1);\\n' + 'for (float h = 0.0; h < 9.0; h+=1.0) {\\n' + 'for (float w = 0.0; w < 9.0; w+=1.0) {\\n' + 'vec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\\n' + 'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 9.0 + w)];\\n' + '}\\n' + '}\\n' + 'float alpha = texture2D(uTexture, vTexCoord).a;\\n' + 'gl_FragColor = color;\\n' + 'gl_FragColor.a = alpha;\\n' + '}'\n    },\n\n    /**\n     * Constructor\n     * @memberOf fabric.Image.filters.Convolute.prototype\n     * @param {Object} [options] Options object\n     * @param {Boolean} [options.opaque=false] Opaque value (true/false)\n     * @param {Array} [options.matrix] Filter matrix\n     */\n\n    /**\n    * Retrieves the cached shader.\n    * @param {Object} options\n    * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n    * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n    */\n    retrieveShader: function (options) {\n      var size = Math.sqrt(this.matrix.length);\n      var cacheKey = this.type + '_' + size + '_' + (this.opaque ? 1 : 0);\n      var shaderSource = this.fragmentSource[cacheKey];\n\n      if (!options.programCache.hasOwnProperty(cacheKey)) {\n        options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\n      }\n\n      return options.programCache[cacheKey];\n    },\n\n    /**\n     * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n     */\n    applyTo2d: function (options) {\n      var imageData = options.imageData,\n          data = imageData.data,\n          weights = this.matrix,\n          side = Math.round(Math.sqrt(weights.length)),\n          halfSide = Math.floor(side / 2),\n          sw = imageData.width,\n          sh = imageData.height,\n          output = options.ctx.createImageData(sw, sh),\n          dst = output.data,\n          // go through the destination image pixels\n      alphaFac = this.opaque ? 1 : 0,\n          r,\n          g,\n          b,\n          a,\n          dstOff,\n          scx,\n          scy,\n          srcOff,\n          wt,\n          x,\n          y,\n          cx,\n          cy;\n\n      for (y = 0; y < sh; y++) {\n        for (x = 0; x < sw; x++) {\n          dstOff = (y * sw + x) * 4; // calculate the weighed sum of the source image pixels that\n          // fall under the convolution matrix\n\n          r = 0;\n          g = 0;\n          b = 0;\n          a = 0;\n\n          for (cy = 0; cy < side; cy++) {\n            for (cx = 0; cx < side; cx++) {\n              scy = y + cy - halfSide;\n              scx = x + cx - halfSide; // eslint-disable-next-line max-depth\n\n              if (scy < 0 || scy >= sh || scx < 0 || scx >= sw) {\n                continue;\n              }\n\n              srcOff = (scy * sw + scx) * 4;\n              wt = weights[cy * side + cx];\n              r += data[srcOff] * wt;\n              g += data[srcOff + 1] * wt;\n              b += data[srcOff + 2] * wt; // eslint-disable-next-line max-depth\n\n              if (!alphaFac) {\n                a += data[srcOff + 3] * wt;\n              }\n            }\n          }\n\n          dst[dstOff] = r;\n          dst[dstOff + 1] = g;\n          dst[dstOff + 2] = b;\n\n          if (!alphaFac) {\n            dst[dstOff + 3] = a;\n          } else {\n            dst[dstOff + 3] = data[dstOff + 3];\n          }\n        }\n      }\n\n      options.imageData = output;\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uMatrix: gl.getUniformLocation(program, 'uMatrix'),\n        uOpaque: gl.getUniformLocation(program, 'uOpaque'),\n        uHalfSize: gl.getUniformLocation(program, 'uHalfSize'),\n        uSize: gl.getUniformLocation(program, 'uSize')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      gl.uniform1fv(uniformLocations.uMatrix, this.matrix);\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function () {\n      return extend(this.callSuper('toObject'), {\n        opaque: this.opaque,\n        matrix: this.matrix\n      });\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Convolute} Instance of fabric.Image.filters.Convolute\n   */\n\n  fabric.Image.filters.Convolute.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Grayscale image filter class\n   * @class fabric.Image.filters.Grayscale\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Grayscale();\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n\n  filters.Grayscale = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.Grayscale.prototype */\n  {\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Grayscale',\n    fragmentSource: {\n      average: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = texture2D(uTexture, vTexCoord);\\n' + 'float average = (color.r + color.b + color.g) / 3.0;\\n' + 'gl_FragColor = vec4(average, average, average, color.a);\\n' + '}',\n      lightness: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform int uMode;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 col = texture2D(uTexture, vTexCoord);\\n' + 'float average = (max(max(col.r, col.g),col.b) + min(min(col.r, col.g),col.b)) / 2.0;\\n' + 'gl_FragColor = vec4(average, average, average, col.a);\\n' + '}',\n      luminosity: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform int uMode;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 col = texture2D(uTexture, vTexCoord);\\n' + 'float average = 0.21 * col.r + 0.72 * col.g + 0.07 * col.b;\\n' + 'gl_FragColor = vec4(average, average, average, col.a);\\n' + '}'\n    },\n\n    /**\n     * Grayscale mode, between 'average', 'lightness', 'luminosity'\n     * @param {String} type\n     * @default\n     */\n    mode: 'average',\n    mainParameter: 'mode',\n\n    /**\n     * Apply the Grayscale operation to a Uint8Array representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8Array to be filtered.\n     */\n    applyTo2d: function (options) {\n      var imageData = options.imageData,\n          data = imageData.data,\n          i,\n          len = data.length,\n          value,\n          mode = this.mode;\n\n      for (i = 0; i < len; i += 4) {\n        if (mode === 'average') {\n          value = (data[i] + data[i + 1] + data[i + 2]) / 3;\n        } else if (mode === 'lightness') {\n          value = (Math.min(data[i], data[i + 1], data[i + 2]) + Math.max(data[i], data[i + 1], data[i + 2])) / 2;\n        } else if (mode === 'luminosity') {\n          value = 0.21 * data[i] + 0.72 * data[i + 1] + 0.07 * data[i + 2];\n        }\n\n        data[i] = value;\n        data[i + 1] = value;\n        data[i + 2] = value;\n      }\n    },\n\n    /**\n     * Retrieves the cached shader.\n     * @param {Object} options\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    retrieveShader: function (options) {\n      var cacheKey = this.type + '_' + this.mode;\n\n      if (!options.programCache.hasOwnProperty(cacheKey)) {\n        var shaderSource = this.fragmentSource[this.mode];\n        options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\n      }\n\n      return options.programCache[cacheKey];\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uMode: gl.getUniformLocation(program, 'uMode')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      // default average mode.\n      var mode = 1;\n      gl.uniform1i(uniformLocations.uMode, mode);\n    },\n\n    /**\n     * Grayscale filter isNeutralState implementation\n     * The filter is never neutral\n     * on the image\n     **/\n    isNeutralState: function () {\n      return false;\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Grayscale} Instance of fabric.Image.filters.Grayscale\n   */\n\n  fabric.Image.filters.Grayscale.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Invert filter class\n   * @class fabric.Image.filters.Invert\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Invert();\n   * object.filters.push(filter);\n   * object.applyFilters(canvas.renderAll.bind(canvas));\n   */\n\n  filters.Invert = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.Invert.prototype */\n  {\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Invert',\n    fragmentSource: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform int uInvert;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = texture2D(uTexture, vTexCoord);\\n' + 'if (uInvert == 1) {\\n' + 'gl_FragColor = vec4(1.0 - color.r,1.0 -color.g,1.0 -color.b,color.a);\\n' + '} else {\\n' + 'gl_FragColor = color;\\n' + '}\\n' + '}',\n\n    /**\n     * Filter invert. if false, does nothing\n     * @param {Boolean} invert\n     * @default\n     */\n    invert: true,\n    mainParameter: 'invert',\n\n    /**\n     * Apply the Invert operation to a Uint8Array representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8Array to be filtered.\n     */\n    applyTo2d: function (options) {\n      var imageData = options.imageData,\n          data = imageData.data,\n          i,\n          len = data.length;\n\n      for (i = 0; i < len; i += 4) {\n        data[i] = 255 - data[i];\n        data[i + 1] = 255 - data[i + 1];\n        data[i + 2] = 255 - data[i + 2];\n      }\n    },\n\n    /**\n     * Invert filter isNeutralState implementation\n     * Used only in image applyFilters to discard filters that will not have an effect\n     * on the image\n     * @param {Object} options\n     **/\n    isNeutralState: function () {\n      return !this.invert;\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uInvert: gl.getUniformLocation(program, 'uInvert')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      gl.uniform1i(uniformLocations.uInvert, this.invert);\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Invert} Instance of fabric.Image.filters.Invert\n   */\n\n  fabric.Image.filters.Invert.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      extend = fabric.util.object.extend,\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Noise filter class\n   * @class fabric.Image.filters.Noise\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Noise#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Noise({\n   *   noise: 700\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   */\n\n  filters.Noise = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.Noise.prototype */\n  {\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Noise',\n\n    /**\n     * Fragment source for the noise program\n     */\n    fragmentSource: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uStepH;\\n' + 'uniform float uNoise;\\n' + 'uniform float uSeed;\\n' + 'varying vec2 vTexCoord;\\n' + 'float rand(vec2 co, float seed, float vScale) {\\n' + 'return fract(sin(dot(co.xy * vScale ,vec2(12.9898 , 78.233))) * 43758.5453 * (seed + 0.01) / 2.0);\\n' + '}\\n' + 'void main() {\\n' + 'vec4 color = texture2D(uTexture, vTexCoord);\\n' + 'color.rgb += (0.5 - rand(vTexCoord, uSeed, 0.1 / uStepH)) * uNoise;\\n' + 'gl_FragColor = color;\\n' + '}',\n\n    /**\n     * Describe the property that is the filter parameter\n     * @param {String} m\n     * @default\n     */\n    mainParameter: 'noise',\n\n    /**\n     * Noise value, from\n     * @param {Number} noise\n     * @default\n     */\n    noise: 0,\n\n    /**\n     * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n     */\n    applyTo2d: function (options) {\n      if (this.noise === 0) {\n        return;\n      }\n\n      var imageData = options.imageData,\n          data = imageData.data,\n          i,\n          len = data.length,\n          noise = this.noise,\n          rand;\n\n      for (i = 0, len = data.length; i < len; i += 4) {\n        rand = (0.5 - Math.random()) * noise;\n        data[i] += rand;\n        data[i + 1] += rand;\n        data[i + 2] += rand;\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uNoise: gl.getUniformLocation(program, 'uNoise'),\n        uSeed: gl.getUniformLocation(program, 'uSeed')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      gl.uniform1f(uniformLocations.uNoise, this.noise / 255);\n      gl.uniform1f(uniformLocations.uSeed, Math.random());\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function () {\n      return extend(this.callSuper('toObject'), {\n        noise: this.noise\n      });\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Noise} Instance of fabric.Image.filters.Noise\n   */\n\n  fabric.Image.filters.Noise.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Pixelate filter class\n   * @class fabric.Image.filters.Pixelate\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Pixelate#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Pixelate({\n   *   blocksize: 8\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n\n  filters.Pixelate = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.Pixelate.prototype */\n  {\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Pixelate',\n    blocksize: 4,\n    mainParameter: 'blocksize',\n\n    /**\n     * Fragment source for the Pixelate program\n     */\n    fragmentSource: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uBlocksize;\\n' + 'uniform float uStepW;\\n' + 'uniform float uStepH;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'float blockW = uBlocksize * uStepW;\\n' + 'float blockH = uBlocksize * uStepW;\\n' + 'int posX = int(vTexCoord.x / blockW);\\n' + 'int posY = int(vTexCoord.y / blockH);\\n' + 'float fposX = float(posX);\\n' + 'float fposY = float(posY);\\n' + 'vec2 squareCoords = vec2(fposX * blockW, fposY * blockH);\\n' + 'vec4 color = texture2D(uTexture, squareCoords);\\n' + 'gl_FragColor = color;\\n' + '}',\n\n    /**\n     * Apply the Pixelate operation to a Uint8ClampedArray representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n     */\n    applyTo2d: function (options) {\n      var imageData = options.imageData,\n          data = imageData.data,\n          iLen = imageData.height,\n          jLen = imageData.width,\n          index,\n          i,\n          j,\n          r,\n          g,\n          b,\n          a,\n          _i,\n          _j,\n          _iLen,\n          _jLen;\n\n      for (i = 0; i < iLen; i += this.blocksize) {\n        for (j = 0; j < jLen; j += this.blocksize) {\n          index = i * 4 * jLen + j * 4;\n          r = data[index];\n          g = data[index + 1];\n          b = data[index + 2];\n          a = data[index + 3];\n          _iLen = Math.min(i + this.blocksize, iLen);\n          _jLen = Math.min(j + this.blocksize, jLen);\n\n          for (_i = i; _i < _iLen; _i++) {\n            for (_j = j; _j < _jLen; _j++) {\n              index = _i * 4 * jLen + _j * 4;\n              data[index] = r;\n              data[index + 1] = g;\n              data[index + 2] = b;\n              data[index + 3] = a;\n            }\n          }\n        }\n      }\n    },\n\n    /**\n     * Indicate when the filter is not gonna apply changes to the image\n     **/\n    isNeutralState: function () {\n      return this.blocksize === 1;\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uBlocksize: gl.getUniformLocation(program, 'uBlocksize'),\n        uStepW: gl.getUniformLocation(program, 'uStepW'),\n        uStepH: gl.getUniformLocation(program, 'uStepH')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      gl.uniform1f(uniformLocations.uBlocksize, this.blocksize);\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Pixelate} Instance of fabric.Image.filters.Pixelate\n   */\n\n  fabric.Image.filters.Pixelate.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      extend = fabric.util.object.extend,\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Remove white filter class\n   * @class fabric.Image.filters.RemoveColor\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.RemoveColor#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.RemoveColor({\n   *   threshold: 0.2,\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   */\n\n  filters.RemoveColor = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.RemoveColor.prototype */\n  {\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'RemoveColor',\n\n    /**\n     * Color to remove, in any format understood by fabric.Color.\n     * @param {String} type\n     * @default\n     */\n    color: '#FFFFFF',\n\n    /**\n     * Fragment source for the brightness program\n     */\n    fragmentSource: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform vec4 uLow;\\n' + 'uniform vec4 uHigh;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'gl_FragColor = texture2D(uTexture, vTexCoord);\\n' + 'if(all(greaterThan(gl_FragColor.rgb,uLow.rgb)) && all(greaterThan(uHigh.rgb,gl_FragColor.rgb))) {\\n' + 'gl_FragColor.a = 0.0;\\n' + '}\\n' + '}',\n\n    /**\n     * distance to actual color, as value up or down from each r,g,b\n     * between 0 and 1\n     **/\n    distance: 0.02,\n\n    /**\n     * For color to remove inside distance, use alpha channel for a smoother deletion\n     * NOT IMPLEMENTED YET\n     **/\n    useAlpha: false,\n\n    /**\n     * Constructor\n     * @memberOf fabric.Image.filters.RemoveWhite.prototype\n     * @param {Object} [options] Options object\n     * @param {Number} [options.color=#RRGGBB] Threshold value\n     * @param {Number} [options.distance=10] Distance value\n     */\n\n    /**\n     * Applies filter to canvas element\n     * @param {Object} canvasEl Canvas element to apply filter to\n     */\n    applyTo2d: function (options) {\n      var imageData = options.imageData,\n          data = imageData.data,\n          i,\n          distance = this.distance * 255,\n          r,\n          g,\n          b,\n          source = new fabric.Color(this.color).getSource(),\n          lowC = [source[0] - distance, source[1] - distance, source[2] - distance],\n          highC = [source[0] + distance, source[1] + distance, source[2] + distance];\n\n      for (i = 0; i < data.length; i += 4) {\n        r = data[i];\n        g = data[i + 1];\n        b = data[i + 2];\n\n        if (r > lowC[0] && g > lowC[1] && b > lowC[2] && r < highC[0] && g < highC[1] && b < highC[2]) {\n          data[i + 3] = 0;\n        }\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uLow: gl.getUniformLocation(program, 'uLow'),\n        uHigh: gl.getUniformLocation(program, 'uHigh')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      var source = new fabric.Color(this.color).getSource(),\n          distance = parseFloat(this.distance),\n          lowC = [0 + source[0] / 255 - distance, 0 + source[1] / 255 - distance, 0 + source[2] / 255 - distance, 1],\n          highC = [source[0] / 255 + distance, source[1] / 255 + distance, source[2] / 255 + distance, 1];\n      gl.uniform4fv(uniformLocations.uLow, lowC);\n      gl.uniform4fv(uniformLocations.uHigh, highC);\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function () {\n      return extend(this.callSuper('toObject'), {\n        color: this.color,\n        distance: this.distance\n      });\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.RemoveColor} Instance of fabric.Image.filters.RemoveWhite\n   */\n\n  fabric.Image.filters.RemoveColor.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  var matrices = {\n    Brownie: [0.59970, 0.34553, -0.27082, 0, 0.186, -0.03770, 0.86095, 0.15059, 0, -0.1449, 0.24113, -0.07441, 0.44972, 0, -0.02965, 0, 0, 0, 1, 0],\n    Vintage: [0.62793, 0.32021, -0.03965, 0, 0.03784, 0.02578, 0.64411, 0.03259, 0, 0.02926, 0.04660, -0.08512, 0.52416, 0, 0.02023, 0, 0, 0, 1, 0],\n    Kodachrome: [1.12855, -0.39673, -0.03992, 0, 0.24991, -0.16404, 1.08352, -0.05498, 0, 0.09698, -0.16786, -0.56034, 1.60148, 0, 0.13972, 0, 0, 0, 1, 0],\n    Technicolor: [1.91252, -0.85453, -0.09155, 0, 0.04624, -0.30878, 1.76589, -0.10601, 0, -0.27589, -0.23110, -0.75018, 1.84759, 0, 0.12137, 0, 0, 0, 1, 0],\n    Polaroid: [1.438, -0.062, -0.062, 0, 0, -0.122, 1.378, -0.122, 0, 0, -0.016, -0.016, 1.483, 0, 0, 0, 0, 0, 1, 0],\n    Sepia: [0.393, 0.769, 0.189, 0, 0, 0.349, 0.686, 0.168, 0, 0, 0.272, 0.534, 0.131, 0, 0, 0, 0, 0, 1, 0],\n    BlackWhite: [1.5, 1.5, 1.5, 0, -1, 1.5, 1.5, 1.5, 0, -1, 1.5, 1.5, 1.5, 0, -1, 0, 0, 0, 1, 0]\n  };\n\n  for (var key in matrices) {\n    filters[key] = createClass(filters.ColorMatrix,\n    /** @lends fabric.Image.filters.Sepia.prototype */\n    {\n      /**\n       * Filter type\n       * @param {String} type\n       * @default\n       */\n      type: key,\n\n      /**\n       * Colormatrix for the effect\n       * array of 20 floats. Numbers in positions 4, 9, 14, 19 loose meaning\n       * outside the -1, 1 range.\n       * @param {Array} matrix array of 20 numbers.\n       * @default\n       */\n      matrix: matrices[key],\n\n      /**\n       * Lock the matrix export for this kind of static, parameter less filters.\n       */\n      mainParameter: false,\n\n      /**\n       * Lock the colormatrix on the color part, skipping alpha\n       */\n      colorsOnly: true\n    });\n    fabric.Image.filters[key].fromObject = fabric.Image.filters.BaseFilter.fromObject;\n  }\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric,\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Color Blend filter class\n   * @class fabric.Image.filter.BlendColor\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @example\n   * var filter = new fabric.Image.filters.BlendColor({\n   *  color: '#000',\n   *  mode: 'multiply'\n   * });\n   *\n   * var filter = new fabric.Image.filters.BlendImage({\n   *  image: fabricImageObject,\n   *  mode: 'multiply',\n   *  alpha: 0.5\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   */\n\n  filters.BlendColor = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.Blend.prototype */\n  {\n    type: 'BlendColor',\n\n    /**\n     * Color to make the blend operation with. default to a reddish color since black or white\n     * gives always strong result.\n     **/\n    color: '#F95C63',\n\n    /**\n     * Blend mode for the filter: one of multiply, add, diff, screen, subtract,\n     * darken, lighten, overlay, exclusion, tint.\n     **/\n    mode: 'multiply',\n\n    /**\n     * alpha value. represent the strength of the blend color operation.\n     **/\n    alpha: 1,\n\n    /**\n     * Fragment source for the Multiply program\n     */\n    fragmentSource: {\n      multiply: 'gl_FragColor.rgb *= uColor.rgb;\\n',\n      screen: 'gl_FragColor.rgb = 1.0 - (1.0 - gl_FragColor.rgb) * (1.0 - uColor.rgb);\\n',\n      add: 'gl_FragColor.rgb += uColor.rgb;\\n',\n      diff: 'gl_FragColor.rgb = abs(gl_FragColor.rgb - uColor.rgb);\\n',\n      subtract: 'gl_FragColor.rgb -= uColor.rgb;\\n',\n      lighten: 'gl_FragColor.rgb = max(gl_FragColor.rgb, uColor.rgb);\\n',\n      darken: 'gl_FragColor.rgb = min(gl_FragColor.rgb, uColor.rgb);\\n',\n      exclusion: 'gl_FragColor.rgb += uColor.rgb - 2.0 * (uColor.rgb * gl_FragColor.rgb);\\n',\n      overlay: 'if (uColor.r < 0.5) {\\n' + 'gl_FragColor.r *= 2.0 * uColor.r;\\n' + '} else {\\n' + 'gl_FragColor.r = 1.0 - 2.0 * (1.0 - gl_FragColor.r) * (1.0 - uColor.r);\\n' + '}\\n' + 'if (uColor.g < 0.5) {\\n' + 'gl_FragColor.g *= 2.0 * uColor.g;\\n' + '} else {\\n' + 'gl_FragColor.g = 1.0 - 2.0 * (1.0 - gl_FragColor.g) * (1.0 - uColor.g);\\n' + '}\\n' + 'if (uColor.b < 0.5) {\\n' + 'gl_FragColor.b *= 2.0 * uColor.b;\\n' + '} else {\\n' + 'gl_FragColor.b = 1.0 - 2.0 * (1.0 - gl_FragColor.b) * (1.0 - uColor.b);\\n' + '}\\n',\n      tint: 'gl_FragColor.rgb *= (1.0 - uColor.a);\\n' + 'gl_FragColor.rgb += uColor.rgb;\\n'\n    },\n\n    /**\n     * build the fragment source for the filters, joining the common part with\n     * the specific one.\n     * @param {String} mode the mode of the filter, a key of this.fragmentSource\n     * @return {String} the source to be compiled\n     * @private\n     */\n    buildSource: function (mode) {\n      return 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform vec4 uColor;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = texture2D(uTexture, vTexCoord);\\n' + 'gl_FragColor = color;\\n' + 'if (color.a > 0.0) {\\n' + this.fragmentSource[mode] + '}\\n' + '}';\n    },\n\n    /**\n     * Retrieves the cached shader.\n     * @param {Object} options\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    retrieveShader: function (options) {\n      var cacheKey = this.type + '_' + this.mode,\n          shaderSource;\n\n      if (!options.programCache.hasOwnProperty(cacheKey)) {\n        shaderSource = this.buildSource(this.mode);\n        options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\n      }\n\n      return options.programCache[cacheKey];\n    },\n\n    /**\n     * Apply the Blend operation to a Uint8ClampedArray representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n     */\n    applyTo2d: function (options) {\n      var imageData = options.imageData,\n          data = imageData.data,\n          iLen = data.length,\n          tr,\n          tg,\n          tb,\n          r,\n          g,\n          b,\n          source,\n          alpha1 = 1 - this.alpha;\n      source = new fabric.Color(this.color).getSource();\n      tr = source[0] * this.alpha;\n      tg = source[1] * this.alpha;\n      tb = source[2] * this.alpha;\n\n      for (var i = 0; i < iLen; i += 4) {\n        r = data[i];\n        g = data[i + 1];\n        b = data[i + 2];\n\n        switch (this.mode) {\n          case 'multiply':\n            data[i] = r * tr / 255;\n            data[i + 1] = g * tg / 255;\n            data[i + 2] = b * tb / 255;\n            break;\n\n          case 'screen':\n            data[i] = 255 - (255 - r) * (255 - tr) / 255;\n            data[i + 1] = 255 - (255 - g) * (255 - tg) / 255;\n            data[i + 2] = 255 - (255 - b) * (255 - tb) / 255;\n            break;\n\n          case 'add':\n            data[i] = r + tr;\n            data[i + 1] = g + tg;\n            data[i + 2] = b + tb;\n            break;\n\n          case 'diff':\n          case 'difference':\n            data[i] = Math.abs(r - tr);\n            data[i + 1] = Math.abs(g - tg);\n            data[i + 2] = Math.abs(b - tb);\n            break;\n\n          case 'subtract':\n            data[i] = r - tr;\n            data[i + 1] = g - tg;\n            data[i + 2] = b - tb;\n            break;\n\n          case 'darken':\n            data[i] = Math.min(r, tr);\n            data[i + 1] = Math.min(g, tg);\n            data[i + 2] = Math.min(b, tb);\n            break;\n\n          case 'lighten':\n            data[i] = Math.max(r, tr);\n            data[i + 1] = Math.max(g, tg);\n            data[i + 2] = Math.max(b, tb);\n            break;\n\n          case 'overlay':\n            data[i] = tr < 128 ? 2 * r * tr / 255 : 255 - 2 * (255 - r) * (255 - tr) / 255;\n            data[i + 1] = tg < 128 ? 2 * g * tg / 255 : 255 - 2 * (255 - g) * (255 - tg) / 255;\n            data[i + 2] = tb < 128 ? 2 * b * tb / 255 : 255 - 2 * (255 - b) * (255 - tb) / 255;\n            break;\n\n          case 'exclusion':\n            data[i] = tr + r - 2 * tr * r / 255;\n            data[i + 1] = tg + g - 2 * tg * g / 255;\n            data[i + 2] = tb + b - 2 * tb * b / 255;\n            break;\n\n          case 'tint':\n            data[i] = tr + r * alpha1;\n            data[i + 1] = tg + g * alpha1;\n            data[i + 2] = tb + b * alpha1;\n        }\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uColor: gl.getUniformLocation(program, 'uColor')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      var source = new fabric.Color(this.color).getSource();\n      source[0] = this.alpha * source[0] / 255;\n      source[1] = this.alpha * source[1] / 255;\n      source[2] = this.alpha * source[2] / 255;\n      source[3] = this.alpha;\n      gl.uniform4fv(uniformLocations.uColor, source);\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function () {\n      return {\n        type: this.type,\n        color: this.color,\n        mode: this.mode,\n        alpha: this.alpha\n      };\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.BlendColor} Instance of fabric.Image.filters.BlendColor\n   */\n\n  fabric.Image.filters.BlendColor.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric,\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Image Blend filter class\n   * @class fabric.Image.filter.BlendImage\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @example\n   * var filter = new fabric.Image.filters.BlendColor({\n   *  color: '#000',\n   *  mode: 'multiply'\n   * });\n   *\n   * var filter = new fabric.Image.filters.BlendImage({\n   *  image: fabricImageObject,\n   *  mode: 'multiply',\n   *  alpha: 0.5\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   */\n\n  filters.BlendImage = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.BlendImage.prototype */\n  {\n    type: 'BlendImage',\n\n    /**\n     * Color to make the blend operation with. default to a reddish color since black or white\n     * gives always strong result.\n     **/\n    image: null,\n\n    /**\n     * Blend mode for the filter: one of multiply, add, diff, screen, subtract,\n     * darken, lighten, overlay, exclusion, tint.\n     **/\n    mode: 'multiply',\n\n    /**\n     * alpha value. represent the strength of the blend image operation.\n     * not implemented.\n     **/\n    alpha: 1,\n    vertexSource: 'attribute vec2 aPosition;\\n' + 'varying vec2 vTexCoord;\\n' + 'varying vec2 vTexCoord2;\\n' + 'uniform mat3 uTransformMatrix;\\n' + 'void main() {\\n' + 'vTexCoord = aPosition;\\n' + 'vTexCoord2 = (uTransformMatrix * vec3(aPosition, 1.0)).xy;\\n' + 'gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\\n' + '}',\n\n    /**\n     * Fragment source for the Multiply program\n     */\n    fragmentSource: {\n      multiply: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform sampler2D uImage;\\n' + 'uniform vec4 uColor;\\n' + 'varying vec2 vTexCoord;\\n' + 'varying vec2 vTexCoord2;\\n' + 'void main() {\\n' + 'vec4 color = texture2D(uTexture, vTexCoord);\\n' + 'vec4 color2 = texture2D(uImage, vTexCoord2);\\n' + 'color.rgba *= color2.rgba;\\n' + 'gl_FragColor = color;\\n' + '}',\n      mask: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform sampler2D uImage;\\n' + 'uniform vec4 uColor;\\n' + 'varying vec2 vTexCoord;\\n' + 'varying vec2 vTexCoord2;\\n' + 'void main() {\\n' + 'vec4 color = texture2D(uTexture, vTexCoord);\\n' + 'vec4 color2 = texture2D(uImage, vTexCoord2);\\n' + 'color.a = color2.a;\\n' + 'gl_FragColor = color;\\n' + '}'\n    },\n\n    /**\n     * Retrieves the cached shader.\n     * @param {Object} options\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    retrieveShader: function (options) {\n      var cacheKey = this.type + '_' + this.mode;\n      var shaderSource = this.fragmentSource[this.mode];\n\n      if (!options.programCache.hasOwnProperty(cacheKey)) {\n        options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\n      }\n\n      return options.programCache[cacheKey];\n    },\n    applyToWebGL: function (options) {\n      // load texture to blend.\n      var gl = options.context,\n          texture = this.createTexture(options.filterBackend, this.image);\n      this.bindAdditionalTexture(gl, texture, gl.TEXTURE1);\n      this.callSuper('applyToWebGL', options);\n      this.unbindAdditionalTexture(gl, gl.TEXTURE1);\n    },\n    createTexture: function (backend, image) {\n      return backend.getCachedTexture(image.cacheKey, image._element);\n    },\n\n    /**\n     * Calculate a transformMatrix to adapt the image to blend over\n     * @param {Object} options\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    calculateMatrix: function () {\n      var image = this.image,\n          width = image._element.width,\n          height = image._element.height;\n      return [1 / image.scaleX, 0, 0, 0, 1 / image.scaleY, 0, -image.left / width, -image.top / height, 1];\n    },\n\n    /**\n     * Apply the Blend operation to a Uint8ClampedArray representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n     */\n    applyTo2d: function (options) {\n      var imageData = options.imageData,\n          resources = options.filterBackend.resources,\n          data = imageData.data,\n          iLen = data.length,\n          width = imageData.width,\n          height = imageData.height,\n          tr,\n          tg,\n          tb,\n          ta,\n          r,\n          g,\n          b,\n          a,\n          canvas1,\n          context,\n          image = this.image,\n          blendData;\n\n      if (!resources.blendImage) {\n        resources.blendImage = fabric.util.createCanvasElement();\n      }\n\n      canvas1 = resources.blendImage;\n      context = canvas1.getContext('2d');\n\n      if (canvas1.width !== width || canvas1.height !== height) {\n        canvas1.width = width;\n        canvas1.height = height;\n      } else {\n        context.clearRect(0, 0, width, height);\n      }\n\n      context.setTransform(image.scaleX, 0, 0, image.scaleY, image.left, image.top);\n      context.drawImage(image._element, 0, 0, width, height);\n      blendData = context.getImageData(0, 0, width, height).data;\n\n      for (var i = 0; i < iLen; i += 4) {\n        r = data[i];\n        g = data[i + 1];\n        b = data[i + 2];\n        a = data[i + 3];\n        tr = blendData[i];\n        tg = blendData[i + 1];\n        tb = blendData[i + 2];\n        ta = blendData[i + 3];\n\n        switch (this.mode) {\n          case 'multiply':\n            data[i] = r * tr / 255;\n            data[i + 1] = g * tg / 255;\n            data[i + 2] = b * tb / 255;\n            data[i + 3] = a * ta / 255;\n            break;\n\n          case 'mask':\n            data[i + 3] = ta;\n            break;\n        }\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uTransformMatrix: gl.getUniformLocation(program, 'uTransformMatrix'),\n        uImage: gl.getUniformLocation(program, 'uImage')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      var matrix = this.calculateMatrix();\n      gl.uniform1i(uniformLocations.uImage, 1); // texture unit 1.\n\n      gl.uniformMatrix3fv(uniformLocations.uTransformMatrix, false, matrix);\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function () {\n      return {\n        type: this.type,\n        image: this.image && this.image.toObject(),\n        mode: this.mode,\n        alpha: this.alpha\n      };\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} callback to be invoked after filter creation\n   * @return {fabric.Image.filters.BlendImage} Instance of fabric.Image.filters.BlendImage\n   */\n\n  fabric.Image.filters.BlendImage.fromObject = function (object, callback) {\n    fabric.Image.fromObject(object.image, function (image) {\n      var options = fabric.util.object.clone(object);\n      options.image = image;\n      callback(new fabric.Image.filters.BlendImage(options));\n    });\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      pow = Math.pow,\n      floor = Math.floor,\n      sqrt = Math.sqrt,\n      abs = Math.abs,\n      round = Math.round,\n      sin = Math.sin,\n      ceil = Math.ceil,\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Resize image filter class\n   * @class fabric.Image.filters.Resize\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Resize();\n   * object.filters.push(filter);\n   * object.applyFilters(canvas.renderAll.bind(canvas));\n   */\n\n  filters.Resize = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.Resize.prototype */\n  {\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Resize',\n\n    /**\n     * Resize type\n     * for webgl resizeType is just lanczos, for canvas2d can be:\n     * bilinear, hermite, sliceHack, lanczos.\n     * @param {String} resizeType\n     * @default\n     */\n    resizeType: 'hermite',\n\n    /**\n     * Scale factor for resizing, x axis\n     * @param {Number} scaleX\n     * @default\n     */\n    scaleX: 1,\n\n    /**\n     * Scale factor for resizing, y axis\n     * @param {Number} scaleY\n     * @default\n     */\n    scaleY: 1,\n\n    /**\n     * LanczosLobes parameter for lanczos filter, valid for resizeType lanczos\n     * @param {Number} lanczosLobes\n     * @default\n     */\n    lanczosLobes: 3,\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uDelta: gl.getUniformLocation(program, 'uDelta'),\n        uTaps: gl.getUniformLocation(program, 'uTaps')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      gl.uniform2fv(uniformLocations.uDelta, this.horizontal ? [1 / this.width, 0] : [0, 1 / this.height]);\n      gl.uniform1fv(uniformLocations.uTaps, this.taps);\n    },\n\n    /**\n     * Retrieves the cached shader.\n     * @param {Object} options\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    retrieveShader: function (options) {\n      var filterWindow = this.getFilterWindow(),\n          cacheKey = this.type + '_' + filterWindow;\n\n      if (!options.programCache.hasOwnProperty(cacheKey)) {\n        var fragmentShader = this.generateShader(filterWindow);\n        options.programCache[cacheKey] = this.createProgram(options.context, fragmentShader);\n      }\n\n      return options.programCache[cacheKey];\n    },\n    getFilterWindow: function () {\n      var scale = this.tempScale;\n      return Math.ceil(this.lanczosLobes / scale);\n    },\n    getTaps: function () {\n      var lobeFunction = this.lanczosCreate(this.lanczosLobes),\n          scale = this.tempScale,\n          filterWindow = this.getFilterWindow(),\n          taps = new Array(filterWindow);\n\n      for (var i = 1; i <= filterWindow; i++) {\n        taps[i - 1] = lobeFunction(i * scale);\n      }\n\n      return taps;\n    },\n\n    /**\n     * Generate vertex and shader sources from the necessary steps numbers\n     * @param {Number} filterWindow\n     */\n    generateShader: function (filterWindow) {\n      var offsets = new Array(filterWindow),\n          fragmentShader = this.fragmentSourceTOP,\n          filterWindow;\n\n      for (var i = 1; i <= filterWindow; i++) {\n        offsets[i - 1] = i + '.0 * uDelta';\n      }\n\n      fragmentShader += 'uniform float uTaps[' + filterWindow + '];\\n';\n      fragmentShader += 'void main() {\\n';\n      fragmentShader += '  vec4 color = texture2D(uTexture, vTexCoord);\\n';\n      fragmentShader += '  float sum = 1.0;\\n';\n      offsets.forEach(function (offset, i) {\n        fragmentShader += '  color += texture2D(uTexture, vTexCoord + ' + offset + ') * uTaps[' + i + '];\\n';\n        fragmentShader += '  color += texture2D(uTexture, vTexCoord - ' + offset + ') * uTaps[' + i + '];\\n';\n        fragmentShader += '  sum += 2.0 * uTaps[' + i + '];\\n';\n      });\n      fragmentShader += '  gl_FragColor = color / sum;\\n';\n      fragmentShader += '}';\n      return fragmentShader;\n    },\n    fragmentSourceTOP: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform vec2 uDelta;\\n' + 'varying vec2 vTexCoord;\\n',\n\n    /**\n     * Apply the resize filter to the image\n     * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\n     *\n     * @param {Object} options\n     * @param {Number} options.passes The number of filters remaining to be executed\n     * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n     * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n     * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    applyTo: function (options) {\n      if (options.webgl) {\n        options.passes++;\n        this.width = options.sourceWidth;\n        this.horizontal = true;\n        this.dW = Math.round(this.width * this.scaleX);\n        this.dH = options.sourceHeight;\n        this.tempScale = this.dW / this.width;\n        this.taps = this.getTaps();\n        options.destinationWidth = this.dW;\n\n        this._setupFrameBuffer(options);\n\n        this.applyToWebGL(options);\n\n        this._swapTextures(options);\n\n        options.sourceWidth = options.destinationWidth;\n        this.height = options.sourceHeight;\n        this.horizontal = false;\n        this.dH = Math.round(this.height * this.scaleY);\n        this.tempScale = this.dH / this.height;\n        this.taps = this.getTaps();\n        options.destinationHeight = this.dH;\n\n        this._setupFrameBuffer(options);\n\n        this.applyToWebGL(options);\n\n        this._swapTextures(options);\n\n        options.sourceHeight = options.destinationHeight;\n      } else {\n        this.applyTo2d(options);\n      }\n    },\n    isNeutralState: function () {\n      return this.scaleX === 1 && this.scaleY === 1;\n    },\n    lanczosCreate: function (lobes) {\n      return function (x) {\n        if (x >= lobes || x <= -lobes) {\n          return 0.0;\n        }\n\n        if (x < 1.19209290E-07 && x > -1.19209290E-07) {\n          return 1.0;\n        }\n\n        x *= Math.PI;\n        var xx = x / lobes;\n        return sin(x) / x * sin(xx) / xx;\n      };\n    },\n\n    /**\n     * Applies filter to canvas element\n     * @memberOf fabric.Image.filters.Resize.prototype\n     * @param {Object} canvasEl Canvas element to apply filter to\n     * @param {Number} scaleX\n     * @param {Number} scaleY\n     */\n    applyTo2d: function (options) {\n      var imageData = options.imageData,\n          scaleX = this.scaleX,\n          scaleY = this.scaleY;\n      this.rcpScaleX = 1 / scaleX;\n      this.rcpScaleY = 1 / scaleY;\n      var oW = imageData.width,\n          oH = imageData.height,\n          dW = round(oW * scaleX),\n          dH = round(oH * scaleY),\n          newData;\n\n      if (this.resizeType === 'sliceHack') {\n        newData = this.sliceByTwo(options, oW, oH, dW, dH);\n      } else if (this.resizeType === 'hermite') {\n        newData = this.hermiteFastResize(options, oW, oH, dW, dH);\n      } else if (this.resizeType === 'bilinear') {\n        newData = this.bilinearFiltering(options, oW, oH, dW, dH);\n      } else if (this.resizeType === 'lanczos') {\n        newData = this.lanczosResize(options, oW, oH, dW, dH);\n      }\n\n      options.imageData = newData;\n    },\n\n    /**\n     * Filter sliceByTwo\n     * @param {Object} canvasEl Canvas element to apply filter to\n     * @param {Number} oW Original Width\n     * @param {Number} oH Original Height\n     * @param {Number} dW Destination Width\n     * @param {Number} dH Destination Height\n     * @returns {ImageData}\n     */\n    sliceByTwo: function (options, oW, oH, dW, dH) {\n      var imageData = options.imageData,\n          mult = 0.5,\n          doneW = false,\n          doneH = false,\n          stepW = oW * mult,\n          stepH = oH * mult,\n          resources = fabric.filterBackend.resources,\n          tmpCanvas,\n          ctx,\n          sX = 0,\n          sY = 0,\n          dX = oW,\n          dY = 0;\n\n      if (!resources.sliceByTwo) {\n        resources.sliceByTwo = document.createElement('canvas');\n      }\n\n      tmpCanvas = resources.sliceByTwo;\n\n      if (tmpCanvas.width < oW * 1.5 || tmpCanvas.height < oH) {\n        tmpCanvas.width = oW * 1.5;\n        tmpCanvas.height = oH;\n      }\n\n      ctx = tmpCanvas.getContext('2d');\n      ctx.clearRect(0, 0, oW * 1.5, oH);\n      ctx.putImageData(imageData, 0, 0);\n      dW = floor(dW);\n      dH = floor(dH);\n\n      while (!doneW || !doneH) {\n        oW = stepW;\n        oH = stepH;\n\n        if (dW < floor(stepW * mult)) {\n          stepW = floor(stepW * mult);\n        } else {\n          stepW = dW;\n          doneW = true;\n        }\n\n        if (dH < floor(stepH * mult)) {\n          stepH = floor(stepH * mult);\n        } else {\n          stepH = dH;\n          doneH = true;\n        }\n\n        ctx.drawImage(tmpCanvas, sX, sY, oW, oH, dX, dY, stepW, stepH);\n        sX = dX;\n        sY = dY;\n        dY += stepH;\n      }\n\n      return ctx.getImageData(sX, sY, dW, dH);\n    },\n\n    /**\n     * Filter lanczosResize\n     * @param {Object} canvasEl Canvas element to apply filter to\n     * @param {Number} oW Original Width\n     * @param {Number} oH Original Height\n     * @param {Number} dW Destination Width\n     * @param {Number} dH Destination Height\n     * @returns {ImageData}\n     */\n    lanczosResize: function (options, oW, oH, dW, dH) {\n      function process(u) {\n        var v, i, weight, idx, a, red, green, blue, alpha, fX, fY;\n        center.x = (u + 0.5) * ratioX;\n        icenter.x = floor(center.x);\n\n        for (v = 0; v < dH; v++) {\n          center.y = (v + 0.5) * ratioY;\n          icenter.y = floor(center.y);\n          a = 0;\n          red = 0;\n          green = 0;\n          blue = 0;\n          alpha = 0;\n\n          for (i = icenter.x - range2X; i <= icenter.x + range2X; i++) {\n            if (i < 0 || i >= oW) {\n              continue;\n            }\n\n            fX = floor(1000 * abs(i - center.x));\n\n            if (!cacheLanc[fX]) {\n              cacheLanc[fX] = {};\n            }\n\n            for (var j = icenter.y - range2Y; j <= icenter.y + range2Y; j++) {\n              if (j < 0 || j >= oH) {\n                continue;\n              }\n\n              fY = floor(1000 * abs(j - center.y));\n\n              if (!cacheLanc[fX][fY]) {\n                cacheLanc[fX][fY] = lanczos(sqrt(pow(fX * rcpRatioX, 2) + pow(fY * rcpRatioY, 2)) / 1000);\n              }\n\n              weight = cacheLanc[fX][fY];\n\n              if (weight > 0) {\n                idx = (j * oW + i) * 4;\n                a += weight;\n                red += weight * srcData[idx];\n                green += weight * srcData[idx + 1];\n                blue += weight * srcData[idx + 2];\n                alpha += weight * srcData[idx + 3];\n              }\n            }\n          }\n\n          idx = (v * dW + u) * 4;\n          destData[idx] = red / a;\n          destData[idx + 1] = green / a;\n          destData[idx + 2] = blue / a;\n          destData[idx + 3] = alpha / a;\n        }\n\n        if (++u < dW) {\n          return process(u);\n        } else {\n          return destImg;\n        }\n      }\n\n      var srcData = options.imageData.data,\n          destImg = options.ctx.createImageData(dW, dH),\n          destData = destImg.data,\n          lanczos = this.lanczosCreate(this.lanczosLobes),\n          ratioX = this.rcpScaleX,\n          ratioY = this.rcpScaleY,\n          rcpRatioX = 2 / this.rcpScaleX,\n          rcpRatioY = 2 / this.rcpScaleY,\n          range2X = ceil(ratioX * this.lanczosLobes / 2),\n          range2Y = ceil(ratioY * this.lanczosLobes / 2),\n          cacheLanc = {},\n          center = {},\n          icenter = {};\n      return process(0);\n    },\n\n    /**\n     * bilinearFiltering\n     * @param {Object} canvasEl Canvas element to apply filter to\n     * @param {Number} oW Original Width\n     * @param {Number} oH Original Height\n     * @param {Number} dW Destination Width\n     * @param {Number} dH Destination Height\n     * @returns {ImageData}\n     */\n    bilinearFiltering: function (options, oW, oH, dW, dH) {\n      var a,\n          b,\n          c,\n          d,\n          x,\n          y,\n          i,\n          j,\n          xDiff,\n          yDiff,\n          chnl,\n          color,\n          offset = 0,\n          origPix,\n          ratioX = this.rcpScaleX,\n          ratioY = this.rcpScaleY,\n          w4 = 4 * (oW - 1),\n          img = options.imageData,\n          pixels = img.data,\n          destImage = options.ctx.createImageData(dW, dH),\n          destPixels = destImage.data;\n\n      for (i = 0; i < dH; i++) {\n        for (j = 0; j < dW; j++) {\n          x = floor(ratioX * j);\n          y = floor(ratioY * i);\n          xDiff = ratioX * j - x;\n          yDiff = ratioY * i - y;\n          origPix = 4 * (y * oW + x);\n\n          for (chnl = 0; chnl < 4; chnl++) {\n            a = pixels[origPix + chnl];\n            b = pixels[origPix + 4 + chnl];\n            c = pixels[origPix + w4 + chnl];\n            d = pixels[origPix + w4 + 4 + chnl];\n            color = a * (1 - xDiff) * (1 - yDiff) + b * xDiff * (1 - yDiff) + c * yDiff * (1 - xDiff) + d * xDiff * yDiff;\n            destPixels[offset++] = color;\n          }\n        }\n      }\n\n      return destImage;\n    },\n\n    /**\n     * hermiteFastResize\n     * @param {Object} canvasEl Canvas element to apply filter to\n     * @param {Number} oW Original Width\n     * @param {Number} oH Original Height\n     * @param {Number} dW Destination Width\n     * @param {Number} dH Destination Height\n     * @returns {ImageData}\n     */\n    hermiteFastResize: function (options, oW, oH, dW, dH) {\n      var ratioW = this.rcpScaleX,\n          ratioH = this.rcpScaleY,\n          ratioWHalf = ceil(ratioW / 2),\n          ratioHHalf = ceil(ratioH / 2),\n          img = options.imageData,\n          data = img.data,\n          img2 = options.ctx.createImageData(dW, dH),\n          data2 = img2.data;\n\n      for (var j = 0; j < dH; j++) {\n        for (var i = 0; i < dW; i++) {\n          var x2 = (i + j * dW) * 4,\n              weight = 0,\n              weights = 0,\n              weightsAlpha = 0,\n              gxR = 0,\n              gxG = 0,\n              gxB = 0,\n              gxA = 0,\n              centerY = (j + 0.5) * ratioH;\n\n          for (var yy = floor(j * ratioH); yy < (j + 1) * ratioH; yy++) {\n            var dy = abs(centerY - (yy + 0.5)) / ratioHHalf,\n                centerX = (i + 0.5) * ratioW,\n                w0 = dy * dy;\n\n            for (var xx = floor(i * ratioW); xx < (i + 1) * ratioW; xx++) {\n              var dx = abs(centerX - (xx + 0.5)) / ratioWHalf,\n                  w = sqrt(w0 + dx * dx);\n              /* eslint-disable max-depth */\n\n              if (w > 1 && w < -1) {\n                continue;\n              } //hermite filter\n\n\n              weight = 2 * w * w * w - 3 * w * w + 1;\n\n              if (weight > 0) {\n                dx = 4 * (xx + yy * oW); //alpha\n\n                gxA += weight * data[dx + 3];\n                weightsAlpha += weight; //colors\n\n                if (data[dx + 3] < 255) {\n                  weight = weight * data[dx + 3] / 250;\n                }\n\n                gxR += weight * data[dx];\n                gxG += weight * data[dx + 1];\n                gxB += weight * data[dx + 2];\n                weights += weight;\n              }\n              /* eslint-enable max-depth */\n\n            }\n          }\n\n          data2[x2] = gxR / weights;\n          data2[x2 + 1] = gxG / weights;\n          data2[x2 + 2] = gxB / weights;\n          data2[x2 + 3] = gxA / weightsAlpha;\n        }\n      }\n\n      return img2;\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function () {\n      return {\n        type: this.type,\n        scaleX: this.scaleX,\n        scaleY: this.scaleY,\n        resizeType: this.resizeType,\n        lanczosLobes: this.lanczosLobes\n      };\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Resize} Instance of fabric.Image.filters.Resize\n   */\n\n  fabric.Image.filters.Resize.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Contrast filter class\n   * @class fabric.Image.filters.Contrast\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Contrast#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Contrast({\n   *   contrast: 0.25\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n\n  filters.Contrast = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.Contrast.prototype */\n  {\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Contrast',\n    fragmentSource: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uContrast;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = texture2D(uTexture, vTexCoord);\\n' + 'float contrastF = 1.015 * (uContrast + 1.0) / (1.0 * (1.015 - uContrast));\\n' + 'color.rgb = contrastF * (color.rgb - 0.5) + 0.5;\\n' + 'gl_FragColor = color;\\n' + '}',\n\n    /**\n     * contrast value, range from -1 to 1.\n     * @param {Number} contrast\n     * @default 0\n     */\n    contrast: 0,\n    mainParameter: 'contrast',\n\n    /**\n     * Constructor\n     * @memberOf fabric.Image.filters.Contrast.prototype\n     * @param {Object} [options] Options object\n     * @param {Number} [options.contrast=0] Value to contrast the image up (-1...1)\n     */\n\n    /**\n      * Apply the Contrast operation to a Uint8Array representing the pixels of an image.\n      *\n      * @param {Object} options\n      * @param {ImageData} options.imageData The Uint8Array to be filtered.\n      */\n    applyTo2d: function (options) {\n      if (this.contrast === 0) {\n        return;\n      }\n\n      var imageData = options.imageData,\n          i,\n          len,\n          data = imageData.data,\n          len = data.length,\n          contrast = Math.floor(this.contrast * 255),\n          contrastF = 259 * (contrast + 255) / (255 * (259 - contrast));\n\n      for (i = 0; i < len; i += 4) {\n        data[i] = contrastF * (data[i] - 128) + 128;\n        data[i + 1] = contrastF * (data[i + 1] - 128) + 128;\n        data[i + 2] = contrastF * (data[i + 2] - 128) + 128;\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uContrast: gl.getUniformLocation(program, 'uContrast')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      gl.uniform1f(uniformLocations.uContrast, this.contrast);\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Contrast} Instance of fabric.Image.filters.Contrast\n   */\n\n  fabric.Image.filters.Contrast.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Saturate filter class\n   * @class fabric.Image.filters.Saturation\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Saturation#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Saturation({\n   *   saturation: 100\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n\n  filters.Saturation = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.Saturation.prototype */\n  {\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Saturation',\n    fragmentSource: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uSaturation;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = texture2D(uTexture, vTexCoord);\\n' + 'float rgMax = max(color.r, color.g);\\n' + 'float rgbMax = max(rgMax, color.b);\\n' + 'color.r += rgbMax != color.r ? (rgbMax - color.r) * uSaturation : 0.00;\\n' + 'color.g += rgbMax != color.g ? (rgbMax - color.g) * uSaturation : 0.00;\\n' + 'color.b += rgbMax != color.b ? (rgbMax - color.b) * uSaturation : 0.00;\\n' + 'gl_FragColor = color;\\n' + '}',\n    saturation: 0,\n    mainParameter: 'saturation',\n\n    /**\n     * Constructor\n     * @memberOf fabric.Image.filters.Saturate.prototype\n     * @param {Object} [options] Options object\n     * @param {Number} [options.saturate=0] Value to saturate the image (-1...1)\n     */\n\n    /**\n     * Apply the Saturation operation to a Uint8ClampedArray representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n     */\n    applyTo2d: function (options) {\n      if (this.saturation === 0) {\n        return;\n      }\n\n      var imageData = options.imageData,\n          data = imageData.data,\n          len = data.length,\n          adjust = -this.saturation,\n          i,\n          max;\n\n      for (i = 0; i < len; i += 4) {\n        max = Math.max(data[i], data[i + 1], data[i + 2]);\n        data[i] += max !== data[i] ? (max - data[i]) * adjust : 0;\n        data[i + 1] += max !== data[i + 1] ? (max - data[i + 1]) * adjust : 0;\n        data[i + 2] += max !== data[i + 2] ? (max - data[i + 2]) * adjust : 0;\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uSaturation: gl.getUniformLocation(program, 'uSaturation')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      gl.uniform1f(uniformLocations.uSaturation, -this.saturation);\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Saturation} Instance of fabric.Image.filters.Saturate\n   */\n\n  fabric.Image.filters.Saturation.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Blur filter class\n   * @class fabric.Image.filters.Blur\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Blur#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Blur({\n   *   blur: 0.5\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   */\n\n  filters.Blur = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.Blur.prototype */\n  {\n    type: 'Blur',\n\n    /*\n    'gl_FragColor = vec4(0.0);',\n    'gl_FragColor += texture2D(texture, vTexCoord + -7 * uDelta)*0.0044299121055113265;',\n    'gl_FragColor += texture2D(texture, vTexCoord + -6 * uDelta)*0.00895781211794;',\n    'gl_FragColor += texture2D(texture, vTexCoord + -5 * uDelta)*0.0215963866053;',\n    'gl_FragColor += texture2D(texture, vTexCoord + -4 * uDelta)*0.0443683338718;',\n    'gl_FragColor += texture2D(texture, vTexCoord + -3 * uDelta)*0.0776744219933;',\n    'gl_FragColor += texture2D(texture, vTexCoord + -2 * uDelta)*0.115876621105;',\n    'gl_FragColor += texture2D(texture, vTexCoord + -1 * uDelta)*0.147308056121;',\n    'gl_FragColor += texture2D(texture, vTexCoord              )*0.159576912161;',\n    'gl_FragColor += texture2D(texture, vTexCoord + 1 * uDelta)*0.147308056121;',\n    'gl_FragColor += texture2D(texture, vTexCoord + 2 * uDelta)*0.115876621105;',\n    'gl_FragColor += texture2D(texture, vTexCoord + 3 * uDelta)*0.0776744219933;',\n    'gl_FragColor += texture2D(texture, vTexCoord + 4 * uDelta)*0.0443683338718;',\n    'gl_FragColor += texture2D(texture, vTexCoord + 5 * uDelta)*0.0215963866053;',\n    'gl_FragColor += texture2D(texture, vTexCoord + 6 * uDelta)*0.00895781211794;',\n    'gl_FragColor += texture2D(texture, vTexCoord + 7 * uDelta)*0.0044299121055113265;',\n    */\n\n    /* eslint-disable max-len */\n    fragmentSource: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform vec2 uDelta;\\n' + 'varying vec2 vTexCoord;\\n' + 'const float nSamples = 15.0;\\n' + 'vec3 v3offset = vec3(12.9898, 78.233, 151.7182);\\n' + 'float random(vec3 scale) {\\n' +\n    /* use the fragment position for a different seed per-pixel */\n    'return fract(sin(dot(gl_FragCoord.xyz, scale)) * 43758.5453);\\n' + '}\\n' + 'void main() {\\n' + 'vec4 color = vec4(0.0);\\n' + 'float total = 0.0;\\n' + 'float offset = random(v3offset);\\n' + 'for (float t = -nSamples; t <= nSamples; t++) {\\n' + 'float percent = (t + offset - 0.5) / nSamples;\\n' + 'float weight = 1.0 - abs(percent);\\n' + 'color += texture2D(uTexture, vTexCoord + uDelta * percent) * weight;\\n' + 'total += weight;\\n' + '}\\n' + 'gl_FragColor = color / total;\\n' + '}',\n\n    /* eslint-enable max-len */\n\n    /**\n     * blur value, in percentage of image dimensions.\n     * specific to keep the image blur constant at different resolutions\n     * range bewteen 0 and 1.\n     */\n    blur: 0,\n    mainParameter: 'blur',\n    applyTo: function (options) {\n      if (options.webgl) {\n        // this aspectRatio is used to give the same blur to vertical and horizontal\n        this.aspectRatio = options.sourceWidth / options.sourceHeight;\n        options.passes++;\n\n        this._setupFrameBuffer(options);\n\n        this.horizontal = true;\n        this.applyToWebGL(options);\n\n        this._swapTextures(options);\n\n        this._setupFrameBuffer(options);\n\n        this.horizontal = false;\n        this.applyToWebGL(options);\n\n        this._swapTextures(options);\n      } else {\n        this.applyTo2d(options);\n      }\n    },\n    applyTo2d: function (options) {\n      // paint canvasEl with current image data.\n      //options.ctx.putImageData(options.imageData, 0, 0);\n      options.imageData = this.simpleBlur(options);\n    },\n    simpleBlur: function (options) {\n      var resources = options.filterBackend.resources,\n          canvas1,\n          canvas2,\n          width = options.imageData.width,\n          height = options.imageData.height;\n\n      if (!resources.blurLayer1) {\n        resources.blurLayer1 = fabric.util.createCanvasElement();\n        resources.blurLayer2 = fabric.util.createCanvasElement();\n      }\n\n      canvas1 = resources.blurLayer1;\n      canvas2 = resources.blurLayer2;\n\n      if (canvas1.width !== width || canvas1.height !== height) {\n        canvas2.width = canvas1.width = width;\n        canvas2.height = canvas1.height = height;\n      }\n\n      var ctx1 = canvas1.getContext('2d'),\n          ctx2 = canvas2.getContext('2d'),\n          nSamples = 15,\n          random,\n          percent,\n          j,\n          i,\n          blur = this.blur * 0.06 * 0.5; // load first canvas\n\n      ctx1.putImageData(options.imageData, 0, 0);\n      ctx2.clearRect(0, 0, width, height);\n\n      for (i = -nSamples; i <= nSamples; i++) {\n        random = (Math.random() - 0.5) / 4;\n        percent = i / nSamples;\n        j = blur * percent * width + random;\n        ctx2.globalAlpha = 1 - Math.abs(percent);\n        ctx2.drawImage(canvas1, j, random);\n        ctx1.drawImage(canvas2, 0, 0);\n        ctx2.globalAlpha = 1;\n        ctx2.clearRect(0, 0, canvas2.width, canvas2.height);\n      }\n\n      for (i = -nSamples; i <= nSamples; i++) {\n        random = (Math.random() - 0.5) / 4;\n        percent = i / nSamples;\n        j = blur * percent * height + random;\n        ctx2.globalAlpha = 1 - Math.abs(percent);\n        ctx2.drawImage(canvas1, random, j);\n        ctx1.drawImage(canvas2, 0, 0);\n        ctx2.globalAlpha = 1;\n        ctx2.clearRect(0, 0, canvas2.width, canvas2.height);\n      }\n\n      options.ctx.drawImage(canvas1, 0, 0);\n      var newImageData = options.ctx.getImageData(0, 0, canvas1.width, canvas1.height);\n      ctx1.globalAlpha = 1;\n      ctx1.clearRect(0, 0, canvas1.width, canvas1.height);\n      return newImageData;\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        delta: gl.getUniformLocation(program, 'uDelta')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      var delta = this.chooseRightDelta();\n      gl.uniform2fv(uniformLocations.delta, delta);\n    },\n\n    /**\n     * choose right value of image percentage to blur with\n     * @returns {Array} a numeric array with delta values\n     */\n    chooseRightDelta: function () {\n      var blurScale = 1,\n          delta = [0, 0],\n          blur;\n\n      if (this.horizontal) {\n        if (this.aspectRatio > 1) {\n          // image is wide, i want to shrink radius horizontal\n          blurScale = 1 / this.aspectRatio;\n        }\n      } else {\n        if (this.aspectRatio < 1) {\n          // image is tall, i want to shrink radius vertical\n          blurScale = this.aspectRatio;\n        }\n      }\n\n      blur = blurScale * this.blur * 0.12;\n\n      if (this.horizontal) {\n        delta[0] = blur;\n      } else {\n        delta[1] = blur;\n      }\n\n      return delta;\n    }\n  });\n  /**\n   * Deserialize a JSON definition of a BlurFilter into a concrete instance.\n   */\n\n  filters.Blur.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * Gamma filter class\n   * @class fabric.Image.filters.Gamma\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Gamma#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Gamma({\n   *   gamma: [1, 0.5, 2.1]\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n\n  filters.Gamma = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.Gamma.prototype */\n  {\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Gamma',\n    fragmentSource: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform vec3 uGamma;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = texture2D(uTexture, vTexCoord);\\n' + 'vec3 correction = (1.0 / uGamma);\\n' + 'color.r = pow(color.r, correction.r);\\n' + 'color.g = pow(color.g, correction.g);\\n' + 'color.b = pow(color.b, correction.b);\\n' + 'gl_FragColor = color;\\n' + 'gl_FragColor.rgb *= color.a;\\n' + '}',\n\n    /**\n     * Gamma array value, from 0.01 to 2.2.\n     * @param {Array} gamma\n     * @default\n     */\n    gamma: [1, 1, 1],\n\n    /**\n     * Describe the property that is the filter parameter\n     * @param {String} m\n     * @default\n     */\n    mainParameter: 'gamma',\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     */\n    initialize: function (options) {\n      this.gamma = [1, 1, 1];\n      filters.BaseFilter.prototype.initialize.call(this, options);\n    },\n\n    /**\n     * Apply the Gamma operation to a Uint8Array representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8Array to be filtered.\n     */\n    applyTo2d: function (options) {\n      var imageData = options.imageData,\n          data = imageData.data,\n          gamma = this.gamma,\n          len = data.length,\n          rInv = 1 / gamma[0],\n          gInv = 1 / gamma[1],\n          bInv = 1 / gamma[2],\n          i;\n\n      if (!this.rVals) {\n        // eslint-disable-next-line\n        this.rVals = new Uint8Array(256); // eslint-disable-next-line\n\n        this.gVals = new Uint8Array(256); // eslint-disable-next-line\n\n        this.bVals = new Uint8Array(256);\n      } // This is an optimization - pre-compute a look-up table for each color channel\n      // instead of performing these pow calls for each pixel in the image.\n\n\n      for (i = 0, len = 256; i < len; i++) {\n        this.rVals[i] = Math.pow(i / 255, rInv) * 255;\n        this.gVals[i] = Math.pow(i / 255, gInv) * 255;\n        this.bVals[i] = Math.pow(i / 255, bInv) * 255;\n      }\n\n      for (i = 0, len = data.length; i < len; i += 4) {\n        data[i] = this.rVals[data[i]];\n        data[i + 1] = this.gVals[data[i + 1]];\n        data[i + 2] = this.bVals[data[i + 2]];\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function (gl, program) {\n      return {\n        uGamma: gl.getUniformLocation(program, 'uGamma')\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function (gl, uniformLocations) {\n      gl.uniform3fv(uniformLocations.uGamma, this.gamma);\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Gamma} Instance of fabric.Image.filters.Gamma\n   */\n\n  fabric.Image.filters.Gamma.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * A container class that knows how to apply a sequence of filters to an input image.\n   */\n\n  filters.Composed = createClass(filters.BaseFilter,\n  /** @lends fabric.Image.filters.Composed.prototype */\n  {\n    type: 'Composed',\n\n    /**\n     * A non sparse array of filters to apply\n     */\n    subFilters: [],\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     */\n    initialize: function (options) {\n      this.callSuper('initialize', options); // create a new array instead mutating the prototype with push\n\n      this.subFilters = this.subFilters.slice(0);\n    },\n\n    /**\n     * Apply this container's filters to the input image provided.\n     *\n     * @param {Object} options\n     * @param {Number} options.passes The number of filters remaining to be applied.\n     */\n    applyTo: function (options) {\n      options.passes += this.subFilters.length - 1;\n      this.subFilters.forEach(function (filter) {\n        filter.applyTo(options);\n      });\n    },\n\n    /**\n     * Serialize this filter into JSON.\n     *\n     * @returns {Object} A JSON representation of this filter.\n     */\n    toObject: function () {\n      return fabric.util.object.extend(this.callSuper('toObject'), {\n        subFilters: this.subFilters.map(function (filter) {\n          return filter.toObject();\n        })\n      });\n    },\n    isNeutralState: function () {\n      return !this.subFilters.some(function (filter) {\n        return !filter.isNeutralState();\n      });\n    }\n  });\n  /**\n   * Deserialize a JSON definition of a ComposedFilter into a concrete instance.\n   */\n\n  fabric.Image.filters.Composed.fromObject = function (object, callback) {\n    var filters = object.subFilters || [],\n        subFilters = filters.map(function (filter) {\n      return new fabric.Image.filters[filter.type](filter);\n    }),\n        instance = new fabric.Image.filters.Composed({\n      subFilters: subFilters\n    });\n    callback && callback(instance);\n    return instance;\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n  /**\n   * HueRotation filter class\n   * @class fabric.Image.filters.HueRotation\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.HueRotation#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.HueRotation({\n   *   rotation: -0.5\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n\n  filters.HueRotation = createClass(filters.ColorMatrix,\n  /** @lends fabric.Image.filters.HueRotation.prototype */\n  {\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'HueRotation',\n\n    /**\n     * HueRotation value, from -1 to 1.\n     * the unit is radians\n     * @param {Number} myParameter\n     * @default\n     */\n    rotation: 0,\n\n    /**\n     * Describe the property that is the filter parameter\n     * @param {String} m\n     * @default\n     */\n    mainParameter: 'rotation',\n    calculateMatrix: function () {\n      var rad = this.rotation * Math.PI,\n          cos = fabric.util.cos(rad),\n          sin = fabric.util.sin(rad),\n          aThird = 1 / 3,\n          aThirdSqtSin = Math.sqrt(aThird) * sin,\n          OneMinusCos = 1 - cos;\n      this.matrix = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0];\n      this.matrix[0] = cos + OneMinusCos / 3;\n      this.matrix[1] = aThird * OneMinusCos - aThirdSqtSin;\n      this.matrix[2] = aThird * OneMinusCos + aThirdSqtSin;\n      this.matrix[5] = aThird * OneMinusCos + aThirdSqtSin;\n      this.matrix[6] = cos + aThird * OneMinusCos;\n      this.matrix[7] = aThird * OneMinusCos - aThirdSqtSin;\n      this.matrix[10] = aThird * OneMinusCos - aThirdSqtSin;\n      this.matrix[11] = aThird * OneMinusCos + aThirdSqtSin;\n      this.matrix[12] = cos + aThird * OneMinusCos;\n    },\n\n    /**\n     * HueRotation isNeutralState implementation\n     * Used only in image applyFilters to discard filters that will not have an effect\n     * on the image\n     * @param {Object} options\n     **/\n    isNeutralState: function (options) {\n      this.calculateMatrix();\n      return filters.BaseFilter.prototype.isNeutralState.call(this, options);\n    },\n\n    /**\n     * Apply this filter to the input image data provided.\n     *\n     * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\n     *\n     * @param {Object} options\n     * @param {Number} options.passes The number of filters remaining to be executed\n     * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n     * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n     * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    applyTo: function (options) {\n      this.calculateMatrix();\n      filters.BaseFilter.prototype.applyTo.call(this, options);\n    }\n  });\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.HueRotation} Instance of fabric.Image.filters.HueRotation\n   */\n\n  fabric.Image.filters.HueRotation.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {}),\n      clone = fabric.util.object.clone;\n\n  if (fabric.Text) {\n    fabric.warn('fabric.Text is already defined');\n    return;\n  }\n  /**\n   * Text class\n   * @class fabric.Text\n   * @extends fabric.Object\n   * @return {fabric.Text} thisArg\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#text}\n   * @see {@link fabric.Text#initialize} for constructor definition\n   */\n\n\n  fabric.Text = fabric.util.createClass(fabric.Object,\n  /** @lends fabric.Text.prototype */\n  {\n    /**\n     * Properties which when set cause object to change dimensions\n     * @type Array\n     * @private\n     */\n    _dimensionAffectingProps: ['fontSize', 'fontWeight', 'fontFamily', 'fontStyle', 'lineHeight', 'text', 'charSpacing', 'textAlign', 'styles'],\n\n    /**\n     * @private\n     */\n    _reNewline: /\\r?\\n/,\n\n    /**\n     * Use this regular expression to filter for whitespaces that is not a new line.\n     * Mostly used when text is 'justify' aligned.\n     * @private\n     */\n    _reSpacesAndTabs: /[ \\t\\r]/g,\n\n    /**\n     * Use this regular expression to filter for whitespace that is not a new line.\n     * Mostly used when text is 'justify' aligned.\n     * @private\n     */\n    _reSpaceAndTab: /[ \\t\\r]/,\n\n    /**\n     * Use this regular expression to filter consecutive groups of non spaces.\n     * Mostly used when text is 'justify' aligned.\n     * @private\n     */\n    _reWords: /\\S+/g,\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'text',\n\n    /**\n     * Font size (in pixels)\n     * @type Number\n     * @default\n     */\n    fontSize: 40,\n\n    /**\n     * Font weight (e.g. bold, normal, 400, 600, 800)\n     * @type {(Number|String)}\n     * @default\n     */\n    fontWeight: 'normal',\n\n    /**\n     * Font family\n     * @type String\n     * @default\n     */\n    fontFamily: 'Times New Roman',\n\n    /**\n     * Text decoration underline.\n     * @type Boolean\n     * @default\n     */\n    underline: false,\n\n    /**\n     * Text decoration overline.\n     * @type Boolean\n     * @default\n     */\n    overline: false,\n\n    /**\n     * Text decoration linethrough.\n     * @type Boolean\n     * @default\n     */\n    linethrough: false,\n\n    /**\n     * Text alignment. Possible values: \"left\", \"center\", \"right\", \"justify\",\n     * \"justify-left\", \"justify-center\" or \"justify-right\".\n     * @type String\n     * @default\n     */\n    textAlign: 'left',\n\n    /**\n     * Font style . Possible values: \"\", \"normal\", \"italic\" or \"oblique\".\n     * @type String\n     * @default\n     */\n    fontStyle: 'normal',\n\n    /**\n     * Line height\n     * @type Number\n     * @default\n     */\n    lineHeight: 1.16,\n\n    /**\n     * Superscript schema object (minimum overlap)\n     * @type {Object}\n     * @default\n     */\n    superscript: {\n      size: 0.60,\n      // fontSize factor\n      baseline: -0.35 // baseline-shift factor (upwards)\n\n    },\n\n    /**\n     * Subscript schema object (minimum overlap)\n     * @type {Object}\n     * @default\n     */\n    subscript: {\n      size: 0.60,\n      // fontSize factor\n      baseline: 0.11 // baseline-shift factor (downwards)\n\n    },\n\n    /**\n     * Background color of text lines\n     * @type String\n     * @default\n     */\n    textBackgroundColor: '',\n\n    /**\n     * List of properties to consider when checking if\n     * state of an object is changed ({@link fabric.Object#hasStateChanged})\n     * as well as for history (undo/redo) purposes\n     * @type Array\n     */\n    stateProperties: fabric.Object.prototype.stateProperties.concat('fontFamily', 'fontWeight', 'fontSize', 'text', 'underline', 'overline', 'linethrough', 'textAlign', 'fontStyle', 'lineHeight', 'textBackgroundColor', 'charSpacing', 'styles'),\n\n    /**\n     * List of properties to consider when checking if cache needs refresh\n     * @type Array\n     */\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('fontFamily', 'fontWeight', 'fontSize', 'text', 'underline', 'overline', 'linethrough', 'textAlign', 'fontStyle', 'lineHeight', 'textBackgroundColor', 'charSpacing', 'styles'),\n\n    /**\n     * When defined, an object is rendered via stroke and this property specifies its color.\n     * <b>Backwards incompatibility note:</b> This property was named \"strokeStyle\" until v1.1.6\n     * @type String\n     * @default\n     */\n    stroke: null,\n\n    /**\n     * Shadow object representing shadow of this shape.\n     * <b>Backwards incompatibility note:</b> This property was named \"textShadow\" (String) until v1.2.11\n     * @type fabric.Shadow\n     * @default\n     */\n    shadow: null,\n\n    /**\n     * @private\n     */\n    _fontSizeFraction: 0.222,\n\n    /**\n     * @private\n     */\n    offsets: {\n      underline: 0.10,\n      linethrough: -0.315,\n      overline: -0.88\n    },\n\n    /**\n     * Text Line proportion to font Size (in pixels)\n     * @type Number\n     * @default\n     */\n    _fontSizeMult: 1.13,\n\n    /**\n     * additional space between characters\n     * expressed in thousands of em unit\n     * @type Number\n     * @default\n     */\n    charSpacing: 0,\n\n    /**\n     * Object containing character styles - top-level properties -> line numbers,\n     * 2nd-level properties - charater numbers\n     * @type Object\n     * @default\n     */\n    styles: null,\n\n    /**\n     * Reference to a context to measure text char or couple of chars\n     * the cacheContext of the canvas will be used or a freshly created one if the object is not on canvas\n     * once created it will be referenced on fabric._measuringContext to avoide creating a canvas for every\n     * text object created.\n     * @type {CanvasRenderingContext2D}\n     * @default\n     */\n    _measuringContext: null,\n\n    /**\n     * Baseline shift, stlyes only, keep at 0 for the main text object\n     * @type {Number}\n     * @default\n     */\n    deltaY: 0,\n\n    /**\n     * Array of properties that define a style unit (of 'styles').\n     * @type {Array}\n     * @default\n     */\n    _styleProperties: ['stroke', 'strokeWidth', 'fill', 'fontFamily', 'fontSize', 'fontWeight', 'fontStyle', 'underline', 'overline', 'linethrough', 'deltaY', 'textBackgroundColor'],\n\n    /**\n     * contains characters bounding boxes\n     */\n    __charBounds: [],\n\n    /**\n     * use this size when measuring text. To avoid IE11 rounding errors\n     * @type {Number}\n     * @default\n     * @readonly\n     * @private\n     */\n    CACHE_FONT_SIZE: 400,\n\n    /**\n     * contains the min text width to avoid getting 0\n     * @type {Number}\n     * @default\n     */\n    MIN_TEXT_WIDTH: 2,\n\n    /**\n     * Constructor\n     * @param {String} text Text string\n     * @param {Object} [options] Options object\n     * @return {fabric.Text} thisArg\n     */\n    initialize: function (text, options) {\n      this.styles = options ? options.styles || {} : {};\n      this.text = text;\n      this.__skipDimension = true;\n      this.callSuper('initialize', options);\n      this.__skipDimension = false;\n      this.initDimensions();\n      this.setCoords();\n      this.setupState({\n        propertySet: '_dimensionAffectingProps'\n      });\n    },\n\n    /**\n     * Return a contex for measurement of text string.\n     * if created it gets stored for reuse\n     * @param {String} text Text string\n     * @param {Object} [options] Options object\n     * @return {fabric.Text} thisArg\n     */\n    getMeasuringContext: function () {\n      // if we did not return we have to measure something.\n      if (!fabric._measuringContext) {\n        fabric._measuringContext = this.canvas && this.canvas.contextCache || fabric.util.createCanvasElement().getContext('2d');\n      }\n\n      return fabric._measuringContext;\n    },\n\n    /**\n     * @private\n     * Divides text into lines of text and lines of graphemes.\n     */\n    _splitText: function () {\n      var newLines = this._splitTextIntoLines(this.text);\n\n      this.textLines = newLines.lines;\n      this._textLines = newLines.graphemeLines;\n      this._unwrappedTextLines = newLines._unwrappedLines;\n      this._text = newLines.graphemeText;\n      return newLines;\n    },\n\n    /**\n     * Initialize or update text dimensions.\n     * Updates this.width and this.height with the proper values.\n     * Does not return dimensions.\n     */\n    initDimensions: function () {\n      if (this.__skipDimension) {\n        return;\n      }\n\n      this._splitText();\n\n      this._clearCache();\n\n      this.width = this.calcTextWidth() || this.cursorWidth || this.MIN_TEXT_WIDTH;\n\n      if (this.textAlign.indexOf('justify') !== -1) {\n        // once text is measured we need to make space fatter to make justified text.\n        this.enlargeSpaces();\n      }\n\n      this.height = this.calcTextHeight();\n      this.saveState({\n        propertySet: '_dimensionAffectingProps'\n      });\n    },\n\n    /**\n     * Enlarge space boxes and shift the others\n     */\n    enlargeSpaces: function () {\n      var diffSpace, currentLineWidth, numberOfSpaces, accumulatedSpace, line, charBound, spaces;\n\n      for (var i = 0, len = this._textLines.length; i < len; i++) {\n        if (this.textAlign !== 'justify' && (i === len - 1 || this.isEndOfWrapping(i))) {\n          continue;\n        }\n\n        accumulatedSpace = 0;\n        line = this._textLines[i];\n        currentLineWidth = this.getLineWidth(i);\n\n        if (currentLineWidth < this.width && (spaces = this.textLines[i].match(this._reSpacesAndTabs))) {\n          numberOfSpaces = spaces.length;\n          diffSpace = (this.width - currentLineWidth) / numberOfSpaces;\n\n          for (var j = 0, jlen = line.length; j <= jlen; j++) {\n            charBound = this.__charBounds[i][j];\n\n            if (this._reSpaceAndTab.test(line[j])) {\n              charBound.width += diffSpace;\n              charBound.kernedWidth += diffSpace;\n              charBound.left += accumulatedSpace;\n              accumulatedSpace += diffSpace;\n            } else {\n              charBound.left += accumulatedSpace;\n            }\n          }\n        }\n      }\n    },\n\n    /**\n     * Detect if the text line is ended with an hard break\n     * text and itext do not have wrapping, return false\n     * @return {Boolean}\n     */\n    isEndOfWrapping: function (lineIndex) {\n      return lineIndex === this._textLines.length - 1;\n    },\n\n    /**\n     * Detect if a line has a linebreak and so we need to account for it when moving\n     * and counting style.\n     * It return always for text and Itext.\n     * @return Number\n     */\n    missingNewlineOffset: function () {\n      return 1;\n    },\n\n    /**\n     * Returns string representation of an instance\n     * @return {String} String representation of text object\n     */\n    toString: function () {\n      return '#<fabric.Text (' + this.complexity() + '): { \"text\": \"' + this.text + '\", \"fontFamily\": \"' + this.fontFamily + '\" }>';\n    },\n\n    /**\n     * Return the dimension and the zoom level needed to create a cache canvas\n     * big enough to host the object to be cached.\n     * @private\n     * @param {Object} dim.x width of object to be cached\n     * @param {Object} dim.y height of object to be cached\n     * @return {Object}.width width of canvas\n     * @return {Object}.height height of canvas\n     * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\n     * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\n     */\n    _getCacheCanvasDimensions: function () {\n      var dims = this.callSuper('_getCacheCanvasDimensions');\n      var fontSize = this.fontSize;\n      dims.width += fontSize * dims.zoomX;\n      dims.height += fontSize * dims.zoomY;\n      return dims;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function (ctx) {\n      this._setTextStyles(ctx);\n\n      this._renderTextLinesBackground(ctx);\n\n      this._renderTextDecoration(ctx, 'underline');\n\n      this._renderText(ctx);\n\n      this._renderTextDecoration(ctx, 'overline');\n\n      this._renderTextDecoration(ctx, 'linethrough');\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderText: function (ctx) {\n      if (this.paintFirst === 'stroke') {\n        this._renderTextStroke(ctx);\n\n        this._renderTextFill(ctx);\n      } else {\n        this._renderTextFill(ctx);\n\n        this._renderTextStroke(ctx);\n      }\n    },\n\n    /**\n     * Set the font parameter of the context with the object properties or with charStyle\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Object} [charStyle] object with font style properties\n     * @param {String} [charStyle.fontFamily] Font Family\n     * @param {Number} [charStyle.fontSize] Font size in pixels. ( without px suffix )\n     * @param {String} [charStyle.fontWeight] Font weight\n     * @param {String} [charStyle.fontStyle] Font style (italic|normal)\n     */\n    _setTextStyles: function (ctx, charStyle, forMeasuring) {\n      ctx.textBaseline = 'alphabetic';\n      ctx.font = this._getFontDeclaration(charStyle, forMeasuring);\n    },\n\n    /**\n     * calculate and return the text Width measuring each line.\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @return {Number} Maximum width of fabric.Text object\n     */\n    calcTextWidth: function () {\n      var maxWidth = this.getLineWidth(0);\n\n      for (var i = 1, len = this._textLines.length; i < len; i++) {\n        var currentLineWidth = this.getLineWidth(i);\n\n        if (currentLineWidth > maxWidth) {\n          maxWidth = currentLineWidth;\n        }\n      }\n\n      return maxWidth;\n    },\n\n    /**\n     * @private\n     * @param {String} method Method name (\"fillText\" or \"strokeText\")\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {String} line Text to render\n     * @param {Number} left Left position of text\n     * @param {Number} top Top position of text\n     * @param {Number} lineIndex Index of a line in a text\n     */\n    _renderTextLine: function (method, ctx, line, left, top, lineIndex) {\n      this._renderChars(method, ctx, line, left, top, lineIndex);\n    },\n\n    /**\n     * Renders the text background for lines, taking care of style\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderTextLinesBackground: function (ctx) {\n      if (!this.textBackgroundColor && !this.styleHas('textBackgroundColor')) {\n        return;\n      }\n\n      var lineTopOffset = 0,\n          heightOfLine,\n          lineLeftOffset,\n          originalFill = ctx.fillStyle,\n          line,\n          lastColor,\n          leftOffset = this._getLeftOffset(),\n          topOffset = this._getTopOffset(),\n          boxStart = 0,\n          boxWidth = 0,\n          charBox,\n          currentColor;\n\n      for (var i = 0, len = this._textLines.length; i < len; i++) {\n        heightOfLine = this.getHeightOfLine(i);\n\n        if (!this.textBackgroundColor && !this.styleHas('textBackgroundColor', i)) {\n          lineTopOffset += heightOfLine;\n          continue;\n        }\n\n        line = this._textLines[i];\n        lineLeftOffset = this._getLineLeftOffset(i);\n        boxWidth = 0;\n        boxStart = 0;\n        lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\n\n        for (var j = 0, jlen = line.length; j < jlen; j++) {\n          charBox = this.__charBounds[i][j];\n          currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\n\n          if (currentColor !== lastColor) {\n            ctx.fillStyle = lastColor;\n            lastColor && ctx.fillRect(leftOffset + lineLeftOffset + boxStart, topOffset + lineTopOffset, boxWidth, heightOfLine / this.lineHeight);\n            boxStart = charBox.left;\n            boxWidth = charBox.width;\n            lastColor = currentColor;\n          } else {\n            boxWidth += charBox.kernedWidth;\n          }\n        }\n\n        if (currentColor) {\n          ctx.fillStyle = currentColor;\n          ctx.fillRect(leftOffset + lineLeftOffset + boxStart, topOffset + lineTopOffset, boxWidth, heightOfLine / this.lineHeight);\n        }\n\n        lineTopOffset += heightOfLine;\n      }\n\n      ctx.fillStyle = originalFill; // if there is text background color no\n      // other shadows should be casted\n\n      this._removeShadow(ctx);\n    },\n\n    /**\n     * @private\n     * @param {Object} decl style declaration for cache\n     * @param {String} decl.fontFamily fontFamily\n     * @param {String} decl.fontStyle fontStyle\n     * @param {String} decl.fontWeight fontWeight\n     * @return {Object} reference to cache\n     */\n    getFontCache: function (decl) {\n      var fontFamily = decl.fontFamily.toLowerCase();\n\n      if (!fabric.charWidthsCache[fontFamily]) {\n        fabric.charWidthsCache[fontFamily] = {};\n      }\n\n      var cache = fabric.charWidthsCache[fontFamily],\n          cacheProp = decl.fontStyle.toLowerCase() + '_' + (decl.fontWeight + '').toLowerCase();\n\n      if (!cache[cacheProp]) {\n        cache[cacheProp] = {};\n      }\n\n      return cache[cacheProp];\n    },\n\n    /**\n     * apply all the character style to canvas for rendering\n     * @private\n     * @param {String} _char\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @param {Object} [decl]\n     */\n    _applyCharStyles: function (method, ctx, lineIndex, charIndex, styleDeclaration) {\n      this._setFillStyles(ctx, styleDeclaration);\n\n      this._setStrokeStyles(ctx, styleDeclaration);\n\n      ctx.font = this._getFontDeclaration(styleDeclaration);\n    },\n\n    /**\n     * measure and return the width of a single character.\n     * possibly overridden to accommodate different measure logic or\n     * to hook some external lib for character measurement\n     * @private\n     * @param {String} _char, char to be measured\n     * @param {Object} charStyle style of char to be measured\n     * @param {String} [previousChar] previous char\n     * @param {Object} [prevCharStyle] style of previous char\n     */\n    _measureChar: function (_char, charStyle, previousChar, prevCharStyle) {\n      // first i try to return from cache\n      var fontCache = this.getFontCache(charStyle),\n          fontDeclaration = this._getFontDeclaration(charStyle),\n          previousFontDeclaration = this._getFontDeclaration(prevCharStyle),\n          couple = previousChar + _char,\n          stylesAreEqual = fontDeclaration === previousFontDeclaration,\n          width,\n          coupleWidth,\n          previousWidth,\n          fontMultiplier = charStyle.fontSize / this.CACHE_FONT_SIZE,\n          kernedWidth;\n\n      if (previousChar && fontCache[previousChar] !== undefined) {\n        previousWidth = fontCache[previousChar];\n      }\n\n      if (fontCache[_char] !== undefined) {\n        kernedWidth = width = fontCache[_char];\n      }\n\n      if (stylesAreEqual && fontCache[couple] !== undefined) {\n        coupleWidth = fontCache[couple];\n        kernedWidth = coupleWidth - previousWidth;\n      }\n\n      if (width === undefined || previousWidth === undefined || coupleWidth === undefined) {\n        var ctx = this.getMeasuringContext(); // send a TRUE to specify measuring font size CACHE_FONT_SIZE\n\n        this._setTextStyles(ctx, charStyle, true);\n      }\n\n      if (width === undefined) {\n        kernedWidth = width = ctx.measureText(_char).width;\n        fontCache[_char] = width;\n      }\n\n      if (previousWidth === undefined && stylesAreEqual && previousChar) {\n        previousWidth = ctx.measureText(previousChar).width;\n        fontCache[previousChar] = previousWidth;\n      }\n\n      if (stylesAreEqual && coupleWidth === undefined) {\n        // we can measure the kerning couple and subtract the width of the previous character\n        coupleWidth = ctx.measureText(couple).width;\n        fontCache[couple] = coupleWidth;\n        kernedWidth = coupleWidth - previousWidth;\n      }\n\n      return {\n        width: width * fontMultiplier,\n        kernedWidth: kernedWidth * fontMultiplier\n      };\n    },\n\n    /**\n     * Computes height of character at given position\n     * @param {Number} line the line index number\n     * @param {Number} _char the character index number\n     * @return {Number} fontSize of the character\n     */\n    getHeightOfChar: function (line, _char) {\n      return this.getValueOfPropertyAt(line, _char, 'fontSize');\n    },\n\n    /**\n     * measure a text line measuring all characters.\n     * @param {Number} lineIndex line number\n     * @return {Number} Line width\n     */\n    measureLine: function (lineIndex) {\n      var lineInfo = this._measureLine(lineIndex);\n\n      if (this.charSpacing !== 0) {\n        lineInfo.width -= this._getWidthOfCharSpacing();\n      }\n\n      if (lineInfo.width < 0) {\n        lineInfo.width = 0;\n      }\n\n      return lineInfo;\n    },\n\n    /**\n     * measure every grapheme of a line, populating __charBounds\n     * @param {Number} lineIndex\n     * @return {Object} object.width total width of characters\n     * @return {Object} object.widthOfSpaces length of chars that match this._reSpacesAndTabs\n     */\n    _measureLine: function (lineIndex) {\n      var width = 0,\n          i,\n          grapheme,\n          line = this._textLines[lineIndex],\n          prevGrapheme,\n          graphemeInfo,\n          numOfSpaces = 0,\n          lineBounds = new Array(line.length);\n      this.__charBounds[lineIndex] = lineBounds;\n\n      for (i = 0; i < line.length; i++) {\n        grapheme = line[i];\n        graphemeInfo = this._getGraphemeBox(grapheme, lineIndex, i, prevGrapheme);\n        lineBounds[i] = graphemeInfo;\n        width += graphemeInfo.kernedWidth;\n        prevGrapheme = grapheme;\n      } // this latest bound box represent the last character of the line\n      // to simplify cursor handling in interactive mode.\n\n\n      lineBounds[i] = {\n        left: graphemeInfo ? graphemeInfo.left + graphemeInfo.width : 0,\n        width: 0,\n        kernedWidth: 0,\n        height: this.fontSize\n      };\n      return {\n        width: width,\n        numOfSpaces: numOfSpaces\n      };\n    },\n\n    /**\n     * Measure and return the info of a single grapheme.\n     * needs the the info of previous graphemes already filled\n     * @private\n     * @param {String} grapheme to be measured\n     * @param {Number} lineIndex index of the line where the char is\n     * @param {Number} charIndex position in the line\n     * @param {String} [prevGrapheme] character preceding the one to be measured\n     */\n    _getGraphemeBox: function (grapheme, lineIndex, charIndex, prevGrapheme, skipLeft) {\n      var style = this.getCompleteStyleDeclaration(lineIndex, charIndex),\n          prevStyle = prevGrapheme ? this.getCompleteStyleDeclaration(lineIndex, charIndex - 1) : {},\n          info = this._measureChar(grapheme, style, prevGrapheme, prevStyle),\n          kernedWidth = info.kernedWidth,\n          width = info.width,\n          charSpacing;\n\n      if (this.charSpacing !== 0) {\n        charSpacing = this._getWidthOfCharSpacing();\n        width += charSpacing;\n        kernedWidth += charSpacing;\n      }\n\n      var box = {\n        width: width,\n        left: 0,\n        height: style.fontSize,\n        kernedWidth: kernedWidth,\n        deltaY: style.deltaY\n      };\n\n      if (charIndex > 0 && !skipLeft) {\n        var previousBox = this.__charBounds[lineIndex][charIndex - 1];\n        box.left = previousBox.left + previousBox.width + info.kernedWidth - info.width;\n      }\n\n      return box;\n    },\n\n    /**\n     * Calculate height of line at 'lineIndex'\n     * @param {Number} lineIndex index of line to calculate\n     * @return {Number}\n     */\n    getHeightOfLine: function (lineIndex) {\n      if (this.__lineHeights[lineIndex]) {\n        return this.__lineHeights[lineIndex];\n      }\n\n      var line = this._textLines[lineIndex],\n          // char 0 is measured before the line cycle because it nneds to char\n      // emptylines\n      maxHeight = this.getHeightOfChar(lineIndex, 0);\n\n      for (var i = 1, len = line.length; i < len; i++) {\n        maxHeight = Math.max(this.getHeightOfChar(lineIndex, i), maxHeight);\n      }\n\n      return this.__lineHeights[lineIndex] = maxHeight * this.lineHeight * this._fontSizeMult;\n    },\n\n    /**\n     * Calculate text box height\n     */\n    calcTextHeight: function () {\n      var lineHeight,\n          height = 0;\n\n      for (var i = 0, len = this._textLines.length; i < len; i++) {\n        lineHeight = this.getHeightOfLine(i);\n        height += i === len - 1 ? lineHeight / this.lineHeight : lineHeight;\n      }\n\n      return height;\n    },\n\n    /**\n     * @private\n     * @return {Number} Left offset\n     */\n    _getLeftOffset: function () {\n      return -this.width / 2;\n    },\n\n    /**\n     * @private\n     * @return {Number} Top offset\n     */\n    _getTopOffset: function () {\n      return -this.height / 2;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {String} method Method name (\"fillText\" or \"strokeText\")\n     */\n    _renderTextCommon: function (ctx, method) {\n      ctx.save();\n\n      var lineHeights = 0,\n          left = this._getLeftOffset(),\n          top = this._getTopOffset(),\n          offsets = this._applyPatternGradientTransform(ctx, method === 'fillText' ? this.fill : this.stroke);\n\n      for (var i = 0, len = this._textLines.length; i < len; i++) {\n        var heightOfLine = this.getHeightOfLine(i),\n            maxHeight = heightOfLine / this.lineHeight,\n            leftOffset = this._getLineLeftOffset(i);\n\n        this._renderTextLine(method, ctx, this._textLines[i], left + leftOffset - offsets.offsetX, top + lineHeights + maxHeight - offsets.offsetY, i);\n\n        lineHeights += heightOfLine;\n      }\n\n      ctx.restore();\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderTextFill: function (ctx) {\n      if (!this.fill && !this.styleHas('fill')) {\n        return;\n      }\n\n      this._renderTextCommon(ctx, 'fillText');\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderTextStroke: function (ctx) {\n      if ((!this.stroke || this.strokeWidth === 0) && this.isEmptyStyles()) {\n        return;\n      }\n\n      if (this.shadow && !this.shadow.affectStroke) {\n        this._removeShadow(ctx);\n      }\n\n      ctx.save();\n\n      this._setLineDash(ctx, this.strokeDashArray);\n\n      ctx.beginPath();\n\n      this._renderTextCommon(ctx, 'strokeText');\n\n      ctx.closePath();\n      ctx.restore();\n    },\n\n    /**\n     * @private\n     * @param {String} method fillText or strokeText.\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Array} line Content of the line, splitted in an array by grapheme\n     * @param {Number} left\n     * @param {Number} top\n     * @param {Number} lineIndex\n     */\n    _renderChars: function (method, ctx, line, left, top, lineIndex) {\n      // set proper line offset\n      var lineHeight = this.getHeightOfLine(lineIndex),\n          isJustify = this.textAlign.indexOf('justify') !== -1,\n          actualStyle,\n          nextStyle,\n          charsToRender = '',\n          charBox,\n          boxWidth = 0,\n          timeToRender,\n          shortCut = !isJustify && this.charSpacing === 0 && this.isEmptyStyles(lineIndex);\n      ctx.save();\n      top -= lineHeight * this._fontSizeFraction / this.lineHeight;\n\n      if (shortCut) {\n        // render all the line in one pass without checking\n        this._renderChar(method, ctx, lineIndex, 0, line.join(''), left, top, lineHeight);\n\n        ctx.restore();\n        return;\n      }\n\n      for (var i = 0, len = line.length - 1; i <= len; i++) {\n        timeToRender = i === len || this.charSpacing;\n        charsToRender += line[i];\n        charBox = this.__charBounds[lineIndex][i];\n\n        if (boxWidth === 0) {\n          left += charBox.kernedWidth - charBox.width;\n          boxWidth += charBox.width;\n        } else {\n          boxWidth += charBox.kernedWidth;\n        }\n\n        if (isJustify && !timeToRender) {\n          if (this._reSpaceAndTab.test(line[i])) {\n            timeToRender = true;\n          }\n        }\n\n        if (!timeToRender) {\n          // if we have charSpacing, we render char by char\n          actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\n          nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\n          timeToRender = this._hasStyleChanged(actualStyle, nextStyle);\n        }\n\n        if (timeToRender) {\n          this._renderChar(method, ctx, lineIndex, i, charsToRender, left, top, lineHeight);\n\n          charsToRender = '';\n          actualStyle = nextStyle;\n          left += boxWidth;\n          boxWidth = 0;\n        }\n      }\n\n      ctx.restore();\n    },\n\n    /**\n     * @private\n     * @param {String} method\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @param {String} _char\n     * @param {Number} left Left coordinate\n     * @param {Number} top Top coordinate\n     * @param {Number} lineHeight Height of the line\n     */\n    _renderChar: function (method, ctx, lineIndex, charIndex, _char, left, top) {\n      var decl = this._getStyleDeclaration(lineIndex, charIndex),\n          fullDecl = this.getCompleteStyleDeclaration(lineIndex, charIndex),\n          shouldFill = method === 'fillText' && fullDecl.fill,\n          shouldStroke = method === 'strokeText' && fullDecl.stroke && fullDecl.strokeWidth;\n\n      if (!shouldStroke && !shouldFill) {\n        return;\n      }\n\n      decl && ctx.save();\n\n      this._applyCharStyles(method, ctx, lineIndex, charIndex, fullDecl);\n\n      if (decl && decl.textBackgroundColor) {\n        this._removeShadow(ctx);\n      }\n\n      if (decl && decl.deltaY) {\n        top += decl.deltaY;\n      }\n\n      shouldFill && ctx.fillText(_char, left, top);\n      shouldStroke && ctx.strokeText(_char, left, top);\n      decl && ctx.restore();\n    },\n\n    /**\n     * Turns the character into a 'superior figure' (i.e. 'superscript')\n     * @param {Number} start selection start\n     * @param {Number} end selection end\n     * @returns {fabric.Text} thisArg\n     * @chainable\n     */\n    setSuperscript: function (start, end) {\n      return this._setScript(start, end, this.superscript);\n    },\n\n    /**\n     * Turns the character into an 'inferior figure' (i.e. 'subscript')\n     * @param {Number} start selection start\n     * @param {Number} end selection end\n     * @returns {fabric.Text} thisArg\n     * @chainable\n     */\n    setSubscript: function (start, end) {\n      return this._setScript(start, end, this.subscript);\n    },\n\n    /**\n     * Applies 'schema' at given position\n     * @private\n     * @param {Number} start selection start\n     * @param {Number} end selection end\n     * @param {Number} schema\n     * @returns {fabric.Text} thisArg\n     * @chainable\n     */\n    _setScript: function (start, end, schema) {\n      var loc = this.get2DCursorLocation(start, true),\n          fontSize = this.getValueOfPropertyAt(loc.lineIndex, loc.charIndex, 'fontSize'),\n          dy = this.getValueOfPropertyAt(loc.lineIndex, loc.charIndex, 'deltaY'),\n          style = {\n        fontSize: fontSize * schema.size,\n        deltaY: dy + fontSize * schema.baseline\n      };\n      this.setSelectionStyles(style, start, end);\n      return this;\n    },\n\n    /**\n     * @private\n     * @param {Object} prevStyle\n     * @param {Object} thisStyle\n     */\n    _hasStyleChanged: function (prevStyle, thisStyle) {\n      return prevStyle.fill !== thisStyle.fill || prevStyle.stroke !== thisStyle.stroke || prevStyle.strokeWidth !== thisStyle.strokeWidth || prevStyle.fontSize !== thisStyle.fontSize || prevStyle.fontFamily !== thisStyle.fontFamily || prevStyle.fontWeight !== thisStyle.fontWeight || prevStyle.fontStyle !== thisStyle.fontStyle || prevStyle.deltaY !== thisStyle.deltaY;\n    },\n\n    /**\n     * @private\n     * @param {Object} prevStyle\n     * @param {Object} thisStyle\n     */\n    _hasStyleChangedForSvg: function (prevStyle, thisStyle) {\n      return this._hasStyleChanged(prevStyle, thisStyle) || prevStyle.overline !== thisStyle.overline || prevStyle.underline !== thisStyle.underline || prevStyle.linethrough !== thisStyle.linethrough;\n    },\n\n    /**\n     * @private\n     * @param {Number} lineIndex index text line\n     * @return {Number} Line left offset\n     */\n    _getLineLeftOffset: function (lineIndex) {\n      var lineWidth = this.getLineWidth(lineIndex);\n\n      if (this.textAlign === 'center') {\n        return (this.width - lineWidth) / 2;\n      }\n\n      if (this.textAlign === 'right') {\n        return this.width - lineWidth;\n      }\n\n      if (this.textAlign === 'justify-center' && this.isEndOfWrapping(lineIndex)) {\n        return (this.width - lineWidth) / 2;\n      }\n\n      if (this.textAlign === 'justify-right' && this.isEndOfWrapping(lineIndex)) {\n        return this.width - lineWidth;\n      }\n\n      return 0;\n    },\n\n    /**\n     * @private\n     */\n    _clearCache: function () {\n      this.__lineWidths = [];\n      this.__lineHeights = [];\n      this.__charBounds = [];\n    },\n\n    /**\n     * @private\n     */\n    _shouldClearDimensionCache: function () {\n      var shouldClear = this._forceClearCache;\n      shouldClear || (shouldClear = this.hasStateChanged('_dimensionAffectingProps'));\n\n      if (shouldClear) {\n        this.dirty = true;\n        this._forceClearCache = false;\n      }\n\n      return shouldClear;\n    },\n\n    /**\n     * Measure a single line given its index. Used to calculate the initial\n     * text bounding box. The values are calculated and stored in __lineWidths cache.\n     * @private\n     * @param {Number} lineIndex line number\n     * @return {Number} Line width\n     */\n    getLineWidth: function (lineIndex) {\n      if (this.__lineWidths[lineIndex]) {\n        return this.__lineWidths[lineIndex];\n      }\n\n      var width,\n          line = this._textLines[lineIndex],\n          lineInfo;\n\n      if (line === '') {\n        width = 0;\n      } else {\n        lineInfo = this.measureLine(lineIndex);\n        width = lineInfo.width;\n      }\n\n      this.__lineWidths[lineIndex] = width;\n      return width;\n    },\n    _getWidthOfCharSpacing: function () {\n      if (this.charSpacing !== 0) {\n        return this.fontSize * this.charSpacing / 1000;\n      }\n\n      return 0;\n    },\n\n    /**\n     * Retrieves the value of property at given character position\n     * @param {Number} lineIndex the line number\n     * @param {Number} charIndex the charater number\n     * @param {String} property the property name\n     * @returns the value of 'property'\n     */\n    getValueOfPropertyAt: function (lineIndex, charIndex, property) {\n      var charStyle = this._getStyleDeclaration(lineIndex, charIndex);\n\n      if (charStyle && typeof charStyle[property] !== 'undefined') {\n        return charStyle[property];\n      }\n\n      return this[property];\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderTextDecoration: function (ctx, type) {\n      if (!this[type] && !this.styleHas(type)) {\n        return;\n      }\n\n      var heightOfLine,\n          size,\n          _size,\n          lineLeftOffset,\n          dy,\n          _dy,\n          line,\n          lastDecoration,\n          leftOffset = this._getLeftOffset(),\n          topOffset = this._getTopOffset(),\n          top,\n          boxStart,\n          boxWidth,\n          charBox,\n          currentDecoration,\n          maxHeight,\n          currentFill,\n          lastFill,\n          charSpacing = this._getWidthOfCharSpacing();\n\n      for (var i = 0, len = this._textLines.length; i < len; i++) {\n        heightOfLine = this.getHeightOfLine(i);\n\n        if (!this[type] && !this.styleHas(type, i)) {\n          topOffset += heightOfLine;\n          continue;\n        }\n\n        line = this._textLines[i];\n        maxHeight = heightOfLine / this.lineHeight;\n        lineLeftOffset = this._getLineLeftOffset(i);\n        boxStart = 0;\n        boxWidth = 0;\n        lastDecoration = this.getValueOfPropertyAt(i, 0, type);\n        lastFill = this.getValueOfPropertyAt(i, 0, 'fill');\n        top = topOffset + maxHeight * (1 - this._fontSizeFraction);\n        size = this.getHeightOfChar(i, 0);\n        dy = this.getValueOfPropertyAt(i, 0, 'deltaY');\n\n        for (var j = 0, jlen = line.length; j < jlen; j++) {\n          charBox = this.__charBounds[i][j];\n          currentDecoration = this.getValueOfPropertyAt(i, j, type);\n          currentFill = this.getValueOfPropertyAt(i, j, 'fill');\n          _size = this.getHeightOfChar(i, j);\n          _dy = this.getValueOfPropertyAt(i, j, 'deltaY');\n\n          if ((currentDecoration !== lastDecoration || currentFill !== lastFill || _size !== size || _dy !== dy) && boxWidth > 0) {\n            ctx.fillStyle = lastFill;\n            lastDecoration && lastFill && ctx.fillRect(leftOffset + lineLeftOffset + boxStart, top + this.offsets[type] * size + dy, boxWidth, this.fontSize / 15);\n            boxStart = charBox.left;\n            boxWidth = charBox.width;\n            lastDecoration = currentDecoration;\n            lastFill = currentFill;\n            size = _size;\n            dy = _dy;\n          } else {\n            boxWidth += charBox.kernedWidth;\n          }\n        }\n\n        ctx.fillStyle = currentFill;\n        currentDecoration && currentFill && ctx.fillRect(leftOffset + lineLeftOffset + boxStart, top + this.offsets[type] * size + dy, boxWidth - charSpacing, this.fontSize / 15);\n        topOffset += heightOfLine;\n      } // if there is text background color no\n      // other shadows should be casted\n\n\n      this._removeShadow(ctx);\n    },\n\n    /**\n     * return font declaration string for canvas context\n     * @param {Object} [styleObject] object\n     * @returns {String} font declaration formatted for canvas context.\n     */\n    _getFontDeclaration: function (styleObject, forMeasuring) {\n      var style = styleObject || this,\n          family = this.fontFamily,\n          fontIsGeneric = fabric.Text.genericFonts.indexOf(family.toLowerCase()) > -1;\n      var fontFamily = family === undefined || family.indexOf('\\'') > -1 || family.indexOf(',') > -1 || family.indexOf('\"') > -1 || fontIsGeneric ? style.fontFamily : '\"' + style.fontFamily + '\"';\n      return [// node-canvas needs \"weight style\", while browsers need \"style weight\"\n      // verify if this can be fixed in JSDOM\n      fabric.isLikelyNode ? style.fontWeight : style.fontStyle, fabric.isLikelyNode ? style.fontStyle : style.fontWeight, forMeasuring ? this.CACHE_FONT_SIZE + 'px' : style.fontSize + 'px', fontFamily].join(' ');\n    },\n\n    /**\n     * Renders text instance on a specified context\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    render: function (ctx) {\n      // do not render if object is not visible\n      if (!this.visible) {\n        return;\n      }\n\n      if (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) {\n        return;\n      }\n\n      if (this._shouldClearDimensionCache()) {\n        this.initDimensions();\n      }\n\n      this.callSuper('render', ctx);\n    },\n\n    /**\n     * Returns the text as an array of lines.\n     * @param {String} text text to split\n     * @returns {Array} Lines in the text\n     */\n    _splitTextIntoLines: function (text) {\n      var lines = text.split(this._reNewline),\n          newLines = new Array(lines.length),\n          newLine = ['\\n'],\n          newText = [];\n\n      for (var i = 0; i < lines.length; i++) {\n        newLines[i] = fabric.util.string.graphemeSplit(lines[i]);\n        newText = newText.concat(newLines[i], newLine);\n      }\n\n      newText.pop();\n      return {\n        _unwrappedLines: newLines,\n        lines: lines,\n        graphemeText: newText,\n        graphemeLines: newLines\n      };\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function (propertiesToInclude) {\n      var additionalProperties = ['text', 'fontSize', 'fontWeight', 'fontFamily', 'fontStyle', 'lineHeight', 'underline', 'overline', 'linethrough', 'textAlign', 'textBackgroundColor', 'charSpacing'].concat(propertiesToInclude);\n      var obj = this.callSuper('toObject', additionalProperties);\n      obj.styles = clone(this.styles, true);\n      return obj;\n    },\n\n    /**\n     * Sets property to a given value. When changing position/dimension -related properties (left, top, scale, angle, etc.) `set` does not update position of object's borders/controls. If you need to update those, call `setCoords()`.\n     * @param {String|Object} key Property name or object (if object, iterate over the object properties)\n     * @param {Object|Function} value Property value (if function, the value is passed into it and its return value is used as a new one)\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    set: function (key, value) {\n      this.callSuper('set', key, value);\n      var needsDims = false;\n\n      if (typeof key === 'object') {\n        for (var _key in key) {\n          needsDims = needsDims || this._dimensionAffectingProps.indexOf(_key) !== -1;\n        }\n      } else {\n        needsDims = this._dimensionAffectingProps.indexOf(key) !== -1;\n      }\n\n      if (needsDims) {\n        this.initDimensions();\n        this.setCoords();\n      }\n\n      return this;\n    },\n\n    /**\n     * Returns complexity of an instance\n     * @return {Number} complexity\n     */\n    complexity: function () {\n      return 1;\n    }\n  });\n  /* _FROM_SVG_START_ */\n\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Text.fromElement})\n   * @static\n   * @memberOf fabric.Text\n   * @see: http://www.w3.org/TR/SVG/text.html#TextElement\n   */\n\n  fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y dx dy font-family font-style font-weight font-size letter-spacing text-decoration text-anchor'.split(' '));\n  /**\n   * Default SVG font size\n   * @static\n   * @memberOf fabric.Text\n   */\n\n  fabric.Text.DEFAULT_SVG_FONT_SIZE = 16;\n  /**\n   * Returns fabric.Text instance from an SVG element (<b>not yet implemented</b>)\n   * @static\n   * @memberOf fabric.Text\n   * @param {SVGElement} element Element to parse\n   * @param {Function} callback callback function invoked after parsing\n   * @param {Object} [options] Options object\n   */\n\n  fabric.Text.fromElement = function (element, callback, options) {\n    if (!element) {\n      return callback(null);\n    }\n\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES),\n        parsedAnchor = parsedAttributes.textAnchor || 'left';\n    options = fabric.util.object.extend(options ? clone(options) : {}, parsedAttributes);\n    options.top = options.top || 0;\n    options.left = options.left || 0;\n\n    if (parsedAttributes.textDecoration) {\n      var textDecoration = parsedAttributes.textDecoration;\n\n      if (textDecoration.indexOf('underline') !== -1) {\n        options.underline = true;\n      }\n\n      if (textDecoration.indexOf('overline') !== -1) {\n        options.overline = true;\n      }\n\n      if (textDecoration.indexOf('line-through') !== -1) {\n        options.linethrough = true;\n      }\n\n      delete options.textDecoration;\n    }\n\n    if ('dx' in parsedAttributes) {\n      options.left += parsedAttributes.dx;\n    }\n\n    if ('dy' in parsedAttributes) {\n      options.top += parsedAttributes.dy;\n    }\n\n    if (!('fontSize' in options)) {\n      options.fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;\n    }\n\n    var textContent = ''; // The XML is not properly parsed in IE9 so a workaround to get\n    // textContent is through firstChild.data. Another workaround would be\n    // to convert XML loaded from a file to be converted using DOMParser (same way loadSVGFromString() does)\n\n    if (!('textContent' in element)) {\n      if ('firstChild' in element && element.firstChild !== null) {\n        if ('data' in element.firstChild && element.firstChild.data !== null) {\n          textContent = element.firstChild.data;\n        }\n      }\n    } else {\n      textContent = element.textContent;\n    }\n\n    textContent = textContent.replace(/^\\s+|\\s+$|\\n+/g, '').replace(/\\s+/g, ' ');\n    var originalStrokeWidth = options.strokeWidth;\n    options.strokeWidth = 0;\n    var text = new fabric.Text(textContent, options),\n        textHeightScaleFactor = text.getScaledHeight() / text.height,\n        lineHeightDiff = (text.height + text.strokeWidth) * text.lineHeight - text.height,\n        scaledDiff = lineHeightDiff * textHeightScaleFactor,\n        textHeight = text.getScaledHeight() + scaledDiff,\n        offX = 0;\n    /*\n      Adjust positioning:\n        x/y attributes in SVG correspond to the bottom-left corner of text bounding box\n        fabric output by default at top, left.\n    */\n\n    if (parsedAnchor === 'center') {\n      offX = text.getScaledWidth() / 2;\n    }\n\n    if (parsedAnchor === 'right') {\n      offX = text.getScaledWidth();\n    }\n\n    text.set({\n      left: text.left - offX,\n      top: text.top - (textHeight - text.fontSize * (0.07 + text._fontSizeFraction)) / text.lineHeight,\n      strokeWidth: typeof originalStrokeWidth !== 'undefined' ? originalStrokeWidth : 1\n    });\n    callback(text);\n  };\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns fabric.Text instance from an object representation\n   * @static\n   * @memberOf fabric.Text\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] Callback to invoke when an fabric.Text instance is created\n   */\n\n\n  fabric.Text.fromObject = function (object, callback) {\n    return fabric.Object._fromObject('Text', object, callback, 'text');\n  };\n\n  fabric.Text.genericFonts = ['sans-serif', 'serif', 'cursive', 'fantasy', 'monospace'];\n  fabric.util.createAccessors && fabric.util.createAccessors(fabric.Text);\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function () {\n  fabric.util.object.extend(fabric.Text.prototype,\n  /** @lends fabric.Text.prototype */\n  {\n    /**\n     * Returns true if object has no styling or no styling in a line\n     * @param {Number} lineIndex , lineIndex is on wrapped lines.\n     * @return {Boolean}\n     */\n    isEmptyStyles: function (lineIndex) {\n      if (!this.styles) {\n        return true;\n      }\n\n      if (typeof lineIndex !== 'undefined' && !this.styles[lineIndex]) {\n        return true;\n      }\n\n      var obj = typeof lineIndex === 'undefined' ? this.styles : {\n        line: this.styles[lineIndex]\n      };\n\n      for (var p1 in obj) {\n        for (var p2 in obj[p1]) {\n          // eslint-disable-next-line no-unused-vars\n          for (var p3 in obj[p1][p2]) {\n            return false;\n          }\n        }\n      }\n\n      return true;\n    },\n\n    /**\n     * Returns true if object has a style property or has it ina specified line\n     * This function is used to detect if a text will use a particular property or not.\n     * @param {String} property to check for\n     * @param {Number} lineIndex to check the style on\n     * @return {Boolean}\n     */\n    styleHas: function (property, lineIndex) {\n      if (!this.styles || !property || property === '') {\n        return false;\n      }\n\n      if (typeof lineIndex !== 'undefined' && !this.styles[lineIndex]) {\n        return false;\n      }\n\n      var obj = typeof lineIndex === 'undefined' ? this.styles : {\n        0: this.styles[lineIndex]\n      }; // eslint-disable-next-line\n\n      for (var p1 in obj) {\n        // eslint-disable-next-line\n        for (var p2 in obj[p1]) {\n          if (typeof obj[p1][p2][property] !== 'undefined') {\n            return true;\n          }\n        }\n      }\n\n      return false;\n    },\n\n    /**\n     * Check if characters in a text have a value for a property\n     * whose value matches the textbox's value for that property.  If so,\n     * the character-level property is deleted.  If the character\n     * has no other properties, then it is also deleted.  Finally,\n     * if the line containing that character has no other characters\n     * then it also is deleted.\n     *\n     * @param {string} property The property to compare between characters and text.\n     */\n    cleanStyle: function (property) {\n      if (!this.styles || !property || property === '') {\n        return false;\n      }\n\n      var obj = this.styles,\n          stylesCount = 0,\n          letterCount,\n          stylePropertyValue,\n          allStyleObjectPropertiesMatch = true,\n          graphemeCount = 0,\n          styleObject; // eslint-disable-next-line\n\n      for (var p1 in obj) {\n        letterCount = 0; // eslint-disable-next-line\n\n        for (var p2 in obj[p1]) {\n          var styleObject = obj[p1][p2],\n              stylePropertyHasBeenSet = styleObject.hasOwnProperty(property);\n          stylesCount++;\n\n          if (stylePropertyHasBeenSet) {\n            if (!stylePropertyValue) {\n              stylePropertyValue = styleObject[property];\n            } else if (styleObject[property] !== stylePropertyValue) {\n              allStyleObjectPropertiesMatch = false;\n            }\n\n            if (styleObject[property] === this[property]) {\n              delete styleObject[property];\n            }\n          } else {\n            allStyleObjectPropertiesMatch = false;\n          }\n\n          if (Object.keys(styleObject).length !== 0) {\n            letterCount++;\n          } else {\n            delete obj[p1][p2];\n          }\n        }\n\n        if (letterCount === 0) {\n          delete obj[p1];\n        }\n      } // if every grapheme has the same style set then\n      // delete those styles and set it on the parent\n\n\n      for (var i = 0; i < this._textLines.length; i++) {\n        graphemeCount += this._textLines[i].length;\n      }\n\n      if (allStyleObjectPropertiesMatch && stylesCount === graphemeCount) {\n        this[property] = stylePropertyValue;\n        this.removeStyle(property);\n      }\n    },\n\n    /**\n     * Remove a style property or properties from all individual character styles\n     * in a text object.  Deletes the character style object if it contains no other style\n     * props.  Deletes a line style object if it contains no other character styles.\n     *\n     * @param {String} props The property to remove from character styles.\n     */\n    removeStyle: function (property) {\n      if (!this.styles || !property || property === '') {\n        return;\n      }\n\n      var obj = this.styles,\n          line,\n          lineNum,\n          charNum;\n\n      for (lineNum in obj) {\n        line = obj[lineNum];\n\n        for (charNum in line) {\n          delete line[charNum][property];\n\n          if (Object.keys(line[charNum]).length === 0) {\n            delete line[charNum];\n          }\n        }\n\n        if (Object.keys(line).length === 0) {\n          delete obj[lineNum];\n        }\n      }\n    },\n\n    /**\n     * @private\n     */\n    _extendStyles: function (index, styles) {\n      var loc = this.get2DCursorLocation(index);\n\n      if (!this._getLineStyle(loc.lineIndex)) {\n        this._setLineStyle(loc.lineIndex);\n      }\n\n      if (!this._getStyleDeclaration(loc.lineIndex, loc.charIndex)) {\n        this._setStyleDeclaration(loc.lineIndex, loc.charIndex, {});\n      }\n\n      fabric.util.object.extend(this._getStyleDeclaration(loc.lineIndex, loc.charIndex), styles);\n    },\n\n    /**\n     * Returns 2d representation (lineIndex and charIndex) of cursor (or selection start)\n     * @param {Number} [selectionStart] Optional index. When not given, current selectionStart is used.\n     * @param {Boolean} [skipWrapping] consider the location for unwrapped lines. useful to manage styles.\n     */\n    get2DCursorLocation: function (selectionStart, skipWrapping) {\n      if (typeof selectionStart === 'undefined') {\n        selectionStart = this.selectionStart;\n      }\n\n      var lines = skipWrapping ? this._unwrappedTextLines : this._textLines,\n          len = lines.length;\n\n      for (var i = 0; i < len; i++) {\n        if (selectionStart <= lines[i].length) {\n          return {\n            lineIndex: i,\n            charIndex: selectionStart\n          };\n        }\n\n        selectionStart -= lines[i].length + this.missingNewlineOffset(i);\n      }\n\n      return {\n        lineIndex: i - 1,\n        charIndex: lines[i - 1].length < selectionStart ? lines[i - 1].length : selectionStart\n      };\n    },\n\n    /**\n     * Gets style of a current selection/cursor (at the start position)\n     * if startIndex or endIndex are not provided, slectionStart or selectionEnd will be used.\n     * @param {Number} [startIndex] Start index to get styles at\n     * @param {Number} [endIndex] End index to get styles at, if not specified selectionEnd or startIndex + 1\n     * @param {Boolean} [complete] get full style or not\n     * @return {Array} styles an array with one, zero or more Style objects\n     */\n    getSelectionStyles: function (startIndex, endIndex, complete) {\n      if (typeof startIndex === 'undefined') {\n        startIndex = this.selectionStart || 0;\n      }\n\n      if (typeof endIndex === 'undefined') {\n        endIndex = this.selectionEnd || startIndex;\n      }\n\n      var styles = [];\n\n      for (var i = startIndex; i < endIndex; i++) {\n        styles.push(this.getStyleAtPosition(i, complete));\n      }\n\n      return styles;\n    },\n\n    /**\n     * Gets style of a current selection/cursor position\n     * @param {Number} position  to get styles at\n     * @param {Boolean} [complete] full style if true\n     * @return {Object} style Style object at a specified index\n     * @private\n     */\n    getStyleAtPosition: function (position, complete) {\n      var loc = this.get2DCursorLocation(position),\n          style = complete ? this.getCompleteStyleDeclaration(loc.lineIndex, loc.charIndex) : this._getStyleDeclaration(loc.lineIndex, loc.charIndex);\n      return style || {};\n    },\n\n    /**\n     * Sets style of a current selection, if no selection exist, do not set anything.\n     * @param {Object} [styles] Styles object\n     * @param {Number} [startIndex] Start index to get styles at\n     * @param {Number} [endIndex] End index to get styles at, if not specified selectionEnd or startIndex + 1\n     * @return {fabric.IText} thisArg\n     * @chainable\n     */\n    setSelectionStyles: function (styles, startIndex, endIndex) {\n      if (typeof startIndex === 'undefined') {\n        startIndex = this.selectionStart || 0;\n      }\n\n      if (typeof endIndex === 'undefined') {\n        endIndex = this.selectionEnd || startIndex;\n      }\n\n      for (var i = startIndex; i < endIndex; i++) {\n        this._extendStyles(i, styles);\n      }\n      /* not included in _extendStyles to avoid clearing cache more than once */\n\n\n      this._forceClearCache = true;\n      return this;\n    },\n\n    /**\n     * get the reference, not a clone, of the style object for a given character\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @return {Object} style object\n     */\n    _getStyleDeclaration: function (lineIndex, charIndex) {\n      var lineStyle = this.styles && this.styles[lineIndex];\n\n      if (!lineStyle) {\n        return null;\n      }\n\n      return lineStyle[charIndex];\n    },\n\n    /**\n     * return a new object that contains all the style property for a character\n     * the object returned is newly created\n     * @param {Number} lineIndex of the line where the character is\n     * @param {Number} charIndex position of the character on the line\n     * @return {Object} style object\n     */\n    getCompleteStyleDeclaration: function (lineIndex, charIndex) {\n      var style = this._getStyleDeclaration(lineIndex, charIndex) || {},\n          styleObject = {},\n          prop;\n\n      for (var i = 0; i < this._styleProperties.length; i++) {\n        prop = this._styleProperties[i];\n        styleObject[prop] = typeof style[prop] === 'undefined' ? this[prop] : style[prop];\n      }\n\n      return styleObject;\n    },\n\n    /**\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @param {Object} style\n     * @private\n     */\n    _setStyleDeclaration: function (lineIndex, charIndex, style) {\n      this.styles[lineIndex][charIndex] = style;\n    },\n\n    /**\n     *\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @private\n     */\n    _deleteStyleDeclaration: function (lineIndex, charIndex) {\n      delete this.styles[lineIndex][charIndex];\n    },\n\n    /**\n     * @param {Number} lineIndex\n     * @return {Boolean} if the line exists or not\n     * @private\n     */\n    _getLineStyle: function (lineIndex) {\n      return !!this.styles[lineIndex];\n    },\n\n    /**\n     * Set the line style to an empty object so that is initialized\n     * @param {Number} lineIndex\n     * @private\n     */\n    _setLineStyle: function (lineIndex) {\n      this.styles[lineIndex] = {};\n    },\n\n    /**\n     * @param {Number} lineIndex\n     * @private\n     */\n    _deleteLineStyle: function (lineIndex) {\n      delete this.styles[lineIndex];\n    }\n  });\n})();\n\n(function () {\n  function parseDecoration(object) {\n    if (object.textDecoration) {\n      object.textDecoration.indexOf('underline') > -1 && (object.underline = true);\n      object.textDecoration.indexOf('line-through') > -1 && (object.linethrough = true);\n      object.textDecoration.indexOf('overline') > -1 && (object.overline = true);\n      delete object.textDecoration;\n    }\n  }\n  /**\n   * IText class (introduced in <b>v1.4</b>) Events are also fired with \"text:\"\n   * prefix when observing canvas.\n   * @class fabric.IText\n   * @extends fabric.Text\n   * @mixes fabric.Observable\n   *\n   * @fires changed\n   * @fires selection:changed\n   * @fires editing:entered\n   * @fires editing:exited\n   *\n   * @return {fabric.IText} thisArg\n   * @see {@link fabric.IText#initialize} for constructor definition\n   *\n   * <p>Supported key combinations:</p>\n   * <pre>\n   *   Move cursor:                    left, right, up, down\n   *   Select character:               shift + left, shift + right\n   *   Select text vertically:         shift + up, shift + down\n   *   Move cursor by word:            alt + left, alt + right\n   *   Select words:                   shift + alt + left, shift + alt + right\n   *   Move cursor to line start/end:  cmd + left, cmd + right or home, end\n   *   Select till start/end of line:  cmd + shift + left, cmd + shift + right or shift + home, shift + end\n   *   Jump to start/end of text:      cmd + up, cmd + down\n   *   Select till start/end of text:  cmd + shift + up, cmd + shift + down or shift + pgUp, shift + pgDown\n   *   Delete character:               backspace\n   *   Delete word:                    alt + backspace\n   *   Delete line:                    cmd + backspace\n   *   Forward delete:                 delete\n   *   Copy text:                      ctrl/cmd + c\n   *   Paste text:                     ctrl/cmd + v\n   *   Cut text:                       ctrl/cmd + x\n   *   Select entire text:             ctrl/cmd + a\n   *   Quit editing                    tab or esc\n   * </pre>\n   *\n   * <p>Supported mouse/touch combination</p>\n   * <pre>\n   *   Position cursor:                click/touch\n   *   Create selection:               click/touch & drag\n   *   Create selection:               click & shift + click\n   *   Select word:                    double click\n   *   Select line:                    triple click\n   * </pre>\n   */\n\n\n  fabric.IText = fabric.util.createClass(fabric.Text, fabric.Observable,\n  /** @lends fabric.IText.prototype */\n  {\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'i-text',\n\n    /**\n     * Index where text selection starts (or where cursor is when there is no selection)\n     * @type Number\n     * @default\n     */\n    selectionStart: 0,\n\n    /**\n     * Index where text selection ends\n     * @type Number\n     * @default\n     */\n    selectionEnd: 0,\n\n    /**\n     * Color of text selection\n     * @type String\n     * @default\n     */\n    selectionColor: 'rgba(17,119,255,0.3)',\n\n    /**\n     * Indicates whether text is in editing mode\n     * @type Boolean\n     * @default\n     */\n    isEditing: false,\n\n    /**\n     * Indicates whether a text can be edited\n     * @type Boolean\n     * @default\n     */\n    editable: true,\n\n    /**\n     * Border color of text object while it's in editing mode\n     * @type String\n     * @default\n     */\n    editingBorderColor: 'rgba(102,153,255,0.25)',\n\n    /**\n     * Width of cursor (in px)\n     * @type Number\n     * @default\n     */\n    cursorWidth: 2,\n\n    /**\n     * Color of text cursor color in editing mode.\n     * if not set (default) will take color from the text.\n     * if set to a color value that fabric can understand, it will\n     * be used instead of the color of the text at the current position.\n     * @type String\n     * @default\n     */\n    cursorColor: '',\n\n    /**\n     * Delay between cursor blink (in ms)\n     * @type Number\n     * @default\n     */\n    cursorDelay: 1000,\n\n    /**\n     * Duration of cursor fadein (in ms)\n     * @type Number\n     * @default\n     */\n    cursorDuration: 600,\n\n    /**\n     * Indicates whether internal text char widths can be cached\n     * @type Boolean\n     * @default\n     */\n    caching: true,\n\n    /**\n     * @private\n     */\n    _reSpace: /\\s|\\n/,\n\n    /**\n     * @private\n     */\n    _currentCursorOpacity: 0,\n\n    /**\n     * @private\n     */\n    _selectionDirection: null,\n\n    /**\n     * @private\n     */\n    _abortCursorAnimation: false,\n\n    /**\n     * @private\n     */\n    __widthOfSpace: [],\n\n    /**\n     * Helps determining when the text is in composition, so that the cursor\n     * rendering is altered.\n     */\n    inCompositionMode: false,\n\n    /**\n     * Constructor\n     * @param {String} text Text string\n     * @param {Object} [options] Options object\n     * @return {fabric.IText} thisArg\n     */\n    initialize: function (text, options) {\n      this.callSuper('initialize', text, options);\n      this.initBehavior();\n    },\n\n    /**\n     * Sets selection start (left boundary of a selection)\n     * @param {Number} index Index to set selection start to\n     */\n    setSelectionStart: function (index) {\n      index = Math.max(index, 0);\n\n      this._updateAndFire('selectionStart', index);\n    },\n\n    /**\n     * Sets selection end (right boundary of a selection)\n     * @param {Number} index Index to set selection end to\n     */\n    setSelectionEnd: function (index) {\n      index = Math.min(index, this.text.length);\n\n      this._updateAndFire('selectionEnd', index);\n    },\n\n    /**\n     * @private\n     * @param {String} property 'selectionStart' or 'selectionEnd'\n     * @param {Number} index new position of property\n     */\n    _updateAndFire: function (property, index) {\n      if (this[property] !== index) {\n        this._fireSelectionChanged();\n\n        this[property] = index;\n      }\n\n      this._updateTextarea();\n    },\n\n    /**\n     * Fires the even of selection changed\n     * @private\n     */\n    _fireSelectionChanged: function () {\n      this.fire('selection:changed');\n      this.canvas && this.canvas.fire('text:selection:changed', {\n        target: this\n      });\n    },\n\n    /**\n     * Initialize text dimensions. Render all text on given context\n     * or on a offscreen canvas to get the text width with measureText.\n     * Updates this.width and this.height with the proper values.\n     * Does not return dimensions.\n     * @private\n     */\n    initDimensions: function () {\n      this.isEditing && this.initDelayedCursor();\n      this.clearContextTop();\n      this.callSuper('initDimensions');\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    render: function (ctx) {\n      this.clearContextTop();\n      this.callSuper('render', ctx); // clear the cursorOffsetCache, so we ensure to calculate once per renderCursor\n      // the correct position but not at every cursor animation.\n\n      this.cursorOffsetCache = {};\n      this.renderCursorOrSelection();\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function (ctx) {\n      this.callSuper('_render', ctx);\n    },\n\n    /**\n     * Prepare and clean the contextTop\n     */\n    clearContextTop: function (skipRestore) {\n      if (!this.isEditing || !this.canvas || !this.canvas.contextTop) {\n        return;\n      }\n\n      var ctx = this.canvas.contextTop,\n          v = this.canvas.viewportTransform;\n      ctx.save();\n      ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n      this.transform(ctx);\n\n      this._clearTextArea(ctx);\n\n      skipRestore || ctx.restore();\n    },\n\n    /**\n     * Renders cursor or selection (depending on what exists)\n     * it does on the contextTop. If contextTop is not available, do nothing.\n     */\n    renderCursorOrSelection: function () {\n      if (!this.isEditing || !this.canvas || !this.canvas.contextTop) {\n        return;\n      }\n\n      var boundaries = this._getCursorBoundaries(),\n          ctx = this.canvas.contextTop;\n\n      this.clearContextTop(true);\n\n      if (this.selectionStart === this.selectionEnd) {\n        this.renderCursor(boundaries, ctx);\n      } else {\n        this.renderSelection(boundaries, ctx);\n      }\n\n      ctx.restore();\n    },\n    _clearTextArea: function (ctx) {\n      // we add 4 pixel, to be sure to do not leave any pixel out\n      var width = this.width + 4,\n          height = this.height + 4;\n      ctx.clearRect(-width / 2, -height / 2, width, height);\n    },\n\n    /**\n     * Returns cursor boundaries (left, top, leftOffset, topOffset)\n     * @private\n     * @param {Array} chars Array of characters\n     * @param {String} typeOfBoundaries\n     */\n    _getCursorBoundaries: function (position) {\n      // left/top are left/top of entire text box\n      // leftOffset/topOffset are offset from that left/top point of a text box\n      if (typeof position === 'undefined') {\n        position = this.selectionStart;\n      }\n\n      var left = this._getLeftOffset(),\n          top = this._getTopOffset(),\n          offsets = this._getCursorBoundariesOffsets(position);\n\n      return {\n        left: left,\n        top: top,\n        leftOffset: offsets.left,\n        topOffset: offsets.top\n      };\n    },\n\n    /**\n     * @private\n     */\n    _getCursorBoundariesOffsets: function (position) {\n      if (this.cursorOffsetCache && 'top' in this.cursorOffsetCache) {\n        return this.cursorOffsetCache;\n      }\n\n      var lineLeftOffset,\n          lineIndex,\n          charIndex,\n          topOffset = 0,\n          leftOffset = 0,\n          boundaries,\n          cursorPosition = this.get2DCursorLocation(position);\n      charIndex = cursorPosition.charIndex;\n      lineIndex = cursorPosition.lineIndex;\n\n      for (var i = 0; i < lineIndex; i++) {\n        topOffset += this.getHeightOfLine(i);\n      }\n\n      lineLeftOffset = this._getLineLeftOffset(lineIndex);\n      var bound = this.__charBounds[lineIndex][charIndex];\n      bound && (leftOffset = bound.left);\n\n      if (this.charSpacing !== 0 && charIndex === this._textLines[lineIndex].length) {\n        leftOffset -= this._getWidthOfCharSpacing();\n      }\n\n      boundaries = {\n        top: topOffset,\n        left: lineLeftOffset + (leftOffset > 0 ? leftOffset : 0)\n      };\n      this.cursorOffsetCache = boundaries;\n      return this.cursorOffsetCache;\n    },\n\n    /**\n     * Renders cursor\n     * @param {Object} boundaries\n     * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n     */\n    renderCursor: function (boundaries, ctx) {\n      var cursorLocation = this.get2DCursorLocation(),\n          lineIndex = cursorLocation.lineIndex,\n          charIndex = cursorLocation.charIndex > 0 ? cursorLocation.charIndex - 1 : 0,\n          charHeight = this.getValueOfPropertyAt(lineIndex, charIndex, 'fontSize'),\n          multiplier = this.scaleX * this.canvas.getZoom(),\n          cursorWidth = this.cursorWidth / multiplier,\n          topOffset = boundaries.topOffset,\n          dy = this.getValueOfPropertyAt(lineIndex, charIndex, 'deltaY');\n      topOffset += (1 - this._fontSizeFraction) * this.getHeightOfLine(lineIndex) / this.lineHeight - charHeight * (1 - this._fontSizeFraction);\n\n      if (this.inCompositionMode) {\n        this.renderSelection(boundaries, ctx);\n      }\n\n      ctx.fillStyle = this.cursorColor || this.getValueOfPropertyAt(lineIndex, charIndex, 'fill');\n      ctx.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity;\n      ctx.fillRect(boundaries.left + boundaries.leftOffset - cursorWidth / 2, topOffset + boundaries.top + dy, cursorWidth, charHeight);\n    },\n\n    /**\n     * Renders text selection\n     * @param {Object} boundaries Object with left/top/leftOffset/topOffset\n     * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n     */\n    renderSelection: function (boundaries, ctx) {\n      var selectionStart = this.inCompositionMode ? this.hiddenTextarea.selectionStart : this.selectionStart,\n          selectionEnd = this.inCompositionMode ? this.hiddenTextarea.selectionEnd : this.selectionEnd,\n          isJustify = this.textAlign.indexOf('justify') !== -1,\n          start = this.get2DCursorLocation(selectionStart),\n          end = this.get2DCursorLocation(selectionEnd),\n          startLine = start.lineIndex,\n          endLine = end.lineIndex,\n          startChar = start.charIndex < 0 ? 0 : start.charIndex,\n          endChar = end.charIndex < 0 ? 0 : end.charIndex;\n\n      for (var i = startLine; i <= endLine; i++) {\n        var lineOffset = this._getLineLeftOffset(i) || 0,\n            lineHeight = this.getHeightOfLine(i),\n            realLineHeight = 0,\n            boxStart = 0,\n            boxEnd = 0;\n\n        if (i === startLine) {\n          boxStart = this.__charBounds[startLine][startChar].left;\n        }\n\n        if (i >= startLine && i < endLine) {\n          boxEnd = isJustify && !this.isEndOfWrapping(i) ? this.width : this.getLineWidth(i) || 5; // WTF is this 5?\n        } else if (i === endLine) {\n          if (endChar === 0) {\n            boxEnd = this.__charBounds[endLine][endChar].left;\n          } else {\n            var charSpacing = this._getWidthOfCharSpacing();\n\n            boxEnd = this.__charBounds[endLine][endChar - 1].left + this.__charBounds[endLine][endChar - 1].width - charSpacing;\n          }\n        }\n\n        realLineHeight = lineHeight;\n\n        if (this.lineHeight < 1 || i === endLine && this.lineHeight > 1) {\n          lineHeight /= this.lineHeight;\n        }\n\n        if (this.inCompositionMode) {\n          ctx.fillStyle = this.compositionColor || 'black';\n          ctx.fillRect(boundaries.left + lineOffset + boxStart, boundaries.top + boundaries.topOffset + lineHeight, boxEnd - boxStart, 1);\n        } else {\n          ctx.fillStyle = this.selectionColor;\n          ctx.fillRect(boundaries.left + lineOffset + boxStart, boundaries.top + boundaries.topOffset, boxEnd - boxStart, lineHeight);\n        }\n\n        boundaries.topOffset += realLineHeight;\n      }\n    },\n\n    /**\n     * High level function to know the height of the cursor.\n     * the currentChar is the one that precedes the cursor\n     * Returns fontSize of char at the current cursor\n     * Unused from the library, is for the end user\n     * @return {Number} Character font size\n     */\n    getCurrentCharFontSize: function () {\n      var cp = this._getCurrentCharIndex();\n\n      return this.getValueOfPropertyAt(cp.l, cp.c, 'fontSize');\n    },\n\n    /**\n     * High level function to know the color of the cursor.\n     * the currentChar is the one that precedes the cursor\n     * Returns color (fill) of char at the current cursor\n     * Unused from the library, is for the end user\n     * @return {String} Character color (fill)\n     */\n    getCurrentCharColor: function () {\n      var cp = this._getCurrentCharIndex();\n\n      return this.getValueOfPropertyAt(cp.l, cp.c, 'fill');\n    },\n\n    /**\n     * Returns the cursor position for the getCurrent.. functions\n     * @private\n     */\n    _getCurrentCharIndex: function () {\n      var cursorPosition = this.get2DCursorLocation(this.selectionStart, true),\n          charIndex = cursorPosition.charIndex > 0 ? cursorPosition.charIndex - 1 : 0;\n      return {\n        l: cursorPosition.lineIndex,\n        c: charIndex\n      };\n    }\n  });\n  /**\n   * Returns fabric.IText instance from an object representation\n   * @static\n   * @memberOf fabric.IText\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] invoked with new instance as argument\n   */\n\n  fabric.IText.fromObject = function (object, callback) {\n    parseDecoration(object);\n\n    if (object.styles) {\n      for (var i in object.styles) {\n        for (var j in object.styles[i]) {\n          parseDecoration(object.styles[i][j]);\n        }\n      }\n    }\n\n    fabric.Object._fromObject('IText', object, callback, 'text');\n  };\n})();\n\n(function () {\n  var clone = fabric.util.object.clone;\n  fabric.util.object.extend(fabric.IText.prototype,\n  /** @lends fabric.IText.prototype */\n  {\n    /**\n     * Initializes all the interactive behavior of IText\n     */\n    initBehavior: function () {\n      this.initAddedHandler();\n      this.initRemovedHandler();\n      this.initCursorSelectionHandlers();\n      this.initDoubleClickSimulation();\n      this.mouseMoveHandler = this.mouseMoveHandler.bind(this);\n    },\n    onDeselect: function () {\n      this.isEditing && this.exitEditing();\n      this.selected = false;\n    },\n\n    /**\n     * Initializes \"added\" event handler\n     */\n    initAddedHandler: function () {\n      var _this = this;\n\n      this.on('added', function () {\n        var canvas = _this.canvas;\n\n        if (canvas) {\n          if (!canvas._hasITextHandlers) {\n            canvas._hasITextHandlers = true;\n\n            _this._initCanvasHandlers(canvas);\n          }\n\n          canvas._iTextInstances = canvas._iTextInstances || [];\n\n          canvas._iTextInstances.push(_this);\n        }\n      });\n    },\n    initRemovedHandler: function () {\n      var _this = this;\n\n      this.on('removed', function () {\n        var canvas = _this.canvas;\n\n        if (canvas) {\n          canvas._iTextInstances = canvas._iTextInstances || [];\n          fabric.util.removeFromArray(canvas._iTextInstances, _this);\n\n          if (canvas._iTextInstances.length === 0) {\n            canvas._hasITextHandlers = false;\n\n            _this._removeCanvasHandlers(canvas);\n          }\n        }\n      });\n    },\n\n    /**\n     * register canvas event to manage exiting on other instances\n     * @private\n     */\n    _initCanvasHandlers: function (canvas) {\n      canvas._mouseUpITextHandler = function () {\n        if (canvas._iTextInstances) {\n          canvas._iTextInstances.forEach(function (obj) {\n            obj.__isMousedown = false;\n          });\n        }\n      };\n\n      canvas.on('mouse:up', canvas._mouseUpITextHandler);\n    },\n\n    /**\n     * remove canvas event to manage exiting on other instances\n     * @private\n     */\n    _removeCanvasHandlers: function (canvas) {\n      canvas.off('mouse:up', canvas._mouseUpITextHandler);\n    },\n\n    /**\n     * @private\n     */\n    _tick: function () {\n      this._currentTickState = this._animateCursor(this, 1, this.cursorDuration, '_onTickComplete');\n    },\n\n    /**\n     * @private\n     */\n    _animateCursor: function (obj, targetOpacity, duration, completeMethod) {\n      var tickState;\n      tickState = {\n        isAborted: false,\n        abort: function () {\n          this.isAborted = true;\n        }\n      };\n      obj.animate('_currentCursorOpacity', targetOpacity, {\n        duration: duration,\n        onComplete: function () {\n          if (!tickState.isAborted) {\n            obj[completeMethod]();\n          }\n        },\n        onChange: function () {\n          // we do not want to animate a selection, only cursor\n          if (obj.canvas && obj.selectionStart === obj.selectionEnd) {\n            obj.renderCursorOrSelection();\n          }\n        },\n        abort: function () {\n          return tickState.isAborted;\n        }\n      });\n      return tickState;\n    },\n\n    /**\n     * @private\n     */\n    _onTickComplete: function () {\n      var _this = this;\n\n      if (this._cursorTimeout1) {\n        clearTimeout(this._cursorTimeout1);\n      }\n\n      this._cursorTimeout1 = setTimeout(function () {\n        _this._currentTickCompleteState = _this._animateCursor(_this, 0, this.cursorDuration / 2, '_tick');\n      }, 100);\n    },\n\n    /**\n     * Initializes delayed cursor\n     */\n    initDelayedCursor: function (restart) {\n      var _this = this,\n          delay = restart ? 0 : this.cursorDelay;\n\n      this.abortCursorAnimation();\n      this._currentCursorOpacity = 1;\n      this._cursorTimeout2 = setTimeout(function () {\n        _this._tick();\n      }, delay);\n    },\n\n    /**\n     * Aborts cursor animation and clears all timeouts\n     */\n    abortCursorAnimation: function () {\n      var shouldClear = this._currentTickState || this._currentTickCompleteState,\n          canvas = this.canvas;\n      this._currentTickState && this._currentTickState.abort();\n      this._currentTickCompleteState && this._currentTickCompleteState.abort();\n      clearTimeout(this._cursorTimeout1);\n      clearTimeout(this._cursorTimeout2);\n      this._currentCursorOpacity = 0; // to clear just itext area we need to transform the context\n      // it may not be worth it\n\n      if (shouldClear && canvas) {\n        canvas.clearContext(canvas.contextTop || canvas.contextContainer);\n      }\n    },\n\n    /**\n     * Selects entire text\n     * @return {fabric.IText} thisArg\n     * @chainable\n     */\n    selectAll: function () {\n      this.selectionStart = 0;\n      this.selectionEnd = this._text.length;\n\n      this._fireSelectionChanged();\n\n      this._updateTextarea();\n\n      return this;\n    },\n\n    /**\n     * Returns selected text\n     * @return {String}\n     */\n    getSelectedText: function () {\n      return this._text.slice(this.selectionStart, this.selectionEnd).join('');\n    },\n\n    /**\n     * Find new selection index representing start of current word according to current selection index\n     * @param {Number} startFrom Current selection index\n     * @return {Number} New selection index\n     */\n    findWordBoundaryLeft: function (startFrom) {\n      var offset = 0,\n          index = startFrom - 1; // remove space before cursor first\n\n      if (this._reSpace.test(this._text[index])) {\n        while (this._reSpace.test(this._text[index])) {\n          offset++;\n          index--;\n        }\n      }\n\n      while (/\\S/.test(this._text[index]) && index > -1) {\n        offset++;\n        index--;\n      }\n\n      return startFrom - offset;\n    },\n\n    /**\n     * Find new selection index representing end of current word according to current selection index\n     * @param {Number} startFrom Current selection index\n     * @return {Number} New selection index\n     */\n    findWordBoundaryRight: function (startFrom) {\n      var offset = 0,\n          index = startFrom; // remove space after cursor first\n\n      if (this._reSpace.test(this._text[index])) {\n        while (this._reSpace.test(this._text[index])) {\n          offset++;\n          index++;\n        }\n      }\n\n      while (/\\S/.test(this._text[index]) && index < this._text.length) {\n        offset++;\n        index++;\n      }\n\n      return startFrom + offset;\n    },\n\n    /**\n     * Find new selection index representing start of current line according to current selection index\n     * @param {Number} startFrom Current selection index\n     * @return {Number} New selection index\n     */\n    findLineBoundaryLeft: function (startFrom) {\n      var offset = 0,\n          index = startFrom - 1;\n\n      while (!/\\n/.test(this._text[index]) && index > -1) {\n        offset++;\n        index--;\n      }\n\n      return startFrom - offset;\n    },\n\n    /**\n     * Find new selection index representing end of current line according to current selection index\n     * @param {Number} startFrom Current selection index\n     * @return {Number} New selection index\n     */\n    findLineBoundaryRight: function (startFrom) {\n      var offset = 0,\n          index = startFrom;\n\n      while (!/\\n/.test(this._text[index]) && index < this._text.length) {\n        offset++;\n        index++;\n      }\n\n      return startFrom + offset;\n    },\n\n    /**\n     * Finds index corresponding to beginning or end of a word\n     * @param {Number} selectionStart Index of a character\n     * @param {Number} direction 1 or -1\n     * @return {Number} Index of the beginning or end of a word\n     */\n    searchWordBoundary: function (selectionStart, direction) {\n      var text = this._text,\n          index = this._reSpace.test(text[selectionStart]) ? selectionStart - 1 : selectionStart,\n          _char = text[index],\n          // wrong\n      reNonWord = fabric.reNonWord;\n\n      while (!reNonWord.test(_char) && index > 0 && index < text.length) {\n        index += direction;\n        _char = text[index];\n      }\n\n      if (reNonWord.test(_char)) {\n        index += direction === 1 ? 0 : 1;\n      }\n\n      return index;\n    },\n\n    /**\n     * Selects a word based on the index\n     * @param {Number} selectionStart Index of a character\n     */\n    selectWord: function (selectionStart) {\n      selectionStart = selectionStart || this.selectionStart;\n      var newSelectionStart = this.searchWordBoundary(selectionStart, -1),\n\n      /* search backwards */\n      newSelectionEnd = this.searchWordBoundary(selectionStart, 1);\n      /* search forward */\n\n      this.selectionStart = newSelectionStart;\n      this.selectionEnd = newSelectionEnd;\n\n      this._fireSelectionChanged();\n\n      this._updateTextarea();\n\n      this.renderCursorOrSelection();\n    },\n\n    /**\n     * Selects a line based on the index\n     * @param {Number} selectionStart Index of a character\n     * @return {fabric.IText} thisArg\n     * @chainable\n     */\n    selectLine: function (selectionStart) {\n      selectionStart = selectionStart || this.selectionStart;\n      var newSelectionStart = this.findLineBoundaryLeft(selectionStart),\n          newSelectionEnd = this.findLineBoundaryRight(selectionStart);\n      this.selectionStart = newSelectionStart;\n      this.selectionEnd = newSelectionEnd;\n\n      this._fireSelectionChanged();\n\n      this._updateTextarea();\n\n      return this;\n    },\n\n    /**\n     * Enters editing state\n     * @return {fabric.IText} thisArg\n     * @chainable\n     */\n    enterEditing: function (e) {\n      if (this.isEditing || !this.editable) {\n        return;\n      }\n\n      if (this.canvas) {\n        this.canvas.calcOffset();\n        this.exitEditingOnOthers(this.canvas);\n      }\n\n      this.isEditing = true;\n      this.initHiddenTextarea(e);\n      this.hiddenTextarea.focus();\n      this.hiddenTextarea.value = this.text;\n\n      this._updateTextarea();\n\n      this._saveEditingProps();\n\n      this._setEditingProps();\n\n      this._textBeforeEdit = this.text;\n\n      this._tick();\n\n      this.fire('editing:entered');\n\n      this._fireSelectionChanged();\n\n      if (!this.canvas) {\n        return this;\n      }\n\n      this.canvas.fire('text:editing:entered', {\n        target: this\n      });\n      this.initMouseMoveHandler();\n      this.canvas.requestRenderAll();\n      return this;\n    },\n    exitEditingOnOthers: function (canvas) {\n      if (canvas._iTextInstances) {\n        canvas._iTextInstances.forEach(function (obj) {\n          obj.selected = false;\n\n          if (obj.isEditing) {\n            obj.exitEditing();\n          }\n        });\n      }\n    },\n\n    /**\n     * Initializes \"mousemove\" event handler\n     */\n    initMouseMoveHandler: function () {\n      this.canvas.on('mouse:move', this.mouseMoveHandler);\n    },\n\n    /**\n     * @private\n     */\n    mouseMoveHandler: function (options) {\n      if (!this.__isMousedown || !this.isEditing) {\n        return;\n      }\n\n      var newSelectionStart = this.getSelectionStartFromPointer(options.e),\n          currentStart = this.selectionStart,\n          currentEnd = this.selectionEnd;\n\n      if ((newSelectionStart !== this.__selectionStartOnMouseDown || currentStart === currentEnd) && (currentStart === newSelectionStart || currentEnd === newSelectionStart)) {\n        return;\n      }\n\n      if (newSelectionStart > this.__selectionStartOnMouseDown) {\n        this.selectionStart = this.__selectionStartOnMouseDown;\n        this.selectionEnd = newSelectionStart;\n      } else {\n        this.selectionStart = newSelectionStart;\n        this.selectionEnd = this.__selectionStartOnMouseDown;\n      }\n\n      if (this.selectionStart !== currentStart || this.selectionEnd !== currentEnd) {\n        this.restartCursorIfNeeded();\n\n        this._fireSelectionChanged();\n\n        this._updateTextarea();\n\n        this.renderCursorOrSelection();\n      }\n    },\n\n    /**\n     * @private\n     */\n    _setEditingProps: function () {\n      this.hoverCursor = 'text';\n\n      if (this.canvas) {\n        this.canvas.defaultCursor = this.canvas.moveCursor = 'text';\n      }\n\n      this.borderColor = this.editingBorderColor;\n      this.hasControls = this.selectable = false;\n      this.lockMovementX = this.lockMovementY = true;\n    },\n\n    /**\n     * convert from textarea to grapheme indexes\n     */\n    fromStringToGraphemeSelection: function (start, end, text) {\n      var smallerTextStart = text.slice(0, start),\n          graphemeStart = fabric.util.string.graphemeSplit(smallerTextStart).length;\n\n      if (start === end) {\n        return {\n          selectionStart: graphemeStart,\n          selectionEnd: graphemeStart\n        };\n      }\n\n      var smallerTextEnd = text.slice(start, end),\n          graphemeEnd = fabric.util.string.graphemeSplit(smallerTextEnd).length;\n      return {\n        selectionStart: graphemeStart,\n        selectionEnd: graphemeStart + graphemeEnd\n      };\n    },\n\n    /**\n     * convert from fabric to textarea values\n     */\n    fromGraphemeToStringSelection: function (start, end, _text) {\n      var smallerTextStart = _text.slice(0, start),\n          graphemeStart = smallerTextStart.join('').length;\n\n      if (start === end) {\n        return {\n          selectionStart: graphemeStart,\n          selectionEnd: graphemeStart\n        };\n      }\n\n      var smallerTextEnd = _text.slice(start, end),\n          graphemeEnd = smallerTextEnd.join('').length;\n\n      return {\n        selectionStart: graphemeStart,\n        selectionEnd: graphemeStart + graphemeEnd\n      };\n    },\n\n    /**\n     * @private\n     */\n    _updateTextarea: function () {\n      this.cursorOffsetCache = {};\n\n      if (!this.hiddenTextarea) {\n        return;\n      }\n\n      if (!this.inCompositionMode) {\n        var newSelection = this.fromGraphemeToStringSelection(this.selectionStart, this.selectionEnd, this._text);\n        this.hiddenTextarea.selectionStart = newSelection.selectionStart;\n        this.hiddenTextarea.selectionEnd = newSelection.selectionEnd;\n      }\n\n      this.updateTextareaPosition();\n    },\n\n    /**\n     * @private\n     */\n    updateFromTextArea: function () {\n      if (!this.hiddenTextarea) {\n        return;\n      }\n\n      this.cursorOffsetCache = {};\n      this.text = this.hiddenTextarea.value;\n\n      if (this._shouldClearDimensionCache()) {\n        this.initDimensions();\n        this.setCoords();\n      }\n\n      var newSelection = this.fromStringToGraphemeSelection(this.hiddenTextarea.selectionStart, this.hiddenTextarea.selectionEnd, this.hiddenTextarea.value);\n      this.selectionEnd = this.selectionStart = newSelection.selectionEnd;\n\n      if (!this.inCompositionMode) {\n        this.selectionStart = newSelection.selectionStart;\n      }\n\n      this.updateTextareaPosition();\n    },\n\n    /**\n     * @private\n     */\n    updateTextareaPosition: function () {\n      if (this.selectionStart === this.selectionEnd) {\n        var style = this._calcTextareaPosition();\n\n        this.hiddenTextarea.style.left = style.left;\n        this.hiddenTextarea.style.top = style.top;\n      }\n    },\n\n    /**\n     * @private\n     * @return {Object} style contains style for hiddenTextarea\n     */\n    _calcTextareaPosition: function () {\n      if (!this.canvas) {\n        return {\n          x: 1,\n          y: 1\n        };\n      }\n\n      var desiredPosition = this.inCompositionMode ? this.compositionStart : this.selectionStart,\n          boundaries = this._getCursorBoundaries(desiredPosition),\n          cursorLocation = this.get2DCursorLocation(desiredPosition),\n          lineIndex = cursorLocation.lineIndex,\n          charIndex = cursorLocation.charIndex,\n          charHeight = this.getValueOfPropertyAt(lineIndex, charIndex, 'fontSize') * this.lineHeight,\n          leftOffset = boundaries.leftOffset,\n          m = this.calcTransformMatrix(),\n          p = {\n        x: boundaries.left + leftOffset,\n        y: boundaries.top + boundaries.topOffset + charHeight\n      },\n          retinaScaling = this.canvas.getRetinaScaling(),\n          upperCanvas = this.canvas.upperCanvasEl,\n          upperCanvasWidth = upperCanvas.width / retinaScaling,\n          upperCanvasHeight = upperCanvas.height / retinaScaling,\n          maxWidth = upperCanvasWidth - charHeight,\n          maxHeight = upperCanvasHeight - charHeight,\n          scaleX = upperCanvas.clientWidth / upperCanvasWidth,\n          scaleY = upperCanvas.clientHeight / upperCanvasHeight;\n\n      p = fabric.util.transformPoint(p, m);\n      p = fabric.util.transformPoint(p, this.canvas.viewportTransform);\n      p.x *= scaleX;\n      p.y *= scaleY;\n\n      if (p.x < 0) {\n        p.x = 0;\n      }\n\n      if (p.x > maxWidth) {\n        p.x = maxWidth;\n      }\n\n      if (p.y < 0) {\n        p.y = 0;\n      }\n\n      if (p.y > maxHeight) {\n        p.y = maxHeight;\n      } // add canvas offset on document\n\n\n      p.x += this.canvas._offset.left;\n      p.y += this.canvas._offset.top;\n      return {\n        left: p.x + 'px',\n        top: p.y + 'px',\n        fontSize: charHeight + 'px',\n        charHeight: charHeight\n      };\n    },\n\n    /**\n     * @private\n     */\n    _saveEditingProps: function () {\n      this._savedProps = {\n        hasControls: this.hasControls,\n        borderColor: this.borderColor,\n        lockMovementX: this.lockMovementX,\n        lockMovementY: this.lockMovementY,\n        hoverCursor: this.hoverCursor,\n        selectable: this.selectable,\n        defaultCursor: this.canvas && this.canvas.defaultCursor,\n        moveCursor: this.canvas && this.canvas.moveCursor\n      };\n    },\n\n    /**\n     * @private\n     */\n    _restoreEditingProps: function () {\n      if (!this._savedProps) {\n        return;\n      }\n\n      this.hoverCursor = this._savedProps.hoverCursor;\n      this.hasControls = this._savedProps.hasControls;\n      this.borderColor = this._savedProps.borderColor;\n      this.selectable = this._savedProps.selectable;\n      this.lockMovementX = this._savedProps.lockMovementX;\n      this.lockMovementY = this._savedProps.lockMovementY;\n\n      if (this.canvas) {\n        this.canvas.defaultCursor = this._savedProps.defaultCursor;\n        this.canvas.moveCursor = this._savedProps.moveCursor;\n      }\n    },\n\n    /**\n     * Exits from editing state\n     * @return {fabric.IText} thisArg\n     * @chainable\n     */\n    exitEditing: function () {\n      var isTextChanged = this._textBeforeEdit !== this.text;\n      var hiddenTextarea = this.hiddenTextarea;\n      this.selected = false;\n      this.isEditing = false;\n      this.selectionEnd = this.selectionStart;\n\n      if (hiddenTextarea) {\n        hiddenTextarea.blur && hiddenTextarea.blur();\n        hiddenTextarea.parentNode && hiddenTextarea.parentNode.removeChild(hiddenTextarea);\n      }\n\n      this.hiddenTextarea = null;\n      this.abortCursorAnimation();\n\n      this._restoreEditingProps();\n\n      this._currentCursorOpacity = 0;\n\n      if (this._shouldClearDimensionCache()) {\n        this.initDimensions();\n        this.setCoords();\n      }\n\n      this.fire('editing:exited');\n      isTextChanged && this.fire('modified');\n\n      if (this.canvas) {\n        this.canvas.off('mouse:move', this.mouseMoveHandler);\n        this.canvas.fire('text:editing:exited', {\n          target: this\n        });\n        isTextChanged && this.canvas.fire('object:modified', {\n          target: this\n        });\n      }\n\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _removeExtraneousStyles: function () {\n      for (var prop in this.styles) {\n        if (!this._textLines[prop]) {\n          delete this.styles[prop];\n        }\n      }\n    },\n\n    /**\n     * remove and reflow a style block from start to end.\n     * @param {Number} start linear start position for removal (included in removal)\n     * @param {Number} end linear end position for removal ( excluded from removal )\n     */\n    removeStyleFromTo: function (start, end) {\n      var cursorStart = this.get2DCursorLocation(start, true),\n          cursorEnd = this.get2DCursorLocation(end, true),\n          lineStart = cursorStart.lineIndex,\n          charStart = cursorStart.charIndex,\n          lineEnd = cursorEnd.lineIndex,\n          charEnd = cursorEnd.charIndex,\n          i,\n          styleObj;\n\n      if (lineStart !== lineEnd) {\n        // step1 remove the trailing of lineStart\n        if (this.styles[lineStart]) {\n          for (i = charStart; i < this._unwrappedTextLines[lineStart].length; i++) {\n            delete this.styles[lineStart][i];\n          }\n        } // step2 move the trailing of lineEnd to lineStart if needed\n\n\n        if (this.styles[lineEnd]) {\n          for (i = charEnd; i < this._unwrappedTextLines[lineEnd].length; i++) {\n            styleObj = this.styles[lineEnd][i];\n\n            if (styleObj) {\n              this.styles[lineStart] || (this.styles[lineStart] = {});\n              this.styles[lineStart][charStart + i - charEnd] = styleObj;\n            }\n          }\n        } // step3 detects lines will be completely removed.\n\n\n        for (i = lineStart + 1; i <= lineEnd; i++) {\n          delete this.styles[i];\n        } // step4 shift remaining lines.\n\n\n        this.shiftLineStyles(lineEnd, lineStart - lineEnd);\n      } else {\n        // remove and shift left on the same line\n        if (this.styles[lineStart]) {\n          styleObj = this.styles[lineStart];\n\n          var diff = charEnd - charStart,\n              numericChar,\n              _char;\n\n          for (i = charStart; i < charEnd; i++) {\n            delete styleObj[i];\n          }\n\n          for (_char in this.styles[lineStart]) {\n            numericChar = parseInt(_char, 10);\n\n            if (numericChar >= charEnd) {\n              styleObj[numericChar - diff] = styleObj[_char];\n              delete styleObj[_char];\n            }\n          }\n        }\n      }\n    },\n\n    /**\n     * Shifts line styles up or down\n     * @param {Number} lineIndex Index of a line\n     * @param {Number} offset Can any number?\n     */\n    shiftLineStyles: function (lineIndex, offset) {\n      // shift all line styles by offset upward or downward\n      // do not clone deep. we need new array, not new style objects\n      var clonedStyles = clone(this.styles);\n\n      for (var line in this.styles) {\n        var numericLine = parseInt(line, 10);\n\n        if (numericLine > lineIndex) {\n          this.styles[numericLine + offset] = clonedStyles[numericLine];\n\n          if (!clonedStyles[numericLine - offset]) {\n            delete this.styles[numericLine];\n          }\n        }\n      }\n    },\n    restartCursorIfNeeded: function () {\n      if (!this._currentTickState || this._currentTickState.isAborted || !this._currentTickCompleteState || this._currentTickCompleteState.isAborted) {\n        this.initDelayedCursor();\n      }\n    },\n\n    /**\n     * Handle insertion of more consecutive style lines for when one or more\n     * newlines gets added to the text. Since current style needs to be shifted\n     * first we shift the current style of the number lines needed, then we add\n     * new lines from the last to the first.\n     * @param {Number} lineIndex Index of a line\n     * @param {Number} charIndex Index of a char\n     * @param {Number} qty number of lines to add\n     * @param {Array} copiedStyle Array of objects styles\n     */\n    insertNewlineStyleObject: function (lineIndex, charIndex, qty, copiedStyle) {\n      var currentCharStyle,\n          newLineStyles = {},\n          somethingAdded = false,\n          isEndOfLine = this._unwrappedTextLines[lineIndex].length === charIndex;\n      qty || (qty = 1);\n      this.shiftLineStyles(lineIndex, qty);\n\n      if (this.styles[lineIndex]) {\n        currentCharStyle = this.styles[lineIndex][charIndex === 0 ? charIndex : charIndex - 1];\n      } // we clone styles of all chars\n      // after cursor onto the current line\n\n\n      for (var index in this.styles[lineIndex]) {\n        var numIndex = parseInt(index, 10);\n\n        if (numIndex >= charIndex) {\n          somethingAdded = true;\n          newLineStyles[numIndex - charIndex] = this.styles[lineIndex][index]; // remove lines from the previous line since they're on a new line now\n\n          if (!(isEndOfLine && charIndex === 0)) {\n            delete this.styles[lineIndex][index];\n          }\n        }\n      }\n\n      var styleCarriedOver = false;\n\n      if (somethingAdded && !isEndOfLine) {\n        // if is end of line, the extra style we copied\n        // is probably not something we want\n        this.styles[lineIndex + qty] = newLineStyles;\n        styleCarriedOver = true;\n      }\n\n      if (styleCarriedOver) {\n        // skip the last line of since we already prepared it.\n        qty--;\n      } // for the all the lines or all the other lines\n      // we clone current char style onto the next (otherwise empty) line\n\n\n      while (qty > 0) {\n        if (copiedStyle && copiedStyle[qty - 1]) {\n          this.styles[lineIndex + qty] = {\n            0: clone(copiedStyle[qty - 1])\n          };\n        } else if (currentCharStyle) {\n          this.styles[lineIndex + qty] = {\n            0: clone(currentCharStyle)\n          };\n        } else {\n          delete this.styles[lineIndex + qty];\n        }\n\n        qty--;\n      }\n\n      this._forceClearCache = true;\n    },\n\n    /**\n     * Inserts style object for a given line/char index\n     * @param {Number} lineIndex Index of a line\n     * @param {Number} charIndex Index of a char\n     * @param {Number} quantity number Style object to insert, if given\n     * @param {Array} copiedStyle array of style objects\n     */\n    insertCharStyleObject: function (lineIndex, charIndex, quantity, copiedStyle) {\n      if (!this.styles) {\n        this.styles = {};\n      }\n\n      var currentLineStyles = this.styles[lineIndex],\n          currentLineStylesCloned = currentLineStyles ? clone(currentLineStyles) : {};\n      quantity || (quantity = 1); // shift all char styles by quantity forward\n      // 0,1,2,3 -> (charIndex=2) -> 0,1,3,4 -> (insert 2) -> 0,1,2,3,4\n\n      for (var index in currentLineStylesCloned) {\n        var numericIndex = parseInt(index, 10);\n\n        if (numericIndex >= charIndex) {\n          currentLineStyles[numericIndex + quantity] = currentLineStylesCloned[numericIndex]; // only delete the style if there was nothing moved there\n\n          if (!currentLineStylesCloned[numericIndex - quantity]) {\n            delete currentLineStyles[numericIndex];\n          }\n        }\n      }\n\n      this._forceClearCache = true;\n\n      if (copiedStyle) {\n        while (quantity--) {\n          if (!Object.keys(copiedStyle[quantity]).length) {\n            continue;\n          }\n\n          if (!this.styles[lineIndex]) {\n            this.styles[lineIndex] = {};\n          }\n\n          this.styles[lineIndex][charIndex + quantity] = clone(copiedStyle[quantity]);\n        }\n\n        return;\n      }\n\n      if (!currentLineStyles) {\n        return;\n      }\n\n      var newStyle = currentLineStyles[charIndex ? charIndex - 1 : 1];\n\n      while (newStyle && quantity--) {\n        this.styles[lineIndex][charIndex + quantity] = clone(newStyle);\n      }\n    },\n\n    /**\n     * Inserts style object(s)\n     * @param {Array} insertedText Characters at the location where style is inserted\n     * @param {Number} start cursor index for inserting style\n     * @param {Array} [copiedStyle] array of style objects to insert.\n     */\n    insertNewStyleBlock: function (insertedText, start, copiedStyle) {\n      var cursorLoc = this.get2DCursorLocation(start, true),\n          addedLines = [0],\n          linesLength = 0; // get an array of how many char per lines are being added.\n\n      for (var i = 0; i < insertedText.length; i++) {\n        if (insertedText[i] === '\\n') {\n          linesLength++;\n          addedLines[linesLength] = 0;\n        } else {\n          addedLines[linesLength]++;\n        }\n      } // for the first line copy the style from the current char position.\n\n\n      if (addedLines[0] > 0) {\n        this.insertCharStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addedLines[0], copiedStyle);\n        copiedStyle = copiedStyle && copiedStyle.slice(addedLines[0] + 1);\n      }\n\n      linesLength && this.insertNewlineStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex + addedLines[0], linesLength);\n\n      for (var i = 1; i < linesLength; i++) {\n        if (addedLines[i] > 0) {\n          this.insertCharStyleObject(cursorLoc.lineIndex + i, 0, addedLines[i], copiedStyle);\n        } else if (copiedStyle) {\n          this.styles[cursorLoc.lineIndex + i][0] = copiedStyle[0];\n        }\n\n        copiedStyle = copiedStyle && copiedStyle.slice(addedLines[i] + 1);\n      } // we use i outside the loop to get it like linesLength\n\n\n      if (addedLines[i] > 0) {\n        this.insertCharStyleObject(cursorLoc.lineIndex + i, 0, addedLines[i], copiedStyle);\n      }\n    },\n\n    /**\n     * Set the selectionStart and selectionEnd according to the new position of cursor\n     * mimic the key - mouse navigation when shift is pressed.\n     */\n    setSelectionStartEndWithShift: function (start, end, newSelection) {\n      if (newSelection <= start) {\n        if (end === start) {\n          this._selectionDirection = 'left';\n        } else if (this._selectionDirection === 'right') {\n          this._selectionDirection = 'left';\n          this.selectionEnd = start;\n        }\n\n        this.selectionStart = newSelection;\n      } else if (newSelection > start && newSelection < end) {\n        if (this._selectionDirection === 'right') {\n          this.selectionEnd = newSelection;\n        } else {\n          this.selectionStart = newSelection;\n        }\n      } else {\n        // newSelection is > selection start and end\n        if (end === start) {\n          this._selectionDirection = 'right';\n        } else if (this._selectionDirection === 'left') {\n          this._selectionDirection = 'right';\n          this.selectionStart = end;\n        }\n\n        this.selectionEnd = newSelection;\n      }\n    },\n    setSelectionInBoundaries: function () {\n      var length = this.text.length;\n\n      if (this.selectionStart > length) {\n        this.selectionStart = length;\n      } else if (this.selectionStart < 0) {\n        this.selectionStart = 0;\n      }\n\n      if (this.selectionEnd > length) {\n        this.selectionEnd = length;\n      } else if (this.selectionEnd < 0) {\n        this.selectionEnd = 0;\n      }\n    }\n  });\n})();\n\nfabric.util.object.extend(fabric.IText.prototype,\n/** @lends fabric.IText.prototype */\n{\n  /**\n   * Initializes \"dbclick\" event handler\n   */\n  initDoubleClickSimulation: function () {\n    // for double click\n    this.__lastClickTime = +new Date(); // for triple click\n\n    this.__lastLastClickTime = +new Date();\n    this.__lastPointer = {};\n    this.on('mousedown', this.onMouseDown);\n  },\n\n  /**\n   * Default event handler to simulate triple click\n   * @private\n   */\n  onMouseDown: function (options) {\n    if (!this.canvas) {\n      return;\n    }\n\n    this.__newClickTime = +new Date();\n    var newPointer = options.pointer;\n\n    if (this.isTripleClick(newPointer)) {\n      this.fire('tripleclick', options);\n\n      this._stopEvent(options.e);\n    }\n\n    this.__lastLastClickTime = this.__lastClickTime;\n    this.__lastClickTime = this.__newClickTime;\n    this.__lastPointer = newPointer;\n    this.__lastIsEditing = this.isEditing;\n    this.__lastSelected = this.selected;\n  },\n  isTripleClick: function (newPointer) {\n    return this.__newClickTime - this.__lastClickTime < 500 && this.__lastClickTime - this.__lastLastClickTime < 500 && this.__lastPointer.x === newPointer.x && this.__lastPointer.y === newPointer.y;\n  },\n\n  /**\n   * @private\n   */\n  _stopEvent: function (e) {\n    e.preventDefault && e.preventDefault();\n    e.stopPropagation && e.stopPropagation();\n  },\n\n  /**\n   * Initializes event handlers related to cursor or selection\n   */\n  initCursorSelectionHandlers: function () {\n    this.initMousedownHandler();\n    this.initMouseupHandler();\n    this.initClicks();\n  },\n\n  /**\n   * Default handler for double click, select a word\n   */\n  doubleClickHandler: function (options) {\n    if (!this.isEditing) {\n      return;\n    }\n\n    this.selectWord(this.getSelectionStartFromPointer(options.e));\n  },\n\n  /**\n   * Default handler for triple click, select a line\n   */\n  tripleClickHandler: function (options) {\n    if (!this.isEditing) {\n      return;\n    }\n\n    this.selectLine(this.getSelectionStartFromPointer(options.e));\n  },\n\n  /**\n   * Initializes double and triple click event handlers\n   */\n  initClicks: function () {\n    this.on('mousedblclick', this.doubleClickHandler);\n    this.on('tripleclick', this.tripleClickHandler);\n  },\n\n  /**\n   * Default event handler for the basic functionalities needed on _mouseDown\n   * can be overridden to do something different.\n   * Scope of this implementation is: find the click position, set selectionStart\n   * find selectionEnd, initialize the drawing of either cursor or selection area\n   * initializing a mousedDown on a text area will cancel fabricjs knowledge of\n   * current compositionMode. It will be set to false.\n   */\n  _mouseDownHandler: function (options) {\n    if (!this.canvas || !this.editable || options.e.button && options.e.button !== 1) {\n      return;\n    }\n\n    this.__isMousedown = true;\n\n    if (this.selected) {\n      this.inCompositionMode = false;\n      this.setCursorByClick(options.e);\n    }\n\n    if (this.isEditing) {\n      this.__selectionStartOnMouseDown = this.selectionStart;\n\n      if (this.selectionStart === this.selectionEnd) {\n        this.abortCursorAnimation();\n      }\n\n      this.renderCursorOrSelection();\n    }\n  },\n\n  /**\n   * Default event handler for the basic functionalities needed on mousedown:before\n   * can be overridden to do something different.\n   * Scope of this implementation is: verify the object is already selected when mousing down\n   */\n  _mouseDownHandlerBefore: function (options) {\n    if (!this.canvas || !this.editable || options.e.button && options.e.button !== 1) {\n      return;\n    } // we want to avoid that an object that was selected and then becomes unselectable,\n    // may trigger editing mode in some way.\n\n\n    this.selected = this === this.canvas._activeObject;\n  },\n\n  /**\n   * Initializes \"mousedown\" event handler\n   */\n  initMousedownHandler: function () {\n    this.on('mousedown', this._mouseDownHandler);\n    this.on('mousedown:before', this._mouseDownHandlerBefore);\n  },\n\n  /**\n   * Initializes \"mouseup\" event handler\n   */\n  initMouseupHandler: function () {\n    this.on('mouseup', this.mouseUpHandler);\n  },\n\n  /**\n   * standard hander for mouse up, overridable\n   * @private\n   */\n  mouseUpHandler: function (options) {\n    this.__isMousedown = false;\n\n    if (!this.editable || this.group || options.transform && options.transform.actionPerformed || options.e.button && options.e.button !== 1) {\n      return;\n    }\n\n    if (this.canvas) {\n      var currentActive = this.canvas._activeObject;\n\n      if (currentActive && currentActive !== this) {\n        // avoid running this logic when there is an active object\n        // this because is possible with shift click and fast clicks,\n        // to rapidly deselect and reselect this object and trigger an enterEdit\n        return;\n      }\n    }\n\n    if (this.__lastSelected && !this.__corner) {\n      this.selected = false;\n      this.__lastSelected = false;\n      this.enterEditing(options.e);\n\n      if (this.selectionStart === this.selectionEnd) {\n        this.initDelayedCursor(true);\n      } else {\n        this.renderCursorOrSelection();\n      }\n    } else {\n      this.selected = true;\n    }\n  },\n\n  /**\n   * Changes cursor location in a text depending on passed pointer (x/y) object\n   * @param {Event} e Event object\n   */\n  setCursorByClick: function (e) {\n    var newSelection = this.getSelectionStartFromPointer(e),\n        start = this.selectionStart,\n        end = this.selectionEnd;\n\n    if (e.shiftKey) {\n      this.setSelectionStartEndWithShift(start, end, newSelection);\n    } else {\n      this.selectionStart = newSelection;\n      this.selectionEnd = newSelection;\n    }\n\n    if (this.isEditing) {\n      this._fireSelectionChanged();\n\n      this._updateTextarea();\n    }\n  },\n\n  /**\n   * Returns index of a character corresponding to where an object was clicked\n   * @param {Event} e Event object\n   * @return {Number} Index of a character\n   */\n  getSelectionStartFromPointer: function (e) {\n    var mouseOffset = this.getLocalPointer(e),\n        prevWidth = 0,\n        width = 0,\n        height = 0,\n        charIndex = 0,\n        lineIndex = 0,\n        lineLeftOffset,\n        line;\n\n    for (var i = 0, len = this._textLines.length; i < len; i++) {\n      if (height <= mouseOffset.y) {\n        height += this.getHeightOfLine(i) * this.scaleY;\n        lineIndex = i;\n\n        if (i > 0) {\n          charIndex += this._textLines[i - 1].length + this.missingNewlineOffset(i - 1);\n        }\n      } else {\n        break;\n      }\n    }\n\n    lineLeftOffset = this._getLineLeftOffset(lineIndex);\n    width = lineLeftOffset * this.scaleX;\n    line = this._textLines[lineIndex];\n\n    for (var j = 0, jlen = line.length; j < jlen; j++) {\n      prevWidth = width; // i removed something about flipX here, check.\n\n      width += this.__charBounds[lineIndex][j].kernedWidth * this.scaleX;\n\n      if (width <= mouseOffset.x) {\n        charIndex++;\n      } else {\n        break;\n      }\n    }\n\n    return this._getNewSelectionStartFromOffset(mouseOffset, prevWidth, width, charIndex, jlen);\n  },\n\n  /**\n   * @private\n   */\n  _getNewSelectionStartFromOffset: function (mouseOffset, prevWidth, width, index, jlen) {\n    // we need Math.abs because when width is after the last char, the offset is given as 1, while is 0\n    var distanceBtwLastCharAndCursor = mouseOffset.x - prevWidth,\n        distanceBtwNextCharAndCursor = width - mouseOffset.x,\n        offset = distanceBtwNextCharAndCursor > distanceBtwLastCharAndCursor || distanceBtwNextCharAndCursor < 0 ? 0 : 1,\n        newSelectionStart = index + offset; // if object is horizontally flipped, mirror cursor location from the end\n\n    if (this.flipX) {\n      newSelectionStart = jlen - newSelectionStart;\n    }\n\n    if (newSelectionStart > this._text.length) {\n      newSelectionStart = this._text.length;\n    }\n\n    return newSelectionStart;\n  }\n});\nfabric.util.object.extend(fabric.IText.prototype,\n/** @lends fabric.IText.prototype */\n{\n  /**\n   * Initializes hidden textarea (needed to bring up keyboard in iOS)\n   */\n  initHiddenTextarea: function () {\n    this.hiddenTextarea = fabric.document.createElement('textarea');\n    this.hiddenTextarea.setAttribute('autocapitalize', 'off');\n    this.hiddenTextarea.setAttribute('autocorrect', 'off');\n    this.hiddenTextarea.setAttribute('autocomplete', 'off');\n    this.hiddenTextarea.setAttribute('spellcheck', 'false');\n    this.hiddenTextarea.setAttribute('data-fabric-hiddentextarea', '');\n    this.hiddenTextarea.setAttribute('wrap', 'off');\n\n    var style = this._calcTextareaPosition(); // line-height: 1px; was removed from the style to fix this:\n    // https://bugs.chromium.org/p/chromium/issues/detail?id=870966\n\n\n    this.hiddenTextarea.style.cssText = 'position: absolute; top: ' + style.top + '; left: ' + style.left + '; z-index: -999; opacity: 0; width: 1px; height: 1px; font-size: 1px;' + ' paddingーtop: ' + style.fontSize + ';';\n    fabric.document.body.appendChild(this.hiddenTextarea);\n    fabric.util.addListener(this.hiddenTextarea, 'keydown', this.onKeyDown.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'keyup', this.onKeyUp.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'input', this.onInput.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'copy', this.copy.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'cut', this.copy.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'paste', this.paste.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'compositionstart', this.onCompositionStart.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'compositionupdate', this.onCompositionUpdate.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'compositionend', this.onCompositionEnd.bind(this));\n\n    if (!this._clickHandlerInitialized && this.canvas) {\n      fabric.util.addListener(this.canvas.upperCanvasEl, 'click', this.onClick.bind(this));\n      this._clickHandlerInitialized = true;\n    }\n  },\n\n  /**\n   * For functionalities on keyDown\n   * Map a special key to a function of the instance/prototype\n   * If you need different behaviour for ESC or TAB or arrows, you have to change\n   * this map setting the name of a function that you build on the fabric.Itext or\n   * your prototype.\n   * the map change will affect all Instances unless you need for only some text Instances\n   * in that case you have to clone this object and assign your Instance.\n   * this.keysMap = fabric.util.object.clone(this.keysMap);\n   * The function must be in fabric.Itext.prototype.myFunction And will receive event as args[0]\n   */\n  keysMap: {\n    9: 'exitEditing',\n    27: 'exitEditing',\n    33: 'moveCursorUp',\n    34: 'moveCursorDown',\n    35: 'moveCursorRight',\n    36: 'moveCursorLeft',\n    37: 'moveCursorLeft',\n    38: 'moveCursorUp',\n    39: 'moveCursorRight',\n    40: 'moveCursorDown'\n  },\n\n  /**\n   * For functionalities on keyUp + ctrl || cmd\n   */\n  ctrlKeysMapUp: {\n    67: 'copy',\n    88: 'cut'\n  },\n\n  /**\n   * For functionalities on keyDown + ctrl || cmd\n   */\n  ctrlKeysMapDown: {\n    65: 'selectAll'\n  },\n  onClick: function () {\n    // No need to trigger click event here, focus is enough to have the keyboard appear on Android\n    this.hiddenTextarea && this.hiddenTextarea.focus();\n  },\n\n  /**\n   * Handles keydown event\n   * only used for arrows and combination of modifier keys.\n   * @param {Event} e Event object\n   */\n  onKeyDown: function (e) {\n    if (!this.isEditing) {\n      return;\n    }\n\n    if (e.keyCode in this.keysMap) {\n      this[this.keysMap[e.keyCode]](e);\n    } else if (e.keyCode in this.ctrlKeysMapDown && (e.ctrlKey || e.metaKey)) {\n      this[this.ctrlKeysMapDown[e.keyCode]](e);\n    } else {\n      return;\n    }\n\n    e.stopImmediatePropagation();\n    e.preventDefault();\n\n    if (e.keyCode >= 33 && e.keyCode <= 40) {\n      // if i press an arrow key just update selection\n      this.inCompositionMode = false;\n      this.clearContextTop();\n      this.renderCursorOrSelection();\n    } else {\n      this.canvas && this.canvas.requestRenderAll();\n    }\n  },\n\n  /**\n   * Handles keyup event\n   * We handle KeyUp because ie11 and edge have difficulties copy/pasting\n   * if a copy/cut event fired, keyup is dismissed\n   * @param {Event} e Event object\n   */\n  onKeyUp: function (e) {\n    if (!this.isEditing || this._copyDone || this.inCompositionMode) {\n      this._copyDone = false;\n      return;\n    }\n\n    if (e.keyCode in this.ctrlKeysMapUp && (e.ctrlKey || e.metaKey)) {\n      this[this.ctrlKeysMapUp[e.keyCode]](e);\n    } else {\n      return;\n    }\n\n    e.stopImmediatePropagation();\n    e.preventDefault();\n    this.canvas && this.canvas.requestRenderAll();\n  },\n\n  /**\n   * Handles onInput event\n   * @param {Event} e Event object\n   */\n  onInput: function (e) {\n    var fromPaste = this.fromPaste;\n    this.fromPaste = false;\n    e && e.stopPropagation();\n\n    if (!this.isEditing) {\n      return;\n    } // decisions about style changes.\n\n\n    var nextText = this._splitTextIntoLines(this.hiddenTextarea.value).graphemeText,\n        charCount = this._text.length,\n        nextCharCount = nextText.length,\n        removedText,\n        insertedText,\n        charDiff = nextCharCount - charCount,\n        selectionStart = this.selectionStart,\n        selectionEnd = this.selectionEnd,\n        selection = selectionStart !== selectionEnd,\n        copiedStyle,\n        removeFrom,\n        removeTo;\n\n    if (this.hiddenTextarea.value === '') {\n      this.styles = {};\n      this.updateFromTextArea();\n      this.fire('changed');\n\n      if (this.canvas) {\n        this.canvas.fire('text:changed', {\n          target: this\n        });\n        this.canvas.requestRenderAll();\n      }\n\n      return;\n    }\n\n    var textareaSelection = this.fromStringToGraphemeSelection(this.hiddenTextarea.selectionStart, this.hiddenTextarea.selectionEnd, this.hiddenTextarea.value);\n    var backDelete = selectionStart > textareaSelection.selectionStart;\n\n    if (selection) {\n      removedText = this._text.slice(selectionStart, selectionEnd);\n      charDiff += selectionEnd - selectionStart;\n    } else if (nextCharCount < charCount) {\n      if (backDelete) {\n        removedText = this._text.slice(selectionEnd + charDiff, selectionEnd);\n      } else {\n        removedText = this._text.slice(selectionStart, selectionStart - charDiff);\n      }\n    }\n\n    insertedText = nextText.slice(textareaSelection.selectionEnd - charDiff, textareaSelection.selectionEnd);\n\n    if (removedText && removedText.length) {\n      if (insertedText.length) {\n        // let's copy some style before deleting.\n        // we want to copy the style before the cursor OR the style at the cursor if selection\n        // is bigger than 0.\n        copiedStyle = this.getSelectionStyles(selectionStart, selectionStart + 1, false); // now duplicate the style one for each inserted text.\n\n        copiedStyle = insertedText.map(function () {\n          // this return an array of references, but that is fine since we are\n          // copying the style later.\n          return copiedStyle[0];\n        });\n      }\n\n      if (selection) {\n        removeFrom = selectionStart;\n        removeTo = selectionEnd;\n      } else if (backDelete) {\n        // detect differencies between forwardDelete and backDelete\n        removeFrom = selectionEnd - removedText.length;\n        removeTo = selectionEnd;\n      } else {\n        removeFrom = selectionEnd;\n        removeTo = selectionEnd + removedText.length;\n      }\n\n      this.removeStyleFromTo(removeFrom, removeTo);\n    }\n\n    if (insertedText.length) {\n      if (fromPaste && insertedText.join('') === fabric.copiedText && !fabric.disableStyleCopyPaste) {\n        copiedStyle = fabric.copiedTextStyle;\n      }\n\n      this.insertNewStyleBlock(insertedText, selectionStart, copiedStyle);\n    }\n\n    this.updateFromTextArea();\n    this.fire('changed');\n\n    if (this.canvas) {\n      this.canvas.fire('text:changed', {\n        target: this\n      });\n      this.canvas.requestRenderAll();\n    }\n  },\n\n  /**\n   * Composition start\n   */\n  onCompositionStart: function () {\n    this.inCompositionMode = true;\n  },\n\n  /**\n   * Composition end\n   */\n  onCompositionEnd: function () {\n    this.inCompositionMode = false;\n  },\n  // /**\n  //  * Composition update\n  //  */\n  onCompositionUpdate: function (e) {\n    this.compositionStart = e.target.selectionStart;\n    this.compositionEnd = e.target.selectionEnd;\n    this.updateTextareaPosition();\n  },\n\n  /**\n   * Copies selected text\n   * @param {Event} e Event object\n   */\n  copy: function () {\n    if (this.selectionStart === this.selectionEnd) {\n      //do not cut-copy if no selection\n      return;\n    }\n\n    fabric.copiedText = this.getSelectedText();\n\n    if (!fabric.disableStyleCopyPaste) {\n      fabric.copiedTextStyle = this.getSelectionStyles(this.selectionStart, this.selectionEnd, true);\n    } else {\n      fabric.copiedTextStyle = null;\n    }\n\n    this._copyDone = true;\n  },\n\n  /**\n   * Pastes text\n   * @param {Event} e Event object\n   */\n  paste: function () {\n    this.fromPaste = true;\n  },\n\n  /**\n   * @private\n   * @param {Event} e Event object\n   * @return {Object} Clipboard data object\n   */\n  _getClipboardData: function (e) {\n    return e && e.clipboardData || fabric.window.clipboardData;\n  },\n\n  /**\n   * Finds the width in pixels before the cursor on the same line\n   * @private\n   * @param {Number} lineIndex\n   * @param {Number} charIndex\n   * @return {Number} widthBeforeCursor width before cursor\n   */\n  _getWidthBeforeCursor: function (lineIndex, charIndex) {\n    var widthBeforeCursor = this._getLineLeftOffset(lineIndex),\n        bound;\n\n    if (charIndex > 0) {\n      bound = this.__charBounds[lineIndex][charIndex - 1];\n      widthBeforeCursor += bound.left + bound.width;\n    }\n\n    return widthBeforeCursor;\n  },\n\n  /**\n   * Gets start offset of a selection\n   * @param {Event} e Event object\n   * @param {Boolean} isRight\n   * @return {Number}\n   */\n  getDownCursorOffset: function (e, isRight) {\n    var selectionProp = this._getSelectionForOffset(e, isRight),\n        cursorLocation = this.get2DCursorLocation(selectionProp),\n        lineIndex = cursorLocation.lineIndex; // if on last line, down cursor goes to end of line\n\n\n    if (lineIndex === this._textLines.length - 1 || e.metaKey || e.keyCode === 34) {\n      // move to the end of a text\n      return this._text.length - selectionProp;\n    }\n\n    var charIndex = cursorLocation.charIndex,\n        widthBeforeCursor = this._getWidthBeforeCursor(lineIndex, charIndex),\n        indexOnOtherLine = this._getIndexOnLine(lineIndex + 1, widthBeforeCursor),\n        textAfterCursor = this._textLines[lineIndex].slice(charIndex);\n\n    return textAfterCursor.length + indexOnOtherLine + 1 + this.missingNewlineOffset(lineIndex);\n  },\n\n  /**\n   * private\n   * Helps finding if the offset should be counted from Start or End\n   * @param {Event} e Event object\n   * @param {Boolean} isRight\n   * @return {Number}\n   */\n  _getSelectionForOffset: function (e, isRight) {\n    if (e.shiftKey && this.selectionStart !== this.selectionEnd && isRight) {\n      return this.selectionEnd;\n    } else {\n      return this.selectionStart;\n    }\n  },\n\n  /**\n   * @param {Event} e Event object\n   * @param {Boolean} isRight\n   * @return {Number}\n   */\n  getUpCursorOffset: function (e, isRight) {\n    var selectionProp = this._getSelectionForOffset(e, isRight),\n        cursorLocation = this.get2DCursorLocation(selectionProp),\n        lineIndex = cursorLocation.lineIndex;\n\n    if (lineIndex === 0 || e.metaKey || e.keyCode === 33) {\n      // if on first line, up cursor goes to start of line\n      return -selectionProp;\n    }\n\n    var charIndex = cursorLocation.charIndex,\n        widthBeforeCursor = this._getWidthBeforeCursor(lineIndex, charIndex),\n        indexOnOtherLine = this._getIndexOnLine(lineIndex - 1, widthBeforeCursor),\n        textBeforeCursor = this._textLines[lineIndex].slice(0, charIndex),\n        missingNewlineOffset = this.missingNewlineOffset(lineIndex - 1); // return a negative offset\n\n\n    return -this._textLines[lineIndex - 1].length + indexOnOtherLine - textBeforeCursor.length + (1 - missingNewlineOffset);\n  },\n\n  /**\n   * for a given width it founds the matching character.\n   * @private\n   */\n  _getIndexOnLine: function (lineIndex, width) {\n    var line = this._textLines[lineIndex],\n        lineLeftOffset = this._getLineLeftOffset(lineIndex),\n        widthOfCharsOnLine = lineLeftOffset,\n        indexOnLine = 0,\n        charWidth,\n        foundMatch;\n\n    for (var j = 0, jlen = line.length; j < jlen; j++) {\n      charWidth = this.__charBounds[lineIndex][j].width;\n      widthOfCharsOnLine += charWidth;\n\n      if (widthOfCharsOnLine > width) {\n        foundMatch = true;\n        var leftEdge = widthOfCharsOnLine - charWidth,\n            rightEdge = widthOfCharsOnLine,\n            offsetFromLeftEdge = Math.abs(leftEdge - width),\n            offsetFromRightEdge = Math.abs(rightEdge - width);\n        indexOnLine = offsetFromRightEdge < offsetFromLeftEdge ? j : j - 1;\n        break;\n      }\n    } // reached end\n\n\n    if (!foundMatch) {\n      indexOnLine = line.length - 1;\n    }\n\n    return indexOnLine;\n  },\n\n  /**\n   * Moves cursor down\n   * @param {Event} e Event object\n   */\n  moveCursorDown: function (e) {\n    if (this.selectionStart >= this._text.length && this.selectionEnd >= this._text.length) {\n      return;\n    }\n\n    this._moveCursorUpOrDown('Down', e);\n  },\n\n  /**\n   * Moves cursor up\n   * @param {Event} e Event object\n   */\n  moveCursorUp: function (e) {\n    if (this.selectionStart === 0 && this.selectionEnd === 0) {\n      return;\n    }\n\n    this._moveCursorUpOrDown('Up', e);\n  },\n\n  /**\n   * Moves cursor up or down, fires the events\n   * @param {String} direction 'Up' or 'Down'\n   * @param {Event} e Event object\n   */\n  _moveCursorUpOrDown: function (direction, e) {\n    // getUpCursorOffset\n    // getDownCursorOffset\n    var action = 'get' + direction + 'CursorOffset',\n        offset = this[action](e, this._selectionDirection === 'right');\n\n    if (e.shiftKey) {\n      this.moveCursorWithShift(offset);\n    } else {\n      this.moveCursorWithoutShift(offset);\n    }\n\n    if (offset !== 0) {\n      this.setSelectionInBoundaries();\n      this.abortCursorAnimation();\n      this._currentCursorOpacity = 1;\n      this.initDelayedCursor();\n\n      this._fireSelectionChanged();\n\n      this._updateTextarea();\n    }\n  },\n\n  /**\n   * Moves cursor with shift\n   * @param {Number} offset\n   */\n  moveCursorWithShift: function (offset) {\n    var newSelection = this._selectionDirection === 'left' ? this.selectionStart + offset : this.selectionEnd + offset;\n    this.setSelectionStartEndWithShift(this.selectionStart, this.selectionEnd, newSelection);\n    return offset !== 0;\n  },\n\n  /**\n   * Moves cursor up without shift\n   * @param {Number} offset\n   */\n  moveCursorWithoutShift: function (offset) {\n    if (offset < 0) {\n      this.selectionStart += offset;\n      this.selectionEnd = this.selectionStart;\n    } else {\n      this.selectionEnd += offset;\n      this.selectionStart = this.selectionEnd;\n    }\n\n    return offset !== 0;\n  },\n\n  /**\n   * Moves cursor left\n   * @param {Event} e Event object\n   */\n  moveCursorLeft: function (e) {\n    if (this.selectionStart === 0 && this.selectionEnd === 0) {\n      return;\n    }\n\n    this._moveCursorLeftOrRight('Left', e);\n  },\n\n  /**\n   * @private\n   * @return {Boolean} true if a change happened\n   */\n  _move: function (e, prop, direction) {\n    var newValue;\n\n    if (e.altKey) {\n      newValue = this['findWordBoundary' + direction](this[prop]);\n    } else if (e.metaKey || e.keyCode === 35 || e.keyCode === 36) {\n      newValue = this['findLineBoundary' + direction](this[prop]);\n    } else {\n      this[prop] += direction === 'Left' ? -1 : 1;\n      return true;\n    }\n\n    if (typeof newValue !== undefined && this[prop] !== newValue) {\n      this[prop] = newValue;\n      return true;\n    }\n  },\n\n  /**\n   * @private\n   */\n  _moveLeft: function (e, prop) {\n    return this._move(e, prop, 'Left');\n  },\n\n  /**\n   * @private\n   */\n  _moveRight: function (e, prop) {\n    return this._move(e, prop, 'Right');\n  },\n\n  /**\n   * Moves cursor left without keeping selection\n   * @param {Event} e\n   */\n  moveCursorLeftWithoutShift: function (e) {\n    var change = true;\n    this._selectionDirection = 'left'; // only move cursor when there is no selection,\n    // otherwise we discard it, and leave cursor on same place\n\n    if (this.selectionEnd === this.selectionStart && this.selectionStart !== 0) {\n      change = this._moveLeft(e, 'selectionStart');\n    }\n\n    this.selectionEnd = this.selectionStart;\n    return change;\n  },\n\n  /**\n   * Moves cursor left while keeping selection\n   * @param {Event} e\n   */\n  moveCursorLeftWithShift: function (e) {\n    if (this._selectionDirection === 'right' && this.selectionStart !== this.selectionEnd) {\n      return this._moveLeft(e, 'selectionEnd');\n    } else if (this.selectionStart !== 0) {\n      this._selectionDirection = 'left';\n      return this._moveLeft(e, 'selectionStart');\n    }\n  },\n\n  /**\n   * Moves cursor right\n   * @param {Event} e Event object\n   */\n  moveCursorRight: function (e) {\n    if (this.selectionStart >= this._text.length && this.selectionEnd >= this._text.length) {\n      return;\n    }\n\n    this._moveCursorLeftOrRight('Right', e);\n  },\n\n  /**\n   * Moves cursor right or Left, fires event\n   * @param {String} direction 'Left', 'Right'\n   * @param {Event} e Event object\n   */\n  _moveCursorLeftOrRight: function (direction, e) {\n    var actionName = 'moveCursor' + direction + 'With';\n    this._currentCursorOpacity = 1;\n\n    if (e.shiftKey) {\n      actionName += 'Shift';\n    } else {\n      actionName += 'outShift';\n    }\n\n    if (this[actionName](e)) {\n      this.abortCursorAnimation();\n      this.initDelayedCursor();\n\n      this._fireSelectionChanged();\n\n      this._updateTextarea();\n    }\n  },\n\n  /**\n   * Moves cursor right while keeping selection\n   * @param {Event} e\n   */\n  moveCursorRightWithShift: function (e) {\n    if (this._selectionDirection === 'left' && this.selectionStart !== this.selectionEnd) {\n      return this._moveRight(e, 'selectionStart');\n    } else if (this.selectionEnd !== this._text.length) {\n      this._selectionDirection = 'right';\n      return this._moveRight(e, 'selectionEnd');\n    }\n  },\n\n  /**\n   * Moves cursor right without keeping selection\n   * @param {Event} e Event object\n   */\n  moveCursorRightWithoutShift: function (e) {\n    var changed = true;\n    this._selectionDirection = 'right';\n\n    if (this.selectionStart === this.selectionEnd) {\n      changed = this._moveRight(e, 'selectionStart');\n      this.selectionEnd = this.selectionStart;\n    } else {\n      this.selectionStart = this.selectionEnd;\n    }\n\n    return changed;\n  },\n\n  /**\n   * Removes characters from start/end\n   * start/end ar per grapheme position in _text array.\n   *\n   * @param {Number} start\n   * @param {Number} end default to start + 1\n   */\n  removeChars: function (start, end) {\n    if (typeof end === 'undefined') {\n      end = start + 1;\n    }\n\n    this.removeStyleFromTo(start, end);\n\n    this._text.splice(start, end - start);\n\n    this.text = this._text.join('');\n    this.set('dirty', true);\n\n    if (this._shouldClearDimensionCache()) {\n      this.initDimensions();\n      this.setCoords();\n    }\n\n    this._removeExtraneousStyles();\n  },\n\n  /**\n   * insert characters at start position, before start position.\n   * start  equal 1 it means the text get inserted between actual grapheme 0 and 1\n   * if style array is provided, it must be as the same length of text in graphemes\n   * if end is provided and is bigger than start, old text is replaced.\n   * start/end ar per grapheme position in _text array.\n   *\n   * @param {String} text text to insert\n   * @param {Array} style array of style objects\n   * @param {Number} start\n   * @param {Number} end default to start + 1\n   */\n  insertChars: function (text, style, start, end) {\n    if (typeof end === 'undefined') {\n      end = start;\n    }\n\n    if (end > start) {\n      this.removeStyleFromTo(start, end);\n    }\n\n    var graphemes = fabric.util.string.graphemeSplit(text);\n    this.insertNewStyleBlock(graphemes, start, style);\n    this._text = [].concat(this._text.slice(0, start), graphemes, this._text.slice(end));\n    this.text = this._text.join('');\n    this.set('dirty', true);\n\n    if (this._shouldClearDimensionCache()) {\n      this.initDimensions();\n      this.setCoords();\n    }\n\n    this._removeExtraneousStyles();\n  }\n});\n/* _TO_SVG_START_ */\n\n(function () {\n  var toFixed = fabric.util.toFixed,\n      multipleSpacesRegex = /  +/g;\n  fabric.util.object.extend(fabric.Text.prototype,\n  /** @lends fabric.Text.prototype */\n  {\n    /**\n     * Returns SVG representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    _toSVG: function () {\n      var offsets = this._getSVGLeftTopOffsets(),\n          textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft);\n\n      return this._wrapSVGTextAndBg(textAndBg);\n    },\n\n    /**\n     * Returns svg representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    toSVG: function (reviver) {\n      return this._createBaseSVGMarkup(this._toSVG(), {\n        reviver: reviver,\n        noStyle: true,\n        withShadow: true\n      });\n    },\n\n    /**\n     * @private\n     */\n    _getSVGLeftTopOffsets: function () {\n      return {\n        textLeft: -this.width / 2,\n        textTop: -this.height / 2,\n        lineTop: this.getHeightOfLine(0)\n      };\n    },\n\n    /**\n     * @private\n     */\n    _wrapSVGTextAndBg: function (textAndBg) {\n      var noShadow = true,\n          textDecoration = this.getSvgTextDecoration(this);\n      return [textAndBg.textBgRects.join(''), '\\t\\t<text xml:space=\"preserve\" ', this.fontFamily ? 'font-family=\"' + this.fontFamily.replace(/\"/g, '\\'') + '\" ' : '', this.fontSize ? 'font-size=\"' + this.fontSize + '\" ' : '', this.fontStyle ? 'font-style=\"' + this.fontStyle + '\" ' : '', this.fontWeight ? 'font-weight=\"' + this.fontWeight + '\" ' : '', textDecoration ? 'text-decoration=\"' + textDecoration + '\" ' : '', 'style=\"', this.getSvgStyles(noShadow), '\"', this.addPaintOrder(), ' >', textAndBg.textSpans.join(''), '</text>\\n'];\n    },\n\n    /**\n     * @private\n     * @param {Number} textTopOffset Text top offset\n     * @param {Number} textLeftOffset Text left offset\n     * @return {Object}\n     */\n    _getSVGTextAndBg: function (textTopOffset, textLeftOffset) {\n      var textSpans = [],\n          textBgRects = [],\n          height = textTopOffset,\n          lineOffset; // bounding-box background\n\n      this._setSVGBg(textBgRects); // text and text-background\n\n\n      for (var i = 0, len = this._textLines.length; i < len; i++) {\n        lineOffset = this._getLineLeftOffset(i);\n\n        if (this.textBackgroundColor || this.styleHas('textBackgroundColor', i)) {\n          this._setSVGTextLineBg(textBgRects, i, textLeftOffset + lineOffset, height);\n        }\n\n        this._setSVGTextLineText(textSpans, i, textLeftOffset + lineOffset, height);\n\n        height += this.getHeightOfLine(i);\n      }\n\n      return {\n        textSpans: textSpans,\n        textBgRects: textBgRects\n      };\n    },\n\n    /**\n     * @private\n     */\n    _createTextCharSpan: function (_char, styleDecl, left, top) {\n      var shouldUseWhitespace = _char !== _char.trim() || _char.match(multipleSpacesRegex),\n          styleProps = this.getSvgSpanStyles(styleDecl, shouldUseWhitespace),\n          fillStyles = styleProps ? 'style=\"' + styleProps + '\"' : '',\n          dy = styleDecl.deltaY,\n          dySpan = '',\n          NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n\n      if (dy) {\n        dySpan = ' dy=\"' + toFixed(dy, NUM_FRACTION_DIGITS) + '\" ';\n      }\n\n      return ['<tspan x=\"', toFixed(left, NUM_FRACTION_DIGITS), '\" y=\"', toFixed(top, NUM_FRACTION_DIGITS), '\" ', dySpan, fillStyles, '>', fabric.util.string.escapeXml(_char), '</tspan>'].join('');\n    },\n    _setSVGTextLineText: function (textSpans, lineIndex, textLeftOffset, textTopOffset) {\n      // set proper line offset\n      var lineHeight = this.getHeightOfLine(lineIndex),\n          isJustify = this.textAlign.indexOf('justify') !== -1,\n          actualStyle,\n          nextStyle,\n          charsToRender = '',\n          charBox,\n          style,\n          boxWidth = 0,\n          line = this._textLines[lineIndex],\n          timeToRender;\n      textTopOffset += lineHeight * (1 - this._fontSizeFraction) / this.lineHeight;\n\n      for (var i = 0, len = line.length - 1; i <= len; i++) {\n        timeToRender = i === len || this.charSpacing;\n        charsToRender += line[i];\n        charBox = this.__charBounds[lineIndex][i];\n\n        if (boxWidth === 0) {\n          textLeftOffset += charBox.kernedWidth - charBox.width;\n          boxWidth += charBox.width;\n        } else {\n          boxWidth += charBox.kernedWidth;\n        }\n\n        if (isJustify && !timeToRender) {\n          if (this._reSpaceAndTab.test(line[i])) {\n            timeToRender = true;\n          }\n        }\n\n        if (!timeToRender) {\n          // if we have charSpacing, we render char by char\n          actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\n          nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\n          timeToRender = this._hasStyleChangedForSvg(actualStyle, nextStyle);\n        }\n\n        if (timeToRender) {\n          style = this._getStyleDeclaration(lineIndex, i) || {};\n          textSpans.push(this._createTextCharSpan(charsToRender, style, textLeftOffset, textTopOffset));\n          charsToRender = '';\n          actualStyle = nextStyle;\n          textLeftOffset += boxWidth;\n          boxWidth = 0;\n        }\n      }\n    },\n    _pushTextBgRect: function (textBgRects, color, left, top, width, height) {\n      var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n      textBgRects.push('\\t\\t<rect ', this._getFillAttributes(color), ' x=\"', toFixed(left, NUM_FRACTION_DIGITS), '\" y=\"', toFixed(top, NUM_FRACTION_DIGITS), '\" width=\"', toFixed(width, NUM_FRACTION_DIGITS), '\" height=\"', toFixed(height, NUM_FRACTION_DIGITS), '\"></rect>\\n');\n    },\n    _setSVGTextLineBg: function (textBgRects, i, leftOffset, textTopOffset) {\n      var line = this._textLines[i],\n          heightOfLine = this.getHeightOfLine(i) / this.lineHeight,\n          boxWidth = 0,\n          boxStart = 0,\n          charBox,\n          currentColor,\n          lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\n\n      for (var j = 0, jlen = line.length; j < jlen; j++) {\n        charBox = this.__charBounds[i][j];\n        currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\n\n        if (currentColor !== lastColor) {\n          lastColor && this._pushTextBgRect(textBgRects, lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine);\n          boxStart = charBox.left;\n          boxWidth = charBox.width;\n          lastColor = currentColor;\n        } else {\n          boxWidth += charBox.kernedWidth;\n        }\n      }\n\n      currentColor && this._pushTextBgRect(textBgRects, currentColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine);\n    },\n\n    /**\n     * Adobe Illustrator (at least CS5) is unable to render rgba()-based fill values\n     * we work around it by \"moving\" alpha channel into opacity attribute and setting fill's alpha to 1\n     *\n     * @private\n     * @param {*} value\n     * @return {String}\n     */\n    _getFillAttributes: function (value) {\n      var fillColor = value && typeof value === 'string' ? new fabric.Color(value) : '';\n\n      if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) {\n        return 'fill=\"' + value + '\"';\n      }\n\n      return 'opacity=\"' + fillColor.getAlpha() + '\" fill=\"' + fillColor.setAlpha(1).toRgb() + '\"';\n    },\n\n    /**\n     * @private\n     */\n    _getSVGLineTopOffset: function (lineIndex) {\n      var lineTopOffset = 0,\n          lastHeight = 0;\n\n      for (var j = 0; j < lineIndex; j++) {\n        lineTopOffset += this.getHeightOfLine(j);\n      }\n\n      lastHeight = this.getHeightOfLine(j);\n      return {\n        lineTop: lineTopOffset,\n        offset: (this._fontSizeMult - this._fontSizeFraction) * lastHeight / (this.lineHeight * this._fontSizeMult)\n      };\n    },\n\n    /**\n     * Returns styles-string for svg-export\n     * @param {Boolean} skipShadow a boolean to skip shadow filter output\n     * @return {String}\n     */\n    getSvgStyles: function (skipShadow) {\n      var svgStyle = fabric.Object.prototype.getSvgStyles.call(this, skipShadow);\n      return svgStyle + ' white-space: pre;';\n    }\n  });\n})();\n/* _TO_SVG_END_ */\n\n\n(function (global) {\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {});\n  /**\n   * Textbox class, based on IText, allows the user to resize the text rectangle\n   * and wraps lines automatically. Textboxes have their Y scaling locked, the\n   * user can only change width. Height is adjusted automatically based on the\n   * wrapping of lines.\n   * @class fabric.Textbox\n   * @extends fabric.IText\n   * @mixes fabric.Observable\n   * @return {fabric.Textbox} thisArg\n   * @see {@link fabric.Textbox#initialize} for constructor definition\n   */\n\n  fabric.Textbox = fabric.util.createClass(fabric.IText, fabric.Observable, {\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'textbox',\n\n    /**\n     * Minimum width of textbox, in pixels.\n     * @type Number\n     * @default\n     */\n    minWidth: 20,\n\n    /**\n     * Minimum calculated width of a textbox, in pixels.\n     * fixed to 2 so that an empty textbox cannot go to 0\n     * and is still selectable without text.\n     * @type Number\n     * @default\n     */\n    dynamicMinWidth: 2,\n\n    /**\n     * Cached array of text wrapping.\n     * @type Array\n     */\n    __cachedLines: null,\n\n    /**\n     * Override standard Object class values\n     */\n    lockScalingFlip: true,\n\n    /**\n     * Override standard Object class values\n     * Textbox needs this on false\n     */\n    noScaleCache: false,\n\n    /**\n     * Properties which when set cause object to change dimensions\n     * @type Object\n     * @private\n     */\n    _dimensionAffectingProps: fabric.Text.prototype._dimensionAffectingProps.concat('width'),\n\n    /**\n     * Use this regular expression to split strings in breakable lines\n     * @private\n     */\n    _wordJoiners: /[ \\t\\r]/,\n\n    /**\n     * Use this boolean property in order to split strings that have no white space concept.\n     * this is a cheap way to help with chinese/japaense\n     * @type Boolean\n     * @since 2.6.0\n     */\n    splitByGrapheme: false,\n\n    /**\n     * Unlike superclass's version of this function, Textbox does not update\n     * its width.\n     * @private\n     * @override\n     */\n    initDimensions: function () {\n      if (this.__skipDimension) {\n        return;\n      }\n\n      this.isEditing && this.initDelayedCursor();\n      this.clearContextTop();\n\n      this._clearCache(); // clear dynamicMinWidth as it will be different after we re-wrap line\n\n\n      this.dynamicMinWidth = 0; // wrap lines\n\n      this._styleMap = this._generateStyleMap(this._splitText()); // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n\n      if (this.dynamicMinWidth > this.width) {\n        this._set('width', this.dynamicMinWidth);\n      }\n\n      if (this.textAlign.indexOf('justify') !== -1) {\n        // once text is measured we need to make space fatter to make justified text.\n        this.enlargeSpaces();\n      } // clear cache and re-calculate height\n\n\n      this.height = this.calcTextHeight();\n      this.saveState({\n        propertySet: '_dimensionAffectingProps'\n      });\n    },\n\n    /**\n     * Generate an object that translates the style object so that it is\n     * broken up by visual lines (new lines and automatic wrapping).\n     * The original text styles object is broken up by actual lines (new lines only),\n     * which is only sufficient for Text / IText\n     * @private\n     */\n    _generateStyleMap: function (textInfo) {\n      var realLineCount = 0,\n          realLineCharCount = 0,\n          charCount = 0,\n          map = {};\n\n      for (var i = 0; i < textInfo.graphemeLines.length; i++) {\n        if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n          realLineCharCount = 0;\n          charCount++;\n          realLineCount++;\n        } else if (!this.splitByGrapheme && this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) && i > 0) {\n          // this case deals with space's that are removed from end of lines when wrapping\n          realLineCharCount++;\n          charCount++;\n        }\n\n        map[i] = {\n          line: realLineCount,\n          offset: realLineCharCount\n        };\n        charCount += textInfo.graphemeLines[i].length;\n        realLineCharCount += textInfo.graphemeLines[i].length;\n      }\n\n      return map;\n    },\n\n    /**\n     * Returns true if object has a style property or has it on a specified line\n     * @param {Number} lineIndex\n     * @return {Boolean}\n     */\n    styleHas: function (property, lineIndex) {\n      if (this._styleMap && !this.isWrapping) {\n        var map = this._styleMap[lineIndex];\n\n        if (map) {\n          lineIndex = map.line;\n        }\n      }\n\n      return fabric.Text.prototype.styleHas.call(this, property, lineIndex);\n    },\n\n    /**\n     * Returns true if object has no styling or no styling in a line\n     * @param {Number} lineIndex , lineIndex is on wrapped lines.\n     * @return {Boolean}\n     */\n    isEmptyStyles: function (lineIndex) {\n      if (!this.styles) {\n        return true;\n      }\n\n      var offset = 0,\n          nextLineIndex = lineIndex + 1,\n          nextOffset,\n          obj,\n          shouldLimit = false,\n          map = this._styleMap[lineIndex],\n          mapNextLine = this._styleMap[lineIndex + 1];\n\n      if (map) {\n        lineIndex = map.line;\n        offset = map.offset;\n      }\n\n      if (mapNextLine) {\n        nextLineIndex = mapNextLine.line;\n        shouldLimit = nextLineIndex === lineIndex;\n        nextOffset = mapNextLine.offset;\n      }\n\n      obj = typeof lineIndex === 'undefined' ? this.styles : {\n        line: this.styles[lineIndex]\n      };\n\n      for (var p1 in obj) {\n        for (var p2 in obj[p1]) {\n          if (p2 >= offset && (!shouldLimit || p2 < nextOffset)) {\n            // eslint-disable-next-line no-unused-vars\n            for (var p3 in obj[p1][p2]) {\n              return false;\n            }\n          }\n        }\n      }\n\n      return true;\n    },\n\n    /**\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @private\n     */\n    _getStyleDeclaration: function (lineIndex, charIndex) {\n      if (this._styleMap && !this.isWrapping) {\n        var map = this._styleMap[lineIndex];\n\n        if (!map) {\n          return null;\n        }\n\n        lineIndex = map.line;\n        charIndex = map.offset + charIndex;\n      }\n\n      return this.callSuper('_getStyleDeclaration', lineIndex, charIndex);\n    },\n\n    /**\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @param {Object} style\n     * @private\n     */\n    _setStyleDeclaration: function (lineIndex, charIndex, style) {\n      var map = this._styleMap[lineIndex];\n      lineIndex = map.line;\n      charIndex = map.offset + charIndex;\n      this.styles[lineIndex][charIndex] = style;\n    },\n\n    /**\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @private\n     */\n    _deleteStyleDeclaration: function (lineIndex, charIndex) {\n      var map = this._styleMap[lineIndex];\n      lineIndex = map.line;\n      charIndex = map.offset + charIndex;\n      delete this.styles[lineIndex][charIndex];\n    },\n\n    /**\n     * probably broken need a fix\n     * Returns the real style line that correspond to the wrapped lineIndex line\n     * Used just to verify if the line does exist or not.\n     * @param {Number} lineIndex\n     * @returns {Boolean} if the line exists or not\n     * @private\n     */\n    _getLineStyle: function (lineIndex) {\n      var map = this._styleMap[lineIndex];\n      return !!this.styles[map.line];\n    },\n\n    /**\n     * Set the line style to an empty object so that is initialized\n     * @param {Number} lineIndex\n     * @param {Object} style\n     * @private\n     */\n    _setLineStyle: function (lineIndex) {\n      var map = this._styleMap[lineIndex];\n      this.styles[map.line] = {};\n    },\n\n    /**\n     * Wraps text using the 'width' property of Textbox. First this function\n     * splits text on newlines, so we preserve newlines entered by the user.\n     * Then it wraps each line using the width of the Textbox by calling\n     * _wrapLine().\n     * @param {Array} lines The string array of text that is split into lines\n     * @param {Number} desiredWidth width you want to wrap to\n     * @returns {Array} Array of lines\n     */\n    _wrapText: function (lines, desiredWidth) {\n      var wrapped = [],\n          i;\n      this.isWrapping = true;\n\n      for (i = 0; i < lines.length; i++) {\n        wrapped = wrapped.concat(this._wrapLine(lines[i], i, desiredWidth));\n      }\n\n      this.isWrapping = false;\n      return wrapped;\n    },\n\n    /**\n     * Helper function to measure a string of text, given its lineIndex and charIndex offset\n     * it gets called when charBounds are not available yet.\n     * @param {CanvasRenderingContext2D} ctx\n     * @param {String} text\n     * @param {number} lineIndex\n     * @param {number} charOffset\n     * @returns {number}\n     * @private\n     */\n    _measureWord: function (word, lineIndex, charOffset) {\n      var width = 0,\n          prevGrapheme,\n          skipLeft = true;\n      charOffset = charOffset || 0;\n\n      for (var i = 0, len = word.length; i < len; i++) {\n        var box = this._getGraphemeBox(word[i], lineIndex, i + charOffset, prevGrapheme, skipLeft);\n\n        width += box.kernedWidth;\n        prevGrapheme = word[i];\n      }\n\n      return width;\n    },\n\n    /**\n     * Wraps a line of text using the width of the Textbox and a context.\n     * @param {Array} line The grapheme array that represent the line\n     * @param {Number} lineIndex\n     * @param {Number} desiredWidth width you want to wrap the line to\n     * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n     * @returns {Array} Array of line(s) into which the given text is wrapped\n     * to.\n     */\n    _wrapLine: function (_line, lineIndex, desiredWidth, reservedSpace) {\n      var lineWidth = 0,\n          splitByGrapheme = this.splitByGrapheme,\n          graphemeLines = [],\n          line = [],\n          // spaces in different languges?\n      words = splitByGrapheme ? fabric.util.string.graphemeSplit(_line) : _line.split(this._wordJoiners),\n          word = '',\n          offset = 0,\n          infix = splitByGrapheme ? '' : ' ',\n          wordWidth = 0,\n          infixWidth = 0,\n          largestWordWidth = 0,\n          lineJustStarted = true,\n          additionalSpace = this._getWidthOfCharSpacing(),\n          reservedSpace = reservedSpace || 0; // fix a difference between split and graphemeSplit\n\n\n      if (words.length === 0) {\n        words.push([]);\n      }\n\n      desiredWidth -= reservedSpace;\n\n      for (var i = 0; i < words.length; i++) {\n        // if using splitByGrapheme words are already in graphemes.\n        word = splitByGrapheme ? words[i] : fabric.util.string.graphemeSplit(words[i]);\n        wordWidth = this._measureWord(word, lineIndex, offset);\n        offset += word.length;\n        lineWidth += infixWidth + wordWidth - additionalSpace;\n\n        if (lineWidth >= desiredWidth && !lineJustStarted) {\n          graphemeLines.push(line);\n          line = [];\n          lineWidth = wordWidth;\n          lineJustStarted = true;\n        } else {\n          lineWidth += additionalSpace;\n        }\n\n        if (!lineJustStarted && !splitByGrapheme) {\n          line.push(infix);\n        }\n\n        line = line.concat(word);\n        infixWidth = splitByGrapheme ? 0 : this._measureWord([infix], lineIndex, offset);\n        offset++;\n        lineJustStarted = false; // keep track of largest word\n\n        if (wordWidth > largestWordWidth) {\n          largestWordWidth = wordWidth;\n        }\n      }\n\n      i && graphemeLines.push(line);\n\n      if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n        this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n      }\n\n      return graphemeLines;\n    },\n\n    /**\n     * Detect if the text line is ended with an hard break\n     * text and itext do not have wrapping, return false\n     * @param {Number} lineIndex text to split\n     * @return {Boolean}\n     */\n    isEndOfWrapping: function (lineIndex) {\n      if (!this._styleMap[lineIndex + 1]) {\n        // is last line, return true;\n        return true;\n      }\n\n      if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n        // this is last line before a line break, return true;\n        return true;\n      }\n\n      return false;\n    },\n\n    /**\n     * Detect if a line has a linebreak and so we need to account for it when moving\n     * and counting style.\n     * @return Number\n     */\n    missingNewlineOffset: function (lineIndex) {\n      if (this.splitByGrapheme) {\n        return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n      }\n\n      return 1;\n    },\n\n    /**\n    * Gets lines of text to render in the Textbox. This function calculates\n    * text wrapping on the fly every time it is called.\n    * @param {String} text text to split\n    * @returns {Array} Array of lines in the Textbox.\n    * @override\n    */\n    _splitTextIntoLines: function (text) {\n      var newText = fabric.Text.prototype._splitTextIntoLines.call(this, text),\n          graphemeLines = this._wrapText(newText.lines, this.width),\n          lines = new Array(graphemeLines.length);\n\n      for (var i = 0; i < graphemeLines.length; i++) {\n        lines[i] = graphemeLines[i].join('');\n      }\n\n      newText.lines = lines;\n      newText.graphemeLines = graphemeLines;\n      return newText;\n    },\n    getMinWidth: function () {\n      return Math.max(this.minWidth, this.dynamicMinWidth);\n    },\n    _removeExtraneousStyles: function () {\n      var linesToKeep = {};\n\n      for (var prop in this._styleMap) {\n        if (this._textLines[prop]) {\n          linesToKeep[this._styleMap[prop].line] = 1;\n        }\n      }\n\n      for (var prop in this.styles) {\n        if (!linesToKeep[prop]) {\n          delete this.styles[prop];\n        }\n      }\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @method toObject\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function (propertiesToInclude) {\n      return this.callSuper('toObject', ['minWidth', 'splitByGrapheme'].concat(propertiesToInclude));\n    }\n  });\n  /**\n   * Returns fabric.Textbox instance from an object representation\n   * @static\n   * @memberOf fabric.Textbox\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] Callback to invoke when an fabric.Textbox instance is created\n   */\n\n  fabric.Textbox.fromObject = function (object, callback) {\n    return fabric.Object._fromObject('Textbox', object, callback, 'text');\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n(function () {\n  var controlsUtils = fabric.controlsUtils,\n      scaleSkewStyleHandler = controlsUtils.scaleSkewCursorStyleHandler,\n      scaleStyleHandler = controlsUtils.scaleCursorStyleHandler,\n      scalingEqually = controlsUtils.scalingEqually,\n      scalingYOrSkewingX = controlsUtils.scalingYOrSkewingX,\n      scalingXOrSkewingY = controlsUtils.scalingXOrSkewingY,\n      scaleOrSkewActionName = controlsUtils.scaleOrSkewActionName,\n      objectControls = fabric.Object.prototype.controls;\n  objectControls.ml = new fabric.Control({\n    x: -0.5,\n    y: 0,\n    cursorStyleHandler: scaleSkewStyleHandler,\n    actionHandler: scalingXOrSkewingY,\n    getActionName: scaleOrSkewActionName\n  });\n  objectControls.mr = new fabric.Control({\n    x: 0.5,\n    y: 0,\n    cursorStyleHandler: scaleSkewStyleHandler,\n    actionHandler: scalingXOrSkewingY,\n    getActionName: scaleOrSkewActionName\n  });\n  objectControls.mb = new fabric.Control({\n    x: 0,\n    y: 0.5,\n    cursorStyleHandler: scaleSkewStyleHandler,\n    actionHandler: scalingYOrSkewingX,\n    getActionName: scaleOrSkewActionName\n  });\n  objectControls.mt = new fabric.Control({\n    x: 0,\n    y: -0.5,\n    cursorStyleHandler: scaleSkewStyleHandler,\n    actionHandler: scalingYOrSkewingX,\n    getActionName: scaleOrSkewActionName\n  });\n  objectControls.tl = new fabric.Control({\n    x: -0.5,\n    y: -0.5,\n    cursorStyleHandler: scaleStyleHandler,\n    actionHandler: scalingEqually\n  });\n  objectControls.tr = new fabric.Control({\n    x: 0.5,\n    y: -0.5,\n    cursorStyleHandler: scaleStyleHandler,\n    actionHandler: scalingEqually\n  });\n  objectControls.bl = new fabric.Control({\n    x: -0.5,\n    y: 0.5,\n    cursorStyleHandler: scaleStyleHandler,\n    actionHandler: scalingEqually\n  });\n  objectControls.br = new fabric.Control({\n    x: 0.5,\n    y: 0.5,\n    cursorStyleHandler: scaleStyleHandler,\n    actionHandler: scalingEqually\n  });\n  objectControls.mtr = new fabric.Control({\n    x: 0,\n    y: -0.5,\n    actionHandler: controlsUtils.rotationWithSnapping,\n    cursorStyleHandler: controlsUtils.rotationStyleHandler,\n    offsetY: -40,\n    withConnection: true,\n    actionName: 'rotate'\n  });\n\n  if (fabric.Textbox) {\n    // this is breaking the prototype inheritance, no time / ideas to fix it.\n    // is important to document that if you want to have all objects to have a\n    // specific custom control, you have to add it to Object prototype and to Textbox\n    // prototype. The controls are shared as references. So changes to control `tr`\n    // can still apply to all objects if needed.\n    var textBoxControls = fabric.Textbox.prototype.controls = {};\n    textBoxControls.mtr = objectControls.mtr;\n    textBoxControls.tr = objectControls.tr;\n    textBoxControls.br = objectControls.br;\n    textBoxControls.tl = objectControls.tl;\n    textBoxControls.bl = objectControls.bl;\n    textBoxControls.mt = objectControls.mt;\n    textBoxControls.mb = objectControls.mb;\n    textBoxControls.mr = new fabric.Control({\n      x: 0.5,\n      y: 0,\n      actionHandler: controlsUtils.changeWidth,\n      cursorStyleHandler: scaleSkewStyleHandler,\n      actionName: 'resizing'\n    });\n    textBoxControls.ml = new fabric.Control({\n      x: -0.5,\n      y: 0,\n      actionHandler: controlsUtils.changeWidth,\n      cursorStyleHandler: scaleSkewStyleHandler,\n      actionName: 'resizing'\n    });\n  }\n})();","map":{"version":3,"sources":["C:/Users/kkwan_000/Desktop/git/2017110269/minsung/node_modules/fabric/dist/fabric.js"],"names":["fabric","version","exports","define","amd","document","window","HTMLDocument","Document","implementation","createHTMLDocument","jsdom","require","virtualWindow","JSDOM","decodeURIComponent","features","FetchExternalResources","resources","jsdomImplForWrapper","implForWrapper","nodeCanvas","Canvas","DOMParser","isTouchSupported","navigator","maxTouchPoints","isLikelyNode","Buffer","SHARED_ATTRIBUTES","DPI","reNum","commaWsp","rePathCommand","reNonWord","fontPaths","iMatrix","svgNS","perfLimitSizeTotal","maxCacheSideLimit","minCacheSideLimit","charWidthsCache","textureSize","disableStyleCopyPaste","enableGLFiltering","devicePixelRatio","webkitDevicePixelRatio","mozDevicePixelRatio","browserShadowBlurConstant","arcToSegmentsCache","boundsOfCurveCache","cachesBoundsOfCurve","forceGLPutImageData","initFilterBackend","isWebglSupported","console","log","maxTextureSize","WebglFilterBackend","tileSize","Canvas2dFilterBackend","_removeEventListener","eventName","handler","__eventListeners","eventListener","indexOf","util","array","fill","on","arguments","length","prop","push","off","call","fire","options","listenersForEvent","i","len","filter","value","Observable","Collection","_objects","add","apply","_onObjectAdded","renderOnAddRemove","requestRenderAll","insertAt","object","index","nonSplicing","objects","splice","remove","somethingRemoved","_onObjectRemoved","forEachObject","callback","context","getObjects","type","concat","o","item","isEmpty","size","contains","complexity","reduce","memo","current","CommonMethods","_setOptions","set","_initGradient","filler","property","colorStops","Gradient","_initPattern","source","Pattern","_setObject","obj","_set","key","toggle","get","global","sqrt","Math","atan2","pow","PiBy180","PI","PiBy2","cos","angle","angleSlice","sin","sign","removeFromArray","idx","getRandomInt","min","max","floor","random","degreesToRadians","degrees","radiansToDegrees","radians","rotatePoint","point","origin","subtractEquals","v","rotateVector","Point","x","y","addEquals","vector","rx","ry","transformPoint","p","t","ignoreOffset","makeBoundingBoxFromPoints","points","transform","xPoints","minX","maxX","width","yPoints","minY","maxY","height","left","top","invertTransform","a","r","toFixed","number","fractionDigits","parseFloat","Number","parseUnit","fontSize","unit","exec","Text","DEFAULT_SVG_FONT_SIZE","falseFunction","getKlass","namespace","string","camelize","charAt","toUpperCase","slice","resolveNamespace","getSvgAttributes","attributes","parts","split","loadImage","url","crossOrigin","img","createImage","onLoadCallback","onload","onerror","src","undefined","substring","loadImageInDom","div","createElement","style","position","appendChild","querySelector","parentNode","removeChild","enlivenObjects","reviver","enlivenedObjects","numLoadedObjects","numTotalObjects","onLoaded","forEach","klass","fromObject","error","enlivenPatterns","patterns","numLoadedPatterns","numPatterns","enlivenedPatterns","pattern","groupSVGElements","elements","path","centerPoint","Group","sourcePath","populateWithProperties","destination","properties","Object","prototype","toString","drawDashedLine","ctx","x2","y2","da","dx","dy","rot","dc","di","draw","save","translate","moveTo","rotate","restore","createCanvasElement","copyCanvasElement","canvas","newCanvas","getContext","drawImage","toDataURL","canvasEl","format","quality","multiplyTransformMatrices","b","is2x2","qrDecompose","denom","scaleX","scaleY","skewX","skewY","translateX","translateY","calcRotateMatrix","theta","calcDimensionsMatrix","scaleMatrix","flipX","flipY","multiply","tan","composeMatrix","matrix","resetObjectTransform","target","saveObjectTransform","isTransparent","tolerance","_isTransparent","temp","imageData","getImageData","l","data","parsePreserveAspectRatioAttribute","attribute","meetOrSlice","alignX","alignY","aspectRatioAttrs","align","pop","clearFabricFontCache","fontFamily","toLowerCase","limitDimsByArea","ar","maximumArea","roughWidth","perfLimitSizeY","capValue","findScaleToFit","findScaleToCover","matrixToSVG","map","NUM_FRACTION_DIGITS","join","sizeAfterTransform","dimX","dimY","transformMatrix","bbox","_join","Array","commandLengths","m","h","c","s","q","repeatedCommands","M","segmentToBezier","th2","th3","cosTh","sinTh","cx1","cy1","mT","fromX","fromY","costh2","sinth2","costh3","sinth3","toX","toY","cp1X","cp1Y","cp2X","cp2Y","arcToSegments","large","sweep","rotateX","th","abs","px","py","rx2","ry2","py2","px2","pl","root","cx","cy","mTheta","calcVectorAngle","dtheta","segments","ceil","result","mDelta","ux","uy","vx","vy","ta","tb","getBoundsOfCurve","x0","y0","x1","y1","x3","y3","argsString","tvalues","bounds","t1","t2","b2ac","sqrtb2ac","j","jlen","mt","fromArcToBeizers","fx","fy","coords","tx","ty","segsNorm","makePathSimpler","converted","destinationPath","previous","controlX","controlY","calcLineLength","CB1","CB2","CB3","CB4","getPointOnCubicBezierIterator","p1x","p1y","p2x","p2y","p3x","p3y","p4x","p4y","pct","c1","c2","c3","c4","QB1","QB2","QB3","getPointOnQuadraticBezierIterator","pathIterator","iterator","tempP","tmpLen","perc","getPathSegmentsInfo","totalLength","info","tempInfo","command","destX","destY","getPointOnPath","infos","distance","segInfo","segPercent","segment","lerp","parsePath","pathString","currentPath","parsed","re","rNumber","rNumberCommaWsp","rFlagCommaWsp","rArcSeq","regArcArgumentSequence","RegExp","match","coordsStr","coordsParsed","trim","args","isNaN","commandLength","repeatedCommand","k","klen","getBoundsOfArc","bound","segs","drawArc","unshift","beizers","beizer","bezierCurveTo","invoke","method","byProperty","find","value1","value2","condition","extend","deep","Element","hasOwnProperty","clone","replace","character","capitalize","firstLetterOnly","escapeXml","graphemeSplit","textstring","chr","graphemes","getWholeChar","str","code","charCodeAt","next","prev","emptyFunction","IS_DONTENUM_BUGGY","addMethods","parent","superclass","constructor","returnValue","valueOf","Subclass","callSuper","methodName","parentMethod","_this","superClassMethod","createClass","shift","initialize","subclasses","couldUseAttachEvent","attachEvent","touchEvents","addListener","element","addEventListener","removeListener","removeEventListener","getTouchInfo","event","touchProp","changedTouches","getPointer","scroll","getScrollLeftTop","_evt","clientX","clientY","isTouchEvent","pointerType","setStyle","styles","elementStyle","cssText","setOpacity","normalizedProperty","styleFloat","parseEl","supportsOpacity","opacity","supportsFilters","reOpacity","es","currentStyle","hasLayout","zoom","test","_slice","getById","id","getElementById","sliceCanConvertNodelists","toArray","arrayLike","childNodes","err","arr","makeElement","tagName","el","className","htmlFor","setAttribute","addClass","wrapElement","wrapper","replaceChild","docElement","documentElement","body","scrollLeft","scrollTop","host","nodeType","getElementOffset","docElem","doc","ownerDocument","box","offset","scrollLeftTop","offsetAttributes","borderLeftWidth","borderTopWidth","paddingLeft","paddingTop","attr","parseInt","getElementStyle","getBoundingClientRect","clientLeft","clientTop","defaultView","getComputedStyle","selectProp","makeElementUnselectable","onselectstart","unselectable","makeElementSelectable","getNodeCanvas","impl","_canvas","_image","cleanUpJsdomNode","_currentSrc","_attributes","_classList","setImageSmoothing","imageSmoothingEnabled","webkitImageSmoothingEnabled","mozImageSmoothingEnabled","msImageSmoothingEnabled","oImageSmoothingEnabled","addParamToUrl","param","emptyFn","request","onComplete","xhr","XMLHttpRequest","parameters","onreadystatechange","readyState","open","setRequestHeader","send","warn","noop","defaultEasing","d","animate","requestAnimFrame","timestamp","start","Date","duration","finish","time","onChange","abort","easing","startValue","endValue","byValue","onStart","tick","ticktime","currentTime","timePerc","valuePerc","_requestAnimFrame","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","setTimeout","_cancelAnimFrame","cancelAnimationFrame","clearTimeout","cancelAnimFrame","calculateColor","begin","end","pos","color","animateColor","fromColor","toColor","startColor","Color","getSource","endColor","originalOnComplete","originalOnChange","posValue","colorEasing","isArray","normalize","asin","elastic","opts","easeOutCubic","easeInOutCubic","easeInQuart","easeOutQuart","easeInOutQuart","easeInQuint","easeOutQuint","easeInOutQuint","easeInSine","easeOutSine","easeInOutSine","easeInExpo","easeOutExpo","easeInOutExpo","easeInCirc","easeOutCirc","easeInOutCirc","easeInElastic","easeOutElastic","easeInOutElastic","easeInBack","easeOutBack","easeInOutBack","easeInBounce","easeOutBounce","easeInOutBounce","ease","easeInQuad","easeOutQuad","easeInOutQuad","easeInCubic","svgValidTagNames","svgViewBoxElements","svgInvalidAncestors","svgValidParents","attributesMap","display","visibility","colorAttributes","stroke","fSize","cPath","svgValidTagNamesRegEx","getSvgRegex","svgViewBoxElementsRegEx","svgInvalidAncestorsRegEx","svgValidParentsRegEx","cssRules","gradientDefs","clipPaths","normalizeAttr","normalizeValue","parentAttributes","parseTransformAttribute","visible","fillIndex","strokeIndex","_setStrokeFillOpacity","setAlpha","getAlpha","toRgba","_getMultipleNodes","nodeNames","nodeName","nodeArray","nodeList","getElementsByTagName","rotateMatrix","multiplierX","multiplierY","skewMatrix","translateMatrix","scale","transforms","transformList","reTransformList","reTransform","attributeValue","matrices","operation","combinedMatrix","parseStyleString","oStyle","chunk","pair","parseStyleObject","getGlobalStylesForElement","svgUid","rule","elementMatchesRule","selectors","firstMatching","parentMatching","selectorMatches","doesSomeParentMatch","selector","classNames","getAttribute","matcher","elementById","node","nodelist","parseUseDirectives","xlink","substr","el2","cloneNode","currentTrans","oldLength","attrs","applyViewboxTransform","el3","createElementNS","setAttributeNS","nodeValue","firstChild","removeAttribute","reViewBoxAttrValue","viewBoxAttr","viewBoxWidth","viewBoxHeight","widthAttr","heightAttr","preserveAspectRatio","missingViewBox","missingDimAttr","toBeParsed","parsedDim","widthDiff","heightDiff","hasAncestorWithNodeName","parseSVGDocument","parsingOptions","__uid","descendants","selectNodes","getGradientDefs","getCSSRules","parseElements","instances","recursivelyParseGradientsXlink","gradient","gradientsAttrs","xlinkAttr","xLink","referencedGradient","hasAttribute","children","referenceClone","reFontDeclaration","parseFontDeclaration","fontStyle","fontWeight","lineHeight","tagArray","elList","parseAttributes","parentFontSize","ownAttributes","cssAttrs","parseStyleAttribute","normalizedAttr","normalizedValue","normalizedStyle","font","mergedAttrs","ElementsParser","parse","parsePointsAttribute","parsedPoints","allRules","rules","styleContents","textContent","ruleObj","declaration","propertyValuePairs","_rule","loadSVGFromURL","xml","responseXML","results","_options","allElements","loadSVGFromString","parser","parseFromString","regexUrl","proto","numElements","createObjects","createObject","findTag","fromElement","createCallback","checkIfDone","resolveGradient","Image","_originalElement","_removeTransformMatrix","resolveClipPath","extractPropertyDefinition","storage","regex","lastIndex","gradientDef","opacityAttr","createClipPathCallback","container","_newObj","fillRule","clipRule","usingElement","clipPath","objTransformInv","gTransform","calcTransformMatrix","clipPathTag","clipPathOwner","setPositionByOrigin","that","scalarAdd","scalar","scalarAddEquals","subtract","scalarSubtract","scalarSubtractEquals","multiplyEquals","divide","divideEquals","eq","lt","lte","gt","gte","distanceFrom","midPointFrom","setXY","setX","setY","setFromPoint","swap","Intersection","status","appendPoint","appendPoints","intersectLineLine","a1","a2","b1","b2","uaT","ubT","uB","ua","ub","intersectLinePolygon","inter","intersectPolygonPolygon","points1","points2","intersectPolygonRectangle","r1","r2","topRight","bottomLeft","inter1","inter2","inter3","inter4","setSource","_tryParsingColor","colorNameMap","sourceFromHex","sourceFromRgb","sourceFromHsl","_rgbToHsl","g","round","_source","toRgb","toHsl","hsl","toHsla","toHex","toHexa","alpha","toGrayscale","average","currentAlpha","toBlackWhite","threshold","overlayWith","otherColor","otherAlpha","otherSource","reRGBa","reHSLa","reHex","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgrey","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgrey","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen","hue2rgb","fromRgb","fromSource","fromRgba","fromHsl","fromHsla","fromHex","isShortNotation","isRGBa","oColor","scaleMap","skewMap","controls","LEFT","TOP","RIGHT","BOTTOM","CENTER","opposite","bottom","right","center","findCornerQuadrant","fabricObject","control","cornerAngle","fireEvent","canvasOptions","scaleIsProportional","eventData","uniScaleKey","uniformIsToggled","uniformScaling","isTransformCentered","originX","originY","scalingIsForbidden","by","scaleProportionally","lockX","lockScalingX","lockY","lockScalingY","scaleCursorStyleHandler","notAllowed","n","skewCursorStyleHandler","lockSkewingY","lockSkewingX","scaleSkewCursorStyleHandler","altActionKey","scaleOrSkewActionName","isAlternative","rotationStyleHandler","lockRotation","cursorStyle","commonEventInfo","e","pointer","wrapWithFixedAnchor","actionHandler","getCenterPoint","constraint","translateToOriginPoint","actionPerformed","getLocalPoint","corner","getZoom","padding","localPoint","toLocalPoint","offsetX","offsetY","targetHasOneFlip","compensateScaleForSkew","oppositeSkew","scaleToCompensate","axis","reference","newDim","_getTransformedDimensions","newValue","skewObjectX","dimNoSkew","totalSkewSize","currentSkew","newSkew","hasSkewed","dimBeforeSkewing","skewObjectY","skewHandlerX","localPointFromCenter","finalHandler","skewHandlerY","rotationWithSnapping","pivotPoint","lastAngle","ey","ex","curAngle","hasRotated","snapAngle","snapThreshold","rightAngleLocked","leftAngleLocked","scaleObject","newPoint","dim","forbidScaling","signX","signY","gestureScale","lockScalingFlip","original","originalDistance","hasScaled","oldScaleX","oldScaleY","scaleObjectFromCorner","scaleObjectX","scaleObjectY","scalingYOrSkewingX","scalingY","scalingXOrSkewingY","scalingX","changeWidth","strokePadding","strokeWidth","strokeUniform","multiplier","oldWidth","hasResized","newWidth","dragHandler","newLeft","newTop","moveX","moveY","scalingEqually","controlsUtils","renderCircleControl","styleOverride","cornerSize","transparentCorners","cornerStrokeColor","fillStyle","cornerColor","strokeStyle","lineWidth","beginPath","arc","renderSquareControl","sizeBy2","strokeCornerColor","strokeRect","Control","actionName","withConnection","mouseDownHandler","mouseUpHandler","getActionHandler","getMouseDownHandler","getMouseUpHandler","cursorStyleHandler","getActionName","getVisibility","controlKey","objectVisibility","_controlsVisibility","setVisibility","positionHandler","finalMatrix","render","cornerStyle","getColorStop","colorAlpha","keyValuePairs","getLinearCoords","getRadialCoords","gradientTransform","gradientUnits","keys","option","addColorStop","toObject","propertiesToInclude","toSVG","markup","commonAttributes","needsSwap","withViewport","additionalTransform","sort","pathOffset","reverse","minRadius","maxRadius","percentageShift","colorStop","toLive","createLinearGradient","createRadialGradient","instance","svgOptions","colorStopEls","__convertPercentUnitsToValues","propValue","finalValue","repeat","patternTransform","setOptions","isError","patternSource","patternWidth","patternHeight","patternOffsetX","patternOffsetY","patternImgSrc","complete","naturalWidth","naturalHeight","createPattern","Shadow","blur","affectStroke","includeDefaultValues","nonScaling","_parseShadow","shadow","shadowStr","offsetsAndBlur","reOffsetsAndBlur","fBoxX","fBoxY","BLUR_BOX","StaticCanvas","CANVAS_INIT_ERROR","Error","renderAndResetBound","renderAndReset","bind","requestRenderAllBound","_initStatic","backgroundColor","backgroundImage","overlayColor","overlayImage","stateful","controlsAboveOverlay","allowTouchScrolling","viewportTransform","backgroundVpt","overlayVpt","enableRetinaScaling","vptCoords","skipOffscreen","cb","_createLowerCanvas","_initOptions","interactive","_initRetinaScaling","setOverlayImage","setBackgroundImage","setBackgroundColor","setOverlayColor","calcOffset","_isRetinaScaling","getRetinaScaling","scaleRatio","__initRetinaScaling","lowerCanvasEl","contextContainer","upperCanvasEl","contextTop","_offset","image","__setBgOverlayImage","__setBgOverlayColor","_createCanvasElement","_applyCanvasStyle","getWidth","getHeight","setWidth","setDimensions","setHeight","dimensions","cssValue","cssOnly","_setBackstoreDimension","hasLostContext","backstoreOnly","_setCssDimension","_isCurrentlyDrawing","freeDrawingBrush","_setBrushStyles","cacheCanvasEl","wrapperEl","setViewportTransform","vpt","activeObject","_activeObject","group","setCoords","calcViewportBoundaries","zoomToPoint","before","after","setZoom","absolutePan","relativePan","getElement","setupState","clearContext","clearRect","clear","_hasITextHandlers","_mouseUpITextHandler","_iTextInstances","renderAll","canvasToDrawOn","renderCanvas","isRendering","iVpt","tl","br","tr","bl","cancelRequestedRender","_renderBackground","_renderObjects","drawControls","shouldCache","_transformDone","renderCache","forClipping","drawClipPathOnCanvas","_renderOverlay","globalCompositeOperation","zoomX","zoomY","_cacheCanvas","cacheTranslationX","cacheTranslationY","_renderBackgroundOrOverlay","needsVpt","lineTo","closePath","getCenter","centerObjectH","_centerObject","centerObjectV","centerObject","viewportCenterObject","vpCenter","getVpCenter","viewportCenterObjectH","viewportCenterObjectV","toDatalessJSON","toDatalessObject","_toObjectMethod","_toObjects","_toObject","__serializeBgOverlay","excludeFromExport","originalValue","bgImage","overlay","background","svgViewportTransformation","_setSVGPreamble","_setSVGHeader","clipPathId","_setSVGBgOverlayColor","_setSVGBgOverlayImage","_setSVGObjects","suppressPreamble","encoding","viewBox","createSVGFontFacesMarkup","createSVGRefElementsMarkup","createSVGClipPathMarkup","toClipPathSVG","shouldTransform","fontList","row","rowIndex","_char","charIndex","_setSVGObject","finalWidth","finalHeight","shouldInvert","sendToBack","activeSelection","objs","bringToFront","sendBackwards","intersecting","newIdx","objsMoved","_findNewLowerIndex","isIntersecting","intersectsWithObject","isContainedWithinObject","bringForward","_findNewUpperIndex","dispose","DataURLExporter","EMPTY_JSON","supports","setLineDash","toJSON","createPNGStream","createJPEGStream","BaseBrush","strokeLineCap","strokeLineJoin","strokeMiterLimit","strokeDashArray","lineCap","miterLimit","lineJoin","_saveAndTransform","_setShadow","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY","needsFullRender","_resetShadow","PencilBrush","decimate","_points","_drawSegment","p1","p2","midPoint","quadraticCurveTo","onMouseDown","_isMainEvent","_prepareForDrawing","_captureDrawingPath","_render","onMouseMove","oldEnd","onMouseUp","_finalizeAndAddPath","_reset","_addPoint","pointerPoint","convertPointsToSVGPath","multSignX","multSignY","manyPoints","createPath","pathData","Path","decimatePoints","adjustedDistance","lastPoint","newPoints","cDistance","CircleBrush","drawDot","addPoint","dot","radius","originalRenderOnAddRemove","circles","circle","Circle","circleRadius","circleColor","SprayBrush","density","dotWidth","dotWidthVariance","randomOpacity","optimizeOverlapping","sprayChunks","addSprayChunk","sprayChunkPoints","rects","ilen","sprayChunk","rect","Rect","_getOptimizedRects","uniqueRects","uniqueRectsArray","globalAlpha","fillRect","PatternBrush","getPatternSrc","dotDistance","patternCanvas","patternCtx","getPatternSrcFunction","String","getPattern","topLeft","_getLeftTopCoords","supportLineDash","STROKE_OFFSET","_initInteractive","_createCacheCanvas","centeredScaling","centeredRotation","centeredKey","selection","selectionKey","altSelectionKey","selectionColor","selectionDashArray","selectionBorderColor","selectionLineWidth","selectionFullyContained","hoverCursor","moveCursor","defaultCursor","freeDrawingCursor","rotationCursor","notAllowedCursor","containerClass","perPixelTargetFind","targetFindTolerance","skipTargetFind","isDrawingMode","preserveObjectStacking","stopContextMenu","fireRightClick","fireMiddleClick","targets","_hoveredTarget","_hoveredTargets","_currentTransform","_groupSelector","_initWrapperElement","_createUpperCanvas","_initEventListeners","_chooseObjectsToRender","activeObjects","getActiveObjects","objsToRender","activeGroupObjects","contextTopDirty","renderTopLayer","_drawSelection","renderTop","_normalizePointer","invertedM","vptPointer","restorePointerVpt","isTargetTransparent","normalizedPointer","targetRelativeX","targetRelativeY","_cacheContext","contextCache","originalColor","selectionBackgroundColor","_renderControls","hasBorders","_isSelectionKeyPressed","selectionKeyPressed","_shouldClearSelection","evented","selectable","_shouldCenterTransform","action","altKey","centerTransform","_getOriginFromCorner","_getActionFromCorner","alreadySelected","_setupCurrentTransform","__corner","lastX","lastY","shiftKey","_beforeTransform","setCursor","cursor","groupSelector","aleft","atop","_setLineDash","findTarget","skipGroup","ignoreZoom","aObjects","activeTarget","activeTargetSubs","isTouch","_searchPossibleTargets","_findTargetCorner","_checkTarget","globalPointer","containsPoint","isEditing","subTarget","objToCheck","pointerToUse","subTargetCheck","_absolutePointer","_pointer","boundsWidth","boundsHeight","cssScale","retinaScaling","lowerCanvasClass","_copyCanvasStyle","fromEl","toEl","getSelectionContext","getSelectionElement","getActiveObject","active","_discardActiveObject","_fireSelectionEvents","oldObjects","somethingChanged","added","removed","opt","oldObject","selected","deselected","updated","setActiveObject","currentActives","_setActiveObject","onSelect","onDeselect","discardActiveObject","removeListeners","originalProperties","_realizeGroupTransformOnObject","_unwindGroupTransformOnObject","layoutProps","originalValues","realizeTransform","clearContextTop","RIGHT_CLICK","MIDDLE_CLICK","LEFT_CLICK","addEventOptions","passive","checkClick","button","mainTouchId","_bindEvents","addOrRemove","_getEventPrefix","enablePointerEvents","functor","eventjsFunctor","canvasElement","eventTypePrefix","_onResize","_onMouseDown","_onMouseMove","_onMouseOut","_onMouseEnter","_onMouseWheel","_onContextMenu","_onDoubleClick","_onDragOver","_onDragEnter","_onDragLeave","_onDrop","_onTouchStart","eventjs","_onGesture","_onDrag","_onOrientationChange","_onShake","_onLongPress","_onMouseUp","_onTouchEnd","eventsBound","_simpleEventHandler","self","__onTransformGesture","__onDrag","__onMouseWheel","_target","hiddenTextarea","focus","__onOrientationChange","__onShake","__onLongPress","preventDefault","_fireEnterLeaveEvents","stopPropagation","_cacheTransformEventData","_handleEvent","_resetTransformEventData","getPointerId","evt","identifier","pointerId","isPrimary","touches","__onMouseDown","__onMouseUp","_willAddMouseDown","__onMouseMove","_shouldRender","shouldRender","isClick","_onMouseUpInDrawingMode","_finalizeCurrentTransform","targetWasActive","_maybeGroupObjects","isMoving","_setCursorFromEvent","eventType","subTargets","absolutePointer","currentTarget","currentSubTargets","_scaling","hasStateChanged","_addEventOptions","_fire","_onMouseDownInDrawingMode","_onMouseMoveInDrawingMode","_previousPointer","shouldGroup","_shouldGroup","_handleGrouping","saveState","_fireOverOutEvents","_transformObject","fireSyntheticInOutEvents","oldTarget","evtOut","canvasEvtOut","evtIn","canvasEvtIn","_draggedoverTarget","config","inOpt","outOpt","outFires","inFires","targetChanged","previousTarget","nextTarget","reset","_performTransformAction","getCornerCursor","_updateActiveSelection","_createActiveSelection","currentActiveObjects","removeWithUpdate","addWithUpdate","_createGroup","isActiveLower","groupObjects","exitEditing","ActiveSelection","_groupSelectedObjects","_collectObjects","aGroup","currentObject","selectionX1Y1","selectionX2Y2","allowIntersect","intersectsWithRect","isContainedWithinRect","toCanvasElement","cropping","scaledWidth","scaledHeight","originalWidth","originalHeight","newZoom","vp","originalInteractive","newVp","originalRetina","originalContextTop","loadFromJSON","json","serialized","JSON","_enlivenObjects","_setBgOverlay","enlivenedCanvasClip","__setupCanvas","loaded","cbIfLoaded","__setBgOverlay","enlivedObject","_toDataURL","_toDataURLWithMultiplier","toDataURLWithMultiplier","stringify","cloneWithoutData","backgroundImageOpacity","backgroundImageStretch","supportsLineDash","objectCaching","ALIASING_LIMIT","touchCornerSize","borderColor","borderDashArray","cornerDashArray","strokeDashOffset","borderOpacityWhenMoving","borderScaleFactor","minScaleLimit","hasControls","lockMovementX","lockMovementY","statefullCache","noScaleCache","dirty","paintFirst","stateProperties","cacheProperties","colorProperties","inverted","absolutePositioned","_cacheProperties","_updateCacheCanvas","_limitCacheSize","dims","limitedDims","capped","_getCacheCanvasDimensions","objectScale","getTotalObjectScaling","neededX","neededY","targetCanvas","minCacheSize","drawingWidth","drawingHeight","dimensionsChanged","cacheWidth","cacheHeight","zoomChanged","shouldRedraw","additionalWidth","additionalHeight","shouldResizeCanvas","canvasWidth","canvasHeight","sizeGrowing","sizeShrinking","setTransform","needFullTransform","_removeDefaultValues","getObjectScaling","retina","getObjectOpacity","shouldConstrainValue","isChanged","groupNeedsUpdate","_constrainScale","isOnACache","setOnGroup","getViewportTransform","isNotVisible","isOnScreen","_setupCompositeOperation","drawSelectionBackground","_setOpacity","drawCacheOnCanvas","_removeCacheCanvas","drawObject","propertySet","isCacheDirty","hasStroke","hasFill","needsItsOwnCache","ownCaching","willDrawShadow","drawClipPathOnCache","originalFill","originalStroke","_setClippingProperties","_setStrokeStyles","_setFillStyles","_drawClipPath","skipCanvas","_getNonTransformedDimensions","_removeShadow","decl","lineDashOffset","dashArray","alternative","drawBorders","forActiveSelection","drawBordersInGroup","scaling","multX","multY","_applyPatternGradientTransform","_renderPaintInOrder","_renderStroke","_renderFill","_renderDashedStroke","_applyPatternForTransformedGradient","pCanvas","pCtx","_findCenterFromElement","_assignTransformMatrixProps","preserveAspectRatioOptions","cropX","cropY","offsetLeft","offsetTop","objectForm","_fromObject","cloneAsImage","utils","origParams","originalGroup","originalShadow","withoutTransform","withoutShadow","boundingRect","getBoundingRect","shadowOffset","originalCanvas","isType","shouldCenterOrigin","_setOriginToCenter","_resetOrigin","centerH","viewportCenterH","centerV","viewportCenterV","viewportCenter","getLocalPointer","pClicked","objectLeftTop","createAccessors","extraParam","enlivedProps","originXOffset","originYOffset","translateToGivenOrigin","fromOriginX","fromOriginY","toOriginX","toOriginY","translateToCenterPoint","leftTop","getPointByOrigin","adjustPosition","to","hypotFull","getScaledWidth","xFull","yFull","offsetFrom","offsetTo","_originalOriginX","_originalOriginY","originPoint","arrayFromCoords","multiplyMatrices","oCoords","aCoords","lineCoords","ownMatrixCache","matrixCache","_getCoords","absolute","calculate","calcACoords","calcLineCoords","getCoords","pointTL","pointBR","intersection","other","otherCoords","lines","_getImageLines","_findCrossPoints","some","_containsCenterOfCanvas","isPartiallyOnScreen","allPointsAreOutside","every","topline","rightline","bottomline","leftline","xi","xcount","iLine","lineKey","getScaledHeight","scaleToWidth","boundingRectFactor","scaleToHeight","calcCoords","calcOCoords","cosP","sinP","cosPSinP","cosPMinusSinP","_calcRotateMatrix","_calcTranslateMatrix","startMatrix","_calculateCurrentDimensions","forEachControl","w","skipCorners","_setCornerCoords","transformMatrixKey","sep","prefix","calcOwnMatrix","cache","tMatrix","_calcDimensionsTransformMatrix","flipping","noSkew","_finalizeDimensions","getSvgColorString","getSvgStyles","skipShadow","getSvgFilter","getSvgSpanStyles","useWhiteSpace","term","textDecoration","getSvgTextDecoration","deltaY","decoration","getSvgCommons","getSvgTransform","full","svgTransform","_setSVGBg","textBgRects","_getFillAttributes","_createBaseSVGMarkup","_toSVG","_createBaseClipPathSVGMarkup","objectMarkup","commonPieces","noStyle","styleInfo","shadowInfo","withShadow","vectorEffect","absoluteClipPath","clipPathMarkup","addPaintOrder","originalSet","saveProps","props","tmpObj","_isEqual","origValue","currentValue","firstPass","dashedPropertySet","forTouch","isControlVisible","touchCorner","fn","newTheta","cosTheta","sinTheta","cornerHypotenuse","touchHypotenuse","cosHalfOffset","sinHalfOffset","touchCosHalfOffset","touchSinHalfOffset","wh","shouldStroke","setControlVisible","setControlsVisibility","FX_DURATION","fxCenterObjectH","callbacks","empty","fxCenterObjectV","fxRemove","propsToAnimate","skipCallbacks","_animate","propPair","propIsColor","from","valueProgress","timeProgress","coordProps","Line","_setWidthHeight","_getLeftToOriginX","_getTopToOriginY","makeEdgeToOriginGetter","axis1","axis2","dimension","nearest","farthest","calcLinePoints","origStrokeStyle","xMult","yMult","ATTRIBUTE_NAMES","parsedAttributes","_callback","propertyNames","originValues","pi","startAngle","endAngle","setRadius","svgString","startX","startY","endX","endY","largeFlag","getRadiusX","getRadiusY","isValidRadius","Triangle","widthBy2","heightBy2","piBy2","Ellipse","getRx","getRy","_initRxRy","isRounded","Polyline","_setPositionDimensions","calcDim","_calcDimensions","correctLeftTop","fromSVG","diffX","diffY","commonRender","fromElementGenerator","_class","Polygon","_toString","fromArray","_renderPathCommands","subpathStartX","subpathStartY","_getOffsetTransform","digits","aX","aY","deltaX","pathUrl","useSetOnGroup","isAlreadyGrouped","_calcBounds","_updateObjectsCoords","_updateObjectsACoords","skipControls","_updateObjectCoords","objectLeft","objectTop","_restoreObjectsState","_includeDefaultValues","objsToObject","originalDefaults","_obj","ownCache","_restoreObjectState","destroy","toActiveSelection","ungroupOnCanvas","setObjectsCoords","onlyWidthHeight","iLen","jLen","_getBounds","minXY","maxXY","enlivedClipPath","toGroup","newGroup","childrenOverride","srcFromAttribute","_lastScaleX","_lastScaleY","_filterScalingX","_filterScalingY","minimumScaleTrigger","cacheKey","imageSmoothing","filters","_initElement","_element","setElement","removeTexture","_initConfig","applyFilters","resizeFilter","applyResizeFilters","backend","filterBackend","evictCachesForKey","getCrossOrigin","getOriginalSize","_stroke","filterObj","getSrc","hasCrop","imageMarkup","strokeSvg","imageRendering","getSvgSrc","origFill","filtered","setSrc","minimumScale","elementToFilter","_filteredEl","sourceWidth","sourceHeight","isNeutralState","imgElement","_needsResize","elementToDraw","elWidth","elHeight","sX","sY","sW","sH","maxDestW","maxDestH","_resetWidthHeight","CSS_CANVAS","_initFilters","pAR","rWidth","rHeight","pWidth","pHeight","_object","resizeFilters","fromURL","imgOptions","_getAngleValueForStraighten","straighten","fxStraighten","straightenObject","fxStraightenObject","testPrecision","gl","precision","fragmentSource","fragmentShader","createShader","FRAGMENT_SHADER","shaderSource","compileShader","getShaderParameter","COMPILE_STATUS","isSupported","getParameter","MAX_TEXTURE_SIZE","precisions","webGlPrecision","setupGLContext","captureGPUInfo","createWebGLCanvas","aPosition","Float32Array","chooseFastestCopyGLTo2DMethod","canMeasurePerf","performance","canUseImageData","ImageData","canUseArrayBuffer","ArrayBuffer","canUseUint8Clamped","Uint8ClampedArray","imageBuffer","copyGLTo2D","copyGLTo2DPutImageData","testContext","destinationWidth","destinationHeight","startTime","drawImageTime","putImageDataTime","now","copyGLTo2DDrawImage","glOptions","premultipliedAlpha","depth","stencil","antialias","clearColor","cachedTexture","getCachedTexture","pipelineState","sourceTexture","createTexture","targetTexture","originalTexture","passes","webgl","programCache","pass","tempFbo","createFramebuffer","bindFramebuffer","FRAMEBUFFER","applyTo","resizeCanvasIfNeeded","bindTexture","TEXTURE_2D","deleteTexture","deleteFramebuffer","clearWebGLCaches","textureCache","textureImageSource","texture","texParameteri","TEXTURE_MAG_FILTER","NEAREST","TEXTURE_MIN_FILTER","TEXTURE_WRAP_S","CLAMP_TO_EDGE","TEXTURE_WRAP_T","texImage2D","RGBA","UNSIGNED_BYTE","uniqueId","gpuInfo","renderer","vendor","ext","getExtension","UNMASKED_RENDERER_WEBGL","UNMASKED_VENDOR_WEBGL","dWidth","dHeight","glCanvas","sourceY","numBytes","u8","Uint8Array","u8Clamped","readPixels","imgData","putImageData","sourceElement","originalImageData","originalEl","BaseFilter","vertexSource","createProgram","vertexShader","VERTEX_SHADER","getShaderInfoLog","program","attachShader","linkProgram","getProgramParameter","LINK_STATUS","getProgramInfoLog","attributeLocations","getAttributeLocations","uniformLocations","getUniformLocations","uStepW","getUniformLocation","uStepH","getAttribLocation","sendAttributeData","aPositionData","attributeLocation","buffer","createBuffer","bindBuffer","ARRAY_BUFFER","enableVertexAttribArray","vertexAttribPointer","FLOAT","bufferData","STATIC_DRAW","_setupFrameBuffer","framebufferTexture2D","COLOR_ATTACHMENT0","_swapTextures","main","mainParameter","applyToWebGL","applyTo2d","retrieveShader","shader","useProgram","uniform1f","sendUniformData","viewport","drawArrays","TRIANGLE_STRIP","bindAdditionalTexture","textureUnit","activeTexture","TEXTURE0","unbindAdditionalTexture","getMainParameter","setMainParameter","createHelpLayer","helpLayer","mainP","ColorMatrix","colorsOnly","uColorMatrix","uConstants","constants","uniformMatrix4fv","uniform4fv","Brightness","brightness","uBrightness","Convolute","opaque","Convolute_3_1","Convolute_3_0","Convolute_5_1","Convolute_5_0","Convolute_7_1","Convolute_7_0","Convolute_9_1","Convolute_9_0","weights","side","halfSide","sw","sh","output","createImageData","dst","alphaFac","dstOff","scx","scy","srcOff","wt","uMatrix","uOpaque","uHalfSize","uSize","uniform1fv","Grayscale","lightness","luminosity","mode","uMode","uniform1i","Invert","invert","uInvert","Noise","noise","rand","uNoise","uSeed","Pixelate","blocksize","_i","_j","_iLen","_jLen","uBlocksize","RemoveColor","useAlpha","lowC","highC","uLow","uHigh","Brownie","Vintage","Kodachrome","Technicolor","Polaroid","Sepia","BlackWhite","BlendColor","screen","diff","lighten","darken","exclusion","tint","buildSource","tg","alpha1","uColor","BlendImage","mask","TEXTURE1","calculateMatrix","canvas1","blendData","blendImage","uTransformMatrix","uImage","uniformMatrix3fv","Resize","resizeType","lanczosLobes","uDelta","uTaps","uniform2fv","horizontal","taps","filterWindow","getFilterWindow","generateShader","tempScale","getTaps","lobeFunction","lanczosCreate","offsets","fragmentSourceTOP","dW","dH","lobes","xx","rcpScaleX","rcpScaleY","oW","oH","newData","sliceByTwo","hermiteFastResize","bilinearFiltering","lanczosResize","mult","doneW","doneH","stepW","stepH","tmpCanvas","dX","dY","process","u","weight","fX","fY","ratioX","icenter","ratioY","range2X","cacheLanc","range2Y","lanczos","rcpRatioX","rcpRatioY","srcData","destData","destImg","xDiff","yDiff","chnl","origPix","w4","pixels","destImage","destPixels","ratioW","ratioH","ratioWHalf","ratioHHalf","img2","data2","weightsAlpha","gxR","gxG","gxB","gxA","centerY","yy","centerX","w0","Contrast","contrast","contrastF","uContrast","Saturation","saturation","adjust","uSaturation","Blur","aspectRatio","simpleBlur","canvas2","blurLayer1","blurLayer2","ctx1","ctx2","nSamples","percent","newImageData","delta","chooseRightDelta","blurScale","Gamma","gamma","rInv","gInv","bInv","rVals","gVals","bVals","uGamma","uniform3fv","Composed","subFilters","HueRotation","rotation","rad","aThird","aThirdSqtSin","OneMinusCos","_dimensionAffectingProps","_reNewline","_reSpacesAndTabs","_reSpaceAndTab","_reWords","underline","overline","linethrough","textAlign","superscript","baseline","subscript","textBackgroundColor","_fontSizeFraction","_fontSizeMult","charSpacing","_measuringContext","_styleProperties","__charBounds","CACHE_FONT_SIZE","MIN_TEXT_WIDTH","text","__skipDimension","initDimensions","getMeasuringContext","_splitText","newLines","_splitTextIntoLines","textLines","_textLines","graphemeLines","_unwrappedTextLines","_unwrappedLines","_text","graphemeText","_clearCache","calcTextWidth","cursorWidth","enlargeSpaces","calcTextHeight","diffSpace","currentLineWidth","numberOfSpaces","accumulatedSpace","line","charBound","spaces","isEndOfWrapping","getLineWidth","kernedWidth","lineIndex","missingNewlineOffset","_setTextStyles","_renderTextLinesBackground","_renderTextDecoration","_renderText","_renderTextStroke","_renderTextFill","charStyle","forMeasuring","textBaseline","_getFontDeclaration","maxWidth","_renderTextLine","_renderChars","styleHas","lineTopOffset","heightOfLine","lineLeftOffset","lastColor","leftOffset","_getLeftOffset","topOffset","_getTopOffset","boxStart","boxWidth","charBox","currentColor","getHeightOfLine","_getLineLeftOffset","getValueOfPropertyAt","getFontCache","cacheProp","_applyCharStyles","styleDeclaration","_measureChar","previousChar","prevCharStyle","fontCache","fontDeclaration","previousFontDeclaration","couple","stylesAreEqual","coupleWidth","previousWidth","fontMultiplier","measureText","getHeightOfChar","measureLine","lineInfo","_measureLine","_getWidthOfCharSpacing","grapheme","prevGrapheme","graphemeInfo","numOfSpaces","lineBounds","_getGraphemeBox","skipLeft","getCompleteStyleDeclaration","prevStyle","previousBox","__lineHeights","maxHeight","_renderTextCommon","lineHeights","isEmptyStyles","isJustify","actualStyle","nextStyle","charsToRender","timeToRender","shortCut","_renderChar","_hasStyleChanged","_getStyleDeclaration","fullDecl","shouldFill","fillText","strokeText","setSuperscript","_setScript","setSubscript","schema","loc","get2DCursorLocation","setSelectionStyles","thisStyle","_hasStyleChangedForSvg","__lineWidths","_shouldClearDimensionCache","shouldClear","_forceClearCache","_size","_dy","lastDecoration","currentDecoration","currentFill","lastFill","styleObject","family","fontIsGeneric","genericFonts","newLine","newText","additionalProperties","needsDims","_key","parsedAnchor","textAnchor","originalStrokeWidth","textHeightScaleFactor","lineHeightDiff","scaledDiff","textHeight","offX","p3","cleanStyle","stylesCount","letterCount","stylePropertyValue","allStyleObjectPropertiesMatch","graphemeCount","stylePropertyHasBeenSet","removeStyle","lineNum","charNum","_extendStyles","_getLineStyle","_setLineStyle","_setStyleDeclaration","selectionStart","skipWrapping","getSelectionStyles","startIndex","endIndex","selectionEnd","getStyleAtPosition","lineStyle","_deleteStyleDeclaration","_deleteLineStyle","parseDecoration","IText","editable","editingBorderColor","cursorColor","cursorDelay","cursorDuration","caching","_reSpace","_currentCursorOpacity","_selectionDirection","_abortCursorAnimation","__widthOfSpace","inCompositionMode","initBehavior","setSelectionStart","_updateAndFire","setSelectionEnd","_fireSelectionChanged","_updateTextarea","initDelayedCursor","cursorOffsetCache","renderCursorOrSelection","skipRestore","_clearTextArea","boundaries","_getCursorBoundaries","renderCursor","renderSelection","_getCursorBoundariesOffsets","cursorPosition","cursorLocation","charHeight","__isMousedown","startLine","endLine","startChar","endChar","lineOffset","realLineHeight","boxEnd","compositionColor","getCurrentCharFontSize","cp","_getCurrentCharIndex","getCurrentCharColor","initAddedHandler","initRemovedHandler","initCursorSelectionHandlers","initDoubleClickSimulation","mouseMoveHandler","_initCanvasHandlers","_removeCanvasHandlers","_tick","_currentTickState","_animateCursor","targetOpacity","completeMethod","tickState","isAborted","_onTickComplete","_cursorTimeout1","_currentTickCompleteState","restart","delay","abortCursorAnimation","_cursorTimeout2","selectAll","getSelectedText","findWordBoundaryLeft","startFrom","findWordBoundaryRight","findLineBoundaryLeft","findLineBoundaryRight","searchWordBoundary","direction","selectWord","newSelectionStart","newSelectionEnd","selectLine","enterEditing","exitEditingOnOthers","initHiddenTextarea","_saveEditingProps","_setEditingProps","_textBeforeEdit","initMouseMoveHandler","getSelectionStartFromPointer","currentStart","currentEnd","__selectionStartOnMouseDown","restartCursorIfNeeded","fromStringToGraphemeSelection","smallerTextStart","graphemeStart","smallerTextEnd","graphemeEnd","fromGraphemeToStringSelection","newSelection","updateTextareaPosition","updateFromTextArea","_calcTextareaPosition","desiredPosition","compositionStart","upperCanvas","upperCanvasWidth","upperCanvasHeight","clientWidth","clientHeight","_savedProps","_restoreEditingProps","isTextChanged","_removeExtraneousStyles","removeStyleFromTo","cursorStart","cursorEnd","lineStart","charStart","lineEnd","charEnd","styleObj","shiftLineStyles","numericChar","clonedStyles","numericLine","insertNewlineStyleObject","qty","copiedStyle","currentCharStyle","newLineStyles","somethingAdded","isEndOfLine","numIndex","styleCarriedOver","insertCharStyleObject","quantity","currentLineStyles","currentLineStylesCloned","numericIndex","newStyle","insertNewStyleBlock","insertedText","cursorLoc","addedLines","linesLength","setSelectionStartEndWithShift","setSelectionInBoundaries","__lastClickTime","__lastLastClickTime","__lastPointer","__newClickTime","newPointer","isTripleClick","_stopEvent","__lastIsEditing","__lastSelected","initMousedownHandler","initMouseupHandler","initClicks","doubleClickHandler","tripleClickHandler","_mouseDownHandler","setCursorByClick","_mouseDownHandlerBefore","currentActive","mouseOffset","prevWidth","_getNewSelectionStartFromOffset","distanceBtwLastCharAndCursor","distanceBtwNextCharAndCursor","onKeyDown","onKeyUp","onInput","copy","paste","onCompositionStart","onCompositionUpdate","onCompositionEnd","_clickHandlerInitialized","onClick","keysMap","ctrlKeysMapUp","ctrlKeysMapDown","keyCode","ctrlKey","metaKey","stopImmediatePropagation","_copyDone","fromPaste","nextText","charCount","nextCharCount","removedText","charDiff","removeFrom","removeTo","textareaSelection","backDelete","copiedText","copiedTextStyle","compositionEnd","_getClipboardData","clipboardData","_getWidthBeforeCursor","widthBeforeCursor","getDownCursorOffset","isRight","selectionProp","_getSelectionForOffset","indexOnOtherLine","_getIndexOnLine","textAfterCursor","getUpCursorOffset","textBeforeCursor","widthOfCharsOnLine","indexOnLine","charWidth","foundMatch","leftEdge","rightEdge","offsetFromLeftEdge","offsetFromRightEdge","moveCursorDown","_moveCursorUpOrDown","moveCursorUp","moveCursorWithShift","moveCursorWithoutShift","moveCursorLeft","_moveCursorLeftOrRight","_move","_moveLeft","_moveRight","moveCursorLeftWithoutShift","change","moveCursorLeftWithShift","moveCursorRight","moveCursorRightWithShift","moveCursorRightWithoutShift","changed","removeChars","insertChars","multipleSpacesRegex","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","lineTop","noShadow","textSpans","textTopOffset","textLeftOffset","_setSVGTextLineBg","_setSVGTextLineText","_createTextCharSpan","styleDecl","shouldUseWhitespace","styleProps","fillStyles","dySpan","_pushTextBgRect","fillColor","_getSVGLineTopOffset","lastHeight","svgStyle","Textbox","minWidth","dynamicMinWidth","__cachedLines","_wordJoiners","splitByGrapheme","_styleMap","_generateStyleMap","textInfo","realLineCount","realLineCharCount","isWrapping","nextLineIndex","nextOffset","shouldLimit","mapNextLine","_wrapText","desiredWidth","wrapped","_wrapLine","_measureWord","word","charOffset","_line","reservedSpace","words","infix","wordWidth","infixWidth","largestWordWidth","lineJustStarted","additionalSpace","getMinWidth","linesToKeep","scaleSkewStyleHandler","scaleStyleHandler","objectControls","ml","mr","mb","mtr","textBoxControls"],"mappings":"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1C,EAAyD,KAAKC,gBAA9D;;AACA,UAAI,KAAKC,aAAT,EAAwB;AACtB,aAAKH,mBAAL,CAAyBD,UAAzB,EAAqC,KAAKI,aAA1C,EAAyD,KAAKC,UAA9D;AACD;AACF,KA3N6G;AA6N9GJ,IAAAA,mBAAmB,EAAE,UAASD,UAAT,EAAqBvoC,MAArB,EAA6BjL,OAA7B,EAAsC;AACzDiL,MAAAA,MAAM,CAACqU,YAAP,CAAoB,OAApB,EAA6B,KAAKza,KAAL,GAAa2uC,UAA1C;AACAvoC,MAAAA,MAAM,CAACqU,YAAP,CAAoB,QAApB,EAA8B,KAAKra,MAAL,GAAcuuC,UAA5C;AACAxzC,MAAAA,OAAO,CAACsrB,KAAR,CAAckoB,UAAd,EAA0BA,UAA1B;AACD,KAjO6G;;AAoO9G;AACJ;AACA;AACA;AACA;AACA;AACIH,IAAAA,UAAU,EAAE,YAAY;AACtB,WAAKS,OAAL,GAAe5zB,gBAAgB,CAAC,KAAKwzB,aAAN,CAA/B;AACA,aAAO,IAAP;AACD,KA7O6G;;AA+O9G;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACIT,IAAAA,eAAe,EAAE,UAAUc,KAAV,EAAiBh0C,QAAjB,EAA2BxB,OAA3B,EAAoC;AACnD,aAAO,KAAKy1C,mBAAL,CAAyB,cAAzB,EAAyCD,KAAzC,EAAgDh0C,QAAhD,EAA0DxB,OAA1D,CAAP;AACD,KAhS6G;;AAkS9G;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A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A;AACA;AACA;AACIM,IAAAA,YAAY,EAAc,KA1awE;;AA4alG;AACJ;AACA;AACA;AACA;AACID,IAAAA,YAAY,EAAc,KAjbwE;;AAmblG;AACJ;AACA;AACA;AACA;AACIiE,IAAAA,eAAe,EAAW,KAxbwE;;AA0blG;AACJ;AACA;AACA;AACA;AACA;AACI2P,IAAAA,iBAAiB,EAAS,KAhcwE;;AAkclG;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACIyb,IAAAA,aAAa,EAAaA,aA1cwE;;AA4clG;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACIa,IAAAA,cAAc,EAAa,KAtduE;;AAwdlG;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACIC,IAAAA,YAAY,EAAe,IAjeuE;;AAmelG;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACIlrB,IAAAA,aAAa,EAAe,KA7esE;;AA+elG;AACJ;AACA;AACA;AACA;AACA;AACImrB,IAAAA,KAAK,EAAiB,IArf4E;;AAuflG;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACInP,IAAAA,QAAQ,EAAE,CA/fwF;;AAigBlG;AACJ;AACA;AACA;AACA;AACIoP,IAAAA,UAAU,EAAY,MAtgB4E;;AAwgBlG;AACJ;AACA;AACA;AACA;AACA;AACIC,IAAAA,eAAe,EAAE,CACf,qFACA,oGADA,GAEA,6EAFA,GAGA,wDAJe,EAKfnvD,KALe,CAKT,GALS,CA9gBiF;;AAqhBlG;AACJ;AACA;AACA;AACA;AACA;AACA;AACIovD,IAAAA,eAAe,EAAE,CACf,kFACA,0FAFe,EAGfpvD,KAHe,CAGT,GAHS,CA5hBiF;;AAiiBlG;AACJ;AACA;AACA;AACIqvD,IAAAA,eAAe,EACb,6BADe,CAEfrvD,KAFe,CAET,GAFS,CAriBiF;;AAyiBlG;AACJ;AACA;AACA;AACA;AACA;AACA;AACIqtB,IAAAA,QAAQ,EAAE3sB,SAhjBwF;;AAkjBlG;AACJ;AACA;AACA;AACA;AACA;AACA;AACI4uD,IAAAA,QAAQ,EAAE,KAzjB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","sourcesContent":["/* build: `node build.js modules=ALL exclude=gestures,accessors requirejs minifier=uglifyjs` */\n/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */\n\nvar fabric = fabric || { version: '4.2.0' };\nif (typeof exports !== 'undefined') {\n  exports.fabric = fabric;\n}\n/* _AMD_START_ */\nelse if (typeof define === 'function' && define.amd) {\n  define([], function() { return fabric; });\n}\n/* _AMD_END_ */\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\n  if (document instanceof (typeof HTMLDocument !== 'undefined' ? HTMLDocument : Document)) {\n    fabric.document = document;\n  }\n  else {\n    fabric.document = document.implementation.createHTMLDocument('');\n  }\n  fabric.window = window;\n}\nelse {\n  // assume we're running under node.js when document/window are not present\n  var jsdom = require('jsdom');\n  var virtualWindow = new jsdom.JSDOM(\n    decodeURIComponent('%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E'),\n    {\n      features: {\n        FetchExternalResources: ['img']\n      },\n      resources: 'usable'\n    }).window;\n  fabric.document = virtualWindow.document;\n  fabric.jsdomImplForWrapper = require('jsdom/lib/jsdom/living/generated/utils').implForWrapper;\n  fabric.nodeCanvas = require('jsdom/lib/jsdom/utils').Canvas;\n  fabric.window = virtualWindow;\n  DOMParser = fabric.window.DOMParser;\n}\n\n/**\n * True when in environment that supports touch events\n * @type boolean\n */\nfabric.isTouchSupported = 'ontouchstart' in fabric.window || 'ontouchstart' in fabric.document ||\n  (fabric.window && fabric.window.navigator && fabric.window.navigator.maxTouchPoints > 0);\n\n/**\n * True when in environment that's probably Node.js\n * @type boolean\n */\nfabric.isLikelyNode = typeof Buffer !== 'undefined' &&\n                      typeof window === 'undefined';\n\n/* _FROM_SVG_START_ */\n/**\n * Attributes parsed from all SVG elements\n * @type array\n */\nfabric.SHARED_ATTRIBUTES = [\n  'display',\n  'transform',\n  'fill', 'fill-opacity', 'fill-rule',\n  'opacity',\n  'stroke', 'stroke-dasharray', 'stroke-linecap', 'stroke-dashoffset',\n  'stroke-linejoin', 'stroke-miterlimit',\n  'stroke-opacity', 'stroke-width',\n  'id', 'paint-order', 'vector-effect',\n  'instantiated_by_use', 'clip-path',\n];\n/* _FROM_SVG_END_ */\n\n/**\n * Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion.\n */\nfabric.DPI = 96;\nfabric.reNum = '(?:[-+]?(?:\\\\d+|\\\\d*\\\\.\\\\d+)(?:[eE][-+]?\\\\d+)?)';\nfabric.commaWsp = '(?:\\\\s+,?\\\\s*|,\\\\s*)'\nfabric.rePathCommand = /([-+]?((\\d+\\.\\d+)|((\\d+)|(\\.\\d+)))(?:[eE][-+]?\\d+)?)/ig;\nfabric.reNonWord = /[ \\n\\.,;!\\?\\-]/;\nfabric.fontPaths = { };\nfabric.iMatrix = [1, 0, 0, 1, 0, 0];\nfabric.svgNS = 'http://www.w3.org/2000/svg';\n\n/**\n * Pixel limit for cache canvases. 1Mpx , 4Mpx should be fine.\n * @since 1.7.14\n * @type Number\n * @default\n */\nfabric.perfLimitSizeTotal = 2097152;\n\n/**\n * Pixel limit for cache canvases width or height. IE fixes the maximum at 5000\n * @since 1.7.14\n * @type Number\n * @default\n */\nfabric.maxCacheSideLimit = 4096;\n\n/**\n * Lowest pixel limit for cache canvases, set at 256PX\n * @since 1.7.14\n * @type Number\n * @default\n */\nfabric.minCacheSideLimit = 256;\n\n/**\n * Cache Object for widths of chars in text rendering.\n */\nfabric.charWidthsCache = { };\n\n/**\n * if webgl is enabled and available, textureSize will determine the size\n * of the canvas backend\n * @since 2.0.0\n * @type Number\n * @default\n */\nfabric.textureSize = 2048;\n\n/**\n * When 'true', style information is not retained when copy/pasting text, making\n * pasted text use destination style.\n * Defaults to 'false'.\n * @type Boolean\n * @default\n */\nfabric.disableStyleCopyPaste = false;\n\n/**\n * Enable webgl for filtering picture is available\n * A filtering backend will be initialized, this will both take memory and\n * time since a default 2048x2048 canvas will be created for the gl context\n * @since 2.0.0\n * @type Boolean\n * @default\n */\nfabric.enableGLFiltering = true;\n\n/**\n * Device Pixel Ratio\n * @see https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/SettingUptheCanvas.html\n */\nfabric.devicePixelRatio = fabric.window.devicePixelRatio ||\n                          fabric.window.webkitDevicePixelRatio ||\n                          fabric.window.mozDevicePixelRatio ||\n                          1;\n/**\n * Browser-specific constant to adjust CanvasRenderingContext2D.shadowBlur value,\n * which is unitless and not rendered equally across browsers.\n *\n * Values that work quite well (as of October 2017) are:\n * - Chrome: 1.5\n * - Edge: 1.75\n * - Firefox: 0.9\n * - Safari: 0.95\n *\n * @since 2.0.0\n * @type Number\n * @default 1\n */\nfabric.browserShadowBlurConstant = 1;\n\n/**\n * This object contains the result of arc to beizer conversion for faster retrieving if the same arc needs to be converted again.\n * It was an internal variable, is accessible since version 2.3.4\n */\nfabric.arcToSegmentsCache = { };\n\n/**\n * This object keeps the results of the boundsOfCurve calculation mapped by the joined arguments necessary to calculate it.\n * It does speed up calculation, if you parse and add always the same paths, but in case of heavy usage of freedrawing\n * you do not get any speed benefit and you get a big object in memory.\n * The object was a private variable before, while now is appended to the lib so that you have access to it and you\n * can eventually clear it.\n * It was an internal variable, is accessible since version 2.3.4\n */\nfabric.boundsOfCurveCache = { };\n\n/**\n * If disabled boundsOfCurveCache is not used. For apps that make heavy usage of pencil drawing probably disabling it is better\n * @default true\n */\nfabric.cachesBoundsOfCurve = true;\n\n/**\n * Skip performance testing of setupGLContext and force the use of putImageData that seems to be the one that works best on\n * Chrome + old hardware. if your users are experiencing empty images after filtering you may try to force this to true\n * this has to be set before instantiating the filtering backend ( before filtering the first image )\n * @type Boolean\n * @default false\n */\nfabric.forceGLPutImageData = false;\n\nfabric.initFilterBackend = function() {\n  if (fabric.enableGLFiltering && fabric.isWebglSupported && fabric.isWebglSupported(fabric.textureSize)) {\n    console.log('max texture size: ' + fabric.maxTextureSize);\n    return (new fabric.WebglFilterBackend({ tileSize: fabric.textureSize }));\n  }\n  else if (fabric.Canvas2dFilterBackend) {\n    return (new fabric.Canvas2dFilterBackend());\n  }\n};\n\n\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\n  // ensure globality even if entire library were function wrapped (as in Meteor.js packaging system)\n  window.fabric = fabric;\n}\n\n\n(function() {\n\n  /**\n   * @private\n   * @param {String} eventName\n   * @param {Function} handler\n   */\n  function _removeEventListener(eventName, handler) {\n    if (!this.__eventListeners[eventName]) {\n      return;\n    }\n    var eventListener = this.__eventListeners[eventName];\n    if (handler) {\n      eventListener[eventListener.indexOf(handler)] = false;\n    }\n    else {\n      fabric.util.array.fill(eventListener, false);\n    }\n  }\n\n  /**\n   * Observes specified event\n   * @memberOf fabric.Observable\n   * @alias on\n   * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n   * @param {Function} handler Function that receives a notification when an event of the specified type occurs\n   * @return {Self} thisArg\n   * @chainable\n   */\n  function on(eventName, handler) {\n    if (!this.__eventListeners) {\n      this.__eventListeners = { };\n    }\n    // one object with key/value pairs was passed\n    if (arguments.length === 1) {\n      for (var prop in eventName) {\n        this.on(prop, eventName[prop]);\n      }\n    }\n    else {\n      if (!this.__eventListeners[eventName]) {\n        this.__eventListeners[eventName] = [];\n      }\n      this.__eventListeners[eventName].push(handler);\n    }\n    return this;\n  }\n\n  /**\n   * Stops event observing for a particular event handler. Calling this method\n   * without arguments removes all handlers for all events\n   * @memberOf fabric.Observable\n   * @alias off\n   * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n   * @param {Function} handler Function to be deleted from EventListeners\n   * @return {Self} thisArg\n   * @chainable\n   */\n  function off(eventName, handler) {\n    if (!this.__eventListeners) {\n      return this;\n    }\n\n    // remove all key/value pairs (event name -> event handler)\n    if (arguments.length === 0) {\n      for (eventName in this.__eventListeners) {\n        _removeEventListener.call(this, eventName);\n      }\n    }\n    // one object with key/value pairs was passed\n    else if (arguments.length === 1 && typeof arguments[0] === 'object') {\n      for (var prop in eventName) {\n        _removeEventListener.call(this, prop, eventName[prop]);\n      }\n    }\n    else {\n      _removeEventListener.call(this, eventName, handler);\n    }\n    return this;\n  }\n\n  /**\n   * Fires event with an optional options object\n   * @memberOf fabric.Observable\n   * @param {String} eventName Event name to fire\n   * @param {Object} [options] Options object\n   * @return {Self} thisArg\n   * @chainable\n   */\n  function fire(eventName, options) {\n    if (!this.__eventListeners) {\n      return this;\n    }\n\n    var listenersForEvent = this.__eventListeners[eventName];\n    if (!listenersForEvent) {\n      return this;\n    }\n\n    for (var i = 0, len = listenersForEvent.length; i < len; i++) {\n      listenersForEvent[i] && listenersForEvent[i].call(this, options || { });\n    }\n    this.__eventListeners[eventName] = listenersForEvent.filter(function(value) {\n      return value !== false;\n    });\n    return this;\n  }\n\n  /**\n   * @namespace fabric.Observable\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#events}\n   * @see {@link http://fabricjs.com/events|Events demo}\n   */\n  fabric.Observable = {\n    fire: fire,\n    on: on,\n    off: off,\n  };\n})();\n\n\n/**\n * @namespace fabric.Collection\n */\nfabric.Collection = {\n\n  _objects: [],\n\n  /**\n   * Adds objects to collection, Canvas or Group, then renders canvas\n   * (if `renderOnAddRemove` is not `false`).\n   * in case of Group no changes to bounding box are made.\n   * Objects should be instances of (or inherit from) fabric.Object\n   * Use of this function is highly discouraged for groups.\n   * you can add a bunch of objects with the add method but then you NEED\n   * to run a addWithUpdate call for the Group class or position/bbox will be wrong.\n   * @param {...fabric.Object} object Zero or more fabric instances\n   * @return {Self} thisArg\n   * @chainable\n   */\n  add: function () {\n    this._objects.push.apply(this._objects, arguments);\n    if (this._onObjectAdded) {\n      for (var i = 0, length = arguments.length; i < length; i++) {\n        this._onObjectAdded(arguments[i]);\n      }\n    }\n    this.renderOnAddRemove && this.requestRenderAll();\n    return this;\n  },\n\n  /**\n   * Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`)\n   * An object should be an instance of (or inherit from) fabric.Object\n   * Use of this function is highly discouraged for groups.\n   * you can add a bunch of objects with the insertAt method but then you NEED\n   * to run a addWithUpdate call for the Group class or position/bbox will be wrong.\n   * @param {Object} object Object to insert\n   * @param {Number} index Index to insert object at\n   * @param {Boolean} nonSplicing When `true`, no splicing (shifting) of objects occurs\n   * @return {Self} thisArg\n   * @chainable\n   */\n  insertAt: function (object, index, nonSplicing) {\n    var objects = this._objects;\n    if (nonSplicing) {\n      objects[index] = object;\n    }\n    else {\n      objects.splice(index, 0, object);\n    }\n    this._onObjectAdded && this._onObjectAdded(object);\n    this.renderOnAddRemove && this.requestRenderAll();\n    return this;\n  },\n\n  /**\n   * Removes objects from a collection, then renders canvas (if `renderOnAddRemove` is not `false`)\n   * @param {...fabric.Object} object Zero or more fabric instances\n   * @return {Self} thisArg\n   * @chainable\n   */\n  remove: function() {\n    var objects = this._objects,\n        index, somethingRemoved = false;\n\n    for (var i = 0, length = arguments.length; i < length; i++) {\n      index = objects.indexOf(arguments[i]);\n\n      // only call onObjectRemoved if an object was actually removed\n      if (index !== -1) {\n        somethingRemoved = true;\n        objects.splice(index, 1);\n        this._onObjectRemoved && this._onObjectRemoved(arguments[i]);\n      }\n    }\n\n    this.renderOnAddRemove && somethingRemoved && this.requestRenderAll();\n    return this;\n  },\n\n  /**\n   * Executes given function for each object in this group\n   * @param {Function} callback\n   *                   Callback invoked with current object as first argument,\n   *                   index - as second and an array of all objects - as third.\n   *                   Callback is invoked in a context of Global Object (e.g. `window`)\n   *                   when no `context` argument is given\n   *\n   * @param {Object} context Context (aka thisObject)\n   * @return {Self} thisArg\n   * @chainable\n   */\n  forEachObject: function(callback, context) {\n    var objects = this.getObjects();\n    for (var i = 0, len = objects.length; i < len; i++) {\n      callback.call(context, objects[i], i, objects);\n    }\n    return this;\n  },\n\n  /**\n   * Returns an array of children objects of this instance\n   * Type parameter introduced in 1.3.10\n   * since 2.3.5 this method return always a COPY of the array;\n   * @param {String} [type] When specified, only objects of this type are returned\n   * @return {Array}\n   */\n  getObjects: function(type) {\n    if (typeof type === 'undefined') {\n      return this._objects.concat();\n    }\n    return this._objects.filter(function(o) {\n      return o.type === type;\n    });\n  },\n\n  /**\n   * Returns object at specified index\n   * @param {Number} index\n   * @return {Self} thisArg\n   */\n  item: function (index) {\n    return this._objects[index];\n  },\n\n  /**\n   * Returns true if collection contains no objects\n   * @return {Boolean} true if collection is empty\n   */\n  isEmpty: function () {\n    return this._objects.length === 0;\n  },\n\n  /**\n   * Returns a size of a collection (i.e: length of an array containing its objects)\n   * @return {Number} Collection size\n   */\n  size: function() {\n    return this._objects.length;\n  },\n\n  /**\n   * Returns true if collection contains an object\n   * @param {Object} object Object to check against\n   * @return {Boolean} `true` if collection contains an object\n   */\n  contains: function(object) {\n    return this._objects.indexOf(object) > -1;\n  },\n\n  /**\n   * Returns number representation of a collection complexity\n   * @return {Number} complexity\n   */\n  complexity: function () {\n    return this._objects.reduce(function (memo, current) {\n      memo += current.complexity ? current.complexity() : 0;\n      return memo;\n    }, 0);\n  }\n};\n\n\n/**\n * @namespace fabric.CommonMethods\n */\nfabric.CommonMethods = {\n\n  /**\n   * Sets object's properties from options\n   * @param {Object} [options] Options object\n   */\n  _setOptions: function(options) {\n    for (var prop in options) {\n      this.set(prop, options[prop]);\n    }\n  },\n\n  /**\n   * @private\n   * @param {Object} [filler] Options object\n   * @param {String} [property] property to set the Gradient to\n   */\n  _initGradient: function(filler, property) {\n    if (filler && filler.colorStops && !(filler instanceof fabric.Gradient)) {\n      this.set(property, new fabric.Gradient(filler));\n    }\n  },\n\n  /**\n   * @private\n   * @param {Object} [filler] Options object\n   * @param {String} [property] property to set the Pattern to\n   * @param {Function} [callback] callback to invoke after pattern load\n   */\n  _initPattern: function(filler, property, callback) {\n    if (filler && filler.source && !(filler instanceof fabric.Pattern)) {\n      this.set(property, new fabric.Pattern(filler, callback));\n    }\n    else {\n      callback && callback();\n    }\n  },\n\n  /**\n   * @private\n   */\n  _setObject: function(obj) {\n    for (var prop in obj) {\n      this._set(prop, obj[prop]);\n    }\n  },\n\n  /**\n   * Sets property to a given value. When changing position/dimension -related properties (left, top, scale, angle, etc.) `set` does not update position of object's borders/controls. If you need to update those, call `setCoords()`.\n   * @param {String|Object} key Property name or object (if object, iterate over the object properties)\n   * @param {Object|Function} value Property value (if function, the value is passed into it and its return value is used as a new one)\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  set: function(key, value) {\n    if (typeof key === 'object') {\n      this._setObject(key);\n    }\n    else {\n      this._set(key, value);\n    }\n    return this;\n  },\n\n  _set: function(key, value) {\n    this[key] = value;\n  },\n\n  /**\n   * Toggles specified property from `true` to `false` or from `false` to `true`\n   * @param {String} property Property to toggle\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  toggle: function(property) {\n    var value = this.get(property);\n    if (typeof value === 'boolean') {\n      this.set(property, !value);\n    }\n    return this;\n  },\n\n  /**\n   * Basic getter\n   * @param {String} property Property name\n   * @return {*} value of a property\n   */\n  get: function(property) {\n    return this[property];\n  }\n};\n\n\n(function(global) {\n\n  var sqrt = Math.sqrt,\n      atan2 = Math.atan2,\n      pow = Math.pow,\n      PiBy180 = Math.PI / 180,\n      PiBy2 = Math.PI / 2;\n\n  /**\n   * @namespace fabric.util\n   */\n  fabric.util = {\n\n    /**\n     * Calculate the cos of an angle, avoiding returning floats for known results\n     * @static\n     * @memberOf fabric.util\n     * @param {Number} angle the angle in radians or in degree\n     * @return {Number}\n     */\n    cos: function(angle) {\n      if (angle === 0) { return 1; }\n      if (angle < 0) {\n        // cos(a) = cos(-a)\n        angle = -angle;\n      }\n      var angleSlice = angle / PiBy2;\n      switch (angleSlice) {\n        case 1: case 3: return 0;\n        case 2: return -1;\n      }\n      return Math.cos(angle);\n    },\n\n    /**\n     * Calculate the sin of an angle, avoiding returning floats for known results\n     * @static\n     * @memberOf fabric.util\n     * @param {Number} angle the angle in radians or in degree\n     * @return {Number}\n     */\n    sin: function(angle) {\n      if (angle === 0) { return 0; }\n      var angleSlice = angle / PiBy2, sign = 1;\n      if (angle < 0) {\n        // sin(-a) = -sin(a)\n        sign = -1;\n      }\n      switch (angleSlice) {\n        case 1: return sign;\n        case 2: return 0;\n        case 3: return -sign;\n      }\n      return Math.sin(angle);\n    },\n\n    /**\n     * Removes value from an array.\n     * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf`\n     * @static\n     * @memberOf fabric.util\n     * @param {Array} array\n     * @param {*} value\n     * @return {Array} original array\n     */\n    removeFromArray: function(array, value) {\n      var idx = array.indexOf(value);\n      if (idx !== -1) {\n        array.splice(idx, 1);\n      }\n      return array;\n    },\n\n    /**\n     * Returns random number between 2 specified ones.\n     * @static\n     * @memberOf fabric.util\n     * @param {Number} min lower limit\n     * @param {Number} max upper limit\n     * @return {Number} random value (between min and max)\n     */\n    getRandomInt: function(min, max) {\n      return Math.floor(Math.random() * (max - min + 1)) + min;\n    },\n\n    /**\n     * Transforms degrees to radians.\n     * @static\n     * @memberOf fabric.util\n     * @param {Number} degrees value in degrees\n     * @return {Number} value in radians\n     */\n    degreesToRadians: function(degrees) {\n      return degrees * PiBy180;\n    },\n\n    /**\n     * Transforms radians to degrees.\n     * @static\n     * @memberOf fabric.util\n     * @param {Number} radians value in radians\n     * @return {Number} value in degrees\n     */\n    radiansToDegrees: function(radians) {\n      return radians / PiBy180;\n    },\n\n    /**\n     * Rotates `point` around `origin` with `radians`\n     * @static\n     * @memberOf fabric.util\n     * @param {fabric.Point} point The point to rotate\n     * @param {fabric.Point} origin The origin of the rotation\n     * @param {Number} radians The radians of the angle for the rotation\n     * @return {fabric.Point} The new rotated point\n     */\n    rotatePoint: function(point, origin, radians) {\n      point.subtractEquals(origin);\n      var v = fabric.util.rotateVector(point, radians);\n      return new fabric.Point(v.x, v.y).addEquals(origin);\n    },\n\n    /**\n     * Rotates `vector` with `radians`\n     * @static\n     * @memberOf fabric.util\n     * @param {Object} vector The vector to rotate (x and y)\n     * @param {Number} radians The radians of the angle for the rotation\n     * @return {Object} The new rotated point\n     */\n    rotateVector: function(vector, radians) {\n      var sin = fabric.util.sin(radians),\n          cos = fabric.util.cos(radians),\n          rx = vector.x * cos - vector.y * sin,\n          ry = vector.x * sin + vector.y * cos;\n      return {\n        x: rx,\n        y: ry\n      };\n    },\n\n    /**\n     * Apply transform t to point p\n     * @static\n     * @memberOf fabric.util\n     * @param  {fabric.Point} p The point to transform\n     * @param  {Array} t The transform\n     * @param  {Boolean} [ignoreOffset] Indicates that the offset should not be applied\n     * @return {fabric.Point} The transformed point\n     */\n    transformPoint: function(p, t, ignoreOffset) {\n      if (ignoreOffset) {\n        return new fabric.Point(\n          t[0] * p.x + t[2] * p.y,\n          t[1] * p.x + t[3] * p.y\n        );\n      }\n      return new fabric.Point(\n        t[0] * p.x + t[2] * p.y + t[4],\n        t[1] * p.x + t[3] * p.y + t[5]\n      );\n    },\n\n    /**\n     * Returns coordinates of points's bounding rectangle (left, top, width, height)\n     * @param {Array} points 4 points array\n     * @param {Array} [transform] an array of 6 numbers representing a 2x3 transform matrix\n     * @return {Object} Object with left, top, width, height properties\n     */\n    makeBoundingBoxFromPoints: function(points, transform) {\n      if (transform) {\n        for (var i = 0; i < points.length; i++) {\n          points[i] = fabric.util.transformPoint(points[i], transform);\n        }\n      }\n      var xPoints = [points[0].x, points[1].x, points[2].x, points[3].x],\n          minX = fabric.util.array.min(xPoints),\n          maxX = fabric.util.array.max(xPoints),\n          width = maxX - minX,\n          yPoints = [points[0].y, points[1].y, points[2].y, points[3].y],\n          minY = fabric.util.array.min(yPoints),\n          maxY = fabric.util.array.max(yPoints),\n          height = maxY - minY;\n\n      return {\n        left: minX,\n        top: minY,\n        width: width,\n        height: height\n      };\n    },\n\n    /**\n     * Invert transformation t\n     * @static\n     * @memberOf fabric.util\n     * @param {Array} t The transform\n     * @return {Array} The inverted transform\n     */\n    invertTransform: function(t) {\n      var a = 1 / (t[0] * t[3] - t[1] * t[2]),\n          r = [a * t[3], -a * t[1], -a * t[2], a * t[0]],\n          o = fabric.util.transformPoint({ x: t[4], y: t[5] }, r, true);\n      r[4] = -o.x;\n      r[5] = -o.y;\n      return r;\n    },\n\n    /**\n     * A wrapper around Number#toFixed, which contrary to native method returns number, not string.\n     * @static\n     * @memberOf fabric.util\n     * @param {Number|String} number number to operate on\n     * @param {Number} fractionDigits number of fraction digits to \"leave\"\n     * @return {Number}\n     */\n    toFixed: function(number, fractionDigits) {\n      return parseFloat(Number(number).toFixed(fractionDigits));\n    },\n\n    /**\n     * Converts from attribute value to pixel value if applicable.\n     * Returns converted pixels or original value not converted.\n     * @param {Number|String} value number to operate on\n     * @param {Number} fontSize\n     * @return {Number|String}\n     */\n    parseUnit: function(value, fontSize) {\n      var unit = /\\D{0,2}$/.exec(value),\n          number = parseFloat(value);\n      if (!fontSize) {\n        fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;\n      }\n      switch (unit[0]) {\n        case 'mm':\n          return number * fabric.DPI / 25.4;\n\n        case 'cm':\n          return number * fabric.DPI / 2.54;\n\n        case 'in':\n          return number * fabric.DPI;\n\n        case 'pt':\n          return number * fabric.DPI / 72; // or * 4 / 3\n\n        case 'pc':\n          return number * fabric.DPI / 72 * 12; // or * 16\n\n        case 'em':\n          return number * fontSize;\n\n        default:\n          return number;\n      }\n    },\n\n    /**\n     * Function which always returns `false`.\n     * @static\n     * @memberOf fabric.util\n     * @return {Boolean}\n     */\n    falseFunction: function() {\n      return false;\n    },\n\n    /**\n     * Returns klass \"Class\" object of given namespace\n     * @memberOf fabric.util\n     * @param {String} type Type of object (eg. 'circle')\n     * @param {String} namespace Namespace to get klass \"Class\" object from\n     * @return {Object} klass \"Class\"\n     */\n    getKlass: function(type, namespace) {\n      // capitalize first letter only\n      type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1));\n      return fabric.util.resolveNamespace(namespace)[type];\n    },\n\n    /**\n     * Returns array of attributes for given svg that fabric parses\n     * @memberOf fabric.util\n     * @param {String} type Type of svg element (eg. 'circle')\n     * @return {Array} string names of supported attributes\n     */\n    getSvgAttributes: function(type) {\n      var attributes = [\n        'instantiated_by_use',\n        'style',\n        'id',\n        'class'\n      ];\n      switch (type) {\n        case 'linearGradient':\n          attributes = attributes.concat(['x1', 'y1', 'x2', 'y2', 'gradientUnits', 'gradientTransform']);\n          break;\n        case 'radialGradient':\n          attributes = attributes.concat(['gradientUnits', 'gradientTransform', 'cx', 'cy', 'r', 'fx', 'fy', 'fr']);\n          break;\n        case 'stop':\n          attributes = attributes.concat(['offset', 'stop-color', 'stop-opacity']);\n          break;\n      }\n      return attributes;\n    },\n\n    /**\n     * Returns object of given namespace\n     * @memberOf fabric.util\n     * @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric'\n     * @return {Object} Object for given namespace (default fabric)\n     */\n    resolveNamespace: function(namespace) {\n      if (!namespace) {\n        return fabric;\n      }\n\n      var parts = namespace.split('.'),\n          len = parts.length, i,\n          obj = global || fabric.window;\n\n      for (i = 0; i < len; ++i) {\n        obj = obj[parts[i]];\n      }\n\n      return obj;\n    },\n\n    /**\n     * Loads image element from given url and passes it to a callback\n     * @memberOf fabric.util\n     * @param {String} url URL representing an image\n     * @param {Function} callback Callback; invoked with loaded image\n     * @param {*} [context] Context to invoke callback in\n     * @param {Object} [crossOrigin] crossOrigin value to set image element to\n     */\n    loadImage: function(url, callback, context, crossOrigin) {\n      if (!url) {\n        callback && callback.call(context, url);\n        return;\n      }\n\n      var img = fabric.util.createImage();\n\n      /** @ignore */\n      var onLoadCallback = function () {\n        callback && callback.call(context, img, false);\n        img = img.onload = img.onerror = null;\n      };\n\n      img.onload = onLoadCallback;\n      /** @ignore */\n      img.onerror = function() {\n        fabric.log('Error loading ' + img.src);\n        callback && callback.call(context, null, true);\n        img = img.onload = img.onerror = null;\n      };\n\n      // data-urls appear to be buggy with crossOrigin\n      // https://github.com/kangax/fabric.js/commit/d0abb90f1cd5c5ef9d2a94d3fb21a22330da3e0a#commitcomment-4513767\n      // see https://code.google.com/p/chromium/issues/detail?id=315152\n      //     https://bugzilla.mozilla.org/show_bug.cgi?id=935069\n      // crossOrigin null is the same as not set.\n      if (url.indexOf('data') !== 0 &&\n        crossOrigin !== undefined &&\n        crossOrigin !== null) {\n        img.crossOrigin = crossOrigin;\n      }\n\n      // IE10 / IE11-Fix: SVG contents from data: URI\n      // will only be available if the IMG is present\n      // in the DOM (and visible)\n      if (url.substring(0,14) === 'data:image/svg') {\n        img.onload = null;\n        fabric.util.loadImageInDom(img, onLoadCallback);\n      }\n\n      img.src = url;\n    },\n\n    /**\n     * Attaches SVG image with data: URL to the dom\n     * @memberOf fabric.util\n     * @param {Object} img Image object with data:image/svg src\n     * @param {Function} callback Callback; invoked with loaded image\n     * @return {Object} DOM element (div containing the SVG image)\n     */\n    loadImageInDom: function(img, onLoadCallback) {\n      var div = fabric.document.createElement('div');\n      div.style.width = div.style.height = '1px';\n      div.style.left = div.style.top = '-100%';\n      div.style.position = 'absolute';\n      div.appendChild(img);\n      fabric.document.querySelector('body').appendChild(div);\n      /**\n       * Wrap in function to:\n       *   1. Call existing callback\n       *   2. Cleanup DOM\n       */\n      img.onload = function () {\n        onLoadCallback();\n        div.parentNode.removeChild(div);\n        div = null;\n      };\n    },\n\n    /**\n     * Creates corresponding fabric instances from their object representations\n     * @static\n     * @memberOf fabric.util\n     * @param {Array} objects Objects to enliven\n     * @param {Function} callback Callback to invoke when all objects are created\n     * @param {String} namespace Namespace to get klass \"Class\" object from\n     * @param {Function} reviver Method for further parsing of object elements,\n     * called after each fabric object created.\n     */\n    enlivenObjects: function(objects, callback, namespace, reviver) {\n      objects = objects || [];\n\n      var enlivenedObjects = [],\n          numLoadedObjects = 0,\n          numTotalObjects = objects.length;\n\n      function onLoaded() {\n        if (++numLoadedObjects === numTotalObjects) {\n          callback && callback(enlivenedObjects.filter(function(obj) {\n            // filter out undefined objects (objects that gave error)\n            return obj;\n          }));\n        }\n      }\n\n      if (!numTotalObjects) {\n        callback && callback(enlivenedObjects);\n        return;\n      }\n\n      objects.forEach(function (o, index) {\n        // if sparse array\n        if (!o || !o.type) {\n          onLoaded();\n          return;\n        }\n        var klass = fabric.util.getKlass(o.type, namespace);\n        klass.fromObject(o, function (obj, error) {\n          error || (enlivenedObjects[index] = obj);\n          reviver && reviver(o, obj, error);\n          onLoaded();\n        });\n      });\n    },\n\n    /**\n     * Create and wait for loading of patterns\n     * @static\n     * @memberOf fabric.util\n     * @param {Array} patterns Objects to enliven\n     * @param {Function} callback Callback to invoke when all objects are created\n     * called after each fabric object created.\n     */\n    enlivenPatterns: function(patterns, callback) {\n      patterns = patterns || [];\n\n      function onLoaded() {\n        if (++numLoadedPatterns === numPatterns) {\n          callback && callback(enlivenedPatterns);\n        }\n      }\n\n      var enlivenedPatterns = [],\n          numLoadedPatterns = 0,\n          numPatterns = patterns.length;\n\n      if (!numPatterns) {\n        callback && callback(enlivenedPatterns);\n        return;\n      }\n\n      patterns.forEach(function (p, index) {\n        if (p && p.source) {\n          new fabric.Pattern(p, function(pattern) {\n            enlivenedPatterns[index] = pattern;\n            onLoaded();\n          });\n        }\n        else {\n          enlivenedPatterns[index] = p;\n          onLoaded();\n        }\n      });\n    },\n\n    /**\n     * Groups SVG elements (usually those retrieved from SVG document)\n     * @static\n     * @memberOf fabric.util\n     * @param {Array} elements SVG elements to group\n     * @param {Object} [options] Options object\n     * @param {String} path Value to set sourcePath to\n     * @return {fabric.Object|fabric.Group}\n     */\n    groupSVGElements: function(elements, options, path) {\n      var object;\n      if (elements && elements.length === 1) {\n        return elements[0];\n      }\n      if (options) {\n        if (options.width && options.height) {\n          options.centerPoint = {\n            x: options.width / 2,\n            y: options.height / 2\n          };\n        }\n        else {\n          delete options.width;\n          delete options.height;\n        }\n      }\n      object = new fabric.Group(elements, options);\n      if (typeof path !== 'undefined') {\n        object.sourcePath = path;\n      }\n      return object;\n    },\n\n    /**\n     * Populates an object with properties of another object\n     * @static\n     * @memberOf fabric.util\n     * @param {Object} source Source object\n     * @param {Object} destination Destination object\n     * @return {Array} properties Properties names to include\n     */\n    populateWithProperties: function(source, destination, properties) {\n      if (properties && Object.prototype.toString.call(properties) === '[object Array]') {\n        for (var i = 0, len = properties.length; i < len; i++) {\n          if (properties[i] in source) {\n            destination[properties[i]] = source[properties[i]];\n          }\n        }\n      }\n    },\n\n    /**\n     * Draws a dashed line between two points\n     *\n     * This method is used to draw dashed line around selection area.\n     * See <a href=\"http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas\">dotted stroke in canvas</a>\n     *\n     * @param {CanvasRenderingContext2D} ctx context\n     * @param {Number} x  start x coordinate\n     * @param {Number} y start y coordinate\n     * @param {Number} x2 end x coordinate\n     * @param {Number} y2 end y coordinate\n     * @param {Array} da dash array pattern\n     */\n    drawDashedLine: function(ctx, x, y, x2, y2, da) {\n      var dx = x2 - x,\n          dy = y2 - y,\n          len = sqrt(dx * dx + dy * dy),\n          rot = atan2(dy, dx),\n          dc = da.length,\n          di = 0,\n          draw = true;\n\n      ctx.save();\n      ctx.translate(x, y);\n      ctx.moveTo(0, 0);\n      ctx.rotate(rot);\n\n      x = 0;\n      while (len > x) {\n        x += da[di++ % dc];\n        if (x > len) {\n          x = len;\n        }\n        ctx[draw ? 'lineTo' : 'moveTo'](x, 0);\n        draw = !draw;\n      }\n\n      ctx.restore();\n    },\n\n    /**\n     * Creates canvas element\n     * @static\n     * @memberOf fabric.util\n     * @return {CanvasElement} initialized canvas element\n     */\n    createCanvasElement: function() {\n      return fabric.document.createElement('canvas');\n    },\n\n    /**\n     * Creates a canvas element that is a copy of another and is also painted\n     * @param {CanvasElement} canvas to copy size and content of\n     * @static\n     * @memberOf fabric.util\n     * @return {CanvasElement} initialized canvas element\n     */\n    copyCanvasElement: function(canvas) {\n      var newCanvas = fabric.util.createCanvasElement();\n      newCanvas.width = canvas.width;\n      newCanvas.height = canvas.height;\n      newCanvas.getContext('2d').drawImage(canvas, 0, 0);\n      return newCanvas;\n    },\n\n    /**\n     * since 2.6.0 moved from canvas instance to utility.\n     * @param {CanvasElement} canvasEl to copy size and content of\n     * @param {String} format 'jpeg' or 'png', in some browsers 'webp' is ok too\n     * @param {Number} quality <= 1 and > 0\n     * @static\n     * @memberOf fabric.util\n     * @return {String} data url\n     */\n    toDataURL: function(canvasEl, format, quality) {\n      return canvasEl.toDataURL('image/' + format, quality);\n    },\n\n    /**\n     * Creates image element (works on client and node)\n     * @static\n     * @memberOf fabric.util\n     * @return {HTMLImageElement} HTML image element\n     */\n    createImage: function() {\n      return fabric.document.createElement('img');\n    },\n\n    /**\n     * Multiply matrix A by matrix B to nest transformations\n     * @static\n     * @memberOf fabric.util\n     * @param  {Array} a First transformMatrix\n     * @param  {Array} b Second transformMatrix\n     * @param  {Boolean} is2x2 flag to multiply matrices as 2x2 matrices\n     * @return {Array} The product of the two transform matrices\n     */\n    multiplyTransformMatrices: function(a, b, is2x2) {\n      // Matrix multiply a * b\n      return [\n        a[0] * b[0] + a[2] * b[1],\n        a[1] * b[0] + a[3] * b[1],\n        a[0] * b[2] + a[2] * b[3],\n        a[1] * b[2] + a[3] * b[3],\n        is2x2 ? 0 : a[0] * b[4] + a[2] * b[5] + a[4],\n        is2x2 ? 0 : a[1] * b[4] + a[3] * b[5] + a[5]\n      ];\n    },\n\n    /**\n     * Decomposes standard 2x3 matrix into transform components\n     * @static\n     * @memberOf fabric.util\n     * @param  {Array} a transformMatrix\n     * @return {Object} Components of transform\n     */\n    qrDecompose: function(a) {\n      var angle = atan2(a[1], a[0]),\n          denom = pow(a[0], 2) + pow(a[1], 2),\n          scaleX = sqrt(denom),\n          scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX,\n          skewX = atan2(a[0] * a[2] + a[1] * a [3], denom);\n      return {\n        angle: angle / PiBy180,\n        scaleX: scaleX,\n        scaleY: scaleY,\n        skewX: skewX / PiBy180,\n        skewY: 0,\n        translateX: a[4],\n        translateY: a[5]\n      };\n    },\n\n    /**\n     * Returns a transform matrix starting from an object of the same kind of\n     * the one returned from qrDecompose, useful also if you want to calculate some\n     * transformations from an object that is not enlived yet\n     * @static\n     * @memberOf fabric.util\n     * @param  {Object} options\n     * @param  {Number} [options.angle] angle in degrees\n     * @return {Number[]} transform matrix\n     */\n    calcRotateMatrix: function(options) {\n      if (!options.angle) {\n        return fabric.iMatrix.concat();\n      }\n      var theta = fabric.util.degreesToRadians(options.angle),\n          cos = fabric.util.cos(theta),\n          sin = fabric.util.sin(theta);\n      return [cos, sin, -sin, cos, 0, 0];\n    },\n\n    /**\n     * Returns a transform matrix starting from an object of the same kind of\n     * the one returned from qrDecompose, useful also if you want to calculate some\n     * transformations from an object that is not enlived yet.\n     * is called DimensionsTransformMatrix because those properties are the one that influence\n     * the size of the resulting box of the object.\n     * @static\n     * @memberOf fabric.util\n     * @param  {Object} options\n     * @param  {Number} [options.scaleX]\n     * @param  {Number} [options.scaleY]\n     * @param  {Boolean} [options.flipX]\n     * @param  {Boolean} [options.flipY]\n     * @param  {Number} [options.skewX]\n     * @param  {Number} [options.skewX]\n     * @return {Number[]} transform matrix\n     */\n    calcDimensionsMatrix: function(options) {\n      var scaleX = typeof options.scaleX === 'undefined' ? 1 : options.scaleX,\n          scaleY = typeof options.scaleY === 'undefined' ? 1 : options.scaleY,\n          scaleMatrix = [\n            options.flipX ? -scaleX : scaleX,\n            0,\n            0,\n            options.flipY ? -scaleY : scaleY,\n            0,\n            0],\n          multiply = fabric.util.multiplyTransformMatrices,\n          degreesToRadians = fabric.util.degreesToRadians;\n      if (options.skewX) {\n        scaleMatrix = multiply(\n          scaleMatrix,\n          [1, 0, Math.tan(degreesToRadians(options.skewX)), 1],\n          true);\n      }\n      if (options.skewY) {\n        scaleMatrix = multiply(\n          scaleMatrix,\n          [1, Math.tan(degreesToRadians(options.skewY)), 0, 1],\n          true);\n      }\n      return scaleMatrix;\n    },\n\n    /**\n     * Returns a transform matrix starting from an object of the same kind of\n     * the one returned from qrDecompose, useful also if you want to calculate some\n     * transformations from an object that is not enlived yet\n     * @static\n     * @memberOf fabric.util\n     * @param  {Object} options\n     * @param  {Number} [options.angle]\n     * @param  {Number} [options.scaleX]\n     * @param  {Number} [options.scaleY]\n     * @param  {Boolean} [options.flipX]\n     * @param  {Boolean} [options.flipY]\n     * @param  {Number} [options.skewX]\n     * @param  {Number} [options.skewX]\n     * @param  {Number} [options.translateX]\n     * @param  {Number} [options.translateY]\n     * @return {Number[]} transform matrix\n     */\n    composeMatrix: function(options) {\n      var matrix = [1, 0, 0, 1, options.translateX || 0, options.translateY || 0],\n          multiply = fabric.util.multiplyTransformMatrices;\n      if (options.angle) {\n        matrix = multiply(matrix, fabric.util.calcRotateMatrix(options));\n      }\n      if (options.scaleX !== 1 || options.scaleY !== 1 ||\n          options.skewX || options.skewY || options.flipX || options.flipY) {\n        matrix = multiply(matrix, fabric.util.calcDimensionsMatrix(options));\n      }\n      return matrix;\n    },\n\n    /**\n     * reset an object transform state to neutral. Top and left are not accounted for\n     * @static\n     * @memberOf fabric.util\n     * @param  {fabric.Object} target object to transform\n     */\n    resetObjectTransform: function (target) {\n      target.scaleX = 1;\n      target.scaleY = 1;\n      target.skewX = 0;\n      target.skewY = 0;\n      target.flipX = false;\n      target.flipY = false;\n      target.rotate(0);\n    },\n\n    /**\n     * Extract Object transform values\n     * @static\n     * @memberOf fabric.util\n     * @param  {fabric.Object} target object to read from\n     * @return {Object} Components of transform\n     */\n    saveObjectTransform: function (target) {\n      return {\n        scaleX: target.scaleX,\n        scaleY: target.scaleY,\n        skewX: target.skewX,\n        skewY: target.skewY,\n        angle: target.angle,\n        left: target.left,\n        flipX: target.flipX,\n        flipY: target.flipY,\n        top: target.top\n      };\n    },\n\n    /**\n     * Returns true if context has transparent pixel\n     * at specified location (taking tolerance into account)\n     * @param {CanvasRenderingContext2D} ctx context\n     * @param {Number} x x coordinate\n     * @param {Number} y y coordinate\n     * @param {Number} tolerance Tolerance\n     */\n    isTransparent: function(ctx, x, y, tolerance) {\n\n      // If tolerance is > 0 adjust start coords to take into account.\n      // If moves off Canvas fix to 0\n      if (tolerance > 0) {\n        if (x > tolerance) {\n          x -= tolerance;\n        }\n        else {\n          x = 0;\n        }\n        if (y > tolerance) {\n          y -= tolerance;\n        }\n        else {\n          y = 0;\n        }\n      }\n\n      var _isTransparent = true, i, temp,\n          imageData = ctx.getImageData(x, y, (tolerance * 2) || 1, (tolerance * 2) || 1),\n          l = imageData.data.length;\n\n      // Split image data - for tolerance > 1, pixelDataSize = 4;\n      for (i = 3; i < l; i += 4) {\n        temp = imageData.data[i];\n        _isTransparent = temp <= 0;\n        if (_isTransparent === false) {\n          break; // Stop if colour found\n        }\n      }\n\n      imageData = null;\n\n      return _isTransparent;\n    },\n\n    /**\n     * Parse preserveAspectRatio attribute from element\n     * @param {string} attribute to be parsed\n     * @return {Object} an object containing align and meetOrSlice attribute\n     */\n    parsePreserveAspectRatioAttribute: function(attribute) {\n      var meetOrSlice = 'meet', alignX = 'Mid', alignY = 'Mid',\n          aspectRatioAttrs = attribute.split(' '), align;\n\n      if (aspectRatioAttrs && aspectRatioAttrs.length) {\n        meetOrSlice = aspectRatioAttrs.pop();\n        if (meetOrSlice !== 'meet' && meetOrSlice !== 'slice') {\n          align = meetOrSlice;\n          meetOrSlice = 'meet';\n        }\n        else if (aspectRatioAttrs.length) {\n          align = aspectRatioAttrs.pop();\n        }\n      }\n      //divide align in alignX and alignY\n      alignX = align !== 'none' ? align.slice(1, 4) : 'none';\n      alignY = align !== 'none' ? align.slice(5, 8) : 'none';\n      return {\n        meetOrSlice: meetOrSlice,\n        alignX: alignX,\n        alignY: alignY\n      };\n    },\n\n    /**\n     * Clear char widths cache for the given font family or all the cache if no\n     * fontFamily is specified.\n     * Use it if you know you are loading fonts in a lazy way and you are not waiting\n     * for custom fonts to load properly when adding text objects to the canvas.\n     * If a text object is added when its own font is not loaded yet, you will get wrong\n     * measurement and so wrong bounding boxes.\n     * After the font cache is cleared, either change the textObject text content or call\n     * initDimensions() to trigger a recalculation\n     * @memberOf fabric.util\n     * @param {String} [fontFamily] font family to clear\n     */\n    clearFabricFontCache: function(fontFamily) {\n      fontFamily = (fontFamily || '').toLowerCase();\n      if (!fontFamily) {\n        fabric.charWidthsCache = { };\n      }\n      else if (fabric.charWidthsCache[fontFamily]) {\n        delete fabric.charWidthsCache[fontFamily];\n      }\n    },\n\n    /**\n     * Given current aspect ratio, determines the max width and height that can\n     * respect the total allowed area for the cache.\n     * @memberOf fabric.util\n     * @param {Number} ar aspect ratio\n     * @param {Number} maximumArea Maximum area you want to achieve\n     * @return {Object.x} Limited dimensions by X\n     * @return {Object.y} Limited dimensions by Y\n     */\n    limitDimsByArea: function(ar, maximumArea) {\n      var roughWidth = Math.sqrt(maximumArea * ar),\n          perfLimitSizeY = Math.floor(maximumArea / roughWidth);\n      return { x: Math.floor(roughWidth), y: perfLimitSizeY };\n    },\n\n    capValue: function(min, value, max) {\n      return Math.max(min, Math.min(value, max));\n    },\n\n    /**\n     * Finds the scale for the object source to fit inside the object destination,\n     * keeping aspect ratio intact.\n     * respect the total allowed area for the cache.\n     * @memberOf fabric.util\n     * @param {Object | fabric.Object} source\n     * @param {Number} source.height natural unscaled height of the object\n     * @param {Number} source.width natural unscaled width of the object\n     * @param {Object | fabric.Object} destination\n     * @param {Number} destination.height natural unscaled height of the object\n     * @param {Number} destination.width natural unscaled width of the object\n     * @return {Number} scale factor to apply to source to fit into destination\n     */\n    findScaleToFit: function(source, destination) {\n      return Math.min(destination.width / source.width, destination.height / source.height);\n    },\n\n    /**\n     * Finds the scale for the object source to cover entirely the object destination,\n     * keeping aspect ratio intact.\n     * respect the total allowed area for the cache.\n     * @memberOf fabric.util\n     * @param {Object | fabric.Object} source\n     * @param {Number} source.height natural unscaled height of the object\n     * @param {Number} source.width natural unscaled width of the object\n     * @param {Object | fabric.Object} destination\n     * @param {Number} destination.height natural unscaled height of the object\n     * @param {Number} destination.width natural unscaled width of the object\n     * @return {Number} scale factor to apply to source to cover destination\n     */\n    findScaleToCover: function(source, destination) {\n      return Math.max(destination.width / source.width, destination.height / source.height);\n    },\n\n    /**\n     * given an array of 6 number returns something like `\"matrix(...numbers)\"`\n     * @memberOf fabric.util\n     * @param {Array} trasnform an array with 6 numbers\n     * @return {String} transform matrix for svg\n     * @return {Object.y} Limited dimensions by Y\n     */\n    matrixToSVG: function(transform) {\n      return 'matrix(' + transform.map(function(value) {\n        return fabric.util.toFixed(value, fabric.Object.NUM_FRACTION_DIGITS);\n      }).join(' ') + ')';\n    },\n\n    /**\n     * given a width and height, return the size of the bounding box\n     * that can contains the box with width/height with applied transform\n     * described in options.\n     * Use to calculate the boxes around objects for controls.\n     * @memberOf fabric.util\n     * @param {Number} width\n     * @param {Number} height\n     * @param {Object} options\n     * @param {Number} options.scaleX\n     * @param {Number} options.scaleY\n     * @param {Number} options.skewX\n     * @param {Number} options.skewY\n     * @return {Object.x} width of containing\n     * @return {Object.y} height of containing\n     */\n    sizeAfterTransform: function(width, height, options) {\n      var dimX = width / 2, dimY = height / 2,\n          points = [\n            {\n              x: -dimX,\n              y: -dimY\n            },\n            {\n              x: dimX,\n              y: -dimY\n            },\n            {\n              x: -dimX,\n              y: dimY\n            },\n            {\n              x: dimX,\n              y: dimY\n            }],\n          transformMatrix = fabric.util.calcDimensionsMatrix(options),\n          bbox = fabric.util.makeBoundingBoxFromPoints(points, transformMatrix);\n      return {\n        x: bbox.width,\n        y: bbox.height,\n      };\n    }\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n  var _join = Array.prototype.join,\n      commandLengths = {\n        m: 2,\n        l: 2,\n        h: 1,\n        v: 1,\n        c: 6,\n        s: 4,\n        q: 4,\n        t: 2,\n        a: 7\n      },\n      repeatedCommands = {\n        m: 'l',\n        M: 'L'\n      };\n  function segmentToBezier(th2, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY) {\n    var costh2 = fabric.util.cos(th2),\n        sinth2 = fabric.util.sin(th2),\n        costh3 = fabric.util.cos(th3),\n        sinth3 = fabric.util.sin(th3),\n        toX = cosTh * rx * costh3 - sinTh * ry * sinth3 + cx1,\n        toY = sinTh * rx * costh3 + cosTh * ry * sinth3 + cy1,\n        cp1X = fromX + mT * ( -cosTh * rx * sinth2 - sinTh * ry * costh2),\n        cp1Y = fromY + mT * ( -sinTh * rx * sinth2 + cosTh * ry * costh2),\n        cp2X = toX + mT * ( cosTh * rx * sinth3 + sinTh * ry * costh3),\n        cp2Y = toY + mT * ( sinTh * rx * sinth3 - cosTh * ry * costh3);\n\n    return ['C',\n      cp1X, cp1Y,\n      cp2X, cp2Y,\n      toX, toY\n    ];\n  }\n\n  /* Adapted from http://dxr.mozilla.org/mozilla-central/source/content/svg/content/src/nsSVGPathDataParser.cpp\n   * by Andrea Bogazzi code is under MPL. if you don't have a copy of the license you can take it here\n   * http://mozilla.org/MPL/2.0/\n   */\n  function arcToSegments(toX, toY, rx, ry, large, sweep, rotateX) {\n    var PI = Math.PI, th = rotateX * PI / 180,\n        sinTh = fabric.util.sin(th),\n        cosTh = fabric.util.cos(th),\n        fromX = 0, fromY = 0;\n\n    rx = Math.abs(rx);\n    ry = Math.abs(ry);\n\n    var px = -cosTh * toX * 0.5 - sinTh * toY * 0.5,\n        py = -cosTh * toY * 0.5 + sinTh * toX * 0.5,\n        rx2 = rx * rx, ry2 = ry * ry, py2 = py * py, px2 = px * px,\n        pl = rx2 * ry2 - rx2 * py2 - ry2 * px2,\n        root = 0;\n\n    if (pl < 0) {\n      var s = Math.sqrt(1 - pl / (rx2 * ry2));\n      rx *= s;\n      ry *= s;\n    }\n    else {\n      root = (large === sweep ? -1.0 : 1.0) *\n              Math.sqrt( pl / (rx2 * py2 + ry2 * px2));\n    }\n\n    var cx = root * rx * py / ry,\n        cy = -root * ry * px / rx,\n        cx1 = cosTh * cx - sinTh * cy + toX * 0.5,\n        cy1 = sinTh * cx + cosTh * cy + toY * 0.5,\n        mTheta = calcVectorAngle(1, 0, (px - cx) / rx, (py - cy) / ry),\n        dtheta = calcVectorAngle((px - cx) / rx, (py - cy) / ry, (-px - cx) / rx, (-py - cy) / ry);\n\n    if (sweep === 0 && dtheta > 0) {\n      dtheta -= 2 * PI;\n    }\n    else if (sweep === 1 && dtheta < 0) {\n      dtheta += 2 * PI;\n    }\n\n    // Convert into cubic bezier segments <= 90deg\n    var segments = Math.ceil(Math.abs(dtheta / PI * 2)),\n        result = [], mDelta = dtheta / segments,\n        mT = 8 / 3 * Math.sin(mDelta / 4) * Math.sin(mDelta / 4) / Math.sin(mDelta / 2),\n        th3 = mTheta + mDelta;\n\n    for (var i = 0; i < segments; i++) {\n      result[i] = segmentToBezier(mTheta, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY);\n      fromX = result[i][5];\n      fromY = result[i][6];\n      mTheta = th3;\n      th3 += mDelta;\n    }\n    return result;\n  }\n\n  /*\n   * Private\n   */\n  function calcVectorAngle(ux, uy, vx, vy) {\n    var ta = Math.atan2(uy, ux),\n        tb = Math.atan2(vy, vx);\n    if (tb >= ta) {\n      return tb - ta;\n    }\n    else {\n      return 2 * Math.PI - (ta - tb);\n    }\n  }\n\n  /**\n   * Calculate bounding box of a beziercurve\n   * @param {Number} x0 starting point\n   * @param {Number} y0\n   * @param {Number} x1 first control point\n   * @param {Number} y1\n   * @param {Number} x2 secondo control point\n   * @param {Number} y2\n   * @param {Number} x3 end of beizer\n   * @param {Number} y3\n   */\n  // taken from http://jsbin.com/ivomiq/56/edit  no credits available for that.\n  // TODO: can we normalize this with the starting points set at 0 and then translated the bbox?\n  function getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3) {\n    var argsString;\n    if (fabric.cachesBoundsOfCurve) {\n      argsString = _join.call(arguments);\n      if (fabric.boundsOfCurveCache[argsString]) {\n        return fabric.boundsOfCurveCache[argsString];\n      }\n    }\n\n    var sqrt = Math.sqrt,\n        min = Math.min, max = Math.max,\n        abs = Math.abs, tvalues = [],\n        bounds = [[], []],\n        a, b, c, t, t1, t2, b2ac, sqrtb2ac;\n\n    b = 6 * x0 - 12 * x1 + 6 * x2;\n    a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;\n    c = 3 * x1 - 3 * x0;\n\n    for (var i = 0; i < 2; ++i) {\n      if (i > 0) {\n        b = 6 * y0 - 12 * y1 + 6 * y2;\n        a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;\n        c = 3 * y1 - 3 * y0;\n      }\n\n      if (abs(a) < 1e-12) {\n        if (abs(b) < 1e-12) {\n          continue;\n        }\n        t = -c / b;\n        if (0 < t && t < 1) {\n          tvalues.push(t);\n        }\n        continue;\n      }\n      b2ac = b * b - 4 * c * a;\n      if (b2ac < 0) {\n        continue;\n      }\n      sqrtb2ac = sqrt(b2ac);\n      t1 = (-b + sqrtb2ac) / (2 * a);\n      if (0 < t1 && t1 < 1) {\n        tvalues.push(t1);\n      }\n      t2 = (-b - sqrtb2ac) / (2 * a);\n      if (0 < t2 && t2 < 1) {\n        tvalues.push(t2);\n      }\n    }\n\n    var x, y, j = tvalues.length, jlen = j, mt;\n    while (j--) {\n      t = tvalues[j];\n      mt = 1 - t;\n      x = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3);\n      bounds[0][j] = x;\n\n      y = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3);\n      bounds[1][j] = y;\n    }\n\n    bounds[0][jlen] = x0;\n    bounds[1][jlen] = y0;\n    bounds[0][jlen + 1] = x3;\n    bounds[1][jlen + 1] = y3;\n    var result = [\n      {\n        x: min.apply(null, bounds[0]),\n        y: min.apply(null, bounds[1])\n      },\n      {\n        x: max.apply(null, bounds[0]),\n        y: max.apply(null, bounds[1])\n      }\n    ];\n    if (fabric.cachesBoundsOfCurve) {\n      fabric.boundsOfCurveCache[argsString] = result;\n    }\n    return result;\n  }\n\n  /**\n   * Converts arc to a bunch of beizer curves\n   * @param {Number} fx starting point x\n   * @param {Number} fy starting point y\n   * @param {Array} coords Arc command\n   */\n  function fromArcToBeizers(fx, fy, coords) {\n    var rx = coords[1],\n        ry = coords[2],\n        rot = coords[3],\n        large = coords[4],\n        sweep = coords[5],\n        tx = coords[6],\n        ty = coords[7],\n        segsNorm = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);\n\n    for (var i = 0, len = segsNorm.length; i < len; i++) {\n      segsNorm[i][1] += fx;\n      segsNorm[i][2] += fy;\n      segsNorm[i][3] += fx;\n      segsNorm[i][4] += fy;\n      segsNorm[i][5] += fx;\n      segsNorm[i][6] += fy;\n    }\n    return segsNorm;\n  };\n\n\n  function makePathSimpler(path) {\n    // x and y represent the last point of the path. the previous command point.\n    // we add them to each relative command to make it an absolute comment.\n    // we also swap the v V h H with L, because are easier to transform.\n    var x = 0, y = 0, len = path.length,\n        // x1 and y1 represent the last point of the subpath. the subpath is started with\n        // m or M command. When a z or Z command is drawn, x and y need to be resetted to\n        // the last x1 and y1.\n        x1 = 0, y1 = 0, current, i, converted,\n        // previous will host the letter of the previous command, to handle S and T.\n        // controlX and controlY will host the previous reflected control point\n        destinationPath = [], previous, controlX, controlY;\n    for (i = 0; i < len; ++i) {\n      converted = false;\n      current = path[i].slice(0);\n      switch (current[0]) { // first letter\n        case 'l': // lineto, relative\n          current[0] = 'L';\n          current[1] += x;\n          current[2] += y;\n          // falls through\n        case 'L':\n          x = current[1];\n          y = current[2];\n          break;\n        case 'h': // horizontal lineto, relative\n          current[1] += x;\n          // falls through\n        case 'H':\n          current[0] = 'L';\n          current[2] = y;\n          x = current[1];\n          break;\n        case 'v': // vertical lineto, relative\n          current[1] += y;\n          // falls through\n        case 'V':\n          current[0] = 'L';\n          y = current[1];\n          current[1] = x;\n          current[2] = y;\n          break;\n        case 'm': // moveTo, relative\n          current[0] = 'M';\n          current[1] += x;\n          current[2] += y;\n          // falls through\n        case 'M':\n          x = current[1];\n          y = current[2];\n          x1 = current[1];\n          y1 = current[2];\n          break;\n        case 'c': // bezierCurveTo, relative\n          current[0] = 'C';\n          current[1] += x;\n          current[2] += y;\n          current[3] += x;\n          current[4] += y;\n          current[5] += x;\n          current[6] += y;\n          // falls through\n        case 'C':\n          controlX = current[3];\n          controlY = current[4];\n          x = current[5];\n          y = current[6];\n          break;\n        case 's': // shorthand cubic bezierCurveTo, relative\n          current[0] = 'S';\n          current[1] += x;\n          current[2] += y;\n          current[3] += x;\n          current[4] += y;\n          // falls through\n        case 'S':\n          // would be sScC but since we are swapping sSc for C, we check just that.\n          if (previous === 'C') {\n            // calculate reflection of previous control points\n            controlX = 2 * x - controlX;\n            controlY = 2 * y - controlY;\n          }\n          else {\n            // If there is no previous command or if the previous command was not a C, c, S, or s,\n            // the control point is coincident with the current point\n            controlX = x;\n            controlY = y;\n          }\n          x = current[3];\n          y = current[4];\n          current[0] = 'C';\n          current[5] = current[3];\n          current[6] = current[4];\n          current[3] = current[1];\n          current[4] = current[2];\n          current[1] = controlX;\n          current[2] = controlY;\n          // current[3] and current[4] are NOW the second control point.\n          // we keep it for the next reflection.\n          controlX = current[3];\n          controlY = current[4];\n          break;\n        case 'q': // quadraticCurveTo, relative\n          current[0] = 'Q';\n          current[1] += x;\n          current[2] += y;\n          current[3] += x;\n          current[4] += y;\n          // falls through\n        case 'Q':\n          controlX = current[1];\n          controlY = current[2];\n          x = current[3];\n          y = current[4];\n          break;\n        case 't': // shorthand quadraticCurveTo, relative\n          current[0] = 'T';\n          current[1] += x;\n          current[2] += y;\n          // falls through\n        case 'T':\n          if (previous === 'Q') {\n            // calculate reflection of previous control point\n            controlX = 2 * x - controlX;\n            controlY = 2 * y - controlY;\n          }\n          else {\n            // If there is no previous command or if the previous command was not a Q, q, T or t,\n            // assume the control point is coincident with the current point\n            controlX = x;\n            controlY = y;\n          }\n          current[0] = 'Q';\n          x = current[1];\n          y = current[2];\n          current[1] = controlX;\n          current[2] = controlY;\n          current[3] = x;\n          current[4] = y;\n          break;\n        case 'a':\n          current[0] = 'A';\n          current[6] += x;\n          current[7] += y;\n          // falls through\n        case 'A':\n          converted = true;\n          destinationPath = destinationPath.concat(fromArcToBeizers(x, y, current));\n          x = current[6];\n          y = current[7];\n          break;\n        case 'z':\n        case 'Z':\n          x = x1;\n          y = y1;\n          break;\n        default:\n      }\n      if (!converted) {\n        destinationPath.push(current);\n      }\n      previous = current[0];\n    }\n    return destinationPath;\n  };\n\n  /**\n   * Calc length from point x1,y1 to x2,y2\n   * @param {Number} x1 starting point x\n   * @param {Number} y1 starting point y\n   * @param {Number} x2 starting point x\n   * @param {Number} y2 starting point y\n   * @return {Number} length of segment\n   */\n  function calcLineLength(x1, y1, x2, y2) {\n    return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));\n  }\n\n  // functions for the Cubic beizer\n  // taken from: https://github.com/konvajs/konva/blob/7.0.5/src/shapes/Path.ts#L350\n  function CB1(t) {\n    return t * t * t;\n  }\n  function CB2(t) {\n    return 3 * t * t * (1 - t);\n  }\n  function CB3(t) {\n    return 3 * t * (1 - t) * (1 - t);\n  }\n  function CB4(t) {\n    return (1 - t) * (1 - t) * (1 - t);\n  }\n\n  function getPointOnCubicBezierIterator(p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y) {\n    return function(pct) {\n      var c1 = CB1(pct), c2 = CB2(pct), c3 = CB3(pct), c4 = CB4(pct);\n      return {\n        x: p4x * c1 + p3x * c2 + p2x * c3 + p1x * c4,\n        y: p4y * c1 + p3y * c2 + p2y * c3 + p1y * c4\n      };\n    };\n  }\n\n  function QB1(t) {\n    return t * t;\n  }\n\n  function QB2(t) {\n    return 2 * t * (1 - t);\n  }\n\n  function QB3(t) {\n    return (1 - t) * (1 - t);\n  }\n\n  function getPointOnQuadraticBezierIterator(p1x, p1y, p2x, p2y, p3x, p3y) {\n    return function(pct) {\n      var c1 = QB1(pct), c2 = QB2(pct), c3 = QB3(pct);\n      return {\n        x: p3x * c1 + p2x * c2 + p1x * c3,\n        y: p3y * c1 + p2y * c2 + p1y * c3\n      };\n    };\n  }\n\n  function pathIterator(iterator, x1, y1) {\n    var tempP = { x: x1, y: y1 }, p, tmpLen = 0, perc;\n    for (perc = 0.01; perc <= 1; perc += 0.01) {\n      p = iterator(perc);\n      tmpLen += calcLineLength(tempP.x, tempP.y, p.x, p.y);\n      tempP = p;\n    }\n    return tmpLen;\n  }\n\n  //measures the length of a pre-simplified path\n  function getPathSegmentsInfo(path) {\n    var totalLength = 0, len = path.length, current,\n        //x2 and y2 are the coords of segment start\n        //x1 and y1 are the coords of the current point\n        x1 = 0, y1 = 0, x2 = 0, y2 = 0, info = [], iterator, tempInfo;\n    for (var i = 0; i < len; i++) {\n      current = path[i];\n      tempInfo = {\n        x: x1,\n        y: y1,\n        command: current[0],\n      };\n      switch (current[0]) { //first letter\n        case 'M':\n          tempInfo.length = 0;\n          x2 = x1 = current[1];\n          y2 = y1 = current[2];\n          break;\n        case 'L':\n          tempInfo.length = calcLineLength(x1, y1, current[1], current[2]);\n          x1 = current[1];\n          y1 = current[2];\n          break;\n        case 'C':\n          iterator = getPointOnCubicBezierIterator(\n            x1,\n            y1,\n            current[1],\n            current[2],\n            current[3],\n            current[4],\n            current[5],\n            current[6]\n          );\n          tempInfo.length = pathIterator(iterator, x1, y1);\n          x1 = current[5];\n          y1 = current[6];\n          break;\n        case 'Q':\n          iterator = getPointOnQuadraticBezierIterator(\n            x1,\n            y1,\n            current[1],\n            current[2],\n            current[3],\n            current[4]\n          );\n          tempInfo.length = pathIterator(iterator, x1, y1);\n          x1 = current[3];\n          y1 = current[4];\n          break;\n        case 'Z':\n        case 'z':\n          // we add those in order to ease calculations later\n          tempInfo.destX = x2;\n          tempInfo.destY = y2;\n          tempInfo.length = calcLineLength(x1, y1, x2, y2);\n          x1 = x2;\n          y1 = y2;\n          break;\n      }\n      totalLength += tempInfo.length;\n      info.push(tempInfo);\n    }\n    info.push({ length: totalLength, x: x1, y: y1 });\n    return info;\n  }\n\n  function getPointOnPath(path, perc, infos) {\n    if (!infos) {\n      infos = getPathSegmentsInfo(path);\n    }\n    var distance = infos[infos.length - 1] * perc, i = 0;\n    while ((distance - infos[i] > 0) && i < infos.length) {\n      distance -= infos[i];\n      i++;\n    }\n    var segInfo = infos[i], segPercent = distance / segInfo.length,\n        command = segInfo.length, segment = path[i];\n    switch (command) {\n      case 'Z':\n      case 'z':\n        return new fabric.Point(segInfo.x, segInfo.y).lerp(\n          new fabric.Point(segInfo.destX, segInfo.destY),\n          segPercent\n        );\n        break;\n      case 'L':\n        return new fabric.Point(segInfo.x, segInfo.y).lerp(\n          new fabric.Point(segment[1], segment[2]),\n          segPercent\n        );\n        break;\n      case 'C':\n        return getPointOnCubicBezierIterator(\n          segInfo.x,\n          segInfo.y,\n          segment[1],\n          segment[2],\n          segment[3],\n          segment[4],\n          segment[5],\n          segment[6]\n        )(segPercent);\n        break;\n      case 'Q':\n        return getPointOnQuadraticBezierIterator(\n          segInfo.x,\n          segInfo.y,\n          segment[1],\n          segment[2],\n          segment[3],\n          segment[4]\n        )(segPercent);\n        break;\n    }\n  }\n\n  function parsePath(pathString) {\n    var result = [],\n        coords = [],\n        currentPath,\n        parsed,\n        re = fabric.rePathCommand,\n        rNumber = '[-+]?(?:\\\\d*\\\\.\\\\d+|\\\\d+\\\\.?)(?:[eE][-+]?\\\\d+)?\\\\s*',\n        rNumberCommaWsp = '(' + rNumber + ')' + fabric.commaWsp,\n        rFlagCommaWsp = '([01])' + fabric.commaWsp + '?',\n        rArcSeq = rNumberCommaWsp + '?' + rNumberCommaWsp + '?' + rNumberCommaWsp + rFlagCommaWsp + rFlagCommaWsp +\n          rNumberCommaWsp + '?(' + rNumber + ')',\n        regArcArgumentSequence = new RegExp(rArcSeq, 'g'),\n        match,\n        coordsStr,\n        // one of commands (m,M,l,L,q,Q,c,C,etc.) followed by non-command characters (i.e. command values)\n        path;\n    if (!pathString || !pathString.match) {\n      return result;\n    }\n    path = pathString.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi);\n\n    for (var i = 0, coordsParsed, len = path.length; i < len; i++) {\n      currentPath = path[i];\n\n      coordsStr = currentPath.slice(1).trim();\n      coords.length = 0;\n\n      var command = currentPath.charAt(0);\n      coordsParsed = [command];\n\n      if (command.toLowerCase() === 'a') {\n        // arcs have special flags that apparently don't require spaces so handle special\n        for (var args; (args = regArcArgumentSequence.exec(coordsStr));) {\n          for (var j = 1; j < args.length; j++) {\n            coords.push(args[j]);\n          }\n        }\n      }\n      else {\n        while ((match = re.exec(coordsStr))) {\n          coords.push(match[0]);\n        }\n      }\n\n      for (var j = 0, jlen = coords.length; j < jlen; j++) {\n        parsed = parseFloat(coords[j]);\n        if (!isNaN(parsed)) {\n          coordsParsed.push(parsed);\n        }\n      }\n\n      var commandLength = commandLengths[command.toLowerCase()],\n          repeatedCommand = repeatedCommands[command] || command;\n\n      if (coordsParsed.length - 1 > commandLength) {\n        for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) {\n          result.push([command].concat(coordsParsed.slice(k, k + commandLength)));\n          command = repeatedCommand;\n        }\n      }\n      else {\n        result.push(coordsParsed);\n      }\n    }\n\n    return result;\n  };\n\n  /**\n   * Calculate bounding box of a elliptic-arc\n   * @deprecated\n   * @param {Number} fx start point of arc\n   * @param {Number} fy\n   * @param {Number} rx horizontal radius\n   * @param {Number} ry vertical radius\n   * @param {Number} rot angle of horizontal axis\n   * @param {Number} large 1 or 0, whatever the arc is the big or the small on the 2 points\n   * @param {Number} sweep 1 or 0, 1 clockwise or counterclockwise direction\n   * @param {Number} tx end point of arc\n   * @param {Number} ty\n   */\n  function getBoundsOfArc(fx, fy, rx, ry, rot, large, sweep, tx, ty) {\n\n    var fromX = 0, fromY = 0, bound, bounds = [],\n        segs = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);\n\n    for (var i = 0, len = segs.length; i < len; i++) {\n      bound = getBoundsOfCurve(fromX, fromY, segs[i][1], segs[i][2], segs[i][3], segs[i][4], segs[i][5], segs[i][6]);\n      bounds.push({ x: bound[0].x + fx, y: bound[0].y + fy });\n      bounds.push({ x: bound[1].x + fx, y: bound[1].y + fy });\n      fromX = segs[i][5];\n      fromY = segs[i][6];\n    }\n    return bounds;\n  };\n\n  /**\n   * Draws arc\n   * @param {CanvasRenderingContext2D} ctx\n   * @param {Number} fx\n   * @param {Number} fy\n   * @param {Array} coords coords of the arc, without the front 'A/a'\n   */\n  function drawArc(ctx, fx, fy, coords) {\n    coords = coords.slice(0).unshift('X'); // command A or a does not matter\n    var beizers = fromArcToBeizers(fx, fy, coords);\n    beizers.forEach(function(beizer) {\n      ctx.bezierCurveTo.apply(ctx, beizer.slice(1));\n    });\n  };\n\n  fabric.util.parsePath = parsePath;\n  fabric.util.makePathSimpler = makePathSimpler;\n  fabric.util.getPathSegmentsInfo = getPathSegmentsInfo;\n  fabric.util.fromArcToBeizers = fromArcToBeizers;\n  fabric.util.getBoundsOfCurve = getBoundsOfCurve;\n  fabric.util.getPointOnPath = getPointOnPath;\n  // kept because we do not want to make breaking changes.\n  // but useless and deprecated.\n  fabric.util.getBoundsOfArc = getBoundsOfArc;\n  fabric.util.drawArc = drawArc;\n})();\n\n\n(function() {\n\n  var slice = Array.prototype.slice;\n\n  /**\n   * Invokes method on all items in a given array\n   * @memberOf fabric.util.array\n   * @param {Array} array Array to iterate over\n   * @param {String} method Name of a method to invoke\n   * @return {Array}\n   */\n  function invoke(array, method) {\n    var args = slice.call(arguments, 2), result = [];\n    for (var i = 0, len = array.length; i < len; i++) {\n      result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]);\n    }\n    return result;\n  }\n\n  /**\n   * Finds maximum value in array (not necessarily \"first\" one)\n   * @memberOf fabric.util.array\n   * @param {Array} array Array to iterate over\n   * @param {String} byProperty\n   * @return {*}\n   */\n  function max(array, byProperty) {\n    return find(array, byProperty, function(value1, value2) {\n      return value1 >= value2;\n    });\n  }\n\n  /**\n   * Finds minimum value in array (not necessarily \"first\" one)\n   * @memberOf fabric.util.array\n   * @param {Array} array Array to iterate over\n   * @param {String} byProperty\n   * @return {*}\n   */\n  function min(array, byProperty) {\n    return find(array, byProperty, function(value1, value2) {\n      return value1 < value2;\n    });\n  }\n\n  /**\n   * @private\n   */\n  function fill(array, value) {\n    var k = array.length;\n    while (k--) {\n      array[k] = value;\n    }\n    return array;\n  }\n\n  /**\n   * @private\n   */\n  function find(array, byProperty, condition) {\n    if (!array || array.length === 0) {\n      return;\n    }\n\n    var i = array.length - 1,\n        result = byProperty ? array[i][byProperty] : array[i];\n    if (byProperty) {\n      while (i--) {\n        if (condition(array[i][byProperty], result)) {\n          result = array[i][byProperty];\n        }\n      }\n    }\n    else {\n      while (i--) {\n        if (condition(array[i], result)) {\n          result = array[i];\n        }\n      }\n    }\n    return result;\n  }\n\n  /**\n   * @namespace fabric.util.array\n   */\n  fabric.util.array = {\n    fill: fill,\n    invoke: invoke,\n    min: min,\n    max: max\n  };\n\n})();\n\n\n(function() {\n  /**\n   * Copies all enumerable properties of one js object to another\n   * this does not and cannot compete with generic utils.\n   * Does not clone or extend fabric.Object subclasses.\n   * This is mostly for internal use and has extra handling for fabricJS objects\n   * it skips the canvas and group properties in deep cloning.\n   * @memberOf fabric.util.object\n   * @param {Object} destination Where to copy to\n   * @param {Object} source Where to copy from\n   * @return {Object}\n   */\n\n  function extend(destination, source, deep) {\n    // JScript DontEnum bug is not taken care of\n    // the deep clone is for internal use, is not meant to avoid\n    // javascript traps or cloning html element or self referenced objects.\n    if (deep) {\n      if (!fabric.isLikelyNode && source instanceof Element) {\n        // avoid cloning deep images, canvases,\n        destination = source;\n      }\n      else if (source instanceof Array) {\n        destination = [];\n        for (var i = 0, len = source.length; i < len; i++) {\n          destination[i] = extend({ }, source[i], deep);\n        }\n      }\n      else if (source && typeof source === 'object') {\n        for (var property in source) {\n          if (property === 'canvas' || property === 'group') {\n            // we do not want to clone this props at all.\n            // we want to keep the keys in the copy\n            destination[property] = null;\n          }\n          else if (source.hasOwnProperty(property)) {\n            destination[property] = extend({ }, source[property], deep);\n          }\n        }\n      }\n      else {\n        // this sounds odd for an extend but is ok for recursive use\n        destination = source;\n      }\n    }\n    else {\n      for (var property in source) {\n        destination[property] = source[property];\n      }\n    }\n    return destination;\n  }\n\n  /**\n   * Creates an empty object and copies all enumerable properties of another object to it\n   * @memberOf fabric.util.object\n   * TODO: this function return an empty object if you try to clone null\n   * @param {Object} object Object to clone\n   * @return {Object}\n   */\n  function clone(object, deep) {\n    return extend({ }, object, deep);\n  }\n\n  /** @namespace fabric.util.object */\n  fabric.util.object = {\n    extend: extend,\n    clone: clone\n  };\n  fabric.util.object.extend(fabric.util, fabric.Observable);\n})();\n\n\n(function() {\n\n  /**\n   * Camelizes a string\n   * @memberOf fabric.util.string\n   * @param {String} string String to camelize\n   * @return {String} Camelized version of a string\n   */\n  function camelize(string) {\n    return string.replace(/-+(.)?/g, function(match, character) {\n      return character ? character.toUpperCase() : '';\n    });\n  }\n\n  /**\n   * Capitalizes a string\n   * @memberOf fabric.util.string\n   * @param {String} string String to capitalize\n   * @param {Boolean} [firstLetterOnly] If true only first letter is capitalized\n   * and other letters stay untouched, if false first letter is capitalized\n   * and other letters are converted to lowercase.\n   * @return {String} Capitalized version of a string\n   */\n  function capitalize(string, firstLetterOnly) {\n    return string.charAt(0).toUpperCase() +\n      (firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase());\n  }\n\n  /**\n   * Escapes XML in a string\n   * @memberOf fabric.util.string\n   * @param {String} string String to escape\n   * @return {String} Escaped version of a string\n   */\n  function escapeXml(string) {\n    return string.replace(/&/g, '&amp;')\n      .replace(/\"/g, '&quot;')\n      .replace(/'/g, '&apos;')\n      .replace(/</g, '&lt;')\n      .replace(/>/g, '&gt;');\n  }\n\n  /**\n   * Divide a string in the user perceived single units\n   * @memberOf fabric.util.string\n   * @param {String} textstring String to escape\n   * @return {Array} array containing the graphemes\n   */\n  function graphemeSplit(textstring) {\n    var i = 0, chr, graphemes = [];\n    for (i = 0, chr; i < textstring.length; i++) {\n      if ((chr = getWholeChar(textstring, i)) === false) {\n        continue;\n      }\n      graphemes.push(chr);\n    }\n    return graphemes;\n  }\n\n  // taken from mdn in the charAt doc page.\n  function getWholeChar(str, i) {\n    var code = str.charCodeAt(i);\n\n    if (isNaN(code)) {\n      return ''; // Position not found\n    }\n    if (code < 0xD800 || code > 0xDFFF) {\n      return str.charAt(i);\n    }\n\n    // High surrogate (could change last hex to 0xDB7F to treat high private\n    // surrogates as single characters)\n    if (0xD800 <= code && code <= 0xDBFF) {\n      if (str.length <= (i + 1)) {\n        throw 'High surrogate without following low surrogate';\n      }\n      var next = str.charCodeAt(i + 1);\n      if (0xDC00 > next || next > 0xDFFF) {\n        throw 'High surrogate without following low surrogate';\n      }\n      return str.charAt(i) + str.charAt(i + 1);\n    }\n    // Low surrogate (0xDC00 <= code && code <= 0xDFFF)\n    if (i === 0) {\n      throw 'Low surrogate without preceding high surrogate';\n    }\n    var prev = str.charCodeAt(i - 1);\n\n    // (could change last hex to 0xDB7F to treat high private\n    // surrogates as single characters)\n    if (0xD800 > prev || prev > 0xDBFF) {\n      throw 'Low surrogate without preceding high surrogate';\n    }\n    // We can pass over low surrogates now as the second component\n    // in a pair which we have already processed\n    return false;\n  }\n\n\n  /**\n   * String utilities\n   * @namespace fabric.util.string\n   */\n  fabric.util.string = {\n    camelize: camelize,\n    capitalize: capitalize,\n    escapeXml: escapeXml,\n    graphemeSplit: graphemeSplit\n  };\n})();\n\n\n(function() {\n\n  var slice = Array.prototype.slice, emptyFunction = function() { },\n\n      IS_DONTENUM_BUGGY = (function() {\n        for (var p in { toString: 1 }) {\n          if (p === 'toString') {\n            return false;\n          }\n        }\n        return true;\n      })(),\n\n      /** @ignore */\n      addMethods = function(klass, source, parent) {\n        for (var property in source) {\n\n          if (property in klass.prototype &&\n              typeof klass.prototype[property] === 'function' &&\n              (source[property] + '').indexOf('callSuper') > -1) {\n\n            klass.prototype[property] = (function(property) {\n              return function() {\n\n                var superclass = this.constructor.superclass;\n                this.constructor.superclass = parent;\n                var returnValue = source[property].apply(this, arguments);\n                this.constructor.superclass = superclass;\n\n                if (property !== 'initialize') {\n                  return returnValue;\n                }\n              };\n            })(property);\n          }\n          else {\n            klass.prototype[property] = source[property];\n          }\n\n          if (IS_DONTENUM_BUGGY) {\n            if (source.toString !== Object.prototype.toString) {\n              klass.prototype.toString = source.toString;\n            }\n            if (source.valueOf !== Object.prototype.valueOf) {\n              klass.prototype.valueOf = source.valueOf;\n            }\n          }\n        }\n      };\n\n  function Subclass() { }\n\n  function callSuper(methodName) {\n    var parentMethod = null,\n        _this = this;\n\n    // climb prototype chain to find method not equal to callee's method\n    while (_this.constructor.superclass) {\n      var superClassMethod = _this.constructor.superclass.prototype[methodName];\n      if (_this[methodName] !== superClassMethod) {\n        parentMethod = superClassMethod;\n        break;\n      }\n      // eslint-disable-next-line\n      _this = _this.constructor.superclass.prototype;\n    }\n\n    if (!parentMethod) {\n      return console.log('tried to callSuper ' + methodName + ', method not found in prototype chain', this);\n    }\n\n    return (arguments.length > 1)\n      ? parentMethod.apply(this, slice.call(arguments, 1))\n      : parentMethod.call(this);\n  }\n\n  /**\n   * Helper for creation of \"classes\".\n   * @memberOf fabric.util\n   * @param {Function} [parent] optional \"Class\" to inherit from\n   * @param {Object} [properties] Properties shared by all instances of this class\n   *                  (be careful modifying objects defined here as this would affect all instances)\n   */\n  function createClass() {\n    var parent = null,\n        properties = slice.call(arguments, 0);\n\n    if (typeof properties[0] === 'function') {\n      parent = properties.shift();\n    }\n    function klass() {\n      this.initialize.apply(this, arguments);\n    }\n\n    klass.superclass = parent;\n    klass.subclasses = [];\n\n    if (parent) {\n      Subclass.prototype = parent.prototype;\n      klass.prototype = new Subclass();\n      parent.subclasses.push(klass);\n    }\n    for (var i = 0, length = properties.length; i < length; i++) {\n      addMethods(klass, properties[i], parent);\n    }\n    if (!klass.prototype.initialize) {\n      klass.prototype.initialize = emptyFunction;\n    }\n    klass.prototype.constructor = klass;\n    klass.prototype.callSuper = callSuper;\n    return klass;\n  }\n\n  fabric.util.createClass = createClass;\n})();\n\n\n(function () {\n  // since ie11 can use addEventListener but they do not support options, i need to check\n  var couldUseAttachEvent = !!fabric.document.createElement('div').attachEvent,\n      touchEvents = ['touchstart', 'touchmove', 'touchend'];\n  /**\n   * Adds an event listener to an element\n   * @function\n   * @memberOf fabric.util\n   * @param {HTMLElement} element\n   * @param {String} eventName\n   * @param {Function} handler\n   */\n  fabric.util.addListener = function(element, eventName, handler, options) {\n    element && element.addEventListener(eventName, handler, couldUseAttachEvent ? false : options);\n  };\n\n  /**\n   * Removes an event listener from an element\n   * @function\n   * @memberOf fabric.util\n   * @param {HTMLElement} element\n   * @param {String} eventName\n   * @param {Function} handler\n   */\n  fabric.util.removeListener = function(element, eventName, handler, options) {\n    element && element.removeEventListener(eventName, handler, couldUseAttachEvent ? false : options);\n  };\n\n  function getTouchInfo(event) {\n    var touchProp = event.changedTouches;\n    if (touchProp && touchProp[0]) {\n      return touchProp[0];\n    }\n    return event;\n  }\n\n  fabric.util.getPointer = function(event) {\n    var element = event.target,\n        scroll = fabric.util.getScrollLeftTop(element),\n        _evt = getTouchInfo(event);\n    return {\n      x: _evt.clientX + scroll.left,\n      y: _evt.clientY + scroll.top\n    };\n  };\n\n  fabric.util.isTouchEvent = function(event) {\n    return touchEvents.indexOf(event.type) > -1 || event.pointerType === 'touch';\n  };\n})();\n\n\n(function () {\n\n  /**\n   * Cross-browser wrapper for setting element's style\n   * @memberOf fabric.util\n   * @param {HTMLElement} element\n   * @param {Object} styles\n   * @return {HTMLElement} Element that was passed as a first argument\n   */\n  function setStyle(element, styles) {\n    var elementStyle = element.style;\n    if (!elementStyle) {\n      return element;\n    }\n    if (typeof styles === 'string') {\n      element.style.cssText += ';' + styles;\n      return styles.indexOf('opacity') > -1\n        ? setOpacity(element, styles.match(/opacity:\\s*(\\d?\\.?\\d*)/)[1])\n        : element;\n    }\n    for (var property in styles) {\n      if (property === 'opacity') {\n        setOpacity(element, styles[property]);\n      }\n      else {\n        var normalizedProperty = (property === 'float' || property === 'cssFloat')\n          ? (typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat')\n          : property;\n        elementStyle[normalizedProperty] = styles[property];\n      }\n    }\n    return element;\n  }\n\n  var parseEl = fabric.document.createElement('div'),\n      supportsOpacity = typeof parseEl.style.opacity === 'string',\n      supportsFilters = typeof parseEl.style.filter === 'string',\n      reOpacity = /alpha\\s*\\(\\s*opacity\\s*=\\s*([^\\)]+)\\)/,\n\n      /** @ignore */\n      setOpacity = function (element) { return element; };\n\n  if (supportsOpacity) {\n    /** @ignore */\n    setOpacity = function(element, value) {\n      element.style.opacity = value;\n      return element;\n    };\n  }\n  else if (supportsFilters) {\n    /** @ignore */\n    setOpacity = function(element, value) {\n      var es = element.style;\n      if (element.currentStyle && !element.currentStyle.hasLayout) {\n        es.zoom = 1;\n      }\n      if (reOpacity.test(es.filter)) {\n        value = value >= 0.9999 ? '' : ('alpha(opacity=' + (value * 100) + ')');\n        es.filter = es.filter.replace(reOpacity, value);\n      }\n      else {\n        es.filter += ' alpha(opacity=' + (value * 100) + ')';\n      }\n      return element;\n    };\n  }\n\n  fabric.util.setStyle = setStyle;\n\n})();\n\n\n(function() {\n\n  var _slice = Array.prototype.slice;\n\n  /**\n   * Takes id and returns an element with that id (if one exists in a document)\n   * @memberOf fabric.util\n   * @param {String|HTMLElement} id\n   * @return {HTMLElement|null}\n   */\n  function getById(id) {\n    return typeof id === 'string' ? fabric.document.getElementById(id) : id;\n  }\n\n  var sliceCanConvertNodelists,\n      /**\n       * Converts an array-like object (e.g. arguments or NodeList) to an array\n       * @memberOf fabric.util\n       * @param {Object} arrayLike\n       * @return {Array}\n       */\n      toArray = function(arrayLike) {\n        return _slice.call(arrayLike, 0);\n      };\n\n  try {\n    sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array;\n  }\n  catch (err) { }\n\n  if (!sliceCanConvertNodelists) {\n    toArray = function(arrayLike) {\n      var arr = new Array(arrayLike.length), i = arrayLike.length;\n      while (i--) {\n        arr[i] = arrayLike[i];\n      }\n      return arr;\n    };\n  }\n\n  /**\n   * Creates specified element with specified attributes\n   * @memberOf fabric.util\n   * @param {String} tagName Type of an element to create\n   * @param {Object} [attributes] Attributes to set on an element\n   * @return {HTMLElement} Newly created element\n   */\n  function makeElement(tagName, attributes) {\n    var el = fabric.document.createElement(tagName);\n    for (var prop in attributes) {\n      if (prop === 'class') {\n        el.className = attributes[prop];\n      }\n      else if (prop === 'for') {\n        el.htmlFor = attributes[prop];\n      }\n      else {\n        el.setAttribute(prop, attributes[prop]);\n      }\n    }\n    return el;\n  }\n\n  /**\n   * Adds class to an element\n   * @memberOf fabric.util\n   * @param {HTMLElement} element Element to add class to\n   * @param {String} className Class to add to an element\n   */\n  function addClass(element, className) {\n    if (element && (' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) {\n      element.className += (element.className ? ' ' : '') + className;\n    }\n  }\n\n  /**\n   * Wraps element with another element\n   * @memberOf fabric.util\n   * @param {HTMLElement} element Element to wrap\n   * @param {HTMLElement|String} wrapper Element to wrap with\n   * @param {Object} [attributes] Attributes to set on a wrapper\n   * @return {HTMLElement} wrapper\n   */\n  function wrapElement(element, wrapper, attributes) {\n    if (typeof wrapper === 'string') {\n      wrapper = makeElement(wrapper, attributes);\n    }\n    if (element.parentNode) {\n      element.parentNode.replaceChild(wrapper, element);\n    }\n    wrapper.appendChild(element);\n    return wrapper;\n  }\n\n  /**\n   * Returns element scroll offsets\n   * @memberOf fabric.util\n   * @param {HTMLElement} element Element to operate on\n   * @return {Object} Object with left/top values\n   */\n  function getScrollLeftTop(element) {\n\n    var left = 0,\n        top = 0,\n        docElement = fabric.document.documentElement,\n        body = fabric.document.body || {\n          scrollLeft: 0, scrollTop: 0\n        };\n\n    // While loop checks (and then sets element to) .parentNode OR .host\n    //  to account for ShadowDOM. We still want to traverse up out of ShadowDOM,\n    //  but the .parentNode of a root ShadowDOM node will always be null, instead\n    //  it should be accessed through .host. See http://stackoverflow.com/a/24765528/4383938\n    while (element && (element.parentNode || element.host)) {\n\n      // Set element to element parent, or 'host' in case of ShadowDOM\n      element = element.parentNode || element.host;\n\n      if (element === fabric.document) {\n        left = body.scrollLeft || docElement.scrollLeft || 0;\n        top = body.scrollTop ||  docElement.scrollTop || 0;\n      }\n      else {\n        left += element.scrollLeft || 0;\n        top += element.scrollTop || 0;\n      }\n\n      if (element.nodeType === 1 && element.style.position === 'fixed') {\n        break;\n      }\n    }\n\n    return { left: left, top: top };\n  }\n\n  /**\n   * Returns offset for a given element\n   * @function\n   * @memberOf fabric.util\n   * @param {HTMLElement} element Element to get offset for\n   * @return {Object} Object with \"left\" and \"top\" properties\n   */\n  function getElementOffset(element) {\n    var docElem,\n        doc = element && element.ownerDocument,\n        box = { left: 0, top: 0 },\n        offset = { left: 0, top: 0 },\n        scrollLeftTop,\n        offsetAttributes = {\n          borderLeftWidth: 'left',\n          borderTopWidth:  'top',\n          paddingLeft:     'left',\n          paddingTop:      'top'\n        };\n\n    if (!doc) {\n      return offset;\n    }\n\n    for (var attr in offsetAttributes) {\n      offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0;\n    }\n\n    docElem = doc.documentElement;\n    if ( typeof element.getBoundingClientRect !== 'undefined' ) {\n      box = element.getBoundingClientRect();\n    }\n\n    scrollLeftTop = getScrollLeftTop(element);\n\n    return {\n      left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left,\n      top: box.top + scrollLeftTop.top - (docElem.clientTop || 0)  + offset.top\n    };\n  }\n\n  /**\n   * Returns style attribute value of a given element\n   * @memberOf fabric.util\n   * @param {HTMLElement} element Element to get style attribute for\n   * @param {String} attr Style attribute to get for element\n   * @return {String} Style attribute value of the given element.\n   */\n  var getElementStyle;\n  if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) {\n    getElementStyle = function(element, attr) {\n      var style = fabric.document.defaultView.getComputedStyle(element, null);\n      return style ? style[attr] : undefined;\n    };\n  }\n  else {\n    getElementStyle = function(element, attr) {\n      var value = element.style[attr];\n      if (!value && element.currentStyle) {\n        value = element.currentStyle[attr];\n      }\n      return value;\n    };\n  }\n\n  (function () {\n    var style = fabric.document.documentElement.style,\n        selectProp = 'userSelect' in style\n          ? 'userSelect'\n          : 'MozUserSelect' in style\n            ? 'MozUserSelect'\n            : 'WebkitUserSelect' in style\n              ? 'WebkitUserSelect'\n              : 'KhtmlUserSelect' in style\n                ? 'KhtmlUserSelect'\n                : '';\n\n    /**\n     * Makes element unselectable\n     * @memberOf fabric.util\n     * @param {HTMLElement} element Element to make unselectable\n     * @return {HTMLElement} Element that was passed in\n     */\n    function makeElementUnselectable(element) {\n      if (typeof element.onselectstart !== 'undefined') {\n        element.onselectstart = fabric.util.falseFunction;\n      }\n      if (selectProp) {\n        element.style[selectProp] = 'none';\n      }\n      else if (typeof element.unselectable === 'string') {\n        element.unselectable = 'on';\n      }\n      return element;\n    }\n\n    /**\n     * Makes element selectable\n     * @memberOf fabric.util\n     * @param {HTMLElement} element Element to make selectable\n     * @return {HTMLElement} Element that was passed in\n     */\n    function makeElementSelectable(element) {\n      if (typeof element.onselectstart !== 'undefined') {\n        element.onselectstart = null;\n      }\n      if (selectProp) {\n        element.style[selectProp] = '';\n      }\n      else if (typeof element.unselectable === 'string') {\n        element.unselectable = '';\n      }\n      return element;\n    }\n\n    fabric.util.makeElementUnselectable = makeElementUnselectable;\n    fabric.util.makeElementSelectable = makeElementSelectable;\n  })();\n\n  function getNodeCanvas(element) {\n    var impl = fabric.jsdomImplForWrapper(element);\n    return impl._canvas || impl._image;\n  };\n\n  function cleanUpJsdomNode(element) {\n    if (!fabric.isLikelyNode) {\n      return;\n    }\n    var impl = fabric.jsdomImplForWrapper(element);\n    if (impl) {\n      impl._image = null;\n      impl._canvas = null;\n      // unsure if necessary\n      impl._currentSrc = null;\n      impl._attributes = null;\n      impl._classList = null;\n    }\n  }\n\n  function setImageSmoothing(ctx, value) {\n    ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled || ctx.webkitImageSmoothingEnabled\n      || ctx.mozImageSmoothingEnabled || ctx.msImageSmoothingEnabled || ctx.oImageSmoothingEnabled;\n    ctx.imageSmoothingEnabled = value;\n  }\n\n  /**\n   * setImageSmoothing sets the context imageSmoothingEnabled property.\n   * Used by canvas and by ImageObject.\n   * @memberOf fabric.util\n   * @since 4.0.0\n   * @param {HTMLRenderingContext2D} ctx to set on\n   * @param {Boolean} value true or false\n   */\n  fabric.util.setImageSmoothing = setImageSmoothing;\n  fabric.util.getById = getById;\n  fabric.util.toArray = toArray;\n  fabric.util.addClass = addClass;\n  fabric.util.makeElement = makeElement;\n  fabric.util.wrapElement = wrapElement;\n  fabric.util.getScrollLeftTop = getScrollLeftTop;\n  fabric.util.getElementOffset = getElementOffset;\n  fabric.util.getNodeCanvas = getNodeCanvas;\n  fabric.util.cleanUpJsdomNode = cleanUpJsdomNode;\n\n})();\n\n\n(function() {\n\n  function addParamToUrl(url, param) {\n    return url + (/\\?/.test(url) ? '&' : '?') + param;\n  }\n\n  function emptyFn() { }\n\n  /**\n   * Cross-browser abstraction for sending XMLHttpRequest\n   * @memberOf fabric.util\n   * @param {String} url URL to send XMLHttpRequest to\n   * @param {Object} [options] Options object\n   * @param {String} [options.method=\"GET\"]\n   * @param {String} [options.parameters] parameters to append to url in GET or in body\n   * @param {String} [options.body] body to send with POST or PUT request\n   * @param {Function} options.onComplete Callback to invoke when request is completed\n   * @return {XMLHttpRequest} request\n   */\n  function request(url, options) {\n    options || (options = { });\n\n    var method = options.method ? options.method.toUpperCase() : 'GET',\n        onComplete = options.onComplete || function() { },\n        xhr = new fabric.window.XMLHttpRequest(),\n        body = options.body || options.parameters;\n\n    /** @ignore */\n    xhr.onreadystatechange = function() {\n      if (xhr.readyState === 4) {\n        onComplete(xhr);\n        xhr.onreadystatechange = emptyFn;\n      }\n    };\n\n    if (method === 'GET') {\n      body = null;\n      if (typeof options.parameters === 'string') {\n        url = addParamToUrl(url, options.parameters);\n      }\n    }\n\n    xhr.open(method, url, true);\n\n    if (method === 'POST' || method === 'PUT') {\n      xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\n    }\n\n    xhr.send(body);\n    return xhr;\n  }\n\n  fabric.util.request = request;\n})();\n\n\n/**\n * Wrapper around `console.log` (when available)\n * @param {*} [values] Values to log\n */\nfabric.log = console.log;\n\n/**\n * Wrapper around `console.warn` (when available)\n * @param {*} [values] Values to log as a warning\n */\nfabric.warn = console.warn;\n\n\n(function() {\n\n  function noop() {\n    return false;\n  }\n\n  function defaultEasing(t, b, c, d) {\n    return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;\n  }\n\n  /**\n   * Changes value from one to another within certain period of time, invoking callbacks as value is being changed.\n   * @memberOf fabric.util\n   * @param {Object} [options] Animation options\n   * @param {Function} [options.onChange] Callback; invoked on every value change\n   * @param {Function} [options.onComplete] Callback; invoked when value change is completed\n   * @param {Number} [options.startValue=0] Starting value\n   * @param {Number} [options.endValue=100] Ending value\n   * @param {Number} [options.byValue=100] Value to modify the property by\n   * @param {Function} [options.easing] Easing function\n   * @param {Number} [options.duration=500] Duration of change (in ms)\n   * @param {Function} [options.abort] Additional function with logic. If returns true, onComplete is called.\n   */\n  function animate(options) {\n\n    requestAnimFrame(function(timestamp) {\n      options || (options = { });\n\n      var start = timestamp || +new Date(),\n          duration = options.duration || 500,\n          finish = start + duration, time,\n          onChange = options.onChange || noop,\n          abort = options.abort || noop,\n          onComplete = options.onComplete || noop,\n          easing = options.easing || defaultEasing,\n          startValue = 'startValue' in options ? options.startValue : 0,\n          endValue = 'endValue' in options ? options.endValue : 100,\n          byValue = options.byValue || endValue - startValue;\n\n      options.onStart && options.onStart();\n\n      (function tick(ticktime) {\n        // TODO: move abort call after calculation\n        // and pass (current,valuePerc, timePerc) as arguments\n        time = ticktime || +new Date();\n        var currentTime = time > finish ? duration : (time - start),\n            timePerc = currentTime / duration,\n            current = easing(currentTime, startValue, byValue, duration),\n            valuePerc = Math.abs((current - startValue) / byValue);\n        if (abort()) {\n          onComplete(endValue, 1, 1);\n          return;\n        }\n        if (time > finish) {\n          onChange(endValue, 1, 1);\n          onComplete(endValue, 1, 1);\n          return;\n        }\n        else {\n          onChange(current, valuePerc, timePerc);\n          requestAnimFrame(tick);\n        }\n      })(start);\n    });\n  }\n\n  var _requestAnimFrame = fabric.window.requestAnimationFrame       ||\n                          fabric.window.webkitRequestAnimationFrame ||\n                          fabric.window.mozRequestAnimationFrame    ||\n                          fabric.window.oRequestAnimationFrame      ||\n                          fabric.window.msRequestAnimationFrame     ||\n                          function(callback) {\n                            return fabric.window.setTimeout(callback, 1000 / 60);\n                          };\n\n  var _cancelAnimFrame = fabric.window.cancelAnimationFrame || fabric.window.clearTimeout;\n\n  /**\n   * requestAnimationFrame polyfill based on http://paulirish.com/2011/requestanimationframe-for-smart-animating/\n   * In order to get a precise start time, `requestAnimFrame` should be called as an entry into the method\n   * @memberOf fabric.util\n   * @param {Function} callback Callback to invoke\n   * @param {DOMElement} element optional Element to associate with animation\n   */\n  function requestAnimFrame() {\n    return _requestAnimFrame.apply(fabric.window, arguments);\n  }\n\n  function cancelAnimFrame() {\n    return _cancelAnimFrame.apply(fabric.window, arguments);\n  }\n\n  fabric.util.animate = animate;\n  fabric.util.requestAnimFrame = requestAnimFrame;\n  fabric.util.cancelAnimFrame = cancelAnimFrame;\n})();\n\n\n(function() {\n  // Calculate an in-between color. Returns a \"rgba()\" string.\n  // Credit: Edwin Martin <edwin@bitstorm.org>\n  //         http://www.bitstorm.org/jquery/color-animation/jquery.animate-colors.js\n  function calculateColor(begin, end, pos) {\n    var color = 'rgba('\n        + parseInt((begin[0] + pos * (end[0] - begin[0])), 10) + ','\n        + parseInt((begin[1] + pos * (end[1] - begin[1])), 10) + ','\n        + parseInt((begin[2] + pos * (end[2] - begin[2])), 10);\n\n    color += ',' + (begin && end ? parseFloat(begin[3] + pos * (end[3] - begin[3])) : 1);\n    color += ')';\n    return color;\n  }\n\n  /**\n   * Changes the color from one to another within certain period of time, invoking callbacks as value is being changed.\n   * @memberOf fabric.util\n   * @param {String} fromColor The starting color in hex or rgb(a) format.\n   * @param {String} toColor The starting color in hex or rgb(a) format.\n   * @param {Number} [duration] Duration of change (in ms).\n   * @param {Object} [options] Animation options\n   * @param {Function} [options.onChange] Callback; invoked on every value change\n   * @param {Function} [options.onComplete] Callback; invoked when value change is completed\n   * @param {Function} [options.colorEasing] Easing function. Note that this function only take two arguments (currentTime, duration). Thus the regular animation easing functions cannot be used.\n   * @param {Function} [options.abort] Additional function with logic. If returns true, onComplete is called.\n   */\n  function animateColor(fromColor, toColor, duration, options) {\n    var startColor = new fabric.Color(fromColor).getSource(),\n        endColor = new fabric.Color(toColor).getSource(),\n        originalOnComplete = options.onComplete,\n        originalOnChange = options.onChange;\n    options = options || {};\n\n    fabric.util.animate(fabric.util.object.extend(options, {\n      duration: duration || 500,\n      startValue: startColor,\n      endValue: endColor,\n      byValue: endColor,\n      easing: function (currentTime, startValue, byValue, duration) {\n        var posValue = options.colorEasing\n          ? options.colorEasing(currentTime, duration)\n          : 1 - Math.cos(currentTime / duration * (Math.PI / 2));\n        return calculateColor(startValue, byValue, posValue);\n      },\n      // has to take in account for color restoring;\n      onComplete: function(current, valuePerc, timePerc) {\n        if (originalOnComplete) {\n          return originalOnComplete(\n            calculateColor(endColor, endColor, 0),\n            valuePerc,\n            timePerc\n          );\n        }\n      },\n      onChange: function(current, valuePerc, timePerc) {\n        if (originalOnChange) {\n          if (Array.isArray(current)) {\n            return originalOnChange(\n              calculateColor(current, current, 0),\n              valuePerc,\n              timePerc\n            );\n          }\n          originalOnChange(current, valuePerc, timePerc);\n        }\n      }\n    }));\n  }\n\n  fabric.util.animateColor = animateColor;\n\n})();\n\n\n(function() {\n\n  function normalize(a, c, p, s) {\n    if (a < Math.abs(c)) {\n      a = c;\n      s = p / 4;\n    }\n    else {\n      //handle the 0/0 case:\n      if (c === 0 && a === 0) {\n        s = p / (2 * Math.PI) * Math.asin(1);\n      }\n      else {\n        s = p / (2 * Math.PI) * Math.asin(c / a);\n      }\n    }\n    return { a: a, c: c, p: p, s: s };\n  }\n\n  function elastic(opts, t, d) {\n    return opts.a *\n      Math.pow(2, 10 * (t -= 1)) *\n      Math.sin( (t * d - opts.s) * (2 * Math.PI) / opts.p );\n  }\n\n  /**\n   * Cubic easing out\n   * @memberOf fabric.util.ease\n   */\n  function easeOutCubic(t, b, c, d) {\n    return c * ((t = t / d - 1) * t * t + 1) + b;\n  }\n\n  /**\n   * Cubic easing in and out\n   * @memberOf fabric.util.ease\n   */\n  function easeInOutCubic(t, b, c, d) {\n    t /= d / 2;\n    if (t < 1) {\n      return c / 2 * t * t * t + b;\n    }\n    return c / 2 * ((t -= 2) * t * t + 2) + b;\n  }\n\n  /**\n   * Quartic easing in\n   * @memberOf fabric.util.ease\n   */\n  function easeInQuart(t, b, c, d) {\n    return c * (t /= d) * t * t * t + b;\n  }\n\n  /**\n   * Quartic easing out\n   * @memberOf fabric.util.ease\n   */\n  function easeOutQuart(t, b, c, d) {\n    return -c * ((t = t / d - 1) * t * t * t - 1) + b;\n  }\n\n  /**\n   * Quartic easing in and out\n   * @memberOf fabric.util.ease\n   */\n  function easeInOutQuart(t, b, c, d) {\n    t /= d / 2;\n    if (t < 1) {\n      return c / 2 * t * t * t * t + b;\n    }\n    return -c / 2 * ((t -= 2) * t * t * t - 2) + b;\n  }\n\n  /**\n   * Quintic easing in\n   * @memberOf fabric.util.ease\n   */\n  function easeInQuint(t, b, c, d) {\n    return c * (t /= d) * t * t * t * t + b;\n  }\n\n  /**\n   * Quintic easing out\n   * @memberOf fabric.util.ease\n   */\n  function easeOutQuint(t, b, c, d) {\n    return c * ((t = t / d - 1) * t * t * t * t + 1) + b;\n  }\n\n  /**\n   * Quintic easing in and out\n   * @memberOf fabric.util.ease\n   */\n  function easeInOutQuint(t, b, c, d) {\n    t /= d / 2;\n    if (t < 1) {\n      return c / 2 * t * t * t * t * t + b;\n    }\n    return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;\n  }\n\n  /**\n   * Sinusoidal easing in\n   * @memberOf fabric.util.ease\n   */\n  function easeInSine(t, b, c, d) {\n    return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;\n  }\n\n  /**\n   * Sinusoidal easing out\n   * @memberOf fabric.util.ease\n   */\n  function easeOutSine(t, b, c, d) {\n    return c * Math.sin(t / d * (Math.PI / 2)) + b;\n  }\n\n  /**\n   * Sinusoidal easing in and out\n   * @memberOf fabric.util.ease\n   */\n  function easeInOutSine(t, b, c, d) {\n    return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;\n  }\n\n  /**\n   * Exponential easing in\n   * @memberOf fabric.util.ease\n   */\n  function easeInExpo(t, b, c, d) {\n    return (t === 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;\n  }\n\n  /**\n   * Exponential easing out\n   * @memberOf fabric.util.ease\n   */\n  function easeOutExpo(t, b, c, d) {\n    return (t === d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;\n  }\n\n  /**\n   * Exponential easing in and out\n   * @memberOf fabric.util.ease\n   */\n  function easeInOutExpo(t, b, c, d) {\n    if (t === 0) {\n      return b;\n    }\n    if (t === d) {\n      return b + c;\n    }\n    t /= d / 2;\n    if (t < 1) {\n      return c / 2 * Math.pow(2, 10 * (t - 1)) + b;\n    }\n    return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;\n  }\n\n  /**\n   * Circular easing in\n   * @memberOf fabric.util.ease\n   */\n  function easeInCirc(t, b, c, d) {\n    return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;\n  }\n\n  /**\n   * Circular easing out\n   * @memberOf fabric.util.ease\n   */\n  function easeOutCirc(t, b, c, d) {\n    return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;\n  }\n\n  /**\n   * Circular easing in and out\n   * @memberOf fabric.util.ease\n   */\n  function easeInOutCirc(t, b, c, d) {\n    t /= d / 2;\n    if (t < 1) {\n      return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;\n    }\n    return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;\n  }\n\n  /**\n   * Elastic easing in\n   * @memberOf fabric.util.ease\n   */\n  function easeInElastic(t, b, c, d) {\n    var s = 1.70158, p = 0, a = c;\n    if (t === 0) {\n      return b;\n    }\n    t /= d;\n    if (t === 1) {\n      return b + c;\n    }\n    if (!p) {\n      p = d * 0.3;\n    }\n    var opts = normalize(a, c, p, s);\n    return -elastic(opts, t, d) + b;\n  }\n\n  /**\n   * Elastic easing out\n   * @memberOf fabric.util.ease\n   */\n  function easeOutElastic(t, b, c, d) {\n    var s = 1.70158, p = 0, a = c;\n    if (t === 0) {\n      return b;\n    }\n    t /= d;\n    if (t === 1) {\n      return b + c;\n    }\n    if (!p) {\n      p = d * 0.3;\n    }\n    var opts = normalize(a, c, p, s);\n    return opts.a * Math.pow(2, -10 * t) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) + opts.c + b;\n  }\n\n  /**\n   * Elastic easing in and out\n   * @memberOf fabric.util.ease\n   */\n  function easeInOutElastic(t, b, c, d) {\n    var s = 1.70158, p = 0, a = c;\n    if (t === 0) {\n      return b;\n    }\n    t /= d / 2;\n    if (t === 2) {\n      return b + c;\n    }\n    if (!p) {\n      p = d * (0.3 * 1.5);\n    }\n    var opts = normalize(a, c, p, s);\n    if (t < 1) {\n      return -0.5 * elastic(opts, t, d) + b;\n    }\n    return opts.a * Math.pow(2, -10 * (t -= 1)) *\n      Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) * 0.5 + opts.c + b;\n  }\n\n  /**\n   * Backwards easing in\n   * @memberOf fabric.util.ease\n   */\n  function easeInBack(t, b, c, d, s) {\n    if (s === undefined) {\n      s = 1.70158;\n    }\n    return c * (t /= d) * t * ((s + 1) * t - s) + b;\n  }\n\n  /**\n   * Backwards easing out\n   * @memberOf fabric.util.ease\n   */\n  function easeOutBack(t, b, c, d, s) {\n    if (s === undefined) {\n      s = 1.70158;\n    }\n    return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;\n  }\n\n  /**\n   * Backwards easing in and out\n   * @memberOf fabric.util.ease\n   */\n  function easeInOutBack(t, b, c, d, s) {\n    if (s === undefined) {\n      s = 1.70158;\n    }\n    t /= d / 2;\n    if (t < 1) {\n      return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;\n    }\n    return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;\n  }\n\n  /**\n   * Bouncing easing in\n   * @memberOf fabric.util.ease\n   */\n  function easeInBounce(t, b, c, d) {\n    return c - easeOutBounce (d - t, 0, c, d) + b;\n  }\n\n  /**\n   * Bouncing easing out\n   * @memberOf fabric.util.ease\n   */\n  function easeOutBounce(t, b, c, d) {\n    if ((t /= d) < (1 / 2.75)) {\n      return c * (7.5625 * t * t) + b;\n    }\n    else if (t < (2 / 2.75)) {\n      return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;\n    }\n    else if (t < (2.5 / 2.75)) {\n      return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;\n    }\n    else {\n      return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;\n    }\n  }\n\n  /**\n   * Bouncing easing in and out\n   * @memberOf fabric.util.ease\n   */\n  function easeInOutBounce(t, b, c, d) {\n    if (t < d / 2) {\n      return easeInBounce (t * 2, 0, c, d) * 0.5 + b;\n    }\n    return easeOutBounce(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;\n  }\n\n  /**\n   * Easing functions\n   * See <a href=\"http://gizma.com/easing/\">Easing Equations by Robert Penner</a>\n   * @namespace fabric.util.ease\n   */\n  fabric.util.ease = {\n\n    /**\n     * Quadratic easing in\n     * @memberOf fabric.util.ease\n     */\n    easeInQuad: function(t, b, c, d) {\n      return c * (t /= d) * t + b;\n    },\n\n    /**\n     * Quadratic easing out\n     * @memberOf fabric.util.ease\n     */\n    easeOutQuad: function(t, b, c, d) {\n      return -c * (t /= d) * (t - 2) + b;\n    },\n\n    /**\n     * Quadratic easing in and out\n     * @memberOf fabric.util.ease\n     */\n    easeInOutQuad: function(t, b, c, d) {\n      t /= (d / 2);\n      if (t < 1) {\n        return c / 2 * t * t + b;\n      }\n      return -c / 2 * ((--t) * (t - 2) - 1) + b;\n    },\n\n    /**\n     * Cubic easing in\n     * @memberOf fabric.util.ease\n     */\n    easeInCubic: function(t, b, c, d) {\n      return c * (t /= d) * t * t + b;\n    },\n\n    easeOutCubic: easeOutCubic,\n    easeInOutCubic: easeInOutCubic,\n    easeInQuart: easeInQuart,\n    easeOutQuart: easeOutQuart,\n    easeInOutQuart: easeInOutQuart,\n    easeInQuint: easeInQuint,\n    easeOutQuint: easeOutQuint,\n    easeInOutQuint: easeInOutQuint,\n    easeInSine: easeInSine,\n    easeOutSine: easeOutSine,\n    easeInOutSine: easeInOutSine,\n    easeInExpo: easeInExpo,\n    easeOutExpo: easeOutExpo,\n    easeInOutExpo: easeInOutExpo,\n    easeInCirc: easeInCirc,\n    easeOutCirc: easeOutCirc,\n    easeInOutCirc: easeInOutCirc,\n    easeInElastic: easeInElastic,\n    easeOutElastic: easeOutElastic,\n    easeInOutElastic: easeInOutElastic,\n    easeInBack: easeInBack,\n    easeOutBack: easeOutBack,\n    easeInOutBack: easeInOutBack,\n    easeInBounce: easeInBounce,\n    easeOutBounce: easeOutBounce,\n    easeInOutBounce: easeInOutBounce\n  };\n\n})();\n\n\n(function(global) {\n\n  'use strict';\n\n  /**\n   * @name fabric\n   * @namespace\n   */\n\n  var fabric = global.fabric || (global.fabric = { }),\n      extend = fabric.util.object.extend,\n      clone = fabric.util.object.clone,\n      toFixed = fabric.util.toFixed,\n      parseUnit = fabric.util.parseUnit,\n      multiplyTransformMatrices = fabric.util.multiplyTransformMatrices,\n\n      svgValidTagNames = ['path', 'circle', 'polygon', 'polyline', 'ellipse', 'rect', 'line',\n        'image', 'text'],\n      svgViewBoxElements = ['symbol', 'image', 'marker', 'pattern', 'view', 'svg'],\n      svgInvalidAncestors = ['pattern', 'defs', 'symbol', 'metadata', 'clipPath', 'mask', 'desc'],\n      svgValidParents = ['symbol', 'g', 'a', 'svg', 'clipPath', 'defs'],\n\n      attributesMap = {\n        cx:                   'left',\n        x:                    'left',\n        r:                    'radius',\n        cy:                   'top',\n        y:                    'top',\n        display:              'visible',\n        visibility:           'visible',\n        transform:            'transformMatrix',\n        'fill-opacity':       'fillOpacity',\n        'fill-rule':          'fillRule',\n        'font-family':        'fontFamily',\n        'font-size':          'fontSize',\n        'font-style':         'fontStyle',\n        'font-weight':        'fontWeight',\n        'letter-spacing':     'charSpacing',\n        'paint-order':        'paintFirst',\n        'stroke-dasharray':   'strokeDashArray',\n        'stroke-dashoffset':  'strokeDashOffset',\n        'stroke-linecap':     'strokeLineCap',\n        'stroke-linejoin':    'strokeLineJoin',\n        'stroke-miterlimit':  'strokeMiterLimit',\n        'stroke-opacity':     'strokeOpacity',\n        'stroke-width':       'strokeWidth',\n        'text-decoration':    'textDecoration',\n        'text-anchor':        'textAnchor',\n        opacity:              'opacity',\n        'clip-path':          'clipPath',\n        'clip-rule':          'clipRule',\n        'vector-effect':      'strokeUniform',\n        'image-rendering':    'imageSmoothing',\n      },\n\n      colorAttributes = {\n        stroke: 'strokeOpacity',\n        fill:   'fillOpacity'\n      },\n\n      fSize = 'font-size', cPath = 'clip-path';\n\n  fabric.svgValidTagNamesRegEx = getSvgRegex(svgValidTagNames);\n  fabric.svgViewBoxElementsRegEx = getSvgRegex(svgViewBoxElements);\n  fabric.svgInvalidAncestorsRegEx = getSvgRegex(svgInvalidAncestors);\n  fabric.svgValidParentsRegEx = getSvgRegex(svgValidParents);\n\n  fabric.cssRules = { };\n  fabric.gradientDefs = { };\n  fabric.clipPaths = { };\n\n  function normalizeAttr(attr) {\n    // transform attribute names\n    if (attr in attributesMap) {\n      return attributesMap[attr];\n    }\n    return attr;\n  }\n\n  function normalizeValue(attr, value, parentAttributes, fontSize) {\n    var isArray = Object.prototype.toString.call(value) === '[object Array]',\n        parsed;\n\n    if ((attr === 'fill' || attr === 'stroke') && value === 'none') {\n      value = '';\n    }\n    else if (attr === 'strokeUniform') {\n      return (value === 'non-scaling-stroke');\n    }\n    else if (attr === 'strokeDashArray') {\n      if (value === 'none') {\n        value = null;\n      }\n      else {\n        value = value.replace(/,/g, ' ').split(/\\s+/).map(parseFloat);\n      }\n    }\n    else if (attr === 'transformMatrix') {\n      if (parentAttributes && parentAttributes.transformMatrix) {\n        value = multiplyTransformMatrices(\n          parentAttributes.transformMatrix, fabric.parseTransformAttribute(value));\n      }\n      else {\n        value = fabric.parseTransformAttribute(value);\n      }\n    }\n    else if (attr === 'visible') {\n      value = value !== 'none' && value !== 'hidden';\n      // display=none on parent element always takes precedence over child element\n      if (parentAttributes && parentAttributes.visible === false) {\n        value = false;\n      }\n    }\n    else if (attr === 'opacity') {\n      value = parseFloat(value);\n      if (parentAttributes && typeof parentAttributes.opacity !== 'undefined') {\n        value *= parentAttributes.opacity;\n      }\n    }\n    else if (attr === 'textAnchor' /* text-anchor */) {\n      value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center';\n    }\n    else if (attr === 'charSpacing') {\n      // parseUnit returns px and we convert it to em\n      parsed = parseUnit(value, fontSize) / fontSize * 1000;\n    }\n    else if (attr === 'paintFirst') {\n      var fillIndex = value.indexOf('fill');\n      var strokeIndex = value.indexOf('stroke');\n      var value = 'fill';\n      if (fillIndex > -1 && strokeIndex > -1 && strokeIndex < fillIndex) {\n        value = 'stroke';\n      }\n      else if (fillIndex === -1 && strokeIndex > -1) {\n        value = 'stroke';\n      }\n    }\n    else if (attr === 'href' || attr === 'xlink:href' || attr === 'font') {\n      return value;\n    }\n    else if (attr === 'imageSmoothing') {\n      return (value === 'optimizeQuality' ? true : false);\n    }\n    else {\n      parsed = isArray ? value.map(parseUnit) : parseUnit(value, fontSize);\n    }\n\n    return (!isArray && isNaN(parsed) ? value : parsed);\n  }\n\n  /**\n    * @private\n    */\n  function getSvgRegex(arr) {\n    return new RegExp('^(' + arr.join('|') + ')\\\\b', 'i');\n  }\n\n  /**\n   * @private\n   * @param {Object} attributes Array of attributes to parse\n   */\n  function _setStrokeFillOpacity(attributes) {\n    for (var attr in colorAttributes) {\n\n      if (typeof attributes[colorAttributes[attr]] === 'undefined' || attributes[attr] === '') {\n        continue;\n      }\n\n      if (typeof attributes[attr] === 'undefined') {\n        if (!fabric.Object.prototype[attr]) {\n          continue;\n        }\n        attributes[attr] = fabric.Object.prototype[attr];\n      }\n\n      if (attributes[attr].indexOf('url(') === 0) {\n        continue;\n      }\n\n      var color = new fabric.Color(attributes[attr]);\n      attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba();\n    }\n    return attributes;\n  }\n\n  /**\n   * @private\n   */\n  function _getMultipleNodes(doc, nodeNames) {\n    var nodeName, nodeArray = [], nodeList, i, len;\n    for (i = 0, len = nodeNames.length; i < len; i++) {\n      nodeName = nodeNames[i];\n      nodeList = doc.getElementsByTagName(nodeName);\n      nodeArray = nodeArray.concat(Array.prototype.slice.call(nodeList));\n    }\n    return nodeArray;\n  }\n\n  /**\n   * Parses \"transform\" attribute, returning an array of values\n   * @static\n   * @function\n   * @memberOf fabric\n   * @param {String} attributeValue String containing attribute value\n   * @return {Array} Array of 6 elements representing transformation matrix\n   */\n  fabric.parseTransformAttribute = (function() {\n    function rotateMatrix(matrix, args) {\n      var cos = fabric.util.cos(args[0]), sin = fabric.util.sin(args[0]),\n          x = 0, y = 0;\n      if (args.length === 3) {\n        x = args[1];\n        y = args[2];\n      }\n\n      matrix[0] = cos;\n      matrix[1] = sin;\n      matrix[2] = -sin;\n      matrix[3] = cos;\n      matrix[4] = x - (cos * x - sin * y);\n      matrix[5] = y - (sin * x + cos * y);\n    }\n\n    function scaleMatrix(matrix, args) {\n      var multiplierX = args[0],\n          multiplierY = (args.length === 2) ? args[1] : args[0];\n\n      matrix[0] = multiplierX;\n      matrix[3] = multiplierY;\n    }\n\n    function skewMatrix(matrix, args, pos) {\n      matrix[pos] = Math.tan(fabric.util.degreesToRadians(args[0]));\n    }\n\n    function translateMatrix(matrix, args) {\n      matrix[4] = args[0];\n      if (args.length === 2) {\n        matrix[5] = args[1];\n      }\n    }\n\n    // identity matrix\n    var iMatrix = fabric.iMatrix,\n\n        // == begin transform regexp\n        number = fabric.reNum,\n\n        commaWsp = fabric.commaWsp,\n\n        skewX = '(?:(skewX)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*\\\\))',\n\n        skewY = '(?:(skewY)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*\\\\))',\n\n        rotate = '(?:(rotate)\\\\s*\\\\(\\\\s*(' + number + ')(?:' +\n                    commaWsp + '(' + number + ')' +\n                    commaWsp + '(' + number + '))?\\\\s*\\\\))',\n\n        scale = '(?:(scale)\\\\s*\\\\(\\\\s*(' + number + ')(?:' +\n                    commaWsp + '(' + number + '))?\\\\s*\\\\))',\n\n        translate = '(?:(translate)\\\\s*\\\\(\\\\s*(' + number + ')(?:' +\n                    commaWsp + '(' + number + '))?\\\\s*\\\\))',\n\n        matrix = '(?:(matrix)\\\\s*\\\\(\\\\s*' +\n                  '(' + number + ')' + commaWsp +\n                  '(' + number + ')' + commaWsp +\n                  '(' + number + ')' + commaWsp +\n                  '(' + number + ')' + commaWsp +\n                  '(' + number + ')' + commaWsp +\n                  '(' + number + ')' +\n                  '\\\\s*\\\\))',\n\n        transform = '(?:' +\n                    matrix + '|' +\n                    translate + '|' +\n                    scale + '|' +\n                    rotate + '|' +\n                    skewX + '|' +\n                    skewY +\n                    ')',\n\n        transforms = '(?:' + transform + '(?:' + commaWsp + '*' + transform + ')*' + ')',\n\n        transformList = '^\\\\s*(?:' + transforms + '?)\\\\s*$',\n\n        // http://www.w3.org/TR/SVG/coords.html#TransformAttribute\n        reTransformList = new RegExp(transformList),\n        // == end transform regexp\n\n        reTransform = new RegExp(transform, 'g');\n\n    return function(attributeValue) {\n\n      // start with identity matrix\n      var matrix = iMatrix.concat(),\n          matrices = [];\n\n      // return if no argument was given or\n      // an argument does not match transform attribute regexp\n      if (!attributeValue || (attributeValue && !reTransformList.test(attributeValue))) {\n        return matrix;\n      }\n\n      attributeValue.replace(reTransform, function(match) {\n\n        var m = new RegExp(transform).exec(match).filter(function (match) {\n              // match !== '' && match != null\n              return (!!match);\n            }),\n            operation = m[1],\n            args = m.slice(2).map(parseFloat);\n\n        switch (operation) {\n          case 'translate':\n            translateMatrix(matrix, args);\n            break;\n          case 'rotate':\n            args[0] = fabric.util.degreesToRadians(args[0]);\n            rotateMatrix(matrix, args);\n            break;\n          case 'scale':\n            scaleMatrix(matrix, args);\n            break;\n          case 'skewX':\n            skewMatrix(matrix, args, 2);\n            break;\n          case 'skewY':\n            skewMatrix(matrix, args, 1);\n            break;\n          case 'matrix':\n            matrix = args;\n            break;\n        }\n\n        // snapshot current matrix into matrices array\n        matrices.push(matrix.concat());\n        // reset\n        matrix = iMatrix.concat();\n      });\n\n      var combinedMatrix = matrices[0];\n      while (matrices.length > 1) {\n        matrices.shift();\n        combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]);\n      }\n      return combinedMatrix;\n    };\n  })();\n\n  /**\n   * @private\n   */\n  function parseStyleString(style, oStyle) {\n    var attr, value;\n    style.replace(/;\\s*$/, '').split(';').forEach(function (chunk) {\n      var pair = chunk.split(':');\n\n      attr = pair[0].trim().toLowerCase();\n      value =  pair[1].trim();\n\n      oStyle[attr] = value;\n    });\n  }\n\n  /**\n   * @private\n   */\n  function parseStyleObject(style, oStyle) {\n    var attr, value;\n    for (var prop in style) {\n      if (typeof style[prop] === 'undefined') {\n        continue;\n      }\n\n      attr = prop.toLowerCase();\n      value = style[prop];\n\n      oStyle[attr] = value;\n    }\n  }\n\n  /**\n   * @private\n   */\n  function getGlobalStylesForElement(element, svgUid) {\n    var styles = { };\n    for (var rule in fabric.cssRules[svgUid]) {\n      if (elementMatchesRule(element, rule.split(' '))) {\n        for (var property in fabric.cssRules[svgUid][rule]) {\n          styles[property] = fabric.cssRules[svgUid][rule][property];\n        }\n      }\n    }\n    return styles;\n  }\n\n  /**\n   * @private\n   */\n  function elementMatchesRule(element, selectors) {\n    var firstMatching, parentMatching = true;\n    //start from rightmost selector.\n    firstMatching = selectorMatches(element, selectors.pop());\n    if (firstMatching && selectors.length) {\n      parentMatching = doesSomeParentMatch(element, selectors);\n    }\n    return firstMatching && parentMatching && (selectors.length === 0);\n  }\n\n  function doesSomeParentMatch(element, selectors) {\n    var selector, parentMatching = true;\n    while (element.parentNode && element.parentNode.nodeType === 1 && selectors.length) {\n      if (parentMatching) {\n        selector = selectors.pop();\n      }\n      element = element.parentNode;\n      parentMatching = selectorMatches(element, selector);\n    }\n    return selectors.length === 0;\n  }\n\n  /**\n   * @private\n   */\n  function selectorMatches(element, selector) {\n    var nodeName = element.nodeName,\n        classNames = element.getAttribute('class'),\n        id = element.getAttribute('id'), matcher, i;\n    // i check if a selector matches slicing away part from it.\n    // if i get empty string i should match\n    matcher = new RegExp('^' + nodeName, 'i');\n    selector = selector.replace(matcher, '');\n    if (id && selector.length) {\n      matcher = new RegExp('#' + id + '(?![a-zA-Z\\\\-]+)', 'i');\n      selector = selector.replace(matcher, '');\n    }\n    if (classNames && selector.length) {\n      classNames = classNames.split(' ');\n      for (i = classNames.length; i--;) {\n        matcher = new RegExp('\\\\.' + classNames[i] + '(?![a-zA-Z\\\\-]+)', 'i');\n        selector = selector.replace(matcher, '');\n      }\n    }\n    return selector.length === 0;\n  }\n\n  /**\n   * @private\n   * to support IE8 missing getElementById on SVGdocument and on node xmlDOM\n   */\n  function elementById(doc, id) {\n    var el;\n    doc.getElementById && (el = doc.getElementById(id));\n    if (el) {\n      return el;\n    }\n    var node, i, len, nodelist = doc.getElementsByTagName('*');\n    for (i = 0, len = nodelist.length; i < len; i++) {\n      node = nodelist[i];\n      if (id === node.getAttribute('id')) {\n        return node;\n      }\n    }\n  }\n\n  /**\n   * @private\n   */\n  function parseUseDirectives(doc) {\n    var nodelist = _getMultipleNodes(doc, ['use', 'svg:use']), i = 0;\n    while (nodelist.length && i < nodelist.length) {\n      var el = nodelist[i],\n          xlink = (el.getAttribute('xlink:href') || el.getAttribute('href')).substr(1),\n          x = el.getAttribute('x') || 0,\n          y = el.getAttribute('y') || 0,\n          el2 = elementById(doc, xlink).cloneNode(true),\n          currentTrans = (el2.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')',\n          parentNode, oldLength = nodelist.length, attr, j, attrs, len, namespace = fabric.svgNS;\n\n      applyViewboxTransform(el2);\n      if (/^svg$/i.test(el2.nodeName)) {\n        var el3 = el2.ownerDocument.createElementNS(namespace, 'g');\n        for (j = 0, attrs = el2.attributes, len = attrs.length; j < len; j++) {\n          attr = attrs.item(j);\n          el3.setAttributeNS(namespace, attr.nodeName, attr.nodeValue);\n        }\n        // el2.firstChild != null\n        while (el2.firstChild) {\n          el3.appendChild(el2.firstChild);\n        }\n        el2 = el3;\n      }\n\n      for (j = 0, attrs = el.attributes, len = attrs.length; j < len; j++) {\n        attr = attrs.item(j);\n        if (attr.nodeName === 'x' || attr.nodeName === 'y' ||\n          attr.nodeName === 'xlink:href' || attr.nodeName === 'href') {\n          continue;\n        }\n\n        if (attr.nodeName === 'transform') {\n          currentTrans = attr.nodeValue + ' ' + currentTrans;\n        }\n        else {\n          el2.setAttribute(attr.nodeName, attr.nodeValue);\n        }\n      }\n\n      el2.setAttribute('transform', currentTrans);\n      el2.setAttribute('instantiated_by_use', '1');\n      el2.removeAttribute('id');\n      parentNode = el.parentNode;\n      parentNode.replaceChild(el2, el);\n      // some browsers do not shorten nodelist after replaceChild (IE8)\n      if (nodelist.length === oldLength) {\n        i++;\n      }\n    }\n  }\n\n  // http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute\n  // matches, e.g.: +14.56e-12, etc.\n  var reViewBoxAttrValue = new RegExp(\n    '^' +\n    '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' +\n    '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' +\n    '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' +\n    '\\\\s*(' + fabric.reNum + '+)\\\\s*' +\n    '$'\n  );\n\n  /**\n   * Add a <g> element that envelop all child elements and makes the viewbox transformMatrix descend on all elements\n   */\n  function applyViewboxTransform(element) {\n    if (!fabric.svgViewBoxElementsRegEx.test(element.nodeName)) {\n      return;\n    }\n    var viewBoxAttr = element.getAttribute('viewBox'),\n        scaleX = 1,\n        scaleY = 1,\n        minX = 0,\n        minY = 0,\n        viewBoxWidth, viewBoxHeight, matrix, el,\n        widthAttr = element.getAttribute('width'),\n        heightAttr = element.getAttribute('height'),\n        x = element.getAttribute('x') || 0,\n        y = element.getAttribute('y') || 0,\n        preserveAspectRatio = element.getAttribute('preserveAspectRatio') || '',\n        missingViewBox = (!viewBoxAttr || !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))),\n        missingDimAttr = (!widthAttr || !heightAttr || widthAttr === '100%' || heightAttr === '100%'),\n        toBeParsed = missingViewBox && missingDimAttr,\n        parsedDim = { }, translateMatrix = '', widthDiff = 0, heightDiff = 0;\n\n    parsedDim.width = 0;\n    parsedDim.height = 0;\n    parsedDim.toBeParsed = toBeParsed;\n\n    if (missingViewBox) {\n      if (((x || y) && element.parentNode.nodeName !== '#document')) {\n        translateMatrix = ' translate(' + parseUnit(x) + ' ' + parseUnit(y) + ') ';\n        matrix = (element.getAttribute('transform') || '') + translateMatrix;\n        element.setAttribute('transform', matrix);\n        element.removeAttribute('x');\n        element.removeAttribute('y');\n      }\n    }\n\n    if (toBeParsed) {\n      return parsedDim;\n    }\n\n    if (missingViewBox) {\n      parsedDim.width = parseUnit(widthAttr);\n      parsedDim.height = parseUnit(heightAttr);\n      // set a transform for elements that have x y and are inner(only) SVGs\n      return parsedDim;\n    }\n    minX = -parseFloat(viewBoxAttr[1]);\n    minY = -parseFloat(viewBoxAttr[2]);\n    viewBoxWidth = parseFloat(viewBoxAttr[3]);\n    viewBoxHeight = parseFloat(viewBoxAttr[4]);\n    parsedDim.minX = minX;\n    parsedDim.minY = minY;\n    parsedDim.viewBoxWidth = viewBoxWidth;\n    parsedDim.viewBoxHeight = viewBoxHeight;\n    if (!missingDimAttr) {\n      parsedDim.width = parseUnit(widthAttr);\n      parsedDim.height = parseUnit(heightAttr);\n      scaleX = parsedDim.width / viewBoxWidth;\n      scaleY = parsedDim.height / viewBoxHeight;\n    }\n    else {\n      parsedDim.width = viewBoxWidth;\n      parsedDim.height = viewBoxHeight;\n    }\n\n    // default is to preserve aspect ratio\n    preserveAspectRatio = fabric.util.parsePreserveAspectRatioAttribute(preserveAspectRatio);\n    if (preserveAspectRatio.alignX !== 'none') {\n      //translate all container for the effect of Mid, Min, Max\n      if (preserveAspectRatio.meetOrSlice === 'meet') {\n        scaleY = scaleX = (scaleX > scaleY ? scaleY : scaleX);\n        // calculate additional translation to move the viewbox\n      }\n      if (preserveAspectRatio.meetOrSlice === 'slice') {\n        scaleY = scaleX = (scaleX > scaleY ? scaleX : scaleY);\n        // calculate additional translation to move the viewbox\n      }\n      widthDiff = parsedDim.width - viewBoxWidth * scaleX;\n      heightDiff = parsedDim.height - viewBoxHeight * scaleX;\n      if (preserveAspectRatio.alignX === 'Mid') {\n        widthDiff /= 2;\n      }\n      if (preserveAspectRatio.alignY === 'Mid') {\n        heightDiff /= 2;\n      }\n      if (preserveAspectRatio.alignX === 'Min') {\n        widthDiff = 0;\n      }\n      if (preserveAspectRatio.alignY === 'Min') {\n        heightDiff = 0;\n      }\n    }\n\n    if (scaleX === 1 && scaleY === 1 && minX === 0 && minY === 0 && x === 0 && y === 0) {\n      return parsedDim;\n    }\n    if ((x || y) && element.parentNode.nodeName !== '#document') {\n      translateMatrix = ' translate(' + parseUnit(x) + ' ' + parseUnit(y) + ') ';\n    }\n\n    matrix = translateMatrix + ' matrix(' + scaleX +\n                  ' 0' +\n                  ' 0 ' +\n                  scaleY + ' ' +\n                  (minX * scaleX + widthDiff) + ' ' +\n                  (minY * scaleY + heightDiff) + ') ';\n    // seems unused.\n    // parsedDim.viewboxTransform = fabric.parseTransformAttribute(matrix);\n    if (element.nodeName === 'svg') {\n      el = element.ownerDocument.createElementNS(fabric.svgNS, 'g');\n      // element.firstChild != null\n      while (element.firstChild) {\n        el.appendChild(element.firstChild);\n      }\n      element.appendChild(el);\n    }\n    else {\n      el = element;\n      el.removeAttribute('x');\n      el.removeAttribute('y');\n      matrix = el.getAttribute('transform') + matrix;\n    }\n    el.setAttribute('transform', matrix);\n    return parsedDim;\n  }\n\n  function hasAncestorWithNodeName(element, nodeName) {\n    while (element && (element = element.parentNode)) {\n      if (element.nodeName && nodeName.test(element.nodeName.replace('svg:', ''))\n        && !element.getAttribute('instantiated_by_use')) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Parses an SVG document, converts it to an array of corresponding fabric.* instances and passes them to a callback\n   * @static\n   * @function\n   * @memberOf fabric\n   * @param {SVGDocument} doc SVG document to parse\n   * @param {Function} callback Callback to call when parsing is finished;\n   * It's being passed an array of elements (parsed from a document).\n   * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n   * @param {Object} [parsingOptions] options for parsing document\n   * @param {String} [parsingOptions.crossOrigin] crossOrigin settings\n   */\n  fabric.parseSVGDocument = function(doc, callback, reviver, parsingOptions) {\n    if (!doc) {\n      return;\n    }\n\n    parseUseDirectives(doc);\n\n    var svgUid =  fabric.Object.__uid++, i, len,\n        options = applyViewboxTransform(doc),\n        descendants = fabric.util.toArray(doc.getElementsByTagName('*'));\n    options.crossOrigin = parsingOptions && parsingOptions.crossOrigin;\n    options.svgUid = svgUid;\n\n    if (descendants.length === 0 && fabric.isLikelyNode) {\n      // we're likely in node, where \"o3-xml\" library fails to gEBTN(\"*\")\n      // https://github.com/ajaxorg/node-o3-xml/issues/21\n      descendants = doc.selectNodes('//*[name(.)!=\"svg\"]');\n      var arr = [];\n      for (i = 0, len = descendants.length; i < len; i++) {\n        arr[i] = descendants[i];\n      }\n      descendants = arr;\n    }\n\n    var elements = descendants.filter(function(el) {\n      applyViewboxTransform(el);\n      return fabric.svgValidTagNamesRegEx.test(el.nodeName.replace('svg:', '')) &&\n            !hasAncestorWithNodeName(el, fabric.svgInvalidAncestorsRegEx); // http://www.w3.org/TR/SVG/struct.html#DefsElement\n    });\n    if (!elements || (elements && !elements.length)) {\n      callback && callback([], {});\n      return;\n    }\n    var clipPaths = { };\n    descendants.filter(function(el) {\n      return el.nodeName.replace('svg:', '') === 'clipPath';\n    }).forEach(function(el) {\n      var id = el.getAttribute('id');\n      clipPaths[id] = fabric.util.toArray(el.getElementsByTagName('*')).filter(function(el) {\n        return fabric.svgValidTagNamesRegEx.test(el.nodeName.replace('svg:', ''));\n      });\n    });\n    fabric.gradientDefs[svgUid] = fabric.getGradientDefs(doc);\n    fabric.cssRules[svgUid] = fabric.getCSSRules(doc);\n    fabric.clipPaths[svgUid] = clipPaths;\n    // Precedence of rules:   style > class > attribute\n    fabric.parseElements(elements, function(instances, elements) {\n      if (callback) {\n        callback(instances, options, elements, descendants);\n        delete fabric.gradientDefs[svgUid];\n        delete fabric.cssRules[svgUid];\n        delete fabric.clipPaths[svgUid];\n      }\n    }, clone(options), reviver, parsingOptions);\n  };\n\n  function recursivelyParseGradientsXlink(doc, gradient) {\n    var gradientsAttrs = ['gradientTransform', 'x1', 'x2', 'y1', 'y2', 'gradientUnits', 'cx', 'cy', 'r', 'fx', 'fy'],\n        xlinkAttr = 'xlink:href',\n        xLink = gradient.getAttribute(xlinkAttr).substr(1),\n        referencedGradient = elementById(doc, xLink);\n    if (referencedGradient && referencedGradient.getAttribute(xlinkAttr)) {\n      recursivelyParseGradientsXlink(doc, referencedGradient);\n    }\n    gradientsAttrs.forEach(function(attr) {\n      if (referencedGradient && !gradient.hasAttribute(attr) && referencedGradient.hasAttribute(attr)) {\n        gradient.setAttribute(attr, referencedGradient.getAttribute(attr));\n      }\n    });\n    if (!gradient.children.length) {\n      var referenceClone = referencedGradient.cloneNode(true);\n      while (referenceClone.firstChild) {\n        gradient.appendChild(referenceClone.firstChild);\n      }\n    }\n    gradient.removeAttribute(xlinkAttr);\n  }\n\n  var reFontDeclaration = new RegExp(\n    '(normal|italic)?\\\\s*(normal|small-caps)?\\\\s*' +\n    '(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\\\\s*(' +\n      fabric.reNum +\n    '(?:px|cm|mm|em|pt|pc|in)*)(?:\\\\/(normal|' + fabric.reNum + '))?\\\\s+(.*)');\n\n  extend(fabric, {\n    /**\n     * Parses a short font declaration, building adding its properties to a style object\n     * @static\n     * @function\n     * @memberOf fabric\n     * @param {String} value font declaration\n     * @param {Object} oStyle definition\n     */\n    parseFontDeclaration: function(value, oStyle) {\n      var match = value.match(reFontDeclaration);\n\n      if (!match) {\n        return;\n      }\n      var fontStyle = match[1],\n          // font variant is not used\n          // fontVariant = match[2],\n          fontWeight = match[3],\n          fontSize = match[4],\n          lineHeight = match[5],\n          fontFamily = match[6];\n\n      if (fontStyle) {\n        oStyle.fontStyle = fontStyle;\n      }\n      if (fontWeight) {\n        oStyle.fontWeight = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight);\n      }\n      if (fontSize) {\n        oStyle.fontSize = parseUnit(fontSize);\n      }\n      if (fontFamily) {\n        oStyle.fontFamily = fontFamily;\n      }\n      if (lineHeight) {\n        oStyle.lineHeight = lineHeight === 'normal' ? 1 : lineHeight;\n      }\n    },\n\n    /**\n     * Parses an SVG document, returning all of the gradient declarations found in it\n     * @static\n     * @function\n     * @memberOf fabric\n     * @param {SVGDocument} doc SVG document to parse\n     * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element\n     */\n    getGradientDefs: function(doc) {\n      var tagArray = [\n            'linearGradient',\n            'radialGradient',\n            'svg:linearGradient',\n            'svg:radialGradient'],\n          elList = _getMultipleNodes(doc, tagArray),\n          el, j = 0, gradientDefs = { };\n      j = elList.length;\n      while (j--) {\n        el = elList[j];\n        if (el.getAttribute('xlink:href')) {\n          recursivelyParseGradientsXlink(doc, el);\n        }\n        gradientDefs[el.getAttribute('id')] = el;\n      }\n      return gradientDefs;\n    },\n\n    /**\n     * Returns an object of attributes' name/value, given element and an array of attribute names;\n     * Parses parent \"g\" nodes recursively upwards.\n     * @static\n     * @memberOf fabric\n     * @param {DOMElement} element Element to parse\n     * @param {Array} attributes Array of attributes to parse\n     * @return {Object} object containing parsed attributes' names/values\n     */\n    parseAttributes: function(element, attributes, svgUid) {\n\n      if (!element) {\n        return;\n      }\n\n      var value,\n          parentAttributes = { },\n          fontSize, parentFontSize;\n\n      if (typeof svgUid === 'undefined') {\n        svgUid = element.getAttribute('svgUid');\n      }\n      // if there's a parent container (`g` or `a` or `symbol` node), parse its attributes recursively upwards\n      if (element.parentNode && fabric.svgValidParentsRegEx.test(element.parentNode.nodeName)) {\n        parentAttributes = fabric.parseAttributes(element.parentNode, attributes, svgUid);\n      }\n\n      var ownAttributes = attributes.reduce(function(memo, attr) {\n        value = element.getAttribute(attr);\n        if (value) { // eslint-disable-line\n          memo[attr] = value;\n        }\n        return memo;\n      }, { });\n      // add values parsed from style, which take precedence over attributes\n      // (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes)\n      var cssAttrs = extend(\n        getGlobalStylesForElement(element, svgUid),\n        fabric.parseStyleAttribute(element)\n      );\n      ownAttributes = extend(\n        ownAttributes,\n        cssAttrs\n      );\n      if (cssAttrs[cPath]) {\n        element.setAttribute(cPath, cssAttrs[cPath]);\n      }\n      fontSize = parentFontSize = parentAttributes.fontSize || fabric.Text.DEFAULT_SVG_FONT_SIZE;\n      if (ownAttributes[fSize]) {\n        // looks like the minimum should be 9px when dealing with ems. this is what looks like in browsers.\n        ownAttributes[fSize] = fontSize = parseUnit(ownAttributes[fSize], parentFontSize);\n      }\n\n      var normalizedAttr, normalizedValue, normalizedStyle = {};\n      for (var attr in ownAttributes) {\n        normalizedAttr = normalizeAttr(attr);\n        normalizedValue = normalizeValue(normalizedAttr, ownAttributes[attr], parentAttributes, fontSize);\n        normalizedStyle[normalizedAttr] = normalizedValue;\n      }\n      if (normalizedStyle && normalizedStyle.font) {\n        fabric.parseFontDeclaration(normalizedStyle.font, normalizedStyle);\n      }\n      var mergedAttrs = extend(parentAttributes, normalizedStyle);\n      return fabric.svgValidParentsRegEx.test(element.nodeName) ? mergedAttrs : _setStrokeFillOpacity(mergedAttrs);\n    },\n\n    /**\n     * Transforms an array of svg elements to corresponding fabric.* instances\n     * @static\n     * @memberOf fabric\n     * @param {Array} elements Array of elements to parse\n     * @param {Function} callback Being passed an array of fabric instances (transformed from SVG elements)\n     * @param {Object} [options] Options object\n     * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n     */\n    parseElements: function(elements, callback, options, reviver, parsingOptions) {\n      new fabric.ElementsParser(elements, callback, options, reviver, parsingOptions).parse();\n    },\n\n    /**\n     * Parses \"style\" attribute, retuning an object with values\n     * @static\n     * @memberOf fabric\n     * @param {SVGElement} element Element to parse\n     * @return {Object} Objects with values parsed from style attribute of an element\n     */\n    parseStyleAttribute: function(element) {\n      var oStyle = { },\n          style = element.getAttribute('style');\n\n      if (!style) {\n        return oStyle;\n      }\n\n      if (typeof style === 'string') {\n        parseStyleString(style, oStyle);\n      }\n      else {\n        parseStyleObject(style, oStyle);\n      }\n\n      return oStyle;\n    },\n\n    /**\n     * Parses \"points\" attribute, returning an array of values\n     * @static\n     * @memberOf fabric\n     * @param {String} points points attribute string\n     * @return {Array} array of points\n     */\n    parsePointsAttribute: function(points) {\n\n      // points attribute is required and must not be empty\n      if (!points) {\n        return null;\n      }\n\n      // replace commas with whitespace and remove bookending whitespace\n      points = points.replace(/,/g, ' ').trim();\n\n      points = points.split(/\\s+/);\n      var parsedPoints = [], i, len;\n\n      for (i = 0, len = points.length; i < len; i += 2) {\n        parsedPoints.push({\n          x: parseFloat(points[i]),\n          y: parseFloat(points[i + 1])\n        });\n      }\n\n      // odd number of points is an error\n      // if (parsedPoints.length % 2 !== 0) {\n      //   return null;\n      // }\n\n      return parsedPoints;\n    },\n\n    /**\n     * Returns CSS rules for a given SVG document\n     * @static\n     * @function\n     * @memberOf fabric\n     * @param {SVGDocument} doc SVG document to parse\n     * @return {Object} CSS rules of this document\n     */\n    getCSSRules: function(doc) {\n      var styles = doc.getElementsByTagName('style'), i, len,\n          allRules = { }, rules;\n\n      // very crude parsing of style contents\n      for (i = 0, len = styles.length; i < len; i++) {\n        // <style/> could produce `undefined`, covering this case with ''\n        var styleContents = styles[i].textContent || '';\n\n        // remove comments\n        styleContents = styleContents.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n        if (styleContents.trim() === '') {\n          continue;\n        }\n        rules = styleContents.match(/[^{]*\\{[\\s\\S]*?\\}/g);\n        rules = rules.map(function(rule) { return rule.trim(); });\n        // eslint-disable-next-line no-loop-func\n        rules.forEach(function(rule) {\n\n          var match = rule.match(/([\\s\\S]*?)\\s*\\{([^}]*)\\}/),\n              ruleObj = { }, declaration = match[2].trim(),\n              propertyValuePairs = declaration.replace(/;$/, '').split(/\\s*;\\s*/);\n\n          for (i = 0, len = propertyValuePairs.length; i < len; i++) {\n            var pair = propertyValuePairs[i].split(/\\s*:\\s*/),\n                property = pair[0],\n                value = pair[1];\n            ruleObj[property] = value;\n          }\n          rule = match[1];\n          rule.split(',').forEach(function(_rule) {\n            _rule = _rule.replace(/^svg/i, '').trim();\n            if (_rule === '') {\n              return;\n            }\n            if (allRules[_rule]) {\n              fabric.util.object.extend(allRules[_rule], ruleObj);\n            }\n            else {\n              allRules[_rule] = fabric.util.object.clone(ruleObj);\n            }\n          });\n        });\n      }\n      return allRules;\n    },\n\n    /**\n     * Takes url corresponding to an SVG document, and parses it into a set of fabric objects.\n     * Note that SVG is fetched via XMLHttpRequest, so it needs to conform to SOP (Same Origin Policy)\n     * @memberOf fabric\n     * @param {String} url\n     * @param {Function} callback\n     * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n     * @param {Object} [options] Object containing options for parsing\n     * @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources\n     */\n    loadSVGFromURL: function(url, callback, reviver, options) {\n\n      url = url.replace(/^\\n\\s*/, '').trim();\n      new fabric.util.request(url, {\n        method: 'get',\n        onComplete: onComplete\n      });\n\n      function onComplete(r) {\n\n        var xml = r.responseXML;\n        if (!xml || !xml.documentElement) {\n          callback && callback(null);\n          return false;\n        }\n\n        fabric.parseSVGDocument(xml.documentElement, function (results, _options, elements, allElements) {\n          callback && callback(results, _options, elements, allElements);\n        }, reviver, options);\n      }\n    },\n\n    /**\n     * Takes string corresponding to an SVG document, and parses it into a set of fabric objects\n     * @memberOf fabric\n     * @param {String} string\n     * @param {Function} callback\n     * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n     * @param {Object} [options] Object containing options for parsing\n     * @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources\n     */\n    loadSVGFromString: function(string, callback, reviver, options) {\n      var parser = new fabric.window.DOMParser(),\n          doc = parser.parseFromString(string.trim(), 'text/xml');\n      fabric.parseSVGDocument(doc.documentElement, function (results, _options, elements, allElements) {\n        callback(results, _options, elements, allElements);\n      }, reviver, options);\n    }\n  });\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\nfabric.ElementsParser = function(elements, callback, options, reviver, parsingOptions, doc) {\n  this.elements = elements;\n  this.callback = callback;\n  this.options = options;\n  this.reviver = reviver;\n  this.svgUid = (options && options.svgUid) || 0;\n  this.parsingOptions = parsingOptions;\n  this.regexUrl = /^url\\(['\"]?#([^'\"]+)['\"]?\\)/g;\n  this.doc = doc;\n};\n\n(function(proto) {\n  proto.parse = function() {\n    this.instances = new Array(this.elements.length);\n    this.numElements = this.elements.length;\n    this.createObjects();\n  };\n\n  proto.createObjects = function() {\n    var _this = this;\n    this.elements.forEach(function(element, i) {\n      element.setAttribute('svgUid', _this.svgUid);\n      _this.createObject(element, i);\n    });\n  };\n\n  proto.findTag = function(el) {\n    return fabric[fabric.util.string.capitalize(el.tagName.replace('svg:', ''))];\n  };\n\n  proto.createObject = function(el, index) {\n    var klass = this.findTag(el);\n    if (klass && klass.fromElement) {\n      try {\n        klass.fromElement(el, this.createCallback(index, el), this.options);\n      }\n      catch (err) {\n        fabric.log(err);\n      }\n    }\n    else {\n      this.checkIfDone();\n    }\n  };\n\n  proto.createCallback = function(index, el) {\n    var _this = this;\n    return function(obj) {\n      var _options;\n      _this.resolveGradient(obj, el, 'fill');\n      _this.resolveGradient(obj, el, 'stroke');\n      if (obj instanceof fabric.Image && obj._originalElement) {\n        _options = obj.parsePreserveAspectRatioAttribute(el);\n      }\n      obj._removeTransformMatrix(_options);\n      _this.resolveClipPath(obj, el);\n      _this.reviver && _this.reviver(el, obj);\n      _this.instances[index] = obj;\n      _this.checkIfDone();\n    };\n  };\n\n  proto.extractPropertyDefinition = function(obj, property, storage) {\n    var value = obj[property], regex = this.regexUrl;\n    if (!regex.test(value)) {\n      return;\n    }\n    regex.lastIndex = 0;\n    var id = regex.exec(value)[1];\n    regex.lastIndex = 0;\n    return fabric[storage][this.svgUid][id];\n  };\n\n  proto.resolveGradient = function(obj, el, property) {\n    var gradientDef = this.extractPropertyDefinition(obj, property, 'gradientDefs');\n    if (gradientDef) {\n      var opacityAttr = el.getAttribute(property + '-opacity');\n      var gradient = fabric.Gradient.fromElement(gradientDef, obj, opacityAttr, this.options);\n      obj.set(property, gradient);\n    }\n  };\n\n  proto.createClipPathCallback = function(obj, container) {\n    return function(_newObj) {\n      _newObj._removeTransformMatrix();\n      _newObj.fillRule = _newObj.clipRule;\n      container.push(_newObj);\n    };\n  };\n\n  proto.resolveClipPath = function(obj, usingElement) {\n    var clipPath = this.extractPropertyDefinition(obj, 'clipPath', 'clipPaths'),\n        element, klass, objTransformInv, container, gTransform, options;\n    if (clipPath) {\n      container = [];\n      objTransformInv = fabric.util.invertTransform(obj.calcTransformMatrix());\n      // move the clipPath tag as sibling to the real element that is using it\n      var clipPathTag = clipPath[0].parentNode;\n      var clipPathOwner = usingElement;\n      while (clipPathOwner.parentNode && clipPathOwner.getAttribute('clip-path') !== obj.clipPath) {\n        clipPathOwner = clipPathOwner.parentNode;\n      }\n      clipPathOwner.parentNode.appendChild(clipPathTag);\n      for (var i = 0; i < clipPath.length; i++) {\n        element = clipPath[i];\n        klass = this.findTag(element);\n        klass.fromElement(\n          element,\n          this.createClipPathCallback(obj, container),\n          this.options\n        );\n      }\n      if (container.length === 1) {\n        clipPath = container[0];\n      }\n      else {\n        clipPath = new fabric.Group(container);\n      }\n      gTransform = fabric.util.multiplyTransformMatrices(\n        objTransformInv,\n        clipPath.calcTransformMatrix()\n      );\n      if (clipPath.clipPath) {\n        this.resolveClipPath(clipPath, clipPathOwner);\n      }\n      var options = fabric.util.qrDecompose(gTransform);\n      clipPath.flipX = false;\n      clipPath.flipY = false;\n      clipPath.set('scaleX', options.scaleX);\n      clipPath.set('scaleY', options.scaleY);\n      clipPath.angle = options.angle;\n      clipPath.skewX = options.skewX;\n      clipPath.skewY = 0;\n      clipPath.setPositionByOrigin({ x: options.translateX, y: options.translateY }, 'center', 'center');\n      obj.clipPath = clipPath;\n    }\n    else {\n      // if clip-path does not resolve to any element, delete the property.\n      delete obj.clipPath;\n    }\n  };\n\n  proto.checkIfDone = function() {\n    if (--this.numElements === 0) {\n      this.instances = this.instances.filter(function(el) {\n        // eslint-disable-next-line no-eq-null, eqeqeq\n        return el != null;\n      });\n      this.callback(this.instances, this.elements);\n    }\n  };\n})(fabric.ElementsParser.prototype);\n\n\n(function(global) {\n\n  'use strict';\n\n  /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */\n\n  var fabric = global.fabric || (global.fabric = { });\n\n  if (fabric.Point) {\n    fabric.warn('fabric.Point is already defined');\n    return;\n  }\n\n  fabric.Point = Point;\n\n  /**\n   * Point class\n   * @class fabric.Point\n   * @memberOf fabric\n   * @constructor\n   * @param {Number} x\n   * @param {Number} y\n   * @return {fabric.Point} thisArg\n   */\n  function Point(x, y) {\n    this.x = x;\n    this.y = y;\n  }\n\n  Point.prototype = /** @lends fabric.Point.prototype */ {\n\n    type: 'point',\n\n    constructor: Point,\n\n    /**\n     * Adds another point to this one and returns another one\n     * @param {fabric.Point} that\n     * @return {fabric.Point} new Point instance with added values\n     */\n    add: function (that) {\n      return new Point(this.x + that.x, this.y + that.y);\n    },\n\n    /**\n     * Adds another point to this one\n     * @param {fabric.Point} that\n     * @return {fabric.Point} thisArg\n     * @chainable\n     */\n    addEquals: function (that) {\n      this.x += that.x;\n      this.y += that.y;\n      return this;\n    },\n\n    /**\n     * Adds value to this point and returns a new one\n     * @param {Number} scalar\n     * @return {fabric.Point} new Point with added value\n     */\n    scalarAdd: function (scalar) {\n      return new Point(this.x + scalar, this.y + scalar);\n    },\n\n    /**\n     * Adds value to this point\n     * @param {Number} scalar\n     * @return {fabric.Point} thisArg\n     * @chainable\n     */\n    scalarAddEquals: function (scalar) {\n      this.x += scalar;\n      this.y += scalar;\n      return this;\n    },\n\n    /**\n     * Subtracts another point from this point and returns a new one\n     * @param {fabric.Point} that\n     * @return {fabric.Point} new Point object with subtracted values\n     */\n    subtract: function (that) {\n      return new Point(this.x - that.x, this.y - that.y);\n    },\n\n    /**\n     * Subtracts another point from this point\n     * @param {fabric.Point} that\n     * @return {fabric.Point} thisArg\n     * @chainable\n     */\n    subtractEquals: function (that) {\n      this.x -= that.x;\n      this.y -= that.y;\n      return this;\n    },\n\n    /**\n     * Subtracts value from this point and returns a new one\n     * @param {Number} scalar\n     * @return {fabric.Point}\n     */\n    scalarSubtract: function (scalar) {\n      return new Point(this.x - scalar, this.y - scalar);\n    },\n\n    /**\n     * Subtracts value from this point\n     * @param {Number} scalar\n     * @return {fabric.Point} thisArg\n     * @chainable\n     */\n    scalarSubtractEquals: function (scalar) {\n      this.x -= scalar;\n      this.y -= scalar;\n      return this;\n    },\n\n    /**\n     * Multiplies this point by a value and returns a new one\n     * TODO: rename in scalarMultiply in 2.0\n     * @param {Number} scalar\n     * @return {fabric.Point}\n     */\n    multiply: function (scalar) {\n      return new Point(this.x * scalar, this.y * scalar);\n    },\n\n    /**\n     * Multiplies this point by a value\n     * TODO: rename in scalarMultiplyEquals in 2.0\n     * @param {Number} scalar\n     * @return {fabric.Point} thisArg\n     * @chainable\n     */\n    multiplyEquals: function (scalar) {\n      this.x *= scalar;\n      this.y *= scalar;\n      return this;\n    },\n\n    /**\n     * Divides this point by a value and returns a new one\n     * TODO: rename in scalarDivide in 2.0\n     * @param {Number} scalar\n     * @return {fabric.Point}\n     */\n    divide: function (scalar) {\n      return new Point(this.x / scalar, this.y / scalar);\n    },\n\n    /**\n     * Divides this point by a value\n     * TODO: rename in scalarDivideEquals in 2.0\n     * @param {Number} scalar\n     * @return {fabric.Point} thisArg\n     * @chainable\n     */\n    divideEquals: function (scalar) {\n      this.x /= scalar;\n      this.y /= scalar;\n      return this;\n    },\n\n    /**\n     * Returns true if this point is equal to another one\n     * @param {fabric.Point} that\n     * @return {Boolean}\n     */\n    eq: function (that) {\n      return (this.x === that.x && this.y === that.y);\n    },\n\n    /**\n     * Returns true if this point is less than another one\n     * @param {fabric.Point} that\n     * @return {Boolean}\n     */\n    lt: function (that) {\n      return (this.x < that.x && this.y < that.y);\n    },\n\n    /**\n     * Returns true if this point is less than or equal to another one\n     * @param {fabric.Point} that\n     * @return {Boolean}\n     */\n    lte: function (that) {\n      return (this.x <= that.x && this.y <= that.y);\n    },\n\n    /**\n\n     * Returns true if this point is greater another one\n     * @param {fabric.Point} that\n     * @return {Boolean}\n     */\n    gt: function (that) {\n      return (this.x > that.x && this.y > that.y);\n    },\n\n    /**\n     * Returns true if this point is greater than or equal to another one\n     * @param {fabric.Point} that\n     * @return {Boolean}\n     */\n    gte: function (that) {\n      return (this.x >= that.x && this.y >= that.y);\n    },\n\n    /**\n     * Returns new point which is the result of linear interpolation with this one and another one\n     * @param {fabric.Point} that\n     * @param {Number} t , position of interpolation, between 0 and 1 default 0.5\n     * @return {fabric.Point}\n     */\n    lerp: function (that, t) {\n      if (typeof t === 'undefined') {\n        t = 0.5;\n      }\n      t = Math.max(Math.min(1, t), 0);\n      return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t);\n    },\n\n    /**\n     * Returns distance from this point and another one\n     * @param {fabric.Point} that\n     * @return {Number}\n     */\n    distanceFrom: function (that) {\n      var dx = this.x - that.x,\n          dy = this.y - that.y;\n      return Math.sqrt(dx * dx + dy * dy);\n    },\n\n    /**\n     * Returns the point between this point and another one\n     * @param {fabric.Point} that\n     * @return {fabric.Point}\n     */\n    midPointFrom: function (that) {\n      return this.lerp(that);\n    },\n\n    /**\n     * Returns a new point which is the min of this and another one\n     * @param {fabric.Point} that\n     * @return {fabric.Point}\n     */\n    min: function (that) {\n      return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y));\n    },\n\n    /**\n     * Returns a new point which is the max of this and another one\n     * @param {fabric.Point} that\n     * @return {fabric.Point}\n     */\n    max: function (that) {\n      return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y));\n    },\n\n    /**\n     * Returns string representation of this point\n     * @return {String}\n     */\n    toString: function () {\n      return this.x + ',' + this.y;\n    },\n\n    /**\n     * Sets x/y of this point\n     * @param {Number} x\n     * @param {Number} y\n     * @chainable\n     */\n    setXY: function (x, y) {\n      this.x = x;\n      this.y = y;\n      return this;\n    },\n\n    /**\n     * Sets x of this point\n     * @param {Number} x\n     * @chainable\n     */\n    setX: function (x) {\n      this.x = x;\n      return this;\n    },\n\n    /**\n     * Sets y of this point\n     * @param {Number} y\n     * @chainable\n     */\n    setY: function (y) {\n      this.y = y;\n      return this;\n    },\n\n    /**\n     * Sets x/y of this point from another point\n     * @param {fabric.Point} that\n     * @chainable\n     */\n    setFromPoint: function (that) {\n      this.x = that.x;\n      this.y = that.y;\n      return this;\n    },\n\n    /**\n     * Swaps x/y of this point and another point\n     * @param {fabric.Point} that\n     */\n    swap: function (that) {\n      var x = this.x,\n          y = this.y;\n      this.x = that.x;\n      this.y = that.y;\n      that.x = x;\n      that.y = y;\n    },\n\n    /**\n     * return a cloned instance of the point\n     * @return {fabric.Point}\n     */\n    clone: function () {\n      return new Point(this.x, this.y);\n    }\n  };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */\n  var fabric = global.fabric || (global.fabric = { });\n\n  if (fabric.Intersection) {\n    fabric.warn('fabric.Intersection is already defined');\n    return;\n  }\n\n  /**\n   * Intersection class\n   * @class fabric.Intersection\n   * @memberOf fabric\n   * @constructor\n   */\n  function Intersection(status) {\n    this.status = status;\n    this.points = [];\n  }\n\n  fabric.Intersection = Intersection;\n\n  fabric.Intersection.prototype = /** @lends fabric.Intersection.prototype */ {\n\n    constructor: Intersection,\n\n    /**\n     * Appends a point to intersection\n     * @param {fabric.Point} point\n     * @return {fabric.Intersection} thisArg\n     * @chainable\n     */\n    appendPoint: function (point) {\n      this.points.push(point);\n      return this;\n    },\n\n    /**\n     * Appends points to intersection\n     * @param {Array} points\n     * @return {fabric.Intersection} thisArg\n     * @chainable\n     */\n    appendPoints: function (points) {\n      this.points = this.points.concat(points);\n      return this;\n    }\n  };\n\n  /**\n   * Checks if one line intersects another\n   * TODO: rename in intersectSegmentSegment\n   * @static\n   * @param {fabric.Point} a1\n   * @param {fabric.Point} a2\n   * @param {fabric.Point} b1\n   * @param {fabric.Point} b2\n   * @return {fabric.Intersection}\n   */\n  fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) {\n    var result,\n        uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x),\n        ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x),\n        uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);\n    if (uB !== 0) {\n      var ua = uaT / uB,\n          ub = ubT / uB;\n      if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {\n        result = new Intersection('Intersection');\n        result.appendPoint(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y)));\n      }\n      else {\n        result = new Intersection();\n      }\n    }\n    else {\n      if (uaT === 0 || ubT === 0) {\n        result = new Intersection('Coincident');\n      }\n      else {\n        result = new Intersection('Parallel');\n      }\n    }\n    return result;\n  };\n\n  /**\n   * Checks if line intersects polygon\n   * TODO: rename in intersectSegmentPolygon\n   * fix detection of coincident\n   * @static\n   * @param {fabric.Point} a1\n   * @param {fabric.Point} a2\n   * @param {Array} points\n   * @return {fabric.Intersection}\n   */\n  fabric.Intersection.intersectLinePolygon = function(a1, a2, points) {\n    var result = new Intersection(),\n        length = points.length,\n        b1, b2, inter, i;\n\n    for (i = 0; i < length; i++) {\n      b1 = points[i];\n      b2 = points[(i + 1) % length];\n      inter = Intersection.intersectLineLine(a1, a2, b1, b2);\n\n      result.appendPoints(inter.points);\n    }\n    if (result.points.length > 0) {\n      result.status = 'Intersection';\n    }\n    return result;\n  };\n\n  /**\n   * Checks if polygon intersects another polygon\n   * @static\n   * @param {Array} points1\n   * @param {Array} points2\n   * @return {fabric.Intersection}\n   */\n  fabric.Intersection.intersectPolygonPolygon = function (points1, points2) {\n    var result = new Intersection(),\n        length = points1.length, i;\n\n    for (i = 0; i < length; i++) {\n      var a1 = points1[i],\n          a2 = points1[(i + 1) % length],\n          inter = Intersection.intersectLinePolygon(a1, a2, points2);\n\n      result.appendPoints(inter.points);\n    }\n    if (result.points.length > 0) {\n      result.status = 'Intersection';\n    }\n    return result;\n  };\n\n  /**\n   * Checks if polygon intersects rectangle\n   * @static\n   * @param {Array} points\n   * @param {fabric.Point} r1\n   * @param {fabric.Point} r2\n   * @return {fabric.Intersection}\n   */\n  fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) {\n    var min = r1.min(r2),\n        max = r1.max(r2),\n        topRight = new fabric.Point(max.x, min.y),\n        bottomLeft = new fabric.Point(min.x, max.y),\n        inter1 = Intersection.intersectLinePolygon(min, topRight, points),\n        inter2 = Intersection.intersectLinePolygon(topRight, max, points),\n        inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points),\n        inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points),\n        result = new Intersection();\n\n    result.appendPoints(inter1.points);\n    result.appendPoints(inter2.points);\n    result.appendPoints(inter3.points);\n    result.appendPoints(inter4.points);\n\n    if (result.points.length > 0) {\n      result.status = 'Intersection';\n    }\n    return result;\n  };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { });\n\n  if (fabric.Color) {\n    fabric.warn('fabric.Color is already defined.');\n    return;\n  }\n\n  /**\n   * Color class\n   * The purpose of {@link fabric.Color} is to abstract and encapsulate common color operations;\n   * {@link fabric.Color} is a constructor and creates instances of {@link fabric.Color} objects.\n   *\n   * @class fabric.Color\n   * @param {String} color optional in hex or rgb(a) or hsl format or from known color list\n   * @return {fabric.Color} thisArg\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#colors}\n   */\n  function Color(color) {\n    if (!color) {\n      this.setSource([0, 0, 0, 1]);\n    }\n    else {\n      this._tryParsingColor(color);\n    }\n  }\n\n  fabric.Color = Color;\n\n  fabric.Color.prototype = /** @lends fabric.Color.prototype */ {\n\n    /**\n     * @private\n     * @param {String|Array} color Color value to parse\n     */\n    _tryParsingColor: function(color) {\n      var source;\n\n      if (color in Color.colorNameMap) {\n        color = Color.colorNameMap[color];\n      }\n\n      if (color === 'transparent') {\n        source = [255, 255, 255, 0];\n      }\n\n      if (!source) {\n        source = Color.sourceFromHex(color);\n      }\n      if (!source) {\n        source = Color.sourceFromRgb(color);\n      }\n      if (!source) {\n        source = Color.sourceFromHsl(color);\n      }\n      if (!source) {\n        //if color is not recognize let's make black as canvas does\n        source = [0, 0, 0, 1];\n      }\n      if (source) {\n        this.setSource(source);\n      }\n    },\n\n    /**\n     * Adapted from <a href=\"https://rawgithub.com/mjijackson/mjijackson.github.com/master/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.html\">https://github.com/mjijackson</a>\n     * @private\n     * @param {Number} r Red color value\n     * @param {Number} g Green color value\n     * @param {Number} b Blue color value\n     * @return {Array} Hsl color\n     */\n    _rgbToHsl: function(r, g, b) {\n      r /= 255; g /= 255; b /= 255;\n\n      var h, s, l,\n          max = fabric.util.array.max([r, g, b]),\n          min = fabric.util.array.min([r, g, b]);\n\n      l = (max + min) / 2;\n\n      if (max === min) {\n        h = s = 0; // achromatic\n      }\n      else {\n        var d = max - min;\n        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n        switch (max) {\n          case r:\n            h = (g - b) / d + (g < b ? 6 : 0);\n            break;\n          case g:\n            h = (b - r) / d + 2;\n            break;\n          case b:\n            h = (r - g) / d + 4;\n            break;\n        }\n        h /= 6;\n      }\n\n      return [\n        Math.round(h * 360),\n        Math.round(s * 100),\n        Math.round(l * 100)\n      ];\n    },\n\n    /**\n     * Returns source of this color (where source is an array representation; ex: [200, 200, 100, 1])\n     * @return {Array}\n     */\n    getSource: function() {\n      return this._source;\n    },\n\n    /**\n     * Sets source of this color (where source is an array representation; ex: [200, 200, 100, 1])\n     * @param {Array} source\n     */\n    setSource: function(source) {\n      this._source = source;\n    },\n\n    /**\n     * Returns color representation in RGB format\n     * @return {String} ex: rgb(0-255,0-255,0-255)\n     */\n    toRgb: function() {\n      var source = this.getSource();\n      return 'rgb(' + source[0] + ',' + source[1] + ',' + source[2] + ')';\n    },\n\n    /**\n     * Returns color representation in RGBA format\n     * @return {String} ex: rgba(0-255,0-255,0-255,0-1)\n     */\n    toRgba: function() {\n      var source = this.getSource();\n      return 'rgba(' + source[0] + ',' + source[1] + ',' + source[2] + ',' + source[3] + ')';\n    },\n\n    /**\n     * Returns color representation in HSL format\n     * @return {String} ex: hsl(0-360,0%-100%,0%-100%)\n     */\n    toHsl: function() {\n      var source = this.getSource(),\n          hsl = this._rgbToHsl(source[0], source[1], source[2]);\n\n      return 'hsl(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%)';\n    },\n\n    /**\n     * Returns color representation in HSLA format\n     * @return {String} ex: hsla(0-360,0%-100%,0%-100%,0-1)\n     */\n    toHsla: function() {\n      var source = this.getSource(),\n          hsl = this._rgbToHsl(source[0], source[1], source[2]);\n\n      return 'hsla(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%,' + source[3] + ')';\n    },\n\n    /**\n     * Returns color representation in HEX format\n     * @return {String} ex: FF5555\n     */\n    toHex: function() {\n      var source = this.getSource(), r, g, b;\n\n      r = source[0].toString(16);\n      r = (r.length === 1) ? ('0' + r) : r;\n\n      g = source[1].toString(16);\n      g = (g.length === 1) ? ('0' + g) : g;\n\n      b = source[2].toString(16);\n      b = (b.length === 1) ? ('0' + b) : b;\n\n      return r.toUpperCase() + g.toUpperCase() + b.toUpperCase();\n    },\n\n    /**\n     * Returns color representation in HEXA format\n     * @return {String} ex: FF5555CC\n     */\n    toHexa: function() {\n      var source = this.getSource(), a;\n\n      a = Math.round(source[3] * 255);\n      a = a.toString(16);\n      a = (a.length === 1) ? ('0' + a) : a;\n\n      return this.toHex() + a.toUpperCase();\n    },\n\n    /**\n     * Gets value of alpha channel for this color\n     * @return {Number} 0-1\n     */\n    getAlpha: function() {\n      return this.getSource()[3];\n    },\n\n    /**\n     * Sets value of alpha channel for this color\n     * @param {Number} alpha Alpha value 0-1\n     * @return {fabric.Color} thisArg\n     */\n    setAlpha: function(alpha) {\n      var source = this.getSource();\n      source[3] = alpha;\n      this.setSource(source);\n      return this;\n    },\n\n    /**\n     * Transforms color to its grayscale representation\n     * @return {fabric.Color} thisArg\n     */\n    toGrayscale: function() {\n      var source = this.getSource(),\n          average = parseInt((source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), 10),\n          currentAlpha = source[3];\n      this.setSource([average, average, average, currentAlpha]);\n      return this;\n    },\n\n    /**\n     * Transforms color to its black and white representation\n     * @param {Number} threshold\n     * @return {fabric.Color} thisArg\n     */\n    toBlackWhite: function(threshold) {\n      var source = this.getSource(),\n          average = (source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0),\n          currentAlpha = source[3];\n\n      threshold = threshold || 127;\n\n      average = (Number(average) < Number(threshold)) ? 0 : 255;\n      this.setSource([average, average, average, currentAlpha]);\n      return this;\n    },\n\n    /**\n     * Overlays color with another color\n     * @param {String|fabric.Color} otherColor\n     * @return {fabric.Color} thisArg\n     */\n    overlayWith: function(otherColor) {\n      if (!(otherColor instanceof Color)) {\n        otherColor = new Color(otherColor);\n      }\n\n      var result = [],\n          alpha = this.getAlpha(),\n          otherAlpha = 0.5,\n          source = this.getSource(),\n          otherSource = otherColor.getSource(), i;\n\n      for (i = 0; i < 3; i++) {\n        result.push(Math.round((source[i] * (1 - otherAlpha)) + (otherSource[i] * otherAlpha)));\n      }\n\n      result[3] = alpha;\n      this.setSource(result);\n      return this;\n    }\n  };\n\n  /**\n   * Regex matching color in RGB or RGBA formats (ex: rgb(0, 0, 0), rgba(255, 100, 10, 0.5), rgba( 255 , 100 , 10 , 0.5 ), rgb(1,1,1), rgba(100%, 60%, 10%, 0.5))\n   * @static\n   * @field\n   * @memberOf fabric.Color\n   */\n  // eslint-disable-next-line max-len\n  fabric.Color.reRGBa = /^rgba?\\(\\s*(\\d{1,3}(?:\\.\\d+)?\\%?)\\s*,\\s*(\\d{1,3}(?:\\.\\d+)?\\%?)\\s*,\\s*(\\d{1,3}(?:\\.\\d+)?\\%?)\\s*(?:\\s*,\\s*((?:\\d*\\.?\\d+)?)\\s*)?\\)$/i;\n\n  /**\n   * Regex matching color in HSL or HSLA formats (ex: hsl(200, 80%, 10%), hsla(300, 50%, 80%, 0.5), hsla( 300 , 50% , 80% , 0.5 ))\n   * @static\n   * @field\n   * @memberOf fabric.Color\n   */\n  fabric.Color.reHSLa = /^hsla?\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3}\\%)\\s*,\\s*(\\d{1,3}\\%)\\s*(?:\\s*,\\s*(\\d+(?:\\.\\d+)?)\\s*)?\\)$/i;\n\n  /**\n   * Regex matching color in HEX format (ex: #FF5544CC, #FF5555, 010155, aff)\n   * @static\n   * @field\n   * @memberOf fabric.Color\n   */\n  fabric.Color.reHex = /^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i;\n\n  /**\n   * Map of the 148 color names with HEX code\n   * @static\n   * @field\n   * @memberOf fabric.Color\n   * @see: https://www.w3.org/TR/css3-color/#svg-color\n   */\n  fabric.Color.colorNameMap = {\n    aliceblue:            '#F0F8FF',\n    antiquewhite:         '#FAEBD7',\n    aqua:                 '#00FFFF',\n    aquamarine:           '#7FFFD4',\n    azure:                '#F0FFFF',\n    beige:                '#F5F5DC',\n    bisque:               '#FFE4C4',\n    black:                '#000000',\n    blanchedalmond:       '#FFEBCD',\n    blue:                 '#0000FF',\n    blueviolet:           '#8A2BE2',\n    brown:                '#A52A2A',\n    burlywood:            '#DEB887',\n    cadetblue:            '#5F9EA0',\n    chartreuse:           '#7FFF00',\n    chocolate:            '#D2691E',\n    coral:                '#FF7F50',\n    cornflowerblue:       '#6495ED',\n    cornsilk:             '#FFF8DC',\n    crimson:              '#DC143C',\n    cyan:                 '#00FFFF',\n    darkblue:             '#00008B',\n    darkcyan:             '#008B8B',\n    darkgoldenrod:        '#B8860B',\n    darkgray:             '#A9A9A9',\n    darkgrey:             '#A9A9A9',\n    darkgreen:            '#006400',\n    darkkhaki:            '#BDB76B',\n    darkmagenta:          '#8B008B',\n    darkolivegreen:       '#556B2F',\n    darkorange:           '#FF8C00',\n    darkorchid:           '#9932CC',\n    darkred:              '#8B0000',\n    darksalmon:           '#E9967A',\n    darkseagreen:         '#8FBC8F',\n    darkslateblue:        '#483D8B',\n    darkslategray:        '#2F4F4F',\n    darkslategrey:        '#2F4F4F',\n    darkturquoise:        '#00CED1',\n    darkviolet:           '#9400D3',\n    deeppink:             '#FF1493',\n    deepskyblue:          '#00BFFF',\n    dimgray:              '#696969',\n    dimgrey:              '#696969',\n    dodgerblue:           '#1E90FF',\n    firebrick:            '#B22222',\n    floralwhite:          '#FFFAF0',\n    forestgreen:          '#228B22',\n    fuchsia:              '#FF00FF',\n    gainsboro:            '#DCDCDC',\n    ghostwhite:           '#F8F8FF',\n    gold:                 '#FFD700',\n    goldenrod:            '#DAA520',\n    gray:                 '#808080',\n    grey:                 '#808080',\n    green:                '#008000',\n    greenyellow:          '#ADFF2F',\n    honeydew:             '#F0FFF0',\n    hotpink:              '#FF69B4',\n    indianred:            '#CD5C5C',\n    indigo:               '#4B0082',\n    ivory:                '#FFFFF0',\n    khaki:                '#F0E68C',\n    lavender:             '#E6E6FA',\n    lavenderblush:        '#FFF0F5',\n    lawngreen:            '#7CFC00',\n    lemonchiffon:         '#FFFACD',\n    lightblue:            '#ADD8E6',\n    lightcoral:           '#F08080',\n    lightcyan:            '#E0FFFF',\n    lightgoldenrodyellow: '#FAFAD2',\n    lightgray:            '#D3D3D3',\n    lightgrey:            '#D3D3D3',\n    lightgreen:           '#90EE90',\n    lightpink:            '#FFB6C1',\n    lightsalmon:          '#FFA07A',\n    lightseagreen:        '#20B2AA',\n    lightskyblue:         '#87CEFA',\n    lightslategray:       '#778899',\n    lightslategrey:       '#778899',\n    lightsteelblue:       '#B0C4DE',\n    lightyellow:          '#FFFFE0',\n    lime:                 '#00FF00',\n    limegreen:            '#32CD32',\n    linen:                '#FAF0E6',\n    magenta:              '#FF00FF',\n    maroon:               '#800000',\n    mediumaquamarine:     '#66CDAA',\n    mediumblue:           '#0000CD',\n    mediumorchid:         '#BA55D3',\n    mediumpurple:         '#9370DB',\n    mediumseagreen:       '#3CB371',\n    mediumslateblue:      '#7B68EE',\n    mediumspringgreen:    '#00FA9A',\n    mediumturquoise:      '#48D1CC',\n    mediumvioletred:      '#C71585',\n    midnightblue:         '#191970',\n    mintcream:            '#F5FFFA',\n    mistyrose:            '#FFE4E1',\n    moccasin:             '#FFE4B5',\n    navajowhite:          '#FFDEAD',\n    navy:                 '#000080',\n    oldlace:              '#FDF5E6',\n    olive:                '#808000',\n    olivedrab:            '#6B8E23',\n    orange:               '#FFA500',\n    orangered:            '#FF4500',\n    orchid:               '#DA70D6',\n    palegoldenrod:        '#EEE8AA',\n    palegreen:            '#98FB98',\n    paleturquoise:        '#AFEEEE',\n    palevioletred:        '#DB7093',\n    papayawhip:           '#FFEFD5',\n    peachpuff:            '#FFDAB9',\n    peru:                 '#CD853F',\n    pink:                 '#FFC0CB',\n    plum:                 '#DDA0DD',\n    powderblue:           '#B0E0E6',\n    purple:               '#800080',\n    rebeccapurple:        '#663399',\n    red:                  '#FF0000',\n    rosybrown:            '#BC8F8F',\n    royalblue:            '#4169E1',\n    saddlebrown:          '#8B4513',\n    salmon:               '#FA8072',\n    sandybrown:           '#F4A460',\n    seagreen:             '#2E8B57',\n    seashell:             '#FFF5EE',\n    sienna:               '#A0522D',\n    silver:               '#C0C0C0',\n    skyblue:              '#87CEEB',\n    slateblue:            '#6A5ACD',\n    slategray:            '#708090',\n    slategrey:            '#708090',\n    snow:                 '#FFFAFA',\n    springgreen:          '#00FF7F',\n    steelblue:            '#4682B4',\n    tan:                  '#D2B48C',\n    teal:                 '#008080',\n    thistle:              '#D8BFD8',\n    tomato:               '#FF6347',\n    turquoise:            '#40E0D0',\n    violet:               '#EE82EE',\n    wheat:                '#F5DEB3',\n    white:                '#FFFFFF',\n    whitesmoke:           '#F5F5F5',\n    yellow:               '#FFFF00',\n    yellowgreen:          '#9ACD32'\n  };\n\n  /**\n   * @private\n   * @param {Number} p\n   * @param {Number} q\n   * @param {Number} t\n   * @return {Number}\n   */\n  function hue2rgb(p, q, t) {\n    if (t < 0) {\n      t += 1;\n    }\n    if (t > 1) {\n      t -= 1;\n    }\n    if (t < 1 / 6) {\n      return p + (q - p) * 6 * t;\n    }\n    if (t < 1 / 2) {\n      return q;\n    }\n    if (t < 2 / 3) {\n      return p + (q - p) * (2 / 3 - t) * 6;\n    }\n    return p;\n  }\n\n  /**\n   * Returns new color object, when given a color in RGB format\n   * @memberOf fabric.Color\n   * @param {String} color Color value ex: rgb(0-255,0-255,0-255)\n   * @return {fabric.Color}\n   */\n  fabric.Color.fromRgb = function(color) {\n    return Color.fromSource(Color.sourceFromRgb(color));\n  };\n\n  /**\n   * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format\n   * @memberOf fabric.Color\n   * @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%)\n   * @return {Array} source\n   */\n  fabric.Color.sourceFromRgb = function(color) {\n    var match = color.match(Color.reRGBa);\n    if (match) {\n      var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1),\n          g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1),\n          b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1);\n\n      return [\n        parseInt(r, 10),\n        parseInt(g, 10),\n        parseInt(b, 10),\n        match[4] ? parseFloat(match[4]) : 1\n      ];\n    }\n  };\n\n  /**\n   * Returns new color object, when given a color in RGBA format\n   * @static\n   * @function\n   * @memberOf fabric.Color\n   * @param {String} color\n   * @return {fabric.Color}\n   */\n  fabric.Color.fromRgba = Color.fromRgb;\n\n  /**\n   * Returns new color object, when given a color in HSL format\n   * @param {String} color Color value ex: hsl(0-260,0%-100%,0%-100%)\n   * @memberOf fabric.Color\n   * @return {fabric.Color}\n   */\n  fabric.Color.fromHsl = function(color) {\n    return Color.fromSource(Color.sourceFromHsl(color));\n  };\n\n  /**\n   * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format.\n   * Adapted from <a href=\"https://rawgithub.com/mjijackson/mjijackson.github.com/master/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.html\">https://github.com/mjijackson</a>\n   * @memberOf fabric.Color\n   * @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1)\n   * @return {Array} source\n   * @see http://http://www.w3.org/TR/css3-color/#hsl-color\n   */\n  fabric.Color.sourceFromHsl = function(color) {\n    var match = color.match(Color.reHSLa);\n    if (!match) {\n      return;\n    }\n\n    var h = (((parseFloat(match[1]) % 360) + 360) % 360) / 360,\n        s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1),\n        l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1),\n        r, g, b;\n\n    if (s === 0) {\n      r = g = b = l;\n    }\n    else {\n      var q = l <= 0.5 ? l * (s + 1) : l + s - l * s,\n          p = l * 2 - q;\n\n      r = hue2rgb(p, q, h + 1 / 3);\n      g = hue2rgb(p, q, h);\n      b = hue2rgb(p, q, h - 1 / 3);\n    }\n\n    return [\n      Math.round(r * 255),\n      Math.round(g * 255),\n      Math.round(b * 255),\n      match[4] ? parseFloat(match[4]) : 1\n    ];\n  };\n\n  /**\n   * Returns new color object, when given a color in HSLA format\n   * @static\n   * @function\n   * @memberOf fabric.Color\n   * @param {String} color\n   * @return {fabric.Color}\n   */\n  fabric.Color.fromHsla = Color.fromHsl;\n\n  /**\n   * Returns new color object, when given a color in HEX format\n   * @static\n   * @memberOf fabric.Color\n   * @param {String} color Color value ex: FF5555\n   * @return {fabric.Color}\n   */\n  fabric.Color.fromHex = function(color) {\n    return Color.fromSource(Color.sourceFromHex(color));\n  };\n\n  /**\n   * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HEX format\n   * @static\n   * @memberOf fabric.Color\n   * @param {String} color ex: FF5555 or FF5544CC (RGBa)\n   * @return {Array} source\n   */\n  fabric.Color.sourceFromHex = function(color) {\n    if (color.match(Color.reHex)) {\n      var value = color.slice(color.indexOf('#') + 1),\n          isShortNotation = (value.length === 3 || value.length === 4),\n          isRGBa = (value.length === 8 || value.length === 4),\n          r = isShortNotation ? (value.charAt(0) + value.charAt(0)) : value.substring(0, 2),\n          g = isShortNotation ? (value.charAt(1) + value.charAt(1)) : value.substring(2, 4),\n          b = isShortNotation ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6),\n          a = isRGBa ? (isShortNotation ? (value.charAt(3) + value.charAt(3)) : value.substring(6, 8)) : 'FF';\n\n      return [\n        parseInt(r, 16),\n        parseInt(g, 16),\n        parseInt(b, 16),\n        parseFloat((parseInt(a, 16) / 255).toFixed(2))\n      ];\n    }\n  };\n\n  /**\n   * Returns new color object, when given color in array representation (ex: [200, 100, 100, 0.5])\n   * @static\n   * @memberOf fabric.Color\n   * @param {Array} source\n   * @return {fabric.Color}\n   */\n  fabric.Color.fromSource = function(source) {\n    var oColor = new Color();\n    oColor.setSource(source);\n    return oColor;\n  };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { }),\n      scaleMap = ['e', 'se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e'],\n      skewMap = ['ns', 'nesw', 'ew', 'nwse'],\n      controls = {},\n      LEFT = 'left', TOP = 'top', RIGHT = 'right', BOTTOM = 'bottom', CENTER = 'center',\n      opposite = {\n        top: BOTTOM,\n        bottom: TOP,\n        left: RIGHT,\n        right: LEFT,\n        center: CENTER,\n      }, radiansToDegrees = fabric.util.radiansToDegrees,\n      sign = (Math.sign || function(x) { return ((x > 0) - (x < 0)) || +x; });\n\n  /**\n   * Combine control position and object angle to find the control direction compared\n   * to the object center.\n   * @param {fabric.Object} fabricObject the fabric object for which we are rendering controls\n   * @param {fabric.Control} control the control class\n   * @return {Number} 0 - 7 a quadrant number\n   */\n  function findCornerQuadrant(fabricObject, control) {\n    var cornerAngle = fabricObject.angle + radiansToDegrees(Math.atan2(control.y, control.x)) + 360;\n    return Math.round((cornerAngle % 360) / 45);\n  }\n\n  function fireEvent(eventName, options) {\n    var target = options.transform.target,\n        canvas = target.canvas,\n        canvasOptions = fabric.util.object.clone(options);\n    canvasOptions.target = target;\n    canvas && canvas.fire('object:' + eventName, canvasOptions);\n    target.fire(eventName, options);\n  }\n\n  /**\n   * Inspect event and fabricObject properties to understand if the scaling action\n   * @param {Event} eventData from the user action\n   * @param {fabric.Object} fabricObject the fabric object about to scale\n   * @return {Boolean} true if scale is proportional\n   */\n  function scaleIsProportional(eventData, fabricObject) {\n    var canvas = fabricObject.canvas, uniScaleKey = canvas.uniScaleKey,\n        uniformIsToggled = eventData[uniScaleKey];\n    return (canvas.uniformScaling && !uniformIsToggled) ||\n    (!canvas.uniformScaling && uniformIsToggled);\n  }\n\n  /**\n   * Checks if transform is centered\n   * @param {Object} transform transform data\n   * @return {Boolean} true if transform is centered\n   */\n  function isTransformCentered(transform) {\n    return transform.originX === CENTER && transform.originY === CENTER;\n  }\n\n  /**\n   * Inspect fabricObject to understand if the current scaling action is allowed\n   * @param {fabric.Object} fabricObject the fabric object about to scale\n   * @param {String} by 'x' or 'y' or ''\n   * @param {Boolean} scaleProportionally true if we are trying to scale proportionally\n   * @return {Boolean} true if scaling is not allowed at current conditions\n   */\n  function scalingIsForbidden(fabricObject, by, scaleProportionally) {\n    var lockX = fabricObject.lockScalingX, lockY = fabricObject.lockScalingY;\n    if (lockX && lockY) {\n      return true;\n    }\n    if (!by && (lockX || lockY) && scaleProportionally) {\n      return true;\n    }\n    if (lockX && by === 'x') {\n      return true;\n    }\n    if (lockY && by === 'y') {\n      return true;\n    }\n    return false;\n  }\n\n  /**\n   * return the correct cursor style for the scale action\n   * @param {Event} eventData the javascript event that is causing the scale\n   * @param {fabric.Control} control the control that is interested in the action\n   * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n   * @return {String} a valid css string for the cursor\n   */\n  function scaleCursorStyleHandler(eventData, control, fabricObject) {\n    var notAllowed = 'not-allowed',\n        scaleProportionally = scaleIsProportional(eventData, fabricObject),\n        by = '';\n    if (control.x !== 0 && control.y === 0) {\n      by = 'x';\n    }\n    else if (control.x === 0 && control.y !== 0) {\n      by = 'y';\n    }\n    if (scalingIsForbidden(fabricObject, by, scaleProportionally)) {\n      return notAllowed;\n    }\n    var n = findCornerQuadrant(fabricObject, control);\n    return scaleMap[n] + '-resize';\n  }\n\n  /**\n   * return the correct cursor style for the skew action\n   * @param {Event} eventData the javascript event that is causing the scale\n   * @param {fabric.Control} control the control that is interested in the action\n   * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n   * @return {String} a valid css string for the cursor\n   */\n  function skewCursorStyleHandler(eventData, control, fabricObject) {\n    var notAllowed = 'not-allowed';\n    if (control.x !== 0 && fabricObject.lockSkewingY) {\n      return notAllowed;\n    }\n    if (control.y !== 0 && fabricObject.lockSkewingX) {\n      return notAllowed;\n    }\n    var n = findCornerQuadrant(fabricObject, control) % 4;\n    return skewMap[n] + '-resize';\n  }\n\n  /**\n   * Combine skew and scale style handlers to cover fabric standard use case\n   * @param {Event} eventData the javascript event that is causing the scale\n   * @param {fabric.Control} control the control that is interested in the action\n   * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n   * @return {String} a valid css string for the cursor\n   */\n  function scaleSkewCursorStyleHandler(eventData, control, fabricObject) {\n    if (eventData[fabricObject.canvas.altActionKey]) {\n      return controls.skewCursorStyleHandler(eventData, control, fabricObject);\n    }\n    return controls.scaleCursorStyleHandler(eventData, control, fabricObject);\n  }\n\n  /**\n   * Inspect event, control and fabricObject to return the correct action name\n   * @param {Event} eventData the javascript event that is causing the scale\n   * @param {fabric.Control} control the control that is interested in the action\n   * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n   * @return {String} an action name\n   */\n  function scaleOrSkewActionName(eventData, control, fabricObject) {\n    var isAlternative = eventData[fabricObject.canvas.altActionKey];\n    if (control.x === 0) {\n      // then is scaleY or skewX\n      return isAlternative ? 'skewX' : 'scaleY';\n    }\n    if (control.y === 0) {\n      // then is scaleY or skewX\n      return isAlternative ? 'skewY' : 'scaleX';\n    }\n  }\n\n  /**\n   * Find the correct style for the control that is used for rotation.\n   * this function is very simple and it just take care of not-allowed or standard cursor\n   * @param {Event} eventData the javascript event that is causing the scale\n   * @param {fabric.Control} control the control that is interested in the action\n   * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n   * @return {String} a valid css string for the cursor\n   */\n  function rotationStyleHandler(eventData, control, fabricObject) {\n    if (fabricObject.lockRotation) {\n      return 'not-allowed';\n    }\n    return control.cursorStyle;\n  }\n\n  function commonEventInfo(eventData, transform, x, y) {\n    return {\n      e: eventData,\n      transform: transform,\n      pointer: {\n        x: x,\n        y: y,\n      }\n    };\n  }\n\n  /**\n   * Wrap an action handler with saving/restoring object position on the transform.\n   * this is the code that permits to objects to keep their position while transforming.\n   * @param {Function} actionHandler the function to wrap\n   * @return {Function} a function with an action handler signature\n   */\n  function wrapWithFixedAnchor(actionHandler) {\n    return function(eventData, transform, x, y) {\n      var target = transform.target, centerPoint = target.getCenterPoint(),\n          constraint = target.translateToOriginPoint(centerPoint, transform.originX, transform.originY),\n          actionPerformed = actionHandler(eventData, transform, x, y);\n      target.setPositionByOrigin(constraint, transform.originX, transform.originY);\n      return actionPerformed;\n    };\n  }\n\n  /**\n   * Transforms a point described by x and y in a distance from the top left corner of the object\n   * bounding box.\n   * @param {Object} transform\n   * @param {String} originX\n   * @param {String} originY\n   * @param {number} x\n   * @param {number} y\n   * @return {Fabric.Point} the normalized point\n   */\n  function getLocalPoint(transform, originX, originY, x, y) {\n    var target = transform.target,\n        control = target.controls[transform.corner],\n        zoom = target.canvas.getZoom(),\n        padding = target.padding / zoom,\n        localPoint = target.toLocalPoint(new fabric.Point(x, y), originX, originY);\n    if (localPoint.x >= padding) {\n      localPoint.x -= padding;\n    }\n    if (localPoint.x <= -padding) {\n      localPoint.x += padding;\n    }\n    if (localPoint.y >= padding) {\n      localPoint.y -= padding;\n    }\n    if (localPoint.y <= padding) {\n      localPoint.y += padding;\n    }\n    localPoint.x -= control.offsetX;\n    localPoint.y -= control.offsetY;\n    return localPoint;\n  }\n\n  /**\n   * Detect if the fabric object is flipped on one side.\n   * @param {fabric.Object} target\n   * @return {Boolean} true if one flip, but not two.\n   */\n  function targetHasOneFlip(target) {\n    return (target.flipX && !target.flipY) || (!target.flipX && target.flipY);\n  }\n\n  /**\n   * Utility function to compensate the scale factor when skew is applied on both axes\n   * @private\n   */\n  function compensateScaleForSkew(target, oppositeSkew, scaleToCompensate, axis, reference) {\n    if (target[oppositeSkew] !== 0) {\n      var newDim = target._getTransformedDimensions()[axis];\n      var newValue = reference / newDim * target[scaleToCompensate];\n      target.set(scaleToCompensate, newValue);\n    }\n  }\n\n  /**\n   * Action handler for skewing on the X axis\n   * @private\n   */\n  function skewObjectX(eventData, transform, x, y) {\n    var target = transform.target,\n        // find how big the object would be, if there was no skewX. takes in account scaling\n        dimNoSkew = target._getTransformedDimensions(0, target.skewY),\n        localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y),\n        // the mouse is in the center of the object, and we want it to stay there.\n        // so the object will grow twice as much as the mouse.\n        // this makes the skew growth to localPoint * 2 - dimNoSkew.\n        totalSkewSize = Math.abs(localPoint.x * 2) - dimNoSkew.x,\n        currentSkew = target.skewX, newSkew;\n    if (totalSkewSize < 2) {\n      // let's make it easy to go back to position 0.\n      newSkew = 0;\n    }\n    else {\n      newSkew = radiansToDegrees(\n        Math.atan2((totalSkewSize / target.scaleX), (dimNoSkew.y / target.scaleY))\n      );\n      // now we have to find the sign of the skew.\n      // it mostly depend on the origin of transformation.\n      if (transform.originX === LEFT && transform.originY === BOTTOM) {\n        newSkew = -newSkew;\n      }\n      if (transform.originX === RIGHT && transform.originY === TOP) {\n        newSkew = -newSkew;\n      }\n      if (targetHasOneFlip(target)) {\n        newSkew = -newSkew;\n      }\n    }\n    var hasSkewed = currentSkew !== newSkew;\n    if (hasSkewed) {\n      var dimBeforeSkewing = target._getTransformedDimensions().y;\n      target.set('skewX', newSkew);\n      compensateScaleForSkew(target, 'skewY', 'scaleY', 'y', dimBeforeSkewing);\n      fireEvent('skewing', commonEventInfo(eventData, transform, x, y));\n    }\n    return hasSkewed;\n  }\n\n  /**\n   * Action handler for skewing on the Y axis\n   * @private\n   */\n  function skewObjectY(eventData, transform, x, y) {\n    var target = transform.target,\n        // find how big the object would be, if there was no skewX. takes in account scaling\n        dimNoSkew = target._getTransformedDimensions(target.skewX, 0),\n        localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y),\n        // the mouse is in the center of the object, and we want it to stay there.\n        // so the object will grow twice as much as the mouse.\n        // this makes the skew growth to localPoint * 2 - dimNoSkew.\n        totalSkewSize = Math.abs(localPoint.y * 2) - dimNoSkew.y,\n        currentSkew = target.skewY, newSkew;\n    if (totalSkewSize < 2) {\n      // let's make it easy to go back to position 0.\n      newSkew = 0;\n    }\n    else {\n      newSkew = radiansToDegrees(\n        Math.atan2((totalSkewSize / target.scaleY), (dimNoSkew.x / target.scaleX))\n      );\n      // now we have to find the sign of the skew.\n      // it mostly depend on the origin of transformation.\n      if (transform.originX === LEFT && transform.originY === BOTTOM) {\n        newSkew = -newSkew;\n      }\n      if (transform.originX === RIGHT && transform.originY === TOP) {\n        newSkew = -newSkew;\n      }\n      if (targetHasOneFlip(target)) {\n        newSkew = -newSkew;\n      }\n    }\n    var hasSkewed = currentSkew !== newSkew;\n    if (hasSkewed) {\n      var dimBeforeSkewing = target._getTransformedDimensions().x;\n      target.set('skewY', newSkew);\n      compensateScaleForSkew(target, 'skewX', 'scaleX', 'x', dimBeforeSkewing);\n      fireEvent('skewing', commonEventInfo(eventData, transform, x, y));\n    }\n    return hasSkewed;\n  }\n\n  /**\n   * Wrapped Action handler for skewing on the Y axis, takes care of the\n   * skew direction and determine the correct transform origin for the anchor point\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n  function skewHandlerX(eventData, transform, x, y) {\n    // step1 figure out and change transform origin.\n    // if skewX > 0 and originY bottom we anchor on right\n    // if skewX > 0 and originY top we anchor on left\n    // if skewX < 0 and originY bottom we anchor on left\n    // if skewX < 0 and originY top we anchor on right\n    // if skewX is 0, we look for mouse position to understand where are we going.\n    var target = transform.target, currentSkew = target.skewX, originX, originY = transform.originY;\n    if (target.lockSkewingX) {\n      return false;\n    }\n    if (currentSkew === 0) {\n      var localPointFromCenter = getLocalPoint(transform, CENTER, CENTER, x, y);\n      if (localPointFromCenter.x > 0) {\n        // we are pulling right, anchor left;\n        originX = LEFT;\n      }\n      else {\n        // we are pulling right, anchor right\n        originX = RIGHT;\n      }\n    }\n    else {\n      if (currentSkew > 0) {\n        originX = originY === TOP ? LEFT : RIGHT;\n      }\n      if (currentSkew < 0) {\n        originX = originY === TOP ? RIGHT : LEFT;\n      }\n      // is the object flipped on one side only? swap the origin.\n      if (targetHasOneFlip(target)) {\n        originX = originX === LEFT ? RIGHT : LEFT;\n      }\n    }\n\n    // once we have the origin, we find the anchor point\n    transform.originX = originX;\n    var finalHandler = wrapWithFixedAnchor(skewObjectX);\n    return finalHandler(eventData, transform, x, y);\n  }\n\n  /**\n   * Wrapped Action handler for skewing on the Y axis, takes care of the\n   * skew direction and determine the correct transform origin for the anchor point\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n  function skewHandlerY(eventData, transform, x, y) {\n    // step1 figure out and change transform origin.\n    // if skewY > 0 and originX left we anchor on top\n    // if skewY > 0 and originX right we anchor on bottom\n    // if skewY < 0 and originX left we anchor on bottom\n    // if skewY < 0 and originX right we anchor on top\n    // if skewY is 0, we look for mouse position to understand where are we going.\n    var target = transform.target, currentSkew = target.skewY, originY, originX = transform.originX;\n    if (target.lockSkewingY) {\n      return false;\n    }\n    if (currentSkew === 0) {\n      var localPointFromCenter = getLocalPoint(transform, CENTER, CENTER, x, y);\n      if (localPointFromCenter.y > 0) {\n        // we are pulling down, anchor up;\n        originY = TOP;\n      }\n      else {\n        // we are pulling up, anchor down\n        originY = BOTTOM;\n      }\n    }\n    else {\n      if (currentSkew > 0) {\n        originY = originX === LEFT ? TOP : BOTTOM;\n      }\n      if (currentSkew < 0) {\n        originY = originX === LEFT ? BOTTOM : TOP;\n      }\n      // is the object flipped on one side only? swap the origin.\n      if (targetHasOneFlip(target)) {\n        originY = originY === TOP ? BOTTOM : TOP;\n      }\n    }\n\n    // once we have the origin, we find the anchor point\n    transform.originY = originY;\n    var finalHandler = wrapWithFixedAnchor(skewObjectY);\n    return finalHandler(eventData, transform, x, y);\n  }\n\n  /**\n   * Action handler for rotation and snapping, without anchor point.\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   * @private\n   */\n  function rotationWithSnapping(eventData, transform, x, y) {\n    var t = transform,\n        target = t.target,\n        pivotPoint = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY);\n\n    if (target.lockRotation) {\n      return false;\n    }\n\n    var lastAngle = Math.atan2(t.ey - pivotPoint.y, t.ex - pivotPoint.x),\n        curAngle = Math.atan2(y - pivotPoint.y, x - pivotPoint.x),\n        angle = radiansToDegrees(curAngle - lastAngle + t.theta),\n        hasRotated = true;\n\n    if (target.snapAngle > 0) {\n      var snapAngle  = target.snapAngle,\n          snapThreshold  = target.snapThreshold || snapAngle,\n          rightAngleLocked = Math.ceil(angle / snapAngle) * snapAngle,\n          leftAngleLocked = Math.floor(angle / snapAngle) * snapAngle;\n\n      if (Math.abs(angle - leftAngleLocked) < snapThreshold) {\n        angle = leftAngleLocked;\n      }\n      else if (Math.abs(angle - rightAngleLocked) < snapThreshold) {\n        angle = rightAngleLocked;\n      }\n    }\n\n    // normalize angle to positive value\n    if (angle < 0) {\n      angle = 360 + angle;\n    }\n    angle %= 360;\n\n    hasRotated = target.angle !== angle;\n    target.angle = angle;\n    if (hasRotated) {\n      fireEvent('rotating', commonEventInfo(eventData, transform, x, y));\n    }\n    return hasRotated;\n  }\n\n  /**\n   * Basic scaling logic, reused with different constrain for scaling X,Y, freely or equally.\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @param {Object} options additional information for scaling\n   * @param {String} options.by 'x', 'y', 'equally' or '' to indicate type of scaling\n   * @return {Boolean} true if some change happened\n   * @private\n   */\n  function scaleObject(eventData, transform, x, y, options) {\n    options = options || {};\n    var target = transform.target,\n        lockScalingX = target.lockScalingX, lockScalingY = target.lockScalingY,\n        by = options.by, newPoint, scaleX, scaleY, dim,\n        scaleProportionally = scaleIsProportional(eventData, target),\n        forbidScaling = scalingIsForbidden(target, by, scaleProportionally),\n        signX, signY, gestureScale = transform.gestureScale;\n\n    if (forbidScaling) {\n      return false;\n    }\n    if (gestureScale) {\n      scaleX = transform.scaleX * gestureScale;\n      scaleY = transform.scaleY * gestureScale;\n    }\n    else {\n      newPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y);\n      // use of sign: We use sign to detect change of direction of an action. sign usually change when\n      // we cross the origin point with the mouse. So a scale flip for example. There is an issue when scaling\n      // by center and scaling using one middle control ( default: mr, mt, ml, mb), the mouse movement can easily\n      // cross many time the origin point and flip the object. so we need a way to filter out the noise.\n      // This ternary here should be ok to filter out X scaling when we want Y only and vice versa.\n      signX = by !== 'y' ? sign(newPoint.x) : 1;\n      signY = by !== 'x' ? sign(newPoint.y) : 1;\n      if (!transform.signX) {\n        transform.signX = signX;\n      }\n      if (!transform.signY) {\n        transform.signY = signY;\n      }\n\n      if (target.lockScalingFlip &&\n        (transform.signX !== signX || transform.signY !== signY)\n      ) {\n        return false;\n      }\n\n      dim = target._getTransformedDimensions();\n      // missing detection of flip and logic to switch the origin\n      if (scaleProportionally && !by) {\n        // uniform scaling\n        var distance = Math.abs(newPoint.x) + Math.abs(newPoint.y),\n            original = transform.original,\n            originalDistance = Math.abs(dim.x * original.scaleX / target.scaleX) +\n              Math.abs(dim.y * original.scaleY / target.scaleY),\n            scale = distance / originalDistance, hasScaled;\n        scaleX = original.scaleX * scale;\n        scaleY = original.scaleY * scale;\n      }\n      else {\n        scaleX = Math.abs(newPoint.x * target.scaleX / dim.x);\n        scaleY = Math.abs(newPoint.y * target.scaleY / dim.y);\n      }\n      // if we are scaling by center, we need to double the scale\n      if (isTransformCentered(transform)) {\n        scaleX *= 2;\n        scaleY *= 2;\n      }\n      if (transform.signX !== signX && by !== 'y') {\n        transform.originX = opposite[transform.originX];\n        scaleX *= -1;\n        transform.signX = signX;\n      }\n      if (transform.signY !== signY && by !== 'x') {\n        transform.originY = opposite[transform.originY];\n        scaleY *= -1;\n        transform.signY = signY;\n      }\n    }\n    // minScale is taken are in the setter.\n    var oldScaleX = target.scaleX, oldScaleY = target.scaleY;\n    if (!by) {\n      !lockScalingX && target.set('scaleX', scaleX);\n      !lockScalingY && target.set('scaleY', scaleY);\n    }\n    else {\n      // forbidden cases already handled on top here.\n      by === 'x' && target.set('scaleX', scaleX);\n      by === 'y' && target.set('scaleY', scaleY);\n    }\n    hasScaled = oldScaleX !== target.scaleX || oldScaleY !== target.scaleY;\n    if (hasScaled) {\n      fireEvent('scaling', commonEventInfo(eventData, transform, x, y));\n    }\n    return hasScaled;\n  }\n\n  /**\n   * Generic scaling logic, to scale from corners either equally or freely.\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n  function scaleObjectFromCorner(eventData, transform, x, y) {\n    return scaleObject(eventData, transform, x, y);\n  }\n\n  /**\n   * Scaling logic for the X axis.\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n  function scaleObjectX(eventData, transform, x, y) {\n    return scaleObject(eventData, transform, x, y , { by: 'x' });\n  }\n\n  /**\n   * Scaling logic for the Y axis.\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n  function scaleObjectY(eventData, transform, x, y) {\n    return scaleObject(eventData, transform, x, y , { by: 'y' });\n  }\n\n  /**\n   * Composed action handler to either scale Y or skew X\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n  function scalingYOrSkewingX(eventData, transform, x, y) {\n    // ok some safety needed here.\n    if (eventData[transform.target.canvas.altActionKey]) {\n      return controls.skewHandlerX(eventData, transform, x, y);\n    }\n    return controls.scalingY(eventData, transform, x, y);\n  }\n\n  /**\n   * Composed action handler to either scale X or skew Y\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n  function scalingXOrSkewingY(eventData, transform, x, y) {\n    // ok some safety needed here.\n    if (eventData[transform.target.canvas.altActionKey]) {\n      return controls.skewHandlerY(eventData, transform, x, y);\n    }\n    return controls.scalingX(eventData, transform, x, y);\n  }\n\n  /**\n   * Action handler to change textbox width\n   * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if some change happened\n   */\n  function changeWidth(eventData, transform, x, y) {\n    var target = transform.target, localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y),\n        strokePadding = target.strokeWidth / (target.strokeUniform ? target.scaleX : 1),\n        multiplier = isTransformCentered(transform) ? 2 : 1,\n        oldWidth = target.width, hasResized,\n        newWidth = Math.abs(localPoint.x * multiplier / target.scaleX) - strokePadding;\n    target.set('width', Math.max(newWidth, 0));\n    hasResized = oldWidth !== newWidth;\n    if (hasResized) {\n      fireEvent('resizing', commonEventInfo(eventData, transform, x, y));\n    }\n    return hasResized;\n  }\n\n  /**\n   * Action handler\n   * @private\n   * @param {Event} eventData javascript event that is doing the transform\n   * @param {Object} transform javascript object containing a series of information around the current transform\n   * @param {number} x current mouse x position, canvas normalized\n   * @param {number} y current mouse y position, canvas normalized\n   * @return {Boolean} true if the translation occurred\n   */\n  function dragHandler(eventData, transform, x, y) {\n    var target = transform.target,\n        newLeft = x - transform.offsetX,\n        newTop = y - transform.offsetY,\n        moveX = !target.get('lockMovementX') && target.left !== newLeft,\n        moveY = !target.get('lockMovementY') && target.top !== newTop;\n    moveX && target.set('left', newLeft);\n    moveY && target.set('top', newTop);\n    if (moveX || moveY) {\n      fireEvent('moving', commonEventInfo(eventData, transform, x, y));\n    }\n    return moveX || moveY;\n  }\n\n  controls.scaleCursorStyleHandler = scaleCursorStyleHandler;\n  controls.skewCursorStyleHandler = skewCursorStyleHandler;\n  controls.scaleSkewCursorStyleHandler = scaleSkewCursorStyleHandler;\n  controls.rotationWithSnapping = wrapWithFixedAnchor(rotationWithSnapping);\n  controls.scalingEqually = wrapWithFixedAnchor(scaleObjectFromCorner);\n  controls.scalingX = wrapWithFixedAnchor(scaleObjectX);\n  controls.scalingY = wrapWithFixedAnchor(scaleObjectY);\n  controls.scalingYOrSkewingX = scalingYOrSkewingX;\n  controls.scalingXOrSkewingY = scalingXOrSkewingY;\n  controls.changeWidth = wrapWithFixedAnchor(changeWidth);\n  controls.skewHandlerX = skewHandlerX;\n  controls.skewHandlerY = skewHandlerY;\n  controls.dragHandler = dragHandler;\n  controls.scaleOrSkewActionName = scaleOrSkewActionName;\n  controls.rotationStyleHandler = rotationStyleHandler;\n  controls.fireEvent = fireEvent;\n  controls.wrapWithFixedAnchor = wrapWithFixedAnchor;\n  controls.getLocalPoint = getLocalPoint;\n  fabric.controlsUtils = controls;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { }),\n      degreesToRadians = fabric.util.degreesToRadians,\n      controls = fabric.controlsUtils;\n\n  /**\n   * Render a round control, as per fabric features.\n   * This function is written to respect object properties like transparentCorners, cornerSize\n   * cornerColor, cornerStrokeColor\n   * plus the addition of offsetY and offsetX.\n   * @param {CanvasRenderingContext2D} ctx context to render on\n   * @param {Number} left x coordinate where the control center should be\n   * @param {Number} top y coordinate where the control center should be\n   * @param {Object} styleOverride override for fabric.Object controls style\n   * @param {fabric.Object} fabricObject the fabric object for which we are rendering controls\n   */\n  function renderCircleControl (ctx, left, top, styleOverride, fabricObject) {\n    styleOverride = styleOverride || {};\n    var size = styleOverride.cornerSize || fabricObject.cornerSize,\n        transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ?\n          styleOverride.transparentCorners : this.transparentCorners,\n        methodName = transparentCorners ? 'stroke' : 'fill',\n        stroke = !transparentCorners && (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor);\n    ctx.save();\n    ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor;\n    ctx.strokeStyle = styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor;\n    // this is still wrong\n    ctx.lineWidth = 1;\n    ctx.beginPath();\n    ctx.arc(left, top, size / 2, 0, 2 * Math.PI, false);\n    ctx[methodName]();\n    if (stroke) {\n      ctx.stroke();\n    }\n    ctx.restore();\n  }\n\n  /**\n   * Render a square control, as per fabric features.\n   * This function is written to respect object properties like transparentCorners, cornerSize\n   * cornerColor, cornerStrokeColor\n   * plus the addition of offsetY and offsetX.\n   * @param {CanvasRenderingContext2D} ctx context to render on\n   * @param {Number} left x coordinate where the control center should be\n   * @param {Number} top y coordinate where the control center should be\n   * @param {Object} styleOverride override for fabric.Object controls style\n   * @param {fabric.Object} fabricObject the fabric object for which we are rendering controls\n   */\n  function renderSquareControl(ctx, left, top, styleOverride, fabricObject) {\n    styleOverride = styleOverride || {};\n    var size = styleOverride.cornerSize || fabricObject.cornerSize,\n        transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ?\n          styleOverride.transparentCorners : fabricObject.transparentCorners,\n        methodName = transparentCorners ? 'stroke' : 'fill',\n        stroke = !transparentCorners && (\n          styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor\n        ), sizeBy2 = size / 2;\n    ctx.save();\n    ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor;\n    ctx.strokeStyle = styleOverride.strokeCornerColor || fabricObject.strokeCornerColor;\n    // this is still wrong\n    ctx.lineWidth = 1;\n    ctx.translate(left, top);\n    ctx.rotate(degreesToRadians(fabricObject.angle));\n    // this does not work, and fixed with ( && ) does not make sense.\n    // to have real transparent corners we need the controls on upperCanvas\n    // transparentCorners || ctx.clearRect(-sizeBy2, -sizeBy2, size, size);\n    ctx[methodName + 'Rect'](-sizeBy2, -sizeBy2, size, size);\n    if (stroke) {\n      ctx.strokeRect(-sizeBy2, -sizeBy2, size, size);\n    }\n    ctx.restore();\n  }\n\n  controls.renderCircleControl = renderCircleControl;\n  controls.renderSquareControl = renderSquareControl;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { });\n\n  function Control(options) {\n    for (var i in options) {\n      this[i] = options[i];\n    }\n  }\n\n  fabric.Control = Control;\n\n  fabric.Control.prototype = /** @lends fabric.Control.prototype */ {\n\n    /**\n     * keep track of control visibility.\n     * mainly for backward compatibility.\n     * if you do not want to see a control, you can remove it\n     * from the controlset.\n     * @type {Boolean}\n     * @default true\n     */\n    visible: true,\n\n    /**\n     * Name of the action that the controll will likely execute.\n     * This is optional. FabricJS uses to identify what the user is doing for some\n     * extra optimizations. If you are writing a custom control and you want to know\n     * somewhere else in the code what is going on, you can use this string here.\n     * you can also provide a custom getActionName if your control run multiple actions\n     * depending on some external state.\n     * default to scale since is the most common, used on 4 corners by default\n     * @type {String}\n     * @default 'scale'\n     */\n    actionName: 'scale',\n\n    /**\n     * Drawing angle of the control.\n     * NOT used for now, but name marked as needed for internal logic\n     * example: to reuse the same drawing function for different rotated controls\n     * @type {Number}\n     * @default 0\n     */\n    angle: 0,\n\n    /**\n     * Relative position of the control. X\n     * 0,0 is the center of the Object, while -0.5 (left) or 0.5 (right) are the extremities\n     * of the bounding box.\n     * @type {Number}\n     * @default 0\n     */\n    x: 0,\n\n    /**\n     * Relative position of the control. Y\n     * 0,0 is the center of the Object, while -0.5 (top) or 0.5 (bottom) are the extremities\n     * of the bounding box.\n     * @type {Number}\n     * @default 0\n     */\n    y: 0,\n\n    /**\n     * Horizontal offset of the control from the defined position. In pixels\n     * Positive offset moves the control to the right, negative to the left.\n     * It used when you want to have position of control that does not scale with\n     * the bounding box. Example: rotation control is placed at x:0, y: 0.5 on\n     * the boundindbox, with an offset of 30 pixels vertivally. Those 30 pixels will\n     * stay 30 pixels no matter how the object is big. Another example is having 2\n     * controls in the corner, that stay in the same position when the object scale.\n     * of the bounding box.\n     * @type {Number}\n     * @default 0\n     */\n    offsetX: 0,\n\n    /**\n     * Vertical offset of the control from the defined position. In pixels\n     * Positive offset moves the control to the bottom, negative to the top.\n     * @type {Number}\n     * @default 0\n     */\n    offsetY: 0,\n\n    /**\n     * Css cursor style to display when the control is hovered.\n     * if the method `cursorStyleHandler` is provided, this property is ignored.\n     * @type {String}\n     * @default 'crosshair'\n     */\n    cursorStyle: 'crosshair',\n\n    /**\n     * If controls has an offsetY or offsetX, draw a line that connects\n     * the control to the bounding box\n     * @type {Boolean}\n     * @default false\n     */\n    withConnection: false,\n\n    /**\n     * The control actionHandler, provide one to handle action ( control being moved )\n     * @param {Event} eventData the native mouse event\n     * @param {Object} transformData properties of the current transform\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {Function}\n     */\n    actionHandler: function(/* eventData, transformData, fabricObject */) { },\n\n    /**\n     * The control handler for mouse down, provide one to handle mouse down on control\n     * @param {Event} eventData the native mouse event\n     * @param {Object} transformData properties of the current transform\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {Function}\n     */\n    mouseDownHandler: function(/* eventData, transformData, fabricObject */) { },\n\n    /**\n     * The control mouseUpHandler, provide one to handle an effect on mouse up.\n     * @param {Event} eventData the native mouse event\n     * @param {Object} transformData properties of the current transform\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {Function}\n     */\n    mouseUpHandler: function(/* eventData, transformData, fabricObject */) { },\n\n    /**\n     * Returns control actionHandler\n     * @param {Event} eventData the native mouse event\n     * @param {Object} transformData properties of the current transform\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {Function}\n     */\n    getActionHandler: function(/* eventData, transformData, fabricObject */) {\n      return this.actionHandler;\n    },\n\n    /**\n     * Returns control mouseDown handler\n     * @param {Event} eventData the native mouse event\n     * @param {Object} transformData properties of the current transform\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {Function}\n     */\n    getMouseDownHandler: function(/* eventData, fabricObject, control */) {\n      return this.mouseDownHandler;\n    },\n\n    /**\n     * Returns control mouseUp handler\n     * @param {Event} eventData the native mouse event\n     * @param {Object} transformData properties of the current transform\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {Function}\n     */\n    getMouseUpHandler: function(/* eventData, fabricObject, control */) {\n      return this.mouseUpHandler;\n    },\n\n    /**\n     * Returns control cursorStyle for css using cursorStyle. If you need a more elaborate\n     * function you can pass one in the constructor\n     * the cursorStyle property\n     * @param {Event} eventData the native mouse event\n     * @param {fabric.Control} control the current control ( likely this)\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {String}\n     */\n    cursorStyleHandler: function(eventData, control /* fabricObject */) {\n      return control.cursorStyle;\n    },\n\n    /**\n     * Returns the action name. The basic implementation just return the actionName property.\n     * @param {Event} eventData the native mouse event\n     * @param {fabric.Control} control the current control ( likely this)\n     * @param {fabric.Object} object on which the control is displayed\n     * @return {String}\n     */\n    getActionName: function(eventData, control /* fabricObject */) {\n      return control.actionName;\n    },\n\n    /**\n     * Returns controls visibility\n     * @param {fabric.Object} object on which the control is displayed\n     * @param {String} controlKey key where the control is memorized on the\n     * @return {Boolean}\n     */\n    getVisibility: function(fabricObject, controlKey) {\n      var objectVisibility = fabricObject._controlsVisibility;\n      if (objectVisibility && typeof objectVisibility[controlKey] !== 'undefined') {\n        return objectVisibility[controlKey];\n      }\n      return this.visible;\n    },\n\n    /**\n     * Sets controls visibility\n     * @param {Boolean} visibility for the object\n     * @return {Void}\n     */\n    setVisibility: function(visibility /* name, fabricObject */) {\n      this.visible = visibility;\n    },\n\n\n    positionHandler: function(dim, finalMatrix /*, fabricObject, currentControl */) {\n      var point = fabric.util.transformPoint({\n        x: this.x * dim.x + this.offsetX,\n        y: this.y * dim.y + this.offsetY }, finalMatrix);\n      return point;\n    },\n\n    /**\n    * Render function for the control.\n    * When this function runs the context is unscaled. unrotate. Just retina scaled.\n    * all the functions will have to translate to the point left,top before starting Drawing\n    * if they want to draw a control where the position is detected.\n    * left and top are the result of the positionHandler function\n    * @param {RenderingContext2D} ctx the context where the control will be drawn\n    * @param {Number} left position of the canvas where we are about to render the control.\n    * @param {Number} top position of the canvas where we are about to render the control.\n    * @param {Object} styleOverride\n    * @param {fabric.Object} fabricObject the object where the control is about to be rendered\n    */\n    render: function(ctx, left, top, styleOverride, fabricObject) {\n      styleOverride = styleOverride || {};\n      switch (styleOverride.cornerStyle || fabricObject.cornerStyle) {\n        case 'circle':\n          fabric.controlsUtils.renderCircleControl.call(this, ctx, left, top, styleOverride, fabricObject);\n          break;\n        default:\n          fabric.controlsUtils.renderSquareControl.call(this, ctx, left, top, styleOverride, fabricObject);\n      }\n    },\n  };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n  /* _FROM_SVG_START_ */\n  function getColorStop(el, multiplier) {\n    var style = el.getAttribute('style'),\n        offset = el.getAttribute('offset') || 0,\n        color, colorAlpha, opacity, i;\n\n    // convert percents to absolute values\n    offset = parseFloat(offset) / (/%$/.test(offset) ? 100 : 1);\n    offset = offset < 0 ? 0 : offset > 1 ? 1 : offset;\n    if (style) {\n      var keyValuePairs = style.split(/\\s*;\\s*/);\n\n      if (keyValuePairs[keyValuePairs.length - 1] === '') {\n        keyValuePairs.pop();\n      }\n\n      for (i = keyValuePairs.length; i--; ) {\n\n        var split = keyValuePairs[i].split(/\\s*:\\s*/),\n            key = split[0].trim(),\n            value = split[1].trim();\n\n        if (key === 'stop-color') {\n          color = value;\n        }\n        else if (key === 'stop-opacity') {\n          opacity = value;\n        }\n      }\n    }\n\n    if (!color) {\n      color = el.getAttribute('stop-color') || 'rgb(0,0,0)';\n    }\n    if (!opacity) {\n      opacity = el.getAttribute('stop-opacity');\n    }\n\n    color = new fabric.Color(color);\n    colorAlpha = color.getAlpha();\n    opacity = isNaN(parseFloat(opacity)) ? 1 : parseFloat(opacity);\n    opacity *= colorAlpha * multiplier;\n\n    return {\n      offset: offset,\n      color: color.toRgb(),\n      opacity: opacity\n    };\n  }\n\n  function getLinearCoords(el) {\n    return {\n      x1: el.getAttribute('x1') || 0,\n      y1: el.getAttribute('y1') || 0,\n      x2: el.getAttribute('x2') || '100%',\n      y2: el.getAttribute('y2') || 0\n    };\n  }\n\n  function getRadialCoords(el) {\n    return {\n      x1: el.getAttribute('fx') || el.getAttribute('cx') || '50%',\n      y1: el.getAttribute('fy') || el.getAttribute('cy') || '50%',\n      r1: 0,\n      x2: el.getAttribute('cx') || '50%',\n      y2: el.getAttribute('cy') || '50%',\n      r2: el.getAttribute('r') || '50%'\n    };\n  }\n  /* _FROM_SVG_END_ */\n\n  var clone = fabric.util.object.clone;\n\n  /**\n   * Gradient class\n   * @class fabric.Gradient\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#gradients}\n   * @see {@link fabric.Gradient#initialize} for constructor definition\n   */\n  fabric.Gradient = fabric.util.createClass(/** @lends fabric.Gradient.prototype */ {\n\n    /**\n     * Horizontal offset for aligning gradients coming from SVG when outside pathgroups\n     * @type Number\n     * @default 0\n     */\n    offsetX: 0,\n\n    /**\n     * Vertical offset for aligning gradients coming from SVG when outside pathgroups\n     * @type Number\n     * @default 0\n     */\n    offsetY: 0,\n\n    /**\n     * A transform matrix to apply to the gradient before painting.\n     * Imported from svg gradients, is not applied with the current transform in the center.\n     * Before this transform is applied, the origin point is at the top left corner of the object\n     * plus the addition of offsetY and offsetX.\n     * @type Number[]\n     * @default null\n     */\n    gradientTransform: null,\n\n    /**\n     * coordinates units for coords.\n     * If `pixels`, the number of coords are in the same unit of width / height.\n     * If set as `percentage` the coords are still a number, but 1 means 100% of width\n     * for the X and 100% of the height for the y. It can be bigger than 1 and negative.\n     * allowed values pixels or percentage.\n     * @type String\n     * @default 'pixels'\n     */\n    gradientUnits: 'pixels',\n\n    /**\n     * Gradient type linear or radial\n     * @type String\n     * @default 'pixels'\n     */\n    type: 'linear',\n\n    /**\n     * Constructor\n     * @param {Object} options Options object with type, coords, gradientUnits and colorStops\n     * @param {Object} [options.type] gradient type linear or radial\n     * @param {Object} [options.gradientUnits] gradient units\n     * @param {Object} [options.offsetX] SVG import compatibility\n     * @param {Object} [options.offsetY] SVG import compatibility\n     * @param {Object[]} options.colorStops contains the colorstops.\n     * @param {Object} options.coords contains the coords of the gradient\n     * @param {Number} [options.coords.x1] X coordiante of the first point for linear or of the focal point for radial\n     * @param {Number} [options.coords.y1] Y coordiante of the first point for linear or of the focal point for radial\n     * @param {Number} [options.coords.x2] X coordiante of the second point for linear or of the center point for radial\n     * @param {Number} [options.coords.y2] Y coordiante of the second point for linear or of the center point for radial\n     * @param {Number} [options.coords.r1] only for radial gradient, radius of the inner circle\n     * @param {Number} [options.coords.r2] only for radial gradient, radius of the external circle\n     * @return {fabric.Gradient} thisArg\n     */\n    initialize: function(options) {\n      options || (options = { });\n      options.coords || (options.coords = { });\n\n      var coords, _this = this;\n\n      // sets everything, then coords and colorstops get sets again\n      Object.keys(options).forEach(function(option) {\n        _this[option] = options[option];\n      });\n\n      if (this.id) {\n        this.id += '_' + fabric.Object.__uid++;\n      }\n      else {\n        this.id = fabric.Object.__uid++;\n      }\n\n      coords = {\n        x1: options.coords.x1 || 0,\n        y1: options.coords.y1 || 0,\n        x2: options.coords.x2 || 0,\n        y2: options.coords.y2 || 0\n      };\n\n      if (this.type === 'radial') {\n        coords.r1 = options.coords.r1 || 0;\n        coords.r2 = options.coords.r2 || 0;\n      }\n\n      this.coords = coords;\n      this.colorStops = options.colorStops.slice();\n    },\n\n    /**\n     * Adds another colorStop\n     * @param {Object} colorStop Object with offset and color\n     * @return {fabric.Gradient} thisArg\n     */\n    addColorStop: function(colorStops) {\n      for (var position in colorStops) {\n        var color = new fabric.Color(colorStops[position]);\n        this.colorStops.push({\n          offset: parseFloat(position),\n          color: color.toRgb(),\n          opacity: color.getAlpha()\n        });\n      }\n      return this;\n    },\n\n    /**\n     * Returns object representation of a gradient\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object}\n     */\n    toObject: function(propertiesToInclude) {\n      var object = {\n        type: this.type,\n        coords: this.coords,\n        colorStops: this.colorStops,\n        offsetX: this.offsetX,\n        offsetY: this.offsetY,\n        gradientUnits: this.gradientUnits,\n        gradientTransform: this.gradientTransform ? this.gradientTransform.concat() : this.gradientTransform\n      };\n      fabric.util.populateWithProperties(this, object, propertiesToInclude);\n\n      return object;\n    },\n\n    /* _TO_SVG_START_ */\n    /**\n     * Returns SVG representation of an gradient\n     * @param {Object} object Object to create a gradient for\n     * @return {String} SVG representation of an gradient (linear/radial)\n     */\n    toSVG: function(object, options) {\n      var coords = clone(this.coords, true), i, len, options = options || {},\n          markup, commonAttributes, colorStops = clone(this.colorStops, true),\n          needsSwap = coords.r1 > coords.r2,\n          transform = this.gradientTransform ? this.gradientTransform.concat() : fabric.iMatrix.concat(),\n          offsetX = -this.offsetX, offsetY = -this.offsetY,\n          withViewport = !!options.additionalTransform,\n          gradientUnits = this.gradientUnits === 'pixels' ? 'userSpaceOnUse' : 'objectBoundingBox';\n      // colorStops must be sorted ascending\n      colorStops.sort(function(a, b) {\n        return a.offset - b.offset;\n      });\n\n      if (gradientUnits === 'objectBoundingBox') {\n        offsetX /= object.width;\n        offsetY /= object.height;\n      }\n      else {\n        offsetX += object.width / 2;\n        offsetY += object.height / 2;\n      }\n      if (object.type === 'path') {\n        offsetX -= object.pathOffset.x;\n        offsetY -= object.pathOffset.y;\n      }\n\n\n      transform[4] -= offsetX;\n      transform[5] -= offsetY;\n\n      commonAttributes = 'id=\"SVGID_' + this.id +\n                     '\" gradientUnits=\"' + gradientUnits + '\"';\n      commonAttributes += ' gradientTransform=\"' + (withViewport ?\n        options.additionalTransform + ' ' : '') + fabric.util.matrixToSVG(transform) + '\" ';\n\n      if (this.type === 'linear') {\n        markup = [\n          '<linearGradient ',\n          commonAttributes,\n          ' x1=\"', coords.x1,\n          '\" y1=\"', coords.y1,\n          '\" x2=\"', coords.x2,\n          '\" y2=\"', coords.y2,\n          '\">\\n'\n        ];\n      }\n      else if (this.type === 'radial') {\n        // svg radial gradient has just 1 radius. the biggest.\n        markup = [\n          '<radialGradient ',\n          commonAttributes,\n          ' cx=\"', needsSwap ? coords.x1 : coords.x2,\n          '\" cy=\"', needsSwap ? coords.y1 : coords.y2,\n          '\" r=\"', needsSwap ? coords.r1 : coords.r2,\n          '\" fx=\"', needsSwap ? coords.x2 : coords.x1,\n          '\" fy=\"', needsSwap ? coords.y2 : coords.y1,\n          '\">\\n'\n        ];\n      }\n\n      if (this.type === 'radial') {\n        if (needsSwap) {\n          // svg goes from internal to external radius. if radius are inverted, swap color stops.\n          colorStops = colorStops.concat();\n          colorStops.reverse();\n          for (i = 0, len = colorStops.length; i < len; i++) {\n            colorStops[i].offset = 1 - colorStops[i].offset;\n          }\n        }\n        var minRadius = Math.min(coords.r1, coords.r2);\n        if (minRadius > 0) {\n          // i have to shift all colorStops and add new one in 0.\n          var maxRadius = Math.max(coords.r1, coords.r2),\n              percentageShift = minRadius / maxRadius;\n          for (i = 0, len = colorStops.length; i < len; i++) {\n            colorStops[i].offset += percentageShift * (1 - colorStops[i].offset);\n          }\n        }\n      }\n\n      for (i = 0, len = colorStops.length; i < len; i++) {\n        var colorStop = colorStops[i];\n        markup.push(\n          '<stop ',\n          'offset=\"', (colorStop.offset * 100) + '%',\n          '\" style=\"stop-color:', colorStop.color,\n          (typeof colorStop.opacity !== 'undefined' ? ';stop-opacity: ' + colorStop.opacity : ';'),\n          '\"/>\\n'\n        );\n      }\n\n      markup.push((this.type === 'linear' ? '</linearGradient>\\n' : '</radialGradient>\\n'));\n\n      return markup.join('');\n    },\n    /* _TO_SVG_END_ */\n\n    /**\n     * Returns an instance of CanvasGradient\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @return {CanvasGradient}\n     */\n    toLive: function(ctx) {\n      var gradient, coords = fabric.util.object.clone(this.coords), i, len;\n\n      if (!this.type) {\n        return;\n      }\n\n      if (this.type === 'linear') {\n        gradient = ctx.createLinearGradient(\n          coords.x1, coords.y1, coords.x2, coords.y2);\n      }\n      else if (this.type === 'radial') {\n        gradient = ctx.createRadialGradient(\n          coords.x1, coords.y1, coords.r1, coords.x2, coords.y2, coords.r2);\n      }\n\n      for (i = 0, len = this.colorStops.length; i < len; i++) {\n        var color = this.colorStops[i].color,\n            opacity = this.colorStops[i].opacity,\n            offset = this.colorStops[i].offset;\n\n        if (typeof opacity !== 'undefined') {\n          color = new fabric.Color(color).setAlpha(opacity).toRgba();\n        }\n        gradient.addColorStop(offset, color);\n      }\n\n      return gradient;\n    }\n  });\n\n  fabric.util.object.extend(fabric.Gradient, {\n\n    /* _FROM_SVG_START_ */\n    /**\n     * Returns {@link fabric.Gradient} instance from an SVG element\n     * @static\n     * @memberOf fabric.Gradient\n     * @param {SVGGradientElement} el SVG gradient element\n     * @param {fabric.Object} instance\n     * @param {String} opacityAttr A fill-opacity or stroke-opacity attribute to multiply to each stop's opacity.\n     * @param {Object} svgOptions an object containing the size of the SVG in order to parse correctly graidents\n     * that uses gradientUnits as 'userSpaceOnUse' and percentages.\n     * @param {Object.number} viewBoxWidth width part of the viewBox attribute on svg\n     * @param {Object.number} viewBoxHeight height part of the viewBox attribute on svg\n     * @param {Object.number} width width part of the svg tag if viewBox is not specified\n     * @param {Object.number} height height part of the svg tag if viewBox is not specified\n     * @return {fabric.Gradient} Gradient instance\n     * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement\n     * @see http://www.w3.org/TR/SVG/pservers.html#RadialGradientElement\n     */\n    fromElement: function(el, instance, opacityAttr, svgOptions) {\n      /**\n       *  @example:\n       *\n       *  <linearGradient id=\"linearGrad1\">\n       *    <stop offset=\"0%\" stop-color=\"white\"/>\n       *    <stop offset=\"100%\" stop-color=\"black\"/>\n       *  </linearGradient>\n       *\n       *  OR\n       *\n       *  <linearGradient id=\"linearGrad2\">\n       *    <stop offset=\"0\" style=\"stop-color:rgb(255,255,255)\"/>\n       *    <stop offset=\"1\" style=\"stop-color:rgb(0,0,0)\"/>\n       *  </linearGradient>\n       *\n       *  OR\n       *\n       *  <radialGradient id=\"radialGrad1\">\n       *    <stop offset=\"0%\" stop-color=\"white\" stop-opacity=\"1\" />\n       *    <stop offset=\"50%\" stop-color=\"black\" stop-opacity=\"0.5\" />\n       *    <stop offset=\"100%\" stop-color=\"white\" stop-opacity=\"1\" />\n       *  </radialGradient>\n       *\n       *  OR\n       *\n       *  <radialGradient id=\"radialGrad2\">\n       *    <stop offset=\"0\" stop-color=\"rgb(255,255,255)\" />\n       *    <stop offset=\"0.5\" stop-color=\"rgb(0,0,0)\" />\n       *    <stop offset=\"1\" stop-color=\"rgb(255,255,255)\" />\n       *  </radialGradient>\n       *\n       */\n\n      var multiplier = parseFloat(opacityAttr) / (/%$/.test(opacityAttr) ? 100 : 1);\n      multiplier = multiplier < 0 ? 0 : multiplier > 1 ? 1 : multiplier;\n      if (isNaN(multiplier)) {\n        multiplier = 1;\n      }\n\n      var colorStopEls = el.getElementsByTagName('stop'),\n          type,\n          gradientUnits = el.getAttribute('gradientUnits') === 'userSpaceOnUse' ?\n            'pixels' : 'percentage',\n          gradientTransform = el.getAttribute('gradientTransform') || '',\n          colorStops = [],\n          coords, i, offsetX = 0, offsetY = 0,\n          transformMatrix;\n      if (el.nodeName === 'linearGradient' || el.nodeName === 'LINEARGRADIENT') {\n        type = 'linear';\n        coords = getLinearCoords(el);\n      }\n      else {\n        type = 'radial';\n        coords = getRadialCoords(el);\n      }\n\n      for (i = colorStopEls.length; i--; ) {\n        colorStops.push(getColorStop(colorStopEls[i], multiplier));\n      }\n\n      transformMatrix = fabric.parseTransformAttribute(gradientTransform);\n\n      __convertPercentUnitsToValues(instance, coords, svgOptions, gradientUnits);\n\n      if (gradientUnits === 'pixels') {\n        offsetX = -instance.left;\n        offsetY = -instance.top;\n      }\n\n      var gradient = new fabric.Gradient({\n        id: el.getAttribute('id'),\n        type: type,\n        coords: coords,\n        colorStops: colorStops,\n        gradientUnits: gradientUnits,\n        gradientTransform: transformMatrix,\n        offsetX: offsetX,\n        offsetY: offsetY,\n      });\n\n      return gradient;\n    }\n    /* _FROM_SVG_END_ */\n  });\n\n  /**\n   * @private\n   */\n  function __convertPercentUnitsToValues(instance, options, svgOptions, gradientUnits) {\n    var propValue, finalValue;\n    Object.keys(options).forEach(function(prop) {\n      propValue = options[prop];\n      if (propValue === 'Infinity') {\n        finalValue = 1;\n      }\n      else if (propValue === '-Infinity') {\n        finalValue = 0;\n      }\n      else {\n        finalValue = parseFloat(options[prop], 10);\n        if (typeof propValue === 'string' && /^(\\d+\\.\\d+)%|(\\d+)%$/.test(propValue)) {\n          finalValue *= 0.01;\n          if (gradientUnits === 'pixels') {\n            // then we need to fix those percentages here in svg parsing\n            if (prop === 'x1' || prop === 'x2' || prop === 'r2') {\n              finalValue *= svgOptions.viewBoxWidth || svgOptions.width;\n            }\n            if (prop === 'y1' || prop === 'y2') {\n              finalValue *= svgOptions.viewBoxHeight || svgOptions.height;\n            }\n          }\n        }\n      }\n      options[prop] = finalValue;\n    });\n  }\n})();\n\n\n(function() {\n\n  'use strict';\n\n  var toFixed = fabric.util.toFixed;\n\n  /**\n   * Pattern class\n   * @class fabric.Pattern\n   * @see {@link http://fabricjs.com/patterns|Pattern demo}\n   * @see {@link http://fabricjs.com/dynamic-patterns|DynamicPattern demo}\n   * @see {@link fabric.Pattern#initialize} for constructor definition\n   */\n\n\n  fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ {\n\n    /**\n     * Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat)\n     * @type String\n     * @default\n     */\n    repeat: 'repeat',\n\n    /**\n     * Pattern horizontal offset from object's left/top corner\n     * @type Number\n     * @default\n     */\n    offsetX: 0,\n\n    /**\n     * Pattern vertical offset from object's left/top corner\n     * @type Number\n     * @default\n     */\n    offsetY: 0,\n\n    /**\n     * crossOrigin value (one of \"\", \"anonymous\", \"use-credentials\")\n     * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes\n     * @type String\n     * @default\n     */\n    crossOrigin: '',\n\n    /**\n     * transform matrix to change the pattern, imported from svgs.\n     * @type Array\n     * @default\n     */\n    patternTransform: null,\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     * @param {Function} [callback] function to invoke after callback init.\n     * @return {fabric.Pattern} thisArg\n     */\n    initialize: function(options, callback) {\n      options || (options = { });\n\n      this.id = fabric.Object.__uid++;\n      this.setOptions(options);\n      if (!options.source || (options.source && typeof options.source !== 'string')) {\n        callback && callback(this);\n        return;\n      }\n      else {\n        // img src string\n        var _this = this;\n        this.source = fabric.util.createImage();\n        fabric.util.loadImage(options.source, function(img, isError) {\n          _this.source = img;\n          callback && callback(_this, isError);\n        }, null, this.crossOrigin);\n      }\n    },\n\n    /**\n     * Returns object representation of a pattern\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} Object representation of a pattern instance\n     */\n    toObject: function(propertiesToInclude) {\n      var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n          source, object;\n\n      // <img> element\n      if (typeof this.source.src === 'string') {\n        source = this.source.src;\n      }\n      // <canvas> element\n      else if (typeof this.source === 'object' && this.source.toDataURL) {\n        source = this.source.toDataURL();\n      }\n\n      object = {\n        type: 'pattern',\n        source: source,\n        repeat: this.repeat,\n        crossOrigin: this.crossOrigin,\n        offsetX: toFixed(this.offsetX, NUM_FRACTION_DIGITS),\n        offsetY: toFixed(this.offsetY, NUM_FRACTION_DIGITS),\n        patternTransform: this.patternTransform ? this.patternTransform.concat() : null\n      };\n      fabric.util.populateWithProperties(this, object, propertiesToInclude);\n\n      return object;\n    },\n\n    /* _TO_SVG_START_ */\n    /**\n     * Returns SVG representation of a pattern\n     * @param {fabric.Object} object\n     * @return {String} SVG representation of a pattern\n     */\n    toSVG: function(object) {\n      var patternSource = typeof this.source === 'function' ? this.source() : this.source,\n          patternWidth = patternSource.width / object.width,\n          patternHeight = patternSource.height / object.height,\n          patternOffsetX = this.offsetX / object.width,\n          patternOffsetY = this.offsetY / object.height,\n          patternImgSrc = '';\n      if (this.repeat === 'repeat-x' || this.repeat === 'no-repeat') {\n        patternHeight = 1;\n        if (patternOffsetY) {\n          patternHeight += Math.abs(patternOffsetY);\n        }\n      }\n      if (this.repeat === 'repeat-y' || this.repeat === 'no-repeat') {\n        patternWidth = 1;\n        if (patternOffsetX) {\n          patternWidth += Math.abs(patternOffsetX);\n        }\n\n      }\n      if (patternSource.src) {\n        patternImgSrc = patternSource.src;\n      }\n      else if (patternSource.toDataURL) {\n        patternImgSrc = patternSource.toDataURL();\n      }\n\n      return '<pattern id=\"SVGID_' + this.id +\n                    '\" x=\"' + patternOffsetX +\n                    '\" y=\"' + patternOffsetY +\n                    '\" width=\"' + patternWidth +\n                    '\" height=\"' + patternHeight + '\">\\n' +\n               '<image x=\"0\" y=\"0\"' +\n                      ' width=\"' + patternSource.width +\n                      '\" height=\"' + patternSource.height +\n                      '\" xlink:href=\"' + patternImgSrc +\n               '\"></image>\\n' +\n             '</pattern>\\n';\n    },\n    /* _TO_SVG_END_ */\n\n    setOptions: function(options) {\n      for (var prop in options) {\n        this[prop] = options[prop];\n      }\n    },\n\n    /**\n     * Returns an instance of CanvasPattern\n     * @param {CanvasRenderingContext2D} ctx Context to create pattern\n     * @return {CanvasPattern}\n     */\n    toLive: function(ctx) {\n      var source = this.source;\n      // if the image failed to load, return, and allow rest to continue loading\n      if (!source) {\n        return '';\n      }\n\n      // if an image\n      if (typeof source.src !== 'undefined') {\n        if (!source.complete) {\n          return '';\n        }\n        if (source.naturalWidth === 0 || source.naturalHeight === 0) {\n          return '';\n        }\n      }\n      return ctx.createPattern(source, this.repeat);\n    }\n  });\n})();\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { }),\n      toFixed = fabric.util.toFixed;\n\n  if (fabric.Shadow) {\n    fabric.warn('fabric.Shadow is already defined.');\n    return;\n  }\n\n  /**\n   * Shadow class\n   * @class fabric.Shadow\n   * @see {@link http://fabricjs.com/shadows|Shadow demo}\n   * @see {@link fabric.Shadow#initialize} for constructor definition\n   */\n  fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ {\n\n    /**\n     * Shadow color\n     * @type String\n     * @default\n     */\n    color: 'rgb(0,0,0)',\n\n    /**\n     * Shadow blur\n     * @type Number\n     */\n    blur: 0,\n\n    /**\n     * Shadow horizontal offset\n     * @type Number\n     * @default\n     */\n    offsetX: 0,\n\n    /**\n     * Shadow vertical offset\n     * @type Number\n     * @default\n     */\n    offsetY: 0,\n\n    /**\n     * Whether the shadow should affect stroke operations\n     * @type Boolean\n     * @default\n     */\n    affectStroke: false,\n\n    /**\n     * Indicates whether toObject should include default values\n     * @type Boolean\n     * @default\n     */\n    includeDefaultValues: true,\n\n    /**\n     * When `false`, the shadow will scale with the object.\n     * When `true`, the shadow's offsetX, offsetY, and blur will not be affected by the object's scale.\n     * default to false\n     * @type Boolean\n     * @default\n     */\n    nonScaling: false,\n\n    /**\n     * Constructor\n     * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetY properties or string (e.g. \"rgba(0,0,0,0.2) 2px 2px 10px\")\n     * @return {fabric.Shadow} thisArg\n     */\n    initialize: function(options) {\n\n      if (typeof options === 'string') {\n        options = this._parseShadow(options);\n      }\n\n      for (var prop in options) {\n        this[prop] = options[prop];\n      }\n\n      this.id = fabric.Object.__uid++;\n    },\n\n    /**\n     * @private\n     * @param {String} shadow Shadow value to parse\n     * @return {Object} Shadow object with color, offsetX, offsetY and blur\n     */\n    _parseShadow: function(shadow) {\n      var shadowStr = shadow.trim(),\n          offsetsAndBlur = fabric.Shadow.reOffsetsAndBlur.exec(shadowStr) || [],\n          color = shadowStr.replace(fabric.Shadow.reOffsetsAndBlur, '') || 'rgb(0,0,0)';\n\n      return {\n        color: color.trim(),\n        offsetX: parseInt(offsetsAndBlur[1], 10) || 0,\n        offsetY: parseInt(offsetsAndBlur[2], 10) || 0,\n        blur: parseInt(offsetsAndBlur[3], 10) || 0\n      };\n    },\n\n    /**\n     * Returns a string representation of an instance\n     * @see http://www.w3.org/TR/css-text-decor-3/#text-shadow\n     * @return {String} Returns CSS3 text-shadow declaration\n     */\n    toString: function() {\n      return [this.offsetX, this.offsetY, this.blur, this.color].join('px ');\n    },\n\n    /* _TO_SVG_START_ */\n    /**\n     * Returns SVG representation of a shadow\n     * @param {fabric.Object} object\n     * @return {String} SVG representation of a shadow\n     */\n    toSVG: function(object) {\n      var fBoxX = 40, fBoxY = 40, NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n          offset = fabric.util.rotateVector(\n            { x: this.offsetX, y: this.offsetY },\n            fabric.util.degreesToRadians(-object.angle)),\n          BLUR_BOX = 20, color = new fabric.Color(this.color);\n\n      if (object.width && object.height) {\n        //http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion\n        // we add some extra space to filter box to contain the blur ( 20 )\n        fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;\n        fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;\n      }\n      if (object.flipX) {\n        offset.x *= -1;\n      }\n      if (object.flipY) {\n        offset.y *= -1;\n      }\n\n      return (\n        '<filter id=\"SVGID_' + this.id + '\" y=\"-' + fBoxY + '%\" height=\"' + (100 + 2 * fBoxY) + '%\" ' +\n          'x=\"-' + fBoxX + '%\" width=\"' + (100 + 2 * fBoxX) + '%\" ' + '>\\n' +\n          '\\t<feGaussianBlur in=\"SourceAlpha\" stdDeviation=\"' +\n            toFixed(this.blur ? this.blur / 2 : 0, NUM_FRACTION_DIGITS) + '\"></feGaussianBlur>\\n' +\n          '\\t<feOffset dx=\"' + toFixed(offset.x, NUM_FRACTION_DIGITS) +\n          '\" dy=\"' + toFixed(offset.y, NUM_FRACTION_DIGITS) + '\" result=\"oBlur\" ></feOffset>\\n' +\n          '\\t<feFlood flood-color=\"' + color.toRgb() + '\" flood-opacity=\"' + color.getAlpha() + '\"/>\\n' +\n          '\\t<feComposite in2=\"oBlur\" operator=\"in\" />\\n' +\n          '\\t<feMerge>\\n' +\n            '\\t\\t<feMergeNode></feMergeNode>\\n' +\n            '\\t\\t<feMergeNode in=\"SourceGraphic\"></feMergeNode>\\n' +\n          '\\t</feMerge>\\n' +\n        '</filter>\\n');\n    },\n    /* _TO_SVG_END_ */\n\n    /**\n     * Returns object representation of a shadow\n     * @return {Object} Object representation of a shadow instance\n     */\n    toObject: function() {\n      if (this.includeDefaultValues) {\n        return {\n          color: this.color,\n          blur: this.blur,\n          offsetX: this.offsetX,\n          offsetY: this.offsetY,\n          affectStroke: this.affectStroke,\n          nonScaling: this.nonScaling\n        };\n      }\n      var obj = { }, proto = fabric.Shadow.prototype;\n\n      ['color', 'blur', 'offsetX', 'offsetY', 'affectStroke', 'nonScaling'].forEach(function(prop) {\n        if (this[prop] !== proto[prop]) {\n          obj[prop] = this[prop];\n        }\n      }, this);\n\n      return obj;\n    }\n  });\n\n  /**\n   * Regex matching shadow offsetX, offsetY and blur (ex: \"2px 2px 10px rgba(0,0,0,0.2)\", \"rgb(0,255,0) 2px 2px\")\n   * @static\n   * @field\n   * @memberOf fabric.Shadow\n   */\n  // eslint-disable-next-line max-len\n  fabric.Shadow.reOffsetsAndBlur = /(?:\\s|^)(-?\\d+(?:px)?(?:\\s?|$))?(-?\\d+(?:px)?(?:\\s?|$))?(\\d+(?:px)?)?(?:\\s?|$)(?:$|\\s)/;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function () {\n\n  'use strict';\n\n  if (fabric.StaticCanvas) {\n    fabric.warn('fabric.StaticCanvas is already defined.');\n    return;\n  }\n\n  // aliases for faster resolution\n  var extend = fabric.util.object.extend,\n      getElementOffset = fabric.util.getElementOffset,\n      removeFromArray = fabric.util.removeFromArray,\n      toFixed = fabric.util.toFixed,\n      transformPoint = fabric.util.transformPoint,\n      invertTransform = fabric.util.invertTransform,\n      getNodeCanvas = fabric.util.getNodeCanvas,\n      createCanvasElement = fabric.util.createCanvasElement,\n\n      CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element');\n\n  /**\n   * Static canvas class\n   * @class fabric.StaticCanvas\n   * @mixes fabric.Collection\n   * @mixes fabric.Observable\n   * @see {@link http://fabricjs.com/static_canvas|StaticCanvas demo}\n   * @see {@link fabric.StaticCanvas#initialize} for constructor definition\n   * @fires before:render\n   * @fires after:render\n   * @fires canvas:cleared\n   * @fires object:added\n   * @fires object:removed\n   */\n  fabric.StaticCanvas = fabric.util.createClass(fabric.CommonMethods, /** @lends fabric.StaticCanvas.prototype */ {\n\n    /**\n     * Constructor\n     * @param {HTMLElement | String} el &lt;canvas> element to initialize instance on\n     * @param {Object} [options] Options object\n     * @return {Object} thisArg\n     */\n    initialize: function(el, options) {\n      options || (options = { });\n      this.renderAndResetBound = this.renderAndReset.bind(this);\n      this.requestRenderAllBound = this.requestRenderAll.bind(this);\n      this._initStatic(el, options);\n    },\n\n    /**\n     * Background color of canvas instance.\n     * Should be set via {@link fabric.StaticCanvas#setBackgroundColor}.\n     * @type {(String|fabric.Pattern)}\n     * @default\n     */\n    backgroundColor: '',\n\n    /**\n     * Background image of canvas instance.\n     * since 2.4.0 image caching is active, please when putting an image as background, add to the\n     * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom\n     * vale. As an alternative you can disable image objectCaching\n     * @type fabric.Image\n     * @default\n     */\n    backgroundImage: null,\n\n    /**\n     * Overlay color of canvas instance.\n     * Should be set via {@link fabric.StaticCanvas#setOverlayColor}\n     * @since 1.3.9\n     * @type {(String|fabric.Pattern)}\n     * @default\n     */\n    overlayColor: '',\n\n    /**\n     * Overlay image of canvas instance.\n     * since 2.4.0 image caching is active, please when putting an image as overlay, add to the\n     * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom\n     * vale. As an alternative you can disable image objectCaching\n     * @type fabric.Image\n     * @default\n     */\n    overlayImage: null,\n\n    /**\n     * Indicates whether toObject/toDatalessObject should include default values\n     * if set to false, takes precedence over the object value.\n     * @type Boolean\n     * @default\n     */\n    includeDefaultValues: true,\n\n    /**\n     * Indicates whether objects' state should be saved\n     * @type Boolean\n     * @default\n     */\n    stateful: false,\n\n    /**\n     * Indicates whether {@link fabric.Collection.add}, {@link fabric.Collection.insertAt} and {@link fabric.Collection.remove},\n     * {@link fabric.StaticCanvas.moveTo}, {@link fabric.StaticCanvas.clear} and many more, should also re-render canvas.\n     * Disabling this option will not give a performance boost when adding/removing a lot of objects to/from canvas at once\n     * since the renders are quequed and executed one per frame.\n     * Disabling is suggested anyway and managing the renders of the app manually is not a big effort ( canvas.requestRenderAll() )\n     * Left default to true to do not break documentation and old app, fiddles.\n     * @type Boolean\n     * @default\n     */\n    renderOnAddRemove: true,\n\n    /**\n     * Indicates whether object controls (borders/controls) are rendered above overlay image\n     * @type Boolean\n     * @default\n     */\n    controlsAboveOverlay: false,\n\n    /**\n     * Indicates whether the browser can be scrolled when using a touchscreen and dragging on the canvas\n     * @type Boolean\n     * @default\n     */\n    allowTouchScrolling: false,\n\n    /**\n     * Indicates whether this canvas will use image smoothing, this is on by default in browsers\n     * @type Boolean\n     * @default\n     */\n    imageSmoothingEnabled: true,\n\n    /**\n     * The transformation (in the format of Canvas transform) which focuses the viewport\n     * @type Array\n     * @default\n     */\n    viewportTransform: fabric.iMatrix.concat(),\n\n    /**\n     * if set to false background image is not affected by viewport transform\n     * @since 1.6.3\n     * @type Boolean\n     * @default\n     */\n    backgroundVpt: true,\n\n    /**\n     * if set to false overlya image is not affected by viewport transform\n     * @since 1.6.3\n     * @type Boolean\n     * @default\n     */\n    overlayVpt: true,\n\n    /**\n     * When true, canvas is scaled by devicePixelRatio for better rendering on retina screens\n     * @type Boolean\n     * @default\n     */\n    enableRetinaScaling: true,\n\n    /**\n     * Describe canvas element extension over design\n     * properties are tl,tr,bl,br.\n     * if canvas is not zoomed/panned those points are the four corner of canvas\n     * if canvas is viewportTransformed you those points indicate the extension\n     * of canvas element in plain untrasformed coordinates\n     * The coordinates get updated with @method calcViewportBoundaries.\n     * @memberOf fabric.StaticCanvas.prototype\n     */\n    vptCoords: { },\n\n    /**\n     * Based on vptCoords and object.aCoords, skip rendering of objects that\n     * are not included in current viewport.\n     * May greatly help in applications with crowded canvas and use of zoom/pan\n     * If One of the corner of the bounding box of the object is on the canvas\n     * the objects get rendered.\n     * @memberOf fabric.StaticCanvas.prototype\n     * @type Boolean\n     * @default\n     */\n    skipOffscreen: true,\n\n    /**\n     * a fabricObject that, without stroke define a clipping area with their shape. filled in black\n     * the clipPath object gets used when the canvas has rendered, and the context is placed in the\n     * top left corner of the canvas.\n     * clipPath will clip away controls, if you do not want this to happen use controlsAboveOverlay = true\n     * @type fabric.Object\n     */\n    clipPath: undefined,\n\n    /**\n     * @private\n     * @param {HTMLElement | String} el &lt;canvas> element to initialize instance on\n     * @param {Object} [options] Options object\n     */\n    _initStatic: function(el, options) {\n      var cb = this.requestRenderAllBound;\n      this._objects = [];\n      this._createLowerCanvas(el);\n      this._initOptions(options);\n      // only initialize retina scaling once\n      if (!this.interactive) {\n        this._initRetinaScaling();\n      }\n\n      if (options.overlayImage) {\n        this.setOverlayImage(options.overlayImage, cb);\n      }\n      if (options.backgroundImage) {\n        this.setBackgroundImage(options.backgroundImage, cb);\n      }\n      if (options.backgroundColor) {\n        this.setBackgroundColor(options.backgroundColor, cb);\n      }\n      if (options.overlayColor) {\n        this.setOverlayColor(options.overlayColor, cb);\n      }\n      this.calcOffset();\n    },\n\n    /**\n     * @private\n     */\n    _isRetinaScaling: function() {\n      return (fabric.devicePixelRatio !== 1 && this.enableRetinaScaling);\n    },\n\n    /**\n     * @private\n     * @return {Number} retinaScaling if applied, otherwise 1;\n     */\n    getRetinaScaling: function() {\n      return this._isRetinaScaling() ? fabric.devicePixelRatio : 1;\n    },\n\n    /**\n     * @private\n     */\n    _initRetinaScaling: function() {\n      if (!this._isRetinaScaling()) {\n        return;\n      }\n      var scaleRatio = fabric.devicePixelRatio;\n      this.__initRetinaScaling(scaleRatio, this.lowerCanvasEl, this.contextContainer);\n      if (this.upperCanvasEl) {\n        this.__initRetinaScaling(scaleRatio, this.upperCanvasEl, this.contextTop);\n      }\n    },\n\n    __initRetinaScaling: function(scaleRatio, canvas, context) {\n      canvas.setAttribute('width', this.width * scaleRatio);\n      canvas.setAttribute('height', this.height * scaleRatio);\n      context.scale(scaleRatio, scaleRatio);\n    },\n\n\n    /**\n     * Calculates canvas element offset relative to the document\n     * This method is also attached as \"resize\" event handler of window\n     * @return {fabric.Canvas} instance\n     * @chainable\n     */\n    calcOffset: function () {\n      this._offset = getElementOffset(this.lowerCanvasEl);\n      return this;\n    },\n\n    /**\n     * Sets {@link fabric.StaticCanvas#overlayImage|overlay image} for this canvas\n     * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set overlay to\n     * @param {Function} callback callback to invoke when image is loaded and set as an overlay\n     * @param {Object} [options] Optional options to set for the {@link fabric.Image|overlay image}.\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     * @see {@link http://jsfiddle.net/fabricjs/MnzHT/|jsFiddle demo}\n     * @example <caption>Normal overlayImage with left/top = 0</caption>\n     * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n     *   // Needed to position overlayImage at 0/0\n     *   originX: 'left',\n     *   originY: 'top'\n     * });\n     * @example <caption>overlayImage with different properties</caption>\n     * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n     *   opacity: 0.5,\n     *   angle: 45,\n     *   left: 400,\n     *   top: 400,\n     *   originX: 'left',\n     *   originY: 'top'\n     * });\n     * @example <caption>Stretched overlayImage #1 - width/height correspond to canvas width/height</caption>\n     * fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img, isError) {\n     *    img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'});\n     *    canvas.setOverlayImage(img, canvas.renderAll.bind(canvas));\n     * });\n     * @example <caption>Stretched overlayImage #2 - width/height correspond to canvas width/height</caption>\n     * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n     *   width: canvas.width,\n     *   height: canvas.height,\n     *   // Needed to position overlayImage at 0/0\n     *   originX: 'left',\n     *   originY: 'top'\n     * });\n     * @example <caption>overlayImage loaded from cross-origin</caption>\n     * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n     *   opacity: 0.5,\n     *   angle: 45,\n     *   left: 400,\n     *   top: 400,\n     *   originX: 'left',\n     *   originY: 'top',\n     *   crossOrigin: 'anonymous'\n     * });\n     */\n    setOverlayImage: function (image, callback, options) {\n      return this.__setBgOverlayImage('overlayImage', image, callback, options);\n    },\n\n    /**\n     * Sets {@link fabric.StaticCanvas#backgroundImage|background image} for this canvas\n     * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set background to\n     * @param {Function} callback Callback to invoke when image is loaded and set as background\n     * @param {Object} [options] Optional options to set for the {@link fabric.Image|background image}.\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     * @see {@link http://jsfiddle.net/djnr8o7a/28/|jsFiddle demo}\n     * @example <caption>Normal backgroundImage with left/top = 0</caption>\n     * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n     *   // Needed to position backgroundImage at 0/0\n     *   originX: 'left',\n     *   originY: 'top'\n     * });\n     * @example <caption>backgroundImage with different properties</caption>\n     * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n     *   opacity: 0.5,\n     *   angle: 45,\n     *   left: 400,\n     *   top: 400,\n     *   originX: 'left',\n     *   originY: 'top'\n     * });\n     * @example <caption>Stretched backgroundImage #1 - width/height correspond to canvas width/height</caption>\n     * fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img, isError) {\n     *    img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'});\n     *    canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas));\n     * });\n     * @example <caption>Stretched backgroundImage #2 - width/height correspond to canvas width/height</caption>\n     * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n     *   width: canvas.width,\n     *   height: canvas.height,\n     *   // Needed to position backgroundImage at 0/0\n     *   originX: 'left',\n     *   originY: 'top'\n     * });\n     * @example <caption>backgroundImage loaded from cross-origin</caption>\n     * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n     *   opacity: 0.5,\n     *   angle: 45,\n     *   left: 400,\n     *   top: 400,\n     *   originX: 'left',\n     *   originY: 'top',\n     *   crossOrigin: 'anonymous'\n     * });\n     */\n    // TODO: fix stretched examples\n    setBackgroundImage: function (image, callback, options) {\n      return this.__setBgOverlayImage('backgroundImage', image, callback, options);\n    },\n\n    /**\n     * Sets {@link fabric.StaticCanvas#overlayColor|foreground color} for this canvas\n     * @param {(String|fabric.Pattern)} overlayColor Color or pattern to set foreground color to\n     * @param {Function} callback Callback to invoke when foreground color is set\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     * @see {@link http://jsfiddle.net/fabricjs/pB55h/|jsFiddle demo}\n     * @example <caption>Normal overlayColor - color value</caption>\n     * canvas.setOverlayColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));\n     * @example <caption>fabric.Pattern used as overlayColor</caption>\n     * canvas.setOverlayColor({\n     *   source: 'http://fabricjs.com/assets/escheresque_ste.png'\n     * }, canvas.renderAll.bind(canvas));\n     * @example <caption>fabric.Pattern used as overlayColor with repeat and offset</caption>\n     * canvas.setOverlayColor({\n     *   source: 'http://fabricjs.com/assets/escheresque_ste.png',\n     *   repeat: 'repeat',\n     *   offsetX: 200,\n     *   offsetY: 100\n     * }, canvas.renderAll.bind(canvas));\n     */\n    setOverlayColor: function(overlayColor, callback) {\n      return this.__setBgOverlayColor('overlayColor', overlayColor, callback);\n    },\n\n    /**\n     * Sets {@link fabric.StaticCanvas#backgroundColor|background color} for this canvas\n     * @param {(String|fabric.Pattern)} backgroundColor Color or pattern to set background color to\n     * @param {Function} callback Callback to invoke when background color is set\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     * @see {@link http://jsfiddle.net/fabricjs/hXzvk/|jsFiddle demo}\n     * @example <caption>Normal backgroundColor - color value</caption>\n     * canvas.setBackgroundColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));\n     * @example <caption>fabric.Pattern used as backgroundColor</caption>\n     * canvas.setBackgroundColor({\n     *   source: 'http://fabricjs.com/assets/escheresque_ste.png'\n     * }, canvas.renderAll.bind(canvas));\n     * @example <caption>fabric.Pattern used as backgroundColor with repeat and offset</caption>\n     * canvas.setBackgroundColor({\n     *   source: 'http://fabricjs.com/assets/escheresque_ste.png',\n     *   repeat: 'repeat',\n     *   offsetX: 200,\n     *   offsetY: 100\n     * }, canvas.renderAll.bind(canvas));\n     */\n    setBackgroundColor: function(backgroundColor, callback) {\n      return this.__setBgOverlayColor('backgroundColor', backgroundColor, callback);\n    },\n\n    /**\n     * @private\n     * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundImage|backgroundImage}\n     * or {@link fabric.StaticCanvas#overlayImage|overlayImage})\n     * @param {(fabric.Image|String|null)} image fabric.Image instance, URL of an image or null to set background or overlay to\n     * @param {Function} callback Callback to invoke when image is loaded and set as background or overlay. The first argument is the created image, the second argument is a flag indicating whether an error occured or not.\n     * @param {Object} [options] Optional options to set for the {@link fabric.Image|image}.\n     */\n    __setBgOverlayImage: function(property, image, callback, options) {\n      if (typeof image === 'string') {\n        fabric.util.loadImage(image, function(img, isError) {\n          if (img) {\n            var instance = new fabric.Image(img, options);\n            this[property] = instance;\n            instance.canvas = this;\n          }\n          callback && callback(img, isError);\n        }, this, options && options.crossOrigin);\n      }\n      else {\n        options && image.setOptions(options);\n        this[property] = image;\n        image && (image.canvas = this);\n        callback && callback(image, false);\n      }\n\n      return this;\n    },\n\n    /**\n     * @private\n     * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundColor|backgroundColor}\n     * or {@link fabric.StaticCanvas#overlayColor|overlayColor})\n     * @param {(Object|String|null)} color Object with pattern information, color value or null\n     * @param {Function} [callback] Callback is invoked when color is set\n     */\n    __setBgOverlayColor: function(property, color, callback) {\n      this[property] = color;\n      this._initGradient(color, property);\n      this._initPattern(color, property, callback);\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _createCanvasElement: function() {\n      var element = createCanvasElement();\n      if (!element) {\n        throw CANVAS_INIT_ERROR;\n      }\n      if (!element.style) {\n        element.style = { };\n      }\n      if (typeof element.getContext === 'undefined') {\n        throw CANVAS_INIT_ERROR;\n      }\n      return element;\n    },\n\n    /**\n     * @private\n     * @param {Object} [options] Options object\n     */\n    _initOptions: function (options) {\n      var lowerCanvasEl = this.lowerCanvasEl;\n      this._setOptions(options);\n\n      this.width = this.width || parseInt(lowerCanvasEl.width, 10) || 0;\n      this.height = this.height || parseInt(lowerCanvasEl.height, 10) || 0;\n\n      if (!this.lowerCanvasEl.style) {\n        return;\n      }\n\n      lowerCanvasEl.width = this.width;\n      lowerCanvasEl.height = this.height;\n\n      lowerCanvasEl.style.width = this.width + 'px';\n      lowerCanvasEl.style.height = this.height + 'px';\n\n      this.viewportTransform = this.viewportTransform.slice();\n    },\n\n    /**\n     * Creates a bottom canvas\n     * @private\n     * @param {HTMLElement} [canvasEl]\n     */\n    _createLowerCanvas: function (canvasEl) {\n      // canvasEl === 'HTMLCanvasElement' does not work on jsdom/node\n      if (canvasEl && canvasEl.getContext) {\n        this.lowerCanvasEl = canvasEl;\n      }\n      else {\n        this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement();\n      }\n\n      fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas');\n\n      if (this.interactive) {\n        this._applyCanvasStyle(this.lowerCanvasEl);\n      }\n\n      this.contextContainer = this.lowerCanvasEl.getContext('2d');\n    },\n\n    /**\n     * Returns canvas width (in px)\n     * @return {Number}\n     */\n    getWidth: function () {\n      return this.width;\n    },\n\n    /**\n     * Returns canvas height (in px)\n     * @return {Number}\n     */\n    getHeight: function () {\n      return this.height;\n    },\n\n    /**\n     * Sets width of this canvas instance\n     * @param {Number|String} value                         Value to set width to\n     * @param {Object}        [options]                     Options object\n     * @param {Boolean}       [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n     * @param {Boolean}       [options.cssOnly=false]       Set the given dimensions only as css dimensions\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    setWidth: function (value, options) {\n      return this.setDimensions({ width: value }, options);\n    },\n\n    /**\n     * Sets height of this canvas instance\n     * @param {Number|String} value                         Value to set height to\n     * @param {Object}        [options]                     Options object\n     * @param {Boolean}       [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n     * @param {Boolean}       [options.cssOnly=false]       Set the given dimensions only as css dimensions\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    setHeight: function (value, options) {\n      return this.setDimensions({ height: value }, options);\n    },\n\n    /**\n     * Sets dimensions (width, height) of this canvas instance. when options.cssOnly flag active you should also supply the unit of measure (px/%/em)\n     * @param {Object}        dimensions                    Object with width/height properties\n     * @param {Number|String} [dimensions.width]            Width of canvas element\n     * @param {Number|String} [dimensions.height]           Height of canvas element\n     * @param {Object}        [options]                     Options object\n     * @param {Boolean}       [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n     * @param {Boolean}       [options.cssOnly=false]       Set the given dimensions only as css dimensions\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    setDimensions: function (dimensions, options) {\n      var cssValue;\n\n      options = options || {};\n\n      for (var prop in dimensions) {\n        cssValue = dimensions[prop];\n\n        if (!options.cssOnly) {\n          this._setBackstoreDimension(prop, dimensions[prop]);\n          cssValue += 'px';\n          this.hasLostContext = true;\n        }\n\n        if (!options.backstoreOnly) {\n          this._setCssDimension(prop, cssValue);\n        }\n      }\n      if (this._isCurrentlyDrawing) {\n        this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles();\n      }\n      this._initRetinaScaling();\n      this.calcOffset();\n\n      if (!options.cssOnly) {\n        this.requestRenderAll();\n      }\n\n      return this;\n    },\n\n    /**\n     * Helper for setting width/height\n     * @private\n     * @param {String} prop property (width|height)\n     * @param {Number} value value to set property to\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    _setBackstoreDimension: function (prop, value) {\n      this.lowerCanvasEl[prop] = value;\n\n      if (this.upperCanvasEl) {\n        this.upperCanvasEl[prop] = value;\n      }\n\n      if (this.cacheCanvasEl) {\n        this.cacheCanvasEl[prop] = value;\n      }\n\n      this[prop] = value;\n\n      return this;\n    },\n\n    /**\n     * Helper for setting css width/height\n     * @private\n     * @param {String} prop property (width|height)\n     * @param {String} value value to set property to\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    _setCssDimension: function (prop, value) {\n      this.lowerCanvasEl.style[prop] = value;\n\n      if (this.upperCanvasEl) {\n        this.upperCanvasEl.style[prop] = value;\n      }\n\n      if (this.wrapperEl) {\n        this.wrapperEl.style[prop] = value;\n      }\n\n      return this;\n    },\n\n    /**\n     * Returns canvas zoom level\n     * @return {Number}\n     */\n    getZoom: function () {\n      return this.viewportTransform[0];\n    },\n\n    /**\n     * Sets viewport transform of this canvas instance\n     * @param {Array} vpt the transform in the form of context.transform\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    setViewportTransform: function (vpt) {\n      var activeObject = this._activeObject, object, i, len;\n      this.viewportTransform = vpt;\n      for (i = 0, len = this._objects.length; i < len; i++) {\n        object = this._objects[i];\n        object.group || object.setCoords(true);\n      }\n      if (activeObject) {\n        activeObject.setCoords();\n      }\n      this.calcViewportBoundaries();\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * Sets zoom level of this canvas instance, zoom centered around point\n     * @param {fabric.Point} point to zoom with respect to\n     * @param {Number} value to set zoom to, less than 1 zooms out\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    zoomToPoint: function (point, value) {\n      // TODO: just change the scale, preserve other transformations\n      var before = point, vpt = this.viewportTransform.slice(0);\n      point = transformPoint(point, invertTransform(this.viewportTransform));\n      vpt[0] = value;\n      vpt[3] = value;\n      var after = transformPoint(point, vpt);\n      vpt[4] += before.x - after.x;\n      vpt[5] += before.y - after.y;\n      return this.setViewportTransform(vpt);\n    },\n\n    /**\n     * Sets zoom level of this canvas instance\n     * @param {Number} value to set zoom to, less than 1 zooms out\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    setZoom: function (value) {\n      this.zoomToPoint(new fabric.Point(0, 0), value);\n      return this;\n    },\n\n    /**\n     * Pan viewport so as to place point at top left corner of canvas\n     * @param {fabric.Point} point to move to\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    absolutePan: function (point) {\n      var vpt = this.viewportTransform.slice(0);\n      vpt[4] = -point.x;\n      vpt[5] = -point.y;\n      return this.setViewportTransform(vpt);\n    },\n\n    /**\n     * Pans viewpoint relatively\n     * @param {fabric.Point} point (position vector) to move by\n     * @return {fabric.Canvas} instance\n     * @chainable true\n     */\n    relativePan: function (point) {\n      return this.absolutePan(new fabric.Point(\n        -point.x - this.viewportTransform[4],\n        -point.y - this.viewportTransform[5]\n      ));\n    },\n\n    /**\n     * Returns &lt;canvas> element corresponding to this instance\n     * @return {HTMLCanvasElement}\n     */\n    getElement: function () {\n      return this.lowerCanvasEl;\n    },\n\n    /**\n     * @private\n     * @param {fabric.Object} obj Object that was added\n     */\n    _onObjectAdded: function(obj) {\n      this.stateful && obj.setupState();\n      obj._set('canvas', this);\n      obj.setCoords();\n      this.fire('object:added', { target: obj });\n      obj.fire('added');\n    },\n\n    /**\n     * @private\n     * @param {fabric.Object} obj Object that was removed\n     */\n    _onObjectRemoved: function(obj) {\n      this.fire('object:removed', { target: obj });\n      obj.fire('removed');\n      delete obj.canvas;\n    },\n\n    /**\n     * Clears specified context of canvas element\n     * @param {CanvasRenderingContext2D} ctx Context to clear\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    clearContext: function(ctx) {\n      ctx.clearRect(0, 0, this.width, this.height);\n      return this;\n    },\n\n    /**\n     * Returns context of canvas where objects are drawn\n     * @return {CanvasRenderingContext2D}\n     */\n    getContext: function () {\n      return this.contextContainer;\n    },\n\n    /**\n     * Clears all contexts (background, main, top) of an instance\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    clear: function () {\n      this._objects.length = 0;\n      this.backgroundImage = null;\n      this.overlayImage = null;\n      this.backgroundColor = '';\n      this.overlayColor = '';\n      if (this._hasITextHandlers) {\n        this.off('mouse:up', this._mouseUpITextHandler);\n        this._iTextInstances = null;\n        this._hasITextHandlers = false;\n      }\n      this.clearContext(this.contextContainer);\n      this.fire('canvas:cleared');\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * Renders the canvas\n     * @return {fabric.Canvas} instance\n     * @chainable\n     */\n    renderAll: function () {\n      var canvasToDrawOn = this.contextContainer;\n      this.renderCanvas(canvasToDrawOn, this._objects);\n      return this;\n    },\n\n    /**\n     * Function created to be instance bound at initialization\n     * used in requestAnimationFrame rendering\n     * Let the fabricJS call it. If you call it manually you could have more\n     * animationFrame stacking on to of each other\n     * for an imperative rendering, use canvas.renderAll\n     * @private\n     * @return {fabric.Canvas} instance\n     * @chainable\n     */\n    renderAndReset: function() {\n      this.isRendering = 0;\n      this.renderAll();\n    },\n\n    /**\n     * Append a renderAll request to next animation frame.\n     * unless one is already in progress, in that case nothing is done\n     * a boolean flag will avoid appending more.\n     * @return {fabric.Canvas} instance\n     * @chainable\n     */\n    requestRenderAll: function () {\n      if (!this.isRendering) {\n        this.isRendering = fabric.util.requestAnimFrame(this.renderAndResetBound);\n      }\n      return this;\n    },\n\n    /**\n     * Calculate the position of the 4 corner of canvas with current viewportTransform.\n     * helps to determinate when an object is in the current rendering viewport using\n     * object absolute coordinates ( aCoords )\n     * @return {Object} points.tl\n     * @chainable\n     */\n    calcViewportBoundaries: function() {\n      var points = { }, width = this.width, height = this.height,\n          iVpt = invertTransform(this.viewportTransform);\n      points.tl = transformPoint({ x: 0, y: 0 }, iVpt);\n      points.br = transformPoint({ x: width, y: height }, iVpt);\n      points.tr = new fabric.Point(points.br.x, points.tl.y);\n      points.bl = new fabric.Point(points.tl.x, points.br.y);\n      this.vptCoords = points;\n      return points;\n    },\n\n    cancelRequestedRender: function() {\n      if (this.isRendering) {\n        fabric.util.cancelAnimFrame(this.isRendering);\n        this.isRendering = 0;\n      }\n    },\n\n    /**\n     * Renders background, objects, overlay and controls.\n     * @param {CanvasRenderingContext2D} ctx\n     * @param {Array} objects to render\n     * @return {fabric.Canvas} instance\n     * @chainable\n     */\n    renderCanvas: function(ctx, objects) {\n      var v = this.viewportTransform, path = this.clipPath;\n      this.cancelRequestedRender();\n      this.calcViewportBoundaries();\n      this.clearContext(ctx);\n      fabric.util.setImageSmoothing(ctx, this.imageSmoothingEnabled);\n      this.fire('before:render', { ctx: ctx, });\n      this._renderBackground(ctx);\n\n      ctx.save();\n      //apply viewport transform once for all rendering process\n      ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n      this._renderObjects(ctx, objects);\n      ctx.restore();\n      if (!this.controlsAboveOverlay && this.interactive) {\n        this.drawControls(ctx);\n      }\n      if (path) {\n        path.canvas = this;\n        // needed to setup a couple of variables\n        path.shouldCache();\n        path._transformDone = true;\n        path.renderCache({ forClipping: true });\n        this.drawClipPathOnCanvas(ctx);\n      }\n      this._renderOverlay(ctx);\n      if (this.controlsAboveOverlay && this.interactive) {\n        this.drawControls(ctx);\n      }\n      this.fire('after:render', { ctx: ctx, });\n    },\n\n    /**\n     * Paint the cached clipPath on the lowerCanvasEl\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    drawClipPathOnCanvas: function(ctx) {\n      var v = this.viewportTransform, path = this.clipPath;\n      ctx.save();\n      ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n      // DEBUG: uncomment this line, comment the following\n      // ctx.globalAlpha = 0.4;\n      ctx.globalCompositeOperation = 'destination-in';\n      path.transform(ctx);\n      ctx.scale(1 / path.zoomX, 1 / path.zoomY);\n      ctx.drawImage(path._cacheCanvas, -path.cacheTranslationX, -path.cacheTranslationY);\n      ctx.restore();\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Array} objects to render\n     */\n    _renderObjects: function(ctx, objects) {\n      var i, len;\n      for (i = 0, len = objects.length; i < len; ++i) {\n        objects[i] && objects[i].render(ctx);\n      }\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {string} property 'background' or 'overlay'\n     */\n    _renderBackgroundOrOverlay: function(ctx, property) {\n      var fill = this[property + 'Color'], object = this[property + 'Image'],\n          v = this.viewportTransform, needsVpt = this[property + 'Vpt'];\n      if (!fill && !object) {\n        return;\n      }\n      if (fill) {\n        ctx.save();\n        ctx.beginPath();\n        ctx.moveTo(0, 0);\n        ctx.lineTo(this.width, 0);\n        ctx.lineTo(this.width, this.height);\n        ctx.lineTo(0, this.height);\n        ctx.closePath();\n        ctx.fillStyle = fill.toLive\n          ? fill.toLive(ctx, this)\n          : fill;\n        if (needsVpt) {\n          ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n        }\n        ctx.transform(1, 0, 0, 1, fill.offsetX || 0, fill.offsetY || 0);\n        var m = fill.gradientTransform || fill.patternTransform;\n        m && ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\n        ctx.fill();\n        ctx.restore();\n      }\n      if (object) {\n        ctx.save();\n        if (needsVpt) {\n          ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n        }\n        object.render(ctx);\n        ctx.restore();\n      }\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderBackground: function(ctx) {\n      this._renderBackgroundOrOverlay(ctx, 'background');\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderOverlay: function(ctx) {\n      this._renderBackgroundOrOverlay(ctx, 'overlay');\n    },\n\n    /**\n     * Returns coordinates of a center of canvas.\n     * Returned value is an object with top and left properties\n     * @return {Object} object with \"top\" and \"left\" number values\n     */\n    getCenter: function () {\n      return {\n        top: this.height / 2,\n        left: this.width / 2\n      };\n    },\n\n    /**\n     * Centers object horizontally in the canvas\n     * @param {fabric.Object} object Object to center horizontally\n     * @return {fabric.Canvas} thisArg\n     */\n    centerObjectH: function (object) {\n      return this._centerObject(object, new fabric.Point(this.getCenter().left, object.getCenterPoint().y));\n    },\n\n    /**\n     * Centers object vertically in the canvas\n     * @param {fabric.Object} object Object to center vertically\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    centerObjectV: function (object) {\n      return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenter().top));\n    },\n\n    /**\n     * Centers object vertically and horizontally in the canvas\n     * @param {fabric.Object} object Object to center vertically and horizontally\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    centerObject: function(object) {\n      var center = this.getCenter();\n\n      return this._centerObject(object, new fabric.Point(center.left, center.top));\n    },\n\n    /**\n     * Centers object vertically and horizontally in the viewport\n     * @param {fabric.Object} object Object to center vertically and horizontally\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    viewportCenterObject: function(object) {\n      var vpCenter = this.getVpCenter();\n\n      return this._centerObject(object, vpCenter);\n    },\n\n    /**\n     * Centers object horizontally in the viewport, object.top is unchanged\n     * @param {fabric.Object} object Object to center vertically and horizontally\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    viewportCenterObjectH: function(object) {\n      var vpCenter = this.getVpCenter();\n      this._centerObject(object, new fabric.Point(vpCenter.x, object.getCenterPoint().y));\n      return this;\n    },\n\n    /**\n     * Centers object Vertically in the viewport, object.top is unchanged\n     * @param {fabric.Object} object Object to center vertically and horizontally\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    viewportCenterObjectV: function(object) {\n      var vpCenter = this.getVpCenter();\n\n      return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, vpCenter.y));\n    },\n\n    /**\n     * Calculate the point in canvas that correspond to the center of actual viewport.\n     * @return {fabric.Point} vpCenter, viewport center\n     * @chainable\n     */\n    getVpCenter: function() {\n      var center = this.getCenter(),\n          iVpt = invertTransform(this.viewportTransform);\n      return transformPoint({ x: center.left, y: center.top }, iVpt);\n    },\n\n    /**\n     * @private\n     * @param {fabric.Object} object Object to center\n     * @param {fabric.Point} center Center point\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    _centerObject: function(object, center) {\n      object.setPositionByOrigin(center, 'center', 'center');\n      object.setCoords();\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * Returs dataless JSON representation of canvas\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {String} json string\n     */\n    toDatalessJSON: function (propertiesToInclude) {\n      return this.toDatalessObject(propertiesToInclude);\n    },\n\n    /**\n     * Returns object representation of canvas\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function (propertiesToInclude) {\n      return this._toObjectMethod('toObject', propertiesToInclude);\n    },\n\n    /**\n     * Returns dataless object representation of canvas\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toDatalessObject: function (propertiesToInclude) {\n      return this._toObjectMethod('toDatalessObject', propertiesToInclude);\n    },\n\n    /**\n     * @private\n     */\n    _toObjectMethod: function (methodName, propertiesToInclude) {\n\n      var clipPath = this.clipPath, data = {\n        version: fabric.version,\n        objects: this._toObjects(methodName, propertiesToInclude),\n      };\n      if (clipPath) {\n        data.clipPath = this._toObject(this.clipPath, methodName, propertiesToInclude);\n      }\n      extend(data, this.__serializeBgOverlay(methodName, propertiesToInclude));\n\n      fabric.util.populateWithProperties(this, data, propertiesToInclude);\n\n      return data;\n    },\n\n    /**\n     * @private\n     */\n    _toObjects: function(methodName, propertiesToInclude) {\n      return this._objects.filter(function(object) {\n        return !object.excludeFromExport;\n      }).map(function(instance) {\n        return this._toObject(instance, methodName, propertiesToInclude);\n      }, this);\n    },\n\n    /**\n     * @private\n     */\n    _toObject: function(instance, methodName, propertiesToInclude) {\n      var originalValue;\n\n      if (!this.includeDefaultValues) {\n        originalValue = instance.includeDefaultValues;\n        instance.includeDefaultValues = false;\n      }\n\n      var object = instance[methodName](propertiesToInclude);\n      if (!this.includeDefaultValues) {\n        instance.includeDefaultValues = originalValue;\n      }\n      return object;\n    },\n\n    /**\n     * @private\n     */\n    __serializeBgOverlay: function(methodName, propertiesToInclude) {\n      var data = { }, bgImage = this.backgroundImage, overlay = this.overlayImage;\n\n      if (this.backgroundColor) {\n        data.background = this.backgroundColor.toObject\n          ? this.backgroundColor.toObject(propertiesToInclude)\n          : this.backgroundColor;\n      }\n\n      if (this.overlayColor) {\n        data.overlay = this.overlayColor.toObject\n          ? this.overlayColor.toObject(propertiesToInclude)\n          : this.overlayColor;\n      }\n      if (bgImage && !bgImage.excludeFromExport) {\n        data.backgroundImage = this._toObject(bgImage, methodName, propertiesToInclude);\n      }\n      if (overlay && !overlay.excludeFromExport) {\n        data.overlayImage = this._toObject(overlay, methodName, propertiesToInclude);\n      }\n\n      return data;\n    },\n\n    /* _TO_SVG_START_ */\n    /**\n     * When true, getSvgTransform() will apply the StaticCanvas.viewportTransform to the SVG transformation. When true,\n     * a zoomed canvas will then produce zoomed SVG output.\n     * @type Boolean\n     * @default\n     */\n    svgViewportTransformation: true,\n\n    /**\n     * Returns SVG representation of canvas\n     * @function\n     * @param {Object} [options] Options object for SVG output\n     * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included\n     * @param {Object} [options.viewBox] SVG viewbox object\n     * @param {Number} [options.viewBox.x] x-cooridnate of viewbox\n     * @param {Number} [options.viewBox.y] y-coordinate of viewbox\n     * @param {Number} [options.viewBox.width] Width of viewbox\n     * @param {Number} [options.viewBox.height] Height of viewbox\n     * @param {String} [options.encoding=UTF-8] Encoding of SVG output\n     * @param {String} [options.width] desired width of svg with or without units\n     * @param {String} [options.height] desired height of svg with or without units\n     * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation.\n     * @return {String} SVG string\n     * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}\n     * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo}\n     * @example <caption>Normal SVG output</caption>\n     * var svg = canvas.toSVG();\n     * @example <caption>SVG output without preamble (without &lt;?xml ../>)</caption>\n     * var svg = canvas.toSVG({suppressPreamble: true});\n     * @example <caption>SVG output with viewBox attribute</caption>\n     * var svg = canvas.toSVG({\n     *   viewBox: {\n     *     x: 100,\n     *     y: 100,\n     *     width: 200,\n     *     height: 300\n     *   }\n     * });\n     * @example <caption>SVG output with different encoding (default: UTF-8)</caption>\n     * var svg = canvas.toSVG({encoding: 'ISO-8859-1'});\n     * @example <caption>Modify SVG output with reviver function</caption>\n     * var svg = canvas.toSVG(null, function(svg) {\n     *   return svg.replace('stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; ', '');\n     * });\n     */\n    toSVG: function(options, reviver) {\n      options || (options = { });\n      options.reviver = reviver;\n      var markup = [];\n\n      this._setSVGPreamble(markup, options);\n      this._setSVGHeader(markup, options);\n      if (this.clipPath) {\n        markup.push('<g clip-path=\"url(#' + this.clipPath.clipPathId + ')\" >\\n');\n      }\n      this._setSVGBgOverlayColor(markup, 'background');\n      this._setSVGBgOverlayImage(markup, 'backgroundImage', reviver);\n      this._setSVGObjects(markup, reviver);\n      if (this.clipPath) {\n        markup.push('</g>\\n');\n      }\n      this._setSVGBgOverlayColor(markup, 'overlay');\n      this._setSVGBgOverlayImage(markup, 'overlayImage', reviver);\n\n      markup.push('</svg>');\n\n      return markup.join('');\n    },\n\n    /**\n     * @private\n     */\n    _setSVGPreamble: function(markup, options) {\n      if (options.suppressPreamble) {\n        return;\n      }\n      markup.push(\n        '<?xml version=\"1.0\" encoding=\"', (options.encoding || 'UTF-8'), '\" standalone=\"no\" ?>\\n',\n        '<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ',\n        '\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\\n'\n      );\n    },\n\n    /**\n     * @private\n     */\n    _setSVGHeader: function(markup, options) {\n      var width = options.width || this.width,\n          height = options.height || this.height,\n          vpt, viewBox = 'viewBox=\"0 0 ' + this.width + ' ' + this.height + '\" ',\n          NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n\n      if (options.viewBox) {\n        viewBox = 'viewBox=\"' +\n                options.viewBox.x + ' ' +\n                options.viewBox.y + ' ' +\n                options.viewBox.width + ' ' +\n                options.viewBox.height + '\" ';\n      }\n      else {\n        if (this.svgViewportTransformation) {\n          vpt = this.viewportTransform;\n          viewBox = 'viewBox=\"' +\n                  toFixed(-vpt[4] / vpt[0], NUM_FRACTION_DIGITS) + ' ' +\n                  toFixed(-vpt[5] / vpt[3], NUM_FRACTION_DIGITS) + ' ' +\n                  toFixed(this.width / vpt[0], NUM_FRACTION_DIGITS) + ' ' +\n                  toFixed(this.height / vpt[3], NUM_FRACTION_DIGITS) + '\" ';\n        }\n      }\n\n      markup.push(\n        '<svg ',\n        'xmlns=\"http://www.w3.org/2000/svg\" ',\n        'xmlns:xlink=\"http://www.w3.org/1999/xlink\" ',\n        'version=\"1.1\" ',\n        'width=\"', width, '\" ',\n        'height=\"', height, '\" ',\n        viewBox,\n        'xml:space=\"preserve\">\\n',\n        '<desc>Created with Fabric.js ', fabric.version, '</desc>\\n',\n        '<defs>\\n',\n        this.createSVGFontFacesMarkup(),\n        this.createSVGRefElementsMarkup(),\n        this.createSVGClipPathMarkup(options),\n        '</defs>\\n'\n      );\n    },\n\n    createSVGClipPathMarkup: function(options) {\n      var clipPath = this.clipPath;\n      if (clipPath) {\n        clipPath.clipPathId = 'CLIPPATH_' + fabric.Object.__uid++;\n        return  '<clipPath id=\"' + clipPath.clipPathId + '\" >\\n' +\n          this.clipPath.toClipPathSVG(options.reviver) +\n          '</clipPath>\\n';\n      }\n      return '';\n    },\n\n    /**\n     * Creates markup containing SVG referenced elements like patterns, gradients etc.\n     * @return {String}\n     */\n    createSVGRefElementsMarkup: function() {\n      var _this = this,\n          markup = ['background', 'overlay'].map(function(prop) {\n            var fill = _this[prop + 'Color'];\n            if (fill && fill.toLive) {\n              var shouldTransform = _this[prop + 'Vpt'], vpt = _this.viewportTransform,\n                  object = {\n                    width: _this.width / (shouldTransform ? vpt[0] : 1),\n                    height: _this.height / (shouldTransform ? vpt[3] : 1)\n                  };\n              return fill.toSVG(\n                object,\n                { additionalTransform: shouldTransform ? fabric.util.matrixToSVG(vpt) : '' }\n              );\n            }\n          });\n      return markup.join('');\n    },\n\n    /**\n     * Creates markup containing SVG font faces,\n     * font URLs for font faces must be collected by developers\n     * and are not extracted from the DOM by fabricjs\n     * @param {Array} objects Array of fabric objects\n     * @return {String}\n     */\n    createSVGFontFacesMarkup: function() {\n      var markup = '', fontList = { }, obj, fontFamily,\n          style, row, rowIndex, _char, charIndex, i, len,\n          fontPaths = fabric.fontPaths, objects = [];\n\n      this._objects.forEach(function add(object) {\n        objects.push(object);\n        if (object._objects) {\n          object._objects.forEach(add);\n        }\n      });\n\n      for (i = 0, len = objects.length; i < len; i++) {\n        obj = objects[i];\n        fontFamily = obj.fontFamily;\n        if (obj.type.indexOf('text') === -1 || fontList[fontFamily] || !fontPaths[fontFamily]) {\n          continue;\n        }\n        fontList[fontFamily] = true;\n        if (!obj.styles) {\n          continue;\n        }\n        style = obj.styles;\n        for (rowIndex in style) {\n          row = style[rowIndex];\n          for (charIndex in row) {\n            _char = row[charIndex];\n            fontFamily = _char.fontFamily;\n            if (!fontList[fontFamily] && fontPaths[fontFamily]) {\n              fontList[fontFamily] = true;\n            }\n          }\n        }\n      }\n\n      for (var j in fontList) {\n        markup += [\n          '\\t\\t@font-face {\\n',\n          '\\t\\t\\tfont-family: \\'', j, '\\';\\n',\n          '\\t\\t\\tsrc: url(\\'', fontPaths[j], '\\');\\n',\n          '\\t\\t}\\n'\n        ].join('');\n      }\n\n      if (markup) {\n        markup = [\n          '\\t<style type=\"text/css\">',\n          '<![CDATA[\\n',\n          markup,\n          ']]>',\n          '</style>\\n'\n        ].join('');\n      }\n\n      return markup;\n    },\n\n    /**\n     * @private\n     */\n    _setSVGObjects: function(markup, reviver) {\n      var instance, i, len, objects = this._objects;\n      for (i = 0, len = objects.length; i < len; i++) {\n        instance = objects[i];\n        if (instance.excludeFromExport) {\n          continue;\n        }\n        this._setSVGObject(markup, instance, reviver);\n      }\n    },\n\n    /**\n     * @private\n     */\n    _setSVGObject: function(markup, instance, reviver) {\n      markup.push(instance.toSVG(reviver));\n    },\n\n    /**\n     * @private\n     */\n    _setSVGBgOverlayImage: function(markup, property, reviver) {\n      if (this[property] && !this[property].excludeFromExport && this[property].toSVG) {\n        markup.push(this[property].toSVG(reviver));\n      }\n    },\n\n    /**\n     * @private\n     */\n    _setSVGBgOverlayColor: function(markup, property) {\n      var filler = this[property + 'Color'], vpt = this.viewportTransform, finalWidth = this.width,\n          finalHeight = this.height;\n      if (!filler) {\n        return;\n      }\n      if (filler.toLive) {\n        var repeat = filler.repeat, iVpt = fabric.util.invertTransform(vpt), shouldInvert = this[property + 'Vpt'],\n            additionalTransform = shouldInvert ? fabric.util.matrixToSVG(iVpt) : '';\n        markup.push(\n          '<rect transform=\"' + additionalTransform + ' translate(', finalWidth / 2, ',', finalHeight / 2, ')\"',\n          ' x=\"', filler.offsetX - finalWidth / 2,\n          '\" y=\"', filler.offsetY - finalHeight / 2, '\" ',\n          'width=\"',\n          (repeat === 'repeat-y' || repeat === 'no-repeat'\n            ? filler.source.width\n            : finalWidth ),\n          '\" height=\"',\n          (repeat === 'repeat-x' || repeat === 'no-repeat'\n            ? filler.source.height\n            : finalHeight),\n          '\" fill=\"url(#SVGID_' + filler.id + ')\"',\n          '></rect>\\n'\n        );\n      }\n      else {\n        markup.push(\n          '<rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" ',\n          'fill=\"', filler, '\"',\n          '></rect>\\n'\n        );\n      }\n    },\n    /* _TO_SVG_END_ */\n\n    /**\n     * Moves an object or the objects of a multiple selection\n     * to the bottom of the stack of drawn objects\n     * @param {fabric.Object} object Object to send to back\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    sendToBack: function (object) {\n      if (!object) {\n        return this;\n      }\n      var activeSelection = this._activeObject,\n          i, obj, objs;\n      if (object === activeSelection && object.type === 'activeSelection') {\n        objs = activeSelection._objects;\n        for (i = objs.length; i--;) {\n          obj = objs[i];\n          removeFromArray(this._objects, obj);\n          this._objects.unshift(obj);\n        }\n      }\n      else {\n        removeFromArray(this._objects, object);\n        this._objects.unshift(object);\n      }\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * Moves an object or the objects of a multiple selection\n     * to the top of the stack of drawn objects\n     * @param {fabric.Object} object Object to send\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    bringToFront: function (object) {\n      if (!object) {\n        return this;\n      }\n      var activeSelection = this._activeObject,\n          i, obj, objs;\n      if (object === activeSelection && object.type === 'activeSelection') {\n        objs = activeSelection._objects;\n        for (i = 0; i < objs.length; i++) {\n          obj = objs[i];\n          removeFromArray(this._objects, obj);\n          this._objects.push(obj);\n        }\n      }\n      else {\n        removeFromArray(this._objects, object);\n        this._objects.push(object);\n      }\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * Moves an object or a selection down in stack of drawn objects\n     * An optional paramter, intersecting allowes to move the object in behind\n     * the first intersecting object. Where intersection is calculated with\n     * bounding box. If no intersection is found, there will not be change in the\n     * stack.\n     * @param {fabric.Object} object Object to send\n     * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    sendBackwards: function (object, intersecting) {\n      if (!object) {\n        return this;\n      }\n      var activeSelection = this._activeObject,\n          i, obj, idx, newIdx, objs, objsMoved = 0;\n\n      if (object === activeSelection && object.type === 'activeSelection') {\n        objs = activeSelection._objects;\n        for (i = 0; i < objs.length; i++) {\n          obj = objs[i];\n          idx = this._objects.indexOf(obj);\n          if (idx > 0 + objsMoved) {\n            newIdx = idx - 1;\n            removeFromArray(this._objects, obj);\n            this._objects.splice(newIdx, 0, obj);\n          }\n          objsMoved++;\n        }\n      }\n      else {\n        idx = this._objects.indexOf(object);\n        if (idx !== 0) {\n          // if object is not on the bottom of stack\n          newIdx = this._findNewLowerIndex(object, idx, intersecting);\n          removeFromArray(this._objects, object);\n          this._objects.splice(newIdx, 0, object);\n        }\n      }\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _findNewLowerIndex: function(object, idx, intersecting) {\n      var newIdx, i;\n\n      if (intersecting) {\n        newIdx = idx;\n\n        // traverse down the stack looking for the nearest intersecting object\n        for (i = idx - 1; i >= 0; --i) {\n\n          var isIntersecting = object.intersectsWithObject(this._objects[i]) ||\n                               object.isContainedWithinObject(this._objects[i]) ||\n                               this._objects[i].isContainedWithinObject(object);\n\n          if (isIntersecting) {\n            newIdx = i;\n            break;\n          }\n        }\n      }\n      else {\n        newIdx = idx - 1;\n      }\n\n      return newIdx;\n    },\n\n    /**\n     * Moves an object or a selection up in stack of drawn objects\n     * An optional paramter, intersecting allowes to move the object in front\n     * of the first intersecting object. Where intersection is calculated with\n     * bounding box. If no intersection is found, there will not be change in the\n     * stack.\n     * @param {fabric.Object} object Object to send\n     * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    bringForward: function (object, intersecting) {\n      if (!object) {\n        return this;\n      }\n      var activeSelection = this._activeObject,\n          i, obj, idx, newIdx, objs, objsMoved = 0;\n\n      if (object === activeSelection && object.type === 'activeSelection') {\n        objs = activeSelection._objects;\n        for (i = objs.length; i--;) {\n          obj = objs[i];\n          idx = this._objects.indexOf(obj);\n          if (idx < this._objects.length - 1 - objsMoved) {\n            newIdx = idx + 1;\n            removeFromArray(this._objects, obj);\n            this._objects.splice(newIdx, 0, obj);\n          }\n          objsMoved++;\n        }\n      }\n      else {\n        idx = this._objects.indexOf(object);\n        if (idx !== this._objects.length - 1) {\n          // if object is not on top of stack (last item in an array)\n          newIdx = this._findNewUpperIndex(object, idx, intersecting);\n          removeFromArray(this._objects, object);\n          this._objects.splice(newIdx, 0, object);\n        }\n      }\n      this.renderOnAddRemove && this.requestRenderAll();\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _findNewUpperIndex: function(object, idx, intersecting) {\n      var newIdx, i, len;\n\n      if (intersecting) {\n        newIdx = idx;\n\n        // traverse up the stack looking for the nearest intersecting object\n        for (i = idx + 1, len = this._objects.length; i < len; ++i) {\n\n          var isIntersecting = object.intersectsWithObject(this._objects[i]) ||\n                               object.isContainedWithinObject(this._objects[i]) ||\n                               this._objects[i].isContainedWithinObject(object);\n\n          if (isIntersecting) {\n            newIdx = i;\n            break;\n          }\n        }\n      }\n      else {\n        newIdx = idx + 1;\n      }\n\n      return newIdx;\n    },\n\n    /**\n     * Moves an object to specified level in stack of drawn objects\n     * @param {fabric.Object} object Object to send\n     * @param {Number} index Position to move to\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    moveTo: function (object, index) {\n      removeFromArray(this._objects, object);\n      this._objects.splice(index, 0, object);\n      return this.renderOnAddRemove && this.requestRenderAll();\n    },\n\n    /**\n     * Clears a canvas element and dispose objects\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    dispose: function () {\n      // cancel eventually ongoing renders\n      if (this.isRendering) {\n        fabric.util.cancelAnimFrame(this.isRendering);\n        this.isRendering = 0;\n      }\n      this.forEachObject(function(object) {\n        object.dispose && object.dispose();\n      });\n      this._objects = [];\n      if (this.backgroundImage && this.backgroundImage.dispose) {\n        this.backgroundImage.dispose();\n      }\n      this.backgroundImage = null;\n      if (this.overlayImage && this.overlayImage.dispose) {\n        this.overlayImage.dispose();\n      }\n      this.overlayImage = null;\n      this._iTextInstances = null;\n      this.contextContainer = null;\n      fabric.util.cleanUpJsdomNode(this.lowerCanvasEl);\n      this.lowerCanvasEl = undefined;\n      return this;\n    },\n\n    /**\n     * Returns a string representation of an instance\n     * @return {String} string representation of an instance\n     */\n    toString: function () {\n      return '#<fabric.Canvas (' + this.complexity() + '): ' +\n               '{ objects: ' + this._objects.length + ' }>';\n    }\n  });\n\n  extend(fabric.StaticCanvas.prototype, fabric.Observable);\n  extend(fabric.StaticCanvas.prototype, fabric.Collection);\n  extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter);\n\n  extend(fabric.StaticCanvas, /** @lends fabric.StaticCanvas */ {\n\n    /**\n     * @static\n     * @type String\n     * @default\n     */\n    EMPTY_JSON: '{\"objects\": [], \"background\": \"white\"}',\n\n    /**\n     * Provides a way to check support of some of the canvas methods\n     * (either those of HTMLCanvasElement itself, or rendering context)\n     *\n     * @param {String} methodName Method to check support for;\n     *                            Could be one of \"setLineDash\"\n     * @return {Boolean | null} `true` if method is supported (or at least exists),\n     *                          `null` if canvas element or context can not be initialized\n     */\n    supports: function (methodName) {\n      var el = createCanvasElement();\n\n      if (!el || !el.getContext) {\n        return null;\n      }\n\n      var ctx = el.getContext('2d');\n      if (!ctx) {\n        return null;\n      }\n\n      switch (methodName) {\n\n        case 'setLineDash':\n          return typeof ctx.setLineDash !== 'undefined';\n\n        default:\n          return null;\n      }\n    }\n  });\n\n  /**\n   * Returns JSON representation of canvas\n   * @function\n   * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n   * @return {String} JSON string\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}\n   * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo}\n   * @example <caption>JSON without additional properties</caption>\n   * var json = canvas.toJSON();\n   * @example <caption>JSON with additional properties included</caption>\n   * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY']);\n   * @example <caption>JSON without default values</caption>\n   * canvas.includeDefaultValues = false;\n   * var json = canvas.toJSON();\n   */\n  fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject;\n\n  if (fabric.isLikelyNode) {\n    fabric.StaticCanvas.prototype.createPNGStream = function() {\n      var impl = getNodeCanvas(this.lowerCanvasEl);\n      return impl && impl.createPNGStream();\n    };\n    fabric.StaticCanvas.prototype.createJPEGStream = function(opts) {\n      var impl = getNodeCanvas(this.lowerCanvasEl);\n      return impl && impl.createJPEGStream(opts);\n    };\n  }\n})();\n\n\n/**\n * BaseBrush class\n * @class fabric.BaseBrush\n * @see {@link http://fabricjs.com/freedrawing|Freedrawing demo}\n */\nfabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype */ {\n\n  /**\n   * Color of a brush\n   * @type String\n   * @default\n   */\n  color: 'rgb(0, 0, 0)',\n\n  /**\n   * Width of a brush, has to be a Number, no string literals\n   * @type Number\n   * @default\n   */\n  width: 1,\n\n  /**\n   * Shadow object representing shadow of this shape.\n   * <b>Backwards incompatibility note:</b> This property replaces \"shadowColor\" (String), \"shadowOffsetX\" (Number),\n   * \"shadowOffsetY\" (Number) and \"shadowBlur\" (Number) since v1.2.12\n   * @type fabric.Shadow\n   * @default\n   */\n  shadow: null,\n\n  /**\n   * Line endings style of a brush (one of \"butt\", \"round\", \"square\")\n   * @type String\n   * @default\n   */\n  strokeLineCap: 'round',\n\n  /**\n   * Corner style of a brush (one of \"bevel\", \"round\", \"miter\")\n   * @type String\n   * @default\n   */\n  strokeLineJoin: 'round',\n\n  /**\n   * Maximum miter length (used for strokeLineJoin = \"miter\") of a brush's\n   * @type Number\n   * @default\n   */\n  strokeMiterLimit:         10,\n\n  /**\n   * Stroke Dash Array.\n   * @type Array\n   * @default\n   */\n  strokeDashArray: null,\n\n  /**\n   * Sets brush styles\n   * @private\n   */\n  _setBrushStyles: function() {\n    var ctx = this.canvas.contextTop;\n    ctx.strokeStyle = this.color;\n    ctx.lineWidth = this.width;\n    ctx.lineCap = this.strokeLineCap;\n    ctx.miterLimit = this.strokeMiterLimit;\n    ctx.lineJoin = this.strokeLineJoin;\n    if (fabric.StaticCanvas.supports('setLineDash')) {\n      ctx.setLineDash(this.strokeDashArray || []);\n    }\n  },\n\n  /**\n   * Sets the transformation on given context\n   * @param {RenderingContext2d} ctx context to render on\n   * @private\n   */\n  _saveAndTransform: function(ctx) {\n    var v = this.canvas.viewportTransform;\n    ctx.save();\n    ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n  },\n\n  /**\n   * Sets brush shadow styles\n   * @private\n   */\n  _setShadow: function() {\n    if (!this.shadow) {\n      return;\n    }\n\n    var canvas = this.canvas,\n        shadow = this.shadow,\n        ctx = canvas.contextTop,\n        zoom = canvas.getZoom();\n    if (canvas && canvas._isRetinaScaling()) {\n      zoom *= fabric.devicePixelRatio;\n    }\n\n    ctx.shadowColor = shadow.color;\n    ctx.shadowBlur = shadow.blur * zoom;\n    ctx.shadowOffsetX = shadow.offsetX * zoom;\n    ctx.shadowOffsetY = shadow.offsetY * zoom;\n  },\n\n  needsFullRender: function() {\n    var color = new fabric.Color(this.color);\n    return color.getAlpha() < 1 || !!this.shadow;\n  },\n\n  /**\n   * Removes brush shadow styles\n   * @private\n   */\n  _resetShadow: function() {\n    var ctx = this.canvas.contextTop;\n\n    ctx.shadowColor = '';\n    ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;\n  }\n});\n\n\n(function() {\n  /**\n   * PencilBrush class\n   * @class fabric.PencilBrush\n   * @extends fabric.BaseBrush\n   */\n  fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.PencilBrush.prototype */ {\n\n    /**\n     * Discard points that are less than `decimate` pixel distant from each other\n     * @type Number\n     * @default 0.4\n     */\n    decimate: 0.4,\n\n    /**\n     * Constructor\n     * @param {fabric.Canvas} canvas\n     * @return {fabric.PencilBrush} Instance of a pencil brush\n     */\n    initialize: function(canvas) {\n      this.canvas = canvas;\n      this._points = [];\n    },\n\n    /**\n     * Invoked inside on mouse down and mouse move\n     * @param {Object} pointer\n     */\n    _drawSegment: function (ctx, p1, p2) {\n      var midPoint = p1.midPointFrom(p2);\n      ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);\n      return midPoint;\n    },\n\n    /**\n     * Inovoked on mouse down\n     * @param {Object} pointer\n     */\n    onMouseDown: function(pointer, options) {\n      if (!this.canvas._isMainEvent(options.e)) {\n        return;\n      }\n      this._prepareForDrawing(pointer);\n      // capture coordinates immediately\n      // this allows to draw dots (when movement never occurs)\n      this._captureDrawingPath(pointer);\n      this._render();\n    },\n\n    /**\n     * Inovoked on mouse move\n     * @param {Object} pointer\n     */\n    onMouseMove: function(pointer, options) {\n      if (!this.canvas._isMainEvent(options.e)) {\n        return;\n      }\n      if (this._captureDrawingPath(pointer) && this._points.length > 1) {\n        if (this.needsFullRender()) {\n          // redraw curve\n          // clear top canvas\n          this.canvas.clearContext(this.canvas.contextTop);\n          this._render();\n        }\n        else {\n          var points = this._points, length = points.length, ctx = this.canvas.contextTop;\n          // draw the curve update\n          this._saveAndTransform(ctx);\n          if (this.oldEnd) {\n            ctx.beginPath();\n            ctx.moveTo(this.oldEnd.x, this.oldEnd.y);\n          }\n          this.oldEnd = this._drawSegment(ctx, points[length - 2], points[length - 1], true);\n          ctx.stroke();\n          ctx.restore();\n        }\n      }\n    },\n\n    /**\n     * Invoked on mouse up\n     */\n    onMouseUp: function(options) {\n      if (!this.canvas._isMainEvent(options.e)) {\n        return true;\n      }\n      this.oldEnd = undefined;\n      this._finalizeAndAddPath();\n      return false;\n    },\n\n    /**\n     * @private\n     * @param {Object} pointer Actual mouse position related to the canvas.\n     */\n    _prepareForDrawing: function(pointer) {\n\n      var p = new fabric.Point(pointer.x, pointer.y);\n\n      this._reset();\n      this._addPoint(p);\n      this.canvas.contextTop.moveTo(p.x, p.y);\n    },\n\n    /**\n     * @private\n     * @param {fabric.Point} point Point to be added to points array\n     */\n    _addPoint: function(point) {\n      if (this._points.length > 1 && point.eq(this._points[this._points.length - 1])) {\n        return false;\n      }\n      this._points.push(point);\n      return true;\n    },\n\n    /**\n     * Clear points array and set contextTop canvas style.\n     * @private\n     */\n    _reset: function() {\n      this._points = [];\n      this._setBrushStyles();\n      this._setShadow();\n    },\n\n    /**\n     * @private\n     * @param {Object} pointer Actual mouse position related to the canvas.\n     */\n    _captureDrawingPath: function(pointer) {\n      var pointerPoint = new fabric.Point(pointer.x, pointer.y);\n      return this._addPoint(pointerPoint);\n    },\n\n    /**\n     * Draw a smooth path on the topCanvas using quadraticCurveTo\n     * @private\n     */\n    _render: function() {\n      var ctx  = this.canvas.contextTop, i, len,\n          p1 = this._points[0],\n          p2 = this._points[1];\n\n      this._saveAndTransform(ctx);\n      ctx.beginPath();\n      //if we only have 2 points in the path and they are the same\n      //it means that the user only clicked the canvas without moving the mouse\n      //then we should be drawing a dot. A path isn't drawn between two identical dots\n      //that's why we set them apart a bit\n      if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) {\n        var width = this.width / 1000;\n        p1 = new fabric.Point(p1.x, p1.y);\n        p2 = new fabric.Point(p2.x, p2.y);\n        p1.x -= width;\n        p2.x += width;\n      }\n      ctx.moveTo(p1.x, p1.y);\n\n      for (i = 1, len = this._points.length; i < len; i++) {\n        // we pick the point between pi + 1 & pi + 2 as the\n        // end point and p1 as our control point.\n        this._drawSegment(ctx, p1, p2);\n        p1 = this._points[i];\n        p2 = this._points[i + 1];\n      }\n      // Draw last line as a straight line while\n      // we wait for the next point to be able to calculate\n      // the bezier control point\n      ctx.lineTo(p1.x, p1.y);\n      ctx.stroke();\n      ctx.restore();\n    },\n\n    /**\n     * Converts points to SVG path\n     * @param {Array} points Array of points\n     * @return {String} SVG path\n     */\n    convertPointsToSVGPath: function(points) {\n      var path = [], i, width = this.width / 1000,\n          p1 = new fabric.Point(points[0].x, points[0].y),\n          p2 = new fabric.Point(points[1].x, points[1].y),\n          len = points.length, multSignX = 1, multSignY = 0, manyPoints = len > 2;\n\n      if (manyPoints) {\n        multSignX = points[2].x < p2.x ? -1 : points[2].x === p2.x ? 0 : 1;\n        multSignY = points[2].y < p2.y ? -1 : points[2].y === p2.y ? 0 : 1;\n      }\n      path.push('M ', p1.x - multSignX * width, ' ', p1.y - multSignY * width, ' ');\n      for (i = 1; i < len; i++) {\n        if (!p1.eq(p2)) {\n          var midPoint = p1.midPointFrom(p2);\n          // p1 is our bezier control point\n          // midpoint is our endpoint\n          // start point is p(i-1) value.\n          path.push('Q ', p1.x, ' ', p1.y, ' ', midPoint.x, ' ', midPoint.y, ' ');\n        }\n        p1 = points[i];\n        if ((i + 1) < points.length) {\n          p2 = points[i + 1];\n        }\n      }\n      if (manyPoints) {\n        multSignX = p1.x > points[i - 2].x ? 1 : p1.x === points[i - 2].x ? 0 : -1;\n        multSignY = p1.y > points[i - 2].y ? 1 : p1.y === points[i - 2].y ? 0 : -1;\n      }\n      path.push('L ', p1.x + multSignX * width, ' ', p1.y + multSignY * width);\n      return path;\n    },\n\n    /**\n     * Creates fabric.Path object to add on canvas\n     * @param {String} pathData Path data\n     * @return {fabric.Path} Path to add on canvas\n     */\n    createPath: function(pathData) {\n      var path = new fabric.Path(pathData, {\n        fill: null,\n        stroke: this.color,\n        strokeWidth: this.width,\n        strokeLineCap: this.strokeLineCap,\n        strokeMiterLimit: this.strokeMiterLimit,\n        strokeLineJoin: this.strokeLineJoin,\n        strokeDashArray: this.strokeDashArray,\n      });\n      if (this.shadow) {\n        this.shadow.affectStroke = true;\n        path.shadow = new fabric.Shadow(this.shadow);\n      }\n\n      return path;\n    },\n\n    /**\n     * Decimate poins array with the decimate value\n     */\n    decimatePoints: function(points, distance) {\n      if (points.length <= 2) {\n        return points;\n      }\n      var zoom = this.canvas.getZoom(), adjustedDistance = Math.pow(distance / zoom, 2),\n          i, l = points.length - 1, lastPoint = points[0], newPoints = [lastPoint],\n          cDistance;\n      for (i = 1; i < l; i++) {\n        cDistance = Math.pow(lastPoint.x - points[i].x, 2) + Math.pow(lastPoint.y - points[i].y, 2);\n        if (cDistance >= adjustedDistance) {\n          lastPoint = points[i];\n          newPoints.push(lastPoint);\n        }\n      }\n      if (newPoints.length === 1) {\n        newPoints.push(new fabric.Point(newPoints[0].x, newPoints[0].y));\n      }\n      return newPoints;\n    },\n\n    /**\n     * On mouseup after drawing the path on contextTop canvas\n     * we use the points captured to create an new fabric path object\n     * and add it to the fabric canvas.\n     */\n    _finalizeAndAddPath: function() {\n      var ctx = this.canvas.contextTop;\n      ctx.closePath();\n      if (this.decimate) {\n        this._points = this.decimatePoints(this._points, this.decimate);\n      }\n      var pathData = this.convertPointsToSVGPath(this._points).join('');\n      if (pathData === 'M 0 0 Q 0 0 0 0 L 0 0') {\n        // do not create 0 width/height paths, as they are\n        // rendered inconsistently across browsers\n        // Firefox 4, for example, renders a dot,\n        // whereas Chrome 10 renders nothing\n        this.canvas.requestRenderAll();\n        return;\n      }\n\n      var path = this.createPath(pathData);\n      this.canvas.clearContext(this.canvas.contextTop);\n      this.canvas.fire('before:path:created', { path: path });\n      this.canvas.add(path);\n      this.canvas.requestRenderAll();\n      path.setCoords();\n      this._resetShadow();\n\n\n      // fire event 'path' created\n      this.canvas.fire('path:created', { path: path });\n    }\n  });\n})();\n\n\n/**\n * CircleBrush class\n * @class fabric.CircleBrush\n */\nfabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.CircleBrush.prototype */ {\n\n  /**\n   * Width of a brush\n   * @type Number\n   * @default\n   */\n  width: 10,\n\n  /**\n   * Constructor\n   * @param {fabric.Canvas} canvas\n   * @return {fabric.CircleBrush} Instance of a circle brush\n   */\n  initialize: function(canvas) {\n    this.canvas = canvas;\n    this.points = [];\n  },\n\n  /**\n   * Invoked inside on mouse down and mouse move\n   * @param {Object} pointer\n   */\n  drawDot: function(pointer) {\n    var point = this.addPoint(pointer),\n        ctx = this.canvas.contextTop;\n    this._saveAndTransform(ctx);\n    this.dot(ctx, point);\n    ctx.restore();\n  },\n\n  dot: function(ctx, point) {\n    ctx.fillStyle = point.fill;\n    ctx.beginPath();\n    ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false);\n    ctx.closePath();\n    ctx.fill();\n  },\n\n  /**\n   * Invoked on mouse down\n   */\n  onMouseDown: function(pointer) {\n    this.points.length = 0;\n    this.canvas.clearContext(this.canvas.contextTop);\n    this._setShadow();\n    this.drawDot(pointer);\n  },\n\n  /**\n   * Render the full state of the brush\n   * @private\n   */\n  _render: function() {\n    var ctx  = this.canvas.contextTop, i, len,\n        points = this.points;\n    this._saveAndTransform(ctx);\n    for (i = 0, len = points.length; i < len; i++) {\n      this.dot(ctx, points[i]);\n    }\n    ctx.restore();\n  },\n\n  /**\n   * Invoked on mouse move\n   * @param {Object} pointer\n   */\n  onMouseMove: function(pointer) {\n    if (this.needsFullRender()) {\n      this.canvas.clearContext(this.canvas.contextTop);\n      this.addPoint(pointer);\n      this._render();\n    }\n    else {\n      this.drawDot(pointer);\n    }\n  },\n\n  /**\n   * Invoked on mouse up\n   */\n  onMouseUp: function() {\n    var originalRenderOnAddRemove = this.canvas.renderOnAddRemove, i, len;\n    this.canvas.renderOnAddRemove = false;\n\n    var circles = [];\n\n    for (i = 0, len = this.points.length; i < len; i++) {\n      var point = this.points[i],\n          circle = new fabric.Circle({\n            radius: point.radius,\n            left: point.x,\n            top: point.y,\n            originX: 'center',\n            originY: 'center',\n            fill: point.fill\n          });\n\n      this.shadow && (circle.shadow = new fabric.Shadow(this.shadow));\n\n      circles.push(circle);\n    }\n    var group = new fabric.Group(circles);\n    group.canvas = this.canvas;\n\n    this.canvas.fire('before:path:created', { path: group });\n    this.canvas.add(group);\n    this.canvas.fire('path:created', { path: group });\n\n    this.canvas.clearContext(this.canvas.contextTop);\n    this._resetShadow();\n    this.canvas.renderOnAddRemove = originalRenderOnAddRemove;\n    this.canvas.requestRenderAll();\n  },\n\n  /**\n   * @param {Object} pointer\n   * @return {fabric.Point} Just added pointer point\n   */\n  addPoint: function(pointer) {\n    var pointerPoint = new fabric.Point(pointer.x, pointer.y),\n\n        circleRadius = fabric.util.getRandomInt(\n          Math.max(0, this.width - 20), this.width + 20) / 2,\n\n        circleColor = new fabric.Color(this.color)\n          .setAlpha(fabric.util.getRandomInt(0, 100) / 100)\n          .toRgba();\n\n    pointerPoint.radius = circleRadius;\n    pointerPoint.fill = circleColor;\n\n    this.points.push(pointerPoint);\n\n    return pointerPoint;\n  }\n});\n\n\n/**\n * SprayBrush class\n * @class fabric.SprayBrush\n */\nfabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric.SprayBrush.prototype */ {\n\n  /**\n   * Width of a spray\n   * @type Number\n   * @default\n   */\n  width:              10,\n\n  /**\n   * Density of a spray (number of dots per chunk)\n   * @type Number\n   * @default\n   */\n  density:            20,\n\n  /**\n   * Width of spray dots\n   * @type Number\n   * @default\n   */\n  dotWidth:           1,\n\n  /**\n   * Width variance of spray dots\n   * @type Number\n   * @default\n   */\n  dotWidthVariance:   1,\n\n  /**\n   * Whether opacity of a dot should be random\n   * @type Boolean\n   * @default\n   */\n  randomOpacity:        false,\n\n  /**\n   * Whether overlapping dots (rectangles) should be removed (for performance reasons)\n   * @type Boolean\n   * @default\n   */\n  optimizeOverlapping:  true,\n\n  /**\n   * Constructor\n   * @param {fabric.Canvas} canvas\n   * @return {fabric.SprayBrush} Instance of a spray brush\n   */\n  initialize: function(canvas) {\n    this.canvas = canvas;\n    this.sprayChunks = [];\n  },\n\n  /**\n   * Invoked on mouse down\n   * @param {Object} pointer\n   */\n  onMouseDown: function(pointer) {\n    this.sprayChunks.length = 0;\n    this.canvas.clearContext(this.canvas.contextTop);\n    this._setShadow();\n\n    this.addSprayChunk(pointer);\n    this.render(this.sprayChunkPoints);\n  },\n\n  /**\n   * Invoked on mouse move\n   * @param {Object} pointer\n   */\n  onMouseMove: function(pointer) {\n    this.addSprayChunk(pointer);\n    this.render(this.sprayChunkPoints);\n  },\n\n  /**\n   * Invoked on mouse up\n   */\n  onMouseUp: function() {\n    var originalRenderOnAddRemove = this.canvas.renderOnAddRemove;\n    this.canvas.renderOnAddRemove = false;\n\n    var rects = [];\n\n    for (var i = 0, ilen = this.sprayChunks.length; i < ilen; i++) {\n      var sprayChunk = this.sprayChunks[i];\n\n      for (var j = 0, jlen = sprayChunk.length; j < jlen; j++) {\n\n        var rect = new fabric.Rect({\n          width: sprayChunk[j].width,\n          height: sprayChunk[j].width,\n          left: sprayChunk[j].x + 1,\n          top: sprayChunk[j].y + 1,\n          originX: 'center',\n          originY: 'center',\n          fill: this.color\n        });\n        rects.push(rect);\n      }\n    }\n\n    if (this.optimizeOverlapping) {\n      rects = this._getOptimizedRects(rects);\n    }\n\n    var group = new fabric.Group(rects);\n    this.shadow && group.set('shadow', new fabric.Shadow(this.shadow));\n    this.canvas.fire('before:path:created', { path: group });\n    this.canvas.add(group);\n    this.canvas.fire('path:created', { path: group });\n\n    this.canvas.clearContext(this.canvas.contextTop);\n    this._resetShadow();\n    this.canvas.renderOnAddRemove = originalRenderOnAddRemove;\n    this.canvas.requestRenderAll();\n  },\n\n  /**\n   * @private\n   * @param {Array} rects\n   */\n  _getOptimizedRects: function(rects) {\n\n    // avoid creating duplicate rects at the same coordinates\n    var uniqueRects = { }, key, i, len;\n\n    for (i = 0, len = rects.length; i < len; i++) {\n      key = rects[i].left + '' + rects[i].top;\n      if (!uniqueRects[key]) {\n        uniqueRects[key] = rects[i];\n      }\n    }\n    var uniqueRectsArray = [];\n    for (key in uniqueRects) {\n      uniqueRectsArray.push(uniqueRects[key]);\n    }\n\n    return uniqueRectsArray;\n  },\n\n  /**\n   * Render new chunk of spray brush\n   */\n  render: function(sprayChunk) {\n    var ctx = this.canvas.contextTop, i, len;\n    ctx.fillStyle = this.color;\n\n    this._saveAndTransform(ctx);\n\n    for (i = 0, len = sprayChunk.length; i < len; i++) {\n      var point = sprayChunk[i];\n      if (typeof point.opacity !== 'undefined') {\n        ctx.globalAlpha = point.opacity;\n      }\n      ctx.fillRect(point.x, point.y, point.width, point.width);\n    }\n    ctx.restore();\n  },\n\n  /**\n   * Render all spray chunks\n   */\n  _render: function() {\n    var ctx = this.canvas.contextTop, i, ilen;\n    ctx.fillStyle = this.color;\n\n    this._saveAndTransform(ctx);\n\n    for (i = 0, ilen = this.sprayChunks.length; i < ilen; i++) {\n      this.render(this.sprayChunks[i]);\n    }\n    ctx.restore();\n  },\n\n  /**\n   * @param {Object} pointer\n   */\n  addSprayChunk: function(pointer) {\n    this.sprayChunkPoints = [];\n\n    var x, y, width, radius = this.width / 2, i;\n\n    for (i = 0; i < this.density; i++) {\n\n      x = fabric.util.getRandomInt(pointer.x - radius, pointer.x + radius);\n      y = fabric.util.getRandomInt(pointer.y - radius, pointer.y + radius);\n\n      if (this.dotWidthVariance) {\n        width = fabric.util.getRandomInt(\n          // bottom clamp width to 1\n          Math.max(1, this.dotWidth - this.dotWidthVariance),\n          this.dotWidth + this.dotWidthVariance);\n      }\n      else {\n        width = this.dotWidth;\n      }\n\n      var point = new fabric.Point(x, y);\n      point.width = width;\n\n      if (this.randomOpacity) {\n        point.opacity = fabric.util.getRandomInt(0, 100) / 100;\n      }\n\n      this.sprayChunkPoints.push(point);\n    }\n\n    this.sprayChunks.push(this.sprayChunkPoints);\n  }\n});\n\n\n/**\n * PatternBrush class\n * @class fabric.PatternBrush\n * @extends fabric.BaseBrush\n */\nfabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fabric.PatternBrush.prototype */ {\n\n  getPatternSrc: function() {\n\n    var dotWidth = 20,\n        dotDistance = 5,\n        patternCanvas = fabric.util.createCanvasElement(),\n        patternCtx = patternCanvas.getContext('2d');\n\n    patternCanvas.width = patternCanvas.height = dotWidth + dotDistance;\n\n    patternCtx.fillStyle = this.color;\n    patternCtx.beginPath();\n    patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false);\n    patternCtx.closePath();\n    patternCtx.fill();\n\n    return patternCanvas;\n  },\n\n  getPatternSrcFunction: function() {\n    return String(this.getPatternSrc).replace('this.color', '\"' + this.color + '\"');\n  },\n\n  /**\n   * Creates \"pattern\" instance property\n   */\n  getPattern: function() {\n    return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), 'repeat');\n  },\n\n  /**\n   * Sets brush styles\n   */\n  _setBrushStyles: function() {\n    this.callSuper('_setBrushStyles');\n    this.canvas.contextTop.strokeStyle = this.getPattern();\n  },\n\n  /**\n   * Creates path\n   */\n  createPath: function(pathData) {\n    var path = this.callSuper('createPath', pathData),\n        topLeft = path._getLeftTopCoords().scalarAdd(path.strokeWidth / 2);\n\n    path.stroke = new fabric.Pattern({\n      source: this.source || this.getPatternSrcFunction(),\n      offsetX: -topLeft.x,\n      offsetY: -topLeft.y\n    });\n    return path;\n  }\n});\n\n\n(function() {\n\n  var getPointer = fabric.util.getPointer,\n      degreesToRadians = fabric.util.degreesToRadians,\n      abs = Math.abs,\n      supportLineDash = fabric.StaticCanvas.supports('setLineDash'),\n      isTouchEvent = fabric.util.isTouchEvent,\n      STROKE_OFFSET = 0.5;\n\n  /**\n   * Canvas class\n   * @class fabric.Canvas\n   * @extends fabric.StaticCanvas\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#canvas}\n   * @see {@link fabric.Canvas#initialize} for constructor definition\n   *\n   * @fires object:modified at the end of a transform or any change when statefull is true\n   * @fires object:rotating while an object is being rotated from the control\n   * @fires object:scaling while an object is being scaled by controls\n   * @fires object:moving while an object is being dragged\n   * @fires object:skewing while an object is being skewed from the controls\n   *\n   * @fires before:transform before a transform is is started\n   * @fires before:selection:cleared\n   * @fires selection:cleared\n   * @fires selection:updated\n   * @fires selection:created\n   *\n   * @fires path:created after a drawing operation ends and the path is added\n   * @fires mouse:down\n   * @fires mouse:move\n   * @fires mouse:up\n   * @fires mouse:down:before  on mouse down, before the inner fabric logic runs\n   * @fires mouse:move:before on mouse move, before the inner fabric logic runs\n   * @fires mouse:up:before on mouse up, before the inner fabric logic runs\n   * @fires mouse:over\n   * @fires mouse:out\n   * @fires mouse:dblclick whenever a native dbl click event fires on the canvas.\n   *\n   * @fires dragover\n   * @fires dragenter\n   * @fires dragleave\n   * @fires drop\n   * @fires after:render at the end of the render process, receives the context in the callback\n   * @fires before:render at start the render process, receives the context in the callback\n   *\n   * the following events are deprecated:\n   * @fires object:rotated at the end of a rotation transform\n   * @fires object:scaled at the end of a scale transform\n   * @fires object:moved at the end of translation transform\n   * @fires object:skewed at the end of a skew transform\n   */\n  fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ {\n\n    /**\n     * Constructor\n     * @param {HTMLElement | String} el &lt;canvas> element to initialize instance on\n     * @param {Object} [options] Options object\n     * @return {Object} thisArg\n     */\n    initialize: function(el, options) {\n      options || (options = { });\n      this.renderAndResetBound = this.renderAndReset.bind(this);\n      this.requestRenderAllBound = this.requestRenderAll.bind(this);\n      this._initStatic(el, options);\n      this._initInteractive();\n      this._createCacheCanvas();\n    },\n\n    /**\n     * When true, objects can be transformed by one side (unproportionally)\n     * when dragged on the corners that normally would not do that.\n     * @type Boolean\n     * @default\n     * @since fabric 4.0 // changed name and default value\n     */\n    uniformScaling:      true,\n\n    /**\n     * Indicates which key switches uniform scaling.\n     * values: 'altKey', 'shiftKey', 'ctrlKey'.\n     * If `null` or 'none' or any other string that is not a modifier key\n     * feature is disabled.\n     * totally wrong named. this sounds like `uniform scaling`\n     * if Canvas.uniformScaling is true, pressing this will set it to false\n     * and viceversa.\n     * @since 1.6.2\n     * @type String\n     * @default\n     */\n    uniScaleKey:           'shiftKey',\n\n    /**\n     * When true, objects use center point as the origin of scale transformation.\n     * <b>Backwards incompatibility note:</b> This property replaces \"centerTransform\" (Boolean).\n     * @since 1.3.4\n     * @type Boolean\n     * @default\n     */\n    centeredScaling:        false,\n\n    /**\n     * When true, objects use center point as the origin of rotate transformation.\n     * <b>Backwards incompatibility note:</b> This property replaces \"centerTransform\" (Boolean).\n     * @since 1.3.4\n     * @type Boolean\n     * @default\n     */\n    centeredRotation:       false,\n\n    /**\n     * Indicates which key enable centered Transform\n     * values: 'altKey', 'shiftKey', 'ctrlKey'.\n     * If `null` or 'none' or any other string that is not a modifier key\n     * feature is disabled feature disabled.\n     * @since 1.6.2\n     * @type String\n     * @default\n     */\n    centeredKey:           'altKey',\n\n    /**\n     * Indicates which key enable alternate action on corner\n     * values: 'altKey', 'shiftKey', 'ctrlKey'.\n     * If `null` or 'none' or any other string that is not a modifier key\n     * feature is disabled feature disabled.\n     * @since 1.6.2\n     * @type String\n     * @default\n     */\n    altActionKey:           'shiftKey',\n\n    /**\n     * Indicates that canvas is interactive. This property should not be changed.\n     * @type Boolean\n     * @default\n     */\n    interactive:            true,\n\n    /**\n     * Indicates whether group selection should be enabled\n     * @type Boolean\n     * @default\n     */\n    selection:              true,\n\n    /**\n     * Indicates which key or keys enable multiple click selection\n     * Pass value as a string or array of strings\n     * values: 'altKey', 'shiftKey', 'ctrlKey'.\n     * If `null` or empty or containing any other string that is not a modifier key\n     * feature is disabled.\n     * @since 1.6.2\n     * @type String|Array\n     * @default\n     */\n    selectionKey:           'shiftKey',\n\n    /**\n     * Indicates which key enable alternative selection\n     * in case of target overlapping with active object\n     * values: 'altKey', 'shiftKey', 'ctrlKey'.\n     * For a series of reason that come from the general expectations on how\n     * things should work, this feature works only for preserveObjectStacking true.\n     * If `null` or 'none' or any other string that is not a modifier key\n     * feature is disabled.\n     * @since 1.6.5\n     * @type null|String\n     * @default\n     */\n    altSelectionKey:           null,\n\n    /**\n     * Color of selection\n     * @type String\n     * @default\n     */\n    selectionColor:         'rgba(100, 100, 255, 0.3)', // blue\n\n    /**\n     * Default dash array pattern\n     * If not empty the selection border is dashed\n     * @type Array\n     */\n    selectionDashArray:     [],\n\n    /**\n     * Color of the border of selection (usually slightly darker than color of selection itself)\n     * @type String\n     * @default\n     */\n    selectionBorderColor:   'rgba(255, 255, 255, 0.3)',\n\n    /**\n     * Width of a line used in object/group selection\n     * @type Number\n     * @default\n     */\n    selectionLineWidth:     1,\n\n    /**\n     * Select only shapes that are fully contained in the dragged selection rectangle.\n     * @type Boolean\n     * @default\n     */\n    selectionFullyContained: false,\n\n    /**\n     * Default cursor value used when hovering over an object on canvas\n     * @type String\n     * @default\n     */\n    hoverCursor:            'move',\n\n    /**\n     * Default cursor value used when moving an object on canvas\n     * @type String\n     * @default\n     */\n    moveCursor:             'move',\n\n    /**\n     * Default cursor value used for the entire canvas\n     * @type String\n     * @default\n     */\n    defaultCursor:          'default',\n\n    /**\n     * Cursor value used during free drawing\n     * @type String\n     * @default\n     */\n    freeDrawingCursor:      'crosshair',\n\n    /**\n     * Cursor value used for rotation point\n     * @type String\n     * @default\n     */\n    rotationCursor:         'crosshair',\n\n    /**\n     * Cursor value used for disabled elements ( corners with disabled action )\n     * @type String\n     * @since 2.0.0\n     * @default\n     */\n    notAllowedCursor:         'not-allowed',\n\n    /**\n     * Default element class that's given to wrapper (div) element of canvas\n     * @type String\n     * @default\n     */\n    containerClass:         'canvas-container',\n\n    /**\n     * When true, object detection happens on per-pixel basis rather than on per-bounding-box\n     * @type Boolean\n     * @default\n     */\n    perPixelTargetFind:     false,\n\n    /**\n     * Number of pixels around target pixel to tolerate (consider active) during object detection\n     * @type Number\n     * @default\n     */\n    targetFindTolerance:    0,\n\n    /**\n     * When true, target detection is skipped. Target detection will return always undefined.\n     * click selection won't work anymore, events will fire with no targets.\n     * if something is selected before setting it to true, it will be deselected at the first click.\n     * area selection will still work. check the `selection` property too.\n     * if you deactivate both, you should look into staticCanvas.\n     * @type Boolean\n     * @default\n     */\n    skipTargetFind:         false,\n\n    /**\n     * When true, mouse events on canvas (mousedown/mousemove/mouseup) result in free drawing.\n     * After mousedown, mousemove creates a shape,\n     * and then mouseup finalizes it and adds an instance of `fabric.Path` onto canvas.\n     * @tutorial {@link http://fabricjs.com/fabric-intro-part-4#free_drawing}\n     * @type Boolean\n     * @default\n     */\n    isDrawingMode:          false,\n\n    /**\n     * Indicates whether objects should remain in current stack position when selected.\n     * When false objects are brought to top and rendered as part of the selection group\n     * @type Boolean\n     * @default\n     */\n    preserveObjectStacking: false,\n\n    /**\n     * Indicates the angle that an object will lock to while rotating.\n     * @type Number\n     * @since 1.6.7\n     * @default\n     */\n    snapAngle: 0,\n\n    /**\n     * Indicates the distance from the snapAngle the rotation will lock to the snapAngle.\n     * When `null`, the snapThreshold will default to the snapAngle.\n     * @type null|Number\n     * @since 1.6.7\n     * @default\n     */\n    snapThreshold: null,\n\n    /**\n     * Indicates if the right click on canvas can output the context menu or not\n     * @type Boolean\n     * @since 1.6.5\n     * @default\n     */\n    stopContextMenu: false,\n\n    /**\n     * Indicates if the canvas can fire right click events\n     * @type Boolean\n     * @since 1.6.5\n     * @default\n     */\n    fireRightClick: false,\n\n    /**\n     * Indicates if the canvas can fire middle click events\n     * @type Boolean\n     * @since 1.7.8\n     * @default\n     */\n    fireMiddleClick: false,\n\n    /**\n     * Keep track of the subTargets for Mouse Events\n     * @type fabric.Object[]\n     */\n    targets: [],\n\n    /**\n     * Keep track of the hovered target\n     * @type fabric.Object\n     * @private\n     */\n    _hoveredTarget: null,\n\n    /**\n     * hold the list of nested targets hovered\n     * @type fabric.Object[]\n     * @private\n     */\n    _hoveredTargets: [],\n\n    /**\n     * @private\n     */\n    _initInteractive: function() {\n      this._currentTransform = null;\n      this._groupSelector = null;\n      this._initWrapperElement();\n      this._createUpperCanvas();\n      this._initEventListeners();\n\n      this._initRetinaScaling();\n\n      this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this);\n\n      this.calcOffset();\n    },\n\n    /**\n     * Divides objects in two groups, one to render immediately\n     * and one to render as activeGroup.\n     * @return {Array} objects to render immediately and pushes the other in the activeGroup.\n     */\n    _chooseObjectsToRender: function() {\n      var activeObjects = this.getActiveObjects(),\n          object, objsToRender, activeGroupObjects;\n\n      if (activeObjects.length > 0 && !this.preserveObjectStacking) {\n        objsToRender = [];\n        activeGroupObjects = [];\n        for (var i = 0, length = this._objects.length; i < length; i++) {\n          object = this._objects[i];\n          if (activeObjects.indexOf(object) === -1 ) {\n            objsToRender.push(object);\n          }\n          else {\n            activeGroupObjects.push(object);\n          }\n        }\n        if (activeObjects.length > 1) {\n          this._activeObject._objects = activeGroupObjects;\n        }\n        objsToRender.push.apply(objsToRender, activeGroupObjects);\n      }\n      else {\n        objsToRender = this._objects;\n      }\n      return objsToRender;\n    },\n\n    /**\n     * Renders both the top canvas and the secondary container canvas.\n     * @return {fabric.Canvas} instance\n     * @chainable\n     */\n    renderAll: function () {\n      if (this.contextTopDirty && !this._groupSelector && !this.isDrawingMode) {\n        this.clearContext(this.contextTop);\n        this.contextTopDirty = false;\n      }\n      if (this.hasLostContext) {\n        this.renderTopLayer(this.contextTop);\n      }\n      var canvasToDrawOn = this.contextContainer;\n      this.renderCanvas(canvasToDrawOn, this._chooseObjectsToRender());\n      return this;\n    },\n\n    renderTopLayer: function(ctx) {\n      ctx.save();\n      if (this.isDrawingMode && this._isCurrentlyDrawing) {\n        this.freeDrawingBrush && this.freeDrawingBrush._render();\n        this.contextTopDirty = true;\n      }\n      // we render the top context - last object\n      if (this.selection && this._groupSelector) {\n        this._drawSelection(ctx);\n        this.contextTopDirty = true;\n      }\n      ctx.restore();\n    },\n\n    /**\n     * Method to render only the top canvas.\n     * Also used to render the group selection box.\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    renderTop: function () {\n      var ctx = this.contextTop;\n      this.clearContext(ctx);\n      this.renderTopLayer(ctx);\n      this.fire('after:render');\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _normalizePointer: function (object, pointer) {\n      var m = object.calcTransformMatrix(),\n          invertedM = fabric.util.invertTransform(m),\n          vptPointer = this.restorePointerVpt(pointer);\n      return fabric.util.transformPoint(vptPointer, invertedM);\n    },\n\n    /**\n     * Returns true if object is transparent at a certain location\n     * @param {fabric.Object} target Object to check\n     * @param {Number} x Left coordinate\n     * @param {Number} y Top coordinate\n     * @return {Boolean}\n     */\n    isTargetTransparent: function (target, x, y) {\n      // in case the target is the activeObject, we cannot execute this optimization\n      // because we need to draw controls too.\n      if (target.shouldCache() && target._cacheCanvas && target !== this._activeObject) {\n        var normalizedPointer = this._normalizePointer(target, {x: x, y: y}),\n            targetRelativeX = Math.max(target.cacheTranslationX + (normalizedPointer.x * target.zoomX), 0),\n            targetRelativeY = Math.max(target.cacheTranslationY + (normalizedPointer.y * target.zoomY), 0);\n\n        var isTransparent = fabric.util.isTransparent(\n          target._cacheContext, Math.round(targetRelativeX), Math.round(targetRelativeY), this.targetFindTolerance);\n\n        return isTransparent;\n      }\n\n      var ctx = this.contextCache,\n          originalColor = target.selectionBackgroundColor, v = this.viewportTransform;\n\n      target.selectionBackgroundColor = '';\n\n      this.clearContext(ctx);\n\n      ctx.save();\n      ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n      target.render(ctx);\n      ctx.restore();\n\n      target === this._activeObject && target._renderControls(ctx, {\n        hasBorders: false,\n        transparentCorners: false\n      }, {\n        hasBorders: false,\n      });\n\n      target.selectionBackgroundColor = originalColor;\n\n      var isTransparent = fabric.util.isTransparent(\n        ctx, x, y, this.targetFindTolerance);\n\n      return isTransparent;\n    },\n\n    /**\n     * takes an event and determins if selection key has been pressed\n     * @private\n     * @param {Event} e Event object\n     */\n    _isSelectionKeyPressed: function(e) {\n      var selectionKeyPressed = false;\n\n      if (Object.prototype.toString.call(this.selectionKey) === '[object Array]') {\n        selectionKeyPressed = !!this.selectionKey.find(function(key) { return e[key] === true; });\n      }\n      else {\n        selectionKeyPressed = e[this.selectionKey];\n      }\n\n      return selectionKeyPressed;\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object\n     * @param {fabric.Object} target\n     */\n    _shouldClearSelection: function (e, target) {\n      var activeObjects = this.getActiveObjects(),\n          activeObject = this._activeObject;\n\n      return (\n        !target\n        ||\n        (target &&\n          activeObject &&\n          activeObjects.length > 1 &&\n          activeObjects.indexOf(target) === -1 &&\n          activeObject !== target &&\n          !this._isSelectionKeyPressed(e))\n        ||\n        (target && !target.evented)\n        ||\n        (target &&\n          !target.selectable &&\n          activeObject &&\n          activeObject !== target)\n      );\n    },\n\n    /**\n     * centeredScaling from object can't override centeredScaling from canvas.\n     * this should be fixed, since object setting should take precedence over canvas.\n     * also this should be something that will be migrated in the control properties.\n     * as ability to define the origin of the transformation that the control provide.\n     * @private\n     * @param {fabric.Object} target\n     * @param {String} action\n     * @param {Boolean} altKey\n     */\n    _shouldCenterTransform: function (target, action, altKey) {\n      if (!target) {\n        return;\n      }\n\n      var centerTransform;\n\n      if (action === 'scale' || action === 'scaleX' || action === 'scaleY' || action === 'resizing') {\n        centerTransform = this.centeredScaling || target.centeredScaling;\n      }\n      else if (action === 'rotate') {\n        centerTransform = this.centeredRotation || target.centeredRotation;\n      }\n\n      return centerTransform ? !altKey : altKey;\n    },\n\n    /**\n     * should disappear before release 4.0\n     * @private\n     */\n    _getOriginFromCorner: function(target, corner) {\n      var origin = {\n        x: target.originX,\n        y: target.originY\n      };\n\n      if (corner === 'ml' || corner === 'tl' || corner === 'bl') {\n        origin.x = 'right';\n      }\n      else if (corner === 'mr' || corner === 'tr' || corner === 'br') {\n        origin.x = 'left';\n      }\n\n      if (corner === 'tl' || corner === 'mt' || corner === 'tr') {\n        origin.y = 'bottom';\n      }\n      else if (corner === 'bl' || corner === 'mb' || corner === 'br') {\n        origin.y = 'top';\n      }\n      else if (corner === 'mtr') {\n        origin.x = 'center';\n        origin.y = 'center';\n      }\n      return origin;\n    },\n\n    /**\n     * @private\n     * @param {Boolean} alreadySelected true if target is already selected\n     * @param {String} corner a string representing the corner ml, mr, tl ...\n     * @param {Event} e Event object\n     * @param {fabric.Object} [target] inserted back to help overriding. Unused\n     */\n    _getActionFromCorner: function(alreadySelected, corner, e, target) {\n      if (!corner || !alreadySelected) {\n        return 'drag';\n      }\n      var control = target.controls[corner];\n      return control.getActionName(e, control, target);\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object\n     * @param {fabric.Object} target\n     */\n    _setupCurrentTransform: function (e, target, alreadySelected) {\n      if (!target) {\n        return;\n      }\n\n      var pointer = this.getPointer(e), corner = target.__corner,\n          actionHandler = (alreadySelected && corner) ?\n            target.controls[corner].getActionHandler() : fabric.controlsUtils.dragHandler,\n          action = this._getActionFromCorner(alreadySelected, corner, e, target),\n          origin = this._getOriginFromCorner(target, corner),\n          altKey = e[this.centeredKey],\n          transform = {\n            target: target,\n            action: action,\n            actionHandler: actionHandler,\n            corner: corner,\n            scaleX: target.scaleX,\n            scaleY: target.scaleY,\n            skewX: target.skewX,\n            skewY: target.skewY,\n            // used by transation\n            offsetX: pointer.x - target.left,\n            offsetY: pointer.y - target.top,\n            originX: origin.x,\n            originY: origin.y,\n            ex: pointer.x,\n            ey: pointer.y,\n            lastX: pointer.x,\n            lastY: pointer.y,\n            // unsure they are useful anymore.\n            // left: target.left,\n            // top: target.top,\n            theta: degreesToRadians(target.angle),\n            // end of unsure\n            width: target.width * target.scaleX,\n            shiftKey: e.shiftKey,\n            altKey: altKey,\n            original: fabric.util.saveObjectTransform(target),\n          };\n\n      if (this._shouldCenterTransform(target, action, altKey)) {\n        transform.originX = 'center';\n        transform.originY = 'center';\n      }\n      transform.original.originX = origin.x;\n      transform.original.originY = origin.y;\n      this._currentTransform = transform;\n      this._beforeTransform(e);\n    },\n\n    /**\n     * Set the cursor type of the canvas element\n     * @param {String} value Cursor type of the canvas element.\n     * @see http://www.w3.org/TR/css3-ui/#cursor\n     */\n    setCursor: function (value) {\n      this.upperCanvasEl.style.cursor = value;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx to draw the selection on\n     */\n    _drawSelection: function (ctx) {\n      var groupSelector = this._groupSelector,\n          left = groupSelector.left,\n          top = groupSelector.top,\n          aleft = abs(left),\n          atop = abs(top);\n\n      if (this.selectionColor) {\n        ctx.fillStyle = this.selectionColor;\n\n        ctx.fillRect(\n          groupSelector.ex - ((left > 0) ? 0 : -left),\n          groupSelector.ey - ((top > 0) ? 0 : -top),\n          aleft,\n          atop\n        );\n      }\n\n      if (!this.selectionLineWidth || !this.selectionBorderColor) {\n        return;\n      }\n      ctx.lineWidth = this.selectionLineWidth;\n      ctx.strokeStyle = this.selectionBorderColor;\n\n      // selection border\n      if (this.selectionDashArray.length > 1 && !supportLineDash) {\n\n        var px = groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft),\n            py = groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop);\n\n        ctx.beginPath();\n\n        fabric.util.drawDashedLine(ctx, px, py, px + aleft, py, this.selectionDashArray);\n        fabric.util.drawDashedLine(ctx, px, py + atop - 1, px + aleft, py + atop - 1, this.selectionDashArray);\n        fabric.util.drawDashedLine(ctx, px, py, px, py + atop, this.selectionDashArray);\n        fabric.util.drawDashedLine(ctx, px + aleft - 1, py, px + aleft - 1, py + atop, this.selectionDashArray);\n\n        ctx.closePath();\n        ctx.stroke();\n      }\n      else {\n        fabric.Object.prototype._setLineDash.call(this, ctx, this.selectionDashArray);\n        ctx.strokeRect(\n          groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft),\n          groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop),\n          aleft,\n          atop\n        );\n      }\n    },\n\n    /**\n     * Method that determines what object we are clicking on\n     * the skipGroup parameter is for internal use, is needed for shift+click action\n     * 11/09/2018 TODO: would be cool if findTarget could discern between being a full target\n     * or the outside part of the corner.\n     * @param {Event} e mouse event\n     * @param {Boolean} skipGroup when true, activeGroup is skipped and only objects are traversed through\n     * @return {fabric.Object} the target found\n     */\n    findTarget: function (e, skipGroup) {\n      if (this.skipTargetFind) {\n        return;\n      }\n\n      var ignoreZoom = true,\n          pointer = this.getPointer(e, ignoreZoom),\n          activeObject = this._activeObject,\n          aObjects = this.getActiveObjects(),\n          activeTarget, activeTargetSubs,\n          isTouch = isTouchEvent(e);\n\n      // first check current group (if one exists)\n      // active group does not check sub targets like normal groups.\n      // if active group just exits.\n      this.targets = [];\n\n      if (aObjects.length > 1 && !skipGroup && activeObject === this._searchPossibleTargets([activeObject], pointer)) {\n        return activeObject;\n      }\n      // if we hit the corner of an activeObject, let's return that.\n      if (aObjects.length === 1 && activeObject._findTargetCorner(pointer, isTouch)) {\n        return activeObject;\n      }\n      if (aObjects.length === 1 &&\n        activeObject === this._searchPossibleTargets([activeObject], pointer)) {\n        if (!this.preserveObjectStacking) {\n          return activeObject;\n        }\n        else {\n          activeTarget = activeObject;\n          activeTargetSubs = this.targets;\n          this.targets = [];\n        }\n      }\n      var target = this._searchPossibleTargets(this._objects, pointer);\n      if (e[this.altSelectionKey] && target && activeTarget && target !== activeTarget) {\n        target = activeTarget;\n        this.targets = activeTargetSubs;\n      }\n      return target;\n    },\n\n    /**\n     * Checks point is inside the object.\n     * @param {Object} [pointer] x,y object of point coordinates we want to check.\n     * @param {fabric.Object} obj Object to test against\n     * @param {Object} [globalPointer] x,y object of point coordinates relative to canvas used to search per pixel target.\n     * @return {Boolean} true if point is contained within an area of given object\n     * @private\n     */\n    _checkTarget: function(pointer, obj, globalPointer) {\n      if (obj &&\n          obj.visible &&\n          obj.evented &&\n          // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html\n          // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html\n          (obj.containsPoint(pointer) || !!obj._findTargetCorner(pointer))\n      ) {\n        if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) {\n          var isTransparent = this.isTargetTransparent(obj, globalPointer.x, globalPointer.y);\n          if (!isTransparent) {\n            return true;\n          }\n        }\n        else {\n          return true;\n        }\n      }\n    },\n\n    /**\n     * Function used to search inside objects an object that contains pointer in bounding box or that contains pointerOnCanvas when painted\n     * @param {Array} [objects] objects array to look into\n     * @param {Object} [pointer] x,y object of point coordinates we want to check.\n     * @return {fabric.Object} object that contains pointer\n     * @private\n     */\n    _searchPossibleTargets: function(objects, pointer) {\n      // Cache all targets where their bounding box contains point.\n      var target, i = objects.length, subTarget;\n      // Do not check for currently grouped objects, since we check the parent group itself.\n      // until we call this function specifically to search inside the activeGroup\n      while (i--) {\n        var objToCheck = objects[i];\n        var pointerToUse = objToCheck.group ?\n          this._normalizePointer(objToCheck.group, pointer) : pointer;\n        if (this._checkTarget(pointerToUse, objToCheck, pointer)) {\n          target = objects[i];\n          if (target.subTargetCheck && target instanceof fabric.Group) {\n            subTarget = this._searchPossibleTargets(target._objects, pointer);\n            subTarget && this.targets.push(subTarget);\n          }\n          break;\n        }\n      }\n      return target;\n    },\n\n    /**\n     * Returns pointer coordinates without the effect of the viewport\n     * @param {Object} pointer with \"x\" and \"y\" number values\n     * @return {Object} object with \"x\" and \"y\" number values\n     */\n    restorePointerVpt: function(pointer) {\n      return fabric.util.transformPoint(\n        pointer,\n        fabric.util.invertTransform(this.viewportTransform)\n      );\n    },\n\n    /**\n     * Returns pointer coordinates relative to canvas.\n     * Can return coordinates with or without viewportTransform.\n     * ignoreZoom false gives back coordinates that represent\n     * the point clicked on canvas element.\n     * ignoreZoom true gives back coordinates after being processed\n     * by the viewportTransform ( sort of coordinates of what is displayed\n     * on the canvas where you are clicking.\n     * ignoreZoom true = HTMLElement coordinates relative to top,left\n     * ignoreZoom false, default = fabric space coordinates, the same used for shape position\n     * To interact with your shapes top and left you want to use ignoreZoom true\n     * most of the time, while ignoreZoom false will give you coordinates\n     * compatible with the object.oCoords system.\n     * of the time.\n     * @param {Event} e\n     * @param {Boolean} ignoreZoom\n     * @return {Object} object with \"x\" and \"y\" number values\n     */\n    getPointer: function (e, ignoreZoom) {\n      // return cached values if we are in the event processing chain\n      if (this._absolutePointer && !ignoreZoom) {\n        return this._absolutePointer;\n      }\n      if (this._pointer && ignoreZoom) {\n        return this._pointer;\n      }\n\n      var pointer = getPointer(e),\n          upperCanvasEl = this.upperCanvasEl,\n          bounds = upperCanvasEl.getBoundingClientRect(),\n          boundsWidth = bounds.width || 0,\n          boundsHeight = bounds.height || 0,\n          cssScale;\n\n      if (!boundsWidth || !boundsHeight ) {\n        if ('top' in bounds && 'bottom' in bounds) {\n          boundsHeight = Math.abs( bounds.top - bounds.bottom );\n        }\n        if ('right' in bounds && 'left' in bounds) {\n          boundsWidth = Math.abs( bounds.right - bounds.left );\n        }\n      }\n\n      this.calcOffset();\n      pointer.x = pointer.x - this._offset.left;\n      pointer.y = pointer.y - this._offset.top;\n      if (!ignoreZoom) {\n        pointer = this.restorePointerVpt(pointer);\n      }\n\n      var retinaScaling = this.getRetinaScaling();\n      if (retinaScaling !== 1) {\n        pointer.x /= retinaScaling;\n        pointer.y /= retinaScaling;\n      }\n\n      if (boundsWidth === 0 || boundsHeight === 0) {\n        // If bounds are not available (i.e. not visible), do not apply scale.\n        cssScale = { width: 1, height: 1 };\n      }\n      else {\n        cssScale = {\n          width: upperCanvasEl.width / boundsWidth,\n          height: upperCanvasEl.height / boundsHeight\n        };\n      }\n\n      return {\n        x: pointer.x * cssScale.width,\n        y: pointer.y * cssScale.height\n      };\n    },\n\n    /**\n     * @private\n     * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized\n     */\n    _createUpperCanvas: function () {\n      var lowerCanvasClass = this.lowerCanvasEl.className.replace(/\\s*lower-canvas\\s*/, ''),\n          lowerCanvasEl = this.lowerCanvasEl, upperCanvasEl = this.upperCanvasEl;\n\n      // there is no need to create a new upperCanvas element if we have already one.\n      if (upperCanvasEl) {\n        upperCanvasEl.className = '';\n      }\n      else {\n        upperCanvasEl = this._createCanvasElement();\n        this.upperCanvasEl = upperCanvasEl;\n      }\n      fabric.util.addClass(upperCanvasEl, 'upper-canvas ' + lowerCanvasClass);\n\n      this.wrapperEl.appendChild(upperCanvasEl);\n\n      this._copyCanvasStyle(lowerCanvasEl, upperCanvasEl);\n      this._applyCanvasStyle(upperCanvasEl);\n      this.contextTop = upperCanvasEl.getContext('2d');\n    },\n\n    /**\n     * @private\n     */\n    _createCacheCanvas: function () {\n      this.cacheCanvasEl = this._createCanvasElement();\n      this.cacheCanvasEl.setAttribute('width', this.width);\n      this.cacheCanvasEl.setAttribute('height', this.height);\n      this.contextCache = this.cacheCanvasEl.getContext('2d');\n    },\n\n    /**\n     * @private\n     */\n    _initWrapperElement: function () {\n      this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', {\n        'class': this.containerClass\n      });\n      fabric.util.setStyle(this.wrapperEl, {\n        width: this.width + 'px',\n        height: this.height + 'px',\n        position: 'relative'\n      });\n      fabric.util.makeElementUnselectable(this.wrapperEl);\n    },\n\n    /**\n     * @private\n     * @param {HTMLElement} element canvas element to apply styles on\n     */\n    _applyCanvasStyle: function (element) {\n      var width = this.width || element.width,\n          height = this.height || element.height;\n\n      fabric.util.setStyle(element, {\n        position: 'absolute',\n        width: width + 'px',\n        height: height + 'px',\n        left: 0,\n        top: 0,\n        'touch-action': this.allowTouchScrolling ? 'manipulation' : 'none',\n        '-ms-touch-action': this.allowTouchScrolling ? 'manipulation' : 'none'\n      });\n      element.width = width;\n      element.height = height;\n      fabric.util.makeElementUnselectable(element);\n    },\n\n    /**\n     * Copy the entire inline style from one element (fromEl) to another (toEl)\n     * @private\n     * @param {Element} fromEl Element style is copied from\n     * @param {Element} toEl Element copied style is applied to\n     */\n    _copyCanvasStyle: function (fromEl, toEl) {\n      toEl.style.cssText = fromEl.style.cssText;\n    },\n\n    /**\n     * Returns context of canvas where object selection is drawn\n     * @return {CanvasRenderingContext2D}\n     */\n    getSelectionContext: function() {\n      return this.contextTop;\n    },\n\n    /**\n     * Returns &lt;canvas> element on which object selection is drawn\n     * @return {HTMLCanvasElement}\n     */\n    getSelectionElement: function () {\n      return this.upperCanvasEl;\n    },\n\n    /**\n     * Returns currently active object\n     * @return {fabric.Object} active object\n     */\n    getActiveObject: function () {\n      return this._activeObject;\n    },\n\n    /**\n     * Returns an array with the current selected objects\n     * @return {fabric.Object} active object\n     */\n    getActiveObjects: function () {\n      var active = this._activeObject;\n      if (active) {\n        if (active.type === 'activeSelection' && active._objects) {\n          return active._objects.slice(0);\n        }\n        else {\n          return [active];\n        }\n      }\n      return [];\n    },\n\n    /**\n     * @private\n     * @param {fabric.Object} obj Object that was removed\n     */\n    _onObjectRemoved: function(obj) {\n      // removing active object should fire \"selection:cleared\" events\n      if (obj === this._activeObject) {\n        this.fire('before:selection:cleared', { target: obj });\n        this._discardActiveObject();\n        this.fire('selection:cleared', { target: obj });\n        obj.fire('deselected');\n      }\n      if (obj === this._hoveredTarget){\n        this._hoveredTarget = null;\n        this._hoveredTargets = [];\n      }\n      this.callSuper('_onObjectRemoved', obj);\n    },\n\n    /**\n     * @private\n     * Compares the old activeObject with the current one and fires correct events\n     * @param {fabric.Object} obj old activeObject\n     */\n    _fireSelectionEvents: function(oldObjects, e) {\n      var somethingChanged = false, objects = this.getActiveObjects(),\n          added = [], removed = [], opt = { e: e };\n      oldObjects.forEach(function(oldObject) {\n        if (objects.indexOf(oldObject) === -1) {\n          somethingChanged = true;\n          oldObject.fire('deselected', opt);\n          removed.push(oldObject);\n        }\n      });\n      objects.forEach(function(object) {\n        if (oldObjects.indexOf(object) === -1) {\n          somethingChanged = true;\n          object.fire('selected', opt);\n          added.push(object);\n        }\n      });\n      if (oldObjects.length > 0 && objects.length > 0) {\n        opt.selected = added;\n        opt.deselected = removed;\n        // added for backward compatibility\n        opt.updated = added[0] || removed[0];\n        opt.target = this._activeObject;\n        somethingChanged && this.fire('selection:updated', opt);\n      }\n      else if (objects.length > 0) {\n        opt.selected = added;\n        // added for backward compatibility\n        opt.target = this._activeObject;\n        this.fire('selection:created', opt);\n      }\n      else if (oldObjects.length > 0) {\n        opt.deselected = removed;\n        this.fire('selection:cleared', opt);\n      }\n    },\n\n    /**\n     * Sets given object as the only active object on canvas\n     * @param {fabric.Object} object Object to set as an active one\n     * @param {Event} [e] Event (passed along when firing \"object:selected\")\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    setActiveObject: function (object, e) {\n      var currentActives = this.getActiveObjects();\n      this._setActiveObject(object, e);\n      this._fireSelectionEvents(currentActives, e);\n      return this;\n    },\n\n    /**\n     * @private\n     * @param {Object} object to set as active\n     * @param {Event} [e] Event (passed along when firing \"object:selected\")\n     * @return {Boolean} true if the selection happened\n     */\n    _setActiveObject: function(object, e) {\n      if (this._activeObject === object) {\n        return false;\n      }\n      if (!this._discardActiveObject(e, object)) {\n        return false;\n      }\n      if (object.onSelect({ e: e })) {\n        return false;\n      }\n      this._activeObject = object;\n      return true;\n    },\n\n    /**\n     * @private\n     */\n    _discardActiveObject: function(e, object) {\n      var obj = this._activeObject;\n      if (obj) {\n        // onDeselect return TRUE to cancel selection;\n        if (obj.onDeselect({ e: e, object: object })) {\n          return false;\n        }\n        this._activeObject = null;\n      }\n      return true;\n    },\n\n    /**\n     * Discards currently active object and fire events. If the function is called by fabric\n     * as a consequence of a mouse event, the event is passed as a parameter and\n     * sent to the fire function for the custom events. When used as a method the\n     * e param does not have any application.\n     * @param {event} e\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    discardActiveObject: function (e) {\n      var currentActives = this.getActiveObjects(), activeObject = this.getActiveObject();\n      if (currentActives.length) {\n        this.fire('before:selection:cleared', { target: activeObject, e: e });\n      }\n      this._discardActiveObject(e);\n      this._fireSelectionEvents(currentActives, e);\n      return this;\n    },\n\n    /**\n     * Clears a canvas element and removes all event listeners\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    dispose: function () {\n      var wrapper = this.wrapperEl;\n      this.removeListeners();\n      wrapper.removeChild(this.upperCanvasEl);\n      wrapper.removeChild(this.lowerCanvasEl);\n      this.contextCache = null;\n      this.contextTop = null;\n      ['upperCanvasEl', 'cacheCanvasEl'].forEach((function(element) {\n        fabric.util.cleanUpJsdomNode(this[element]);\n        this[element] = undefined;\n      }).bind(this));\n      if (wrapper.parentNode) {\n        wrapper.parentNode.replaceChild(this.lowerCanvasEl, this.wrapperEl);\n      }\n      delete this.wrapperEl;\n      fabric.StaticCanvas.prototype.dispose.call(this);\n      return this;\n    },\n\n    /**\n     * Clears all contexts (background, main, top) of an instance\n     * @return {fabric.Canvas} thisArg\n     * @chainable\n     */\n    clear: function () {\n      // this.discardActiveGroup();\n      this.discardActiveObject();\n      this.clearContext(this.contextTop);\n      return this.callSuper('clear');\n    },\n\n    /**\n     * Draws objects' controls (borders/controls)\n     * @param {CanvasRenderingContext2D} ctx Context to render controls on\n     */\n    drawControls: function(ctx) {\n      var activeObject = this._activeObject;\n\n      if (activeObject) {\n        activeObject._renderControls(ctx);\n      }\n    },\n\n    /**\n     * @private\n     */\n    _toObject: function(instance, methodName, propertiesToInclude) {\n      //If the object is part of the current selection group, it should\n      //be transformed appropriately\n      //i.e. it should be serialised as it would appear if the selection group\n      //were to be destroyed.\n      var originalProperties = this._realizeGroupTransformOnObject(instance),\n          object = this.callSuper('_toObject', instance, methodName, propertiesToInclude);\n      //Undo the damage we did by changing all of its properties\n      this._unwindGroupTransformOnObject(instance, originalProperties);\n      return object;\n    },\n\n    /**\n     * Realises an object's group transformation on it\n     * @private\n     * @param {fabric.Object} [instance] the object to transform (gets mutated)\n     * @returns the original values of instance which were changed\n     */\n    _realizeGroupTransformOnObject: function(instance) {\n      if (instance.group && instance.group.type === 'activeSelection' && this._activeObject === instance.group) {\n        var layoutProps = ['angle', 'flipX', 'flipY', 'left', 'scaleX', 'scaleY', 'skewX', 'skewY', 'top'];\n        //Copy all the positionally relevant properties across now\n        var originalValues = {};\n        layoutProps.forEach(function(prop) {\n          originalValues[prop] = instance[prop];\n        });\n        this._activeObject.realizeTransform(instance);\n        return originalValues;\n      }\n      else {\n        return null;\n      }\n    },\n\n    /**\n     * Restores the changed properties of instance\n     * @private\n     * @param {fabric.Object} [instance] the object to un-transform (gets mutated)\n     * @param {Object} [originalValues] the original values of instance, as returned by _realizeGroupTransformOnObject\n     */\n    _unwindGroupTransformOnObject: function(instance, originalValues) {\n      if (originalValues) {\n        instance.set(originalValues);\n      }\n    },\n\n    /**\n     * @private\n     */\n    _setSVGObject: function(markup, instance, reviver) {\n      //If the object is in a selection group, simulate what would happen to that\n      //object when the group is deselected\n      var originalProperties = this._realizeGroupTransformOnObject(instance);\n      this.callSuper('_setSVGObject', markup, instance, reviver);\n      this._unwindGroupTransformOnObject(instance, originalProperties);\n    },\n\n    setViewportTransform: function (vpt) {\n      if (this.renderOnAddRemove && this._activeObject && this._activeObject.isEditing) {\n        this._activeObject.clearContextTop();\n      }\n      fabric.StaticCanvas.prototype.setViewportTransform.call(this, vpt);\n    }\n  });\n\n  // copying static properties manually to work around Opera's bug,\n  // where \"prototype\" property is enumerable and overrides existing prototype\n  for (var prop in fabric.StaticCanvas) {\n    if (prop !== 'prototype') {\n      fabric.Canvas[prop] = fabric.StaticCanvas[prop];\n    }\n  }\n})();\n\n\n(function() {\n\n  var addListener = fabric.util.addListener,\n      removeListener = fabric.util.removeListener,\n      RIGHT_CLICK = 3, MIDDLE_CLICK = 2, LEFT_CLICK = 1,\n      addEventOptions = { passive: false };\n\n  function checkClick(e, value) {\n    return e.button && (e.button === value - 1);\n  }\n\n  fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ {\n\n    /**\n     * Contains the id of the touch event that owns the fabric transform\n     * @type Number\n     * @private\n     */\n    mainTouchId: null,\n\n    /**\n     * Adds mouse listeners to canvas\n     * @private\n     */\n    _initEventListeners: function () {\n      // in case we initialized the class twice. This should not happen normally\n      // but in some kind of applications where the canvas element may be changed\n      // this is a workaround to having double listeners.\n      this.removeListeners();\n      this._bindEvents();\n      this.addOrRemove(addListener, 'add');\n    },\n\n    /**\n     * return an event prefix pointer or mouse.\n     * @private\n     */\n    _getEventPrefix: function () {\n      return this.enablePointerEvents ? 'pointer' : 'mouse';\n    },\n\n    addOrRemove: function(functor, eventjsFunctor) {\n      var canvasElement = this.upperCanvasEl,\n          eventTypePrefix = this._getEventPrefix();\n      functor(fabric.window, 'resize', this._onResize);\n      functor(canvasElement, eventTypePrefix + 'down', this._onMouseDown);\n      functor(canvasElement, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n      functor(canvasElement, eventTypePrefix + 'out', this._onMouseOut);\n      functor(canvasElement, eventTypePrefix + 'enter', this._onMouseEnter);\n      functor(canvasElement, 'wheel', this._onMouseWheel);\n      functor(canvasElement, 'contextmenu', this._onContextMenu);\n      functor(canvasElement, 'dblclick', this._onDoubleClick);\n      functor(canvasElement, 'dragover', this._onDragOver);\n      functor(canvasElement, 'dragenter', this._onDragEnter);\n      functor(canvasElement, 'dragleave', this._onDragLeave);\n      functor(canvasElement, 'drop', this._onDrop);\n      if (!this.enablePointerEvents) {\n        functor(canvasElement, 'touchstart', this._onTouchStart, addEventOptions);\n      }\n      if (typeof eventjs !== 'undefined' && eventjsFunctor in eventjs) {\n        eventjs[eventjsFunctor](canvasElement, 'gesture', this._onGesture);\n        eventjs[eventjsFunctor](canvasElement, 'drag', this._onDrag);\n        eventjs[eventjsFunctor](canvasElement, 'orientation', this._onOrientationChange);\n        eventjs[eventjsFunctor](canvasElement, 'shake', this._onShake);\n        eventjs[eventjsFunctor](canvasElement, 'longpress', this._onLongPress);\n      }\n    },\n\n    /**\n     * Removes all event listeners\n     */\n    removeListeners: function() {\n      this.addOrRemove(removeListener, 'remove');\n      // if you dispose on a mouseDown, before mouse up, you need to clean document to...\n      var eventTypePrefix = this._getEventPrefix();\n      removeListener(fabric.document, eventTypePrefix + 'up', this._onMouseUp);\n      removeListener(fabric.document, 'touchend', this._onTouchEnd, addEventOptions);\n      removeListener(fabric.document, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n      removeListener(fabric.document, 'touchmove', this._onMouseMove, addEventOptions);\n    },\n\n    /**\n     * @private\n     */\n    _bindEvents: function() {\n      if (this.eventsBound) {\n        // for any reason we pass here twice we do not want to bind events twice.\n        return;\n      }\n      this._onMouseDown = this._onMouseDown.bind(this);\n      this._onTouchStart = this._onTouchStart.bind(this);\n      this._onMouseMove = this._onMouseMove.bind(this);\n      this._onMouseUp = this._onMouseUp.bind(this);\n      this._onTouchEnd = this._onTouchEnd.bind(this);\n      this._onResize = this._onResize.bind(this);\n      this._onGesture = this._onGesture.bind(this);\n      this._onDrag = this._onDrag.bind(this);\n      this._onShake = this._onShake.bind(this);\n      this._onLongPress = this._onLongPress.bind(this);\n      this._onOrientationChange = this._onOrientationChange.bind(this);\n      this._onMouseWheel = this._onMouseWheel.bind(this);\n      this._onMouseOut = this._onMouseOut.bind(this);\n      this._onMouseEnter = this._onMouseEnter.bind(this);\n      this._onContextMenu = this._onContextMenu.bind(this);\n      this._onDoubleClick = this._onDoubleClick.bind(this);\n      this._onDragOver = this._onDragOver.bind(this);\n      this._onDragEnter = this._simpleEventHandler.bind(this, 'dragenter');\n      this._onDragLeave = this._simpleEventHandler.bind(this, 'dragleave');\n      this._onDrop = this._simpleEventHandler.bind(this, 'drop');\n      this.eventsBound = true;\n    },\n\n    /**\n     * @private\n     * @param {Event} [e] Event object fired on Event.js gesture\n     * @param {Event} [self] Inner Event object\n     */\n    _onGesture: function(e, self) {\n      this.__onTransformGesture && this.__onTransformGesture(e, self);\n    },\n\n    /**\n     * @private\n     * @param {Event} [e] Event object fired on Event.js drag\n     * @param {Event} [self] Inner Event object\n     */\n    _onDrag: function(e, self) {\n      this.__onDrag && this.__onDrag(e, self);\n    },\n\n    /**\n     * @private\n     * @param {Event} [e] Event object fired on wheel event\n     */\n    _onMouseWheel: function(e) {\n      this.__onMouseWheel(e);\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onMouseOut: function(e) {\n      var target = this._hoveredTarget;\n      this.fire('mouse:out', { target: target, e: e });\n      this._hoveredTarget = null;\n      target && target.fire('mouseout', { e: e });\n\n      var _this = this;\n      this._hoveredTargets.forEach(function(_target){\n        _this.fire('mouse:out', { target: target, e: e });\n        _target && target.fire('mouseout', { e: e });\n      });\n      this._hoveredTargets = [];\n\n      if (this._iTextInstances) {\n        this._iTextInstances.forEach(function(obj) {\n          if (obj.isEditing) {\n            obj.hiddenTextarea.focus();\n          }\n        });\n      }\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mouseenter\n     */\n    _onMouseEnter: function(e) {\n      // This find target and consequent 'mouse:over' is used to\n      // clear old instances on hovered target.\n      // calling findTarget has the side effect of killing target.__corner.\n      // as a short term fix we are not firing this if we are currently transforming.\n      // as a long term fix we need to separate the action of finding a target with the\n      // side effects we added to it.\n      if (!this._currentTransform && !this.findTarget(e)) {\n        this.fire('mouse:over', { target: null, e: e });\n        this._hoveredTarget = null;\n        this._hoveredTargets = [];\n      }\n    },\n\n    /**\n     * @private\n     * @param {Event} [e] Event object fired on Event.js orientation change\n     * @param {Event} [self] Inner Event object\n     */\n    _onOrientationChange: function(e, self) {\n      this.__onOrientationChange && this.__onOrientationChange(e, self);\n    },\n\n    /**\n     * @private\n     * @param {Event} [e] Event object fired on Event.js shake\n     * @param {Event} [self] Inner Event object\n     */\n    _onShake: function(e, self) {\n      this.__onShake && this.__onShake(e, self);\n    },\n\n    /**\n     * @private\n     * @param {Event} [e] Event object fired on Event.js shake\n     * @param {Event} [self] Inner Event object\n     */\n    _onLongPress: function(e, self) {\n      this.__onLongPress && this.__onLongPress(e, self);\n    },\n\n    /**\n     * prevent default to allow drop event to be fired\n     * @private\n     * @param {Event} [e] Event object fired on Event.js shake\n     */\n    _onDragOver: function(e) {\n      e.preventDefault();\n      var target = this._simpleEventHandler('dragover', e);\n      this._fireEnterLeaveEvents(target, e);\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onContextMenu: function (e) {\n      if (this.stopContextMenu) {\n        e.stopPropagation();\n        e.preventDefault();\n      }\n      return false;\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onDoubleClick: function (e) {\n      this._cacheTransformEventData(e);\n      this._handleEvent(e, 'dblclick');\n      this._resetTransformEventData(e);\n    },\n\n    /**\n     * Return a the id of an event.\n     * returns either the pointerId or the identifier or 0 for the mouse event\n     * @private\n     * @param {Event} evt Event object\n     */\n    getPointerId: function(evt) {\n      var changedTouches = evt.changedTouches;\n\n      if (changedTouches) {\n        return changedTouches[0] && changedTouches[0].identifier;\n      }\n\n      if (this.enablePointerEvents) {\n        return evt.pointerId;\n      }\n\n      return -1;\n    },\n\n    /**\n     * Determines if an event has the id of the event that is considered main\n     * @private\n     * @param {evt} event Event object\n     */\n    _isMainEvent: function(evt) {\n      if (evt.isPrimary === true) {\n        return true;\n      }\n      if (evt.isPrimary === false) {\n        return false;\n      }\n      if (evt.type === 'touchend' && evt.touches.length === 0) {\n        return true;\n      }\n      if (evt.changedTouches) {\n        return evt.changedTouches[0].identifier === this.mainTouchId;\n      }\n      return true;\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onTouchStart: function(e) {\n      e.preventDefault();\n      if (this.mainTouchId === null) {\n        this.mainTouchId = this.getPointerId(e);\n      }\n      this.__onMouseDown(e);\n      this._resetTransformEventData();\n      var canvasElement = this.upperCanvasEl,\n          eventTypePrefix = this._getEventPrefix();\n      addListener(fabric.document, 'touchend', this._onTouchEnd, addEventOptions);\n      addListener(fabric.document, 'touchmove', this._onMouseMove, addEventOptions);\n      // Unbind mousedown to prevent double triggers from touch devices\n      removeListener(canvasElement, eventTypePrefix + 'down', this._onMouseDown);\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onMouseDown: function (e) {\n      this.__onMouseDown(e);\n      this._resetTransformEventData();\n      var canvasElement = this.upperCanvasEl,\n          eventTypePrefix = this._getEventPrefix();\n      removeListener(canvasElement, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n      addListener(fabric.document, eventTypePrefix + 'up', this._onMouseUp);\n      addListener(fabric.document, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onTouchEnd: function(e) {\n      if (e.touches.length > 0) {\n        // if there are still touches stop here\n        return;\n      }\n      this.__onMouseUp(e);\n      this._resetTransformEventData();\n      this.mainTouchId = null;\n      var eventTypePrefix = this._getEventPrefix();\n      removeListener(fabric.document, 'touchend', this._onTouchEnd, addEventOptions);\n      removeListener(fabric.document, 'touchmove', this._onMouseMove, addEventOptions);\n      var _this = this;\n      if (this._willAddMouseDown) {\n        clearTimeout(this._willAddMouseDown);\n      }\n      this._willAddMouseDown = setTimeout(function() {\n        // Wait 400ms before rebinding mousedown to prevent double triggers\n        // from touch devices\n        addListener(_this.upperCanvasEl, eventTypePrefix + 'down', _this._onMouseDown);\n        _this._willAddMouseDown = 0;\n      }, 400);\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mouseup\n     */\n    _onMouseUp: function (e) {\n      this.__onMouseUp(e);\n      this._resetTransformEventData();\n      var canvasElement = this.upperCanvasEl,\n          eventTypePrefix = this._getEventPrefix();\n      if (this._isMainEvent(e)) {\n        removeListener(fabric.document, eventTypePrefix + 'up', this._onMouseUp);\n        removeListener(fabric.document, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n        addListener(canvasElement, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n      }\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousemove\n     */\n    _onMouseMove: function (e) {\n      !this.allowTouchScrolling && e.preventDefault && e.preventDefault();\n      this.__onMouseMove(e);\n    },\n\n    /**\n     * @private\n     */\n    _onResize: function () {\n      this.calcOffset();\n    },\n\n    /**\n     * Decides whether the canvas should be redrawn in mouseup and mousedown events.\n     * @private\n     * @param {Object} target\n     */\n    _shouldRender: function(target) {\n      var activeObject = this._activeObject;\n\n      if (\n        !!activeObject !== !!target ||\n        (activeObject && target && (activeObject !== target))\n      ) {\n        // this covers: switch of target, from target to no target, selection of target\n        // multiSelection with key and mouse\n        return true;\n      }\n      else if (activeObject && activeObject.isEditing) {\n        // if we mouse up/down over a editing textbox a cursor change,\n        // there is no need to re render\n        return false;\n      }\n      return false;\n    },\n\n    /**\n     * Method that defines the actions when mouse is released on canvas.\n     * The method resets the currentTransform parameters, store the image corner\n     * position in the image object and render the canvas on top.\n     * @private\n     * @param {Event} e Event object fired on mouseup\n     */\n    __onMouseUp: function (e) {\n      var target, transform = this._currentTransform,\n          groupSelector = this._groupSelector, shouldRender = false,\n          isClick = (!groupSelector || (groupSelector.left === 0 && groupSelector.top === 0));\n      this._cacheTransformEventData(e);\n      target = this._target;\n      this._handleEvent(e, 'up:before');\n      // if right/middle click just fire events and return\n      // target undefined will make the _handleEvent search the target\n      if (checkClick(e, RIGHT_CLICK)) {\n        if (this.fireRightClick) {\n          this._handleEvent(e, 'up', RIGHT_CLICK, isClick);\n        }\n        return;\n      }\n\n      if (checkClick(e, MIDDLE_CLICK)) {\n        if (this.fireMiddleClick) {\n          this._handleEvent(e, 'up', MIDDLE_CLICK, isClick);\n        }\n        this._resetTransformEventData();\n        return;\n      }\n\n      if (this.isDrawingMode && this._isCurrentlyDrawing) {\n        this._onMouseUpInDrawingMode(e);\n        return;\n      }\n\n      if (!this._isMainEvent(e)) {\n        return;\n      }\n      if (transform) {\n        this._finalizeCurrentTransform(e);\n        shouldRender = transform.actionPerformed;\n      }\n      if (!isClick) {\n        var targetWasActive = target === this._activeObject;\n        this._maybeGroupObjects(e);\n        if (!shouldRender) {\n          shouldRender = (\n            this._shouldRender(target) ||\n            (!targetWasActive && target === this._activeObject)\n          );\n        }\n      }\n      if (target) {\n        var corner = target._findTargetCorner(\n          this.getPointer(e, true),\n          fabric.util.isTouchEvent(e)\n        );\n        var control = target.controls[corner],\n            mouseUpHandler = control && control.getMouseUpHandler(e, target, control);\n        if (mouseUpHandler) {\n          mouseUpHandler(e, target, control);\n        }\n        target.isMoving = false;\n      }\n      this._setCursorFromEvent(e, target);\n      this._handleEvent(e, 'up', LEFT_CLICK, isClick);\n      this._groupSelector = null;\n      this._currentTransform = null;\n      // reset the target information about which corner is selected\n      target && (target.__corner = 0);\n      if (shouldRender) {\n        this.requestRenderAll();\n      }\n      else if (!isClick) {\n        this.renderTop();\n      }\n    },\n\n    /**\n     * @private\n     * Handle event firing for target and subtargets\n     * @param {Event} e event from mouse\n     * @param {String} eventType event to fire (up, down or move)\n     * @return {Fabric.Object} target return the the target found, for internal reasons.\n     */\n    _simpleEventHandler: function(eventType, e) {\n      var target = this.findTarget(e),\n          targets = this.targets,\n          options = {\n            e: e,\n            target: target,\n            subTargets: targets,\n          };\n      this.fire(eventType, options);\n      target && target.fire(eventType, options);\n      if (!targets) {\n        return target;\n      }\n      for (var i = 0; i < targets.length; i++) {\n        targets[i].fire(eventType, options);\n      }\n      return target;\n    },\n\n    /**\n     * @private\n     * Handle event firing for target and subtargets\n     * @param {Event} e event from mouse\n     * @param {String} eventType event to fire (up, down or move)\n     * @param {fabric.Object} targetObj receiving event\n     * @param {Number} [button] button used in the event 1 = left, 2 = middle, 3 = right\n     * @param {Boolean} isClick for left button only, indicates that the mouse up happened without move.\n     */\n    _handleEvent: function(e, eventType, button, isClick) {\n      var target = this._target,\n          targets = this.targets || [],\n          options = {\n            e: e,\n            target: target,\n            subTargets: targets,\n            button: button || LEFT_CLICK,\n            isClick: isClick || false,\n            pointer: this._pointer,\n            absolutePointer: this._absolutePointer,\n            transform: this._currentTransform\n          };\n      if (eventType === 'up') {\n        options.currentTarget = this.findTarget(e);\n        options.currentSubTargets = this.targets;\n      }\n      this.fire('mouse:' + eventType, options);\n      target && target.fire('mouse' + eventType, options);\n      for (var i = 0; i < targets.length; i++) {\n        targets[i].fire('mouse' + eventType, options);\n      }\n    },\n\n    /**\n     * @private\n     * @param {Event} e send the mouse event that generate the finalize down, so it can be used in the event\n     */\n    _finalizeCurrentTransform: function(e) {\n\n      var transform = this._currentTransform,\n          target = transform.target,\n          eventName,\n          options = {\n            e: e,\n            target: target,\n            transform: transform,\n            action: transform.action,\n          };\n\n      if (target._scaling) {\n        target._scaling = false;\n      }\n\n      target.setCoords();\n\n      if (transform.actionPerformed || (this.stateful && target.hasStateChanged())) {\n        if (transform.actionPerformed) {\n          // this is not friendly to the new control api.\n          // is deprecated.\n          eventName = this._addEventOptions(options, transform);\n          this._fire(eventName, options);\n        }\n        this._fire('modified', options);\n      }\n    },\n\n    /**\n     * Mutate option object in order to add by property and give back the event name.\n     * @private\n     * @deprecated since 4.2.0\n     * @param {Object} options to mutate\n     * @param {Object} transform to inspect action from\n     */\n    _addEventOptions: function(options, transform) {\n      // we can probably add more details at low cost\n      // scale change, rotation changes, translation changes\n      var eventName, by;\n      switch (transform.action) {\n        case 'scaleX':\n          eventName = 'scaled';\n          by = 'x';\n          break;\n        case 'scaleY':\n          eventName = 'scaled';\n          by = 'y';\n          break;\n        case 'skewX':\n          eventName = 'skewed';\n          by = 'x';\n          break;\n        case 'skewY':\n          eventName = 'skewed';\n          by = 'y';\n          break;\n        case 'scale':\n          eventName = 'scaled';\n          by = 'equally';\n          break;\n        case 'rotate':\n          eventName = 'rotated';\n          break;\n        case 'drag':\n          eventName = 'moved';\n          break;\n      }\n      options.by = by;\n      return eventName;\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    _onMouseDownInDrawingMode: function(e) {\n      this._isCurrentlyDrawing = true;\n      if (this.getActiveObject()) {\n        this.discardActiveObject(e).requestRenderAll();\n      }\n      var pointer = this.getPointer(e);\n      this.freeDrawingBrush.onMouseDown(pointer, { e: e, pointer: pointer });\n      this._handleEvent(e, 'down');\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mousemove\n     */\n    _onMouseMoveInDrawingMode: function(e) {\n      if (this._isCurrentlyDrawing) {\n        var pointer = this.getPointer(e);\n        this.freeDrawingBrush.onMouseMove(pointer, { e: e, pointer: pointer });\n      }\n      this.setCursor(this.freeDrawingCursor);\n      this._handleEvent(e, 'move');\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object fired on mouseup\n     */\n    _onMouseUpInDrawingMode: function(e) {\n      var pointer = this.getPointer(e);\n      this._isCurrentlyDrawing = this.freeDrawingBrush.onMouseUp({ e: e, pointer: pointer });\n      this._handleEvent(e, 'up');\n    },\n\n    /**\n     * Method that defines the actions when mouse is clicked on canvas.\n     * The method inits the currentTransform parameters and renders all the\n     * canvas so the current image can be placed on the top canvas and the rest\n     * in on the container one.\n     * @private\n     * @param {Event} e Event object fired on mousedown\n     */\n    __onMouseDown: function (e) {\n      this._cacheTransformEventData(e);\n      this._handleEvent(e, 'down:before');\n      var target = this._target;\n      // if right click just fire events\n      if (checkClick(e, RIGHT_CLICK)) {\n        if (this.fireRightClick) {\n          this._handleEvent(e, 'down', RIGHT_CLICK);\n        }\n        return;\n      }\n\n      if (checkClick(e, MIDDLE_CLICK)) {\n        if (this.fireMiddleClick) {\n          this._handleEvent(e, 'down', MIDDLE_CLICK);\n        }\n        return;\n      }\n\n      if (this.isDrawingMode) {\n        this._onMouseDownInDrawingMode(e);\n        return;\n      }\n\n      if (!this._isMainEvent(e)) {\n        return;\n      }\n\n      // ignore if some object is being transformed at this moment\n      if (this._currentTransform) {\n        return;\n      }\n\n      var pointer = this._pointer;\n      // save pointer for check in __onMouseUp event\n      this._previousPointer = pointer;\n      var shouldRender = this._shouldRender(target),\n          shouldGroup = this._shouldGroup(e, target);\n      if (this._shouldClearSelection(e, target)) {\n        this.discardActiveObject(e);\n      }\n      else if (shouldGroup) {\n        this._handleGrouping(e, target);\n        target = this._activeObject;\n      }\n\n      if (this.selection && (!target ||\n        (!target.selectable && !target.isEditing && target !== this._activeObject))) {\n        this._groupSelector = {\n          ex: pointer.x,\n          ey: pointer.y,\n          top: 0,\n          left: 0\n        };\n      }\n\n      if (target) {\n        var alreadySelected = target === this._activeObject;\n        if (target.selectable) {\n          this.setActiveObject(target, e);\n        }\n        var corner = target._findTargetCorner(\n          this.getPointer(e, true),\n          fabric.util.isTouchEvent(e)\n        );\n        target.__corner = corner;\n        if (target === this._activeObject && (corner || !shouldGroup)) {\n          var control = target.controls[corner],\n              mouseDownHandler = control && control.getMouseDownHandler(e, target, control);\n          if (mouseDownHandler) {\n            mouseDownHandler(e, target, control);\n          }\n          this._setupCurrentTransform(e, target, alreadySelected);\n        }\n      }\n      this._handleEvent(e, 'down');\n      // we must renderAll so that we update the visuals\n      (shouldRender || shouldGroup) && this.requestRenderAll();\n    },\n\n    /**\n     * reset cache form common information needed during event processing\n     * @private\n     */\n    _resetTransformEventData: function() {\n      this._target = null;\n      this._pointer = null;\n      this._absolutePointer = null;\n    },\n\n    /**\n     * Cache common information needed during event processing\n     * @private\n     * @param {Event} e Event object fired on event\n     */\n    _cacheTransformEventData: function(e) {\n      // reset in order to avoid stale caching\n      this._resetTransformEventData();\n      this._pointer = this.getPointer(e, true);\n      this._absolutePointer = this.restorePointerVpt(this._pointer);\n      this._target = this._currentTransform ? this._currentTransform.target : this.findTarget(e) || null;\n    },\n\n    /**\n     * @private\n     */\n    _beforeTransform: function(e) {\n      var t = this._currentTransform;\n      this.stateful && t.target.saveState();\n      this.fire('before:transform', {\n        e: e,\n        transform: t,\n      });\n    },\n\n    /**\n     * Method that defines the actions when mouse is hovering the canvas.\n     * The currentTransform parameter will define whether the user is rotating/scaling/translating\n     * an image or neither of them (only hovering). A group selection is also possible and would cancel\n     * all any other type of action.\n     * In case of an image transformation only the top canvas will be rendered.\n     * @private\n     * @param {Event} e Event object fired on mousemove\n     */\n    __onMouseMove: function (e) {\n      this._handleEvent(e, 'move:before');\n      this._cacheTransformEventData(e);\n      var target, pointer;\n\n      if (this.isDrawingMode) {\n        this._onMouseMoveInDrawingMode(e);\n        return;\n      }\n\n      if (!this._isMainEvent(e)) {\n        return;\n      }\n\n      var groupSelector = this._groupSelector;\n\n      // We initially clicked in an empty area, so we draw a box for multiple selection\n      if (groupSelector) {\n        pointer = this._pointer;\n\n        groupSelector.left = pointer.x - groupSelector.ex;\n        groupSelector.top = pointer.y - groupSelector.ey;\n\n        this.renderTop();\n      }\n      else if (!this._currentTransform) {\n        target = this.findTarget(e) || null;\n        this._setCursorFromEvent(e, target);\n        this._fireOverOutEvents(target, e);\n      }\n      else {\n        this._transformObject(e);\n      }\n      this._handleEvent(e, 'move');\n      this._resetTransformEventData();\n    },\n\n    /**\n     * Manage the mouseout, mouseover events for the fabric object on the canvas\n     * @param {Fabric.Object} target the target where the target from the mousemove event\n     * @param {Event} e Event object fired on mousemove\n     * @private\n     */\n    _fireOverOutEvents: function(target, e) {\n      var _hoveredTarget = this._hoveredTarget,\n          _hoveredTargets = this._hoveredTargets, targets = this.targets,\n          length = Math.max(_hoveredTargets.length, targets.length);\n\n      this.fireSyntheticInOutEvents(target, e, {\n        oldTarget: _hoveredTarget,\n        evtOut: 'mouseout',\n        canvasEvtOut: 'mouse:out',\n        evtIn: 'mouseover',\n        canvasEvtIn: 'mouse:over',\n      });\n      for (var i = 0; i < length; i++){\n        this.fireSyntheticInOutEvents(targets[i], e, {\n          oldTarget: _hoveredTargets[i],\n          evtOut: 'mouseout',\n          evtIn: 'mouseover',\n        });\n      }\n      this._hoveredTarget = target;\n      this._hoveredTargets = this.targets.concat();\n    },\n\n    /**\n     * Manage the dragEnter, dragLeave events for the fabric objects on the canvas\n     * @param {Fabric.Object} target the target where the target from the onDrag event\n     * @param {Event} e Event object fired on ondrag\n     * @private\n     */\n    _fireEnterLeaveEvents: function(target, e) {\n      var _draggedoverTarget = this._draggedoverTarget,\n          _hoveredTargets = this._hoveredTargets, targets = this.targets,\n          length = Math.max(_hoveredTargets.length, targets.length);\n\n      this.fireSyntheticInOutEvents(target, e, {\n        oldTarget: _draggedoverTarget,\n        evtOut: 'dragleave',\n        evtIn: 'dragenter',\n      });\n      for (var i = 0; i < length; i++) {\n        this.fireSyntheticInOutEvents(targets[i], e, {\n          oldTarget: _hoveredTargets[i],\n          evtOut: 'dragleave',\n          evtIn: 'dragenter',\n        });\n      }\n      this._draggedoverTarget = target;\n    },\n\n    /**\n     * Manage the synthetic in/out events for the fabric objects on the canvas\n     * @param {Fabric.Object} target the target where the target from the supported events\n     * @param {Event} e Event object fired\n     * @param {Object} config configuration for the function to work\n     * @param {String} config.targetName property on the canvas where the old target is stored\n     * @param {String} [config.canvasEvtOut] name of the event to fire at canvas level for out\n     * @param {String} config.evtOut name of the event to fire for out\n     * @param {String} [config.canvasEvtIn] name of the event to fire at canvas level for in\n     * @param {String} config.evtIn name of the event to fire for in\n     * @private\n     */\n    fireSyntheticInOutEvents: function(target, e, config) {\n      var inOpt, outOpt, oldTarget = config.oldTarget, outFires, inFires,\n          targetChanged = oldTarget !== target, canvasEvtIn = config.canvasEvtIn, canvasEvtOut = config.canvasEvtOut;\n      if (targetChanged) {\n        inOpt = { e: e, target: target, previousTarget: oldTarget };\n        outOpt = { e: e, target: oldTarget, nextTarget: target };\n      }\n      inFires = target && targetChanged;\n      outFires = oldTarget && targetChanged;\n      if (outFires) {\n        canvasEvtOut && this.fire(canvasEvtOut, outOpt);\n        oldTarget.fire(config.evtOut, outOpt);\n      }\n      if (inFires) {\n        canvasEvtIn && this.fire(canvasEvtIn, inOpt);\n        target.fire(config.evtIn, inOpt);\n      }\n    },\n\n    /**\n     * Method that defines actions when an Event Mouse Wheel\n     * @param {Event} e Event object fired on mouseup\n     */\n    __onMouseWheel: function(e) {\n      this._cacheTransformEventData(e);\n      this._handleEvent(e, 'wheel');\n      this._resetTransformEventData();\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event fired on mousemove\n     */\n    _transformObject: function(e) {\n      var pointer = this.getPointer(e),\n          transform = this._currentTransform;\n\n      transform.reset = false;\n      transform.target.isMoving = true;\n      transform.shiftKey = e.shiftKey;\n      transform.altKey = e[this.centeredKey];\n\n      this._performTransformAction(e, transform, pointer);\n      transform.actionPerformed && this.requestRenderAll();\n    },\n\n    /**\n     * @private\n     */\n    _performTransformAction: function(e, transform, pointer) {\n      var x = pointer.x,\n          y = pointer.y,\n          action = transform.action,\n          actionPerformed = false,\n          actionHandler = transform.actionHandler;\n          // this object could be created from the function in the control handlers\n\n\n      if (actionHandler) {\n        actionPerformed = actionHandler(e, transform, x, y);\n      }\n      if (action === 'drag' && actionPerformed) {\n        this.setCursor(transform.target.moveCursor || this.moveCursor);\n      }\n      transform.actionPerformed = transform.actionPerformed || actionPerformed;\n    },\n\n    /**\n     * @private\n     */\n    _fire: fabric.controlsUtils.fireEvent,\n\n    /**\n     * Sets the cursor depending on where the canvas is being hovered.\n     * Note: very buggy in Opera\n     * @param {Event} e Event object\n     * @param {Object} target Object that the mouse is hovering, if so.\n     */\n    _setCursorFromEvent: function (e, target) {\n      if (!target) {\n        this.setCursor(this.defaultCursor);\n        return false;\n      }\n      var hoverCursor = target.hoverCursor || this.hoverCursor,\n          activeSelection = this._activeObject && this._activeObject.type === 'activeSelection' ?\n            this._activeObject : null,\n          // only show proper corner when group selection is not active\n          corner = (!activeSelection || !activeSelection.contains(target))\n          // here we call findTargetCorner always with undefined for the touch parameter.\n          // we assume that if you are using a cursor you do not need to interact with\n          // the bigger touch area.\n                    && target._findTargetCorner(this.getPointer(e, true));\n\n      if (!corner) {\n        if (target.subTargetCheck){\n          // hoverCursor should come from top-most subTarget,\n          // so we walk the array backwards\n          this.targets.concat().reverse().map(function(_target){\n            hoverCursor = _target.hoverCursor || hoverCursor;\n          });\n        }\n        this.setCursor(hoverCursor);\n      }\n      else {\n        this.setCursor(this.getCornerCursor(corner, target, e));\n      }\n    },\n\n    /**\n     * @private\n     */\n    getCornerCursor: function(corner, target, e) {\n      var control = target.controls[corner];\n      return control.cursorStyleHandler(e, control, target);\n    }\n  });\n})();\n\n\n(function() {\n\n  var min = Math.min,\n      max = Math.max;\n\n  fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ {\n\n    /**\n     * @private\n     * @param {Event} e Event object\n     * @param {fabric.Object} target\n     * @return {Boolean}\n     */\n    _shouldGroup: function(e, target) {\n      var activeObject = this._activeObject;\n      return activeObject && this._isSelectionKeyPressed(e) && target && target.selectable && this.selection &&\n            (activeObject !== target || activeObject.type === 'activeSelection') && !target.onSelect({ e: e });\n    },\n\n    /**\n     * @private\n     * @param {Event} e Event object\n     * @param {fabric.Object} target\n     */\n    _handleGrouping: function (e, target) {\n      var activeObject = this._activeObject;\n      // avoid multi select when shift click on a corner\n      if (activeObject.__corner) {\n        return;\n      }\n      if (target === activeObject) {\n        // if it's a group, find target again, using activeGroup objects\n        target = this.findTarget(e, true);\n        // if even object is not found or we are on activeObjectCorner, bail out\n        if (!target || !target.selectable) {\n          return;\n        }\n      }\n      if (activeObject && activeObject.type === 'activeSelection') {\n        this._updateActiveSelection(target, e);\n      }\n      else {\n        this._createActiveSelection(target, e);\n      }\n    },\n\n    /**\n     * @private\n     */\n    _updateActiveSelection: function(target, e) {\n      var activeSelection = this._activeObject,\n          currentActiveObjects = activeSelection._objects.slice(0);\n      if (activeSelection.contains(target)) {\n        activeSelection.removeWithUpdate(target);\n        this._hoveredTarget = target;\n        this._hoveredTargets = this.targets.concat();\n        if (activeSelection.size() === 1) {\n          // activate last remaining object\n          this._setActiveObject(activeSelection.item(0), e);\n        }\n      }\n      else {\n        activeSelection.addWithUpdate(target);\n        this._hoveredTarget = activeSelection;\n        this._hoveredTargets = this.targets.concat();\n      }\n      this._fireSelectionEvents(currentActiveObjects, e);\n    },\n\n    /**\n     * @private\n     */\n    _createActiveSelection: function(target, e) {\n      var currentActives = this.getActiveObjects(), group = this._createGroup(target);\n      this._hoveredTarget = group;\n      // ISSUE 4115: should we consider subTargets here?\n      // this._hoveredTargets = [];\n      // this._hoveredTargets = this.targets.concat();\n      this._setActiveObject(group, e);\n      this._fireSelectionEvents(currentActives, e);\n    },\n\n    /**\n     * @private\n     * @param {Object} target\n     */\n    _createGroup: function(target) {\n      var objects = this._objects,\n          isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target),\n          groupObjects = isActiveLower\n            ? [this._activeObject, target]\n            : [target, this._activeObject];\n      this._activeObject.isEditing && this._activeObject.exitEditing();\n      return new fabric.ActiveSelection(groupObjects, {\n        canvas: this\n      });\n    },\n\n    /**\n     * @private\n     * @param {Event} e mouse event\n     */\n    _groupSelectedObjects: function (e) {\n\n      var group = this._collectObjects(e),\n          aGroup;\n\n      // do not create group for 1 element only\n      if (group.length === 1) {\n        this.setActiveObject(group[0], e);\n      }\n      else if (group.length > 1) {\n        aGroup = new fabric.ActiveSelection(group.reverse(), {\n          canvas: this\n        });\n        this.setActiveObject(aGroup, e);\n      }\n    },\n\n    /**\n     * @private\n     */\n    _collectObjects: function(e) {\n      var group = [],\n          currentObject,\n          x1 = this._groupSelector.ex,\n          y1 = this._groupSelector.ey,\n          x2 = x1 + this._groupSelector.left,\n          y2 = y1 + this._groupSelector.top,\n          selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)),\n          selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)),\n          allowIntersect = !this.selectionFullyContained,\n          isClick = x1 === x2 && y1 === y2;\n      // we iterate reverse order to collect top first in case of click.\n      for (var i = this._objects.length; i--; ) {\n        currentObject = this._objects[i];\n\n        if (!currentObject || !currentObject.selectable || !currentObject.visible) {\n          continue;\n        }\n\n        if ((allowIntersect && currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2)) ||\n            currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) ||\n            (allowIntersect && currentObject.containsPoint(selectionX1Y1)) ||\n            (allowIntersect && currentObject.containsPoint(selectionX2Y2))\n        ) {\n          group.push(currentObject);\n          // only add one object if it's a click\n          if (isClick) {\n            break;\n          }\n        }\n      }\n\n      if (group.length > 1) {\n        group = group.filter(function(object) {\n          return !object.onSelect({ e: e });\n        });\n      }\n\n      return group;\n    },\n\n    /**\n     * @private\n     */\n    _maybeGroupObjects: function(e) {\n      if (this.selection && this._groupSelector) {\n        this._groupSelectedObjects(e);\n      }\n      this.setCursor(this.defaultCursor);\n      // clear selection and current transformation\n      this._groupSelector = null;\n    }\n  });\n\n})();\n\n\n(function () {\n  fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n    /**\n     * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately\n     * @param {Object} [options] Options object\n     * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\n     * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\n     * @param {Number} [options.multiplier=1] Multiplier to scale by, to have consistent\n     * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n     * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n     * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n     * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n     * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 2.0.0\n     * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format\n     * @see {@link http://jsfiddle.net/fabricjs/NfZVb/|jsFiddle demo}\n     * @example <caption>Generate jpeg dataURL with lower quality</caption>\n     * var dataURL = canvas.toDataURL({\n     *   format: 'jpeg',\n     *   quality: 0.8\n     * });\n     * @example <caption>Generate cropped png dataURL (clipping of canvas)</caption>\n     * var dataURL = canvas.toDataURL({\n     *   format: 'png',\n     *   left: 100,\n     *   top: 100,\n     *   width: 200,\n     *   height: 200\n     * });\n     * @example <caption>Generate double scaled png dataURL</caption>\n     * var dataURL = canvas.toDataURL({\n     *   format: 'png',\n     *   multiplier: 2\n     * });\n     */\n    toDataURL: function (options) {\n      options || (options = { });\n\n      var format = options.format || 'png',\n          quality = options.quality || 1,\n          multiplier = (options.multiplier || 1) * (options.enableRetinaScaling ? this.getRetinaScaling() : 1),\n          canvasEl = this.toCanvasElement(multiplier, options);\n      return fabric.util.toDataURL(canvasEl, format, quality);\n    },\n\n    /**\n     * Create a new HTMLCanvas element painted with the current canvas content.\n     * No need to resize the actual one or repaint it.\n     * Will transfer object ownership to a new canvas, paint it, and set everything back.\n     * This is an intermediary step used to get to a dataUrl but also it is useful to\n     * create quick image copies of a canvas without passing for the dataUrl string\n     * @param {Number} [multiplier] a zoom factor.\n     * @param {Object} [cropping] Cropping informations\n     * @param {Number} [cropping.left] Cropping left offset.\n     * @param {Number} [cropping.top] Cropping top offset.\n     * @param {Number} [cropping.width] Cropping width.\n     * @param {Number} [cropping.height] Cropping height.\n     */\n    toCanvasElement: function(multiplier, cropping) {\n      multiplier = multiplier || 1;\n      cropping = cropping || { };\n      var scaledWidth = (cropping.width || this.width) * multiplier,\n          scaledHeight = (cropping.height || this.height) * multiplier,\n          zoom = this.getZoom(),\n          originalWidth = this.width,\n          originalHeight = this.height,\n          newZoom = zoom * multiplier,\n          vp = this.viewportTransform,\n          translateX = (vp[4] - (cropping.left || 0)) * multiplier,\n          translateY = (vp[5] - (cropping.top || 0)) * multiplier,\n          originalInteractive = this.interactive,\n          newVp = [newZoom, 0, 0, newZoom, translateX, translateY],\n          originalRetina = this.enableRetinaScaling,\n          canvasEl = fabric.util.createCanvasElement(),\n          originalContextTop = this.contextTop;\n      canvasEl.width = scaledWidth;\n      canvasEl.height = scaledHeight;\n      this.contextTop = null;\n      this.enableRetinaScaling = false;\n      this.interactive = false;\n      this.viewportTransform = newVp;\n      this.width = scaledWidth;\n      this.height = scaledHeight;\n      this.calcViewportBoundaries();\n      this.renderCanvas(canvasEl.getContext('2d'), this._objects);\n      this.viewportTransform = vp;\n      this.width = originalWidth;\n      this.height = originalHeight;\n      this.calcViewportBoundaries();\n      this.interactive = originalInteractive;\n      this.enableRetinaScaling = originalRetina;\n      this.contextTop = originalContextTop;\n      return canvasEl;\n    },\n  });\n\n})();\n\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n  /**\n   * Populates canvas with data from the specified JSON.\n   * JSON format must conform to the one of {@link fabric.Canvas#toJSON}\n   * @param {String|Object} json JSON string or object\n   * @param {Function} callback Callback, invoked when json is parsed\n   *                            and corresponding objects (e.g: {@link fabric.Image})\n   *                            are initialized\n   * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created.\n   * @return {fabric.Canvas} instance\n   * @chainable\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#deserialization}\n   * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo}\n   * @example <caption>loadFromJSON</caption>\n   * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));\n   * @example <caption>loadFromJSON with reviver</caption>\n   * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas), function(o, object) {\n   *   // `o` = json object\n   *   // `object` = fabric.Object instance\n   *   // ... do some stuff ...\n   * });\n   */\n  loadFromJSON: function (json, callback, reviver) {\n    if (!json) {\n      return;\n    }\n\n    // serialize if it wasn't already\n    var serialized = (typeof json === 'string')\n      ? JSON.parse(json)\n      : fabric.util.object.clone(json);\n\n    var _this = this,\n        clipPath = serialized.clipPath,\n        renderOnAddRemove = this.renderOnAddRemove;\n\n    this.renderOnAddRemove = false;\n\n    delete serialized.clipPath;\n\n    this._enlivenObjects(serialized.objects, function (enlivenedObjects) {\n      _this.clear();\n      _this._setBgOverlay(serialized, function () {\n        if (clipPath) {\n          _this._enlivenObjects([clipPath], function (enlivenedCanvasClip) {\n            _this.clipPath = enlivenedCanvasClip[0];\n            _this.__setupCanvas.call(_this, serialized, enlivenedObjects, renderOnAddRemove, callback);\n          });\n        }\n        else {\n          _this.__setupCanvas.call(_this, serialized, enlivenedObjects, renderOnAddRemove, callback);\n        }\n      });\n    }, reviver);\n    return this;\n  },\n\n  /**\n   * @private\n   * @param {Object} serialized Object with background and overlay information\n   * @param {Array} restored canvas objects\n   * @param {Function} cached renderOnAddRemove callback\n   * @param {Function} callback Invoked after all background and overlay images/patterns loaded\n   */\n  __setupCanvas: function(serialized, enlivenedObjects, renderOnAddRemove, callback) {\n    var _this = this;\n    enlivenedObjects.forEach(function(obj, index) {\n      // we splice the array just in case some custom classes restored from JSON\n      // will add more object to canvas at canvas init.\n      _this.insertAt(obj, index);\n    });\n    this.renderOnAddRemove = renderOnAddRemove;\n    // remove parts i cannot set as options\n    delete serialized.objects;\n    delete serialized.backgroundImage;\n    delete serialized.overlayImage;\n    delete serialized.background;\n    delete serialized.overlay;\n    // this._initOptions does too many things to just\n    // call it. Normally loading an Object from JSON\n    // create the Object instance. Here the Canvas is\n    // already an instance and we are just loading things over it\n    this._setOptions(serialized);\n    this.renderAll();\n    callback && callback();\n  },\n\n  /**\n   * @private\n   * @param {Object} serialized Object with background and overlay information\n   * @param {Function} callback Invoked after all background and overlay images/patterns loaded\n   */\n  _setBgOverlay: function(serialized, callback) {\n    var loaded = {\n      backgroundColor: false,\n      overlayColor: false,\n      backgroundImage: false,\n      overlayImage: false\n    };\n\n    if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background && !serialized.overlay) {\n      callback && callback();\n      return;\n    }\n\n    var cbIfLoaded = function () {\n      if (loaded.backgroundImage && loaded.overlayImage && loaded.backgroundColor && loaded.overlayColor) {\n        callback && callback();\n      }\n    };\n\n    this.__setBgOverlay('backgroundImage', serialized.backgroundImage, loaded, cbIfLoaded);\n    this.__setBgOverlay('overlayImage', serialized.overlayImage, loaded, cbIfLoaded);\n    this.__setBgOverlay('backgroundColor', serialized.background, loaded, cbIfLoaded);\n    this.__setBgOverlay('overlayColor', serialized.overlay, loaded, cbIfLoaded);\n  },\n\n  /**\n   * @private\n   * @param {String} property Property to set (backgroundImage, overlayImage, backgroundColor, overlayColor)\n   * @param {(Object|String)} value Value to set\n   * @param {Object} loaded Set loaded property to true if property is set\n   * @param {Object} callback Callback function to invoke after property is set\n   */\n  __setBgOverlay: function(property, value, loaded, callback) {\n    var _this = this;\n\n    if (!value) {\n      loaded[property] = true;\n      callback && callback();\n      return;\n    }\n\n    if (property === 'backgroundImage' || property === 'overlayImage') {\n      fabric.util.enlivenObjects([value], function(enlivedObject){\n        _this[property] = enlivedObject[0];\n        loaded[property] = true;\n        callback && callback();\n      });\n    }\n    else {\n      this['set' + fabric.util.string.capitalize(property, true)](value, function() {\n        loaded[property] = true;\n        callback && callback();\n      });\n    }\n  },\n\n  /**\n   * @private\n   * @param {Array} objects\n   * @param {Function} callback\n   * @param {Function} [reviver]\n   */\n  _enlivenObjects: function (objects, callback, reviver) {\n    if (!objects || objects.length === 0) {\n      callback && callback([]);\n      return;\n    }\n\n    fabric.util.enlivenObjects(objects, function(enlivenedObjects) {\n      callback && callback(enlivenedObjects);\n    }, null, reviver);\n  },\n\n  /**\n   * @private\n   * @param {String} format\n   * @param {Function} callback\n   */\n  _toDataURL: function (format, callback) {\n    this.clone(function (clone) {\n      callback(clone.toDataURL(format));\n    });\n  },\n\n  /**\n   * @private\n   * @param {String} format\n   * @param {Number} multiplier\n   * @param {Function} callback\n   */\n  _toDataURLWithMultiplier: function (format, multiplier, callback) {\n    this.clone(function (clone) {\n      callback(clone.toDataURLWithMultiplier(format, multiplier));\n    });\n  },\n\n  /**\n   * Clones canvas instance\n   * @param {Object} [callback] Receives cloned instance as a first argument\n   * @param {Array} [properties] Array of properties to include in the cloned canvas and children\n   */\n  clone: function (callback, properties) {\n    var data = JSON.stringify(this.toJSON(properties));\n    this.cloneWithoutData(function(clone) {\n      clone.loadFromJSON(data, function() {\n        callback && callback(clone);\n      });\n    });\n  },\n\n  /**\n   * Clones canvas instance without cloning existing data.\n   * This essentially copies canvas dimensions, clipping properties, etc.\n   * but leaves data empty (so that you can populate it with your own)\n   * @param {Object} [callback] Receives cloned instance as a first argument\n   */\n  cloneWithoutData: function(callback) {\n    var el = fabric.util.createCanvasElement();\n\n    el.width = this.width;\n    el.height = this.height;\n\n    var clone = new fabric.Canvas(el);\n    if (this.backgroundImage) {\n      clone.setBackgroundImage(this.backgroundImage.src, function() {\n        clone.renderAll();\n        callback && callback(clone);\n      });\n      clone.backgroundImageOpacity = this.backgroundImageOpacity;\n      clone.backgroundImageStretch = this.backgroundImageStretch;\n    }\n    else {\n      callback && callback(clone);\n    }\n  }\n});\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { }),\n      extend = fabric.util.object.extend,\n      clone = fabric.util.object.clone,\n      toFixed = fabric.util.toFixed,\n      capitalize = fabric.util.string.capitalize,\n      degreesToRadians = fabric.util.degreesToRadians,\n      supportsLineDash = fabric.StaticCanvas.supports('setLineDash'),\n      objectCaching = !fabric.isLikelyNode,\n      ALIASING_LIMIT = 2;\n\n  if (fabric.Object) {\n    return;\n  }\n\n  /**\n   * Root object class from which all 2d shape classes inherit from\n   * @class fabric.Object\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#objects}\n   * @see {@link fabric.Object#initialize} for constructor definition\n   *\n   * @fires added\n   * @fires removed\n   *\n   * @fires selected\n   * @fires deselected\n   * @fires modified\n   * @fires modified\n   * @fires moved\n   * @fires scaled\n   * @fires rotated\n   * @fires skewed\n   *\n   * @fires rotating\n   * @fires scaling\n   * @fires moving\n   * @fires skewing\n   *\n   * @fires mousedown\n   * @fires mouseup\n   * @fires mouseover\n   * @fires mouseout\n   * @fires mousewheel\n   * @fires mousedblclick\n   *\n   * @fires dragover\n   * @fires dragenter\n   * @fires dragleave\n   * @fires drop\n   */\n  fabric.Object = fabric.util.createClass(fabric.CommonMethods, /** @lends fabric.Object.prototype */ {\n\n    /**\n     * Type of an object (rect, circle, path, etc.).\n     * Note that this property is meant to be read-only and not meant to be modified.\n     * If you modify, certain parts of Fabric (such as JSON loading) won't work correctly.\n     * @type String\n     * @default\n     */\n    type:                     'object',\n\n    /**\n     * Horizontal origin of transformation of an object (one of \"left\", \"right\", \"center\")\n     * See http://jsfiddle.net/1ow02gea/244/ on how originX/originY affect objects in groups\n     * @type String\n     * @default\n     */\n    originX:                  'left',\n\n    /**\n     * Vertical origin of transformation of an object (one of \"top\", \"bottom\", \"center\")\n     * See http://jsfiddle.net/1ow02gea/244/ on how originX/originY affect objects in groups\n     * @type String\n     * @default\n     */\n    originY:                  'top',\n\n    /**\n     * Top position of an object. Note that by default it's relative to object top. You can change this by setting originY={top/center/bottom}\n     * @type Number\n     * @default\n     */\n    top:                      0,\n\n    /**\n     * Left position of an object. Note that by default it's relative to object left. You can change this by setting originX={left/center/right}\n     * @type Number\n     * @default\n     */\n    left:                     0,\n\n    /**\n     * Object width\n     * @type Number\n     * @default\n     */\n    width:                    0,\n\n    /**\n     * Object height\n     * @type Number\n     * @default\n     */\n    height:                   0,\n\n    /**\n     * Object scale factor (horizontal)\n     * @type Number\n     * @default\n     */\n    scaleX:                   1,\n\n    /**\n     * Object scale factor (vertical)\n     * @type Number\n     * @default\n     */\n    scaleY:                   1,\n\n    /**\n     * When true, an object is rendered as flipped horizontally\n     * @type Boolean\n     * @default\n     */\n    flipX:                    false,\n\n    /**\n     * When true, an object is rendered as flipped vertically\n     * @type Boolean\n     * @default\n     */\n    flipY:                    false,\n\n    /**\n     * Opacity of an object\n     * @type Number\n     * @default\n     */\n    opacity:                  1,\n\n    /**\n     * Angle of rotation of an object (in degrees)\n     * @type Number\n     * @default\n     */\n    angle:                    0,\n\n    /**\n     * Angle of skew on x axes of an object (in degrees)\n     * @type Number\n     * @default\n     */\n    skewX:                    0,\n\n    /**\n     * Angle of skew on y axes of an object (in degrees)\n     * @type Number\n     * @default\n     */\n    skewY:                    0,\n\n    /**\n     * Size of object's controlling corners (in pixels)\n     * @type Number\n     * @default\n     */\n    cornerSize:               13,\n\n    /**\n     * Size of object's controlling corners when touch interaction is detected\n     * @type Number\n     * @default\n     */\n    touchCornerSize:               24,\n\n    /**\n     * When true, object's controlling corners are rendered as transparent inside (i.e. stroke instead of fill)\n     * @type Boolean\n     * @default\n     */\n    transparentCorners:       true,\n\n    /**\n     * Default cursor value used when hovering over this object on canvas\n     * @type String\n     * @default\n     */\n    hoverCursor:              null,\n\n    /**\n     * Default cursor value used when moving this object on canvas\n     * @type String\n     * @default\n     */\n    moveCursor:               null,\n\n    /**\n     * Padding between object and its controlling borders (in pixels)\n     * @type Number\n     * @default\n     */\n    padding:                  0,\n\n    /**\n     * Color of controlling borders of an object (when it's active)\n     * @type String\n     * @default\n     */\n    borderColor:              'rgb(178,204,255)',\n\n    /**\n     * Array specifying dash pattern of an object's borders (hasBorder must be true)\n     * @since 1.6.2\n     * @type Array\n     */\n    borderDashArray:          null,\n\n    /**\n     * Color of controlling corners of an object (when it's active)\n     * @type String\n     * @default\n     */\n    cornerColor:              'rgb(178,204,255)',\n\n    /**\n     * Color of controlling corners of an object (when it's active and transparentCorners false)\n     * @since 1.6.2\n     * @type String\n     * @default\n     */\n    cornerStrokeColor:        null,\n\n    /**\n     * Specify style of control, 'rect' or 'circle'\n     * @since 1.6.2\n     * @type String\n     */\n    cornerStyle:          'rect',\n\n    /**\n     * Array specifying dash pattern of an object's control (hasBorder must be true)\n     * @since 1.6.2\n     * @type Array\n     */\n    cornerDashArray:          null,\n\n    /**\n     * When true, this object will use center point as the origin of transformation\n     * when being scaled via the controls.\n     * <b>Backwards incompatibility note:</b> This property replaces \"centerTransform\" (Boolean).\n     * @since 1.3.4\n     * @type Boolean\n     * @default\n     */\n    centeredScaling:          false,\n\n    /**\n     * When true, this object will use center point as the origin of transformation\n     * when being rotated via the controls.\n     * <b>Backwards incompatibility note:</b> This property replaces \"centerTransform\" (Boolean).\n     * @since 1.3.4\n     * @type Boolean\n     * @default\n     */\n    centeredRotation:         true,\n\n    /**\n     * Color of object's fill\n     * takes css colors https://www.w3.org/TR/css-color-3/\n     * @type String\n     * @default\n     */\n    fill:                     'rgb(0,0,0)',\n\n    /**\n     * Fill rule used to fill an object\n     * accepted values are nonzero, evenodd\n     * <b>Backwards incompatibility note:</b> This property was used for setting globalCompositeOperation until v1.4.12 (use `fabric.Object#globalCompositeOperation` instead)\n     * @type String\n     * @default\n     */\n    fillRule:                 'nonzero',\n\n    /**\n     * Composite rule used for canvas globalCompositeOperation\n     * @type String\n     * @default\n     */\n    globalCompositeOperation: 'source-over',\n\n    /**\n     * Background color of an object.\n     * takes css colors https://www.w3.org/TR/css-color-3/\n     * @type String\n     * @default\n     */\n    backgroundColor:          '',\n\n    /**\n     * Selection Background color of an object. colored layer behind the object when it is active.\n     * does not mix good with globalCompositeOperation methods.\n     * @type String\n     * @default\n     */\n    selectionBackgroundColor:          '',\n\n    /**\n     * When defined, an object is rendered via stroke and this property specifies its color\n     * takes css colors https://www.w3.org/TR/css-color-3/\n     * @type String\n     * @default\n     */\n    stroke:                   null,\n\n    /**\n     * Width of a stroke used to render this object\n     * @type Number\n     * @default\n     */\n    strokeWidth:              1,\n\n    /**\n     * Array specifying dash pattern of an object's stroke (stroke must be defined)\n     * @type Array\n     */\n    strokeDashArray:          null,\n\n    /**\n     * Line offset of an object's stroke\n     * @type Number\n     * @default\n     */\n    strokeDashOffset: 0,\n\n    /**\n     * Line endings style of an object's stroke (one of \"butt\", \"round\", \"square\")\n     * @type String\n     * @default\n     */\n    strokeLineCap:            'butt',\n\n    /**\n     * Corner style of an object's stroke (one of \"bevil\", \"round\", \"miter\")\n     * @type String\n     * @default\n     */\n    strokeLineJoin:           'miter',\n\n    /**\n     * Maximum miter length (used for strokeLineJoin = \"miter\") of an object's stroke\n     * @type Number\n     * @default\n     */\n    strokeMiterLimit:         4,\n\n    /**\n     * Shadow object representing shadow of this shape\n     * @type fabric.Shadow\n     * @default\n     */\n    shadow:                   null,\n\n    /**\n     * Opacity of object's controlling borders when object is active and moving\n     * @type Number\n     * @default\n     */\n    borderOpacityWhenMoving:  0.4,\n\n    /**\n     * Scale factor of object's controlling borders\n     * bigger number will make a thicker border\n     * border is 1, so this is basically a border tickness\n     * since there is no way to change the border itself.\n     * @type Number\n     * @default\n     */\n    borderScaleFactor:        1,\n\n    /**\n     * Minimum allowed scale value of an object\n     * @type Number\n     * @default\n     */\n    minScaleLimit:            0,\n\n    /**\n     * When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection).\n     * But events still fire on it.\n     * @type Boolean\n     * @default\n     */\n    selectable:               true,\n\n    /**\n     * When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4\n     * @type Boolean\n     * @default\n     */\n    evented:                  true,\n\n    /**\n     * When set to `false`, an object is not rendered on canvas\n     * @type Boolean\n     * @default\n     */\n    visible:                  true,\n\n    /**\n     * When set to `false`, object's controls are not displayed and can not be used to manipulate object\n     * @type Boolean\n     * @default\n     */\n    hasControls:              true,\n\n    /**\n     * When set to `false`, object's controlling borders are not rendered\n     * @type Boolean\n     * @default\n     */\n    hasBorders:               true,\n\n    /**\n     * When set to `true`, objects are \"found\" on canvas on per-pixel basis rather than according to bounding box\n     * @type Boolean\n     * @default\n     */\n    perPixelTargetFind:       false,\n\n    /**\n     * When `false`, default object's values are not included in its serialization\n     * @type Boolean\n     * @default\n     */\n    includeDefaultValues:     true,\n\n    /**\n     * When `true`, object horizontal movement is locked\n     * @type Boolean\n     * @default\n     */\n    lockMovementX:            false,\n\n    /**\n     * When `true`, object vertical movement is locked\n     * @type Boolean\n     * @default\n     */\n    lockMovementY:            false,\n\n    /**\n     * When `true`, object rotation is locked\n     * @type Boolean\n     * @default\n     */\n    lockRotation:             false,\n\n    /**\n     * When `true`, object horizontal scaling is locked\n     * @type Boolean\n     * @default\n     */\n    lockScalingX:             false,\n\n    /**\n     * When `true`, object vertical scaling is locked\n     * @type Boolean\n     * @default\n     */\n    lockScalingY:             false,\n\n    /**\n     * When `true`, object horizontal skewing is locked\n     * @type Boolean\n     * @default\n     */\n    lockSkewingX:             false,\n\n    /**\n     * When `true`, object vertical skewing is locked\n     * @type Boolean\n     * @default\n     */\n    lockSkewingY:             false,\n\n    /**\n     * When `true`, object cannot be flipped by scaling into negative values\n     * @type Boolean\n     * @default\n     */\n    lockScalingFlip:          false,\n\n    /**\n     * When `true`, object is not exported in OBJECT/JSON\n     * @since 1.6.3\n     * @type Boolean\n     * @default\n     */\n    excludeFromExport:        false,\n\n    /**\n     * When `true`, object is cached on an additional canvas.\n     * When `false`, object is not cached unless necessary ( clipPath )\n     * default to true\n     * @since 1.7.0\n     * @type Boolean\n     * @default true\n     */\n    objectCaching:            objectCaching,\n\n    /**\n     * When `true`, object properties are checked for cache invalidation. In some particular\n     * situation you may want this to be disabled ( spray brush, very big, groups)\n     * or if your application does not allow you to modify properties for groups child you want\n     * to disable it for groups.\n     * default to false\n     * since 1.7.0\n     * @type Boolean\n     * @default false\n     */\n    statefullCache:            false,\n\n    /**\n     * When `true`, cache does not get updated during scaling. The picture will get blocky if scaled\n     * too much and will be redrawn with correct details at the end of scaling.\n     * this setting is performance and application dependant.\n     * default to true\n     * since 1.7.0\n     * @type Boolean\n     * @default true\n     */\n    noScaleCache:              true,\n\n    /**\n     * When `false`, the stoke width will scale with the object.\n     * When `true`, the stroke will always match the exact pixel size entered for stroke width.\n     * default to false\n     * @since 2.6.0\n     * @type Boolean\n     * @default false\n     * @type Boolean\n     * @default false\n     */\n    strokeUniform:              false,\n\n    /**\n     * When set to `true`, object's cache will be rerendered next render call.\n     * since 1.7.0\n     * @type Boolean\n     * @default true\n     */\n    dirty:                true,\n\n    /**\n     * keeps the value of the last hovered corner during mouse move.\n     * 0 is no corner, or 'mt', 'ml', 'mtr' etc..\n     * It should be private, but there is no harm in using it as\n     * a read-only property.\n     * @type number|string|any\n     * @default 0\n     */\n    __corner: 0,\n\n    /**\n     * Determines if the fill or the stroke is drawn first (one of \"fill\" or \"stroke\")\n     * @type String\n     * @default\n     */\n    paintFirst:           'fill',\n\n    /**\n     * List of properties to consider when checking if state\n     * of an object is changed (fabric.Object#hasStateChanged)\n     * as well as for history (undo/redo) purposes\n     * @type Array\n     */\n    stateProperties: (\n      'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' +\n      'stroke strokeWidth strokeDashArray strokeLineCap strokeDashOffset strokeLineJoin strokeMiterLimit ' +\n      'angle opacity fill globalCompositeOperation shadow visible backgroundColor ' +\n      'skewX skewY fillRule paintFirst clipPath strokeUniform'\n    ).split(' '),\n\n    /**\n     * List of properties to consider when checking if cache needs refresh\n     * Those properties are checked by statefullCache ON ( or lazy mode if we want ) or from single\n     * calls to Object.set(key, value). If the key is in this list, the object is marked as dirty\n     * and refreshed at the next render\n     * @type Array\n     */\n    cacheProperties: (\n      'fill stroke strokeWidth strokeDashArray width height paintFirst strokeUniform' +\n      ' strokeLineCap strokeDashOffset strokeLineJoin strokeMiterLimit backgroundColor clipPath'\n    ).split(' '),\n\n    /**\n     * List of properties to consider for animating colors.\n     * @type Array\n     */\n    colorProperties: (\n      'fill stroke backgroundColor'\n    ).split(' '),\n\n    /**\n     * a fabricObject that, without stroke define a clipping area with their shape. filled in black\n     * the clipPath object gets used when the object has rendered, and the context is placed in the center\n     * of the object cacheCanvas.\n     * If you want 0,0 of a clipPath to align with an object center, use clipPath.originX/Y to 'center'\n     * @type fabric.Object\n     */\n    clipPath: undefined,\n\n    /**\n     * Meaningful ONLY when the object is used as clipPath.\n     * if true, the clipPath will make the object clip to the outside of the clipPath\n     * since 2.4.0\n     * @type boolean\n     * @default false\n     */\n    inverted: false,\n\n    /**\n     * Meaningful ONLY when the object is used as clipPath.\n     * if true, the clipPath will have its top and left relative to canvas, and will\n     * not be influenced by the object transform. This will make the clipPath relative\n     * to the canvas, but clipping just a particular object.\n     * WARNING this is beta, this feature may change or be renamed.\n     * since 2.4.0\n     * @type boolean\n     * @default false\n     */\n    absolutePositioned: false,\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     */\n    initialize: function(options) {\n      if (options) {\n        this.setOptions(options);\n      }\n    },\n\n    /**\n     * Create a the canvas used to keep the cached copy of the object\n     * @private\n     */\n    _createCacheCanvas: function() {\n      this._cacheProperties = {};\n      this._cacheCanvas = fabric.util.createCanvasElement();\n      this._cacheContext = this._cacheCanvas.getContext('2d');\n      this._updateCacheCanvas();\n      // if canvas gets created, is empty, so dirty.\n      this.dirty = true;\n    },\n\n    /**\n     * Limit the cache dimensions so that X * Y do not cross fabric.perfLimitSizeTotal\n     * and each side do not cross fabric.cacheSideLimit\n     * those numbers are configurable so that you can get as much detail as you want\n     * making bargain with performances.\n     * @param {Object} dims\n     * @param {Object} dims.width width of canvas\n     * @param {Object} dims.height height of canvas\n     * @param {Object} dims.zoomX zoomX zoom value to unscale the canvas before drawing cache\n     * @param {Object} dims.zoomY zoomY zoom value to unscale the canvas before drawing cache\n     * @return {Object}.width width of canvas\n     * @return {Object}.height height of canvas\n     * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\n     * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\n     */\n    _limitCacheSize: function(dims) {\n      var perfLimitSizeTotal = fabric.perfLimitSizeTotal,\n          width = dims.width, height = dims.height,\n          max = fabric.maxCacheSideLimit, min = fabric.minCacheSideLimit;\n      if (width <= max && height <= max && width * height <= perfLimitSizeTotal) {\n        if (width < min) {\n          dims.width = min;\n        }\n        if (height < min) {\n          dims.height = min;\n        }\n        return dims;\n      }\n      var ar = width / height, limitedDims = fabric.util.limitDimsByArea(ar, perfLimitSizeTotal),\n          capValue = fabric.util.capValue,\n          x = capValue(min, limitedDims.x, max),\n          y = capValue(min, limitedDims.y, max);\n      if (width > x) {\n        dims.zoomX /= width / x;\n        dims.width = x;\n        dims.capped = true;\n      }\n      if (height > y) {\n        dims.zoomY /= height / y;\n        dims.height = y;\n        dims.capped = true;\n      }\n      return dims;\n    },\n\n    /**\n     * Return the dimension and the zoom level needed to create a cache canvas\n     * big enough to host the object to be cached.\n     * @private\n     * @return {Object}.x width of object to be cached\n     * @return {Object}.y height of object to be cached\n     * @return {Object}.width width of canvas\n     * @return {Object}.height height of canvas\n     * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\n     * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\n     */\n    _getCacheCanvasDimensions: function() {\n      var objectScale = this.getTotalObjectScaling(),\n          // caculate dimensions without skewing\n          dim = this._getTransformedDimensions(0, 0),\n          neededX = dim.x * objectScale.scaleX / this.scaleX,\n          neededY = dim.y * objectScale.scaleY / this.scaleY;\n      return {\n        // for sure this ALIASING_LIMIT is slightly creating problem\n        // in situation in which the cache canvas gets an upper limit\n        // also objectScale contains already scaleX and scaleY\n        width: neededX + ALIASING_LIMIT,\n        height: neededY + ALIASING_LIMIT,\n        zoomX: objectScale.scaleX,\n        zoomY: objectScale.scaleY,\n        x: neededX,\n        y: neededY\n      };\n    },\n\n    /**\n     * Update width and height of the canvas for cache\n     * returns true or false if canvas needed resize.\n     * @private\n     * @return {Boolean} true if the canvas has been resized\n     */\n    _updateCacheCanvas: function() {\n      var targetCanvas = this.canvas;\n      if (this.noScaleCache && targetCanvas && targetCanvas._currentTransform) {\n        var target = targetCanvas._currentTransform.target,\n            action = targetCanvas._currentTransform.action;\n        if (this === target && action.slice && action.slice(0, 5) === 'scale') {\n          return false;\n        }\n      }\n      var canvas = this._cacheCanvas,\n          dims = this._limitCacheSize(this._getCacheCanvasDimensions()),\n          minCacheSize = fabric.minCacheSideLimit,\n          width = dims.width, height = dims.height, drawingWidth, drawingHeight,\n          zoomX = dims.zoomX, zoomY = dims.zoomY,\n          dimensionsChanged = width !== this.cacheWidth || height !== this.cacheHeight,\n          zoomChanged = this.zoomX !== zoomX || this.zoomY !== zoomY,\n          shouldRedraw = dimensionsChanged || zoomChanged,\n          additionalWidth = 0, additionalHeight = 0, shouldResizeCanvas = false;\n      if (dimensionsChanged) {\n        var canvasWidth = this._cacheCanvas.width,\n            canvasHeight = this._cacheCanvas.height,\n            sizeGrowing = width > canvasWidth || height > canvasHeight,\n            sizeShrinking = (width < canvasWidth * 0.9 || height < canvasHeight * 0.9) &&\n              canvasWidth > minCacheSize && canvasHeight > minCacheSize;\n        shouldResizeCanvas = sizeGrowing || sizeShrinking;\n        if (sizeGrowing && !dims.capped && (width > minCacheSize || height > minCacheSize)) {\n          additionalWidth = width * 0.1;\n          additionalHeight = height * 0.1;\n        }\n      }\n      if (shouldRedraw) {\n        if (shouldResizeCanvas) {\n          canvas.width = Math.ceil(width + additionalWidth);\n          canvas.height = Math.ceil(height + additionalHeight);\n        }\n        else {\n          this._cacheContext.setTransform(1, 0, 0, 1, 0, 0);\n          this._cacheContext.clearRect(0, 0, canvas.width, canvas.height);\n        }\n        drawingWidth = dims.x / 2;\n        drawingHeight = dims.y / 2;\n        this.cacheTranslationX = Math.round(canvas.width / 2 - drawingWidth) + drawingWidth;\n        this.cacheTranslationY = Math.round(canvas.height / 2 - drawingHeight) + drawingHeight;\n        this.cacheWidth = width;\n        this.cacheHeight = height;\n        this._cacheContext.translate(this.cacheTranslationX, this.cacheTranslationY);\n        this._cacheContext.scale(zoomX, zoomY);\n        this.zoomX = zoomX;\n        this.zoomY = zoomY;\n        return true;\n      }\n      return false;\n    },\n\n    /**\n     * Sets object's properties from options\n     * @param {Object} [options] Options object\n     */\n    setOptions: function(options) {\n      this._setOptions(options);\n      this._initGradient(options.fill, 'fill');\n      this._initGradient(options.stroke, 'stroke');\n      this._initPattern(options.fill, 'fill');\n      this._initPattern(options.stroke, 'stroke');\n    },\n\n    /**\n     * Transforms context when rendering an object\n     * @param {CanvasRenderingContext2D} ctx Context\n     */\n    transform: function(ctx) {\n      var needFullTransform = (this.group && !this.group._transformDone) ||\n         (this.group && this.canvas && ctx === this.canvas.contextTop);\n      var m = this.calcTransformMatrix(!needFullTransform);\n      ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\n    },\n\n    /**\n     * Returns an object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function(propertiesToInclude) {\n      var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n\n          object = {\n            type:                     this.type,\n            version:                  fabric.version,\n            originX:                  this.originX,\n            originY:                  this.originY,\n            left:                     toFixed(this.left, NUM_FRACTION_DIGITS),\n            top:                      toFixed(this.top, NUM_FRACTION_DIGITS),\n            width:                    toFixed(this.width, NUM_FRACTION_DIGITS),\n            height:                   toFixed(this.height, NUM_FRACTION_DIGITS),\n            fill:                     (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill,\n            stroke:                   (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke,\n            strokeWidth:              toFixed(this.strokeWidth, NUM_FRACTION_DIGITS),\n            strokeDashArray:          this.strokeDashArray ? this.strokeDashArray.concat() : this.strokeDashArray,\n            strokeLineCap:            this.strokeLineCap,\n            strokeDashOffset:         this.strokeDashOffset,\n            strokeLineJoin:           this.strokeLineJoin,\n            // strokeUniform:            this.strokeUniform,\n            strokeMiterLimit:         toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS),\n            scaleX:                   toFixed(this.scaleX, NUM_FRACTION_DIGITS),\n            scaleY:                   toFixed(this.scaleY, NUM_FRACTION_DIGITS),\n            angle:                    toFixed(this.angle, NUM_FRACTION_DIGITS),\n            flipX:                    this.flipX,\n            flipY:                    this.flipY,\n            opacity:                  toFixed(this.opacity, NUM_FRACTION_DIGITS),\n            shadow:                   (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow,\n            visible:                  this.visible,\n            backgroundColor:          this.backgroundColor,\n            fillRule:                 this.fillRule,\n            paintFirst:               this.paintFirst,\n            globalCompositeOperation: this.globalCompositeOperation,\n            skewX:                    toFixed(this.skewX, NUM_FRACTION_DIGITS),\n            skewY:                    toFixed(this.skewY, NUM_FRACTION_DIGITS),\n          };\n\n      if (this.clipPath) {\n        object.clipPath = this.clipPath.toObject(propertiesToInclude);\n        object.clipPath.inverted = this.clipPath.inverted;\n        object.clipPath.absolutePositioned = this.clipPath.absolutePositioned;\n      }\n\n      fabric.util.populateWithProperties(this, object, propertiesToInclude);\n      if (!this.includeDefaultValues) {\n        object = this._removeDefaultValues(object);\n      }\n\n      return object;\n    },\n\n    /**\n     * Returns (dataless) object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} Object representation of an instance\n     */\n    toDatalessObject: function(propertiesToInclude) {\n      // will be overwritten by subclasses\n      return this.toObject(propertiesToInclude);\n    },\n\n    /**\n     * @private\n     * @param {Object} object\n     */\n    _removeDefaultValues: function(object) {\n      var prototype = fabric.util.getKlass(object.type).prototype,\n          stateProperties = prototype.stateProperties;\n      stateProperties.forEach(function(prop) {\n        if (prop === 'left' || prop === 'top') {\n          return;\n        }\n        if (object[prop] === prototype[prop]) {\n          delete object[prop];\n        }\n        var isArray = Object.prototype.toString.call(object[prop]) === '[object Array]' &&\n                      Object.prototype.toString.call(prototype[prop]) === '[object Array]';\n\n        // basically a check for [] === []\n        if (isArray && object[prop].length === 0 && prototype[prop].length === 0) {\n          delete object[prop];\n        }\n      });\n\n      return object;\n    },\n\n    /**\n     * Returns a string representation of an instance\n     * @return {String}\n     */\n    toString: function() {\n      return '#<fabric.' + capitalize(this.type) + '>';\n    },\n\n    /**\n     * Return the object scale factor counting also the group scaling\n     * @return {Object} object with scaleX and scaleY properties\n     */\n    getObjectScaling: function() {\n      var options = fabric.util.qrDecompose(this.calcTransformMatrix());\n      return { scaleX: Math.abs(options.scaleX), scaleY: Math.abs(options.scaleY) };\n    },\n\n    /**\n     * Return the object scale factor counting also the group scaling, zoom and retina\n     * @return {Object} object with scaleX and scaleY properties\n     */\n    getTotalObjectScaling: function() {\n      var scale = this.getObjectScaling(), scaleX = scale.scaleX, scaleY = scale.scaleY;\n      if (this.canvas) {\n        var zoom = this.canvas.getZoom();\n        var retina = this.canvas.getRetinaScaling();\n        scaleX *= zoom * retina;\n        scaleY *= zoom * retina;\n      }\n      return { scaleX: scaleX, scaleY: scaleY };\n    },\n\n    /**\n     * Return the object opacity counting also the group property\n     * @return {Number}\n     */\n    getObjectOpacity: function() {\n      var opacity = this.opacity;\n      if (this.group) {\n        opacity *= this.group.getObjectOpacity();\n      }\n      return opacity;\n    },\n\n    /**\n     * @private\n     * @param {String} key\n     * @param {*} value\n     * @return {fabric.Object} thisArg\n     */\n    _set: function(key, value) {\n      var shouldConstrainValue = (key === 'scaleX' || key === 'scaleY'),\n          isChanged = this[key] !== value, groupNeedsUpdate = false;\n\n      if (shouldConstrainValue) {\n        value = this._constrainScale(value);\n      }\n      if (key === 'scaleX' && value < 0) {\n        this.flipX = !this.flipX;\n        value *= -1;\n      }\n      else if (key === 'scaleY' && value < 0) {\n        this.flipY = !this.flipY;\n        value *= -1;\n      }\n      else if (key === 'shadow' && value && !(value instanceof fabric.Shadow)) {\n        value = new fabric.Shadow(value);\n      }\n      else if (key === 'dirty' && this.group) {\n        this.group.set('dirty', value);\n      }\n\n      this[key] = value;\n\n      if (isChanged) {\n        groupNeedsUpdate = this.group && this.group.isOnACache();\n        if (this.cacheProperties.indexOf(key) > -1) {\n          this.dirty = true;\n          groupNeedsUpdate && this.group.set('dirty', true);\n        }\n        else if (groupNeedsUpdate && this.stateProperties.indexOf(key) > -1) {\n          this.group.set('dirty', true);\n        }\n      }\n\n      return this;\n    },\n\n    /**\n     * This callback function is called by the parent group of an object every\n     * time a non-delegated property changes on the group. It is passed the key\n     * and value as parameters. Not adding in this function's signature to avoid\n     * Travis build error about unused variables.\n     */\n    setOnGroup: function() {\n      // implemented by sub-classes, as needed.\n    },\n\n    /**\n     * Retrieves viewportTransform from Object's canvas if possible\n     * @method getViewportTransform\n     * @memberOf fabric.Object.prototype\n     * @return {Array}\n     */\n    getViewportTransform: function() {\n      if (this.canvas && this.canvas.viewportTransform) {\n        return this.canvas.viewportTransform;\n      }\n      return fabric.iMatrix.concat();\n    },\n\n    /*\n     * @private\n     * return if the object would be visible in rendering\n     * @memberOf fabric.Object.prototype\n     * @return {Boolean}\n     */\n    isNotVisible: function() {\n      return this.opacity === 0 ||\n        (!this.width && !this.height && this.strokeWidth === 0) ||\n        !this.visible;\n    },\n\n    /**\n     * Renders an object on a specified context\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    render: function(ctx) {\n      // do not render if width/height are zeros or object is not visible\n      if (this.isNotVisible()) {\n        return;\n      }\n      if (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) {\n        return;\n      }\n      ctx.save();\n      this._setupCompositeOperation(ctx);\n      this.drawSelectionBackground(ctx);\n      this.transform(ctx);\n      this._setOpacity(ctx);\n      this._setShadow(ctx, this);\n      if (this.shouldCache()) {\n        this.renderCache();\n        this.drawCacheOnCanvas(ctx);\n      }\n      else {\n        this._removeCacheCanvas();\n        this.dirty = false;\n        this.drawObject(ctx);\n        if (this.objectCaching && this.statefullCache) {\n          this.saveState({ propertySet: 'cacheProperties' });\n        }\n      }\n      ctx.restore();\n    },\n\n    renderCache: function(options) {\n      options = options || {};\n      if (!this._cacheCanvas) {\n        this._createCacheCanvas();\n      }\n      if (this.isCacheDirty()) {\n        this.statefullCache && this.saveState({ propertySet: 'cacheProperties' });\n        this.drawObject(this._cacheContext, options.forClipping);\n        this.dirty = false;\n      }\n    },\n\n    /**\n     * Remove cacheCanvas and its dimensions from the objects\n     */\n    _removeCacheCanvas: function() {\n      this._cacheCanvas = null;\n      this.cacheWidth = 0;\n      this.cacheHeight = 0;\n    },\n\n    /**\n     * return true if the object will draw a stroke\n     * Does not consider text styles. This is just a shortcut used at rendering time\n     * We want it to be an aproximation and be fast.\n     * wrote to avoid extra caching, it has to return true when stroke happens,\n     * can guess when it will not happen at 100% chance, does not matter if it misses\n     * some use case where the stroke is invisible.\n     * @since 3.0.0\n     * @returns Boolean\n     */\n    hasStroke: function() {\n      return this.stroke && this.stroke !== 'transparent' && this.strokeWidth !== 0;\n    },\n\n    /**\n     * return true if the object will draw a fill\n     * Does not consider text styles. This is just a shortcut used at rendering time\n     * We want it to be an aproximation and be fast.\n     * wrote to avoid extra caching, it has to return true when fill happens,\n     * can guess when it will not happen at 100% chance, does not matter if it misses\n     * some use case where the fill is invisible.\n     * @since 3.0.0\n     * @returns Boolean\n     */\n    hasFill: function() {\n      return this.fill && this.fill !== 'transparent';\n    },\n\n    /**\n     * When set to `true`, force the object to have its own cache, even if it is inside a group\n     * it may be needed when your object behave in a particular way on the cache and always needs\n     * its own isolated canvas to render correctly.\n     * Created to be overridden\n     * since 1.7.12\n     * @returns Boolean\n     */\n    needsItsOwnCache: function() {\n      if (this.paintFirst === 'stroke' &&\n        this.hasFill() && this.hasStroke() && typeof this.shadow === 'object') {\n        return true;\n      }\n      if (this.clipPath) {\n        return true;\n      }\n      return false;\n    },\n\n    /**\n     * Decide if the object should cache or not. Create its own cache level\n     * objectCaching is a global flag, wins over everything\n     * needsItsOwnCache should be used when the object drawing method requires\n     * a cache step. None of the fabric classes requires it.\n     * Generally you do not cache objects in groups because the group outside is cached.\n     * Read as: cache if is needed, or if the feature is enabled but we are not already caching.\n     * @return {Boolean}\n     */\n    shouldCache: function() {\n      this.ownCaching = this.needsItsOwnCache() || (\n        this.objectCaching &&\n        (!this.group || !this.group.isOnACache())\n      );\n      return this.ownCaching;\n    },\n\n    /**\n     * Check if this object or a child object will cast a shadow\n     * used by Group.shouldCache to know if child has a shadow recursively\n     * @return {Boolean}\n     */\n    willDrawShadow: function() {\n      return !!this.shadow && (this.shadow.offsetX !== 0 || this.shadow.offsetY !== 0);\n    },\n\n    /**\n     * Execute the drawing operation for an object clipPath\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    drawClipPathOnCache: function(ctx) {\n      var path = this.clipPath;\n      ctx.save();\n      // DEBUG: uncomment this line, comment the following\n      // ctx.globalAlpha = 0.4\n      if (path.inverted) {\n        ctx.globalCompositeOperation = 'destination-out';\n      }\n      else {\n        ctx.globalCompositeOperation = 'destination-in';\n      }\n      //ctx.scale(1 / 2, 1 / 2);\n      if (path.absolutePositioned) {\n        var m = fabric.util.invertTransform(this.calcTransformMatrix());\n        ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\n      }\n      path.transform(ctx);\n      ctx.scale(1 / path.zoomX, 1 / path.zoomY);\n      ctx.drawImage(path._cacheCanvas, -path.cacheTranslationX, -path.cacheTranslationY);\n      ctx.restore();\n    },\n\n    /**\n     * Execute the drawing operation for an object on a specified context\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    drawObject: function(ctx, forClipping) {\n      var originalFill = this.fill, originalStroke = this.stroke;\n      if (forClipping) {\n        this.fill = 'black';\n        this.stroke = '';\n        this._setClippingProperties(ctx);\n      }\n      else {\n        this._renderBackground(ctx);\n        this._setStrokeStyles(ctx, this);\n        this._setFillStyles(ctx, this);\n      }\n      this._render(ctx);\n      this._drawClipPath(ctx);\n      this.fill = originalFill;\n      this.stroke = originalStroke;\n    },\n\n    _drawClipPath: function(ctx) {\n      var path = this.clipPath;\n      if (!path) { return; }\n      // needed to setup a couple of variables\n      // path canvas gets overridden with this one.\n      // TODO find a better solution?\n      path.canvas = this.canvas;\n      path.shouldCache();\n      path._transformDone = true;\n      path.renderCache({ forClipping: true });\n      this.drawClipPathOnCache(ctx);\n    },\n\n    /**\n     * Paint the cached copy of the object on the target context.\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    drawCacheOnCanvas: function(ctx) {\n      ctx.scale(1 / this.zoomX, 1 / this.zoomY);\n      ctx.drawImage(this._cacheCanvas, -this.cacheTranslationX, -this.cacheTranslationY);\n    },\n\n    /**\n     * Check if cache is dirty\n     * @param {Boolean} skipCanvas skip canvas checks because this object is painted\n     * on parent canvas.\n     */\n    isCacheDirty: function(skipCanvas) {\n      if (this.isNotVisible()) {\n        return false;\n      }\n      if (this._cacheCanvas && !skipCanvas && this._updateCacheCanvas()) {\n        // in this case the context is already cleared.\n        return true;\n      }\n      else {\n        if (this.dirty ||\n          (this.clipPath && this.clipPath.absolutePositioned) ||\n          (this.statefullCache && this.hasStateChanged('cacheProperties'))\n        ) {\n          if (this._cacheCanvas && !skipCanvas) {\n            var width = this.cacheWidth / this.zoomX;\n            var height = this.cacheHeight / this.zoomY;\n            this._cacheContext.clearRect(-width / 2, -height / 2, width, height);\n          }\n          return true;\n        }\n      }\n      return false;\n    },\n\n    /**\n     * Draws a background for the object big as its untransformed dimensions\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderBackground: function(ctx) {\n      if (!this.backgroundColor) {\n        return;\n      }\n      var dim = this._getNonTransformedDimensions();\n      ctx.fillStyle = this.backgroundColor;\n\n      ctx.fillRect(\n        -dim.x / 2,\n        -dim.y / 2,\n        dim.x,\n        dim.y\n      );\n      // if there is background color no other shadows\n      // should be casted\n      this._removeShadow(ctx);\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _setOpacity: function(ctx) {\n      if (this.group && !this.group._transformDone) {\n        ctx.globalAlpha = this.getObjectOpacity();\n      }\n      else {\n        ctx.globalAlpha *= this.opacity;\n      }\n    },\n\n    _setStrokeStyles: function(ctx, decl) {\n      if (decl.stroke) {\n        ctx.lineWidth = decl.strokeWidth;\n        ctx.lineCap = decl.strokeLineCap;\n        ctx.lineDashOffset = decl.strokeDashOffset;\n        ctx.lineJoin = decl.strokeLineJoin;\n        ctx.miterLimit = decl.strokeMiterLimit;\n        ctx.strokeStyle = decl.stroke.toLive\n          ? decl.stroke.toLive(ctx, this)\n          : decl.stroke;\n      }\n    },\n\n    _setFillStyles: function(ctx, decl) {\n      if (decl.fill) {\n        ctx.fillStyle = decl.fill.toLive\n          ? decl.fill.toLive(ctx, this)\n          : decl.fill;\n      }\n    },\n\n    _setClippingProperties: function(ctx) {\n      ctx.globalAlpha = 1;\n      ctx.strokeStyle = 'transparent';\n      ctx.fillStyle = '#000000';\n    },\n\n    /**\n     * @private\n     * Sets line dash\n     * @param {CanvasRenderingContext2D} ctx Context to set the dash line on\n     * @param {Array} dashArray array representing dashes\n     * @param {Function} alternative function to call if browser does not support lineDash\n     */\n    _setLineDash: function(ctx, dashArray, alternative) {\n      if (!dashArray || dashArray.length === 0) {\n        return;\n      }\n      // Spec requires the concatenation of two copies the dash list when the number of elements is odd\n      if (1 & dashArray.length) {\n        dashArray.push.apply(dashArray, dashArray);\n      }\n      if (supportsLineDash) {\n        ctx.setLineDash(dashArray);\n      }\n      else {\n        alternative && alternative(ctx);\n      }\n    },\n\n    /**\n     * Renders controls and borders for the object\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Object} [styleOverride] properties to override the object style\n     */\n    _renderControls: function(ctx, styleOverride) {\n      var vpt = this.getViewportTransform(),\n          matrix = this.calcTransformMatrix(),\n          options, drawBorders, drawControls;\n      styleOverride = styleOverride || { };\n      drawBorders = typeof styleOverride.hasBorders !== 'undefined' ? styleOverride.hasBorders : this.hasBorders;\n      drawControls = typeof styleOverride.hasControls !== 'undefined' ? styleOverride.hasControls : this.hasControls;\n      matrix = fabric.util.multiplyTransformMatrices(vpt, matrix);\n      options = fabric.util.qrDecompose(matrix);\n      ctx.save();\n      ctx.translate(options.translateX, options.translateY);\n      ctx.lineWidth = 1 * this.borderScaleFactor;\n      if (!this.group) {\n        ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n      }\n      if (styleOverride.forActiveSelection) {\n        ctx.rotate(degreesToRadians(options.angle));\n        drawBorders && this.drawBordersInGroup(ctx, options, styleOverride);\n      }\n      else {\n        ctx.rotate(degreesToRadians(this.angle));\n        drawBorders && this.drawBorders(ctx, styleOverride);\n      }\n      drawControls && this.drawControls(ctx, styleOverride);\n      ctx.restore();\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _setShadow: function(ctx) {\n      if (!this.shadow) {\n        return;\n      }\n\n      var shadow = this.shadow, canvas = this.canvas, scaling,\n          multX = (canvas && canvas.viewportTransform[0]) || 1,\n          multY = (canvas && canvas.viewportTransform[3]) || 1;\n      if (shadow.nonScaling) {\n        scaling = { scaleX: 1, scaleY: 1 };\n      }\n      else {\n        scaling = this.getObjectScaling();\n      }\n      if (canvas && canvas._isRetinaScaling()) {\n        multX *= fabric.devicePixelRatio;\n        multY *= fabric.devicePixelRatio;\n      }\n      ctx.shadowColor = shadow.color;\n      ctx.shadowBlur = shadow.blur * fabric.browserShadowBlurConstant *\n        (multX + multY) * (scaling.scaleX + scaling.scaleY) / 4;\n      ctx.shadowOffsetX = shadow.offsetX * multX * scaling.scaleX;\n      ctx.shadowOffsetY = shadow.offsetY * multY * scaling.scaleY;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _removeShadow: function(ctx) {\n      if (!this.shadow) {\n        return;\n      }\n\n      ctx.shadowColor = '';\n      ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Object} filler fabric.Pattern or fabric.Gradient\n     * @return {Object} offset.offsetX offset for text rendering\n     * @return {Object} offset.offsetY offset for text rendering\n     */\n    _applyPatternGradientTransform: function(ctx, filler) {\n      if (!filler || !filler.toLive) {\n        return { offsetX: 0, offsetY: 0 };\n      }\n      var t = filler.gradientTransform || filler.patternTransform;\n      var offsetX = -this.width / 2 + filler.offsetX || 0,\n          offsetY = -this.height / 2 + filler.offsetY || 0;\n\n      if (filler.gradientUnits === 'percentage') {\n        ctx.transform(this.width, 0, 0, this.height, offsetX, offsetY);\n      }\n      else {\n        ctx.transform(1, 0, 0, 1, offsetX, offsetY);\n      }\n      if (t) {\n        ctx.transform(t[0], t[1], t[2], t[3], t[4], t[5]);\n      }\n      return { offsetX: offsetX, offsetY: offsetY };\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderPaintInOrder: function(ctx) {\n      if (this.paintFirst === 'stroke') {\n        this._renderStroke(ctx);\n        this._renderFill(ctx);\n      }\n      else {\n        this._renderFill(ctx);\n        this._renderStroke(ctx);\n      }\n    },\n\n    /**\n     * @private\n     * function that actually render something on the context.\n     * empty here to allow Obects to work on tests to benchmark fabric functionalites\n     * not related to rendering\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function(/* ctx */) {\n\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderFill: function(ctx) {\n      if (!this.fill) {\n        return;\n      }\n\n      ctx.save();\n      this._applyPatternGradientTransform(ctx, this.fill);\n      if (this.fillRule === 'evenodd') {\n        ctx.fill('evenodd');\n      }\n      else {\n        ctx.fill();\n      }\n      ctx.restore();\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderStroke: function(ctx) {\n      if (!this.stroke || this.strokeWidth === 0) {\n        return;\n      }\n\n      if (this.shadow && !this.shadow.affectStroke) {\n        this._removeShadow(ctx);\n      }\n\n      ctx.save();\n      if (this.strokeUniform && this.group) {\n        var scaling = this.getObjectScaling();\n        ctx.scale(1 / scaling.scaleX, 1 / scaling.scaleY);\n      }\n      else if (this.strokeUniform) {\n        ctx.scale(1 / this.scaleX, 1 / this.scaleY);\n      }\n      this._setLineDash(ctx, this.strokeDashArray, this._renderDashedStroke);\n      if (this.stroke.toLive && this.stroke.gradientUnits === 'percentage') {\n        // need to transform gradient in a pattern.\n        // this is a slow process. If you are hitting this codepath, and the object\n        // is not using caching, you should consider switching it on.\n        // we need a canvas as big as the current object caching canvas.\n        this._applyPatternForTransformedGradient(ctx, this.stroke);\n      }\n      else {\n        this._applyPatternGradientTransform(ctx, this.stroke);\n      }\n      ctx.stroke();\n      ctx.restore();\n    },\n\n    /**\n     * This function try to patch the missing gradientTransform on canvas gradients.\n     * transforming a context to transform the gradient, is going to transform the stroke too.\n     * we want to transform the gradient but not the stroke operation, so we create\n     * a transformed gradient on a pattern and then we use the pattern instead of the gradient.\n     * this method has drwabacks: is slow, is in low resolution, needs a patch for when the size\n     * is limited.\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {fabric.Gradient} filler a fabric gradient instance\n     */\n    _applyPatternForTransformedGradient: function(ctx, filler) {\n      var dims = this._limitCacheSize(this._getCacheCanvasDimensions()),\n          pCanvas = fabric.util.createCanvasElement(), pCtx, retinaScaling = this.canvas.getRetinaScaling(),\n          width = dims.x / this.scaleX / retinaScaling, height = dims.y / this.scaleY / retinaScaling;\n      pCanvas.width = width;\n      pCanvas.height = height;\n      pCtx = pCanvas.getContext('2d');\n      pCtx.beginPath(); pCtx.moveTo(0, 0); pCtx.lineTo(width, 0); pCtx.lineTo(width, height);\n      pCtx.lineTo(0, height); pCtx.closePath();\n      pCtx.translate(width / 2, height / 2);\n      pCtx.scale(\n        dims.zoomX / this.scaleX / retinaScaling,\n        dims.zoomY / this.scaleY / retinaScaling\n      );\n      this._applyPatternGradientTransform(pCtx, filler);\n      pCtx.fillStyle = filler.toLive(ctx);\n      pCtx.fill();\n      ctx.translate(-this.width / 2 - this.strokeWidth / 2, -this.height / 2 - this.strokeWidth / 2);\n      ctx.scale(\n        retinaScaling * this.scaleX / dims.zoomX,\n        retinaScaling * this.scaleY / dims.zoomY\n      );\n      ctx.strokeStyle = pCtx.createPattern(pCanvas, 'no-repeat');\n    },\n\n    /**\n     * This function is an helper for svg import. it returns the center of the object in the svg\n     * untransformed coordinates\n     * @private\n     * @return {Object} center point from element coordinates\n     */\n    _findCenterFromElement: function() {\n      return { x: this.left + this.width / 2, y: this.top + this.height / 2 };\n    },\n\n    /**\n     * This function is an helper for svg import. it decompose the transformMatrix\n     * and assign properties to object.\n     * untransformed coordinates\n     * @private\n     * @chainable\n     */\n    _assignTransformMatrixProps: function() {\n      if (this.transformMatrix) {\n        var options = fabric.util.qrDecompose(this.transformMatrix);\n        this.flipX = false;\n        this.flipY = false;\n        this.set('scaleX', options.scaleX);\n        this.set('scaleY', options.scaleY);\n        this.angle = options.angle;\n        this.skewX = options.skewX;\n        this.skewY = 0;\n      }\n    },\n\n    /**\n     * This function is an helper for svg import. it removes the transform matrix\n     * and set to object properties that fabricjs can handle\n     * @private\n     * @param {Object} preserveAspectRatioOptions\n     * @return {thisArg}\n     */\n    _removeTransformMatrix: function(preserveAspectRatioOptions) {\n      var center = this._findCenterFromElement();\n      if (this.transformMatrix) {\n        this._assignTransformMatrixProps();\n        center = fabric.util.transformPoint(center, this.transformMatrix);\n      }\n      this.transformMatrix = null;\n      if (preserveAspectRatioOptions) {\n        this.scaleX *= preserveAspectRatioOptions.scaleX;\n        this.scaleY *= preserveAspectRatioOptions.scaleY;\n        this.cropX = preserveAspectRatioOptions.cropX;\n        this.cropY = preserveAspectRatioOptions.cropY;\n        center.x += preserveAspectRatioOptions.offsetLeft;\n        center.y += preserveAspectRatioOptions.offsetTop;\n        this.width = preserveAspectRatioOptions.width;\n        this.height = preserveAspectRatioOptions.height;\n      }\n      this.setPositionByOrigin(center, 'center', 'center');\n    },\n\n    /**\n     * Clones an instance, using a callback method will work for every object.\n     * @param {Function} callback Callback is invoked with a clone as a first argument\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     */\n    clone: function(callback, propertiesToInclude) {\n      var objectForm = this.toObject(propertiesToInclude);\n      if (this.constructor.fromObject) {\n        this.constructor.fromObject(objectForm, callback);\n      }\n      else {\n        fabric.Object._fromObject('Object', objectForm, callback);\n      }\n    },\n\n    /**\n     * Creates an instance of fabric.Image out of an object\n     * could make use of both toDataUrl or toCanvasElement.\n     * @param {Function} callback callback, invoked with an instance as a first argument\n     * @param {Object} [options] for clone as image, passed to toDataURL\n     * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\n     * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\n     * @param {Number} [options.multiplier=1] Multiplier to scale by\n     * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n     * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n     * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n     * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n     * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\n     * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\n     * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\n     * @return {fabric.Object} thisArg\n     */\n    cloneAsImage: function(callback, options) {\n      var canvasEl = this.toCanvasElement(options);\n      if (callback) {\n        callback(new fabric.Image(canvasEl));\n      }\n      return this;\n    },\n\n    /**\n     * Converts an object into a HTMLCanvas element\n     * @param {Object} options Options object\n     * @param {Number} [options.multiplier=1] Multiplier to scale by\n     * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n     * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n     * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n     * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n     * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\n     * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\n     * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\n     * @return {HTMLCanvasElement} Returns DOM element <canvas> with the fabric.Object\n     */\n    toCanvasElement: function(options) {\n      options || (options = { });\n\n      var utils = fabric.util, origParams = utils.saveObjectTransform(this),\n          originalGroup = this.group,\n          originalShadow = this.shadow, abs = Math.abs,\n          multiplier = (options.multiplier || 1) * (options.enableRetinaScaling ? fabric.devicePixelRatio : 1);\n      delete this.group;\n      if (options.withoutTransform) {\n        utils.resetObjectTransform(this);\n      }\n      if (options.withoutShadow) {\n        this.shadow = null;\n      }\n\n      var el = fabric.util.createCanvasElement(),\n          // skip canvas zoom and calculate with setCoords now.\n          boundingRect = this.getBoundingRect(true, true),\n          shadow = this.shadow, scaling,\n          shadowOffset = { x: 0, y: 0 }, shadowBlur,\n          width, height;\n\n      if (shadow) {\n        shadowBlur = shadow.blur;\n        if (shadow.nonScaling) {\n          scaling = { scaleX: 1, scaleY: 1 };\n        }\n        else {\n          scaling = this.getObjectScaling();\n        }\n        // consider non scaling shadow.\n        shadowOffset.x = 2 * Math.round(abs(shadow.offsetX) + shadowBlur) * (abs(scaling.scaleX));\n        shadowOffset.y = 2 * Math.round(abs(shadow.offsetY) + shadowBlur) * (abs(scaling.scaleY));\n      }\n      width = boundingRect.width + shadowOffset.x;\n      height = boundingRect.height + shadowOffset.y;\n      // if the current width/height is not an integer\n      // we need to make it so.\n      el.width = Math.ceil(width);\n      el.height = Math.ceil(height);\n      var canvas = new fabric.StaticCanvas(el, {\n        enableRetinaScaling: false,\n        renderOnAddRemove: false,\n        skipOffscreen: false,\n      });\n      if (options.format === 'jpeg') {\n        canvas.backgroundColor = '#fff';\n      }\n      this.setPositionByOrigin(new fabric.Point(canvas.width / 2, canvas.height / 2), 'center', 'center');\n\n      var originalCanvas = this.canvas;\n      canvas.add(this);\n      var canvasEl = canvas.toCanvasElement(multiplier || 1, options);\n      this.shadow = originalShadow;\n      this.set('canvas', originalCanvas);\n      if (originalGroup) {\n        this.group = originalGroup;\n      }\n      this.set(origParams).setCoords();\n      // canvas.dispose will call image.dispose that will nullify the elements\n      // since this canvas is a simple element for the process, we remove references\n      // to objects in this way in order to avoid object trashing.\n      canvas._objects = [];\n      canvas.dispose();\n      canvas = null;\n\n      return canvasEl;\n    },\n\n    /**\n     * Converts an object into a data-url-like string\n     * @param {Object} options Options object\n     * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\n     * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\n     * @param {Number} [options.multiplier=1] Multiplier to scale by\n     * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n     * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n     * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n     * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n     * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\n     * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\n     * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\n     * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format\n     */\n    toDataURL: function(options) {\n      options || (options = { });\n      return fabric.util.toDataURL(this.toCanvasElement(options), options.format || 'png', options.quality || 1);\n    },\n\n    /**\n     * Returns true if specified type is identical to the type of an instance\n     * @param {String} type Type to check against\n     * @return {Boolean}\n     */\n    isType: function(type) {\n      return this.type === type;\n    },\n\n    /**\n     * Returns complexity of an instance\n     * @return {Number} complexity of this instance (is 1 unless subclassed)\n     */\n    complexity: function() {\n      return 1;\n    },\n\n    /**\n     * Returns a JSON representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} JSON\n     */\n    toJSON: function(propertiesToInclude) {\n      // delegate, not alias\n      return this.toObject(propertiesToInclude);\n    },\n\n    /**\n     * Sets \"angle\" of an instance with centered rotation\n     * @param {Number} angle Angle value (in degrees)\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    rotate: function(angle) {\n      var shouldCenterOrigin = (this.originX !== 'center' || this.originY !== 'center') && this.centeredRotation;\n\n      if (shouldCenterOrigin) {\n        this._setOriginToCenter();\n      }\n\n      this.set('angle', angle);\n\n      if (shouldCenterOrigin) {\n        this._resetOrigin();\n      }\n\n      return this;\n    },\n\n    /**\n     * Centers object horizontally on canvas to which it was added last.\n     * You might need to call `setCoords` on an object after centering, to update controls area.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    centerH: function () {\n      this.canvas && this.canvas.centerObjectH(this);\n      return this;\n    },\n\n    /**\n     * Centers object horizontally on current viewport of canvas to which it was added last.\n     * You might need to call `setCoords` on an object after centering, to update controls area.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    viewportCenterH: function () {\n      this.canvas && this.canvas.viewportCenterObjectH(this);\n      return this;\n    },\n\n    /**\n     * Centers object vertically on canvas to which it was added last.\n     * You might need to call `setCoords` on an object after centering, to update controls area.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    centerV: function () {\n      this.canvas && this.canvas.centerObjectV(this);\n      return this;\n    },\n\n    /**\n     * Centers object vertically on current viewport of canvas to which it was added last.\n     * You might need to call `setCoords` on an object after centering, to update controls area.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    viewportCenterV: function () {\n      this.canvas && this.canvas.viewportCenterObjectV(this);\n      return this;\n    },\n\n    /**\n     * Centers object vertically and horizontally on canvas to which is was added last\n     * You might need to call `setCoords` on an object after centering, to update controls area.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    center: function () {\n      this.canvas && this.canvas.centerObject(this);\n      return this;\n    },\n\n    /**\n     * Centers object on current viewport of canvas to which it was added last.\n     * You might need to call `setCoords` on an object after centering, to update controls area.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    viewportCenter: function () {\n      this.canvas && this.canvas.viewportCenterObject(this);\n      return this;\n    },\n\n    /**\n     * Returns coordinates of a pointer relative to an object\n     * @param {Event} e Event to operate upon\n     * @param {Object} [pointer] Pointer to operate upon (instead of event)\n     * @return {Object} Coordinates of a pointer (x, y)\n     */\n    getLocalPointer: function(e, pointer) {\n      pointer = pointer || this.canvas.getPointer(e);\n      var pClicked = new fabric.Point(pointer.x, pointer.y),\n          objectLeftTop = this._getLeftTopCoords();\n      if (this.angle) {\n        pClicked = fabric.util.rotatePoint(\n          pClicked, objectLeftTop, degreesToRadians(-this.angle));\n      }\n      return {\n        x: pClicked.x - objectLeftTop.x,\n        y: pClicked.y - objectLeftTop.y\n      };\n    },\n\n    /**\n     * Sets canvas globalCompositeOperation for specific object\n     * custom composition operation for the particular object can be specified using globalCompositeOperation property\n     * @param {CanvasRenderingContext2D} ctx Rendering canvas context\n     */\n    _setupCompositeOperation: function (ctx) {\n      if (this.globalCompositeOperation) {\n        ctx.globalCompositeOperation = this.globalCompositeOperation;\n      }\n    }\n  });\n\n  fabric.util.createAccessors && fabric.util.createAccessors(fabric.Object);\n\n  extend(fabric.Object.prototype, fabric.Observable);\n\n  /**\n   * Defines the number of fraction digits to use when serializing object values.\n   * You can use it to increase/decrease precision of such values like left, top, scaleX, scaleY, etc.\n   * @static\n   * @memberOf fabric.Object\n   * @constant\n   * @type Number\n   */\n  fabric.Object.NUM_FRACTION_DIGITS = 2;\n\n  fabric.Object._fromObject = function(className, object, callback, extraParam) {\n    var klass = fabric[className];\n    object = clone(object, true);\n    fabric.util.enlivenPatterns([object.fill, object.stroke], function(patterns) {\n      if (typeof patterns[0] !== 'undefined') {\n        object.fill = patterns[0];\n      }\n      if (typeof patterns[1] !== 'undefined') {\n        object.stroke = patterns[1];\n      }\n      fabric.util.enlivenObjects([object.clipPath], function(enlivedProps) {\n        object.clipPath = enlivedProps[0];\n        var instance = extraParam ? new klass(object[extraParam], object) : new klass(object);\n        callback && callback(instance);\n      });\n    });\n  };\n\n  /**\n   * Unique id used internally when creating SVG elements\n   * @static\n   * @memberOf fabric.Object\n   * @type Number\n   */\n  fabric.Object.__uid = 0;\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n  var degreesToRadians = fabric.util.degreesToRadians,\n      originXOffset = {\n        left: -0.5,\n        center: 0,\n        right: 0.5\n      },\n      originYOffset = {\n        top: -0.5,\n        center: 0,\n        bottom: 0.5\n      };\n\n  fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n    /**\n     * Translates the coordinates from a set of origin to another (based on the object's dimensions)\n     * @param {fabric.Point} point The point which corresponds to the originX and originY params\n     * @param {String} fromOriginX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} fromOriginY Vertical origin: 'top', 'center' or 'bottom'\n     * @param {String} toOriginX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} toOriginY Vertical origin: 'top', 'center' or 'bottom'\n     * @return {fabric.Point}\n     */\n    translateToGivenOrigin: function(point, fromOriginX, fromOriginY, toOriginX, toOriginY) {\n      var x = point.x,\n          y = point.y,\n          offsetX, offsetY, dim;\n\n      if (typeof fromOriginX === 'string') {\n        fromOriginX = originXOffset[fromOriginX];\n      }\n      else {\n        fromOriginX -= 0.5;\n      }\n\n      if (typeof toOriginX === 'string') {\n        toOriginX = originXOffset[toOriginX];\n      }\n      else {\n        toOriginX -= 0.5;\n      }\n\n      offsetX = toOriginX - fromOriginX;\n\n      if (typeof fromOriginY === 'string') {\n        fromOriginY = originYOffset[fromOriginY];\n      }\n      else {\n        fromOriginY -= 0.5;\n      }\n\n      if (typeof toOriginY === 'string') {\n        toOriginY = originYOffset[toOriginY];\n      }\n      else {\n        toOriginY -= 0.5;\n      }\n\n      offsetY = toOriginY - fromOriginY;\n\n      if (offsetX || offsetY) {\n        dim = this._getTransformedDimensions();\n        x = point.x + offsetX * dim.x;\n        y = point.y + offsetY * dim.y;\n      }\n\n      return new fabric.Point(x, y);\n    },\n\n    /**\n     * Translates the coordinates from origin to center coordinates (based on the object's dimensions)\n     * @param {fabric.Point} point The point which corresponds to the originX and originY params\n     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n     * @return {fabric.Point}\n     */\n    translateToCenterPoint: function(point, originX, originY) {\n      var p = this.translateToGivenOrigin(point, originX, originY, 'center', 'center');\n      if (this.angle) {\n        return fabric.util.rotatePoint(p, point, degreesToRadians(this.angle));\n      }\n      return p;\n    },\n\n    /**\n     * Translates the coordinates from center to origin coordinates (based on the object's dimensions)\n     * @param {fabric.Point} center The point which corresponds to center of the object\n     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n     * @return {fabric.Point}\n     */\n    translateToOriginPoint: function(center, originX, originY) {\n      var p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY);\n      if (this.angle) {\n        return fabric.util.rotatePoint(p, center, degreesToRadians(this.angle));\n      }\n      return p;\n    },\n\n    /**\n     * Returns the real center coordinates of the object\n     * @return {fabric.Point}\n     */\n    getCenterPoint: function() {\n      var leftTop = new fabric.Point(this.left, this.top);\n      return this.translateToCenterPoint(leftTop, this.originX, this.originY);\n    },\n\n    /**\n     * Returns the coordinates of the object based on center coordinates\n     * @param {fabric.Point} point The point which corresponds to the originX and originY params\n     * @return {fabric.Point}\n     */\n    // getOriginPoint: function(center) {\n    //   return this.translateToOriginPoint(center, this.originX, this.originY);\n    // },\n\n    /**\n     * Returns the coordinates of the object as if it has a different origin\n     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n     * @return {fabric.Point}\n     */\n    getPointByOrigin: function(originX, originY) {\n      var center = this.getCenterPoint();\n      return this.translateToOriginPoint(center, originX, originY);\n    },\n\n    /**\n     * Returns the point in local coordinates\n     * @param {fabric.Point} point The point relative to the global coordinate system\n     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n     * @return {fabric.Point}\n     */\n    toLocalPoint: function(point, originX, originY) {\n      var center = this.getCenterPoint(),\n          p, p2;\n\n      if (typeof originX !== 'undefined' && typeof originY !== 'undefined' ) {\n        p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY);\n      }\n      else {\n        p = new fabric.Point(this.left, this.top);\n      }\n\n      p2 = new fabric.Point(point.x, point.y);\n      if (this.angle) {\n        p2 = fabric.util.rotatePoint(p2, center, -degreesToRadians(this.angle));\n      }\n      return p2.subtractEquals(p);\n    },\n\n    /**\n     * Returns the point in global coordinates\n     * @param {fabric.Point} The point relative to the local coordinate system\n     * @return {fabric.Point}\n     */\n    // toGlobalPoint: function(point) {\n    //   return fabric.util.rotatePoint(point, this.getCenterPoint(), degreesToRadians(this.angle)).addEquals(new fabric.Point(this.left, this.top));\n    // },\n\n    /**\n     * Sets the position of the object taking into consideration the object's origin\n     * @param {fabric.Point} pos The new position of the object\n     * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n     * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n     * @return {void}\n     */\n    setPositionByOrigin: function(pos, originX, originY) {\n      var center = this.translateToCenterPoint(pos, originX, originY),\n          position = this.translateToOriginPoint(center, this.originX, this.originY);\n      this.set('left', position.x);\n      this.set('top', position.y);\n    },\n\n    /**\n     * @param {String} to One of 'left', 'center', 'right'\n     */\n    adjustPosition: function(to) {\n      var angle = degreesToRadians(this.angle),\n          hypotFull = this.getScaledWidth(),\n          xFull = fabric.util.cos(angle) * hypotFull,\n          yFull = fabric.util.sin(angle) * hypotFull,\n          offsetFrom, offsetTo;\n\n      //TODO: this function does not consider mixed situation like top, center.\n      if (typeof this.originX === 'string') {\n        offsetFrom = originXOffset[this.originX];\n      }\n      else {\n        offsetFrom = this.originX - 0.5;\n      }\n      if (typeof to === 'string') {\n        offsetTo = originXOffset[to];\n      }\n      else {\n        offsetTo = to - 0.5;\n      }\n      this.left += xFull * (offsetTo - offsetFrom);\n      this.top += yFull * (offsetTo - offsetFrom);\n      this.setCoords();\n      this.originX = to;\n    },\n\n    /**\n     * Sets the origin/position of the object to it's center point\n     * @private\n     * @return {void}\n     */\n    _setOriginToCenter: function() {\n      this._originalOriginX = this.originX;\n      this._originalOriginY = this.originY;\n\n      var center = this.getCenterPoint();\n\n      this.originX = 'center';\n      this.originY = 'center';\n\n      this.left = center.x;\n      this.top = center.y;\n    },\n\n    /**\n     * Resets the origin/position of the object to it's original origin\n     * @private\n     * @return {void}\n     */\n    _resetOrigin: function() {\n      var originPoint = this.translateToOriginPoint(\n        this.getCenterPoint(),\n        this._originalOriginX,\n        this._originalOriginY);\n\n      this.originX = this._originalOriginX;\n      this.originY = this._originalOriginY;\n\n      this.left = originPoint.x;\n      this.top = originPoint.y;\n\n      this._originalOriginX = null;\n      this._originalOriginY = null;\n    },\n\n    /**\n     * @private\n     */\n    _getLeftTopCoords: function() {\n      return this.translateToOriginPoint(this.getCenterPoint(), 'left', 'top');\n    },\n  });\n\n})();\n\n\n(function() {\n\n  function arrayFromCoords(coords) {\n    return [\n      new fabric.Point(coords.tl.x, coords.tl.y),\n      new fabric.Point(coords.tr.x, coords.tr.y),\n      new fabric.Point(coords.br.x, coords.br.y),\n      new fabric.Point(coords.bl.x, coords.bl.y)\n    ];\n  }\n\n  var util = fabric.util,\n      degreesToRadians = util.degreesToRadians,\n      multiplyMatrices = util.multiplyTransformMatrices,\n      transformPoint = util.transformPoint;\n\n  util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n    /**\n     * Describe object's corner position in canvas element coordinates.\n     * properties are depending on control keys and padding the main controls.\n     * each property is an object with x, y and corner.\n     * The `corner` property contains in a similar manner the 4 points of the\n     * interactive area of the corner.\n     * The coordinates depends from the controls positionHandler and are used\n     * to draw and locate controls\n     * @memberOf fabric.Object.prototype\n     */\n    oCoords: null,\n\n    /**\n     * Describe object's corner position in canvas object absolute coordinates\n     * properties are tl,tr,bl,br and describe the four main corner.\n     * each property is an object with x, y, instance of Fabric.Point.\n     * The coordinates depends from this properties: width, height, scaleX, scaleY\n     * skewX, skewY, angle, strokeWidth, top, left.\n     * Those coordinates are useful to understand where an object is. They get updated\n     * with oCoords but they do not need to be updated when zoom or panning change.\n     * The coordinates get updated with @method setCoords.\n     * You can calculate them without updating with @method calcACoords();\n     * @memberOf fabric.Object.prototype\n     */\n    aCoords: null,\n\n    /**\n     * Describe object's corner position in canvas element coordinates.\n     * includes padding. Used of object detection.\n     * set and refreshed with setCoords and calcCoords.\n     * @memberOf fabric.Object.prototype\n     */\n    lineCoords: null,\n\n    /**\n     * storage for object transform matrix\n     */\n    ownMatrixCache: null,\n\n    /**\n     * storage for object full transform matrix\n     */\n    matrixCache: null,\n\n    /**\n     * custom controls interface\n     * controls are added by default_controls.js\n     */\n    controls: { },\n\n    /**\n     * return correct set of coordinates for intersection\n     * this will return either aCoords or lineCoords.\n     * @param {Boolean} absolute will return aCoords if true or lineCoords\n     * @return {Object} {tl, tr, br, bl} points\n     */\n    _getCoords: function(absolute, calculate) {\n      if (calculate) {\n        return (absolute ? this.calcACoords() : this.calcLineCoords());\n      }\n      if (!this.aCoords || !this.lineCoords) {\n        this.setCoords(true);\n      }\n      return (absolute ? this.aCoords : this.lineCoords);\n    },\n\n    /**\n     * return correct set of coordinates for intersection\n     * this will return either aCoords or lineCoords.\n     * The coords are returned in an array.\n     * @return {Array} [tl, tr, br, bl] of points\n     */\n    getCoords: function(absolute, calculate) {\n      return arrayFromCoords(this._getCoords(absolute, calculate));\n    },\n\n    /**\n     * Checks if object intersects with an area formed by 2 points\n     * @param {Object} pointTL top-left point of area\n     * @param {Object} pointBR bottom-right point of area\n     * @param {Boolean} [absolute] use coordinates without viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if object intersects with an area formed by 2 points\n     */\n    intersectsWithRect: function(pointTL, pointBR, absolute, calculate) {\n      var coords = this.getCoords(absolute, calculate),\n          intersection = fabric.Intersection.intersectPolygonRectangle(\n            coords,\n            pointTL,\n            pointBR\n          );\n      return intersection.status === 'Intersection';\n    },\n\n    /**\n     * Checks if object intersects with another object\n     * @param {Object} other Object to test\n     * @param {Boolean} [absolute] use coordinates without viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if object intersects with another object\n     */\n    intersectsWithObject: function(other, absolute, calculate) {\n      var intersection = fabric.Intersection.intersectPolygonPolygon(\n        this.getCoords(absolute, calculate),\n        other.getCoords(absolute, calculate)\n      );\n\n      return intersection.status === 'Intersection'\n        || other.isContainedWithinObject(this, absolute, calculate)\n        || this.isContainedWithinObject(other, absolute, calculate);\n    },\n\n    /**\n     * Checks if object is fully contained within area of another object\n     * @param {Object} other Object to test\n     * @param {Boolean} [absolute] use coordinates without viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if object is fully contained within area of another object\n     */\n    isContainedWithinObject: function(other, absolute, calculate) {\n      var points = this.getCoords(absolute, calculate),\n          otherCoords = absolute ? other.aCoords : other.lineCoords,\n          i = 0, lines = other._getImageLines(otherCoords);\n      for (; i < 4; i++) {\n        if (!other.containsPoint(points[i], lines)) {\n          return false;\n        }\n      }\n      return true;\n    },\n\n    /**\n     * Checks if object is fully contained within area formed by 2 points\n     * @param {Object} pointTL top-left point of area\n     * @param {Object} pointBR bottom-right point of area\n     * @param {Boolean} [absolute] use coordinates without viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if object is fully contained within area formed by 2 points\n     */\n    isContainedWithinRect: function(pointTL, pointBR, absolute, calculate) {\n      var boundingRect = this.getBoundingRect(absolute, calculate);\n\n      return (\n        boundingRect.left >= pointTL.x &&\n        boundingRect.left + boundingRect.width <= pointBR.x &&\n        boundingRect.top >= pointTL.y &&\n        boundingRect.top + boundingRect.height <= pointBR.y\n      );\n    },\n\n    /**\n     * Checks if point is inside the object\n     * @param {fabric.Point} point Point to check against\n     * @param {Object} [lines] object returned from @method _getImageLines\n     * @param {Boolean} [absolute] use coordinates without viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if point is inside the object\n     */\n    containsPoint: function(point, lines, absolute, calculate) {\n      var coords = this._getCoords(absolute, calculate),\n          lines = lines || this._getImageLines(coords),\n          xPoints = this._findCrossPoints(point, lines);\n      // if xPoints is odd then point is inside the object\n      return (xPoints !== 0 && xPoints % 2 === 1);\n    },\n\n    /**\n     * Checks if object is contained within the canvas with current viewportTransform\n     * the check is done stopping at first point that appears on screen\n     * @param {Boolean} [calculate] use coordinates of current position instead of .aCoords\n     * @return {Boolean} true if object is fully or partially contained within canvas\n     */\n    isOnScreen: function(calculate) {\n      if (!this.canvas) {\n        return false;\n      }\n      var pointTL = this.canvas.vptCoords.tl, pointBR = this.canvas.vptCoords.br;\n      var points = this.getCoords(true, calculate);\n      // if some point is on screen, the object is on screen.\n      if (points.some(function(point) {\n        return point.x <= pointBR.x && point.x >= pointTL.x &&\n        point.y <= pointBR.y && point.y >= pointTL.y;\n      })) {\n        return true;\n      }\n      // no points on screen, check intersection with absolute coordinates\n      if (this.intersectsWithRect(pointTL, pointBR, true, calculate)) {\n        return true;\n      }\n      return this._containsCenterOfCanvas(pointTL, pointBR, calculate);\n    },\n\n    /**\n     * Checks if the object contains the midpoint between canvas extremities\n     * Does not make sense outside the context of isOnScreen and isPartiallyOnScreen\n     * @private\n     * @param {Fabric.Point} pointTL Top Left point\n     * @param {Fabric.Point} pointBR Top Right point\n     * @param {Boolean} calculate use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if the object contains the point\n     */\n    _containsCenterOfCanvas: function(pointTL, pointBR, calculate) {\n      // worst case scenario the object is so big that contains the screen\n      var centerPoint = { x: (pointTL.x + pointBR.x) / 2, y: (pointTL.y + pointBR.y) / 2 };\n      if (this.containsPoint(centerPoint, null, true, calculate)) {\n        return true;\n      }\n      return false;\n    },\n\n    /**\n     * Checks if object is partially contained within the canvas with current viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n     * @return {Boolean} true if object is partially contained within canvas\n     */\n    isPartiallyOnScreen: function(calculate) {\n      if (!this.canvas) {\n        return false;\n      }\n      var pointTL = this.canvas.vptCoords.tl, pointBR = this.canvas.vptCoords.br;\n      if (this.intersectsWithRect(pointTL, pointBR, true, calculate)) {\n        return true;\n      }\n      var allPointsAreOutside = this.getCoords(true, calculate).every(function(point) {\n        return (point.x >= pointBR.x || point.x <= pointTL.x) &&\n        (point.y >= pointBR.y || point.y <= pointTL.y);\n      });\n      return allPointsAreOutside && this._containsCenterOfCanvas(pointTL, pointBR, calculate);\n    },\n\n    /**\n     * Method that returns an object with the object edges in it, given the coordinates of the corners\n     * @private\n     * @param {Object} oCoords Coordinates of the object corners\n     */\n    _getImageLines: function(oCoords) {\n\n      var lines = {\n        topline: {\n          o: oCoords.tl,\n          d: oCoords.tr\n        },\n        rightline: {\n          o: oCoords.tr,\n          d: oCoords.br\n        },\n        bottomline: {\n          o: oCoords.br,\n          d: oCoords.bl\n        },\n        leftline: {\n          o: oCoords.bl,\n          d: oCoords.tl\n        }\n      };\n\n      // // debugging\n      // if (this.canvas.contextTop) {\n      //   this.canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);\n      //   this.canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);\n      //\n      //   this.canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);\n      //   this.canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);\n      //\n      //   this.canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);\n      //   this.canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);\n      //\n      //   this.canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);\n      //   this.canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);\n      // }\n\n      return lines;\n    },\n\n    /**\n     * Helper method to determine how many cross points are between the 4 object edges\n     * and the horizontal line determined by a point on canvas\n     * @private\n     * @param {fabric.Point} point Point to check\n     * @param {Object} lines Coordinates of the object being evaluated\n     */\n    // remove yi, not used but left code here just in case.\n    _findCrossPoints: function(point, lines) {\n      var b1, b2, a1, a2, xi, // yi,\n          xcount = 0,\n          iLine;\n\n      for (var lineKey in lines) {\n        iLine = lines[lineKey];\n        // optimisation 1: line below point. no cross\n        if ((iLine.o.y < point.y) && (iLine.d.y < point.y)) {\n          continue;\n        }\n        // optimisation 2: line above point. no cross\n        if ((iLine.o.y >= point.y) && (iLine.d.y >= point.y)) {\n          continue;\n        }\n        // optimisation 3: vertical line case\n        if ((iLine.o.x === iLine.d.x) && (iLine.o.x >= point.x)) {\n          xi = iLine.o.x;\n          // yi = point.y;\n        }\n        // calculate the intersection point\n        else {\n          b1 = 0;\n          b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x);\n          a1 = point.y - b1 * point.x;\n          a2 = iLine.o.y - b2 * iLine.o.x;\n\n          xi = -(a1 - a2) / (b1 - b2);\n          // yi = a1 + b1 * xi;\n        }\n        // dont count xi < point.x cases\n        if (xi >= point.x) {\n          xcount += 1;\n        }\n        // optimisation 4: specific for square images\n        if (xcount === 2) {\n          break;\n        }\n      }\n      return xcount;\n    },\n\n    /**\n     * Returns coordinates of object's bounding rectangle (left, top, width, height)\n     * the box is intended as aligned to axis of canvas.\n     * @param {Boolean} [absolute] use coordinates without viewportTransform\n     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords / .aCoords\n     * @return {Object} Object with left, top, width, height properties\n     */\n    getBoundingRect: function(absolute, calculate) {\n      var coords = this.getCoords(absolute, calculate);\n      return util.makeBoundingBoxFromPoints(coords);\n    },\n\n    /**\n     * Returns width of an object's bounding box counting transformations\n     * before 2.0 it was named getWidth();\n     * @return {Number} width value\n     */\n    getScaledWidth: function() {\n      return this._getTransformedDimensions().x;\n    },\n\n    /**\n     * Returns height of an object bounding box counting transformations\n     * before 2.0 it was named getHeight();\n     * @return {Number} height value\n     */\n    getScaledHeight: function() {\n      return this._getTransformedDimensions().y;\n    },\n\n    /**\n     * Makes sure the scale is valid and modifies it if necessary\n     * @private\n     * @param {Number} value\n     * @return {Number}\n     */\n    _constrainScale: function(value) {\n      if (Math.abs(value) < this.minScaleLimit) {\n        if (value < 0) {\n          return -this.minScaleLimit;\n        }\n        else {\n          return this.minScaleLimit;\n        }\n      }\n      else if (value === 0) {\n        return 0.0001;\n      }\n      return value;\n    },\n\n    /**\n     * Scales an object (equally by x and y)\n     * @param {Number} value Scale factor\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    scale: function(value) {\n      this._set('scaleX', value);\n      this._set('scaleY', value);\n      return this.setCoords();\n    },\n\n    /**\n     * Scales an object to a given width, with respect to bounding box (scaling by x/y equally)\n     * @param {Number} value New width value\n     * @param {Boolean} absolute ignore viewport\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    scaleToWidth: function(value, absolute) {\n      // adjust to bounding rect factor so that rotated shapes would fit as well\n      var boundingRectFactor = this.getBoundingRect(absolute).width / this.getScaledWidth();\n      return this.scale(value / this.width / boundingRectFactor);\n    },\n\n    /**\n     * Scales an object to a given height, with respect to bounding box (scaling by x/y equally)\n     * @param {Number} value New height value\n     * @param {Boolean} absolute ignore viewport\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    scaleToHeight: function(value, absolute) {\n      // adjust to bounding rect factor so that rotated shapes would fit as well\n      var boundingRectFactor = this.getBoundingRect(absolute).height / this.getScaledHeight();\n      return this.scale(value / this.height / boundingRectFactor);\n    },\n\n    /**\n     * Calculates and returns the .coords of an object.\n     * unused by the library, only for the end dev.\n     * @return {Object} Object with tl, tr, br, bl ....\n     * @chainable\n     * @deprecated\n     */\n    calcCoords: function(absolute) {\n      // this is a compatibility function to avoid removing calcCoords now.\n      if (absolute) {\n        return this.calcACoords();\n      }\n      return this.calcOCoords();\n    },\n\n    calcLineCoords: function() {\n      var vpt = this.getViewportTransform(),\n          padding = this.padding, angle = degreesToRadians(this.angle),\n          cos = util.cos(angle), sin = util.sin(angle),\n          cosP = cos * padding, sinP = sin * padding, cosPSinP = cosP + sinP,\n          cosPMinusSinP = cosP - sinP, aCoords = this.calcACoords();\n\n      var lineCoords = {\n        tl: transformPoint(aCoords.tl, vpt),\n        tr: transformPoint(aCoords.tr, vpt),\n        bl: transformPoint(aCoords.bl, vpt),\n        br: transformPoint(aCoords.br, vpt),\n      };\n\n      if (padding) {\n        lineCoords.tl.x -= cosPMinusSinP;\n        lineCoords.tl.y -= cosPSinP;\n        lineCoords.tr.x += cosPSinP;\n        lineCoords.tr.y -= cosPMinusSinP;\n        lineCoords.bl.x -= cosPSinP;\n        lineCoords.bl.y += cosPMinusSinP;\n        lineCoords.br.x += cosPMinusSinP;\n        lineCoords.br.y += cosPSinP;\n      }\n\n      return lineCoords;\n    },\n\n    calcOCoords: function() {\n      var rotateMatrix = this._calcRotateMatrix(),\n          translateMatrix = this._calcTranslateMatrix(),\n          vpt = this.getViewportTransform(),\n          startMatrix = multiplyMatrices(vpt, translateMatrix),\n          finalMatrix = multiplyMatrices(startMatrix, rotateMatrix),\n          finalMatrix = multiplyMatrices(finalMatrix, [1 / vpt[0], 0, 0, 1 / vpt[3], 0, 0]),\n          dim = this._calculateCurrentDimensions(),\n          coords = {};\n      this.forEachControl(function(control, key, fabricObject) {\n        coords[key] = control.positionHandler(dim, finalMatrix, fabricObject);\n      });\n\n      // debug code\n      // var canvas = this.canvas;\n      // setTimeout(function() {\n      //   canvas.contextTop.clearRect(0, 0, 700, 700);\n      //   canvas.contextTop.fillStyle = 'green';\n      //   Object.keys(coords).forEach(function(key) {\n      //     var control = coords[key];\n      //     canvas.contextTop.fillRect(control.x, control.y, 3, 3);\n      //   });\n      // }, 50);\n      return coords;\n    },\n\n    calcACoords: function() {\n      var rotateMatrix = this._calcRotateMatrix(),\n          translateMatrix = this._calcTranslateMatrix(),\n          finalMatrix = multiplyMatrices(translateMatrix, rotateMatrix),\n          dim = this._getTransformedDimensions(),\n          w = dim.x / 2, h = dim.y / 2;\n      return {\n        // corners\n        tl: transformPoint({ x: -w, y: -h }, finalMatrix),\n        tr: transformPoint({ x: w, y: -h }, finalMatrix),\n        bl: transformPoint({ x: -w, y: h }, finalMatrix),\n        br: transformPoint({ x: w, y: h }, finalMatrix)\n      };\n    },\n\n    /**\n     * Sets corner position coordinates based on current angle, width and height.\n     * oCoords are used to find the corners\n     * aCoords are used to quickly find an object on the canvas\n     * lineCoords are used to quickly find object during pointer events.\n     * See {@link https://github.com/kangax/fabric.js/wiki/When-to-call-setCoords|When-to-call-setCoords}\n     * @param {Boolean} [skipCorners] skip calculation of oCoords.\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    setCoords: function(skipCorners) {\n      this.aCoords = this.calcACoords();\n      // in case we are in a group, for how the inner group target check works,\n      // lineCoords are exactly aCoords. Since the vpt gets absorbed by the normalized pointer.\n      this.lineCoords = this.group ? this.aCoords : this.calcLineCoords();\n      if (skipCorners) {\n        return this;\n      }\n      // set coordinates of the draggable boxes in the corners used to scale/rotate the image\n      this.oCoords = this.calcOCoords();\n      this._setCornerCoords && this._setCornerCoords();\n      return this;\n    },\n\n    /**\n     * calculate rotation matrix of an object\n     * @return {Array} rotation matrix for the object\n     */\n    _calcRotateMatrix: function() {\n      return util.calcRotateMatrix(this);\n    },\n\n    /**\n     * calculate the translation matrix for an object transform\n     * @return {Array} rotation matrix for the object\n     */\n    _calcTranslateMatrix: function() {\n      var center = this.getCenterPoint();\n      return [1, 0, 0, 1, center.x, center.y];\n    },\n\n    transformMatrixKey: function(skipGroup) {\n      var sep = '_', prefix = '';\n      if (!skipGroup && this.group) {\n        prefix = this.group.transformMatrixKey(skipGroup) + sep;\n      };\n      return prefix + this.top + sep + this.left + sep + this.scaleX + sep + this.scaleY +\n        sep + this.skewX + sep + this.skewY + sep + this.angle + sep + this.originX + sep + this.originY +\n        sep + this.width + sep + this.height + sep + this.strokeWidth + this.flipX + this.flipY;\n    },\n\n    /**\n     * calculate transform matrix that represents the current transformations from the\n     * object's properties.\n     * @param {Boolean} [skipGroup] return transform matrix for object not counting parent transformations\n     * There are some situation in which this is useful to avoid the fake rotation.\n     * @return {Array} transform matrix for the object\n     */\n    calcTransformMatrix: function(skipGroup) {\n      var matrix = this.calcOwnMatrix();\n      if (skipGroup || !this.group) {\n        return matrix;\n      }\n      var key = this.transformMatrixKey(skipGroup), cache = this.matrixCache || (this.matrixCache = {});\n      if (cache.key === key) {\n        return cache.value;\n      }\n      if (this.group) {\n        matrix = multiplyMatrices(this.group.calcTransformMatrix(false), matrix);\n      }\n      cache.key = key;\n      cache.value = matrix;\n      return matrix;\n    },\n\n    /**\n     * calculate transform matrix that represents the current transformations from the\n     * object's properties, this matrix does not include the group transformation\n     * @return {Array} transform matrix for the object\n     */\n    calcOwnMatrix: function() {\n      var key = this.transformMatrixKey(true), cache = this.ownMatrixCache || (this.ownMatrixCache = {});\n      if (cache.key === key) {\n        return cache.value;\n      }\n      var tMatrix = this._calcTranslateMatrix(),\n          options = {\n            angle: this.angle,\n            translateX: tMatrix[4],\n            translateY: tMatrix[5],\n            scaleX: this.scaleX,\n            scaleY: this.scaleY,\n            skewX: this.skewX,\n            skewY: this.skewY,\n            flipX: this.flipX,\n            flipY: this.flipY,\n          };\n      cache.key = key;\n      cache.value = util.composeMatrix(options);\n      return cache.value;\n    },\n\n    /*\n     * Calculate object dimensions from its properties\n     * @private\n     * @deprecated since 3.4.0, please use fabric.util._calcDimensionsTransformMatrix\n     * not including or including flipX, flipY to emulate the flipping boolean\n     * @return {Object} .x width dimension\n     * @return {Object} .y height dimension\n     */\n    _calcDimensionsTransformMatrix: function(skewX, skewY, flipping) {\n      return util.calcDimensionsMatrix({\n        skewX: skewX,\n        skewY: skewY,\n        scaleX: this.scaleX * (flipping && this.flipX ? -1 : 1),\n        scaleY: this.scaleY * (flipping && this.flipY ? -1 : 1)\n      });\n    },\n\n    /*\n     * Calculate object dimensions from its properties\n     * @private\n     * @return {Object} .x width dimension\n     * @return {Object} .y height dimension\n     */\n    _getNonTransformedDimensions: function() {\n      var strokeWidth = this.strokeWidth,\n          w = this.width + strokeWidth,\n          h = this.height + strokeWidth;\n      return { x: w, y: h };\n    },\n\n    /*\n     * Calculate object bounding box dimensions from its properties scale, skew.\n     * @param {Number} skewX, a value to override current skewX\n     * @param {Number} skewY, a value to override current skewY\n     * @private\n     * @return {Object} .x width dimension\n     * @return {Object} .y height dimension\n     */\n    _getTransformedDimensions: function(skewX, skewY) {\n      if (typeof skewX === 'undefined') {\n        skewX = this.skewX;\n      }\n      if (typeof skewY === 'undefined') {\n        skewY = this.skewY;\n      }\n      var dimensions = this._getNonTransformedDimensions(), dimX, dimY,\n          noSkew = skewX === 0 && skewY === 0;\n\n      if (this.strokeUniform) {\n        dimX = this.width;\n        dimY = this.height;\n      }\n      else {\n        dimX = dimensions.x;\n        dimY = dimensions.y;\n      }\n      if (noSkew) {\n        return this._finalizeDimensions(dimX * this.scaleX, dimY * this.scaleY);\n      }\n      var bbox = util.sizeAfterTransform(dimX, dimY, {\n        scaleX: this.scaleX,\n        scaleY: this.scaleY,\n        skewX: skewX,\n        skewY: skewY,\n      });\n      return this._finalizeDimensions(bbox.x, bbox.y);\n    },\n\n    /*\n     * Calculate object bounding box dimensions from its properties scale, skew.\n     * @param Number width width of the bbox\n     * @param Number height height of the bbox\n     * @private\n     * @return {Object} .x finalized width dimension\n     * @return {Object} .y finalized height dimension\n     */\n    _finalizeDimensions: function(width, height) {\n      return this.strokeUniform ?\n        { x: width + this.strokeWidth, y: height + this.strokeWidth }\n        :\n        { x: width, y: height };\n    },\n\n    /*\n     * Calculate object dimensions for controls box, including padding and canvas zoom.\n     * and active selection\n     * private\n     */\n    _calculateCurrentDimensions: function()  {\n      var vpt = this.getViewportTransform(),\n          dim = this._getTransformedDimensions(),\n          p = transformPoint(dim, vpt, true);\n      return p.scalarAdd(2 * this.padding);\n    },\n  });\n})();\n\n\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n  /**\n   * Moves an object to the bottom of the stack of drawn objects\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  sendToBack: function() {\n    if (this.group) {\n      fabric.StaticCanvas.prototype.sendToBack.call(this.group, this);\n    }\n    else if (this.canvas) {\n      this.canvas.sendToBack(this);\n    }\n    return this;\n  },\n\n  /**\n   * Moves an object to the top of the stack of drawn objects\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  bringToFront: function() {\n    if (this.group) {\n      fabric.StaticCanvas.prototype.bringToFront.call(this.group, this);\n    }\n    else if (this.canvas) {\n      this.canvas.bringToFront(this);\n    }\n    return this;\n  },\n\n  /**\n   * Moves an object down in stack of drawn objects\n   * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  sendBackwards: function(intersecting) {\n    if (this.group) {\n      fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting);\n    }\n    else if (this.canvas) {\n      this.canvas.sendBackwards(this, intersecting);\n    }\n    return this;\n  },\n\n  /**\n   * Moves an object up in stack of drawn objects\n   * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  bringForward: function(intersecting) {\n    if (this.group) {\n      fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting);\n    }\n    else if (this.canvas) {\n      this.canvas.bringForward(this, intersecting);\n    }\n    return this;\n  },\n\n  /**\n   * Moves an object to specified level in stack of drawn objects\n   * @param {Number} index New position of object\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  moveTo: function(index) {\n    if (this.group && this.group.type !== 'activeSelection') {\n      fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index);\n    }\n    else if (this.canvas) {\n      this.canvas.moveTo(this, index);\n    }\n    return this;\n  }\n});\n\n\n/* _TO_SVG_START_ */\n(function() {\n  function getSvgColorString(prop, value) {\n    if (!value) {\n      return prop + ': none; ';\n    }\n    else if (value.toLive) {\n      return prop + ': url(#SVGID_' + value.id + '); ';\n    }\n    else {\n      var color = new fabric.Color(value),\n          str = prop + ': ' + color.toRgb() + '; ',\n          opacity = color.getAlpha();\n      if (opacity !== 1) {\n        //change the color in rgb + opacity\n        str += prop + '-opacity: ' + opacity.toString() + '; ';\n      }\n      return str;\n    }\n  }\n\n  var toFixed = fabric.util.toFixed;\n\n  fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n    /**\n     * Returns styles-string for svg-export\n     * @param {Boolean} skipShadow a boolean to skip shadow filter output\n     * @return {String}\n     */\n    getSvgStyles: function(skipShadow) {\n\n      var fillRule = this.fillRule ? this.fillRule : 'nonzero',\n          strokeWidth = this.strokeWidth ? this.strokeWidth : '0',\n          strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : 'none',\n          strokeDashOffset = this.strokeDashOffset ? this.strokeDashOffset : '0',\n          strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt',\n          strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter',\n          strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4',\n          opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1',\n          visibility = this.visible ? '' : ' visibility: hidden;',\n          filter = skipShadow ? '' : this.getSvgFilter(),\n          fill = getSvgColorString('fill', this.fill),\n          stroke = getSvgColorString('stroke', this.stroke);\n\n      return [\n        stroke,\n        'stroke-width: ', strokeWidth, '; ',\n        'stroke-dasharray: ', strokeDashArray, '; ',\n        'stroke-linecap: ', strokeLineCap, '; ',\n        'stroke-dashoffset: ', strokeDashOffset, '; ',\n        'stroke-linejoin: ', strokeLineJoin, '; ',\n        'stroke-miterlimit: ', strokeMiterLimit, '; ',\n        fill,\n        'fill-rule: ', fillRule, '; ',\n        'opacity: ', opacity, ';',\n        filter,\n        visibility\n      ].join('');\n    },\n\n    /**\n     * Returns styles-string for svg-export\n     * @param {Object} style the object from which to retrieve style properties\n     * @param {Boolean} useWhiteSpace a boolean to include an additional attribute in the style.\n     * @return {String}\n     */\n    getSvgSpanStyles: function(style, useWhiteSpace) {\n      var term = '; ';\n      var fontFamily = style.fontFamily ?\n        'font-family: ' + (((style.fontFamily.indexOf('\\'') === -1 && style.fontFamily.indexOf('\"') === -1) ?\n          '\\'' + style.fontFamily  + '\\'' : style.fontFamily)) + term : '';\n      var strokeWidth = style.strokeWidth ? 'stroke-width: ' + style.strokeWidth + term : '',\n          fontFamily = fontFamily,\n          fontSize = style.fontSize ? 'font-size: ' + style.fontSize + 'px' + term : '',\n          fontStyle = style.fontStyle ? 'font-style: ' + style.fontStyle + term : '',\n          fontWeight = style.fontWeight ? 'font-weight: ' + style.fontWeight + term : '',\n          fill = style.fill ? getSvgColorString('fill', style.fill) : '',\n          stroke = style.stroke ? getSvgColorString('stroke', style.stroke) : '',\n          textDecoration = this.getSvgTextDecoration(style),\n          deltaY = style.deltaY ? 'baseline-shift: ' + (-style.deltaY) + '; ' : '';\n      if (textDecoration) {\n        textDecoration = 'text-decoration: ' + textDecoration + term;\n      }\n\n      return [\n        stroke,\n        strokeWidth,\n        fontFamily,\n        fontSize,\n        fontStyle,\n        fontWeight,\n        textDecoration,\n        fill,\n        deltaY,\n        useWhiteSpace ? 'white-space: pre; ' : ''\n      ].join('');\n    },\n\n    /**\n     * Returns text-decoration property for svg-export\n     * @param {Object} style the object from which to retrieve style properties\n     * @return {String}\n     */\n    getSvgTextDecoration: function(style) {\n      return ['overline', 'underline', 'line-through'].filter(function(decoration) {\n        return style[decoration.replace('-', '')];\n      }).join(' ');\n    },\n\n    /**\n     * Returns filter for svg shadow\n     * @return {String}\n     */\n    getSvgFilter: function() {\n      return this.shadow ? 'filter: url(#SVGID_' + this.shadow.id + ');' : '';\n    },\n\n    /**\n     * Returns id attribute for svg output\n     * @return {String}\n     */\n    getSvgCommons: function() {\n      return [\n        this.id ? 'id=\"' + this.id + '\" ' : '',\n        this.clipPath ? 'clip-path=\"url(#' + this.clipPath.clipPathId + ')\" ' : '',\n      ].join('');\n    },\n\n    /**\n     * Returns transform-string for svg-export\n     * @param {Boolean} use the full transform or the single object one.\n     * @return {String}\n     */\n    getSvgTransform: function(full, additionalTransform) {\n      var transform = full ? this.calcTransformMatrix() : this.calcOwnMatrix(),\n          svgTransform = 'transform=\"' + fabric.util.matrixToSVG(transform);\n      return svgTransform +\n        (additionalTransform || '') + '\" ';\n    },\n\n    _setSVGBg: function(textBgRects) {\n      if (this.backgroundColor) {\n        var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n        textBgRects.push(\n          '\\t\\t<rect ',\n          this._getFillAttributes(this.backgroundColor),\n          ' x=\"',\n          toFixed(-this.width / 2, NUM_FRACTION_DIGITS),\n          '\" y=\"',\n          toFixed(-this.height / 2, NUM_FRACTION_DIGITS),\n          '\" width=\"',\n          toFixed(this.width, NUM_FRACTION_DIGITS),\n          '\" height=\"',\n          toFixed(this.height, NUM_FRACTION_DIGITS),\n          '\"></rect>\\n');\n      }\n    },\n\n    /**\n     * Returns svg representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    toSVG: function(reviver) {\n      return this._createBaseSVGMarkup(this._toSVG(reviver), { reviver: reviver });\n    },\n\n    /**\n     * Returns svg clipPath representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    toClipPathSVG: function(reviver) {\n      return '\\t' + this._createBaseClipPathSVGMarkup(this._toSVG(reviver), { reviver: reviver });\n    },\n\n    /**\n     * @private\n     */\n    _createBaseClipPathSVGMarkup: function(objectMarkup, options) {\n      options = options || {};\n      var reviver = options.reviver,\n          additionalTransform = options.additionalTransform || '',\n          commonPieces = [\n            this.getSvgTransform(true, additionalTransform),\n            this.getSvgCommons(),\n          ].join(''),\n          // insert commons in the markup, style and svgCommons\n          index = objectMarkup.indexOf('COMMON_PARTS');\n      objectMarkup[index] = commonPieces;\n      return reviver ? reviver(objectMarkup.join('')) : objectMarkup.join('');\n    },\n\n    /**\n     * @private\n     */\n    _createBaseSVGMarkup: function(objectMarkup, options) {\n      options = options || {};\n      var noStyle = options.noStyle,\n          reviver = options.reviver,\n          styleInfo = noStyle ? '' : 'style=\"' + this.getSvgStyles() + '\" ',\n          shadowInfo = options.withShadow ? 'style=\"' + this.getSvgFilter() + '\" ' : '',\n          clipPath = this.clipPath,\n          vectorEffect = this.strokeUniform ? 'vector-effect=\"non-scaling-stroke\" ' : '',\n          absoluteClipPath = clipPath && clipPath.absolutePositioned,\n          stroke = this.stroke, fill = this.fill, shadow = this.shadow,\n          commonPieces, markup = [], clipPathMarkup,\n          // insert commons in the markup, style and svgCommons\n          index = objectMarkup.indexOf('COMMON_PARTS'),\n          additionalTransform = options.additionalTransform;\n      if (clipPath) {\n        clipPath.clipPathId = 'CLIPPATH_' + fabric.Object.__uid++;\n        clipPathMarkup = '<clipPath id=\"' + clipPath.clipPathId + '\" >\\n' +\n          clipPath.toClipPathSVG(reviver) +\n          '</clipPath>\\n';\n      }\n      if (absoluteClipPath) {\n        markup.push(\n          '<g ', shadowInfo, this.getSvgCommons(), ' >\\n'\n        );\n      }\n      markup.push(\n        '<g ',\n        this.getSvgTransform(false),\n        !absoluteClipPath ? shadowInfo + this.getSvgCommons() : '',\n        ' >\\n'\n      );\n      commonPieces = [\n        styleInfo,\n        vectorEffect,\n        noStyle ? '' : this.addPaintOrder(), ' ',\n        additionalTransform ? 'transform=\"' + additionalTransform + '\" ' : '',\n      ].join('');\n      objectMarkup[index] = commonPieces;\n      if (fill && fill.toLive) {\n        markup.push(fill.toSVG(this));\n      }\n      if (stroke && stroke.toLive) {\n        markup.push(stroke.toSVG(this));\n      }\n      if (shadow) {\n        markup.push(shadow.toSVG(this));\n      }\n      if (clipPath) {\n        markup.push(clipPathMarkup);\n      }\n      markup.push(objectMarkup.join(''));\n      markup.push('</g>\\n');\n      absoluteClipPath && markup.push('</g>\\n');\n      return reviver ? reviver(markup.join('')) : markup.join('');\n    },\n\n    addPaintOrder: function() {\n      return this.paintFirst !== 'fill' ? ' paint-order=\"' + this.paintFirst + '\" ' : '';\n    }\n  });\n})();\n/* _TO_SVG_END_ */\n\n\n(function() {\n\n  var extend = fabric.util.object.extend,\n      originalSet = 'stateProperties';\n\n  /*\n    Depends on `stateProperties`\n  */\n  function saveProps(origin, destination, props) {\n    var tmpObj = { }, deep = true;\n    props.forEach(function(prop) {\n      tmpObj[prop] = origin[prop];\n    });\n\n    extend(origin[destination], tmpObj, deep);\n  }\n\n  function _isEqual(origValue, currentValue, firstPass) {\n    if (origValue === currentValue) {\n      // if the objects are identical, return\n      return true;\n    }\n    else if (Array.isArray(origValue)) {\n      if (!Array.isArray(currentValue) || origValue.length !== currentValue.length) {\n        return false;\n      }\n      for (var i = 0, len = origValue.length; i < len; i++) {\n        if (!_isEqual(origValue[i], currentValue[i])) {\n          return false;\n        }\n      }\n      return true;\n    }\n    else if (origValue && typeof origValue === 'object') {\n      var keys = Object.keys(origValue), key;\n      if (!currentValue ||\n          typeof currentValue !== 'object' ||\n          (!firstPass && keys.length !== Object.keys(currentValue).length)\n      ) {\n        return false;\n      }\n      for (var i = 0, len = keys.length; i < len; i++) {\n        key = keys[i];\n        // since clipPath is in the statefull cache list and the clipPath objects\n        // would be iterated as an object, this would lead to possible infinite recursion\n        // we do not want to compare those.\n        if (key === 'canvas' || key === 'group') {\n          continue;\n        }\n        if (!_isEqual(origValue[key], currentValue[key])) {\n          return false;\n        }\n      }\n      return true;\n    }\n  }\n\n\n  fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n    /**\n     * Returns true if object state (one of its state properties) was changed\n     * @param {String} [propertySet] optional name for the set of property we want to save\n     * @return {Boolean} true if instance' state has changed since `{@link fabric.Object#saveState}` was called\n     */\n    hasStateChanged: function(propertySet) {\n      propertySet = propertySet || originalSet;\n      var dashedPropertySet = '_' + propertySet;\n      if (Object.keys(this[dashedPropertySet]).length < this[propertySet].length) {\n        return true;\n      }\n      return !_isEqual(this[dashedPropertySet], this, true);\n    },\n\n    /**\n     * Saves state of an object\n     * @param {Object} [options] Object with additional `stateProperties` array to include when saving state\n     * @return {fabric.Object} thisArg\n     */\n    saveState: function(options) {\n      var propertySet = options && options.propertySet || originalSet,\n          destination = '_' + propertySet;\n      if (!this[destination]) {\n        return this.setupState(options);\n      }\n      saveProps(this, destination, this[propertySet]);\n      if (options && options.stateProperties) {\n        saveProps(this, destination, options.stateProperties);\n      }\n      return this;\n    },\n\n    /**\n     * Setups state of an object\n     * @param {Object} [options] Object with additional `stateProperties` array to include when saving state\n     * @return {fabric.Object} thisArg\n     */\n    setupState: function(options) {\n      options = options || { };\n      var propertySet = options.propertySet || originalSet;\n      options.propertySet = propertySet;\n      this['_' + propertySet] = { };\n      this.saveState(options);\n      return this;\n    }\n  });\n})();\n\n\n(function() {\n\n  var degreesToRadians = fabric.util.degreesToRadians;\n\n  fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n    /**\n     * Determines which corner has been clicked\n     * @private\n     * @param {Object} pointer The pointer indicating the mouse position\n     * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or false if nothing is found\n     */\n    _findTargetCorner: function(pointer, forTouch) {\n      // objects in group, anykind, are not self modificable,\n      // must not return an hovered corner.\n      if (!this.hasControls || this.group || (!this.canvas || this.canvas._activeObject !== this)) {\n        return false;\n      }\n\n      var ex = pointer.x,\n          ey = pointer.y,\n          xPoints,\n          lines, keys = Object.keys(this.oCoords),\n          j = keys.length - 1, i;\n      this.__corner = 0;\n\n      // cycle in reverse order so we pick first the one on top\n      for (; j >= 0; j--) {\n        i = keys[j];\n        if (!this.isControlVisible(i)) {\n          continue;\n        }\n\n        lines = this._getImageLines(forTouch ? this.oCoords[i].touchCorner : this.oCoords[i].corner);\n        // debugging\n\n        // this.canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);\n        // this.canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);\n        //\n        // this.canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);\n        // this.canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);\n        //\n        // this.canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);\n        // this.canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);\n        //\n        // this.canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);\n        // this.canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);\n\n        xPoints = this._findCrossPoints({ x: ex, y: ey }, lines);\n        if (xPoints !== 0 && xPoints % 2 === 1) {\n          this.__corner = i;\n          return i;\n        }\n      }\n      return false;\n    },\n\n    /**\n     * Calls a function for each control. The function gets called,\n     * with the control, the object that is calling the iterator and the control's key\n     * @param {Function} fn function to iterate over the controls over\n     */\n    forEachControl: function(fn) {\n      for (var i in this.controls) {\n        fn(this.controls[i], i, this);\n      };\n    },\n\n    /**\n     * Sets the coordinates of the draggable boxes in the corners of\n     * the image used to scale/rotate it.\n     * note: if we would switch to ROUND corner area, all of this would disappear.\n     * everything would resolve to a single point and a pythagorean theorem for the distance\n     * @private\n     */\n    _setCornerCoords: function() {\n      var coords = this.oCoords,\n          newTheta = degreesToRadians(45 - this.angle),\n          cosTheta = fabric.util.cos(newTheta),\n          sinTheta = fabric.util.sin(newTheta),\n          /* Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, */\n          /* 0.707106 stands for sqrt(2)/2 */\n          cornerHypotenuse = this.cornerSize * 0.707106,\n          touchHypotenuse = this.touchCornerSize * 0.707106,\n          cosHalfOffset = cornerHypotenuse * cosTheta,\n          sinHalfOffset = cornerHypotenuse * sinTheta,\n          touchCosHalfOffset = touchHypotenuse * cosTheta,\n          touchSinHalfOffset = touchHypotenuse * sinTheta,\n          x, y;\n\n      for (var control in coords) {\n        x = coords[control].x;\n        y = coords[control].y;\n        coords[control].corner = {\n          tl: {\n            x: x - sinHalfOffset,\n            y: y - cosHalfOffset\n          },\n          tr: {\n            x: x + cosHalfOffset,\n            y: y - sinHalfOffset\n          },\n          bl: {\n            x: x - cosHalfOffset,\n            y: y + sinHalfOffset\n          },\n          br: {\n            x: x + sinHalfOffset,\n            y: y + cosHalfOffset\n          }\n        };\n        coords[control].touchCorner = {\n          tl: {\n            x: x - touchSinHalfOffset,\n            y: y - touchCosHalfOffset\n          },\n          tr: {\n            x: x + touchCosHalfOffset,\n            y: y - touchSinHalfOffset\n          },\n          bl: {\n            x: x - touchCosHalfOffset,\n            y: y + touchSinHalfOffset\n          },\n          br: {\n            x: x + touchSinHalfOffset,\n            y: y + touchCosHalfOffset\n          }\n        };\n      }\n    },\n\n    /**\n     * Draws a colored layer behind the object, inside its selection borders.\n     * Requires public options: padding, selectionBackgroundColor\n     * this function is called when the context is transformed\n     * has checks to be skipped when the object is on a staticCanvas\n     * @param {CanvasRenderingContext2D} ctx Context to draw on\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    drawSelectionBackground: function(ctx) {\n      if (!this.selectionBackgroundColor ||\n        (this.canvas && !this.canvas.interactive) ||\n        (this.canvas && this.canvas._activeObject !== this)\n      ) {\n        return this;\n      }\n      ctx.save();\n      var center = this.getCenterPoint(), wh = this._calculateCurrentDimensions(),\n          vpt = this.canvas.viewportTransform;\n      ctx.translate(center.x, center.y);\n      ctx.scale(1 / vpt[0], 1 / vpt[3]);\n      ctx.rotate(degreesToRadians(this.angle));\n      ctx.fillStyle = this.selectionBackgroundColor;\n      ctx.fillRect(-wh.x / 2, -wh.y / 2, wh.x, wh.y);\n      ctx.restore();\n      return this;\n    },\n\n    /**\n     * Draws borders of an object's bounding box.\n     * Requires public properties: width, height\n     * Requires public options: padding, borderColor\n     * @param {CanvasRenderingContext2D} ctx Context to draw on\n     * @param {Object} styleOverride object to override the object style\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    drawBorders: function(ctx, styleOverride) {\n      styleOverride = styleOverride || {};\n      var wh = this._calculateCurrentDimensions(),\n          strokeWidth = this.borderScaleFactor,\n          width = wh.x + strokeWidth,\n          height = wh.y + strokeWidth,\n          hasControls = typeof styleOverride.hasControls !== 'undefined' ?\n            styleOverride.hasControls : this.hasControls,\n          shouldStroke = false;\n\n      ctx.save();\n      ctx.strokeStyle = styleOverride.borderColor || this.borderColor;\n      this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray, null);\n\n      ctx.strokeRect(\n        -width / 2,\n        -height / 2,\n        width,\n        height\n      );\n\n      if (hasControls) {\n        ctx.beginPath();\n        this.forEachControl(function(control, key, fabricObject) {\n          // in this moment, the ctx is centered on the object.\n          // width and height of the above function are the size of the bbox.\n          if (control.withConnection && control.getVisibility(fabricObject, key)) {\n            // reset movement for each control\n            shouldStroke = true;\n            ctx.moveTo(control.x * width, control.y * height);\n            ctx.lineTo(\n              control.x * width + control.offsetX,\n              control.y * height + control.offsetY\n            );\n          }\n        });\n        if (shouldStroke) {\n          ctx.stroke();\n        }\n      }\n      ctx.restore();\n      return this;\n    },\n\n    /**\n     * Draws borders of an object's bounding box when it is inside a group.\n     * Requires public properties: width, height\n     * Requires public options: padding, borderColor\n     * @param {CanvasRenderingContext2D} ctx Context to draw on\n     * @param {object} options object representing current object parameters\n     * @param {Object} styleOverride object to override the object style\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    drawBordersInGroup: function(ctx, options, styleOverride) {\n      styleOverride = styleOverride || {};\n      var bbox = fabric.util.sizeAfterTransform(this.width, this.height, options),\n          strokeWidth = this.strokeWidth,\n          strokeUniform = this.strokeUniform,\n          borderScaleFactor = this.borderScaleFactor,\n          width =\n            bbox.x + strokeWidth * (strokeUniform ? this.canvas.getZoom() : options.scaleX) + borderScaleFactor,\n          height =\n            bbox.y + strokeWidth * (strokeUniform ? this.canvas.getZoom() : options.scaleY) + borderScaleFactor;\n      ctx.save();\n      this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray, null);\n      ctx.strokeStyle = styleOverride.borderColor || this.borderColor;\n      ctx.strokeRect(\n        -width / 2,\n        -height / 2,\n        width,\n        height\n      );\n\n      ctx.restore();\n      return this;\n    },\n\n    /**\n     * Draws corners of an object's bounding box.\n     * Requires public properties: width, height\n     * Requires public options: cornerSize, padding\n     * @param {CanvasRenderingContext2D} ctx Context to draw on\n     * @param {Object} styleOverride object to override the object style\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    drawControls: function(ctx, styleOverride) {\n      styleOverride = styleOverride || {};\n      ctx.save();\n      ctx.setTransform(this.canvas.getRetinaScaling(), 0, 0, this.canvas.getRetinaScaling(), 0, 0);\n      ctx.strokeStyle = ctx.fillStyle = styleOverride.cornerColor || this.cornerColor;\n      if (!this.transparentCorners) {\n        ctx.strokeStyle = styleOverride.cornerStrokeColor || this.cornerStrokeColor;\n      }\n      this._setLineDash(ctx, styleOverride.cornerDashArray || this.cornerDashArray, null);\n      this.setCoords();\n      this.forEachControl(function(control, key, fabricObject) {\n        if (control.getVisibility(fabricObject, key)) {\n          control.render(ctx,\n            fabricObject.oCoords[key].x,\n            fabricObject.oCoords[key].y, styleOverride, fabricObject);\n        }\n      });\n      ctx.restore();\n\n      return this;\n    },\n\n    /**\n     * Returns true if the specified control is visible, false otherwise.\n     * @param {String} controlKey The key of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'.\n     * @returns {Boolean} true if the specified control is visible, false otherwise\n     */\n    isControlVisible: function(controlKey) {\n      return this.controls[controlKey] && this.controls[controlKey].getVisibility(this, controlKey);\n    },\n\n    /**\n     * Sets the visibility of the specified control.\n     * @param {String} controlKey The key of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'.\n     * @param {Boolean} visible true to set the specified control visible, false otherwise\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    setControlVisible: function(controlKey, visible) {\n      if (!this._controlsVisibility) {\n        this._controlsVisibility = {};\n      }\n      this._controlsVisibility[controlKey] = visible;\n      return this;\n    },\n\n    /**\n     * Sets the visibility state of object controls.\n     * @param {Object} [options] Options object\n     * @param {Boolean} [options.bl] true to enable the bottom-left control, false to disable it\n     * @param {Boolean} [options.br] true to enable the bottom-right control, false to disable it\n     * @param {Boolean} [options.mb] true to enable the middle-bottom control, false to disable it\n     * @param {Boolean} [options.ml] true to enable the middle-left control, false to disable it\n     * @param {Boolean} [options.mr] true to enable the middle-right control, false to disable it\n     * @param {Boolean} [options.mt] true to enable the middle-top control, false to disable it\n     * @param {Boolean} [options.tl] true to enable the top-left control, false to disable it\n     * @param {Boolean} [options.tr] true to enable the top-right control, false to disable it\n     * @param {Boolean} [options.mtr] true to enable the middle-top-rotate control, false to disable it\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    setControlsVisibility: function(options) {\n      options || (options = { });\n\n      for (var p in options) {\n        this.setControlVisible(p, options[p]);\n      }\n      return this;\n    },\n\n\n    /**\n     * This callback function is called every time _discardActiveObject or _setActiveObject\n     * try to to deselect this object. If the function returns true, the process is cancelled\n     * @param {Object} [options] options sent from the upper functions\n     * @param {Event} [options.e] event if the process is generated by an event\n     */\n    onDeselect: function() {\n      // implemented by sub-classes, as needed.\n    },\n\n\n    /**\n     * This callback function is called every time _discardActiveObject or _setActiveObject\n     * try to to select this object. If the function returns true, the process is cancelled\n     * @param {Object} [options] options sent from the upper functions\n     * @param {Event} [options.e] event if the process is generated by an event\n     */\n    onSelect: function() {\n      // implemented by sub-classes, as needed.\n    }\n  });\n})();\n\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n  /**\n   * Animation duration (in ms) for fx* methods\n   * @type Number\n   * @default\n   */\n  FX_DURATION: 500,\n\n  /**\n   * Centers object horizontally with animation.\n   * @param {fabric.Object} object Object to center\n   * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n   * @param {Function} [callbacks.onComplete] Invoked on completion\n   * @param {Function} [callbacks.onChange] Invoked on every step of animation\n   * @return {fabric.Canvas} thisArg\n   * @chainable\n   */\n  fxCenterObjectH: function (object, callbacks) {\n    callbacks = callbacks || { };\n\n    var empty = function() { },\n        onComplete = callbacks.onComplete || empty,\n        onChange = callbacks.onChange || empty,\n        _this = this;\n\n    fabric.util.animate({\n      startValue: object.left,\n      endValue: this.getCenter().left,\n      duration: this.FX_DURATION,\n      onChange: function(value) {\n        object.set('left', value);\n        _this.requestRenderAll();\n        onChange();\n      },\n      onComplete: function() {\n        object.setCoords();\n        onComplete();\n      }\n    });\n\n    return this;\n  },\n\n  /**\n   * Centers object vertically with animation.\n   * @param {fabric.Object} object Object to center\n   * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n   * @param {Function} [callbacks.onComplete] Invoked on completion\n   * @param {Function} [callbacks.onChange] Invoked on every step of animation\n   * @return {fabric.Canvas} thisArg\n   * @chainable\n   */\n  fxCenterObjectV: function (object, callbacks) {\n    callbacks = callbacks || { };\n\n    var empty = function() { },\n        onComplete = callbacks.onComplete || empty,\n        onChange = callbacks.onChange || empty,\n        _this = this;\n\n    fabric.util.animate({\n      startValue: object.top,\n      endValue: this.getCenter().top,\n      duration: this.FX_DURATION,\n      onChange: function(value) {\n        object.set('top', value);\n        _this.requestRenderAll();\n        onChange();\n      },\n      onComplete: function() {\n        object.setCoords();\n        onComplete();\n      }\n    });\n\n    return this;\n  },\n\n  /**\n   * Same as `fabric.Canvas#remove` but animated\n   * @param {fabric.Object} object Object to remove\n   * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n   * @param {Function} [callbacks.onComplete] Invoked on completion\n   * @param {Function} [callbacks.onChange] Invoked on every step of animation\n   * @return {fabric.Canvas} thisArg\n   * @chainable\n   */\n  fxRemove: function (object, callbacks) {\n    callbacks = callbacks || { };\n\n    var empty = function() { },\n        onComplete = callbacks.onComplete || empty,\n        onChange = callbacks.onChange || empty,\n        _this = this;\n\n    fabric.util.animate({\n      startValue: object.opacity,\n      endValue: 0,\n      duration: this.FX_DURATION,\n      onChange: function(value) {\n        object.set('opacity', value);\n        _this.requestRenderAll();\n        onChange();\n      },\n      onComplete: function () {\n        _this.remove(object);\n        onComplete();\n      }\n    });\n\n    return this;\n  }\n});\n\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n  /**\n   * Animates object's properties\n   * @param {String|Object} property Property to animate (if string) or properties to animate (if object)\n   * @param {Number|Object} value Value to animate property to (if string was given first) or options object\n   * @return {fabric.Object} thisArg\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#animation}\n   * @chainable\n   *\n   * As object — multiple properties\n   *\n   * object.animate({ left: ..., top: ... });\n   * object.animate({ left: ..., top: ... }, { duration: ... });\n   *\n   * As string — one property\n   *\n   * object.animate('left', ...);\n   * object.animate('left', { duration: ... });\n   *\n   */\n  animate: function() {\n    if (arguments[0] && typeof arguments[0] === 'object') {\n      var propsToAnimate = [], prop, skipCallbacks;\n      for (prop in arguments[0]) {\n        propsToAnimate.push(prop);\n      }\n      for (var i = 0, len = propsToAnimate.length; i < len; i++) {\n        prop = propsToAnimate[i];\n        skipCallbacks = i !== len - 1;\n        this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks);\n      }\n    }\n    else {\n      this._animate.apply(this, arguments);\n    }\n    return this;\n  },\n\n  /**\n   * @private\n   * @param {String} property Property to animate\n   * @param {String} to Value to animate to\n   * @param {Object} [options] Options object\n   * @param {Boolean} [skipCallbacks] When true, callbacks like onchange and oncomplete are not invoked\n   */\n  _animate: function(property, to, options, skipCallbacks) {\n    var _this = this, propPair;\n\n    to = to.toString();\n\n    if (!options) {\n      options = { };\n    }\n    else {\n      options = fabric.util.object.clone(options);\n    }\n\n    if (~property.indexOf('.')) {\n      propPair = property.split('.');\n    }\n\n    var propIsColor =\n      _this.colorProperties.indexOf(property) > -1 ||\n      (propPair && _this.colorProperties.indexOf(propPair[1]) > -1);\n\n    var currentValue = propPair\n      ? this.get(propPair[0])[propPair[1]]\n      : this.get(property);\n\n    if (!('from' in options)) {\n      options.from = currentValue;\n    }\n\n    if (!propIsColor) {\n      if (~to.indexOf('=')) {\n        to = currentValue + parseFloat(to.replace('=', ''));\n      }\n      else {\n        to = parseFloat(to);\n      }\n    }\n\n    var _options = {\n      startValue: options.from,\n      endValue: to,\n      byValue: options.by,\n      easing: options.easing,\n      duration: options.duration,\n      abort: options.abort && function () {\n        return options.abort.call(_this);\n      },\n      onChange: function (value, valueProgress, timeProgress) {\n        if (propPair) {\n          _this[propPair[0]][propPair[1]] = value;\n        }\n        else {\n          _this.set(property, value);\n        }\n        if (skipCallbacks) {\n          return;\n        }\n        options.onChange && options.onChange(value, valueProgress, timeProgress);\n      },\n      onComplete: function (value, valueProgress, timeProgress) {\n        if (skipCallbacks) {\n          return;\n        }\n\n        _this.setCoords();\n        options.onComplete && options.onComplete(value, valueProgress, timeProgress);\n      }\n    };\n\n    if (propIsColor) {\n      fabric.util.animateColor(_options.startValue, _options.endValue, _options.duration, _options);\n    }\n    else {\n      fabric.util.animate(_options);\n    }\n  }\n});\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { }),\n      extend = fabric.util.object.extend,\n      clone = fabric.util.object.clone,\n      coordProps = { x1: 1, x2: 1, y1: 1, y2: 1 },\n      supportsLineDash = fabric.StaticCanvas.supports('setLineDash');\n\n  if (fabric.Line) {\n    fabric.warn('fabric.Line is already defined');\n    return;\n  }\n\n  /**\n   * Line class\n   * @class fabric.Line\n   * @extends fabric.Object\n   * @see {@link fabric.Line#initialize} for constructor definition\n   */\n  fabric.Line = fabric.util.createClass(fabric.Object, /** @lends fabric.Line.prototype */ {\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'line',\n\n    /**\n     * x value or first line edge\n     * @type Number\n     * @default\n     */\n    x1: 0,\n\n    /**\n     * y value or first line edge\n     * @type Number\n     * @default\n     */\n    y1: 0,\n\n    /**\n     * x value or second line edge\n     * @type Number\n     * @default\n     */\n    x2: 0,\n\n    /**\n     * y value or second line edge\n     * @type Number\n     * @default\n     */\n    y2: 0,\n\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('x1', 'x2', 'y1', 'y2'),\n\n    /**\n     * Constructor\n     * @param {Array} [points] Array of points\n     * @param {Object} [options] Options object\n     * @return {fabric.Line} thisArg\n     */\n    initialize: function(points, options) {\n      if (!points) {\n        points = [0, 0, 0, 0];\n      }\n\n      this.callSuper('initialize', options);\n\n      this.set('x1', points[0]);\n      this.set('y1', points[1]);\n      this.set('x2', points[2]);\n      this.set('y2', points[3]);\n\n      this._setWidthHeight(options);\n    },\n\n    /**\n     * @private\n     * @param {Object} [options] Options\n     */\n    _setWidthHeight: function(options) {\n      options || (options = { });\n\n      this.width = Math.abs(this.x2 - this.x1);\n      this.height = Math.abs(this.y2 - this.y1);\n\n      this.left = 'left' in options\n        ? options.left\n        : this._getLeftToOriginX();\n\n      this.top = 'top' in options\n        ? options.top\n        : this._getTopToOriginY();\n    },\n\n    /**\n     * @private\n     * @param {String} key\n     * @param {*} value\n     */\n    _set: function(key, value) {\n      this.callSuper('_set', key, value);\n      if (typeof coordProps[key] !== 'undefined') {\n        this._setWidthHeight();\n      }\n      return this;\n    },\n\n    /**\n     * @private\n     * @return {Number} leftToOriginX Distance from left edge of canvas to originX of Line.\n     */\n    _getLeftToOriginX: makeEdgeToOriginGetter(\n      { // property names\n        origin: 'originX',\n        axis1: 'x1',\n        axis2: 'x2',\n        dimension: 'width'\n      },\n      { // possible values of origin\n        nearest: 'left',\n        center: 'center',\n        farthest: 'right'\n      }\n    ),\n\n    /**\n     * @private\n     * @return {Number} topToOriginY Distance from top edge of canvas to originY of Line.\n     */\n    _getTopToOriginY: makeEdgeToOriginGetter(\n      { // property names\n        origin: 'originY',\n        axis1: 'y1',\n        axis2: 'y2',\n        dimension: 'height'\n      },\n      { // possible values of origin\n        nearest: 'top',\n        center: 'center',\n        farthest: 'bottom'\n      }\n    ),\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function(ctx) {\n      ctx.beginPath();\n\n      if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) {\n        // move from center (of virtual box) to its left/top corner\n        // we can't assume x1, y1 is top left and x2, y2 is bottom right\n        var p = this.calcLinePoints();\n        ctx.moveTo(p.x1, p.y1);\n        ctx.lineTo(p.x2, p.y2);\n      }\n\n      ctx.lineWidth = this.strokeWidth;\n\n      // TODO: test this\n      // make sure setting \"fill\" changes color of a line\n      // (by copying fillStyle to strokeStyle, since line is stroked, not filled)\n      var origStrokeStyle = ctx.strokeStyle;\n      ctx.strokeStyle = this.stroke || ctx.fillStyle;\n      this.stroke && this._renderStroke(ctx);\n      ctx.strokeStyle = origStrokeStyle;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderDashedStroke: function(ctx) {\n      var p = this.calcLinePoints();\n\n      ctx.beginPath();\n      fabric.util.drawDashedLine(ctx, p.x1, p.y1, p.x2, p.y2, this.strokeDashArray);\n      ctx.closePath();\n    },\n\n    /**\n     * This function is an helper for svg import. it returns the center of the object in the svg\n     * untransformed coordinates\n     * @private\n     * @return {Object} center point from element coordinates\n     */\n    _findCenterFromElement: function() {\n      return {\n        x: (this.x1 + this.x2) / 2,\n        y: (this.y1 + this.y2) / 2,\n      };\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @methd toObject\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function(propertiesToInclude) {\n      return extend(this.callSuper('toObject', propertiesToInclude), this.calcLinePoints());\n    },\n\n    /*\n     * Calculate object dimensions from its properties\n     * @private\n     */\n    _getNonTransformedDimensions: function() {\n      var dim = this.callSuper('_getNonTransformedDimensions');\n      if (this.strokeLineCap === 'butt') {\n        if (this.width === 0) {\n          dim.y -= this.strokeWidth;\n        }\n        if (this.height === 0) {\n          dim.x -= this.strokeWidth;\n        }\n      }\n      return dim;\n    },\n\n    /**\n     * Recalculates line points given width and height\n     * @private\n     */\n    calcLinePoints: function() {\n      var xMult = this.x1 <= this.x2 ? -1 : 1,\n          yMult = this.y1 <= this.y2 ? -1 : 1,\n          x1 = (xMult * this.width * 0.5),\n          y1 = (yMult * this.height * 0.5),\n          x2 = (xMult * this.width * -0.5),\n          y2 = (yMult * this.height * -0.5);\n\n      return {\n        x1: x1,\n        x2: x2,\n        y1: y1,\n        y2: y2\n      };\n    },\n\n    /* _TO_SVG_START_ */\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function() {\n      var p = this.calcLinePoints();\n      return [\n        '<line ', 'COMMON_PARTS',\n        'x1=\"', p.x1,\n        '\" y1=\"', p.y1,\n        '\" x2=\"', p.x2,\n        '\" y2=\"', p.y2,\n        '\" />\\n'\n      ];\n    },\n    /* _TO_SVG_END_ */\n  });\n\n  /* _FROM_SVG_START_ */\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement})\n   * @static\n   * @memberOf fabric.Line\n   * @see http://www.w3.org/TR/SVG/shapes.html#LineElement\n   */\n  fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' '));\n\n  /**\n   * Returns fabric.Line instance from an SVG element\n   * @static\n   * @memberOf fabric.Line\n   * @param {SVGElement} element Element to parse\n   * @param {Object} [options] Options object\n   * @param {Function} [callback] callback function invoked after parsing\n   */\n  fabric.Line.fromElement = function(element, callback, options) {\n    options = options || { };\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES),\n        points = [\n          parsedAttributes.x1 || 0,\n          parsedAttributes.y1 || 0,\n          parsedAttributes.x2 || 0,\n          parsedAttributes.y2 || 0\n        ];\n    callback(new fabric.Line(points, extend(parsedAttributes, options)));\n  };\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns fabric.Line instance from an object representation\n   * @static\n   * @memberOf fabric.Line\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] invoked with new instance as first argument\n   */\n  fabric.Line.fromObject = function(object, callback) {\n    function _callback(instance) {\n      delete instance.points;\n      callback && callback(instance);\n    };\n    var options = clone(object, true);\n    options.points = [object.x1, object.y1, object.x2, object.y2];\n    fabric.Object._fromObject('Line', options, _callback, 'points');\n  };\n\n  /**\n   * Produces a function that calculates distance from canvas edge to Line origin.\n   */\n  function makeEdgeToOriginGetter(propertyNames, originValues) {\n    var origin = propertyNames.origin,\n        axis1 = propertyNames.axis1,\n        axis2 = propertyNames.axis2,\n        dimension = propertyNames.dimension,\n        nearest = originValues.nearest,\n        center = originValues.center,\n        farthest = originValues.farthest;\n\n    return function() {\n      switch (this.get(origin)) {\n        case nearest:\n          return Math.min(this.get(axis1), this.get(axis2));\n        case center:\n          return Math.min(this.get(axis1), this.get(axis2)) + (0.5 * this.get(dimension));\n        case farthest:\n          return Math.max(this.get(axis1), this.get(axis2));\n      }\n    };\n\n  }\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { }),\n      pi = Math.PI;\n\n  if (fabric.Circle) {\n    fabric.warn('fabric.Circle is already defined.');\n    return;\n  }\n\n  /**\n   * Circle class\n   * @class fabric.Circle\n   * @extends fabric.Object\n   * @see {@link fabric.Circle#initialize} for constructor definition\n   */\n  fabric.Circle = fabric.util.createClass(fabric.Object, /** @lends fabric.Circle.prototype */ {\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'circle',\n\n    /**\n     * Radius of this circle\n     * @type Number\n     * @default\n     */\n    radius: 0,\n\n    /**\n     * Start angle of the circle, moving clockwise\n     * deprectated type, this should be in degree, this was an oversight.\n     * probably will change to degrees in next major version\n     * @type Number\n     * @default 0\n     */\n    startAngle: 0,\n\n    /**\n     * End angle of the circle\n     * deprectated type, this should be in degree, this was an oversight.\n     * probably will change to degrees in next major version\n     * @type Number\n     * @default 2Pi\n     */\n    endAngle: pi * 2,\n\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('radius', 'startAngle', 'endAngle'),\n\n    /**\n     * @private\n     * @param {String} key\n     * @param {*} value\n     * @return {fabric.Circle} thisArg\n     */\n    _set: function(key, value) {\n      this.callSuper('_set', key, value);\n\n      if (key === 'radius') {\n        this.setRadius(value);\n      }\n\n      return this;\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function(propertiesToInclude) {\n      return this.callSuper('toObject', ['radius', 'startAngle', 'endAngle'].concat(propertiesToInclude));\n    },\n\n    /* _TO_SVG_START_ */\n\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function() {\n      var svgString, x = 0, y = 0,\n          angle = (this.endAngle - this.startAngle) % ( 2 * pi);\n\n      if (angle === 0) {\n        svgString = [\n          '<circle ', 'COMMON_PARTS',\n          'cx=\"' + x + '\" cy=\"' + y + '\" ',\n          'r=\"', this.radius,\n          '\" />\\n'\n        ];\n      }\n      else {\n        var startX = fabric.util.cos(this.startAngle) * this.radius,\n            startY = fabric.util.sin(this.startAngle) * this.radius,\n            endX = fabric.util.cos(this.endAngle) * this.radius,\n            endY = fabric.util.sin(this.endAngle) * this.radius,\n            largeFlag = angle > pi ? '1' : '0';\n        svgString = [\n          '<path d=\"M ' + startX + ' ' + startY,\n          ' A ' + this.radius + ' ' + this.radius,\n          ' 0 ', +largeFlag + ' 1', ' ' + endX + ' ' + endY,\n          '\" ', 'COMMON_PARTS', ' />\\n'\n        ];\n      }\n      return svgString;\n    },\n    /* _TO_SVG_END_ */\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx context to render on\n     */\n    _render: function(ctx) {\n      ctx.beginPath();\n      ctx.arc(\n        0,\n        0,\n        this.radius,\n        this.startAngle,\n        this.endAngle, false);\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * Returns horizontal radius of an object (according to how an object is scaled)\n     * @return {Number}\n     */\n    getRadiusX: function() {\n      return this.get('radius') * this.get('scaleX');\n    },\n\n    /**\n     * Returns vertical radius of an object (according to how an object is scaled)\n     * @return {Number}\n     */\n    getRadiusY: function() {\n      return this.get('radius') * this.get('scaleY');\n    },\n\n    /**\n     * Sets radius of an object (and updates width accordingly)\n     * @return {fabric.Circle} thisArg\n     */\n    setRadius: function(value) {\n      this.radius = value;\n      return this.set('width', value * 2).set('height', value * 2);\n    },\n  });\n\n  /* _FROM_SVG_START_ */\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Circle.fromElement})\n   * @static\n   * @memberOf fabric.Circle\n   * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement\n   */\n  fabric.Circle.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy r'.split(' '));\n\n  /**\n   * Returns {@link fabric.Circle} instance from an SVG element\n   * @static\n   * @memberOf fabric.Circle\n   * @param {SVGElement} element Element to parse\n   * @param {Function} [callback] Options callback invoked after parsing is finished\n   * @param {Object} [options] Options object\n   * @throws {Error} If value of `r` attribute is missing or invalid\n   */\n  fabric.Circle.fromElement = function(element, callback) {\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES);\n\n    if (!isValidRadius(parsedAttributes)) {\n      throw new Error('value of `r` attribute is required and can not be negative');\n    }\n\n    parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.radius;\n    parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.radius;\n    callback(new fabric.Circle(parsedAttributes));\n  };\n\n  /**\n   * @private\n   */\n  function isValidRadius(attributes) {\n    return (('radius' in attributes) && (attributes.radius >= 0));\n  }\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns {@link fabric.Circle} instance from an object representation\n   * @static\n   * @memberOf fabric.Circle\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] invoked with new instance as first argument\n   * @return {Object} Instance of fabric.Circle\n   */\n  fabric.Circle.fromObject = function(object, callback) {\n    return fabric.Object._fromObject('Circle', object, callback);\n  };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { });\n\n  if (fabric.Triangle) {\n    fabric.warn('fabric.Triangle is already defined');\n    return;\n  }\n\n  /**\n   * Triangle class\n   * @class fabric.Triangle\n   * @extends fabric.Object\n   * @return {fabric.Triangle} thisArg\n   * @see {@link fabric.Triangle#initialize} for constructor definition\n   */\n  fabric.Triangle = fabric.util.createClass(fabric.Object, /** @lends fabric.Triangle.prototype */ {\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'triangle',\n\n    /**\n     * Width is set to 100 to compensate the old initialize code that was setting it to 100\n     * @type Number\n     * @default\n     */\n    width: 100,\n\n    /**\n     * Height is set to 100 to compensate the old initialize code that was setting it to 100\n     * @type Number\n     * @default\n     */\n    height: 100,\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function(ctx) {\n      var widthBy2 = this.width / 2,\n          heightBy2 = this.height / 2;\n\n      ctx.beginPath();\n      ctx.moveTo(-widthBy2, heightBy2);\n      ctx.lineTo(0, -heightBy2);\n      ctx.lineTo(widthBy2, heightBy2);\n      ctx.closePath();\n\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderDashedStroke: function(ctx) {\n      var widthBy2 = this.width / 2,\n          heightBy2 = this.height / 2;\n\n      ctx.beginPath();\n      fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray);\n      ctx.closePath();\n    },\n\n    /* _TO_SVG_START_ */\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function() {\n      var widthBy2 = this.width / 2,\n          heightBy2 = this.height / 2,\n          points = [\n            -widthBy2 + ' ' + heightBy2,\n            '0 ' + -heightBy2,\n            widthBy2 + ' ' + heightBy2\n          ].join(',');\n      return [\n        '<polygon ', 'COMMON_PARTS',\n        'points=\"', points,\n        '\" />'\n      ];\n    },\n    /* _TO_SVG_END_ */\n  });\n\n  /**\n   * Returns {@link fabric.Triangle} instance from an object representation\n   * @static\n   * @memberOf fabric.Triangle\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] invoked with new instance as first argument\n   */\n  fabric.Triangle.fromObject = function(object, callback) {\n    return fabric.Object._fromObject('Triangle', object, callback);\n  };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { }),\n      piBy2   = Math.PI * 2;\n\n  if (fabric.Ellipse) {\n    fabric.warn('fabric.Ellipse is already defined.');\n    return;\n  }\n\n  /**\n   * Ellipse class\n   * @class fabric.Ellipse\n   * @extends fabric.Object\n   * @return {fabric.Ellipse} thisArg\n   * @see {@link fabric.Ellipse#initialize} for constructor definition\n   */\n  fabric.Ellipse = fabric.util.createClass(fabric.Object, /** @lends fabric.Ellipse.prototype */ {\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'ellipse',\n\n    /**\n     * Horizontal radius\n     * @type Number\n     * @default\n     */\n    rx:   0,\n\n    /**\n     * Vertical radius\n     * @type Number\n     * @default\n     */\n    ry:   0,\n\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('rx', 'ry'),\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     * @return {fabric.Ellipse} thisArg\n     */\n    initialize: function(options) {\n      this.callSuper('initialize', options);\n      this.set('rx', options && options.rx || 0);\n      this.set('ry', options && options.ry || 0);\n    },\n\n    /**\n     * @private\n     * @param {String} key\n     * @param {*} value\n     * @return {fabric.Ellipse} thisArg\n     */\n    _set: function(key, value) {\n      this.callSuper('_set', key, value);\n      switch (key) {\n\n        case 'rx':\n          this.rx = value;\n          this.set('width', value * 2);\n          break;\n\n        case 'ry':\n          this.ry = value;\n          this.set('height', value * 2);\n          break;\n\n      }\n      return this;\n    },\n\n    /**\n     * Returns horizontal radius of an object (according to how an object is scaled)\n     * @return {Number}\n     */\n    getRx: function() {\n      return this.get('rx') * this.get('scaleX');\n    },\n\n    /**\n     * Returns Vertical radius of an object (according to how an object is scaled)\n     * @return {Number}\n     */\n    getRy: function() {\n      return this.get('ry') * this.get('scaleY');\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function(propertiesToInclude) {\n      return this.callSuper('toObject', ['rx', 'ry'].concat(propertiesToInclude));\n    },\n\n    /* _TO_SVG_START_ */\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function() {\n      return [\n        '<ellipse ', 'COMMON_PARTS',\n        'cx=\"0\" cy=\"0\" ',\n        'rx=\"', this.rx,\n        '\" ry=\"', this.ry,\n        '\" />\\n'\n      ];\n    },\n    /* _TO_SVG_END_ */\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx context to render on\n     */\n    _render: function(ctx) {\n      ctx.beginPath();\n      ctx.save();\n      ctx.transform(1, 0, 0, this.ry / this.rx, 0, 0);\n      ctx.arc(\n        0,\n        0,\n        this.rx,\n        0,\n        piBy2,\n        false);\n      ctx.restore();\n      this._renderPaintInOrder(ctx);\n    },\n  });\n\n  /* _FROM_SVG_START_ */\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Ellipse.fromElement})\n   * @static\n   * @memberOf fabric.Ellipse\n   * @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement\n   */\n  fabric.Ellipse.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy rx ry'.split(' '));\n\n  /**\n   * Returns {@link fabric.Ellipse} instance from an SVG element\n   * @static\n   * @memberOf fabric.Ellipse\n   * @param {SVGElement} element Element to parse\n   * @param {Function} [callback] Options callback invoked after parsing is finished\n   * @return {fabric.Ellipse}\n   */\n  fabric.Ellipse.fromElement = function(element, callback) {\n\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES);\n\n    parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.rx;\n    parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.ry;\n    callback(new fabric.Ellipse(parsedAttributes));\n  };\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns {@link fabric.Ellipse} instance from an object representation\n   * @static\n   * @memberOf fabric.Ellipse\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] invoked with new instance as first argument\n   * @return {fabric.Ellipse}\n   */\n  fabric.Ellipse.fromObject = function(object, callback) {\n    return fabric.Object._fromObject('Ellipse', object, callback);\n  };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { }),\n      extend = fabric.util.object.extend;\n\n  if (fabric.Rect) {\n    fabric.warn('fabric.Rect is already defined');\n    return;\n  }\n\n  /**\n   * Rectangle class\n   * @class fabric.Rect\n   * @extends fabric.Object\n   * @return {fabric.Rect} thisArg\n   * @see {@link fabric.Rect#initialize} for constructor definition\n   */\n  fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ {\n\n    /**\n     * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})\n     * as well as for history (undo/redo) purposes\n     * @type Array\n     */\n    stateProperties: fabric.Object.prototype.stateProperties.concat('rx', 'ry'),\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'rect',\n\n    /**\n     * Horizontal border radius\n     * @type Number\n     * @default\n     */\n    rx:   0,\n\n    /**\n     * Vertical border radius\n     * @type Number\n     * @default\n     */\n    ry:   0,\n\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('rx', 'ry'),\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     * @return {Object} thisArg\n     */\n    initialize: function(options) {\n      this.callSuper('initialize', options);\n      this._initRxRy();\n    },\n\n    /**\n     * Initializes rx/ry attributes\n     * @private\n     */\n    _initRxRy: function() {\n      if (this.rx && !this.ry) {\n        this.ry = this.rx;\n      }\n      else if (this.ry && !this.rx) {\n        this.rx = this.ry;\n      }\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function(ctx) {\n\n      // 1x1 case (used in spray brush) optimization was removed because\n      // with caching and higher zoom level this makes more damage than help\n\n      var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0,\n          ry = this.ry ? Math.min(this.ry, this.height / 2) : 0,\n          w = this.width,\n          h = this.height,\n          x = -this.width / 2,\n          y = -this.height / 2,\n          isRounded = rx !== 0 || ry !== 0,\n          /* \"magic number\" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */\n          k = 1 - 0.5522847498;\n      ctx.beginPath();\n\n      ctx.moveTo(x + rx, y);\n\n      ctx.lineTo(x + w - rx, y);\n      isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry);\n\n      ctx.lineTo(x + w, y + h - ry);\n      isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h);\n\n      ctx.lineTo(x + rx, y + h);\n      isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry);\n\n      ctx.lineTo(x, y + ry);\n      isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y);\n\n      ctx.closePath();\n\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderDashedStroke: function(ctx) {\n      var x = -this.width / 2,\n          y = -this.height / 2,\n          w = this.width,\n          h = this.height;\n\n      ctx.beginPath();\n      fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);\n      ctx.closePath();\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function(propertiesToInclude) {\n      return this.callSuper('toObject', ['rx', 'ry'].concat(propertiesToInclude));\n    },\n\n    /* _TO_SVG_START_ */\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function() {\n      var x = -this.width / 2, y = -this.height / 2;\n      return [\n        '<rect ', 'COMMON_PARTS',\n        'x=\"', x, '\" y=\"', y,\n        '\" rx=\"', this.rx, '\" ry=\"', this.ry,\n        '\" width=\"', this.width, '\" height=\"', this.height,\n        '\" />\\n'\n      ];\n    },\n    /* _TO_SVG_END_ */\n  });\n\n  /* _FROM_SVG_START_ */\n  /**\n   * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`)\n   * @static\n   * @memberOf fabric.Rect\n   * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement\n   */\n  fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' '));\n\n  /**\n   * Returns {@link fabric.Rect} instance from an SVG element\n   * @static\n   * @memberOf fabric.Rect\n   * @param {SVGElement} element Element to parse\n   * @param {Function} callback callback function invoked after parsing\n   * @param {Object} [options] Options object\n   */\n  fabric.Rect.fromElement = function(element, callback, options) {\n    if (!element) {\n      return callback(null);\n    }\n    options = options || { };\n\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);\n    parsedAttributes.left = parsedAttributes.left || 0;\n    parsedAttributes.top  = parsedAttributes.top  || 0;\n    parsedAttributes.height  = parsedAttributes.height || 0;\n    parsedAttributes.width  = parsedAttributes.width || 0;\n    var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));\n    rect.visible = rect.visible && rect.width > 0 && rect.height > 0;\n    callback(rect);\n  };\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns {@link fabric.Rect} instance from an object representation\n   * @static\n   * @memberOf fabric.Rect\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] Callback to invoke when an fabric.Rect instance is created\n   */\n  fabric.Rect.fromObject = function(object, callback) {\n    return fabric.Object._fromObject('Rect', object, callback);\n  };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { }),\n      extend = fabric.util.object.extend,\n      min = fabric.util.array.min,\n      max = fabric.util.array.max,\n      toFixed = fabric.util.toFixed;\n\n  if (fabric.Polyline) {\n    fabric.warn('fabric.Polyline is already defined');\n    return;\n  }\n\n  /**\n   * Polyline class\n   * @class fabric.Polyline\n   * @extends fabric.Object\n   * @see {@link fabric.Polyline#initialize} for constructor definition\n   */\n  fabric.Polyline = fabric.util.createClass(fabric.Object, /** @lends fabric.Polyline.prototype */ {\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'polyline',\n\n    /**\n     * Points array\n     * @type Array\n     * @default\n     */\n    points: null,\n\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('points'),\n\n    /**\n     * Constructor\n     * @param {Array} points Array of points (where each point is an object with x and y)\n     * @param {Object} [options] Options object\n     * @return {fabric.Polyline} thisArg\n     * @example\n     * var poly = new fabric.Polyline([\n     *     { x: 10, y: 10 },\n     *     { x: 50, y: 30 },\n     *     { x: 40, y: 70 },\n     *     { x: 60, y: 50 },\n     *     { x: 100, y: 150 },\n     *     { x: 40, y: 100 }\n     *   ], {\n     *   stroke: 'red',\n     *   left: 100,\n     *   top: 100\n     * });\n     */\n    initialize: function(points, options) {\n      options = options || {};\n      this.points = points || [];\n      this.callSuper('initialize', options);\n      this._setPositionDimensions(options);\n    },\n\n    _setPositionDimensions: function(options) {\n      var calcDim = this._calcDimensions(options), correctLeftTop;\n      this.width = calcDim.width;\n      this.height = calcDim.height;\n      if (!options.fromSVG) {\n        correctLeftTop = this.translateToGivenOrigin(\n          { x: calcDim.left - this.strokeWidth / 2, y: calcDim.top - this.strokeWidth / 2 },\n          'left',\n          'top',\n          this.originX,\n          this.originY\n        );\n      }\n      if (typeof options.left === 'undefined') {\n        this.left = options.fromSVG ? calcDim.left : correctLeftTop.x;\n      }\n      if (typeof options.top === 'undefined') {\n        this.top = options.fromSVG ? calcDim.top : correctLeftTop.y;\n      }\n      this.pathOffset = {\n        x: calcDim.left + this.width / 2,\n        y: calcDim.top + this.height / 2\n      };\n    },\n\n    /**\n     * Calculate the polygon min and max point from points array,\n     * returning an object with left, top, widht, height to measure the\n     * polygon size\n     * @return {Object} object.left X coordinate of the polygon leftmost point\n     * @return {Object} object.top Y coordinate of the polygon topmost point\n     * @return {Object} object.width distance between X coordinates of the polygon leftmost and rightmost point\n     * @return {Object} object.height distance between Y coordinates of the polygon topmost and bottommost point\n     * @private\n     */\n    _calcDimensions: function() {\n\n      var points = this.points,\n          minX = min(points, 'x') || 0,\n          minY = min(points, 'y') || 0,\n          maxX = max(points, 'x') || 0,\n          maxY = max(points, 'y') || 0,\n          width = (maxX - minX),\n          height = (maxY - minY);\n\n      return {\n        left: minX,\n        top: minY,\n        width: width,\n        height: height\n      };\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function(propertiesToInclude) {\n      return extend(this.callSuper('toObject', propertiesToInclude), {\n        points: this.points.concat()\n      });\n    },\n\n    /* _TO_SVG_START_ */\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function() {\n      var points = [], diffX = this.pathOffset.x, diffY = this.pathOffset.y,\n          NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n\n      for (var i = 0, len = this.points.length; i < len; i++) {\n        points.push(\n          toFixed(this.points[i].x - diffX, NUM_FRACTION_DIGITS), ',',\n          toFixed(this.points[i].y - diffY, NUM_FRACTION_DIGITS), ' '\n        );\n      }\n      return [\n        '<' + this.type + ' ', 'COMMON_PARTS',\n        'points=\"', points.join(''),\n        '\" />\\n'\n      ];\n    },\n    /* _TO_SVG_END_ */\n\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    commonRender: function(ctx) {\n      var point, len = this.points.length,\n          x = this.pathOffset.x,\n          y = this.pathOffset.y;\n\n      if (!len || isNaN(this.points[len - 1].y)) {\n        // do not draw if no points or odd points\n        // NaN comes from parseFloat of a empty string in parser\n        return false;\n      }\n      ctx.beginPath();\n      ctx.moveTo(this.points[0].x - x, this.points[0].y - y);\n      for (var i = 0; i < len; i++) {\n        point = this.points[i];\n        ctx.lineTo(point.x - x, point.y - y);\n      }\n      return true;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function(ctx) {\n      if (!this.commonRender(ctx)) {\n        return;\n      }\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderDashedStroke: function(ctx) {\n      var p1, p2;\n\n      ctx.beginPath();\n      for (var i = 0, len = this.points.length; i < len; i++) {\n        p1 = this.points[i];\n        p2 = this.points[i + 1] || p1;\n        fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray);\n      }\n    },\n\n    /**\n     * Returns complexity of an instance\n     * @return {Number} complexity of this instance\n     */\n    complexity: function() {\n      return this.get('points').length;\n    }\n  });\n\n  /* _FROM_SVG_START_ */\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Polyline.fromElement})\n   * @static\n   * @memberOf fabric.Polyline\n   * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement\n   */\n  fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat();\n\n  /**\n   * Returns fabric.Polyline instance from an SVG element\n   * @static\n   * @memberOf fabric.Polyline\n   * @param {SVGElement} element Element to parser\n   * @param {Function} callback callback function invoked after parsing\n   * @param {Object} [options] Options object\n   */\n  fabric.Polyline.fromElementGenerator = function(_class) {\n    return function(element, callback, options) {\n      if (!element) {\n        return callback(null);\n      }\n      options || (options = { });\n\n      var points = fabric.parsePointsAttribute(element.getAttribute('points')),\n          parsedAttributes = fabric.parseAttributes(element, fabric[_class].ATTRIBUTE_NAMES);\n      parsedAttributes.fromSVG = true;\n      callback(new fabric[_class](points, extend(parsedAttributes, options)));\n    };\n  };\n\n  fabric.Polyline.fromElement = fabric.Polyline.fromElementGenerator('Polyline');\n\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns fabric.Polyline instance from an object representation\n   * @static\n   * @memberOf fabric.Polyline\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\n   */\n  fabric.Polyline.fromObject = function(object, callback) {\n    return fabric.Object._fromObject('Polyline', object, callback, 'points');\n  };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { });\n\n  if (fabric.Polygon) {\n    fabric.warn('fabric.Polygon is already defined');\n    return;\n  }\n\n  /**\n   * Polygon class\n   * @class fabric.Polygon\n   * @extends fabric.Polyline\n   * @see {@link fabric.Polygon#initialize} for constructor definition\n   */\n  fabric.Polygon = fabric.util.createClass(fabric.Polyline, /** @lends fabric.Polygon.prototype */ {\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'polygon',\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function(ctx) {\n      if (!this.commonRender(ctx)) {\n        return;\n      }\n      ctx.closePath();\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderDashedStroke: function(ctx) {\n      this.callSuper('_renderDashedStroke', ctx);\n      ctx.closePath();\n    },\n  });\n\n  /* _FROM_SVG_START_ */\n  /**\n   * List of attribute names to account for when parsing SVG element (used by `fabric.Polygon.fromElement`)\n   * @static\n   * @memberOf fabric.Polygon\n   * @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement\n   */\n  fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat();\n\n  /**\n   * Returns {@link fabric.Polygon} instance from an SVG element\n   * @static\n   * @memberOf fabric.Polygon\n   * @param {SVGElement} element Element to parse\n   * @param {Function} callback callback function invoked after parsing\n   * @param {Object} [options] Options object\n   */\n  fabric.Polygon.fromElement = fabric.Polyline.fromElementGenerator('Polygon');\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns fabric.Polygon instance from an object representation\n   * @static\n   * @memberOf fabric.Polygon\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\n   */\n  fabric.Polygon.fromObject = function(object, callback) {\n    return fabric.Object._fromObject('Polygon', object, callback, 'points');\n  };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { }),\n      min = fabric.util.array.min,\n      max = fabric.util.array.max,\n      extend = fabric.util.object.extend,\n      _toString = Object.prototype.toString,\n      toFixed = fabric.util.toFixed;\n\n  if (fabric.Path) {\n    fabric.warn('fabric.Path is already defined');\n    return;\n  }\n\n  /**\n   * Path class\n   * @class fabric.Path\n   * @extends fabric.Object\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#path_and_pathgroup}\n   * @see {@link fabric.Path#initialize} for constructor definition\n   */\n  fabric.Path = fabric.util.createClass(fabric.Object, /** @lends fabric.Path.prototype */ {\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'path',\n\n    /**\n     * Array of path points\n     * @type Array\n     * @default\n     */\n    path: null,\n\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('path', 'fillRule'),\n\n    stateProperties: fabric.Object.prototype.stateProperties.concat('path'),\n\n    /**\n     * Constructor\n     * @param {Array|String} path Path data (sequence of coordinates and corresponding \"command\" tokens)\n     * @param {Object} [options] Options object\n     * @return {fabric.Path} thisArg\n     */\n    initialize: function(path, options) {\n      options = options || { };\n      this.callSuper('initialize', options);\n      if (!path) {\n        path = [];\n      }\n\n      var fromArray = _toString.call(path) === '[object Array]';\n\n      this.path = fromArray\n        ? fabric.util.makePathSimpler(path)\n\n        : fabric.util.makePathSimpler(\n          fabric.util.parsePath(path)\n        );\n\n      if (!this.path) {\n        return;\n      }\n      fabric.Polyline.prototype._setPositionDimensions.call(this, options);\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx context to render path on\n     */\n    _renderPathCommands: function(ctx) {\n      var current, // current instruction\n          subpathStartX = 0,\n          subpathStartY = 0,\n          x = 0, // current x\n          y = 0, // current y\n          controlX = 0, // current control point x\n          controlY = 0, // current control point y\n          l = -this.pathOffset.x,\n          t = -this.pathOffset.y;\n\n      ctx.beginPath();\n\n      for (var i = 0, len = this.path.length; i < len; ++i) {\n\n        current = this.path[i];\n\n        switch (current[0]) { // first letter\n\n          case 'L': // lineto, absolute\n            x = current[1];\n            y = current[2];\n            ctx.lineTo(x + l, y + t);\n            break;\n\n          case 'M': // moveTo, absolute\n            x = current[1];\n            y = current[2];\n            subpathStartX = x;\n            subpathStartY = y;\n            ctx.moveTo(x + l, y + t);\n            break;\n\n          case 'C': // bezierCurveTo, absolute\n            x = current[5];\n            y = current[6];\n            controlX = current[3];\n            controlY = current[4];\n            ctx.bezierCurveTo(\n              current[1] + l,\n              current[2] + t,\n              controlX + l,\n              controlY + t,\n              x + l,\n              y + t\n            );\n            break;\n\n          case 'Q': // quadraticCurveTo, absolute\n            ctx.quadraticCurveTo(\n              current[1] + l,\n              current[2] + t,\n              current[3] + l,\n              current[4] + t\n            );\n            x = current[3];\n            y = current[4];\n            controlX = current[1];\n            controlY = current[2];\n            break;\n\n          case 'z':\n          case 'Z':\n            x = subpathStartX;\n            y = subpathStartY;\n            ctx.closePath();\n            break;\n        }\n      }\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx context to render path on\n     */\n    _render: function(ctx) {\n      this._renderPathCommands(ctx);\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * Returns string representation of an instance\n     * @return {String} string representation of an instance\n     */\n    toString: function() {\n      return '#<fabric.Path (' + this.complexity() +\n        '): { \"top\": ' + this.top + ', \"left\": ' + this.left + ' }>';\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function(propertiesToInclude) {\n      return extend(this.callSuper('toObject', propertiesToInclude), {\n        path: this.path.map(function(item) { return item.slice(); }),\n      });\n    },\n\n    /**\n     * Returns dataless object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toDatalessObject: function(propertiesToInclude) {\n      var o = this.toObject(['sourcePath'].concat(propertiesToInclude));\n      if (o.sourcePath) {\n        delete o.path;\n      }\n      return o;\n    },\n\n    /* _TO_SVG_START_ */\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function() {\n      var path = this.path.map(function(path) {\n        return path.join(' ');\n      }).join(' ');\n      return [\n        '<path ', 'COMMON_PARTS',\n        'd=\"', path,\n        '\" stroke-linecap=\"round\" ',\n        '/>\\n'\n      ];\n    },\n\n    _getOffsetTransform: function() {\n      var digits = fabric.Object.NUM_FRACTION_DIGITS;\n      return ' translate(' + toFixed(-this.pathOffset.x, digits) + ', ' +\n          toFixed(-this.pathOffset.y, digits) + ')';\n    },\n\n    /**\n     * Returns svg clipPath representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    toClipPathSVG: function(reviver) {\n      var additionalTransform = this._getOffsetTransform();\n      return '\\t' + this._createBaseClipPathSVGMarkup(\n        this._toSVG(), { reviver: reviver, additionalTransform: additionalTransform }\n      );\n    },\n\n    /**\n     * Returns svg representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    toSVG: function(reviver) {\n      var additionalTransform = this._getOffsetTransform();\n      return this._createBaseSVGMarkup(this._toSVG(), { reviver: reviver, additionalTransform: additionalTransform  });\n    },\n    /* _TO_SVG_END_ */\n\n    /**\n     * Returns number representation of an instance complexity\n     * @return {Number} complexity of this instance\n     */\n    complexity: function() {\n      return this.path.length;\n    },\n\n    /**\n     * @private\n     */\n    _calcDimensions: function() {\n\n      var aX = [],\n          aY = [],\n          current, // current instruction\n          subpathStartX = 0,\n          subpathStartY = 0,\n          x = 0, // current x\n          y = 0, // current y\n          bounds;\n\n      for (var i = 0, len = this.path.length; i < len; ++i) {\n\n        current = this.path[i];\n\n        switch (current[0]) { // first letter\n\n          case 'L': // lineto, absolute\n            x = current[1];\n            y = current[2];\n            bounds = [];\n            break;\n\n          case 'M': // moveTo, absolute\n            x = current[1];\n            y = current[2];\n            subpathStartX = x;\n            subpathStartY = y;\n            bounds = [];\n            break;\n\n          case 'C': // bezierCurveTo, absolute\n            bounds = fabric.util.getBoundsOfCurve(x, y,\n              current[1],\n              current[2],\n              current[3],\n              current[4],\n              current[5],\n              current[6]\n            );\n            x = current[5];\n            y = current[6];\n            break;\n\n          case 'Q': // quadraticCurveTo, absolute\n            bounds = fabric.util.getBoundsOfCurve(x, y,\n              current[1],\n              current[2],\n              current[1],\n              current[2],\n              current[3],\n              current[4]\n            );\n            x = current[3];\n            y = current[4];\n            break;\n\n          case 'z':\n          case 'Z':\n            x = subpathStartX;\n            y = subpathStartY;\n            break;\n        }\n        bounds.forEach(function (point) {\n          aX.push(point.x);\n          aY.push(point.y);\n        });\n        aX.push(x);\n        aY.push(y);\n      }\n\n      var minX = min(aX) || 0,\n          minY = min(aY) || 0,\n          maxX = max(aX) || 0,\n          maxY = max(aY) || 0,\n          deltaX = maxX - minX,\n          deltaY = maxY - minY;\n\n      return {\n        left: minX,\n        top: minY,\n        width: deltaX,\n        height: deltaY\n      };\n    }\n  });\n\n  /**\n   * Creates an instance of fabric.Path from an object\n   * @static\n   * @memberOf fabric.Path\n   * @param {Object} object\n   * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\n   */\n  fabric.Path.fromObject = function(object, callback) {\n    if (typeof object.sourcePath === 'string') {\n      var pathUrl = object.sourcePath;\n      fabric.loadSVGFromURL(pathUrl, function (elements) {\n        var path = elements[0];\n        path.setOptions(object);\n        callback && callback(path);\n      });\n    }\n    else {\n      fabric.Object._fromObject('Path', object, callback, 'path');\n    }\n  };\n\n  /* _FROM_SVG_START_ */\n  /**\n   * List of attribute names to account for when parsing SVG element (used by `fabric.Path.fromElement`)\n   * @static\n   * @memberOf fabric.Path\n   * @see http://www.w3.org/TR/SVG/paths.html#PathElement\n   */\n  fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(['d']);\n\n  /**\n   * Creates an instance of fabric.Path from an SVG <path> element\n   * @static\n   * @memberOf fabric.Path\n   * @param {SVGElement} element to parse\n   * @param {Function} callback Callback to invoke when an fabric.Path instance is created\n   * @param {Object} [options] Options object\n   * @param {Function} [callback] Options callback invoked after parsing is finished\n   */\n  fabric.Path.fromElement = function(element, callback, options) {\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES);\n    parsedAttributes.fromSVG = true;\n    callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options)));\n  };\n  /* _FROM_SVG_END_ */\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { }),\n      min = fabric.util.array.min,\n      max = fabric.util.array.max;\n\n  if (fabric.Group) {\n    return;\n  }\n\n  /**\n   * Group class\n   * @class fabric.Group\n   * @extends fabric.Object\n   * @mixes fabric.Collection\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#groups}\n   * @see {@link fabric.Group#initialize} for constructor definition\n   */\n  fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection, /** @lends fabric.Group.prototype */ {\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'group',\n\n    /**\n     * Width of stroke\n     * @type Number\n     * @default\n     */\n    strokeWidth: 0,\n\n    /**\n     * Indicates if click, mouseover, mouseout events & hoverCursor should also check for subtargets\n     * @type Boolean\n     * @default\n     */\n    subTargetCheck: false,\n\n    /**\n     * Groups are container, do not render anything on theyr own, ence no cache properties\n     * @type Array\n     * @default\n     */\n    cacheProperties: [],\n\n    /**\n     * setOnGroup is a method used for TextBox that is no more used since 2.0.0 The behavior is still\n     * available setting this boolean to true.\n     * @type Boolean\n     * @since 2.0.0\n     * @default\n     */\n    useSetOnGroup: false,\n\n    /**\n     * Constructor\n     * @param {Object} objects Group objects\n     * @param {Object} [options] Options object\n     * @param {Boolean} [isAlreadyGrouped] if true, objects have been grouped already.\n     * @return {Object} thisArg\n     */\n    initialize: function(objects, options, isAlreadyGrouped) {\n      options = options || {};\n      this._objects = [];\n      // if objects enclosed in a group have been grouped already,\n      // we cannot change properties of objects.\n      // Thus we need to set options to group without objects,\n      isAlreadyGrouped && this.callSuper('initialize', options);\n      this._objects = objects || [];\n      for (var i = this._objects.length; i--; ) {\n        this._objects[i].group = this;\n      }\n\n      if (!isAlreadyGrouped) {\n        var center = options && options.centerPoint;\n        // we want to set origins before calculating the bounding box.\n        // so that the topleft can be set with that in mind.\n        // if specific top and left are passed, are overwritten later\n        // with the callSuper('initialize', options)\n        if (options.originX !== undefined) {\n          this.originX = options.originX;\n        }\n        if (options.originY !== undefined) {\n          this.originY = options.originY;\n        }\n        // if coming from svg i do not want to calc bounds.\n        // i assume width and height are passed along options\n        center || this._calcBounds();\n        this._updateObjectsCoords(center);\n        delete options.centerPoint;\n        this.callSuper('initialize', options);\n      }\n      else {\n        this._updateObjectsACoords();\n      }\n\n      this.setCoords();\n    },\n\n    /**\n     * @private\n     */\n    _updateObjectsACoords: function() {\n      var skipControls = true;\n      for (var i = this._objects.length; i--; ){\n        this._objects[i].setCoords(skipControls);\n      }\n    },\n\n    /**\n     * @private\n     * @param {Boolean} [skipCoordsChange] if true, coordinates of objects enclosed in a group do not change\n     */\n    _updateObjectsCoords: function(center) {\n      var center = center || this.getCenterPoint();\n      for (var i = this._objects.length; i--; ){\n        this._updateObjectCoords(this._objects[i], center);\n      }\n    },\n\n    /**\n     * @private\n     * @param {Object} object\n     * @param {fabric.Point} center, current center of group.\n     */\n    _updateObjectCoords: function(object, center) {\n      var objectLeft = object.left,\n          objectTop = object.top,\n          skipControls = true;\n\n      object.set({\n        left: objectLeft - center.x,\n        top: objectTop - center.y\n      });\n      object.group = this;\n      object.setCoords(skipControls);\n    },\n\n    /**\n     * Returns string represenation of a group\n     * @return {String}\n     */\n    toString: function() {\n      return '#<fabric.Group: (' + this.complexity() + ')>';\n    },\n\n    /**\n     * Adds an object to a group; Then recalculates group's dimension, position.\n     * @param {Object} object\n     * @return {fabric.Group} thisArg\n     * @chainable\n     */\n    addWithUpdate: function(object) {\n      this._restoreObjectsState();\n      fabric.util.resetObjectTransform(this);\n      if (object) {\n        this._objects.push(object);\n        object.group = this;\n        object._set('canvas', this.canvas);\n      }\n      this._calcBounds();\n      this._updateObjectsCoords();\n      this.setCoords();\n      this.dirty = true;\n      return this;\n    },\n\n    /**\n     * Removes an object from a group; Then recalculates group's dimension, position.\n     * @param {Object} object\n     * @return {fabric.Group} thisArg\n     * @chainable\n     */\n    removeWithUpdate: function(object) {\n      this._restoreObjectsState();\n      fabric.util.resetObjectTransform(this);\n\n      this.remove(object);\n      this._calcBounds();\n      this._updateObjectsCoords();\n      this.setCoords();\n      this.dirty = true;\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _onObjectAdded: function(object) {\n      this.dirty = true;\n      object.group = this;\n      object._set('canvas', this.canvas);\n    },\n\n    /**\n     * @private\n     */\n    _onObjectRemoved: function(object) {\n      this.dirty = true;\n      delete object.group;\n    },\n\n    /**\n     * @private\n     */\n    _set: function(key, value) {\n      var i = this._objects.length;\n      if (this.useSetOnGroup) {\n        while (i--) {\n          this._objects[i].setOnGroup(key, value);\n        }\n      }\n      if (key === 'canvas') {\n        while (i--) {\n          this._objects[i]._set(key, value);\n        }\n      }\n      fabric.Object.prototype._set.call(this, key, value);\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function(propertiesToInclude) {\n      var _includeDefaultValues = this.includeDefaultValues;\n      var objsToObject = this._objects.map(function(obj) {\n        var originalDefaults = obj.includeDefaultValues;\n        obj.includeDefaultValues = _includeDefaultValues;\n        var _obj = obj.toObject(propertiesToInclude);\n        obj.includeDefaultValues = originalDefaults;\n        return _obj;\n      });\n      var obj = fabric.Object.prototype.toObject.call(this, propertiesToInclude);\n      obj.objects = objsToObject;\n      return obj;\n    },\n\n    /**\n     * Returns object representation of an instance, in dataless mode.\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toDatalessObject: function(propertiesToInclude) {\n      var objsToObject, sourcePath = this.sourcePath;\n      if (sourcePath) {\n        objsToObject = sourcePath;\n      }\n      else {\n        var _includeDefaultValues = this.includeDefaultValues;\n        objsToObject = this._objects.map(function(obj) {\n          var originalDefaults = obj.includeDefaultValues;\n          obj.includeDefaultValues = _includeDefaultValues;\n          var _obj = obj.toDatalessObject(propertiesToInclude);\n          obj.includeDefaultValues = originalDefaults;\n          return _obj;\n        });\n      }\n      var obj = fabric.Object.prototype.toDatalessObject.call(this, propertiesToInclude);\n      obj.objects = objsToObject;\n      return obj;\n    },\n\n    /**\n     * Renders instance on a given context\n     * @param {CanvasRenderingContext2D} ctx context to render instance on\n     */\n    render: function(ctx) {\n      this._transformDone = true;\n      this.callSuper('render', ctx);\n      this._transformDone = false;\n    },\n\n    /**\n     * Decide if the object should cache or not. Create its own cache level\n     * needsItsOwnCache should be used when the object drawing method requires\n     * a cache step. None of the fabric classes requires it.\n     * Generally you do not cache objects in groups because the group is already cached.\n     * @return {Boolean}\n     */\n    shouldCache: function() {\n      var ownCache = fabric.Object.prototype.shouldCache.call(this);\n      if (ownCache) {\n        for (var i = 0, len = this._objects.length; i < len; i++) {\n          if (this._objects[i].willDrawShadow()) {\n            this.ownCaching = false;\n            return false;\n          }\n        }\n      }\n      return ownCache;\n    },\n\n    /**\n     * Check if this object or a child object will cast a shadow\n     * @return {Boolean}\n     */\n    willDrawShadow: function() {\n      if (fabric.Object.prototype.willDrawShadow.call(this)) {\n        return true;\n      }\n      for (var i = 0, len = this._objects.length; i < len; i++) {\n        if (this._objects[i].willDrawShadow()) {\n          return true;\n        }\n      }\n      return false;\n    },\n\n    /**\n     * Check if this group or its parent group are caching, recursively up\n     * @return {Boolean}\n     */\n    isOnACache: function() {\n      return this.ownCaching || (this.group && this.group.isOnACache());\n    },\n\n    /**\n     * Execute the drawing operation for an object on a specified context\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    drawObject: function(ctx) {\n      for (var i = 0, len = this._objects.length; i < len; i++) {\n        this._objects[i].render(ctx);\n      }\n      this._drawClipPath(ctx);\n    },\n\n    /**\n     * Check if cache is dirty\n     */\n    isCacheDirty: function(skipCanvas) {\n      if (this.callSuper('isCacheDirty', skipCanvas)) {\n        return true;\n      }\n      if (!this.statefullCache) {\n        return false;\n      }\n      for (var i = 0, len = this._objects.length; i < len; i++) {\n        if (this._objects[i].isCacheDirty(true)) {\n          if (this._cacheCanvas) {\n            // if this group has not a cache canvas there is nothing to clean\n            var x = this.cacheWidth / this.zoomX, y = this.cacheHeight / this.zoomY;\n            this._cacheContext.clearRect(-x / 2, -y / 2, x, y);\n          }\n          return true;\n        }\n      }\n      return false;\n    },\n\n    /**\n     * Retores original state of each of group objects (original state is that which was before group was created).\n     * @private\n     * @return {fabric.Group} thisArg\n     * @chainable\n     */\n    _restoreObjectsState: function() {\n      this._objects.forEach(this._restoreObjectState, this);\n      return this;\n    },\n\n    /**\n     * Realises the transform from this group onto the supplied object\n     * i.e. it tells you what would happen if the supplied object was in\n     * the group, and then the group was destroyed. It mutates the supplied\n     * object.\n     * @param {fabric.Object} object\n     * @return {fabric.Object} transformedObject\n     */\n    realizeTransform: function(object) {\n      var matrix = object.calcTransformMatrix(),\n          options = fabric.util.qrDecompose(matrix),\n          center = new fabric.Point(options.translateX, options.translateY);\n      object.flipX = false;\n      object.flipY = false;\n      object.set('scaleX', options.scaleX);\n      object.set('scaleY', options.scaleY);\n      object.skewX = options.skewX;\n      object.skewY = options.skewY;\n      object.angle = options.angle;\n      object.setPositionByOrigin(center, 'center', 'center');\n      return object;\n    },\n\n    /**\n     * Restores original state of a specified object in group\n     * @private\n     * @param {fabric.Object} object\n     * @return {fabric.Group} thisArg\n     */\n    _restoreObjectState: function(object) {\n      this.realizeTransform(object);\n      delete object.group;\n      object.setCoords();\n      return this;\n    },\n\n    /**\n     * Destroys a group (restoring state of its objects)\n     * @return {fabric.Group} thisArg\n     * @chainable\n     */\n    destroy: function() {\n      // when group is destroyed objects needs to get a repaint to be eventually\n      // displayed on canvas.\n      this._objects.forEach(function(object) {\n        object.set('dirty', true);\n      });\n      return this._restoreObjectsState();\n    },\n\n    /**\n     * make a group an active selection, remove the group from canvas\n     * the group has to be on canvas for this to work.\n     * @return {fabric.ActiveSelection} thisArg\n     * @chainable\n     */\n    toActiveSelection: function() {\n      if (!this.canvas) {\n        return;\n      }\n      var objects = this._objects, canvas = this.canvas;\n      this._objects = [];\n      var options = this.toObject();\n      delete options.objects;\n      var activeSelection = new fabric.ActiveSelection([]);\n      activeSelection.set(options);\n      activeSelection.type = 'activeSelection';\n      canvas.remove(this);\n      objects.forEach(function(object) {\n        object.group = activeSelection;\n        object.dirty = true;\n        canvas.add(object);\n      });\n      activeSelection.canvas = canvas;\n      activeSelection._objects = objects;\n      canvas._activeObject = activeSelection;\n      activeSelection.setCoords();\n      return activeSelection;\n    },\n\n    /**\n     * Destroys a group (restoring state of its objects)\n     * @return {fabric.Group} thisArg\n     * @chainable\n     */\n    ungroupOnCanvas: function() {\n      return this._restoreObjectsState();\n    },\n\n    /**\n     * Sets coordinates of all objects inside group\n     * @return {fabric.Group} thisArg\n     * @chainable\n     */\n    setObjectsCoords: function() {\n      var skipControls = true;\n      this.forEachObject(function(object) {\n        object.setCoords(skipControls);\n      });\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _calcBounds: function(onlyWidthHeight) {\n      var aX = [],\n          aY = [],\n          o, prop,\n          props = ['tr', 'br', 'bl', 'tl'],\n          i = 0, iLen = this._objects.length,\n          j, jLen = props.length;\n\n      for ( ; i < iLen; ++i) {\n        o = this._objects[i];\n        o.aCoords = o.calcACoords();\n        for (j = 0; j < jLen; j++) {\n          prop = props[j];\n          aX.push(o.aCoords[prop].x);\n          aY.push(o.aCoords[prop].y);\n        }\n      }\n\n      this._getBounds(aX, aY, onlyWidthHeight);\n    },\n\n    /**\n     * @private\n     */\n    _getBounds: function(aX, aY, onlyWidthHeight) {\n      var minXY = new fabric.Point(min(aX), min(aY)),\n          maxXY = new fabric.Point(max(aX), max(aY)),\n          top = minXY.y || 0, left = minXY.x || 0,\n          width = (maxXY.x - minXY.x) || 0,\n          height = (maxXY.y - minXY.y) || 0;\n      this.width = width;\n      this.height = height;\n      if (!onlyWidthHeight) {\n        // the bounding box always finds the topleft most corner.\n        // whatever is the group origin, we set up here the left/top position.\n        this.setPositionByOrigin({ x: left, y: top }, 'left', 'top');\n      }\n    },\n\n    /* _TO_SVG_START_ */\n    /**\n     * Returns svg representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    _toSVG: function(reviver) {\n      var svgString = ['<g ', 'COMMON_PARTS', ' >\\n'];\n\n      for (var i = 0, len = this._objects.length; i < len; i++) {\n        svgString.push('\\t\\t', this._objects[i].toSVG(reviver));\n      }\n      svgString.push('</g>\\n');\n      return svgString;\n    },\n\n    /**\n     * Returns styles-string for svg-export, specific version for group\n     * @return {String}\n     */\n    getSvgStyles: function() {\n      var opacity = typeof this.opacity !== 'undefined' && this.opacity !== 1 ?\n            'opacity: ' + this.opacity + ';' : '',\n          visibility = this.visible ? '' : ' visibility: hidden;';\n      return [\n        opacity,\n        this.getSvgFilter(),\n        visibility\n      ].join('');\n    },\n\n    /**\n     * Returns svg clipPath representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    toClipPathSVG: function(reviver) {\n      var svgString = [];\n\n      for (var i = 0, len = this._objects.length; i < len; i++) {\n        svgString.push('\\t', this._objects[i].toClipPathSVG(reviver));\n      }\n\n      return this._createBaseClipPathSVGMarkup(svgString, { reviver: reviver });\n    },\n    /* _TO_SVG_END_ */\n  });\n\n  /**\n   * Returns {@link fabric.Group} instance from an object representation\n   * @static\n   * @memberOf fabric.Group\n   * @param {Object} object Object to create a group from\n   * @param {Function} [callback] Callback to invoke when an group instance is created\n   */\n  fabric.Group.fromObject = function(object, callback) {\n    var objects = object.objects,\n        options = fabric.util.object.clone(object, true);\n    delete options.objects;\n    if (typeof objects === 'string') {\n      // it has to be an url or something went wrong.\n      fabric.loadSVGFromURL(objects, function (elements) {\n        var group = fabric.util.groupSVGElements(elements, object, objects);\n        group.set(options);\n        callback && callback(group);\n      });\n      return;\n    }\n    fabric.util.enlivenObjects(objects, function(enlivenedObjects) {\n      fabric.util.enlivenObjects([object.clipPath], function(enlivedClipPath) {\n        var options = fabric.util.object.clone(object, true);\n        options.clipPath = enlivedClipPath[0];\n        delete options.objects;\n        callback && callback(new fabric.Group(enlivenedObjects, options, true));\n      });\n    });\n  };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { });\n\n  if (fabric.ActiveSelection) {\n    return;\n  }\n\n  /**\n   * Group class\n   * @class fabric.ActiveSelection\n   * @extends fabric.Group\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#groups}\n   * @see {@link fabric.ActiveSelection#initialize} for constructor definition\n   */\n  fabric.ActiveSelection = fabric.util.createClass(fabric.Group, /** @lends fabric.ActiveSelection.prototype */ {\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'activeSelection',\n\n    /**\n     * Constructor\n     * @param {Object} objects ActiveSelection objects\n     * @param {Object} [options] Options object\n     * @return {Object} thisArg\n     */\n    initialize: function(objects, options) {\n      options = options || {};\n      this._objects = objects || [];\n      for (var i = this._objects.length; i--; ) {\n        this._objects[i].group = this;\n      }\n\n      if (options.originX) {\n        this.originX = options.originX;\n      }\n      if (options.originY) {\n        this.originY = options.originY;\n      }\n      this._calcBounds();\n      this._updateObjectsCoords();\n      fabric.Object.prototype.initialize.call(this, options);\n      this.setCoords();\n    },\n\n    /**\n     * Change te activeSelection to a normal group,\n     * High level function that automatically adds it to canvas as\n     * active object. no events fired.\n     * @since 2.0.0\n     * @return {fabric.Group}\n     */\n    toGroup: function() {\n      var objects = this._objects.concat();\n      this._objects = [];\n      var options = fabric.Object.prototype.toObject.call(this);\n      var newGroup = new fabric.Group([]);\n      delete options.type;\n      newGroup.set(options);\n      objects.forEach(function(object) {\n        object.canvas.remove(object);\n        object.group = newGroup;\n      });\n      newGroup._objects = objects;\n      if (!this.canvas) {\n        return newGroup;\n      }\n      var canvas = this.canvas;\n      canvas.add(newGroup);\n      canvas._activeObject = newGroup;\n      newGroup.setCoords();\n      return newGroup;\n    },\n\n    /**\n     * If returns true, deselection is cancelled.\n     * @since 2.0.0\n     * @return {Boolean} [cancel]\n     */\n    onDeselect: function() {\n      this.destroy();\n      return false;\n    },\n\n    /**\n     * Returns string representation of a group\n     * @return {String}\n     */\n    toString: function() {\n      return '#<fabric.ActiveSelection: (' + this.complexity() + ')>';\n    },\n\n    /**\n     * Decide if the object should cache or not. Create its own cache level\n     * objectCaching is a global flag, wins over everything\n     * needsItsOwnCache should be used when the object drawing method requires\n     * a cache step. None of the fabric classes requires it.\n     * Generally you do not cache objects in groups because the group outside is cached.\n     * @return {Boolean}\n     */\n    shouldCache: function() {\n      return false;\n    },\n\n    /**\n     * Check if this group or its parent group are caching, recursively up\n     * @return {Boolean}\n     */\n    isOnACache: function() {\n      return false;\n    },\n\n    /**\n     * Renders controls and borders for the object\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Object} [styleOverride] properties to override the object style\n     * @param {Object} [childrenOverride] properties to override the children overrides\n     */\n    _renderControls: function(ctx, styleOverride, childrenOverride) {\n      ctx.save();\n      ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n      this.callSuper('_renderControls', ctx, styleOverride);\n      childrenOverride = childrenOverride || { };\n      if (typeof childrenOverride.hasControls === 'undefined') {\n        childrenOverride.hasControls = false;\n      }\n      childrenOverride.forActiveSelection = true;\n      for (var i = 0, len = this._objects.length; i < len; i++) {\n        this._objects[i]._renderControls(ctx, childrenOverride);\n      }\n      ctx.restore();\n    },\n  });\n\n  /**\n   * Returns {@link fabric.ActiveSelection} instance from an object representation\n   * @static\n   * @memberOf fabric.ActiveSelection\n   * @param {Object} object Object to create a group from\n   * @param {Function} [callback] Callback to invoke when an ActiveSelection instance is created\n   */\n  fabric.ActiveSelection.fromObject = function(object, callback) {\n    fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) {\n      delete object.objects;\n      callback && callback(new fabric.ActiveSelection(enlivenedObjects, object, true));\n    });\n  };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var extend = fabric.util.object.extend;\n\n  if (!global.fabric) {\n    global.fabric = { };\n  }\n\n  if (global.fabric.Image) {\n    fabric.warn('fabric.Image is already defined.');\n    return;\n  }\n\n  /**\n   * Image class\n   * @class fabric.Image\n   * @extends fabric.Object\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#images}\n   * @see {@link fabric.Image#initialize} for constructor definition\n   */\n  fabric.Image = fabric.util.createClass(fabric.Object, /** @lends fabric.Image.prototype */ {\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'image',\n\n    /**\n     * Width of a stroke.\n     * For image quality a stroke multiple of 2 gives better results.\n     * @type Number\n     * @default\n     */\n    strokeWidth: 0,\n\n    /**\n     * When calling {@link fabric.Image.getSrc}, return value from element src with `element.getAttribute('src')`.\n     * This allows for relative urls as image src.\n     * @since 2.7.0\n     * @type Boolean\n     * @default\n     */\n    srcFromAttribute: false,\n\n    /**\n     * private\n     * contains last value of scaleX to detect\n     * if the Image got resized after the last Render\n     * @type Number\n     */\n    _lastScaleX: 1,\n\n    /**\n     * private\n     * contains last value of scaleY to detect\n     * if the Image got resized after the last Render\n     * @type Number\n     */\n    _lastScaleY: 1,\n\n    /**\n     * private\n     * contains last value of scaling applied by the apply filter chain\n     * @type Number\n     */\n    _filterScalingX: 1,\n\n    /**\n     * private\n     * contains last value of scaling applied by the apply filter chain\n     * @type Number\n     */\n    _filterScalingY: 1,\n\n    /**\n     * minimum scale factor under which any resizeFilter is triggered to resize the image\n     * 0 will disable the automatic resize. 1 will trigger automatically always.\n     * number bigger than 1 are not implemented yet.\n     * @type Number\n     */\n    minimumScaleTrigger: 0.5,\n\n    /**\n     * List of properties to consider when checking if\n     * state of an object is changed ({@link fabric.Object#hasStateChanged})\n     * as well as for history (undo/redo) purposes\n     * @type Array\n     */\n    stateProperties: fabric.Object.prototype.stateProperties.concat('cropX', 'cropY'),\n\n    /**\n     * key used to retrieve the texture representing this image\n     * @since 2.0.0\n     * @type String\n     * @default\n     */\n    cacheKey: '',\n\n    /**\n     * Image crop in pixels from original image size.\n     * @since 2.0.0\n     * @type Number\n     * @default\n     */\n    cropX: 0,\n\n    /**\n     * Image crop in pixels from original image size.\n     * @since 2.0.0\n     * @type Number\n     * @default\n     */\n    cropY: 0,\n\n    /**\n     * Indicates whether this canvas will use image smoothing when painting this image.\n     * Also influence if the cacheCanvas for this image uses imageSmoothing\n     * @since 4.0.0-beta.11\n     * @type Boolean\n     * @default\n     */\n    imageSmoothing: true,\n\n    /**\n     * Constructor\n     * @param {HTMLImageElement | String} element Image element\n     * @param {Object} [options] Options object\n     * @param {function} [callback] callback function to call after eventual filters applied.\n     * @return {fabric.Image} thisArg\n     */\n    initialize: function(element, options) {\n      options || (options = { });\n      this.filters = [];\n      this.cacheKey = 'texture' + fabric.Object.__uid++;\n      this.callSuper('initialize', options);\n      this._initElement(element, options);\n    },\n\n    /**\n     * Returns image element which this instance if based on\n     * @return {HTMLImageElement} Image element\n     */\n    getElement: function() {\n      return this._element || {};\n    },\n\n    /**\n     * Sets image element for this instance to a specified one.\n     * If filters defined they are applied to new image.\n     * You might need to call `canvas.renderAll` and `object.setCoords` after replacing, to render new image and update controls area.\n     * @param {HTMLImageElement} element\n     * @param {Object} [options] Options object\n     * @return {fabric.Image} thisArg\n     * @chainable\n     */\n    setElement: function(element, options) {\n      this.removeTexture(this.cacheKey);\n      this.removeTexture(this.cacheKey + '_filtered');\n      this._element = element;\n      this._originalElement = element;\n      this._initConfig(options);\n      if (this.filters.length !== 0) {\n        this.applyFilters();\n      }\n      // resizeFilters work on the already filtered copy.\n      // we need to apply resizeFilters AFTER normal filters.\n      // applyResizeFilters is run more often than normal fiters\n      // and is triggered by user interactions rather than dev code\n      if (this.resizeFilter) {\n        this.applyResizeFilters();\n      }\n      return this;\n    },\n\n    /**\n     * Delete a single texture if in webgl mode\n     */\n    removeTexture: function(key) {\n      var backend = fabric.filterBackend;\n      if (backend && backend.evictCachesForKey) {\n        backend.evictCachesForKey(key);\n      }\n    },\n\n    /**\n     * Delete textures, reference to elements and eventually JSDOM cleanup\n     */\n    dispose: function() {\n      this.removeTexture(this.cacheKey);\n      this.removeTexture(this.cacheKey + '_filtered');\n      this._cacheContext = undefined;\n      ['_originalElement', '_element', '_filteredEl', '_cacheCanvas'].forEach((function(element) {\n        fabric.util.cleanUpJsdomNode(this[element]);\n        this[element] = undefined;\n      }).bind(this));\n    },\n\n    /**\n     * Get the crossOrigin value (of the corresponding image element)\n     */\n    getCrossOrigin: function() {\n      return this._originalElement && (this._originalElement.crossOrigin || null);\n    },\n\n    /**\n     * Returns original size of an image\n     * @return {Object} Object with \"width\" and \"height\" properties\n     */\n    getOriginalSize: function() {\n      var element = this.getElement();\n      return {\n        width: element.naturalWidth || element.width,\n        height: element.naturalHeight || element.height\n      };\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _stroke: function(ctx) {\n      if (!this.stroke || this.strokeWidth === 0) {\n        return;\n      }\n      var w = this.width / 2, h = this.height / 2;\n      ctx.beginPath();\n      ctx.moveTo(-w, -h);\n      ctx.lineTo(w, -h);\n      ctx.lineTo(w, h);\n      ctx.lineTo(-w, h);\n      ctx.lineTo(-w, -h);\n      ctx.closePath();\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderDashedStroke: function(ctx) {\n      var x = -this.width / 2,\n          y = -this.height / 2,\n          w = this.width,\n          h = this.height;\n\n      ctx.save();\n      this._setStrokeStyles(ctx, this);\n\n      ctx.beginPath();\n      fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);\n      fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);\n      ctx.closePath();\n      ctx.restore();\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function(propertiesToInclude) {\n      var filters = [];\n\n      this.filters.forEach(function(filterObj) {\n        if (filterObj) {\n          filters.push(filterObj.toObject());\n        }\n      });\n      var object = extend(\n        this.callSuper(\n          'toObject',\n          ['cropX', 'cropY'].concat(propertiesToInclude)\n        ), {\n          src: this.getSrc(),\n          crossOrigin: this.getCrossOrigin(),\n          filters: filters,\n        });\n      if (this.resizeFilter) {\n        object.resizeFilter = this.resizeFilter.toObject();\n      }\n      return object;\n    },\n\n    /**\n     * Returns true if an image has crop applied, inspecting values of cropX,cropY,width,hight.\n     * @return {Boolean}\n     */\n    hasCrop: function() {\n      return this.cropX || this.cropY || this.width < this._element.width || this.height < this._element.height;\n    },\n\n    /* _TO_SVG_START_ */\n    /**\n     * Returns svg representation of an instance\n     * @return {Array} an array of strings with the specific svg representation\n     * of the instance\n     */\n    _toSVG: function() {\n      var svgString = [], imageMarkup = [], strokeSvg, element = this._element,\n          x = -this.width / 2, y = -this.height / 2, clipPath = '', imageRendering = '';\n      if (!element) {\n        return [];\n      }\n      if (this.hasCrop()) {\n        var clipPathId = fabric.Object.__uid++;\n        svgString.push(\n          '<clipPath id=\"imageCrop_' + clipPathId + '\">\\n',\n          '\\t<rect x=\"' + x + '\" y=\"' + y + '\" width=\"' + this.width + '\" height=\"' + this.height + '\" />\\n',\n          '</clipPath>\\n'\n        );\n        clipPath = ' clip-path=\"url(#imageCrop_' + clipPathId + ')\" ';\n      }\n      if (!this.imageSmoothing) {\n        imageRendering = '\" image-rendering=\"optimizeSpeed';\n      }\n      imageMarkup.push('\\t<image ', 'COMMON_PARTS', 'xlink:href=\"', this.getSvgSrc(true),\n        '\" x=\"', x - this.cropX, '\" y=\"', y - this.cropY,\n        // we're essentially moving origin of transformation from top/left corner to the center of the shape\n        // by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left\n        // so that object's center aligns with container's left/top\n        '\" width=\"', element.width || element.naturalWidth,\n        '\" height=\"', element.height || element.height,\n        imageRendering,\n        '\"', clipPath,\n        '></image>\\n');\n\n      if (this.stroke || this.strokeDashArray) {\n        var origFill = this.fill;\n        this.fill = null;\n        strokeSvg = [\n          '\\t<rect ',\n          'x=\"', x, '\" y=\"', y,\n          '\" width=\"', this.width, '\" height=\"', this.height,\n          '\" style=\"', this.getSvgStyles(),\n          '\"/>\\n'\n        ];\n        this.fill = origFill;\n      }\n      if (this.paintFirst !== 'fill') {\n        svgString = svgString.concat(strokeSvg, imageMarkup);\n      }\n      else {\n        svgString = svgString.concat(imageMarkup, strokeSvg);\n      }\n      return svgString;\n    },\n    /* _TO_SVG_END_ */\n\n    /**\n     * Returns source of an image\n     * @param {Boolean} filtered indicates if the src is needed for svg\n     * @return {String} Source of an image\n     */\n    getSrc: function(filtered) {\n      var element = filtered ? this._element : this._originalElement;\n      if (element) {\n        if (element.toDataURL) {\n          return element.toDataURL();\n        }\n\n        if (this.srcFromAttribute) {\n          return element.getAttribute('src');\n        }\n        else {\n          return element.src;\n        }\n      }\n      else {\n        return this.src || '';\n      }\n    },\n\n    /**\n     * Sets source of an image\n     * @param {String} src Source string (URL)\n     * @param {Function} [callback] Callback is invoked when image has been loaded (and all filters have been applied)\n     * @param {Object} [options] Options object\n     * @param {String} [options.crossOrigin] crossOrigin value (one of \"\", \"anonymous\", \"use-credentials\")\n     * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes\n     * @return {fabric.Image} thisArg\n     * @chainable\n     */\n    setSrc: function(src, callback, options) {\n      fabric.util.loadImage(src, function(img, isError) {\n        this.setElement(img, options);\n        this._setWidthHeight();\n        callback && callback(this, isError);\n      }, this, options && options.crossOrigin);\n      return this;\n    },\n\n    /**\n     * Returns string representation of an instance\n     * @return {String} String representation of an instance\n     */\n    toString: function() {\n      return '#<fabric.Image: { src: \"' + this.getSrc() + '\" }>';\n    },\n\n    applyResizeFilters: function() {\n      var filter = this.resizeFilter,\n          minimumScale = this.minimumScaleTrigger,\n          objectScale = this.getTotalObjectScaling(),\n          scaleX = objectScale.scaleX,\n          scaleY = objectScale.scaleY,\n          elementToFilter = this._filteredEl || this._originalElement;\n      if (this.group) {\n        this.set('dirty', true);\n      }\n      if (!filter || (scaleX > minimumScale && scaleY > minimumScale)) {\n        this._element = elementToFilter;\n        this._filterScalingX = 1;\n        this._filterScalingY = 1;\n        this._lastScaleX = scaleX;\n        this._lastScaleY = scaleY;\n        return;\n      }\n      if (!fabric.filterBackend) {\n        fabric.filterBackend = fabric.initFilterBackend();\n      }\n      var canvasEl = fabric.util.createCanvasElement(),\n          cacheKey = this._filteredEl ? (this.cacheKey + '_filtered') : this.cacheKey,\n          sourceWidth = elementToFilter.width, sourceHeight = elementToFilter.height;\n      canvasEl.width = sourceWidth;\n      canvasEl.height = sourceHeight;\n      this._element = canvasEl;\n      this._lastScaleX = filter.scaleX = scaleX;\n      this._lastScaleY = filter.scaleY = scaleY;\n      fabric.filterBackend.applyFilters(\n        [filter], elementToFilter, sourceWidth, sourceHeight, this._element, cacheKey);\n      this._filterScalingX = canvasEl.width / this._originalElement.width;\n      this._filterScalingY = canvasEl.height / this._originalElement.height;\n    },\n\n    /**\n     * Applies filters assigned to this image (from \"filters\" array) or from filter param\n     * @method applyFilters\n     * @param {Array} filters to be applied\n     * @param {Boolean} forResizing specify if the filter operation is a resize operation\n     * @return {thisArg} return the fabric.Image object\n     * @chainable\n     */\n    applyFilters: function(filters) {\n\n      filters = filters || this.filters || [];\n      filters = filters.filter(function(filter) { return filter && !filter.isNeutralState(); });\n      this.set('dirty', true);\n\n      // needs to clear out or WEBGL will not resize correctly\n      this.removeTexture(this.cacheKey + '_filtered');\n\n      if (filters.length === 0) {\n        this._element = this._originalElement;\n        this._filteredEl = null;\n        this._filterScalingX = 1;\n        this._filterScalingY = 1;\n        return this;\n      }\n\n      var imgElement = this._originalElement,\n          sourceWidth = imgElement.naturalWidth || imgElement.width,\n          sourceHeight = imgElement.naturalHeight || imgElement.height;\n\n      if (this._element === this._originalElement) {\n        // if the element is the same we need to create a new element\n        var canvasEl = fabric.util.createCanvasElement();\n        canvasEl.width = sourceWidth;\n        canvasEl.height = sourceHeight;\n        this._element = canvasEl;\n        this._filteredEl = canvasEl;\n      }\n      else {\n        // clear the existing element to get new filter data\n        // also dereference the eventual resized _element\n        this._element = this._filteredEl;\n        this._filteredEl.getContext('2d').clearRect(0, 0, sourceWidth, sourceHeight);\n        // we also need to resize again at next renderAll, so remove saved _lastScaleX/Y\n        this._lastScaleX = 1;\n        this._lastScaleY = 1;\n      }\n      if (!fabric.filterBackend) {\n        fabric.filterBackend = fabric.initFilterBackend();\n      }\n      fabric.filterBackend.applyFilters(\n        filters, this._originalElement, sourceWidth, sourceHeight, this._element, this.cacheKey);\n      if (this._originalElement.width !== this._element.width ||\n        this._originalElement.height !== this._element.height) {\n        this._filterScalingX = this._element.width / this._originalElement.width;\n        this._filterScalingY = this._element.height / this._originalElement.height;\n      }\n      return this;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function(ctx) {\n      fabric.util.setImageSmoothing(ctx, this.imageSmoothing);\n      if (this.isMoving !== true && this.resizeFilter && this._needsResize()) {\n        this.applyResizeFilters();\n      }\n      this._stroke(ctx);\n      this._renderPaintInOrder(ctx);\n    },\n\n    /**\n     * Paint the cached copy of the object on the target context.\n     * it will set the imageSmoothing for the draw operation\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    drawCacheOnCanvas: function(ctx) {\n      fabric.util.setImageSmoothing(ctx, this.imageSmoothing);\n      fabric.Object.prototype.drawCacheOnCanvas.call(this, ctx);\n    },\n\n    /**\n     * Decide if the object should cache or not. Create its own cache level\n     * needsItsOwnCache should be used when the object drawing method requires\n     * a cache step. None of the fabric classes requires it.\n     * Generally you do not cache objects in groups because the group outside is cached.\n     * This is the special image version where we would like to avoid caching where possible.\n     * Essentially images do not benefit from caching. They may require caching, and in that\n     * case we do it. Also caching an image usually ends in a loss of details.\n     * A full performance audit should be done.\n     * @return {Boolean}\n     */\n    shouldCache: function() {\n      return this.needsItsOwnCache();\n    },\n\n    _renderFill: function(ctx) {\n      var elementToDraw = this._element;\n      if (!elementToDraw) {\n        return;\n      }\n      var scaleX = this._filterScalingX, scaleY = this._filterScalingY,\n          w = this.width, h = this.height, min = Math.min, max = Math.max,\n          // crop values cannot be lesser than 0.\n          cropX = max(this.cropX, 0), cropY = max(this.cropY, 0),\n          elWidth = elementToDraw.naturalWidth || elementToDraw.width,\n          elHeight = elementToDraw.naturalHeight || elementToDraw.height,\n          sX = cropX * scaleX,\n          sY = cropY * scaleY,\n          // the width height cannot exceed element width/height, starting from the crop offset.\n          sW = min(w * scaleX, elWidth - sX),\n          sH = min(h * scaleY, elHeight - sY),\n          x = -w / 2, y = -h / 2,\n          maxDestW = min(w, elWidth / scaleX - cropX),\n          maxDestH = min(h, elHeight / scaleX - cropY);\n\n      elementToDraw && ctx.drawImage(elementToDraw, sX, sY, sW, sH, x, y, maxDestW, maxDestH);\n    },\n\n    /**\n     * needed to check if image needs resize\n     * @private\n     */\n    _needsResize: function() {\n      var scale = this.getTotalObjectScaling();\n      return (scale.scaleX !== this._lastScaleX || scale.scaleY !== this._lastScaleY);\n    },\n\n    /**\n     * @private\n     */\n    _resetWidthHeight: function() {\n      this.set(this.getOriginalSize());\n    },\n\n    /**\n     * The Image class's initialization method. This method is automatically\n     * called by the constructor.\n     * @private\n     * @param {HTMLImageElement|String} element The element representing the image\n     * @param {Object} [options] Options object\n     */\n    _initElement: function(element, options) {\n      this.setElement(fabric.util.getById(element), options);\n      fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS);\n    },\n\n    /**\n     * @private\n     * @param {Object} [options] Options object\n     */\n    _initConfig: function(options) {\n      options || (options = { });\n      this.setOptions(options);\n      this._setWidthHeight(options);\n    },\n\n    /**\n     * @private\n     * @param {Array} filters to be initialized\n     * @param {Function} callback Callback to invoke when all fabric.Image.filters instances are created\n     */\n    _initFilters: function(filters, callback) {\n      if (filters && filters.length) {\n        fabric.util.enlivenObjects(filters, function(enlivenedObjects) {\n          callback && callback(enlivenedObjects);\n        }, 'fabric.Image.filters');\n      }\n      else {\n        callback && callback();\n      }\n    },\n\n    /**\n     * @private\n     * Set the width and the height of the image object, using the element or the\n     * options.\n     * @param {Object} [options] Object with width/height properties\n     */\n    _setWidthHeight: function(options) {\n      options || (options = { });\n      var el = this.getElement();\n      this.width = options.width || el.naturalWidth || el.width || 0;\n      this.height = options.height || el.naturalHeight || el.height || 0;\n    },\n\n    /**\n     * Calculate offset for center and scale factor for the image in order to respect\n     * the preserveAspectRatio attribute\n     * @private\n     * @return {Object}\n     */\n    parsePreserveAspectRatioAttribute: function() {\n      var pAR = fabric.util.parsePreserveAspectRatioAttribute(this.preserveAspectRatio || ''),\n          rWidth = this._element.width, rHeight = this._element.height,\n          scaleX = 1, scaleY = 1, offsetLeft = 0, offsetTop = 0, cropX = 0, cropY = 0,\n          offset, pWidth = this.width, pHeight = this.height, parsedAttributes = { width: pWidth, height: pHeight };\n      if (pAR && (pAR.alignX !== 'none' || pAR.alignY !== 'none')) {\n        if (pAR.meetOrSlice === 'meet') {\n          scaleX = scaleY = fabric.util.findScaleToFit(this._element, parsedAttributes);\n          offset = (pWidth - rWidth * scaleX) / 2;\n          if (pAR.alignX === 'Min') {\n            offsetLeft = -offset;\n          }\n          if (pAR.alignX === 'Max') {\n            offsetLeft = offset;\n          }\n          offset = (pHeight - rHeight * scaleY) / 2;\n          if (pAR.alignY === 'Min') {\n            offsetTop = -offset;\n          }\n          if (pAR.alignY === 'Max') {\n            offsetTop = offset;\n          }\n        }\n        if (pAR.meetOrSlice === 'slice') {\n          scaleX = scaleY = fabric.util.findScaleToCover(this._element, parsedAttributes);\n          offset = rWidth - pWidth / scaleX;\n          if (pAR.alignX === 'Mid') {\n            cropX = offset / 2;\n          }\n          if (pAR.alignX === 'Max') {\n            cropX = offset;\n          }\n          offset = rHeight - pHeight / scaleY;\n          if (pAR.alignY === 'Mid') {\n            cropY = offset / 2;\n          }\n          if (pAR.alignY === 'Max') {\n            cropY = offset;\n          }\n          rWidth = pWidth / scaleX;\n          rHeight = pHeight / scaleY;\n        }\n      }\n      else {\n        scaleX = pWidth / rWidth;\n        scaleY = pHeight / rHeight;\n      }\n      return {\n        width: rWidth,\n        height: rHeight,\n        scaleX: scaleX,\n        scaleY: scaleY,\n        offsetLeft: offsetLeft,\n        offsetTop: offsetTop,\n        cropX: cropX,\n        cropY: cropY\n      };\n    }\n  });\n\n  /**\n   * Default CSS class name for canvas\n   * @static\n   * @type String\n   * @default\n   */\n  fabric.Image.CSS_CANVAS = 'canvas-img';\n\n  /**\n   * Alias for getSrc\n   * @static\n   */\n  fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc;\n\n  /**\n   * Creates an instance of fabric.Image from its object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {Function} callback Callback to invoke when an image instance is created\n   */\n  fabric.Image.fromObject = function(_object, callback) {\n    var object = fabric.util.object.clone(_object);\n    fabric.util.loadImage(object.src, function(img, isError) {\n      if (isError) {\n        callback && callback(null, true);\n        return;\n      }\n      fabric.Image.prototype._initFilters.call(object, object.filters, function(filters) {\n        object.filters = filters || [];\n        fabric.Image.prototype._initFilters.call(object, [object.resizeFilter], function(resizeFilters) {\n          object.resizeFilter = resizeFilters[0];\n          fabric.util.enlivenObjects([object.clipPath], function(enlivedProps) {\n            object.clipPath = enlivedProps[0];\n            var image = new fabric.Image(img, object);\n            callback(image, false);\n          });\n        });\n      });\n    }, null, object.crossOrigin);\n  };\n\n  /**\n   * Creates an instance of fabric.Image from an URL string\n   * @static\n   * @param {String} url URL to create an image from\n   * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument). Second argument is a boolean indicating if an error occured or not.\n   * @param {Object} [imgOptions] Options object\n   */\n  fabric.Image.fromURL = function(url, callback, imgOptions) {\n    fabric.util.loadImage(url, function(img, isError) {\n      callback && callback(new fabric.Image(img, imgOptions), isError);\n    }, null, imgOptions && imgOptions.crossOrigin);\n  };\n\n  /* _FROM_SVG_START_ */\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Image.fromElement})\n   * @static\n   * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement}\n   */\n  fabric.Image.ATTRIBUTE_NAMES =\n    fabric.SHARED_ATTRIBUTES.concat(\n      'x y width height preserveAspectRatio xlink:href crossOrigin image-rendering'.split(' ')\n    );\n\n  /**\n   * Returns {@link fabric.Image} instance from an SVG element\n   * @static\n   * @param {SVGElement} element Element to parse\n   * @param {Object} [options] Options object\n   * @param {Function} callback Callback to execute when fabric.Image object is created\n   * @return {fabric.Image} Instance of fabric.Image\n   */\n  fabric.Image.fromElement = function(element, callback, options) {\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES);\n    fabric.Image.fromURL(parsedAttributes['xlink:href'], callback,\n      extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));\n  };\n  /* _FROM_SVG_END_ */\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n  /**\n   * @private\n   * @return {Number} angle value\n   */\n  _getAngleValueForStraighten: function() {\n    var angle = this.angle % 360;\n    if (angle > 0) {\n      return Math.round((angle - 1) / 90) * 90;\n    }\n    return Math.round(angle / 90) * 90;\n  },\n\n  /**\n   * Straightens an object (rotating it from current angle to one of 0, 90, 180, 270, etc. depending on which is closer)\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  straighten: function() {\n    this.rotate(this._getAngleValueForStraighten());\n    return this;\n  },\n\n  /**\n   * Same as {@link fabric.Object.prototype.straighten} but with animation\n   * @param {Object} callbacks Object with callback functions\n   * @param {Function} [callbacks.onComplete] Invoked on completion\n   * @param {Function} [callbacks.onChange] Invoked on every step of animation\n   * @return {fabric.Object} thisArg\n   * @chainable\n   */\n  fxStraighten: function(callbacks) {\n    callbacks = callbacks || { };\n\n    var empty = function() { },\n        onComplete = callbacks.onComplete || empty,\n        onChange = callbacks.onChange || empty,\n        _this = this;\n\n    fabric.util.animate({\n      startValue: this.get('angle'),\n      endValue: this._getAngleValueForStraighten(),\n      duration: this.FX_DURATION,\n      onChange: function(value) {\n        _this.rotate(value);\n        onChange();\n      },\n      onComplete: function() {\n        _this.setCoords();\n        onComplete();\n      },\n    });\n\n    return this;\n  }\n});\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n  /**\n   * Straightens object, then rerenders canvas\n   * @param {fabric.Object} object Object to straighten\n   * @return {fabric.Canvas} thisArg\n   * @chainable\n   */\n  straightenObject: function (object) {\n    object.straighten();\n    this.requestRenderAll();\n    return this;\n  },\n\n  /**\n   * Same as {@link fabric.Canvas.prototype.straightenObject}, but animated\n   * @param {fabric.Object} object Object to straighten\n   * @return {fabric.Canvas} thisArg\n   * @chainable\n   */\n  fxStraightenObject: function (object) {\n    object.fxStraighten({\n      onChange: this.requestRenderAllBound\n    });\n    return this;\n  }\n});\n\n\n(function() {\n\n  'use strict';\n\n  /**\n   * Tests if webgl supports certain precision\n   * @param {WebGL} Canvas WebGL context to test on\n   * @param {String} Precision to test can be any of following: 'lowp', 'mediump', 'highp'\n   * @returns {Boolean} Whether the user's browser WebGL supports given precision.\n   */\n  function testPrecision(gl, precision){\n    var fragmentSource = 'precision ' + precision + ' float;\\nvoid main(){}';\n    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n    gl.shaderSource(fragmentShader, fragmentSource);\n    gl.compileShader(fragmentShader);\n    if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\n      return false;\n    }\n    return true;\n  }\n\n  /**\n   * Indicate whether this filtering backend is supported by the user's browser.\n   * @param {Number} tileSize check if the tileSize is supported\n   * @returns {Boolean} Whether the user's browser supports WebGL.\n   */\n  fabric.isWebglSupported = function(tileSize) {\n    if (fabric.isLikelyNode) {\n      return false;\n    }\n    tileSize = tileSize || fabric.WebglFilterBackend.prototype.tileSize;\n    var canvas = document.createElement('canvas');\n    var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n    var isSupported = false;\n    // eslint-disable-next-line\n    if (gl) {\n      fabric.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);\n      isSupported = fabric.maxTextureSize >= tileSize;\n      var precisions = ['highp', 'mediump', 'lowp'];\n      for (var i = 0; i < 3; i++){\n        if (testPrecision(gl, precisions[i])){\n          fabric.webGlPrecision = precisions[i];\n          break;\n        };\n      }\n    }\n    this.isSupported = isSupported;\n    return isSupported;\n  };\n\n  fabric.WebglFilterBackend = WebglFilterBackend;\n\n  /**\n   * WebGL filter backend.\n   */\n  function WebglFilterBackend(options) {\n    if (options && options.tileSize) {\n      this.tileSize = options.tileSize;\n    }\n    this.setupGLContext(this.tileSize, this.tileSize);\n    this.captureGPUInfo();\n  };\n\n  WebglFilterBackend.prototype = /** @lends fabric.WebglFilterBackend.prototype */ {\n\n    tileSize: 2048,\n\n    /**\n     * Experimental. This object is a sort of repository of help layers used to avoid\n     * of recreating them during frequent filtering. If you are previewing a filter with\n     * a slider you problably do not want to create help layers every filter step.\n     * in this object there will be appended some canvases, created once, resized sometimes\n     * cleared never. Clearing is left to the developer.\n     **/\n    resources: {\n\n    },\n\n    /**\n     * Setup a WebGL context suitable for filtering, and bind any needed event handlers.\n     */\n    setupGLContext: function(width, height) {\n      this.dispose();\n      this.createWebGLCanvas(width, height);\n      // eslint-disable-next-line\n      this.aPosition = new Float32Array([0, 0, 0, 1, 1, 0, 1, 1]);\n      this.chooseFastestCopyGLTo2DMethod(width, height);\n    },\n\n    /**\n     * Pick a method to copy data from GL context to 2d canvas.  In some browsers using\n     * putImageData is faster than drawImage for that specific operation.\n     */\n    chooseFastestCopyGLTo2DMethod: function(width, height) {\n      var canMeasurePerf = typeof window.performance !== 'undefined', canUseImageData;\n      try {\n        new ImageData(1, 1);\n        canUseImageData = true;\n      }\n      catch (e) {\n        canUseImageData = false;\n      }\n      // eslint-disable-next-line no-undef\n      var canUseArrayBuffer = typeof ArrayBuffer !== 'undefined';\n      // eslint-disable-next-line no-undef\n      var canUseUint8Clamped = typeof Uint8ClampedArray !== 'undefined';\n\n      if (!(canMeasurePerf && canUseImageData && canUseArrayBuffer && canUseUint8Clamped)) {\n        return;\n      }\n\n      var targetCanvas = fabric.util.createCanvasElement();\n      // eslint-disable-next-line no-undef\n      var imageBuffer = new ArrayBuffer(width * height * 4);\n      if (fabric.forceGLPutImageData) {\n        this.imageBuffer = imageBuffer;\n        this.copyGLTo2D = copyGLTo2DPutImageData;\n        return;\n      }\n      var testContext = {\n        imageBuffer: imageBuffer,\n        destinationWidth: width,\n        destinationHeight: height,\n        targetCanvas: targetCanvas\n      };\n      var startTime, drawImageTime, putImageDataTime;\n      targetCanvas.width = width;\n      targetCanvas.height = height;\n\n      startTime = window.performance.now();\n      copyGLTo2DDrawImage.call(testContext, this.gl, testContext);\n      drawImageTime = window.performance.now() - startTime;\n\n      startTime = window.performance.now();\n      copyGLTo2DPutImageData.call(testContext, this.gl, testContext);\n      putImageDataTime = window.performance.now() - startTime;\n\n      if (drawImageTime > putImageDataTime) {\n        this.imageBuffer = imageBuffer;\n        this.copyGLTo2D = copyGLTo2DPutImageData;\n      }\n      else {\n        this.copyGLTo2D = copyGLTo2DDrawImage;\n      }\n    },\n\n    /**\n     * Create a canvas element and associated WebGL context and attaches them as\n     * class properties to the GLFilterBackend class.\n     */\n    createWebGLCanvas: function(width, height) {\n      var canvas = fabric.util.createCanvasElement();\n      canvas.width = width;\n      canvas.height = height;\n      var glOptions = {\n            alpha: true,\n            premultipliedAlpha: false,\n            depth: false,\n            stencil: false,\n            antialias: false\n          },\n          gl = canvas.getContext('webgl', glOptions);\n      if (!gl) {\n        gl = canvas.getContext('experimental-webgl', glOptions);\n      }\n      if (!gl) {\n        return;\n      }\n      gl.clearColor(0, 0, 0, 0);\n      // this canvas can fire webglcontextlost and webglcontextrestored\n      this.canvas = canvas;\n      this.gl = gl;\n    },\n\n    /**\n     * Attempts to apply the requested filters to the source provided, drawing the filtered output\n     * to the provided target canvas.\n     *\n     * @param {Array} filters The filters to apply.\n     * @param {HTMLImageElement|HTMLCanvasElement} source The source to be filtered.\n     * @param {Number} width The width of the source input.\n     * @param {Number} height The height of the source input.\n     * @param {HTMLCanvasElement} targetCanvas The destination for filtered output to be drawn.\n     * @param {String|undefined} cacheKey A key used to cache resources related to the source. If\n     * omitted, caching will be skipped.\n     */\n    applyFilters: function(filters, source, width, height, targetCanvas, cacheKey) {\n      var gl = this.gl;\n      var cachedTexture;\n      if (cacheKey) {\n        cachedTexture = this.getCachedTexture(cacheKey, source);\n      }\n      var pipelineState = {\n        originalWidth: source.width || source.originalWidth,\n        originalHeight: source.height || source.originalHeight,\n        sourceWidth: width,\n        sourceHeight: height,\n        destinationWidth: width,\n        destinationHeight: height,\n        context: gl,\n        sourceTexture: this.createTexture(gl, width, height, !cachedTexture && source),\n        targetTexture: this.createTexture(gl, width, height),\n        originalTexture: cachedTexture ||\n          this.createTexture(gl, width, height, !cachedTexture && source),\n        passes: filters.length,\n        webgl: true,\n        aPosition: this.aPosition,\n        programCache: this.programCache,\n        pass: 0,\n        filterBackend: this,\n        targetCanvas: targetCanvas\n      };\n      var tempFbo = gl.createFramebuffer();\n      gl.bindFramebuffer(gl.FRAMEBUFFER, tempFbo);\n      filters.forEach(function(filter) { filter && filter.applyTo(pipelineState); });\n      resizeCanvasIfNeeded(pipelineState);\n      this.copyGLTo2D(gl, pipelineState);\n      gl.bindTexture(gl.TEXTURE_2D, null);\n      gl.deleteTexture(pipelineState.sourceTexture);\n      gl.deleteTexture(pipelineState.targetTexture);\n      gl.deleteFramebuffer(tempFbo);\n      targetCanvas.getContext('2d').setTransform(1, 0, 0, 1, 0, 0);\n      return pipelineState;\n    },\n\n    /**\n     * Detach event listeners, remove references, and clean up caches.\n     */\n    dispose: function() {\n      if (this.canvas) {\n        this.canvas = null;\n        this.gl = null;\n      }\n      this.clearWebGLCaches();\n    },\n\n    /**\n     * Wipe out WebGL-related caches.\n     */\n    clearWebGLCaches: function() {\n      this.programCache = {};\n      this.textureCache = {};\n    },\n\n    /**\n     * Create a WebGL texture object.\n     *\n     * Accepts specific dimensions to initialize the textuer to or a source image.\n     *\n     * @param {WebGLRenderingContext} gl The GL context to use for creating the texture.\n     * @param {Number} width The width to initialize the texture at.\n     * @param {Number} height The height to initialize the texture.\n     * @param {HTMLImageElement|HTMLCanvasElement} textureImageSource A source for the texture data.\n     * @returns {WebGLTexture}\n     */\n    createTexture: function(gl, width, height, textureImageSource) {\n      var texture = gl.createTexture();\n      gl.bindTexture(gl.TEXTURE_2D, texture);\n      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n      if (textureImageSource) {\n        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureImageSource);\n      }\n      else {\n        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n      }\n      return texture;\n    },\n\n    /**\n     * Can be optionally used to get a texture from the cache array\n     *\n     * If an existing texture is not found, a new texture is created and cached.\n     *\n     * @param {String} uniqueId A cache key to use to find an existing texture.\n     * @param {HTMLImageElement|HTMLCanvasElement} textureImageSource A source to use to create the\n     * texture cache entry if one does not already exist.\n     */\n    getCachedTexture: function(uniqueId, textureImageSource) {\n      if (this.textureCache[uniqueId]) {\n        return this.textureCache[uniqueId];\n      }\n      else {\n        var texture = this.createTexture(\n          this.gl, textureImageSource.width, textureImageSource.height, textureImageSource);\n        this.textureCache[uniqueId] = texture;\n        return texture;\n      }\n    },\n\n    /**\n     * Clear out cached resources related to a source image that has been\n     * filtered previously.\n     *\n     * @param {String} cacheKey The cache key provided when the source image was filtered.\n     */\n    evictCachesForKey: function(cacheKey) {\n      if (this.textureCache[cacheKey]) {\n        this.gl.deleteTexture(this.textureCache[cacheKey]);\n        delete this.textureCache[cacheKey];\n      }\n    },\n\n    copyGLTo2D: copyGLTo2DDrawImage,\n\n    /**\n     * Attempt to extract GPU information strings from a WebGL context.\n     *\n     * Useful information when debugging or blacklisting specific GPUs.\n     *\n     * @returns {Object} A GPU info object with renderer and vendor strings.\n     */\n    captureGPUInfo: function() {\n      if (this.gpuInfo) {\n        return this.gpuInfo;\n      }\n      var gl = this.gl, gpuInfo = { renderer: '', vendor: '' };\n      if (!gl) {\n        return gpuInfo;\n      }\n      var ext = gl.getExtension('WEBGL_debug_renderer_info');\n      if (ext) {\n        var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);\n        var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);\n        if (renderer) {\n          gpuInfo.renderer = renderer.toLowerCase();\n        }\n        if (vendor) {\n          gpuInfo.vendor = vendor.toLowerCase();\n        }\n      }\n      this.gpuInfo = gpuInfo;\n      return gpuInfo;\n    },\n  };\n})();\n\nfunction resizeCanvasIfNeeded(pipelineState) {\n  var targetCanvas = pipelineState.targetCanvas,\n      width = targetCanvas.width, height = targetCanvas.height,\n      dWidth = pipelineState.destinationWidth,\n      dHeight = pipelineState.destinationHeight;\n\n  if (width !== dWidth || height !== dHeight) {\n    targetCanvas.width = dWidth;\n    targetCanvas.height = dHeight;\n  }\n}\n\n/**\n * Copy an input WebGL canvas on to an output 2D canvas.\n *\n * The WebGL canvas is assumed to be upside down, with the top-left pixel of the\n * desired output image appearing in the bottom-left corner of the WebGL canvas.\n *\n * @param {WebGLRenderingContext} sourceContext The WebGL context to copy from.\n * @param {HTMLCanvasElement} targetCanvas The 2D target canvas to copy on to.\n * @param {Object} pipelineState The 2D target canvas to copy on to.\n */\nfunction copyGLTo2DDrawImage(gl, pipelineState) {\n  var glCanvas = gl.canvas, targetCanvas = pipelineState.targetCanvas,\n      ctx = targetCanvas.getContext('2d');\n  ctx.translate(0, targetCanvas.height); // move it down again\n  ctx.scale(1, -1); // vertical flip\n  // where is my image on the big glcanvas?\n  var sourceY = glCanvas.height - targetCanvas.height;\n  ctx.drawImage(glCanvas, 0, sourceY, targetCanvas.width, targetCanvas.height, 0, 0,\n    targetCanvas.width, targetCanvas.height);\n}\n\n/**\n * Copy an input WebGL canvas on to an output 2D canvas using 2d canvas' putImageData\n * API. Measurably faster than using ctx.drawImage in Firefox (version 54 on OSX Sierra).\n *\n * @param {WebGLRenderingContext} sourceContext The WebGL context to copy from.\n * @param {HTMLCanvasElement} targetCanvas The 2D target canvas to copy on to.\n * @param {Object} pipelineState The 2D target canvas to copy on to.\n */\nfunction copyGLTo2DPutImageData(gl, pipelineState) {\n  var targetCanvas = pipelineState.targetCanvas, ctx = targetCanvas.getContext('2d'),\n      dWidth = pipelineState.destinationWidth,\n      dHeight = pipelineState.destinationHeight,\n      numBytes = dWidth * dHeight * 4;\n\n  // eslint-disable-next-line no-undef\n  var u8 = new Uint8Array(this.imageBuffer, 0, numBytes);\n  // eslint-disable-next-line no-undef\n  var u8Clamped = new Uint8ClampedArray(this.imageBuffer, 0, numBytes);\n\n  gl.readPixels(0, 0, dWidth, dHeight, gl.RGBA, gl.UNSIGNED_BYTE, u8);\n  var imgData = new ImageData(u8Clamped, dWidth, dHeight);\n  ctx.putImageData(imgData, 0, 0);\n}\n\n\n(function() {\n\n  'use strict';\n\n  var noop = function() {};\n\n  fabric.Canvas2dFilterBackend = Canvas2dFilterBackend;\n\n  /**\n   * Canvas 2D filter backend.\n   */\n  function Canvas2dFilterBackend() {};\n\n  Canvas2dFilterBackend.prototype = /** @lends fabric.Canvas2dFilterBackend.prototype */ {\n    evictCachesForKey: noop,\n    dispose: noop,\n    clearWebGLCaches: noop,\n\n    /**\n     * Experimental. This object is a sort of repository of help layers used to avoid\n     * of recreating them during frequent filtering. If you are previewing a filter with\n     * a slider you probably do not want to create help layers every filter step.\n     * in this object there will be appended some canvases, created once, resized sometimes\n     * cleared never. Clearing is left to the developer.\n     **/\n    resources: {\n\n    },\n\n    /**\n     * Apply a set of filters against a source image and draw the filtered output\n     * to the provided destination canvas.\n     *\n     * @param {EnhancedFilter} filters The filter to apply.\n     * @param {HTMLImageElement|HTMLCanvasElement} sourceElement The source to be filtered.\n     * @param {Number} sourceWidth The width of the source input.\n     * @param {Number} sourceHeight The height of the source input.\n     * @param {HTMLCanvasElement} targetCanvas The destination for filtered output to be drawn.\n     */\n    applyFilters: function(filters, sourceElement, sourceWidth, sourceHeight, targetCanvas) {\n      var ctx = targetCanvas.getContext('2d');\n      ctx.drawImage(sourceElement, 0, 0, sourceWidth, sourceHeight);\n      var imageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight);\n      var originalImageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight);\n      var pipelineState = {\n        sourceWidth: sourceWidth,\n        sourceHeight: sourceHeight,\n        imageData: imageData,\n        originalEl: sourceElement,\n        originalImageData: originalImageData,\n        canvasEl: targetCanvas,\n        ctx: ctx,\n        filterBackend: this,\n      };\n      filters.forEach(function(filter) { filter.applyTo(pipelineState); });\n      if (pipelineState.imageData.width !== sourceWidth || pipelineState.imageData.height !== sourceHeight) {\n        targetCanvas.width = pipelineState.imageData.width;\n        targetCanvas.height = pipelineState.imageData.height;\n      }\n      ctx.putImageData(pipelineState.imageData, 0, 0);\n      return pipelineState;\n    },\n\n  };\n})();\n\n\n/**\n * @namespace fabric.Image.filters\n * @memberOf fabric.Image\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#image_filters}\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n */\nfabric.Image = fabric.Image || { };\nfabric.Image.filters = fabric.Image.filters || { };\n\n/**\n * Root filter class from which all filter classes inherit from\n * @class fabric.Image.filters.BaseFilter\n * @memberOf fabric.Image.filters\n */\nfabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Image.filters.BaseFilter.prototype */ {\n\n  /**\n   * Filter type\n   * @param {String} type\n   * @default\n   */\n  type: 'BaseFilter',\n\n  /**\n   * Array of attributes to send with buffers. do not modify\n   * @private\n   */\n\n  vertexSource: 'attribute vec2 aPosition;\\n' +\n    'varying vec2 vTexCoord;\\n' +\n    'void main() {\\n' +\n      'vTexCoord = aPosition;\\n' +\n      'gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\\n' +\n    '}',\n\n  fragmentSource: 'precision highp float;\\n' +\n    'varying vec2 vTexCoord;\\n' +\n    'uniform sampler2D uTexture;\\n' +\n    'void main() {\\n' +\n      'gl_FragColor = texture2D(uTexture, vTexCoord);\\n' +\n    '}',\n\n  /**\n   * Constructor\n   * @param {Object} [options] Options object\n   */\n  initialize: function(options) {\n    if (options) {\n      this.setOptions(options);\n    }\n  },\n\n  /**\n   * Sets filter's properties from options\n   * @param {Object} [options] Options object\n   */\n  setOptions: function(options) {\n    for (var prop in options) {\n      this[prop] = options[prop];\n    }\n  },\n\n  /**\n   * Compile this filter's shader program.\n   *\n   * @param {WebGLRenderingContext} gl The GL canvas context to use for shader compilation.\n   * @param {String} fragmentSource fragmentShader source for compilation\n   * @param {String} vertexSource vertexShader source for compilation\n   */\n  createProgram: function(gl, fragmentSource, vertexSource) {\n    fragmentSource = fragmentSource || this.fragmentSource;\n    vertexSource = vertexSource || this.vertexSource;\n    if (fabric.webGlPrecision !== 'highp'){\n      fragmentSource = fragmentSource.replace(\n        /precision highp float/g,\n        'precision ' + fabric.webGlPrecision + ' float'\n      );\n    }\n    var vertexShader = gl.createShader(gl.VERTEX_SHADER);\n    gl.shaderSource(vertexShader, vertexSource);\n    gl.compileShader(vertexShader);\n    if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {\n      throw new Error(\n        // eslint-disable-next-line prefer-template\n        'Vertex shader compile error for ' + this.type + ': ' +\n        gl.getShaderInfoLog(vertexShader)\n      );\n    }\n\n    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n    gl.shaderSource(fragmentShader, fragmentSource);\n    gl.compileShader(fragmentShader);\n    if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\n      throw new Error(\n        // eslint-disable-next-line prefer-template\n        'Fragment shader compile error for ' + this.type + ': ' +\n        gl.getShaderInfoLog(fragmentShader)\n      );\n    }\n\n    var program = gl.createProgram();\n    gl.attachShader(program, vertexShader);\n    gl.attachShader(program, fragmentShader);\n    gl.linkProgram(program);\n    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n      throw new Error(\n        // eslint-disable-next-line prefer-template\n        'Shader link error for \"${this.type}\" ' +\n        gl.getProgramInfoLog(program)\n      );\n    }\n\n    var attributeLocations = this.getAttributeLocations(gl, program);\n    var uniformLocations = this.getUniformLocations(gl, program) || { };\n    uniformLocations.uStepW = gl.getUniformLocation(program, 'uStepW');\n    uniformLocations.uStepH = gl.getUniformLocation(program, 'uStepH');\n    return {\n      program: program,\n      attributeLocations: attributeLocations,\n      uniformLocations: uniformLocations\n    };\n  },\n\n  /**\n   * Return a map of attribute names to WebGLAttributeLocation objects.\n   *\n   * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n   * @param {WebGLShaderProgram} program The shader program from which to take attribute locations.\n   * @returns {Object} A map of attribute names to attribute locations.\n   */\n  getAttributeLocations: function(gl, program) {\n    return {\n      aPosition: gl.getAttribLocation(program, 'aPosition'),\n    };\n  },\n\n  /**\n   * Return a map of uniform names to WebGLUniformLocation objects.\n   *\n   * Intended to be overridden by subclasses.\n   *\n   * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n   * @param {WebGLShaderProgram} program The shader program from which to take uniform locations.\n   * @returns {Object} A map of uniform names to uniform locations.\n   */\n  getUniformLocations: function (/* gl, program */) {\n    // in case i do not need any special uniform i need to return an empty object\n    return { };\n  },\n\n  /**\n   * Send attribute data from this filter to its shader program on the GPU.\n   *\n   * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n   * @param {Object} attributeLocations A map of shader attribute names to their locations.\n   */\n  sendAttributeData: function(gl, attributeLocations, aPositionData) {\n    var attributeLocation = attributeLocations.aPosition;\n    var buffer = gl.createBuffer();\n    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n    gl.enableVertexAttribArray(attributeLocation);\n    gl.vertexAttribPointer(attributeLocation, 2, gl.FLOAT, false, 0, 0);\n    gl.bufferData(gl.ARRAY_BUFFER, aPositionData, gl.STATIC_DRAW);\n  },\n\n  _setupFrameBuffer: function(options) {\n    var gl = options.context, width, height;\n    if (options.passes > 1) {\n      width = options.destinationWidth;\n      height = options.destinationHeight;\n      if (options.sourceWidth !== width || options.sourceHeight !== height) {\n        gl.deleteTexture(options.targetTexture);\n        options.targetTexture = options.filterBackend.createTexture(gl, width, height);\n      }\n      gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D,\n        options.targetTexture, 0);\n    }\n    else {\n      // draw last filter on canvas and not to framebuffer.\n      gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n      gl.finish();\n    }\n  },\n\n  _swapTextures: function(options) {\n    options.passes--;\n    options.pass++;\n    var temp = options.targetTexture;\n    options.targetTexture = options.sourceTexture;\n    options.sourceTexture = temp;\n  },\n\n  /**\n   * Generic isNeutral implementation for one parameter based filters.\n   * Used only in image applyFilters to discard filters that will not have an effect\n   * on the image\n   * Other filters may need their own verison ( ColorMatrix, HueRotation, gamma, ComposedFilter )\n   * @param {Object} options\n   **/\n  isNeutralState: function(/* options */) {\n    var main = this.mainParameter,\n        _class = fabric.Image.filters[this.type].prototype;\n    if (main) {\n      if (Array.isArray(_class[main])) {\n        for (var i = _class[main].length; i--;) {\n          if (this[main][i] !== _class[main][i]) {\n            return false;\n          }\n        }\n        return true;\n      }\n      else {\n        return _class[main] === this[main];\n      }\n    }\n    else {\n      return false;\n    }\n  },\n\n  /**\n   * Apply this filter to the input image data provided.\n   *\n   * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\n   *\n   * @param {Object} options\n   * @param {Number} options.passes The number of filters remaining to be executed\n   * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n   * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n   * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n   * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n   * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n   */\n  applyTo: function(options) {\n    if (options.webgl) {\n      this._setupFrameBuffer(options);\n      this.applyToWebGL(options);\n      this._swapTextures(options);\n    }\n    else {\n      this.applyTo2d(options);\n    }\n  },\n\n  /**\n   * Retrieves the cached shader.\n   * @param {Object} options\n   * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n   * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n   */\n  retrieveShader: function(options) {\n    if (!options.programCache.hasOwnProperty(this.type)) {\n      options.programCache[this.type] = this.createProgram(options.context);\n    }\n    return options.programCache[this.type];\n  },\n\n  /**\n   * Apply this filter using webgl.\n   *\n   * @param {Object} options\n   * @param {Number} options.passes The number of filters remaining to be executed\n   * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n   * @param {WebGLTexture} options.originalTexture The texture of the original input image.\n   * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n   * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n   * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n   * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n   */\n  applyToWebGL: function(options) {\n    var gl = options.context;\n    var shader = this.retrieveShader(options);\n    if (options.pass === 0 && options.originalTexture) {\n      gl.bindTexture(gl.TEXTURE_2D, options.originalTexture);\n    }\n    else {\n      gl.bindTexture(gl.TEXTURE_2D, options.sourceTexture);\n    }\n    gl.useProgram(shader.program);\n    this.sendAttributeData(gl, shader.attributeLocations, options.aPosition);\n\n    gl.uniform1f(shader.uniformLocations.uStepW, 1 / options.sourceWidth);\n    gl.uniform1f(shader.uniformLocations.uStepH, 1 / options.sourceHeight);\n\n    this.sendUniformData(gl, shader.uniformLocations);\n    gl.viewport(0, 0, options.destinationWidth, options.destinationHeight);\n    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n  },\n\n  bindAdditionalTexture: function(gl, texture, textureUnit) {\n    gl.activeTexture(textureUnit);\n    gl.bindTexture(gl.TEXTURE_2D, texture);\n    // reset active texture to 0 as usual\n    gl.activeTexture(gl.TEXTURE0);\n  },\n\n  unbindAdditionalTexture: function(gl, textureUnit) {\n    gl.activeTexture(textureUnit);\n    gl.bindTexture(gl.TEXTURE_2D, null);\n    gl.activeTexture(gl.TEXTURE0);\n  },\n\n  getMainParameter: function() {\n    return this[this.mainParameter];\n  },\n\n  setMainParameter: function(value) {\n    this[this.mainParameter] = value;\n  },\n\n  /**\n   * Send uniform data from this filter to its shader program on the GPU.\n   *\n   * Intended to be overridden by subclasses.\n   *\n   * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n   * @param {Object} uniformLocations A map of shader uniform names to their locations.\n   */\n  sendUniformData: function(/* gl, uniformLocations */) {\n    // Intentionally left blank.  Override me in subclasses.\n  },\n\n  /**\n   * If needed by a 2d filter, this functions can create an helper canvas to be used\n   * remember that options.targetCanvas is available for use till end of chain.\n   */\n  createHelpLayer: function(options) {\n    if (!options.helpLayer) {\n      var helpLayer = document.createElement('canvas');\n      helpLayer.width = options.sourceWidth;\n      helpLayer.height = options.sourceHeight;\n      options.helpLayer = helpLayer;\n    }\n  },\n\n  /**\n   * Returns object representation of an instance\n   * @return {Object} Object representation of an instance\n   */\n  toObject: function() {\n    var object = { type: this.type }, mainP = this.mainParameter;\n    if (mainP) {\n      object[mainP] = this[mainP];\n    }\n    return object;\n  },\n\n  /**\n   * Returns a JSON representation of an instance\n   * @return {Object} JSON\n   */\n  toJSON: function() {\n    // delegate, not alias\n    return this.toObject();\n  }\n});\n\nfabric.Image.filters.BaseFilter.fromObject = function(object, callback) {\n  var filter = new fabric.Image.filters[object.type](object);\n  callback && callback(filter);\n  return filter;\n};\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Color Matrix filter class\n   * @class fabric.Image.filters.ColorMatrix\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.ColorMatrix#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @see {@Link http://www.webwasp.co.uk/tutorials/219/Color_Matrix_Filter.php}\n   * @see {@Link http://phoboslab.org/log/2013/11/fast-image-filters-with-webgl}\n   * @example <caption>Kodachrome filter</caption>\n   * var filter = new fabric.Image.filters.ColorMatrix({\n   *  matrix: [\n       1.1285582396593525, -0.3967382283601348, -0.03992559172921793, 0, 63.72958762196502,\n       -0.16404339962244616, 1.0835251566291304, -0.05498805115633132, 0, 24.732407896706203,\n       -0.16786010706155763, -0.5603416277695248, 1.6014850761964943, 0, 35.62982807460946,\n       0, 0, 0, 1, 0\n      ]\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n  filters.ColorMatrix = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.ColorMatrix.prototype */ {\n\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'ColorMatrix',\n\n    fragmentSource: 'precision highp float;\\n' +\n      'uniform sampler2D uTexture;\\n' +\n      'varying vec2 vTexCoord;\\n' +\n      'uniform mat4 uColorMatrix;\\n' +\n      'uniform vec4 uConstants;\\n' +\n      'void main() {\\n' +\n        'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n        'color *= uColorMatrix;\\n' +\n        'color += uConstants;\\n' +\n        'gl_FragColor = color;\\n' +\n      '}',\n\n    /**\n     * Colormatrix for pixels.\n     * array of 20 floats. Numbers in positions 4, 9, 14, 19 loose meaning\n     * outside the -1, 1 range.\n     * 0.0039215686 is the part of 1 that get translated to 1 in 2d\n     * @param {Array} matrix array of 20 numbers.\n     * @default\n     */\n    matrix: [\n      1, 0, 0, 0, 0,\n      0, 1, 0, 0, 0,\n      0, 0, 1, 0, 0,\n      0, 0, 0, 1, 0\n    ],\n\n    mainParameter: 'matrix',\n\n    /**\n     * Lock the colormatrix on the color part, skipping alpha, manly for non webgl scenario\n     * to save some calculation\n     */\n    colorsOnly: true,\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     */\n    initialize: function(options) {\n      this.callSuper('initialize', options);\n      // create a new array instead mutating the prototype with push\n      this.matrix = this.matrix.slice(0);\n    },\n\n    /**\n     * Apply the ColorMatrix operation to a Uint8Array representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8Array to be filtered.\n     */\n    applyTo2d: function(options) {\n      var imageData = options.imageData,\n          data = imageData.data,\n          iLen = data.length,\n          m = this.matrix,\n          r, g, b, a, i, colorsOnly = this.colorsOnly;\n\n      for (i = 0; i < iLen; i += 4) {\n        r = data[i];\n        g = data[i + 1];\n        b = data[i + 2];\n        if (colorsOnly) {\n          data[i] = r * m[0] + g * m[1] + b * m[2] + m[4] * 255;\n          data[i + 1] = r * m[5] + g * m[6] + b * m[7] + m[9] * 255;\n          data[i + 2] = r * m[10] + g * m[11] + b * m[12] + m[14] * 255;\n        }\n        else {\n          a = data[i + 3];\n          data[i] = r * m[0] + g * m[1] + b * m[2] + a * m[3] + m[4] * 255;\n          data[i + 1] = r * m[5] + g * m[6] + b * m[7] + a * m[8] + m[9] * 255;\n          data[i + 2] = r * m[10] + g * m[11] + b * m[12] + a * m[13] + m[14] * 255;\n          data[i + 3] = r * m[15] + g * m[16] + b * m[17] + a * m[18] + m[19] * 255;\n        }\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uColorMatrix: gl.getUniformLocation(program, 'uColorMatrix'),\n        uConstants: gl.getUniformLocation(program, 'uConstants'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      var m = this.matrix,\n          matrix = [\n            m[0], m[1], m[2], m[3],\n            m[5], m[6], m[7], m[8],\n            m[10], m[11], m[12], m[13],\n            m[15], m[16], m[17], m[18]\n          ],\n          constants = [m[4], m[9], m[14], m[19]];\n      gl.uniformMatrix4fv(uniformLocations.uColorMatrix, false, matrix);\n      gl.uniform4fv(uniformLocations.uConstants, constants);\n    },\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] function to invoke after filter creation\n   * @return {fabric.Image.filters.ColorMatrix} Instance of fabric.Image.filters.ColorMatrix\n   */\n  fabric.Image.filters.ColorMatrix.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Brightness filter class\n   * @class fabric.Image.filters.Brightness\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Brightness#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Brightness({\n   *   brightness: 0.05\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n  filters.Brightness = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Brightness.prototype */ {\n\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Brightness',\n\n    /**\n     * Fragment source for the brightness program\n     */\n    fragmentSource: 'precision highp float;\\n' +\n      'uniform sampler2D uTexture;\\n' +\n      'uniform float uBrightness;\\n' +\n      'varying vec2 vTexCoord;\\n' +\n      'void main() {\\n' +\n        'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n        'color.rgb += uBrightness;\\n' +\n        'gl_FragColor = color;\\n' +\n      '}',\n\n    /**\n     * Brightness value, from -1 to 1.\n     * translated to -255 to 255 for 2d\n     * 0.0039215686 is the part of 1 that get translated to 1 in 2d\n     * @param {Number} brightness\n     * @default\n     */\n    brightness: 0,\n\n    /**\n     * Describe the property that is the filter parameter\n     * @param {String} m\n     * @default\n     */\n    mainParameter: 'brightness',\n\n    /**\n    * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\n    *\n    * @param {Object} options\n    * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n    */\n    applyTo2d: function(options) {\n      if (this.brightness === 0) {\n        return;\n      }\n      var imageData = options.imageData,\n          data = imageData.data, i, len = data.length,\n          brightness = Math.round(this.brightness * 255);\n      for (i = 0; i < len; i += 4) {\n        data[i] = data[i] + brightness;\n        data[i + 1] = data[i + 1] + brightness;\n        data[i + 2] = data[i + 2] + brightness;\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uBrightness: gl.getUniformLocation(program, 'uBrightness'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      gl.uniform1f(uniformLocations.uBrightness, this.brightness);\n    },\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Brightness} Instance of fabric.Image.filters.Brightness\n   */\n  fabric.Image.filters.Brightness.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      extend = fabric.util.object.extend,\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Adapted from <a href=\"http://www.html5rocks.com/en/tutorials/canvas/imagefilters/\">html5rocks article</a>\n   * @class fabric.Image.filters.Convolute\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Convolute#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example <caption>Sharpen filter</caption>\n   * var filter = new fabric.Image.filters.Convolute({\n   *   matrix: [ 0, -1,  0,\n   *            -1,  5, -1,\n   *             0, -1,  0 ]\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   * @example <caption>Blur filter</caption>\n   * var filter = new fabric.Image.filters.Convolute({\n   *   matrix: [ 1/9, 1/9, 1/9,\n   *             1/9, 1/9, 1/9,\n   *             1/9, 1/9, 1/9 ]\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   * @example <caption>Emboss filter</caption>\n   * var filter = new fabric.Image.filters.Convolute({\n   *   matrix: [ 1,   1,  1,\n   *             1, 0.7, -1,\n   *            -1,  -1, -1 ]\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   * @example <caption>Emboss filter with opaqueness</caption>\n   * var filter = new fabric.Image.filters.Convolute({\n   *   opaque: true,\n   *   matrix: [ 1,   1,  1,\n   *             1, 0.7, -1,\n   *            -1,  -1, -1 ]\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   */\n  filters.Convolute = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Convolute.prototype */ {\n\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Convolute',\n\n    /*\n     * Opaque value (true/false)\n     */\n    opaque: false,\n\n    /*\n     * matrix for the filter, max 9x9\n     */\n    matrix: [0, 0, 0, 0, 1, 0, 0, 0, 0],\n\n    /**\n     * Fragment source for the brightness program\n     */\n    fragmentSource: {\n      Convolute_3_1: 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'uniform float uMatrix[9];\\n' +\n        'uniform float uStepW;\\n' +\n        'uniform float uStepH;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'void main() {\\n' +\n          'vec4 color = vec4(0, 0, 0, 0);\\n' +\n          'for (float h = 0.0; h < 3.0; h+=1.0) {\\n' +\n            'for (float w = 0.0; w < 3.0; w+=1.0) {\\n' +\n              'vec2 matrixPos = vec2(uStepW * (w - 1), uStepH * (h - 1));\\n' +\n              'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 3.0 + w)];\\n' +\n            '}\\n' +\n          '}\\n' +\n          'gl_FragColor = color;\\n' +\n        '}',\n      Convolute_3_0: 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'uniform float uMatrix[9];\\n' +\n        'uniform float uStepW;\\n' +\n        'uniform float uStepH;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'void main() {\\n' +\n          'vec4 color = vec4(0, 0, 0, 1);\\n' +\n          'for (float h = 0.0; h < 3.0; h+=1.0) {\\n' +\n            'for (float w = 0.0; w < 3.0; w+=1.0) {\\n' +\n              'vec2 matrixPos = vec2(uStepW * (w - 1.0), uStepH * (h - 1.0));\\n' +\n              'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 3.0 + w)];\\n' +\n            '}\\n' +\n          '}\\n' +\n          'float alpha = texture2D(uTexture, vTexCoord).a;\\n' +\n          'gl_FragColor = color;\\n' +\n          'gl_FragColor.a = alpha;\\n' +\n        '}',\n      Convolute_5_1: 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'uniform float uMatrix[25];\\n' +\n        'uniform float uStepW;\\n' +\n        'uniform float uStepH;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'void main() {\\n' +\n          'vec4 color = vec4(0, 0, 0, 0);\\n' +\n          'for (float h = 0.0; h < 5.0; h+=1.0) {\\n' +\n            'for (float w = 0.0; w < 5.0; w+=1.0) {\\n' +\n              'vec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\\n' +\n              'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 5.0 + w)];\\n' +\n            '}\\n' +\n          '}\\n' +\n          'gl_FragColor = color;\\n' +\n        '}',\n      Convolute_5_0: 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'uniform float uMatrix[25];\\n' +\n        'uniform float uStepW;\\n' +\n        'uniform float uStepH;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'void main() {\\n' +\n          'vec4 color = vec4(0, 0, 0, 1);\\n' +\n          'for (float h = 0.0; h < 5.0; h+=1.0) {\\n' +\n            'for (float w = 0.0; w < 5.0; w+=1.0) {\\n' +\n              'vec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\\n' +\n              'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 5.0 + w)];\\n' +\n            '}\\n' +\n          '}\\n' +\n          'float alpha = texture2D(uTexture, vTexCoord).a;\\n' +\n          'gl_FragColor = color;\\n' +\n          'gl_FragColor.a = alpha;\\n' +\n        '}',\n      Convolute_7_1: 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'uniform float uMatrix[49];\\n' +\n        'uniform float uStepW;\\n' +\n        'uniform float uStepH;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'void main() {\\n' +\n          'vec4 color = vec4(0, 0, 0, 0);\\n' +\n          'for (float h = 0.0; h < 7.0; h+=1.0) {\\n' +\n            'for (float w = 0.0; w < 7.0; w+=1.0) {\\n' +\n              'vec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\\n' +\n              'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 7.0 + w)];\\n' +\n            '}\\n' +\n          '}\\n' +\n          'gl_FragColor = color;\\n' +\n        '}',\n      Convolute_7_0: 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'uniform float uMatrix[49];\\n' +\n        'uniform float uStepW;\\n' +\n        'uniform float uStepH;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'void main() {\\n' +\n          'vec4 color = vec4(0, 0, 0, 1);\\n' +\n          'for (float h = 0.0; h < 7.0; h+=1.0) {\\n' +\n            'for (float w = 0.0; w < 7.0; w+=1.0) {\\n' +\n              'vec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\\n' +\n              'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 7.0 + w)];\\n' +\n            '}\\n' +\n          '}\\n' +\n          'float alpha = texture2D(uTexture, vTexCoord).a;\\n' +\n          'gl_FragColor = color;\\n' +\n          'gl_FragColor.a = alpha;\\n' +\n        '}',\n      Convolute_9_1: 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'uniform float uMatrix[81];\\n' +\n        'uniform float uStepW;\\n' +\n        'uniform float uStepH;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'void main() {\\n' +\n          'vec4 color = vec4(0, 0, 0, 0);\\n' +\n          'for (float h = 0.0; h < 9.0; h+=1.0) {\\n' +\n            'for (float w = 0.0; w < 9.0; w+=1.0) {\\n' +\n              'vec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\\n' +\n              'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 9.0 + w)];\\n' +\n            '}\\n' +\n          '}\\n' +\n          'gl_FragColor = color;\\n' +\n        '}',\n      Convolute_9_0: 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'uniform float uMatrix[81];\\n' +\n        'uniform float uStepW;\\n' +\n        'uniform float uStepH;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'void main() {\\n' +\n          'vec4 color = vec4(0, 0, 0, 1);\\n' +\n          'for (float h = 0.0; h < 9.0; h+=1.0) {\\n' +\n            'for (float w = 0.0; w < 9.0; w+=1.0) {\\n' +\n              'vec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\\n' +\n              'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 9.0 + w)];\\n' +\n            '}\\n' +\n          '}\\n' +\n          'float alpha = texture2D(uTexture, vTexCoord).a;\\n' +\n          'gl_FragColor = color;\\n' +\n          'gl_FragColor.a = alpha;\\n' +\n        '}',\n    },\n\n    /**\n     * Constructor\n     * @memberOf fabric.Image.filters.Convolute.prototype\n     * @param {Object} [options] Options object\n     * @param {Boolean} [options.opaque=false] Opaque value (true/false)\n     * @param {Array} [options.matrix] Filter matrix\n     */\n\n\n    /**\n    * Retrieves the cached shader.\n    * @param {Object} options\n    * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n    * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n    */\n    retrieveShader: function(options) {\n      var size = Math.sqrt(this.matrix.length);\n      var cacheKey = this.type + '_' + size + '_' + (this.opaque ? 1 : 0);\n      var shaderSource = this.fragmentSource[cacheKey];\n      if (!options.programCache.hasOwnProperty(cacheKey)) {\n        options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\n      }\n      return options.programCache[cacheKey];\n    },\n\n    /**\n     * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n     */\n    applyTo2d: function(options) {\n      var imageData = options.imageData,\n          data = imageData.data,\n          weights = this.matrix,\n          side = Math.round(Math.sqrt(weights.length)),\n          halfSide = Math.floor(side / 2),\n          sw = imageData.width,\n          sh = imageData.height,\n          output = options.ctx.createImageData(sw, sh),\n          dst = output.data,\n          // go through the destination image pixels\n          alphaFac = this.opaque ? 1 : 0,\n          r, g, b, a, dstOff,\n          scx, scy, srcOff, wt,\n          x, y, cx, cy;\n\n      for (y = 0; y < sh; y++) {\n        for (x = 0; x < sw; x++) {\n          dstOff = (y * sw + x) * 4;\n          // calculate the weighed sum of the source image pixels that\n          // fall under the convolution matrix\n          r = 0; g = 0; b = 0; a = 0;\n\n          for (cy = 0; cy < side; cy++) {\n            for (cx = 0; cx < side; cx++) {\n              scy = y + cy - halfSide;\n              scx = x + cx - halfSide;\n\n              // eslint-disable-next-line max-depth\n              if (scy < 0 || scy >= sh || scx < 0 || scx >= sw) {\n                continue;\n              }\n\n              srcOff = (scy * sw + scx) * 4;\n              wt = weights[cy * side + cx];\n\n              r += data[srcOff] * wt;\n              g += data[srcOff + 1] * wt;\n              b += data[srcOff + 2] * wt;\n              // eslint-disable-next-line max-depth\n              if (!alphaFac) {\n                a += data[srcOff + 3] * wt;\n              }\n            }\n          }\n          dst[dstOff] = r;\n          dst[dstOff + 1] = g;\n          dst[dstOff + 2] = b;\n          if (!alphaFac) {\n            dst[dstOff + 3] = a;\n          }\n          else {\n            dst[dstOff + 3] = data[dstOff + 3];\n          }\n        }\n      }\n      options.imageData = output;\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uMatrix: gl.getUniformLocation(program, 'uMatrix'),\n        uOpaque: gl.getUniformLocation(program, 'uOpaque'),\n        uHalfSize: gl.getUniformLocation(program, 'uHalfSize'),\n        uSize: gl.getUniformLocation(program, 'uSize'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      gl.uniform1fv(uniformLocations.uMatrix, this.matrix);\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function() {\n      return extend(this.callSuper('toObject'), {\n        opaque: this.opaque,\n        matrix: this.matrix\n      });\n    }\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Convolute} Instance of fabric.Image.filters.Convolute\n   */\n  fabric.Image.filters.Convolute.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Grayscale image filter class\n   * @class fabric.Image.filters.Grayscale\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Grayscale();\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n  filters.Grayscale = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Grayscale.prototype */ {\n\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Grayscale',\n\n    fragmentSource: {\n      average: 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'void main() {\\n' +\n          'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n          'float average = (color.r + color.b + color.g) / 3.0;\\n' +\n          'gl_FragColor = vec4(average, average, average, color.a);\\n' +\n        '}',\n      lightness: 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'uniform int uMode;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'void main() {\\n' +\n          'vec4 col = texture2D(uTexture, vTexCoord);\\n' +\n          'float average = (max(max(col.r, col.g),col.b) + min(min(col.r, col.g),col.b)) / 2.0;\\n' +\n          'gl_FragColor = vec4(average, average, average, col.a);\\n' +\n        '}',\n      luminosity: 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'uniform int uMode;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'void main() {\\n' +\n          'vec4 col = texture2D(uTexture, vTexCoord);\\n' +\n          'float average = 0.21 * col.r + 0.72 * col.g + 0.07 * col.b;\\n' +\n          'gl_FragColor = vec4(average, average, average, col.a);\\n' +\n        '}',\n    },\n\n\n    /**\n     * Grayscale mode, between 'average', 'lightness', 'luminosity'\n     * @param {String} type\n     * @default\n     */\n    mode: 'average',\n\n    mainParameter: 'mode',\n\n    /**\n     * Apply the Grayscale operation to a Uint8Array representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8Array to be filtered.\n     */\n    applyTo2d: function(options) {\n      var imageData = options.imageData,\n          data = imageData.data, i,\n          len = data.length, value,\n          mode = this.mode;\n      for (i = 0; i < len; i += 4) {\n        if (mode === 'average') {\n          value = (data[i] + data[i + 1] + data[i + 2]) / 3;\n        }\n        else if (mode === 'lightness') {\n          value = (Math.min(data[i], data[i + 1], data[i + 2]) +\n            Math.max(data[i], data[i + 1], data[i + 2])) / 2;\n        }\n        else if (mode === 'luminosity') {\n          value = 0.21 * data[i] + 0.72 * data[i + 1] + 0.07 * data[i + 2];\n        }\n        data[i] = value;\n        data[i + 1] = value;\n        data[i + 2] = value;\n      }\n    },\n\n    /**\n     * Retrieves the cached shader.\n     * @param {Object} options\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    retrieveShader: function(options) {\n      var cacheKey = this.type + '_' + this.mode;\n      if (!options.programCache.hasOwnProperty(cacheKey)) {\n        var shaderSource = this.fragmentSource[this.mode];\n        options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\n      }\n      return options.programCache[cacheKey];\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uMode: gl.getUniformLocation(program, 'uMode'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      // default average mode.\n      var mode = 1;\n      gl.uniform1i(uniformLocations.uMode, mode);\n    },\n\n    /**\n     * Grayscale filter isNeutralState implementation\n     * The filter is never neutral\n     * on the image\n     **/\n    isNeutralState: function() {\n      return false;\n    },\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Grayscale} Instance of fabric.Image.filters.Grayscale\n   */\n  fabric.Image.filters.Grayscale.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Invert filter class\n   * @class fabric.Image.filters.Invert\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Invert();\n   * object.filters.push(filter);\n   * object.applyFilters(canvas.renderAll.bind(canvas));\n   */\n  filters.Invert = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Invert.prototype */ {\n\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Invert',\n\n    fragmentSource: 'precision highp float;\\n' +\n      'uniform sampler2D uTexture;\\n' +\n      'uniform int uInvert;\\n' +\n      'varying vec2 vTexCoord;\\n' +\n      'void main() {\\n' +\n        'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n        'if (uInvert == 1) {\\n' +\n          'gl_FragColor = vec4(1.0 - color.r,1.0 -color.g,1.0 -color.b,color.a);\\n' +\n        '} else {\\n' +\n          'gl_FragColor = color;\\n' +\n        '}\\n' +\n      '}',\n\n    /**\n     * Filter invert. if false, does nothing\n     * @param {Boolean} invert\n     * @default\n     */\n    invert: true,\n\n    mainParameter: 'invert',\n\n    /**\n     * Apply the Invert operation to a Uint8Array representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8Array to be filtered.\n     */\n    applyTo2d: function(options) {\n      var imageData = options.imageData,\n          data = imageData.data, i,\n          len = data.length;\n      for (i = 0; i < len; i += 4) {\n        data[i] = 255 - data[i];\n        data[i + 1] = 255 - data[i + 1];\n        data[i + 2] = 255 - data[i + 2];\n      }\n    },\n\n    /**\n     * Invert filter isNeutralState implementation\n     * Used only in image applyFilters to discard filters that will not have an effect\n     * on the image\n     * @param {Object} options\n     **/\n    isNeutralState: function() {\n      return !this.invert;\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uInvert: gl.getUniformLocation(program, 'uInvert'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      gl.uniform1i(uniformLocations.uInvert, this.invert);\n    },\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Invert} Instance of fabric.Image.filters.Invert\n   */\n  fabric.Image.filters.Invert.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      extend = fabric.util.object.extend,\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Noise filter class\n   * @class fabric.Image.filters.Noise\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Noise#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Noise({\n   *   noise: 700\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   */\n  filters.Noise = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Noise.prototype */ {\n\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Noise',\n\n    /**\n     * Fragment source for the noise program\n     */\n    fragmentSource: 'precision highp float;\\n' +\n      'uniform sampler2D uTexture;\\n' +\n      'uniform float uStepH;\\n' +\n      'uniform float uNoise;\\n' +\n      'uniform float uSeed;\\n' +\n      'varying vec2 vTexCoord;\\n' +\n      'float rand(vec2 co, float seed, float vScale) {\\n' +\n        'return fract(sin(dot(co.xy * vScale ,vec2(12.9898 , 78.233))) * 43758.5453 * (seed + 0.01) / 2.0);\\n' +\n      '}\\n' +\n      'void main() {\\n' +\n        'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n        'color.rgb += (0.5 - rand(vTexCoord, uSeed, 0.1 / uStepH)) * uNoise;\\n' +\n        'gl_FragColor = color;\\n' +\n      '}',\n\n    /**\n     * Describe the property that is the filter parameter\n     * @param {String} m\n     * @default\n     */\n    mainParameter: 'noise',\n\n    /**\n     * Noise value, from\n     * @param {Number} noise\n     * @default\n     */\n    noise: 0,\n\n    /**\n     * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n     */\n    applyTo2d: function(options) {\n      if (this.noise === 0) {\n        return;\n      }\n      var imageData = options.imageData,\n          data = imageData.data, i, len = data.length,\n          noise = this.noise, rand;\n\n      for (i = 0, len = data.length; i < len; i += 4) {\n\n        rand = (0.5 - Math.random()) * noise;\n\n        data[i] += rand;\n        data[i + 1] += rand;\n        data[i + 2] += rand;\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uNoise: gl.getUniformLocation(program, 'uNoise'),\n        uSeed: gl.getUniformLocation(program, 'uSeed'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      gl.uniform1f(uniformLocations.uNoise, this.noise / 255);\n      gl.uniform1f(uniformLocations.uSeed, Math.random());\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function() {\n      return extend(this.callSuper('toObject'), {\n        noise: this.noise\n      });\n    }\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Noise} Instance of fabric.Image.filters.Noise\n   */\n  fabric.Image.filters.Noise.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Pixelate filter class\n   * @class fabric.Image.filters.Pixelate\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Pixelate#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Pixelate({\n   *   blocksize: 8\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n  filters.Pixelate = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Pixelate.prototype */ {\n\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Pixelate',\n\n    blocksize: 4,\n\n    mainParameter: 'blocksize',\n\n    /**\n     * Fragment source for the Pixelate program\n     */\n    fragmentSource: 'precision highp float;\\n' +\n      'uniform sampler2D uTexture;\\n' +\n      'uniform float uBlocksize;\\n' +\n      'uniform float uStepW;\\n' +\n      'uniform float uStepH;\\n' +\n      'varying vec2 vTexCoord;\\n' +\n      'void main() {\\n' +\n        'float blockW = uBlocksize * uStepW;\\n' +\n        'float blockH = uBlocksize * uStepW;\\n' +\n        'int posX = int(vTexCoord.x / blockW);\\n' +\n        'int posY = int(vTexCoord.y / blockH);\\n' +\n        'float fposX = float(posX);\\n' +\n        'float fposY = float(posY);\\n' +\n        'vec2 squareCoords = vec2(fposX * blockW, fposY * blockH);\\n' +\n        'vec4 color = texture2D(uTexture, squareCoords);\\n' +\n        'gl_FragColor = color;\\n' +\n      '}',\n\n    /**\n     * Apply the Pixelate operation to a Uint8ClampedArray representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n     */\n    applyTo2d: function(options) {\n      var imageData = options.imageData,\n          data = imageData.data,\n          iLen = imageData.height,\n          jLen = imageData.width,\n          index, i, j, r, g, b, a,\n          _i, _j, _iLen, _jLen;\n\n      for (i = 0; i < iLen; i += this.blocksize) {\n        for (j = 0; j < jLen; j += this.blocksize) {\n\n          index = (i * 4) * jLen + (j * 4);\n\n          r = data[index];\n          g = data[index + 1];\n          b = data[index + 2];\n          a = data[index + 3];\n\n          _iLen = Math.min(i + this.blocksize, iLen);\n          _jLen = Math.min(j + this.blocksize, jLen);\n          for (_i = i; _i < _iLen; _i++) {\n            for (_j = j; _j < _jLen; _j++) {\n              index = (_i * 4) * jLen + (_j * 4);\n              data[index] = r;\n              data[index + 1] = g;\n              data[index + 2] = b;\n              data[index + 3] = a;\n            }\n          }\n        }\n      }\n    },\n\n    /**\n     * Indicate when the filter is not gonna apply changes to the image\n     **/\n    isNeutralState: function() {\n      return this.blocksize === 1;\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uBlocksize: gl.getUniformLocation(program, 'uBlocksize'),\n        uStepW: gl.getUniformLocation(program, 'uStepW'),\n        uStepH: gl.getUniformLocation(program, 'uStepH'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      gl.uniform1f(uniformLocations.uBlocksize, this.blocksize);\n    },\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Pixelate} Instance of fabric.Image.filters.Pixelate\n   */\n  fabric.Image.filters.Pixelate.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      extend = fabric.util.object.extend,\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Remove white filter class\n   * @class fabric.Image.filters.RemoveColor\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.RemoveColor#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.RemoveColor({\n   *   threshold: 0.2,\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   */\n  filters.RemoveColor = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.RemoveColor.prototype */ {\n\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'RemoveColor',\n\n    /**\n     * Color to remove, in any format understood by fabric.Color.\n     * @param {String} type\n     * @default\n     */\n    color: '#FFFFFF',\n\n    /**\n     * Fragment source for the brightness program\n     */\n    fragmentSource: 'precision highp float;\\n' +\n      'uniform sampler2D uTexture;\\n' +\n      'uniform vec4 uLow;\\n' +\n      'uniform vec4 uHigh;\\n' +\n      'varying vec2 vTexCoord;\\n' +\n      'void main() {\\n' +\n        'gl_FragColor = texture2D(uTexture, vTexCoord);\\n' +\n        'if(all(greaterThan(gl_FragColor.rgb,uLow.rgb)) && all(greaterThan(uHigh.rgb,gl_FragColor.rgb))) {\\n' +\n          'gl_FragColor.a = 0.0;\\n' +\n        '}\\n' +\n      '}',\n\n    /**\n     * distance to actual color, as value up or down from each r,g,b\n     * between 0 and 1\n     **/\n    distance: 0.02,\n\n    /**\n     * For color to remove inside distance, use alpha channel for a smoother deletion\n     * NOT IMPLEMENTED YET\n     **/\n    useAlpha: false,\n\n    /**\n     * Constructor\n     * @memberOf fabric.Image.filters.RemoveWhite.prototype\n     * @param {Object} [options] Options object\n     * @param {Number} [options.color=#RRGGBB] Threshold value\n     * @param {Number} [options.distance=10] Distance value\n     */\n\n    /**\n     * Applies filter to canvas element\n     * @param {Object} canvasEl Canvas element to apply filter to\n     */\n    applyTo2d: function(options) {\n      var imageData = options.imageData,\n          data = imageData.data, i,\n          distance = this.distance * 255,\n          r, g, b,\n          source = new fabric.Color(this.color).getSource(),\n          lowC = [\n            source[0] - distance,\n            source[1] - distance,\n            source[2] - distance,\n          ],\n          highC = [\n            source[0] + distance,\n            source[1] + distance,\n            source[2] + distance,\n          ];\n\n\n      for (i = 0; i < data.length; i += 4) {\n        r = data[i];\n        g = data[i + 1];\n        b = data[i + 2];\n\n        if (r > lowC[0] &&\n            g > lowC[1] &&\n            b > lowC[2] &&\n            r < highC[0] &&\n            g < highC[1] &&\n            b < highC[2]) {\n          data[i + 3] = 0;\n        }\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uLow: gl.getUniformLocation(program, 'uLow'),\n        uHigh: gl.getUniformLocation(program, 'uHigh'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      var source = new fabric.Color(this.color).getSource(),\n          distance = parseFloat(this.distance),\n          lowC = [\n            0 + source[0] / 255 - distance,\n            0 + source[1] / 255 - distance,\n            0 + source[2] / 255 - distance,\n            1\n          ],\n          highC = [\n            source[0] / 255 + distance,\n            source[1] / 255 + distance,\n            source[2] / 255 + distance,\n            1\n          ];\n      gl.uniform4fv(uniformLocations.uLow, lowC);\n      gl.uniform4fv(uniformLocations.uHigh, highC);\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function() {\n      return extend(this.callSuper('toObject'), {\n        color: this.color,\n        distance: this.distance\n      });\n    }\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.RemoveColor} Instance of fabric.Image.filters.RemoveWhite\n   */\n  fabric.Image.filters.RemoveColor.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  var matrices = {\n    Brownie: [\n      0.59970,0.34553,-0.27082,0,0.186,\n      -0.03770,0.86095,0.15059,0,-0.1449,\n      0.24113,-0.07441,0.44972,0,-0.02965,\n      0,0,0,1,0\n    ],\n    Vintage: [\n      0.62793,0.32021,-0.03965,0,0.03784,\n      0.02578,0.64411,0.03259,0,0.02926,\n      0.04660,-0.08512,0.52416,0,0.02023,\n      0,0,0,1,0\n    ],\n    Kodachrome: [\n      1.12855,-0.39673,-0.03992,0,0.24991,\n      -0.16404,1.08352,-0.05498,0,0.09698,\n      -0.16786,-0.56034,1.60148,0,0.13972,\n      0,0,0,1,0\n    ],\n    Technicolor: [\n      1.91252,-0.85453,-0.09155,0,0.04624,\n      -0.30878,1.76589,-0.10601,0,-0.27589,\n      -0.23110,-0.75018,1.84759,0,0.12137,\n      0,0,0,1,0\n    ],\n    Polaroid: [\n      1.438,-0.062,-0.062,0,0,\n      -0.122,1.378,-0.122,0,0,\n      -0.016,-0.016,1.483,0,0,\n      0,0,0,1,0\n    ],\n    Sepia: [\n      0.393, 0.769, 0.189, 0, 0,\n      0.349, 0.686, 0.168, 0, 0,\n      0.272, 0.534, 0.131, 0, 0,\n      0, 0, 0, 1, 0\n    ],\n    BlackWhite: [\n      1.5, 1.5, 1.5, 0, -1,\n      1.5, 1.5, 1.5, 0, -1,\n      1.5, 1.5, 1.5, 0, -1,\n      0, 0, 0, 1, 0,\n    ]\n  };\n\n  for (var key in matrices) {\n    filters[key] = createClass(filters.ColorMatrix, /** @lends fabric.Image.filters.Sepia.prototype */ {\n\n      /**\n       * Filter type\n       * @param {String} type\n       * @default\n       */\n      type: key,\n\n      /**\n       * Colormatrix for the effect\n       * array of 20 floats. Numbers in positions 4, 9, 14, 19 loose meaning\n       * outside the -1, 1 range.\n       * @param {Array} matrix array of 20 numbers.\n       * @default\n       */\n      matrix: matrices[key],\n\n      /**\n       * Lock the matrix export for this kind of static, parameter less filters.\n       */\n      mainParameter: false,\n      /**\n       * Lock the colormatrix on the color part, skipping alpha\n       */\n      colorsOnly: true,\n\n    });\n    fabric.Image.filters[key].fromObject = fabric.Image.filters.BaseFilter.fromObject;\n  }\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n  'use strict';\n\n  var fabric = global.fabric,\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Color Blend filter class\n   * @class fabric.Image.filter.BlendColor\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @example\n   * var filter = new fabric.Image.filters.BlendColor({\n   *  color: '#000',\n   *  mode: 'multiply'\n   * });\n   *\n   * var filter = new fabric.Image.filters.BlendImage({\n   *  image: fabricImageObject,\n   *  mode: 'multiply',\n   *  alpha: 0.5\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   */\n\n  filters.BlendColor = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Blend.prototype */ {\n    type: 'BlendColor',\n\n    /**\n     * Color to make the blend operation with. default to a reddish color since black or white\n     * gives always strong result.\n     **/\n    color: '#F95C63',\n\n    /**\n     * Blend mode for the filter: one of multiply, add, diff, screen, subtract,\n     * darken, lighten, overlay, exclusion, tint.\n     **/\n    mode: 'multiply',\n\n    /**\n     * alpha value. represent the strength of the blend color operation.\n     **/\n    alpha: 1,\n\n    /**\n     * Fragment source for the Multiply program\n     */\n    fragmentSource: {\n      multiply: 'gl_FragColor.rgb *= uColor.rgb;\\n',\n      screen: 'gl_FragColor.rgb = 1.0 - (1.0 - gl_FragColor.rgb) * (1.0 - uColor.rgb);\\n',\n      add: 'gl_FragColor.rgb += uColor.rgb;\\n',\n      diff: 'gl_FragColor.rgb = abs(gl_FragColor.rgb - uColor.rgb);\\n',\n      subtract: 'gl_FragColor.rgb -= uColor.rgb;\\n',\n      lighten: 'gl_FragColor.rgb = max(gl_FragColor.rgb, uColor.rgb);\\n',\n      darken: 'gl_FragColor.rgb = min(gl_FragColor.rgb, uColor.rgb);\\n',\n      exclusion: 'gl_FragColor.rgb += uColor.rgb - 2.0 * (uColor.rgb * gl_FragColor.rgb);\\n',\n      overlay: 'if (uColor.r < 0.5) {\\n' +\n          'gl_FragColor.r *= 2.0 * uColor.r;\\n' +\n        '} else {\\n' +\n          'gl_FragColor.r = 1.0 - 2.0 * (1.0 - gl_FragColor.r) * (1.0 - uColor.r);\\n' +\n        '}\\n' +\n        'if (uColor.g < 0.5) {\\n' +\n          'gl_FragColor.g *= 2.0 * uColor.g;\\n' +\n        '} else {\\n' +\n          'gl_FragColor.g = 1.0 - 2.0 * (1.0 - gl_FragColor.g) * (1.0 - uColor.g);\\n' +\n        '}\\n' +\n        'if (uColor.b < 0.5) {\\n' +\n          'gl_FragColor.b *= 2.0 * uColor.b;\\n' +\n        '} else {\\n' +\n          'gl_FragColor.b = 1.0 - 2.0 * (1.0 - gl_FragColor.b) * (1.0 - uColor.b);\\n' +\n        '}\\n',\n      tint: 'gl_FragColor.rgb *= (1.0 - uColor.a);\\n' +\n        'gl_FragColor.rgb += uColor.rgb;\\n',\n    },\n\n    /**\n     * build the fragment source for the filters, joining the common part with\n     * the specific one.\n     * @param {String} mode the mode of the filter, a key of this.fragmentSource\n     * @return {String} the source to be compiled\n     * @private\n     */\n    buildSource: function(mode) {\n      return 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'uniform vec4 uColor;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'void main() {\\n' +\n          'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n          'gl_FragColor = color;\\n' +\n          'if (color.a > 0.0) {\\n' +\n            this.fragmentSource[mode] +\n          '}\\n' +\n        '}';\n    },\n\n    /**\n     * Retrieves the cached shader.\n     * @param {Object} options\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    retrieveShader: function(options) {\n      var cacheKey = this.type + '_' + this.mode, shaderSource;\n      if (!options.programCache.hasOwnProperty(cacheKey)) {\n        shaderSource = this.buildSource(this.mode);\n        options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\n      }\n      return options.programCache[cacheKey];\n    },\n\n    /**\n     * Apply the Blend operation to a Uint8ClampedArray representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n     */\n    applyTo2d: function(options) {\n      var imageData = options.imageData,\n          data = imageData.data, iLen = data.length,\n          tr, tg, tb,\n          r, g, b,\n          source, alpha1 = 1 - this.alpha;\n\n      source = new fabric.Color(this.color).getSource();\n      tr = source[0] * this.alpha;\n      tg = source[1] * this.alpha;\n      tb = source[2] * this.alpha;\n\n      for (var i = 0; i < iLen; i += 4) {\n\n        r = data[i];\n        g = data[i + 1];\n        b = data[i + 2];\n\n        switch (this.mode) {\n          case 'multiply':\n            data[i] = r * tr / 255;\n            data[i + 1] = g * tg / 255;\n            data[i + 2] = b * tb / 255;\n            break;\n          case 'screen':\n            data[i] = 255 - (255 - r) * (255 - tr) / 255;\n            data[i + 1] = 255 - (255 - g) * (255 - tg) / 255;\n            data[i + 2] = 255 - (255 - b) * (255 - tb) / 255;\n            break;\n          case 'add':\n            data[i] = r + tr;\n            data[i + 1] = g + tg;\n            data[i + 2] = b + tb;\n            break;\n          case 'diff':\n          case 'difference':\n            data[i] = Math.abs(r - tr);\n            data[i + 1] = Math.abs(g - tg);\n            data[i + 2] = Math.abs(b - tb);\n            break;\n          case 'subtract':\n            data[i] = r - tr;\n            data[i + 1] = g - tg;\n            data[i + 2] = b - tb;\n            break;\n          case 'darken':\n            data[i] = Math.min(r, tr);\n            data[i + 1] = Math.min(g, tg);\n            data[i + 2] = Math.min(b, tb);\n            break;\n          case 'lighten':\n            data[i] = Math.max(r, tr);\n            data[i + 1] = Math.max(g, tg);\n            data[i + 2] = Math.max(b, tb);\n            break;\n          case 'overlay':\n            data[i] = tr < 128 ? (2 * r * tr / 255) : (255 - 2 * (255 - r) * (255 - tr) / 255);\n            data[i + 1] = tg < 128 ? (2 * g * tg / 255) : (255 - 2 * (255 - g) * (255 - tg) / 255);\n            data[i + 2] = tb < 128 ? (2 * b * tb / 255) : (255 - 2 * (255 - b) * (255 - tb) / 255);\n            break;\n          case 'exclusion':\n            data[i] = tr + r - ((2 * tr * r) / 255);\n            data[i + 1] = tg + g - ((2 * tg * g) / 255);\n            data[i + 2] = tb + b - ((2 * tb * b) / 255);\n            break;\n          case 'tint':\n            data[i] = tr + r * alpha1;\n            data[i + 1] = tg + g * alpha1;\n            data[i + 2] = tb + b * alpha1;\n        }\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uColor: gl.getUniformLocation(program, 'uColor'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      var source = new fabric.Color(this.color).getSource();\n      source[0] = this.alpha * source[0] / 255;\n      source[1] = this.alpha * source[1] / 255;\n      source[2] = this.alpha * source[2] / 255;\n      source[3] = this.alpha;\n      gl.uniform4fv(uniformLocations.uColor, source);\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function() {\n      return {\n        type: this.type,\n        color: this.color,\n        mode: this.mode,\n        alpha: this.alpha\n      };\n    }\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.BlendColor} Instance of fabric.Image.filters.BlendColor\n   */\n  fabric.Image.filters.BlendColor.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n  'use strict';\n\n  var fabric = global.fabric,\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Image Blend filter class\n   * @class fabric.Image.filter.BlendImage\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @example\n   * var filter = new fabric.Image.filters.BlendColor({\n   *  color: '#000',\n   *  mode: 'multiply'\n   * });\n   *\n   * var filter = new fabric.Image.filters.BlendImage({\n   *  image: fabricImageObject,\n   *  mode: 'multiply',\n   *  alpha: 0.5\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   */\n\n  filters.BlendImage = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.BlendImage.prototype */ {\n    type: 'BlendImage',\n\n    /**\n     * Color to make the blend operation with. default to a reddish color since black or white\n     * gives always strong result.\n     **/\n    image: null,\n\n    /**\n     * Blend mode for the filter: one of multiply, add, diff, screen, subtract,\n     * darken, lighten, overlay, exclusion, tint.\n     **/\n    mode: 'multiply',\n\n    /**\n     * alpha value. represent the strength of the blend image operation.\n     * not implemented.\n     **/\n    alpha: 1,\n\n    vertexSource: 'attribute vec2 aPosition;\\n' +\n      'varying vec2 vTexCoord;\\n' +\n      'varying vec2 vTexCoord2;\\n' +\n      'uniform mat3 uTransformMatrix;\\n' +\n      'void main() {\\n' +\n        'vTexCoord = aPosition;\\n' +\n        'vTexCoord2 = (uTransformMatrix * vec3(aPosition, 1.0)).xy;\\n' +\n        'gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\\n' +\n      '}',\n\n    /**\n     * Fragment source for the Multiply program\n     */\n    fragmentSource: {\n      multiply: 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'uniform sampler2D uImage;\\n' +\n        'uniform vec4 uColor;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'varying vec2 vTexCoord2;\\n' +\n        'void main() {\\n' +\n          'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n          'vec4 color2 = texture2D(uImage, vTexCoord2);\\n' +\n          'color.rgba *= color2.rgba;\\n' +\n          'gl_FragColor = color;\\n' +\n        '}',\n      mask: 'precision highp float;\\n' +\n        'uniform sampler2D uTexture;\\n' +\n        'uniform sampler2D uImage;\\n' +\n        'uniform vec4 uColor;\\n' +\n        'varying vec2 vTexCoord;\\n' +\n        'varying vec2 vTexCoord2;\\n' +\n        'void main() {\\n' +\n          'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n          'vec4 color2 = texture2D(uImage, vTexCoord2);\\n' +\n          'color.a = color2.a;\\n' +\n          'gl_FragColor = color;\\n' +\n        '}',\n    },\n\n    /**\n     * Retrieves the cached shader.\n     * @param {Object} options\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    retrieveShader: function(options) {\n      var cacheKey = this.type + '_' + this.mode;\n      var shaderSource = this.fragmentSource[this.mode];\n      if (!options.programCache.hasOwnProperty(cacheKey)) {\n        options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\n      }\n      return options.programCache[cacheKey];\n    },\n\n    applyToWebGL: function(options) {\n      // load texture to blend.\n      var gl = options.context,\n          texture = this.createTexture(options.filterBackend, this.image);\n      this.bindAdditionalTexture(gl, texture, gl.TEXTURE1);\n      this.callSuper('applyToWebGL', options);\n      this.unbindAdditionalTexture(gl, gl.TEXTURE1);\n    },\n\n    createTexture: function(backend, image) {\n      return backend.getCachedTexture(image.cacheKey, image._element);\n    },\n\n    /**\n     * Calculate a transformMatrix to adapt the image to blend over\n     * @param {Object} options\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    calculateMatrix: function() {\n      var image = this.image,\n          width = image._element.width,\n          height = image._element.height;\n      return [\n        1 / image.scaleX, 0, 0,\n        0, 1 / image.scaleY, 0,\n        -image.left / width, -image.top / height, 1\n      ];\n    },\n\n    /**\n     * Apply the Blend operation to a Uint8ClampedArray representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n     */\n    applyTo2d: function(options) {\n      var imageData = options.imageData,\n          resources = options.filterBackend.resources,\n          data = imageData.data, iLen = data.length,\n          width = imageData.width,\n          height = imageData.height,\n          tr, tg, tb, ta,\n          r, g, b, a,\n          canvas1, context, image = this.image, blendData;\n\n      if (!resources.blendImage) {\n        resources.blendImage = fabric.util.createCanvasElement();\n      }\n      canvas1 = resources.blendImage;\n      context = canvas1.getContext('2d');\n      if (canvas1.width !== width || canvas1.height !== height) {\n        canvas1.width = width;\n        canvas1.height = height;\n      }\n      else {\n        context.clearRect(0, 0, width, height);\n      }\n      context.setTransform(image.scaleX, 0, 0, image.scaleY, image.left, image.top);\n      context.drawImage(image._element, 0, 0, width, height);\n      blendData = context.getImageData(0, 0, width, height).data;\n      for (var i = 0; i < iLen; i += 4) {\n\n        r = data[i];\n        g = data[i + 1];\n        b = data[i + 2];\n        a = data[i + 3];\n\n        tr = blendData[i];\n        tg = blendData[i + 1];\n        tb = blendData[i + 2];\n        ta = blendData[i + 3];\n\n        switch (this.mode) {\n          case 'multiply':\n            data[i] = r * tr / 255;\n            data[i + 1] = g * tg / 255;\n            data[i + 2] = b * tb / 255;\n            data[i + 3] = a * ta / 255;\n            break;\n          case 'mask':\n            data[i + 3] = ta;\n            break;\n        }\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uTransformMatrix: gl.getUniformLocation(program, 'uTransformMatrix'),\n        uImage: gl.getUniformLocation(program, 'uImage'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      var matrix = this.calculateMatrix();\n      gl.uniform1i(uniformLocations.uImage, 1); // texture unit 1.\n      gl.uniformMatrix3fv(uniformLocations.uTransformMatrix, false, matrix);\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function() {\n      return {\n        type: this.type,\n        image: this.image && this.image.toObject(),\n        mode: this.mode,\n        alpha: this.alpha\n      };\n    }\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} callback to be invoked after filter creation\n   * @return {fabric.Image.filters.BlendImage} Instance of fabric.Image.filters.BlendImage\n   */\n  fabric.Image.filters.BlendImage.fromObject = function(object, callback) {\n    fabric.Image.fromObject(object.image, function(image) {\n      var options = fabric.util.object.clone(object);\n      options.image = image;\n      callback(new fabric.Image.filters.BlendImage(options));\n    });\n  };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }), pow = Math.pow, floor = Math.floor,\n      sqrt = Math.sqrt, abs = Math.abs, round = Math.round, sin = Math.sin,\n      ceil = Math.ceil,\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Resize image filter class\n   * @class fabric.Image.filters.Resize\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Resize();\n   * object.filters.push(filter);\n   * object.applyFilters(canvas.renderAll.bind(canvas));\n   */\n  filters.Resize = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Resize.prototype */ {\n\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Resize',\n\n    /**\n     * Resize type\n     * for webgl resizeType is just lanczos, for canvas2d can be:\n     * bilinear, hermite, sliceHack, lanczos.\n     * @param {String} resizeType\n     * @default\n     */\n    resizeType: 'hermite',\n\n    /**\n     * Scale factor for resizing, x axis\n     * @param {Number} scaleX\n     * @default\n     */\n    scaleX: 1,\n\n    /**\n     * Scale factor for resizing, y axis\n     * @param {Number} scaleY\n     * @default\n     */\n    scaleY: 1,\n\n    /**\n     * LanczosLobes parameter for lanczos filter, valid for resizeType lanczos\n     * @param {Number} lanczosLobes\n     * @default\n     */\n    lanczosLobes: 3,\n\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uDelta: gl.getUniformLocation(program, 'uDelta'),\n        uTaps: gl.getUniformLocation(program, 'uTaps'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      gl.uniform2fv(uniformLocations.uDelta, this.horizontal ? [1 / this.width, 0] : [0, 1 / this.height]);\n      gl.uniform1fv(uniformLocations.uTaps, this.taps);\n    },\n\n    /**\n     * Retrieves the cached shader.\n     * @param {Object} options\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    retrieveShader: function(options) {\n      var filterWindow = this.getFilterWindow(), cacheKey = this.type + '_' + filterWindow;\n      if (!options.programCache.hasOwnProperty(cacheKey)) {\n        var fragmentShader = this.generateShader(filterWindow);\n        options.programCache[cacheKey] = this.createProgram(options.context, fragmentShader);\n      }\n      return options.programCache[cacheKey];\n    },\n\n    getFilterWindow: function() {\n      var scale = this.tempScale;\n      return Math.ceil(this.lanczosLobes / scale);\n    },\n\n    getTaps: function() {\n      var lobeFunction = this.lanczosCreate(this.lanczosLobes), scale = this.tempScale,\n          filterWindow = this.getFilterWindow(), taps = new Array(filterWindow);\n      for (var i = 1; i <= filterWindow; i++) {\n        taps[i - 1] = lobeFunction(i * scale);\n      }\n      return taps;\n    },\n\n    /**\n     * Generate vertex and shader sources from the necessary steps numbers\n     * @param {Number} filterWindow\n     */\n    generateShader: function(filterWindow) {\n      var offsets = new Array(filterWindow),\n          fragmentShader = this.fragmentSourceTOP, filterWindow;\n\n      for (var i = 1; i <= filterWindow; i++) {\n        offsets[i - 1] = i + '.0 * uDelta';\n      }\n\n      fragmentShader += 'uniform float uTaps[' + filterWindow + '];\\n';\n      fragmentShader += 'void main() {\\n';\n      fragmentShader += '  vec4 color = texture2D(uTexture, vTexCoord);\\n';\n      fragmentShader += '  float sum = 1.0;\\n';\n\n      offsets.forEach(function(offset, i) {\n        fragmentShader += '  color += texture2D(uTexture, vTexCoord + ' + offset + ') * uTaps[' + i + '];\\n';\n        fragmentShader += '  color += texture2D(uTexture, vTexCoord - ' + offset + ') * uTaps[' + i + '];\\n';\n        fragmentShader += '  sum += 2.0 * uTaps[' + i + '];\\n';\n      });\n      fragmentShader += '  gl_FragColor = color / sum;\\n';\n      fragmentShader += '}';\n      return fragmentShader;\n    },\n\n    fragmentSourceTOP: 'precision highp float;\\n' +\n      'uniform sampler2D uTexture;\\n' +\n      'uniform vec2 uDelta;\\n' +\n      'varying vec2 vTexCoord;\\n',\n\n    /**\n     * Apply the resize filter to the image\n     * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\n     *\n     * @param {Object} options\n     * @param {Number} options.passes The number of filters remaining to be executed\n     * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n     * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n     * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    applyTo: function(options) {\n      if (options.webgl) {\n        options.passes++;\n        this.width = options.sourceWidth;\n        this.horizontal = true;\n        this.dW = Math.round(this.width * this.scaleX);\n        this.dH = options.sourceHeight;\n        this.tempScale = this.dW / this.width;\n        this.taps = this.getTaps();\n        options.destinationWidth = this.dW;\n        this._setupFrameBuffer(options);\n        this.applyToWebGL(options);\n        this._swapTextures(options);\n        options.sourceWidth = options.destinationWidth;\n\n        this.height = options.sourceHeight;\n        this.horizontal = false;\n        this.dH = Math.round(this.height * this.scaleY);\n        this.tempScale = this.dH / this.height;\n        this.taps = this.getTaps();\n        options.destinationHeight = this.dH;\n        this._setupFrameBuffer(options);\n        this.applyToWebGL(options);\n        this._swapTextures(options);\n        options.sourceHeight = options.destinationHeight;\n      }\n      else {\n        this.applyTo2d(options);\n      }\n    },\n\n    isNeutralState: function() {\n      return this.scaleX === 1 && this.scaleY === 1;\n    },\n\n    lanczosCreate: function(lobes) {\n      return function(x) {\n        if (x >= lobes || x <= -lobes) {\n          return 0.0;\n        }\n        if (x < 1.19209290E-07 && x > -1.19209290E-07) {\n          return 1.0;\n        }\n        x *= Math.PI;\n        var xx = x / lobes;\n        return (sin(x) / x) * sin(xx) / xx;\n      };\n    },\n\n    /**\n     * Applies filter to canvas element\n     * @memberOf fabric.Image.filters.Resize.prototype\n     * @param {Object} canvasEl Canvas element to apply filter to\n     * @param {Number} scaleX\n     * @param {Number} scaleY\n     */\n    applyTo2d: function(options) {\n      var imageData = options.imageData,\n          scaleX = this.scaleX,\n          scaleY = this.scaleY;\n\n      this.rcpScaleX = 1 / scaleX;\n      this.rcpScaleY = 1 / scaleY;\n\n      var oW = imageData.width, oH = imageData.height,\n          dW = round(oW * scaleX), dH = round(oH * scaleY),\n          newData;\n\n      if (this.resizeType === 'sliceHack') {\n        newData = this.sliceByTwo(options, oW, oH, dW, dH);\n      }\n      else if (this.resizeType === 'hermite') {\n        newData = this.hermiteFastResize(options, oW, oH, dW, dH);\n      }\n      else if (this.resizeType === 'bilinear') {\n        newData = this.bilinearFiltering(options, oW, oH, dW, dH);\n      }\n      else if (this.resizeType === 'lanczos') {\n        newData = this.lanczosResize(options, oW, oH, dW, dH);\n      }\n      options.imageData = newData;\n    },\n\n    /**\n     * Filter sliceByTwo\n     * @param {Object} canvasEl Canvas element to apply filter to\n     * @param {Number} oW Original Width\n     * @param {Number} oH Original Height\n     * @param {Number} dW Destination Width\n     * @param {Number} dH Destination Height\n     * @returns {ImageData}\n     */\n    sliceByTwo: function(options, oW, oH, dW, dH) {\n      var imageData = options.imageData,\n          mult = 0.5, doneW = false, doneH = false, stepW = oW * mult,\n          stepH = oH * mult, resources = fabric.filterBackend.resources,\n          tmpCanvas, ctx, sX = 0, sY = 0, dX = oW, dY = 0;\n      if (!resources.sliceByTwo) {\n        resources.sliceByTwo = document.createElement('canvas');\n      }\n      tmpCanvas = resources.sliceByTwo;\n      if (tmpCanvas.width < oW * 1.5 || tmpCanvas.height < oH) {\n        tmpCanvas.width = oW * 1.5;\n        tmpCanvas.height = oH;\n      }\n      ctx = tmpCanvas.getContext('2d');\n      ctx.clearRect(0, 0, oW * 1.5, oH);\n      ctx.putImageData(imageData, 0, 0);\n\n      dW = floor(dW);\n      dH = floor(dH);\n\n      while (!doneW || !doneH) {\n        oW = stepW;\n        oH = stepH;\n        if (dW < floor(stepW * mult)) {\n          stepW = floor(stepW * mult);\n        }\n        else {\n          stepW = dW;\n          doneW = true;\n        }\n        if (dH < floor(stepH * mult)) {\n          stepH = floor(stepH * mult);\n        }\n        else {\n          stepH = dH;\n          doneH = true;\n        }\n        ctx.drawImage(tmpCanvas, sX, sY, oW, oH, dX, dY, stepW, stepH);\n        sX = dX;\n        sY = dY;\n        dY += stepH;\n      }\n      return ctx.getImageData(sX, sY, dW, dH);\n    },\n\n    /**\n     * Filter lanczosResize\n     * @param {Object} canvasEl Canvas element to apply filter to\n     * @param {Number} oW Original Width\n     * @param {Number} oH Original Height\n     * @param {Number} dW Destination Width\n     * @param {Number} dH Destination Height\n     * @returns {ImageData}\n     */\n    lanczosResize: function(options, oW, oH, dW, dH) {\n\n      function process(u) {\n        var v, i, weight, idx, a, red, green,\n            blue, alpha, fX, fY;\n        center.x = (u + 0.5) * ratioX;\n        icenter.x = floor(center.x);\n        for (v = 0; v < dH; v++) {\n          center.y = (v + 0.5) * ratioY;\n          icenter.y = floor(center.y);\n          a = 0; red = 0; green = 0; blue = 0; alpha = 0;\n          for (i = icenter.x - range2X; i <= icenter.x + range2X; i++) {\n            if (i < 0 || i >= oW) {\n              continue;\n            }\n            fX = floor(1000 * abs(i - center.x));\n            if (!cacheLanc[fX]) {\n              cacheLanc[fX] = { };\n            }\n            for (var j = icenter.y - range2Y; j <= icenter.y + range2Y; j++) {\n              if (j < 0 || j >= oH) {\n                continue;\n              }\n              fY = floor(1000 * abs(j - center.y));\n              if (!cacheLanc[fX][fY]) {\n                cacheLanc[fX][fY] = lanczos(sqrt(pow(fX * rcpRatioX, 2) + pow(fY * rcpRatioY, 2)) / 1000);\n              }\n              weight = cacheLanc[fX][fY];\n              if (weight > 0) {\n                idx = (j * oW + i) * 4;\n                a += weight;\n                red += weight * srcData[idx];\n                green += weight * srcData[idx + 1];\n                blue += weight * srcData[idx + 2];\n                alpha += weight * srcData[idx + 3];\n              }\n            }\n          }\n          idx = (v * dW + u) * 4;\n          destData[idx] = red / a;\n          destData[idx + 1] = green / a;\n          destData[idx + 2] = blue / a;\n          destData[idx + 3] = alpha / a;\n        }\n\n        if (++u < dW) {\n          return process(u);\n        }\n        else {\n          return destImg;\n        }\n      }\n\n      var srcData = options.imageData.data,\n          destImg = options.ctx.createImageData(dW, dH),\n          destData = destImg.data,\n          lanczos = this.lanczosCreate(this.lanczosLobes),\n          ratioX = this.rcpScaleX, ratioY = this.rcpScaleY,\n          rcpRatioX = 2 / this.rcpScaleX, rcpRatioY = 2 / this.rcpScaleY,\n          range2X = ceil(ratioX * this.lanczosLobes / 2),\n          range2Y = ceil(ratioY * this.lanczosLobes / 2),\n          cacheLanc = { }, center = { }, icenter = { };\n\n      return process(0);\n    },\n\n    /**\n     * bilinearFiltering\n     * @param {Object} canvasEl Canvas element to apply filter to\n     * @param {Number} oW Original Width\n     * @param {Number} oH Original Height\n     * @param {Number} dW Destination Width\n     * @param {Number} dH Destination Height\n     * @returns {ImageData}\n     */\n    bilinearFiltering: function(options, oW, oH, dW, dH) {\n      var a, b, c, d, x, y, i, j, xDiff, yDiff, chnl,\n          color, offset = 0, origPix, ratioX = this.rcpScaleX,\n          ratioY = this.rcpScaleY,\n          w4 = 4 * (oW - 1), img = options.imageData,\n          pixels = img.data, destImage = options.ctx.createImageData(dW, dH),\n          destPixels = destImage.data;\n      for (i = 0; i < dH; i++) {\n        for (j = 0; j < dW; j++) {\n          x = floor(ratioX * j);\n          y = floor(ratioY * i);\n          xDiff = ratioX * j - x;\n          yDiff = ratioY * i - y;\n          origPix = 4 * (y * oW + x);\n\n          for (chnl = 0; chnl < 4; chnl++) {\n            a = pixels[origPix + chnl];\n            b = pixels[origPix + 4 + chnl];\n            c = pixels[origPix + w4 + chnl];\n            d = pixels[origPix + w4 + 4 + chnl];\n            color = a * (1 - xDiff) * (1 - yDiff) + b * xDiff * (1 - yDiff) +\n                    c * yDiff * (1 - xDiff) + d * xDiff * yDiff;\n            destPixels[offset++] = color;\n          }\n        }\n      }\n      return destImage;\n    },\n\n    /**\n     * hermiteFastResize\n     * @param {Object} canvasEl Canvas element to apply filter to\n     * @param {Number} oW Original Width\n     * @param {Number} oH Original Height\n     * @param {Number} dW Destination Width\n     * @param {Number} dH Destination Height\n     * @returns {ImageData}\n     */\n    hermiteFastResize: function(options, oW, oH, dW, dH) {\n      var ratioW = this.rcpScaleX, ratioH = this.rcpScaleY,\n          ratioWHalf = ceil(ratioW / 2),\n          ratioHHalf = ceil(ratioH / 2),\n          img = options.imageData, data = img.data,\n          img2 = options.ctx.createImageData(dW, dH), data2 = img2.data;\n      for (var j = 0; j < dH; j++) {\n        for (var i = 0; i < dW; i++) {\n          var x2 = (i + j * dW) * 4, weight = 0, weights = 0, weightsAlpha = 0,\n              gxR = 0, gxG = 0, gxB = 0, gxA = 0, centerY = (j + 0.5) * ratioH;\n          for (var yy = floor(j * ratioH); yy < (j + 1) * ratioH; yy++) {\n            var dy = abs(centerY - (yy + 0.5)) / ratioHHalf,\n                centerX = (i + 0.5) * ratioW, w0 = dy * dy;\n            for (var xx = floor(i * ratioW); xx < (i + 1) * ratioW; xx++) {\n              var dx = abs(centerX - (xx + 0.5)) / ratioWHalf,\n                  w = sqrt(w0 + dx * dx);\n              /* eslint-disable max-depth */\n              if (w > 1 && w < -1) {\n                continue;\n              }\n              //hermite filter\n              weight = 2 * w * w * w - 3 * w * w + 1;\n              if (weight > 0) {\n                dx = 4 * (xx + yy * oW);\n                //alpha\n                gxA += weight * data[dx + 3];\n                weightsAlpha += weight;\n                //colors\n                if (data[dx + 3] < 255) {\n                  weight = weight * data[dx + 3] / 250;\n                }\n                gxR += weight * data[dx];\n                gxG += weight * data[dx + 1];\n                gxB += weight * data[dx + 2];\n                weights += weight;\n              }\n              /* eslint-enable max-depth */\n            }\n          }\n          data2[x2] = gxR / weights;\n          data2[x2 + 1] = gxG / weights;\n          data2[x2 + 2] = gxB / weights;\n          data2[x2 + 3] = gxA / weightsAlpha;\n        }\n      }\n      return img2;\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function() {\n      return {\n        type: this.type,\n        scaleX: this.scaleX,\n        scaleY: this.scaleY,\n        resizeType: this.resizeType,\n        lanczosLobes: this.lanczosLobes\n      };\n    }\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Resize} Instance of fabric.Image.filters.Resize\n   */\n  fabric.Image.filters.Resize.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Contrast filter class\n   * @class fabric.Image.filters.Contrast\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Contrast#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Contrast({\n   *   contrast: 0.25\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n  filters.Contrast = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Contrast.prototype */ {\n\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Contrast',\n\n    fragmentSource: 'precision highp float;\\n' +\n      'uniform sampler2D uTexture;\\n' +\n      'uniform float uContrast;\\n' +\n      'varying vec2 vTexCoord;\\n' +\n      'void main() {\\n' +\n        'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n        'float contrastF = 1.015 * (uContrast + 1.0) / (1.0 * (1.015 - uContrast));\\n' +\n        'color.rgb = contrastF * (color.rgb - 0.5) + 0.5;\\n' +\n        'gl_FragColor = color;\\n' +\n      '}',\n\n    /**\n     * contrast value, range from -1 to 1.\n     * @param {Number} contrast\n     * @default 0\n     */\n    contrast: 0,\n\n    mainParameter: 'contrast',\n\n    /**\n     * Constructor\n     * @memberOf fabric.Image.filters.Contrast.prototype\n     * @param {Object} [options] Options object\n     * @param {Number} [options.contrast=0] Value to contrast the image up (-1...1)\n     */\n\n    /**\n      * Apply the Contrast operation to a Uint8Array representing the pixels of an image.\n      *\n      * @param {Object} options\n      * @param {ImageData} options.imageData The Uint8Array to be filtered.\n      */\n    applyTo2d: function(options) {\n      if (this.contrast === 0) {\n        return;\n      }\n      var imageData = options.imageData, i, len,\n          data = imageData.data, len = data.length,\n          contrast = Math.floor(this.contrast * 255),\n          contrastF = 259 * (contrast + 255) / (255 * (259 - contrast));\n\n      for (i = 0; i < len; i += 4) {\n        data[i] = contrastF * (data[i] - 128) + 128;\n        data[i + 1] = contrastF * (data[i + 1] - 128) + 128;\n        data[i + 2] = contrastF * (data[i + 2] - 128) + 128;\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uContrast: gl.getUniformLocation(program, 'uContrast'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      gl.uniform1f(uniformLocations.uContrast, this.contrast);\n    },\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Contrast} Instance of fabric.Image.filters.Contrast\n   */\n  fabric.Image.filters.Contrast.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Saturate filter class\n   * @class fabric.Image.filters.Saturation\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Saturation#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Saturation({\n   *   saturation: 100\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n  filters.Saturation = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Saturation.prototype */ {\n\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Saturation',\n\n    fragmentSource: 'precision highp float;\\n' +\n      'uniform sampler2D uTexture;\\n' +\n      'uniform float uSaturation;\\n' +\n      'varying vec2 vTexCoord;\\n' +\n      'void main() {\\n' +\n        'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n        'float rgMax = max(color.r, color.g);\\n' +\n        'float rgbMax = max(rgMax, color.b);\\n' +\n        'color.r += rgbMax != color.r ? (rgbMax - color.r) * uSaturation : 0.00;\\n' +\n        'color.g += rgbMax != color.g ? (rgbMax - color.g) * uSaturation : 0.00;\\n' +\n        'color.b += rgbMax != color.b ? (rgbMax - color.b) * uSaturation : 0.00;\\n' +\n        'gl_FragColor = color;\\n' +\n      '}',\n\n    saturation: 0,\n\n    mainParameter: 'saturation',\n\n    /**\n     * Constructor\n     * @memberOf fabric.Image.filters.Saturate.prototype\n     * @param {Object} [options] Options object\n     * @param {Number} [options.saturate=0] Value to saturate the image (-1...1)\n     */\n\n    /**\n     * Apply the Saturation operation to a Uint8ClampedArray representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n     */\n    applyTo2d: function(options) {\n      if (this.saturation === 0) {\n        return;\n      }\n      var imageData = options.imageData,\n          data = imageData.data, len = data.length,\n          adjust = -this.saturation, i, max;\n\n      for (i = 0; i < len; i += 4) {\n        max = Math.max(data[i], data[i + 1], data[i + 2]);\n        data[i] += max !== data[i] ? (max - data[i]) * adjust : 0;\n        data[i + 1] += max !== data[i + 1] ? (max - data[i + 1]) * adjust : 0;\n        data[i + 2] += max !== data[i + 2] ? (max - data[i + 2]) * adjust : 0;\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uSaturation: gl.getUniformLocation(program, 'uSaturation'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      gl.uniform1f(uniformLocations.uSaturation, -this.saturation);\n    },\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Saturation} Instance of fabric.Image.filters.Saturate\n   */\n  fabric.Image.filters.Saturation.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Blur filter class\n   * @class fabric.Image.filters.Blur\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Blur#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Blur({\n   *   blur: 0.5\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   * canvas.renderAll();\n   */\n  filters.Blur = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Blur.prototype */ {\n\n    type: 'Blur',\n\n    /*\n'gl_FragColor = vec4(0.0);',\n'gl_FragColor += texture2D(texture, vTexCoord + -7 * uDelta)*0.0044299121055113265;',\n'gl_FragColor += texture2D(texture, vTexCoord + -6 * uDelta)*0.00895781211794;',\n'gl_FragColor += texture2D(texture, vTexCoord + -5 * uDelta)*0.0215963866053;',\n'gl_FragColor += texture2D(texture, vTexCoord + -4 * uDelta)*0.0443683338718;',\n'gl_FragColor += texture2D(texture, vTexCoord + -3 * uDelta)*0.0776744219933;',\n'gl_FragColor += texture2D(texture, vTexCoord + -2 * uDelta)*0.115876621105;',\n'gl_FragColor += texture2D(texture, vTexCoord + -1 * uDelta)*0.147308056121;',\n'gl_FragColor += texture2D(texture, vTexCoord              )*0.159576912161;',\n'gl_FragColor += texture2D(texture, vTexCoord + 1 * uDelta)*0.147308056121;',\n'gl_FragColor += texture2D(texture, vTexCoord + 2 * uDelta)*0.115876621105;',\n'gl_FragColor += texture2D(texture, vTexCoord + 3 * uDelta)*0.0776744219933;',\n'gl_FragColor += texture2D(texture, vTexCoord + 4 * uDelta)*0.0443683338718;',\n'gl_FragColor += texture2D(texture, vTexCoord + 5 * uDelta)*0.0215963866053;',\n'gl_FragColor += texture2D(texture, vTexCoord + 6 * uDelta)*0.00895781211794;',\n'gl_FragColor += texture2D(texture, vTexCoord + 7 * uDelta)*0.0044299121055113265;',\n*/\n\n    /* eslint-disable max-len */\n    fragmentSource: 'precision highp float;\\n' +\n      'uniform sampler2D uTexture;\\n' +\n      'uniform vec2 uDelta;\\n' +\n      'varying vec2 vTexCoord;\\n' +\n      'const float nSamples = 15.0;\\n' +\n      'vec3 v3offset = vec3(12.9898, 78.233, 151.7182);\\n' +\n      'float random(vec3 scale) {\\n' +\n        /* use the fragment position for a different seed per-pixel */\n        'return fract(sin(dot(gl_FragCoord.xyz, scale)) * 43758.5453);\\n' +\n      '}\\n' +\n      'void main() {\\n' +\n        'vec4 color = vec4(0.0);\\n' +\n        'float total = 0.0;\\n' +\n        'float offset = random(v3offset);\\n' +\n        'for (float t = -nSamples; t <= nSamples; t++) {\\n' +\n          'float percent = (t + offset - 0.5) / nSamples;\\n' +\n          'float weight = 1.0 - abs(percent);\\n' +\n          'color += texture2D(uTexture, vTexCoord + uDelta * percent) * weight;\\n' +\n          'total += weight;\\n' +\n        '}\\n' +\n        'gl_FragColor = color / total;\\n' +\n      '}',\n    /* eslint-enable max-len */\n\n    /**\n     * blur value, in percentage of image dimensions.\n     * specific to keep the image blur constant at different resolutions\n     * range bewteen 0 and 1.\n     */\n    blur: 0,\n\n    mainParameter: 'blur',\n\n    applyTo: function(options) {\n      if (options.webgl) {\n        // this aspectRatio is used to give the same blur to vertical and horizontal\n        this.aspectRatio = options.sourceWidth / options.sourceHeight;\n        options.passes++;\n        this._setupFrameBuffer(options);\n        this.horizontal = true;\n        this.applyToWebGL(options);\n        this._swapTextures(options);\n        this._setupFrameBuffer(options);\n        this.horizontal = false;\n        this.applyToWebGL(options);\n        this._swapTextures(options);\n      }\n      else {\n        this.applyTo2d(options);\n      }\n    },\n\n    applyTo2d: function(options) {\n      // paint canvasEl with current image data.\n      //options.ctx.putImageData(options.imageData, 0, 0);\n      options.imageData = this.simpleBlur(options);\n    },\n\n    simpleBlur: function(options) {\n      var resources = options.filterBackend.resources, canvas1, canvas2,\n          width = options.imageData.width,\n          height = options.imageData.height;\n\n      if (!resources.blurLayer1) {\n        resources.blurLayer1 = fabric.util.createCanvasElement();\n        resources.blurLayer2 = fabric.util.createCanvasElement();\n      }\n      canvas1 = resources.blurLayer1;\n      canvas2 = resources.blurLayer2;\n      if (canvas1.width !== width || canvas1.height !== height) {\n        canvas2.width = canvas1.width = width;\n        canvas2.height = canvas1.height = height;\n      }\n      var ctx1 = canvas1.getContext('2d'),\n          ctx2 = canvas2.getContext('2d'),\n          nSamples = 15,\n          random, percent, j, i,\n          blur = this.blur * 0.06 * 0.5;\n\n      // load first canvas\n      ctx1.putImageData(options.imageData, 0, 0);\n      ctx2.clearRect(0, 0, width, height);\n\n      for (i = -nSamples; i <= nSamples; i++) {\n        random = (Math.random() - 0.5) / 4;\n        percent = i / nSamples;\n        j = blur * percent * width + random;\n        ctx2.globalAlpha = 1 - Math.abs(percent);\n        ctx2.drawImage(canvas1, j, random);\n        ctx1.drawImage(canvas2, 0, 0);\n        ctx2.globalAlpha = 1;\n        ctx2.clearRect(0, 0, canvas2.width, canvas2.height);\n      }\n      for (i = -nSamples; i <= nSamples; i++) {\n        random = (Math.random() - 0.5) / 4;\n        percent = i / nSamples;\n        j = blur * percent * height + random;\n        ctx2.globalAlpha = 1 - Math.abs(percent);\n        ctx2.drawImage(canvas1, random, j);\n        ctx1.drawImage(canvas2, 0, 0);\n        ctx2.globalAlpha = 1;\n        ctx2.clearRect(0, 0, canvas2.width, canvas2.height);\n      }\n      options.ctx.drawImage(canvas1, 0, 0);\n      var newImageData = options.ctx.getImageData(0, 0, canvas1.width, canvas1.height);\n      ctx1.globalAlpha = 1;\n      ctx1.clearRect(0, 0, canvas1.width, canvas1.height);\n      return newImageData;\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        delta: gl.getUniformLocation(program, 'uDelta'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      var delta = this.chooseRightDelta();\n      gl.uniform2fv(uniformLocations.delta, delta);\n    },\n\n    /**\n     * choose right value of image percentage to blur with\n     * @returns {Array} a numeric array with delta values\n     */\n    chooseRightDelta: function() {\n      var blurScale = 1, delta = [0, 0], blur;\n      if (this.horizontal) {\n        if (this.aspectRatio > 1) {\n          // image is wide, i want to shrink radius horizontal\n          blurScale = 1 / this.aspectRatio;\n        }\n      }\n      else {\n        if (this.aspectRatio < 1) {\n          // image is tall, i want to shrink radius vertical\n          blurScale = this.aspectRatio;\n        }\n      }\n      blur = blurScale * this.blur * 0.12;\n      if (this.horizontal) {\n        delta[0] = blur;\n      }\n      else {\n        delta[1] = blur;\n      }\n      return delta;\n    },\n  });\n\n  /**\n   * Deserialize a JSON definition of a BlurFilter into a concrete instance.\n   */\n  filters.Blur.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * Gamma filter class\n   * @class fabric.Image.filters.Gamma\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.Gamma#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.Gamma({\n   *   gamma: [1, 0.5, 2.1]\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n  filters.Gamma = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Gamma.prototype */ {\n\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'Gamma',\n\n    fragmentSource: 'precision highp float;\\n' +\n      'uniform sampler2D uTexture;\\n' +\n      'uniform vec3 uGamma;\\n' +\n      'varying vec2 vTexCoord;\\n' +\n      'void main() {\\n' +\n        'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n        'vec3 correction = (1.0 / uGamma);\\n' +\n        'color.r = pow(color.r, correction.r);\\n' +\n        'color.g = pow(color.g, correction.g);\\n' +\n        'color.b = pow(color.b, correction.b);\\n' +\n        'gl_FragColor = color;\\n' +\n        'gl_FragColor.rgb *= color.a;\\n' +\n      '}',\n\n    /**\n     * Gamma array value, from 0.01 to 2.2.\n     * @param {Array} gamma\n     * @default\n     */\n    gamma: [1, 1, 1],\n\n    /**\n     * Describe the property that is the filter parameter\n     * @param {String} m\n     * @default\n     */\n    mainParameter: 'gamma',\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     */\n    initialize: function(options) {\n      this.gamma = [1, 1, 1];\n      filters.BaseFilter.prototype.initialize.call(this, options);\n    },\n\n    /**\n     * Apply the Gamma operation to a Uint8Array representing the pixels of an image.\n     *\n     * @param {Object} options\n     * @param {ImageData} options.imageData The Uint8Array to be filtered.\n     */\n    applyTo2d: function(options) {\n      var imageData = options.imageData, data = imageData.data,\n          gamma = this.gamma, len = data.length,\n          rInv = 1 / gamma[0], gInv = 1 / gamma[1],\n          bInv = 1 / gamma[2], i;\n\n      if (!this.rVals) {\n        // eslint-disable-next-line\n        this.rVals = new Uint8Array(256);\n        // eslint-disable-next-line\n        this.gVals = new Uint8Array(256);\n        // eslint-disable-next-line\n        this.bVals = new Uint8Array(256);\n      }\n\n      // This is an optimization - pre-compute a look-up table for each color channel\n      // instead of performing these pow calls for each pixel in the image.\n      for (i = 0, len = 256; i < len; i++) {\n        this.rVals[i] = Math.pow(i / 255, rInv) * 255;\n        this.gVals[i] = Math.pow(i / 255, gInv) * 255;\n        this.bVals[i] = Math.pow(i / 255, bInv) * 255;\n      }\n      for (i = 0, len = data.length; i < len; i += 4) {\n        data[i] = this.rVals[data[i]];\n        data[i + 1] = this.gVals[data[i + 1]];\n        data[i + 2] = this.bVals[data[i + 2]];\n      }\n    },\n\n    /**\n     * Return WebGL uniform locations for this filter's shader.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {WebGLShaderProgram} program This filter's compiled shader program.\n     */\n    getUniformLocations: function(gl, program) {\n      return {\n        uGamma: gl.getUniformLocation(program, 'uGamma'),\n      };\n    },\n\n    /**\n     * Send data from this filter to its shader program's uniforms.\n     *\n     * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n     * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n     */\n    sendUniformData: function(gl, uniformLocations) {\n      gl.uniform3fv(uniformLocations.uGamma, this.gamma);\n    },\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.Gamma} Instance of fabric.Image.filters.Gamma\n   */\n  fabric.Image.filters.Gamma.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * A container class that knows how to apply a sequence of filters to an input image.\n   */\n  filters.Composed = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Composed.prototype */ {\n\n    type: 'Composed',\n\n    /**\n     * A non sparse array of filters to apply\n     */\n    subFilters: [],\n\n    /**\n     * Constructor\n     * @param {Object} [options] Options object\n     */\n    initialize: function(options) {\n      this.callSuper('initialize', options);\n      // create a new array instead mutating the prototype with push\n      this.subFilters = this.subFilters.slice(0);\n    },\n\n    /**\n     * Apply this container's filters to the input image provided.\n     *\n     * @param {Object} options\n     * @param {Number} options.passes The number of filters remaining to be applied.\n     */\n    applyTo: function(options) {\n      options.passes += this.subFilters.length - 1;\n      this.subFilters.forEach(function(filter) {\n        filter.applyTo(options);\n      });\n    },\n\n    /**\n     * Serialize this filter into JSON.\n     *\n     * @returns {Object} A JSON representation of this filter.\n     */\n    toObject: function() {\n      return fabric.util.object.extend(this.callSuper('toObject'), {\n        subFilters: this.subFilters.map(function(filter) { return filter.toObject(); }),\n      });\n    },\n\n    isNeutralState: function() {\n      return !this.subFilters.some(function(filter) { return !filter.isNeutralState(); });\n    }\n  });\n\n  /**\n   * Deserialize a JSON definition of a ComposedFilter into a concrete instance.\n   */\n  fabric.Image.filters.Composed.fromObject = function(object, callback) {\n    var filters = object.subFilters || [],\n        subFilters = filters.map(function(filter) {\n          return new fabric.Image.filters[filter.type](filter);\n        }),\n        instance = new fabric.Image.filters.Composed({ subFilters: subFilters });\n    callback && callback(instance);\n    return instance;\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric  = global.fabric || (global.fabric = { }),\n      filters = fabric.Image.filters,\n      createClass = fabric.util.createClass;\n\n  /**\n   * HueRotation filter class\n   * @class fabric.Image.filters.HueRotation\n   * @memberOf fabric.Image.filters\n   * @extends fabric.Image.filters.BaseFilter\n   * @see {@link fabric.Image.filters.HueRotation#initialize} for constructor definition\n   * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n   * @example\n   * var filter = new fabric.Image.filters.HueRotation({\n   *   rotation: -0.5\n   * });\n   * object.filters.push(filter);\n   * object.applyFilters();\n   */\n  filters.HueRotation = createClass(filters.ColorMatrix, /** @lends fabric.Image.filters.HueRotation.prototype */ {\n\n    /**\n     * Filter type\n     * @param {String} type\n     * @default\n     */\n    type: 'HueRotation',\n\n    /**\n     * HueRotation value, from -1 to 1.\n     * the unit is radians\n     * @param {Number} myParameter\n     * @default\n     */\n    rotation: 0,\n\n    /**\n     * Describe the property that is the filter parameter\n     * @param {String} m\n     * @default\n     */\n    mainParameter: 'rotation',\n\n    calculateMatrix: function() {\n      var rad = this.rotation * Math.PI, cos = fabric.util.cos(rad), sin = fabric.util.sin(rad),\n          aThird = 1 / 3, aThirdSqtSin = Math.sqrt(aThird) * sin, OneMinusCos = 1 - cos;\n      this.matrix = [\n        1, 0, 0, 0, 0,\n        0, 1, 0, 0, 0,\n        0, 0, 1, 0, 0,\n        0, 0, 0, 1, 0\n      ];\n      this.matrix[0] = cos + OneMinusCos / 3;\n      this.matrix[1] = aThird * OneMinusCos - aThirdSqtSin;\n      this.matrix[2] = aThird * OneMinusCos + aThirdSqtSin;\n      this.matrix[5] = aThird * OneMinusCos + aThirdSqtSin;\n      this.matrix[6] = cos + aThird * OneMinusCos;\n      this.matrix[7] = aThird * OneMinusCos - aThirdSqtSin;\n      this.matrix[10] = aThird * OneMinusCos - aThirdSqtSin;\n      this.matrix[11] = aThird * OneMinusCos + aThirdSqtSin;\n      this.matrix[12] = cos + aThird * OneMinusCos;\n    },\n\n    /**\n     * HueRotation isNeutralState implementation\n     * Used only in image applyFilters to discard filters that will not have an effect\n     * on the image\n     * @param {Object} options\n     **/\n    isNeutralState: function(options) {\n      this.calculateMatrix();\n      return filters.BaseFilter.prototype.isNeutralState.call(this, options);\n    },\n\n    /**\n     * Apply this filter to the input image data provided.\n     *\n     * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\n     *\n     * @param {Object} options\n     * @param {Number} options.passes The number of filters remaining to be executed\n     * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n     * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n     * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n     * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n     */\n    applyTo: function(options) {\n      this.calculateMatrix();\n      filters.BaseFilter.prototype.applyTo.call(this, options);\n    },\n\n  });\n\n  /**\n   * Returns filter instance from an object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] to be invoked after filter creation\n   * @return {fabric.Image.filters.HueRotation} Instance of fabric.Image.filters.HueRotation\n   */\n  fabric.Image.filters.HueRotation.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = { }),\n      clone = fabric.util.object.clone;\n\n  if (fabric.Text) {\n    fabric.warn('fabric.Text is already defined');\n    return;\n  }\n\n  /**\n   * Text class\n   * @class fabric.Text\n   * @extends fabric.Object\n   * @return {fabric.Text} thisArg\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#text}\n   * @see {@link fabric.Text#initialize} for constructor definition\n   */\n  fabric.Text = fabric.util.createClass(fabric.Object, /** @lends fabric.Text.prototype */ {\n\n    /**\n     * Properties which when set cause object to change dimensions\n     * @type Array\n     * @private\n     */\n    _dimensionAffectingProps: [\n      'fontSize',\n      'fontWeight',\n      'fontFamily',\n      'fontStyle',\n      'lineHeight',\n      'text',\n      'charSpacing',\n      'textAlign',\n      'styles',\n    ],\n\n    /**\n     * @private\n     */\n    _reNewline: /\\r?\\n/,\n\n    /**\n     * Use this regular expression to filter for whitespaces that is not a new line.\n     * Mostly used when text is 'justify' aligned.\n     * @private\n     */\n    _reSpacesAndTabs: /[ \\t\\r]/g,\n\n    /**\n     * Use this regular expression to filter for whitespace that is not a new line.\n     * Mostly used when text is 'justify' aligned.\n     * @private\n     */\n    _reSpaceAndTab: /[ \\t\\r]/,\n\n    /**\n     * Use this regular expression to filter consecutive groups of non spaces.\n     * Mostly used when text is 'justify' aligned.\n     * @private\n     */\n    _reWords: /\\S+/g,\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type:                 'text',\n\n    /**\n     * Font size (in pixels)\n     * @type Number\n     * @default\n     */\n    fontSize:             40,\n\n    /**\n     * Font weight (e.g. bold, normal, 400, 600, 800)\n     * @type {(Number|String)}\n     * @default\n     */\n    fontWeight:           'normal',\n\n    /**\n     * Font family\n     * @type String\n     * @default\n     */\n    fontFamily:           'Times New Roman',\n\n    /**\n     * Text decoration underline.\n     * @type Boolean\n     * @default\n     */\n    underline:       false,\n\n    /**\n     * Text decoration overline.\n     * @type Boolean\n     * @default\n     */\n    overline:       false,\n\n    /**\n     * Text decoration linethrough.\n     * @type Boolean\n     * @default\n     */\n    linethrough:       false,\n\n    /**\n     * Text alignment. Possible values: \"left\", \"center\", \"right\", \"justify\",\n     * \"justify-left\", \"justify-center\" or \"justify-right\".\n     * @type String\n     * @default\n     */\n    textAlign:            'left',\n\n    /**\n     * Font style . Possible values: \"\", \"normal\", \"italic\" or \"oblique\".\n     * @type String\n     * @default\n     */\n    fontStyle:            'normal',\n\n    /**\n     * Line height\n     * @type Number\n     * @default\n     */\n    lineHeight:           1.16,\n\n    /**\n     * Superscript schema object (minimum overlap)\n     * @type {Object}\n     * @default\n     */\n    superscript: {\n      size:      0.60, // fontSize factor\n      baseline: -0.35  // baseline-shift factor (upwards)\n    },\n\n    /**\n     * Subscript schema object (minimum overlap)\n     * @type {Object}\n     * @default\n     */\n    subscript: {\n      size:      0.60, // fontSize factor\n      baseline:  0.11  // baseline-shift factor (downwards)\n    },\n\n    /**\n     * Background color of text lines\n     * @type String\n     * @default\n     */\n    textBackgroundColor:  '',\n\n    /**\n     * List of properties to consider when checking if\n     * state of an object is changed ({@link fabric.Object#hasStateChanged})\n     * as well as for history (undo/redo) purposes\n     * @type Array\n     */\n    stateProperties: fabric.Object.prototype.stateProperties.concat('fontFamily',\n      'fontWeight',\n      'fontSize',\n      'text',\n      'underline',\n      'overline',\n      'linethrough',\n      'textAlign',\n      'fontStyle',\n      'lineHeight',\n      'textBackgroundColor',\n      'charSpacing',\n      'styles'),\n\n    /**\n     * List of properties to consider when checking if cache needs refresh\n     * @type Array\n     */\n    cacheProperties: fabric.Object.prototype.cacheProperties.concat('fontFamily',\n      'fontWeight',\n      'fontSize',\n      'text',\n      'underline',\n      'overline',\n      'linethrough',\n      'textAlign',\n      'fontStyle',\n      'lineHeight',\n      'textBackgroundColor',\n      'charSpacing',\n      'styles'),\n\n    /**\n     * When defined, an object is rendered via stroke and this property specifies its color.\n     * <b>Backwards incompatibility note:</b> This property was named \"strokeStyle\" until v1.1.6\n     * @type String\n     * @default\n     */\n    stroke:               null,\n\n    /**\n     * Shadow object representing shadow of this shape.\n     * <b>Backwards incompatibility note:</b> This property was named \"textShadow\" (String) until v1.2.11\n     * @type fabric.Shadow\n     * @default\n     */\n    shadow:               null,\n\n    /**\n     * @private\n     */\n    _fontSizeFraction: 0.222,\n\n    /**\n     * @private\n     */\n    offsets: {\n      underline: 0.10,\n      linethrough: -0.315,\n      overline: -0.88\n    },\n\n    /**\n     * Text Line proportion to font Size (in pixels)\n     * @type Number\n     * @default\n     */\n    _fontSizeMult:             1.13,\n\n    /**\n     * additional space between characters\n     * expressed in thousands of em unit\n     * @type Number\n     * @default\n     */\n    charSpacing:             0,\n\n    /**\n     * Object containing character styles - top-level properties -> line numbers,\n     * 2nd-level properties - charater numbers\n     * @type Object\n     * @default\n     */\n    styles: null,\n\n    /**\n     * Reference to a context to measure text char or couple of chars\n     * the cacheContext of the canvas will be used or a freshly created one if the object is not on canvas\n     * once created it will be referenced on fabric._measuringContext to avoide creating a canvas for every\n     * text object created.\n     * @type {CanvasRenderingContext2D}\n     * @default\n     */\n    _measuringContext: null,\n\n    /**\n     * Baseline shift, stlyes only, keep at 0 for the main text object\n     * @type {Number}\n     * @default\n     */\n    deltaY: 0,\n\n    /**\n     * Array of properties that define a style unit (of 'styles').\n     * @type {Array}\n     * @default\n     */\n    _styleProperties: [\n      'stroke',\n      'strokeWidth',\n      'fill',\n      'fontFamily',\n      'fontSize',\n      'fontWeight',\n      'fontStyle',\n      'underline',\n      'overline',\n      'linethrough',\n      'deltaY',\n      'textBackgroundColor',\n    ],\n\n    /**\n     * contains characters bounding boxes\n     */\n    __charBounds: [],\n\n    /**\n     * use this size when measuring text. To avoid IE11 rounding errors\n     * @type {Number}\n     * @default\n     * @readonly\n     * @private\n     */\n    CACHE_FONT_SIZE: 400,\n\n    /**\n     * contains the min text width to avoid getting 0\n     * @type {Number}\n     * @default\n     */\n    MIN_TEXT_WIDTH: 2,\n\n    /**\n     * Constructor\n     * @param {String} text Text string\n     * @param {Object} [options] Options object\n     * @return {fabric.Text} thisArg\n     */\n    initialize: function(text, options) {\n      this.styles = options ? (options.styles || { }) : { };\n      this.text = text;\n      this.__skipDimension = true;\n      this.callSuper('initialize', options);\n      this.__skipDimension = false;\n      this.initDimensions();\n      this.setCoords();\n      this.setupState({ propertySet: '_dimensionAffectingProps' });\n    },\n\n    /**\n     * Return a contex for measurement of text string.\n     * if created it gets stored for reuse\n     * @param {String} text Text string\n     * @param {Object} [options] Options object\n     * @return {fabric.Text} thisArg\n     */\n    getMeasuringContext: function() {\n      // if we did not return we have to measure something.\n      if (!fabric._measuringContext) {\n        fabric._measuringContext = this.canvas && this.canvas.contextCache ||\n          fabric.util.createCanvasElement().getContext('2d');\n      }\n      return fabric._measuringContext;\n    },\n\n    /**\n     * @private\n     * Divides text into lines of text and lines of graphemes.\n     */\n    _splitText: function() {\n      var newLines = this._splitTextIntoLines(this.text);\n      this.textLines = newLines.lines;\n      this._textLines = newLines.graphemeLines;\n      this._unwrappedTextLines = newLines._unwrappedLines;\n      this._text = newLines.graphemeText;\n      return newLines;\n    },\n\n    /**\n     * Initialize or update text dimensions.\n     * Updates this.width and this.height with the proper values.\n     * Does not return dimensions.\n     */\n    initDimensions: function() {\n      if (this.__skipDimension) {\n        return;\n      }\n      this._splitText();\n      this._clearCache();\n      this.width = this.calcTextWidth() || this.cursorWidth || this.MIN_TEXT_WIDTH;\n      if (this.textAlign.indexOf('justify') !== -1) {\n        // once text is measured we need to make space fatter to make justified text.\n        this.enlargeSpaces();\n      }\n      this.height = this.calcTextHeight();\n      this.saveState({ propertySet: '_dimensionAffectingProps' });\n    },\n\n    /**\n     * Enlarge space boxes and shift the others\n     */\n    enlargeSpaces: function() {\n      var diffSpace, currentLineWidth, numberOfSpaces, accumulatedSpace, line, charBound, spaces;\n      for (var i = 0, len = this._textLines.length; i < len; i++) {\n        if (this.textAlign !== 'justify' && (i === len - 1 || this.isEndOfWrapping(i))) {\n          continue;\n        }\n        accumulatedSpace = 0;\n        line = this._textLines[i];\n        currentLineWidth = this.getLineWidth(i);\n        if (currentLineWidth < this.width && (spaces = this.textLines[i].match(this._reSpacesAndTabs))) {\n          numberOfSpaces = spaces.length;\n          diffSpace = (this.width - currentLineWidth) / numberOfSpaces;\n          for (var j = 0, jlen = line.length; j <= jlen; j++) {\n            charBound = this.__charBounds[i][j];\n            if (this._reSpaceAndTab.test(line[j])) {\n              charBound.width += diffSpace;\n              charBound.kernedWidth += diffSpace;\n              charBound.left += accumulatedSpace;\n              accumulatedSpace += diffSpace;\n            }\n            else {\n              charBound.left += accumulatedSpace;\n            }\n          }\n        }\n      }\n    },\n\n    /**\n     * Detect if the text line is ended with an hard break\n     * text and itext do not have wrapping, return false\n     * @return {Boolean}\n     */\n    isEndOfWrapping: function(lineIndex) {\n      return lineIndex === this._textLines.length - 1;\n    },\n\n    /**\n     * Detect if a line has a linebreak and so we need to account for it when moving\n     * and counting style.\n     * It return always for text and Itext.\n     * @return Number\n     */\n    missingNewlineOffset: function() {\n      return 1;\n    },\n\n    /**\n     * Returns string representation of an instance\n     * @return {String} String representation of text object\n     */\n    toString: function() {\n      return '#<fabric.Text (' + this.complexity() +\n        '): { \"text\": \"' + this.text + '\", \"fontFamily\": \"' + this.fontFamily + '\" }>';\n    },\n\n    /**\n     * Return the dimension and the zoom level needed to create a cache canvas\n     * big enough to host the object to be cached.\n     * @private\n     * @param {Object} dim.x width of object to be cached\n     * @param {Object} dim.y height of object to be cached\n     * @return {Object}.width width of canvas\n     * @return {Object}.height height of canvas\n     * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\n     * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\n     */\n    _getCacheCanvasDimensions: function() {\n      var dims = this.callSuper('_getCacheCanvasDimensions');\n      var fontSize = this.fontSize;\n      dims.width += fontSize * dims.zoomX;\n      dims.height += fontSize * dims.zoomY;\n      return dims;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function(ctx) {\n      this._setTextStyles(ctx);\n      this._renderTextLinesBackground(ctx);\n      this._renderTextDecoration(ctx, 'underline');\n      this._renderText(ctx);\n      this._renderTextDecoration(ctx, 'overline');\n      this._renderTextDecoration(ctx, 'linethrough');\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderText: function(ctx) {\n      if (this.paintFirst === 'stroke') {\n        this._renderTextStroke(ctx);\n        this._renderTextFill(ctx);\n      }\n      else {\n        this._renderTextFill(ctx);\n        this._renderTextStroke(ctx);\n      }\n    },\n\n    /**\n     * Set the font parameter of the context with the object properties or with charStyle\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Object} [charStyle] object with font style properties\n     * @param {String} [charStyle.fontFamily] Font Family\n     * @param {Number} [charStyle.fontSize] Font size in pixels. ( without px suffix )\n     * @param {String} [charStyle.fontWeight] Font weight\n     * @param {String} [charStyle.fontStyle] Font style (italic|normal)\n     */\n    _setTextStyles: function(ctx, charStyle, forMeasuring) {\n      ctx.textBaseline = 'alphabetic';\n      ctx.font = this._getFontDeclaration(charStyle, forMeasuring);\n    },\n\n    /**\n     * calculate and return the text Width measuring each line.\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @return {Number} Maximum width of fabric.Text object\n     */\n    calcTextWidth: function() {\n      var maxWidth = this.getLineWidth(0);\n\n      for (var i = 1, len = this._textLines.length; i < len; i++) {\n        var currentLineWidth = this.getLineWidth(i);\n        if (currentLineWidth > maxWidth) {\n          maxWidth = currentLineWidth;\n        }\n      }\n      return maxWidth;\n    },\n\n    /**\n     * @private\n     * @param {String} method Method name (\"fillText\" or \"strokeText\")\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {String} line Text to render\n     * @param {Number} left Left position of text\n     * @param {Number} top Top position of text\n     * @param {Number} lineIndex Index of a line in a text\n     */\n    _renderTextLine: function(method, ctx, line, left, top, lineIndex) {\n      this._renderChars(method, ctx, line, left, top, lineIndex);\n    },\n\n    /**\n     * Renders the text background for lines, taking care of style\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderTextLinesBackground: function(ctx) {\n      if (!this.textBackgroundColor && !this.styleHas('textBackgroundColor')) {\n        return;\n      }\n      var lineTopOffset = 0, heightOfLine,\n          lineLeftOffset, originalFill = ctx.fillStyle,\n          line, lastColor,\n          leftOffset = this._getLeftOffset(),\n          topOffset = this._getTopOffset(),\n          boxStart = 0, boxWidth = 0, charBox, currentColor;\n\n      for (var i = 0, len = this._textLines.length; i < len; i++) {\n        heightOfLine = this.getHeightOfLine(i);\n        if (!this.textBackgroundColor && !this.styleHas('textBackgroundColor', i)) {\n          lineTopOffset += heightOfLine;\n          continue;\n        }\n        line = this._textLines[i];\n        lineLeftOffset = this._getLineLeftOffset(i);\n        boxWidth = 0;\n        boxStart = 0;\n        lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\n        for (var j = 0, jlen = line.length; j < jlen; j++) {\n          charBox = this.__charBounds[i][j];\n          currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\n          if (currentColor !== lastColor) {\n            ctx.fillStyle = lastColor;\n            lastColor && ctx.fillRect(\n              leftOffset + lineLeftOffset + boxStart,\n              topOffset + lineTopOffset,\n              boxWidth,\n              heightOfLine / this.lineHeight\n            );\n            boxStart = charBox.left;\n            boxWidth = charBox.width;\n            lastColor = currentColor;\n          }\n          else {\n            boxWidth += charBox.kernedWidth;\n          }\n        }\n        if (currentColor) {\n          ctx.fillStyle = currentColor;\n          ctx.fillRect(\n            leftOffset + lineLeftOffset + boxStart,\n            topOffset + lineTopOffset,\n            boxWidth,\n            heightOfLine / this.lineHeight\n          );\n        }\n        lineTopOffset += heightOfLine;\n      }\n      ctx.fillStyle = originalFill;\n      // if there is text background color no\n      // other shadows should be casted\n      this._removeShadow(ctx);\n    },\n\n    /**\n     * @private\n     * @param {Object} decl style declaration for cache\n     * @param {String} decl.fontFamily fontFamily\n     * @param {String} decl.fontStyle fontStyle\n     * @param {String} decl.fontWeight fontWeight\n     * @return {Object} reference to cache\n     */\n    getFontCache: function(decl) {\n      var fontFamily = decl.fontFamily.toLowerCase();\n      if (!fabric.charWidthsCache[fontFamily]) {\n        fabric.charWidthsCache[fontFamily] = { };\n      }\n      var cache = fabric.charWidthsCache[fontFamily],\n          cacheProp = decl.fontStyle.toLowerCase() + '_' + (decl.fontWeight + '').toLowerCase();\n      if (!cache[cacheProp]) {\n        cache[cacheProp] = { };\n      }\n      return cache[cacheProp];\n    },\n\n    /**\n     * apply all the character style to canvas for rendering\n     * @private\n     * @param {String} _char\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @param {Object} [decl]\n     */\n    _applyCharStyles: function(method, ctx, lineIndex, charIndex, styleDeclaration) {\n\n      this._setFillStyles(ctx, styleDeclaration);\n      this._setStrokeStyles(ctx, styleDeclaration);\n\n      ctx.font = this._getFontDeclaration(styleDeclaration);\n    },\n\n    /**\n     * measure and return the width of a single character.\n     * possibly overridden to accommodate different measure logic or\n     * to hook some external lib for character measurement\n     * @private\n     * @param {String} _char, char to be measured\n     * @param {Object} charStyle style of char to be measured\n     * @param {String} [previousChar] previous char\n     * @param {Object} [prevCharStyle] style of previous char\n     */\n    _measureChar: function(_char, charStyle, previousChar, prevCharStyle) {\n      // first i try to return from cache\n      var fontCache = this.getFontCache(charStyle), fontDeclaration = this._getFontDeclaration(charStyle),\n          previousFontDeclaration = this._getFontDeclaration(prevCharStyle), couple = previousChar + _char,\n          stylesAreEqual = fontDeclaration === previousFontDeclaration, width, coupleWidth, previousWidth,\n          fontMultiplier = charStyle.fontSize / this.CACHE_FONT_SIZE, kernedWidth;\n\n      if (previousChar && fontCache[previousChar] !== undefined) {\n        previousWidth = fontCache[previousChar];\n      }\n      if (fontCache[_char] !== undefined) {\n        kernedWidth = width = fontCache[_char];\n      }\n      if (stylesAreEqual && fontCache[couple] !== undefined) {\n        coupleWidth = fontCache[couple];\n        kernedWidth = coupleWidth - previousWidth;\n      }\n      if (width === undefined || previousWidth === undefined || coupleWidth === undefined) {\n        var ctx = this.getMeasuringContext();\n        // send a TRUE to specify measuring font size CACHE_FONT_SIZE\n        this._setTextStyles(ctx, charStyle, true);\n      }\n      if (width === undefined) {\n        kernedWidth = width = ctx.measureText(_char).width;\n        fontCache[_char] = width;\n      }\n      if (previousWidth === undefined && stylesAreEqual && previousChar) {\n        previousWidth = ctx.measureText(previousChar).width;\n        fontCache[previousChar] = previousWidth;\n      }\n      if (stylesAreEqual && coupleWidth === undefined) {\n        // we can measure the kerning couple and subtract the width of the previous character\n        coupleWidth = ctx.measureText(couple).width;\n        fontCache[couple] = coupleWidth;\n        kernedWidth = coupleWidth - previousWidth;\n      }\n      return { width: width * fontMultiplier, kernedWidth: kernedWidth * fontMultiplier };\n    },\n\n    /**\n     * Computes height of character at given position\n     * @param {Number} line the line index number\n     * @param {Number} _char the character index number\n     * @return {Number} fontSize of the character\n     */\n    getHeightOfChar: function(line, _char) {\n      return this.getValueOfPropertyAt(line, _char, 'fontSize');\n    },\n\n    /**\n     * measure a text line measuring all characters.\n     * @param {Number} lineIndex line number\n     * @return {Number} Line width\n     */\n    measureLine: function(lineIndex) {\n      var lineInfo = this._measureLine(lineIndex);\n      if (this.charSpacing !== 0) {\n        lineInfo.width -= this._getWidthOfCharSpacing();\n      }\n      if (lineInfo.width < 0) {\n        lineInfo.width = 0;\n      }\n      return lineInfo;\n    },\n\n    /**\n     * measure every grapheme of a line, populating __charBounds\n     * @param {Number} lineIndex\n     * @return {Object} object.width total width of characters\n     * @return {Object} object.widthOfSpaces length of chars that match this._reSpacesAndTabs\n     */\n    _measureLine: function(lineIndex) {\n      var width = 0, i, grapheme, line = this._textLines[lineIndex], prevGrapheme,\n          graphemeInfo, numOfSpaces = 0, lineBounds = new Array(line.length);\n\n      this.__charBounds[lineIndex] = lineBounds;\n      for (i = 0; i < line.length; i++) {\n        grapheme = line[i];\n        graphemeInfo = this._getGraphemeBox(grapheme, lineIndex, i, prevGrapheme);\n        lineBounds[i] = graphemeInfo;\n        width += graphemeInfo.kernedWidth;\n        prevGrapheme = grapheme;\n      }\n      // this latest bound box represent the last character of the line\n      // to simplify cursor handling in interactive mode.\n      lineBounds[i] = {\n        left: graphemeInfo ? graphemeInfo.left + graphemeInfo.width : 0,\n        width: 0,\n        kernedWidth: 0,\n        height: this.fontSize\n      };\n      return { width: width, numOfSpaces: numOfSpaces };\n    },\n\n    /**\n     * Measure and return the info of a single grapheme.\n     * needs the the info of previous graphemes already filled\n     * @private\n     * @param {String} grapheme to be measured\n     * @param {Number} lineIndex index of the line where the char is\n     * @param {Number} charIndex position in the line\n     * @param {String} [prevGrapheme] character preceding the one to be measured\n     */\n    _getGraphemeBox: function(grapheme, lineIndex, charIndex, prevGrapheme, skipLeft) {\n      var style = this.getCompleteStyleDeclaration(lineIndex, charIndex),\n          prevStyle = prevGrapheme ? this.getCompleteStyleDeclaration(lineIndex, charIndex - 1) : { },\n          info = this._measureChar(grapheme, style, prevGrapheme, prevStyle),\n          kernedWidth = info.kernedWidth,\n          width = info.width, charSpacing;\n\n      if (this.charSpacing !== 0) {\n        charSpacing = this._getWidthOfCharSpacing();\n        width += charSpacing;\n        kernedWidth += charSpacing;\n      }\n\n      var box = {\n        width: width,\n        left: 0,\n        height: style.fontSize,\n        kernedWidth: kernedWidth,\n        deltaY: style.deltaY,\n      };\n      if (charIndex > 0 && !skipLeft) {\n        var previousBox = this.__charBounds[lineIndex][charIndex - 1];\n        box.left = previousBox.left + previousBox.width + info.kernedWidth - info.width;\n      }\n      return box;\n    },\n\n    /**\n     * Calculate height of line at 'lineIndex'\n     * @param {Number} lineIndex index of line to calculate\n     * @return {Number}\n     */\n    getHeightOfLine: function(lineIndex) {\n      if (this.__lineHeights[lineIndex]) {\n        return this.__lineHeights[lineIndex];\n      }\n\n      var line = this._textLines[lineIndex],\n          // char 0 is measured before the line cycle because it nneds to char\n          // emptylines\n          maxHeight = this.getHeightOfChar(lineIndex, 0);\n      for (var i = 1, len = line.length; i < len; i++) {\n        maxHeight = Math.max(this.getHeightOfChar(lineIndex, i), maxHeight);\n      }\n\n      return this.__lineHeights[lineIndex] = maxHeight * this.lineHeight * this._fontSizeMult;\n    },\n\n    /**\n     * Calculate text box height\n     */\n    calcTextHeight: function() {\n      var lineHeight, height = 0;\n      for (var i = 0, len = this._textLines.length; i < len; i++) {\n        lineHeight = this.getHeightOfLine(i);\n        height += (i === len - 1 ? lineHeight / this.lineHeight : lineHeight);\n      }\n      return height;\n    },\n\n    /**\n     * @private\n     * @return {Number} Left offset\n     */\n    _getLeftOffset: function() {\n      return -this.width / 2;\n    },\n\n    /**\n     * @private\n     * @return {Number} Top offset\n     */\n    _getTopOffset: function() {\n      return -this.height / 2;\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {String} method Method name (\"fillText\" or \"strokeText\")\n     */\n    _renderTextCommon: function(ctx, method) {\n      ctx.save();\n      var lineHeights = 0, left = this._getLeftOffset(), top = this._getTopOffset(),\n          offsets = this._applyPatternGradientTransform(ctx, method === 'fillText' ? this.fill : this.stroke);\n      for (var i = 0, len = this._textLines.length; i < len; i++) {\n        var heightOfLine = this.getHeightOfLine(i),\n            maxHeight = heightOfLine / this.lineHeight,\n            leftOffset = this._getLineLeftOffset(i);\n        this._renderTextLine(\n          method,\n          ctx,\n          this._textLines[i],\n          left + leftOffset - offsets.offsetX,\n          top + lineHeights + maxHeight - offsets.offsetY,\n          i\n        );\n        lineHeights += heightOfLine;\n      }\n      ctx.restore();\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderTextFill: function(ctx) {\n      if (!this.fill && !this.styleHas('fill')) {\n        return;\n      }\n\n      this._renderTextCommon(ctx, 'fillText');\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderTextStroke: function(ctx) {\n      if ((!this.stroke || this.strokeWidth === 0) && this.isEmptyStyles()) {\n        return;\n      }\n\n      if (this.shadow && !this.shadow.affectStroke) {\n        this._removeShadow(ctx);\n      }\n\n      ctx.save();\n      this._setLineDash(ctx, this.strokeDashArray);\n      ctx.beginPath();\n      this._renderTextCommon(ctx, 'strokeText');\n      ctx.closePath();\n      ctx.restore();\n    },\n\n    /**\n     * @private\n     * @param {String} method fillText or strokeText.\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Array} line Content of the line, splitted in an array by grapheme\n     * @param {Number} left\n     * @param {Number} top\n     * @param {Number} lineIndex\n     */\n    _renderChars: function(method, ctx, line, left, top, lineIndex) {\n      // set proper line offset\n      var lineHeight = this.getHeightOfLine(lineIndex),\n          isJustify = this.textAlign.indexOf('justify') !== -1,\n          actualStyle,\n          nextStyle,\n          charsToRender = '',\n          charBox,\n          boxWidth = 0,\n          timeToRender,\n          shortCut = !isJustify && this.charSpacing === 0 && this.isEmptyStyles(lineIndex);\n\n      ctx.save();\n      top -= lineHeight * this._fontSizeFraction / this.lineHeight;\n      if (shortCut) {\n        // render all the line in one pass without checking\n        this._renderChar(method, ctx, lineIndex, 0, line.join(''), left, top, lineHeight);\n        ctx.restore();\n        return;\n      }\n      for (var i = 0, len = line.length - 1; i <= len; i++) {\n        timeToRender = i === len || this.charSpacing;\n        charsToRender += line[i];\n        charBox = this.__charBounds[lineIndex][i];\n        if (boxWidth === 0) {\n          left += charBox.kernedWidth - charBox.width;\n          boxWidth += charBox.width;\n        }\n        else {\n          boxWidth += charBox.kernedWidth;\n        }\n        if (isJustify && !timeToRender) {\n          if (this._reSpaceAndTab.test(line[i])) {\n            timeToRender = true;\n          }\n        }\n        if (!timeToRender) {\n          // if we have charSpacing, we render char by char\n          actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\n          nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\n          timeToRender = this._hasStyleChanged(actualStyle, nextStyle);\n        }\n        if (timeToRender) {\n          this._renderChar(method, ctx, lineIndex, i, charsToRender, left, top, lineHeight);\n          charsToRender = '';\n          actualStyle = nextStyle;\n          left += boxWidth;\n          boxWidth = 0;\n        }\n      }\n      ctx.restore();\n    },\n\n    /**\n     * @private\n     * @param {String} method\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @param {String} _char\n     * @param {Number} left Left coordinate\n     * @param {Number} top Top coordinate\n     * @param {Number} lineHeight Height of the line\n     */\n    _renderChar: function(method, ctx, lineIndex, charIndex, _char, left, top) {\n      var decl = this._getStyleDeclaration(lineIndex, charIndex),\n          fullDecl = this.getCompleteStyleDeclaration(lineIndex, charIndex),\n          shouldFill = method === 'fillText' && fullDecl.fill,\n          shouldStroke = method === 'strokeText' && fullDecl.stroke && fullDecl.strokeWidth;\n\n      if (!shouldStroke && !shouldFill) {\n        return;\n      }\n      decl && ctx.save();\n\n      this._applyCharStyles(method, ctx, lineIndex, charIndex, fullDecl);\n\n      if (decl && decl.textBackgroundColor) {\n        this._removeShadow(ctx);\n      }\n      if (decl && decl.deltaY) {\n        top += decl.deltaY;\n      }\n\n      shouldFill && ctx.fillText(_char, left, top);\n      shouldStroke && ctx.strokeText(_char, left, top);\n      decl && ctx.restore();\n    },\n\n    /**\n     * Turns the character into a 'superior figure' (i.e. 'superscript')\n     * @param {Number} start selection start\n     * @param {Number} end selection end\n     * @returns {fabric.Text} thisArg\n     * @chainable\n     */\n    setSuperscript: function(start, end) {\n      return this._setScript(start, end, this.superscript);\n    },\n\n    /**\n     * Turns the character into an 'inferior figure' (i.e. 'subscript')\n     * @param {Number} start selection start\n     * @param {Number} end selection end\n     * @returns {fabric.Text} thisArg\n     * @chainable\n     */\n    setSubscript: function(start, end) {\n      return this._setScript(start, end, this.subscript);\n    },\n\n    /**\n     * Applies 'schema' at given position\n     * @private\n     * @param {Number} start selection start\n     * @param {Number} end selection end\n     * @param {Number} schema\n     * @returns {fabric.Text} thisArg\n     * @chainable\n     */\n    _setScript: function(start, end, schema) {\n      var loc = this.get2DCursorLocation(start, true),\n          fontSize = this.getValueOfPropertyAt(loc.lineIndex, loc.charIndex, 'fontSize'),\n          dy = this.getValueOfPropertyAt(loc.lineIndex, loc.charIndex, 'deltaY'),\n          style = { fontSize: fontSize * schema.size, deltaY: dy + fontSize * schema.baseline };\n      this.setSelectionStyles(style, start, end);\n      return this;\n    },\n\n    /**\n     * @private\n     * @param {Object} prevStyle\n     * @param {Object} thisStyle\n     */\n    _hasStyleChanged: function(prevStyle, thisStyle) {\n      return prevStyle.fill !== thisStyle.fill ||\n              prevStyle.stroke !== thisStyle.stroke ||\n              prevStyle.strokeWidth !== thisStyle.strokeWidth ||\n              prevStyle.fontSize !== thisStyle.fontSize ||\n              prevStyle.fontFamily !== thisStyle.fontFamily ||\n              prevStyle.fontWeight !== thisStyle.fontWeight ||\n              prevStyle.fontStyle !== thisStyle.fontStyle ||\n              prevStyle.deltaY !== thisStyle.deltaY;\n    },\n\n    /**\n     * @private\n     * @param {Object} prevStyle\n     * @param {Object} thisStyle\n     */\n    _hasStyleChangedForSvg: function(prevStyle, thisStyle) {\n      return this._hasStyleChanged(prevStyle, thisStyle) ||\n        prevStyle.overline !== thisStyle.overline ||\n        prevStyle.underline !== thisStyle.underline ||\n        prevStyle.linethrough !== thisStyle.linethrough;\n    },\n\n    /**\n     * @private\n     * @param {Number} lineIndex index text line\n     * @return {Number} Line left offset\n     */\n    _getLineLeftOffset: function(lineIndex) {\n      var lineWidth = this.getLineWidth(lineIndex);\n      if (this.textAlign === 'center') {\n        return (this.width - lineWidth) / 2;\n      }\n      if (this.textAlign === 'right') {\n        return this.width - lineWidth;\n      }\n      if (this.textAlign === 'justify-center' && this.isEndOfWrapping(lineIndex)) {\n        return (this.width - lineWidth) / 2;\n      }\n      if (this.textAlign === 'justify-right' && this.isEndOfWrapping(lineIndex)) {\n        return this.width - lineWidth;\n      }\n      return 0;\n    },\n\n    /**\n     * @private\n     */\n    _clearCache: function() {\n      this.__lineWidths = [];\n      this.__lineHeights = [];\n      this.__charBounds = [];\n    },\n\n    /**\n     * @private\n     */\n    _shouldClearDimensionCache: function() {\n      var shouldClear = this._forceClearCache;\n      shouldClear || (shouldClear = this.hasStateChanged('_dimensionAffectingProps'));\n      if (shouldClear) {\n        this.dirty = true;\n        this._forceClearCache = false;\n      }\n      return shouldClear;\n    },\n\n    /**\n     * Measure a single line given its index. Used to calculate the initial\n     * text bounding box. The values are calculated and stored in __lineWidths cache.\n     * @private\n     * @param {Number} lineIndex line number\n     * @return {Number} Line width\n     */\n    getLineWidth: function(lineIndex) {\n      if (this.__lineWidths[lineIndex]) {\n        return this.__lineWidths[lineIndex];\n      }\n\n      var width, line = this._textLines[lineIndex], lineInfo;\n\n      if (line === '') {\n        width = 0;\n      }\n      else {\n        lineInfo = this.measureLine(lineIndex);\n        width = lineInfo.width;\n      }\n      this.__lineWidths[lineIndex] = width;\n      return width;\n    },\n\n    _getWidthOfCharSpacing: function() {\n      if (this.charSpacing !== 0) {\n        return this.fontSize * this.charSpacing / 1000;\n      }\n      return 0;\n    },\n\n    /**\n     * Retrieves the value of property at given character position\n     * @param {Number} lineIndex the line number\n     * @param {Number} charIndex the charater number\n     * @param {String} property the property name\n     * @returns the value of 'property'\n     */\n    getValueOfPropertyAt: function(lineIndex, charIndex, property) {\n      var charStyle = this._getStyleDeclaration(lineIndex, charIndex);\n      if (charStyle && typeof charStyle[property] !== 'undefined') {\n        return charStyle[property];\n      }\n      return this[property];\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _renderTextDecoration: function(ctx, type) {\n      if (!this[type] && !this.styleHas(type)) {\n        return;\n      }\n      var heightOfLine, size, _size,\n          lineLeftOffset, dy, _dy,\n          line, lastDecoration,\n          leftOffset = this._getLeftOffset(),\n          topOffset = this._getTopOffset(), top,\n          boxStart, boxWidth, charBox, currentDecoration,\n          maxHeight, currentFill, lastFill,\n          charSpacing = this._getWidthOfCharSpacing();\n\n      for (var i = 0, len = this._textLines.length; i < len; i++) {\n        heightOfLine = this.getHeightOfLine(i);\n        if (!this[type] && !this.styleHas(type, i)) {\n          topOffset += heightOfLine;\n          continue;\n        }\n        line = this._textLines[i];\n        maxHeight = heightOfLine / this.lineHeight;\n        lineLeftOffset = this._getLineLeftOffset(i);\n        boxStart = 0;\n        boxWidth = 0;\n        lastDecoration = this.getValueOfPropertyAt(i, 0, type);\n        lastFill = this.getValueOfPropertyAt(i, 0, 'fill');\n        top = topOffset + maxHeight * (1 - this._fontSizeFraction);\n        size = this.getHeightOfChar(i, 0);\n        dy = this.getValueOfPropertyAt(i, 0, 'deltaY');\n        for (var j = 0, jlen = line.length; j < jlen; j++) {\n          charBox = this.__charBounds[i][j];\n          currentDecoration = this.getValueOfPropertyAt(i, j, type);\n          currentFill = this.getValueOfPropertyAt(i, j, 'fill');\n          _size = this.getHeightOfChar(i, j);\n          _dy = this.getValueOfPropertyAt(i, j, 'deltaY');\n          if ((currentDecoration !== lastDecoration || currentFill !== lastFill || _size !== size || _dy !== dy) &&\n              boxWidth > 0) {\n            ctx.fillStyle = lastFill;\n            lastDecoration && lastFill && ctx.fillRect(\n              leftOffset + lineLeftOffset + boxStart,\n              top + this.offsets[type] * size + dy,\n              boxWidth,\n              this.fontSize / 15\n            );\n            boxStart = charBox.left;\n            boxWidth = charBox.width;\n            lastDecoration = currentDecoration;\n            lastFill = currentFill;\n            size = _size;\n            dy = _dy;\n          }\n          else {\n            boxWidth += charBox.kernedWidth;\n          }\n        }\n        ctx.fillStyle = currentFill;\n        currentDecoration && currentFill && ctx.fillRect(\n          leftOffset + lineLeftOffset + boxStart,\n          top + this.offsets[type] * size + dy,\n          boxWidth - charSpacing,\n          this.fontSize / 15\n        );\n        topOffset += heightOfLine;\n      }\n      // if there is text background color no\n      // other shadows should be casted\n      this._removeShadow(ctx);\n    },\n\n    /**\n     * return font declaration string for canvas context\n     * @param {Object} [styleObject] object\n     * @returns {String} font declaration formatted for canvas context.\n     */\n    _getFontDeclaration: function(styleObject, forMeasuring) {\n      var style = styleObject || this, family = this.fontFamily,\n          fontIsGeneric = fabric.Text.genericFonts.indexOf(family.toLowerCase()) > -1;\n      var fontFamily = family === undefined ||\n      family.indexOf('\\'') > -1 || family.indexOf(',') > -1 ||\n      family.indexOf('\"') > -1 || fontIsGeneric\n        ? style.fontFamily : '\"' + style.fontFamily + '\"';\n      return [\n        // node-canvas needs \"weight style\", while browsers need \"style weight\"\n        // verify if this can be fixed in JSDOM\n        (fabric.isLikelyNode ? style.fontWeight : style.fontStyle),\n        (fabric.isLikelyNode ? style.fontStyle : style.fontWeight),\n        forMeasuring ? this.CACHE_FONT_SIZE + 'px' : style.fontSize + 'px',\n        fontFamily\n      ].join(' ');\n    },\n\n    /**\n     * Renders text instance on a specified context\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    render: function(ctx) {\n      // do not render if object is not visible\n      if (!this.visible) {\n        return;\n      }\n      if (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) {\n        return;\n      }\n      if (this._shouldClearDimensionCache()) {\n        this.initDimensions();\n      }\n      this.callSuper('render', ctx);\n    },\n\n    /**\n     * Returns the text as an array of lines.\n     * @param {String} text text to split\n     * @returns {Array} Lines in the text\n     */\n    _splitTextIntoLines: function(text) {\n      var lines = text.split(this._reNewline),\n          newLines = new Array(lines.length),\n          newLine = ['\\n'],\n          newText = [];\n      for (var i = 0; i < lines.length; i++) {\n        newLines[i] = fabric.util.string.graphemeSplit(lines[i]);\n        newText = newText.concat(newLines[i], newLine);\n      }\n      newText.pop();\n      return { _unwrappedLines: newLines, lines: lines, graphemeText: newText, graphemeLines: newLines };\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} Object representation of an instance\n     */\n    toObject: function(propertiesToInclude) {\n      var additionalProperties = [\n        'text',\n        'fontSize',\n        'fontWeight',\n        'fontFamily',\n        'fontStyle',\n        'lineHeight',\n        'underline',\n        'overline',\n        'linethrough',\n        'textAlign',\n        'textBackgroundColor',\n        'charSpacing',\n      ].concat(propertiesToInclude);\n      var obj = this.callSuper('toObject', additionalProperties);\n      obj.styles = clone(this.styles, true);\n      return obj;\n    },\n\n    /**\n     * Sets property to a given value. When changing position/dimension -related properties (left, top, scale, angle, etc.) `set` does not update position of object's borders/controls. If you need to update those, call `setCoords()`.\n     * @param {String|Object} key Property name or object (if object, iterate over the object properties)\n     * @param {Object|Function} value Property value (if function, the value is passed into it and its return value is used as a new one)\n     * @return {fabric.Object} thisArg\n     * @chainable\n     */\n    set: function(key, value) {\n      this.callSuper('set', key, value);\n      var needsDims = false;\n      if (typeof key === 'object') {\n        for (var _key in key) {\n          needsDims = needsDims || this._dimensionAffectingProps.indexOf(_key) !== -1;\n        }\n      }\n      else {\n        needsDims = this._dimensionAffectingProps.indexOf(key) !== -1;\n      }\n      if (needsDims) {\n        this.initDimensions();\n        this.setCoords();\n      }\n      return this;\n    },\n\n    /**\n     * Returns complexity of an instance\n     * @return {Number} complexity\n     */\n    complexity: function() {\n      return 1;\n    }\n  });\n\n  /* _FROM_SVG_START_ */\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Text.fromElement})\n   * @static\n   * @memberOf fabric.Text\n   * @see: http://www.w3.org/TR/SVG/text.html#TextElement\n   */\n  fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(\n    'x y dx dy font-family font-style font-weight font-size letter-spacing text-decoration text-anchor'.split(' '));\n\n  /**\n   * Default SVG font size\n   * @static\n   * @memberOf fabric.Text\n   */\n  fabric.Text.DEFAULT_SVG_FONT_SIZE = 16;\n\n  /**\n   * Returns fabric.Text instance from an SVG element (<b>not yet implemented</b>)\n   * @static\n   * @memberOf fabric.Text\n   * @param {SVGElement} element Element to parse\n   * @param {Function} callback callback function invoked after parsing\n   * @param {Object} [options] Options object\n   */\n  fabric.Text.fromElement = function(element, callback, options) {\n    if (!element) {\n      return callback(null);\n    }\n\n    var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES),\n        parsedAnchor = parsedAttributes.textAnchor || 'left';\n    options = fabric.util.object.extend((options ? clone(options) : { }), parsedAttributes);\n\n    options.top = options.top || 0;\n    options.left = options.left || 0;\n    if (parsedAttributes.textDecoration) {\n      var textDecoration = parsedAttributes.textDecoration;\n      if (textDecoration.indexOf('underline') !== -1) {\n        options.underline = true;\n      }\n      if (textDecoration.indexOf('overline') !== -1) {\n        options.overline = true;\n      }\n      if (textDecoration.indexOf('line-through') !== -1) {\n        options.linethrough = true;\n      }\n      delete options.textDecoration;\n    }\n    if ('dx' in parsedAttributes) {\n      options.left += parsedAttributes.dx;\n    }\n    if ('dy' in parsedAttributes) {\n      options.top += parsedAttributes.dy;\n    }\n    if (!('fontSize' in options)) {\n      options.fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;\n    }\n\n    var textContent = '';\n\n    // The XML is not properly parsed in IE9 so a workaround to get\n    // textContent is through firstChild.data. Another workaround would be\n    // to convert XML loaded from a file to be converted using DOMParser (same way loadSVGFromString() does)\n    if (!('textContent' in element)) {\n      if ('firstChild' in element && element.firstChild !== null) {\n        if ('data' in element.firstChild && element.firstChild.data !== null) {\n          textContent = element.firstChild.data;\n        }\n      }\n    }\n    else {\n      textContent = element.textContent;\n    }\n\n    textContent = textContent.replace(/^\\s+|\\s+$|\\n+/g, '').replace(/\\s+/g, ' ');\n    var originalStrokeWidth = options.strokeWidth;\n    options.strokeWidth = 0;\n\n    var text = new fabric.Text(textContent, options),\n        textHeightScaleFactor = text.getScaledHeight() / text.height,\n        lineHeightDiff = (text.height + text.strokeWidth) * text.lineHeight - text.height,\n        scaledDiff = lineHeightDiff * textHeightScaleFactor,\n        textHeight = text.getScaledHeight() + scaledDiff,\n        offX = 0;\n    /*\n      Adjust positioning:\n        x/y attributes in SVG correspond to the bottom-left corner of text bounding box\n        fabric output by default at top, left.\n    */\n    if (parsedAnchor === 'center') {\n      offX = text.getScaledWidth() / 2;\n    }\n    if (parsedAnchor === 'right') {\n      offX = text.getScaledWidth();\n    }\n    text.set({\n      left: text.left - offX,\n      top: text.top - (textHeight - text.fontSize * (0.07 + text._fontSizeFraction)) / text.lineHeight,\n      strokeWidth: typeof originalStrokeWidth !== 'undefined' ? originalStrokeWidth : 1,\n    });\n    callback(text);\n  };\n  /* _FROM_SVG_END_ */\n\n  /**\n   * Returns fabric.Text instance from an object representation\n   * @static\n   * @memberOf fabric.Text\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] Callback to invoke when an fabric.Text instance is created\n   */\n  fabric.Text.fromObject = function(object, callback) {\n    return fabric.Object._fromObject('Text', object, callback, 'text');\n  };\n\n  fabric.Text.genericFonts = ['sans-serif', 'serif', 'cursive', 'fantasy', 'monospace'];\n\n  fabric.util.createAccessors && fabric.util.createAccessors(fabric.Text);\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n  fabric.util.object.extend(fabric.Text.prototype, /** @lends fabric.Text.prototype */ {\n    /**\n     * Returns true if object has no styling or no styling in a line\n     * @param {Number} lineIndex , lineIndex is on wrapped lines.\n     * @return {Boolean}\n     */\n    isEmptyStyles: function(lineIndex) {\n      if (!this.styles) {\n        return true;\n      }\n      if (typeof lineIndex !== 'undefined' && !this.styles[lineIndex]) {\n        return true;\n      }\n      var obj = typeof lineIndex === 'undefined' ? this.styles : { line: this.styles[lineIndex] };\n      for (var p1 in obj) {\n        for (var p2 in obj[p1]) {\n          // eslint-disable-next-line no-unused-vars\n          for (var p3 in obj[p1][p2]) {\n            return false;\n          }\n        }\n      }\n      return true;\n    },\n\n    /**\n     * Returns true if object has a style property or has it ina specified line\n     * This function is used to detect if a text will use a particular property or not.\n     * @param {String} property to check for\n     * @param {Number} lineIndex to check the style on\n     * @return {Boolean}\n     */\n    styleHas: function(property, lineIndex) {\n      if (!this.styles || !property || property === '') {\n        return false;\n      }\n      if (typeof lineIndex !== 'undefined' && !this.styles[lineIndex]) {\n        return false;\n      }\n      var obj = typeof lineIndex === 'undefined' ? this.styles : { 0: this.styles[lineIndex] };\n      // eslint-disable-next-line\n      for (var p1 in obj) {\n        // eslint-disable-next-line\n        for (var p2 in obj[p1]) {\n          if (typeof obj[p1][p2][property] !== 'undefined') {\n            return true;\n          }\n        }\n      }\n      return false;\n    },\n\n    /**\n     * Check if characters in a text have a value for a property\n     * whose value matches the textbox's value for that property.  If so,\n     * the character-level property is deleted.  If the character\n     * has no other properties, then it is also deleted.  Finally,\n     * if the line containing that character has no other characters\n     * then it also is deleted.\n     *\n     * @param {string} property The property to compare between characters and text.\n     */\n    cleanStyle: function(property) {\n      if (!this.styles || !property || property === '') {\n        return false;\n      }\n      var obj = this.styles, stylesCount = 0, letterCount, stylePropertyValue,\n          allStyleObjectPropertiesMatch = true, graphemeCount = 0, styleObject;\n      // eslint-disable-next-line\n      for (var p1 in obj) {\n        letterCount = 0;\n        // eslint-disable-next-line\n        for (var p2 in obj[p1]) {\n          var styleObject = obj[p1][p2],\n              stylePropertyHasBeenSet = styleObject.hasOwnProperty(property);\n\n          stylesCount++;\n\n          if (stylePropertyHasBeenSet) {\n            if (!stylePropertyValue) {\n              stylePropertyValue = styleObject[property];\n            }\n            else if (styleObject[property] !== stylePropertyValue) {\n              allStyleObjectPropertiesMatch = false;\n            }\n\n            if (styleObject[property] === this[property]) {\n              delete styleObject[property];\n            }\n          }\n          else {\n            allStyleObjectPropertiesMatch = false;\n          }\n\n          if (Object.keys(styleObject).length !== 0) {\n            letterCount++;\n          }\n          else {\n            delete obj[p1][p2];\n          }\n        }\n\n        if (letterCount === 0) {\n          delete obj[p1];\n        }\n      }\n      // if every grapheme has the same style set then\n      // delete those styles and set it on the parent\n      for (var i = 0; i < this._textLines.length; i++) {\n        graphemeCount += this._textLines[i].length;\n      }\n      if (allStyleObjectPropertiesMatch && stylesCount === graphemeCount) {\n        this[property] = stylePropertyValue;\n        this.removeStyle(property);\n      }\n    },\n\n    /**\n     * Remove a style property or properties from all individual character styles\n     * in a text object.  Deletes the character style object if it contains no other style\n     * props.  Deletes a line style object if it contains no other character styles.\n     *\n     * @param {String} props The property to remove from character styles.\n     */\n    removeStyle: function(property) {\n      if (!this.styles || !property || property === '') {\n        return;\n      }\n      var obj = this.styles, line, lineNum, charNum;\n      for (lineNum in obj) {\n        line = obj[lineNum];\n        for (charNum in line) {\n          delete line[charNum][property];\n          if (Object.keys(line[charNum]).length === 0) {\n            delete line[charNum];\n          }\n        }\n        if (Object.keys(line).length === 0) {\n          delete obj[lineNum];\n        }\n      }\n    },\n\n    /**\n     * @private\n     */\n    _extendStyles: function(index, styles) {\n      var loc = this.get2DCursorLocation(index);\n\n      if (!this._getLineStyle(loc.lineIndex)) {\n        this._setLineStyle(loc.lineIndex);\n      }\n\n      if (!this._getStyleDeclaration(loc.lineIndex, loc.charIndex)) {\n        this._setStyleDeclaration(loc.lineIndex, loc.charIndex, {});\n      }\n\n      fabric.util.object.extend(this._getStyleDeclaration(loc.lineIndex, loc.charIndex), styles);\n    },\n\n    /**\n     * Returns 2d representation (lineIndex and charIndex) of cursor (or selection start)\n     * @param {Number} [selectionStart] Optional index. When not given, current selectionStart is used.\n     * @param {Boolean} [skipWrapping] consider the location for unwrapped lines. useful to manage styles.\n     */\n    get2DCursorLocation: function(selectionStart, skipWrapping) {\n      if (typeof selectionStart === 'undefined') {\n        selectionStart = this.selectionStart;\n      }\n      var lines = skipWrapping ? this._unwrappedTextLines : this._textLines,\n          len = lines.length;\n      for (var i = 0; i < len; i++) {\n        if (selectionStart <= lines[i].length) {\n          return {\n            lineIndex: i,\n            charIndex: selectionStart\n          };\n        }\n        selectionStart -= lines[i].length + this.missingNewlineOffset(i);\n      }\n      return {\n        lineIndex: i - 1,\n        charIndex: lines[i - 1].length < selectionStart ? lines[i - 1].length : selectionStart\n      };\n    },\n\n    /**\n     * Gets style of a current selection/cursor (at the start position)\n     * if startIndex or endIndex are not provided, slectionStart or selectionEnd will be used.\n     * @param {Number} [startIndex] Start index to get styles at\n     * @param {Number} [endIndex] End index to get styles at, if not specified selectionEnd or startIndex + 1\n     * @param {Boolean} [complete] get full style or not\n     * @return {Array} styles an array with one, zero or more Style objects\n     */\n    getSelectionStyles: function(startIndex, endIndex, complete) {\n      if (typeof startIndex === 'undefined') {\n        startIndex = this.selectionStart || 0;\n      }\n      if (typeof endIndex === 'undefined') {\n        endIndex = this.selectionEnd || startIndex;\n      }\n      var styles = [];\n      for (var i = startIndex; i < endIndex; i++) {\n        styles.push(this.getStyleAtPosition(i, complete));\n      }\n      return styles;\n    },\n\n    /**\n     * Gets style of a current selection/cursor position\n     * @param {Number} position  to get styles at\n     * @param {Boolean} [complete] full style if true\n     * @return {Object} style Style object at a specified index\n     * @private\n     */\n    getStyleAtPosition: function(position, complete) {\n      var loc = this.get2DCursorLocation(position),\n          style = complete ? this.getCompleteStyleDeclaration(loc.lineIndex, loc.charIndex) :\n            this._getStyleDeclaration(loc.lineIndex, loc.charIndex);\n      return style || {};\n    },\n\n    /**\n     * Sets style of a current selection, if no selection exist, do not set anything.\n     * @param {Object} [styles] Styles object\n     * @param {Number} [startIndex] Start index to get styles at\n     * @param {Number} [endIndex] End index to get styles at, if not specified selectionEnd or startIndex + 1\n     * @return {fabric.IText} thisArg\n     * @chainable\n     */\n    setSelectionStyles: function(styles, startIndex, endIndex) {\n      if (typeof startIndex === 'undefined') {\n        startIndex = this.selectionStart || 0;\n      }\n      if (typeof endIndex === 'undefined') {\n        endIndex = this.selectionEnd || startIndex;\n      }\n      for (var i = startIndex; i < endIndex; i++) {\n        this._extendStyles(i, styles);\n      }\n      /* not included in _extendStyles to avoid clearing cache more than once */\n      this._forceClearCache = true;\n      return this;\n    },\n\n    /**\n     * get the reference, not a clone, of the style object for a given character\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @return {Object} style object\n     */\n    _getStyleDeclaration: function(lineIndex, charIndex) {\n      var lineStyle = this.styles && this.styles[lineIndex];\n      if (!lineStyle) {\n        return null;\n      }\n      return lineStyle[charIndex];\n    },\n\n    /**\n     * return a new object that contains all the style property for a character\n     * the object returned is newly created\n     * @param {Number} lineIndex of the line where the character is\n     * @param {Number} charIndex position of the character on the line\n     * @return {Object} style object\n     */\n    getCompleteStyleDeclaration: function(lineIndex, charIndex) {\n      var style = this._getStyleDeclaration(lineIndex, charIndex) || { },\n          styleObject = { }, prop;\n      for (var i = 0; i < this._styleProperties.length; i++) {\n        prop = this._styleProperties[i];\n        styleObject[prop] = typeof style[prop] === 'undefined' ? this[prop] : style[prop];\n      }\n      return styleObject;\n    },\n\n    /**\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @param {Object} style\n     * @private\n     */\n    _setStyleDeclaration: function(lineIndex, charIndex, style) {\n      this.styles[lineIndex][charIndex] = style;\n    },\n\n    /**\n     *\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @private\n     */\n    _deleteStyleDeclaration: function(lineIndex, charIndex) {\n      delete this.styles[lineIndex][charIndex];\n    },\n\n    /**\n     * @param {Number} lineIndex\n     * @return {Boolean} if the line exists or not\n     * @private\n     */\n    _getLineStyle: function(lineIndex) {\n      return !!this.styles[lineIndex];\n    },\n\n    /**\n     * Set the line style to an empty object so that is initialized\n     * @param {Number} lineIndex\n     * @private\n     */\n    _setLineStyle: function(lineIndex) {\n      this.styles[lineIndex] = {};\n    },\n\n    /**\n     * @param {Number} lineIndex\n     * @private\n     */\n    _deleteLineStyle: function(lineIndex) {\n      delete this.styles[lineIndex];\n    }\n  });\n})();\n\n\n(function() {\n\n  function parseDecoration(object) {\n    if (object.textDecoration) {\n      object.textDecoration.indexOf('underline') > -1 && (object.underline = true);\n      object.textDecoration.indexOf('line-through') > -1 && (object.linethrough = true);\n      object.textDecoration.indexOf('overline') > -1 && (object.overline = true);\n      delete object.textDecoration;\n    }\n  }\n\n  /**\n   * IText class (introduced in <b>v1.4</b>) Events are also fired with \"text:\"\n   * prefix when observing canvas.\n   * @class fabric.IText\n   * @extends fabric.Text\n   * @mixes fabric.Observable\n   *\n   * @fires changed\n   * @fires selection:changed\n   * @fires editing:entered\n   * @fires editing:exited\n   *\n   * @return {fabric.IText} thisArg\n   * @see {@link fabric.IText#initialize} for constructor definition\n   *\n   * <p>Supported key combinations:</p>\n   * <pre>\n   *   Move cursor:                    left, right, up, down\n   *   Select character:               shift + left, shift + right\n   *   Select text vertically:         shift + up, shift + down\n   *   Move cursor by word:            alt + left, alt + right\n   *   Select words:                   shift + alt + left, shift + alt + right\n   *   Move cursor to line start/end:  cmd + left, cmd + right or home, end\n   *   Select till start/end of line:  cmd + shift + left, cmd + shift + right or shift + home, shift + end\n   *   Jump to start/end of text:      cmd + up, cmd + down\n   *   Select till start/end of text:  cmd + shift + up, cmd + shift + down or shift + pgUp, shift + pgDown\n   *   Delete character:               backspace\n   *   Delete word:                    alt + backspace\n   *   Delete line:                    cmd + backspace\n   *   Forward delete:                 delete\n   *   Copy text:                      ctrl/cmd + c\n   *   Paste text:                     ctrl/cmd + v\n   *   Cut text:                       ctrl/cmd + x\n   *   Select entire text:             ctrl/cmd + a\n   *   Quit editing                    tab or esc\n   * </pre>\n   *\n   * <p>Supported mouse/touch combination</p>\n   * <pre>\n   *   Position cursor:                click/touch\n   *   Create selection:               click/touch & drag\n   *   Create selection:               click & shift + click\n   *   Select word:                    double click\n   *   Select line:                    triple click\n   * </pre>\n   */\n  fabric.IText = fabric.util.createClass(fabric.Text, fabric.Observable, /** @lends fabric.IText.prototype */ {\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'i-text',\n\n    /**\n     * Index where text selection starts (or where cursor is when there is no selection)\n     * @type Number\n     * @default\n     */\n    selectionStart: 0,\n\n    /**\n     * Index where text selection ends\n     * @type Number\n     * @default\n     */\n    selectionEnd: 0,\n\n    /**\n     * Color of text selection\n     * @type String\n     * @default\n     */\n    selectionColor: 'rgba(17,119,255,0.3)',\n\n    /**\n     * Indicates whether text is in editing mode\n     * @type Boolean\n     * @default\n     */\n    isEditing: false,\n\n    /**\n     * Indicates whether a text can be edited\n     * @type Boolean\n     * @default\n     */\n    editable: true,\n\n    /**\n     * Border color of text object while it's in editing mode\n     * @type String\n     * @default\n     */\n    editingBorderColor: 'rgba(102,153,255,0.25)',\n\n    /**\n     * Width of cursor (in px)\n     * @type Number\n     * @default\n     */\n    cursorWidth: 2,\n\n    /**\n     * Color of text cursor color in editing mode.\n     * if not set (default) will take color from the text.\n     * if set to a color value that fabric can understand, it will\n     * be used instead of the color of the text at the current position.\n     * @type String\n     * @default\n     */\n    cursorColor: '',\n\n    /**\n     * Delay between cursor blink (in ms)\n     * @type Number\n     * @default\n     */\n    cursorDelay: 1000,\n\n    /**\n     * Duration of cursor fadein (in ms)\n     * @type Number\n     * @default\n     */\n    cursorDuration: 600,\n\n    /**\n     * Indicates whether internal text char widths can be cached\n     * @type Boolean\n     * @default\n     */\n    caching: true,\n\n    /**\n     * @private\n     */\n    _reSpace: /\\s|\\n/,\n\n    /**\n     * @private\n     */\n    _currentCursorOpacity: 0,\n\n    /**\n     * @private\n     */\n    _selectionDirection: null,\n\n    /**\n     * @private\n     */\n    _abortCursorAnimation: false,\n\n    /**\n     * @private\n     */\n    __widthOfSpace: [],\n\n    /**\n     * Helps determining when the text is in composition, so that the cursor\n     * rendering is altered.\n     */\n    inCompositionMode: false,\n\n    /**\n     * Constructor\n     * @param {String} text Text string\n     * @param {Object} [options] Options object\n     * @return {fabric.IText} thisArg\n     */\n    initialize: function(text, options) {\n      this.callSuper('initialize', text, options);\n      this.initBehavior();\n    },\n\n    /**\n     * Sets selection start (left boundary of a selection)\n     * @param {Number} index Index to set selection start to\n     */\n    setSelectionStart: function(index) {\n      index = Math.max(index, 0);\n      this._updateAndFire('selectionStart', index);\n    },\n\n    /**\n     * Sets selection end (right boundary of a selection)\n     * @param {Number} index Index to set selection end to\n     */\n    setSelectionEnd: function(index) {\n      index = Math.min(index, this.text.length);\n      this._updateAndFire('selectionEnd', index);\n    },\n\n    /**\n     * @private\n     * @param {String} property 'selectionStart' or 'selectionEnd'\n     * @param {Number} index new position of property\n     */\n    _updateAndFire: function(property, index) {\n      if (this[property] !== index) {\n        this._fireSelectionChanged();\n        this[property] = index;\n      }\n      this._updateTextarea();\n    },\n\n    /**\n     * Fires the even of selection changed\n     * @private\n     */\n    _fireSelectionChanged: function() {\n      this.fire('selection:changed');\n      this.canvas && this.canvas.fire('text:selection:changed', { target: this });\n    },\n\n    /**\n     * Initialize text dimensions. Render all text on given context\n     * or on a offscreen canvas to get the text width with measureText.\n     * Updates this.width and this.height with the proper values.\n     * Does not return dimensions.\n     * @private\n     */\n    initDimensions: function() {\n      this.isEditing && this.initDelayedCursor();\n      this.clearContextTop();\n      this.callSuper('initDimensions');\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    render: function(ctx) {\n      this.clearContextTop();\n      this.callSuper('render', ctx);\n      // clear the cursorOffsetCache, so we ensure to calculate once per renderCursor\n      // the correct position but not at every cursor animation.\n      this.cursorOffsetCache = { };\n      this.renderCursorOrSelection();\n    },\n\n    /**\n     * @private\n     * @param {CanvasRenderingContext2D} ctx Context to render on\n     */\n    _render: function(ctx) {\n      this.callSuper('_render', ctx);\n    },\n\n    /**\n     * Prepare and clean the contextTop\n     */\n    clearContextTop: function(skipRestore) {\n      if (!this.isEditing || !this.canvas || !this.canvas.contextTop) {\n        return;\n      }\n      var ctx = this.canvas.contextTop, v = this.canvas.viewportTransform;\n      ctx.save();\n      ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n      this.transform(ctx);\n      this._clearTextArea(ctx);\n      skipRestore || ctx.restore();\n    },\n    /**\n     * Renders cursor or selection (depending on what exists)\n     * it does on the contextTop. If contextTop is not available, do nothing.\n     */\n    renderCursorOrSelection: function() {\n      if (!this.isEditing || !this.canvas || !this.canvas.contextTop) {\n        return;\n      }\n      var boundaries = this._getCursorBoundaries(),\n          ctx = this.canvas.contextTop;\n      this.clearContextTop(true);\n      if (this.selectionStart === this.selectionEnd) {\n        this.renderCursor(boundaries, ctx);\n      }\n      else {\n        this.renderSelection(boundaries, ctx);\n      }\n      ctx.restore();\n    },\n\n    _clearTextArea: function(ctx) {\n      // we add 4 pixel, to be sure to do not leave any pixel out\n      var width = this.width + 4, height = this.height + 4;\n      ctx.clearRect(-width / 2, -height / 2, width, height);\n    },\n\n    /**\n     * Returns cursor boundaries (left, top, leftOffset, topOffset)\n     * @private\n     * @param {Array} chars Array of characters\n     * @param {String} typeOfBoundaries\n     */\n    _getCursorBoundaries: function(position) {\n\n      // left/top are left/top of entire text box\n      // leftOffset/topOffset are offset from that left/top point of a text box\n\n      if (typeof position === 'undefined') {\n        position = this.selectionStart;\n      }\n\n      var left = this._getLeftOffset(),\n          top = this._getTopOffset(),\n          offsets = this._getCursorBoundariesOffsets(position);\n\n      return {\n        left: left,\n        top: top,\n        leftOffset: offsets.left,\n        topOffset: offsets.top\n      };\n    },\n\n    /**\n     * @private\n     */\n    _getCursorBoundariesOffsets: function(position) {\n      if (this.cursorOffsetCache && 'top' in this.cursorOffsetCache) {\n        return this.cursorOffsetCache;\n      }\n      var lineLeftOffset,\n          lineIndex,\n          charIndex,\n          topOffset = 0,\n          leftOffset = 0,\n          boundaries,\n          cursorPosition = this.get2DCursorLocation(position);\n      charIndex = cursorPosition.charIndex;\n      lineIndex = cursorPosition.lineIndex;\n      for (var i = 0; i < lineIndex; i++) {\n        topOffset += this.getHeightOfLine(i);\n      }\n      lineLeftOffset = this._getLineLeftOffset(lineIndex);\n      var bound = this.__charBounds[lineIndex][charIndex];\n      bound && (leftOffset = bound.left);\n      if (this.charSpacing !== 0 && charIndex === this._textLines[lineIndex].length) {\n        leftOffset -= this._getWidthOfCharSpacing();\n      }\n      boundaries = {\n        top: topOffset,\n        left: lineLeftOffset + (leftOffset > 0 ? leftOffset : 0),\n      };\n      this.cursorOffsetCache = boundaries;\n      return this.cursorOffsetCache;\n    },\n\n    /**\n     * Renders cursor\n     * @param {Object} boundaries\n     * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n     */\n    renderCursor: function(boundaries, ctx) {\n      var cursorLocation = this.get2DCursorLocation(),\n          lineIndex = cursorLocation.lineIndex,\n          charIndex = cursorLocation.charIndex > 0 ? cursorLocation.charIndex - 1 : 0,\n          charHeight = this.getValueOfPropertyAt(lineIndex, charIndex, 'fontSize'),\n          multiplier = this.scaleX * this.canvas.getZoom(),\n          cursorWidth = this.cursorWidth / multiplier,\n          topOffset = boundaries.topOffset,\n          dy = this.getValueOfPropertyAt(lineIndex, charIndex, 'deltaY');\n\n      topOffset += (1 - this._fontSizeFraction) * this.getHeightOfLine(lineIndex) / this.lineHeight\n        - charHeight * (1 - this._fontSizeFraction);\n\n      if (this.inCompositionMode) {\n        this.renderSelection(boundaries, ctx);\n      }\n\n      ctx.fillStyle = this.cursorColor || this.getValueOfPropertyAt(lineIndex, charIndex, 'fill');\n      ctx.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity;\n      ctx.fillRect(\n        boundaries.left + boundaries.leftOffset - cursorWidth / 2,\n        topOffset + boundaries.top + dy,\n        cursorWidth,\n        charHeight);\n    },\n\n    /**\n     * Renders text selection\n     * @param {Object} boundaries Object with left/top/leftOffset/topOffset\n     * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n     */\n    renderSelection: function(boundaries, ctx) {\n\n      var selectionStart = this.inCompositionMode ? this.hiddenTextarea.selectionStart : this.selectionStart,\n          selectionEnd = this.inCompositionMode ? this.hiddenTextarea.selectionEnd : this.selectionEnd,\n          isJustify = this.textAlign.indexOf('justify') !== -1,\n          start = this.get2DCursorLocation(selectionStart),\n          end = this.get2DCursorLocation(selectionEnd),\n          startLine = start.lineIndex,\n          endLine = end.lineIndex,\n          startChar = start.charIndex < 0 ? 0 : start.charIndex,\n          endChar = end.charIndex < 0 ? 0 : end.charIndex;\n\n      for (var i = startLine; i <= endLine; i++) {\n        var lineOffset = this._getLineLeftOffset(i) || 0,\n            lineHeight = this.getHeightOfLine(i),\n            realLineHeight = 0, boxStart = 0, boxEnd = 0;\n\n        if (i === startLine) {\n          boxStart = this.__charBounds[startLine][startChar].left;\n        }\n        if (i >= startLine && i < endLine) {\n          boxEnd = isJustify && !this.isEndOfWrapping(i) ? this.width : this.getLineWidth(i) || 5; // WTF is this 5?\n        }\n        else if (i === endLine) {\n          if (endChar === 0) {\n            boxEnd = this.__charBounds[endLine][endChar].left;\n          }\n          else {\n            var charSpacing = this._getWidthOfCharSpacing();\n            boxEnd = this.__charBounds[endLine][endChar - 1].left\n              + this.__charBounds[endLine][endChar - 1].width - charSpacing;\n          }\n        }\n        realLineHeight = lineHeight;\n        if (this.lineHeight < 1 || (i === endLine && this.lineHeight > 1)) {\n          lineHeight /= this.lineHeight;\n        }\n        if (this.inCompositionMode) {\n          ctx.fillStyle = this.compositionColor || 'black';\n          ctx.fillRect(\n            boundaries.left + lineOffset + boxStart,\n            boundaries.top + boundaries.topOffset + lineHeight,\n            boxEnd - boxStart,\n            1);\n        }\n        else {\n          ctx.fillStyle = this.selectionColor;\n          ctx.fillRect(\n            boundaries.left + lineOffset + boxStart,\n            boundaries.top + boundaries.topOffset,\n            boxEnd - boxStart,\n            lineHeight);\n        }\n\n\n        boundaries.topOffset += realLineHeight;\n      }\n    },\n\n    /**\n     * High level function to know the height of the cursor.\n     * the currentChar is the one that precedes the cursor\n     * Returns fontSize of char at the current cursor\n     * Unused from the library, is for the end user\n     * @return {Number} Character font size\n     */\n    getCurrentCharFontSize: function() {\n      var cp = this._getCurrentCharIndex();\n      return this.getValueOfPropertyAt(cp.l, cp.c, 'fontSize');\n    },\n\n    /**\n     * High level function to know the color of the cursor.\n     * the currentChar is the one that precedes the cursor\n     * Returns color (fill) of char at the current cursor\n     * Unused from the library, is for the end user\n     * @return {String} Character color (fill)\n     */\n    getCurrentCharColor: function() {\n      var cp = this._getCurrentCharIndex();\n      return this.getValueOfPropertyAt(cp.l, cp.c, 'fill');\n    },\n\n    /**\n     * Returns the cursor position for the getCurrent.. functions\n     * @private\n     */\n    _getCurrentCharIndex: function() {\n      var cursorPosition = this.get2DCursorLocation(this.selectionStart, true),\n          charIndex = cursorPosition.charIndex > 0 ? cursorPosition.charIndex - 1 : 0;\n      return { l: cursorPosition.lineIndex, c: charIndex };\n    }\n  });\n\n  /**\n   * Returns fabric.IText instance from an object representation\n   * @static\n   * @memberOf fabric.IText\n   * @param {Object} object Object to create an instance from\n   * @param {function} [callback] invoked with new instance as argument\n   */\n  fabric.IText.fromObject = function(object, callback) {\n    parseDecoration(object);\n    if (object.styles) {\n      for (var i in object.styles) {\n        for (var j in object.styles[i]) {\n          parseDecoration(object.styles[i][j]);\n        }\n      }\n    }\n    fabric.Object._fromObject('IText', object, callback, 'text');\n  };\n})();\n\n\n(function() {\n\n  var clone = fabric.util.object.clone;\n\n  fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ {\n\n    /**\n     * Initializes all the interactive behavior of IText\n     */\n    initBehavior: function() {\n      this.initAddedHandler();\n      this.initRemovedHandler();\n      this.initCursorSelectionHandlers();\n      this.initDoubleClickSimulation();\n      this.mouseMoveHandler = this.mouseMoveHandler.bind(this);\n    },\n\n    onDeselect: function() {\n      this.isEditing && this.exitEditing();\n      this.selected = false;\n    },\n\n    /**\n     * Initializes \"added\" event handler\n     */\n    initAddedHandler: function() {\n      var _this = this;\n      this.on('added', function() {\n        var canvas = _this.canvas;\n        if (canvas) {\n          if (!canvas._hasITextHandlers) {\n            canvas._hasITextHandlers = true;\n            _this._initCanvasHandlers(canvas);\n          }\n          canvas._iTextInstances = canvas._iTextInstances || [];\n          canvas._iTextInstances.push(_this);\n        }\n      });\n    },\n\n    initRemovedHandler: function() {\n      var _this = this;\n      this.on('removed', function() {\n        var canvas = _this.canvas;\n        if (canvas) {\n          canvas._iTextInstances = canvas._iTextInstances || [];\n          fabric.util.removeFromArray(canvas._iTextInstances, _this);\n          if (canvas._iTextInstances.length === 0) {\n            canvas._hasITextHandlers = false;\n            _this._removeCanvasHandlers(canvas);\n          }\n        }\n      });\n    },\n\n    /**\n     * register canvas event to manage exiting on other instances\n     * @private\n     */\n    _initCanvasHandlers: function(canvas) {\n      canvas._mouseUpITextHandler = function() {\n        if (canvas._iTextInstances) {\n          canvas._iTextInstances.forEach(function(obj) {\n            obj.__isMousedown = false;\n          });\n        }\n      };\n      canvas.on('mouse:up', canvas._mouseUpITextHandler);\n    },\n\n    /**\n     * remove canvas event to manage exiting on other instances\n     * @private\n     */\n    _removeCanvasHandlers: function(canvas) {\n      canvas.off('mouse:up', canvas._mouseUpITextHandler);\n    },\n\n    /**\n     * @private\n     */\n    _tick: function() {\n      this._currentTickState = this._animateCursor(this, 1, this.cursorDuration, '_onTickComplete');\n    },\n\n    /**\n     * @private\n     */\n    _animateCursor: function(obj, targetOpacity, duration, completeMethod) {\n\n      var tickState;\n\n      tickState = {\n        isAborted: false,\n        abort: function() {\n          this.isAborted = true;\n        },\n      };\n\n      obj.animate('_currentCursorOpacity', targetOpacity, {\n        duration: duration,\n        onComplete: function() {\n          if (!tickState.isAborted) {\n            obj[completeMethod]();\n          }\n        },\n        onChange: function() {\n          // we do not want to animate a selection, only cursor\n          if (obj.canvas && obj.selectionStart === obj.selectionEnd) {\n            obj.renderCursorOrSelection();\n          }\n        },\n        abort: function() {\n          return tickState.isAborted;\n        }\n      });\n      return tickState;\n    },\n\n    /**\n     * @private\n     */\n    _onTickComplete: function() {\n\n      var _this = this;\n\n      if (this._cursorTimeout1) {\n        clearTimeout(this._cursorTimeout1);\n      }\n      this._cursorTimeout1 = setTimeout(function() {\n        _this._currentTickCompleteState = _this._animateCursor(_this, 0, this.cursorDuration / 2, '_tick');\n      }, 100);\n    },\n\n    /**\n     * Initializes delayed cursor\n     */\n    initDelayedCursor: function(restart) {\n      var _this = this,\n          delay = restart ? 0 : this.cursorDelay;\n\n      this.abortCursorAnimation();\n      this._currentCursorOpacity = 1;\n      this._cursorTimeout2 = setTimeout(function() {\n        _this._tick();\n      }, delay);\n    },\n\n    /**\n     * Aborts cursor animation and clears all timeouts\n     */\n    abortCursorAnimation: function() {\n      var shouldClear = this._currentTickState || this._currentTickCompleteState,\n          canvas = this.canvas;\n      this._currentTickState && this._currentTickState.abort();\n      this._currentTickCompleteState && this._currentTickCompleteState.abort();\n\n      clearTimeout(this._cursorTimeout1);\n      clearTimeout(this._cursorTimeout2);\n\n      this._currentCursorOpacity = 0;\n      // to clear just itext area we need to transform the context\n      // it may not be worth it\n      if (shouldClear && canvas) {\n        canvas.clearContext(canvas.contextTop || canvas.contextContainer);\n      }\n\n    },\n\n    /**\n     * Selects entire text\n     * @return {fabric.IText} thisArg\n     * @chainable\n     */\n    selectAll: function() {\n      this.selectionStart = 0;\n      this.selectionEnd = this._text.length;\n      this._fireSelectionChanged();\n      this._updateTextarea();\n      return this;\n    },\n\n    /**\n     * Returns selected text\n     * @return {String}\n     */\n    getSelectedText: function() {\n      return this._text.slice(this.selectionStart, this.selectionEnd).join('');\n    },\n\n    /**\n     * Find new selection index representing start of current word according to current selection index\n     * @param {Number} startFrom Current selection index\n     * @return {Number} New selection index\n     */\n    findWordBoundaryLeft: function(startFrom) {\n      var offset = 0, index = startFrom - 1;\n\n      // remove space before cursor first\n      if (this._reSpace.test(this._text[index])) {\n        while (this._reSpace.test(this._text[index])) {\n          offset++;\n          index--;\n        }\n      }\n      while (/\\S/.test(this._text[index]) && index > -1) {\n        offset++;\n        index--;\n      }\n\n      return startFrom - offset;\n    },\n\n    /**\n     * Find new selection index representing end of current word according to current selection index\n     * @param {Number} startFrom Current selection index\n     * @return {Number} New selection index\n     */\n    findWordBoundaryRight: function(startFrom) {\n      var offset = 0, index = startFrom;\n\n      // remove space after cursor first\n      if (this._reSpace.test(this._text[index])) {\n        while (this._reSpace.test(this._text[index])) {\n          offset++;\n          index++;\n        }\n      }\n      while (/\\S/.test(this._text[index]) && index < this._text.length) {\n        offset++;\n        index++;\n      }\n\n      return startFrom + offset;\n    },\n\n    /**\n     * Find new selection index representing start of current line according to current selection index\n     * @param {Number} startFrom Current selection index\n     * @return {Number} New selection index\n     */\n    findLineBoundaryLeft: function(startFrom) {\n      var offset = 0, index = startFrom - 1;\n\n      while (!/\\n/.test(this._text[index]) && index > -1) {\n        offset++;\n        index--;\n      }\n\n      return startFrom - offset;\n    },\n\n    /**\n     * Find new selection index representing end of current line according to current selection index\n     * @param {Number} startFrom Current selection index\n     * @return {Number} New selection index\n     */\n    findLineBoundaryRight: function(startFrom) {\n      var offset = 0, index = startFrom;\n\n      while (!/\\n/.test(this._text[index]) && index < this._text.length) {\n        offset++;\n        index++;\n      }\n\n      return startFrom + offset;\n    },\n\n    /**\n     * Finds index corresponding to beginning or end of a word\n     * @param {Number} selectionStart Index of a character\n     * @param {Number} direction 1 or -1\n     * @return {Number} Index of the beginning or end of a word\n     */\n    searchWordBoundary: function(selectionStart, direction) {\n      var text = this._text,\n          index     = this._reSpace.test(text[selectionStart]) ? selectionStart - 1 : selectionStart,\n          _char     = text[index],\n          // wrong\n          reNonWord = fabric.reNonWord;\n\n      while (!reNonWord.test(_char) && index > 0 && index < text.length) {\n        index += direction;\n        _char = text[index];\n      }\n      if (reNonWord.test(_char)) {\n        index += direction === 1 ? 0 : 1;\n      }\n      return index;\n    },\n\n    /**\n     * Selects a word based on the index\n     * @param {Number} selectionStart Index of a character\n     */\n    selectWord: function(selectionStart) {\n      selectionStart = selectionStart || this.selectionStart;\n      var newSelectionStart = this.searchWordBoundary(selectionStart, -1), /* search backwards */\n          newSelectionEnd = this.searchWordBoundary(selectionStart, 1); /* search forward */\n\n      this.selectionStart = newSelectionStart;\n      this.selectionEnd = newSelectionEnd;\n      this._fireSelectionChanged();\n      this._updateTextarea();\n      this.renderCursorOrSelection();\n    },\n\n    /**\n     * Selects a line based on the index\n     * @param {Number} selectionStart Index of a character\n     * @return {fabric.IText} thisArg\n     * @chainable\n     */\n    selectLine: function(selectionStart) {\n      selectionStart = selectionStart || this.selectionStart;\n      var newSelectionStart = this.findLineBoundaryLeft(selectionStart),\n          newSelectionEnd = this.findLineBoundaryRight(selectionStart);\n\n      this.selectionStart = newSelectionStart;\n      this.selectionEnd = newSelectionEnd;\n      this._fireSelectionChanged();\n      this._updateTextarea();\n      return this;\n    },\n\n    /**\n     * Enters editing state\n     * @return {fabric.IText} thisArg\n     * @chainable\n     */\n    enterEditing: function(e) {\n      if (this.isEditing || !this.editable) {\n        return;\n      }\n\n      if (this.canvas) {\n        this.canvas.calcOffset();\n        this.exitEditingOnOthers(this.canvas);\n      }\n\n      this.isEditing = true;\n\n      this.initHiddenTextarea(e);\n      this.hiddenTextarea.focus();\n      this.hiddenTextarea.value = this.text;\n      this._updateTextarea();\n      this._saveEditingProps();\n      this._setEditingProps();\n      this._textBeforeEdit = this.text;\n\n      this._tick();\n      this.fire('editing:entered');\n      this._fireSelectionChanged();\n      if (!this.canvas) {\n        return this;\n      }\n      this.canvas.fire('text:editing:entered', { target: this });\n      this.initMouseMoveHandler();\n      this.canvas.requestRenderAll();\n      return this;\n    },\n\n    exitEditingOnOthers: function(canvas) {\n      if (canvas._iTextInstances) {\n        canvas._iTextInstances.forEach(function(obj) {\n          obj.selected = false;\n          if (obj.isEditing) {\n            obj.exitEditing();\n          }\n        });\n      }\n    },\n\n    /**\n     * Initializes \"mousemove\" event handler\n     */\n    initMouseMoveHandler: function() {\n      this.canvas.on('mouse:move', this.mouseMoveHandler);\n    },\n\n    /**\n     * @private\n     */\n    mouseMoveHandler: function(options) {\n      if (!this.__isMousedown || !this.isEditing) {\n        return;\n      }\n\n      var newSelectionStart = this.getSelectionStartFromPointer(options.e),\n          currentStart = this.selectionStart,\n          currentEnd = this.selectionEnd;\n      if (\n        (newSelectionStart !== this.__selectionStartOnMouseDown || currentStart === currentEnd)\n        &&\n        (currentStart === newSelectionStart || currentEnd === newSelectionStart)\n      ) {\n        return;\n      }\n      if (newSelectionStart > this.__selectionStartOnMouseDown) {\n        this.selectionStart = this.__selectionStartOnMouseDown;\n        this.selectionEnd = newSelectionStart;\n      }\n      else {\n        this.selectionStart = newSelectionStart;\n        this.selectionEnd = this.__selectionStartOnMouseDown;\n      }\n      if (this.selectionStart !== currentStart || this.selectionEnd !== currentEnd) {\n        this.restartCursorIfNeeded();\n        this._fireSelectionChanged();\n        this._updateTextarea();\n        this.renderCursorOrSelection();\n      }\n    },\n\n    /**\n     * @private\n     */\n    _setEditingProps: function() {\n      this.hoverCursor = 'text';\n\n      if (this.canvas) {\n        this.canvas.defaultCursor = this.canvas.moveCursor = 'text';\n      }\n\n      this.borderColor = this.editingBorderColor;\n      this.hasControls = this.selectable = false;\n      this.lockMovementX = this.lockMovementY = true;\n    },\n\n    /**\n     * convert from textarea to grapheme indexes\n     */\n    fromStringToGraphemeSelection: function(start, end, text) {\n      var smallerTextStart = text.slice(0, start),\n          graphemeStart = fabric.util.string.graphemeSplit(smallerTextStart).length;\n      if (start === end) {\n        return { selectionStart: graphemeStart, selectionEnd: graphemeStart };\n      }\n      var smallerTextEnd = text.slice(start, end),\n          graphemeEnd = fabric.util.string.graphemeSplit(smallerTextEnd).length;\n      return { selectionStart: graphemeStart, selectionEnd: graphemeStart + graphemeEnd };\n    },\n\n    /**\n     * convert from fabric to textarea values\n     */\n    fromGraphemeToStringSelection: function(start, end, _text) {\n      var smallerTextStart = _text.slice(0, start),\n          graphemeStart = smallerTextStart.join('').length;\n      if (start === end) {\n        return { selectionStart: graphemeStart, selectionEnd: graphemeStart };\n      }\n      var smallerTextEnd = _text.slice(start, end),\n          graphemeEnd = smallerTextEnd.join('').length;\n      return { selectionStart: graphemeStart, selectionEnd: graphemeStart + graphemeEnd };\n    },\n\n    /**\n     * @private\n     */\n    _updateTextarea: function() {\n      this.cursorOffsetCache = { };\n      if (!this.hiddenTextarea) {\n        return;\n      }\n      if (!this.inCompositionMode) {\n        var newSelection = this.fromGraphemeToStringSelection(this.selectionStart, this.selectionEnd, this._text);\n        this.hiddenTextarea.selectionStart = newSelection.selectionStart;\n        this.hiddenTextarea.selectionEnd = newSelection.selectionEnd;\n      }\n      this.updateTextareaPosition();\n    },\n\n    /**\n     * @private\n     */\n    updateFromTextArea: function() {\n      if (!this.hiddenTextarea) {\n        return;\n      }\n      this.cursorOffsetCache = { };\n      this.text = this.hiddenTextarea.value;\n      if (this._shouldClearDimensionCache()) {\n        this.initDimensions();\n        this.setCoords();\n      }\n      var newSelection = this.fromStringToGraphemeSelection(\n        this.hiddenTextarea.selectionStart, this.hiddenTextarea.selectionEnd, this.hiddenTextarea.value);\n      this.selectionEnd = this.selectionStart = newSelection.selectionEnd;\n      if (!this.inCompositionMode) {\n        this.selectionStart = newSelection.selectionStart;\n      }\n      this.updateTextareaPosition();\n    },\n\n    /**\n     * @private\n     */\n    updateTextareaPosition: function() {\n      if (this.selectionStart === this.selectionEnd) {\n        var style = this._calcTextareaPosition();\n        this.hiddenTextarea.style.left = style.left;\n        this.hiddenTextarea.style.top = style.top;\n      }\n    },\n\n    /**\n     * @private\n     * @return {Object} style contains style for hiddenTextarea\n     */\n    _calcTextareaPosition: function() {\n      if (!this.canvas) {\n        return { x: 1, y: 1 };\n      }\n      var desiredPosition = this.inCompositionMode ? this.compositionStart : this.selectionStart,\n          boundaries = this._getCursorBoundaries(desiredPosition),\n          cursorLocation = this.get2DCursorLocation(desiredPosition),\n          lineIndex = cursorLocation.lineIndex,\n          charIndex = cursorLocation.charIndex,\n          charHeight = this.getValueOfPropertyAt(lineIndex, charIndex, 'fontSize') * this.lineHeight,\n          leftOffset = boundaries.leftOffset,\n          m = this.calcTransformMatrix(),\n          p = {\n            x: boundaries.left + leftOffset,\n            y: boundaries.top + boundaries.topOffset + charHeight\n          },\n          retinaScaling = this.canvas.getRetinaScaling(),\n          upperCanvas = this.canvas.upperCanvasEl,\n          upperCanvasWidth = upperCanvas.width / retinaScaling,\n          upperCanvasHeight = upperCanvas.height / retinaScaling,\n          maxWidth = upperCanvasWidth - charHeight,\n          maxHeight = upperCanvasHeight - charHeight,\n          scaleX = upperCanvas.clientWidth / upperCanvasWidth,\n          scaleY = upperCanvas.clientHeight / upperCanvasHeight;\n\n      p = fabric.util.transformPoint(p, m);\n      p = fabric.util.transformPoint(p, this.canvas.viewportTransform);\n      p.x *= scaleX;\n      p.y *= scaleY;\n      if (p.x < 0) {\n        p.x = 0;\n      }\n      if (p.x > maxWidth) {\n        p.x = maxWidth;\n      }\n      if (p.y < 0) {\n        p.y = 0;\n      }\n      if (p.y > maxHeight) {\n        p.y = maxHeight;\n      }\n\n      // add canvas offset on document\n      p.x += this.canvas._offset.left;\n      p.y += this.canvas._offset.top;\n\n      return { left: p.x + 'px', top: p.y + 'px', fontSize: charHeight + 'px', charHeight: charHeight };\n    },\n\n    /**\n     * @private\n     */\n    _saveEditingProps: function() {\n      this._savedProps = {\n        hasControls: this.hasControls,\n        borderColor: this.borderColor,\n        lockMovementX: this.lockMovementX,\n        lockMovementY: this.lockMovementY,\n        hoverCursor: this.hoverCursor,\n        selectable: this.selectable,\n        defaultCursor: this.canvas && this.canvas.defaultCursor,\n        moveCursor: this.canvas && this.canvas.moveCursor\n      };\n    },\n\n    /**\n     * @private\n     */\n    _restoreEditingProps: function() {\n      if (!this._savedProps) {\n        return;\n      }\n\n      this.hoverCursor = this._savedProps.hoverCursor;\n      this.hasControls = this._savedProps.hasControls;\n      this.borderColor = this._savedProps.borderColor;\n      this.selectable = this._savedProps.selectable;\n      this.lockMovementX = this._savedProps.lockMovementX;\n      this.lockMovementY = this._savedProps.lockMovementY;\n\n      if (this.canvas) {\n        this.canvas.defaultCursor = this._savedProps.defaultCursor;\n        this.canvas.moveCursor = this._savedProps.moveCursor;\n      }\n    },\n\n    /**\n     * Exits from editing state\n     * @return {fabric.IText} thisArg\n     * @chainable\n     */\n    exitEditing: function() {\n      var isTextChanged = (this._textBeforeEdit !== this.text);\n      var hiddenTextarea = this.hiddenTextarea;\n      this.selected = false;\n      this.isEditing = false;\n\n      this.selectionEnd = this.selectionStart;\n\n      if (hiddenTextarea) {\n        hiddenTextarea.blur && hiddenTextarea.blur();\n        hiddenTextarea.parentNode && hiddenTextarea.parentNode.removeChild(hiddenTextarea);\n      }\n      this.hiddenTextarea = null;\n      this.abortCursorAnimation();\n      this._restoreEditingProps();\n      this._currentCursorOpacity = 0;\n      if (this._shouldClearDimensionCache()) {\n        this.initDimensions();\n        this.setCoords();\n      }\n      this.fire('editing:exited');\n      isTextChanged && this.fire('modified');\n      if (this.canvas) {\n        this.canvas.off('mouse:move', this.mouseMoveHandler);\n        this.canvas.fire('text:editing:exited', { target: this });\n        isTextChanged && this.canvas.fire('object:modified', { target: this });\n      }\n      return this;\n    },\n\n    /**\n     * @private\n     */\n    _removeExtraneousStyles: function() {\n      for (var prop in this.styles) {\n        if (!this._textLines[prop]) {\n          delete this.styles[prop];\n        }\n      }\n    },\n\n    /**\n     * remove and reflow a style block from start to end.\n     * @param {Number} start linear start position for removal (included in removal)\n     * @param {Number} end linear end position for removal ( excluded from removal )\n     */\n    removeStyleFromTo: function(start, end) {\n      var cursorStart = this.get2DCursorLocation(start, true),\n          cursorEnd = this.get2DCursorLocation(end, true),\n          lineStart = cursorStart.lineIndex,\n          charStart = cursorStart.charIndex,\n          lineEnd = cursorEnd.lineIndex,\n          charEnd = cursorEnd.charIndex,\n          i, styleObj;\n      if (lineStart !== lineEnd) {\n        // step1 remove the trailing of lineStart\n        if (this.styles[lineStart]) {\n          for (i = charStart; i < this._unwrappedTextLines[lineStart].length; i++) {\n            delete this.styles[lineStart][i];\n          }\n        }\n        // step2 move the trailing of lineEnd to lineStart if needed\n        if (this.styles[lineEnd]) {\n          for (i = charEnd; i < this._unwrappedTextLines[lineEnd].length; i++) {\n            styleObj = this.styles[lineEnd][i];\n            if (styleObj) {\n              this.styles[lineStart] || (this.styles[lineStart] = { });\n              this.styles[lineStart][charStart + i - charEnd] = styleObj;\n            }\n          }\n        }\n        // step3 detects lines will be completely removed.\n        for (i = lineStart + 1; i <= lineEnd; i++) {\n          delete this.styles[i];\n        }\n        // step4 shift remaining lines.\n        this.shiftLineStyles(lineEnd, lineStart - lineEnd);\n      }\n      else {\n        // remove and shift left on the same line\n        if (this.styles[lineStart]) {\n          styleObj = this.styles[lineStart];\n          var diff = charEnd - charStart, numericChar, _char;\n          for (i = charStart; i < charEnd; i++) {\n            delete styleObj[i];\n          }\n          for (_char in this.styles[lineStart]) {\n            numericChar = parseInt(_char, 10);\n            if (numericChar >= charEnd) {\n              styleObj[numericChar - diff] = styleObj[_char];\n              delete styleObj[_char];\n            }\n          }\n        }\n      }\n    },\n\n    /**\n     * Shifts line styles up or down\n     * @param {Number} lineIndex Index of a line\n     * @param {Number} offset Can any number?\n     */\n    shiftLineStyles: function(lineIndex, offset) {\n      // shift all line styles by offset upward or downward\n      // do not clone deep. we need new array, not new style objects\n      var clonedStyles = clone(this.styles);\n      for (var line in this.styles) {\n        var numericLine = parseInt(line, 10);\n        if (numericLine > lineIndex) {\n          this.styles[numericLine + offset] = clonedStyles[numericLine];\n          if (!clonedStyles[numericLine - offset]) {\n            delete this.styles[numericLine];\n          }\n        }\n      }\n    },\n\n    restartCursorIfNeeded: function() {\n      if (!this._currentTickState || this._currentTickState.isAborted\n        || !this._currentTickCompleteState || this._currentTickCompleteState.isAborted\n      ) {\n        this.initDelayedCursor();\n      }\n    },\n\n    /**\n     * Handle insertion of more consecutive style lines for when one or more\n     * newlines gets added to the text. Since current style needs to be shifted\n     * first we shift the current style of the number lines needed, then we add\n     * new lines from the last to the first.\n     * @param {Number} lineIndex Index of a line\n     * @param {Number} charIndex Index of a char\n     * @param {Number} qty number of lines to add\n     * @param {Array} copiedStyle Array of objects styles\n     */\n    insertNewlineStyleObject: function(lineIndex, charIndex, qty, copiedStyle) {\n      var currentCharStyle,\n          newLineStyles = {},\n          somethingAdded = false,\n          isEndOfLine = this._unwrappedTextLines[lineIndex].length === charIndex;\n\n      qty || (qty = 1);\n      this.shiftLineStyles(lineIndex, qty);\n      if (this.styles[lineIndex]) {\n        currentCharStyle = this.styles[lineIndex][charIndex === 0 ? charIndex : charIndex - 1];\n      }\n      // we clone styles of all chars\n      // after cursor onto the current line\n      for (var index in this.styles[lineIndex]) {\n        var numIndex = parseInt(index, 10);\n        if (numIndex >= charIndex) {\n          somethingAdded = true;\n          newLineStyles[numIndex - charIndex] = this.styles[lineIndex][index];\n          // remove lines from the previous line since they're on a new line now\n          if (!(isEndOfLine && charIndex === 0)) {\n            delete this.styles[lineIndex][index];\n          }\n        }\n      }\n      var styleCarriedOver = false;\n      if (somethingAdded && !isEndOfLine) {\n        // if is end of line, the extra style we copied\n        // is probably not something we want\n        this.styles[lineIndex + qty] = newLineStyles;\n        styleCarriedOver = true;\n      }\n      if (styleCarriedOver) {\n        // skip the last line of since we already prepared it.\n        qty--;\n      }\n      // for the all the lines or all the other lines\n      // we clone current char style onto the next (otherwise empty) line\n      while (qty > 0) {\n        if (copiedStyle && copiedStyle[qty - 1]) {\n          this.styles[lineIndex + qty] = { 0: clone(copiedStyle[qty - 1]) };\n        }\n        else if (currentCharStyle) {\n          this.styles[lineIndex + qty] = { 0: clone(currentCharStyle) };\n        }\n        else {\n          delete this.styles[lineIndex + qty];\n        }\n        qty--;\n      }\n      this._forceClearCache = true;\n    },\n\n    /**\n     * Inserts style object for a given line/char index\n     * @param {Number} lineIndex Index of a line\n     * @param {Number} charIndex Index of a char\n     * @param {Number} quantity number Style object to insert, if given\n     * @param {Array} copiedStyle array of style objects\n     */\n    insertCharStyleObject: function(lineIndex, charIndex, quantity, copiedStyle) {\n      if (!this.styles) {\n        this.styles = {};\n      }\n      var currentLineStyles       = this.styles[lineIndex],\n          currentLineStylesCloned = currentLineStyles ? clone(currentLineStyles) : {};\n\n      quantity || (quantity = 1);\n      // shift all char styles by quantity forward\n      // 0,1,2,3 -> (charIndex=2) -> 0,1,3,4 -> (insert 2) -> 0,1,2,3,4\n      for (var index in currentLineStylesCloned) {\n        var numericIndex = parseInt(index, 10);\n        if (numericIndex >= charIndex) {\n          currentLineStyles[numericIndex + quantity] = currentLineStylesCloned[numericIndex];\n          // only delete the style if there was nothing moved there\n          if (!currentLineStylesCloned[numericIndex - quantity]) {\n            delete currentLineStyles[numericIndex];\n          }\n        }\n      }\n      this._forceClearCache = true;\n      if (copiedStyle) {\n        while (quantity--) {\n          if (!Object.keys(copiedStyle[quantity]).length) {\n            continue;\n          }\n          if (!this.styles[lineIndex]) {\n            this.styles[lineIndex] = {};\n          }\n          this.styles[lineIndex][charIndex + quantity] = clone(copiedStyle[quantity]);\n        }\n        return;\n      }\n      if (!currentLineStyles) {\n        return;\n      }\n      var newStyle = currentLineStyles[charIndex ? charIndex - 1 : 1];\n      while (newStyle && quantity--) {\n        this.styles[lineIndex][charIndex + quantity] = clone(newStyle);\n      }\n    },\n\n    /**\n     * Inserts style object(s)\n     * @param {Array} insertedText Characters at the location where style is inserted\n     * @param {Number} start cursor index for inserting style\n     * @param {Array} [copiedStyle] array of style objects to insert.\n     */\n    insertNewStyleBlock: function(insertedText, start, copiedStyle) {\n      var cursorLoc = this.get2DCursorLocation(start, true),\n          addedLines = [0], linesLength = 0;\n      // get an array of how many char per lines are being added.\n      for (var i = 0; i < insertedText.length; i++) {\n        if (insertedText[i] === '\\n') {\n          linesLength++;\n          addedLines[linesLength] = 0;\n        }\n        else {\n          addedLines[linesLength]++;\n        }\n      }\n      // for the first line copy the style from the current char position.\n      if (addedLines[0] > 0) {\n        this.insertCharStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addedLines[0], copiedStyle);\n        copiedStyle = copiedStyle && copiedStyle.slice(addedLines[0] + 1);\n      }\n      linesLength && this.insertNewlineStyleObject(\n        cursorLoc.lineIndex, cursorLoc.charIndex + addedLines[0], linesLength);\n      for (var i = 1; i < linesLength; i++) {\n        if (addedLines[i] > 0) {\n          this.insertCharStyleObject(cursorLoc.lineIndex + i, 0, addedLines[i], copiedStyle);\n        }\n        else if (copiedStyle) {\n          this.styles[cursorLoc.lineIndex + i][0] = copiedStyle[0];\n        }\n        copiedStyle = copiedStyle && copiedStyle.slice(addedLines[i] + 1);\n      }\n      // we use i outside the loop to get it like linesLength\n      if (addedLines[i] > 0) {\n        this.insertCharStyleObject(cursorLoc.lineIndex + i, 0, addedLines[i], copiedStyle);\n      }\n    },\n\n    /**\n     * Set the selectionStart and selectionEnd according to the new position of cursor\n     * mimic the key - mouse navigation when shift is pressed.\n     */\n    setSelectionStartEndWithShift: function(start, end, newSelection) {\n      if (newSelection <= start) {\n        if (end === start) {\n          this._selectionDirection = 'left';\n        }\n        else if (this._selectionDirection === 'right') {\n          this._selectionDirection = 'left';\n          this.selectionEnd = start;\n        }\n        this.selectionStart = newSelection;\n      }\n      else if (newSelection > start && newSelection < end) {\n        if (this._selectionDirection === 'right') {\n          this.selectionEnd = newSelection;\n        }\n        else {\n          this.selectionStart = newSelection;\n        }\n      }\n      else {\n        // newSelection is > selection start and end\n        if (end === start) {\n          this._selectionDirection = 'right';\n        }\n        else if (this._selectionDirection === 'left') {\n          this._selectionDirection = 'right';\n          this.selectionStart = end;\n        }\n        this.selectionEnd = newSelection;\n      }\n    },\n\n    setSelectionInBoundaries: function() {\n      var length = this.text.length;\n      if (this.selectionStart > length) {\n        this.selectionStart = length;\n      }\n      else if (this.selectionStart < 0) {\n        this.selectionStart = 0;\n      }\n      if (this.selectionEnd > length) {\n        this.selectionEnd = length;\n      }\n      else if (this.selectionEnd < 0) {\n        this.selectionEnd = 0;\n      }\n    }\n  });\n})();\n\n\nfabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ {\n  /**\n   * Initializes \"dbclick\" event handler\n   */\n  initDoubleClickSimulation: function() {\n\n    // for double click\n    this.__lastClickTime = +new Date();\n\n    // for triple click\n    this.__lastLastClickTime = +new Date();\n\n    this.__lastPointer = { };\n\n    this.on('mousedown', this.onMouseDown);\n  },\n\n  /**\n   * Default event handler to simulate triple click\n   * @private\n   */\n  onMouseDown: function(options) {\n    if (!this.canvas) {\n      return;\n    }\n    this.__newClickTime = +new Date();\n    var newPointer = options.pointer;\n    if (this.isTripleClick(newPointer)) {\n      this.fire('tripleclick', options);\n      this._stopEvent(options.e);\n    }\n    this.__lastLastClickTime = this.__lastClickTime;\n    this.__lastClickTime = this.__newClickTime;\n    this.__lastPointer = newPointer;\n    this.__lastIsEditing = this.isEditing;\n    this.__lastSelected = this.selected;\n  },\n\n  isTripleClick: function(newPointer) {\n    return this.__newClickTime - this.__lastClickTime < 500 &&\n        this.__lastClickTime - this.__lastLastClickTime < 500 &&\n        this.__lastPointer.x === newPointer.x &&\n        this.__lastPointer.y === newPointer.y;\n  },\n\n  /**\n   * @private\n   */\n  _stopEvent: function(e) {\n    e.preventDefault && e.preventDefault();\n    e.stopPropagation && e.stopPropagation();\n  },\n\n  /**\n   * Initializes event handlers related to cursor or selection\n   */\n  initCursorSelectionHandlers: function() {\n    this.initMousedownHandler();\n    this.initMouseupHandler();\n    this.initClicks();\n  },\n\n  /**\n   * Default handler for double click, select a word\n   */\n  doubleClickHandler: function(options) {\n    if (!this.isEditing) {\n      return;\n    }\n    this.selectWord(this.getSelectionStartFromPointer(options.e));\n  },\n\n  /**\n   * Default handler for triple click, select a line\n   */\n  tripleClickHandler: function(options) {\n    if (!this.isEditing) {\n      return;\n    }\n    this.selectLine(this.getSelectionStartFromPointer(options.e));\n  },\n\n  /**\n   * Initializes double and triple click event handlers\n   */\n  initClicks: function() {\n    this.on('mousedblclick', this.doubleClickHandler);\n    this.on('tripleclick', this.tripleClickHandler);\n  },\n\n  /**\n   * Default event handler for the basic functionalities needed on _mouseDown\n   * can be overridden to do something different.\n   * Scope of this implementation is: find the click position, set selectionStart\n   * find selectionEnd, initialize the drawing of either cursor or selection area\n   * initializing a mousedDown on a text area will cancel fabricjs knowledge of\n   * current compositionMode. It will be set to false.\n   */\n  _mouseDownHandler: function(options) {\n    if (!this.canvas || !this.editable || (options.e.button && options.e.button !== 1)) {\n      return;\n    }\n\n    this.__isMousedown = true;\n\n    if (this.selected) {\n      this.inCompositionMode = false;\n      this.setCursorByClick(options.e);\n    }\n\n    if (this.isEditing) {\n      this.__selectionStartOnMouseDown = this.selectionStart;\n      if (this.selectionStart === this.selectionEnd) {\n        this.abortCursorAnimation();\n      }\n      this.renderCursorOrSelection();\n    }\n  },\n\n  /**\n   * Default event handler for the basic functionalities needed on mousedown:before\n   * can be overridden to do something different.\n   * Scope of this implementation is: verify the object is already selected when mousing down\n   */\n  _mouseDownHandlerBefore: function(options) {\n    if (!this.canvas || !this.editable || (options.e.button && options.e.button !== 1)) {\n      return;\n    }\n    // we want to avoid that an object that was selected and then becomes unselectable,\n    // may trigger editing mode in some way.\n    this.selected = this === this.canvas._activeObject;\n  },\n\n  /**\n   * Initializes \"mousedown\" event handler\n   */\n  initMousedownHandler: function() {\n    this.on('mousedown', this._mouseDownHandler);\n    this.on('mousedown:before', this._mouseDownHandlerBefore);\n  },\n\n  /**\n   * Initializes \"mouseup\" event handler\n   */\n  initMouseupHandler: function() {\n    this.on('mouseup', this.mouseUpHandler);\n  },\n\n  /**\n   * standard hander for mouse up, overridable\n   * @private\n   */\n  mouseUpHandler: function(options) {\n    this.__isMousedown = false;\n    if (!this.editable || this.group ||\n      (options.transform && options.transform.actionPerformed) ||\n      (options.e.button && options.e.button !== 1)) {\n      return;\n    }\n\n    if (this.canvas) {\n      var currentActive = this.canvas._activeObject;\n      if (currentActive && currentActive !== this) {\n        // avoid running this logic when there is an active object\n        // this because is possible with shift click and fast clicks,\n        // to rapidly deselect and reselect this object and trigger an enterEdit\n        return;\n      }\n    }\n\n    if (this.__lastSelected && !this.__corner) {\n      this.selected = false;\n      this.__lastSelected = false;\n      this.enterEditing(options.e);\n      if (this.selectionStart === this.selectionEnd) {\n        this.initDelayedCursor(true);\n      }\n      else {\n        this.renderCursorOrSelection();\n      }\n    }\n    else {\n      this.selected = true;\n    }\n  },\n\n  /**\n   * Changes cursor location in a text depending on passed pointer (x/y) object\n   * @param {Event} e Event object\n   */\n  setCursorByClick: function(e) {\n    var newSelection = this.getSelectionStartFromPointer(e),\n        start = this.selectionStart, end = this.selectionEnd;\n    if (e.shiftKey) {\n      this.setSelectionStartEndWithShift(start, end, newSelection);\n    }\n    else {\n      this.selectionStart = newSelection;\n      this.selectionEnd = newSelection;\n    }\n    if (this.isEditing) {\n      this._fireSelectionChanged();\n      this._updateTextarea();\n    }\n  },\n\n  /**\n   * Returns index of a character corresponding to where an object was clicked\n   * @param {Event} e Event object\n   * @return {Number} Index of a character\n   */\n  getSelectionStartFromPointer: function(e) {\n    var mouseOffset = this.getLocalPointer(e),\n        prevWidth = 0,\n        width = 0,\n        height = 0,\n        charIndex = 0,\n        lineIndex = 0,\n        lineLeftOffset,\n        line;\n\n    for (var i = 0, len = this._textLines.length; i < len; i++) {\n      if (height <= mouseOffset.y) {\n        height += this.getHeightOfLine(i) * this.scaleY;\n        lineIndex = i;\n        if (i > 0) {\n          charIndex += this._textLines[i - 1].length + this.missingNewlineOffset(i - 1);\n        }\n      }\n      else {\n        break;\n      }\n    }\n    lineLeftOffset = this._getLineLeftOffset(lineIndex);\n    width = lineLeftOffset * this.scaleX;\n    line = this._textLines[lineIndex];\n    for (var j = 0, jlen = line.length; j < jlen; j++) {\n      prevWidth = width;\n      // i removed something about flipX here, check.\n      width += this.__charBounds[lineIndex][j].kernedWidth * this.scaleX;\n      if (width <= mouseOffset.x) {\n        charIndex++;\n      }\n      else {\n        break;\n      }\n    }\n    return this._getNewSelectionStartFromOffset(mouseOffset, prevWidth, width, charIndex, jlen);\n  },\n\n  /**\n   * @private\n   */\n  _getNewSelectionStartFromOffset: function(mouseOffset, prevWidth, width, index, jlen) {\n    // we need Math.abs because when width is after the last char, the offset is given as 1, while is 0\n    var distanceBtwLastCharAndCursor = mouseOffset.x - prevWidth,\n        distanceBtwNextCharAndCursor = width - mouseOffset.x,\n        offset = distanceBtwNextCharAndCursor > distanceBtwLastCharAndCursor ||\n          distanceBtwNextCharAndCursor < 0 ? 0 : 1,\n        newSelectionStart = index + offset;\n    // if object is horizontally flipped, mirror cursor location from the end\n    if (this.flipX) {\n      newSelectionStart = jlen - newSelectionStart;\n    }\n\n    if (newSelectionStart > this._text.length) {\n      newSelectionStart = this._text.length;\n    }\n\n    return newSelectionStart;\n  }\n});\n\n\nfabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ {\n\n  /**\n   * Initializes hidden textarea (needed to bring up keyboard in iOS)\n   */\n  initHiddenTextarea: function() {\n    this.hiddenTextarea = fabric.document.createElement('textarea');\n    this.hiddenTextarea.setAttribute('autocapitalize', 'off');\n    this.hiddenTextarea.setAttribute('autocorrect', 'off');\n    this.hiddenTextarea.setAttribute('autocomplete', 'off');\n    this.hiddenTextarea.setAttribute('spellcheck', 'false');\n    this.hiddenTextarea.setAttribute('data-fabric-hiddentextarea', '');\n    this.hiddenTextarea.setAttribute('wrap', 'off');\n    var style = this._calcTextareaPosition();\n    // line-height: 1px; was removed from the style to fix this:\n    // https://bugs.chromium.org/p/chromium/issues/detail?id=870966\n    this.hiddenTextarea.style.cssText = 'position: absolute; top: ' + style.top +\n    '; left: ' + style.left + '; z-index: -999; opacity: 0; width: 1px; height: 1px; font-size: 1px;' +\n    ' paddingーtop: ' + style.fontSize + ';';\n    fabric.document.body.appendChild(this.hiddenTextarea);\n\n    fabric.util.addListener(this.hiddenTextarea, 'keydown', this.onKeyDown.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'keyup', this.onKeyUp.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'input', this.onInput.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'copy', this.copy.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'cut', this.copy.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'paste', this.paste.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'compositionstart', this.onCompositionStart.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'compositionupdate', this.onCompositionUpdate.bind(this));\n    fabric.util.addListener(this.hiddenTextarea, 'compositionend', this.onCompositionEnd.bind(this));\n\n    if (!this._clickHandlerInitialized && this.canvas) {\n      fabric.util.addListener(this.canvas.upperCanvasEl, 'click', this.onClick.bind(this));\n      this._clickHandlerInitialized = true;\n    }\n  },\n\n  /**\n   * For functionalities on keyDown\n   * Map a special key to a function of the instance/prototype\n   * If you need different behaviour for ESC or TAB or arrows, you have to change\n   * this map setting the name of a function that you build on the fabric.Itext or\n   * your prototype.\n   * the map change will affect all Instances unless you need for only some text Instances\n   * in that case you have to clone this object and assign your Instance.\n   * this.keysMap = fabric.util.object.clone(this.keysMap);\n   * The function must be in fabric.Itext.prototype.myFunction And will receive event as args[0]\n   */\n  keysMap: {\n    9:  'exitEditing',\n    27: 'exitEditing',\n    33: 'moveCursorUp',\n    34: 'moveCursorDown',\n    35: 'moveCursorRight',\n    36: 'moveCursorLeft',\n    37: 'moveCursorLeft',\n    38: 'moveCursorUp',\n    39: 'moveCursorRight',\n    40: 'moveCursorDown',\n  },\n\n  /**\n   * For functionalities on keyUp + ctrl || cmd\n   */\n  ctrlKeysMapUp: {\n    67: 'copy',\n    88: 'cut'\n  },\n\n  /**\n   * For functionalities on keyDown + ctrl || cmd\n   */\n  ctrlKeysMapDown: {\n    65: 'selectAll'\n  },\n\n  onClick: function() {\n    // No need to trigger click event here, focus is enough to have the keyboard appear on Android\n    this.hiddenTextarea && this.hiddenTextarea.focus();\n  },\n\n  /**\n   * Handles keydown event\n   * only used for arrows and combination of modifier keys.\n   * @param {Event} e Event object\n   */\n  onKeyDown: function(e) {\n    if (!this.isEditing) {\n      return;\n    }\n    if (e.keyCode in this.keysMap) {\n      this[this.keysMap[e.keyCode]](e);\n    }\n    else if ((e.keyCode in this.ctrlKeysMapDown) && (e.ctrlKey || e.metaKey)) {\n      this[this.ctrlKeysMapDown[e.keyCode]](e);\n    }\n    else {\n      return;\n    }\n    e.stopImmediatePropagation();\n    e.preventDefault();\n    if (e.keyCode >= 33 && e.keyCode <= 40) {\n      // if i press an arrow key just update selection\n      this.inCompositionMode = false;\n      this.clearContextTop();\n      this.renderCursorOrSelection();\n    }\n    else {\n      this.canvas && this.canvas.requestRenderAll();\n    }\n  },\n\n  /**\n   * Handles keyup event\n   * We handle KeyUp because ie11 and edge have difficulties copy/pasting\n   * if a copy/cut event fired, keyup is dismissed\n   * @param {Event} e Event object\n   */\n  onKeyUp: function(e) {\n    if (!this.isEditing || this._copyDone || this.inCompositionMode) {\n      this._copyDone = false;\n      return;\n    }\n    if ((e.keyCode in this.ctrlKeysMapUp) && (e.ctrlKey || e.metaKey)) {\n      this[this.ctrlKeysMapUp[e.keyCode]](e);\n    }\n    else {\n      return;\n    }\n    e.stopImmediatePropagation();\n    e.preventDefault();\n    this.canvas && this.canvas.requestRenderAll();\n  },\n\n  /**\n   * Handles onInput event\n   * @param {Event} e Event object\n   */\n  onInput: function(e) {\n    var fromPaste = this.fromPaste;\n    this.fromPaste = false;\n    e && e.stopPropagation();\n    if (!this.isEditing) {\n      return;\n    }\n    // decisions about style changes.\n    var nextText = this._splitTextIntoLines(this.hiddenTextarea.value).graphemeText,\n        charCount = this._text.length,\n        nextCharCount = nextText.length,\n        removedText, insertedText,\n        charDiff = nextCharCount - charCount,\n        selectionStart = this.selectionStart, selectionEnd = this.selectionEnd,\n        selection = selectionStart !== selectionEnd,\n        copiedStyle, removeFrom, removeTo;\n    if (this.hiddenTextarea.value === '') {\n      this.styles = { };\n      this.updateFromTextArea();\n      this.fire('changed');\n      if (this.canvas) {\n        this.canvas.fire('text:changed', { target: this });\n        this.canvas.requestRenderAll();\n      }\n      return;\n    }\n\n    var textareaSelection = this.fromStringToGraphemeSelection(\n      this.hiddenTextarea.selectionStart,\n      this.hiddenTextarea.selectionEnd,\n      this.hiddenTextarea.value\n    );\n    var backDelete = selectionStart > textareaSelection.selectionStart;\n\n    if (selection) {\n      removedText = this._text.slice(selectionStart, selectionEnd);\n      charDiff += selectionEnd - selectionStart;\n    }\n    else if (nextCharCount < charCount) {\n      if (backDelete) {\n        removedText = this._text.slice(selectionEnd + charDiff, selectionEnd);\n      }\n      else {\n        removedText = this._text.slice(selectionStart, selectionStart - charDiff);\n      }\n    }\n    insertedText = nextText.slice(textareaSelection.selectionEnd - charDiff, textareaSelection.selectionEnd);\n    if (removedText && removedText.length) {\n      if (insertedText.length) {\n        // let's copy some style before deleting.\n        // we want to copy the style before the cursor OR the style at the cursor if selection\n        // is bigger than 0.\n        copiedStyle = this.getSelectionStyles(selectionStart, selectionStart + 1, false);\n        // now duplicate the style one for each inserted text.\n        copiedStyle = insertedText.map(function() {\n          // this return an array of references, but that is fine since we are\n          // copying the style later.\n          return copiedStyle[0];\n        });\n      }\n      if (selection) {\n        removeFrom = selectionStart;\n        removeTo = selectionEnd;\n      }\n      else if (backDelete) {\n        // detect differencies between forwardDelete and backDelete\n        removeFrom = selectionEnd - removedText.length;\n        removeTo = selectionEnd;\n      }\n      else {\n        removeFrom = selectionEnd;\n        removeTo = selectionEnd + removedText.length;\n      }\n      this.removeStyleFromTo(removeFrom, removeTo);\n    }\n    if (insertedText.length) {\n      if (fromPaste && insertedText.join('') === fabric.copiedText && !fabric.disableStyleCopyPaste) {\n        copiedStyle = fabric.copiedTextStyle;\n      }\n      this.insertNewStyleBlock(insertedText, selectionStart, copiedStyle);\n    }\n    this.updateFromTextArea();\n    this.fire('changed');\n    if (this.canvas) {\n      this.canvas.fire('text:changed', { target: this });\n      this.canvas.requestRenderAll();\n    }\n  },\n  /**\n   * Composition start\n   */\n  onCompositionStart: function() {\n    this.inCompositionMode = true;\n  },\n\n  /**\n   * Composition end\n   */\n  onCompositionEnd: function() {\n    this.inCompositionMode = false;\n  },\n\n  // /**\n  //  * Composition update\n  //  */\n  onCompositionUpdate: function(e) {\n    this.compositionStart = e.target.selectionStart;\n    this.compositionEnd = e.target.selectionEnd;\n    this.updateTextareaPosition();\n  },\n\n  /**\n   * Copies selected text\n   * @param {Event} e Event object\n   */\n  copy: function() {\n    if (this.selectionStart === this.selectionEnd) {\n      //do not cut-copy if no selection\n      return;\n    }\n\n    fabric.copiedText = this.getSelectedText();\n    if (!fabric.disableStyleCopyPaste) {\n      fabric.copiedTextStyle = this.getSelectionStyles(this.selectionStart, this.selectionEnd, true);\n    }\n    else {\n      fabric.copiedTextStyle = null;\n    }\n    this._copyDone = true;\n  },\n\n  /**\n   * Pastes text\n   * @param {Event} e Event object\n   */\n  paste: function() {\n    this.fromPaste = true;\n  },\n\n  /**\n   * @private\n   * @param {Event} e Event object\n   * @return {Object} Clipboard data object\n   */\n  _getClipboardData: function(e) {\n    return (e && e.clipboardData) || fabric.window.clipboardData;\n  },\n\n  /**\n   * Finds the width in pixels before the cursor on the same line\n   * @private\n   * @param {Number} lineIndex\n   * @param {Number} charIndex\n   * @return {Number} widthBeforeCursor width before cursor\n   */\n  _getWidthBeforeCursor: function(lineIndex, charIndex) {\n    var widthBeforeCursor = this._getLineLeftOffset(lineIndex), bound;\n\n    if (charIndex > 0) {\n      bound = this.__charBounds[lineIndex][charIndex - 1];\n      widthBeforeCursor += bound.left + bound.width;\n    }\n    return widthBeforeCursor;\n  },\n\n  /**\n   * Gets start offset of a selection\n   * @param {Event} e Event object\n   * @param {Boolean} isRight\n   * @return {Number}\n   */\n  getDownCursorOffset: function(e, isRight) {\n    var selectionProp = this._getSelectionForOffset(e, isRight),\n        cursorLocation = this.get2DCursorLocation(selectionProp),\n        lineIndex = cursorLocation.lineIndex;\n    // if on last line, down cursor goes to end of line\n    if (lineIndex === this._textLines.length - 1 || e.metaKey || e.keyCode === 34) {\n      // move to the end of a text\n      return this._text.length - selectionProp;\n    }\n    var charIndex = cursorLocation.charIndex,\n        widthBeforeCursor = this._getWidthBeforeCursor(lineIndex, charIndex),\n        indexOnOtherLine = this._getIndexOnLine(lineIndex + 1, widthBeforeCursor),\n        textAfterCursor = this._textLines[lineIndex].slice(charIndex);\n    return textAfterCursor.length + indexOnOtherLine + 1 + this.missingNewlineOffset(lineIndex);\n  },\n\n  /**\n   * private\n   * Helps finding if the offset should be counted from Start or End\n   * @param {Event} e Event object\n   * @param {Boolean} isRight\n   * @return {Number}\n   */\n  _getSelectionForOffset: function(e, isRight) {\n    if (e.shiftKey && this.selectionStart !== this.selectionEnd && isRight) {\n      return this.selectionEnd;\n    }\n    else {\n      return this.selectionStart;\n    }\n  },\n\n  /**\n   * @param {Event} e Event object\n   * @param {Boolean} isRight\n   * @return {Number}\n   */\n  getUpCursorOffset: function(e, isRight) {\n    var selectionProp = this._getSelectionForOffset(e, isRight),\n        cursorLocation = this.get2DCursorLocation(selectionProp),\n        lineIndex = cursorLocation.lineIndex;\n    if (lineIndex === 0 || e.metaKey || e.keyCode === 33) {\n      // if on first line, up cursor goes to start of line\n      return -selectionProp;\n    }\n    var charIndex = cursorLocation.charIndex,\n        widthBeforeCursor = this._getWidthBeforeCursor(lineIndex, charIndex),\n        indexOnOtherLine = this._getIndexOnLine(lineIndex - 1, widthBeforeCursor),\n        textBeforeCursor = this._textLines[lineIndex].slice(0, charIndex),\n        missingNewlineOffset = this.missingNewlineOffset(lineIndex - 1);\n    // return a negative offset\n    return -this._textLines[lineIndex - 1].length\n     + indexOnOtherLine - textBeforeCursor.length + (1 - missingNewlineOffset);\n  },\n\n  /**\n   * for a given width it founds the matching character.\n   * @private\n   */\n  _getIndexOnLine: function(lineIndex, width) {\n\n    var line = this._textLines[lineIndex],\n        lineLeftOffset = this._getLineLeftOffset(lineIndex),\n        widthOfCharsOnLine = lineLeftOffset,\n        indexOnLine = 0, charWidth, foundMatch;\n\n    for (var j = 0, jlen = line.length; j < jlen; j++) {\n      charWidth = this.__charBounds[lineIndex][j].width;\n      widthOfCharsOnLine += charWidth;\n      if (widthOfCharsOnLine > width) {\n        foundMatch = true;\n        var leftEdge = widthOfCharsOnLine - charWidth,\n            rightEdge = widthOfCharsOnLine,\n            offsetFromLeftEdge = Math.abs(leftEdge - width),\n            offsetFromRightEdge = Math.abs(rightEdge - width);\n\n        indexOnLine = offsetFromRightEdge < offsetFromLeftEdge ? j : (j - 1);\n        break;\n      }\n    }\n\n    // reached end\n    if (!foundMatch) {\n      indexOnLine = line.length - 1;\n    }\n\n    return indexOnLine;\n  },\n\n\n  /**\n   * Moves cursor down\n   * @param {Event} e Event object\n   */\n  moveCursorDown: function(e) {\n    if (this.selectionStart >= this._text.length && this.selectionEnd >= this._text.length) {\n      return;\n    }\n    this._moveCursorUpOrDown('Down', e);\n  },\n\n  /**\n   * Moves cursor up\n   * @param {Event} e Event object\n   */\n  moveCursorUp: function(e) {\n    if (this.selectionStart === 0 && this.selectionEnd === 0) {\n      return;\n    }\n    this._moveCursorUpOrDown('Up', e);\n  },\n\n  /**\n   * Moves cursor up or down, fires the events\n   * @param {String} direction 'Up' or 'Down'\n   * @param {Event} e Event object\n   */\n  _moveCursorUpOrDown: function(direction, e) {\n    // getUpCursorOffset\n    // getDownCursorOffset\n    var action = 'get' + direction + 'CursorOffset',\n        offset = this[action](e, this._selectionDirection === 'right');\n    if (e.shiftKey) {\n      this.moveCursorWithShift(offset);\n    }\n    else {\n      this.moveCursorWithoutShift(offset);\n    }\n    if (offset !== 0) {\n      this.setSelectionInBoundaries();\n      this.abortCursorAnimation();\n      this._currentCursorOpacity = 1;\n      this.initDelayedCursor();\n      this._fireSelectionChanged();\n      this._updateTextarea();\n    }\n  },\n\n  /**\n   * Moves cursor with shift\n   * @param {Number} offset\n   */\n  moveCursorWithShift: function(offset) {\n    var newSelection = this._selectionDirection === 'left'\n      ? this.selectionStart + offset\n      : this.selectionEnd + offset;\n    this.setSelectionStartEndWithShift(this.selectionStart, this.selectionEnd, newSelection);\n    return offset !== 0;\n  },\n\n  /**\n   * Moves cursor up without shift\n   * @param {Number} offset\n   */\n  moveCursorWithoutShift: function(offset) {\n    if (offset < 0) {\n      this.selectionStart += offset;\n      this.selectionEnd = this.selectionStart;\n    }\n    else {\n      this.selectionEnd += offset;\n      this.selectionStart = this.selectionEnd;\n    }\n    return offset !== 0;\n  },\n\n  /**\n   * Moves cursor left\n   * @param {Event} e Event object\n   */\n  moveCursorLeft: function(e) {\n    if (this.selectionStart === 0 && this.selectionEnd === 0) {\n      return;\n    }\n    this._moveCursorLeftOrRight('Left', e);\n  },\n\n  /**\n   * @private\n   * @return {Boolean} true if a change happened\n   */\n  _move: function(e, prop, direction) {\n    var newValue;\n    if (e.altKey) {\n      newValue = this['findWordBoundary' + direction](this[prop]);\n    }\n    else if (e.metaKey || e.keyCode === 35 ||  e.keyCode === 36 ) {\n      newValue = this['findLineBoundary' + direction](this[prop]);\n    }\n    else {\n      this[prop] += direction === 'Left' ? -1 : 1;\n      return true;\n    }\n    if (typeof newValue !== undefined && this[prop] !== newValue) {\n      this[prop] = newValue;\n      return true;\n    }\n  },\n\n  /**\n   * @private\n   */\n  _moveLeft: function(e, prop) {\n    return this._move(e, prop, 'Left');\n  },\n\n  /**\n   * @private\n   */\n  _moveRight: function(e, prop) {\n    return this._move(e, prop, 'Right');\n  },\n\n  /**\n   * Moves cursor left without keeping selection\n   * @param {Event} e\n   */\n  moveCursorLeftWithoutShift: function(e) {\n    var change = true;\n    this._selectionDirection = 'left';\n\n    // only move cursor when there is no selection,\n    // otherwise we discard it, and leave cursor on same place\n    if (this.selectionEnd === this.selectionStart && this.selectionStart !== 0) {\n      change = this._moveLeft(e, 'selectionStart');\n\n    }\n    this.selectionEnd = this.selectionStart;\n    return change;\n  },\n\n  /**\n   * Moves cursor left while keeping selection\n   * @param {Event} e\n   */\n  moveCursorLeftWithShift: function(e) {\n    if (this._selectionDirection === 'right' && this.selectionStart !== this.selectionEnd) {\n      return this._moveLeft(e, 'selectionEnd');\n    }\n    else if (this.selectionStart !== 0){\n      this._selectionDirection = 'left';\n      return this._moveLeft(e, 'selectionStart');\n    }\n  },\n\n  /**\n   * Moves cursor right\n   * @param {Event} e Event object\n   */\n  moveCursorRight: function(e) {\n    if (this.selectionStart >= this._text.length && this.selectionEnd >= this._text.length) {\n      return;\n    }\n    this._moveCursorLeftOrRight('Right', e);\n  },\n\n  /**\n   * Moves cursor right or Left, fires event\n   * @param {String} direction 'Left', 'Right'\n   * @param {Event} e Event object\n   */\n  _moveCursorLeftOrRight: function(direction, e) {\n    var actionName = 'moveCursor' + direction + 'With';\n    this._currentCursorOpacity = 1;\n\n    if (e.shiftKey) {\n      actionName += 'Shift';\n    }\n    else {\n      actionName += 'outShift';\n    }\n    if (this[actionName](e)) {\n      this.abortCursorAnimation();\n      this.initDelayedCursor();\n      this._fireSelectionChanged();\n      this._updateTextarea();\n    }\n  },\n\n  /**\n   * Moves cursor right while keeping selection\n   * @param {Event} e\n   */\n  moveCursorRightWithShift: function(e) {\n    if (this._selectionDirection === 'left' && this.selectionStart !== this.selectionEnd) {\n      return this._moveRight(e, 'selectionStart');\n    }\n    else if (this.selectionEnd !== this._text.length) {\n      this._selectionDirection = 'right';\n      return this._moveRight(e, 'selectionEnd');\n    }\n  },\n\n  /**\n   * Moves cursor right without keeping selection\n   * @param {Event} e Event object\n   */\n  moveCursorRightWithoutShift: function(e) {\n    var changed = true;\n    this._selectionDirection = 'right';\n\n    if (this.selectionStart === this.selectionEnd) {\n      changed = this._moveRight(e, 'selectionStart');\n      this.selectionEnd = this.selectionStart;\n    }\n    else {\n      this.selectionStart = this.selectionEnd;\n    }\n    return changed;\n  },\n\n  /**\n   * Removes characters from start/end\n   * start/end ar per grapheme position in _text array.\n   *\n   * @param {Number} start\n   * @param {Number} end default to start + 1\n   */\n  removeChars: function(start, end) {\n    if (typeof end === 'undefined') {\n      end = start + 1;\n    }\n    this.removeStyleFromTo(start, end);\n    this._text.splice(start, end - start);\n    this.text = this._text.join('');\n    this.set('dirty', true);\n    if (this._shouldClearDimensionCache()) {\n      this.initDimensions();\n      this.setCoords();\n    }\n    this._removeExtraneousStyles();\n  },\n\n  /**\n   * insert characters at start position, before start position.\n   * start  equal 1 it means the text get inserted between actual grapheme 0 and 1\n   * if style array is provided, it must be as the same length of text in graphemes\n   * if end is provided and is bigger than start, old text is replaced.\n   * start/end ar per grapheme position in _text array.\n   *\n   * @param {String} text text to insert\n   * @param {Array} style array of style objects\n   * @param {Number} start\n   * @param {Number} end default to start + 1\n   */\n  insertChars: function(text, style, start, end) {\n    if (typeof end === 'undefined') {\n      end = start;\n    }\n    if (end > start) {\n      this.removeStyleFromTo(start, end);\n    }\n    var graphemes = fabric.util.string.graphemeSplit(text);\n    this.insertNewStyleBlock(graphemes, start, style);\n    this._text = [].concat(this._text.slice(0, start), graphemes, this._text.slice(end));\n    this.text = this._text.join('');\n    this.set('dirty', true);\n    if (this._shouldClearDimensionCache()) {\n      this.initDimensions();\n      this.setCoords();\n    }\n    this._removeExtraneousStyles();\n  },\n\n});\n\n\n/* _TO_SVG_START_ */\n(function() {\n  var toFixed = fabric.util.toFixed,\n      multipleSpacesRegex = /  +/g;\n\n  fabric.util.object.extend(fabric.Text.prototype, /** @lends fabric.Text.prototype */ {\n\n    /**\n     * Returns SVG representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    _toSVG: function() {\n      var offsets = this._getSVGLeftTopOffsets(),\n          textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft);\n      return this._wrapSVGTextAndBg(textAndBg);\n    },\n\n    /**\n     * Returns svg representation of an instance\n     * @param {Function} [reviver] Method for further parsing of svg representation.\n     * @return {String} svg representation of an instance\n     */\n    toSVG: function(reviver) {\n      return this._createBaseSVGMarkup(\n        this._toSVG(),\n        { reviver: reviver, noStyle: true, withShadow: true }\n      );\n    },\n\n    /**\n     * @private\n     */\n    _getSVGLeftTopOffsets: function() {\n      return {\n        textLeft: -this.width / 2,\n        textTop: -this.height / 2,\n        lineTop: this.getHeightOfLine(0)\n      };\n    },\n\n    /**\n     * @private\n     */\n    _wrapSVGTextAndBg: function(textAndBg) {\n      var noShadow = true,\n          textDecoration = this.getSvgTextDecoration(this);\n      return [\n        textAndBg.textBgRects.join(''),\n        '\\t\\t<text xml:space=\"preserve\" ',\n        (this.fontFamily ? 'font-family=\"' + this.fontFamily.replace(/\"/g, '\\'') + '\" ' : ''),\n        (this.fontSize ? 'font-size=\"' + this.fontSize + '\" ' : ''),\n        (this.fontStyle ? 'font-style=\"' + this.fontStyle + '\" ' : ''),\n        (this.fontWeight ? 'font-weight=\"' + this.fontWeight + '\" ' : ''),\n        (textDecoration ? 'text-decoration=\"' + textDecoration + '\" ' : ''),\n        'style=\"', this.getSvgStyles(noShadow), '\"', this.addPaintOrder(), ' >',\n        textAndBg.textSpans.join(''),\n        '</text>\\n'\n      ];\n    },\n\n    /**\n     * @private\n     * @param {Number} textTopOffset Text top offset\n     * @param {Number} textLeftOffset Text left offset\n     * @return {Object}\n     */\n    _getSVGTextAndBg: function(textTopOffset, textLeftOffset) {\n      var textSpans = [],\n          textBgRects = [],\n          height = textTopOffset, lineOffset;\n      // bounding-box background\n      this._setSVGBg(textBgRects);\n\n      // text and text-background\n      for (var i = 0, len = this._textLines.length; i < len; i++) {\n        lineOffset = this._getLineLeftOffset(i);\n        if (this.textBackgroundColor || this.styleHas('textBackgroundColor', i)) {\n          this._setSVGTextLineBg(textBgRects, i, textLeftOffset + lineOffset, height);\n        }\n        this._setSVGTextLineText(textSpans, i, textLeftOffset + lineOffset, height);\n        height += this.getHeightOfLine(i);\n      }\n\n      return {\n        textSpans: textSpans,\n        textBgRects: textBgRects\n      };\n    },\n\n    /**\n     * @private\n     */\n    _createTextCharSpan: function(_char, styleDecl, left, top) {\n      var shouldUseWhitespace = _char !== _char.trim() || _char.match(multipleSpacesRegex),\n          styleProps = this.getSvgSpanStyles(styleDecl, shouldUseWhitespace),\n          fillStyles = styleProps ? 'style=\"' + styleProps + '\"' : '',\n          dy = styleDecl.deltaY, dySpan = '',\n          NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n      if (dy) {\n        dySpan = ' dy=\"' + toFixed(dy, NUM_FRACTION_DIGITS) + '\" ';\n      }\n      return [\n        '<tspan x=\"', toFixed(left, NUM_FRACTION_DIGITS), '\" y=\"',\n        toFixed(top, NUM_FRACTION_DIGITS), '\" ', dySpan,\n        fillStyles, '>',\n        fabric.util.string.escapeXml(_char),\n        '</tspan>'\n      ].join('');\n    },\n\n    _setSVGTextLineText: function(textSpans, lineIndex, textLeftOffset, textTopOffset) {\n      // set proper line offset\n      var lineHeight = this.getHeightOfLine(lineIndex),\n          isJustify = this.textAlign.indexOf('justify') !== -1,\n          actualStyle,\n          nextStyle,\n          charsToRender = '',\n          charBox, style,\n          boxWidth = 0,\n          line = this._textLines[lineIndex],\n          timeToRender;\n\n      textTopOffset += lineHeight * (1 - this._fontSizeFraction) / this.lineHeight;\n      for (var i = 0, len = line.length - 1; i <= len; i++) {\n        timeToRender = i === len || this.charSpacing;\n        charsToRender += line[i];\n        charBox = this.__charBounds[lineIndex][i];\n        if (boxWidth === 0) {\n          textLeftOffset += charBox.kernedWidth - charBox.width;\n          boxWidth += charBox.width;\n        }\n        else {\n          boxWidth += charBox.kernedWidth;\n        }\n        if (isJustify && !timeToRender) {\n          if (this._reSpaceAndTab.test(line[i])) {\n            timeToRender = true;\n          }\n        }\n        if (!timeToRender) {\n          // if we have charSpacing, we render char by char\n          actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\n          nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\n          timeToRender = this._hasStyleChangedForSvg(actualStyle, nextStyle);\n        }\n        if (timeToRender) {\n          style = this._getStyleDeclaration(lineIndex, i) || { };\n          textSpans.push(this._createTextCharSpan(charsToRender, style, textLeftOffset, textTopOffset));\n          charsToRender = '';\n          actualStyle = nextStyle;\n          textLeftOffset += boxWidth;\n          boxWidth = 0;\n        }\n      }\n    },\n\n    _pushTextBgRect: function(textBgRects, color, left, top, width, height) {\n      var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n      textBgRects.push(\n        '\\t\\t<rect ',\n        this._getFillAttributes(color),\n        ' x=\"',\n        toFixed(left, NUM_FRACTION_DIGITS),\n        '\" y=\"',\n        toFixed(top, NUM_FRACTION_DIGITS),\n        '\" width=\"',\n        toFixed(width, NUM_FRACTION_DIGITS),\n        '\" height=\"',\n        toFixed(height, NUM_FRACTION_DIGITS),\n        '\"></rect>\\n');\n    },\n\n    _setSVGTextLineBg: function(textBgRects, i, leftOffset, textTopOffset) {\n      var line = this._textLines[i],\n          heightOfLine = this.getHeightOfLine(i) / this.lineHeight,\n          boxWidth = 0,\n          boxStart = 0,\n          charBox, currentColor,\n          lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\n      for (var j = 0, jlen = line.length; j < jlen; j++) {\n        charBox = this.__charBounds[i][j];\n        currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\n        if (currentColor !== lastColor) {\n          lastColor && this._pushTextBgRect(textBgRects, lastColor, leftOffset + boxStart,\n            textTopOffset, boxWidth, heightOfLine);\n          boxStart = charBox.left;\n          boxWidth = charBox.width;\n          lastColor = currentColor;\n        }\n        else {\n          boxWidth += charBox.kernedWidth;\n        }\n      }\n      currentColor && this._pushTextBgRect(textBgRects, currentColor, leftOffset + boxStart,\n        textTopOffset, boxWidth, heightOfLine);\n    },\n\n    /**\n     * Adobe Illustrator (at least CS5) is unable to render rgba()-based fill values\n     * we work around it by \"moving\" alpha channel into opacity attribute and setting fill's alpha to 1\n     *\n     * @private\n     * @param {*} value\n     * @return {String}\n     */\n    _getFillAttributes: function(value) {\n      var fillColor = (value && typeof value === 'string') ? new fabric.Color(value) : '';\n      if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) {\n        return 'fill=\"' + value + '\"';\n      }\n      return 'opacity=\"' + fillColor.getAlpha() + '\" fill=\"' + fillColor.setAlpha(1).toRgb() + '\"';\n    },\n\n    /**\n     * @private\n     */\n    _getSVGLineTopOffset: function(lineIndex) {\n      var lineTopOffset = 0, lastHeight = 0;\n      for (var j = 0; j < lineIndex; j++) {\n        lineTopOffset += this.getHeightOfLine(j);\n      }\n      lastHeight = this.getHeightOfLine(j);\n      return {\n        lineTop: lineTopOffset,\n        offset: (this._fontSizeMult - this._fontSizeFraction) * lastHeight / (this.lineHeight * this._fontSizeMult)\n      };\n    },\n\n    /**\n     * Returns styles-string for svg-export\n     * @param {Boolean} skipShadow a boolean to skip shadow filter output\n     * @return {String}\n     */\n    getSvgStyles: function(skipShadow) {\n      var svgStyle = fabric.Object.prototype.getSvgStyles.call(this, skipShadow);\n      return svgStyle + ' white-space: pre;';\n    },\n  });\n})();\n/* _TO_SVG_END_ */\n\n\n(function(global) {\n\n  'use strict';\n\n  var fabric = global.fabric || (global.fabric = {});\n\n  /**\n   * Textbox class, based on IText, allows the user to resize the text rectangle\n   * and wraps lines automatically. Textboxes have their Y scaling locked, the\n   * user can only change width. Height is adjusted automatically based on the\n   * wrapping of lines.\n   * @class fabric.Textbox\n   * @extends fabric.IText\n   * @mixes fabric.Observable\n   * @return {fabric.Textbox} thisArg\n   * @see {@link fabric.Textbox#initialize} for constructor definition\n   */\n  fabric.Textbox = fabric.util.createClass(fabric.IText, fabric.Observable, {\n\n    /**\n     * Type of an object\n     * @type String\n     * @default\n     */\n    type: 'textbox',\n\n    /**\n     * Minimum width of textbox, in pixels.\n     * @type Number\n     * @default\n     */\n    minWidth: 20,\n\n    /**\n     * Minimum calculated width of a textbox, in pixels.\n     * fixed to 2 so that an empty textbox cannot go to 0\n     * and is still selectable without text.\n     * @type Number\n     * @default\n     */\n    dynamicMinWidth: 2,\n\n    /**\n     * Cached array of text wrapping.\n     * @type Array\n     */\n    __cachedLines: null,\n\n    /**\n     * Override standard Object class values\n     */\n    lockScalingFlip: true,\n\n    /**\n     * Override standard Object class values\n     * Textbox needs this on false\n     */\n    noScaleCache: false,\n\n    /**\n     * Properties which when set cause object to change dimensions\n     * @type Object\n     * @private\n     */\n    _dimensionAffectingProps: fabric.Text.prototype._dimensionAffectingProps.concat('width'),\n\n    /**\n     * Use this regular expression to split strings in breakable lines\n     * @private\n     */\n    _wordJoiners: /[ \\t\\r]/,\n\n    /**\n     * Use this boolean property in order to split strings that have no white space concept.\n     * this is a cheap way to help with chinese/japaense\n     * @type Boolean\n     * @since 2.6.0\n     */\n    splitByGrapheme: false,\n\n    /**\n     * Unlike superclass's version of this function, Textbox does not update\n     * its width.\n     * @private\n     * @override\n     */\n    initDimensions: function() {\n      if (this.__skipDimension) {\n        return;\n      }\n      this.isEditing && this.initDelayedCursor();\n      this.clearContextTop();\n      this._clearCache();\n      // clear dynamicMinWidth as it will be different after we re-wrap line\n      this.dynamicMinWidth = 0;\n      // wrap lines\n      this._styleMap = this._generateStyleMap(this._splitText());\n      // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n      if (this.dynamicMinWidth > this.width) {\n        this._set('width', this.dynamicMinWidth);\n      }\n      if (this.textAlign.indexOf('justify') !== -1) {\n        // once text is measured we need to make space fatter to make justified text.\n        this.enlargeSpaces();\n      }\n      // clear cache and re-calculate height\n      this.height = this.calcTextHeight();\n      this.saveState({ propertySet: '_dimensionAffectingProps' });\n    },\n\n    /**\n     * Generate an object that translates the style object so that it is\n     * broken up by visual lines (new lines and automatic wrapping).\n     * The original text styles object is broken up by actual lines (new lines only),\n     * which is only sufficient for Text / IText\n     * @private\n     */\n    _generateStyleMap: function(textInfo) {\n      var realLineCount     = 0,\n          realLineCharCount = 0,\n          charCount         = 0,\n          map               = {};\n\n      for (var i = 0; i < textInfo.graphemeLines.length; i++) {\n        if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n          realLineCharCount = 0;\n          charCount++;\n          realLineCount++;\n        }\n        else if (!this.splitByGrapheme && this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) && i > 0) {\n          // this case deals with space's that are removed from end of lines when wrapping\n          realLineCharCount++;\n          charCount++;\n        }\n\n        map[i] = { line: realLineCount, offset: realLineCharCount };\n\n        charCount += textInfo.graphemeLines[i].length;\n        realLineCharCount += textInfo.graphemeLines[i].length;\n      }\n\n      return map;\n    },\n\n    /**\n     * Returns true if object has a style property or has it on a specified line\n     * @param {Number} lineIndex\n     * @return {Boolean}\n     */\n    styleHas: function(property, lineIndex) {\n      if (this._styleMap && !this.isWrapping) {\n        var map = this._styleMap[lineIndex];\n        if (map) {\n          lineIndex = map.line;\n        }\n      }\n      return fabric.Text.prototype.styleHas.call(this, property, lineIndex);\n    },\n\n    /**\n     * Returns true if object has no styling or no styling in a line\n     * @param {Number} lineIndex , lineIndex is on wrapped lines.\n     * @return {Boolean}\n     */\n    isEmptyStyles: function(lineIndex) {\n      if (!this.styles) {\n        return true;\n      }\n      var offset = 0, nextLineIndex = lineIndex + 1, nextOffset, obj, shouldLimit = false,\n          map = this._styleMap[lineIndex], mapNextLine = this._styleMap[lineIndex + 1];\n      if (map) {\n        lineIndex = map.line;\n        offset = map.offset;\n      }\n      if (mapNextLine) {\n        nextLineIndex = mapNextLine.line;\n        shouldLimit = nextLineIndex === lineIndex;\n        nextOffset = mapNextLine.offset;\n      }\n      obj = typeof lineIndex === 'undefined' ? this.styles : { line: this.styles[lineIndex] };\n      for (var p1 in obj) {\n        for (var p2 in obj[p1]) {\n          if (p2 >= offset && (!shouldLimit || p2 < nextOffset)) {\n            // eslint-disable-next-line no-unused-vars\n            for (var p3 in obj[p1][p2]) {\n              return false;\n            }\n          }\n        }\n      }\n      return true;\n    },\n\n    /**\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @private\n     */\n    _getStyleDeclaration: function(lineIndex, charIndex) {\n      if (this._styleMap && !this.isWrapping) {\n        var map = this._styleMap[lineIndex];\n        if (!map) {\n          return null;\n        }\n        lineIndex = map.line;\n        charIndex = map.offset + charIndex;\n      }\n      return this.callSuper('_getStyleDeclaration', lineIndex, charIndex);\n    },\n\n    /**\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @param {Object} style\n     * @private\n     */\n    _setStyleDeclaration: function(lineIndex, charIndex, style) {\n      var map = this._styleMap[lineIndex];\n      lineIndex = map.line;\n      charIndex = map.offset + charIndex;\n\n      this.styles[lineIndex][charIndex] = style;\n    },\n\n    /**\n     * @param {Number} lineIndex\n     * @param {Number} charIndex\n     * @private\n     */\n    _deleteStyleDeclaration: function(lineIndex, charIndex) {\n      var map = this._styleMap[lineIndex];\n      lineIndex = map.line;\n      charIndex = map.offset + charIndex;\n      delete this.styles[lineIndex][charIndex];\n    },\n\n    /**\n     * probably broken need a fix\n     * Returns the real style line that correspond to the wrapped lineIndex line\n     * Used just to verify if the line does exist or not.\n     * @param {Number} lineIndex\n     * @returns {Boolean} if the line exists or not\n     * @private\n     */\n    _getLineStyle: function(lineIndex) {\n      var map = this._styleMap[lineIndex];\n      return !!this.styles[map.line];\n    },\n\n    /**\n     * Set the line style to an empty object so that is initialized\n     * @param {Number} lineIndex\n     * @param {Object} style\n     * @private\n     */\n    _setLineStyle: function(lineIndex) {\n      var map = this._styleMap[lineIndex];\n      this.styles[map.line] = {};\n    },\n\n    /**\n     * Wraps text using the 'width' property of Textbox. First this function\n     * splits text on newlines, so we preserve newlines entered by the user.\n     * Then it wraps each line using the width of the Textbox by calling\n     * _wrapLine().\n     * @param {Array} lines The string array of text that is split into lines\n     * @param {Number} desiredWidth width you want to wrap to\n     * @returns {Array} Array of lines\n     */\n    _wrapText: function(lines, desiredWidth) {\n      var wrapped = [], i;\n      this.isWrapping = true;\n      for (i = 0; i < lines.length; i++) {\n        wrapped = wrapped.concat(this._wrapLine(lines[i], i, desiredWidth));\n      }\n      this.isWrapping = false;\n      return wrapped;\n    },\n\n    /**\n     * Helper function to measure a string of text, given its lineIndex and charIndex offset\n     * it gets called when charBounds are not available yet.\n     * @param {CanvasRenderingContext2D} ctx\n     * @param {String} text\n     * @param {number} lineIndex\n     * @param {number} charOffset\n     * @returns {number}\n     * @private\n     */\n    _measureWord: function(word, lineIndex, charOffset) {\n      var width = 0, prevGrapheme, skipLeft = true;\n      charOffset = charOffset || 0;\n      for (var i = 0, len = word.length; i < len; i++) {\n        var box = this._getGraphemeBox(word[i], lineIndex, i + charOffset, prevGrapheme, skipLeft);\n        width += box.kernedWidth;\n        prevGrapheme = word[i];\n      }\n      return width;\n    },\n\n    /**\n     * Wraps a line of text using the width of the Textbox and a context.\n     * @param {Array} line The grapheme array that represent the line\n     * @param {Number} lineIndex\n     * @param {Number} desiredWidth width you want to wrap the line to\n     * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n     * @returns {Array} Array of line(s) into which the given text is wrapped\n     * to.\n     */\n    _wrapLine: function(_line, lineIndex, desiredWidth, reservedSpace) {\n      var lineWidth = 0,\n          splitByGrapheme = this.splitByGrapheme,\n          graphemeLines = [],\n          line = [],\n          // spaces in different languges?\n          words = splitByGrapheme ? fabric.util.string.graphemeSplit(_line) : _line.split(this._wordJoiners),\n          word = '',\n          offset = 0,\n          infix = splitByGrapheme ? '' : ' ',\n          wordWidth = 0,\n          infixWidth = 0,\n          largestWordWidth = 0,\n          lineJustStarted = true,\n          additionalSpace = this._getWidthOfCharSpacing(),\n          reservedSpace = reservedSpace || 0;\n      // fix a difference between split and graphemeSplit\n      if (words.length === 0) {\n        words.push([]);\n      }\n      desiredWidth -= reservedSpace;\n      for (var i = 0; i < words.length; i++) {\n        // if using splitByGrapheme words are already in graphemes.\n        word = splitByGrapheme ? words[i] : fabric.util.string.graphemeSplit(words[i]);\n        wordWidth = this._measureWord(word, lineIndex, offset);\n        offset += word.length;\n\n        lineWidth += infixWidth + wordWidth - additionalSpace;\n        if (lineWidth >= desiredWidth && !lineJustStarted) {\n          graphemeLines.push(line);\n          line = [];\n          lineWidth = wordWidth;\n          lineJustStarted = true;\n        }\n        else {\n          lineWidth += additionalSpace;\n        }\n\n        if (!lineJustStarted && !splitByGrapheme) {\n          line.push(infix);\n        }\n        line = line.concat(word);\n\n        infixWidth = splitByGrapheme ? 0 : this._measureWord([infix], lineIndex, offset);\n        offset++;\n        lineJustStarted = false;\n        // keep track of largest word\n        if (wordWidth > largestWordWidth) {\n          largestWordWidth = wordWidth;\n        }\n      }\n\n      i && graphemeLines.push(line);\n\n      if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n        this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n      }\n      return graphemeLines;\n    },\n\n    /**\n     * Detect if the text line is ended with an hard break\n     * text and itext do not have wrapping, return false\n     * @param {Number} lineIndex text to split\n     * @return {Boolean}\n     */\n    isEndOfWrapping: function(lineIndex) {\n      if (!this._styleMap[lineIndex + 1]) {\n        // is last line, return true;\n        return true;\n      }\n      if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n        // this is last line before a line break, return true;\n        return true;\n      }\n      return false;\n    },\n\n    /**\n     * Detect if a line has a linebreak and so we need to account for it when moving\n     * and counting style.\n     * @return Number\n     */\n    missingNewlineOffset: function(lineIndex) {\n      if (this.splitByGrapheme) {\n        return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n      }\n      return 1;\n    },\n\n    /**\n    * Gets lines of text to render in the Textbox. This function calculates\n    * text wrapping on the fly every time it is called.\n    * @param {String} text text to split\n    * @returns {Array} Array of lines in the Textbox.\n    * @override\n    */\n    _splitTextIntoLines: function(text) {\n      var newText = fabric.Text.prototype._splitTextIntoLines.call(this, text),\n          graphemeLines = this._wrapText(newText.lines, this.width),\n          lines = new Array(graphemeLines.length);\n      for (var i = 0; i < graphemeLines.length; i++) {\n        lines[i] = graphemeLines[i].join('');\n      }\n      newText.lines = lines;\n      newText.graphemeLines = graphemeLines;\n      return newText;\n    },\n\n    getMinWidth: function() {\n      return Math.max(this.minWidth, this.dynamicMinWidth);\n    },\n\n    _removeExtraneousStyles: function() {\n      var linesToKeep = {};\n      for (var prop in this._styleMap) {\n        if (this._textLines[prop]) {\n          linesToKeep[this._styleMap[prop].line] = 1;\n        }\n      }\n      for (var prop in this.styles) {\n        if (!linesToKeep[prop]) {\n          delete this.styles[prop];\n        }\n      }\n    },\n\n    /**\n     * Returns object representation of an instance\n     * @method toObject\n     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n     * @return {Object} object representation of an instance\n     */\n    toObject: function(propertiesToInclude) {\n      return this.callSuper('toObject', ['minWidth', 'splitByGrapheme'].concat(propertiesToInclude));\n    }\n  });\n\n  /**\n   * Returns fabric.Textbox instance from an object representation\n   * @static\n   * @memberOf fabric.Textbox\n   * @param {Object} object Object to create an instance from\n   * @param {Function} [callback] Callback to invoke when an fabric.Textbox instance is created\n   */\n  fabric.Textbox.fromObject = function(object, callback) {\n    return fabric.Object._fromObject('Textbox', object, callback, 'text');\n  };\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n  var controlsUtils = fabric.controlsUtils,\n      scaleSkewStyleHandler = controlsUtils.scaleSkewCursorStyleHandler,\n      scaleStyleHandler = controlsUtils.scaleCursorStyleHandler,\n      scalingEqually = controlsUtils.scalingEqually,\n      scalingYOrSkewingX = controlsUtils.scalingYOrSkewingX,\n      scalingXOrSkewingY = controlsUtils.scalingXOrSkewingY,\n      scaleOrSkewActionName = controlsUtils.scaleOrSkewActionName,\n      objectControls = fabric.Object.prototype.controls;\n\n  objectControls.ml = new fabric.Control({\n    x: -0.5,\n    y: 0,\n    cursorStyleHandler: scaleSkewStyleHandler,\n    actionHandler: scalingXOrSkewingY,\n    getActionName: scaleOrSkewActionName,\n  });\n\n  objectControls.mr = new fabric.Control({\n    x: 0.5,\n    y: 0,\n    cursorStyleHandler: scaleSkewStyleHandler,\n    actionHandler: scalingXOrSkewingY,\n    getActionName: scaleOrSkewActionName,\n  });\n\n  objectControls.mb = new fabric.Control({\n    x: 0,\n    y: 0.5,\n    cursorStyleHandler: scaleSkewStyleHandler,\n    actionHandler: scalingYOrSkewingX,\n    getActionName: scaleOrSkewActionName,\n  });\n\n  objectControls.mt = new fabric.Control({\n    x: 0,\n    y: -0.5,\n    cursorStyleHandler: scaleSkewStyleHandler,\n    actionHandler: scalingYOrSkewingX,\n    getActionName: scaleOrSkewActionName,\n  });\n\n  objectControls.tl = new fabric.Control({\n    x: -0.5,\n    y: -0.5,\n    cursorStyleHandler: scaleStyleHandler,\n    actionHandler: scalingEqually\n  });\n\n  objectControls.tr = new fabric.Control({\n    x: 0.5,\n    y: -0.5,\n    cursorStyleHandler: scaleStyleHandler,\n    actionHandler: scalingEqually\n  });\n\n  objectControls.bl = new fabric.Control({\n    x: -0.5,\n    y: 0.5,\n    cursorStyleHandler: scaleStyleHandler,\n    actionHandler: scalingEqually\n  });\n\n  objectControls.br = new fabric.Control({\n    x: 0.5,\n    y: 0.5,\n    cursorStyleHandler: scaleStyleHandler,\n    actionHandler: scalingEqually\n  });\n\n  objectControls.mtr = new fabric.Control({\n    x: 0,\n    y: -0.5,\n    actionHandler: controlsUtils.rotationWithSnapping,\n    cursorStyleHandler: controlsUtils.rotationStyleHandler,\n    offsetY: -40,\n    withConnection: true,\n    actionName: 'rotate',\n  });\n\n  if (fabric.Textbox) {\n    // this is breaking the prototype inheritance, no time / ideas to fix it.\n    // is important to document that if you want to have all objects to have a\n    // specific custom control, you have to add it to Object prototype and to Textbox\n    // prototype. The controls are shared as references. So changes to control `tr`\n    // can still apply to all objects if needed.\n    var textBoxControls = fabric.Textbox.prototype.controls = { };\n\n    textBoxControls.mtr = objectControls.mtr;\n    textBoxControls.tr = objectControls.tr;\n    textBoxControls.br = objectControls.br;\n    textBoxControls.tl = objectControls.tl;\n    textBoxControls.bl = objectControls.bl;\n    textBoxControls.mt = objectControls.mt;\n    textBoxControls.mb = objectControls.mb;\n\n    textBoxControls.mr = new fabric.Control({\n      x: 0.5,\n      y: 0,\n      actionHandler: controlsUtils.changeWidth,\n      cursorStyleHandler: scaleSkewStyleHandler,\n      actionName: 'resizing',\n    });\n\n    textBoxControls.ml = new fabric.Control({\n      x: -0.5,\n      y: 0,\n      actionHandler: controlsUtils.changeWidth,\n      cursorStyleHandler: scaleSkewStyleHandler,\n      actionName: 'resizing',\n    });\n  }\n})();\n\n"]},"metadata":{},"sourceType":"script"}