{"version":3,"file":"pwc-576.510ba28d.chunk.js","mappings":"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","sources":["../node_modules/fabric/dist/fabric.js","../node_modules/use-query-params/adapters/react-router-5/index.js"],"sourcesContent":["/* build: `node build.js modules=ALL exclude=gestures,accessors,erasing requirejs minifier=uglifyjs` */\n/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */\n\nvar fabric = fabric || { version: '5.3.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 bezier 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 function _once(eventName, handler) {\n var _handler = function () {\n handler.apply(this, arguments);\n this.off(eventName, _handler);\n }.bind(this);\n this.on(eventName, _handler);\n }\n\n function once(eventName, handler) {\n // one object with key/value pairs was passed\n if (arguments.length === 1) {\n for (var prop in eventName) {\n _once.call(this, prop, eventName[prop]);\n }\n }\n else {\n _once.call(this, eventName, 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 once: once,\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 * @param {Boolean} [deep=false] `true` to check all descendants, `false` to check only `_objects`\n * @return {Boolean} `true` if collection contains an object\n */\n contains: function (object, deep) {\n if (this._objects.indexOf(object) > -1) {\n return true;\n }\n else if (deep) {\n return this._objects.some(function (obj) {\n return typeof obj.contains === 'function' && obj.contains(object, true);\n });\n }\n return false;\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 var newPoint = new fabric.Point(point.x - origin.x, point.y - origin.y),\n v = fabric.util.rotateVector(newPoint, 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 * Creates a vetor from points represented as a point\n * @static\n * @memberOf fabric.util\n *\n * @typedef {Object} Point\n * @property {number} x\n * @property {number} y\n *\n * @param {Point} from\n * @param {Point} to\n * @returns {Point} vector\n */\n createVector: function (from, to) {\n return new fabric.Point(to.x - from.x, to.y - from.y);\n },\n\n /**\n * Calculates angle between 2 vectors using dot product\n * @static\n * @memberOf fabric.util\n * @param {Point} a\n * @param {Point} b\n * @returns the angle in radian between the vectors\n */\n calcAngleBetweenVectors: function (a, b) {\n return Math.acos((a.x * b.x + a.y * b.y) / (Math.hypot(a.x, a.y) * Math.hypot(b.x, b.y)));\n },\n\n /**\n * @static\n * @memberOf fabric.util\n * @param {Point} v\n * @returns {Point} vector representing the unit vector of pointing to the direction of `v`\n */\n getHatVector: function (v) {\n return new fabric.Point(v.x, v.y).multiply(1 / Math.hypot(v.x, v.y));\n },\n\n /**\n * @static\n * @memberOf fabric.util\n * @param {Point} A\n * @param {Point} B\n * @param {Point} C\n * @returns {{ vector: Point, angle: number }} vector representing the bisector of A and A's angle\n */\n getBisector: function (A, B, C) {\n var AB = fabric.util.createVector(A, B), AC = fabric.util.createVector(A, C);\n var alpha = fabric.util.calcAngleBetweenVectors(AB, AC);\n // check if alpha is relative to AB->BC\n var ro = fabric.util.calcAngleBetweenVectors(fabric.util.rotateVector(AB, alpha), AC);\n var phi = alpha * (ro === 0 ? 1 : -1) / 2;\n return {\n vector: fabric.util.getHatVector(fabric.util.rotateVector(AB, phi)),\n angle: alpha\n };\n },\n\n /**\n * Project stroke width on points returning 2 projections for each point as follows:\n * - `miter`: 2 points corresponding to the outer boundary and the inner boundary of stroke.\n * - `bevel`: 2 points corresponding to the bevel boundaries, tangent to the bisector.\n * - `round`: same as `bevel`\n * Used to calculate object's bounding box\n * @static\n * @memberOf fabric.util\n * @param {Point[]} points\n * @param {Object} options\n * @param {number} options.strokeWidth\n * @param {'miter'|'bevel'|'round'} options.strokeLineJoin\n * @param {number} options.strokeMiterLimit https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit\n * @param {boolean} options.strokeUniform\n * @param {number} options.scaleX\n * @param {number} options.scaleY\n * @param {boolean} [openPath] whether the shape is open or not, affects the calculations of the first and last points\n * @returns {fabric.Point[]} array of size 2n/4n of all suspected points\n */\n projectStrokeOnPoints: function (points, options, openPath) {\n var coords = [], s = options.strokeWidth / 2,\n strokeUniformScalar = options.strokeUniform ?\n new fabric.Point(1 / options.scaleX, 1 / options.scaleY) : new fabric.Point(1, 1),\n getStrokeHatVector = function (v) {\n var scalar = s / (Math.hypot(v.x, v.y));\n return new fabric.Point(v.x * scalar * strokeUniformScalar.x, v.y * scalar * strokeUniformScalar.y);\n };\n if (points.length <= 1) {return coords;}\n points.forEach(function (p, index) {\n var A = new fabric.Point(p.x, p.y), B, C;\n if (index === 0) {\n C = points[index + 1];\n B = openPath ? getStrokeHatVector(fabric.util.createVector(C, A)).addEquals(A) : points[points.length - 1];\n }\n else if (index === points.length - 1) {\n B = points[index - 1];\n C = openPath ? getStrokeHatVector(fabric.util.createVector(B, A)).addEquals(A) : points[0];\n }\n else {\n B = points[index - 1];\n C = points[index + 1];\n }\n var bisector = fabric.util.getBisector(A, B, C),\n bisectorVector = bisector.vector,\n alpha = bisector.angle,\n scalar,\n miterVector;\n if (options.strokeLineJoin === 'miter') {\n scalar = -s / Math.sin(alpha / 2);\n miterVector = new fabric.Point(\n bisectorVector.x * scalar * strokeUniformScalar.x,\n bisectorVector.y * scalar * strokeUniformScalar.y\n );\n if (Math.hypot(miterVector.x, miterVector.y) / s <= options.strokeMiterLimit) {\n coords.push(A.add(miterVector));\n coords.push(A.subtract(miterVector));\n return;\n }\n }\n scalar = -s * Math.SQRT2;\n miterVector = new fabric.Point(\n bisectorVector.x * scalar * strokeUniformScalar.x,\n bisectorVector.y * scalar * strokeUniformScalar.y\n );\n coords.push(A.add(miterVector));\n coords.push(A.subtract(miterVector));\n });\n return coords;\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 * Creates corresponding fabric instances residing in an object, e.g. `clipPath`\n * @see {@link fabric.Object.ENLIVEN_PROPS}\n * @param {Object} object\n * @param {Object} [context] assign enlived props to this object (pass null to skip this)\n * @param {(objects:fabric.Object[]) => void} callback\n */\n enlivenObjectEnlivables: function (object, context, callback) {\n var enlivenProps = fabric.Object.ENLIVEN_PROPS.filter(function (key) { return !!object[key]; });\n fabric.util.enlivenObjects(enlivenProps.map(function (key) { return object[key]; }), function (enlivedProps) {\n var objects = {};\n enlivenProps.forEach(function (key, index) {\n objects[key] = enlivedProps[index];\n context && (context[key] = enlivedProps[index]);\n });\n callback && callback(objects);\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 if (typeof path !== 'undefined') {\n elements[0].sourcePath = path;\n }\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 && Array.isArray(properties)) {\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 * 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.skewY]\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} transform 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 an object and a transform, apply the inverse transform to the object,\n * this is equivalent to remove from that object that transformation, so that\n * added in a space with the removed transform, the object will be the same as before.\n * Removing from an object a transform that scale by 2 is like scaling it by 1/2.\n * Removing from an object a transfrom that rotate by 30deg is like rotating by 30deg\n * in the opposite direction.\n * This util is used to add objects inside transformed groups or nested groups.\n * @memberOf fabric.util\n * @param {fabric.Object} object the object you want to transform\n * @param {Array} transform the destination transform\n */\n removeTransformFromObject: function(object, transform) {\n var inverted = fabric.util.invertTransform(transform),\n finalTransform = fabric.util.multiplyTransformMatrices(inverted, object.calcOwnMatrix());\n fabric.util.applyTransformToObject(object, finalTransform);\n },\n\n /**\n * given an object and a transform, apply the transform to the object.\n * this is equivalent to change the space where the object is drawn.\n * Adding to an object a transform that scale by 2 is like scaling it by 2.\n * This is used when removing an object from an active selection for example.\n * @memberOf fabric.util\n * @param {fabric.Object} object the object you want to transform\n * @param {Array} transform the destination transform\n */\n addTransformToObject: function(object, transform) {\n fabric.util.applyTransformToObject(\n object,\n fabric.util.multiplyTransformMatrices(transform, object.calcOwnMatrix())\n );\n },\n\n /**\n * discard an object transform state and apply the one from the matrix.\n * @memberOf fabric.util\n * @param {fabric.Object} object the object you want to transform\n * @param {Array} transform the destination transform\n */\n applyTransformToObject: function(object, transform) {\n var options = fabric.util.qrDecompose(transform),\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 },\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 /**\n * Merges 2 clip paths into one visually equal clip path\n *\n * **IMPORTANT**:\\\n * Does **NOT** clone the arguments, clone them proir if necessary.\n *\n * Creates a wrapper (group) that contains one clip path and is clipped by the other so content is kept where both overlap.\n * Use this method if both the clip paths may have nested clip paths of their own, so assigning one to the other's clip path property is not possible.\n *\n * In order to handle the `inverted` property we follow logic described in the following cases:\\\n * **(1)** both clip paths are inverted - the clip paths pass the inverted prop to the wrapper and loose it themselves.\\\n * **(2)** one is inverted and the other isn't - the wrapper shouldn't become inverted and the inverted clip path must clip the non inverted one to produce an identical visual effect.\\\n * **(3)** both clip paths are not inverted - wrapper and clip paths remain unchanged.\n *\n * @memberOf fabric.util\n * @param {fabric.Object} c1\n * @param {fabric.Object} c2\n * @returns {fabric.Object} merged clip path\n */\n mergeClipPaths: function (c1, c2) {\n var a = c1, b = c2;\n if (a.inverted && !b.inverted) {\n // case (2)\n a = c2;\n b = c1;\n }\n // `b` becomes `a`'s clip path so we transform `b` to `a` coordinate plane\n fabric.util.applyTransformToObject(\n b,\n fabric.util.multiplyTransformMatrices(\n fabric.util.invertTransform(a.calcTransformMatrix()),\n b.calcTransformMatrix()\n )\n );\n // assign the `inverted` prop to the wrapping group\n var inverted = a.inverted && b.inverted;\n if (inverted) {\n // case (1)\n a.inverted = b.inverted = false;\n }\n return new fabric.Group([a], { clipPath: b, inverted: inverted });\n },\n\n /**\n * @memberOf fabric.util\n * @param {Object} prevStyle first style to compare\n * @param {Object} thisStyle second style to compare\n * @param {boolean} forTextSpans whether to check overline, underline, and line-through properties\n * @return {boolean} true if the style changed\n */\n hasStyleChanged: function(prevStyle, thisStyle, forTextSpans) {\n forTextSpans = forTextSpans || false;\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.textBackgroundColor !== thisStyle.textBackgroundColor ||\n prevStyle.deltaY !== thisStyle.deltaY) ||\n (forTextSpans &&\n (prevStyle.overline !== thisStyle.overline ||\n prevStyle.underline !== thisStyle.underline ||\n prevStyle.linethrough !== thisStyle.linethrough));\n },\n\n /**\n * Returns the array form of a text object's inline styles property with styles grouped in ranges\n * rather than per character. This format is less verbose, and is better suited for storage\n * so it is used in serialization (not during runtime).\n * @memberOf fabric.util\n * @param {object} styles per character styles for a text object\n * @param {String} text the text string that the styles are applied to\n * @return {{start: number, end: number, style: object}[]}\n */\n stylesToArray: function(styles, text) {\n // clone style structure to prevent mutation\n var styles = fabric.util.object.clone(styles, true),\n textLines = text.split('\\n'),\n charIndex = -1, prevStyle = {}, stylesArray = [];\n //loop through each textLine\n for (var i = 0; i < textLines.length; i++) {\n if (!styles[i]) {\n //no styles exist for this line, so add the line's length to the charIndex total\n charIndex += textLines[i].length;\n continue;\n }\n //loop through each character of the current line\n for (var c = 0; c < textLines[i].length; c++) {\n charIndex++;\n var thisStyle = styles[i][c];\n //check if style exists for this character\n if (thisStyle && Object.keys(thisStyle).length > 0) {\n var styleChanged = fabric.util.hasStyleChanged(prevStyle, thisStyle, true);\n if (styleChanged) {\n stylesArray.push({\n start: charIndex,\n end: charIndex + 1,\n style: thisStyle\n });\n }\n else {\n //if style is the same as previous character, increase end index\n stylesArray[stylesArray.length - 1].end++;\n }\n }\n prevStyle = thisStyle || {};\n }\n }\n return stylesArray;\n },\n\n /**\n * Returns the object form of the styles property with styles that are assigned per\n * character rather than grouped by range. This format is more verbose, and is\n * only used during runtime (not for serialization/storage)\n * @memberOf fabric.util\n * @param {Array} styles the serialized form of a text object's styles\n * @param {String} text the text string that the styles are applied to\n * @return {Object}\n */\n stylesFromArray: function(styles, text) {\n if (!Array.isArray(styles)) {\n return styles;\n }\n var textLines = text.split('\\n'),\n charIndex = -1, styleIndex = 0, stylesObject = {};\n //loop through each textLine\n for (var i = 0; i < textLines.length; i++) {\n //loop through each character of the current line\n for (var c = 0; c < textLines[i].length; c++) {\n charIndex++;\n //check if there's a style collection that includes the current character\n if (styles[styleIndex]\n && styles[styleIndex].start <= charIndex\n && charIndex < styles[styleIndex].end) {\n //create object for line index if it doesn't exist\n stylesObject[i] = stylesObject[i] || {};\n //assign a style at this character's index\n stylesObject[i][c] = Object.assign({}, styles[styleIndex].style);\n //if character is at the end of the current style collection, move to the next\n if (charIndex === styles[styleIndex].end - 1) {\n styleIndex++;\n }\n }\n }\n }\n return stylesObject;\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 bezier\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 bezier curves\n * @param {Number} fx starting point x\n * @param {Number} fy starting point y\n * @param {Array} coords Arc command\n */\n function fromArcToBeziers(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 * This function take a parsed SVG path and make it simpler for fabricJS logic.\n * simplification consist of: only UPPERCASE absolute commands ( relative converted to absolute )\n * S converted in C, T converted in Q, A converted in C.\n * @param {Array} path the array of commands of a parsed svg path for fabric.Path\n * @return {Array} the simplified array of commands of a parsed svg path for fabric.Path\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(fromArcToBeziers(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 getTangentCubicIterator(p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y) {\n return function (pct) {\n var invT = 1 - pct,\n tangentX = (3 * invT * invT * (p2x - p1x)) + (6 * invT * pct * (p3x - p2x)) +\n (3 * pct * pct * (p4x - p3x)),\n tangentY = (3 * invT * invT * (p2y - p1y)) + (6 * invT * pct * (p3y - p2y)) +\n (3 * pct * pct * (p4y - p3y));\n return Math.atan2(tangentY, tangentX);\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 getTangentQuadraticIterator(p1x, p1y, p2x, p2y, p3x, p3y) {\n return function (pct) {\n var invT = 1 - pct,\n tangentX = (2 * invT * (p2x - p1x)) + (2 * pct * (p3x - p2x)),\n tangentY = (2 * invT * (p2y - p1y)) + (2 * pct * (p3y - p2y));\n return Math.atan2(tangentY, tangentX);\n };\n }\n\n\n // this will run over a path segment ( a cubic or quadratic segment) and approximate it\n // with 100 segemnts. This will good enough to calculate the length of the curve\n function pathIterator(iterator, x1, y1) {\n var tempP = { x: x1, y: y1 }, p, tmpLen = 0, perc;\n for (perc = 1; perc <= 100; perc += 1) {\n p = iterator(perc / 100);\n tmpLen += calcLineLength(tempP.x, tempP.y, p.x, p.y);\n tempP = p;\n }\n return tmpLen;\n }\n\n /**\n * Given a pathInfo, and a distance in pixels, find the percentage from 0 to 1\n * that correspond to that pixels run over the path.\n * The percentage will be then used to find the correct point on the canvas for the path.\n * @param {Array} segInfo fabricJS collection of information on a parsed path\n * @param {Number} distance from starting point, in pixels.\n * @return {Object} info object with x and y ( the point on canvas ) and angle, the tangent on that point;\n */\n function findPercentageForDistance(segInfo, distance) {\n var perc = 0, tmpLen = 0, iterator = segInfo.iterator, tempP = { x: segInfo.x, y: segInfo.y },\n p, nextLen, nextStep = 0.01, angleFinder = segInfo.angleFinder, lastPerc;\n // nextStep > 0.0001 covers 0.00015625 that 1/64th of 1/100\n // the path\n while (tmpLen < distance && nextStep > 0.0001) {\n p = iterator(perc);\n lastPerc = perc;\n nextLen = calcLineLength(tempP.x, tempP.y, p.x, p.y);\n // compare tmpLen each cycle with distance, decide next perc to test.\n if ((nextLen + tmpLen) > distance) {\n // we discard this step and we make smaller steps.\n perc -= nextStep;\n nextStep /= 2;\n }\n else {\n tempP = p;\n perc += nextStep;\n tmpLen += nextLen;\n }\n }\n p.angle = angleFinder(lastPerc);\n return p;\n }\n\n /**\n * Run over a parsed and simplifed path and extrac some informations.\n * informations are length of each command and starting point\n * @param {Array} path fabricJS parsed path commands\n * @return {Array} path commands informations\n */\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, angleFinder;\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 angleFinder = getTangentCubicIterator(\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.iterator = iterator;\n tempInfo.angleFinder = angleFinder;\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 angleFinder = getTangentQuadraticIterator(\n x1,\n y1,\n current[1],\n current[2],\n current[3],\n current[4]\n );\n tempInfo.iterator = iterator;\n tempInfo.angleFinder = angleFinder;\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, distance, infos) {\n if (!infos) {\n infos = getPathSegmentsInfo(path);\n }\n var i = 0;\n while ((distance - infos[i].length > 0) && i < (infos.length - 2)) {\n distance -= infos[i].length;\n i++;\n }\n // var distance = infos[infos.length - 1] * perc;\n var segInfo = infos[i], segPercent = distance / segInfo.length,\n command = segInfo.command, segment = path[i], info;\n\n switch (command) {\n case 'M':\n return { x: segInfo.x, y: segInfo.y, angle: 0 };\n case 'Z':\n case 'z':\n info = new fabric.Point(segInfo.x, segInfo.y).lerp(\n new fabric.Point(segInfo.destX, segInfo.destY),\n segPercent\n );\n info.angle = Math.atan2(segInfo.destY - segInfo.y, segInfo.destX - segInfo.x);\n return info;\n case 'L':\n info = new fabric.Point(segInfo.x, segInfo.y).lerp(\n new fabric.Point(segment[1], segment[2]),\n segPercent\n );\n info.angle = Math.atan2(segment[2] - segInfo.y, segment[1] - segInfo.x);\n return info;\n case 'C':\n return findPercentageForDistance(segInfo, distance);\n case 'Q':\n return findPercentageForDistance(segInfo, distance);\n }\n }\n\n /**\n *\n * @param {string} pathString\n * @return {(string|number)[][]} An array of SVG path commands\n * @example Usage\n * parsePath('M 3 4 Q 3 5 2 1 4 0 Q 9 12 2 1 4 0') === [\n * ['M', 3, 4],\n * ['Q', 3, 5, 2, 1, 4, 0],\n * ['Q', 9, 12, 2, 1, 4, 0],\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 *\n * Converts points to a smooth SVG path\n * @param {{ x: number,y: number }[]} points Array of points\n * @param {number} [correction] Apply a correction to the path (usually we use `width / 1000`). If value is undefined 0 is used as the correction value.\n * @return {(string|number)[][]} An array of SVG path commands\n */\n function getSmoothPathFromPoints(points, correction) {\n var path = [], i,\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 correction = correction || 0;\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 * correction, p1.y - multSignY * correction]);\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 * correction, p1.y + multSignY * correction]);\n return path;\n }\n /**\n * Transform a path by transforming each segment.\n * it has to be a simplified path or it won't work.\n * WARNING: this depends from pathOffset for correct operation\n * @param {Array} path fabricJS parsed and simplified path commands\n * @param {Array} transform matrix that represent the transformation\n * @param {Object} [pathOffset] the fabric.Path pathOffset\n * @param {Number} pathOffset.x\n * @param {Number} pathOffset.y\n * @returns {Array} the transformed path\n */\n function transformPath(path, transform, pathOffset) {\n if (pathOffset) {\n transform = fabric.util.multiplyTransformMatrices(\n transform,\n [1, 0, 0, 1, -pathOffset.x, -pathOffset.y]\n );\n }\n return path.map(function(pathSegment) {\n var newSegment = pathSegment.slice(0), point = {};\n for (var i = 1; i < pathSegment.length - 1; i += 2) {\n point.x = pathSegment[i];\n point.y = pathSegment[i + 1];\n point = fabric.util.transformPoint(point, transform);\n newSegment[i] = point.x;\n newSegment[i + 1] = point.y;\n }\n return newSegment;\n });\n }\n\n /**\n * Join path commands to go back to svg format\n * @param {Array} pathData fabricJS parsed path commands\n * @return {String} joined path 'M 0 0 L 20 30'\n */\n fabric.util.joinPath = function(pathData) {\n return pathData.map(function (segment) { return segment.join(' '); }).join(' ');\n };\n fabric.util.parsePath = parsePath;\n fabric.util.makePathSimpler = makePathSimpler;\n fabric.util.getSmoothPathFromPoints = getSmoothPathFromPoints;\n fabric.util.getPathSegmentsInfo = getPathSegmentsInfo;\n fabric.util.getBoundsOfCurve = getBoundsOfCurve;\n fabric.util.getPointOnPath = getPointOnPath;\n fabric.util.transformPath = transformPath;\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 * @param {Boolean} [deep] Whether to extend nested objects\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 * This method is mostly for internal use, and not intended for duplicating shapes in canvas. \n * @memberOf fabric.util.object\n * @param {Object} object Object to clone\n * @param {Boolean} [deep] Whether to clone nested objects\n * @return {Object}\n */\n\n //TODO: this function return an empty object if you try to clone null\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, '&')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .replace(//g, '>');\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.setProperty(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 var extend = fabric.util.object.extend,\n clone = fabric.util.object.clone;\n\n /**\n * @typedef {Object} AnimationOptions\n * Animation of a value or list of values.\n * When using lists, think of something like this:\n * fabric.util.animate({\n * startValue: [1, 2, 3],\n * endValue: [2, 4, 6],\n * onChange: function([a, b, c]) {\n * canvas.zoomToPoint({x: b, y: c}, a)\n * canvas.renderAll()\n * }\n * });\n * @example\n * @property {Function} [onChange] Callback; invoked on every value change\n * @property {Function} [onComplete] Callback; invoked when value change is completed\n * @example\n * // Note: startValue, endValue, and byValue must match the type\n * var animationOptions = { startValue: 0, endValue: 1, byValue: 0.25 }\n * var animationOptions = { startValue: [0, 1], endValue: [1, 2], byValue: [0.25, 0.25] }\n * @property {number | number[]} [startValue=0] Starting value\n * @property {number | number[]} [endValue=100] Ending value\n * @property {number | number[]} [byValue=100] Value to modify the property by\n * @property {Function} [easing] Easing function\n * @property {Number} [duration=500] Duration of change (in ms)\n * @property {Function} [abort] Additional function with logic. If returns true, animation aborts.\n *\n * @typedef {() => void} CancelFunction\n *\n * @typedef {Object} AnimationCurrentState\n * @property {number | number[]} currentValue value in range [`startValue`, `endValue`]\n * @property {number} completionRate value in range [0, 1]\n * @property {number} durationRate value in range [0, 1]\n *\n * @typedef {(AnimationOptions & AnimationCurrentState & { cancel: CancelFunction }} AnimationContext\n */\n\n /**\n * Array holding all running animations\n * @memberof fabric\n * @type {AnimationContext[]}\n */\n var RUNNING_ANIMATIONS = [];\n fabric.util.object.extend(RUNNING_ANIMATIONS, {\n\n /**\n * cancel all running animations at the next requestAnimFrame\n * @returns {AnimationContext[]}\n */\n cancelAll: function () {\n var animations = this.splice(0);\n animations.forEach(function (animation) {\n animation.cancel();\n });\n return animations;\n },\n\n /**\n * cancel all running animations attached to canvas at the next requestAnimFrame\n * @param {fabric.Canvas} canvas\n * @returns {AnimationContext[]}\n */\n cancelByCanvas: function (canvas) {\n if (!canvas) {\n return [];\n }\n var cancelled = this.filter(function (animation) {\n return typeof animation.target === 'object' && animation.target.canvas === canvas;\n });\n cancelled.forEach(function (animation) {\n animation.cancel();\n });\n return cancelled;\n },\n\n /**\n * cancel all running animations for target at the next requestAnimFrame\n * @param {*} target\n * @returns {AnimationContext[]}\n */\n cancelByTarget: function (target) {\n var cancelled = this.findAnimationsByTarget(target);\n cancelled.forEach(function (animation) {\n animation.cancel();\n });\n return cancelled;\n },\n\n /**\n *\n * @param {CancelFunction} cancelFunc the function returned by animate\n * @returns {number}\n */\n findAnimationIndex: function (cancelFunc) {\n return this.indexOf(this.findAnimation(cancelFunc));\n },\n\n /**\n *\n * @param {CancelFunction} cancelFunc the function returned by animate\n * @returns {AnimationContext | undefined} animation's options object\n */\n findAnimation: function (cancelFunc) {\n return this.find(function (animation) {\n return animation.cancel === cancelFunc;\n });\n },\n\n /**\n *\n * @param {*} target the object that is assigned to the target property of the animation context\n * @returns {AnimationContext[]} array of animation options object associated with target\n */\n findAnimationsByTarget: function (target) {\n if (!target) {\n return [];\n }\n return this.filter(function (animation) {\n return animation.target === target;\n });\n }\n });\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 {AnimationOptions} [options] Animation options\n * @example\n * // Note: startValue, endValue, and byValue must match the type\n * fabric.util.animate({ startValue: 0, endValue: 1, byValue: 0.25 })\n * fabric.util.animate({ startValue: [0, 1], endValue: [1, 2], byValue: [0.25, 0.25] })\n * @returns {CancelFunction} cancel function\n */\n function animate(options) {\n options || (options = {});\n var cancel = false,\n context,\n removeFromRegistry = function () {\n var index = fabric.runningAnimations.indexOf(context);\n return index > -1 && fabric.runningAnimations.splice(index, 1)[0];\n };\n\n context = extend(clone(options), {\n cancel: function () {\n cancel = true;\n return removeFromRegistry();\n },\n currentValue: 'startValue' in options ? options.startValue : 0,\n completionRate: 0,\n durationRate: 0\n });\n fabric.runningAnimations.push(context);\n\n requestAnimFrame(function(timestamp) {\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 isMany = 'startValue' in options ? options.startValue.length > 0 : false,\n startValue = 'startValue' in options ? options.startValue : 0,\n endValue = 'endValue' in options ? options.endValue : 100,\n byValue = options.byValue || (isMany ? startValue.map(function(value, i) {\n return endValue[i] - startValue[i];\n }) : endValue - startValue);\n\n options.onStart && options.onStart();\n\n (function tick(ticktime) {\n time = ticktime || +new Date();\n var currentTime = time > finish ? duration : (time - start),\n timePerc = currentTime / duration,\n current = isMany ? startValue.map(function(_value, i) {\n return easing(currentTime, startValue[i], byValue[i], duration);\n }) : easing(currentTime, startValue, byValue, duration),\n valuePerc = isMany ? Math.abs((current[0] - startValue[0]) / byValue[0])\n : Math.abs((current - startValue) / byValue);\n // update context\n context.currentValue = isMany ? current.slice() : current;\n context.completionRate = valuePerc;\n context.durationRate = timePerc;\n if (cancel) {\n return;\n }\n if (abort(current, valuePerc, timePerc)) {\n removeFromRegistry();\n return;\n }\n if (time > finish) {\n // update context\n context.currentValue = isMany ? endValue.slice() : endValue;\n context.completionRate = 1;\n context.durationRate = 1;\n // execute callbacks\n onChange(isMany ? endValue.slice() : endValue, 1, 1);\n onComplete(endValue, 1, 1);\n removeFromRegistry();\n return;\n }\n else {\n onChange(current, valuePerc, timePerc);\n requestAnimFrame(tick);\n }\n })(start);\n });\n\n return context.cancel;\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 fabric.runningAnimations = RUNNING_ANIMATIONS;\n})();\n\n\n(function() {\n // Calculate an in-between color. Returns a \"rgba()\" string.\n // Credit: Edwin Martin \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 * @returns {Function} abort function\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 return 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 Easing Equations by Robert Penner\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 = Array.isArray(value), 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');\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 xlinkAttribute = el.getAttribute('xlink:href') || el.getAttribute('href');\n\n if (xlinkAttribute === null) {\n return;\n }\n\n var xlink = xlinkAttribute.slice(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, attr,\n j,\n attrs,\n len,\n 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 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 && 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).slice(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 var styleContents = styles[i].textContent;\n\n // remove comments\n styleContents = styleContents.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n if (styleContents.trim() === '') {\n continue;\n }\n // recovers all the rule in this form `body { style code... }`\n // rules = styleContents.match(/[^{]*\\{[\\s\\S]*?\\}/g);\n rules = styleContents.split('}');\n // remove empty rules.\n rules = rules.filter(function(rule) { return rule.trim(); });\n // at this point we have hopefully an array of rules `body { style code... `\n // eslint-disable-next-line no-loop-func\n rules.forEach(function(rule) {\n\n var match = rule.split('{'),\n ruleObj = { }, declaration = match[1].trim(),\n propertyValuePairs = declaration.split(';').filter(function(pair) { return pair.trim(); });\n\n for (i = 0, len = propertyValuePairs.length; i < len; i++) {\n var pair = propertyValuePairs[i].split(':'),\n property = pair[0].trim(),\n value = pair[1].trim();\n ruleObj[property] = value;\n }\n rule = match[0].trim();\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 https://github.com/mjijackson\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 https://github.com/mjijackson\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 * Wrap an action handler with firing an event if the action is performed\n * @param {Function} actionHandler the function to wrap\n * @return {Function} a function with an action handler signature\n */\n function wrapWithFireEvent(eventName, actionHandler) {\n return function(eventData, transform, x, y) {\n var actionPerformed = actionHandler(eventData, transform, x, y);\n if (actionPerformed) {\n fireEvent(eventName, commonEventInfo(eventData, transform, x, y));\n }\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;\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 }\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 }\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 = wrapWithFireEvent('skewing', 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 = wrapWithFireEvent('skewing', 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 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;\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 return oldScaleX !== target.scaleX || oldScaleY !== target.scaleY;\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,\n newWidth = Math.abs(localPoint.x * multiplier / target.scaleX) - strokePadding;\n target.set('width', Math.max(newWidth, 0));\n return oldWidth !== newWidth;\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 = wrapWithFireEvent('rotating', wrapWithFixedAnchor(rotationWithSnapping));\n controls.scalingEqually = wrapWithFireEvent('scaling', wrapWithFixedAnchor( scaleObjectFromCorner));\n controls.scalingX = wrapWithFireEvent('scaling', wrapWithFixedAnchor(scaleObjectX));\n controls.scalingY = wrapWithFireEvent('scaling', wrapWithFixedAnchor(scaleObjectY));\n controls.scalingYOrSkewingX = scalingYOrSkewingX;\n controls.scalingXOrSkewingY = scalingXOrSkewingY;\n controls.changeWidth = wrapWithFireEvent('resizing', 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.wrapWithFireEvent = wrapWithFireEvent;\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 xSize = this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize,\n ySize = this.sizeY || styleOverride.cornerSize || fabricObject.cornerSize,\n transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ?\n styleOverride.transparentCorners : fabricObject.transparentCorners,\n methodName = transparentCorners ? 'stroke' : 'fill',\n stroke = !transparentCorners && (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor),\n myLeft = left,\n myTop = top, size;\n ctx.save();\n ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor;\n ctx.strokeStyle = styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor;\n // as soon as fabric react v5, remove ie11, use proper ellipse code.\n if (xSize > ySize) {\n size = xSize;\n ctx.scale(1.0, ySize / xSize);\n myTop = top * xSize / ySize;\n }\n else if (ySize > xSize) {\n size = ySize;\n ctx.scale(xSize / ySize, 1.0);\n myLeft = left * ySize / xSize;\n }\n else {\n size = xSize;\n }\n // this is still wrong\n ctx.lineWidth = 1;\n ctx.beginPath();\n ctx.arc(myLeft, myTop, 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 xSize = this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize,\n ySize = this.sizeY || 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 ), xSizeBy2 = xSize / 2, ySizeBy2 = ySize / 2;\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.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(-xSizeBy2, -ySizeBy2, xSize, ySize);\n ctx[methodName + 'Rect'](-xSizeBy2, -ySizeBy2, xSize, ySize);\n if (stroke) {\n ctx.strokeRect(-xSizeBy2, -ySizeBy2, xSize, ySize);\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 control 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 vertically. 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 * Sets the length of the control. If null, defaults to object's cornerSize.\n * Expects both sizeX and sizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n sizeX: null,\n\n /**\n * Sets the height of the control. If null, defaults to object's cornerSize.\n * Expects both sizeX and sizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n sizeY: null,\n\n /**\n * Sets the length of the touch area of the control. If null, defaults to object's touchCornerSize.\n * Expects both touchSizeX and touchSizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n touchSizeX: null,\n\n /**\n * Sets the height of the touch area of the control. If null, defaults to object's touchCornerSize.\n * Expects both touchSizeX and touchSizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n touchSizeY: null,\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 {Number} x x position of the cursor\n * @param {Number} y y position of the cursor\n * @return {Boolean} true if the action/event modified the object\n */\n actionHandler: function(/* eventData, transformData, x, y */) { },\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 {Number} x x position of the cursor\n * @param {Number} y y position of the cursor\n * @return {Boolean} true if the action/event modified the object\n */\n mouseDownHandler: function(/* eventData, transformData, x, y */) { },\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 {Number} x x position of the cursor\n * @param {Number} y y position of the cursor\n * @return {Boolean} true if the action/event modified the object\n */\n mouseUpHandler: function(/* eventData, transformData, x, y */) { },\n\n /**\n * Returns control actionHandler\n * @param {Event} eventData the native mouse event\n * @param {fabric.Object} fabricObject on which the control is displayed\n * @param {fabric.Control} control control for which the action handler is being asked\n * @return {Function} the action handler\n */\n getActionHandler: function(/* eventData, fabricObject, control */) {\n return this.actionHandler;\n },\n\n /**\n * Returns control mouseDown handler\n * @param {Event} eventData the native mouse event\n * @param {fabric.Object} fabricObject on which the control is displayed\n * @param {fabric.Control} control control for which the action handler is being asked\n * @return {Function} the action handler\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 {fabric.Object} fabricObject on which the control is displayed\n * @param {fabric.Control} control control for which the action handler is being asked\n * @return {Function} the action handler\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 * Returns the coords for this control based on object values.\n * @param {Number} objectAngle angle from the fabric object holding the control\n * @param {Number} objectCornerSize cornerSize from the fabric object holding the control (or touchCornerSize if\n * isTouch is true)\n * @param {Number} centerX x coordinate where the control center should be\n * @param {Number} centerY y coordinate where the control center should be\n * @param {boolean} isTouch true if touch corner, false if normal corner\n */\n calcCornerCoords: function(objectAngle, objectCornerSize, centerX, centerY, isTouch) {\n var cosHalfOffset,\n sinHalfOffset,\n cosHalfOffsetComp,\n sinHalfOffsetComp,\n xSize = (isTouch) ? this.touchSizeX : this.sizeX,\n ySize = (isTouch) ? this.touchSizeY : this.sizeY;\n if (xSize && ySize && xSize !== ySize) {\n // handle rectangular corners\n var controlTriangleAngle = Math.atan2(ySize, xSize);\n var cornerHypotenuse = Math.sqrt(xSize * xSize + ySize * ySize) / 2;\n var newTheta = controlTriangleAngle - fabric.util.degreesToRadians(objectAngle);\n var newThetaComp = Math.PI / 2 - controlTriangleAngle - fabric.util.degreesToRadians(objectAngle);\n cosHalfOffset = cornerHypotenuse * fabric.util.cos(newTheta);\n sinHalfOffset = cornerHypotenuse * fabric.util.sin(newTheta);\n // use complementary angle for two corners\n cosHalfOffsetComp = cornerHypotenuse * fabric.util.cos(newThetaComp);\n sinHalfOffsetComp = cornerHypotenuse * fabric.util.sin(newThetaComp);\n }\n else {\n // handle square corners\n // use default object corner size unless size is defined\n var cornerSize = (xSize && ySize) ? xSize : objectCornerSize;\n /* 0.7071067812 stands for sqrt(2)/2 */\n cornerHypotenuse = cornerSize * 0.7071067812;\n // complementary angles are equal since they're both 45 degrees\n var newTheta = fabric.util.degreesToRadians(45 - objectAngle);\n cosHalfOffset = cosHalfOffsetComp = cornerHypotenuse * fabric.util.cos(newTheta);\n sinHalfOffset = sinHalfOffsetComp = cornerHypotenuse * fabric.util.sin(newTheta);\n }\n\n return {\n tl: {\n x: centerX - sinHalfOffsetComp,\n y: centerY - cosHalfOffsetComp,\n },\n tr: {\n x: centerX + cosHalfOffset,\n y: centerY - sinHalfOffset,\n },\n bl: {\n x: centerX - cosHalfOffset,\n y: centerY + sinHalfOffset,\n },\n br: {\n x: centerX + sinHalfOffsetComp,\n y: centerY + cosHalfOffsetComp,\n },\n };\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' && this.gradientUnits !== 'percentage') {\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 '\\n'\n ];\n }\n else if (this.type === 'radial') {\n // svg radial gradient has just 1 radius. the biggest.\n markup = [\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 '\\n'\n );\n }\n\n markup.push((this.type === 'linear' ? '\\n' : '\\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 gradients\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 * \n * \n * \n * \n *\n * OR\n *\n * \n * \n * \n * \n *\n * OR\n *\n * \n * \n * \n * \n * \n *\n * OR\n *\n * \n * \n * \n * \n * \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 // element\n if (typeof this.source.src === 'string') {\n source = this.source.src;\n }\n // 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 '\\n' +\n '\\n' +\n '\\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: parseFloat(offsetsAndBlur[1], 10) || 0,\n offsetY: parseFloat(offsetsAndBlur[2], 10) || 0,\n blur: parseFloat(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 '\\n' +\n '\\t\\n' +\n '\\t\\n' +\n '\\t\\n' +\n '\\t\\n' +\n '\\t\\n' +\n '\\t\\t\\n' +\n '\\t\\t\\n' +\n '\\t\\n' +\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 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+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?(-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?(\\d+(?:\\.\\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 <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 (a Canvas 2D API transform matrix) which focuses the viewport\n * @type Array\n * @example Default transform\n * canvas.viewportTransform = [1, 0, 0, 1, 0, 0];\n * @example Scale by 70% and translate toward bottom-right by 50, without skewing\n * canvas.viewportTransform = [0.7, 0, 0, 0.7, 50, 50];\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 <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() ? Math.max(1, 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 Normal overlayImage with left/top = 0\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 overlayImage with different properties\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 Stretched overlayImage #1 - width/height correspond to canvas width/height\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 Stretched overlayImage #2 - width/height correspond to canvas width/height\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 overlayImage loaded from cross-origin\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 Normal backgroundImage with left/top = 0\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 backgroundImage with different properties\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 Stretched backgroundImage #1 - width/height correspond to canvas width/height\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 Stretched backgroundImage #2 - width/height correspond to canvas width/height\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 backgroundImage loaded from cross-origin\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 Normal overlayColor - color value\n * canvas.setOverlayColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));\n * @example fabric.Pattern used as overlayColor\n * canvas.setOverlayColor({\n * source: 'http://fabricjs.com/assets/escheresque_ste.png'\n * }, canvas.renderAll.bind(canvas));\n * @example fabric.Pattern used as overlayColor with repeat and offset\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 Normal backgroundColor - color value\n * canvas.setBackgroundColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));\n * @example fabric.Pattern used as backgroundColor\n * canvas.setBackgroundColor({\n * source: 'http://fabricjs.com/assets/escheresque_ste.png'\n * }, canvas.renderAll.bind(canvas));\n * @example fabric.Pattern used as backgroundColor with repeat and offset\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 occurred 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 this._originalCanvasStyle = this.lowerCanvasEl.style;\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(this.contextTop);\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 transformation of this canvas instance\n * @param {Array} vpt a Canvas 2D API transform matrix\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n setViewportTransform: function (vpt) {\n var activeObject = this._activeObject,\n backgroundObject = this.backgroundImage,\n overlayObject = this.overlayImage,\n 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 if (backgroundObject) {\n backgroundObject.setCoords(true);\n }\n if (overlayObject) {\n overlayObject.setCoords(true);\n }\n this.calcViewportBoundaries();\n this.renderOnAddRemove && this.requestRenderAll();\n return this;\n },\n\n /**\n * Sets zoom level of this canvas instance, the zoom centered around point\n * meaning that following zoom to point with the same point will have the visual\n * effect of the zoom originating from that point. The point won't move.\n * It has nothing to do with canvas center or visual center of the viewport.\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 <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.remove.apply(this, this.getObjects());\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 * @deprecated migrate to `getCenterPoint`\n */\n getCenter: function () {\n return {\n top: this.height / 2,\n left: this.width / 2\n };\n },\n\n /**\n * Returns coordinates of a center of canvas.\n * @return {fabric.Point} \n */\n getCenterPoint: function () {\n return new fabric.Point(this.width / 2, this.height / 2);\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.getCenterPoint().x, 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.getCenterPoint().y));\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.getCenterPoint();\n return this._centerObject(object, center);\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 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.getCenterPoint(),\n iVpt = invertTransform(this.viewportTransform);\n return transformPoint(center, 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 * Returns 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 && !clipPath.excludeFromExport) {\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, overlayImage = this.overlayImage,\n bgColor = this.backgroundColor, overlayColor = this.overlayColor;\n\n if (bgColor && bgColor.toObject) {\n if (!bgColor.excludeFromExport) {\n data.background = bgColor.toObject(propertiesToInclude);\n }\n }\n else if (bgColor) {\n data.background = bgColor;\n }\n\n if (overlayColor && overlayColor.toObject) {\n if (!overlayColor.excludeFromExport) {\n data.overlay = overlayColor.toObject(propertiesToInclude);\n }\n }\n else if (overlayColor) {\n data.overlay = overlayColor;\n }\n\n if (bgImage && !bgImage.excludeFromExport) {\n data.backgroundImage = this._toObject(bgImage, methodName, propertiesToInclude);\n }\n if (overlayImage && !overlayImage.excludeFromExport) {\n data.overlayImage = this._toObject(overlayImage, 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-coordinate 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 Normal SVG output\n * var svg = canvas.toSVG();\n * @example SVG output without preamble (without <?xml ../>)\n * var svg = canvas.toSVG({suppressPreamble: true});\n * @example SVG output with viewBox attribute\n * var svg = canvas.toSVG({\n * viewBox: {\n * x: 100,\n * y: 100,\n * width: 200,\n * height: 300\n * }\n * });\n * @example SVG output with different encoding (default: UTF-8)\n * var svg = canvas.toSVG({encoding: 'ISO-8859-1'});\n * @example Modify SVG output with reviver function\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('\\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('\\n');\n }\n this._setSVGBgOverlayColor(markup, 'overlay');\n this._setSVGBgOverlayImage(markup, 'overlayImage', reviver);\n\n markup.push('');\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 '\\n',\n '\\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 '\\n',\n 'Created with Fabric.js ', fabric.version, '\\n',\n '\\n',\n this.createSVGFontFacesMarkup(),\n this.createSVGRefElementsMarkup(),\n this.createSVGClipPathMarkup(options),\n '\\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 '\\n' +\n this.clipPath.toClipPathSVG(options.reviver) +\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 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\\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 '\\n'\n );\n }\n else {\n markup.push(\n '\\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 parameter, intersecting allows 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 parameter, intersecting allows 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 // restore canvas style\n this.lowerCanvasEl.classList.remove('lower-canvas');\n fabric.util.setStyle(this.lowerCanvasEl, this._originalCanvasStyle);\n delete this._originalCanvasStyle;\n // restore canvas size to original size in case retina scaling was applied\n this.lowerCanvasEl.setAttribute('width', this.width);\n this.lowerCanvasEl.setAttribute('height', this.height);\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 '#';\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 Object representation of canvas\n * this alias is provided because if you call JSON.stringify on an instance,\n * the toJSON object will be invoked if it exists.\n * Having a toJSON method means you can do JSON.stringify(myCanvas)\n * @function\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} JSON compatible object\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}\n * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo}\n * @example JSON without additional properties\n * var json = canvas.toJSON();\n * @example JSON with additional properties included\n * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY']);\n * @example JSON without default values\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 * Backwards incompatibility note: 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 * When `true`, the free drawing is limited to the whiteboard size. Default to false.\n * @type Boolean\n * @default false\n */\n\n limitedToCanvasSize: false,\n\n\n /**\n * Sets brush styles\n * @private\n * @param {CanvasRenderingContext2D} ctx\n */\n _setBrushStyles: function (ctx) {\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 ctx.setLineDash(this.strokeDashArray || []);\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 * Check is pointer is outside canvas boundaries\n * @param {Object} pointer\n * @private\n */\n _isOutSideCanvas: function(pointer) {\n return pointer.x < 0 || pointer.x > this.canvas.getWidth() || pointer.y < 0 || pointer.y > this.canvas.getHeight();\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 * Draws a straight line between last recorded point to current pointer\n * Used for `shift` functionality\n *\n * @type boolean\n * @default false\n */\n drawStraightLine: false,\n\n /**\n * The event modifier key that makes the brush draw a straight line.\n * If `null` or 'none' or any other string that is not a modifier key the feature is disabled.\n * @type {'altKey' | 'shiftKey' | 'ctrlKey' | 'none' | undefined | null}\n */\n straightLineKey: 'shiftKey',\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 needsFullRender: function () {\n return this.callSuper('needsFullRender') || this._hasStraightLine;\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 * Invoked 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.drawStraightLine = options.e[this.straightLineKey];\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 * Invoked on mouse move\n * @param {Object} pointer\n */\n onMouseMove: function(pointer, options) {\n if (!this.canvas._isMainEvent(options.e)) {\n return;\n }\n this.drawStraightLine = options.e[this.straightLineKey];\n if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\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.drawStraightLine = false;\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 if (this.drawStraightLine && this._points.length > 1) {\n this._hasStraightLine = true;\n this._points.pop();\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(this.canvas.contextTop);\n this._setShadow();\n this._hasStraightLine = false;\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 * @param {CanvasRenderingContext2D} [ctx]\n */\n _render: function(ctx) {\n var i, len,\n p1 = this._points[0],\n p2 = this._points[1];\n ctx = ctx || this.canvas.contextTop;\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|number)[][]} SVG path commands\n */\n convertPointsToSVGPath: function (points) {\n var correction = this.width / 1000;\n return fabric.util.getSmoothPathFromPoints(points, correction);\n },\n\n /**\n * @private\n * @param {(string|number)[][]} pathData SVG path commands\n * @returns {boolean}\n */\n _isEmptySVGPath: function (pathData) {\n var pathString = fabric.util.joinPath(pathData);\n return pathString === 'M 0 0 Q 0 0 0 0 L 0 0';\n },\n\n /**\n * Creates fabric.Path object to add on canvas\n * @param {(string|number)[][]} 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 points 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 - 1; 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 /**\n * Add the last point from the original line to the end of the array.\n * This ensures decimate doesn't delete the last point on the line, and ensures the line is > 1 point.\n */\n newPoints.push(points[l]);\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);\n if (this._isEmptySVGPath(pathData)) {\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.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\n return;\n }\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 if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\n return;\n }\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 * @param {CanvasRenderingContext2D} ctx\n */\n getPattern: function(ctx) {\n return ctx.createPattern(this.source || this.getPatternSrc(), 'repeat');\n },\n\n /**\n * Sets brush styles\n * @param {CanvasRenderingContext2D} ctx\n */\n _setBrushStyles: function(ctx) {\n this.callSuper('_setBrushStyles', ctx);\n ctx.strokeStyle = this.getPattern(ctx);\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 isTouchEvent = fabric.util.isTouchEvent;\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:before before drop event. same native event. This is added to handle edge cases\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 */\n fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ {\n\n /**\n * Constructor\n * @param {HTMLElement | String} el <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 * Backwards incompatibility note: 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 * Backwards incompatibility note: 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 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 * When the option is enabled, PointerEvent is used instead of MouseEvent.\n * @type Boolean\n * @default\n */\n enablePointerEvents: false,\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 this.hasLostContext = false;\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.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 determines 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 (Array.isArray(this.selectionKey)) {\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 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 control = target.controls[corner],\n actionHandler = (alreadySelected && corner) ?\n control.getActionHandler(e, target, control) : 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 selector = this._groupSelector,\n viewportStart = new fabric.Point(selector.ex, selector.ey),\n start = fabric.util.transformPoint(viewportStart, this.viewportTransform),\n viewportExtent = new fabric.Point(selector.ex + selector.left, selector.ey + selector.top),\n extent = fabric.util.transformPoint(viewportExtent, this.viewportTransform),\n minX = Math.min(start.x, extent.x),\n minY = Math.min(start.y, extent.y),\n maxX = Math.max(start.x, extent.x),\n maxY = Math.max(start.y, extent.y),\n strokeOffset = this.selectionLineWidth / 2;\n\n if (this.selectionColor) {\n ctx.fillStyle = this.selectionColor;\n ctx.fillRect(minX, minY, maxX - minX, maxY - minY);\n }\n\n if (!this.selectionLineWidth || !this.selectionBorderColor) {\n return;\n }\n ctx.lineWidth = this.selectionLineWidth;\n ctx.strokeStyle = this.selectionBorderColor;\n\n minX += strokeOffset;\n minY += strokeOffset;\n maxX -= strokeOffset;\n maxY -= strokeOffset;\n // selection border\n fabric.Object.prototype._setLineDash.call(this, ctx, this.selectionDashArray);\n ctx.strokeRect(minX, minY, maxX - minX, maxY - minY);\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 shouldLookForActive = (aObjects.length > 1 && !skipGroup) || aObjects.length === 1;\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 we hit the corner of an activeObject, let's return that.\n if (shouldLookForActive && activeObject._findTargetCorner(pointer, isTouch)) {\n return activeObject;\n }\n if (aObjects.length > 1 && !skipGroup && activeObject === this._searchPossibleTargets([activeObject], pointer)) {\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)\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 * Returns context of top canvas where interactions are drawn\n * @returns {CanvasRenderingContext2D}\n */\n getTopContext: function () {\n return this.contextTop;\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 <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 = [];\n oldObjects.forEach(function(oldObject) {\n if (objects.indexOf(oldObject) === -1) {\n somethingChanged = true;\n oldObject.fire('deselected', {\n e: e,\n target: oldObject\n });\n removed.push(oldObject);\n }\n });\n objects.forEach(function(object) {\n if (oldObjects.indexOf(object) === -1) {\n somethingChanged = true;\n object.fire('selected', {\n e: e,\n target: object\n });\n added.push(object);\n }\n });\n if (oldObjects.length > 0 && objects.length > 0) {\n somethingChanged && this.fire('selection:updated', {\n e: e,\n selected: added,\n deselected: removed,\n });\n }\n else if (objects.length > 0) {\n this.fire('selection:created', {\n e: e,\n selected: added,\n });\n }\n else if (oldObjects.length > 0) {\n this.fire('selection:cleared', {\n e: e,\n deselected: removed,\n });\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 * This is a private method for now.\n * This is supposed to be equivalent to setActiveObject but without firing\n * any event. There is commitment to have this stay this way.\n * This is the functional part of setActiveObject.\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 * This is a private method for now.\n * This is supposed to be equivalent to discardActiveObject but without firing\n * any events. There is commitment to have this stay this way.\n * This is the functional part of discardActiveObject.\n * @param {Event} [e] Event (passed along when firing \"object:deselected\")\n * @param {Object} object to set as active\n * @return {Boolean} true if the selection happened\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 fabric.util.addTransformToObject(instance, this._activeObject.calcOwnMatrix());\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._onDrop.bind(this);\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\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 * `drop:before` is a an event that allow you to schedule logic\n * before the `drop` event. Prefer `drop` event always, but if you need\n * to run some drop-disabling logic on an event, since there is no way\n * to handle event handlers ordering, use `drop:before`\n * @param {Event} e\n */\n _onDrop: function (e) {\n this._simpleEventHandler('drop:before', e);\n return this._simpleEventHandler('drop', 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 var corner, pointer;\n if (target) {\n corner = target._findTargetCorner(\n this.getPointer(e, true),\n fabric.util.isTouchEvent(e)\n );\n if (target.selectable && target !== this._activeObject && target.activeOn === 'up') {\n this.setActiveObject(target, e);\n shouldRender = true;\n }\n else {\n var control = target.controls[corner],\n mouseUpHandler = control && control.getMouseUpHandler(e, target, control);\n if (mouseUpHandler) {\n pointer = this.getPointer(e);\n mouseUpHandler(e, transform, pointer.x, pointer.y);\n }\n }\n target.isMoving = false;\n }\n // if we are ending up a transform on a different control or a new object\n // fire the original mouse up from the corner that started the transform\n if (transform && (transform.target !== target || transform.corner !== corner)) {\n var originalControl = transform.target && transform.target.controls[transform.corner],\n originalMouseUpHandler = originalControl && originalControl.getMouseUpHandler(e, target, control);\n pointer = pointer || this.getPointer(e);\n originalMouseUpHandler && originalMouseUpHandler(e, transform, pointer.x, pointer.y);\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 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 this._fire('modified', options);\n }\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: this._absolutePointer.x,\n ey: this._absolutePointer.y,\n top: 0,\n left: 0\n };\n }\n\n if (target) {\n var alreadySelected = target === this._activeObject;\n if (target.selectable && target.activeOn === 'down') {\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 this._setupCurrentTransform(e, target, alreadySelected);\n var control = target.controls[corner],\n pointer = this.getPointer(e),\n mouseDownHandler = control && control.getMouseDownHandler(e, target, control);\n if (mouseDownHandler) {\n mouseDownHandler(e, this._currentTransform, pointer.x, pointer.y);\n }\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._absolutePointer;\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.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 transform.target.isMoving = true;\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, true)) ||\n currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2, true) ||\n (allowIntersect && currentObject.containsPoint(selectionX1Y1, null, true)) ||\n (allowIntersect && currentObject.containsPoint(selectionX2Y2, null, true))\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 Generate jpeg dataURL with lower quality\n * var dataURL = canvas.toDataURL({\n * format: 'jpeg',\n * quality: 0.8\n * });\n * @example Generate cropped png dataURL (clipping of canvas)\n * var dataURL = canvas.toDataURL({\n * format: 'png',\n * left: 100,\n * top: 100,\n * width: 200,\n * height: 200\n * });\n * @example Generate double scaled png dataURL\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 loadFromJSON\n * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));\n * @example loadFromJSON with reviver\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 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 * Backwards incompatibility note: 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 * Backwards incompatibility note: 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 * Backwards incompatibility note: 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 \"bevel\", \"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 thickness\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 * this Property does not work on Text classes or drawing call that uses strokeText,fillText methods\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 * When 'down', object is set to active on mousedown/touchstart\n * When 'up', object is set to active on mouseup/touchend\n * Experimental. Let's see if this breaks anything before supporting officially\n * @private\n * since 4.4.0\n * @type String\n * @default 'down'\n */\n activeOn: 'down',\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 (this instanceof fabric.Text && this.path) {\n shouldRedraw = true;\n shouldResizeCanvas = true;\n additionalWidth += this.getHeightOfLine(0) * this.zoomX;\n additionalHeight += this.getHeightOfLine(0) * this.zoomY;\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 && !this.clipPath.excludeFromExport) {\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 // basically a check for [] === []\n if (Array.isArray(object[prop]) && Array.isArray(prototype[prop])\n && 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 '#';\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 // if the object is a top level one, on the canvas, we go for simple aritmetic\n // otherwise the complex method with angles will return approximations and decimals\n // and will likely kill the cache when not needed\n // https://github.com/fabricjs/fabric.js/issues/7157\n if (!this.group) {\n return {\n scaleX: this.scaleX,\n scaleY: this.scaleY,\n };\n }\n // if we are inside a group total zoom calculation is complex, we defer to generic matrices\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 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 || !this._cacheContext) {\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._cacheContext = 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 approximation 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 approximation 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 * @param {fabric.Object} clipPath\n */\n drawClipPathOnCache: function(ctx, clipPath) {\n ctx.save();\n // DEBUG: uncomment this line, comment the following\n // ctx.globalAlpha = 0.4\n if (clipPath.inverted) {\n ctx.globalCompositeOperation = 'destination-out';\n }\n else {\n ctx.globalCompositeOperation = 'destination-in';\n }\n //ctx.scale(1 / 2, 1 / 2);\n if (clipPath.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 clipPath.transform(ctx);\n ctx.scale(1 / clipPath.zoomX, 1 / clipPath.zoomY);\n ctx.drawImage(clipPath._cacheCanvas, -clipPath.cacheTranslationX, -clipPath.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 }\n this._render(ctx);\n this._drawClipPath(ctx, this.clipPath);\n this.fill = originalFill;\n this.stroke = originalStroke;\n },\n\n /**\n * Prepare clipPath state and cache and draw it on instance's cache\n * @param {CanvasRenderingContext2D} ctx\n * @param {fabric.Object} clipPath\n */\n _drawClipPath: function (ctx, clipPath) {\n if (!clipPath) { return; }\n // needed to setup a couple of variables\n // path canvas gets overridden with this one.\n // TODO find a better solution?\n clipPath.canvas = this.canvas;\n clipPath.shouldCache();\n clipPath._transformDone = true;\n clipPath.renderCache({ forClipping: true });\n this.drawClipPathOnCache(ctx, clipPath);\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 && this._cacheContext && !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 && this._cacheContext && !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 var stroke = decl.stroke;\n if (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 if (stroke.toLive) {\n if (stroke.gradientUnits === 'percentage' || stroke.gradientTransform || stroke.patternTransform) {\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, stroke);\n }\n else {\n // is a simple gradient or pattern\n ctx.strokeStyle = stroke.toLive(ctx, this);\n this._applyPatternGradientTransform(ctx, stroke);\n }\n }\n else {\n // is a color\n ctx.strokeStyle = decl.stroke;\n }\n }\n },\n\n _setFillStyles: function(ctx, decl) {\n var fill = decl.fill;\n if (fill) {\n if (fill.toLive) {\n ctx.fillStyle = fill.toLive(ctx, this);\n this._applyPatternGradientTransform(ctx, decl.fill);\n }\n else {\n ctx.fillStyle = fill;\n }\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 */\n _setLineDash: function(ctx, dashArray) {\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 ctx.setLineDash(dashArray);\n },\n\n /**\n * Renders controls and borders for the object\n * the context here is not transformed\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 (this.flipX) {\n options.angle -= 180;\n }\n ctx.rotate(degreesToRadians(this.group ? options.angle : this.angle));\n if (styleOverride.forActiveSelection || this.group) {\n drawBorders && this.drawBordersInGroup(ctx, options, styleOverride);\n }\n else {\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._setFillStyles(ctx, this);\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);\n this._setStrokeStyles(ctx, this);\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 * makes use of toCanvasElement.\n * Once this method was based on toDataUrl and loadImage, so it also had a quality\n * and format option. toCanvasElement is faster and produce no loss of quality.\n * If you need to get a real Jpeg or Png from an object, using toDataURL is the right way to do it.\n * toCanvasElement and then toBlob from the obtained canvas is also a good option.\n * This method is sync now, but still support the callback because we did not want to break.\n * When fabricJS 5.0 will be planned, this will probably be changed to not have a callback.\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 {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 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 arguments.length > 1 ? Array.from(arguments).includes(this.type) : 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 * cancel instance's running animations\n * override if necessary to dispose artifacts such as `clipPath`\n */\n dispose: function () {\n if (fabric.runningAnimations) {\n fabric.runningAnimations.cancelByTarget(this);\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 /**\n * Defines which properties should be enlivened from the object passed to {@link fabric.Object._fromObject}\n * @static\n * @memberOf fabric.Object\n * @constant\n * @type string[]\n */\n fabric.Object.ENLIVEN_PROPS = ['clipPath'];\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.enlivenObjectEnlivables(object, object, function () {\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.\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 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 and controls position coordinates based on current angle, width and height, left and top.\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/fabricjs/fabric.js/wiki/When-to-call-setCoords} and {@link http://fabricjs.com/fabric-gotchas}\n *\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 * @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, 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 dimensions = this._getNonTransformedDimensions();\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\\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 = '\\n' +\n clipPath.toClipPathSVG(reviver) +\n '\\n';\n }\n if (absoluteClipPath) {\n markup.push(\n '\\n'\n );\n }\n markup.push(\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('\\n');\n absoluteClipPath && markup.push('\\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\n for (var control in coords) {\n var controlObject = this.controls[control];\n coords[control].corner = controlObject.calcCornerCoords(\n this.angle, this.cornerSize, coords[control].x, coords[control].y, false);\n coords[control].touchCorner = controlObject.calcCornerCoords(\n this.angle, this.touchCornerSize, coords[control].x, coords[control].y, true);\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);\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);\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 var retinaScaling = this.canvas.getRetinaScaling(), matrix, p;\n ctx.setTransform(retinaScaling, 0, 0, retinaScaling, 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);\n this.setCoords();\n if (this.group) {\n // fabricJS does not really support drawing controls inside groups,\n // this piece of code here helps having at least the control in places.\n // If an application needs to show some objects as selected because of some UI state\n // can still call Object._renderControls() on any object they desire, independently of groups.\n // using no padding, circular controls and hiding the rotating cursor is higly suggested,\n matrix = this.group.calcTransformMatrix();\n }\n this.forEachControl(function(control, key, fabricObject) {\n p = fabricObject.oCoords[key];\n if (control.getVisibility(fabricObject, key)) {\n if (matrix) {\n p = fabric.util.transformPoint(p, matrix);\n }\n control.render(ctx, p.x, p.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.AnimationContext} context\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 return fabric.util.animate({\n target: this,\n startValue: object.left,\n endValue: this.getCenterPoint().x,\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\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.AnimationContext} context\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 return fabric.util.animate({\n target: this,\n startValue: object.top,\n endValue: this.getCenterPoint().y,\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\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.AnimationContext} context\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 return fabric.util.animate({\n target: this,\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});\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 * @return {fabric.AnimationContext | fabric.AnimationContext[]} animation context (or an array if passed multiple properties)\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, out = [];\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 out.push(this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks));\n }\n return out;\n }\n else {\n return this._animate.apply(this, arguments);\n }\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 target: this,\n startValue: options.from,\n endValue: to,\n byValue: options.by,\n easing: options.easing,\n duration: options.duration,\n abort: options.abort && function(value, valueProgress, timeProgress) {\n return options.abort.call(_this, value, valueProgress, timeProgress);\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 return fabric.util.animateColor(_options.startValue, _options.endValue, _options.duration, _options);\n }\n else {\n return 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\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\n var p = this.calcLinePoints();\n ctx.moveTo(p.x1, p.y1);\n ctx.lineTo(p.x2, p.y2);\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 * 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 * @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 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 '\\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 degreesToRadians = fabric.util.degreesToRadians;\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 * degrees of start of the circle.\n * probably will change to degrees in next major version\n * @type Number 0 - 359\n * @default 0\n */\n startAngle: 0,\n\n /**\n * End angle of the circle\n * probably will change to degrees in next major version\n * @type Number 1 - 360\n * @default 360\n */\n endAngle: 360,\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) % 360;\n\n if (angle === 0) {\n svgString = [\n '\\n'\n ];\n }\n else {\n var start = degreesToRadians(this.startAngle),\n end = degreesToRadians(this.endAngle),\n radius = this.radius,\n startX = fabric.util.cos(start) * radius,\n startY = fabric.util.sin(start) * radius,\n endX = fabric.util.cos(end) * radius,\n endY = fabric.util.sin(end) * radius,\n largeFlag = angle > 180 ? '1' : '0';\n svgString = [\n '\\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 degreesToRadians(this.startAngle),\n degreesToRadians(this.endAngle),\n 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\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 {void}\n */\n fabric.Circle.fromObject = function(object, callback) {\n 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 /* _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 ''\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 '\\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 {void}\n */\n fabric.Ellipse.fromObject = function(object, callback) {\n 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 * 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 '\\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 projectStrokeOnPoints = fabric.util.projectStrokeOnPoints;\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 /**\n * WARNING: Feature in progress\n * Calculate the exact bounding box taking in account strokeWidth on acute angles\n * this will be turned to true by default on fabric 6.0\n * maybe will be left in as an optimization since calculations may be slow\n * @deprecated\n * @type Boolean\n * @default false\n */\n exactBoundingBox: false,\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 /**\n * @private\n */\n _projectStrokeOnPoints: function () {\n return projectStrokeOnPoints(this.points, this, true);\n },\n\n _setPositionDimensions: function(options) {\n var calcDim = this._calcDimensions(options), correctLeftTop,\n correctSize = this.exactBoundingBox ? this.strokeWidth : 0;\n this.width = calcDim.width - correctSize;\n this.height = calcDim.height - correctSize;\n if (!options.fromSVG) {\n correctLeftTop = this.translateToGivenOrigin(\n {\n // this looks bad, but is one way to keep it optional for now.\n x: calcDim.left - this.strokeWidth / 2 + correctSize / 2,\n y: calcDim.top - this.strokeWidth / 2 + correctSize / 2\n },\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 + correctSize / 2,\n y: calcDim.top + this.height / 2 + correctSize / 2\n };\n },\n\n /**\n * Calculate the polygon min and max point from points array,\n * returning an object with left, top, width, 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.exactBoundingBox ? this._projectStrokeOnPoints() : 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 * 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 projectStrokeOnPoints = fabric.util.projectStrokeOnPoints;\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 */\n _projectStrokeOnPoints: function () {\n return projectStrokeOnPoints(this.points, this);\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 ctx.closePath();\n this._renderPaintInOrder(ctx);\n },\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 * @return {void}\n */\n fabric.Polygon.fromObject = function(object, callback) {\n 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 clone = fabric.util.object.clone,\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 = clone(options || {});\n delete options.path;\n this.callSuper('initialize', options);\n this._setPath(path || [], options);\n },\n\n /**\n * @private\n * @param {Array|String} path Path data (sequence of coordinates and corresponding \"command\" tokens)\n * @param {Object} [options] Options object\n */\n _setPath: function (path, options) {\n this.path = fabric.util.makePathSimpler(\n Array.isArray(path) ? path : fabric.util.parsePath(path)\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, // 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 '#';\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 = fabric.util.joinPath(this.path);\n return [\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 if (object.clipPath) {\n fabric.util.enlivenObjects([object.clipPath], function(elivenedObjects) {\n path.clipPath = elivenedObjects[0];\n callback && callback(path);\n });\n }\n else {\n callback && callback(path);\n }\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 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 '#';\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 var nested = !!this.group;\n this._restoreObjectsState();\n fabric.util.resetObjectTransform(this);\n if (object) {\n if (nested) {\n // if this group is inside another group, we need to pre transform the object\n fabric.util.removeTransformFromObject(object, this.group.calcTransformMatrix());\n }\n this._objects.push(object);\n object.group = this;\n object._set('canvas', this.canvas);\n }\n this._calcBounds();\n this._updateObjectsCoords();\n this.dirty = true;\n if (nested) {\n this.group.addWithUpdate();\n }\n else {\n this.setCoords();\n }\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\n .filter(function (obj) {\n return !obj.excludeFromExport;\n })\n .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, this.clipPath);\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 * Restores original state of each of group objects (original state is that which was before group was created).\n * if the nested boolean is true, the original state will be restored just for the\n * first group and not for all the group chain\n * @private\n * @param {Boolean} nested tell the function to restore object state up to the parent group and not more\n * @return {fabric.Group} thisArg\n * @chainable\n */\n _restoreObjectsState: function() {\n var groupMatrix = this.calcOwnMatrix();\n this._objects.forEach(function(object) {\n // instead of using _this = this;\n fabric.util.addTransformToObject(object, groupMatrix);\n delete object.group;\n object.setCoords();\n });\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 dispose: function () {\n this.callSuper('dispose');\n this.forEachObject(function (object) {\n object.dispose && object.dispose();\n });\n this._objects = [];\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, coords,\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 coords = o.calcACoords();\n for (j = 0; j < jLen; j++) {\n prop = props[j];\n aX.push(coords[prop].x);\n aY.push(coords[prop].y);\n }\n o.aCoords = coords;\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 = ['\\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('\\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 var clipPath = options.clipPath;\n delete options.clipPath;\n group.set(options);\n if (clipPath) {\n fabric.util.enlivenObjects([clipPath], function(elivenedObjects) {\n group.clipPath = elivenedObjects[0];\n callback && callback(group);\n });\n }\n else {\n callback && callback(group);\n }\n });\n return;\n }\n fabric.util.enlivenObjects(objects, function (enlivenedObjects) {\n fabric.util.enlivenObjectEnlivables(object, options, function () {\n callback && callback(new fabric.Group(enlivenedObjects, options, true));\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 '#';\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 * 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: fabric.Object.prototype.cacheProperties.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 * Image can be initialized with any canvas drawable or a string.\n * The string should be a url and will be loaded as an image.\n * Canvas and Image element work out of the box, while videos require extra code to work.\n * Please check video element events for seeking.\n * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | 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 filters\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.callSuper('dispose');\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 * 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,height.\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 '\\n',\n '\\t\\n',\n '\\n'\n );\n clipPath = ' clip-path=\"url(#imageCrop_' + clipPathId + ')\" ';\n }\n if (!this.imageSmoothing) {\n imageRendering = '\" image-rendering=\"optimizeSpeed';\n }\n imageMarkup.push('\\t 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 '>\\n');\n\n if (this.stroke || this.strokeDashArray) {\n var origFill = this.fill;\n this.fill = null;\n strokeSvg = [\n '\\t\\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 '#';\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 / scaleY - 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.enlivenObjectEnlivables(object, object, function () {\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 occurred 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 return this.rotate(this._getAngleValueForStraighten());\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 */\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 return fabric.util.animate({\n target: this,\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});\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 */\n fxStraightenObject: function (object) {\n return object.fxStraighten({\n onChange: this.requestRenderAllBound\n });\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 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 * 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 texture 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 * @param {Number} filterType gl.NEAREST or gl.LINEAR usually, webgl numeri constants\n * @returns {WebGLTexture}\n */\n createTexture: function(gl, width, height, textureImageSource, filterType) {\n var texture = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filterType || gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filterType || 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 version ( 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 Kodachrome filter\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, mainly for non webgl scenario\n * to save some calculation\n * @type Boolean\n * @default true\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 html5rocks article\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 Sharpen filter\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 Blur filter\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 Emboss filter\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 Emboss filter with opaqueness\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 * @type String\n * @default\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 * @type String\n * @default\n **/\n mode: 'multiply',\n\n /**\n * alpha value. represent the strength of the blend color operation.\n * @type Number\n * @default\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\", \"mask\")\n * @type String\n * @default\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: 1\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 /**\n * Saturation value, from -1 to 1.\n * Increases/decreases the color saturation.\n * A value of 0 has no effect.\n * \n * @param {Number} saturation\n * @default\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 * Vibrance filter class\n * @class fabric.Image.filters.Vibrance\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Vibrance#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Vibrance({\n * vibrance: 1\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\n filters.Vibrance = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Vibrance.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Vibrance',\n\n fragmentSource: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uVibrance;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n 'float max = max(color.r, max(color.g, color.b));\\n' +\n 'float avg = (color.r + color.g + color.b) / 3.0;\\n' +\n 'float amt = (abs(max - avg) * 2.0) * uVibrance;\\n' +\n 'color.r += max != color.r ? (max - color.r) * amt : 0.00;\\n' +\n 'color.g += max != color.g ? (max - color.g) * amt : 0.00;\\n' +\n 'color.b += max != color.b ? (max - color.b) * amt : 0.00;\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n\n /**\n * Vibrance value, from -1 to 1.\n * Increases/decreases the saturation of more muted colors with less effect on saturated colors.\n * A value of 0 has no effect.\n * \n * @param {Number} vibrance\n * @default\n */\n vibrance: 0,\n\n mainParameter: 'vibrance',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Vibrance.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.vibrance=0] Vibrance value for the image (between -1 and 1)\n */\n\n /**\n * Apply the Vibrance 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.vibrance === 0) {\n return;\n }\n var imageData = options.imageData,\n data = imageData.data, len = data.length,\n adjust = -this.vibrance, i, max, avg, amt;\n\n for (i = 0; i < len; i += 4) {\n max = Math.max(data[i], data[i + 1], data[i + 2]);\n avg = (data[i] + data[i + 1] + data[i + 2]) / 3;\n amt = ((Math.abs(max - avg) * 2 / 255) * adjust);\n data[i] += max !== data[i] ? (max - data[i]) * amt : 0;\n data[i + 1] += max !== data[i + 1] ? (max - data[i + 1]) * amt : 0;\n data[i + 2] += max !== data[i + 2] ? (max - data[i + 2]) * amt : 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 uVibrance: gl.getUniformLocation(program, 'uVibrance'),\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.uVibrance, -this.vibrance);\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.Vibrance} Instance of fabric.Image.filters.Vibrance\n */\n fabric.Image.filters.Vibrance.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 between 0 and 1.\n * @type Number\n * @default\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 var additionalProps =\n ('fontFamily fontWeight fontSize text underline overline linethrough' +\n ' textAlign fontStyle lineHeight textBackgroundColor charSpacing styles' +\n ' direction path pathStartOffset pathSide pathAlign').split(' ');\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 'path',\n 'pathStartOffset',\n 'pathSide',\n 'pathAlign'\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(additionalProps),\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(additionalProps),\n\n /**\n * When defined, an object is rendered via stroke and this property specifies its color.\n * Backwards incompatibility note: 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 * Backwards incompatibility note: This property was named \"textShadow\" (String) until v1.2.11\n * @type fabric.Shadow\n * @default\n */\n shadow: null,\n\n /**\n * fabric.Path that the text should follow.\n * since 4.6.0 the path will be drawn automatically.\n * if you want to make the path visible, give it a stroke and strokeWidth or fill value\n * if you want it to be hidden, assign visible = false to the path.\n * This feature is in BETA, and SVG import/export is not yet supported.\n * @type fabric.Path\n * @example\n * var textPath = new fabric.Text('Text on a path', {\n * top: 150,\n * left: 150,\n * textAlign: 'center',\n * charSpacing: -50,\n * path: new fabric.Path('M 0 0 C 50 -100 150 -100 200 0', {\n * strokeWidth: 1,\n * visible: false\n * }),\n * pathSide: 'left',\n * pathStartOffset: 0\n * });\n * @default\n */\n path: null,\n\n /**\n * Offset amount for text path starting position\n * Only used when text has a path\n * @type Number\n * @default\n */\n pathStartOffset: 0,\n\n /**\n * Which side of the path the text should be drawn on.\n * Only used when text has a path\n * @type {String} 'left|right'\n * @default\n */\n pathSide: 'left',\n\n /**\n * How text is aligned to the path. This property determines\n * the perpendicular position of each character relative to the path.\n * (one of \"baseline\", \"center\", \"ascender\", \"descender\")\n * This feature is in BETA, and its behavior may change\n * @type String\n * @default\n */\n pathAlign: 'baseline',\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 - character 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 avoid creating a canvas for every\n * text object created.\n * @type {CanvasRenderingContext2D}\n * @default\n */\n _measuringContext: null,\n\n /**\n * Baseline shift, styles only, keep at 0 for the main text object\n * @type {Number}\n * @default\n */\n deltaY: 0,\n\n /**\n * WARNING: EXPERIMENTAL. NOT SUPPORTED YET\n * determine the direction of the text.\n * This has to be set manually together with textAlign and originX for proper\n * experience.\n * some interesting link for the future\n * https://www.w3.org/International/questions/qa-bidi-unicode-controls\n * @since 4.5.0\n * @type {String} 'ltr|rtl'\n * @default\n */\n direction: 'ltr',\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 if (this.path) {\n this.setPathInfo();\n }\n this.__skipDimension = false;\n this.initDimensions();\n this.setCoords();\n this.setupState({ propertySet: '_dimensionAffectingProps' });\n },\n\n /**\n * If text has a path, it will add the extra information needed\n * for path and text calculations\n * @return {fabric.Text} thisArg\n */\n setPathInfo: function() {\n var path = this.path;\n if (path) {\n path.segmentsInfo = fabric.util.getPathSegmentsInfo(path.path);\n }\n },\n\n /**\n * Return a context for measurement of text string.\n * if created it gets stored for reuse\n * this is for internal use, please do not use it\n * @private\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 if (this.path) {\n this.width = this.path.width;\n this.height = this.path.height;\n }\n else {\n this.width = this.calcTextWidth() || this.cursorWidth || this.MIN_TEXT_WIDTH;\n this.height = this.calcTextHeight();\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 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 '#';\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 var path = this.path;\n path && !path.isNotVisible() && path._render(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 = 'alphabetical';\n if (this.path) {\n switch (this.pathAlign) {\n case 'center':\n ctx.textBaseline = 'middle';\n break;\n case 'ascender':\n ctx.textBaseline = 'top';\n break;\n case 'descender':\n ctx.textBaseline = 'bottom';\n break;\n }\n }\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 heightOfLine,\n lineLeftOffset, originalFill = ctx.fillStyle,\n line, lastColor,\n leftOffset = this._getLeftOffset(),\n lineTopOffset = this._getTopOffset(),\n boxStart = 0, boxWidth = 0, charBox, currentColor, path = this.path,\n drawStart;\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 (path) {\n ctx.save();\n ctx.translate(charBox.renderLeft, charBox.renderTop);\n ctx.rotate(charBox.angle);\n ctx.fillStyle = currentColor;\n currentColor && ctx.fillRect(\n -charBox.width / 2,\n -heightOfLine / this.lineHeight * (1 - this._fontSizeFraction),\n charBox.width,\n heightOfLine / this.lineHeight\n );\n ctx.restore();\n }\n else if (currentColor !== lastColor) {\n drawStart = leftOffset + lineLeftOffset + boxStart;\n if (this.direction === 'rtl') {\n drawStart = this.width - drawStart - boxWidth;\n }\n ctx.fillStyle = lastColor;\n lastColor && ctx.fillRect(\n drawStart,\n 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 && !path) {\n drawStart = leftOffset + lineLeftOffset + boxStart;\n if (this.direction === 'rtl') {\n drawStart = this.width - drawStart - boxWidth;\n }\n ctx.fillStyle = currentColor;\n ctx.fillRect(\n drawStart,\n 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 * 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 positionInPath = 0, startingPoint, totalPathLength, path = this.path,\n reverse = this.pathSide === 'right';\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 if (path) {\n totalPathLength = path.segmentsInfo[path.segmentsInfo.length - 1].length;\n startingPoint = fabric.util.getPointOnPath(path.path, 0, path.segmentsInfo);\n startingPoint.x += path.pathOffset.x;\n startingPoint.y += path.pathOffset.y;\n switch (this.textAlign) {\n case 'left':\n positionInPath = reverse ? (totalPathLength - width) : 0;\n break;\n case 'center':\n positionInPath = (totalPathLength - width) / 2;\n break;\n case 'right':\n positionInPath = reverse ? 0 : (totalPathLength - width);\n break;\n //todo - add support for justify\n }\n positionInPath += this.pathStartOffset * (reverse ? -1 : 1);\n for (i = reverse ? line.length - 1 : 0;\n reverse ? i >= 0 : i < line.length;\n reverse ? i-- : i++) {\n graphemeInfo = lineBounds[i];\n if (positionInPath > totalPathLength) {\n positionInPath %= totalPathLength;\n }\n else if (positionInPath < 0) {\n positionInPath += totalPathLength;\n }\n // it would probably much faster to send all the grapheme position for a line\n // and calculate path position/angle at once.\n this._setGraphemeOnPath(positionInPath, graphemeInfo, startingPoint);\n positionInPath += graphemeInfo.kernedWidth;\n }\n }\n return { width: width, numOfSpaces: numOfSpaces };\n },\n\n /**\n * Calculate the angle and the left,top position of the char that follow a path.\n * It appends it to graphemeInfo to be reused later at rendering\n * @private\n * @param {Number} positionInPath to be measured\n * @param {Object} graphemeInfo current grapheme box information\n * @param {Object} startingPoint position of the point\n */\n _setGraphemeOnPath: function(positionInPath, graphemeInfo, startingPoint) {\n var centerPosition = positionInPath + graphemeInfo.kernedWidth / 2,\n path = this.path;\n\n // we are at currentPositionOnPath. we want to know what point on the path is.\n var info = fabric.util.getPointOnPath(path.path, centerPosition, path.segmentsInfo);\n graphemeInfo.renderLeft = info.x - startingPoint.x;\n graphemeInfo.renderTop = info.y - startingPoint.y;\n graphemeInfo.angle = info.angle + (this.pathSide === 'right' ? Math.PI : 0);\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.direction === 'ltr' ? -this.width / 2 : 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 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,\n top + lineHeights + maxHeight,\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 path = this.path,\n shortCut = !isJustify && this.charSpacing === 0 && this.isEmptyStyles(lineIndex) && !path,\n isLtr = this.direction === 'ltr', sign = this.direction === 'ltr' ? 1 : -1,\n drawingLeft, currentDirection = ctx.canvas.getAttribute('dir');\n ctx.save();\n if (currentDirection !== this.direction) {\n ctx.canvas.setAttribute('dir', isLtr ? 'ltr' : 'rtl');\n ctx.direction = isLtr ? 'ltr' : 'rtl';\n ctx.textAlign = isLtr ? 'left' : 'right';\n }\n top -= lineHeight * this._fontSizeFraction / this.lineHeight;\n if (shortCut) {\n // render all the line in one pass without checking\n // drawingLeft = isLtr ? left : left - this.getLineWidth(lineIndex);\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 || path;\n charsToRender += line[i];\n charBox = this.__charBounds[lineIndex][i];\n if (boxWidth === 0) {\n left += sign * (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 = fabric.util.hasStyleChanged(actualStyle, nextStyle, false);\n }\n if (timeToRender) {\n if (path) {\n ctx.save();\n ctx.translate(charBox.renderLeft, charBox.renderTop);\n ctx.rotate(charBox.angle);\n this._renderChar(method, ctx, lineIndex, i, charsToRender, -boxWidth / 2, 0, lineHeight);\n ctx.restore();\n }\n else {\n drawingLeft = left;\n this._renderChar(method, ctx, lineIndex, i, charsToRender, drawingLeft, top, lineHeight);\n }\n charsToRender = '';\n actualStyle = nextStyle;\n left += sign * boxWidth;\n boxWidth = 0;\n }\n }\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 drawbacks: is slow, is in low resolution, needs a patch for when the size\n * is limited.\n * @private\n * @param {fabric.Gradient} filler a fabric gradient instance\n * @return {CanvasPattern} a pattern to use as fill/stroke style\n */\n _applyPatternGradientTransformText: function(filler) {\n var pCanvas = fabric.util.createCanvasElement(), pCtx,\n // TODO: verify compatibility with strokeUniform\n width = this.width + this.strokeWidth, height = this.height + this.strokeWidth;\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.fillStyle = filler.toLive(pCtx);\n this._applyPatternGradientTransform(pCtx, filler);\n pCtx.fill();\n return pCtx.createPattern(pCanvas, 'no-repeat');\n },\n\n handleFiller: function(ctx, property, filler) {\n var offsetX, offsetY;\n if (filler.toLive) {\n if (filler.gradientUnits === 'percentage' || filler.gradientTransform || filler.patternTransform) {\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 offsetX = -this.width / 2;\n offsetY = -this.height / 2;\n ctx.translate(offsetX, offsetY);\n ctx[property] = this._applyPatternGradientTransformText(filler);\n return { offsetX: offsetX, offsetY: offsetY };\n }\n else {\n // is a simple gradient or pattern\n ctx[property] = filler.toLive(ctx, this);\n return this._applyPatternGradientTransform(ctx, filler);\n }\n }\n else {\n // is a color\n ctx[property] = filler;\n }\n return { offsetX: 0, offsetY: 0 };\n },\n\n _setStrokeStyles: function(ctx, decl) {\n ctx.lineWidth = decl.strokeWidth;\n ctx.lineCap = this.strokeLineCap;\n ctx.lineDashOffset = this.strokeDashOffset;\n ctx.lineJoin = this.strokeLineJoin;\n ctx.miterLimit = this.strokeMiterLimit;\n return this.handleFiller(ctx, 'strokeStyle', decl.stroke);\n },\n\n _setFillStyles: function(ctx, decl) {\n return this.handleFiller(ctx, 'fillStyle', decl.fill);\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 fillOffsets, strokeOffsets;\n\n if (!shouldStroke && !shouldFill) {\n return;\n }\n ctx.save();\n\n shouldFill && (fillOffsets = this._setFillStyles(ctx, fullDecl));\n shouldStroke && (strokeOffsets = this._setStrokeStyles(ctx, fullDecl));\n\n ctx.font = this._getFontDeclaration(fullDecl);\n\n\n if (decl && decl.textBackgroundColor) {\n this._removeShadow(ctx);\n }\n if (decl && decl.deltaY) {\n top += decl.deltaY;\n }\n shouldFill && ctx.fillText(_char, left - fillOffsets.offsetX, top - fillOffsets.offsetY);\n shouldStroke && ctx.strokeText(_char, left - strokeOffsets.offsetX, top - strokeOffsets.offsetY);\n 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 {Number} lineIndex index text line\n * @return {Number} Line left offset\n */\n _getLineLeftOffset: function(lineIndex) {\n var lineWidth = this.getLineWidth(lineIndex),\n lineDiff = this.width - lineWidth, textAlign = this.textAlign, direction = this.direction,\n isEndOfWrapping, leftOffset = 0, isEndOfWrapping = this.isEndOfWrapping(lineIndex);\n if (textAlign === 'justify'\n || (textAlign === 'justify-center' && !isEndOfWrapping)\n || (textAlign === 'justify-right' && !isEndOfWrapping)\n || (textAlign === 'justify-left' && !isEndOfWrapping)\n ) {\n return 0;\n }\n if (textAlign === 'center') {\n leftOffset = lineDiff / 2;\n }\n if (textAlign === 'right') {\n leftOffset = lineDiff;\n }\n if (textAlign === 'justify-center') {\n leftOffset = lineDiff / 2;\n }\n if (textAlign === 'justify-right') {\n leftOffset = lineDiff;\n }\n if (direction === 'rtl') {\n leftOffset -= lineDiff;\n }\n return leftOffset;\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] !== undefined) {\n return this.__lineWidths[lineIndex];\n }\n\n var lineInfo = this.measureLine(lineIndex);\n var width = lineInfo.width;\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 character 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, path = this.path,\n charSpacing = this._getWidthOfCharSpacing(),\n offsetY = this.offsets[type];\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 (path && currentDecoration && currentFill) {\n ctx.save();\n ctx.fillStyle = lastFill;\n ctx.translate(charBox.renderLeft, charBox.renderTop);\n ctx.rotate(charBox.angle);\n ctx.fillRect(\n -charBox.kernedWidth / 2,\n offsetY * _size + _dy,\n charBox.kernedWidth,\n this.fontSize / 15\n );\n ctx.restore();\n }\n else if (\n (currentDecoration !== lastDecoration || currentFill !== lastFill || _size !== size || _dy !== dy)\n && boxWidth > 0\n ) {\n var drawStart = leftOffset + lineLeftOffset + boxStart;\n if (this.direction === 'rtl') {\n drawStart = this.width - drawStart - boxWidth;\n }\n if (lastDecoration && lastFill) {\n ctx.fillStyle = lastFill;\n ctx.fillRect(\n drawStart,\n top + offsetY * size + dy,\n boxWidth,\n this.fontSize / 15\n );\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 var drawStart = leftOffset + lineLeftOffset + boxStart;\n if (this.direction === 'rtl') {\n drawStart = this.width - drawStart - boxWidth;\n }\n ctx.fillStyle = currentFill;\n currentDecoration && currentFill && ctx.fillRect(\n drawStart,\n top + offsetY * 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 allProperties = additionalProps.concat(propertiesToInclude);\n var obj = this.callSuper('toObject', allProperties);\n obj.styles = fabric.util.stylesToArray(this.styles, this.text);\n if (obj.path) {\n obj.path = this.path.toObject();\n }\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 var isAddingPath = false;\n if (typeof key === 'object') {\n for (var _key in key) {\n if (_key === 'path') {\n this.setPathInfo();\n }\n needsDims = needsDims || this._dimensionAffectingProps.indexOf(_key) !== -1;\n isAddingPath = isAddingPath || _key === 'path';\n }\n }\n else {\n needsDims = this._dimensionAffectingProps.indexOf(key) !== -1;\n isAddingPath = key === 'path';\n }\n if (isAddingPath) {\n this.setPathInfo();\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 (not yet implemented)\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 plain js 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 var objectCopy = clone(object), path = object.path;\n delete objectCopy.path;\n return fabric.Object._fromObject('Text', objectCopy, function(textInstance) {\n textInstance.styles = fabric.util.stylesFromArray(object.styles, object.text);\n if (path) {\n fabric.Object._fromObject('Path', path, function(pathInstance) {\n textInstance.set('path', pathInstance);\n callback(textInstance);\n }, 'path');\n }\n else {\n callback(textInstance);\n }\n }, '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, selectionStart 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 v1.4) 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 *

Supported key combinations:

\n *
\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   * 
\n *\n *

Supported mouse/touch combination

\n *
\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   * 
\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 * DOM container to append the hiddenTextarea.\n * An alternative to attaching to the document.body.\n * Useful to reduce laggish redraw of the full document.body tree and\n * also with modals event capturing that won't let the textarea take focus.\n * @type HTMLElement\n * @default\n */\n hiddenTextareaContainer: null,\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 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 if (this.direction === 'rtl') {\n boundaries.left *= -1;\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\n - charHeight * (1 - this._fontSizeFraction);\n\n if (this.inCompositionMode) {\n this.renderSelection(boundaries, ctx);\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 var drawStart = boundaries.left + lineOffset + boxStart,\n drawWidth = boxEnd - boxStart,\n drawHeight = lineHeight, extraTop = 0;\n if (this.inCompositionMode) {\n ctx.fillStyle = this.compositionColor || 'black';\n drawHeight = 1;\n extraTop = lineHeight;\n }\n else {\n ctx.fillStyle = this.selectionColor;\n }\n if (this.direction === 'rtl') {\n drawStart = this.width - drawStart - drawWidth;\n }\n ctx.fillRect(\n drawStart,\n boundaries.top + boundaries.topOffset + extraTop,\n drawWidth,\n drawHeight);\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 * if the text object has a pattern or gradient for filler, it will return that.\n * Unused by the library, is for the end user\n * @return {String | fabric.Gradient | fabric.Pattern} 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 var styles = fabric.util.stylesFromArray(object.styles, object.text);\n //copy object to prevent mutation\n var objCopy = Object.assign({}, object, { styles: styles });\n parseDecoration(objCopy);\n if (objCopy.styles) {\n for (var i in objCopy.styles) {\n for (var j in objCopy.styles[i]) {\n parseDecoration(objCopy.styles[i][j]);\n }\n }\n }\n fabric.Object._fromObject('IText', objCopy, 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 // regain focus\n document.activeElement !== this.hiddenTextarea && this.hiddenTextarea.focus();\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 test is required in order to close #6841\n // when a pasted buffer begins with a newline then\n // this.styles[cursorLoc.lineIndex + i] and copiedStyle[0]\n // may be undefined for some reason\n if (this.styles[cursorLoc.lineIndex + i] && copiedStyle[0]) {\n this.styles[cursorLoc.lineIndex + i][0] = copiedStyle[0];\n }\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 handler 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 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 // handling of RTL: in order to get things work correctly,\n // we assume RTL writing is mirrored compared to LTR writing.\n // so in position detection we mirror the X offset, and when is time\n // of rendering it, we mirror it again.\n if (this.direction === 'rtl') {\n mouseOffset.x = this.width * this.scaleX - mouseOffset.x + width;\n }\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\n if (this.hiddenTextareaContainer) {\n this.hiddenTextareaContainer.appendChild(this.hiddenTextarea);\n }\n else {\n fabric.document.body.appendChild(this.hiddenTextarea);\n }\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 keysMapRtl: {\n 9: 'exitEditing',\n 27: 'exitEditing',\n 33: 'moveCursorUp',\n 34: 'moveCursorDown',\n 35: 'moveCursorLeft',\n 36: 'moveCursorRight',\n 37: 'moveCursorRight',\n 38: 'moveCursorUp',\n 39: 'moveCursorLeft',\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 var keyMap = this.direction === 'rtl' ? this.keysMapRtl : this.keysMap;\n if (e.keyCode in keyMap) {\n this[keyMap[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 differences 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',\n textAndBg.textSpans.join(''),\n '\\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 '',\n fabric.util.string.escapeXml(_char),\n ''\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 = fabric.util.hasStyleChanged(actualStyle, nextStyle, true);\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\\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/japanese\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 languages?\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 var styles = fabric.util.stylesFromArray(object.styles, object.text);\n //copy object to prevent mutation\n var objCopy = Object.assign({}, object, { styles: styles });\n return fabric.Object._fromObject('Textbox', objCopy, 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","import { useHistory, useLocation } from \"react-router-dom\";\nconst ReactRouter5Adapter = ({\n children\n}) => {\n const location = useLocation();\n const history = useHistory();\n const adapter = {\n replace(location2) {\n history.replace(location2.search || \"?\", location2.state);\n },\n push(location2) {\n history.push(location2.search || \"?\", location2.state);\n },\n get location() {\n return history.location;\n }\n };\n return children(adapter);\n};\nexport {\n ReactRouter5Adapter\n};\n"],"names":["global","sqrt","atan2","pow","PiBy180","PiBy2","couldUseAttachEvent","touchEvents","parseEl","supportsOpacity","supportsFilters","reOpacity","setOpacity","proto","min","max","degreesToRadians","originXOffset","originYOffset","clone","toFixed","multipleSpacesRegex","fabric","version","exports","document","window","HTMLDocument","Document","implementation","createHTMLDocument","virtualWindow","JSDOM","decodeURIComponent","features","FetchExternalResources","resources","jsdomImplForWrapper","nodeCanvas","DOMParser","copyGLTo2DDrawImage","gl","pipelineState","glCanvas","canvas","targetCanvas","ctx","getContext","translate","height","scale","sourceY","drawImage","width","copyGLTo2DPutImageData","dWidth","destinationWidth","dHeight","destinationHeight","numBytes","u8","Uint8Array","this","imageBuffer","u8Clamped","Uint8ClampedArray","readPixels","RGBA","UNSIGNED_BYTE","imgData","ImageData","putImageData","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","_once","_handler","apply","arguments","off","bind","on","Observable","fire","options","listenersForEvent","i","len","length","call","filter","value","prop","push","once","Collection","_objects","add","_onObjectAdded","renderOnAddRemove","requestRenderAll","insertAt","object","index","nonSplicing","objects","splice","remove","somethingRemoved","_onObjectRemoved","forEachObject","callback","context","getObjects","type","concat","o","item","isEmpty","size","contains","deep","some","obj","complexity","reduce","memo","current","CommonMethods","_setOptions","set","_initGradient","filler","property","colorStops","Gradient","_initPattern","source","Pattern","_setObject","_set","key","toggle","get","Math","PI","cos","angle","sin","sign","removeFromArray","idx","getRandomInt","floor","random","degrees","radiansToDegrees","radians","rotatePoint","point","origin","newPoint","Point","x","y","v","rotateVector","addEquals","vector","createVector","from","to","calcAngleBetweenVectors","a","b","acos","hypot","getHatVector","multiply","getBisector","A","B","C","AB","AC","alpha","phi","projectStrokeOnPoints","points","openPath","coords","s","strokeWidth","strokeUniformScalar","strokeUniform","scaleX","scaleY","getStrokeHatVector","scalar","forEach","p","miterVector","bisector","bisectorVector","strokeLineJoin","strokeMiterLimit","subtract","SQRT2","transformPoint","t","ignoreOffset","makeBoundingBoxFromPoints","transform","xPoints","minX","yPoints","minY","left","top","invertTransform","r","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","substring","loadImageInDom","div","createElement","style","position","appendChild","querySelector","parentNode","removeChild","enlivenObjects","reviver","enlivenedObjects","numLoadedObjects","numTotalObjects","onLoaded","fromObject","error","enlivenObjectEnlivables","enlivenProps","Object","ENLIVEN_PROPS","map","enlivedProps","enlivenPatterns","patterns","numLoadedPatterns","numPatterns","enlivenedPatterns","pattern","groupSVGElements","elements","path","sourcePath","centerPoint","Group","populateWithProperties","destination","properties","Array","isArray","createCanvasElement","copyCanvasElement","newCanvas","toDataURL","canvasEl","format","quality","multiplyTransformMatrices","is2x2","qrDecompose","denom","skewX","skewY","translateX","translateY","calcRotateMatrix","theta","calcDimensionsMatrix","scaleMatrix","flipX","flipY","tan","composeMatrix","matrix","resetObjectTransform","target","rotate","saveObjectTransform","isTransparent","tolerance","_isTransparent","imageData","getImageData","l","data","parsePreserveAspectRatioAttribute","attribute","align","meetOrSlice","aspectRatioAttrs","pop","alignX","alignY","clearFabricFontCache","fontFamily","toLowerCase","limitDimsByArea","ar","maximumArea","roughWidth","perfLimitSizeY","capValue","findScaleToFit","findScaleToCover","matrixToSVG","NUM_FRACTION_DIGITS","join","removeTransformFromObject","inverted","finalTransform","calcOwnMatrix","applyTransformToObject","addTransformToObject","center","setPositionByOrigin","sizeAfterTransform","dimX","dimY","transformMatrix","bbox","mergeClipPaths","c1","c2","calcTransformMatrix","clipPath","hasStyleChanged","prevStyle","thisStyle","forTextSpans","stroke","fontWeight","fontStyle","textBackgroundColor","deltaY","overline","underline","linethrough","stylesToArray","styles","text","textLines","charIndex","stylesArray","c","keys","start","end","stylesFromArray","styleIndex","stylesObject","assign","_join","prototype","commandLengths","m","h","q","repeatedCommands","M","segmentToBezier","th2","th3","cosTh","sinTh","rx","ry","cx1","cy1","mT","fromX","fromY","costh2","sinth2","costh3","sinth3","toX","toY","calcVectorAngle","ux","uy","vx","vy","ta","tb","fromArcToBeziers","fx","fy","rot","large","sweep","segsNorm","rotateX","th","px","py","rx2","abs","ry2","py2","px2","pl","root","cx","cy","mTheta","dtheta","segments","ceil","result","mDelta","arcToSegments","calcLineLength","x1","y1","x2","y2","getPointOnCubicBezierIterator","p1x","p1y","p2x","p2y","p3x","p3y","p4x","p4y","pct","CB2","c3","CB3","c4","CB4","getTangentCubicIterator","invT","tangentX","tangentY","getPointOnQuadraticBezierIterator","QB2","QB3","getTangentQuadraticIterator","pathIterator","iterator","perc","tempP","tmpLen","findPercentageForDistance","segInfo","distance","nextLen","lastPerc","nextStep","angleFinder","getPathSegmentsInfo","tempInfo","totalLength","info","command","destX","destY","joinPath","pathData","segment","parsePath","pathString","currentPath","parsed","match","coordsStr","re","rNumber","rNumberCommaWsp","rFlagCommaWsp","regArcArgumentSequence","RegExp","coordsParsed","trim","args","j","jlen","isNaN","commandLength","repeatedCommand","k","klen","makePathSimpler","converted","previous","controlX","controlY","destinationPath","getSmoothPathFromPoints","correction","p1","p2","multSignX","multSignY","manyPoints","eq","midPoint","midPointFrom","getBoundsOfCurve","x0","y0","x3","y3","argsString","t1","t2","b2ac","sqrtb2ac","tvalues","bounds","mt","getPointOnPath","infos","segPercent","lerp","transformPath","pathOffset","pathSegment","newSegment","find","byProperty","condition","invoke","method","value1","value2","extend","Element","hasOwnProperty","getWholeChar","str","code","charCodeAt","next","prev","replace","character","capitalize","firstLetterOnly","escapeXml","graphemeSplit","textstring","chr","graphemes","emptyFunction","IS_DONTENUM_BUGGY","toString","addMethods","klass","parent","superclass","constructor","returnValue","valueOf","Subclass","callSuper","methodName","parentMethod","_this","superClassMethod","createClass","initialize","shift","subclasses","attachEvent","addListener","element","addEventListener","removeListener","removeEventListener","getPointer","event","scroll","getScrollLeftTop","_evt","touchProp","changedTouches","getTouchInfo","clientX","clientY","isTouchEvent","pointerType","opacity","es","currentStyle","hasLayout","zoom","test","setStyle","elementStyle","cssText","normalizedProperty","styleFloat","setProperty","_slice","sliceCanConvertNodelists","getElementStyle","selectProp","toArray","arrayLike","childNodes","err","makeElement","tagName","el","className","htmlFor","setAttribute","docElement","documentElement","body","scrollLeft","scrollTop","host","nodeType","arr","defaultView","getComputedStyle","attr","undefined","makeElementUnselectable","onselectstart","unselectable","makeElementSelectable","setImageSmoothing","imageSmoothingEnabled","webkitImageSmoothingEnabled","mozImageSmoothingEnabled","msImageSmoothingEnabled","oImageSmoothingEnabled","getById","id","getElementById","addClass","wrapElement","wrapper","replaceChild","getElementOffset","docElem","scrollLeftTop","doc","ownerDocument","box","offset","offsetAttributes","borderLeftWidth","borderTopWidth","paddingLeft","paddingTop","parseInt","getBoundingClientRect","clientLeft","clientTop","getNodeCanvas","impl","_canvas","_image","cleanUpJsdomNode","_currentSrc","_attributes","_classList","emptyFn","request","onComplete","xhr","XMLHttpRequest","parameters","onreadystatechange","readyState","param","addParamToUrl","open","setRequestHeader","send","warn","RUNNING_ANIMATIONS","noop","defaultEasing","d","cancelAll","animations","animation","cancel","cancelByCanvas","cancelled","cancelByTarget","findAnimationsByTarget","findAnimationIndex","cancelFunc","findAnimation","_requestAnimFrame","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","setTimeout","_cancelAnimFrame","cancelAnimationFrame","clearTimeout","requestAnimFrame","animate","removeFromRegistry","runningAnimations","currentValue","startValue","completionRate","durationRate","timestamp","time","Date","duration","finish","onChange","abort","easing","isMany","endValue","byValue","onStart","tick","ticktime","currentTime","timePerc","_value","valuePerc","cancelAnimFrame","calculateColor","begin","pos","color","animateColor","fromColor","toColor","startColor","Color","getSource","endColor","originalOnComplete","originalOnChange","colorEasing","normalize","asin","elastic","opts","easeInBounce","easeOutBounce","ease","easeInQuad","easeOutQuad","easeInOutQuad","easeInCubic","easeOutCubic","easeInOutCubic","easeInQuart","easeOutQuart","easeInOutQuart","easeInQuint","easeOutQuint","easeInOutQuint","easeInSine","easeOutSine","easeInOutSine","easeInExpo","easeOutExpo","easeInOutExpo","easeInCirc","easeOutCirc","easeInOutCirc","easeInElastic","easeOutElastic","easeInOutElastic","easeInBack","easeOutBack","easeInOutBack","easeInOutBounce","attributesMap","display","visibility","colorAttributes","normalizeAttr","normalizeValue","parentAttributes","parseTransformAttribute","visible","fillIndex","strokeIndex","getSvgRegex","_getMultipleNodes","nodeNames","nodeName","nodeList","nodeArray","getElementsByTagName","elementMatchesRule","selectors","firstMatching","parentMatching","selectorMatches","selector","doesSomeParentMatch","matcher","classNames","getAttribute","elementById","node","nodelist","svgValidTagNamesRegEx","svgViewBoxElementsRegEx","svgInvalidAncestorsRegEx","svgValidParentsRegEx","cssRules","gradientDefs","clipPaths","skewMatrix","reTransformList","reTransform","attributeValue","matrices","operation","translateMatrix","rotateMatrix","multiplierX","multiplierY","combinedMatrix","reViewBoxAttrValue","applyViewboxTransform","viewBoxWidth","viewBoxHeight","viewBoxAttr","widthAttr","heightAttr","preserveAspectRatio","missingViewBox","missingDimAttr","toBeParsed","parsedDim","widthDiff","heightDiff","removeAttribute","createElementNS","firstChild","recursivelyParseGradientsXlink","gradient","referencedGradient","hasAttribute","children","referenceClone","cloneNode","parseSVGDocument","parsingOptions","xlinkAttribute","attrs","xlink","el2","currentTrans","oldLength","el3","setAttributeNS","nodeValue","parseUseDirectives","svgUid","__uid","descendants","selectNodes","hasAncestorWithNodeName","getGradientDefs","getCSSRules","parseElements","instances","reFontDeclaration","parseFontDeclaration","oStyle","lineHeight","elList","parseAttributes","parentFontSize","ownAttributes","cssAttrs","rule","getGlobalStylesForElement","parseStyleAttribute","normalizedAttr","normalizedValue","normalizedStyle","font","mergedAttrs","setAlpha","getAlpha","toRgba","_setStrokeFillOpacity","ElementsParser","parse","chunk","pair","parseStyleString","parseStyleObject","parsePointsAttribute","parsedPoints","allRules","styleContents","textContent","ruleObj","propertyValuePairs","_rule","loadSVGFromURL","xml","responseXML","results","_options","allElements","loadSVGFromString","parseFromString","regexUrl","numElements","createObjects","createObject","findTag","fromElement","createCallback","checkIfDone","resolveGradient","Image","_originalElement","_removeTransformMatrix","resolveClipPath","extractPropertyDefinition","storage","regex","lastIndex","gradientDef","opacityAttr","createClipPathCallback","container","_newObj","fillRule","clipRule","usingElement","objTransformInv","gTransform","clipPathTag","clipPathOwner","that","scalarAdd","scalarAddEquals","subtractEquals","scalarSubtract","scalarSubtractEquals","multiplyEquals","divide","divideEquals","lt","lte","gt","gte","distanceFrom","dx","dy","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","_tryParsingColor","setSource","hue2rgb","colorNameMap","sourceFromHex","sourceFromRgb","sourceFromHsl","_rgbToHsl","g","round","_source","toRgb","toHsl","hsl","toHsla","toHex","toHexa","toGrayscale","average","currentAlpha","toBlackWhite","threshold","overlayWith","otherColor","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","fromRgb","fromSource","fromRgba","fromHsl","fromHsla","fromHex","isShortNotation","isRGBa","oColor","scaleMap","skewMap","controls","LEFT","TOP","RIGHT","BOTTOM","CENTER","opposite","bottom","right","findCornerQuadrant","fabricObject","control","cornerAngle","fireEvent","canvasOptions","scaleIsProportional","eventData","uniformIsToggled","uniScaleKey","uniformScaling","isTransformCentered","originX","originY","scalingIsForbidden","by","scaleProportionally","lockX","lockScalingX","lockY","lockScalingY","commonEventInfo","e","pointer","wrapWithFixedAnchor","actionHandler","getCenterPoint","constraint","translateToOriginPoint","actionPerformed","wrapWithFireEvent","getLocalPoint","corner","getZoom","padding","localPoint","toLocalPoint","offsetX","offsetY","targetHasOneFlip","compensateScaleForSkew","oppositeSkew","scaleToCompensate","axis","reference","newValue","_getTransformedDimensions","skewObjectX","newSkew","dimNoSkew","totalSkewSize","currentSkew","hasSkewed","dimBeforeSkewing","skewObjectY","scaleObject","dim","signX","signY","forbidScaling","gestureScale","lockScalingFlip","original","oldScaleX","oldScaleY","scaleCursorStyleHandler","n","skewCursorStyleHandler","lockSkewingY","lockSkewingX","scaleSkewCursorStyleHandler","altActionKey","rotationWithSnapping","pivotPoint","lockRotation","hasRotated","lastAngle","ey","ex","curAngle","snapAngle","snapThreshold","rightAngleLocked","leftAngleLocked","scalingEqually","scalingX","scalingY","scalingYOrSkewingX","skewHandlerX","scalingXOrSkewingY","skewHandlerY","changeWidth","strokePadding","multiplier","oldWidth","newWidth","finalHandler","dragHandler","newLeft","newTop","moveX","moveY","scaleOrSkewActionName","isAlternative","rotationStyleHandler","cursorStyle","controlsUtils","renderCircleControl","styleOverride","xSize","sizeX","cornerSize","ySize","sizeY","transparentCorners","cornerStrokeColor","myLeft","myTop","save","fillStyle","cornerColor","strokeStyle","lineWidth","beginPath","arc","restore","renderSquareControl","xSizeBy2","ySizeBy2","strokeRect","Control","actionName","touchSizeX","touchSizeY","withConnection","mouseDownHandler","mouseUpHandler","getActionHandler","getMouseDownHandler","getMouseUpHandler","cursorStyleHandler","getActionName","getVisibility","controlKey","objectVisibility","_controlsVisibility","setVisibility","positionHandler","finalMatrix","calcCornerCoords","objectAngle","objectCornerSize","centerX","centerY","isTouch","cosHalfOffset","sinHalfOffset","cosHalfOffsetComp","sinHalfOffsetComp","controlTriangleAngle","cornerHypotenuse","newTheta","newThetaComp","tl","tr","bl","br","render","cornerStyle","getColorStop","colorAlpha","keyValuePairs","gradientTransform","gradientUnits","option","addColorStop","toObject","propertiesToInclude","toSVG","markup","commonAttributes","needsSwap","withViewport","additionalTransform","sort","reverse","minRadius","percentageShift","colorStop","toLive","createLinearGradient","createRadialGradient","instance","svgOptions","colorStopEls","getLinearCoords","getRadialCoords","propValue","finalValue","__convertPercentUnitsToValues","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","StaticCanvas","CANVAS_INIT_ERROR","Error","renderAndResetBound","renderAndReset","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","_originalCanvasStyle","_applyCanvasStyle","getWidth","getHeight","setWidth","setDimensions","setHeight","dimensions","cssValue","cssOnly","_setBackstoreDimension","hasLostContext","backstoreOnly","_setCssDimension","_isCurrentlyDrawing","freeDrawingBrush","_setBrushStyles","cacheCanvasEl","wrapperEl","setViewportTransform","vpt","activeObject","_activeObject","backgroundObject","overlayObject","group","setCoords","calcViewportBoundaries","zoomToPoint","before","after","setZoom","absolutePan","relativePan","getElement","setupState","clearContext","clearRect","clear","_hasITextHandlers","_mouseUpITextHandler","_iTextInstances","renderAll","canvasToDrawOn","renderCanvas","isRendering","iVpt","cancelRequestedRender","_renderBackground","_renderObjects","drawControls","shouldCache","_transformDone","renderCache","forClipping","drawClipPathOnCanvas","_renderOverlay","globalCompositeOperation","zoomX","zoomY","_cacheCanvas","cacheTranslationX","cacheTranslationY","_renderBackgroundOrOverlay","needsVpt","moveTo","lineTo","closePath","getCenter","centerObjectH","_centerObject","centerObjectV","centerObject","viewportCenterObject","vpCenter","getVpCenter","viewportCenterObjectH","viewportCenterObjectV","toDatalessJSON","toDatalessObject","_toObjectMethod","_toObjects","excludeFromExport","_toObject","__serializeBgOverlay","originalValue","bgImage","bgColor","background","overlay","svgViewportTransformation","_setSVGPreamble","_setSVGHeader","clipPathId","_setSVGBgOverlayColor","_setSVGBgOverlayImage","_setSVGObjects","suppressPreamble","encoding","viewBox","createSVGFontFacesMarkup","createSVGRefElementsMarkup","createSVGClipPathMarkup","toClipPathSVG","shouldTransform","row","rowIndex","fontList","_setSVGObject","finalWidth","finalHeight","sendToBack","objs","activeSelection","unshift","bringToFront","sendBackwards","intersecting","newIdx","objsMoved","_findNewLowerIndex","intersectsWithObject","isContainedWithinObject","bringForward","_findNewUpperIndex","dispose","classList","DataURLExporter","EMPTY_JSON","supports","setLineDash","toJSON","createPNGStream","createJPEGStream","BaseBrush","strokeLineCap","strokeDashArray","limitedToCanvasSize","lineCap","miterLimit","lineJoin","_saveAndTransform","_setShadow","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY","needsFullRender","_resetShadow","_isOutSideCanvas","PencilBrush","decimate","drawStraightLine","straightLineKey","_points","_hasStraightLine","_drawSegment","quadraticCurveTo","onMouseDown","_isMainEvent","_prepareForDrawing","_captureDrawingPath","_render","onMouseMove","oldEnd","onMouseUp","_finalizeAndAddPath","_reset","_addPoint","pointerPoint","convertPointsToSVGPath","_isEmptySVGPath","createPath","Path","decimatePoints","adjustedDistance","lastPoint","newPoints","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","patternCanvas","patternCtx","getPatternSrcFunction","String","getPattern","topLeft","_getLeftTopCoords","Canvas","_initInteractive","_createCacheCanvas","centeredScaling","centeredRotation","centeredKey","selection","selectionKey","altSelectionKey","selectionColor","selectionDashArray","selectionBorderColor","selectionLineWidth","selectionFullyContained","hoverCursor","moveCursor","defaultCursor","freeDrawingCursor","notAllowedCursor","containerClass","perPixelTargetFind","targetFindTolerance","skipTargetFind","isDrawingMode","preserveObjectStacking","stopContextMenu","fireRightClick","fireMiddleClick","targets","enablePointerEvents","_hoveredTarget","_hoveredTargets","_currentTransform","_groupSelector","_initWrapperElement","_createUpperCanvas","_initEventListeners","_chooseObjectsToRender","objsToRender","activeGroupObjects","activeObjects","getActiveObjects","contextTopDirty","renderTopLayer","_drawSelection","renderTop","_normalizePointer","invertedM","vptPointer","restorePointerVpt","isTargetTransparent","normalizedPointer","targetRelativeX","targetRelativeY","_cacheContext","contextCache","originalColor","selectionBackgroundColor","_isSelectionKeyPressed","_shouldClearSelection","evented","selectable","_shouldCenterTransform","action","altKey","centerTransform","_getOriginFromCorner","_getActionFromCorner","alreadySelected","_setupCurrentTransform","__corner","lastX","lastY","shiftKey","_beforeTransform","setCursor","cursor","viewportStart","viewportExtent","extent","maxX","maxY","strokeOffset","_setLineDash","findTarget","skipGroup","activeTarget","activeTargetSubs","aObjects","shouldLookForActive","_findTargetCorner","_searchPossibleTargets","_checkTarget","globalPointer","containsPoint","isEditing","subTarget","objToCheck","pointerToUse","subTargetCheck","ignoreZoom","_absolutePointer","_pointer","cssScale","boundsWidth","boundsHeight","retinaScaling","lowerCanvasClass","_copyCanvasStyle","getTopContext","fromEl","toEl","getSelectionContext","getSelectionElement","getActiveObject","active","_discardActiveObject","_fireSelectionEvents","oldObjects","somethingChanged","added","removed","oldObject","selected","deselected","setActiveObject","currentActives","_setActiveObject","onSelect","onDeselect","discardActiveObject","removeListeners","_renderControls","originalProperties","_realizeGroupTransformOnObject","_unwindGroupTransformOnObject","originalValues","clearContextTop","addEventOptions","passive","checkClick","button","mainTouchId","_bindEvents","addOrRemove","_getEventPrefix","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","__onOrientationChange","__onShake","__onLongPress","preventDefault","_fireEnterLeaveEvents","stopPropagation","_cacheTransformEventData","_handleEvent","_resetTransformEventData","getPointerId","evt","identifier","pointerId","isPrimary","touches","__onMouseDown","__onMouseUp","_willAddMouseDown","__onMouseMove","_shouldRender","groupSelector","shouldRender","isClick","_onMouseUpInDrawingMode","_finalizeCurrentTransform","targetWasActive","_maybeGroupObjects","activeOn","isMoving","originalControl","originalMouseUpHandler","_setCursorFromEvent","eventType","subTargets","absolutePointer","currentTarget","currentSubTargets","_scaling","hasStateChanged","_fire","_onMouseDownInDrawingMode","_onMouseMoveInDrawingMode","_previousPointer","shouldGroup","_shouldGroup","_handleGrouping","saveState","_transformObject","_fireOverOutEvents","fireSyntheticInOutEvents","oldTarget","evtOut","canvasEvtOut","evtIn","canvasEvtIn","_draggedoverTarget","config","inOpt","outOpt","inFires","targetChanged","previousTarget","nextTarget","reset","_performTransformAction","getCornerCursor","_updateActiveSelection","_createActiveSelection","currentActiveObjects","removeWithUpdate","addWithUpdate","_createGroup","groupObjects","exitEditing","ActiveSelection","_groupSelectedObjects","aGroup","_collectObjects","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","objectCaching","touchCornerSize","borderColor","borderDashArray","cornerDashArray","strokeDashOffset","borderOpacityWhenMoving","borderScaleFactor","minScaleLimit","hasControls","hasBorders","lockMovementX","lockMovementY","statefullCache","noScaleCache","dirty","paintFirst","stateProperties","cacheProperties","colorProperties","absolutePositioned","_cacheProperties","_updateCacheCanvas","_limitCacheSize","dims","limitedDims","capped","_getCacheCanvasDimensions","objectScale","getTotalObjectScaling","neededX","neededY","drawingWidth","drawingHeight","minCacheSize","dimensionsChanged","cacheWidth","cacheHeight","zoomChanged","shouldRedraw","additionalWidth","additionalHeight","shouldResizeCanvas","canvasWidth","canvasHeight","sizeGrowing","getHeightOfLine","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","_drawClipPath","skipCanvas","_getNonTransformedDimensions","_removeShadow","_setStrokeStyles","decl","lineDashOffset","_applyPatternForTransformedGradient","_applyPatternGradientTransform","_setFillStyles","dashArray","drawBorders","forActiveSelection","drawBordersInGroup","scaling","multX","multY","_renderPaintInOrder","_renderStroke","_renderFill","pCtx","pCanvas","_findCenterFromElement","_assignTransformMatrixProps","preserveAspectRatioOptions","cropX","cropY","offsetLeft","offsetTop","objectForm","_fromObject","cloneAsImage","utils","origParams","originalGroup","originalShadow","withoutTransform","withoutShadow","boundingRect","getBoundingRect","shadowOffset","originalCanvas","isType","includes","shouldCenterOrigin","_setOriginToCenter","_resetOrigin","centerH","viewportCenterH","centerV","viewportCenterV","viewportCenter","getLocalPointer","pClicked","objectLeftTop","createAccessors","extraParam","translateToGivenOrigin","fromOriginX","fromOriginY","toOriginX","toOriginY","translateToCenterPoint","leftTop","getPointByOrigin","adjustPosition","offsetFrom","offsetTo","hypotFull","getScaledWidth","xFull","yFull","_originalOriginX","_originalOriginY","originPoint","multiplyMatrices","oCoords","aCoords","lineCoords","ownMatrixCache","matrixCache","_getCoords","absolute","calculate","calcACoords","calcLineCoords","getCoords","pointTL","pointBR","other","otherCoords","lines","_getImageLines","_findCrossPoints","_containsCenterOfCanvas","isPartiallyOnScreen","every","topline","rightline","bottomline","leftline","xi","iLine","xcount","lineKey","getScaledHeight","scaleToWidth","boundingRectFactor","scaleToHeight","cosP","sinP","cosPSinP","cosPMinusSinP","calcOCoords","_calcRotateMatrix","_calcTranslateMatrix","startMatrix","_calculateCurrentDimensions","forEachControl","w","skipCorners","_setCornerCoords","transformMatrixKey","prefix","cache","tMatrix","noSkew","_finalizeDimensions","getSvgColorString","getSvgStyles","skipShadow","getSvgFilter","getSvgSpanStyles","useWhiteSpace","textDecoration","getSvgTextDecoration","decoration","getSvgCommons","getSvgTransform","full","_setSVGBg","textBgRects","_getFillAttributes","_createBaseSVGMarkup","_toSVG","_createBaseClipPathSVGMarkup","objectMarkup","commonPieces","clipPathMarkup","noStyle","styleInfo","shadowInfo","withShadow","vectorEffect","absoluteClipPath","addPaintOrder","saveProps","props","tmpObj","_isEqual","origValue","firstPass","dashedPropertySet","forTouch","isControlVisible","touchCorner","fn","controlObject","wh","shouldStroke","setControlVisible","setControlsVisibility","FX_DURATION","fxCenterObjectH","callbacks","empty","fxCenterObjectV","fxRemove","skipCallbacks","propsToAnimate","out","_animate","propPair","propIsColor","valueProgress","timeProgress","coordProps","makeEdgeToOriginGetter","propertyNames","originValues","axis1","axis2","dimension","nearest","farthest","Line","_setWidthHeight","_getLeftToOriginX","_getTopToOriginY","calcLinePoints","origStrokeStyle","xMult","yMult","ATTRIBUTE_NAMES","parsedAttributes","startAngle","endAngle","setRadius","svgString","getRadiusX","getRadiusY","Triangle","widthBy2","heightBy2","piBy2","Ellipse","getRx","getRy","_initRxRy","isRounded","bezierCurveTo","Polyline","exactBoundingBox","_setPositionDimensions","_projectStrokeOnPoints","correctLeftTop","calcDim","_calcDimensions","correctSize","fromSVG","diffX","diffY","commonRender","fromElementGenerator","_class","Polygon","_setPath","_renderPathCommands","subpathStartX","subpathStartY","_getOffsetTransform","digits","aX","aY","pathUrl","elivenedObjects","useSetOnGroup","isAlreadyGrouped","_updateObjectsACoords","_calcBounds","_updateObjectsCoords","_updateObjectCoords","objectLeft","objectTop","nested","_restoreObjectsState","_includeDefaultValues","objsToObject","originalDefaults","_obj","ownCache","groupMatrix","destroy","toActiveSelection","ungroupOnCanvas","setObjectsCoords","onlyWidthHeight","iLen","jLen","_getBounds","minXY","maxXY","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","strokeSvg","imageMarkup","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","precision","fragmentSource","fragmentShader","createShader","FRAGMENT_SHADER","shaderSource","compileShader","getShaderParameter","COMPILE_STATUS","setupGLContext","captureGPUInfo","isSupported","getParameter","MAX_TEXTURE_SIZE","precisions","webGlPrecision","createWebGLCanvas","aPosition","Float32Array","chooseFastestCopyGLTo2DMethod","canUseImageData","canMeasurePerf","performance","canUseArrayBuffer","ArrayBuffer","canUseUint8Clamped","copyGLTo2D","startTime","drawImageTime","testContext","now","glOptions","premultipliedAlpha","depth","stencil","antialias","clearColor","cachedTexture","getCachedTexture","sourceTexture","createTexture","targetTexture","originalTexture","passes","webgl","programCache","pass","tempFbo","createFramebuffer","bindFramebuffer","FRAMEBUFFER","applyTo","resizeCanvasIfNeeded","bindTexture","TEXTURE_2D","deleteTexture","deleteFramebuffer","clearWebGLCaches","textureCache","textureImageSource","filterType","texture","texParameteri","TEXTURE_MAG_FILTER","NEAREST","TEXTURE_MIN_FILTER","TEXTURE_WRAP_S","CLAMP_TO_EDGE","TEXTURE_WRAP_T","texImage2D","uniqueId","gpuInfo","renderer","vendor","ext","getExtension","UNMASKED_RENDERER_WEBGL","UNMASKED_VENDOR_WEBGL","sourceElement","originalEl","originalImageData","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","temp","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","dstOff","scx","scy","srcOff","wt","weights","side","halfSide","sw","sh","output","createImageData","dst","alphaFac","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","newData","oW","oH","sliceByTwo","hermiteFastResize","bilinearFiltering","lanczosResize","tmpCanvas","doneW","doneH","stepW","stepH","dX","dY","srcData","destImg","destData","lanczos","ratioX","ratioY","rcpRatioX","rcpRatioY","range2X","range2Y","cacheLanc","icenter","process","u","weight","fX","fY","xDiff","yDiff","chnl","origPix","w4","pixels","destImage","destPixels","ratioW","ratioH","ratioWHalf","ratioHHalf","img2","data2","weightsAlpha","gxR","gxG","gxB","gxA","yy","w0","Contrast","contrast","contrastF","uContrast","Saturation","saturation","adjust","uSaturation","Vibrance","vibrance","avg","amt","uVibrance","Blur","aspectRatio","simpleBlur","canvas2","blurLayer1","blurLayer2","percent","ctx1","ctx2","newImageData","delta","chooseRightDelta","blurScale","Gamma","gamma","rInv","gInv","bInv","rVals","gVals","bVals","uGamma","uniform3fv","Composed","subFilters","HueRotation","rotation","rad","aThird","aThirdSqtSin","OneMinusCos","additionalProps","_dimensionAffectingProps","_reNewline","_reSpacesAndTabs","_reSpaceAndTab","_reWords","textAlign","superscript","baseline","subscript","pathStartOffset","pathSide","pathAlign","_fontSizeFraction","_fontSizeMult","charSpacing","_measuringContext","direction","_styleProperties","__charBounds","CACHE_FONT_SIZE","MIN_TEXT_WIDTH","__skipDimension","setPathInfo","initDimensions","segmentsInfo","getMeasuringContext","_splitText","newLines","_splitTextIntoLines","_textLines","graphemeLines","_unwrappedTextLines","_unwrappedLines","_text","graphemeText","_clearCache","calcTextWidth","cursorWidth","calcTextHeight","enlargeSpaces","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","heightOfLine","lineLeftOffset","lastColor","charBox","currentColor","drawStart","leftOffset","_getLeftOffset","lineTopOffset","_getTopOffset","boxStart","boxWidth","_getLineLeftOffset","getValueOfPropertyAt","renderLeft","getFontCache","cacheProp","_measureChar","_char","previousChar","prevCharStyle","coupleWidth","previousWidth","fontCache","couple","stylesAreEqual","fontMultiplier","measureText","getHeightOfChar","measureLine","lineInfo","_measureLine","_getWidthOfCharSpacing","grapheme","prevGrapheme","graphemeInfo","startingPoint","totalPathLength","lineBounds","positionInPath","_getGraphemeBox","_setGraphemeOnPath","numOfSpaces","centerPosition","skipLeft","getCompleteStyleDeclaration","previousBox","__lineHeights","maxHeight","_renderTextCommon","lineHeights","isEmptyStyles","actualStyle","nextStyle","timeToRender","drawingLeft","isJustify","charsToRender","shortCut","isLtr","currentDirection","_renderChar","_applyPatternGradientTransformText","handleFiller","fillOffsets","strokeOffsets","_getStyleDeclaration","fullDecl","shouldFill","fillText","strokeText","setSuperscript","_setScript","setSubscript","schema","loc","get2DCursorLocation","setSelectionStyles","lineDiff","__lineWidths","_shouldClearDimensionCache","shouldClear","_forceClearCache","_size","_dy","lastDecoration","currentDecoration","currentFill","lastFill","topOffset","styleObject","family","fontIsGeneric","genericFonts","newLine","newText","allProperties","needsDims","isAddingPath","_key","parsedAnchor","textAnchor","originalStrokeWidth","textHeightScaleFactor","scaledDiff","textHeight","offX","objectCopy","textInstance","pathInstance","p3","cleanStyle","letterCount","stylePropertyValue","stylesCount","allStyleObjectPropertiesMatch","graphemeCount","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","hiddenTextareaContainer","_reSpace","_currentCursorOpacity","_selectionDirection","_abortCursorAnimation","__widthOfSpace","inCompositionMode","initBehavior","setSelectionStart","_updateAndFire","setSelectionEnd","_fireSelectionChanged","_updateTextarea","initDelayedCursor","cursorOffsetCache","renderCursorOrSelection","skipRestore","_clearTextArea","boundaries","_getCursorBoundaries","renderCursor","renderSelection","_getCursorBoundariesOffsets","cursorPosition","bound","cursorLocation","charHeight","__isMousedown","hiddenTextarea","startLine","endLine","startChar","endChar","realLineHeight","lineOffset","boxEnd","drawWidth","drawHeight","extraTop","compositionColor","getCurrentCharFontSize","cp","_getCurrentCharIndex","getCurrentCharColor","objCopy","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","selectWord","newSelectionStart","newSelectionEnd","selectLine","enterEditing","exitEditingOnOthers","initHiddenTextarea","focus","_saveEditingProps","_setEditingProps","_textBeforeEdit","initMouseMoveHandler","activeElement","getSelectionStartFromPointer","currentStart","currentEnd","__selectionStartOnMouseDown","restartCursorIfNeeded","fromStringToGraphemeSelection","smallerTextStart","graphemeStart","smallerTextEnd","fromGraphemeToStringSelection","newSelection","updateTextareaPosition","updateFromTextArea","_calcTextareaPosition","desiredPosition","compositionStart","upperCanvas","upperCanvasWidth","upperCanvasHeight","clientWidth","clientHeight","_savedProps","_restoreEditingProps","isTextChanged","_removeExtraneousStyles","removeStyleFromTo","styleObj","cursorStart","cursorEnd","lineStart","charStart","lineEnd","charEnd","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","keysMapRtl","ctrlKeysMapUp","ctrlKeysMapDown","keyMap","keyCode","ctrlKey","metaKey","stopImmediatePropagation","_copyDone","fromPaste","removedText","removeFrom","removeTo","nextText","charCount","nextCharCount","charDiff","textareaSelection","backDelete","copiedText","copiedTextStyle","compositionEnd","_getClipboardData","clipboardData","_getWidthBeforeCursor","widthBeforeCursor","getDownCursorOffset","isRight","selectionProp","_getSelectionForOffset","indexOnOtherLine","_getIndexOnLine","getUpCursorOffset","textBeforeCursor","charWidth","foundMatch","widthOfCharsOnLine","indexOnLine","leftEdge","rightEdge","offsetFromLeftEdge","moveCursorDown","_moveCursorUpOrDown","moveCursorUp","moveCursorWithShift","moveCursorWithoutShift","moveCursorLeft","_moveCursorLeftOrRight","_move","_moveLeft","_moveRight","moveCursorLeftWithoutShift","change","moveCursorLeftWithShift","moveCursorRight","moveCursorRightWithShift","moveCursorRightWithoutShift","changed","removeChars","insertChars","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","lineTop","textSpans","textTopOffset","textLeftOffset","_setSVGTextLineBg","_setSVGTextLineText","_createTextCharSpan","styleDecl","shouldUseWhitespace","styleProps","fillStyles","dySpan","_pushTextBgRect","fillColor","_getSVGLineTopOffset","lastHeight","Textbox","minWidth","dynamicMinWidth","__cachedLines","_wordJoiners","splitByGrapheme","_styleMap","_generateStyleMap","textInfo","realLineCount","realLineCharCount","isWrapping","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","ReactRouter5Adapter","useLocation","history","useHistory","location2","search","state","location"],"sourceRoot":""}