{"version":3,"file":"pwc-375.3237a742.chunk.js","mappings":"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","sources":["../node_modules/fabric-webpack/dist/fabric.js","../node_modules/querystring/decode.js","../node_modules/querystring/encode.js","../node_modules/querystring/index.js","../node_modules/url/node_modules/punycode/punycode.js","../node_modules/url/url.js","../node_modules/url/util.js"],"sourcesContent":["/* build: `node build.js modules=ALL exclude=json,gestures minifier=uglifyjs` */\n/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */\n\nvar fabric = fabric || { version: \"1.6.0-rc.1\" };\nif (typeof exports !== 'undefined') {\n exports.fabric = fabric;\n}\n\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\n fabric.document = document;\n fabric.window = window;\n // ensure globality even if entire library were function wrapped (as in Meteor.js packaging system)\n window.fabric = fabric;\n}\nelse {\n // assume we're running under node.js when document/window are not present\n fabric.document = require(\"jsdom\")\n .jsdom(\"\");\n\n if (fabric.document.createWindow) {\n fabric.window = fabric.document.createWindow();\n } else {\n fabric.window = fabric.document.parentWindow;\n }\n}\n\n/**\n * True when in environment that supports touch events\n * @type boolean\n */\nfabric.isTouchSupported = \"ontouchstart\" in fabric.document.documentElement;\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\",\n \"stroke-linejoin\", \"stroke-miterlimit\",\n \"stroke-opacity\", \"stroke-width\",\n \"id\"\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+)(?:e[-+]?\\\\d+)?)';\n\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\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\n if (handler) {\n fabric.util.removeFromArray(this.__eventListeners[eventName], handler);\n }\n else {\n this.__eventListeners[eventName].length = 0;\n }\n }\n\n /**\n * Observes specified event\n * @deprecated `observe` deprecated since 0.8.34 (use `on` instead)\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 observe(eventName, handler) {\n if (!this.__eventListeners) {\n this.__eventListeners = { };\n }\n // one object with key/value pairs was passed\n if (arguments.length === 1) {\n for (var prop in eventName) {\n this.on(prop, eventName[prop]);\n }\n }\n else {\n if (!this.__eventListeners[eventName]) {\n this.__eventListeners[eventName] = [ ];\n }\n this.__eventListeners[eventName].push(handler);\n }\n return this;\n }\n\n /**\n * Stops event observing for a particular event handler. Calling this method\n * without arguments removes all handlers for all events\n * @deprecated `stopObserving` deprecated since 0.8.34 (use `off` instead)\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 stopObserving(eventName, handler) {\n if (!this.__eventListeners) {\n return;\n }\n\n // remove all key/value pairs (event name -> event handler)\n if (arguments.length === 0) {\n this.__eventListeners = { };\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 * @deprecated `fire` deprecated since 1.0.7 (use `trigger` instead)\n * @memberOf fabric.Observable\n * @alias trigger\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;\n }\n\n var listenersForEvent = this.__eventListeners[eventName];\n if (!listenersForEvent) {\n return;\n }\n\n for (var i = 0, len = listenersForEvent.length; i < len; i++) {\n // avoiding try/catch for perf. reasons\n listenersForEvent[i].call(this, options || { });\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 observe: observe,\n stopObserving: stopObserving,\n fire: fire,\n\n on: observe,\n off: stopObserving,\n trigger: fire\n };\n})();\n\n\n/**\n * @namespace fabric.Collection\n */\nfabric.Collection = {\n\n /**\n * Adds objects to collection, then renders canvas (if `renderOnAddRemove` is not `false`)\n * Objects should be instances of (or inherit from) fabric.Object\n * @param {...fabric.Object} object Zero or more fabric instances\n * @return {Self} thisArg\n */\n add: function () {\n this._objects.push.apply(this._objects, arguments);\n for (var i = 0, length = arguments.length; i < length; i++) {\n this._onObjectAdded(arguments[i]);\n }\n this.renderOnAddRemove && this.renderAll();\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 * @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.getObjects();\n if (nonSplicing) {\n objects[index] = object;\n }\n else {\n objects.splice(index, 0, object);\n }\n this._onObjectAdded(object);\n this.renderOnAddRemove && this.renderAll();\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.getObjects(),\n index;\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 objects.splice(index, 1);\n this._onObjectRemoved(arguments[i]);\n }\n }\n\n this.renderOnAddRemove && this.renderAll();\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 * Iteration happens in reverse order (for performance reasons).\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 */\n forEachObject: function(callback, context) {\n var objects = this.getObjects(),\n i = objects.length;\n while (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 * @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;\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.getObjects()[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.getObjects().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.getObjects().length;\n },\n\n /**\n * Returns true if collection contains an object\n * @param {Object} object Object to check against\n * @return {Boolean} `true` if collection contains an object\n */\n contains: function(object) {\n return this.getObjects().indexOf(object) > -1;\n },\n\n /**\n * Returns number representation of a collection complexity\n * @return {Number} complexity\n */\n complexity: function () {\n return this.getObjects().reduce(function (memo, current) {\n memo += current.complexity ? current.complexity() : 0;\n return memo;\n }, 0);\n }\n};\n\n\n(function(global) {\n\n var sqrt = Math.sqrt,\n atan2 = Math.atan2,\n PiBy180 = Math.PI / 180;\n\n /**\n * @namespace fabric.util\n */\n fabric.util = {\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 {Any} value\n * @return {Array} original array\n */\n removeFromArray: function(array, value) {\n var idx = array.indexOf(value);\n if (idx !== -1) {\n array.splice(idx, 1);\n }\n return array;\n },\n\n /**\n * Returns random number between 2 specified ones.\n * @static\n * @memberOf fabric.util\n * @param {Number} min lower limit\n * @param {Number} max upper limit\n * @return {Number} random value (between min and max)\n */\n getRandomInt: function(min, max) {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n },\n\n /**\n * Transforms degrees to radians.\n * @static\n * @memberOf fabric.util\n * @param {Number} degrees value in degrees\n * @return {Number} value in radians\n */\n degreesToRadians: function(degrees) {\n return degrees * PiBy180;\n },\n\n /**\n * Transforms radians to degrees.\n * @static\n * @memberOf fabric.util\n * @param {Number} radians value in radians\n * @return {Number} value in degrees\n */\n radiansToDegrees: function(radians) {\n return radians / PiBy180;\n },\n\n /**\n * Rotates `point` around `origin` with `radians`\n * @static\n * @memberOf fabric.util\n * @param {fabric.Point} point The point to rotate\n * @param {fabric.Point} origin The origin of the rotation\n * @param {Number} radians The radians of the angle for the rotation\n * @return {fabric.Point} The new rotated point\n */\n rotatePoint: function(point, origin, radians) {\n point.subtractEquals(origin);\n var sin = Math.sin(radians),\n cos = Math.cos(radians),\n rx = point.x * cos - point.y * sin,\n ry = point.x * sin + point.y * cos;\n return new fabric.Point(rx, ry).addEquals(origin);\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 * 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 * @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 object of given namespace\n * @memberOf fabric.util\n * @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric'\n * @return {Object} Object for given namespace (default fabric)\n */\n resolveNamespace: function(namespace) {\n if (!namespace) {\n return fabric;\n }\n\n var parts = namespace.split('.'),\n len = parts.length,\n obj = global || fabric.window;\n\n for (var 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 {Any} [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 img.onload = function () {\n callback && callback.call(context, img);\n img = img.onload = img.onerror = null;\n };\n\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 if (url.indexOf('data') !== 0 && typeof crossOrigin !== 'undefined') {\n img.crossOrigin = crossOrigin;\n }\n\n img.src = url;\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 function onLoaded() {\n if (++numLoadedObjects === numTotalObjects) {\n callback && callback(enlivenedObjects);\n }\n }\n\n var enlivenedObjects = [ ],\n numLoadedObjects = 0,\n numTotalObjects = objects.length;\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 if (klass.async) {\n klass.fromObject(o, function (obj, error) {\n if (!error) {\n enlivenedObjects[index] = obj;\n reviver && reviver(o, enlivenedObjects[index]);\n }\n onLoaded();\n });\n }\n else {\n enlivenedObjects[index] = klass.fromObject(o);\n reviver && reviver(o, enlivenedObjects[index]);\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 * @return {fabric.Object|fabric.PathGroup}\n */\n groupSVGElements: function(elements, options, path) {\n var object;\n\n object = new fabric.PathGroup(elements, options);\n\n if (typeof path !== 'undefined') {\n object.setSourcePath(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 Propertie names to include\n */\n populateWithProperties: function(source, destination, properties) {\n if (properties && Object.prototype.toString.call(properties) === '[object Array]') {\n for (var i = 0, len = properties.length; i < len; i++) {\n if (properties[i] in source) {\n destination[properties[i]] = source[properties[i]];\n }\n }\n }\n },\n\n /**\n * Draws a dashed line between two points\n *\n * This method is used to draw dashed line around selection area.\n * See dotted stroke in canvas\n *\n * @param {CanvasRenderingContext2D} ctx context\n * @param {Number} x start x coordinate\n * @param {Number} y start y coordinate\n * @param {Number} x2 end x coordinate\n * @param {Number} y2 end y coordinate\n * @param {Array} da dash array pattern\n */\n drawDashedLine: function(ctx, x, y, x2, y2, da) {\n var dx = x2 - x,\n dy = y2 - y,\n len = sqrt(dx * dx + dy * dy),\n rot = atan2(dy, dx),\n dc = da.length,\n di = 0,\n draw = true;\n\n ctx.save();\n ctx.translate(x, y);\n ctx.moveTo(0, 0);\n ctx.rotate(rot);\n\n x = 0;\n while (len > x) {\n x += da[di++ % dc];\n if (x > len) {\n x = len;\n }\n ctx[draw ? 'lineTo' : 'moveTo'](x, 0);\n draw = !draw;\n }\n\n ctx.restore();\n },\n\n /**\n * Creates canvas element and initializes it via excanvas if necessary\n * @static\n * @memberOf fabric.util\n * @param {CanvasElement} [canvasEl] optional canvas element to initialize;\n * when not given, element is created implicitly\n * @return {CanvasElement} initialized canvas element\n */\n createCanvasElement: function(canvasEl) {\n canvasEl || (canvasEl = fabric.document.createElement('canvas'));\n //jscs:disable requireCamelCaseOrUpperCaseIdentifiers\n if (!canvasEl.getContext && typeof G_vmlCanvasManager !== 'undefined') {\n G_vmlCanvasManager.initElement(canvasEl);\n }\n //jscs:enable requireCamelCaseOrUpperCaseIdentifiers\n return canvasEl;\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.isLikelyNode\n ? new (require('canvas').Image)()\n : fabric.document.createElement('img');\n },\n\n /**\n * Creates accessors (getXXX, setXXX) for a \"class\", based on \"stateProperties\" array\n * @static\n * @memberOf fabric.util\n * @param {Object} klass \"Class\" to create accessors for\n */\n createAccessors: function(klass) {\n var proto = klass.prototype;\n\n for (var i = proto.stateProperties.length; i--; ) {\n\n var propName = proto.stateProperties[i],\n capitalizedPropName = propName.charAt(0).toUpperCase() + propName.slice(1),\n setterName = 'set' + capitalizedPropName,\n getterName = 'get' + capitalizedPropName;\n\n // using `new Function` for better introspection\n if (!proto[getterName]) {\n proto[getterName] = (function(property) {\n return new Function('return this.get(\"' + property + '\")');\n })(propName);\n }\n if (!proto[setterName]) {\n proto[setterName] = (function(property) {\n return new Function('value', 'return this.set(\"' + property + '\", value)');\n })(propName);\n }\n }\n },\n\n /**\n * @static\n * @memberOf fabric.util\n * @param {fabric.Object} receiver Object implementing `clipTo` method\n * @param {CanvasRenderingContext2D} ctx Context to clip\n */\n clipContext: function(receiver, ctx) {\n ctx.save();\n ctx.beginPath();\n receiver.clipTo(ctx);\n ctx.clip();\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 * @return {Array} The product of the two transform matrices\n */\n multiplyTransformMatrices: function(a, b) {\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 a[0] * b[4] + a[2] * b[5] + a[4],\n a[1] * b[4] + a[3] * b[5] + a[5]\n ];\n },\n\n /**\n * Returns string representation of function body\n * @param {Function} fn Function to get body of\n * @return {String} Function body\n */\n getFunctionBody: function(fn) {\n return (String(fn).match(/function[^{]*\\{([\\s\\S]*)\\}/) || {})[1];\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,\n imageData = ctx.getImageData(x, y, (tolerance * 2) || 1, (tolerance * 2) || 1);\n\n // Split image data - for tolerance > 1, pixelDataSize = 4;\n for (var i = 3, l = imageData.data.length; i < l; i += 4) {\n var 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})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n var arcToSegmentsCache = { },\n segmentToBezierCache = { },\n boundsOfCurveCache = { },\n _join = Array.prototype.join;\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 argsString = _join.call(arguments);\n if (arcToSegmentsCache[argsString]) {\n return arcToSegmentsCache[argsString];\n }\n\n var PI = Math.PI, th = rotateX * PI / 180,\n sinTh = Math.sin(th),\n cosTh = Math.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][4];\n fromY = result[i][5];\n mTheta = th3;\n th3 += mDelta;\n }\n arcToSegmentsCache[argsString] = result;\n return result;\n }\n\n function segmentToBezier(th2, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY) {\n var argsString2 = _join.call(arguments);\n if (segmentToBezierCache[argsString2]) {\n return segmentToBezierCache[argsString2];\n }\n\n var costh2 = Math.cos(th2),\n sinth2 = Math.sin(th2),\n costh3 = Math.cos(th3),\n sinth3 = Math.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 segmentToBezierCache[argsString2] = [\n cp1X, cp1Y,\n cp2X, cp2Y,\n toX, toY\n ];\n return segmentToBezierCache[argsString2];\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 * Draws arc\n * @param {CanvasRenderingContext2D} ctx\n * @param {Number} fx\n * @param {Number} fy\n * @param {Array} coords\n */\n fabric.util.drawArc = function(ctx, fx, fy, coords) {\n var rx = coords[0],\n ry = coords[1],\n rot = coords[2],\n large = coords[3],\n sweep = coords[4],\n tx = coords[5],\n ty = coords[6],\n segs = [[ ], [ ], [ ], [ ]],\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 segs[i][0] = segsNorm[i][0] + fx;\n segs[i][1] = segsNorm[i][1] + fy;\n segs[i][2] = segsNorm[i][2] + fx;\n segs[i][3] = segsNorm[i][3] + fy;\n segs[i][4] = segsNorm[i][4] + fx;\n segs[i][5] = segsNorm[i][5] + fy;\n ctx.bezierCurveTo.apply(ctx, segs[i]);\n }\n };\n\n /**\n * Calculate bounding box of a elliptic-arc\n * @param {Number} fx start point of arc\n * @param {Number} fy\n * @param {Number} rx horizontal radius\n * @param {Number} ry vertical radius\n * @param {Number} rot angle of horizontal axe\n * @param {Number} large 1 or 0, whatever the arc is the big or the small on the 2 points\n * @param {Number} sweep 1 or 0, 1 clockwise or counterclockwise direction\n * @param {Number} tx end point of arc\n * @param {Number} ty\n */\n fabric.util.getBoundsOfArc = function(fx, fy, rx, ry, rot, large, sweep, tx, ty) {\n\n var fromX = 0, fromY = 0, bound = [ ], bounds = [ ],\n segs = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot),\n boundCopy = [[ ], [ ]];\n\n for (var i = 0, len = segs.length; i < len; i++) {\n bound = getBoundsOfCurve(fromX, fromY, segs[i][0], segs[i][1], segs[i][2], segs[i][3], segs[i][4], segs[i][5]);\n boundCopy[0].x = bound[0].x + fx;\n boundCopy[0].y = bound[0].y + fy;\n boundCopy[1].x = bound[1].x + fx;\n boundCopy[1].y = bound[1].y + fy;\n bounds.push(boundCopy[0]);\n bounds.push(boundCopy[1]);\n fromX = segs[i][4];\n fromY = segs[i][5];\n }\n return bounds;\n };\n\n /**\n * Calculate bounding box of a beziercurve\n * @param {Number} x0 starting point\n * @param {Number} y0\n * @param {Number} x1 first control point\n * @param {Number} y1\n * @param {Number} x2 secondo control point\n * @param {Number} y2\n * @param {Number} x3 end of beizer\n * @param {Number} y3\n */\n // taken from http://jsbin.com/ivomiq/56/edit no credits available for that.\n function getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3) {\n var argsString = _join.call(arguments);\n if (boundsOfCurveCache[argsString]) {\n return boundsOfCurveCache[argsString];\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 boundsOfCurveCache[argsString] = result;\n return result;\n }\n\n fabric.util.getBoundsOfCurve = getBoundsOfCurve;\n\n})();\n\n\n(function() {\n\n var slice = Array.prototype.slice;\n\n /* _ES5_COMPAT_START_ */\n\n if (!Array.prototype.indexOf) {\n /**\n * Finds index of an element in an array\n * @param {Any} searchElement\n * @param {Number} [fromIndex]\n * @return {Number}\n */\n Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {\n if (this === void 0 || this === null) {\n throw new TypeError();\n }\n var t = Object(this), len = t.length >>> 0;\n if (len === 0) {\n return -1;\n }\n var n = 0;\n if (arguments.length > 0) {\n n = Number(arguments[1]);\n if (n !== n) { // shortcut for verifying if it's NaN\n n = 0;\n }\n else if (n !== 0 && n !== Number.POSITIVE_INFINITY && n !== Number.NEGATIVE_INFINITY) {\n n = (n > 0 || -1) * Math.floor(Math.abs(n));\n }\n }\n if (n >= len) {\n return -1;\n }\n var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);\n for (; k < len; k++) {\n if (k in t && t[k] === searchElement) {\n return k;\n }\n }\n return -1;\n };\n }\n\n if (!Array.prototype.forEach) {\n /**\n * Iterates an array, invoking callback for each element\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Array}\n */\n Array.prototype.forEach = function(fn, context) {\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this) {\n fn.call(context, this[i], i, this);\n }\n }\n };\n }\n\n if (!Array.prototype.map) {\n /**\n * Returns a result of iterating over an array, invoking callback for each element\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Array}\n */\n Array.prototype.map = function(fn, context) {\n var result = [ ];\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this) {\n result[i] = fn.call(context, this[i], i, this);\n }\n }\n return result;\n };\n }\n\n if (!Array.prototype.every) {\n /**\n * Returns true if a callback returns truthy value for all elements in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Boolean}\n */\n Array.prototype.every = function(fn, context) {\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this && !fn.call(context, this[i], i, this)) {\n return false;\n }\n }\n return true;\n };\n }\n\n if (!Array.prototype.some) {\n /**\n * Returns true if a callback returns truthy value for at least one element in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Boolean}\n */\n Array.prototype.some = function(fn, context) {\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this && fn.call(context, this[i], i, this)) {\n return true;\n }\n }\n return false;\n };\n }\n\n if (!Array.prototype.filter) {\n /**\n * Returns the result of iterating over elements in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Array}\n */\n Array.prototype.filter = function(fn, context) {\n var result = [ ], val;\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this) {\n val = this[i]; // in case fn mutates this\n if (fn.call(context, val, i, this)) {\n result.push(val);\n }\n }\n }\n return result;\n };\n }\n\n if (!Array.prototype.reduce) {\n /**\n * Returns \"folded\" (reduced) result of iterating over elements in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [initial] Object to use as the first argument to the first call of the callback\n * @return {Any}\n */\n Array.prototype.reduce = function(fn /*, initial*/) {\n var len = this.length >>> 0,\n i = 0,\n rv;\n\n if (arguments.length > 1) {\n rv = arguments[1];\n }\n else {\n do {\n if (i in this) {\n rv = this[i++];\n break;\n }\n // if array contains no values, no initial value to return\n if (++i >= len) {\n throw new TypeError();\n }\n }\n while (true);\n }\n for (; i < len; i++) {\n if (i in this) {\n rv = fn.call(null, rv, this[i], i, this);\n }\n }\n return rv;\n };\n }\n\n /* _ES5_COMPAT_END_ */\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 {Any}\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 {Any}\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 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 invoke: invoke,\n min: min,\n max: max\n };\n\n})();\n\n\n(function() {\n\n /**\n * Copies all enumerable properties of one object to another\n * @memberOf fabric.util.object\n * @param {Object} destination Where to copy to\n * @param {Object} source Where to copy from\n * @return {Object}\n */\n function extend(destination, source) {\n // JScript DontEnum bug is not taken care of\n for (var property in source) {\n destination[property] = source[property];\n }\n return destination;\n }\n\n /**\n * Creates an empty object and copies all enumerable properties of another object to it\n * @memberOf fabric.util.object\n * @param {Object} object Object to clone\n * @return {Object}\n */\n function clone(object) {\n return extend({ }, object);\n }\n\n /** @namespace fabric.util.object */\n fabric.util.object = {\n extend: extend,\n clone: clone\n };\n\n})();\n\n\n(function() {\n\n /* _ES5_COMPAT_START_ */\n if (!String.prototype.trim) {\n /**\n * Trims a string (removing whitespace from the beginning and the end)\n * @function external:String#trim\n * @see String#trim on MDN\n */\n String.prototype.trim = function () {\n // this trim is not fully ES3 or ES5 compliant, but it should cover most cases for now\n return this.replace(/^[\\s\\xA0]+/, '').replace(/[\\s\\xA0]+$/, '');\n };\n }\n /* _ES5_COMPAT_END_ */\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 * String utilities\n * @namespace fabric.util.string\n */\n fabric.util.string = {\n camelize: camelize,\n capitalize: capitalize,\n escapeXml: escapeXml\n };\n}());\n\n\n/* _ES5_COMPAT_START_ */\n(function() {\n\n var slice = Array.prototype.slice,\n apply = Function.prototype.apply,\n Dummy = function() { };\n\n if (!Function.prototype.bind) {\n /**\n * Cross-browser approximation of ES5 Function.prototype.bind (not fully spec conforming)\n * @see Function#bind on MDN\n * @param {Object} thisArg Object to bind function to\n * @param {Any[]} [...] Values to pass to a bound function\n * @return {Function}\n */\n Function.prototype.bind = function(thisArg) {\n var _this = this, args = slice.call(arguments, 1), bound;\n if (args.length) {\n bound = function() {\n return apply.call(_this, this instanceof Dummy ? this : thisArg, args.concat(slice.call(arguments)));\n };\n }\n else {\n /** @ignore */\n bound = function() {\n return apply.call(_this, this instanceof Dummy ? this : thisArg, arguments);\n };\n }\n Dummy.prototype = this.prototype;\n bound.prototype = new Dummy();\n\n return bound;\n };\n }\n\n})();\n/* _ES5_COMPAT_END_ */\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 fn = this.constructor.superclass.prototype[methodName];\n return (arguments.length > 1)\n ? fn.apply(this, slice.call(arguments, 1))\n : fn.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\n var unknown = 'unknown';\n\n /* EVENT HANDLING */\n\n function areHostMethods(object) {\n var methodNames = Array.prototype.slice.call(arguments, 1),\n t, i, len = methodNames.length;\n for (i = 0; i < len; i++) {\n t = typeof object[methodNames[i]];\n if (!(/^(?:function|object|unknown)$/).test(t)) {\n return false;\n }\n }\n return true;\n }\n\n /** @ignore */\n var getElement,\n setElement,\n getUniqueId = (function () {\n var uid = 0;\n return function (element) {\n return element.__uniqueID || (element.__uniqueID = 'uniqueID__' + uid++);\n };\n })();\n\n (function () {\n var elements = { };\n /** @ignore */\n getElement = function (uid) {\n return elements[uid];\n };\n /** @ignore */\n setElement = function (uid, element) {\n elements[uid] = element;\n };\n })();\n\n function createListener(uid, handler) {\n return {\n handler: handler,\n wrappedHandler: createWrappedHandler(uid, handler)\n };\n }\n\n function createWrappedHandler(uid, handler) {\n return function (e) {\n handler.call(getElement(uid), e || fabric.window.event);\n };\n }\n\n function createDispatcher(uid, eventName) {\n return function (e) {\n if (handlers[uid] && handlers[uid][eventName]) {\n var handlersForEvent = handlers[uid][eventName];\n for (var i = 0, len = handlersForEvent.length; i < len; i++) {\n handlersForEvent[i].call(this, e || fabric.window.event);\n }\n }\n };\n }\n\n var shouldUseAddListenerRemoveListener = (\n areHostMethods(fabric.document.documentElement, 'addEventListener', 'removeEventListener') &&\n areHostMethods(fabric.window, 'addEventListener', 'removeEventListener')),\n\n shouldUseAttachEventDetachEvent = (\n areHostMethods(fabric.document.documentElement, 'attachEvent', 'detachEvent') &&\n areHostMethods(fabric.window, 'attachEvent', 'detachEvent')),\n\n // IE branch\n listeners = { },\n\n // DOM L0 branch\n handlers = { },\n\n addListener, removeListener;\n\n if (shouldUseAddListenerRemoveListener) {\n /** @ignore */\n addListener = function (element, eventName, handler) {\n element.addEventListener(eventName, handler, false);\n };\n /** @ignore */\n removeListener = function (element, eventName, handler) {\n element.removeEventListener(eventName, handler, false);\n };\n }\n\n else if (shouldUseAttachEventDetachEvent) {\n /** @ignore */\n addListener = function (element, eventName, handler) {\n var uid = getUniqueId(element);\n setElement(uid, element);\n if (!listeners[uid]) {\n listeners[uid] = { };\n }\n if (!listeners[uid][eventName]) {\n listeners[uid][eventName] = [ ];\n\n }\n var listener = createListener(uid, handler);\n listeners[uid][eventName].push(listener);\n element.attachEvent('on' + eventName, listener.wrappedHandler);\n };\n /** @ignore */\n removeListener = function (element, eventName, handler) {\n var uid = getUniqueId(element), listener;\n if (listeners[uid] && listeners[uid][eventName]) {\n for (var i = 0, len = listeners[uid][eventName].length; i < len; i++) {\n listener = listeners[uid][eventName][i];\n if (listener && listener.handler === handler) {\n element.detachEvent('on' + eventName, listener.wrappedHandler);\n listeners[uid][eventName][i] = null;\n }\n }\n }\n };\n }\n else {\n /** @ignore */\n addListener = function (element, eventName, handler) {\n var uid = getUniqueId(element);\n if (!handlers[uid]) {\n handlers[uid] = { };\n }\n if (!handlers[uid][eventName]) {\n handlers[uid][eventName] = [ ];\n var existingHandler = element['on' + eventName];\n if (existingHandler) {\n handlers[uid][eventName].push(existingHandler);\n }\n element['on' + eventName] = createDispatcher(uid, eventName);\n }\n handlers[uid][eventName].push(handler);\n };\n /** @ignore */\n removeListener = function (element, eventName, handler) {\n var uid = getUniqueId(element);\n if (handlers[uid] && handlers[uid][eventName]) {\n var handlersForEvent = handlers[uid][eventName];\n for (var i = 0, len = handlersForEvent.length; i < len; i++) {\n if (handlersForEvent[i] === handler) {\n handlersForEvent.splice(i, 1);\n }\n }\n }\n };\n }\n\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 = addListener;\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 = removeListener;\n\n /**\n * Cross-browser wrapper for getting event's coordinates\n * @memberOf fabric.util\n * @param {Event} event Event object\n */\n function getPointer(event) {\n event || (event = fabric.window.event);\n\n var element = event.target ||\n (typeof event.srcElement !== unknown ? event.srcElement : null),\n\n scroll = fabric.util.getScrollLeftTop(element);\n\n return {\n x: pointerX(event) + scroll.left,\n y: pointerY(event) + scroll.top\n };\n }\n\n var pointerX = function(event) {\n // looks like in IE (<9) clientX at certain point (apparently when mouseup fires on VML element)\n // is represented as COM object, with all the consequences, like \"unknown\" type and error on [[Get]]\n // need to investigate later\n return (typeof event.clientX !== unknown ? event.clientX : 0);\n },\n\n pointerY = function(event) {\n return (typeof event.clientY !== unknown ? event.clientY : 0);\n };\n\n function _getPointer(event, pageProp, clientProp) {\n var touchProp = event.type === 'touchend' ? 'changedTouches' : 'touches';\n\n return (event[touchProp] && event[touchProp][0]\n ? (event[touchProp][0][pageProp] - (event[touchProp][0][pageProp] - event[touchProp][0][clientProp]))\n || event[clientProp]\n : event[clientProp]);\n }\n\n if (fabric.isTouchSupported) {\n pointerX = function(event) {\n return _getPointer(event, 'pageX', 'clientX');\n };\n pointerY = function(event) {\n return _getPointer(event, 'pageY', 'clientY');\n };\n }\n\n fabric.util.getPointer = getPointer;\n\n fabric.util.object.extend(fabric.util, fabric.Observable);\n\n})();\n\n\n(function () {\n\n /**\n * Cross-browser wrapper for setting element's style\n * @memberOf fabric.util\n * @param {HTMLElement} element\n * @param {Object} styles\n * @return {HTMLElement} Element that was passed as a first argument\n */\n function setStyle(element, styles) {\n var elementStyle = element.style;\n if (!elementStyle) {\n return element;\n }\n if (typeof styles === 'string') {\n element.style.cssText += ';' + styles;\n return styles.indexOf('opacity') > -1\n ? setOpacity(element, styles.match(/opacity:\\s*(\\d?\\.?\\d*)/)[1])\n : element;\n }\n for (var property in styles) {\n if (property === 'opacity') {\n setOpacity(element, styles[property]);\n }\n else {\n var normalizedProperty = (property === 'float' || property === 'cssFloat')\n ? (typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat')\n : property;\n elementStyle[normalizedProperty] = styles[property];\n }\n }\n return element;\n }\n\n var parseEl = fabric.document.createElement('div'),\n supportsOpacity = typeof parseEl.style.opacity === 'string',\n supportsFilters = typeof parseEl.style.filter === 'string',\n reOpacity = /alpha\\s*\\(\\s*opacity\\s*=\\s*([^\\)]+)\\)/,\n\n /** @ignore */\n setOpacity = function (element) { return element; };\n\n if (supportsOpacity) {\n /** @ignore */\n setOpacity = function(element, value) {\n element.style.opacity = value;\n return element;\n };\n }\n else if (supportsFilters) {\n /** @ignore */\n setOpacity = function(element, value) {\n var es = element.style;\n if (element.currentStyle && !element.currentStyle.hasLayout) {\n es.zoom = 1;\n }\n if (reOpacity.test(es.filter)) {\n value = value >= 0.9999 ? '' : ('alpha(opacity=' + (value * 100) + ')');\n es.filter = es.filter.replace(reOpacity, value);\n }\n else {\n es.filter += ' alpha(opacity=' + (value * 100) + ')';\n }\n return element;\n };\n }\n\n fabric.util.setStyle = setStyle;\n\n})();\n\n\n(function() {\n\n var _slice = Array.prototype.slice;\n\n /**\n * Takes id and returns an element with that id (if one exists in a document)\n * @memberOf fabric.util\n * @param {String|HTMLElement} id\n * @return {HTMLElement|null}\n */\n function getById(id) {\n return typeof id === 'string' ? fabric.document.getElementById(id) : id;\n }\n\n var sliceCanConvertNodelists,\n /**\n * Converts an array-like object (e.g. arguments or NodeList) to an array\n * @memberOf fabric.util\n * @param {Object} arrayLike\n * @return {Array}\n */\n toArray = function(arrayLike) {\n return _slice.call(arrayLike, 0);\n };\n\n try {\n sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array;\n }\n catch (err) { }\n\n if (!sliceCanConvertNodelists) {\n toArray = function(arrayLike) {\n var arr = new Array(arrayLike.length), i = arrayLike.length;\n while (i--) {\n arr[i] = arrayLike[i];\n }\n return arr;\n };\n }\n\n /**\n * Creates specified element with specified attributes\n * @memberOf fabric.util\n * @param {String} tagName Type of an element to create\n * @param {Object} [attributes] Attributes to set on an element\n * @return {HTMLElement} Newly created element\n */\n function makeElement(tagName, attributes) {\n var el = fabric.document.createElement(tagName);\n for (var prop in attributes) {\n if (prop === 'class') {\n el.className = attributes[prop];\n }\n else if (prop === 'for') {\n el.htmlFor = attributes[prop];\n }\n else {\n el.setAttribute(prop, attributes[prop]);\n }\n }\n return el;\n }\n\n /**\n * Adds class to an element\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to add class to\n * @param {String} className Class to add to an element\n */\n function addClass(element, className) {\n if (element && (' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) {\n element.className += (element.className ? ' ' : '') + className;\n }\n }\n\n /**\n * Wraps element with another element\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to wrap\n * @param {HTMLElement|String} wrapper Element to wrap with\n * @param {Object} [attributes] Attributes to set on a wrapper\n * @return {HTMLElement} wrapper\n */\n function wrapElement(element, wrapper, attributes) {\n if (typeof wrapper === 'string') {\n wrapper = makeElement(wrapper, attributes);\n }\n if (element.parentNode) {\n element.parentNode.replaceChild(wrapper, element);\n }\n wrapper.appendChild(element);\n return wrapper;\n }\n\n /**\n * Returns element scroll offsets\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to operate on\n * @return {Object} Object with left/top values\n */\n function getScrollLeftTop(element) {\n\n var left = 0,\n top = 0,\n docElement = fabric.document.documentElement,\n body = fabric.document.body || {\n scrollLeft: 0, scrollTop: 0\n };\n\n while (element && element.parentNode) {\n\n element = element.parentNode;\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 &&\n fabric.util.getElementStyle(element, '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() {\n\n /**\n * Inserts a script element with a given url into a document; invokes callback, when that script is finished loading\n * @memberOf fabric.util\n * @param {String} url URL of a script to load\n * @param {Function} callback Callback to execute when script is finished loading\n */\n function getScript(url, callback) {\n var headEl = fabric.document.getElementsByTagName('head')[0],\n scriptEl = fabric.document.createElement('script'),\n loading = true;\n\n /** @ignore */\n scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) {\n if (loading) {\n if (typeof this.readyState === 'string' &&\n this.readyState !== 'loaded' &&\n this.readyState !== 'complete') {\n return;\n }\n loading = false;\n callback(e || fabric.window.event);\n scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null;\n }\n };\n scriptEl.src = url;\n headEl.appendChild(scriptEl);\n // causes issue in Opera\n // headEl.removeChild(scriptEl);\n }\n\n fabric.util.getScript = getScript;\n })();\n\n fabric.util.getById = getById;\n fabric.util.toArray = toArray;\n fabric.util.makeElement = makeElement;\n fabric.util.addClass = addClass;\n fabric.util.wrapElement = wrapElement;\n fabric.util.getScrollLeftTop = getScrollLeftTop;\n fabric.util.getElementOffset = getElementOffset;\n fabric.util.getElementStyle = getElementStyle;\n\n})();\n\n\n(function() {\n\n function addParamToUrl(url, param) {\n return url + (/\\?/.test(url) ? '&' : '?') + param;\n }\n\n var makeXHR = (function() {\n var factories = [\n function() { return new ActiveXObject('Microsoft.XMLHTTP'); },\n function() { return new ActiveXObject('Msxml2.XMLHTTP'); },\n function() { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); },\n function() { return new XMLHttpRequest(); }\n ];\n for (var i = factories.length; i--; ) {\n try {\n var req = factories[i]();\n if (req) {\n return factories[i];\n }\n }\n catch (err) { }\n }\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 {Function} options.onComplete Callback to invoke when request is completed\n * @return {XMLHttpRequest} request\n */\n function request(url, options) {\n\n options || (options = { });\n\n var method = options.method ? options.method.toUpperCase() : 'GET',\n onComplete = options.onComplete || function() { },\n xhr = makeXHR(),\n body;\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 {Any} [values] Values to log\n */\nfabric.log = function() { };\n\n/**\n * Wrapper around `console.warn` (when available)\n * @param {Any} [values] Values to log as a warning\n */\nfabric.warn = function() { };\n\n/* jshint ignore:start */\nif (typeof console !== 'undefined') {\n\n ['log', 'warn'].forEach(function(methodName) {\n\n if (typeof console[methodName] !== 'undefined' &&\n typeof console[methodName].apply === 'function') {\n\n fabric[methodName] = function() {\n return console[methodName].apply(console, arguments);\n };\n }\n });\n}\n/* jshint ignore:end */\n\n\n(function() {\n\n /**\n * Changes value from one to another within certain period of time, invoking callbacks as value is being changed.\n * @memberOf fabric.util\n * @param {Object} [options] Animation options\n * @param {Function} [options.onChange] Callback; invoked on every value change\n * @param {Function} [options.onComplete] Callback; invoked when value change is completed\n * @param {Number} [options.startValue=0] Starting value\n * @param {Number} [options.endValue=100] Ending value\n * @param {Number} [options.byValue=100] Value to modify the property by\n * @param {Function} [options.easing] Easing function\n * @param {Number} [options.duration=500] Duration of change (in ms)\n */\n function animate(options) {\n\n requestAnimFrame(function(timestamp) {\n options || (options = { });\n\n var start = timestamp || +new Date(),\n duration = options.duration || 500,\n finish = start + duration, time,\n onChange = options.onChange || function() { },\n abort = options.abort || function() { return false; },\n easing = options.easing || function(t, b, c, d) {return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;},\n startValue = 'startValue' in options ? options.startValue : 0,\n endValue = 'endValue' in options ? options.endValue : 100,\n byValue = options.byValue || endValue - startValue;\n\n options.onStart && options.onStart();\n\n (function tick(ticktime) {\n time = ticktime || +new Date();\n var currentTime = time > finish ? duration : (time - start);\n if (abort()) {\n options.onComplete && options.onComplete();\n return;\n }\n onChange(easing(currentTime, startValue, byValue, duration));\n if (time > finish) {\n options.onComplete && options.onComplete();\n return;\n }\n requestAnimFrame(tick);\n })(start);\n });\n\n }\n\n var _requestAnimFrame = fabric.window.requestAnimationFrame ||\n fabric.window.webkitRequestAnimationFrame ||\n fabric.window.mozRequestAnimationFrame ||\n fabric.window.oRequestAnimationFrame ||\n fabric.window.msRequestAnimationFrame ||\n function(callback) {\n fabric.window.setTimeout(callback, 1000 / 60);\n };\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 fabric.util.animate = animate;\n fabric.util.requestAnimFrame = requestAnimFrame;\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 s = p / (2 * Math.PI) * Math.asin(c / a);\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 capitalize = fabric.util.string.capitalize,\n clone = fabric.util.object.clone,\n toFixed = fabric.util.toFixed,\n parseUnit = fabric.util.parseUnit,\n multiplyTransformMatrices = fabric.util.multiplyTransformMatrices,\n\n reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/i,\n reViewBoxTagNames = /^(symbol|image|marker|pattern|view|svg)$/i,\n reNotAllowedAncestors = /^(?:pattern|defs|symbol|metadata)$/i,\n reAllowedParents = /^(symbol|g|a|svg)$/i,\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 'stroke-dasharray': 'strokeDashArray',\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': 'originX'\n },\n\n colorAttributes = {\n stroke: 'strokeOpacity',\n fill: 'fillOpacity'\n };\n\n fabric.cssRules = { };\n fabric.gradientDefs = { };\n\n function normalizeAttr(attr) {\n // transform attribute names\n if (attr in attributesMap) {\n return attributesMap[attr];\n }\n return attr;\n }\n\n function normalizeValue(attr, value, parentAttributes, fontSize) {\n var isArray = Object.prototype.toString.call(value) === '[object Array]',\n parsed;\n\n if ((attr === 'fill' || attr === 'stroke') && value === 'none') {\n value = '';\n }\n else if (attr === 'strokeDashArray') {\n value = value.replace(/,/g, ' ').split(/\\s+/).map(function(n) {\n return parseFloat(n);\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') ? false : true;\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 === 'originX' /* text-anchor */) {\n value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center';\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 * @param {Object} attributes Array of attributes to parse\n */\n function _setStrokeFillOpacity(attributes) {\n for (var attr in colorAttributes) {\n\n if (!attributes[attr] || typeof attributes[colorAttributes[attr]] === 'undefined') {\n continue;\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 * 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 angle = args[0];\n\n matrix[0] = Math.cos(angle);\n matrix[1] = Math.sin(angle);\n matrix[2] = -Math.sin(angle);\n matrix[3] = Math.cos(angle);\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 skewXMatrix(matrix, args) {\n matrix[2] = Math.tan(fabric.util.degreesToRadians(args[0]));\n }\n\n function skewYMatrix(matrix, args) {\n matrix[1] = 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 = [\n 1, // a\n 0, // b\n 0, // c\n 1, // d\n 0, // e\n 0 // f\n ],\n\n // == begin transform regexp\n number = fabric.reNum,\n\n commaWsp = '(?:\\\\s+,?\\\\s*|,\\\\s*)',\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 return (match !== '' && match != null);\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 skewXMatrix(matrix, args);\n break;\n case 'skewY':\n skewYMatrix(matrix, args);\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 = normalizeAttr(pair[0].trim().toLowerCase());\n value = normalizeValue(attr, 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 = normalizeAttr(prop.toLowerCase());\n value = normalizeValue(attr, 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;\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 (var 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\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, idAttr, nodelist = doc.getElementsByTagName('*');\n for (i = 0; i < nodelist.length; i++) {\n node = nodelist[i];\n if (idAttr === node.getAttribute('id')) {\n return node;\n }\n }\n }\n\n /**\n * @private\n */\n function parseUseDirectives(doc) {\n var nodelist = doc.getElementsByTagName('use'), i = 0;\n while (nodelist.length && i < nodelist.length) {\n var el = nodelist[i],\n xlink = el.getAttribute('xlink:href').substr(1),\n x = el.getAttribute('x') || 0,\n y = el.getAttribute('y') || 0,\n el2 = elementById(doc, xlink).cloneNode(true),\n currentTrans = (el2.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')',\n parentNode, oldLength = nodelist.length, attr, j, attrs, l;\n\n applyViewboxTransform(el2);\n if (/^svg$/i.test(el2.nodeName)) {\n var el3 = el2.ownerDocument.createElement('g');\n for (j = 0, attrs = el2.attributes, l = attrs.length; j < l; j++) {\n attr = attrs.item(j);\n el3.setAttribute(attr.nodeName, attr.nodeValue);\n }\n while (el2.firstChild != null) {\n el3.appendChild(el2.firstChild);\n }\n el2 = el3;\n }\n\n for (j = 0, attrs = el.attributes, l = attrs.length; j < l; j++) {\n attr = attrs.item(j);\n if (attr.nodeName === 'x' || attr.nodeName === 'y' || attr.nodeName === 'xlink: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\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 missingViewBox = (!viewBoxAttr || !reViewBoxTagNames.test(element.tagName)\n || !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))),\n missingDimAttr = (!widthAttr || !heightAttr || widthAttr === '100%' || heightAttr === '100%'),\n toBeParsed = missingViewBox && missingDimAttr,\n parsedDim = { };\n\n parsedDim.width = 0;\n parsedDim.height = 0;\n parsedDim.toBeParsed = toBeParsed;\n\n if (toBeParsed) {\n return parsedDim;\n }\n\n if (missingViewBox) {\n parsedDim.width = parseUnit(widthAttr);\n parsedDim.height = parseUnit(heightAttr);\n return parsedDim;\n }\n\n minX = -parseFloat(viewBoxAttr[1]),\n minY = -parseFloat(viewBoxAttr[2]),\n viewBoxWidth = parseFloat(viewBoxAttr[3]),\n viewBoxHeight = parseFloat(viewBoxAttr[4]);\n\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 attribute to be implemented\n scaleY = scaleX = (scaleX > scaleY ? scaleY : scaleX);\n\n if (scaleX === 1 && scaleY === 1 && minX === 0 && minY === 0) {\n return parsedDim;\n }\n\n matrix = ' matrix(' + scaleX +\n ' 0' +\n ' 0 ' +\n scaleY + ' ' +\n (minX * scaleX) + ' ' +\n (minY * scaleY) + ') ';\n\n if (element.tagName === 'svg') {\n el = element.ownerDocument.createElement('g');\n while (element.firstChild != null) {\n el.appendChild(element.firstChild);\n }\n element.appendChild(el);\n }\n else {\n el = element;\n matrix = el.getAttribute('transform') + matrix;\n }\n\n el.setAttribute('transform', matrix);\n return parsedDim;\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; 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 */\n fabric.parseSVGDocument = (function() {\n\n function hasAncestorWithNodeName(element, nodeName) {\n while (element && (element = element.parentNode)) {\n if (nodeName.test(element.nodeName) && !element.getAttribute('instantiated_by_use')) {\n return true;\n }\n }\n return false;\n }\n\n return function(doc, callback, reviver) {\n if (!doc) {\n return;\n }\n\n parseUseDirectives(doc);\n\n var startTime = new Date(),\n svgUid = fabric.Object.__uid++,\n options = applyViewboxTransform(doc),\n descendants = fabric.util.toArray(doc.getElementsByTagName('*'));\n\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 (var 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 reAllowedSVGTagNames.test(el.tagName) &&\n !hasAncestorWithNodeName(el, reNotAllowedAncestors); // http://www.w3.org/TR/SVG/struct.html#DefsElement\n });\n\n if (!elements || (elements && !elements.length)) {\n callback && callback([], {});\n return;\n }\n\n fabric.gradientDefs[svgUid] = fabric.getGradientDefs(doc);\n fabric.cssRules[svgUid] = fabric.getCSSRules(doc);\n // Precedence of rules: style > class > attribute\n fabric.parseElements(elements, function(instances) {\n fabric.documentParsingTime = new Date() - startTime;\n if (callback) {\n callback(instances, options);\n }\n }, clone(options), reviver);\n };\n })();\n\n /**\n * Used for caching SVG documents (loaded via `fabric.Canvas#loadSVGFromURL`)\n * @namespace\n */\n var svgCache = {\n\n /**\n * @param {String} name\n * @param {Function} callback\n */\n has: function (name, callback) {\n callback(false);\n },\n\n get: function () {\n /* NOOP */\n },\n\n set: function () {\n /* NOOP */\n }\n };\n\n /**\n * @private\n */\n function _enlivenCachedObject(cachedObject) {\n\n var objects = cachedObject.objects,\n options = cachedObject.options;\n\n objects = objects.map(function (o) {\n return fabric[capitalize(o.type)].fromObject(o);\n });\n\n return ({ objects: objects, options: options });\n }\n\n /**\n * @private\n */\n function _createSVGPattern(markup, canvas, property) {\n if (canvas[property] && canvas[property].toSVG) {\n markup.push(\n '',\n ''\n );\n }\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 linearGradientEls = doc.getElementsByTagName('linearGradient'),\n radialGradientEls = doc.getElementsByTagName('radialGradient'),\n el, i, j = 0, id, xlink, elList = [ ],\n gradientDefs = { }, idsToXlinkMap = { };\n\n elList.length = linearGradientEls.length + radialGradientEls.length;\n i = linearGradientEls.length;\n while (i--) {\n elList[j++] = linearGradientEls[i];\n }\n i = radialGradientEls.length;\n while (i--) {\n elList[j++] = radialGradientEls[i];\n }\n\n while (j--) {\n el = elList[j];\n xlink = el.getAttribute('xlink:href');\n id = el.getAttribute('id');\n if (xlink) {\n idsToXlinkMap[id] = xlink.substr(1);\n }\n gradientDefs[id] = el;\n }\n\n for (id in idsToXlinkMap) {\n var el2 = gradientDefs[idsToXlinkMap[id]].cloneNode(true);\n el = gradientDefs[id];\n while (el2.firstChild) {\n el.appendChild(el2.firstChild);\n }\n }\n return gradientDefs;\n },\n\n /**\n * Returns an object of attributes' name/value, given element and an array of attribute names;\n * Parses parent \"g\" nodes recursively upwards.\n * @static\n * @memberOf fabric\n * @param {DOMElement} element Element to parse\n * @param {Array} attributes Array of attributes to parse\n * @return {Object} object containing parsed attributes' names/values\n */\n parseAttributes: function(element, attributes, svgUid) {\n\n if (!element) {\n return;\n }\n\n var value,\n parentAttributes = { },\n fontSize;\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 && reAllowedParents.test(element.parentNode.nodeName)) {\n parentAttributes = fabric.parseAttributes(element.parentNode, attributes, svgUid);\n }\n fontSize = (parentAttributes && parentAttributes.fontSize ) ||\n element.getAttribute('font-size') || fabric.Text.DEFAULT_SVG_FONT_SIZE;\n\n var ownAttributes = attributes.reduce(function(memo, attr) {\n value = element.getAttribute(attr);\n if (value) {\n attr = normalizeAttr(attr);\n value = normalizeValue(attr, value, parentAttributes, fontSize);\n\n memo[attr] = value;\n }\n return memo;\n }, { });\n\n // add values parsed from style, which take precedence over attributes\n // (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes)\n ownAttributes = extend(ownAttributes,\n extend(getGlobalStylesForElement(element, svgUid), fabric.parseStyleAttribute(element)));\n if (ownAttributes.font) {\n fabric.parseFontDeclaration(ownAttributes.font, ownAttributes);\n }\n return _setStrokeFillOpacity(extend(parentAttributes, ownAttributes));\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) {\n new fabric.ElementsParser(elements, callback, options, reviver).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 i = 0;\n len = points.length;\n for (; 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'),\n allRules = { }, rules;\n\n // very crude parsing of style contents\n for (var 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 rules = styleContents.match(/[^{]*\\{[\\s\\S]*?\\}/g);\n rules = rules.map(function(rule) { return rule.trim(); });\n\n rules.forEach(function(rule) {\n\n var match = rule.match(/([\\s\\S]*?)\\s*\\{([^}]*)\\}/),\n ruleObj = { }, declaration = match[2].trim(),\n propertyValuePairs = declaration.replace(/;$/, '').split(/\\s*;\\s*/);\n\n for (var i = 0, len = propertyValuePairs.length; i < len; i++) {\n var pair = propertyValuePairs[i].split(/\\s*:\\s*/),\n property = normalizeAttr(pair[0]),\n value = normalizeValue(property, pair[1], pair[0]);\n ruleObj[property] = value;\n }\n rule = match[1];\n rule.split(',').forEach(function(_rule) {\n _rule = _rule.replace(/^svg/i, '').trim();\n if (_rule === '') {\n return;\n }\n allRules[_rule] = fabric.util.object.clone(ruleObj);\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. 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 */\n loadSVGFromURL: function(url, callback, reviver) {\n\n url = url.replace(/^\\n\\s*/, '').trim();\n svgCache.has(url, function (hasUrl) {\n if (hasUrl) {\n svgCache.get(url, function (value) {\n var enlivedRecord = _enlivenCachedObject(value);\n callback(enlivedRecord.objects, enlivedRecord.options);\n });\n }\n else {\n new fabric.util.request(url, {\n method: 'get',\n onComplete: onComplete\n });\n }\n });\n\n function onComplete(r) {\n\n var xml = r.responseXML;\n if (xml && !xml.documentElement && fabric.window.ActiveXObject && r.responseText) {\n xml = new ActiveXObject('Microsoft.XMLDOM');\n xml.async = 'false';\n //IE chokes on DOCTYPE\n xml.loadXML(r.responseText.replace(//i, ''));\n }\n if (!xml || !xml.documentElement) {\n return;\n }\n\n fabric.parseSVGDocument(xml.documentElement, function (results, options) {\n svgCache.set(url, {\n objects: fabric.util.array.invoke(results, 'toObject'),\n options: options\n });\n callback(results, options);\n }, reviver);\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 */\n loadSVGFromString: function(string, callback, reviver) {\n string = string.trim();\n var doc;\n if (typeof DOMParser !== 'undefined') {\n var parser = new DOMParser();\n if (parser && parser.parseFromString) {\n doc = parser.parseFromString(string, 'text/xml');\n }\n }\n else if (fabric.window.ActiveXObject) {\n doc = new ActiveXObject('Microsoft.XMLDOM');\n doc.async = 'false';\n // IE chokes on DOCTYPE\n doc.loadXML(string.replace(//i, ''));\n }\n\n fabric.parseSVGDocument(doc.documentElement, function (results, options) {\n callback(results, options);\n }, reviver);\n },\n\n /**\n * Creates markup containing SVG font faces\n * @param {Array} objects Array of fabric objects\n * @return {String}\n */\n createSVGFontFacesMarkup: function(objects) {\n var markup = '';\n\n for (var i = 0, len = objects.length; i < len; i++) {\n if (objects[i].type !== 'text' || !objects[i].path) {\n continue;\n }\n\n markup += [\n //jscs:disable validateIndentation\n '@font-face {',\n 'font-family: ', objects[i].fontFamily, '; ',\n 'src: url(\\'', objects[i].path, '\\')',\n '}'\n //jscs:enable validateIndentation\n ].join('');\n }\n\n if (markup) {\n markup = [\n //jscs:disable validateIndentation\n ''\n //jscs:enable validateIndentation\n ].join('');\n }\n\n return markup;\n },\n\n /**\n * Creates markup containing SVG referenced elements like patterns, gradients etc.\n * @param {fabric.Canvas} canvas instance of fabric.Canvas\n * @return {String}\n */\n createSVGRefElementsMarkup: function(canvas) {\n var markup = [ ];\n\n _createSVGPattern(markup, canvas, 'backgroundColor');\n _createSVGPattern(markup, canvas, 'overlayColor');\n\n return markup.join('');\n }\n });\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\nfabric.ElementsParser = function(elements, callback, options, reviver) {\n this.elements = elements;\n this.callback = callback;\n this.options = options;\n this.reviver = reviver;\n this.svgUid = (options && options.svgUid) || 0;\n};\n\nfabric.ElementsParser.prototype.parse = function() {\n this.instances = new Array(this.elements.length);\n this.numElements = this.elements.length;\n\n this.createObjects();\n};\n\nfabric.ElementsParser.prototype.createObjects = function() {\n for (var i = 0, len = this.elements.length; i < len; i++) {\n this.elements[i].setAttribute('svgUid', this.svgUid);\n (function(_this, i) {\n setTimeout(function() {\n _this.createObject(_this.elements[i], i);\n }, 0);\n })(this, i);\n }\n};\n\nfabric.ElementsParser.prototype.createObject = function(el, index) {\n var klass = fabric[fabric.util.string.capitalize(el.tagName)];\n if (klass && klass.fromElement) {\n try {\n this._createObject(klass, el, index);\n }\n catch (err) {\n fabric.log(err);\n }\n }\n else {\n this.checkIfDone();\n }\n};\n\nfabric.ElementsParser.prototype._createObject = function(klass, el, index) {\n if (klass.async) {\n klass.fromElement(el, this.createCallback(index, el), this.options);\n }\n else {\n var obj = klass.fromElement(el, this.options);\n this.resolveGradient(obj, 'fill');\n this.resolveGradient(obj, 'stroke');\n this.reviver && this.reviver(el, obj);\n this.instances[index] = obj;\n this.checkIfDone();\n }\n};\n\nfabric.ElementsParser.prototype.createCallback = function(index, el) {\n var _this = this;\n return function(obj) {\n _this.resolveGradient(obj, 'fill');\n _this.resolveGradient(obj, 'stroke');\n _this.reviver && _this.reviver(el, obj);\n _this.instances[index] = obj;\n _this.checkIfDone();\n };\n};\n\nfabric.ElementsParser.prototype.resolveGradient = function(obj, property) {\n\n var instanceFillValue = obj.get(property);\n if (!(/^url\\(/).test(instanceFillValue)) {\n return;\n }\n var gradientId = instanceFillValue.slice(5, instanceFillValue.length - 1);\n if (fabric.gradientDefs[this.svgUid][gradientId]) {\n obj.set(property,\n fabric.Gradient.fromElement(fabric.gradientDefs[this.svgUid][gradientId], obj));\n }\n};\n\nfabric.ElementsParser.prototype.checkIfDone = function() {\n if (--this.numElements === 0) {\n this.instances = this.instances.filter(function(el) {\n return el != null;\n });\n this.callback(this.instances);\n }\n};\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 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 */\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 */\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 */\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 */\n scalarSubtractEquals: function (scalar) {\n this.x -= scalar;\n this.y -= scalar;\n return this;\n },\n\n /**\n * Miltiplies this point by a value and returns a new one\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 * Miltiplies this point by a value\n * @param {Number} scalar\n * @return {fabric.Point} thisArg\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 * @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 * @param {Number} scalar\n * @return {fabric.Point} thisArg\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\n * @return {fabric.Point}\n */\n lerp: function (that, t) {\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 new Point(this.x + (that.x - this.x)/2, this.y + (that.y - this.y)/2);\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 */\n setXY: function (x, y) {\n this.x = x;\n this.y = y;\n },\n\n /**\n * Sets x/y of this point from another point\n * @param {fabric.Point} that\n */\n setFromPoint: function (that) {\n this.x = that.x;\n this.y = that.y;\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})(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 /**\n * Appends a point to intersection\n * @param {fabric.Point} point\n */\n appendPoint: function (point) {\n this.points.push(point);\n },\n\n /**\n * Appends points to intersection\n * @param {Array} points\n */\n appendPoints: function (points) {\n this.points = this.points.concat(points);\n }\n };\n\n /**\n * Checks if one line intersects another\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.points.push(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 * @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\n for (var i = 0; i < length; i++) {\n var 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;\n\n for (var 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 {Number} r1\n * @param {Number} 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) format\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 this.setSource([255, 255, 255, 0]);\n return;\n }\n\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 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 represenation 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 represenation 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 represenation 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 represenation 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 represenation 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 * 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();\n\n for (var 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 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*)?\\)$/;\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*)?\\)$/;\n\n /**\n * Regex matching color in HEX format (ex: #FF5555, 010155, aff)\n * @static\n * @field\n * @memberOf fabric.Color\n */\n fabric.Color.reHex = /^#?([0-9a-f]{6}|[0-9a-f]{3})$/i;\n\n /**\n * Map of the 17 basic color names with HEX code\n * @static\n * @field\n * @memberOf fabric.Color\n * @see: http://www.w3.org/TR/CSS2/syndata.html#color-units\n */\n fabric.Color.colorNameMap = {\n aqua: '#00FFFF',\n black: '#000000',\n blue: '#0000FF',\n fuchsia: '#FF00FF',\n gray: '#808080',\n green: '#008000',\n lime: '#00FF00',\n maroon: '#800000',\n navy: '#000080',\n olive: '#808000',\n orange: '#FFA500',\n purple: '#800080',\n red: '#FF0000',\n silver: '#C0C0C0',\n teal: '#008080',\n white: '#FFFFFF',\n yellow: '#FFFF00'\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 represenatation (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 represenatation (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 represenatation (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\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),\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\n return [\n parseInt(r, 16),\n parseInt(g, 16),\n parseInt(b, 16),\n 1\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() {\n\n /* _FROM_SVG_START_ */\n function getColorStop(el) {\n var style = el.getAttribute('style'),\n offset = el.getAttribute('offset'),\n color, colorAlpha, opacity;\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 (var 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;\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 /**\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 * Constructor\n * @param {Object} [options] Options object with type, coords, gradientUnits and colorStops\n * @return {fabric.Gradient} thisArg\n */\n initialize: function(options) {\n options || (options = { });\n\n var coords = { };\n\n this.id = fabric.Object.__uid++;\n this.type = options.type || 'linear';\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 this.coords = coords;\n this.colorStops = options.colorStops.slice();\n if (options.gradientTransform) {\n this.gradientTransform = options.gradientTransform;\n }\n this.offsetX = options.offsetX || this.offsetX;\n this.offsetY = options.offsetY || this.offsetY;\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(colorStop) {\n for (var position in colorStop) {\n var color = new fabric.Color(colorStop[position]);\n this.colorStops.push({\n offset: 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 * @return {Object}\n */\n toObject: function() {\n return {\n type: this.type,\n coords: this.coords,\n colorStops: this.colorStops,\n offsetX: this.offsetX,\n offsetY: this.offsetY\n };\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 * @param {Boolean} normalize Whether coords should be normalized\n * @return {String} SVG representation of an gradient (linear/radial)\n */\n toSVG: function(object) {\n var coords = fabric.util.object.clone(this.coords),\n markup, commonAttributes;\n\n // colorStops must be sorted ascending\n this.colorStops.sort(function(a, b) {\n return a.offset - b.offset;\n });\n\n if (!(object.group && object.group.type === 'path-group')) {\n for (var prop in coords) {\n if (prop === 'x1' || prop === 'x2' || prop === 'r2') {\n coords[prop] += this.offsetX - object.width / 2;\n }\n else if (prop === 'y1' || prop === 'y2') {\n coords[prop] += this.offsetY - object.height / 2;\n }\n }\n }\n\n commonAttributes = 'id=\"SVGID_' + this.id +\n '\" gradientUnits=\"userSpaceOnUse\"';\n if (this.gradientTransform) {\n commonAttributes += ' gradientTransform=\"matrix(' + this.gradientTransform.join(' ') + ')\" ';\n }\n if (this.type === 'linear') {\n markup = [\n //jscs:disable validateIndentation\n '\\n'\n //jscs:enable validateIndentation\n ];\n }\n else if (this.type === 'radial') {\n markup = [\n //jscs:disable validateIndentation\n '\\n'\n //jscs:enable validateIndentation\n ];\n }\n\n for (var i = 0; i < this.colorStops.length; i++) {\n markup.push(\n //jscs:disable validateIndentation\n '\\n'\n //jscs:enable validateIndentation\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, object) {\n var gradient, prop, coords = fabric.util.object.clone(this.coords);\n\n if (!this.type) {\n return;\n }\n\n if (object.group && object.group.type === 'path-group') {\n for (prop in coords) {\n if (prop === 'x1' || prop === 'x2') {\n coords[prop] += -this.offsetX + object.width / 2;\n }\n else if (prop === 'y1' || prop === 'y2') {\n coords[prop] += -this.offsetY + object.height / 2;\n }\n }\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 (var 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(parseFloat(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 * @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) {\n\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 colorStopEls = el.getElementsByTagName('stop'),\n type = (el.nodeName === 'linearGradient' ? 'linear' : 'radial'),\n gradientUnits = el.getAttribute('gradientUnits') || 'objectBoundingBox',\n gradientTransform = el.getAttribute('gradientTransform'),\n colorStops = [],\n coords = { }, ellipseMatrix;\n\n if (type === 'linear') {\n coords = getLinearCoords(el);\n }\n else if (type === 'radial') {\n coords = getRadialCoords(el);\n }\n\n for (var i = colorStopEls.length; i--; ) {\n colorStops.push(getColorStop(colorStopEls[i]));\n }\n\n ellipseMatrix = _convertPercentUnitsToValues(instance, coords, gradientUnits);\n\n var gradient = new fabric.Gradient({\n type: type,\n coords: coords,\n colorStops: colorStops,\n offsetX: -instance.left,\n offsetY: -instance.top\n });\n\n if (gradientTransform || ellipseMatrix !== '') {\n gradient.gradientTransform = fabric.parseTransformAttribute((gradientTransform || '') + ellipseMatrix);\n }\n return gradient;\n },\n /* _FROM_SVG_END_ */\n\n /**\n * Returns {@link fabric.Gradient} instance from its object representation\n * @static\n * @memberOf fabric.Gradient\n * @param {Object} obj\n * @param {Object} [options] Options object\n */\n forObject: function(obj, options) {\n options || (options = { });\n _convertPercentUnitsToValues(obj, options.coords, 'userSpaceOnUse');\n return new fabric.Gradient(options);\n }\n });\n\n /**\n * @private\n */\n function _convertPercentUnitsToValues(object, options, gradientUnits) {\n var propValue, addFactor = 0, multFactor = 1, ellipseMatrix = '';\n for (var prop in options) {\n propValue = parseFloat(options[prop], 10);\n if (typeof options[prop] === 'string' && /^\\d+%$/.test(options[prop])) {\n multFactor = 0.01;\n }\n else {\n multFactor = 1;\n }\n if (prop === 'x1' || prop === 'x2' || prop === 'r2') {\n multFactor *= gradientUnits === 'objectBoundingBox' ? object.width : 1;\n addFactor = gradientUnits === 'objectBoundingBox' ? object.left || 0 : 0;\n }\n else if (prop === 'y1' || prop === 'y2') {\n multFactor *= gradientUnits === 'objectBoundingBox' ? object.height : 1;\n addFactor = gradientUnits === 'objectBoundingBox' ? object.top || 0 : 0;\n }\n options[prop] = propValue * multFactor + addFactor;\n }\n if (object.type === 'ellipse' &&\n options.r2 !== null &&\n gradientUnits === 'objectBoundingBox' &&\n object.rx !== object.ry) {\n\n var scaleFactor = object.ry/object.rx;\n ellipseMatrix = ' scale(1, ' + scaleFactor + ')';\n if (options.y1) {\n options.y1 /= scaleFactor;\n }\n if (options.y2) {\n options.y2 /= scaleFactor;\n }\n }\n return ellipseMatrix;\n }\n})();\n\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 */\nfabric.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 * Constructor\n * @param {Object} [options] Options object\n * @return {fabric.Pattern} thisArg\n */\n initialize: function(options) {\n options || (options = { });\n\n this.id = fabric.Object.__uid++;\n\n if (options.source) {\n if (typeof options.source === 'string') {\n // function string\n if (typeof fabric.util.getFunctionBody(options.source) !== 'undefined') {\n this.source = new Function(fabric.util.getFunctionBody(options.source));\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) {\n _this.source = img;\n });\n }\n }\n else {\n // img element\n this.source = options.source;\n }\n }\n if (options.repeat) {\n this.repeat = options.repeat;\n }\n if (options.offsetX) {\n this.offsetX = options.offsetX;\n }\n if (options.offsetY) {\n this.offsetY = options.offsetY;\n }\n },\n\n /**\n * Returns object representation of a pattern\n * @return {Object} Object representation of a pattern instance\n */\n toObject: function() {\n\n var source;\n\n // callback\n if (typeof this.source === 'function') {\n source = String(this.source);\n }\n // element\n else 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 return {\n source: source,\n repeat: this.repeat,\n offsetX: this.offsetX,\n offsetY: this.offsetY\n };\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.getWidth(),\n patternHeight = patternSource.height / object.getHeight(),\n patternOffsetX = this.offsetX / object.getWidth(),\n patternOffsetY = this.offsetY / object.getHeight(),\n patternImgSrc = '';\n if (this.repeat === 'repeat-x' || this.repeat === 'no-repeat') {\n patternHeight = 1;\n }\n if (this.repeat === 'repeat-y' || this.repeat === 'no-repeat') {\n patternWidth = 1;\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 /**\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 = typeof this.source === 'function'\n ? this.source()\n : this.source;\n\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(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 * Constructor\n * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetX properties or string (e.g. \"rgba(0,0,0,0.2) 2px 2px 10px, \"2px 2px 10px rgba(0,0,0,0.2)\")\n * @return {fabric.Shadow} thisArg\n */\n initialize: function(options) {\n\n if (typeof options === 'string') {\n options = this._parseShadow(options);\n }\n\n for (var prop in options) {\n this[prop] = options[prop];\n }\n\n this.id = fabric.Object.__uid++;\n },\n\n /**\n * @private\n * @param {String} shadow Shadow value to parse\n * @return {Object} Shadow object with color, offsetX, offsetY and blur\n */\n _parseShadow: function(shadow) {\n var shadowStr = shadow.trim(),\n offsetsAndBlur = fabric.Shadow.reOffsetsAndBlur.exec(shadowStr) || [ ],\n color = shadowStr.replace(fabric.Shadow.reOffsetsAndBlur, '') || 'rgb(0,0,0)';\n\n return {\n color: color.trim(),\n offsetX: parseInt(offsetsAndBlur[1], 10) || 0,\n offsetY: parseInt(offsetsAndBlur[2], 10) || 0,\n blur: parseInt(offsetsAndBlur[3], 10) || 0\n };\n },\n\n /**\n * Returns a string representation of an instance\n * @see http://www.w3.org/TR/css-text-decor-3/#text-shadow\n * @return {String} Returns CSS3 text-shadow declaration\n */\n toString: function() {\n return [this.offsetX, this.offsetY, this.blur, this.color].join('px ');\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of a shadow\n * @param {fabric.Object} object\n * @return {String} SVG representation of a shadow\n */\n toSVG: function(object) {\n var fBoxX = 40, fBoxY = 40;\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(this.offsetX) + this.blur) / object.width, 2) * 100 + 20;\n fBoxY = toFixed((Math.abs(this.offsetY) + this.blur) / object.height, 2) * 100 + 20;\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 };\n }\n var obj = { }, proto = fabric.Shadow.prototype;\n if (this.color !== proto.color) {\n obj.color = this.color;\n }\n if (this.blur !== proto.blur) {\n obj.blur = this.blur;\n }\n if (this.offsetX !== proto.offsetX) {\n obj.offsetX = this.offsetX;\n }\n if (this.offsetY !== proto.offsetY) {\n obj.offsetY = this.offsetY;\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 fabric.Shadow.reOffsetsAndBlur = /(?:\\s|^)(-?\\d+(?:px)?(?:\\s?|$))?(-?\\d+(?:px)?(?:\\s?|$))?(\\d+(?:px)?)?(?:\\s?|$)(?:$|\\s)/;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function () {\n\n 'use strict';\n\n if (fabric.StaticCanvas) {\n fabric.warn('fabric.StaticCanvas is already defined.');\n return;\n }\n\n // aliases for faster resolution\n var extend = fabric.util.object.extend,\n getElementOffset = fabric.util.getElementOffset,\n removeFromArray = fabric.util.removeFromArray,\n\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(/** @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\n this._initStatic(el, options);\n fabric.StaticCanvas.activeInstance = this;\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 * Should be set via {@link fabric.StaticCanvas#setBackgroundImage}.\n * Backwards incompatibility note: The \"backgroundImageOpacity\"\n * and \"backgroundImageStretch\" properties are deprecated since 1.3.9.\n * Use {@link fabric.Image#opacity}, {@link fabric.Image#width} and {@link fabric.Image#height}.\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 * Should be set via {@link fabric.StaticCanvas#setOverlayImage}.\n * Backwards incompatibility note: The \"overlayImageLeft\"\n * and \"overlayImageTop\" properties are deprecated since 1.3.9.\n * Use {@link fabric.Image#left} and {@link fabric.Image#top}.\n * @type fabric.Image\n * @default\n */\n overlayImage: null,\n\n /**\n * Indicates whether toObject/toDatalessObject should include default values\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: true,\n\n /**\n * Indicates whether {@link fabric.Collection.add}, {@link fabric.Collection.insertAt} and {@link fabric.Collection.remove} should also re-render canvas.\n * Disabling this option could give a great performance boost when adding/removing a lot of objects to/from canvas at once\n * (followed by a manual rendering after addition/deletion)\n * @type Boolean\n * @default\n */\n renderOnAddRemove: true,\n\n /**\n * Function that determines clipping of entire canvas area\n * Being passed context as first argument. See clipping canvas area in {@link https://github.com/kangax/fabric.js/wiki/FAQ}\n * @type Function\n * @default\n */\n clipTo: null,\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 * Indicates whether objects should remain in current stack position when selected. 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 * The transformation (in the format of Canvas transform) which focuses the viewport\n * @type Array\n * @default\n */\n viewportTransform: [1, 0, 0, 1, 0, 0],\n\n /**\n * Callback; invoked right before object is about to be scaled/rotated\n */\n onBeforeScaleRotate: function () {\n /* NOOP */\n },\n\n /**\n * When true, canvas is scaled by devicePixelRatio for better rendering on retina screens\n */\n enableRetinaScaling: true,\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 this._objects = [];\n\n this._createLowerCanvas(el);\n this._initOptions(options);\n this._setImageSmoothing();\n\n // only initialize retina scaling once\n if (!this.interactive) {\n this._initRetinaScaling();\n }\n\n if (options.overlayImage) {\n this.setOverlayImage(options.overlayImage, this.renderAll.bind(this));\n }\n if (options.backgroundImage) {\n this.setBackgroundImage(options.backgroundImage, this.renderAll.bind(this));\n }\n if (options.backgroundColor) {\n this.setBackgroundColor(options.backgroundColor, this.renderAll.bind(this));\n }\n if (options.overlayColor) {\n this.setOverlayColor(options.overlayColor, this.renderAll.bind(this));\n }\n this.calcOffset();\n },\n\n /**\n * @private\n */\n _initRetinaScaling: function() {\n if (fabric.devicePixelRatio === 1 || !this.enableRetinaScaling) {\n return;\n }\n\n this.lowerCanvasEl.setAttribute('width', this.width * fabric.devicePixelRatio);\n this.lowerCanvasEl.setAttribute('height', this.height * fabric.devicePixelRatio);\n\n this.contextContainer.scale(fabric.devicePixelRatio, fabric.devicePixelRatio);\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) {\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/fabricjs/YH9yD/|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) {\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 setBackgroundImage: function (image, callback, options) {\n return this.__setBgOverlayImage('backgroundImage', image, callback, options);\n },\n\n /**\n * Sets {@link fabric.StaticCanvas#overlayColor|background color} for this canvas\n * @param {(String|fabric.Pattern)} overlayColor 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/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 * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-imagesmoothingenabled|WhatWG Canvas Standard}\n */\n _setImageSmoothing: function() {\n var ctx = this.getContext();\n\n if (typeof ctx.imageSmoothingEnabled !== 'undefined') {\n ctx.imageSmoothingEnabled = this.imageSmoothingEnabled;\n return;\n }\n ctx.webkitImageSmoothingEnabled = this.imageSmoothingEnabled;\n ctx.mozImageSmoothingEnabled = this.imageSmoothingEnabled;\n ctx.msImageSmoothingEnabled = this.imageSmoothingEnabled;\n ctx.oImageSmoothingEnabled = this.imageSmoothingEnabled;\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\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) {\n this[property] = new fabric.Image(img, options);\n callback && callback();\n }, this, options && options.crossOrigin);\n }\n else {\n options && image.setOptions(options);\n this[property] = image;\n callback && callback();\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 if (color && color.source) {\n var _this = this;\n fabric.util.loadImage(color.source, function(img) {\n _this[property] = new fabric.Pattern({\n source: img,\n repeat: color.repeat,\n offsetX: color.offsetX,\n offsetY: color.offsetY\n });\n callback && callback();\n });\n }\n else {\n this[property] = color;\n callback && callback();\n }\n\n return this;\n },\n\n /**\n * @private\n */\n _createCanvasElement: function() {\n var element = fabric.document.createElement('canvas');\n if (!element.style) {\n element.style = { };\n }\n if (!element) {\n throw CANVAS_INIT_ERROR;\n }\n this._initCanvasElement(element);\n return element;\n },\n\n /**\n * @private\n * @param {HTMLElement} element\n */\n _initCanvasElement: function(element) {\n fabric.util.createCanvasElement(element);\n\n if (typeof element.getContext === 'undefined') {\n throw CANVAS_INIT_ERROR;\n }\n },\n\n /**\n * @private\n * @param {Object} [options] Options object\n */\n _initOptions: function (options) {\n for (var prop in options) {\n this[prop] = options[prop];\n }\n\n this.width = this.width || parseInt(this.lowerCanvasEl.width, 10) || 0;\n this.height = this.height || parseInt(this.lowerCanvasEl.height, 10) || 0;\n\n if (!this.lowerCanvasEl.style) {\n return;\n }\n\n this.lowerCanvasEl.width = this.width;\n this.lowerCanvasEl.height = this.height;\n\n this.lowerCanvasEl.style.width = this.width + 'px';\n this.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 this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement();\n this._initCanvasElement(this.lowerCanvasEl);\n\n fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas');\n\n if (this.interactive) {\n this._applyCanvasStyle(this.lowerCanvasEl);\n }\n\n this.contextContainer = this.lowerCanvasEl.getContext('2d');\n },\n\n /**\n * Returns canvas width (in px)\n * @return {Number}\n */\n getWidth: function () {\n return this.width;\n },\n\n /**\n * Returns canvas height (in px)\n * @return {Number}\n */\n getHeight: function () {\n return this.height;\n },\n\n /**\n * Sets width of this canvas instance\n * @param {Number|String} value Value to set width to\n * @param {Object} [options] Options object\n * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n setWidth: function (value, options) {\n return this.setDimensions({ width: value }, options);\n },\n\n /**\n * Sets height of this canvas instance\n * @param {Number|String} value Value to set height to\n * @param {Object} [options] Options object\n * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n setHeight: function (value, options) {\n return this.setDimensions({ height: value }, options);\n },\n\n /**\n * Sets dimensions (width, height) of this canvas instance. when options.cssOnly flag active you should also supply the unit of measure (px/%/em)\n * @param {Object} dimensions Object with width/height properties\n * @param {Number|String} [dimensions.width] Width of canvas element\n * @param {Number|String} [dimensions.height] Height of canvas element\n * @param {Object} [options] Options object\n * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n setDimensions: function (dimensions, options) {\n var cssValue;\n\n options = options || {};\n\n for (var prop in dimensions) {\n cssValue = dimensions[prop];\n\n if (!options.cssOnly) {\n this._setBackstoreDimension(prop, dimensions[prop]);\n cssValue += 'px';\n }\n\n if (!options.backstoreOnly) {\n this._setCssDimension(prop, cssValue);\n }\n }\n\n this._setImageSmoothing();\n this.calcOffset();\n\n if (!options.cssOnly) {\n this.renderAll();\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 Math.sqrt(this.viewportTransform[0] * this.viewportTransform[3]);\n },\n\n /**\n * Sets viewport transform of this canvas instance\n * @param {Array} vpt the transform in the form of context.transform\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n setViewportTransform: function (vpt) {\n var activeGroup = this.getActiveGroup();\n this.viewportTransform = vpt;\n this.renderAll();\n for (var i = 0, len = this._objects.length; i < len; i++) {\n this._objects[i].setCoords();\n }\n if (activeGroup) {\n activeGroup.setCoords();\n }\n return this;\n },\n\n /**\n * Sets zoom level of this canvas instance, zoom centered around point\n * @param {fabric.Point} point to zoom with respect to\n * @param {Number} value to set zoom to, less than 1 zooms out\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n zoomToPoint: function (point, value) {\n // TODO: just change the scale, preserve other transformations\n var before = point;\n point = fabric.util.transformPoint(point, fabric.util.invertTransform(this.viewportTransform));\n this.viewportTransform[0] = value;\n this.viewportTransform[3] = value;\n var after = fabric.util.transformPoint(point, this.viewportTransform);\n this.viewportTransform[4] += before.x - after.x;\n this.viewportTransform[5] += before.y - after.y;\n this.renderAll();\n for (var i = 0, len = this._objects.length; i < len; i++) {\n this._objects[i].setCoords();\n }\n return this;\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 this.viewportTransform[4] = -point.x;\n this.viewportTransform[5] = -point.y;\n this.renderAll();\n for (var i = 0, len = this._objects.length; i < len; i++) {\n this._objects[i].setCoords();\n }\n return this;\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 * Returns currently selected object, if any\n * @return {fabric.Object}\n */\n getActiveObject: function() {\n return null;\n },\n\n /**\n * Returns currently selected group of object, if any\n * @return {fabric.Group}\n */\n getActiveGroup: function() {\n return null;\n },\n\n /**\n * Given a context, renders an object on that context\n * @param {CanvasRenderingContext2D} ctx Context to render object on\n * @param {fabric.Object} object Object to render\n * @private\n */\n _draw: function (ctx, object) {\n if (!object) {\n return;\n }\n\n ctx.save();\n var v = this.viewportTransform;\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n if (this._shouldRenderObject(object)) {\n object.render(ctx);\n }\n ctx.restore();\n if (!this.controlsAboveOverlay) {\n object._renderControls(ctx);\n }\n },\n\n _shouldRenderObject: function(object) {\n if (!object) {\n return false;\n }\n return (object !== this.getActiveGroup() || !this.preserveObjectStacking);\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 // removing active object should fire \"selection:cleared\" events\n if (this.getActiveObject() === obj) {\n this.fire('before:selection:cleared', { target: obj });\n this._discardActiveObject();\n this.fire('selection:cleared');\n }\n\n this.fire('object:removed', { target: obj });\n obj.fire('removed');\n },\n\n /**\n * Clears specified context of canvas element\n * @param {CanvasRenderingContext2D} ctx Context to clear\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n clearContext: function(ctx) {\n ctx.clearRect(0, 0, this.width, this.height);\n return this;\n },\n\n /**\n * Returns context of canvas where objects are drawn\n * @return {CanvasRenderingContext2D}\n */\n getContext: function () {\n return this.contextContainer;\n },\n\n /**\n * Clears all contexts (background, main, top) of an instance\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n clear: function () {\n this._objects.length = 0;\n if (this.discardActiveGroup) {\n this.discardActiveGroup();\n }\n if (this.discardActiveObject) {\n this.discardActiveObject();\n }\n this.clearContext(this.contextContainer);\n if (this.contextTop) {\n this.clearContext(this.contextTop);\n }\n this.fire('canvas:cleared');\n this.renderAll();\n return this;\n },\n\n /**\n * Renders both the top canvas and the secondary container canvas.\n * @param {Boolean} [allOnTop] Whether we want to force all images to be rendered on the top canvas\n * @return {fabric.Canvas} instance\n * @chainable\n */\n renderAll: function (allOnTop) {\n var canvasToDrawOn = this[(allOnTop === true && this.interactive) ? 'contextTop' : 'contextContainer'],\n activeGroup = this.getActiveGroup();\n\n if (this.contextTop && this.selection && !this._groupSelector) {\n this.clearContext(this.contextTop);\n }\n\n if (!allOnTop) {\n this.clearContext(canvasToDrawOn);\n }\n\n this.fire('before:render');\n\n if (this.clipTo) {\n fabric.util.clipContext(this, canvasToDrawOn);\n }\n\n this._renderBackground(canvasToDrawOn);\n this._renderObjects(canvasToDrawOn, activeGroup);\n this._renderActiveGroup(canvasToDrawOn, activeGroup);\n\n if (this.clipTo) {\n canvasToDrawOn.restore();\n }\n\n this._renderOverlay(canvasToDrawOn);\n\n if (this.controlsAboveOverlay && this.interactive) {\n this.drawControls(canvasToDrawOn);\n }\n\n this.fire('after:render');\n\n return this;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {fabric.Group} activeGroup\n */\n _renderObjects: function(ctx, activeGroup) {\n var i, length;\n\n // fast path\n if (!activeGroup || this.preserveObjectStacking) {\n for (i = 0, length = this._objects.length; i < length; ++i) {\n this._draw(ctx, this._objects[i]);\n }\n }\n else {\n for (i = 0, length = this._objects.length; i < length; ++i) {\n if (this._objects[i] && !activeGroup.contains(this._objects[i])) {\n this._draw(ctx, this._objects[i]);\n }\n }\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {fabric.Group} activeGroup\n */\n _renderActiveGroup: function(ctx, activeGroup) {\n\n // delegate rendering to group selection (if one exists)\n if (activeGroup) {\n\n //Store objects in group preserving order, then replace\n var sortedObjects = [];\n this.forEachObject(function (object) {\n if (activeGroup.contains(object)) {\n sortedObjects.push(object);\n }\n });\n // forEachObject reverses the object, so we reverse again\n activeGroup._set('_objects', sortedObjects.reverse());\n this._draw(ctx, activeGroup);\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderBackground: function(ctx) {\n if (this.backgroundColor) {\n ctx.fillStyle = this.backgroundColor.toLive\n ? this.backgroundColor.toLive(ctx)\n : this.backgroundColor;\n\n ctx.fillRect(\n this.backgroundColor.offsetX || 0,\n this.backgroundColor.offsetY || 0,\n this.width,\n this.height);\n }\n if (this.backgroundImage) {\n this._draw(ctx, this.backgroundImage);\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderOverlay: function(ctx) {\n if (this.overlayColor) {\n ctx.fillStyle = this.overlayColor.toLive\n ? this.overlayColor.toLive(ctx)\n : this.overlayColor;\n\n ctx.fillRect(\n this.overlayColor.offsetX || 0,\n this.overlayColor.offsetY || 0,\n this.width,\n this.height);\n }\n if (this.overlayImage) {\n this._draw(ctx, this.overlayImage);\n }\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 || this.contextContainer;\n this.clearContext(ctx);\n\n // we render the top context - last object\n if (this.selection && this._groupSelector) {\n this._drawSelection();\n }\n\n // delegate rendering to group selection if one exists\n // used for drawing selection borders/controls\n var activeGroup = this.getActiveGroup();\n if (activeGroup) {\n activeGroup.render(ctx);\n }\n\n this._renderOverlay(ctx);\n\n this.fire('after:render');\n\n return this;\n },\n\n /**\n * Returns coordinates of a center of canvas.\n * Returned value is an object with top and left properties\n * @return {Object} object with \"top\" and \"left\" number values\n */\n getCenter: function () {\n return {\n top: this.getHeight() / 2,\n left: this.getWidth() / 2\n };\n },\n\n /**\n * Centers object horizontally.\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @param {fabric.Object} object Object to center horizontally\n * @return {fabric.Canvas} thisArg\n */\n centerObjectH: function (object) {\n this._centerObject(object, new fabric.Point(this.getCenter().left, object.getCenterPoint().y));\n this.renderAll();\n return this;\n },\n\n /**\n * Centers object vertically.\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @param {fabric.Object} object Object to center vertically\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n centerObjectV: function (object) {\n this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenter().top));\n this.renderAll();\n return this;\n },\n\n /**\n * Centers object vertically and horizontally.\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @param {fabric.Object} object Object to center vertically and horizontally\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n centerObject: function(object) {\n var center = this.getCenter();\n\n this._centerObject(object, new fabric.Point(center.left, center.top));\n this.renderAll();\n return this;\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 return this;\n },\n\n /**\n * Returs dataless JSON representation of canvas\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {String} json string\n */\n toDatalessJSON: function (propertiesToInclude) {\n return this.toDatalessObject(propertiesToInclude);\n },\n\n /**\n * Returns object representation of canvas\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function (propertiesToInclude) {\n return this._toObjectMethod('toObject', propertiesToInclude);\n },\n\n /**\n * Returns dataless object representation of canvas\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toDatalessObject: function (propertiesToInclude) {\n return this._toObjectMethod('toDatalessObject', propertiesToInclude);\n },\n\n /**\n * @private\n */\n _toObjectMethod: function (methodName, propertiesToInclude) {\n\n var data = {\n objects: this._toObjects(methodName, propertiesToInclude)\n };\n\n extend(data, this.__serializeBgOverlay());\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.getObjects().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 //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 = instance[methodName](propertiesToInclude);\n if (!this.includeDefaultValues) {\n instance.includeDefaultValues = originalValue;\n }\n\n //Undo the damage we did by changing all of its properties\n this._unwindGroupTransformOnObject(instance, originalProperties);\n\n return object;\n },\n\n /**\n * Realises an object's group transformation on it\n * @private\n * @param {fabric.Object} [instance] the object to transform (gets mutated)\n * @returns the original values of instance which were changed\n */\n _realizeGroupTransformOnObject: function(instance) {\n var layoutProps = ['angle', 'flipX', 'flipY', 'height', 'left', 'scaleX', 'scaleY', 'top', 'width'];\n if (instance.group && instance.group === this.getActiveGroup()) {\n //Copy all the positionally relevant properties across now\n var originalValues = {};\n layoutProps.forEach(function(prop) {\n originalValues[prop] = instance[prop];\n });\n this.getActiveGroup().realizeTransform(instance);\n return originalValues;\n }\n else {\n return null;\n }\n },\n\n /**\n * Restores the changed properties of instance\n * @private\n * @param {fabric.Object} [instance] the object to un-transform (gets mutated)\n * @param {Object} [originalValues] the original values of instance, as returned by _realizeGroupTransformOnObject\n */\n _unwindGroupTransformOnObject: function(instance, originalValues) {\n if (originalValues) {\n instance.set(originalValues);\n }\n },\n\n /**\n * @private\n */\n __serializeBgOverlay: function() {\n var data = {\n background: (this.backgroundColor && this.backgroundColor.toObject)\n ? this.backgroundColor.toObject()\n : this.backgroundColor\n };\n\n if (this.overlayColor) {\n data.overlay = this.overlayColor.toObject\n ? this.overlayColor.toObject()\n : this.overlayColor;\n }\n if (this.backgroundImage) {\n data.backgroundImage = this.backgroundImage.toObject();\n }\n if (this.overlayImage) {\n data.overlayImage = this.overlayImage.toObject();\n }\n\n return data;\n },\n\n /* _TO_SVG_START_ */\n /**\n * When true, getSvgTransform() will apply the StaticCanvas.viewportTransform to the SVG transformation. When true,\n * a zoomed canvas will then produce zoomed SVG output.\n * @type Boolean\n * @default\n */\n svgViewportTransformation: true,\n\n /**\n * Returns SVG representation of canvas\n * @function\n * @param {Object} [options] Options object for SVG output\n * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included\n * @param {Object} [options.viewBox] SVG viewbox object\n * @param {Number} [options.viewBox.x] x-cooridnate of viewbox\n * @param {Number} [options.viewBox.y] y-coordinate of viewbox\n * @param {Number} [options.viewBox.width] Width of viewbox\n * @param {Number} [options.viewBox.height] Height of viewbox\n * @param {String} [options.encoding=UTF-8] Encoding of SVG output\n * @param {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\n var markup = [];\n\n this._setSVGPreamble(markup, options);\n this._setSVGHeader(markup, options);\n\n this._setSVGBgOverlayColor(markup, 'backgroundColor');\n this._setSVGBgOverlayImage(markup, 'backgroundImage');\n\n this._setSVGObjects(markup, reviver);\n\n this._setSVGBgOverlayColor(markup, 'overlayColor');\n this._setSVGBgOverlayImage(markup, 'overlayImage');\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 markup.push(\n '',\n '\\n'\n );\n }\n },\n\n /**\n * @private\n */\n _setSVGHeader: function(markup, options) {\n var width, height, vpt;\n\n if (options.viewBox) {\n width = options.viewBox.width;\n height = options.viewBox.height;\n }\n else {\n width = this.width;\n height = this.height;\n if (!this.svgViewportTransformation) {\n vpt = this.viewportTransform;\n width /= vpt[0];\n height /= vpt[3];\n }\n }\n\n markup.push(\n '',\n 'Created with Fabric.js ', fabric.version, '',\n '',\n fabric.createSVGFontFacesMarkup(this.getObjects()),\n fabric.createSVGRefElementsMarkup(this),\n ''\n );\n },\n\n /**\n * @private\n */\n _setSVGObjects: function(markup, reviver) {\n for (var i = 0, objects = this.getObjects(), len = objects.length; i < len; i++) {\n var instance = objects[i],\n //If the object is in a selection group, simulate what would happen to that\n //object when the group is deselected\n originalProperties = this._realizeGroupTransformOnObject(instance);\n markup.push(instance.toSVG(reviver));\n this._unwindGroupTransformOnObject(instance, originalProperties);\n }\n },\n\n /**\n * @private\n */\n _setSVGBgOverlayImage: function(markup, property) {\n if (this[property] && this[property].toSVG) {\n markup.push(this[property].toSVG());\n }\n },\n\n /**\n * @private\n */\n _setSVGBgOverlayColor: function(markup, property) {\n if (this[property] && this[property].source) {\n markup.push(\n ''\n );\n }\n else if (this[property] && property === 'overlayColor') {\n markup.push(\n ''\n );\n }\n },\n /* _TO_SVG_END_ */\n\n /**\n * Moves an object 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 removeFromArray(this._objects, object);\n this._objects.unshift(object);\n return this.renderAll && this.renderAll();\n },\n\n /**\n * Moves an object 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 removeFromArray(this._objects, object);\n this._objects.push(object);\n return this.renderAll && this.renderAll();\n },\n\n /**\n * Moves an object down in stack of drawn objects\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 var idx = this._objects.indexOf(object);\n\n // if object is not on the bottom of stack\n if (idx !== 0) {\n var newIdx = this._findNewLowerIndex(object, idx, intersecting);\n\n removeFromArray(this._objects, object);\n this._objects.splice(newIdx, 0, object);\n this.renderAll && this.renderAll();\n }\n return this;\n },\n\n /**\n * @private\n */\n _findNewLowerIndex: function(object, idx, intersecting) {\n var newIdx;\n\n if (intersecting) {\n newIdx = idx;\n\n // traverse down the stack looking for the nearest intersecting object\n for (var 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 up in stack of drawn objects\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 var idx = this._objects.indexOf(object);\n\n // if object is not on top of stack (last item in an array)\n if (idx !== this._objects.length - 1) {\n var newIdx = this._findNewUpperIndex(object, idx, intersecting);\n\n removeFromArray(this._objects, object);\n this._objects.splice(newIdx, 0, object);\n this.renderAll && this.renderAll();\n }\n return this;\n },\n\n /**\n * @private\n */\n _findNewUpperIndex: function(object, idx, intersecting) {\n var newIdx;\n\n if (intersecting) {\n newIdx = idx;\n\n // traverse up the stack looking for the nearest intersecting object\n for (var i = idx + 1; i < this._objects.length; ++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.renderAll && this.renderAll();\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 this.clear();\n this.interactive && this.removeListeners();\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 \"getImageData\", \"toDataURL\", \"toDataURLWithQuality\" or \"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 = fabric.util.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 'getImageData':\n return typeof ctx.getImageData !== 'undefined';\n\n case 'setLineDash':\n return typeof ctx.setLineDash !== 'undefined';\n\n case 'toDataURL':\n return typeof el.toDataURL !== 'undefined';\n\n case 'toDataURLWithQuality':\n try {\n el.toDataURL('image/jpeg', 0);\n return true;\n }\n catch (e) { }\n return false;\n\n default:\n return null;\n }\n }\n });\n\n /**\n * Returns JSON representation of canvas\n * @function\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {String} JSON string\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization}\n * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo}\n * @example 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', 'lockUniScaling']);\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})();\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\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 \"bevil\", \"round\", \"miter\")\n * @type String\n * @default\n */\n strokeLineJoin: 'round',\n\n /**\n * Stroke Dash Array.\n * @type Array\n * @default\n */\n strokeDashArray: null,\n\n /**\n * Sets shadow of an object\n * @param {Object|String} [options] Options object or string (e.g. \"2px 2px 10px rgba(0,0,0,0.2)\")\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setShadow: function(options) {\n this.shadow = new fabric.Shadow(options);\n return this;\n },\n\n /**\n * Sets brush styles\n * @private\n */\n _setBrushStyles: function() {\n var ctx = this.canvas.contextTop;\n\n ctx.strokeStyle = this.color;\n ctx.lineWidth = this.width;\n ctx.lineCap = this.strokeLineCap;\n ctx.lineJoin = this.strokeLineJoin;\n if (this.strokeDashArray && fabric.StaticCanvas.supports('setLineDash')) {\n ctx.setLineDash(this.strokeDashArray);\n }\n },\n\n /**\n * Sets brush shadow styles\n * @private\n */\n _setShadow: function() {\n if (!this.shadow) {\n return;\n }\n\n var ctx = this.canvas.contextTop;\n\n ctx.shadowColor = this.shadow.color;\n ctx.shadowBlur = this.shadow.blur;\n ctx.shadowOffsetX = this.shadow.offsetX;\n ctx.shadowOffsetY = this.shadow.offsetY;\n },\n\n /**\n * Removes brush shadow styles\n * @private\n */\n _resetShadow: function() {\n var ctx = this.canvas.contextTop;\n\n ctx.shadowColor = '';\n ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;\n }\n});\n\n\n(function() {\n\n /**\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 * Constructor\n * @param {fabric.Canvas} canvas\n * @return {fabric.PencilBrush} Instance of a pencil brush\n */\n initialize: function(canvas) {\n this.canvas = canvas;\n this._points = [ ];\n },\n\n /**\n * Inovoked on mouse down\n * @param {Object} pointer\n */\n onMouseDown: function(pointer) {\n this._prepareForDrawing(pointer);\n // capture coordinates immediately\n // this allows to draw dots (when movement never occurs)\n this._captureDrawingPath(pointer);\n this._render();\n },\n\n /**\n * Inovoked on mouse move\n * @param {Object} pointer\n */\n onMouseMove: function(pointer) {\n this._captureDrawingPath(pointer);\n // redraw curve\n // clear top canvas\n this.canvas.clearContext(this.canvas.contextTop);\n this._render();\n },\n\n /**\n * Invoked on mouse up\n */\n onMouseUp: function() {\n this._finalizeAndAddPath();\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\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 this._points.push(point);\n },\n\n /**\n * Clear points array and set contextTop canvas style.\n * @private\n */\n _reset: function() {\n this._points.length = 0;\n\n this._setBrushStyles();\n this._setShadow();\n },\n\n /**\n * @private\n * @param {Object} pointer Actual mouse position related to the canvas.\n */\n _captureDrawingPath: function(pointer) {\n var pointerPoint = new fabric.Point(pointer.x, pointer.y);\n this._addPoint(pointerPoint);\n },\n\n /**\n * Draw a smooth path on the topCanvas using quadraticCurveTo\n * @private\n */\n _render: function() {\n var ctx = this.canvas.contextTop,\n v = this.canvas.viewportTransform,\n p1 = this._points[0],\n p2 = this._points[1];\n\n ctx.save();\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n ctx.beginPath();\n\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 p1.x -= 0.5;\n p2.x += 0.5;\n }\n ctx.moveTo(p1.x, p1.y);\n\n for (var 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 var midPoint = p1.midPointFrom(p2);\n ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);\n\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 * @param {Number} minX\n * @param {Number} minY\n * @return {String} SVG path\n */\n convertPointsToSVGPath: function(points) {\n var path = [],\n p1 = new fabric.Point(points[0].x, points[0].y),\n p2 = new fabric.Point(points[1].x, points[1].y);\n\n path.push('M ', points[0].x, ' ', points[0].y, ' ');\n for (var i = 1, len = points.length; i < len; i++) {\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 p1 = new fabric.Point(points[i].x, points[i].y);\n if ((i + 1) < points.length) {\n p2 = new fabric.Point(points[i + 1].x, points[i + 1].y);\n }\n }\n path.push('L ', p1.x, ' ', p1.y, ' ');\n return path;\n },\n\n /**\n * Creates fabric.Path object to add on canvas\n * @param {String} pathData Path data\n * @return {fabric.Path} Path to add on canvas\n */\n createPath: function(pathData) {\n var path = new fabric.Path(pathData, {\n fill: null,\n stroke: this.color,\n strokeWidth: this.width,\n strokeLineCap: this.strokeLineCap,\n strokeLineJoin: this.strokeLineJoin,\n strokeDashArray: this.strokeDashArray,\n originX: 'center',\n originY: 'center'\n });\n\n if (this.shadow) {\n this.shadow.affectStroke = true;\n path.setShadow(this.shadow);\n }\n\n return path;\n },\n\n /**\n * On mouseup after drawing the path on contextTop canvas\n * we use the points captured to create an new fabric path object\n * and add it to the fabric canvas.\n */\n _finalizeAndAddPath: function() {\n var ctx = this.canvas.contextTop;\n ctx.closePath();\n\n var pathData = this.convertPointsToSVGPath(this._points).join('');\n if (pathData === 'M 0 0 Q 0 0 0 0 L 0 0') {\n // do not create 0 width/height paths, as they are\n // rendered inconsistently across browsers\n // Firefox 4, for example, renders a dot,\n // whereas Chrome 10 renders nothing\n this.canvas.renderAll();\n return;\n }\n\n var path = this.createPath(pathData);\n\n this.canvas.add(path);\n path.setCoords();\n\n this.canvas.clearContext(this.canvas.contextTop);\n this._resetShadow();\n this.canvas.renderAll();\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 v = this.canvas.viewportTransform;\n ctx.save();\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n\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 ctx.restore();\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 * Invoked on mouse move\n * @param {Object} pointer\n */\n onMouseMove: function(pointer) {\n this.drawDot(pointer);\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 circles = [ ];\n\n for (var 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.setShadow(this.shadow);\n\n circles.push(circle);\n }\n var group = new fabric.Group(circles, { originX: 'center', originY: 'center' });\n group.canvas = this.canvas;\n\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.renderAll();\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();\n },\n\n /**\n * Invoked on mouse move\n * @param {Object} pointer\n */\n onMouseMove: function(pointer) {\n this.addSprayChunk(pointer);\n this.render();\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\n this.shadow && rect.setShadow(this.shadow);\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, { originX: 'center', originY: 'center' });\n group.canvas = this.canvas;\n\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.renderAll();\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;\n\n for (var 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 * Renders brush\n */\n render: function() {\n var ctx = this.canvas.contextTop;\n ctx.fillStyle = this.color;\n\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 for (var i = 0, len = this.sprayChunkPoints.length; i < len; i++) {\n var point = this.sprayChunkPoints[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 * @param {Object} pointer\n */\n addSprayChunk: function(pointer) {\n this.sprayChunkPoints = [ ];\n\n var x, y, width, radius = this.width / 2;\n\n for (var 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.document.createElement('canvas'),\n patternCtx = patternCanvas.getContext('2d');\n\n patternCanvas.width = patternCanvas.height = dotWidth + dotDistance;\n\n patternCtx.fillStyle = this.color;\n patternCtx.beginPath();\n patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false);\n patternCtx.closePath();\n patternCtx.fill();\n\n return patternCanvas;\n },\n\n getPatternSrcFunction: function() {\n return String(this.getPatternSrc).replace('this.color', '\"' + this.color + '\"');\n },\n\n /**\n * Creates \"pattern\" instance property\n */\n getPattern: function() {\n return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), 'repeat');\n },\n\n /**\n * Sets brush styles\n */\n _setBrushStyles: function() {\n this.callSuper('_setBrushStyles');\n this.canvas.contextTop.strokeStyle = this.getPattern();\n },\n\n /**\n * Creates path\n */\n createPath: function(pathData) {\n var path = this.callSuper('createPath', pathData);\n path.stroke = new fabric.Pattern({\n source: this.source || this.getPatternSrcFunction()\n });\n return path;\n }\n});\n\n\n(function() {\n\n var getPointer = fabric.util.getPointer,\n degreesToRadians = fabric.util.degreesToRadians,\n radiansToDegrees = fabric.util.radiansToDegrees,\n atan2 = Math.atan2,\n abs = Math.abs,\n\n STROKE_OFFSET = 0.5;\n\n /**\n * Canvas class\n * @class fabric.Canvas\n * @extends fabric.StaticCanvas\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#canvas}\n * @see {@link fabric.Canvas#initialize} for constructor definition\n *\n * @fires object:modified\n * @fires object:rotating\n * @fires object:scaling\n * @fires object:moving\n * @fires object:selected\n *\n * @fires before:selection:cleared\n * @fires selection:cleared\n * @fires selection:created\n *\n * @fires path:created\n * @fires mouse:down\n * @fires mouse:move\n * @fires mouse:up\n * @fires mouse:over\n * @fires mouse:out\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\n this._initStatic(el, options);\n this._initInteractive();\n this._createCacheCanvas();\n\n fabric.Canvas.activeInstance = this;\n },\n\n /**\n * When true, objects can be transformed by one side (unproportionally)\n * @type Boolean\n * @default\n */\n uniScaleTransform: false,\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 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 * 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 * Default cursor value used when hovering over an object on canvas\n * @type String\n * @default\n */\n hoverCursor: 'move',\n\n /**\n * Default cursor value used when moving an object on canvas\n * @type String\n * @default\n */\n moveCursor: 'move',\n\n /**\n * Default cursor value used for the entire canvas\n * @type String\n * @default\n */\n defaultCursor: 'default',\n\n /**\n * Cursor value used during free drawing\n * @type String\n * @default\n */\n freeDrawingCursor: 'crosshair',\n\n /**\n * Cursor value used for rotation point\n * @type String\n * @default\n */\n rotationCursor: 'crosshair',\n\n /**\n * 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 when hovering over canvas. This can be used to improve performance.\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 * @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 * Resets the current transform to its original values and chooses the type of resizing based on the event\n * @private\n * @param {Event} e Event object fired on mousemove\n */\n _resetCurrentTransform: function(e) {\n var t = this._currentTransform;\n\n t.target.set({\n scaleX: t.original.scaleX,\n scaleY: t.original.scaleY,\n left: t.original.left,\n top: t.original.top\n });\n\n if (this._shouldCenterTransform(e, t.target)) {\n if (t.action === 'rotate') {\n this._setOriginToCenter(t.target);\n }\n else {\n if (t.originX !== 'center') {\n if (t.originX === 'right') {\n t.mouseXSign = -1;\n }\n else {\n t.mouseXSign = 1;\n }\n }\n if (t.originY !== 'center') {\n if (t.originY === 'bottom') {\n t.mouseYSign = -1;\n }\n else {\n t.mouseYSign = 1;\n }\n }\n\n t.originX = 'center';\n t.originY = 'center';\n }\n }\n else {\n t.originX = t.original.originX;\n t.originY = t.original.originY;\n }\n },\n\n /**\n * Checks if point is contained within an area of given object\n * @param {Event} e Event object\n * @param {fabric.Object} target Object to test against\n * @return {Boolean} true if point is contained within an area of given object\n */\n containsPoint: function (e, target) {\n var pointer = this.getPointer(e, true),\n xy = this._normalizePointer(target, pointer);\n\n // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html\n // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html\n return (target.containsPoint(xy) || target._findTargetCorner(pointer));\n },\n\n /**\n * @private\n */\n _normalizePointer: function (object, pointer) {\n var activeGroup = this.getActiveGroup(),\n x = pointer.x,\n y = pointer.y,\n isObjectInGroup = (\n activeGroup &&\n object.type !== 'group' &&\n activeGroup.contains(object)),\n lt;\n\n if (isObjectInGroup) {\n lt = fabric.util.transformPoint(activeGroup.getCenterPoint(), this.viewportTransform, true);\n x -= lt.x;\n y -= lt.y;\n x /= activeGroup.scaleX;\n y /= activeGroup.scaleY;\n }\n return { x: x, y: y };\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 var hasBorders = target.hasBorders,\n transparentCorners = target.transparentCorners;\n\n target.hasBorders = target.transparentCorners = false;\n\n this._draw(this.contextCache, target);\n\n target.hasBorders = hasBorders;\n target.transparentCorners = transparentCorners;\n\n var isTransparent = fabric.util.isTransparent(\n this.contextCache, x, y, this.targetFindTolerance);\n\n this.clearContext(this.contextCache);\n\n return isTransparent;\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n */\n _shouldClearSelection: function (e, target) {\n var activeGroup = this.getActiveGroup(),\n activeObject = this.getActiveObject();\n\n return (\n !target\n ||\n (target &&\n activeGroup &&\n !activeGroup.contains(target) &&\n activeGroup !== target &&\n !e.shiftKey)\n ||\n (target && !target.evented)\n ||\n (target &&\n !target.selectable &&\n activeObject &&\n activeObject !== target)\n );\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n */\n _shouldCenterTransform: function (e, target) {\n if (!target) {\n return;\n }\n\n var t = this._currentTransform,\n centerTransform;\n\n if (t.action === 'scale' || t.action === 'scaleX' || t.action === 'scaleY') {\n centerTransform = this.centeredScaling || target.centeredScaling;\n }\n else if (t.action === 'rotate') {\n centerTransform = this.centeredRotation || target.centeredRotation;\n }\n\n return centerTransform ? !e.altKey : e.altKey;\n },\n\n /**\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\n return origin;\n },\n\n /**\n * @private\n */\n _getActionFromCorner: function(target, corner) {\n var action = 'drag';\n if (corner) {\n action = (corner === 'ml' || corner === 'mr')\n ? 'scaleX'\n : (corner === 'mt' || corner === 'mb')\n ? 'scaleY'\n : corner === 'mtr'\n ? 'rotate'\n : 'scale';\n }\n return action;\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n */\n _setupCurrentTransform: function (e, target) {\n if (!target) {\n return;\n }\n\n var pointer = this.getPointer(e),\n corner = target._findTargetCorner(this.getPointer(e, true)),\n action = this._getActionFromCorner(target, corner),\n origin = this._getOriginFromCorner(target, corner);\n\n this._currentTransform = {\n target: target,\n action: action,\n scaleX: target.scaleX,\n scaleY: target.scaleY,\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 left: target.left,\n top: target.top,\n theta: degreesToRadians(target.angle),\n width: target.width * target.scaleX,\n mouseXSign: 1,\n mouseYSign: 1\n };\n\n this._currentTransform.original = {\n left: target.left,\n top: target.top,\n scaleX: target.scaleX,\n scaleY: target.scaleY,\n originX: origin.x,\n originY: origin.y\n };\n\n this._resetCurrentTransform(e);\n },\n\n /**\n * Translates object by \"setting\" its left/top\n * @private\n * @param {Number} x pointer's x coordinate\n * @param {Number} y pointer's y coordinate\n */\n _translateObject: function (x, y) {\n var target = this._currentTransform.target;\n\n if (!target.get('lockMovementX')) {\n target.set('left', x - this._currentTransform.offsetX);\n }\n if (!target.get('lockMovementY')) {\n target.set('top', y - this._currentTransform.offsetY);\n }\n },\n\n /**\n * Scales object by invoking its scaleX/scaleY methods\n * @private\n * @param {Number} x pointer's x coordinate\n * @param {Number} y pointer's y coordinate\n * @param {String} by Either 'x' or 'y' - specifies dimension constraint by which to scale an object.\n * When not provided, an object is scaled by both dimensions equally\n */\n _scaleObject: function (x, y, by) {\n var t = this._currentTransform,\n target = t.target,\n lockScalingX = target.get('lockScalingX'),\n lockScalingY = target.get('lockScalingY'),\n lockScalingFlip = target.get('lockScalingFlip');\n\n if (lockScalingX && lockScalingY) {\n return;\n }\n\n // Get the constraint point\n var constraintPosition = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY),\n localMouse = target.toLocalPoint(new fabric.Point(x, y), t.originX, t.originY);\n\n this._setLocalMouse(localMouse, t);\n\n // Actually scale the object\n this._setObjectScale(localMouse, t, lockScalingX, lockScalingY, by, lockScalingFlip);\n\n // Make sure the constraints apply\n target.setPositionByOrigin(constraintPosition, t.originX, t.originY);\n },\n\n /**\n * @private\n */\n _setObjectScale: function(localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip) {\n var target = transform.target, forbidScalingX = false, forbidScalingY = false,\n dim = target._getNonTransformedDimensions();\n\n transform.newScaleX = localMouse.x / dim.x;\n transform.newScaleY = localMouse.y / dim.y;\n\n if (lockScalingFlip && transform.newScaleX <= 0 && transform.newScaleX < target.scaleX) {\n forbidScalingX = true;\n }\n\n if (lockScalingFlip && transform.newScaleY <= 0 && transform.newScaleY < target.scaleY) {\n forbidScalingY = true;\n }\n\n if (by === 'equally' && !lockScalingX && !lockScalingY) {\n forbidScalingX || forbidScalingY || this._scaleObjectEqually(localMouse, target, transform);\n }\n else if (!by) {\n forbidScalingX || lockScalingX || target.set('scaleX', transform.newScaleX);\n forbidScalingY || lockScalingY || target.set('scaleY', transform.newScaleY);\n }\n else if (by === 'x' && !target.get('lockUniScaling')) {\n forbidScalingX || lockScalingX || target.set('scaleX', transform.newScaleX);\n }\n else if (by === 'y' && !target.get('lockUniScaling')) {\n forbidScalingY || lockScalingY || target.set('scaleY', transform.newScaleY);\n }\n\n forbidScalingX || forbidScalingY || this._flipObject(transform, by);\n\n },\n\n /**\n * @private\n */\n _scaleObjectEqually: function(localMouse, target, transform) {\n\n var dist = localMouse.y + localMouse.x,\n dim = target._getNonTransformedDimensions(),\n lastDist = dim.y * transform.original.scaleY +\n dim.x * transform.original.scaleX;\n\n // We use transform.scaleX/Y instead of target.scaleX/Y\n // because the object may have a min scale and we'll loose the proportions\n transform.newScaleX = transform.original.scaleX * dist / lastDist;\n transform.newScaleY = transform.original.scaleY * dist / lastDist;\n\n target.set('scaleX', transform.newScaleX);\n target.set('scaleY', transform.newScaleY);\n },\n\n /**\n * @private\n */\n _flipObject: function(transform, by) {\n if (transform.newScaleX < 0 && by !== 'y') {\n if (transform.originX === 'left') {\n transform.originX = 'right';\n }\n else if (transform.originX === 'right') {\n transform.originX = 'left';\n }\n }\n\n if (transform.newScaleY < 0 && by !== 'x') {\n if (transform.originY === 'top') {\n transform.originY = 'bottom';\n }\n else if (transform.originY === 'bottom') {\n transform.originY = 'top';\n }\n }\n },\n\n /**\n * @private\n */\n _setLocalMouse: function(localMouse, t) {\n var target = t.target;\n\n if (t.originX === 'right') {\n localMouse.x *= -1;\n }\n else if (t.originX === 'center') {\n localMouse.x *= t.mouseXSign * 2;\n\n if (localMouse.x < 0) {\n t.mouseXSign = -t.mouseXSign;\n }\n }\n\n if (t.originY === 'bottom') {\n localMouse.y *= -1;\n }\n else if (t.originY === 'center') {\n localMouse.y *= t.mouseYSign * 2;\n\n if (localMouse.y < 0) {\n t.mouseYSign = -t.mouseYSign;\n }\n }\n\n // adjust the mouse coordinates when dealing with padding\n if (abs(localMouse.x) > target.padding) {\n if (localMouse.x < 0) {\n localMouse.x += target.padding;\n }\n else {\n localMouse.x -= target.padding;\n }\n }\n else { // mouse is within the padding, set to 0\n localMouse.x = 0;\n }\n\n if (abs(localMouse.y) > target.padding) {\n if (localMouse.y < 0) {\n localMouse.y += target.padding;\n }\n else {\n localMouse.y -= target.padding;\n }\n }\n else {\n localMouse.y = 0;\n }\n },\n\n /**\n * Rotates object by invoking its rotate method\n * @private\n * @param {Number} x pointer's x coordinate\n * @param {Number} y pointer's y coordinate\n */\n _rotateObject: function (x, y) {\n\n var t = this._currentTransform;\n\n if (t.target.get('lockRotation')) {\n return;\n }\n\n var lastAngle = atan2(t.ey - t.top, t.ex - t.left),\n curAngle = atan2(y - t.top, x - t.left),\n angle = radiansToDegrees(curAngle - lastAngle + t.theta);\n\n // normalize angle to positive value\n if (angle < 0) {\n angle = 360 + angle;\n }\n\n t.target.angle = angle % 360;\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 */\n _resetObjectTransform: function (target) {\n target.scaleX = 1;\n target.scaleY = 1;\n target.setAngle(0);\n },\n\n /**\n * @private\n */\n _drawSelection: function () {\n var ctx = this.contextTop,\n groupSelector = this._groupSelector,\n left = groupSelector.left,\n top = groupSelector.top,\n aleft = abs(left),\n atop = abs(top);\n\n ctx.fillStyle = this.selectionColor;\n\n ctx.fillRect(\n groupSelector.ex - ((left > 0) ? 0 : -left),\n groupSelector.ey - ((top > 0) ? 0 : -top),\n aleft,\n atop\n );\n\n ctx.lineWidth = this.selectionLineWidth;\n ctx.strokeStyle = this.selectionBorderColor;\n\n // selection border\n if (this.selectionDashArray.length > 1) {\n\n var px = groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0: aleft),\n py = groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0: atop);\n\n ctx.beginPath();\n\n fabric.util.drawDashedLine(ctx, px, py, px + aleft, py, this.selectionDashArray);\n fabric.util.drawDashedLine(ctx, px, py + atop - 1, px + aleft, py + atop - 1, this.selectionDashArray);\n fabric.util.drawDashedLine(ctx, px, py, px, py + atop, this.selectionDashArray);\n fabric.util.drawDashedLine(ctx, px + aleft - 1, py, px + aleft - 1, py + atop, this.selectionDashArray);\n\n ctx.closePath();\n ctx.stroke();\n }\n else {\n ctx.strokeRect(\n groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft),\n groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop),\n aleft,\n atop\n );\n }\n },\n\n /**\n * @private\n */\n _isLastRenderedObject: function(e) {\n return (\n this.controlsAboveOverlay &&\n this.lastRenderedObjectWithControlsAboveOverlay &&\n this.lastRenderedObjectWithControlsAboveOverlay.visible &&\n this.containsPoint(e, this.lastRenderedObjectWithControlsAboveOverlay) &&\n this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(this.getPointer(e, true)));\n },\n\n /**\n * Method that determines what object we are clicking on\n * @param {Event} e mouse event\n * @param {Boolean} skipGroup when true, group is skipped and only objects are traversed through\n */\n findTarget: function (e, skipGroup) {\n if (this.skipTargetFind) {\n return;\n }\n\n if (this._isLastRenderedObject(e)) {\n return this.lastRenderedObjectWithControlsAboveOverlay;\n }\n\n // first check current group (if one exists)\n var activeGroup = this.getActiveGroup();\n if (activeGroup && !skipGroup && this.containsPoint(e, activeGroup)) {\n return activeGroup;\n }\n\n var target = this._searchPossibleTargets(e, skipGroup);\n this._fireOverOutEvents(target, e);\n\n return target;\n },\n\n /**\n * @private\n */\n _fireOverOutEvents: function(target, e) {\n if (target) {\n if (this._hoveredTarget !== target) {\n if (this._hoveredTarget) {\n this.fire('mouse:out', { target: this._hoveredTarget, e: e });\n this._hoveredTarget.fire('mouseout');\n }\n this.fire('mouse:over', { target: target, e: e });\n target.fire('mouseover');\n this._hoveredTarget = target;\n }\n }\n else if (this._hoveredTarget) {\n this.fire('mouse:out', { target: this._hoveredTarget, e: e });\n this._hoveredTarget.fire('mouseout');\n this._hoveredTarget = null;\n }\n },\n\n /**\n * @private\n */\n _checkTarget: function(e, obj, pointer) {\n if (obj &&\n obj.visible &&\n obj.evented &&\n this.containsPoint(e, obj)){\n if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) {\n var isTransparent = this.isTargetTransparent(obj, pointer.x, pointer.y);\n if (!isTransparent) {\n return true;\n }\n }\n else {\n return true;\n }\n }\n },\n\n /**\n * @private\n */\n _searchPossibleTargets: function(e, skipGroup) {\n\n // Cache all targets where their bounding box contains point.\n var target,\n pointer = this.getPointer(e, true),\n i = this._objects.length;\n // Do not check for currently grouped objects, since we check the parent group itself.\n // untill we call this function specifically to search inside the activeGroup\n while (i--) {\n if ((!this._objects[i].group || skipGroup) && this._checkTarget(e, this._objects[i], pointer)){\n this.relatedTarget = this._objects[i];\n target = this._objects[i];\n break;\n }\n }\n\n return target;\n },\n\n /**\n * Returns pointer coordinates relative to canvas.\n * @param {Event} e\n * @return {Object} object with \"x\" and \"y\" number values\n */\n getPointer: function (e, ignoreZoom, upperCanvasEl) {\n if (!upperCanvasEl) {\n upperCanvasEl = this.upperCanvasEl;\n }\n var pointer = getPointer(e),\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\n pointer.x = pointer.x - this._offset.left;\n pointer.y = pointer.y - this._offset.top;\n if (!ignoreZoom) {\n pointer = fabric.util.transformPoint(\n pointer,\n fabric.util.invertTransform(this.viewportTransform)\n );\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\n this.upperCanvasEl = this._createCanvasElement();\n fabric.util.addClass(this.upperCanvasEl, 'upper-canvas ' + lowerCanvasClass);\n\n this.wrapperEl.appendChild(this.upperCanvasEl);\n\n this._copyCanvasStyle(this.lowerCanvasEl, this.upperCanvasEl);\n this._applyCanvasStyle(this.upperCanvasEl);\n this.contextTop = this.upperCanvasEl.getContext('2d');\n },\n\n /**\n * @private\n */\n _createCacheCanvas: function () {\n this.cacheCanvasEl = this._createCanvasElement();\n this.cacheCanvasEl.setAttribute('width', this.width);\n this.cacheCanvasEl.setAttribute('height', this.height);\n this.contextCache = this.cacheCanvasEl.getContext('2d');\n },\n\n /**\n * @private\n */\n _initWrapperElement: function () {\n this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', {\n 'class': this.containerClass\n });\n fabric.util.setStyle(this.wrapperEl, {\n width: this.getWidth() + 'px',\n height: this.getHeight() + '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.getWidth() || element.width,\n height = this.getHeight() || 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 });\n element.width = width;\n element.height = height;\n fabric.util.makeElementUnselectable(element);\n },\n\n /**\n * Copys the 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 * @private\n * @param {Object} object\n */\n _setActiveObject: function(object) {\n if (this._activeObject) {\n this._activeObject.set('active', false);\n }\n this._activeObject = object;\n object.set('active', true);\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 this._setActiveObject(object);\n this.renderAll();\n this.fire('object:selected', { target: object, e: e });\n object.fire('selected', { e: e });\n return this;\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 * @private\n */\n _discardActiveObject: function() {\n if (this._activeObject) {\n this._activeObject.set('active', false);\n }\n this._activeObject = null;\n },\n\n /**\n * Discards currently active object\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n discardActiveObject: function (e) {\n this._discardActiveObject();\n this.renderAll();\n this.fire('selection:cleared', { e: e });\n return this;\n },\n\n /**\n * @private\n * @param {fabric.Group} group\n */\n _setActiveGroup: function(group) {\n this._activeGroup = group;\n if (group) {\n group.set('active', true);\n }\n },\n\n /**\n * Sets active group to a speicified one\n * @param {fabric.Group} group Group to set as a current one\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n setActiveGroup: function (group, e) {\n this._setActiveGroup(group);\n if (group) {\n this.fire('object:selected', { target: group, e: e });\n group.fire('selected', { e: e });\n }\n return this;\n },\n\n /**\n * Returns currently active group\n * @return {fabric.Group} Current group\n */\n getActiveGroup: function () {\n return this._activeGroup;\n },\n\n /**\n * @private\n */\n _discardActiveGroup: function() {\n var g = this.getActiveGroup();\n if (g) {\n g.destroy();\n }\n this.setActiveGroup(null);\n },\n\n /**\n * Discards currently active group\n * @return {fabric.Canvas} thisArg\n */\n discardActiveGroup: function (e) {\n this._discardActiveGroup();\n this.fire('selection:cleared', { e: e });\n return this;\n },\n\n /**\n * Deactivates all objects on canvas, removing any active group or object\n * @return {fabric.Canvas} thisArg\n */\n deactivateAll: function () {\n var allObjects = this.getObjects(),\n i = 0,\n len = allObjects.length;\n for ( ; i < len; i++) {\n allObjects[i].set('active', false);\n }\n this._discardActiveGroup();\n this._discardActiveObject();\n return this;\n },\n\n /**\n * Deactivates all objects and dispatches appropriate events\n * @return {fabric.Canvas} thisArg\n */\n deactivateAllWithDispatch: function (e) {\n var activeObject = this.getActiveGroup() || this.getActiveObject();\n if (activeObject) {\n this.fire('before:selection:cleared', { target: activeObject, e: e });\n }\n this.deactivateAll();\n if (activeObject) {\n this.fire('selection:cleared', { e: e });\n }\n return this;\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 activeGroup = this.getActiveGroup();\n if (activeGroup) {\n this._drawGroupControls(ctx, activeGroup);\n }\n else {\n this._drawObjectsControls(ctx);\n }\n },\n\n /**\n * @private\n */\n _drawGroupControls: function(ctx, activeGroup) {\n activeGroup._renderControls(ctx);\n },\n\n /**\n * @private\n */\n _drawObjectsControls: function(ctx) {\n for (var i = 0, len = this._objects.length; i < len; ++i) {\n if (!this._objects[i] || !this._objects[i].active) {\n continue;\n }\n this._objects[i]._renderControls(ctx);\n this.lastRenderedObjectWithControlsAboveOverlay = this._objects[i];\n }\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 if (fabric.isTouchSupported) {\n /** @ignore */\n fabric.Canvas.prototype._setCursorFromEvent = function() { };\n }\n\n /**\n * @class fabric.Element\n * @alias fabric.Canvas\n * @deprecated Use {@link fabric.Canvas} instead.\n * @constructor\n */\n fabric.Element = fabric.Canvas;\n})();\n\n\n(function() {\n\n var cursorOffset = {\n mt: 0, // n\n tr: 1, // ne\n mr: 2, // e\n br: 3, // se\n mb: 4, // s\n bl: 5, // sw\n ml: 6, // w\n tl: 7 // nw\n },\n addListener = fabric.util.addListener,\n removeListener = fabric.util.removeListener;\n\n fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ {\n\n /**\n * Map of cursor style values for each of the object controls\n * @private\n */\n cursorMap: [\n 'n-resize',\n 'ne-resize',\n 'e-resize',\n 'se-resize',\n 's-resize',\n 'sw-resize',\n 'w-resize',\n 'nw-resize'\n ],\n\n /**\n * Adds mouse listeners to canvas\n * @private\n */\n _initEventListeners: function () {\n\n this._bindEvents();\n\n addListener(fabric.window, 'resize', this._onResize);\n\n // mouse events\n addListener(this.upperCanvasEl, 'mousedown', this._onMouseDown);\n addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);\n addListener(this.upperCanvasEl, 'mousewheel', this._onMouseWheel);\n\n // touch events\n addListener(this.upperCanvasEl, 'touchstart', this._onMouseDown);\n addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);\n\n if (typeof eventjs !== 'undefined' && 'add' in eventjs) {\n eventjs.add(this.upperCanvasEl, 'gesture', this._onGesture);\n eventjs.add(this.upperCanvasEl, 'drag', this._onDrag);\n eventjs.add(this.upperCanvasEl, 'orientation', this._onOrientationChange);\n eventjs.add(this.upperCanvasEl, 'shake', this._onShake);\n eventjs.add(this.upperCanvasEl, 'longpress', this._onLongPress);\n }\n },\n\n /**\n * @private\n */\n _bindEvents: function() {\n this._onMouseDown = this._onMouseDown.bind(this);\n this._onMouseMove = this._onMouseMove.bind(this);\n this._onMouseUp = this._onMouseUp.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 },\n\n /**\n * Removes all event listeners\n */\n removeListeners: function() {\n removeListener(fabric.window, 'resize', this._onResize);\n\n removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown);\n removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);\n removeListener(this.upperCanvasEl, 'mousewheel', this._onMouseWheel);\n\n removeListener(this.upperCanvasEl, 'touchstart', this._onMouseDown);\n removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);\n\n if (typeof eventjs !== 'undefined' && 'remove' in eventjs) {\n eventjs.remove(this.upperCanvasEl, 'gesture', this._onGesture);\n eventjs.remove(this.upperCanvasEl, 'drag', this._onDrag);\n eventjs.remove(this.upperCanvasEl, 'orientation', this._onOrientationChange);\n eventjs.remove(this.upperCanvasEl, 'shake', this._onShake);\n eventjs.remove(this.upperCanvasEl, 'longpress', this._onLongPress);\n }\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 Event.js wheel event\n * @param {Event} [self] Inner Event object\n */\n _onMouseWheel: function(e, self) {\n this.__onMouseWheel && this.__onMouseWheel(e, self);\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 * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onMouseDown: function (e) {\n this.__onMouseDown(e);\n\n addListener(fabric.document, 'touchend', this._onMouseUp);\n addListener(fabric.document, 'touchmove', this._onMouseMove);\n\n removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);\n removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);\n\n if (e.type === 'touchstart') {\n // Unbind mousedown to prevent double triggers from touch devices\n removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown);\n }\n else {\n addListener(fabric.document, 'mouseup', this._onMouseUp);\n addListener(fabric.document, 'mousemove', this._onMouseMove);\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mouseup\n */\n _onMouseUp: function (e) {\n this.__onMouseUp(e);\n\n removeListener(fabric.document, 'mouseup', this._onMouseUp);\n removeListener(fabric.document, 'touchend', this._onMouseUp);\n\n removeListener(fabric.document, 'mousemove', this._onMouseMove);\n removeListener(fabric.document, 'touchmove', this._onMouseMove);\n\n addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);\n addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);\n\n if (e.type === 'touchend') {\n // Wait 400ms before rebinding mousedown to prevent double triggers\n // from touch devices\n var _this = this;\n setTimeout(function() {\n addListener(_this.upperCanvasEl, 'mousedown', _this._onMouseDown);\n }, 400);\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 * @param {Object} pointer\n */\n _shouldRender: function(target, pointer) {\n var activeObject = this.getActiveGroup() || this.getActiveObject();\n\n return !!(\n (target && (\n target.isMoving ||\n target !== activeObject))\n ||\n (!target && !!activeObject)\n ||\n (!target && !activeObject && !this._groupSelector)\n ||\n (pointer &&\n this._previousPointer &&\n this.selection && (\n pointer.x !== this._previousPointer.x ||\n pointer.y !== this._previousPointer.y))\n );\n },\n\n /**\n * Method that defines the actions when mouse is released on canvas.\n * The method resets the currentTransform parameters, store the image corner\n * position in the image object and render the canvas on top.\n * @private\n * @param {Event} e Event object fired on mouseup\n */\n __onMouseUp: function (e) {\n var target;\n\n if (this.isDrawingMode && this._isCurrentlyDrawing) {\n this._onMouseUpInDrawingMode(e);\n return;\n }\n\n if (this._currentTransform) {\n this._finalizeCurrentTransform();\n target = this._currentTransform.target;\n }\n else {\n target = this.findTarget(e, true);\n }\n\n var shouldRender = this._shouldRender(target, this.getPointer(e));\n\n this._maybeGroupObjects(e);\n\n if (target) {\n target.isMoving = false;\n }\n\n shouldRender && this.renderAll();\n\n this._handleCursorAndEvent(e, target);\n },\n\n _handleCursorAndEvent: function(e, target) {\n this._setCursorFromEvent(e, target);\n\n // TODO: why are we doing this?\n var _this = this;\n setTimeout(function () {\n _this._setCursorFromEvent(e, target);\n }, 50);\n\n this.fire('mouse:up', { target: target, e: e });\n target && target.fire('mouseup', { e: e });\n },\n\n /**\n * @private\n */\n _finalizeCurrentTransform: function() {\n\n var transform = this._currentTransform,\n target = transform.target;\n\n if (target._scaling) {\n target._scaling = false;\n }\n\n target.setCoords();\n\n // only fire :modified event if target coordinates were changed during mousedown-mouseup\n if (this.stateful && target.hasStateChanged()) {\n this.fire('object:modified', { target: target });\n target.fire('modified');\n }\n\n this._restoreOriginXY(target);\n },\n\n /**\n * @private\n * @param {Object} target Object to restore\n */\n _restoreOriginXY: function(target) {\n if (this._previousOriginX && this._previousOriginY) {\n\n var originPoint = target.translateToOriginPoint(\n target.getCenterPoint(),\n this._previousOriginX,\n this._previousOriginY);\n\n target.originX = this._previousOriginX;\n target.originY = this._previousOriginY;\n\n target.left = originPoint.x;\n target.top = originPoint.y;\n\n this._previousOriginX = null;\n this._previousOriginY = null;\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 this.discardActiveObject(e).renderAll();\n if (this.clipTo) {\n fabric.util.clipContext(this, this.contextTop);\n }\n var ivt = fabric.util.invertTransform(this.viewportTransform),\n pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt);\n this.freeDrawingBrush.onMouseDown(pointer);\n this.fire('mouse:down', { e: e });\n\n var target = this.findTarget(e);\n if (typeof target !== 'undefined') {\n target.fire('mousedown', { e: e, target: target });\n }\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 ivt = fabric.util.invertTransform(this.viewportTransform),\n pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt);\n this.freeDrawingBrush.onMouseMove(pointer);\n }\n this.setCursor(this.freeDrawingCursor);\n this.fire('mouse:move', { e: e });\n\n var target = this.findTarget(e);\n if (typeof target !== 'undefined') {\n target.fire('mousemove', { e: e, target: target });\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mouseup\n */\n _onMouseUpInDrawingMode: function(e) {\n this._isCurrentlyDrawing = false;\n if (this.clipTo) {\n this.contextTop.restore();\n }\n this.freeDrawingBrush.onMouseUp();\n this.fire('mouse:up', { e: e });\n\n var target = this.findTarget(e);\n if (typeof target !== 'undefined') {\n target.fire('mouseup', { e: e, target: target });\n }\n },\n\n /**\n * Method that defines the actions when mouse is clic ked 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\n // accept only left clicks\n var isLeftClick = 'which' in e ? e.which === 1 : e.button === 1;\n if (!isLeftClick && !fabric.isTouchSupported) {\n return;\n }\n\n if (this.isDrawingMode) {\n this._onMouseDownInDrawingMode(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 target = this.findTarget(e),\n pointer = this.getPointer(e, true);\n\n // save pointer for check in __onMouseUp event\n this._previousPointer = pointer;\n\n var shouldRender = this._shouldRender(target, pointer),\n shouldGroup = this._shouldGroup(e, target);\n\n if (this._shouldClearSelection(e, target)) {\n this._clearSelection(e, target, pointer);\n }\n else if (shouldGroup) {\n this._handleGrouping(e, target);\n target = this.getActiveGroup();\n }\n\n if (target && target.selectable && !shouldGroup) {\n this._beforeTransform(e, target);\n this._setupCurrentTransform(e, target);\n }\n // we must renderAll so that active image is placed on the top canvas\n shouldRender && this.renderAll();\n\n this.fire('mouse:down', { target: target, e: e });\n target && target.fire('mousedown', { e: e });\n },\n\n /**\n * @private\n */\n _beforeTransform: function(e, target) {\n this.stateful && target.saveState();\n\n // determine if it's a drag or rotate case\n if (target._findTargetCorner(this.getPointer(e))) {\n this.onBeforeScaleRotate(target);\n }\n\n if (target !== this.getActiveGroup() && target !== this.getActiveObject()) {\n this.deactivateAll();\n this.setActiveObject(target, e);\n }\n },\n\n /**\n * @private\n */\n _clearSelection: function(e, target, pointer) {\n this.deactivateAllWithDispatch(e);\n\n if (target && target.selectable) {\n this.setActiveObject(target, e);\n }\n else if (this.selection) {\n this._groupSelector = {\n ex: pointer.x,\n ey: pointer.y,\n top: 0,\n left: 0\n };\n }\n },\n\n /**\n * @private\n * @param {Object} target Object for that origin is set to center\n */\n _setOriginToCenter: function(target) {\n this._previousOriginX = this._currentTransform.target.originX;\n this._previousOriginY = this._currentTransform.target.originY;\n\n var center = target.getCenterPoint();\n\n target.originX = 'center';\n target.originY = 'center';\n\n target.left = center.x;\n target.top = center.y;\n\n this._currentTransform.left = target.left;\n this._currentTransform.top = target.top;\n },\n\n /**\n * @private\n * @param {Object} target Object for that center is set to origin\n */\n _setCenterToOrigin: function(target) {\n var originPoint = target.translateToOriginPoint(\n target.getCenterPoint(),\n this._previousOriginX,\n this._previousOriginY);\n\n target.originX = this._previousOriginX;\n target.originY = this._previousOriginY;\n\n target.left = originPoint.x;\n target.top = originPoint.y;\n\n this._previousOriginX = null;\n this._previousOriginY = null;\n },\n\n /**\n * Method that defines the actions when mouse is hovering the canvas.\n * The currentTransform parameter will definde 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\n var target, pointer;\n\n if (this.isDrawingMode) {\n this._onMouseMoveInDrawingMode(e);\n return;\n }\n if (typeof e.touches !== 'undefined' && e.touches.length > 1) {\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.getPointer(e, true);\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\n target = this.findTarget(e);\n\n if (!target || target && !target.selectable) {\n this.setCursor(this.defaultCursor);\n }\n else {\n this._setCursorFromEvent(e, target);\n }\n }\n else {\n this._transformObject(e);\n }\n\n this.fire('mouse:move', { target: target, e: e });\n target && target.fire('mousemove', { e: e });\n },\n\n /**\n * @private\n * @param {Event} e Event fired on mousemove\n */\n _transformObject: function(e) {\n var pointer = this.getPointer(e),\n transform = this._currentTransform;\n\n transform.reset = false,\n transform.target.isMoving = true;\n\n this._beforeScaleTransform(e, transform);\n this._performTransformAction(e, transform, pointer);\n\n this.renderAll();\n },\n\n /**\n * @private\n */\n _performTransformAction: function(e, transform, pointer) {\n var x = pointer.x,\n y = pointer.y,\n target = transform.target,\n action = transform.action;\n\n if (action === 'rotate') {\n this._rotateObject(x, y);\n this._fire('rotating', target, e);\n }\n else if (action === 'scale') {\n this._onScale(e, transform, x, y);\n this._fire('scaling', target, e);\n }\n else if (action === 'scaleX') {\n this._scaleObject(x, y, 'x');\n this._fire('scaling', target, e);\n }\n else if (action === 'scaleY') {\n this._scaleObject(x, y, 'y');\n this._fire('scaling', target, e);\n }\n else {\n this._translateObject(x, y);\n this._fire('moving', target, e);\n this.setCursor(this.moveCursor);\n }\n },\n\n /**\n * @private\n */\n _fire: function(eventName, target, e) {\n this.fire('object:' + eventName, { target: target, e: e });\n target.fire(eventName, { e: e });\n },\n\n /**\n * @private\n */\n _beforeScaleTransform: function(e, transform) {\n if (transform.action === 'scale' || transform.action === 'scaleX' || transform.action === 'scaleY') {\n var centerTransform = this._shouldCenterTransform(e, transform.target);\n\n // Switch from a normal resize to center-based\n if ((centerTransform && (transform.originX !== 'center' || transform.originY !== 'center')) ||\n // Switch from center-based resize to normal one\n (!centerTransform && transform.originX === 'center' && transform.originY === 'center')\n ) {\n this._resetCurrentTransform(e);\n transform.reset = true;\n }\n }\n },\n\n /**\n * @private\n */\n _onScale: function(e, transform, x, y) {\n // rotate object only if shift key is not pressed\n // and if it is not a group we are transforming\n if ((e.shiftKey || this.uniScaleTransform) && !transform.target.get('lockUniScaling')) {\n transform.currentAction = 'scale';\n this._scaleObject(x, y);\n }\n else {\n // Switch from a normal resize to proportional\n if (!transform.reset && transform.currentAction === 'scale') {\n this._resetCurrentTransform(e, transform.target);\n }\n\n transform.currentAction = 'scaleEqually';\n this._scaleObject(x, y, 'equally');\n }\n },\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 || !target.selectable) {\n this.setCursor(this.defaultCursor);\n return false;\n }\n else {\n var activeGroup = this.getActiveGroup(),\n // only show proper corner when group selection is not active\n corner = target._findTargetCorner\n && (!activeGroup || !activeGroup.contains(target))\n && target._findTargetCorner(this.getPointer(e, true));\n\n if (!corner) {\n this.setCursor(target.hoverCursor || this.hoverCursor);\n }\n else {\n this._setCornerCursor(corner, target);\n }\n }\n return true;\n },\n\n /**\n * @private\n */\n _setCornerCursor: function(corner, target) {\n if (corner in cursorOffset) {\n this.setCursor(this._getRotatedCornerCursor(corner, target));\n }\n else if (corner === 'mtr' && target.hasRotatingPoint) {\n this.setCursor(this.rotationCursor);\n }\n else {\n this.setCursor(this.defaultCursor);\n return false;\n }\n },\n\n /**\n * @private\n */\n _getRotatedCornerCursor: function(corner, target) {\n var n = Math.round((target.getAngle() % 360) / 45);\n\n if (n < 0) {\n n += 8; // full circle ahead\n }\n n += cursorOffset[corner];\n // normalize n to be from 0 to 7\n n %= 8;\n\n return this.cursorMap[n];\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.getActiveObject();\n return e.shiftKey &&\n (this.getActiveGroup() || (activeObject && activeObject !== target))\n && this.selection;\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n */\n _handleGrouping: function (e, target) {\n\n if (target === this.getActiveGroup()) {\n\n // if it's a group, find target again, this time skipping group\n target = this.findTarget(e, true);\n\n // if even object is not found, bail out\n if (!target || target.isType('group')) {\n return;\n }\n }\n if (this.getActiveGroup()) {\n this._updateActiveGroup(target, e);\n }\n else {\n this._createActiveGroup(target, e);\n }\n\n if (this._activeGroup) {\n this._activeGroup.saveCoords();\n }\n },\n\n /**\n * @private\n */\n _updateActiveGroup: function(target, e) {\n var activeGroup = this.getActiveGroup();\n\n if (activeGroup.contains(target)) {\n\n activeGroup.removeWithUpdate(target);\n this._resetObjectTransform(activeGroup);\n target.set('active', false);\n\n if (activeGroup.size() === 1) {\n // remove group alltogether if after removal it only contains 1 object\n this.discardActiveGroup(e);\n // activate last remaining object\n this.setActiveObject(activeGroup.item(0));\n return;\n }\n }\n else {\n activeGroup.addWithUpdate(target);\n this._resetObjectTransform(activeGroup);\n }\n this.fire('selection:created', { target: activeGroup, e: e });\n activeGroup.set('active', true);\n },\n\n /**\n * @private\n */\n _createActiveGroup: function(target, e) {\n\n if (this._activeObject && target !== this._activeObject) {\n\n var group = this._createGroup(target);\n group.addWithUpdate();\n\n this.setActiveGroup(group);\n this._activeObject = null;\n\n this.fire('selection:created', { target: group, e: e });\n }\n\n target.set('active', true);\n },\n\n /**\n * @private\n * @param {Object} target\n */\n _createGroup: function(target) {\n\n var objects = this.getObjects(),\n isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target),\n groupObjects = isActiveLower\n ? [ this._activeObject, target ]\n : [ target, this._activeObject ];\n\n return new fabric.Group(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();\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 group = new fabric.Group(group.reverse(), {\n canvas: this\n });\n group.addWithUpdate();\n this.setActiveGroup(group, e);\n group.saveCoords();\n this.fire('selection:created', { target: group });\n this.renderAll();\n }\n },\n\n /**\n * @private\n */\n _collectObjects: function() {\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 isClick = x1 === x2 && y1 === y2;\n\n for (var i = this._objects.length; i--; ) {\n currentObject = this._objects[i];\n\n if (!currentObject || !currentObject.selectable || !currentObject.visible) {\n continue;\n }\n\n if (currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2) ||\n currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) ||\n currentObject.containsPoint(selectionX1Y1) ||\n currentObject.containsPoint(selectionX2Y2)\n ) {\n currentObject.set('active', true);\n group.push(currentObject);\n\n // only add one object if it's a click\n if (isClick) {\n break;\n }\n }\n }\n\n return group;\n },\n\n /**\n * @private\n */\n _maybeGroupObjects: function(e) {\n if (this.selection && this._groupSelector) {\n this._groupSelectedObjects(e);\n }\n\n var activeGroup = this.getActiveGroup();\n if (activeGroup) {\n activeGroup.setObjectsCoords().setCoords();\n activeGroup.isMoving = false;\n this.setCursor(this.defaultCursor);\n }\n\n // clear selection and current transformation\n this._groupSelector = null;\n this._currentTransform = null;\n }\n });\n\n})();\n\n\nfabric.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\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 * @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,\n cropping = {\n left: options.left,\n top: options.top,\n width: options.width,\n height: options.height\n };\n\n if (multiplier !== 1) {\n return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier);\n }\n else {\n return this.__toDataURL(format, quality, cropping);\n }\n },\n\n /**\n * @private\n */\n __toDataURL: function(format, quality, cropping) {\n\n this.renderAll(true);\n\n var canvasEl = this.upperCanvasEl || this.lowerCanvasEl,\n croppedCanvasEl = this.__getCroppedCanvas(canvasEl, cropping);\n\n // to avoid common confusion https://github.com/kangax/fabric.js/issues/806\n if (format === 'jpg') {\n format = 'jpeg';\n }\n\n var data = (fabric.StaticCanvas.supports('toDataURLWithQuality'))\n ? (croppedCanvasEl || canvasEl).toDataURL('image/' + format, quality)\n : (croppedCanvasEl || canvasEl).toDataURL('image/' + format);\n\n this.contextTop && this.clearContext(this.contextTop);\n this.renderAll();\n\n if (croppedCanvasEl) {\n croppedCanvasEl = null;\n }\n\n return data;\n },\n\n /**\n * @private\n */\n __getCroppedCanvas: function(canvasEl, cropping) {\n\n var croppedCanvasEl,\n croppedCtx,\n shouldCrop = 'left' in cropping ||\n 'top' in cropping ||\n 'width' in cropping ||\n 'height' in cropping;\n\n if (shouldCrop) {\n\n croppedCanvasEl = fabric.util.createCanvasElement();\n croppedCtx = croppedCanvasEl.getContext('2d');\n\n croppedCanvasEl.width = cropping.width || this.width;\n croppedCanvasEl.height = cropping.height || this.height;\n\n croppedCtx.drawImage(canvasEl, -cropping.left || 0, -cropping.top || 0);\n }\n\n return croppedCanvasEl;\n },\n\n /**\n * @private\n */\n __toDataURLWithMultiplier: function(format, quality, cropping, multiplier) {\n\n var origWidth = this.getWidth(),\n origHeight = this.getHeight(),\n scaledWidth = origWidth * multiplier,\n scaledHeight = origHeight * multiplier,\n activeObject = this.getActiveObject(),\n activeGroup = this.getActiveGroup(),\n\n ctx = this.contextTop || this.contextContainer;\n\n if (multiplier > 1) {\n this.setWidth(scaledWidth).setHeight(scaledHeight);\n }\n ctx.scale(multiplier, multiplier);\n\n if (cropping.left) {\n cropping.left *= multiplier;\n }\n if (cropping.top) {\n cropping.top *= multiplier;\n }\n if (cropping.width) {\n cropping.width *= multiplier;\n }\n else if (multiplier < 1) {\n cropping.width = scaledWidth;\n }\n if (cropping.height) {\n cropping.height *= multiplier;\n }\n else if (multiplier < 1) {\n cropping.height = scaledHeight;\n }\n\n if (activeGroup) {\n // not removing group due to complications with restoring it with correct state afterwords\n this._tempRemoveBordersControlsFromGroup(activeGroup);\n }\n else if (activeObject && this.deactivateAll) {\n this.deactivateAll();\n }\n\n this.renderAll(true);\n\n var data = this.__toDataURL(format, quality, cropping);\n\n // restoring width, height for `renderAll` to draw\n // background properly (while context is scaled)\n this.width = origWidth;\n this.height = origHeight;\n\n ctx.scale(1 / multiplier, 1 / multiplier);\n this.setWidth(origWidth).setHeight(origHeight);\n\n if (activeGroup) {\n this._restoreBordersControlsOnGroup(activeGroup);\n }\n else if (activeObject && this.setActiveObject) {\n this.setActiveObject(activeObject);\n }\n\n this.contextTop && this.clearContext(this.contextTop);\n this.renderAll();\n\n return data;\n },\n\n /**\n * Exports canvas element to a dataurl image (allowing to change image size via multiplier).\n * @deprecated since 1.0.13\n * @param {String} format (png|jpeg)\n * @param {Number} multiplier\n * @param {Number} quality (0..1)\n * @return {String}\n */\n toDataURLWithMultiplier: function (format, multiplier, quality) {\n return this.toDataURL({\n format: format,\n multiplier: multiplier,\n quality: quality\n });\n },\n\n /**\n * @private\n */\n _tempRemoveBordersControlsFromGroup: function(group) {\n group.origHasControls = group.hasControls;\n group.origBorderColor = group.borderColor;\n\n group.hasControls = true;\n group.borderColor = 'rgba(0,0,0,0)';\n\n group.forEachObject(function(o) {\n o.origBorderColor = o.borderColor;\n o.borderColor = 'rgba(0,0,0,0)';\n });\n },\n\n /**\n * @private\n */\n _restoreBordersControlsOnGroup: function(group) {\n group.hideControls = group.origHideControls;\n group.borderColor = group.origBorderColor;\n\n group.forEachObject(function(o) {\n o.borderColor = o.origBorderColor;\n delete o.origBorderColor;\n });\n }\n});\n\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n /**\n * Populates canvas with data from the specified dataless JSON.\n * JSON format must conform to the one of {@link fabric.Canvas#toDatalessJSON}\n * @deprecated since 1.2.2\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 */\n loadFromDatalessJSON: function (json, callback, reviver) {\n return this.loadFromJSON(json, callback, reviver);\n },\n\n /**\n * Populates canvas with data from the specified JSON.\n * JSON format must conform to the one of {@link fabric.Canvas#toJSON}\n * @param {String|Object} json JSON string or object\n * @param {Function} callback Callback, invoked when json is parsed\n * and corresponding objects (e.g: {@link fabric.Image})\n * are initialized\n * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created.\n * @return {fabric.Canvas} instance\n * @chainable\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#deserialization}\n * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo}\n * @example 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 : json;\n\n this.clear();\n\n var _this = this;\n this._enlivenObjects(serialized.objects, function () {\n _this._setBgOverlay(serialized, callback);\n }, reviver);\n\n return this;\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 _this = this,\n 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 _this.renderAll();\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 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 return;\n }\n\n if (property === 'backgroundImage' || property === 'overlayImage') {\n fabric.Image.fromObject(value, function(img) {\n _this[property] = img;\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 var _this = this;\n\n if (!objects || objects.length === 0) {\n callback && callback();\n return;\n }\n\n var renderOnAddRemove = this.renderOnAddRemove;\n this.renderOnAddRemove = false;\n\n fabric.util.enlivenObjects(objects, function(enlivenedObjects) {\n enlivenedObjects.forEach(function(obj, index) {\n _this.insertAt(obj, index, true);\n });\n\n _this.renderOnAddRemove = renderOnAddRemove;\n callback && callback();\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.document.createElement('canvas');\n\n el.width = this.getWidth();\n el.height = this.getHeight();\n\n var clone = new fabric.Canvas(el);\n clone.clipTo = this.clipTo;\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 toFixed = fabric.util.toFixed,\n capitalize = fabric.util.string.capitalize,\n degreesToRadians = fabric.util.degreesToRadians,\n supportsLineDash = fabric.StaticCanvas.supports('setLineDash');\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 modified\n * @fires rotating\n * @fires scaling\n * @fires moving\n *\n * @fires mousedown\n * @fires mouseup\n */\n fabric.Object = fabric.util.createClass(/** @lends fabric.Object.prototype */ {\n\n /**\n * Retrieves object's {@link fabric.Object#clipTo|clipping function}\n * @method getClipTo\n * @memberOf fabric.Object.prototype\n * @return {Function}\n */\n\n /**\n * Sets object's {@link fabric.Object#clipTo|clipping function}\n * @method setClipTo\n * @memberOf fabric.Object.prototype\n * @param {Function} clipTo Clipping function\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#transformMatrix|transformMatrix}\n * @method getTransformMatrix\n * @memberOf fabric.Object.prototype\n * @return {Array} transformMatrix\n */\n\n /**\n * Sets object's {@link fabric.Object#transformMatrix|transformMatrix}\n * @method setTransformMatrix\n * @memberOf fabric.Object.prototype\n * @param {Array} transformMatrix\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#visible|visible} state\n * @method getVisible\n * @memberOf fabric.Object.prototype\n * @return {Boolean} True if visible\n */\n\n /**\n * Sets object's {@link fabric.Object#visible|visible} state\n * @method setVisible\n * @memberOf fabric.Object.prototype\n * @param {Boolean} value visible value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#shadow|shadow}\n * @method getShadow\n * @memberOf fabric.Object.prototype\n * @return {Object} Shadow instance\n */\n\n /**\n * Retrieves object's {@link fabric.Object#stroke|stroke}\n * @method getStroke\n * @memberOf fabric.Object.prototype\n * @return {String} stroke value\n */\n\n /**\n * Sets object's {@link fabric.Object#stroke|stroke}\n * @method setStroke\n * @memberOf fabric.Object.prototype\n * @param {String} value stroke value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#strokeWidth|strokeWidth}\n * @method getStrokeWidth\n * @memberOf fabric.Object.prototype\n * @return {Number} strokeWidth value\n */\n\n /**\n * Sets object's {@link fabric.Object#strokeWidth|strokeWidth}\n * @method setStrokeWidth\n * @memberOf fabric.Object.prototype\n * @param {Number} value strokeWidth value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#originX|originX}\n * @method getOriginX\n * @memberOf fabric.Object.prototype\n * @return {String} originX value\n */\n\n /**\n * Sets object's {@link fabric.Object#originX|originX}\n * @method setOriginX\n * @memberOf fabric.Object.prototype\n * @param {String} value originX value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#originY|originY}\n * @method getOriginY\n * @memberOf fabric.Object.prototype\n * @return {String} originY value\n */\n\n /**\n * Sets object's {@link fabric.Object#originY|originY}\n * @method setOriginY\n * @memberOf fabric.Object.prototype\n * @param {String} value originY value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#fill|fill}\n * @method getFill\n * @memberOf fabric.Object.prototype\n * @return {String} Fill value\n */\n\n /**\n * Sets object's {@link fabric.Object#fill|fill}\n * @method setFill\n * @memberOf fabric.Object.prototype\n * @param {String} value Fill value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#opacity|opacity}\n * @method getOpacity\n * @memberOf fabric.Object.prototype\n * @return {Number} Opacity value (0-1)\n */\n\n /**\n * Sets object's {@link fabric.Object#opacity|opacity}\n * @method setOpacity\n * @memberOf fabric.Object.prototype\n * @param {Number} value Opacity value (0-1)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#angle|angle} (in degrees)\n * @method getAngle\n * @memberOf fabric.Object.prototype\n * @return {Number}\n */\n\n /**\n * Retrieves object's {@link fabric.Object#top|top position}\n * @method getTop\n * @memberOf fabric.Object.prototype\n * @return {Number} Top value (in pixels)\n */\n\n /**\n * Sets object's {@link fabric.Object#top|top position}\n * @method setTop\n * @memberOf fabric.Object.prototype\n * @param {Number} value Top value (in pixels)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#left|left position}\n * @method getLeft\n * @memberOf fabric.Object.prototype\n * @return {Number} Left value (in pixels)\n */\n\n /**\n * Sets object's {@link fabric.Object#left|left position}\n * @method setLeft\n * @memberOf fabric.Object.prototype\n * @param {Number} value Left value (in pixels)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#scaleX|scaleX} value\n * @method getScaleX\n * @memberOf fabric.Object.prototype\n * @return {Number} scaleX value\n */\n\n /**\n * Sets object's {@link fabric.Object#scaleX|scaleX} value\n * @method setScaleX\n * @memberOf fabric.Object.prototype\n * @param {Number} value scaleX value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#scaleY|scaleY} value\n * @method getScaleY\n * @memberOf fabric.Object.prototype\n * @return {Number} scaleY value\n */\n\n /**\n * Sets object's {@link fabric.Object#scaleY|scaleY} value\n * @method setScaleY\n * @memberOf fabric.Object.prototype\n * @param {Number} value scaleY value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#flipX|flipX} value\n * @method getFlipX\n * @memberOf fabric.Object.prototype\n * @return {Boolean} flipX value\n */\n\n /**\n * Sets object's {@link fabric.Object#flipX|flipX} value\n * @method setFlipX\n * @memberOf fabric.Object.prototype\n * @param {Boolean} value flipX value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#flipY|flipY} value\n * @method getFlipY\n * @memberOf fabric.Object.prototype\n * @return {Boolean} flipY value\n */\n\n /**\n * Sets object's {@link fabric.Object#flipY|flipY} value\n * @method setFlipY\n * @memberOf fabric.Object.prototype\n * @param {Boolean} value flipY value\n * @return {fabric.Object} thisArg\n * @chainable\n */\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/40/ 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/40/ 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 center. 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 center. 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 * Size of object's controlling corners (in pixels)\n * @type Number\n * @default\n */\n cornerSize: 12,\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 * 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: 'rgba(102,153,255,0.75)',\n\n /**\n * Color of controlling corners of an object (when it's active)\n * @type String\n * @default\n */\n cornerColor: 'rgba(102,153,255,0.5)',\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 * @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. Only works with text objects at the moment.\n * @type String\n * @default\n */\n backgroundColor: '',\n\n /**\n * When defined, an object is rendered via stroke and this property specifies its color\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 endings style of an object's stroke (one of \"butt\", \"round\", \"square\")\n * @type String\n * @default\n */\n strokeLineCap: 'butt',\n\n /**\n * Corner style of an object's stroke (one of \"bevil\", \"round\", \"miter\")\n * @type String\n * @default\n */\n strokeLineJoin: 'miter',\n\n /**\n * Maximum miter length (used for strokeLineJoin = \"miter\") of an object's stroke\n * @type Number\n * @default\n */\n strokeMiterLimit: 10,\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 * @type Number\n * @default\n */\n borderScaleFactor: 1,\n\n /**\n * Transform matrix (similar to SVG's transform matrix)\n * @type Array\n */\n transformMatrix: null,\n\n /**\n * Minimum allowed scale value of an object\n * @type Number\n * @default\n */\n minScaleLimit: 0.01,\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 `false`, object's controlling rotating point will not be visible or selectable\n * @type Boolean\n * @default\n */\n hasRotatingPoint: true,\n\n /**\n * Offset for object's controlling rotating point (when enabled via `hasRotatingPoint`)\n * @type Number\n * @default\n */\n rotatingPointOffset: 40,\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 * Function that determines clipping of an object (context is passed as a first argument)\n * Note that context origin is at the object's center point (not left/top corner)\n * @type Function\n */\n clipTo: null,\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 non-uniform scaling is locked\n * @type Boolean\n * @default\n */\n lockUniScaling: false,\n\n /**\n * When `true`, object cannot be flipped by scaling into negative values\n * @type Boolean\n * @default\n */\n\n lockScalingFlip: false,\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 strokeLineJoin strokeMiterLimit ' +\n 'angle opacity fill fillRule globalCompositeOperation shadow clipTo visible backgroundColor ' +\n 'alignX alignY meetOrSlice'\n ).split(' '),\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 * @private\n * @param {Object} [options] Options object\n */\n _initGradient: function(options) {\n if (options.fill && options.fill.colorStops && !(options.fill instanceof fabric.Gradient)) {\n this.set('fill', new fabric.Gradient(options.fill));\n }\n if (options.stroke && options.stroke.colorStops && !(options.stroke instanceof fabric.Gradient)) {\n this.set('stroke', new fabric.Gradient(options.stroke));\n }\n },\n\n /**\n * @private\n * @param {Object} [options] Options object\n */\n _initPattern: function(options) {\n if (options.fill && options.fill.source && !(options.fill instanceof fabric.Pattern)) {\n this.set('fill', new fabric.Pattern(options.fill));\n }\n if (options.stroke && options.stroke.source && !(options.stroke instanceof fabric.Pattern)) {\n this.set('stroke', new fabric.Pattern(options.stroke));\n }\n },\n\n /**\n * @private\n * @param {Object} [options] Options object\n */\n _initClipping: function(options) {\n if (!options.clipTo || typeof options.clipTo !== 'string') {\n return;\n }\n\n var functionBody = fabric.util.getFunctionBody(options.clipTo);\n if (typeof functionBody !== 'undefined') {\n this.clipTo = new Function('ctx', functionBody);\n }\n },\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 this._initGradient(options);\n this._initPattern(options);\n this._initClipping(options);\n },\n\n /**\n * Transforms context when rendering an object\n * @param {CanvasRenderingContext2D} ctx Context\n * @param {Boolean} fromLeft When true, context is transformed to object's top/left corner. This is used when rendering text on Node\n */\n transform: function(ctx, fromLeft) {\n if (this.group && this.canvas.preserveObjectStacking && this.group === this.canvas._activeGroup) {\n this.group.transform(ctx);\n }\n var center = fromLeft ? this._getLeftTopCoords() : this.getCenterPoint();\n ctx.translate(center.x, center.y);\n ctx.rotate(degreesToRadians(this.angle));\n ctx.scale(\n this.scaleX * (this.flipX ? -1 : 1),\n this.scaleY * (this.flipY ? -1 : 1)\n );\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 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,\n strokeLineCap: this.strokeLineCap,\n strokeLineJoin: this.strokeLineJoin,\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.getAngle(), 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 clipTo: this.clipTo && String(this.clipTo),\n backgroundColor: this.backgroundColor,\n fillRule: this.fillRule,\n globalCompositeOperation: this.globalCompositeOperation,\n transformMatrix: this.transformMatrix\n };\n\n if (!this.includeDefaultValues) {\n object = this._removeDefaultValues(object);\n }\n\n fabric.util.populateWithProperties(this, object, propertiesToInclude);\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\n stateProperties.forEach(function(prop) {\n if (object[prop] === prototype[prop]) {\n delete object[prop];\n }\n var isArray = Object.prototype.toString.call(object[prop]) === '[object Array]' &&\n Object.prototype.toString.call(prototype[prop]) === '[object Array]';\n\n // basically a check for [] === []\n if (isArray && object[prop].length === 0 && prototype[prop].length === 0) {\n delete object[prop];\n }\n });\n\n return object;\n },\n\n /**\n * Returns a string representation of an instance\n * @return {String}\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Basic getter\n * @param {String} property Property name\n * @return {Any} value of a property\n */\n get: function(property) {\n return this[property];\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 if (typeof value === 'function' && key !== 'clipTo') {\n this._set(key, value(this.get(key)));\n }\n else {\n this._set(key, value);\n }\n }\n return this;\n },\n\n /**\n * @private\n * @param {String} key\n * @param {Any} value\n * @return {fabric.Object} thisArg\n */\n _set: function(key, value) {\n var shouldConstrainValue = (key === 'scaleX' || key === 'scaleY');\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 === 'width' || key === 'height') {\n this.minScaleLimit = toFixed(Math.min(0.1, 1/Math.max(this.width, this.height)), 2);\n }\n else if (key === 'shadow' && value && !(value instanceof fabric.Shadow)) {\n value = new fabric.Shadow(value);\n }\n\n this[key] = value;\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 * 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 * Sets sourcePath of an object\n * @param {String} value Value to set sourcePath to\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setSourcePath: function(value) {\n this.sourcePath = value;\n return this;\n },\n\n /**\n * Retrieves viewportTransform from Object's canvas if possible\n * @method getViewportTransform\n * @memberOf fabric.Object.prototype\n * @return {Boolean} flipY value // TODO\n */\n getViewportTransform: function() {\n if (this.canvas && this.canvas.viewportTransform) {\n return this.canvas.viewportTransform;\n }\n return [1, 0, 0, 1, 0, 0];\n },\n\n /**\n * Renders an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n render: function(ctx, noTransform) {\n // do not render if width/height are zeros or object is not visible\n if ((this.width === 0 && this.height === 0) || !this.visible) {\n return;\n }\n\n ctx.save();\n\n //setup fill rule for current object\n this._setupCompositeOperation(ctx);\n if (!noTransform) {\n this.transform(ctx);\n }\n this._setStrokeStyles(ctx);\n this._setFillStyles(ctx);\n if (this.transformMatrix) {\n ctx.transform.apply(ctx, this.transformMatrix);\n }\n this._setOpacity(ctx);\n this._setShadow(ctx);\n this.clipTo && fabric.util.clipContext(this, ctx);\n this._render(ctx, noTransform);\n this.clipTo && ctx.restore();\n\n ctx.restore();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _setOpacity: function(ctx) {\n if (this.group) {\n this.group._setOpacity(ctx);\n }\n ctx.globalAlpha *= this.opacity;\n },\n\n _setStrokeStyles: function(ctx) {\n if (this.stroke) {\n ctx.lineWidth = this.strokeWidth;\n ctx.lineCap = this.strokeLineCap;\n ctx.lineJoin = this.strokeLineJoin;\n ctx.miterLimit = this.strokeMiterLimit;\n ctx.strokeStyle = this.stroke.toLive\n ? this.stroke.toLive(ctx, this)\n : this.stroke;\n }\n },\n\n _setFillStyles: function(ctx) {\n if (this.fill) {\n ctx.fillStyle = this.fill.toLive\n ? this.fill.toLive(ctx, this)\n : this.fill;\n }\n },\n\n /**\n * Renders controls and borders for the object\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n _renderControls: function(ctx, noTransform) {\n if (!this.active || noTransform) {\n return;\n }\n var vpt = this.getViewportTransform();\n ctx.save();\n var center;\n if (this.group) {\n center = fabric.util.transformPoint(this.group.getCenterPoint(), vpt);\n ctx.translate(center.x, center.y);\n ctx.rotate(degreesToRadians(this.group.angle));\n }\n center = fabric.util.transformPoint(this.getCenterPoint(), vpt, null != this.group);\n if (this.group) {\n center.x *= this.group.scaleX;\n center.y *= this.group.scaleY;\n }\n ctx.translate(center.x, center.y);\n ctx.rotate(degreesToRadians(this.angle));\n this.drawBorders(ctx);\n this.drawControls(ctx);\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 multX = (this.canvas && this.canvas.viewportTransform[0]) || 1,\n multY = (this.canvas && this.canvas.viewportTransform[3]) || 1;\n\n ctx.shadowColor = this.shadow.color;\n ctx.shadowBlur = this.shadow.blur * (multX + multY) * (this.scaleX + this.scaleY) / 4;\n ctx.shadowOffsetX = this.shadow.offsetX * multX * this.scaleX;\n ctx.shadowOffsetY = this.shadow.offsetY * multY * this.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 */\n _renderFill: function(ctx) {\n if (!this.fill) {\n return;\n }\n\n ctx.save();\n if (this.fill.gradientTransform) {\n var g = this.fill.gradientTransform;\n ctx.transform.apply(ctx, g);\n }\n if (this.fill.toLive) {\n ctx.translate(\n -this.width / 2 + this.fill.offsetX || 0,\n -this.height / 2 + this.fill.offsetY || 0);\n }\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\n if (this.strokeDashArray) {\n // Spec requires the concatenation of two copies the dash list when the number of elements is odd\n if (1 & this.strokeDashArray.length) {\n this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray);\n }\n if (supportsLineDash) {\n ctx.setLineDash(this.strokeDashArray);\n this._stroke && this._stroke(ctx);\n }\n else {\n this._renderDashedStroke && this._renderDashedStroke(ctx);\n }\n ctx.stroke();\n }\n else {\n if (this.stroke.gradientTransform) {\n var g = this.stroke.gradientTransform;\n ctx.transform.apply(ctx, g);\n }\n this._stroke ? this._stroke(ctx) : ctx.stroke();\n }\n ctx.restore();\n },\n\n /**\n * Clones an instance\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 * @return {fabric.Object} clone of an instance\n */\n clone: function(callback, propertiesToInclude) {\n if (this.constructor.fromObject) {\n return this.constructor.fromObject(this.toObject(propertiesToInclude), callback);\n }\n return new fabric.Object(this.toObject(propertiesToInclude));\n },\n\n /**\n * Creates an instance of fabric.Image out of an object\n * @param {Function} callback callback, invoked with an instance as a first argument\n * @return {fabric.Object} thisArg\n */\n cloneAsImage: function(callback) {\n var dataUrl = this.toDataURL();\n fabric.util.loadImage(dataUrl, function(img) {\n if (callback) {\n callback(new fabric.Image(img));\n }\n });\n return this;\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 * @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\n var el = fabric.util.createCanvasElement(),\n boundingRect = this.getBoundingRect();\n\n el.width = boundingRect.width;\n el.height = boundingRect.height;\n\n fabric.util.wrapElement(el, 'div');\n var canvas = new fabric.StaticCanvas(el);\n\n // to avoid common confusion https://github.com/kangax/fabric.js/issues/806\n if (options.format === 'jpg') {\n options.format = 'jpeg';\n }\n\n if (options.format === 'jpeg') {\n canvas.backgroundColor = '#fff';\n }\n\n var origParams = {\n active: this.get('active'),\n left: this.getLeft(),\n top: this.getTop()\n };\n\n this.set('active', false);\n this.setPositionByOrigin(new fabric.Point(el.width / 2, el.height / 2), 'center', 'center');\n\n var originalCanvas = this.canvas;\n canvas.add(this);\n var data = canvas.toDataURL(options);\n\n this.set(origParams).setCoords();\n this.canvas = originalCanvas;\n\n canvas.dispose();\n canvas = null;\n\n return data;\n },\n\n /**\n * Returns true if specified type is identical to the type of an instance\n * @param {String} type Type to check against\n * @return {Boolean}\n */\n isType: function(type) {\n return this.type === type;\n },\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity of this instance\n */\n complexity: function() {\n return 0;\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 gradient (fill or stroke) of an object\n * Backwards incompatibility note: This method was named \"setGradientFill\" until v1.1.0\n * @param {String} property Property name 'stroke' or 'fill'\n * @param {Object} [options] Options object\n * @param {String} [options.type] Type of gradient 'radial' or 'linear'\n * @param {Number} [options.x1=0] x-coordinate of start point\n * @param {Number} [options.y1=0] y-coordinate of start point\n * @param {Number} [options.x2=0] x-coordinate of end point\n * @param {Number} [options.y2=0] y-coordinate of end point\n * @param {Number} [options.r1=0] Radius of start point (only for radial gradients)\n * @param {Number} [options.r2=0] Radius of end point (only for radial gradients)\n * @param {Object} [options.colorStops] Color stops object eg. {0: 'ff0000', 1: '000000'}\n * @return {fabric.Object} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/58y8b/|jsFiddle demo}\n * @example Set linear gradient\n * object.setGradient('fill', {\n * type: 'linear',\n * x1: -object.width / 2,\n * y1: 0,\n * x2: object.width / 2,\n * y2: 0,\n * colorStops: {\n * 0: 'red',\n * 0.5: '#005555',\n * 1: 'rgba(0,0,255,0.5)'\n * }\n * });\n * canvas.renderAll();\n * @example Set radial gradient\n * object.setGradient('fill', {\n * type: 'radial',\n * x1: 0,\n * y1: 0,\n * x2: 0,\n * y2: 0,\n * r1: object.width / 2,\n * r2: 10,\n * colorStops: {\n * 0: 'red',\n * 0.5: '#005555',\n * 1: 'rgba(0,0,255,0.5)'\n * }\n * });\n * canvas.renderAll();\n */\n setGradient: function(property, options) {\n options || (options = { });\n\n var gradient = { colorStops: [] };\n\n gradient.type = options.type || (options.r1 || options.r2 ? 'radial' : 'linear');\n gradient.coords = {\n x1: options.x1,\n y1: options.y1,\n x2: options.x2,\n y2: options.y2\n };\n\n if (options.r1 || options.r2) {\n gradient.coords.r1 = options.r1;\n gradient.coords.r2 = options.r2;\n }\n\n for (var position in options.colorStops) {\n var color = new fabric.Color(options.colorStops[position]);\n gradient.colorStops.push({\n offset: position,\n color: color.toRgb(),\n opacity: color.getAlpha()\n });\n }\n\n return this.set(property, fabric.Gradient.forObject(this, gradient));\n },\n\n /**\n * Sets pattern fill of an object\n * @param {Object} options Options object\n * @param {(String|HTMLImageElement)} options.source Pattern source\n * @param {String} [options.repeat=repeat] Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat)\n * @param {Number} [options.offsetX=0] Pattern horizontal offset from object's left/top corner\n * @param {Number} [options.offsetY=0] Pattern vertical offset from object's left/top corner\n * @return {fabric.Object} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/QT3pa/|jsFiddle demo}\n * @example Set pattern\n * fabric.util.loadImage('http://fabricjs.com/assets/escheresque_ste.png', function(img) {\n * object.setPatternFill({\n * source: img,\n * repeat: 'repeat'\n * });\n * canvas.renderAll();\n * });\n */\n setPatternFill: function(options) {\n return this.set('fill', new fabric.Pattern(options));\n },\n\n /**\n * Sets {@link fabric.Object#shadow|shadow} of an object\n * @param {Object|String} [options] Options object or string (e.g. \"2px 2px 10px rgba(0,0,0,0.2)\")\n * @param {String} [options.color=rgb(0,0,0)] Shadow color\n * @param {Number} [options.blur=0] Shadow blur\n * @param {Number} [options.offsetX=0] Shadow horizontal offset\n * @param {Number} [options.offsetY=0] Shadow vertical offset\n * @return {fabric.Object} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/7gvJG/|jsFiddle demo}\n * @example Set shadow with string notation\n * object.setShadow('2px 2px 10px rgba(0,0,0,0.2)');\n * canvas.renderAll();\n * @example Set shadow with object notation\n * object.setShadow({\n * color: 'red',\n * blur: 10,\n * offsetX: 20,\n * offsetY: 20\n * });\n * canvas.renderAll();\n */\n setShadow: function(options) {\n return this.set('shadow', options ? new fabric.Shadow(options) : null);\n },\n\n /**\n * Sets \"color\" of an instance (alias of `set('fill', …)`)\n * @param {String} color Color value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setColor: function(color) {\n this.set('fill', color);\n return this;\n },\n\n /**\n * Sets \"angle\" of an instance\n * @param {Number} angle Angle value (in degrees)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setAngle: 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.centerObjectH(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.centerObjectV(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.centerObject(this);\n return this;\n },\n\n /**\n * Removes object from canvas to which it was added last\n * @return {fabric.Object} thisArg\n * @chainable\n */\n remove: function() {\n this.canvas.remove(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, fabric.util.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 specifed using globalCompositeOperation property\n * @param {CanvasRenderingContext2D} ctx Rendering canvas context\n */\n _setupCompositeOperation: function (ctx) {\n if (this.globalCompositeOperation) {\n ctx.globalCompositeOperation = this.globalCompositeOperation;\n }\n }\n });\n\n fabric.util.createAccessors(fabric.Object);\n\n /**\n * Alias for {@link fabric.Object.prototype.setAngle}\n * @alias rotate -> setAngle\n * @memberOf fabric.Object\n */\n fabric.Object.prototype.rotate = fabric.Object.prototype.setAngle;\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 * Unique id used internally when creating SVG elements\n * @static\n * @memberOf fabric.Object\n * @type Number\n */\n fabric.Object.__uid = 0;\n\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 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} 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 = originXOffset[toOriginX] - originXOffset[fromOriginX],\n offsetY = originYOffset[toOriginY] - originYOffset[fromOriginY],\n dim;\n if (offsetX || offsetY) {\n dim = this._getTransformedDimensions();\n x = point.x + offsetX * dim.x;\n y = point.y + offsetY * dim.y;\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 (originX && originY) {\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\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.getWidth(),\n xFull = Math.cos(angle) * hypotFull,\n yFull = Math.sin(angle) * hypotFull;\n\n //TODO: this function does not consider mixed situation like top, center.\n this.left += xFull * (originXOffset[to] - originXOffset[this.originX]);\n this.top += yFull * (originXOffset[to] - originXOffset[this.originX]);\n\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 var degreesToRadians = fabric.util.degreesToRadians;\n\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * Object containing coordinates of object's controls\n * @type Object\n * @default\n */\n oCoords: null,\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 * @return {Boolean} true if object intersects with an area formed by 2 points\n */\n intersectsWithRect: function(pointTL, pointBR) {\n var oCoords = this.oCoords,\n tl = new fabric.Point(oCoords.tl.x, oCoords.tl.y),\n tr = new fabric.Point(oCoords.tr.x, oCoords.tr.y),\n bl = new fabric.Point(oCoords.bl.x, oCoords.bl.y),\n br = new fabric.Point(oCoords.br.x, oCoords.br.y),\n intersection = fabric.Intersection.intersectPolygonRectangle(\n [tl, tr, br, bl],\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 * @return {Boolean} true if object intersects with another object\n */\n intersectsWithObject: function(other) {\n // extracts coords\n function getCoords(oCoords) {\n return {\n tl: new fabric.Point(oCoords.tl.x, oCoords.tl.y),\n tr: new fabric.Point(oCoords.tr.x, oCoords.tr.y),\n bl: new fabric.Point(oCoords.bl.x, oCoords.bl.y),\n br: new fabric.Point(oCoords.br.x, oCoords.br.y)\n };\n }\n var thisCoords = getCoords(this.oCoords),\n otherCoords = getCoords(other.oCoords),\n intersection = fabric.Intersection.intersectPolygonPolygon(\n [thisCoords.tl, thisCoords.tr, thisCoords.br, thisCoords.bl],\n [otherCoords.tl, otherCoords.tr, otherCoords.br, otherCoords.bl]\n );\n\n return intersection.status === 'Intersection';\n },\n\n /**\n * Checks if object is fully contained within area of another object\n * @param {Object} other Object to test\n * @return {Boolean} true if object is fully contained within area of another object\n */\n isContainedWithinObject: function(other) {\n var boundingRect = other.getBoundingRect(),\n point1 = new fabric.Point(boundingRect.left, boundingRect.top),\n point2 = new fabric.Point(boundingRect.left + boundingRect.width, boundingRect.top + boundingRect.height);\n\n return this.isContainedWithinRect(point1, point2);\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 * @return {Boolean} true if object is fully contained within area formed by 2 points\n */\n isContainedWithinRect: function(pointTL, pointBR) {\n var boundingRect = this.getBoundingRect();\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 * @return {Boolean} true if point is inside the object\n */\n containsPoint: function(point) {\n var lines = this._getImageLines(this.oCoords),\n xPoints = this._findCrossPoints(point, lines);\n\n // if xPoints is odd then point is inside the object\n return (xPoints !== 0 && xPoints % 2 === 1);\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 return {\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\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} oCoords Coordinates of the object being evaluated\n */\n _findCrossPoints: function(point, oCoords) {\n var b1, b2, a1, a2, xi, yi,\n xcount = 0,\n iLine;\n\n for (var lineKey in oCoords) {\n iLine = oCoords[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 width of an object's bounding rectangle\n * @deprecated since 1.0.4\n * @return {Number} width value\n */\n getBoundingRectWidth: function() {\n return this.getBoundingRect().width;\n },\n\n /**\n * Returns height of an object's bounding rectangle\n * @deprecated since 1.0.4\n * @return {Number} height value\n */\n getBoundingRectHeight: function() {\n return this.getBoundingRect().height;\n },\n\n /**\n * Returns coordinates of object's bounding rectangle (left, top, width, height)\n * @return {Object} Object with left, top, width, height properties\n */\n getBoundingRect: function() {\n this.oCoords || this.setCoords();\n\n var xCoords = [this.oCoords.tl.x, this.oCoords.tr.x, this.oCoords.br.x, this.oCoords.bl.x],\n minX = fabric.util.array.min(xCoords),\n maxX = fabric.util.array.max(xCoords),\n width = Math.abs(minX - maxX),\n\n yCoords = [this.oCoords.tl.y, this.oCoords.tr.y, this.oCoords.br.y, this.oCoords.bl.y],\n minY = fabric.util.array.min(yCoords),\n maxY = fabric.util.array.max(yCoords),\n height = Math.abs(minY - maxY);\n\n return {\n left: minX,\n top: minY,\n width: width,\n height: height\n };\n },\n\n /**\n * Returns width of an object\n * @return {Number} width value\n */\n getWidth: function() {\n return this.width * this.scaleX;\n },\n\n /**\n * Returns height of an object\n * @return {Number} height value\n */\n getHeight: function() {\n return this.height * this.scaleY;\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 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 value = this._constrainScale(value);\n\n if (value < 0) {\n this.flipX = !this.flipX;\n this.flipY = !this.flipY;\n value *= -1;\n }\n\n this.scaleX = value;\n this.scaleY = value;\n this.setCoords();\n return this;\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 * @return {fabric.Object} thisArg\n * @chainable\n */\n scaleToWidth: function(value) {\n // adjust to bounding rect factor so that rotated shapes would fit as well\n var boundingRectFactor = this.getBoundingRectWidth() / this.getWidth();\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 * @return {fabric.Object} thisArg\n * @chainable\n */\n scaleToHeight: function(value) {\n // adjust to bounding rect factor so that rotated shapes would fit as well\n var boundingRectFactor = this.getBoundingRectHeight() / this.getHeight();\n return this.scale(value / this.height / boundingRectFactor);\n },\n\n /**\n * Sets corner position coordinates based on current angle, width and height\n * See https://github.com/kangax/fabric.js/wiki/When-to-call-setCoords\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setCoords: function() {\n var theta = degreesToRadians(this.angle),\n vpt = this.getViewportTransform(),\n dim = this._calculateCurrentDimensions(true),\n currentWidth = dim.x, currentHeight = dim.y;\n\n // If width is negative, make postive. Fixes path selection issue\n if (currentWidth < 0) {\n currentWidth = Math.abs(currentWidth);\n }\n\n var sinTh = Math.sin(theta),\n cosTh = Math.cos(theta),\n _angle = currentWidth > 0 ? Math.atan(currentHeight / currentWidth) : 0,\n _hypotenuse = (currentWidth / Math.cos(_angle)) / 2,\n offsetX = Math.cos(_angle + theta) * _hypotenuse,\n offsetY = Math.sin(_angle + theta) * _hypotenuse,\n\n // offset added for rotate and scale actions\n coords = fabric.util.transformPoint(this.getCenterPoint(), vpt),\n tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY),\n tr = new fabric.Point(tl.x + (currentWidth * cosTh), tl.y + (currentWidth * sinTh)),\n bl = new fabric.Point(tl.x - (currentHeight * sinTh), tl.y + (currentHeight * cosTh)),\n br = new fabric.Point(coords.x + offsetX, coords.y + offsetY),\n ml = new fabric.Point((tl.x + bl.x)/2, (tl.y + bl.y)/2),\n mt = new fabric.Point((tr.x + tl.x)/2, (tr.y + tl.y)/2),\n mr = new fabric.Point((br.x + tr.x)/2, (br.y + tr.y)/2),\n mb = new fabric.Point((br.x + bl.x)/2, (br.y + bl.y)/2),\n mtr = new fabric.Point(mt.x + sinTh * this.rotatingPointOffset, mt.y - cosTh * this.rotatingPointOffset);\n // debugging\n\n /* setTimeout(function() {\n canvas.contextTop.fillStyle = 'green';\n canvas.contextTop.fillRect(mb.x, mb.y, 3, 3);\n canvas.contextTop.fillRect(bl.x, bl.y, 3, 3);\n canvas.contextTop.fillRect(br.x, br.y, 3, 3);\n canvas.contextTop.fillRect(tl.x, tl.y, 3, 3);\n canvas.contextTop.fillRect(tr.x, tr.y, 3, 3);\n canvas.contextTop.fillRect(ml.x, ml.y, 3, 3);\n canvas.contextTop.fillRect(mr.x, mr.y, 3, 3);\n canvas.contextTop.fillRect(mt.x, mt.y, 3, 3);\n canvas.contextTop.fillRect(mtr.x, mtr.y, 3, 3);\n }, 50); */\n\n this.oCoords = {\n // corners\n tl: tl, tr: tr, br: br, bl: bl,\n // middle\n ml: ml, mt: mt, mr: mr, mb: mb,\n // rotating point\n mtr: mtr\n };\n\n // set coordinates of the draggable boxes in the corners used to scale/rotate the image\n this._setCornerCoords && this._setCornerCoords();\n\n return this;\n },\n\n _calcDimensionsTransformMatrix: function() {\n // introduce skew matrix here later\n return [this.scaleX, 0, 0, this.scaleY, 0, 0];\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 {\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 {\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 {\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 {\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) {\n fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index);\n }\n else {\n this.canvas.moveTo(this, index);\n }\n return this;\n }\n});\n\n\n/* _TO_SVG_START_ */\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * Returns styles-string for svg-export\n * @return {String}\n */\n getSvgStyles: function() {\n\n var fill = this.fill\n ? (this.fill.toLive ? 'url(#SVGID_' + this.fill.id + ')' : this.fill)\n : 'none',\n fillRule = this.fillRule,\n stroke = this.stroke\n ? (this.stroke.toLive ? 'url(#SVGID_' + this.stroke.id + ')' : this.stroke)\n : 'none',\n\n strokeWidth = this.strokeWidth ? this.strokeWidth : '0',\n strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : 'none',\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\n visibility = this.visible ? '' : ' visibility: hidden;',\n filter = this.shadow ? 'filter: url(#SVGID_' + this.shadow.id + ');' : '';\n\n return [\n 'stroke: ', stroke, '; ',\n 'stroke-width: ', strokeWidth, '; ',\n 'stroke-dasharray: ', strokeDashArray, '; ',\n 'stroke-linecap: ', strokeLineCap, '; ',\n 'stroke-linejoin: ', strokeLineJoin, '; ',\n 'stroke-miterlimit: ', strokeMiterLimit, '; ',\n 'fill: ', fill, '; ',\n 'fill-rule: ', fillRule, '; ',\n 'opacity: ', opacity, ';',\n filter,\n visibility\n ].join('');\n },\n\n /**\n * Returns transform-string for svg-export\n * @return {String}\n */\n getSvgTransform: function() {\n if (this.group && this.group.type === 'path-group') {\n return '';\n }\n var toFixed = fabric.util.toFixed,\n angle = this.getAngle(),\n vpt = !this.canvas || this.canvas.svgViewportTransformation ? this.getViewportTransform() : [1, 0, 0, 1, 0, 0],\n center = fabric.util.transformPoint(this.getCenterPoint(), vpt),\n\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n\n translatePart = this.type === 'path-group' ? '' : 'translate(' +\n toFixed(center.x, NUM_FRACTION_DIGITS) +\n ' ' +\n toFixed(center.y, NUM_FRACTION_DIGITS) +\n ')',\n\n anglePart = angle !== 0\n ? (' rotate(' + toFixed(angle, NUM_FRACTION_DIGITS) + ')')\n : '',\n\n scalePart = (this.scaleX === 1 && this.scaleY === 1 && vpt[0] === 1 && vpt[3] === 1)\n ? '' :\n (' scale(' +\n toFixed(this.scaleX * vpt[0], NUM_FRACTION_DIGITS) +\n ' ' +\n toFixed(this.scaleY * vpt[3], NUM_FRACTION_DIGITS) +\n ')'),\n\n addTranslateX = this.type === 'path-group' ? this.width * vpt[0] : 0,\n\n flipXPart = this.flipX ? ' matrix(-1 0 0 1 ' + addTranslateX + ' 0) ' : '',\n\n addTranslateY = this.type === 'path-group' ? this.height * vpt[3] : 0,\n\n flipYPart = this.flipY ? ' matrix(1 0 0 -1 0 ' + addTranslateY + ')' : '';\n\n return [\n translatePart, anglePart, scalePart, flipXPart, flipYPart\n ].join('');\n },\n\n /**\n * Returns transform-string for svg-export from the transform matrix of single elements\n * @return {String}\n */\n getSvgTransformMatrix: function() {\n return this.transformMatrix ? ' matrix(' + this.transformMatrix.join(' ') + ') ' : '';\n },\n\n /**\n * @private\n */\n _createBaseSVGMarkup: function() {\n var markup = [ ];\n\n if (this.fill && this.fill.toLive) {\n markup.push(this.fill.toSVG(this, false));\n }\n if (this.stroke && this.stroke.toLive) {\n markup.push(this.stroke.toSVG(this, false));\n }\n if (this.shadow) {\n markup.push(this.shadow.toSVG(this));\n }\n return markup;\n }\n});\n/* _TO_SVG_END_ */\n\n\n/*\n Depends on `stateProperties`\n*/\nfabric.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 * @return {Boolean} true if instance' state has changed since `{@link fabric.Object#saveState}` was called\n */\n hasStateChanged: function() {\n return this.stateProperties.some(function(prop) {\n return this.get(prop) !== this.originalState[prop];\n }, this);\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 this.stateProperties.forEach(function(prop) {\n this.originalState[prop] = this.get(prop);\n }, this);\n\n if (options && options.stateProperties) {\n options.stateProperties.forEach(function(prop) {\n this.originalState[prop] = this.get(prop);\n }, this);\n }\n\n return this;\n },\n\n /**\n * Setups state of an object\n * @return {fabric.Object} thisArg\n */\n setupState: function() {\n this.originalState = { };\n this.saveState();\n\n return this;\n }\n});\n\n\n(function() {\n\n var degreesToRadians = fabric.util.degreesToRadians,\n //jscs:disable requireCamelCaseOrUpperCaseIdentifiers\n isVML = function() { return typeof G_vmlCanvasManager !== 'undefined'; };\n //jscs:enable requireCamelCaseOrUpperCaseIdentifiers\n\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * The object interactivity controls.\n * @private\n */\n _controlsVisibility: null,\n\n /**\n * Determines which corner has been clicked\n * @private\n * @param {Object} pointer The pointer indicating the mouse position\n * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or false if nothing is found\n */\n _findTargetCorner: function(pointer) {\n if (!this.hasControls || !this.active) {\n return false;\n }\n\n var ex = pointer.x,\n ey = pointer.y,\n xPoints,\n lines;\n\n for (var i in this.oCoords) {\n\n if (!this.isControlVisible(i)) {\n continue;\n }\n\n if (i === 'mtr' && !this.hasRotatingPoint) {\n continue;\n }\n\n if (this.get('lockUniScaling') &&\n (i === 'mt' || i === 'mr' || i === 'mb' || i === 'ml')) {\n continue;\n }\n\n lines = this._getImageLines(this.oCoords[i].corner);\n\n // debugging\n\n // canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);\n // canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);\n\n // canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);\n // canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);\n\n // canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);\n // canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);\n\n // canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);\n // 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 * Sets the coordinates of the draggable boxes in the corners of\n * the image used to scale/rotate it.\n * @private\n */\n _setCornerCoords: function() {\n var coords = this.oCoords,\n newTheta = degreesToRadians(45 - this.angle),\n /* Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, */\n /* 0.707106 stands for sqrt(2)/2 */\n cornerHypotenuse = this.cornerSize * 0.707106,\n cosHalfOffset = cornerHypotenuse * Math.cos(newTheta),\n sinHalfOffset = cornerHypotenuse * Math.sin(newTheta),\n x, y;\n\n for (var point in coords) {\n x = coords[point].x;\n y = coords[point].y;\n coords[point].corner = {\n tl: {\n x: x - sinHalfOffset,\n y: y - cosHalfOffset\n },\n tr: {\n x: x + cosHalfOffset,\n y: y - sinHalfOffset\n },\n bl: {\n x: x - cosHalfOffset,\n y: y + sinHalfOffset\n },\n br: {\n x: x + sinHalfOffset,\n y: y + cosHalfOffset\n }\n };\n }\n },\n\n /*\n * Calculate object dimensions from its properties\n * @private\n */\n _getNonTransformedDimensions: function() {\n var strokeWidth = this.strokeWidth,\n w = this.width,\n h = this.height,\n capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square',\n vLine = this.type === 'line' && this.width === 0,\n hLine = this.type === 'line' && this.height === 0,\n sLine = vLine || hLine,\n strokeW = (capped && hLine) || !sLine,\n strokeH = (capped && vLine) || !sLine;\n\n if (vLine) {\n w = strokeWidth;\n }\n else if (hLine) {\n h = strokeWidth;\n }\n if (strokeW) {\n w += (w < 0 ? -strokeWidth : strokeWidth);\n }\n if (strokeH) {\n h += (h < 0 ? -strokeWidth : strokeWidth);\n }\n return { x: w, y: h };\n },\n\n /*\n * @private\n */\n _getTransformedDimensions: function(dimensions) {\n if (!dimensions) {\n dimensions = this._getNonTransformedDimensions();\n }\n var transformMatrix = this._calcDimensionsTransformMatrix();\n return fabric.util.transformPoint(dimensions, transformMatrix, true);\n },\n\n /*\n * private\n */\n _calculateCurrentDimensions: function(shouldTransform) {\n var vpt = this.getViewportTransform(),\n dim = this._getTransformedDimensions(),\n w = dim.x, h = dim.y;\n\n w += 2 * this.padding;\n h += 2 * this.padding;\n\n if (shouldTransform) {\n return fabric.util.transformPoint(new fabric.Point(w, h), vpt, true);\n }\n return { x: w, y: h };\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 * @return {fabric.Object} thisArg\n * @chainable\n */\n drawBorders: function(ctx) {\n if (!this.hasBorders) {\n return this;\n }\n\n ctx.save();\n\n ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n ctx.strokeStyle = this.borderColor;\n ctx.lineWidth = 1 / this.borderScaleFactor;\n\n var wh = this._calculateCurrentDimensions(true),\n width = wh.x,\n height = wh.y;\n if (this.group) {\n width = width * this.group.scaleX;\n height = height * this.group.scaleY;\n }\n\n ctx.strokeRect(\n ~~(-(width / 2)) - 0.5, // offset needed to make lines look sharper\n ~~(-(height / 2)) - 0.5,\n ~~(width) + 1, // double offset needed to make lines look sharper\n ~~(height) + 1\n );\n\n if (this.hasRotatingPoint && this.isControlVisible('mtr') && !this.get('lockRotation') && this.hasControls) {\n\n var rotateHeight = -height / 2;\n\n ctx.beginPath();\n ctx.moveTo(0, rotateHeight);\n ctx.lineTo(0, rotateHeight - this.rotatingPointOffset);\n ctx.closePath();\n ctx.stroke();\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 * @return {fabric.Object} thisArg\n * @chainable\n */\n drawControls: function(ctx) {\n if (!this.hasControls) {\n return this;\n }\n\n var wh = this._calculateCurrentDimensions(true),\n width = wh.x,\n height = wh.y,\n left = -(width / 2),\n top = -(height / 2),\n scaleOffset = this.cornerSize / 2,\n methodName = this.transparentCorners ? 'strokeRect' : 'fillRect';\n\n ctx.save();\n\n ctx.lineWidth = 1;\n\n ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n ctx.strokeStyle = ctx.fillStyle = this.cornerColor;\n\n // top-left\n this._drawControl('tl', ctx, methodName,\n left - scaleOffset,\n top - scaleOffset);\n\n // top-right\n this._drawControl('tr', ctx, methodName,\n left + width - scaleOffset,\n top - scaleOffset);\n\n // bottom-left\n this._drawControl('bl', ctx, methodName,\n left - scaleOffset,\n top + height - scaleOffset);\n\n // bottom-right\n this._drawControl('br', ctx, methodName,\n left + width - scaleOffset,\n top + height - scaleOffset);\n\n if (!this.get('lockUniScaling')) {\n\n // middle-top\n this._drawControl('mt', ctx, methodName,\n left + width/2 - scaleOffset,\n top - scaleOffset);\n\n // middle-bottom\n this._drawControl('mb', ctx, methodName,\n left + width/2 - scaleOffset,\n top + height - scaleOffset);\n\n // middle-right\n this._drawControl('mr', ctx, methodName,\n left + width - scaleOffset,\n top + height/2 - scaleOffset);\n\n // middle-left\n this._drawControl('ml', ctx, methodName,\n left - scaleOffset,\n top + height/2 - scaleOffset);\n }\n\n // middle-top-rotate\n if (this.hasRotatingPoint) {\n this._drawControl('mtr', ctx, methodName,\n left + width/2 - scaleOffset,\n top - this.rotatingPointOffset - scaleOffset);\n }\n\n ctx.restore();\n\n return this;\n },\n\n /**\n * @private\n */\n _drawControl: function(control, ctx, methodName, left, top) {\n if (!this.isControlVisible(control)) {\n return;\n }\n var size = this.cornerSize;\n isVML() || this.transparentCorners || ctx.clearRect(left, top, size, size);\n ctx[methodName](left, top, size, size);\n },\n\n /**\n * Returns true if the specified control is visible, false otherwise.\n * @param {String} controlName The name 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(controlName) {\n return this._getControlsVisibility()[controlName];\n },\n\n /**\n * Sets the visibility of the specified control.\n * @param {String} controlName The name 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(controlName, visible) {\n this._getControlsVisibility()[controlName] = 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 * Returns the instance of the control visibility set for this object.\n * @private\n * @returns {Object}\n */\n _getControlsVisibility: function() {\n if (!this._controlsVisibility) {\n this._controlsVisibility = {\n tl: true,\n tr: true,\n br: true,\n bl: true,\n ml: true,\n mt: true,\n mr: true,\n mb: true,\n mtr: true\n };\n }\n return this._controlsVisibility;\n }\n });\n})();\n\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n /**\n * Animation duration (in ms) for fx* methods\n * @type Number\n * @default\n */\n FX_DURATION: 500,\n\n /**\n * Centers object horizontally with animation.\n * @param {fabric.Object} object Object to center\n * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n * @param {Function} [callbacks.onComplete] Invoked on completion\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n fxCenterObjectH: function (object, callbacks) {\n callbacks = callbacks || { };\n\n var empty = function() { },\n onComplete = callbacks.onComplete || empty,\n onChange = callbacks.onChange || empty,\n _this = this;\n\n fabric.util.animate({\n startValue: object.get('left'),\n endValue: this.getCenter().left,\n duration: this.FX_DURATION,\n onChange: function(value) {\n object.set('left', value);\n _this.renderAll();\n onChange();\n },\n onComplete: function() {\n object.setCoords();\n onComplete();\n }\n });\n\n return this;\n },\n\n /**\n * Centers object vertically with animation.\n * @param {fabric.Object} object Object to center\n * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n * @param {Function} [callbacks.onComplete] Invoked on completion\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n fxCenterObjectV: function (object, callbacks) {\n callbacks = callbacks || { };\n\n var empty = function() { },\n onComplete = callbacks.onComplete || empty,\n onChange = callbacks.onChange || empty,\n _this = this;\n\n fabric.util.animate({\n startValue: object.get('top'),\n endValue: this.getCenter().top,\n duration: this.FX_DURATION,\n onChange: function(value) {\n object.set('top', value);\n _this.renderAll();\n onChange();\n },\n onComplete: function() {\n object.setCoords();\n onComplete();\n }\n });\n\n return this;\n },\n\n /**\n * Same as `fabric.Canvas#remove` but animated\n * @param {fabric.Object} object Object to remove\n * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n * @param {Function} [callbacks.onComplete] Invoked on completion\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n fxRemove: function (object, callbacks) {\n callbacks = callbacks || { };\n\n var empty = function() { },\n onComplete = callbacks.onComplete || empty,\n onChange = callbacks.onChange || empty,\n _this = this;\n\n fabric.util.animate({\n startValue: object.get('opacity'),\n endValue: 0,\n duration: this.FX_DURATION,\n onStart: function() {\n object.set('active', false);\n },\n onChange: function(value) {\n object.set('opacity', value);\n _this.renderAll();\n onChange();\n },\n onComplete: function () {\n _this.remove(object);\n onComplete();\n }\n });\n\n return this;\n }\n});\n\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n /**\n * Animates object's properties\n * @param {String|Object} property Property to animate (if string) or properties to animate (if object)\n * @param {Number|Object} value Value to animate property to (if string was given first) or options object\n * @return {fabric.Object} thisArg\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#animation}\n * @chainable\n *\n * As object — multiple properties\n *\n * object.animate({ left: ..., top: ... });\n * object.animate({ left: ..., top: ... }, { duration: ... });\n *\n * As string — one property\n *\n * object.animate('left', ...);\n * object.animate('left', { duration: ... });\n *\n */\n animate: function() {\n if (arguments[0] && typeof arguments[0] === 'object') {\n var propsToAnimate = [ ], prop, skipCallbacks;\n for (prop in arguments[0]) {\n propsToAnimate.push(prop);\n }\n for (var i = 0, len = propsToAnimate.length; i < len; i++) {\n prop = propsToAnimate[i];\n skipCallbacks = i !== len - 1;\n this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks);\n }\n }\n else {\n this._animate.apply(this, arguments);\n }\n return this;\n },\n\n /**\n * @private\n * @param {String} property Property to animate\n * @param {String} to Value to animate to\n * @param {Object} [options] Options object\n * @param {Boolean} [skipCallbacks] When true, callbacks like onchange and oncomplete are not invoked\n */\n _animate: function(property, to, options, skipCallbacks) {\n var _this = this, propPair;\n\n to = to.toString();\n\n if (!options) {\n options = { };\n }\n else {\n options = fabric.util.object.clone(options);\n }\n\n if (~property.indexOf('.')) {\n propPair = property.split('.');\n }\n\n var 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 (~to.indexOf('=')) {\n to = currentValue + parseFloat(to.replace('=', ''));\n }\n else {\n to = parseFloat(to);\n }\n\n fabric.util.animate({\n startValue: options.from,\n endValue: to,\n byValue: options.by,\n easing: options.easing,\n duration: options.duration,\n abort: options.abort && function() {\n return options.abort.call(_this);\n },\n onChange: function(value) {\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();\n },\n onComplete: function() {\n if (skipCallbacks) {\n return;\n }\n\n _this.setCoords();\n options.onComplete && options.onComplete();\n }\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 coordProps = { x1: 1, x2: 1, y1: 1, y2: 1 },\n supportsLineDash = fabric.StaticCanvas.supports('setLineDash');\n\n if (fabric.Line) {\n fabric.warn('fabric.Line is already defined');\n return;\n }\n\n /**\n * Line class\n * @class fabric.Line\n * @extends fabric.Object\n * @see {@link fabric.Line#initialize} for constructor definition\n */\n fabric.Line = fabric.util.createClass(fabric.Object, /** @lends fabric.Line.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'line',\n\n /**\n * x value or first line edge\n * @type Number\n * @default\n */\n x1: 0,\n\n /**\n * y value or first line edge\n * @type Number\n * @default\n */\n y1: 0,\n\n /**\n * x value or second line edge\n * @type Number\n * @default\n */\n x2: 0,\n\n /**\n * y value or second line edge\n * @type Number\n * @default\n */\n y2: 0,\n\n /**\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 options = options || { };\n\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 {Any} 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, noTransform) {\n ctx.beginPath();\n\n if (noTransform) {\n // Line coords are distances from left-top of canvas to origin of line.\n // To render line in a path-group, we need to translate them to\n // distances from center of path-group to center of line.\n var cp = this.getCenterPoint();\n ctx.translate(\n cp.x - this.strokeWidth / 2,\n cp.y - this.strokeWidth / 2\n );\n }\n\n if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) {\n // move from center (of virtual box) to its left/top corner\n // we can't assume x1, y1 is top left and x2, y2 is bottom right\n var p = this.calcLinePoints();\n ctx.moveTo(p.x1, p.y1);\n ctx.lineTo(p.x2, p.y2);\n }\n\n ctx.lineWidth = this.strokeWidth;\n\n // TODO: test this\n // make sure setting \"fill\" changes color of a line\n // (by copying fillStyle to strokeStyle, since line is stroked, not filled)\n var origStrokeStyle = ctx.strokeStyle;\n ctx.strokeStyle = this.stroke || ctx.fillStyle;\n this.stroke && this._renderStroke(ctx);\n ctx.strokeStyle = origStrokeStyle;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var p = this.calcLinePoints();\n\n ctx.beginPath();\n fabric.util.drawDashedLine(ctx, p.x1, p.y1, p.x2, p.y2, this.strokeDashArray);\n ctx.closePath();\n },\n\n /**\n * Returns object representation of an instance\n * @methd toObject\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return extend(this.callSuper('toObject', propertiesToInclude), this.calcLinePoints());\n },\n\n /**\n * 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 * @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 markup = this._createBaseSVGMarkup(),\n p = { x1: this.x1, x2: this.x2, y1: this.y1, y2: this.y2 };\n\n if (!(this.group && this.group.type === 'path-group')) {\n p = this.calcLinePoints();\n }\n markup.push(\n '\\n'\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\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.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 * @return {fabric.Line} instance of fabric.Line\n */\n fabric.Line.fromElement = function(element, 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 return 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 * @return {fabric.Line} instance of fabric.Line\n */\n fabric.Line.fromObject = function(object) {\n var points = [object.x1, object.y1, object.x2, object.y2];\n return new fabric.Line(points, object);\n };\n\n /**\n * Produces a function that calculates distance from canvas edge to Line origin.\n */\n function makeEdgeToOriginGetter(propertyNames, originValues) {\n var origin = propertyNames.origin,\n axis1 = propertyNames.axis1,\n axis2 = propertyNames.axis2,\n dimension = propertyNames.dimension,\n nearest = originValues.nearest,\n center = originValues.center,\n farthest = originValues.farthest;\n\n return function() {\n switch (this.get(origin)) {\n case nearest:\n return Math.min(this.get(axis1), this.get(axis2));\n case center:\n return Math.min(this.get(axis1), this.get(axis2)) + (0.5 * this.get(dimension));\n case farthest:\n return Math.max(this.get(axis1), this.get(axis2));\n }\n };\n\n }\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n pi = Math.PI,\n extend = fabric.util.object.extend;\n\n if (fabric.Circle) {\n fabric.warn('fabric.Circle is already defined.');\n return;\n }\n\n /**\n * Circle class\n * @class fabric.Circle\n * @extends fabric.Object\n * @see {@link fabric.Circle#initialize} for constructor definition\n */\n fabric.Circle = fabric.util.createClass(fabric.Object, /** @lends fabric.Circle.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'circle',\n\n /**\n * Radius of this circle\n * @type Number\n * @default\n */\n radius: 0,\n\n /**\n * Start angle of the circle, moving clockwise\n * @type Number\n * @default 0\n */\n startAngle: 0,\n\n /**\n * End angle of the circle\n * @type Number\n * @default 2Pi\n */\n endAngle: pi * 2,\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n * @return {fabric.Circle} thisArg\n */\n initialize: function(options) {\n options = options || { };\n\n this.callSuper('initialize', options);\n this.set('radius', options.radius || 0);\n\n this.startAngle = options.startAngle || this.startAngle;\n this.endAngle = options.endAngle || this.endAngle;\n },\n\n /**\n * @private\n * @param {String} key\n * @param {Any} 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 extend(this.callSuper('toObject', propertiesToInclude), {\n radius: this.get('radius'),\n startAngle: this.startAngle,\n endAngle: this.endAngle\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 markup = this._createBaseSVGMarkup(), x = 0, y = 0,\n angle = (this.endAngle - this.startAngle) % ( 2 * pi);\n\n if (angle === 0) {\n if (this.group && this.group.type === 'path-group') {\n x = this.left + this.radius;\n y = this.top + this.radius;\n }\n markup.push(\n '\\n'\n );\n }\n else {\n var startX = Math.cos(this.startAngle) * this.radius,\n startY = Math.sin(this.startAngle) * this.radius,\n endX = Math.cos(this.endAngle) * this.radius,\n endY = Math.sin(this.endAngle) * this.radius,\n largeFlag = angle > pi ? '1' : '0';\n\n markup.push(\n '\\n'\n );\n }\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n _render: function(ctx, noTransform) {\n ctx.beginPath();\n ctx.arc(noTransform ? this.left + this.radius : 0,\n noTransform ? this.top + this.radius : 0,\n this.radius,\n this.startAngle,\n this.endAngle, false);\n this._renderFill(ctx);\n this._renderStroke(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 * Returns complexity of an instance\n * @return {Number} complexity of this instance\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.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 {Object} [options] Options object\n * @throws {Error} If value of `r` attribute is missing or invalid\n * @return {fabric.Circle} Instance of fabric.Circle\n */\n fabric.Circle.fromElement = function(element, options) {\n options || (options = { });\n\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;\n parsedAttributes.top = parsedAttributes.top || 0;\n\n var obj = new fabric.Circle(extend(parsedAttributes, options));\n\n obj.left -= obj.radius;\n obj.top -= obj.radius;\n return obj;\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 * @return {Object} Instance of fabric.Circle\n */\n fabric.Circle.fromObject = function(object) {\n return new fabric.Circle(object);\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 * Constructor\n * @param {Object} [options] Options object\n * @return {Object} thisArg\n */\n initialize: function(options) {\n options = options || { };\n\n this.callSuper('initialize', options);\n\n this.set('width', options.width || 100)\n .set('height', options.height || 100);\n },\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._renderFill(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var widthBy2 = this.width / 2,\n heightBy2 = this.height / 2;\n\n ctx.beginPath();\n fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray);\n ctx.closePath();\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of an instance\n * @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 markup = this._createBaseSVGMarkup(),\n widthBy2 = this.width / 2,\n heightBy2 = this.height / 2,\n points = [\n -widthBy2 + ' ' + heightBy2,\n '0 ' + -heightBy2,\n widthBy2 + ' ' + heightBy2\n ]\n .join(',');\n\n markup.push(\n ''\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity of this instance\n */\n complexity: function() {\n return 1;\n }\n });\n\n /**\n * Returns fabric.Triangle instance from an object representation\n * @static\n * @memberOf fabric.Triangle\n * @param {Object} object Object to create an instance from\n * @return {Object} instance of Canvas.Triangle\n */\n fabric.Triangle.fromObject = function(object) {\n return new fabric.Triangle(object);\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 extend = fabric.util.object.extend;\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 /**\n * Constructor\n * @param {Object} [options] Options object\n * @return {fabric.Ellipse} thisArg\n */\n initialize: function(options) {\n options = options || { };\n\n this.callSuper('initialize', options);\n\n this.set('rx', options.rx || 0);\n this.set('ry', options.ry || 0);\n },\n\n /**\n * @private\n * @param {String} key\n * @param {Any} 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 extend(this.callSuper('toObject', propertiesToInclude), {\n rx: this.get('rx'),\n ry: this.get('ry')\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 markup = this._createBaseSVGMarkup(), x = 0, y = 0;\n if (this.group && this.group.type === 'path-group') {\n x = this.left + this.rx;\n y = this.top + this.ry;\n }\n markup.push(\n '\\n'\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n _render: function(ctx, noTransform) {\n ctx.beginPath();\n ctx.save();\n ctx.transform(1, 0, 0, this.ry/this.rx, 0, 0);\n ctx.arc(\n noTransform ? this.left + this.rx : 0,\n noTransform ? (this.top + this.ry) * this.rx/this.ry : 0,\n this.rx,\n 0,\n piBy2,\n false);\n ctx.restore();\n this._renderFill(ctx);\n this._renderStroke(ctx);\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.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 {Object} [options] Options object\n * @return {fabric.Ellipse}\n */\n fabric.Ellipse.fromElement = function(element, options) {\n options || (options = { });\n\n var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES);\n\n parsedAttributes.left = parsedAttributes.left || 0;\n parsedAttributes.top = parsedAttributes.top || 0;\n\n var ellipse = new fabric.Ellipse(extend(parsedAttributes, options));\n\n ellipse.top -= ellipse.ry;\n ellipse.left -= ellipse.rx;\n return ellipse;\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 * @return {fabric.Ellipse}\n */\n fabric.Ellipse.fromObject = function(object) {\n return new fabric.Ellipse(object);\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 var stateProperties = fabric.Object.prototype.stateProperties.concat();\n stateProperties.push('rx', 'ry', 'x', 'y');\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: stateProperties,\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 /**\n * Used to specify dash pattern for stroke on this object\n * @type Array\n */\n strokeDashArray: null,\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n * @return {Object} thisArg\n */\n initialize: function(options) {\n options = options || { };\n\n this.callSuper('initialize', options);\n this._initRxRy();\n\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, noTransform) {\n\n // optimize 1x1 case (used in spray brush)\n if (this.width === 1 && this.height === 1) {\n ctx.fillRect(0, 0, 1, 1);\n return;\n }\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 = noTransform ? this.left : -this.width / 2,\n y = noTransform ? this.top : -this.height / 2,\n isRounded = rx !== 0 || ry !== 0,\n k = 1 - 0.5522847498 /* \"magic number\" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */;\n\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._renderFill(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var x = -this.width / 2,\n y = -this.height / 2,\n w = this.width,\n h = this.height;\n\n ctx.beginPath();\n fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);\n ctx.closePath();\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n var object = extend(this.callSuper('toObject', propertiesToInclude), {\n rx: this.get('rx') || 0,\n ry: this.get('ry') || 0\n });\n if (!this.includeDefaultValues) {\n this._removeDefaultValues(object);\n }\n return object;\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 markup = this._createBaseSVGMarkup(), x = this.left, y = this.top;\n if (!(this.group && this.group.type === 'path-group')) {\n x = -this.width / 2;\n y = -this.height / 2;\n }\n markup.push(\n '\\n');\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\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 `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 {Object} [options] Options object\n * @return {fabric.Rect} Instance of fabric.Rect\n */\n fabric.Rect.fromElement = function(element, options) {\n if (!element) {\n return null;\n }\n options = options || { };\n\n var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);\n\n parsedAttributes.left = parsedAttributes.left || 0;\n parsedAttributes.top = parsedAttributes.top || 0;\n var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));\n rect.visible = rect.width > 0 && rect.height > 0;\n return 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 * @return {Object} instance of fabric.Rect\n */\n fabric.Rect.fromObject = function(object) {\n return new fabric.Rect(object);\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.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 * Minimum X from points values, necessary to offset points\n * @type Number\n * @default\n */\n minX: 0,\n\n /**\n * Minimum Y from points values, necessary to offset points\n * @type Number\n * @default\n */\n minY: 0,\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 * @param {Boolean} [skipOffset] Whether points offsetting should be skipped\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 return fabric.Polygon.prototype.initialize.call(this, points, options);\n },\n\n /**\n * @private\n */\n _calcDimensions: function() {\n return fabric.Polygon.prototype._calcDimensions.call(this);\n },\n\n /**\n * @private\n */\n _applyPointOffset: function() {\n return fabric.Polygon.prototype._applyPointOffset.call(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 fabric.Polygon.prototype.toObject.call(this, propertiesToInclude);\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 return fabric.Polygon.prototype.toSVG.call(this, reviver);\n },\n /* _TO_SVG_END_ */\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n if (!fabric.Polygon.prototype.commonRender.call(this, ctx)) {\n return;\n }\n this._renderFill(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var p1, p2;\n\n ctx.beginPath();\n for (var i = 0, len = this.points.length; i < len; i++) {\n p1 = this.points[i];\n p2 = this.points[i + 1] || p1;\n fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray);\n }\n },\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity of this instance\n */\n complexity: function() {\n return this.get('points').length;\n }\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Polyline.fromElement})\n * @static\n * @memberOf fabric.Polyline\n * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement\n */\n fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat();\n\n /**\n * Returns fabric.Polyline instance from an SVG element\n * @static\n * @memberOf fabric.Polyline\n * @param {SVGElement} element Element to parse\n * @param {Object} [options] Options object\n * @return {fabric.Polyline} Instance of fabric.Polyline\n */\n fabric.Polyline.fromElement = function(element, options) {\n if (!element) {\n return null;\n }\n options || (options = { });\n\n var points = fabric.parsePointsAttribute(element.getAttribute('points')),\n parsedAttributes = fabric.parseAttributes(element, fabric.Polyline.ATTRIBUTE_NAMES);\n\n return new fabric.Polyline(points, fabric.util.object.extend(parsedAttributes, options));\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 * @return {fabric.Polyline} Instance of fabric.Polyline\n */\n fabric.Polyline.fromObject = function(object) {\n var points = object.points;\n return new fabric.Polyline(points, object, true);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n min = fabric.util.array.min,\n max = fabric.util.array.max,\n toFixed = fabric.util.toFixed;\n\n if (fabric.Polygon) {\n fabric.warn('fabric.Polygon is already defined');\n return;\n }\n\n /**\n * Polygon class\n * @class fabric.Polygon\n * @extends fabric.Object\n * @see {@link fabric.Polygon#initialize} for constructor definition\n */\n fabric.Polygon = fabric.util.createClass(fabric.Object, /** @lends fabric.Polygon.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'polygon',\n\n /**\n * Points array\n * @type Array\n * @default\n */\n points: null,\n\n /**\n * Minimum X from points values, necessary to offset points\n * @type Number\n * @default\n */\n minX: 0,\n\n /**\n * Minimum Y from points values, necessary to offset points\n * @type Number\n * @default\n */\n minY: 0,\n\n /**\n * Constructor\n * @param {Array} points Array of points\n * @param {Object} [options] Options object\n * @return {fabric.Polygon} thisArg\n */\n initialize: function(points, options) {\n options = options || { };\n this.points = points || [ ];\n this.callSuper('initialize', options);\n this._calcDimensions();\n if (!('top' in options)) {\n this.top = this.minY;\n }\n if (!('left' in options)) {\n this.left = this.minX;\n }\n },\n\n /**\n * @private\n */\n _calcDimensions: function() {\n\n var points = this.points,\n minX = min(points, 'x'),\n minY = min(points, 'y'),\n maxX = max(points, 'x'),\n maxY = max(points, 'y');\n\n this.width = (maxX - minX) || 0;\n this.height = (maxY - minY) || 0;\n\n this.minX = minX || 0,\n this.minY = minY || 0;\n },\n\n /**\n * @private\n */\n _applyPointOffset: function() {\n // change points to offset polygon into a bounding box\n // executed one time\n this.points.forEach(function(p) {\n p.x -= (this.minX + this.width / 2);\n p.y -= (this.minY + this.height / 2);\n }, 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 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 * @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 points = [],\n markup = this._createBaseSVGMarkup();\n\n for (var i = 0, len = this.points.length; i < len; i++) {\n points.push(toFixed(this.points[i].x, 2), ',', toFixed(this.points[i].y, 2), ' ');\n }\n\n markup.push(\n '<', this.type, ' ',\n 'points=\"', points.join(''),\n '\" style=\"', this.getSvgStyles(),\n '\" transform=\"', this.getSvgTransform(),\n ' ', this.getSvgTransformMatrix(),\n '\"/>\\n'\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\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._renderFill(ctx);\n if (this.stroke || this.strokeDashArray) {\n ctx.closePath();\n this._renderStroke(ctx);\n }\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\n if (!len || isNaN(this.points[len - 1].y)) {\n // do not draw if no points or odd points\n // NaN comes from parseFloat of a empty string in parser\n return false;\n }\n\n ctx.beginPath();\n\n if (this._applyPointOffset) {\n if (!(this.group && this.group.type === 'path-group')) {\n this._applyPointOffset();\n }\n this._applyPointOffset = null;\n }\n\n ctx.moveTo(this.points[0].x, this.points[0].y);\n for (var i = 0; i < len; i++) {\n point = this.points[i];\n ctx.lineTo(point.x, point.y);\n }\n return true;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n fabric.Polyline.prototype._renderDashedStroke.call(this, ctx);\n ctx.closePath();\n },\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity of this instance\n */\n complexity: function() {\n return this.points.length;\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 {Object} [options] Options object\n * @return {fabric.Polygon} Instance of fabric.Polygon\n */\n fabric.Polygon.fromElement = function(element, options) {\n if (!element) {\n return null;\n }\n\n options || (options = { });\n\n var points = fabric.parsePointsAttribute(element.getAttribute('points')),\n parsedAttributes = fabric.parseAttributes(element, fabric.Polygon.ATTRIBUTE_NAMES);\n\n return new fabric.Polygon(points, extend(parsedAttributes, options));\n };\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 * @return {fabric.Polygon} Instance of fabric.Polygon\n */\n fabric.Polygon.fromObject = function(object) {\n return new fabric.Polygon(object.points, object, true);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n min = fabric.util.array.min,\n max = fabric.util.array.max,\n extend = fabric.util.object.extend,\n _toString = Object.prototype.toString,\n drawArc = fabric.util.drawArc,\n commandLengths = {\n m: 2,\n l: 2,\n h: 1,\n v: 1,\n c: 6,\n s: 4,\n q: 4,\n t: 2,\n a: 7\n },\n repeatedCommands = {\n m: 'l',\n M: 'L'\n };\n\n 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 /**\n * Minimum X from points values, necessary to offset points\n * @type Number\n * @default\n */\n minX: 0,\n\n /**\n * Minimum Y from points values, necessary to offset points\n * @type Number\n * @default\n */\n minY: 0,\n\n /**\n * Constructor\n * @param {Array|String} path Path data (sequence of coordinates and corresponding \"command\" tokens)\n * @param {Object} [options] Options object\n * @return {fabric.Path} thisArg\n */\n initialize: function(path, options) {\n options = options || { };\n\n this.setOptions(options);\n\n if (!path) {\n path = [ ];\n }\n\n var fromArray = _toString.call(path) === '[object Array]';\n\n this.path = fromArray\n ? path\n // one of commands (m,M,l,L,q,Q,c,C,etc.) followed by non-command characters (i.e. command values)\n : path.match && path.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi);\n\n if (!this.path) {\n return;\n }\n\n if (!fromArray) {\n this.path = this._parsePath();\n }\n\n this._setPositionDimensions(options);\n\n if (options.sourcePath) {\n this.setSourcePath(options.sourcePath);\n }\n },\n\n /**\n * @private\n * @param {Object} options Options object\n */\n _setPositionDimensions: function(options) {\n var calcDim = this._parseDimensions();\n\n this.minX = calcDim.left;\n this.minY = calcDim.top;\n this.width = calcDim.width;\n this.height = calcDim.height;\n\n if (typeof options.left === 'undefined') {\n this.left = calcDim.left + (this.originX === 'center'\n ? this.width / 2\n : this.originX === 'right'\n ? this.width\n : 0);\n }\n\n if (typeof options.top === 'undefined') {\n this.top = calcDim.top + (this.originY === 'center'\n ? this.height / 2\n : this.originY === 'bottom'\n ? this.height\n : 0);\n }\n\n this.pathOffset = this.pathOffset || {\n x: this.minX + this.width / 2,\n y: this.minY + this.height / 2\n };\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render path on\n */\n _render: function(ctx) {\n var current, // current instruction\n previous = null,\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 tempX,\n tempY,\n l = -this.pathOffset.x,\n t = -this.pathOffset.y;\n\n if (this.group && this.group.type === 'path-group') {\n l = 0;\n t = 0;\n }\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, relative\n x += current[1];\n y += current[2];\n ctx.lineTo(x + l, y + t);\n break;\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 'h': // horizontal lineto, relative\n x += current[1];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'H': // horizontal lineto, absolute\n x = current[1];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'v': // vertical lineto, relative\n y += current[1];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'V': // verical lineto, absolute\n y = current[1];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'm': // moveTo, relative\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 '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, relative\n tempX = x + current[5];\n tempY = y + current[6];\n controlX = x + current[3];\n controlY = y + current[4];\n ctx.bezierCurveTo(\n x + current[1] + l, // x1\n y + current[2] + t, // y1\n controlX + l, // x2\n controlY + t, // y2\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\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 's': // shorthand cubic bezierCurveTo, relative\n\n // transform to absolute x,y\n tempX = x + current[3];\n tempY = y + current[4];\n\n if (previous[0].match(/[CcSs]/) === null) {\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 else {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n\n ctx.bezierCurveTo(\n controlX + l,\n controlY + t,\n x + current[1] + l,\n y + current[2] + t,\n tempX + l,\n tempY + t\n );\n // set control point to 2nd one of this command\n // \"... the first control point is assumed to be\n // the reflection of the second control point on\n // the previous command relative to the current point.\"\n controlX = x + current[1];\n controlY = y + current[2];\n\n x = tempX;\n y = tempY;\n break;\n\n case 'S': // shorthand cubic bezierCurveTo, absolute\n tempX = current[3];\n tempY = current[4];\n if (previous[0].match(/[CcSs]/) === null) {\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 else {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n ctx.bezierCurveTo(\n controlX + l,\n controlY + t,\n current[1] + l,\n current[2] + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n\n // set control point to 2nd one of this command\n // \"... the first control point is assumed to be\n // the reflection of the second control point on\n // the previous command relative to the current point.\"\n controlX = current[1];\n controlY = current[2];\n\n break;\n\n case 'q': // quadraticCurveTo, relative\n // transform to absolute x,y\n tempX = x + current[3];\n tempY = y + current[4];\n\n controlX = x + current[1];\n controlY = y + current[2];\n\n ctx.quadraticCurveTo(\n controlX + l,\n controlY + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'Q': // quadraticCurveTo, absolute\n tempX = current[3];\n tempY = current[4];\n\n ctx.quadraticCurveTo(\n current[1] + l,\n current[2] + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n controlX = current[1];\n controlY = current[2];\n break;\n\n case 't': // shorthand quadraticCurveTo, relative\n\n // transform to absolute x,y\n tempX = x + current[1];\n tempY = y + current[2];\n\n if (previous[0].match(/[QqTt]/) === null) {\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 else {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n\n ctx.quadraticCurveTo(\n controlX + l,\n controlY + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n\n break;\n\n case 'T':\n tempX = current[1];\n tempY = current[2];\n\n if (previous[0].match(/[QqTt]/) === null) {\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 else {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n ctx.quadraticCurveTo(\n controlX + l,\n controlY + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'a':\n // TODO: optimize this\n drawArc(ctx, x + l, y + t, [\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6] + x + l,\n current[7] + y + t\n ]);\n x += current[6];\n y += current[7];\n break;\n\n case 'A':\n // TODO: optimize this\n drawArc(ctx, x + l, y + t, [\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6] + l,\n current[7] + t\n ]);\n x = current[6];\n y = current[7];\n break;\n\n case 'z':\n case 'Z':\n x = subpathStartX;\n y = subpathStartY;\n ctx.closePath();\n break;\n }\n previous = current;\n }\n this._renderFill(ctx);\n this._renderStroke(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 var o = extend(this.callSuper('toObject', propertiesToInclude), {\n path: this.path.map(function(item) { return item.slice() }),\n pathOffset: this.pathOffset\n });\n if (this.sourcePath) {\n o.sourcePath = this.sourcePath;\n }\n if (this.transformMatrix) {\n o.transformMatrix = this.transformMatrix;\n }\n return o;\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(propertiesToInclude);\n if (this.sourcePath) {\n o.path = this.sourcePath;\n }\n delete o.sourcePath;\n return o;\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 chunks = [],\n markup = this._createBaseSVGMarkup(), addTransform = '';\n\n for (var i = 0, len = this.path.length; i < len; i++) {\n chunks.push(this.path[i].join(' '));\n }\n var path = chunks.join(' ');\n if (!(this.group && this.group.type === 'path-group')) {\n addTransform = ' translate(' + (-this.pathOffset.x) + ', ' + (-this.pathOffset.y) + ') ';\n }\n markup.push(\n //jscs:disable validateIndentation\n '\\n'\n //jscs:enable validateIndentation\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\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 _parsePath: function() {\n var result = [ ],\n coords = [ ],\n currentPath,\n parsed,\n re = /([-+]?((\\d+\\.\\d+)|((\\d+)|(\\.\\d+)))(?:e[-+]?\\d+)?)/ig,\n match,\n coordsStr;\n\n for (var i = 0, coordsParsed, len = this.path.length; i < len; i++) {\n currentPath = this.path[i];\n\n coordsStr = currentPath.slice(1).trim();\n coords.length = 0;\n\n while ((match = re.exec(coordsStr))) {\n coords.push(match[0]);\n }\n\n coordsParsed = [ currentPath.charAt(0) ];\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 command = coordsParsed[0],\n 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 * @private\n */\n _parseDimensions: function() {\n\n var aX = [],\n aY = [],\n current, // current instruction\n previous = null,\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 tempX,\n tempY,\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, relative\n x += current[1];\n y += current[2];\n bounds = [ ];\n break;\n\n case 'L': // lineto, absolute\n x = current[1];\n y = current[2];\n bounds = [ ];\n break;\n\n case 'h': // horizontal lineto, relative\n x += current[1];\n bounds = [ ];\n break;\n\n case 'H': // horizontal lineto, absolute\n x = current[1];\n bounds = [ ];\n break;\n\n case 'v': // vertical lineto, relative\n y += current[1];\n bounds = [ ];\n break;\n\n case 'V': // verical lineto, absolute\n y = current[1];\n bounds = [ ];\n break;\n\n case 'm': // moveTo, relative\n x += current[1];\n y += current[2];\n subpathStartX = x;\n subpathStartY = y;\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, relative\n tempX = x + current[5];\n tempY = y + current[6];\n controlX = x + current[3];\n controlY = y + current[4];\n bounds = fabric.util.getBoundsOfCurve(x, y,\n x + current[1], // x1\n y + current[2], // y1\n controlX, // x2\n controlY, // y2\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\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 bounds = fabric.util.getBoundsOfCurve(x, y,\n current[1],\n current[2],\n controlX,\n controlY,\n x,\n y\n );\n break;\n\n case 's': // shorthand cubic bezierCurveTo, relative\n\n // transform to absolute x,y\n tempX = x + current[3];\n tempY = y + current[4];\n\n if (previous[0].match(/[CcSs]/) === null) {\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 else {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n x + current[1],\n y + current[2],\n tempX,\n tempY\n );\n // set control point to 2nd one of this command\n // \"... the first control point is assumed to be\n // the reflection of the second control point on\n // the previous command relative to the current point.\"\n controlX = x + current[1];\n controlY = y + current[2];\n x = tempX;\n y = tempY;\n break;\n\n case 'S': // shorthand cubic bezierCurveTo, absolute\n tempX = current[3];\n tempY = current[4];\n if (previous[0].match(/[CcSs]/) === null) {\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 else {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n current[1],\n current[2],\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n // set control point to 2nd one of this command\n // \"... the first control point is assumed to be\n // the reflection of the second control point on\n // the previous command relative to the current point.\"\n controlX = current[1];\n controlY = current[2];\n break;\n\n case 'q': // quadraticCurveTo, relative\n // transform to absolute x,y\n tempX = x + current[3];\n tempY = y + current[4];\n controlX = x + current[1];\n controlY = y + current[2];\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n controlX,\n controlY,\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'Q': // quadraticCurveTo, absolute\n controlX = current[1];\n controlY = current[2];\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n controlX,\n controlY,\n current[3],\n current[4]\n );\n x = current[3];\n y = current[4];\n break;\n\n case 't': // shorthand quadraticCurveTo, relative\n // transform to absolute x,y\n tempX = x + current[1];\n tempY = y + current[2];\n if (previous[0].match(/[QqTt]/) === null) {\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 else {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n controlX,\n controlY,\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n\n break;\n\n case 'T':\n tempX = current[1];\n tempY = current[2];\n\n if (previous[0].match(/[QqTt]/) === null) {\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 else {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n controlX,\n controlY,\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'a':\n // TODO: optimize this\n bounds = fabric.util.getBoundsOfArc(x, y,\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6] + x,\n current[7] + y\n );\n x += current[6];\n y += current[7];\n break;\n\n case 'A':\n // TODO: optimize this\n bounds = fabric.util.getBoundsOfArc(x, y,\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6],\n current[7]\n );\n x = current[6];\n y = current[7];\n break;\n\n case 'z':\n case 'Z':\n x = subpathStartX;\n y = subpathStartY;\n break;\n }\n previous = current;\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 o = {\n left: minX,\n top: minY,\n width: deltaX,\n height: deltaY\n };\n\n return o;\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.path === 'string') {\n fabric.loadSVGFromURL(object.path, function (elements) {\n var path = elements[0],\n pathUrl = object.path;\n\n delete object.path;\n\n fabric.util.object.extend(path, object);\n path.setSourcePath(pathUrl);\n\n callback(path);\n });\n }\n else {\n callback(new fabric.Path(object.path, object));\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 */\n fabric.Path.fromElement = function(element, callback, options) {\n var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES);\n callback && callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options)));\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @memberOf fabric.Path\n * @type Boolean\n * @default\n */\n fabric.Path.async = true;\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 invoke = fabric.util.array.invoke,\n parentToObject = fabric.Object.prototype.toObject;\n\n if (fabric.PathGroup) {\n fabric.warn('fabric.PathGroup is already defined');\n return;\n }\n\n /**\n * Path group class\n * @class fabric.PathGroup\n * @extends fabric.Path\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1/#path_and_pathgroup}\n * @see {@link fabric.PathGroup#initialize} for constructor definition\n */\n fabric.PathGroup = fabric.util.createClass(fabric.Path, /** @lends fabric.PathGroup.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'path-group',\n\n /**\n * Fill value\n * @type String\n * @default\n */\n fill: '',\n\n /**\n * Constructor\n * @param {Array} paths\n * @param {Object} [options] Options object\n * @return {fabric.PathGroup} thisArg\n */\n initialize: function(paths, options) {\n\n options = options || { };\n this.paths = paths || [ ];\n\n for (var i = this.paths.length; i--;) {\n this.paths[i].group = this;\n }\n\n if (options.toBeParsed) {\n this.parseDimensionsFromPaths(options);\n delete options.toBeParsed;\n }\n this.setOptions(options);\n this.setCoords();\n\n if (options.sourcePath) {\n this.setSourcePath(options.sourcePath);\n }\n },\n\n /**\n * Calculate width and height based on paths contained\n */\n parseDimensionsFromPaths: function(options) {\n var points, p, xC = [ ], yC = [ ], path, height, width,\n m;\n for (var j = this.paths.length; j--;) {\n path = this.paths[j];\n height = path.height + path.strokeWidth;\n width = path.width + path.strokeWidth;\n points = [\n { x: path.left, y: path.top },\n { x: path.left + width, y: path.top },\n { x: path.left, y: path.top + height },\n { x: path.left + width, y: path.top + height }\n ];\n m = this.paths[j].transformMatrix;\n for (var i = 0; i < points.length; i++) {\n p = points[i];\n if (m) {\n p = fabric.util.transformPoint(p, m, false);\n }\n xC.push(p.x);\n yC.push(p.y);\n }\n }\n options.width = Math.max.apply(null, xC);\n options.height = Math.max.apply(null, yC);\n },\n\n /**\n * Renders this group on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render this instance on\n */\n render: function(ctx) {\n // do not render if object is not visible\n if (!this.visible) {\n return;\n }\n\n ctx.save();\n\n if (this.transformMatrix) {\n ctx.transform.apply(ctx, this.transformMatrix);\n }\n this.transform(ctx);\n\n this._setShadow(ctx);\n this.clipTo && fabric.util.clipContext(this, ctx);\n ctx.translate(-this.width/2, -this.height/2);\n for (var i = 0, l = this.paths.length; i < l; ++i) {\n this.paths[i].render(ctx, true);\n }\n this.clipTo && ctx.restore();\n ctx.restore();\n },\n\n /**\n * Sets certain property to a certain value\n * @param {String} prop\n * @param {Any} value\n * @return {fabric.PathGroup} thisArg\n */\n _set: function(prop, value) {\n\n if (prop === 'fill' && value && this.isSameColor()) {\n var i = this.paths.length;\n while (i--) {\n this.paths[i]._set(prop, value);\n }\n }\n\n return this.callSuper('_set', prop, value);\n },\n\n /**\n * Returns object representation of this path group\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 o = extend(parentToObject.call(this, propertiesToInclude), {\n paths: invoke(this.getObjects(), 'toObject', propertiesToInclude)\n });\n if (this.sourcePath) {\n o.sourcePath = this.sourcePath;\n }\n return o;\n },\n\n /**\n * Returns dataless object representation of this path group\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} dataless object representation of an instance\n */\n toDatalessObject: function(propertiesToInclude) {\n var o = this.toObject(propertiesToInclude);\n if (this.sourcePath) {\n o.paths = this.sourcePath;\n }\n return o;\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 objects = this.getObjects(),\n p = this.getPointByOrigin('left', 'top'),\n translatePart = 'translate(' + p.x + ' ' + p.y + ')',\n markup = [\n //jscs:disable validateIndentation\n '\\n'\n //jscs:enable validateIndentation\n ];\n\n for (var i = 0, len = objects.length; i < len; i++) {\n markup.push(objects[i].toSVG(reviver));\n }\n markup.push('\\n');\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns a string representation of this path group\n * @return {String} string representation of an object\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Returns true if all paths in this group are of same color\n * @return {Boolean} true if all paths are of the same color (`fill`)\n */\n isSameColor: function() {\n var firstPathFill = (this.getObjects()[0].get('fill') || '').toLowerCase();\n return this.getObjects().every(function(path) {\n return (path.get('fill') || '').toLowerCase() === firstPathFill;\n });\n },\n\n /**\n * Returns number representation of object's complexity\n * @return {Number} complexity\n */\n complexity: function() {\n return this.paths.reduce(function(total, path) {\n return total + ((path && path.complexity) ? path.complexity() : 0);\n }, 0);\n },\n\n /**\n * Returns all paths in this path group\n * @return {Array} array of path objects included in this path group\n */\n getObjects: function() {\n return this.paths;\n }\n });\n\n /**\n * Creates fabric.PathGroup instance from an object representation\n * @static\n * @memberOf fabric.PathGroup\n * @param {Object} object Object to create an instance from\n * @param {Function} callback Callback to invoke when an fabric.PathGroup instance is created\n */\n fabric.PathGroup.fromObject = function(object, callback) {\n if (typeof object.paths === 'string') {\n fabric.loadSVGFromURL(object.paths, function (elements) {\n\n var pathUrl = object.paths;\n delete object.paths;\n\n var pathGroup = fabric.util.groupSVGElements(elements, object, pathUrl);\n\n callback(pathGroup);\n });\n }\n else {\n fabric.util.enlivenObjects(object.paths, function(enlivenedObjects) {\n delete object.paths;\n callback(new fabric.PathGroup(enlivenedObjects, object));\n });\n }\n };\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @memberOf fabric.PathGroup\n * @type Boolean\n * @default\n */\n fabric.PathGroup.async = true;\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 invoke = fabric.util.array.invoke;\n\n if (fabric.Group) {\n return;\n }\n\n // lock-related properties, for use in fabric.Group#get\n // to enable locking behavior on group\n // when one of its objects has lock-related properties set\n var _lockProperties = {\n lockMovementX: true,\n lockMovementY: true,\n lockRotation: true,\n lockScalingX: true,\n lockScalingY: true,\n lockUniScaling: true\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 * 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\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 // because delegatedProperties propagate to objects.\n isAlreadyGrouped && this.callSuper('initialize', options);\n\n this._objects = objects || [];\n for (var i = this._objects.length; i--; ) {\n this._objects[i].group = this;\n }\n\n this.originalState = { };\n\n if (options.originX) {\n this.originX = options.originX;\n }\n if (options.originY) {\n this.originY = options.originY;\n }\n\n if (isAlreadyGrouped) {\n // do not change coordinate of objects enclosed in a group,\n // because objects coordinate system have been group coodinate system already.\n this._updateObjectsCoords(true);\n }\n else {\n this._calcBounds();\n this._updateObjectsCoords();\n this.callSuper('initialize', options);\n }\n\n this.setCoords();\n this.saveCoords();\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(skipCoordsChange) {\n for (var i = this._objects.length; i--; ){\n this._updateObjectCoords(this._objects[i], skipCoordsChange);\n }\n },\n\n /**\n * @private\n * @param {Object} object\n * @param {Boolean} [skipCoordsChange] if true, coordinates of object dose not change\n */\n _updateObjectCoords: function(object, skipCoordsChange) {\n // do not display corners of objects enclosed in a group\n object.__origHasControls = object.hasControls;\n object.hasControls = false;\n\n if (skipCoordsChange) {\n return;\n }\n\n var objectLeft = object.getLeft(),\n objectTop = object.getTop(),\n center = this.getCenterPoint();\n\n object.set({\n originalLeft: objectLeft,\n originalTop: objectTop,\n left: objectLeft - center.x,\n top: objectTop - center.y\n });\n object.setCoords();\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 this._restoreObjectsState();\n if (object) {\n this._objects.push(object);\n object.group = this;\n object._set('canvas', this.canvas);\n }\n // since _restoreObjectsState set objects inactive\n this.forEachObject(this._setObjectActive, this);\n this._calcBounds();\n this._updateObjectsCoords();\n return this;\n },\n\n /**\n * @private\n */\n _setObjectActive: function(object) {\n object.set('active', true);\n object.group = 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._moveFlippedObject(object);\n this._restoreObjectsState();\n\n // since _restoreObjectsState set objects inactive\n this.forEachObject(this._setObjectActive, this);\n\n this.remove(object);\n this._calcBounds();\n this._updateObjectsCoords();\n\n return this;\n },\n\n /**\n * @private\n */\n _onObjectAdded: function(object) {\n object.group = this;\n object._set('canvas', this.canvas);\n },\n\n /**\n * @private\n */\n _onObjectRemoved: function(object) {\n delete object.group;\n object.set('active', false);\n },\n\n /**\n * Properties that are delegated to group objects when reading/writing\n * @param {Object} delegatedProperties\n */\n delegatedProperties: {\n fill: true,\n opacity: true,\n fontFamily: true,\n fontWeight: true,\n fontSize: true,\n fontStyle: true,\n lineHeight: true,\n textDecoration: true,\n textAlign: true,\n backgroundColor: true\n },\n\n /**\n * @private\n */\n _set: function(key, value) {\n var i = this._objects.length;\n\n if (this.delegatedProperties[key] || key === 'canvas') {\n while (i--) {\n this._objects[i].set(key, value);\n }\n }\n else {\n while (i--) {\n this._objects[i].setOnGroup(key, value);\n }\n }\n\n this.callSuper('_set', 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 return extend(this.callSuper('toObject', propertiesToInclude), {\n objects: invoke(this._objects, 'toObject', propertiesToInclude)\n });\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 // do not render if object is not visible\n if (!this.visible) {\n return;\n }\n\n ctx.save();\n if (this.transformMatrix) {\n ctx.transform.apply(ctx, this.transformMatrix);\n }\n this.transform(ctx);\n this.clipTo && fabric.util.clipContext(this, ctx);\n // the array is now sorted in order of highest first, so start from end\n for (var i = 0, len = this._objects.length; i < len; i++) {\n this._renderObject(this._objects[i], ctx);\n }\n\n this.clipTo && ctx.restore();\n\n ctx.restore();\n },\n\n /**\n * Renders controls and borders for the object\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n _renderControls: function(ctx, noTransform) {\n this.callSuper('_renderControls', ctx, noTransform);\n for (var i = 0, len = this._objects.length; i < len; i++) {\n this._objects[i]._renderControls(ctx);\n }\n },\n\n /**\n * @private\n */\n _renderObject: function(object, ctx) {\n // do not render if object is not visible\n if (!object.visible) {\n return;\n }\n\n var originalHasRotatingPoint = object.hasRotatingPoint;\n object.hasRotatingPoint = false;\n object.render(ctx);\n object.hasRotatingPoint = originalHasRotatingPoint;\n },\n\n /**\n * Retores original state of each of group objects (original state is that which was before group was created).\n * @private\n * @return {fabric.Group} thisArg\n * @chainable\n */\n _restoreObjectsState: function() {\n this._objects.forEach(this._restoreObjectState, this);\n return this;\n },\n\n /**\n * Realises the transform from this group onto the supplied object\n * i.e. it tells you what would happen if the supplied object was in\n * the group, and then the group was destroyed. It mutates the supplied\n * object.\n * @param {fabric.Object} object\n * @return {fabric.Object} transformedObject\n */\n realizeTransform: function(object) {\n this._moveFlippedObject(object);\n this._setObjectPosition(object);\n return object;\n },\n\n /**\n * Moves a flipped object to the position where it's displayed\n * @private\n * @param {fabric.Object} object\n * @return {fabric.Group} thisArg\n */\n _moveFlippedObject: function(object) {\n var oldOriginX = object.get('originX'),\n oldOriginY = object.get('originY'),\n center = object.getCenterPoint();\n\n object.set({\n originX: 'center',\n originY: 'center',\n left: center.x,\n top: center.y\n });\n\n this._toggleFlipping(object);\n\n var newOrigin = object.getPointByOrigin(oldOriginX, oldOriginY);\n\n object.set({\n originX: oldOriginX,\n originY: oldOriginY,\n left: newOrigin.x,\n top: newOrigin.y\n });\n\n return this;\n },\n\n /**\n * @private\n */\n _toggleFlipping: function(object) {\n if (this.flipX) {\n object.toggle('flipX');\n object.set('left', -object.get('left'));\n object.setAngle(-object.getAngle());\n }\n if (this.flipY) {\n object.toggle('flipY');\n object.set('top', -object.get('top'));\n object.setAngle(-object.getAngle());\n }\n },\n\n /**\n * Restores original state of a specified object in group\n * @private\n * @param {fabric.Object} object\n * @return {fabric.Group} thisArg\n */\n _restoreObjectState: function(object) {\n this._setObjectPosition(object);\n\n object.setCoords();\n object.hasControls = object.__origHasControls;\n delete object.__origHasControls;\n object.set('active', false);\n object.setCoords();\n delete object.group;\n\n return this;\n },\n\n /**\n * @private\n */\n _setObjectPosition: function(object) {\n var center = this.getCenterPoint(),\n rotated = this._getRotatedLeftTop(object);\n\n object.set({\n angle: object.getAngle() + this.getAngle(),\n left: center.x + rotated.left,\n top: center.y + rotated.top,\n scaleX: object.get('scaleX') * this.get('scaleX'),\n scaleY: object.get('scaleY') * this.get('scaleY')\n });\n },\n\n /**\n * @private\n */\n _getRotatedLeftTop: function(object) {\n var groupAngle = this.getAngle() * (Math.PI / 180);\n return {\n left: (-Math.sin(groupAngle) * object.getTop() * this.get('scaleY') +\n Math.cos(groupAngle) * object.getLeft() * this.get('scaleX')),\n\n top: (Math.cos(groupAngle) * object.getTop() * this.get('scaleY') +\n Math.sin(groupAngle) * object.getLeft() * this.get('scaleX'))\n };\n },\n\n /**\n * Destroys a group (restoring state of its objects)\n * @return {fabric.Group} thisArg\n * @chainable\n */\n destroy: function() {\n this._objects.forEach(this._moveFlippedObject, this);\n return this._restoreObjectsState();\n },\n\n /**\n * Saves coordinates of this instance (to be used together with `hasMoved`)\n * @saveCoords\n * @return {fabric.Group} thisArg\n * @chainable\n */\n saveCoords: function() {\n this._originalLeft = this.get('left');\n this._originalTop = this.get('top');\n return this;\n },\n\n /**\n * Checks whether this group was moved (since `saveCoords` was called last)\n * @return {Boolean} true if an object was moved (since fabric.Group#saveCoords was called)\n */\n hasMoved: function() {\n return this._originalLeft !== this.get('left') ||\n this._originalTop !== this.get('top');\n },\n\n /**\n * Sets coordinates of all group objects\n * @return {fabric.Group} thisArg\n * @chainable\n */\n setObjectsCoords: function() {\n this.forEachObject(function(object) {\n object.setCoords();\n });\n return this;\n },\n\n /**\n * @private\n */\n _calcBounds: function(onlyWidthHeight) {\n var aX = [],\n aY = [],\n o, prop,\n props = ['tr', 'br', 'bl', 'tl'],\n i = 0, iLen = this._objects.length,\n j, jLen = props.length;\n\n for ( ; i < iLen; ++i) {\n o = this._objects[i];\n o.setCoords();\n for (j = 0; j < jLen; j++) {\n prop = props[j];\n aX.push(o.oCoords[prop].x);\n aY.push(o.oCoords[prop].y);\n }\n }\n\n this.set(this._getBounds(aX, aY, onlyWidthHeight));\n },\n\n /**\n * @private\n */\n _getBounds: function(aX, aY, onlyWidthHeight) {\n var ivt = fabric.util.invertTransform(this.getViewportTransform()),\n minXY = fabric.util.transformPoint(new fabric.Point(min(aX), min(aY)), ivt),\n maxXY = fabric.util.transformPoint(new fabric.Point(max(aX), max(aY)), ivt),\n obj = {\n width: (maxXY.x - minXY.x) || 0,\n height: (maxXY.y - minXY.y) || 0\n };\n\n if (!onlyWidthHeight) {\n obj.left = minXY.x || 0;\n obj.top = minXY.y || 0;\n if (this.originX === 'center') {\n obj.left += obj.width / 2;\n }\n if (this.originX === 'right') {\n obj.left += obj.width;\n }\n if (this.originY === 'center') {\n obj.top += obj.height / 2;\n }\n if (this.originY === 'bottom') {\n obj.top += obj.height;\n }\n }\n return obj;\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 markup = [\n //jscs:disable validateIndentation\n '\\n'\n //jscs:enable validateIndentation\n ];\n\n for (var i = 0, len = this._objects.length; i < len; i++) {\n markup.push(this._objects[i].toSVG(reviver));\n }\n\n markup.push('\\n');\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns requested property\n * @param {String} prop Property to get\n * @return {Any}\n */\n get: function(prop) {\n if (prop in _lockProperties) {\n if (this[prop]) {\n return this[prop];\n }\n else {\n for (var i = 0, len = this._objects.length; i < len; i++) {\n if (this._objects[i][prop]) {\n return true;\n }\n }\n return false;\n }\n }\n else {\n if (prop in this.delegatedProperties) {\n return this._objects[0] && this._objects[0].get(prop);\n }\n return this[prop];\n }\n }\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 * @return {fabric.Group} An instance of fabric.Group\n */\n fabric.Group.fromObject = function(object, callback) {\n fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) {\n delete object.objects;\n callback && callback(new fabric.Group(enlivenedObjects, object, true));\n });\n };\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @memberOf fabric.Group\n * @type Boolean\n * @default\n */\n fabric.Group.async = true;\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 * crossOrigin value (one of \"\", \"anonymous\", \"allow-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 * AlignX value, part of preserveAspectRatio (one of \"none\", \"mid\", \"min\", \"max\")\n * @see http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute\n * This parameter defines how the picture is aligned to its viewport when image element width differs from image width.\n * @type String\n * @default\n */\n alignX: 'none',\n\n /**\n * AlignY value, part of preserveAspectRatio (one of \"none\", \"mid\", \"min\", \"max\")\n * @see http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute\n * This parameter defines how the picture is aligned to its viewport when image element height differs from image height.\n * @type String\n * @default\n */\n alignY: 'none',\n\n /**\n * meetOrSlice value, part of preserveAspectRatio (one of \"meet\", \"slice\").\n * if meet the image is always fully visibile, if slice the viewport is always filled with image.\n * @see http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute\n * @type String\n * @default\n */\n meetOrSlice: 'meet',\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 * Constructor\n * @param {HTMLImageElement | String} element Image element\n * @param {Object} [options] Options object\n * @return {fabric.Image} thisArg\n */\n initialize: function(element, options) {\n options || (options = { });\n this.filters = [ ];\n this.resizeFilters = [ ];\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 {Function} [callback] Callback is invoked when all filters have been applied and new image is generated\n * @param {Object} [options] Options object\n * @return {fabric.Image} thisArg\n * @chainable\n */\n setElement: function(element, callback, options) {\n this._element = element;\n this._originalElement = element;\n this._initConfig(options);\n\n if (this.filters.length !== 0) {\n this.applyFilters(callback);\n }\n else if (callback) {\n callback();\n }\n\n return this;\n },\n\n /**\n * Sets crossOrigin value (on an instance and corresponding image element)\n * @return {fabric.Image} thisArg\n * @chainable\n */\n setCrossOrigin: function(value) {\n this.crossOrigin = value;\n this._element.crossOrigin = value;\n\n return this;\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.width,\n height: element.height\n };\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _stroke: function(ctx) {\n ctx.save();\n this._setStrokeStyles(ctx);\n ctx.beginPath();\n ctx.strokeRect(-this.width / 2, -this.height / 2, this.width, this.height);\n ctx.closePath();\n ctx.restore();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var x = -this.width / 2,\n y = -this.height / 2,\n w = this.width,\n h = this.height;\n\n ctx.save();\n this._setStrokeStyles(ctx);\n\n ctx.beginPath();\n fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);\n ctx.closePath();\n ctx.restore();\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n var filters = [ ];\n this.filters.forEach(function(filterObj) {\n if (filterObj) {\n filters.push(filterObj.toObject());\n }\n });\n var object = extend(this.callSuper('toObject', propertiesToInclude), {\n src: this._originalElement.src || this._originalElement._src,\n filters: filters,\n crossOrigin: this.crossOrigin,\n alignX: this.alignX,\n alignY: this.alignY,\n meetOrSlice: this.meetOrSlice\n });\n\n if (this.resizeFilters.length > 0) {\n object.resizeFilters = this.resizeFilters.map(function(filterObj) {\n return filterObj && filterObj.toObject();\n });\n }\n\n if (!this.includeDefaultValues) {\n this._removeDefaultValues(object);\n }\n\n return object;\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 markup = [], x = -this.width / 2, y = -this.height / 2,\n preserveAspectRatio = 'none';\n if (this.group && this.group.type === 'path-group') {\n x = this.left;\n y = this.top;\n }\n if (this.alignX !== 'none' && this.alignY !== 'none') {\n preserveAspectRatio = 'x' + this.alignX + 'Y' + this.alignY + ' ' + this.meetOrSlice;\n }\n markup.push(\n '\\n',\n ' 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=\"', this.width,\n '\" height=\"', this.height,\n '\" preserveAspectRatio=\"', preserveAspectRatio, '\"',\n '>\\n'\n );\n\n if (this.stroke || this.strokeDashArray) {\n var origFill = this.fill;\n this.fill = null;\n markup.push(\n '\\n'\n );\n this.fill = origFill;\n }\n\n markup.push('\\n');\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns source of an image\n * @return {String} Source of an image\n */\n getSrc: function() {\n if (this.getElement()) {\n return this.getElement().src || this.getElement()._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 * @return {fabric.Image} thisArg\n * @chainable\n */\n setSrc: function(src, callback, options) {\n fabric.util.loadImage(src, function(img) {\n return this.setElement(img, callback, options);\n }, this, options && options.crossOrigin);\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 a clone of an instance\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 this.constructor.fromObject(this.toObject(propertiesToInclude), callback);\n },\n\n /**\n * Applies filters assigned to this image (from \"filters\" array)\n * @method applyFilters\n * @param {Function} callback Callback is invoked when all filters have been applied and new image is generated\n * @return {fabric.Image} thisArg\n * @chainable\n */\n applyFilters: function(callback, filters, imgElement, forResizing) {\n\n filters = filters || this.filters;\n imgElement = imgElement || this._originalElement;\n\n if (!imgElement) {\n return;\n }\n\n var imgEl = imgElement,\n canvasEl = fabric.util.createCanvasElement(),\n replacement = fabric.util.createImage(),\n _this = this;\n\n canvasEl.width = imgEl.width;\n canvasEl.height = imgEl.height;\n canvasEl.getContext('2d').drawImage(imgEl, 0, 0, imgEl.width, imgEl.height);\n\n if (filters.length === 0) {\n this._element = imgElement;\n callback && callback();\n return canvasEl;\n }\n filters.forEach(function(filter) {\n filter && filter.applyTo(canvasEl, filter.scaleX || _this.scaleX, filter.scaleY || _this.scaleY);\n if (!forResizing && filter && filter.type === 'Resize') {\n _this.width *= filter.scaleX;\n _this.height *= filter.scaleY;\n }\n });\n\n /** @ignore */\n replacement.width = canvasEl.width;\n replacement.height = canvasEl.height;\n\n if (fabric.isLikelyNode) {\n replacement.src = canvasEl.toBuffer(undefined, fabric.Image.pngCompression);\n // onload doesn't fire in some node versions, so we invoke callback manually\n _this._element = replacement;\n !forResizing && (_this._filteredEl = replacement);\n callback && callback();\n }\n else {\n replacement.onload = function() {\n _this._element = replacement;\n !forResizing && (_this._filteredEl = replacement);\n callback && callback();\n replacement.onload = canvasEl = imgEl = null;\n };\n replacement.src = canvasEl.toDataURL('image/png');\n }\n return canvasEl;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx, noTransform) {\n var x, y, imageMargins = this._findMargins(), elementToDraw;\n\n x = (noTransform ? this.left : -this.width / 2);\n y = (noTransform ? this.top : -this.height / 2);\n\n if (this.meetOrSlice === 'slice') {\n ctx.beginPath();\n ctx.rect(x, y, this.width, this.height);\n ctx.clip();\n }\n\n if (this.isMoving === false && this.resizeFilters.length && this._needsResize()) {\n this._lastScaleX = this.scaleX;\n this._lastScaleY = this.scaleY;\n elementToDraw = this.applyFilters(null, this.resizeFilters, this._filteredEl || this._originalElement, true);\n }\n else {\n elementToDraw = this._element;\n }\n elementToDraw && ctx.drawImage(elementToDraw,\n x + imageMargins.marginX,\n y + imageMargins.marginY,\n imageMargins.width,\n imageMargins.height\n );\n\n this._renderStroke(ctx);\n },\n\n /**\n * @private, needed to check if image needs resize\n */\n _needsResize: function() {\n return (this.scaleX !== this._lastScaleX || this.scaleY !== this._lastScaleY);\n },\n\n /**\n * @private\n */\n _findMargins: function() {\n var width = this.width, height = this.height, scales,\n scale, marginX = 0, marginY = 0;\n\n if (this.alignX !== 'none' || this.alignY !== 'none') {\n scales = [this.width / this._element.width, this.height / this._element.height];\n scale = this.meetOrSlice === 'meet'\n ? Math.min.apply(null, scales) : Math.max.apply(null, scales);\n width = this._element.width * scale;\n height = this._element.height * scale;\n if (this.alignX === 'Mid') {\n marginX = (this.width - width) / 2;\n }\n if (this.alignX === 'Max') {\n marginX = this.width - width;\n }\n if (this.alignY === 'Mid') {\n marginY = (this.height - height) / 2;\n }\n if (this.alignY === 'Max') {\n marginY = this.height - height;\n }\n }\n return {\n width: width,\n height: height,\n marginX: marginX,\n marginY: marginY\n };\n },\n\n /**\n * @private\n */\n _resetWidthHeight: function() {\n var element = this.getElement();\n\n this.set('width', element.width);\n this.set('height', element.height);\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), null, 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 if (this._element && this.crossOrigin) {\n this._element.crossOrigin = this.crossOrigin;\n }\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 * @param {Object} [options] Object with width/height properties\n */\n _setWidthHeight: function(options) {\n this.width = 'width' in options\n ? options.width\n : (this.getElement()\n ? this.getElement().width || 0\n : 0);\n\n this.height = 'height' in options\n ? options.height\n : (this.getElement()\n ? this.getElement().height || 0\n : 0);\n },\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity of this instance\n */\n complexity: function() {\n return 1;\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 fabric.util.loadImage(object.src, function(img) {\n fabric.Image.prototype._initFilters.call(object, object.filters, function(filters) {\n object.filters = filters || [ ];\n fabric.Image.prototype._initFilters.call(object, object.resizeFilters, function(resizeFilters) {\n object.resizeFilters = resizeFilters || [ ];\n var instance = new fabric.Image(img, object);\n callback && callback(instance);\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)\n * @param {Object} [imgOptions] Options object\n */\n fabric.Image.fromURL = function(url, callback, imgOptions) {\n fabric.util.loadImage(url, function(img) {\n callback && callback(new fabric.Image(img, imgOptions));\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('x y width height preserveAspectRatio xlink:href'.split(' '));\n\n /**\n * Returns {@link fabric.Image} instance from an SVG element\n * @static\n * @param {SVGElement} element Element to parse\n * @param {Function} callback Callback to execute when fabric.Image object is created\n * @param {Object} [options] Options object\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 align = 'xMidYMid', meetOrSlice = 'meet', alignX, alignY, aspectRatioAttrs;\n\n if (parsedAttributes.preserveAspectRatio) {\n aspectRatioAttrs = parsedAttributes.preserveAspectRatio.split(' ');\n }\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 parsedAttributes.alignX = alignX;\n parsedAttributes.alignY = alignY;\n parsedAttributes.meetOrSlice = meetOrSlice;\n fabric.Image.fromURL(parsedAttributes['xlink:href'], callback,\n extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @type Boolean\n * @default\n */\n fabric.Image.async = true;\n\n /**\n * Indicates compression level used when generating PNG under Node (in applyFilters). Any of 0-9\n * @static\n * @type Number\n * @default\n */\n fabric.Image.pngCompression = 1;\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.getAngle() % 360;\n if (angle > 0) {\n return Math.round((angle - 1) / 90) * 90;\n }\n return Math.round(angle / 90) * 90;\n },\n\n /**\n * Straightens an object (rotating it from current angle to one of 0, 90, 180, 270, etc. depending on which is closer)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n straighten: function() {\n this.setAngle(this._getAngleValueForStraighten());\n return this;\n },\n\n /**\n * Same as {@link fabric.Object.prototype.straighten} but with animation\n * @param {Object} callbacks Object with callback functions\n * @param {Function} [callbacks.onComplete] Invoked on completion\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\n * @return {fabric.Object} thisArg\n * @chainable\n */\n fxStraighten: function(callbacks) {\n callbacks = callbacks || { };\n\n var empty = function() { },\n onComplete = callbacks.onComplete || empty,\n onChange = callbacks.onChange || empty,\n _this = this;\n\n fabric.util.animate({\n startValue: this.get('angle'),\n endValue: this._getAngleValueForStraighten(),\n duration: this.FX_DURATION,\n onChange: function(value) {\n _this.setAngle(value);\n onChange();\n },\n onComplete: function() {\n _this.setCoords();\n onComplete();\n },\n onStart: function() {\n _this.set('active', false);\n }\n });\n\n return this;\n }\n});\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n /**\n * Straightens object, then rerenders canvas\n * @param {fabric.Object} object Object to straighten\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n straightenObject: function (object) {\n object.straighten();\n this.renderAll();\n return this;\n },\n\n /**\n * Same as {@link fabric.Canvas.prototype.straightenObject}, but animated\n * @param {fabric.Object} object Object to straighten\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n fxStraightenObject: function (object) {\n object.fxStraighten({\n onChange: this.renderAll.bind(this)\n });\n return this;\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.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 * 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 * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return { type: this.type };\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\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend;\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: 200\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n fabric.Image.filters.Brightness = fabric.util.createClass(fabric.Image.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 * Constructor\n * @memberOf fabric.Image.filters.Brightness.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.brightness=0] Value to brighten the image up (0..255)\n */\n initialize: function(options) {\n options = options || { };\n this.brightness = options.brightness || 0;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n brightness = this.brightness;\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n data[i] += brightness;\n data[i + 1] += brightness;\n data[i + 2] += brightness;\n }\n\n context.putImageData(imageData, 0, 0);\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 brightness: this.brightness\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 * @return {fabric.Image.filters.Brightness} Instance of fabric.Image.filters.Brightness\n */\n fabric.Image.filters.Brightness.fromObject = function(object) {\n return new fabric.Image.filters.Brightness(object);\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 /**\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(canvas.renderAll.bind(canvas));\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(canvas.renderAll.bind(canvas));\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(canvas.renderAll.bind(canvas));\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(canvas.renderAll.bind(canvas));\n */\n fabric.Image.filters.Convolute = fabric.util.createClass(fabric.Image.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 * 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 initialize: function(options) {\n options = options || { };\n\n this.opaque = options.opaque;\n this.matrix = options.matrix || [\n 0, 0, 0,\n 0, 1, 0,\n 0, 0, 0\n ];\n\n var canvasEl = fabric.util.createCanvasElement();\n this.tmpCtx = canvasEl.getContext('2d');\n },\n\n /**\n * @private\n */\n _createImageData: function(w, h) {\n return this.tmpCtx.createImageData(w, h);\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n\n var weights = this.matrix,\n context = canvasEl.getContext('2d'),\n pixels = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n\n side = Math.round(Math.sqrt(weights.length)),\n halfSide = Math.floor(side/2),\n src = pixels.data,\n sw = pixels.width,\n sh = pixels.height,\n\n // pad output by the convolution matrix\n w = sw,\n h = sh,\n output = this._createImageData(w, h),\n\n dst = output.data,\n\n // go through the destination image pixels\n alphaFac = this.opaque ? 1 : 0;\n\n for (var y = 0; y < h; y++) {\n for (var x = 0; x < w; x++) {\n var sy = y,\n sx = x,\n dstOff = (y * w + 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 (var cy = 0; cy < side; cy++) {\n for (var cx = 0; cx < side; cx++) {\n\n var scy = sy + cy - halfSide,\n scx = sx + cx - halfSide;\n\n /* jshint maxdepth:5 */\n if (scy < 0 || scy > sh || scx < 0 || scx > sw) {\n continue;\n }\n\n var srcOff = (scy * sw + scx) * 4,\n wt = weights[cy * side + cx];\n\n r += src[srcOff] * wt;\n g += src[srcOff + 1] * wt;\n b += src[srcOff + 2] * wt;\n a += src[srcOff + 3] * wt;\n }\n }\n dst[dstOff] = r;\n dst[dstOff + 1] = g;\n dst[dstOff + 2] = b;\n dst[dstOff + 3] = a + alphaFac * (255 - a);\n }\n }\n\n context.putImageData(output, 0, 0);\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 * @return {fabric.Image.filters.Convolute} Instance of fabric.Image.filters.Convolute\n */\n fabric.Image.filters.Convolute.fromObject = function(object) {\n return new fabric.Image.filters.Convolute(object);\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 /**\n * GradientTransparency filter class\n * @class fabric.Image.filters.GradientTransparency\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.GradientTransparency#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.GradientTransparency({\n * threshold: 200\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n fabric.Image.filters.GradientTransparency = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.GradientTransparency.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'GradientTransparency',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.GradientTransparency.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.threshold=100] Threshold value\n */\n initialize: function(options) {\n options = options || { };\n this.threshold = options.threshold || 100;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n threshold = this.threshold,\n total = data.length;\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n data[i + 3] = threshold + 255 * (total - i) / total;\n }\n\n context.putImageData(imageData, 0, 0);\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 threshold: this.threshold\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 * @return {fabric.Image.filters.GradientTransparency} Instance of fabric.Image.filters.GradientTransparency\n */\n fabric.Image.filters.GradientTransparency.fromObject = function(object) {\n return new fabric.Image.filters.GradientTransparency(object);\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 /**\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(canvas.renderAll.bind(canvas));\n */\n fabric.Image.filters.Grayscale = fabric.util.createClass(fabric.Image.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 /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Grayscale.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n len = imageData.width * imageData.height * 4,\n index = 0,\n average;\n\n while (index < len) {\n average = (data[index] + data[index + 1] + data[index + 2]) / 3;\n data[index] = average;\n data[index + 1] = average;\n data[index + 2] = average;\n index += 4;\n }\n\n context.putImageData(imageData, 0, 0);\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @return {fabric.Image.filters.Grayscale} Instance of fabric.Image.filters.Grayscale\n */\n fabric.Image.filters.Grayscale.fromObject = function() {\n return new fabric.Image.filters.Grayscale();\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 /**\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 fabric.Image.filters.Invert = fabric.util.createClass(fabric.Image.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 /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Invert.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i;\n\n for (i = 0; i < iLen; 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 context.putImageData(imageData, 0, 0);\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @return {fabric.Image.filters.Invert} Instance of fabric.Image.filters.Invert\n */\n fabric.Image.filters.Invert.fromObject = function() {\n return new fabric.Image.filters.Invert();\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 /**\n * Mask filter class\n * See http://resources.aleph-1.com/mask/\n * @class fabric.Image.filters.Mask\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Mask#initialize} for constructor definition\n */\n fabric.Image.filters.Mask = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Mask.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Mask',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Mask.prototype\n * @param {Object} [options] Options object\n * @param {fabric.Image} [options.mask] Mask image object\n * @param {Number} [options.channel=0] Rgb channel (0, 1, 2 or 3)\n */\n initialize: function(options) {\n options = options || { };\n\n this.mask = options.mask;\n this.channel = [ 0, 1, 2, 3 ].indexOf(options.channel) > -1 ? options.channel : 0;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n if (!this.mask) {\n return;\n }\n\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n maskEl = this.mask.getElement(),\n maskCanvasEl = fabric.util.createCanvasElement(),\n channel = this.channel,\n i,\n iLen = imageData.width * imageData.height * 4;\n\n maskCanvasEl.width = maskEl.width;\n maskCanvasEl.height = maskEl.height;\n\n maskCanvasEl.getContext('2d').drawImage(maskEl, 0, 0, maskEl.width, maskEl.height);\n\n var maskImageData = maskCanvasEl.getContext('2d').getImageData(0, 0, maskEl.width, maskEl.height),\n maskData = maskImageData.data;\n\n for (i = 0; i < iLen; i += 4) {\n data[i + 3] = maskData[i + channel];\n }\n\n context.putImageData(imageData, 0, 0);\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 mask: this.mask.toObject(),\n channel: this.channel\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] Callback to invoke when a mask filter instance is created\n */\n fabric.Image.filters.Mask.fromObject = function(object, callback) {\n fabric.util.loadImage(object.mask.src, function(img) {\n object.mask = new fabric.Image(img, object.mask);\n callback && callback(new fabric.Image.filters.Mask(object));\n });\n };\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @type Boolean\n * @default\n */\n fabric.Image.filters.Mask.async = true;\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 /**\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(canvas.renderAll.bind(canvas));\n */\n fabric.Image.filters.Noise = fabric.util.createClass(fabric.Image.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 * Constructor\n * @memberOf fabric.Image.filters.Noise.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.noise=0] Noise value\n */\n initialize: function(options) {\n options = options || { };\n this.noise = options.noise || 0;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n noise = this.noise, rand;\n\n for (var 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 context.putImageData(imageData, 0, 0);\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 * @return {fabric.Image.filters.Noise} Instance of fabric.Image.filters.Noise\n */\n fabric.Image.filters.Noise.fromObject = function(object) {\n return new fabric.Image.filters.Noise(object);\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 /**\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(canvas.renderAll.bind(canvas));\n */\n fabric.Image.filters.Pixelate = fabric.util.createClass(fabric.Image.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 /**\n * Constructor\n * @memberOf fabric.Image.filters.Pixelate.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.blocksize=4] Blocksize for pixelate\n */\n initialize: function(options) {\n options = options || { };\n this.blocksize = options.blocksize || 4;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = imageData.height,\n jLen = imageData.width,\n index, i, j, r, g, b, a;\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 /*\n blocksize: 4\n\n [1,x,x,x,1]\n [x,x,x,x,1]\n [x,x,x,x,1]\n [x,x,x,x,1]\n [1,1,1,1,1]\n */\n\n for (var _i = i, _ilen = i + this.blocksize; _i < _ilen; _i++) {\n for (var _j = j, _jlen = j + this.blocksize; _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 context.putImageData(imageData, 0, 0);\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 blocksize: this.blocksize\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 * @return {fabric.Image.filters.Pixelate} Instance of fabric.Image.filters.Pixelate\n */\n fabric.Image.filters.Pixelate.fromObject = function(object) {\n return new fabric.Image.filters.Pixelate(object);\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 /**\n * Remove white filter class\n * @class fabric.Image.filters.RemoveWhite\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.RemoveWhite#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.RemoveWhite({\n * threshold: 40,\n * distance: 140\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n fabric.Image.filters.RemoveWhite = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.RemoveWhite.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'RemoveWhite',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.RemoveWhite.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.threshold=30] Threshold value\n * @param {Number} [options.distance=20] Distance value\n */\n initialize: function(options) {\n options = options || { };\n this.threshold = options.threshold || 30;\n this.distance = options.distance || 20;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n threshold = this.threshold,\n distance = this.distance,\n limit = 255 - threshold,\n abs = Math.abs,\n r, g, b;\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n if (r > limit &&\n g > limit &&\n b > limit &&\n abs(r - g) < distance &&\n abs(r - b) < distance &&\n abs(g - b) < distance\n ) {\n data[i + 3] = 1;\n }\n }\n\n context.putImageData(imageData, 0, 0);\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 threshold: this.threshold,\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 * @return {fabric.Image.filters.RemoveWhite} Instance of fabric.Image.filters.RemoveWhite\n */\n fabric.Image.filters.RemoveWhite.fromObject = function(object) {\n return new fabric.Image.filters.RemoveWhite(object);\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 /**\n * Sepia filter class\n * @class fabric.Image.filters.Sepia\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.Sepia();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n fabric.Image.filters.Sepia = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Sepia.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Sepia',\n\n /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Sepia.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i, avg;\n\n for (i = 0; i < iLen; i+=4) {\n avg = 0.3 * data[i] + 0.59 * data[i + 1] + 0.11 * data[i + 2];\n data[i] = avg + 100;\n data[i + 1] = avg + 50;\n data[i + 2] = avg + 255;\n }\n\n context.putImageData(imageData, 0, 0);\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @return {fabric.Image.filters.Sepia} Instance of fabric.Image.filters.Sepia\n */\n fabric.Image.filters.Sepia.fromObject = function() {\n return new fabric.Image.filters.Sepia();\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 /**\n * Sepia2 filter class\n * @class fabric.Image.filters.Sepia2\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.Sepia2();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n fabric.Image.filters.Sepia2 = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Sepia2.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Sepia2',\n\n /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Sepia.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i, r, g, b;\n\n for (i = 0; i < iLen; i+=4) {\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n data[i] = (r * 0.393 + g * 0.769 + b * 0.189 ) / 1.351;\n data[i + 1] = (r * 0.349 + g * 0.686 + b * 0.168 ) / 1.203;\n data[i + 2] = (r * 0.272 + g * 0.534 + b * 0.131 ) / 2.140;\n }\n\n context.putImageData(imageData, 0, 0);\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @return {fabric.Image.filters.Sepia2} Instance of fabric.Image.filters.Sepia2\n */\n fabric.Image.filters.Sepia2.fromObject = function() {\n return new fabric.Image.filters.Sepia2();\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 /**\n * Tint filter class\n * Adapted from https://github.com/mezzoblue/PaintbrushJS\n * @class fabric.Image.filters.Tint\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Tint#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo}\n * @example Tint filter with hex color and opacity\n * var filter = new fabric.Image.filters.Tint({\n * color: '#3513B0',\n * opacity: 0.5\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n * @example Tint filter with rgba color\n * var filter = new fabric.Image.filters.Tint({\n * color: 'rgba(53, 21, 176, 0.5)'\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n fabric.Image.filters.Tint = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Tint.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Tint',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Tint.prototype\n * @param {Object} [options] Options object\n * @param {String} [options.color=#000000] Color to tint the image with\n * @param {Number} [options.opacity] Opacity value that controls the tint effect's transparency (0..1)\n */\n initialize: function(options) {\n options = options || { };\n\n this.color = options.color || '#000000';\n this.opacity = typeof options.opacity !== 'undefined'\n ? options.opacity\n : new fabric.Color(this.color).getAlpha();\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i,\n tintR, tintG, tintB,\n r, g, b, alpha1,\n source;\n\n source = new fabric.Color(this.color).getSource();\n\n tintR = source[0] * this.opacity;\n tintG = source[1] * this.opacity;\n tintB = source[2] * this.opacity;\n\n alpha1 = 1 - this.opacity;\n\n for (i = 0; i < iLen; i+=4) {\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n // alpha compositing\n data[i] = tintR + r * alpha1;\n data[i + 1] = tintG + g * alpha1;\n data[i + 2] = tintB + b * alpha1;\n }\n\n context.putImageData(imageData, 0, 0);\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 opacity: this.opacity\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 * @return {fabric.Image.filters.Tint} Instance of fabric.Image.filters.Tint\n */\n fabric.Image.filters.Tint.fromObject = function(object) {\n return new fabric.Image.filters.Tint(object);\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 /**\n * Multiply filter class\n * Adapted from http://www.laurenscorijn.com/articles/colormath-basics\n * @class fabric.Image.filters.Multiply\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @example Multiply filter with hex color\n * var filter = new fabric.Image.filters.Multiply({\n * color: '#F0F'\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n * @example Multiply filter with rgb color\n * var filter = new fabric.Image.filters.Multiply({\n * color: 'rgb(53, 21, 176)'\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n fabric.Image.filters.Multiply = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Multiply.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Multiply',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Multiply.prototype\n * @param {Object} [options] Options object\n * @param {String} [options.color=#000000] Color to multiply the image pixels with\n */\n initialize: function(options) {\n options = options || { };\n\n this.color = options.color || '#000000';\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i,\n source;\n\n source = new fabric.Color(this.color).getSource();\n\n for (i = 0; i < iLen; i+=4) {\n data[i] *= source[0] / 255;\n data[i + 1] *= source[1] / 255;\n data[i + 2] *= source[2] / 255;\n }\n\n context.putImageData(imageData, 0, 0);\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 });\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 * @return {fabric.Image.filters.Multiply} Instance of fabric.Image.filters.Multiply\n */\n fabric.Image.filters.Multiply.fromObject = function(object) {\n return new fabric.Image.filters.Multiply(object);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n 'use strict';\n\n var fabric = global.fabric;\n\n /**\n * Color Blend filter class\n * @class fabric.Image.filter.Blend\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @example\n * var filter = new fabric.Image.filters.Blend({\n * color: '#000',\n * mode: 'multiply'\n * });\n *\n * var filter = new fabric.Image.filters.Blend({\n * image: fabricImageObject,\n * mode: 'multiply',\n * alpha: 0.5\n * });\n\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n fabric.Image.filters.Blend = fabric.util.createClass({\n type: 'Blend',\n\n initialize: function(options) {\n options = options || {};\n this.color = options.color || '#000';\n this.image = options.image || false;\n this.mode = options.mode || 'multiply';\n this.alpha = options.alpha || 1;\n },\n\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n tr, tg, tb,\n r, g, b,\n _r, _g, _b,\n source,\n isImage = false;\n\n if (this.image) {\n // Blend images\n isImage = true;\n\n var _el = fabric.util.createCanvasElement();\n _el.width = this.image.width;\n _el.height = this.image.height;\n\n var tmpCanvas = new fabric.StaticCanvas(_el);\n tmpCanvas.add(this.image);\n var context2 = tmpCanvas.getContext('2d');\n source = context2.getImageData(0, 0, tmpCanvas.width, tmpCanvas.height).data;\n }\n else {\n // Blend color\n source = new fabric.Color(this.color).getSource();\n\n tr = source[0] * this.alpha;\n tg = source[1] * this.alpha;\n tb = source[2] * this.alpha;\n }\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n if (isImage) {\n tr = source[i] * this.alpha;\n tg = source[i + 1] * this.alpha;\n tb = source[i + 2] * this.alpha;\n }\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] = 1 - (1 - r) * (1 - tr);\n data[i + 1] = 1 - (1 - g) * (1 - tg);\n data[i + 2] = 1 - (1 - b) * (1 - tb);\n break;\n case 'add':\n data[i] = Math.min(255, r + tr);\n data[i + 1] = Math.min(255, g + tg);\n data[i + 2] = Math.min(255, 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 _r = r - tr;\n _g = g - tg;\n _b = b - tb;\n\n data[i] = (_r < 0) ? 0 : _r;\n data[i + 1] = (_g < 0) ? 0 : _g;\n data[i + 2] = (_b < 0) ? 0 : _b;\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 }\n }\n\n context.putImageData(imageData, 0, 0);\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 color: this.color,\n image: this.image,\n mode: this.mode,\n alpha: this.alpha\n };\n }\n });\n\n fabric.Image.filters.Blend.fromObject = function(object) {\n return new fabric.Image.filters.Blend(object);\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, max = Math.max, round = Math.round, sin = Math.sin,\n ceil = Math.ceil;\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 fabric.Image.filters.Resize = fabric.util.createClass(fabric.Image.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 * @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: 0,\n\n /**\n * Scale factor for resizing, y axis\n * @param {Number} scaleY\n * @default\n */\n scaleY: 0,\n\n /**\n * LanczosLobes parameter for lanczos filter\n * @param {Number} lanczosLobes\n * @default\n */\n lanczosLobes: 3,\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 */\n applyTo: function(canvasEl, scaleX, scaleY) {\n\n this.rcpScaleX = 1 / scaleX;\n this.rcpScaleY = 1 / scaleY;\n\n var oW = canvasEl.width, oH = canvasEl.height,\n dW = round(oW * scaleX), dH = round(oH * scaleY),\n imageData;\n\n if (this.resizeType === 'sliceHack') {\n imageData = this.sliceByTwo(canvasEl, oW, oH, dW, dH);\n }\n if (this.resizeType === 'hermite') {\n imageData = this.hermiteFastResize(canvasEl, oW, oH, dW, dH);\n }\n if (this.resizeType === 'bilinear') {\n imageData = this.bilinearFiltering(canvasEl, oW, oH, dW, dH);\n }\n if (this.resizeType === 'lanczos') {\n imageData = this.lanczosResize(canvasEl, oW, oH, dW, dH);\n }\n canvasEl.width = dW;\n canvasEl.height = dH;\n canvasEl.getContext('2d').putImageData(imageData, 0, 0);\n },\n\n sliceByTwo: function(canvasEl, width, height, newWidth, newHeight) {\n var context = canvasEl.getContext('2d'), imageData,\n multW = 0.5, multH = 0.5, signW = 1, signH = 1,\n doneW = false, doneH = false, stepW = width, stepH = height,\n tmpCanvas = fabric.util.createCanvasElement(),\n tmpCtx = tmpCanvas.getContext('2d');\n newWidth = floor(newWidth);\n newHeight = floor(newHeight);\n tmpCanvas.width = max(newWidth, width);\n tmpCanvas.height = max(newHeight, height);\n\n if (newWidth > width) {\n multW = 2;\n signW = -1;\n }\n if (newHeight > height) {\n multH = 2;\n signH = -1;\n }\n imageData = context.getImageData(0, 0, width, height);\n canvasEl.width = max(newWidth, width);\n canvasEl.height = max(newHeight, height);\n context.putImageData(imageData, 0, 0);\n\n while (!doneW || !doneH) {\n width = stepW;\n height = stepH;\n if (newWidth * signW < floor(stepW * multW * signW)) {\n stepW = floor(stepW * multW);\n }\n else {\n stepW = newWidth;\n doneW = true;\n }\n if (newHeight * signH < floor(stepH * multH * signH)) {\n stepH = floor(stepH * multH);\n }\n else {\n stepH = newHeight;\n doneH = true;\n }\n imageData = context.getImageData(0, 0, width, height);\n tmpCtx.putImageData(imageData, 0, 0);\n context.clearRect(0, 0, stepW, stepH);\n context.drawImage(tmpCanvas, 0, 0, width, height, 0, 0, stepW, stepH);\n }\n return context.getImageData(0, 0, newWidth, newHeight);\n },\n\n lanczosResize: function(canvasEl, oW, oH, dW, dH) {\n\n function lanczosCreate(lobes) {\n return function(x) {\n if (x > lobes) {\n return 0;\n }\n x *= Math.PI;\n if (abs(x) < 1e-16) {\n return 1;\n }\n var xx = x / lobes;\n return sin(x) * sin(xx) / x / xx;\n };\n }\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 context = canvasEl.getContext('2d'),\n srcImg = context.getImageData(0, 0, oW, oH),\n destImg = context.getImageData(0, 0, dW, dH),\n srcData = srcImg.data, destData = destImg.data,\n lanczos = 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 bilinearFiltering: function(canvasEl, w, h, w2, h2) {\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, context = canvasEl.getContext('2d'),\n w4 = 4 * (w - 1), img = context.getImageData(0, 0, w, h),\n pixels = img.data, destImage = context.getImageData(0, 0, w2, h2),\n destPixels = destImage.data;\n for (i = 0; i < h2; i++) {\n for (j = 0; j < w2; 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 * w + 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 hermiteFastResize: function(canvasEl, oW, oH, dW, dH) {\n var ratioW = this.rcpScaleX, ratioH = this.rcpScaleY,\n ratioWHalf = ceil(ratioW / 2),\n ratioHHalf = ceil(ratioH / 2),\n context = canvasEl.getContext('2d'),\n img = context.getImageData(0, 0, oW, oH), data = img.data,\n img2 = context.getImageData(0, 0, 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 /*jshint maxdepth:5 */\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 /*jshint maxdepth:6 */\n if (data[dx + 3] < 255) {\n weight = weight * data[dx + 3] / 250;\n }\n /*jshint maxdepth:5 */\n gxR += weight * data[dx];\n gxG += weight * data[dx + 1];\n gxB += weight * data[dx + 2];\n weights += weight;\n }\n /*jshint maxdepth:4 */\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 * @return {fabric.Image.filters.Resize} Instance of fabric.Image.filters.Resize\n */\n fabric.Image.filters.Resize.fromObject = function(object) {\n return new fabric.Image.filters.Resize(object);\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 clone = fabric.util.object.clone,\n toFixed = fabric.util.toFixed,\n supportsLineDash = fabric.StaticCanvas.supports('setLineDash'),\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n\n if (fabric.Text) {\n fabric.warn('fabric.Text is already defined');\n return;\n }\n\n var stateProperties = fabric.Object.prototype.stateProperties.concat();\n stateProperties.push(\n 'fontFamily',\n 'fontWeight',\n 'fontSize',\n 'text',\n 'textDecoration',\n 'textAlign',\n 'fontStyle',\n 'lineHeight',\n 'textBackgroundColor'\n );\n\n /**\n * Text class\n * @class fabric.Text\n * @extends fabric.Object\n * @return {fabric.Text} thisArg\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#text}\n * @see {@link fabric.Text#initialize} for constructor definition\n */\n fabric.Text = fabric.util.createClass(fabric.Object, /** @lends fabric.Text.prototype */ {\n\n /**\n * Properties which when set cause object to change dimensions\n * @type Object\n * @private\n */\n _dimensionAffectingProps: {\n fontSize: true,\n fontWeight: true,\n fontFamily: true,\n fontStyle: true,\n lineHeight: true,\n stroke: true,\n strokeWidth: true,\n text: true,\n textAlign: true\n },\n\n /**\n * @private\n */\n _reNewline: /\\r?\\n/,\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 _reSpacesAndTabs: /[ \\t\\r]+/g,\n\n /**\n * Retrieves object's fontSize\n * @method getFontSize\n * @memberOf fabric.Text.prototype\n * @return {String} Font size (in pixels)\n */\n\n /**\n * Sets object's fontSize\n * @method setFontSize\n * @memberOf fabric.Text.prototype\n * @param {Number} fontSize Font size (in pixels)\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's fontWeight\n * @method getFontWeight\n * @memberOf fabric.Text.prototype\n * @return {(String|Number)} Font weight\n */\n\n /**\n * Sets object's fontWeight\n * @method setFontWeight\n * @memberOf fabric.Text.prototype\n * @param {(Number|String)} fontWeight Font weight\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's fontFamily\n * @method getFontFamily\n * @memberOf fabric.Text.prototype\n * @return {String} Font family\n */\n\n /**\n * Sets object's fontFamily\n * @method setFontFamily\n * @memberOf fabric.Text.prototype\n * @param {String} fontFamily Font family\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's text\n * @method getText\n * @memberOf fabric.Text.prototype\n * @return {String} text\n */\n\n /**\n * Sets object's text\n * @method setText\n * @memberOf fabric.Text.prototype\n * @param {String} text Text\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's textDecoration\n * @method getTextDecoration\n * @memberOf fabric.Text.prototype\n * @return {String} Text decoration\n */\n\n /**\n * Sets object's textDecoration\n * @method setTextDecoration\n * @memberOf fabric.Text.prototype\n * @param {String} textDecoration Text decoration\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's fontStyle\n * @method getFontStyle\n * @memberOf fabric.Text.prototype\n * @return {String} Font style\n */\n\n /**\n * Sets object's fontStyle\n * @method setFontStyle\n * @memberOf fabric.Text.prototype\n * @param {String} fontStyle Font style\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's lineHeight\n * @method getLineHeight\n * @memberOf fabric.Text.prototype\n * @return {Number} Line height\n */\n\n /**\n * Sets object's lineHeight\n * @method setLineHeight\n * @memberOf fabric.Text.prototype\n * @param {Number} lineHeight Line height\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's textAlign\n * @method getTextAlign\n * @memberOf fabric.Text.prototype\n * @return {String} Text alignment\n */\n\n /**\n * Sets object's textAlign\n * @method setTextAlign\n * @memberOf fabric.Text.prototype\n * @param {String} textAlign Text alignment\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's textBackgroundColor\n * @method getTextBackgroundColor\n * @memberOf fabric.Text.prototype\n * @return {String} Text background color\n */\n\n /**\n * Sets object's textBackgroundColor\n * @method setTextBackgroundColor\n * @memberOf fabric.Text.prototype\n * @param {String} textBackgroundColor Text background color\n * @return {fabric.Text}\n * @chainable\n */\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 Possible values: \"\", \"underline\", \"overline\" or \"line-through\".\n * @type String\n * @default\n */\n textDecoration: '',\n\n /**\n * Text alignment. Possible values: \"left\", \"center\", or \"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: '',\n\n /**\n * Line height\n * @type Number\n * @default\n */\n lineHeight: 1.16,\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: stateProperties,\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 * @private\n */\n _fontSizeFraction: 0.25,\n\n /**\n * Text Line proportion to font Size (in pixels)\n * @type Number\n * @default\n */\n _fontSizeMult: 1.13,\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 options = options || { };\n this.text = text;\n this.__skipDimension = true;\n this.setOptions(options);\n this.__skipDimension = false;\n this._initDimensions();\n },\n\n /**\n * Renders text object on offscreen canvas, so that it would get dimensions\n * @private\n */\n _initDimensions: function(ctx) {\n if (this.__skipDimension) {\n return;\n }\n if (!ctx) {\n ctx = fabric.util.createCanvasElement().getContext('2d');\n this._setTextStyles(ctx);\n }\n this._textLines = this._splitTextIntoLines();\n this._clearCache();\n //if textAlign is 'justify' i have to disable caching\n //when calculating width of text and widths of line.\n this._cacheLinesWidth = (this.textAlign !== 'justify');\n this.width = this._getTextWidth(ctx);\n this._cacheLinesWidth = true;\n this.height = this._getTextHeight(ctx);\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 * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n this.clipTo && fabric.util.clipContext(this, ctx);\n this._setOpacity(ctx);\n this._setShadow(ctx);\n this._setupCompositeOperation(ctx);\n this._renderTextBackground(ctx);\n this._setStrokeStyles(ctx);\n this._setFillStyles(ctx);\n this._renderText(ctx);\n this._renderTextDecoration(ctx);\n this.clipTo && ctx.restore();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderText: function(ctx) {\n\n this._translateForTextAlign(ctx);\n this._renderTextFill(ctx);\n this._renderTextStroke(ctx);\n this._translateForTextAlign(ctx, true);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} back Indicates if translate back or forward\n */\n _translateForTextAlign: function(ctx, back) {\n if (this.textAlign !== 'left' && this.textAlign !== 'justify') {\n var sign = back ? -1 : 1;\n ctx.translate(this.textAlign === 'center' ? (sign * this.width / 2) : sign * this.width, 0);\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _setTextStyles: function(ctx) {\n ctx.textBaseline = 'alphabetic';\n if (!this.skipTextAlign) {\n ctx.textAlign = this.textAlign;\n }\n ctx.font = this._getFontDeclaration();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @return {Number} Height of fabric.Text object\n */\n _getTextHeight: function() {\n return this._textLines.length * this._getHeightOfLine();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @return {Number} Maximum width of fabric.Text object\n */\n _getTextWidth: function(ctx) {\n var maxWidth = this._getLineWidth(ctx, 0);\n\n for (var i = 1, len = this._textLines.length; i < len; i++) {\n var currentLineWidth = this._getLineWidth(ctx, 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} chars Chars to render\n * @param {Number} left Left position of text\n * @param {Number} top Top position of text\n */\n _renderChars: function(method, ctx, chars, left, top) {\n // remove Text word from method var\n var shortM = method.slice(0, -4);\n if (this[shortM].toLive) {\n var offsetX = -this.width / 2 + this[shortM].offsetX || 0,\n offsetY = -this.height / 2 + this[shortM].offsetY || 0;\n ctx.save();\n ctx.translate(offsetX, offsetY);\n left -= offsetX;\n top -= offsetY;\n }\n ctx[method](chars, left, top);\n this[shortM].toLive && ctx.restore();\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 // lift the line by quarter of fontSize\n top -= this.fontSize * this._fontSizeFraction;\n\n // short-circuit\n if (this.textAlign !== 'justify') {\n this._renderChars(method, ctx, line, left, top, lineIndex);\n return;\n }\n\n var lineWidth = this._getLineWidth(ctx, lineIndex),\n totalWidth = this.width;\n if (totalWidth >= lineWidth) {\n // stretch the line\n var words = line.split(/\\s+/),\n wordsWidth = this._getWidthOfWords(ctx, line, lineIndex),\n widthDiff = totalWidth - wordsWidth,\n numSpaces = words.length - 1,\n spaceWidth = widthDiff / numSpaces,\n leftOffset = 0;\n\n for (var i = 0, len = words.length; i < len; i++) {\n this._renderChars(method, ctx, words[i], left + leftOffset, top, lineIndex);\n leftOffset += ctx.measureText(words[i]).width + spaceWidth;\n }\n }\n else {\n this._renderChars(method, ctx, line, left, top, lineIndex);\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} line\n */\n _getWidthOfWords: function (ctx, line) {\n return ctx.measureText(line.replace(/\\s+/g, '')).width;\n },\n\n /**\n * @private\n * @return {Number} Left offset\n */\n _getLeftOffset: function() {\n return -this.width / 2;\n },\n\n /**\n * @private\n * @return {Number} Top offset\n */\n _getTopOffset: function() {\n return -this.height / 2;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextFill: function(ctx) {\n if (!this.fill && !this._skipFillStrokeCheck) {\n return;\n }\n\n var lineHeights = 0;\n\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n var heightOfLine = this._getHeightOfLine(ctx, i),\n maxHeight = heightOfLine / this.lineHeight;\n\n this._renderTextLine(\n 'fillText',\n ctx,\n this._textLines[i],\n this._getLeftOffset(),\n this._getTopOffset() + lineHeights + maxHeight,\n i\n );\n lineHeights += heightOfLine;\n }\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._skipFillStrokeCheck) {\n return;\n }\n\n var lineHeights = 0;\n\n if (this.shadow && !this.shadow.affectStroke) {\n this._removeShadow(ctx);\n }\n\n ctx.save();\n\n if (this.strokeDashArray) {\n // Spec requires the concatenation of two copies the dash list when the number of elements is odd\n if (1 & this.strokeDashArray.length) {\n this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray);\n }\n supportsLineDash && ctx.setLineDash(this.strokeDashArray);\n }\n\n ctx.beginPath();\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n var heightOfLine = this._getHeightOfLine(ctx, i),\n maxHeight = heightOfLine / this.lineHeight;\n\n this._renderTextLine(\n 'strokeText',\n ctx,\n this._textLines[i],\n this._getLeftOffset(),\n this._getTopOffset() + lineHeights + maxHeight,\n i\n );\n lineHeights += heightOfLine;\n }\n ctx.closePath();\n ctx.restore();\n },\n\n _getHeightOfLine: function() {\n return this.fontSize * this._fontSizeMult * this.lineHeight;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Array} textLines Array of all text lines\n */\n _renderTextBackground: function(ctx) {\n this._renderTextBoxBackground(ctx);\n this._renderTextLinesBackground(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextBoxBackground: function(ctx) {\n if (!this.backgroundColor) {\n return;\n }\n\n ctx.fillStyle = this.backgroundColor;\n\n ctx.fillRect(\n this._getLeftOffset(),\n this._getTopOffset(),\n this.width,\n this.height\n );\n\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextLinesBackground: function(ctx) {\n if (!this.textBackgroundColor) {\n return;\n }\n var lineTopOffset = 0, heightOfLine = this._getHeightOfLine(),\n lineWidth, lineLeftOffset;\n\n ctx.fillStyle = this.textBackgroundColor;\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n if (this._textLines[i] !== '') {\n lineWidth = this._getLineWidth(ctx, i);\n lineLeftOffset = this._getLineLeftOffset(lineWidth);\n ctx.fillRect(\n this._getLeftOffset() + lineLeftOffset,\n this._getTopOffset() + lineTopOffset,\n lineWidth,\n this.fontSize * this._fontSizeMult\n );\n }\n lineTopOffset += heightOfLine;\n }\n },\n\n /**\n * @private\n * @param {Number} lineWidth Width of text line\n * @return {Number} Line left offset\n */\n _getLineLeftOffset: function(lineWidth) {\n if (this.textAlign === 'center') {\n return (this.width - lineWidth) / 2;\n }\n if (this.textAlign === 'right') {\n return this.width - lineWidth;\n }\n return 0;\n },\n\n /**\n * @private\n */\n _clearCache: function() {\n this.__lineWidths = [ ];\n this.__lineHeights = [ ];\n this.__lineOffsets = [ ];\n },\n\n /**\n * @private\n */\n _shouldClearCache: function() {\n var shouldClear = false;\n if (this._forceClearCache) {\n this._forceClearCache = false;\n return true;\n }\n for (var prop in this._dimensionAffectingProps) {\n if (this['__' + prop] !== this[prop]) {\n this['__' + prop] = this[prop];\n shouldClear = true;\n }\n }\n return shouldClear;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex line number\n * @return {Number} Line width\n */\n _getLineWidth: function(ctx, lineIndex) {\n if (this.__lineWidths[lineIndex]) {\n return this.__lineWidths[lineIndex];\n }\n var width, wordCount, line = this._textLines[lineIndex];\n if (line === '') {\n width = 0;\n }\n else if (this.textAlign === 'justify' && this._cacheLinesWidth) {\n wordCount = line.split(' ');\n //consider not justify last line, not for now.\n if (wordCount.length > 1) {\n width = this.width;\n }\n else {\n width = ctx.measureText(line).width;\n }\n }\n else {\n width = ctx.measureText(line).width;\n }\n this._cacheLinesWidth && (this.__lineWidths[lineIndex] = width);\n return width;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextDecoration: function(ctx) {\n if (!this.textDecoration) {\n return;\n }\n\n var halfOfVerticalBox = this.height / 2,\n _this = this, offsets = [];\n\n /** @ignore */\n function renderLinesAtOffset(offsets) {\n var i, lineHeight = 0, len, j, oLen, lineWidth,\n lineLeftOffset, heightOfLine;\n\n for (i = 0, len = _this._textLines.length; i < len; i++) {\n\n lineWidth = _this._getLineWidth(ctx, i),\n lineLeftOffset = _this._getLineLeftOffset(lineWidth),\n heightOfLine = _this._getHeightOfLine(ctx, i);\n\n for (j = 0, oLen = offsets.length; j < oLen; j++) {\n ctx.fillRect(\n _this._getLeftOffset() + lineLeftOffset,\n lineHeight + (_this._fontSizeMult - 1 + offsets[j] ) * _this.fontSize - halfOfVerticalBox,\n lineWidth,\n _this.fontSize / 15);\n }\n lineHeight += heightOfLine;\n }\n }\n\n if (this.textDecoration.indexOf('underline') > -1) {\n offsets.push(0.85); // 1 - 3/16\n }\n if (this.textDecoration.indexOf('line-through') > -1) {\n offsets.push(0.43);\n }\n if (this.textDecoration.indexOf('overline') > -1) {\n offsets.push(-0.12);\n }\n if (offsets.length > 0) {\n renderLinesAtOffset(offsets);\n }\n },\n\n /**\n * @private\n */\n _getFontDeclaration: function() {\n return [\n // node-canvas needs \"weight style\", while browsers need \"style weight\"\n (fabric.isLikelyNode ? this.fontWeight : this.fontStyle),\n (fabric.isLikelyNode ? this.fontStyle : this.fontWeight),\n this.fontSize + 'px',\n (fabric.isLikelyNode ? ('\"' + this.fontFamily + '\"') : this.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, noTransform) {\n // do not render if object is not visible\n if (!this.visible) {\n return;\n }\n\n ctx.save();\n this._setTextStyles(ctx);\n\n if (this._shouldClearCache()) {\n this._initDimensions(ctx);\n }\n if (!noTransform) {\n this.transform(ctx);\n }\n if (this.transformMatrix) {\n ctx.transform.apply(ctx, this.transformMatrix);\n }\n if (this.group && this.group.type === 'path-group') {\n ctx.translate(this.left, this.top);\n }\n this._render(ctx);\n ctx.restore();\n },\n\n /**\n * Returns the text as an array of lines.\n * @returns {Array} Lines in the text\n */\n _splitTextIntoLines: function() {\n return this.text.split(this._reNewline);\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 object = extend(this.callSuper('toObject', propertiesToInclude), {\n text: this.text,\n fontSize: this.fontSize,\n fontWeight: this.fontWeight,\n fontFamily: this.fontFamily,\n fontStyle: this.fontStyle,\n lineHeight: this.lineHeight,\n textDecoration: this.textDecoration,\n textAlign: this.textAlign,\n textBackgroundColor: this.textBackgroundColor\n });\n if (!this.includeDefaultValues) {\n this._removeDefaultValues(object);\n }\n return object;\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 markup = this._createBaseSVGMarkup(),\n offsets = this._getSVGLeftTopOffsets(this.ctx),\n textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft);\n this._wrapSVGTextAndBg(markup, textAndBg);\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n\n /**\n * @private\n */\n _getSVGLeftTopOffsets: function(ctx) {\n var lineTop = this._getHeightOfLine(ctx, 0),\n textLeft = -this.width / 2,\n textTop = 0;\n\n return {\n textLeft: textLeft + (this.group && this.group.type === 'path-group' ? this.left : 0),\n textTop: textTop + (this.group && this.group.type === 'path-group' ? -this.top : 0),\n lineTop: lineTop\n };\n },\n\n /**\n * @private\n */\n _wrapSVGTextAndBg: function(markup, textAndBg) {\n markup.push(\n '\\t\\n',\n textAndBg.textBgRects.join(''),\n '\\t\\t',\n textAndBg.textSpans.join(''),\n '\\n',\n '\\t\\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 = 0;\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 if (this.textBackgroundColor) {\n this._setSVGTextLineBg(textBgRects, i, textLeftOffset, textTopOffset, height);\n }\n this._setSVGTextLineText(i, textSpans, height, textLeftOffset, textTopOffset, textBgRects);\n height += this._getHeightOfLine(this.ctx, i);\n }\n\n return {\n textSpans: textSpans,\n textBgRects: textBgRects\n };\n },\n\n _setSVGTextLineText: function(i, textSpans, height, textLeftOffset, textTopOffset) {\n var yPos = this.fontSize * (this._fontSizeMult - this._fontSizeFraction)\n - textTopOffset + height - this.height / 2;\n textSpans.push(\n ' elements since setting opacity\n // on containing one doesn't work in Illustrator\n this._getFillAttributes(this.fill), '>',\n fabric.util.string.escapeXml(this._textLines[i]),\n ''\n );\n },\n\n _setSVGTextLineBg: function(textBgRects, i, textLeftOffset, textTopOffset, height) {\n textBgRects.push(\n '\\t\\t\\n');\n },\n\n _setSVGBg: function(textBgRects) {\n if (this.backgroundColor) {\n textBgRects.push(\n '\\t\\t\\n');\n }\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 {Any} 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 /* _TO_SVG_END_ */\n\n /**\n * Sets specified property to a specified value\n * @param {String} key\n * @param {Any} value\n * @return {fabric.Text} thisArg\n * @chainable\n */\n _set: function(key, value) {\n this.callSuper('_set', key, value);\n\n if (key in this._dimensionAffectingProps) {\n this._initDimensions();\n this.setCoords();\n }\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 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 {Object} [options] Options object\n * @return {fabric.Text} Instance of fabric.Text\n */\n fabric.Text.fromElement = function(element, options) {\n if (!element) {\n return null;\n }\n\n var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES);\n options = fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes);\n\n options.top = options.top || 0;\n options.left = options.left || 0;\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 if (!options.originX) {\n options.originX = 'left';\n }\n var textContent = element.textContent.replace(/^\\s+|\\s+$|\\n+/g, '').replace(/\\s+/g, ' '),\n text = new fabric.Text(textContent, options),\n /*\n Adjust positioning:\n x/y attributes in SVG correspond to the bottom-left corner of text bounding box\n top/left properties in Fabric correspond to center point of text bounding box\n */\n offX = 0;\n\n if (text.originX === 'left') {\n offX = text.getWidth() / 2;\n }\n if (text.originX === 'right') {\n offX = -text.getWidth() / 2;\n }\n text.set({\n left: text.getLeft() + offX,\n top: text.getTop() - text.getHeight() / 2 + text.fontSize * (0.18 + text._fontSizeFraction) /* 0.3 is the old lineHeight */\n });\n\n return text;\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Returns fabric.Text instance from an object representation\n * @static\n * @memberOf fabric.Text\n * @param {Object} object Object to create an instance from\n * @return {fabric.Text} Instance of fabric.Text\n */\n fabric.Text.fromObject = function(object) {\n return new fabric.Text(object.text, clone(object));\n };\n\n fabric.util.createAccessors(fabric.Text);\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n var clone = fabric.util.object.clone;\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 default cursor (when not overwritten by character style)\n * @type String\n * @default\n */\n cursorColor: '#333',\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 * Object containing character styles\n * (where top-level properties corresponds to line number and 2nd-level properties -- to char number in a line)\n * @type Object\n * @default\n */\n styles: null,\n\n /**\n * Indicates whether internal text char widths can be cached\n * @type Boolean\n * @default\n */\n caching: true,\n\n /**\n * @private\n * @type Boolean\n * @default\n */\n _skipFillStrokeCheck: false,\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 _charWidthsCache: { },\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.styles = options ? (options.styles || { }) : { };\n this.callSuper('initialize', text, options);\n this.initBehavior();\n },\n\n /**\n * @private\n */\n _clearCache: function() {\n this.callSuper('_clearCache');\n this.__maxFontHeights = [ ];\n this.__widthOfSpace = [ ];\n },\n\n /**\n * Returns true if object has no styling\n */\n isEmptyStyles: function() {\n if (!this.styles) {\n return true;\n }\n var obj = this.styles;\n\n for (var p1 in obj) {\n for (var p2 in obj[p1]) {\n /*jshint unused:false */\n for (var p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n return true;\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 if (this.selectionStart !== index) {\n this.fire('selection:changed');\n this.canvas && this.canvas.fire('text:selection:changed', { target: this });\n this.selectionStart = index;\n }\n this._updateTextarea();\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 if (this.selectionEnd !== index) {\n this.fire('selection:changed');\n this.canvas && this.canvas.fire('text:selection:changed', { target: this });\n this.selectionEnd = index;\n }\n this._updateTextarea();\n },\n\n /**\n * Gets style of a current selection/cursor (at the start position)\n * @param {Number} [startIndex] Start index to get styles at\n * @param {Number} [endIndex] End index to get styles at\n * @return {Object} styles Style object at a specified (or current) index\n */\n getSelectionStyles: function(startIndex, endIndex) {\n\n if (arguments.length === 2) {\n var styles = [ ];\n for (var i = startIndex; i < endIndex; i++) {\n styles.push(this.getSelectionStyles(i));\n }\n return styles;\n }\n\n var loc = this.get2DCursorLocation(startIndex),\n style = this._getStyleDeclaration(loc.lineIndex, loc.charIndex);\n\n return style || {};\n },\n\n /**\n * Sets style of a current selection\n * @param {Object} [styles] Styles object\n * @return {fabric.IText} thisArg\n * @chainable\n */\n setSelectionStyles: function(styles) {\n if (this.selectionStart === this.selectionEnd) {\n this._extendStyles(this.selectionStart, styles);\n }\n else {\n for (var i = this.selectionStart; i < this.selectionEnd; i++) {\n this._extendStyles(i, styles);\n }\n }\n /* not included in _extendStyles to avoid clearing cache more than once */\n this._forceClearCache = true;\n return this;\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 * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n this.callSuper('_render', ctx);\n this.ctx = ctx;\n this.isEditing && this.renderCursorOrSelection();\n },\n\n /**\n * Renders cursor or selection (depending on what exists)\n */\n renderCursorOrSelection: function() {\n if (!this.active) {\n return;\n }\n\n var chars = this.text.split(''),\n boundaries, ctx;\n\n if (this.canvas.contextTop) {\n ctx = this.canvas.contextTop;\n ctx.save();\n ctx.transform.apply(ctx, this.canvas.viewportTransform);\n this.transform(ctx);\n this.transformMatrix && ctx.transform.apply(ctx, this.transformMatrix);\n }\n else {\n ctx = this.ctx;\n ctx.save();\n }\n\n if (this.selectionStart === this.selectionEnd) {\n boundaries = this._getCursorBoundaries(chars, 'cursor');\n this.renderCursor(boundaries, ctx);\n }\n else {\n boundaries = this._getCursorBoundaries(chars, 'selection');\n this.renderSelection(chars, boundaries, ctx);\n }\n\n ctx.restore();\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 */\n get2DCursorLocation: function(selectionStart) {\n if (typeof selectionStart === 'undefined') {\n selectionStart = this.selectionStart;\n }\n var len = this._textLines.length;\n for (var i = 0; i < len; i++) {\n if (selectionStart <= this._textLines[i].length) {\n return {\n lineIndex: i,\n charIndex: selectionStart\n };\n }\n selectionStart -= this._textLines[i].length + 1;\n }\n return {\n lineIndex: i - 1,\n charIndex: this._textLines[i - 1].length < selectionStart ? this._textLines[i - 1].length : selectionStart\n };\n },\n\n /**\n * Returns complete style of char at the current cursor\n * @param {Number} lineIndex Line index\n * @param {Number} charIndex Char index\n * @return {Object} Character style\n */\n getCurrentCharStyle: function(lineIndex, charIndex) {\n var style = this._getStyleDeclaration(lineIndex, charIndex === 0 ? 0 : charIndex - 1);\n\n return {\n fontSize: style && style.fontSize || this.fontSize,\n fill: style && style.fill || this.fill,\n textBackgroundColor: style && style.textBackgroundColor || this.textBackgroundColor,\n textDecoration: style && style.textDecoration || this.textDecoration,\n fontFamily: style && style.fontFamily || this.fontFamily,\n fontWeight: style && style.fontWeight || this.fontWeight,\n fontStyle: style && style.fontStyle || this.fontStyle,\n stroke: style && style.stroke || this.stroke,\n strokeWidth: style && style.strokeWidth || this.strokeWidth\n };\n },\n\n /**\n * Returns fontSize of char at the current cursor\n * @param {Number} lineIndex Line index\n * @param {Number} charIndex Char index\n * @return {Number} Character font size\n */\n getCurrentCharFontSize: function(lineIndex, charIndex) {\n var style = this._getStyleDeclaration(lineIndex, charIndex === 0 ? 0 : charIndex - 1);\n return style && style.fontSize ? style.fontSize : this.fontSize;\n },\n\n /**\n * Returns color (fill) of char at the current cursor\n * @param {Number} lineIndex Line index\n * @param {Number} charIndex Char index\n * @return {String} Character color (fill)\n */\n getCurrentCharColor: function(lineIndex, charIndex) {\n var style = this._getStyleDeclaration(lineIndex, charIndex === 0 ? 0 : charIndex - 1);\n return style && style.fill ? style.fill : this.cursorColor;\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(chars, typeOfBoundaries) {\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 var left = Math.round(this._getLeftOffset()),\n top = this._getTopOffset(),\n\n offsets = this._getCursorBoundariesOffsets(\n chars, typeOfBoundaries);\n\n return {\n left: left,\n top: top,\n leftOffset: offsets.left + offsets.lineLeft,\n topOffset: offsets.top\n };\n },\n\n /**\n * @private\n */\n _getCursorBoundariesOffsets: function(chars, typeOfBoundaries) {\n\n var lineLeftOffset = 0,\n\n lineIndex = 0,\n charIndex = 0,\n topOffset = 0,\n leftOffset = 0;\n\n for (var i = 0; i < this.selectionStart; i++) {\n if (chars[i] === '\\n') {\n leftOffset = 0;\n topOffset += this._getHeightOfLine(this.ctx, lineIndex);\n\n lineIndex++;\n charIndex = 0;\n }\n else {\n leftOffset += this._getWidthOfChar(this.ctx, chars[i], lineIndex, charIndex);\n charIndex++;\n }\n\n lineLeftOffset = this._getCachedLineOffset(lineIndex);\n }\n if (typeOfBoundaries === 'cursor') {\n topOffset += (1 - this._fontSizeFraction) * this._getHeightOfLine(this.ctx, lineIndex) / this.lineHeight\n - this.getCurrentCharFontSize(lineIndex, charIndex) * (1 - this._fontSizeFraction);\n }\n\n return {\n top: topOffset,\n left: leftOffset,\n lineLeft: lineLeftOffset\n };\n },\n\n /**\n * @private\n */\n _getCachedLineOffset: function(lineIndex) {\n var widthOfLine = this._getLineWidth(this.ctx, lineIndex);\n\n return this.__lineOffsets[lineIndex] ||\n (this.__lineOffsets[lineIndex] = this._getLineLeftOffset(widthOfLine));\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\n var cursorLocation = this.get2DCursorLocation(),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex,\n charHeight = this.getCurrentCharFontSize(lineIndex, charIndex),\n leftOffset = (lineIndex === 0 && charIndex === 0)\n ? this._getCachedLineOffset(lineIndex)\n : boundaries.leftOffset;\n\n ctx.fillStyle = this.getCurrentCharColor(lineIndex, charIndex);\n ctx.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity;\n\n ctx.fillRect(\n boundaries.left + leftOffset,\n boundaries.top + boundaries.topOffset,\n this.cursorWidth / this.scaleX,\n charHeight);\n\n },\n\n /**\n * Renders text selection\n * @param {Array} chars Array of characters\n * @param {Object} boundaries Object with left/top/leftOffset/topOffset\n * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n */\n renderSelection: function(chars, boundaries, ctx) {\n\n ctx.fillStyle = this.selectionColor;\n\n var start = this.get2DCursorLocation(this.selectionStart),\n end = this.get2DCursorLocation(this.selectionEnd),\n startLine = start.lineIndex,\n endLine = end.lineIndex;\n\n for (var i = startLine; i <= endLine; i++) {\n var lineOffset = this._getCachedLineOffset(i) || 0,\n lineHeight = this._getHeightOfLine(this.ctx, i),\n boxWidth = 0, line = this._textLines[i];\n\n if (i === startLine) {\n for (var j = 0, len = line.length; j < len; j++) {\n if (j >= start.charIndex && (i !== endLine || j < end.charIndex)) {\n boxWidth += this._getWidthOfChar(ctx, line[j], i, j);\n }\n if (j < start.charIndex) {\n lineOffset += this._getWidthOfChar(ctx, line[j], i, j);\n }\n }\n }\n else if (i > startLine && i < endLine) {\n boxWidth += this._getLineWidth(ctx, i) || 5;\n }\n else if (i === endLine) {\n for (var j2 = 0, j2len = end.charIndex; j2 < j2len; j2++) {\n boxWidth += this._getWidthOfChar(ctx, line[j2], i, j2);\n }\n }\n\n ctx.fillRect(\n boundaries.left + lineOffset,\n boundaries.top + boundaries.topOffset,\n boxWidth,\n lineHeight);\n\n boundaries.topOffset += lineHeight;\n }\n },\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderChars: function(method, ctx, line, left, top, lineIndex) {\n\n if (this.isEmptyStyles()) {\n return this._renderCharsFast(method, ctx, line, left, top);\n }\n\n this.skipTextAlign = true;\n\n // set proper box offset\n left -= this.textAlign === 'center'\n ? (this.width / 2)\n : (this.textAlign === 'right')\n ? this.width\n : 0;\n\n // set proper line offset\n var lineHeight = this._getHeightOfLine(ctx, lineIndex),\n lineLeftOffset = this._getCachedLineOffset(lineIndex),\n prevStyle,\n charsToRender = '';\n\n left += lineLeftOffset || 0;\n\n ctx.save();\n top -= lineHeight / this.lineHeight * this._fontSizeFraction;\n for (var i = 0, len = line.length; i <= len; i++) {\n prevStyle = prevStyle || this.getCurrentCharStyle(lineIndex, i);\n var thisStyle = this.getCurrentCharStyle(lineIndex, i + 1);\n\n if (this._hasStyleChanged(prevStyle, thisStyle) || i === len) {\n this._renderChar(method, ctx, lineIndex, i - 1, charsToRender, left, top, lineHeight);\n charsToRender = '';\n prevStyle = thisStyle;\n }\n charsToRender += line[i];\n }\n\n ctx.restore();\n },\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} line Content of the line\n * @param {Number} left Left coordinate\n * @param {Number} top Top coordinate\n */\n _renderCharsFast: function(method, ctx, line, left, top) {\n this.skipTextAlign = false;\n\n if (method === 'fillText' && this.fill) {\n this.callSuper('_renderChars', method, ctx, line, left, top);\n }\n if (method === 'strokeText' && ((this.stroke && this.strokeWidth > 0) || this.skipFillStrokeCheck)) {\n this.callSuper('_renderChars', method, ctx, line, left, top);\n }\n },\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex\n * @param {Number} i\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, i, _char, left, top, lineHeight) {\n var charWidth, charHeight,\n decl = this._getStyleDeclaration(lineIndex, i),\n offset = this._fontSizeFraction * lineHeight / this.lineHeight;\n\n if (decl) {\n var shouldStroke = decl.stroke || this.stroke,\n shouldFill = decl.fill || this.fill;\n\n ctx.save();\n charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i, decl);\n charHeight = this._getHeightOfChar(ctx, _char, lineIndex, i);\n\n if (shouldFill) {\n ctx.fillText(_char, left, top);\n }\n if (shouldStroke) {\n ctx.strokeText(_char, left, top);\n }\n\n this._renderCharDecoration(ctx, decl, left, top, offset, charWidth, charHeight);\n ctx.restore();\n\n ctx.translate(charWidth, 0);\n }\n else {\n if (method === 'strokeText' && this.stroke) {\n ctx[method](_char, left, top);\n }\n if (method === 'fillText' && this.fill) {\n ctx[method](_char, left, top);\n }\n charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i);\n this._renderCharDecoration(ctx, null, left, top, offset, charWidth, this.fontSize);\n\n ctx.translate(ctx.measureText(_char).width, 0);\n }\n },\n\n /**\n * @private\n * @param {Object} prevStyle\n * @param {Object} thisStyle\n */\n _hasStyleChanged: function(prevStyle, thisStyle) {\n return (prevStyle.fill !== thisStyle.fill ||\n prevStyle.fontSize !== thisStyle.fontSize ||\n prevStyle.textBackgroundColor !== thisStyle.textBackgroundColor ||\n prevStyle.textDecoration !== thisStyle.textDecoration ||\n prevStyle.fontFamily !== thisStyle.fontFamily ||\n prevStyle.fontWeight !== thisStyle.fontWeight ||\n prevStyle.fontStyle !== thisStyle.fontStyle ||\n prevStyle.stroke !== thisStyle.stroke ||\n prevStyle.strokeWidth !== thisStyle.strokeWidth\n );\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderCharDecoration: function(ctx, styleDeclaration, left, top, offset, charWidth, charHeight) {\n\n var textDecoration = styleDeclaration\n ? (styleDeclaration.textDecoration || this.textDecoration)\n : this.textDecoration;\n\n if (!textDecoration) {\n return;\n }\n\n if (textDecoration.indexOf('underline') > -1) {\n ctx.fillRect(\n left,\n top + charHeight / 10,\n charWidth ,\n charHeight / 15\n );\n }\n if (textDecoration.indexOf('line-through') > -1) {\n ctx.fillRect(\n left,\n top - charHeight * (this._fontSizeFraction + this._fontSizeMult - 1) + charHeight / 15,\n charWidth,\n charHeight / 15\n );\n }\n if (textDecoration.indexOf('overline') > -1) {\n ctx.fillRect(\n left,\n top - (this._fontSizeMult - this._fontSizeFraction) * charHeight,\n charWidth,\n charHeight / 15\n );\n }\n },\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} line\n */\n _renderTextLine: function(method, ctx, line, left, top, lineIndex) {\n // to \"cancel\" this.fontSize subtraction in fabric.Text#_renderTextLine\n // the adding 0.03 is just to align text with itext by overlap test\n if (!this.isEmptyStyles()) {\n top += this.fontSize * (this._fontSizeFraction + 0.03);\n }\n this.callSuper('_renderTextLine', method, ctx, line, left, top, lineIndex);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextDecoration: function(ctx) {\n if (this.isEmptyStyles()) {\n return this.callSuper('_renderTextDecoration', ctx);\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextLinesBackground: function(ctx) {\n if (!this.textBackgroundColor && !this.styles) {\n return;\n }\n\n ctx.save();\n\n if (this.textBackgroundColor) {\n ctx.fillStyle = this.textBackgroundColor;\n }\n\n var lineHeights = 0;\n\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n\n var heightOfLine = this._getHeightOfLine(ctx, i);\n if (this._textLines[i] === '') {\n lineHeights += heightOfLine;\n continue;\n }\n\n var lineWidth = this._getLineWidth(ctx, i),\n lineLeftOffset = this._getCachedLineOffset(i);\n\n if (this.textBackgroundColor) {\n ctx.fillStyle = this.textBackgroundColor;\n\n ctx.fillRect(\n this._getLeftOffset() + lineLeftOffset,\n this._getTopOffset() + lineHeights,\n lineWidth,\n heightOfLine / this.lineHeight\n );\n }\n if (this._getLineStyle(i)) {\n for (var j = 0, jlen = this._textLines[i].length; j < jlen; j++) {\n var style = this._getStyleDeclaration(i, j);\n if (style && style.textBackgroundColor) {\n\n var _char = this._textLines[i][j];\n\n ctx.fillStyle = style.textBackgroundColor;\n\n ctx.fillRect(\n this._getLeftOffset() + lineLeftOffset + this._getWidthOfCharsAt(ctx, i, j),\n this._getTopOffset() + lineHeights,\n this._getWidthOfChar(ctx, _char, i, j) + 1,\n heightOfLine / this.lineHeight\n );\n }\n }\n }\n lineHeights += heightOfLine;\n }\n ctx.restore();\n },\n\n /**\n * @private\n */\n _getCacheProp: function(_char, styleDeclaration) {\n return _char +\n styleDeclaration.fontFamily +\n styleDeclaration.fontSize +\n styleDeclaration.fontWeight +\n styleDeclaration.fontStyle +\n styleDeclaration.shadow;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} _char\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} [decl]\n */\n _applyCharStylesGetWidth: function(ctx, _char, lineIndex, charIndex, decl) {\n var styleDeclaration = decl || this._getStyleDeclaration(lineIndex, charIndex);\n\n if (styleDeclaration) {\n // cloning so that original style object is not polluted with following font declarations\n styleDeclaration = clone(styleDeclaration);\n }\n else {\n styleDeclaration = { };\n }\n\n this._applyFontStyles(styleDeclaration);\n\n var cacheProp = this._getCacheProp(_char, styleDeclaration);\n\n // short-circuit if no styles\n if (this.isEmptyStyles() && this._charWidthsCache[cacheProp] && this.caching) {\n return this._charWidthsCache[cacheProp];\n }\n\n if (typeof styleDeclaration.shadow === 'string') {\n styleDeclaration.shadow = new fabric.Shadow(styleDeclaration.shadow);\n }\n\n var fill = styleDeclaration.fill || this.fill;\n ctx.fillStyle = fill.toLive\n ? fill.toLive(ctx, this)\n : fill;\n\n if (styleDeclaration.stroke) {\n ctx.strokeStyle = (styleDeclaration.stroke && styleDeclaration.stroke.toLive)\n ? styleDeclaration.stroke.toLive(ctx, this)\n : styleDeclaration.stroke;\n }\n\n ctx.lineWidth = styleDeclaration.strokeWidth || this.strokeWidth;\n ctx.font = this._getFontDeclaration.call(styleDeclaration);\n this._setShadow.call(styleDeclaration, ctx);\n\n if (!this.caching) {\n return ctx.measureText(_char).width;\n }\n\n if (!this._charWidthsCache[cacheProp]) {\n this._charWidthsCache[cacheProp] = ctx.measureText(_char).width;\n }\n\n return this._charWidthsCache[cacheProp];\n },\n\n /**\n * @private\n * @param {Object} styleDeclaration\n */\n _applyFontStyles: function(styleDeclaration) {\n if (!styleDeclaration.fontFamily) {\n styleDeclaration.fontFamily = this.fontFamily;\n }\n if (!styleDeclaration.fontSize) {\n styleDeclaration.fontSize = this.fontSize;\n }\n if (!styleDeclaration.fontWeight) {\n styleDeclaration.fontWeight = this.fontWeight;\n }\n if (!styleDeclaration.fontStyle) {\n styleDeclaration.fontStyle = this.fontStyle;\n }\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Boolean} [returnCloneOrEmpty=false]\n * @private\n */\n _getStyleDeclaration: function(lineIndex, charIndex, returnCloneOrEmpty) {\n if (returnCloneOrEmpty) {\n return (this.styles[lineIndex] && this.styles[lineIndex][charIndex])\n ? clone(this.styles[lineIndex][charIndex])\n : { };\n }\n\n return this.styles[lineIndex] && this.styles[lineIndex][charIndex] ? this.styles[lineIndex][charIndex] : null;\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 * @private\n */\n _getLineStyle: function(lineIndex) {\n return this.styles[lineIndex];\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n _setLineStyle: function(lineIndex, style) {\n this.styles[lineIndex] = style;\n },\n\n /**\n * @param {Number} lineIndex\n * @private\n */\n _deleteLineStyle: function(lineIndex) {\n delete this.styles[lineIndex];\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _getWidthOfChar: function(ctx, _char, lineIndex, charIndex) {\n if (this.textAlign === 'justify' && this._reSpacesAndTabs.test(_char)) {\n return this._getWidthOfSpace(ctx, lineIndex);\n }\n\n var styleDeclaration = this._getStyleDeclaration(lineIndex, charIndex, true);\n this._applyFontStyles(styleDeclaration);\n var cacheProp = this._getCacheProp(_char, styleDeclaration);\n\n if (this._charWidthsCache[cacheProp] && this.caching) {\n return this._charWidthsCache[cacheProp];\n }\n else if (ctx) {\n ctx.save();\n var width = this._applyCharStylesGetWidth(ctx, _char, lineIndex, charIndex);\n ctx.restore();\n return width;\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _getHeightOfChar: function(ctx, _char, lineIndex, charIndex) {\n var style = this._getStyleDeclaration(lineIndex, charIndex);\n return style && style.fontSize ? style.fontSize : this.fontSize;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _getHeightOfCharAt: function(ctx, lineIndex, charIndex) {\n var _char = this._textLines[lineIndex][charIndex];\n return this._getHeightOfChar(ctx, _char, lineIndex, charIndex);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _getWidthOfCharsAt: function(ctx, lineIndex, charIndex) {\n var width = 0, i, _char;\n for (i = 0; i < charIndex; i++) {\n _char = this._textLines[lineIndex][i];\n width += this._getWidthOfChar(ctx, _char, lineIndex, i);\n }\n return width;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _getLineWidth: function(ctx, lineIndex) {\n if (this.__lineWidths[lineIndex]) {\n return this.__lineWidths[lineIndex];\n }\n this.__lineWidths[lineIndex] = this._getWidthOfCharsAt(ctx, lineIndex, this._textLines[lineIndex].length);\n return this.__lineWidths[lineIndex];\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex\n */\n _getWidthOfSpace: function (ctx, lineIndex) {\n if (this.__widthOfSpace[lineIndex]) {\n return this.__widthOfSpace[lineIndex];\n }\n var line = this._textLines[lineIndex],\n wordsWidth = this._getWidthOfWords(ctx, line, lineIndex),\n widthDiff = this.width - wordsWidth,\n numSpaces = line.length - line.replace(this._reSpacesAndTabs, '').length,\n width = widthDiff / numSpaces;\n this.__widthOfSpace[lineIndex] = width;\n return width;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} line\n * @param {Number} lineIndex\n */\n _getWidthOfWords: function (ctx, line, lineIndex) {\n var width = 0;\n\n for (var charIndex = 0; charIndex < line.length; charIndex++) {\n var _char = line[charIndex];\n\n if (!_char.match(/\\s/)) {\n width += this._getWidthOfChar(ctx, _char, lineIndex, charIndex);\n }\n }\n\n return width;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _getHeightOfLine: function(ctx, lineIndex) {\n if (this.__lineHeights[lineIndex]) {\n return this.__lineHeights[lineIndex];\n }\n\n var line = this._textLines[lineIndex],\n maxHeight = this._getHeightOfChar(ctx, line[0], lineIndex, 0);\n\n for (var i = 1, len = line.length; i < len; i++) {\n var currentCharHeight = this._getHeightOfChar(ctx, line[i], lineIndex, i);\n if (currentCharHeight > maxHeight) {\n maxHeight = currentCharHeight;\n }\n }\n this.__maxFontHeights[lineIndex] = maxHeight;\n this.__lineHeights[lineIndex] = maxHeight * this.lineHeight * this._fontSizeMult;\n return this.__lineHeights[lineIndex];\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _getTextHeight: function(ctx) {\n var height = 0;\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n height += this._getHeightOfLine(ctx, i);\n }\n return height;\n },\n\n /**\n * This method is overwritten to account for different top offset\n * @private\n */\n _renderTextBoxBackground: function(ctx) {\n if (!this.backgroundColor) {\n return;\n }\n\n ctx.save();\n ctx.fillStyle = this.backgroundColor;\n\n ctx.fillRect(\n this._getLeftOffset(),\n this._getTopOffset(),\n this.width,\n this.height\n );\n\n ctx.restore();\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 fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), {\n styles: clone(this.styles)\n });\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 * @return {fabric.IText} instance of fabric.IText\n */\n fabric.IText.fromObject = function(object) {\n return new fabric.IText(object.text, clone(object));\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 },\n\n /**\n * Initializes \"selected\" event handler\n */\n initSelectedHandler: function() {\n this.on('selected', function() {\n\n var _this = this;\n setTimeout(function() {\n _this.selected = true;\n }, 100);\n });\n },\n\n /**\n * Initializes \"added\" event handler\n */\n initAddedHandler: function() {\n var _this = this;\n this.on('added', function() {\n if (this.canvas && !this.canvas._hasITextHandlers) {\n this.canvas._hasITextHandlers = true;\n this._initCanvasHandlers();\n }\n\n // Track IText instances per-canvas. Only register in this array once added\n // to a canvas; we don't want to leak a reference to the instance forever\n // simply because it existed at some point.\n // (Might be added to a collection, but not on a canvas.)\n if (_this.canvas) {\n _this.canvas._iTextInstances = _this.canvas._iTextInstances || [];\n _this.canvas._iTextInstances.push(_this);\n }\n });\n },\n\n initRemovedHandler: function() {\n var _this = this;\n this.on('removed', function() {\n // (Might be removed from a collection, but not on a canvas.)\n if (_this.canvas) {\n _this.canvas._iTextInstances = _this.canvas._iTextInstances || [];\n fabric.util.removeFromArray(_this.canvas._iTextInstances, _this);\n }\n });\n },\n\n /**\n * @private\n */\n _initCanvasHandlers: function() {\n var _this = this;\n\n this.canvas.on('selection:cleared', function() {\n fabric.IText.prototype.exitEditingOnOthers(_this.canvas);\n });\n\n this.canvas.on('mouse:up', function() {\n if (_this.canvas._iTextInstances) {\n _this.canvas._iTextInstances.forEach(function(obj) {\n obj.__isMousedown = false;\n });\n }\n });\n\n this.canvas.on('object:selected', function() {\n fabric.IText.prototype.exitEditingOnOthers(_this.canvas);\n });\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 if (obj.canvas) {\n obj.canvas.clearContext(obj.canvas.contextTop || obj.ctx);\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._currentTickState && this._currentTickState.abort();\n this._currentTickCompleteState && this._currentTickCompleteState.abort();\n clearTimeout(this._cursorTimeout1);\n this._currentCursorOpacity = 1;\n if (this.canvas) {\n this.canvas.clearContext(this.canvas.contextTop || this.ctx);\n this.renderCursorOrSelection();\n }\n if (this._cursorTimeout2) {\n clearTimeout(this._cursorTimeout2);\n }\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 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 this.canvas && this.canvas.clearContext(this.canvas.contextTop || this.ctx);\n },\n\n /**\n * Selects entire text\n */\n selectAll: function() {\n this.setSelectionStart(0);\n this.setSelectionEnd(this.text.length);\n },\n\n /**\n * Returns selected text\n * @return {String}\n */\n getSelectedText: function() {\n return this.text.slice(this.selectionStart, this.selectionEnd);\n },\n\n /**\n * Find new selection index representing start of current word according to current selection index\n * @param {Number} startFrom Surrent 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.charAt(index))) {\n while (this._reSpace.test(this.text.charAt(index))) {\n offset++;\n index--;\n }\n }\n while (/\\S/.test(this.text.charAt(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.charAt(index))) {\n while (this._reSpace.test(this.text.charAt(index))) {\n offset++;\n index++;\n }\n }\n while (/\\S/.test(this.text.charAt(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.charAt(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.charAt(index)) && index < this.text.length) {\n offset++;\n index++;\n }\n\n return startFrom + offset;\n },\n\n /**\n * Returns number of newlines in selected text\n * @return {Number} Number of newlines in selected text\n */\n getNumNewLinesInSelectedText: function() {\n var selectedText = this.getSelectedText(),\n numNewLines = 0;\n\n for (var i = 0, len = selectedText.length; i < len; i++) {\n if (selectedText[i] === '\\n') {\n numNewLines++;\n }\n }\n return numNewLines;\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 index = this._reSpace.test(this.text.charAt(selectionStart)) ? selectionStart - 1 : selectionStart,\n _char = this.text.charAt(index),\n reNonWord = /[ \\n\\.,;!\\?\\-]/;\n\n while (!reNonWord.test(_char) && index > 0 && index < this.text.length) {\n index += direction;\n _char = this.text.charAt(index);\n }\n if (reNonWord.test(_char) && _char !== '\\n') {\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 var newSelectionStart = this.searchWordBoundary(selectionStart, -1), /* search backwards */\n newSelectionEnd = this.searchWordBoundary(selectionStart, 1);\n /* search forward */\n\n this.setSelectionStart(newSelectionStart);\n this.setSelectionEnd(newSelectionEnd);\n },\n\n /**\n * Selects a line based on the index\n * @param {Number} selectionStart Index of a character\n */\n selectLine: function(selectionStart) {\n var newSelectionStart = this.findLineBoundaryLeft(selectionStart),\n newSelectionEnd = this.findLineBoundaryRight(selectionStart);\n\n this.setSelectionStart(newSelectionStart);\n this.setSelectionEnd(newSelectionEnd);\n },\n\n /**\n * Enters editing state\n * @return {fabric.IText} thisArg\n * @chainable\n */\n enterEditing: function() {\n if (this.isEditing || !this.editable) {\n return;\n }\n\n if (this.canvas) {\n this.exitEditingOnOthers(this.canvas);\n }\n\n this.isEditing = true;\n\n this.initHiddenTextarea();\n this.hiddenTextarea.focus();\n this._updateTextarea();\n this._saveEditingProps();\n this._setEditingProps();\n\n this._tick();\n this.fire('editing:entered');\n\n if (!this.canvas) {\n return this;\n }\n\n this.canvas.renderAll();\n this.canvas.fire('text:editing:entered', { target: this });\n this.initMouseMoveHandler();\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 var _this = this;\n this.canvas.on('mouse:move', function(options) {\n if (!_this.__isMousedown || !_this.isEditing) {\n return;\n }\n\n var newSelectionStart = _this.getSelectionStartFromPointer(options.e);\n if (newSelectionStart >= _this.__selectionStartOnMouseDown) {\n _this.setSelectionStart(_this.__selectionStartOnMouseDown);\n _this.setSelectionEnd(newSelectionStart);\n }\n else {\n _this.setSelectionStart(newSelectionStart);\n _this.setSelectionEnd(_this.__selectionStartOnMouseDown);\n }\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\n this.hasControls = this.selectable = false;\n this.lockMovementX = this.lockMovementY = true;\n },\n\n /**\n * @private\n */\n _updateTextarea: function() {\n if (!this.hiddenTextarea) {\n return;\n }\n\n this.hiddenTextarea.value = this.text;\n this.hiddenTextarea.selectionStart = this.selectionStart;\n this.hiddenTextarea.selectionEnd = this.selectionEnd;\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 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.overCursor;\n this.hasControls = this._savedProps.hasControls;\n this.borderColor = this._savedProps.borderColor;\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\n this.selected = false;\n this.isEditing = false;\n this.selectable = true;\n\n this.selectionEnd = this.selectionStart;\n this.hiddenTextarea && this.canvas && this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea);\n this.hiddenTextarea = null;\n\n this.abortCursorAnimation();\n this._restoreEditingProps();\n this._currentCursorOpacity = 0;\n\n this.fire('editing:exited');\n this.canvas && this.canvas.fire('text:editing:exited', { 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 * @private\n */\n _removeCharsFromTo: function(start, end) {\n while (end !== start) {\n this._removeSingleCharAndStyle(start + 1);\n end--;\n }\n this.setSelectionStart(start);\n },\n\n _removeSingleCharAndStyle: function(index) {\n var isBeginningOfLine = this.text[index - 1] === '\\n',\n indexStyle = isBeginningOfLine ? index : index - 1;\n this.removeStyleObject(isBeginningOfLine, indexStyle);\n this.text = this.text.slice(0, index - 1) +\n this.text.slice(index);\n\n this._textLines = this._splitTextIntoLines();\n },\n\n /**\n * Inserts characters where cursor is (replacing selection if one exists)\n * @param {String} _chars Characters to insert\n * @param {Boolean} useCopiedStyle use fabric.copiedTextStyle\n */\n insertChars: function(_chars, useCopiedStyle) {\n var style;\n\n if (this.selectionEnd - this.selectionStart > 1) {\n this._removeCharsFromTo(this.selectionStart, this.selectionEnd);\n this.setSelectionEnd(this.selectionStart);\n }\n\n for (var i = 0, len = _chars.length; i < len; i++) {\n if (useCopiedStyle) {\n style = fabric.copiedTextStyle[i];\n }\n this.insertChar(_chars[i], i < len - 1, style);\n }\n },\n\n /**\n * Inserts a character where cursor is\n * @param {String} _char Characters to insert\n * @param {Boolean} skipUpdate trigger rendering and updates at the end of text insert\n * @param {Object} styleObject Style to be inserted for the new char\n */\n insertChar: function(_char, skipUpdate, styleObject) {\n var isEndOfLine = this.text[this.selectionStart] === '\\n';\n this.text = this.text.slice(0, this.selectionStart) +\n _char + this.text.slice(this.selectionEnd);\n this._textLines = this._splitTextIntoLines();\n this.insertStyleObjects(_char, isEndOfLine, styleObject);\n this.setSelectionStart(this.selectionStart + 1);\n this.setSelectionEnd(this.selectionStart);\n if (skipUpdate) {\n return;\n }\n this.canvas && this.canvas.renderAll();\n this.setCoords();\n this.fire('changed');\n this.canvas && this.canvas.fire('text:changed', { target: this });\n },\n\n /**\n * Inserts new style object\n * @param {Number} lineIndex Index of a line\n * @param {Number} charIndex Index of a char\n * @param {Boolean} isEndOfLine True if it's end of line\n */\n insertNewlineStyleObject: function(lineIndex, charIndex, isEndOfLine) {\n\n this.shiftLineStyles(lineIndex, +1);\n\n if (!this.styles[lineIndex + 1]) {\n this.styles[lineIndex + 1] = {};\n }\n\n var currentCharStyle = {},\n newLineStyles = {};\n\n if (this.styles[lineIndex] && this.styles[lineIndex][charIndex - 1]) {\n currentCharStyle = this.styles[lineIndex][charIndex - 1];\n }\n\n // if there's nothing after cursor,\n // we clone current char style onto the next (otherwise empty) line\n if (isEndOfLine) {\n newLineStyles[0] = clone(currentCharStyle);\n this.styles[lineIndex + 1] = newLineStyles;\n }\n // otherwise we clone styles of all chars\n // after cursor onto the next line, from the beginning\n else {\n for (var index in this.styles[lineIndex]) {\n if (parseInt(index, 10) >= charIndex) {\n newLineStyles[parseInt(index, 10) - charIndex] = this.styles[lineIndex][index];\n // remove lines from the previous line since they're on a new line now\n delete this.styles[lineIndex][index];\n }\n }\n this.styles[lineIndex + 1] = newLineStyles;\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 {Object} [style] Style object to insert, if given\n */\n insertCharStyleObject: function(lineIndex, charIndex, style) {\n\n var currentLineStyles = this.styles[lineIndex],\n currentLineStylesCloned = clone(currentLineStyles);\n\n if (charIndex === 0 && !style) {\n charIndex = 1;\n }\n\n // shift all char styles by 1 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\n if (numericIndex >= charIndex) {\n currentLineStyles[numericIndex + 1] = currentLineStylesCloned[numericIndex];\n\n // only delete the style if there was nothing moved there\n if (!currentLineStylesCloned[numericIndex - 1]) {\n delete currentLineStyles[numericIndex];\n }\n }\n }\n\n this.styles[lineIndex][charIndex] =\n style || clone(currentLineStyles[charIndex - 1]);\n this._forceClearCache = true;\n },\n\n /**\n * Inserts style object(s)\n * @param {String} _chars Characters at the location where style is inserted\n * @param {Boolean} isEndOfLine True if it's end of line\n * @param {Object} [styleObject] Style to insert\n */\n insertStyleObjects: function(_chars, isEndOfLine, styleObject) {\n // removed shortcircuit over isEmptyStyles\n\n var cursorLocation = this.get2DCursorLocation(),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex;\n\n if (!this._getLineStyle(lineIndex)) {\n this._setLineStyle(lineIndex, {});\n }\n\n if (_chars === '\\n') {\n this.insertNewlineStyleObject(lineIndex, charIndex, isEndOfLine);\n }\n else {\n this.insertCharStyleObject(lineIndex, charIndex, styleObject);\n }\n },\n\n /**\n * Shifts line styles up or down\n * @param {Number} lineIndex Index of a line\n * @param {Number} offset Can be -1 or +1\n */\n shiftLineStyles: function(lineIndex, offset) {\n // shift all line styles by 1 upward\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 //TODO: evaluate if delete old style lines with offset -1\n },\n\n /**\n * Removes style object\n * @param {Boolean} isBeginningOfLine True if cursor is at the beginning of line\n * @param {Number} [index] Optional index. When not given, current selectionStart is used.\n */\n removeStyleObject: function(isBeginningOfLine, index) {\n\n var cursorLocation = this.get2DCursorLocation(index),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex;\n\n if (isBeginningOfLine) {\n\n var textOnPreviousLine = this._textLines[lineIndex - 1],\n newCharIndexOnPrevLine = textOnPreviousLine\n ? textOnPreviousLine.length\n : 0;\n\n if (!this.styles[lineIndex - 1]) {\n this.styles[lineIndex - 1] = {};\n }\n\n for (charIndex in this.styles[lineIndex]) {\n this.styles[lineIndex - 1][parseInt(charIndex, 10) + newCharIndexOnPrevLine]\n = this.styles[lineIndex][charIndex];\n }\n\n this.shiftLineStyles(lineIndex, -1);\n\n }\n else {\n var currentLineStyles = this.styles[lineIndex];\n\n if (currentLineStyles) {\n delete currentLineStyles[charIndex];\n //console.log('deleting', lineIndex, charIndex + offset);\n }\n\n var currentLineStylesCloned = clone(currentLineStyles);\n\n // shift all styles by 1 backwards\n for (var i in currentLineStylesCloned) {\n var numericIndex = parseInt(i, 10);\n if (numericIndex >= charIndex && numericIndex !== 0) {\n currentLineStyles[numericIndex - 1] = currentLineStylesCloned[numericIndex];\n delete currentLineStyles[numericIndex];\n }\n }\n }\n },\n\n /**\n * Inserts new line\n */\n insertNewline: function() {\n this.insertChars('\\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.bind(this));\n },\n\n onMouseDown: function(options) {\n\n this.__newClickTime = +new Date();\n var newPointer = this.canvas.getPointer(options.e);\n\n if (this.isTripleClick(newPointer)) {\n this.fire('tripleclick', options);\n this._stopEvent(options.e);\n }\n else if (this.isDoubleClick(newPointer)) {\n this.fire('dblclick', options);\n this._stopEvent(options.e);\n }\n\n this.__lastLastClickTime = this.__lastClickTime;\n this.__lastClickTime = this.__newClickTime;\n this.__lastPointer = newPointer;\n this.__lastIsEditing = this.isEditing;\n this.__lastSelected = this.selected;\n },\n\n isDoubleClick: function(newPointer) {\n return this.__newClickTime - this.__lastClickTime < 500 &&\n this.__lastPointer.x === newPointer.x &&\n this.__lastPointer.y === newPointer.y && this.__lastIsEditing;\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.initSelectedHandler();\n this.initMousedownHandler();\n this.initMouseupHandler();\n this.initClicks();\n },\n\n /**\n * Initializes double and triple click event handlers\n */\n initClicks: function() {\n this.on('dblclick', function(options) {\n this.selectWord(this.getSelectionStartFromPointer(options.e));\n });\n this.on('tripleclick', function(options) {\n this.selectLine(this.getSelectionStartFromPointer(options.e));\n });\n },\n\n /**\n * Initializes \"mousedown\" event handler\n */\n initMousedownHandler: function() {\n this.on('mousedown', function(options) {\n\n var pointer = this.canvas.getPointer(options.e);\n\n this.__mousedownX = pointer.x;\n this.__mousedownY = pointer.y;\n this.__isMousedown = true;\n\n if (this.hiddenTextarea && this.canvas) {\n this.canvas.wrapperEl.appendChild(this.hiddenTextarea);\n }\n\n if (this.selected) {\n this.setCursorByClick(options.e);\n }\n\n if (this.isEditing) {\n this.__selectionStartOnMouseDown = this.selectionStart;\n this.initDelayedCursor(true);\n }\n });\n },\n\n /**\n * @private\n */\n _isObjectMoved: function(e) {\n var pointer = this.canvas.getPointer(e);\n\n return this.__mousedownX !== pointer.x ||\n this.__mousedownY !== pointer.y;\n },\n\n /**\n * Initializes \"mouseup\" event handler\n */\n initMouseupHandler: function() {\n this.on('mouseup', function(options) {\n this.__isMousedown = false;\n if (this._isObjectMoved(options.e)) {\n return;\n }\n\n if (this.__lastSelected) {\n this.enterEditing();\n this.initDelayedCursor(true);\n }\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 newSelectionStart = this.getSelectionStartFromPointer(e);\n\n if (e.shiftKey) {\n if (newSelectionStart < this.selectionStart) {\n this.setSelectionEnd(this.selectionStart);\n this.setSelectionStart(newSelectionStart);\n }\n else {\n this.setSelectionEnd(newSelectionStart);\n }\n }\n else {\n this.setSelectionStart(newSelectionStart);\n this.setSelectionEnd(newSelectionStart);\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 newSelectionStart,\n line;\n\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n line = this._textLines[i];\n height += this._getHeightOfLine(this.ctx, i) * this.scaleY;\n\n var widthOfLine = this._getLineWidth(this.ctx, i),\n lineLeftOffset = this._getLineLeftOffset(widthOfLine);\n\n width = lineLeftOffset * this.scaleX;\n\n if (this.flipX) {\n // when oject is horizontally flipped we reverse chars\n // we should reverse also style or do not revers at all.\n this._textLines[i] = line.reverse().join('');\n }\n\n for (var j = 0, jlen = line.length; j < jlen; j++) {\n\n prevWidth = width;\n\n width += this._getWidthOfChar(this.ctx, line[j], i, this.flipX ? jlen - j : j) *\n this.scaleX;\n\n if (height <= mouseOffset.y || width <= mouseOffset.x) {\n charIndex++;\n continue;\n }\n\n return this._getNewSelectionStartFromOffset(\n mouseOffset, prevWidth, width, charIndex + i, jlen);\n }\n\n if (mouseOffset.y < height) {\n //this happens just on end of lines.\n return this._getNewSelectionStartFromOffset(\n mouseOffset, prevWidth, width, charIndex + i - 1, jlen);\n }\n }\n\n // clicked somewhere after all chars, so set at the end\n if (typeof newSelectionStart === 'undefined') {\n return this.text.length;\n }\n },\n\n /**\n * @private\n */\n _getNewSelectionStartFromOffset: function(mouseOffset, prevWidth, width, index, jlen) {\n\n var distanceBtwLastCharAndCursor = mouseOffset.x - prevWidth,\n distanceBtwNextCharAndCursor = width - mouseOffset.x,\n offset = distanceBtwNextCharAndCursor > distanceBtwLastCharAndCursor ? 0 : 1,\n newSelectionStart = index + offset;\n\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\n this.hiddenTextarea.setAttribute('autocapitalize', 'off');\n this.hiddenTextarea.style.cssText = 'position: fixed; bottom: 20px; left: 0px; opacity: 0;'\n + ' width: 0px; height: 0px; z-index: -999;';\n fabric.document.body.appendChild(this.hiddenTextarea);\n\n fabric.util.addListener(this.hiddenTextarea, 'keydown', this.onKeyDown.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'input', this.onInput.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'copy', this.copy.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'paste', this.paste.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 * @private\n */\n _keysMap: {\n 8: 'removeChars',\n 9: 'exitEditing',\n 27: 'exitEditing',\n 13: 'insertNewline',\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 46: 'forwardDelete'\n },\n\n /**\n * @private\n */\n _ctrlKeysMap: {\n 65: 'selectAll',\n 88: 'cut'\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 keyup event\n * @param {Event} e Event object\n */\n onKeyDown: function(e) {\n if (!this.isEditing) {\n return;\n }\n if (e.keyCode in this._keysMap) {\n this[this._keysMap[e.keyCode]](e);\n }\n else if ((e.keyCode in this._ctrlKeysMap) && (e.ctrlKey || e.metaKey)) {\n this[this._ctrlKeysMap[e.keyCode]](e);\n }\n else {\n return;\n }\n e.stopImmediatePropagation();\n e.preventDefault();\n this.canvas && this.canvas.renderAll();\n },\n\n /**\n * Handles onInput event\n * @param {Event} e Event object\n */\n onInput: function(e) {\n if (!this.isEditing || this._cancelOnInput) {\n this._cancelOnInput = false;\n return;\n }\n var offset = this.selectionStart || 0,\n textLength = this.text.length,\n newTextLength = this.hiddenTextarea.value.length,\n diff = newTextLength - textLength,\n charsToInsert = this.hiddenTextarea.value.slice(offset, offset + diff);\n this.insertChars(charsToInsert);\n e.stopPropagation();\n },\n\n /**\n * Forward delete\n */\n forwardDelete: function(e) {\n if (this.selectionStart === this.selectionEnd) {\n if (this.selectionStart === this.text.length) {\n return;\n }\n this.moveCursorRight(e);\n }\n this.removeChars(e);\n },\n\n /**\n * Copies selected text\n * @param {Event} e Event object\n */\n copy: function(e) {\n var selectedText = this.getSelectedText(),\n clipboardData = this._getClipboardData(e);\n\n // Check for backward compatibility with old browsers\n if (clipboardData) {\n clipboardData.setData('text', selectedText);\n }\n\n fabric.copiedText = selectedText;\n fabric.copiedTextStyle = this.getSelectionStyles(\n this.selectionStart,\n this.selectionEnd);\n },\n\n /**\n * Pastes text\n * @param {Event} e Event object\n */\n paste: function(e) {\n var copiedText = null,\n clipboardData = this._getClipboardData(e),\n useCopiedStyle = true;\n\n // Check for backward compatibility with old browsers\n if (clipboardData) {\n copiedText = clipboardData.getData('text').replace(/\\r/g, '');\n if (!fabric.copiedTextStyle || fabric.copiedText !== copiedText) {\n useCopiedStyle = false;\n }\n }\n else {\n copiedText = fabric.copiedText;\n }\n\n if (copiedText) {\n this.insertChars(copiedText, useCopiedStyle);\n }\n this._cancelOnInput = true;\n },\n\n /**\n * Cuts text\n * @param {Event} e Event object\n */\n cut: function(e) {\n if (this.selectionStart === this.selectionEnd) {\n return;\n }\n\n this.copy();\n this.removeChars(e);\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 * 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 = isRight ? this.selectionEnd : this.selectionStart,\n cursorLocation = this.get2DCursorLocation(selectionProp),\n _char, lineLeftOffset, lineIndex = cursorLocation.lineIndex,\n textOnSameLineBeforeCursor = this._textLines[lineIndex].slice(0, cursorLocation.charIndex),\n textOnSameLineAfterCursor = this._textLines[lineIndex].slice(cursorLocation.charIndex),\n textOnNextLine = this._textLines[lineIndex + 1] || '';\n\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\n // move to the end of a text\n return this.text.length - selectionProp;\n }\n\n var widthOfSameLineBeforeCursor = this._getLineWidth(this.ctx, lineIndex);\n lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor);\n\n var widthOfCharsOnSameLineBeforeCursor = lineLeftOffset;\n\n for (var i = 0, len = textOnSameLineBeforeCursor.length; i < len; i++) {\n _char = textOnSameLineBeforeCursor[i];\n widthOfCharsOnSameLineBeforeCursor += this._getWidthOfChar(this.ctx, _char, lineIndex, i);\n }\n\n var indexOnNextLine = this._getIndexOnNextLine(\n cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor);\n\n return textOnSameLineAfterCursor.length + 1 + indexOnNextLine;\n },\n\n /**\n * @private\n */\n _getIndexOnNextLine: function(cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor) {\n var lineIndex = cursorLocation.lineIndex + 1,\n widthOfNextLine = this._getLineWidth(this.ctx, lineIndex),\n lineLeftOffset = this._getLineLeftOffset(widthOfNextLine),\n widthOfCharsOnNextLine = lineLeftOffset,\n indexOnNextLine = 0,\n foundMatch;\n\n for (var j = 0, jlen = textOnNextLine.length; j < jlen; j++) {\n\n var _char = textOnNextLine[j],\n widthOfChar = this._getWidthOfChar(this.ctx, _char, lineIndex, j);\n\n widthOfCharsOnNextLine += widthOfChar;\n\n if (widthOfCharsOnNextLine > widthOfCharsOnSameLineBeforeCursor) {\n\n foundMatch = true;\n\n var leftEdge = widthOfCharsOnNextLine - widthOfChar,\n rightEdge = widthOfCharsOnNextLine,\n offsetFromLeftEdge = Math.abs(leftEdge - widthOfCharsOnSameLineBeforeCursor),\n offsetFromRightEdge = Math.abs(rightEdge - widthOfCharsOnSameLineBeforeCursor);\n\n indexOnNextLine = offsetFromRightEdge < offsetFromLeftEdge ? j + 1 : j;\n\n break;\n }\n }\n\n // reached end\n if (!foundMatch) {\n indexOnNextLine = textOnNextLine.length;\n }\n\n return indexOnNextLine;\n },\n\n /**\n * Moves cursor down\n * @param {Event} e Event object\n */\n moveCursorDown: function(e) {\n this.abortCursorAnimation();\n this._currentCursorOpacity = 1;\n\n var offset = this.getDownCursorOffset(e, this._selectionDirection === 'right');\n\n if (e.shiftKey) {\n this.moveCursorDownWithShift(offset);\n }\n else {\n this.moveCursorDownWithoutShift(offset);\n }\n\n this.initDelayedCursor();\n },\n\n /**\n * Moves cursor down without keeping selection\n * @param {Number} offset\n */\n moveCursorDownWithoutShift: function(offset) {\n this._selectionDirection = 'right';\n this.setSelectionStart(this.selectionStart + offset);\n this.setSelectionEnd(this.selectionStart);\n },\n\n /**\n * private\n */\n swapSelectionPoints: function() {\n var swapSel = this.selectionEnd;\n this.setSelectionEnd(this.selectionStart);\n this.setSelectionStart(swapSel);\n },\n\n /**\n * Moves cursor down while keeping selection\n * @param {Number} offset\n */\n moveCursorDownWithShift: function(offset) {\n if (this.selectionEnd === this.selectionStart) {\n this._selectionDirection = 'right';\n }\n if (this._selectionDirection === 'right') {\n this.setSelectionEnd(this.selectionEnd + offset);\n }\n else {\n this.setSelectionStart(this.selectionStart + offset);\n }\n if (this.selectionEnd < this.selectionStart && this._selectionDirection === 'left') {\n this.swapSelectionPoints();\n this._selectionDirection = 'right';\n }\n if (this.selectionEnd > this.text.length) {\n this.setSelectionEnd(this.text.length);\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 = isRight ? this.selectionEnd : this.selectionStart,\n cursorLocation = this.get2DCursorLocation(selectionProp),\n lineIndex = cursorLocation.lineIndex;\n // if on first line, up cursor goes to start of line\n if (lineIndex === 0 || e.metaKey || e.keyCode === 33) {\n return selectionProp;\n }\n\n var textOnSameLineBeforeCursor = this._textLines[lineIndex].slice(0, cursorLocation.charIndex),\n textOnPreviousLine = this._textLines[lineIndex - 1] || '',\n _char,\n widthOfSameLineBeforeCursor = this._getLineWidth(this.ctx, cursorLocation.lineIndex),\n lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor),\n widthOfCharsOnSameLineBeforeCursor = lineLeftOffset;\n\n for (var i = 0, len = textOnSameLineBeforeCursor.length; i < len; i++) {\n _char = textOnSameLineBeforeCursor[i];\n widthOfCharsOnSameLineBeforeCursor += this._getWidthOfChar(this.ctx, _char, lineIndex, i);\n }\n\n var indexOnPrevLine = this._getIndexOnPrevLine(\n cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor);\n\n return textOnPreviousLine.length - indexOnPrevLine + textOnSameLineBeforeCursor.length;\n },\n\n /**\n * @private\n */\n _getIndexOnPrevLine: function(cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor) {\n\n var lineIndex = cursorLocation.lineIndex - 1,\n widthOfPreviousLine = this._getLineWidth(this.ctx, lineIndex),\n lineLeftOffset = this._getLineLeftOffset(widthOfPreviousLine),\n widthOfCharsOnPreviousLine = lineLeftOffset,\n indexOnPrevLine = 0,\n foundMatch;\n\n for (var j = 0, jlen = textOnPreviousLine.length; j < jlen; j++) {\n\n var _char = textOnPreviousLine[j],\n widthOfChar = this._getWidthOfChar(this.ctx, _char, lineIndex, j);\n\n widthOfCharsOnPreviousLine += widthOfChar;\n\n if (widthOfCharsOnPreviousLine > widthOfCharsOnSameLineBeforeCursor) {\n\n foundMatch = true;\n\n var leftEdge = widthOfCharsOnPreviousLine - widthOfChar,\n rightEdge = widthOfCharsOnPreviousLine,\n offsetFromLeftEdge = Math.abs(leftEdge - widthOfCharsOnSameLineBeforeCursor),\n offsetFromRightEdge = Math.abs(rightEdge - widthOfCharsOnSameLineBeforeCursor);\n\n indexOnPrevLine = offsetFromRightEdge < offsetFromLeftEdge ? j : (j - 1);\n\n break;\n }\n }\n\n // reached end\n if (!foundMatch) {\n indexOnPrevLine = textOnPreviousLine.length - 1;\n }\n\n return indexOnPrevLine;\n },\n\n /**\n * Moves cursor up\n * @param {Event} e Event object\n */\n moveCursorUp: function(e) {\n\n this.abortCursorAnimation();\n this._currentCursorOpacity = 1;\n\n var offset = this.getUpCursorOffset(e, this._selectionDirection === 'right');\n if (e.shiftKey) {\n this.moveCursorUpWithShift(offset);\n }\n else {\n this.moveCursorUpWithoutShift(offset);\n }\n\n this.initDelayedCursor();\n },\n\n /**\n * Moves cursor up with shift\n * @param {Number} offset\n */\n moveCursorUpWithShift: function(offset) {\n if (this.selectionEnd === this.selectionStart) {\n this._selectionDirection = 'left';\n }\n if (this._selectionDirection === 'right') {\n this.setSelectionEnd(this.selectionEnd - offset);\n }\n else {\n this.setSelectionStart(this.selectionStart - offset);\n }\n if (this.selectionEnd < this.selectionStart && this._selectionDirection === 'right') {\n this.swapSelectionPoints();\n this._selectionDirection = 'left';\n }\n },\n\n /**\n * Moves cursor up without shift\n * @param {Number} offset\n */\n moveCursorUpWithoutShift: function(offset) {\n if (this.selectionStart === this.selectionEnd) {\n this.setSelectionStart(this.selectionStart - offset);\n }\n this.setSelectionEnd(this.selectionStart);\n\n this._selectionDirection = 'left';\n },\n\n /**\n * Moves cursor left\n * @param {Event} e Event object\n */\n moveCursorLeft: function(e) {\n if (this.selectionStart === 0 && this.selectionEnd === 0) {\n return;\n }\n\n this.abortCursorAnimation();\n this._currentCursorOpacity = 1;\n\n if (e.shiftKey) {\n this.moveCursorLeftWithShift(e);\n }\n else {\n this.moveCursorLeftWithoutShift(e);\n }\n\n this.initDelayedCursor();\n },\n\n /**\n * @private\n */\n _move: function(e, prop, direction) {\n var propMethod = (prop === 'selectionStart' ? 'setSelectionStart' : 'setSelectionEnd');\n if (e.altKey) {\n this[propMethod](this['findWordBoundary' + direction](this[prop]));\n }\n else if (e.metaKey || e.keyCode === 35 || e.keyCode === 36 ) {\n this[propMethod](this['findLineBoundary' + direction](this[prop]));\n }\n else {\n this[propMethod](this[prop] + (direction === 'Left' ? -1 : 1));\n }\n },\n\n /**\n * @private\n */\n _moveLeft: function(e, prop) {\n this._move(e, prop, 'Left');\n },\n\n /**\n * @private\n */\n _moveRight: function(e, prop) {\n 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 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) {\n this._moveLeft(e, 'selectionStart');\n }\n this.setSelectionEnd(this.selectionStart);\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 this._moveLeft(e, 'selectionEnd');\n }\n else {\n this._selectionDirection = 'left';\n this._moveLeft(e, 'selectionStart');\n }\n },\n\n /**\n * Moves cursor right\n * @param {Event} e Event object\n */\n moveCursorRight: function(e) {\n if (this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length) {\n return;\n }\n\n this.abortCursorAnimation();\n this._currentCursorOpacity = 1;\n\n if (e.shiftKey) {\n this.moveCursorRightWithShift(e);\n }\n else {\n this.moveCursorRightWithoutShift(e);\n }\n\n this.initDelayedCursor();\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 this._moveRight(e, 'selectionStart');\n }\n else {\n this._selectionDirection = 'right';\n 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 this._selectionDirection = 'right';\n\n if (this.selectionStart === this.selectionEnd) {\n this._moveRight(e, 'selectionStart');\n this.setSelectionEnd(this.selectionStart);\n }\n else {\n this.setSelectionEnd(this.selectionEnd + this.getNumNewLinesInSelectedText());\n this.setSelectionStart(this.selectionEnd);\n }\n },\n\n /**\n * Removes characters selected by selection\n * @param {Event} e Event object\n */\n removeChars: function(e) {\n if (this.selectionStart === this.selectionEnd) {\n this._removeCharsNearCursor(e);\n }\n else {\n this._removeCharsFromTo(this.selectionStart, this.selectionEnd);\n }\n\n this.setSelectionEnd(this.selectionStart);\n\n this._removeExtraneousStyles();\n\n this.canvas && this.canvas.renderAll();\n\n this.setCoords();\n this.fire('changed');\n this.canvas && this.canvas.fire('text:changed', { target: this });\n },\n\n /**\n * @private\n * @param {Event} e Event object\n */\n _removeCharsNearCursor: function(e) {\n if (this.selectionStart === 0) {\n return;\n }\n if (e.metaKey) {\n // remove all till the start of current line\n var leftLineBoundary = this.findLineBoundaryLeft(this.selectionStart);\n\n this._removeCharsFromTo(leftLineBoundary, this.selectionStart);\n this.setSelectionStart(leftLineBoundary);\n }\n else if (e.altKey) {\n // remove all till the start of current word\n var leftWordBoundary = this.findWordBoundaryLeft(this.selectionStart);\n\n this._removeCharsFromTo(leftWordBoundary, this.selectionStart);\n this.setSelectionStart(leftWordBoundary);\n }\n else {\n this._removeSingleCharAndStyle(this.selectionStart);\n this.setSelectionStart(this.selectionStart - 1);\n }\n }\n});\n\n\n/* _TO_SVG_START_ */\n(function() {\n var toFixed = fabric.util.toFixed,\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n\n fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ {\n\n /**\n * @private\n */\n _setSVGTextLineText: function(lineIndex, textSpans, height, textLeftOffset, textTopOffset, textBgRects) {\n if (!this.styles[lineIndex]) {\n fabric.Text.prototype._setSVGTextLineText.call(this,\n lineIndex, textSpans, height, textLeftOffset, textTopOffset);\n }\n else {\n this._setSVGTextLineChars(\n lineIndex, textSpans, height, textLeftOffset, textBgRects);\n }\n },\n\n /**\n * @private\n */\n _setSVGTextLineChars: function(lineIndex, textSpans, height, textLeftOffset, textBgRects) {\n\n var chars = this._textLines[lineIndex],\n charOffset = 0,\n lineLeftOffset = this._getSVGLineLeftOffset(lineIndex) - this.width / 2,\n lineOffset = this._getSVGLineTopOffset(lineIndex),\n heightOfLine = this._getHeightOfLine(this.ctx, lineIndex);\n\n for (var i = 0, len = chars.length; i < len; i++) {\n var styleDecl = this.styles[lineIndex][i] || { };\n\n textSpans.push(\n this._createTextCharSpan(\n chars[i], styleDecl, lineLeftOffset, lineOffset.lineTop + lineOffset.offset, charOffset));\n\n var charWidth = this._getWidthOfChar(this.ctx, chars[i], lineIndex, i);\n\n if (styleDecl.textBackgroundColor) {\n textBgRects.push(\n this._createTextCharBg(\n styleDecl, lineLeftOffset, lineOffset.lineTop, heightOfLine, charWidth, charOffset));\n }\n\n charOffset += charWidth;\n }\n },\n\n /**\n * @private\n */\n _getSVGLineLeftOffset: function(lineIndex) {\n return fabric.util.toFixed(this._getLineLeftOffset(this.__lineWidths[lineIndex]), 2);\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(this.ctx, j);\n }\n lastHeight = this._getHeightOfLine(this.ctx, j);\n return {\n lineTop: lineTopOffset,\n offset: (this._fontSizeMult - this._fontSizeFraction) * lastHeight / (this.lineHeight * this._fontSizeMult)\n };\n },\n\n /**\n * @private\n */\n _createTextCharBg: function(styleDecl, lineLeftOffset, lineTopOffset, heightOfLine, charWidth, charOffset) {\n return [\n //jscs:disable validateIndentation\n ''\n //jscs:enable validateIndentation\n ].join('');\n },\n\n /**\n * @private\n */\n _createTextCharSpan: function(_char, styleDecl, lineLeftOffset, lineTopOffset, charOffset) {\n\n var fillStyles = this.getSvgStyles.call(fabric.util.object.extend({\n visible: true,\n fill: this.fill,\n stroke: this.stroke,\n type: 'text'\n }, styleDecl));\n\n return [\n //jscs:disable validateIndentation\n '',\n fabric.util.string.escapeXml(_char),\n ''\n //jscs:enable validateIndentation\n ].join('');\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 clone = fabric.util.object.clone;\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 * Type of an object\n * @type String\n * @default\n */\n type: 'textbox',\n /**\n * Minimum width of textbox, in pixels.\n * @type Number\n * @default\n */\n minWidth: 20,\n /**\n * Minimum calculated width of a textbox, in pixels.\n * @type Number\n * @default\n */\n dynamicMinWidth: 0,\n /**\n * Cached array of text wrapping.\n * @type Array\n */\n __cachedLines: null,\n /**\n * Constructor. Some scaling related property values are forced. Visibility\n * of controls is also fixed; only the rotation and width controls are\n * made available.\n * @param {String} text Text string\n * @param {Object} [options] Options object\n * @return {fabric.Textbox} thisArg\n */\n initialize: function(text, options) {\n this.ctx = fabric.util.createCanvasElement().getContext('2d');\n\n this.callSuper('initialize', text, options);\n this.set({\n lockUniScaling: false,\n lockScalingY: true,\n lockScalingFlip: true,\n hasBorders: true\n });\n this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());\n\n // add width to this list of props that effect line wrapping.\n this._dimensionAffectingProps.width = true;\n },\n\n /**\n * Unlike superclass's version of this function, Textbox does not update\n * its width.\n * @param {CanvasRenderingContext2D} ctx Context to use for measurements\n * @private\n * @override\n */\n _initDimensions: function(ctx) {\n if (this.__skipDimension) {\n return;\n }\n\n if (!ctx) {\n ctx = fabric.util.createCanvasElement().getContext('2d');\n this._setTextStyles(ctx);\n }\n\n // clear dynamicMinWidth as it will be different after we re-wrap line\n this.dynamicMinWidth = 0;\n\n // wrap lines\n this._textLines = this._splitTextIntoLines();\n\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\n // clear cache and re-calculate height\n this._clearCache();\n this.height = this._getTextHeight(ctx);\n this._setLineWidths();\n },\n\n /**\n * set the __lineWidths cache array to support\n * functions that expect it to be filled\n * @private\n */\n _setLineWidths: function() {\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n this.__lineWidths[i] = this.width;\n }\n },\n\n /**\n * Generate an object that translates the style object so that it is\n * broken up by visual lines (new lines and automatic wrapping).\n * The original text styles object is broken up by actual lines (new lines only),\n * which is only sufficient for Text / IText\n * @private\n */\n _generateStyleMap: function() {\n var realLineCount = 0,\n realLineCharCount = 0,\n charCount = 0,\n map = {};\n\n for (var i = 0; i < this._textLines.length; i++) {\n if (this.text[charCount] === '\\n') {\n realLineCharCount = 0;\n charCount++;\n realLineCount++;\n }\n else if (this.text[charCount] === ' ') {\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 += this._textLines[i].length;\n realLineCharCount += this._textLines[i].length;\n }\n\n return map;\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Boolean} [returnCloneOrEmpty=false]\n * @private\n */\n _getStyleDeclaration: function(lineIndex, charIndex, returnCloneOrEmpty) {\n if (this._styleMap) {\n var map = this._styleMap[lineIndex];\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n }\n\n if (returnCloneOrEmpty) {\n return (this.styles[lineIndex] && this.styles[lineIndex][charIndex])\n ? clone(this.styles[lineIndex][charIndex])\n : {};\n }\n\n return this.styles[lineIndex] && this.styles[lineIndex][charIndex] ? this.styles[lineIndex][charIndex] : null;\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\n delete this.styles[lineIndex][charIndex];\n },\n\n /**\n * @param {Number} lineIndex\n * @private\n */\n _getLineStyle: function(lineIndex) {\n var map = this._styleMap[lineIndex];\n return this.styles[map.line];\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n _setLineStyle: function(lineIndex, style) {\n var map = this._styleMap[lineIndex];\n this.styles[map.line] = style;\n },\n\n /**\n * @param {Number} lineIndex\n * @private\n */\n _deleteLineStyle: function(lineIndex) {\n var map = this._styleMap[lineIndex];\n delete 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 {CanvasRenderingContext2D} ctx Context to use for measurements\n * @param {String} text The string of text that is split into lines\n * @returns {Array} Array of lines\n */\n _wrapText: function(ctx, text) {\n var lines = text.split(this._reNewline), wrapped = [], i;\n\n for (i = 0; i < lines.length; i++) {\n wrapped = wrapped.concat(this._wrapLine(ctx, lines[i], i));\n }\n\n return wrapped;\n },\n\n /**\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {String} text\n * @param {number} lineIndex\n * @param {number} charOffset\n * @returns {number}\n * @private\n */\n _measureText: function(ctx, text, lineIndex, charOffset) {\n var width = 0, decl;\n charOffset = charOffset || 0;\n\n for (var i = 0; i < text.length; i++) {\n if (this.styles && this.styles[lineIndex] && (decl = this.styles[lineIndex][i + charOffset])) {\n ctx.save();\n width += this._applyCharStylesGetWidth(ctx, text[i], lineIndex, i, decl);\n ctx.restore();\n }\n else {\n // @note: we intentionally pass in an empty style declaration, because if we pass in nothing, it will\n // retry fetching style declaration\n width += this._applyCharStylesGetWidth(ctx, text[i], lineIndex, i, {});\n }\n }\n\n return width;\n },\n\n /**\n * Wraps a line of text using the width of the Textbox and a context.\n * @param {CanvasRenderingContext2D} ctx Context to use for measurements\n * @param {String} text The string of text to split into lines\n * @param {Number} lineIndex\n * @returns {Array} Array of line(s) into which the given text is wrapped\n * to.\n */\n _wrapLine: function(ctx, text, lineIndex) {\n var maxWidth = this.width,\n lineWidth = this._measureText(ctx, text, lineIndex, 0);\n\n // first case: does the whole line fit?\n if (lineWidth < maxWidth) {\n // if the current line is only one word, we need to keep track of it if it's a large word\n if (text.indexOf(' ') === -1 && lineWidth > this.dynamicMinWidth) {\n this.dynamicMinWidth = lineWidth;\n }\n\n return [text];\n }\n\n // if the whole line doesn't fit, we break it up into words\n var lines = [],\n line = '',\n words = text.split(' '),\n offset = 0,\n infix = '',\n wordWidth = 0,\n largestWordWidth = 0;\n\n while (words.length > 0) {\n infix = line === '' ? '' : ' ';\n wordWidth = this._measureText(ctx, words[0], lineIndex, line.length + infix.length + offset);\n lineWidth = line === '' ? wordWidth : this._measureText(ctx, line + infix + words[0], lineIndex, offset);\n\n if (lineWidth < maxWidth || (line === '' && wordWidth >= maxWidth)) {\n line += infix + words.shift();\n }\n else {\n offset += line.length + 1; // add 1 because each word is separated by a space\n lines.push(line);\n line = '';\n }\n\n if (words.length === 0) {\n lines.push(line);\n }\n\n // keep track of largest word\n if (wordWidth > largestWordWidth) {\n largestWordWidth = wordWidth;\n }\n }\n\n if (largestWordWidth > this.dynamicMinWidth) {\n this.dynamicMinWidth = largestWordWidth;\n }\n\n return lines;\n },\n\n /**\n * Gets lines of text to render in the Textbox. This function calculates\n * text wrapping on the fly everytime it is called.\n * @returns {Array} Array of lines in the Textbox.\n * @override\n */\n _splitTextIntoLines: function() {\n this.ctx.save();\n this._setTextStyles(this.ctx);\n\n var lines = this._wrapText(this.ctx, this.text);\n\n this.ctx.restore();\n this._textLines = lines;\n this._styleMap = this._generateStyleMap();\n return lines;\n },\n\n /**\n * When part of a group, we don't want the Textbox's scale to increase if\n * the group's increases. That's why we reduce the scale of the Textbox by\n * the amount that the group's increases. This is to maintain the effective\n * scale of the Textbox at 1, so that font-size values make sense. Otherwise\n * the same font-size value would result in different actual size depending\n * on the value of the scale.\n * @param {String} key\n * @param {Any} value\n */\n setOnGroup: function(key, value) {\n if (key === 'scaleX') {\n this.set('scaleX', Math.abs(1 / value));\n this.set('width', (this.get('width') * value) /\n (typeof this.__oldScaleX === 'undefined' ? 1 : this.__oldScaleX));\n this.__oldScaleX = value;\n }\n },\n\n /**\n * Returns 2d representation (lineIndex and charIndex) of cursor (or selection start).\n * Overrides the superclass function to take into account text wrapping.\n *\n * @param {Number} [selectionStart] Optional index. When not given, current selectionStart is used.\n */\n get2DCursorLocation: function(selectionStart) {\n if (typeof selectionStart === 'undefined') {\n selectionStart = this.selectionStart;\n }\n\n var numLines = this._textLines.length,\n removed = 0;\n\n for (var i = 0; i < numLines; i++) {\n var line = this._textLines[i],\n lineLen = line.length;\n\n if (selectionStart <= removed + lineLen) {\n return {\n lineIndex: i,\n charIndex: selectionStart - removed\n };\n }\n\n removed += lineLen;\n\n if (this.text[removed] === '\\n' || this.text[removed] === ' ') {\n removed++;\n }\n }\n\n return {\n lineIndex: numLines - 1,\n charIndex: this._textLines[numLines - 1].length\n };\n },\n\n /**\n * Overrides superclass function and uses text wrapping data to get cursor\n * boundary offsets instead of the array of chars.\n * @param {Array} chars Unused\n * @param {String} typeOfBoundaries Can be 'cursor' or 'selection'\n * @returns {Object} Object with 'top', 'left', and 'lineLeft' properties set.\n */\n _getCursorBoundariesOffsets: function(chars, typeOfBoundaries) {\n var topOffset = 0,\n leftOffset = 0,\n cursorLocation = this.get2DCursorLocation(),\n lineChars = this._textLines[cursorLocation.lineIndex].split(''),\n lineLeftOffset = this._getCachedLineOffset(cursorLocation.lineIndex);\n\n for (var i = 0; i < cursorLocation.charIndex; i++) {\n leftOffset += this._getWidthOfChar(this.ctx, lineChars[i], cursorLocation.lineIndex, i);\n }\n\n for (i = 0; i < cursorLocation.lineIndex; i++) {\n topOffset += this._getHeightOfLine(this.ctx, i);\n }\n\n if (typeOfBoundaries === 'cursor') {\n topOffset += (1 - this._fontSizeFraction) * this._getHeightOfLine(this.ctx, cursorLocation.lineIndex)\n / this.lineHeight - this.getCurrentCharFontSize(cursorLocation.lineIndex, cursorLocation.charIndex)\n * (1 - this._fontSizeFraction);\n }\n\n return {\n top: topOffset,\n left: leftOffset,\n lineLeft: lineLeftOffset\n };\n },\n\n getMinWidth: function() {\n return Math.max(this.minWidth, this.dynamicMinWidth);\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 fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), {\n minWidth: this.minWidth\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 * @return {fabric.Textbox} instance of fabric.Textbox\n */\n fabric.Textbox.fromObject = function(object) {\n return new fabric.Textbox(object.text, clone(object));\n };\n /**\n * Returns the default controls visibility required for Textboxes.\n * @returns {Object}\n */\n fabric.Textbox.getTextboxControlVisibility = function() {\n return {\n tl: false,\n tr: false,\n br: false,\n bl: false,\n ml: true,\n mt: false,\n mr: true,\n mb: false,\n mtr: true\n };\n };\n /**\n * Contains all fabric.Textbox objects that have been created\n * @static\n * @memberOf fabric.Textbox\n * @type Array\n */\n fabric.Textbox.instances = [];\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n /**\n * Override _setObjectScale and add Textbox specific resizing behavior. Resizing\n * a Textbox doesn't scale text, it only changes width and makes text wrap automatically.\n */\n var setObjectScaleOverridden = fabric.Canvas.prototype._setObjectScale;\n\n fabric.Canvas.prototype._setObjectScale = function(localMouse, transform,\n lockScalingX, lockScalingY, by, lockScalingFlip) {\n\n var t = transform.target;\n if (t instanceof fabric.Textbox) {\n var w = t.width * ((localMouse.x / transform.scaleX) / (t.width + t.strokeWidth));\n if (w >= t.getMinWidth()) {\n t.set('width', w);\n }\n }\n else {\n setObjectScaleOverridden.call(fabric.Canvas.prototype, localMouse, transform,\n lockScalingX, lockScalingY, by, lockScalingFlip);\n }\n };\n\n /**\n * Sets controls of this group to the Textbox's special configuration if\n * one is present in the group. Deletes _controlsVisibility otherwise, so that\n * it gets initialized to default value at runtime.\n */\n fabric.Group.prototype._refreshControlsVisibility = function() {\n if (typeof fabric.Textbox === 'undefined') {\n return;\n }\n for (var i = this._objects.length; i--;) {\n if (this._objects[i] instanceof fabric.Textbox) {\n this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());\n return;\n }\n }\n };\n\n var clone = fabric.util.object.clone;\n\n fabric.util.object.extend(fabric.Textbox.prototype, /** @lends fabric.IText.prototype */ {\n /**\n * @private\n */\n _removeExtraneousStyles: function() {\n for (var prop in this._styleMap) {\n if (!this._textLines[prop]) {\n delete this.styles[this._styleMap[prop].line];\n }\n }\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 {Object} [style] Style object to insert, if given\n */\n insertCharStyleObject: function(lineIndex, charIndex, style) {\n // adjust lineIndex and charIndex\n var map = this._styleMap[lineIndex];\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n\n fabric.IText.prototype.insertCharStyleObject.apply(this, [lineIndex, charIndex, style]);\n },\n\n /**\n * Inserts new style object\n * @param {Number} lineIndex Index of a line\n * @param {Number} charIndex Index of a char\n * @param {Boolean} isEndOfLine True if it's end of line\n */\n insertNewlineStyleObject: function(lineIndex, charIndex, isEndOfLine) {\n // adjust lineIndex and charIndex\n var map = this._styleMap[lineIndex];\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n\n fabric.IText.prototype.insertNewlineStyleObject.apply(this, [lineIndex, charIndex, isEndOfLine]);\n },\n\n /**\n * Shifts line styles up or down. This function is slightly different than the one in\n * itext_behaviour as it takes into account the styleMap.\n *\n * @param {Number} lineIndex Index of a line\n * @param {Number} offset Can be -1 or +1\n */\n shiftLineStyles: function(lineIndex, offset) {\n // shift all line styles by 1 upward\n var clonedStyles = clone(this.styles),\n map = this._styleMap[lineIndex];\n\n // adjust line index\n lineIndex = map.line;\n\n for (var line in this.styles) {\n var numericLine = parseInt(line, 10);\n\n if (numericLine > lineIndex) {\n this.styles[numericLine + offset] = clonedStyles[numericLine];\n\n if (!clonedStyles[numericLine - offset]) {\n delete this.styles[numericLine];\n }\n }\n }\n //TODO: evaluate if delete old style lines with offset -1\n },\n\n /**\n * Figure out programatically the text on previous actual line (actual = separated by \\n);\n *\n * @param {Number} lIndex\n * @returns {String}\n * @private\n */\n _getTextOnPreviousLine: function(lIndex) {\n var textOnPreviousLine = this._textLines[lIndex - 1];\n\n while (this._styleMap[lIndex - 2] && this._styleMap[lIndex - 2].line === this._styleMap[lIndex - 1].line) {\n textOnPreviousLine = this._textLines[lIndex - 2] + textOnPreviousLine;\n\n lIndex--;\n }\n\n return textOnPreviousLine;\n },\n\n /**\n * Removes style object\n * @param {Boolean} isBeginningOfLine True if cursor is at the beginning of line\n * @param {Number} [index] Optional index. When not given, current selectionStart is used.\n */\n removeStyleObject: function(isBeginningOfLine, index) {\n\n var cursorLocation = this.get2DCursorLocation(index),\n map = this._styleMap[cursorLocation.lineIndex],\n lineIndex = map.line,\n charIndex = map.offset + cursorLocation.charIndex;\n\n if (isBeginningOfLine) {\n var textOnPreviousLine = this._getTextOnPreviousLine(cursorLocation.lineIndex),\n newCharIndexOnPrevLine = textOnPreviousLine ? textOnPreviousLine.length : 0;\n\n if (!this.styles[lineIndex - 1]) {\n this.styles[lineIndex - 1] = {};\n }\n\n for (charIndex in this.styles[lineIndex]) {\n this.styles[lineIndex - 1][parseInt(charIndex, 10) + newCharIndexOnPrevLine]\n = this.styles[lineIndex][charIndex];\n }\n\n this.shiftLineStyles(cursorLocation.lineIndex, -1);\n\n }\n else {\n var currentLineStyles = this.styles[lineIndex];\n\n if (currentLineStyles) {\n delete currentLineStyles[charIndex];\n //console.log('deleting', lineIndex, charIndex + offset);\n }\n\n var currentLineStylesCloned = clone(currentLineStyles);\n\n // shift all styles by 1 backwards\n for (var i in currentLineStylesCloned) {\n var numericIndex = parseInt(i, 10);\n if (numericIndex >= charIndex && numericIndex !== 0) {\n currentLineStyles[numericIndex - 1] = currentLineStylesCloned[numericIndex];\n delete currentLineStyles[numericIndex];\n }\n }\n }\n }\n });\n})();\n\n\n(function() {\n var override = fabric.IText.prototype._getNewSelectionStartFromOffset;\n /**\n * Overrides the IText implementation and adjusts character index as there is not always a linebreak\n *\n * @param {Number} mouseOffset\n * @param {Number} prevWidth\n * @param {Number} width\n * @param {Number} index\n * @param {Number} jlen\n * @returns {Number}\n */\n fabric.IText.prototype._getNewSelectionStartFromOffset = function(mouseOffset, prevWidth, width, index, jlen) {\n index = override.call(this, mouseOffset, prevWidth, width, index, jlen);\n\n // the index passed into the function is padded by the amount of lines from _textLines (to account for \\n)\n // we need to remove this padding, and pad it by actual lines, and / or spaces that are meant to be there\n var tmp = 0,\n removed = 0;\n\n // account for removed characters\n for (var i = 0; i < this._textLines.length; i++) {\n tmp += this._textLines[i].length;\n\n if (tmp + removed >= index) {\n break;\n }\n\n if (this.text[tmp + removed] === '\\n' || this.text[tmp + removed] === ' ') {\n removed++;\n }\n }\n\n return index - i + removed;\n };\n})();\n\n\n(function() {\n\n if (typeof document !== 'undefined' && typeof window !== 'undefined') {\n return;\n }\n\n var DOMParser = require('xmldom').DOMParser,\n URL = require('url'),\n HTTP = require('http'),\n HTTPS = require('https'),\n\n Canvas = require('canvas'),\n Image = require('canvas').Image;\n\n /** @private */\n function request(url, encoding, callback) {\n var oURL = URL.parse(url);\n\n // detect if http or https is used\n if ( !oURL.port ) {\n oURL.port = ( oURL.protocol.indexOf('https:') === 0 ) ? 443 : 80;\n }\n\n // assign request handler based on protocol\n var reqHandler = (oURL.protocol.indexOf('https:') === 0 ) ? HTTPS : HTTP,\n req = reqHandler.request({\n hostname: oURL.hostname,\n port: oURL.port,\n path: oURL.path,\n method: 'GET'\n }, function(response) {\n var body = '';\n if (encoding) {\n response.setEncoding(encoding);\n }\n response.on('end', function () {\n callback(body);\n });\n response.on('data', function (chunk) {\n if (response.statusCode === 200) {\n body += chunk;\n }\n });\n });\n\n req.on('error', function(err) {\n if (err.errno === process.ECONNREFUSED) {\n fabric.log('ECONNREFUSED: connection refused to ' + oURL.hostname + ':' + oURL.port);\n }\n else {\n fabric.log(err.message);\n }\n callback(null);\n });\n\n req.end();\n }\n\n /** @private */\n function requestFs(path, callback) {\n var fs = require('fs');\n fs.readFile(path, function (err, data) {\n if (err) {\n fabric.log(err);\n throw err;\n }\n else {\n callback(data);\n }\n });\n }\n\n fabric.util.loadImage = function(url, callback, context) {\n function createImageAndCallBack(data) {\n if (data) {\n img.src = new Buffer(data, 'binary');\n // preserving original url, which seems to be lost in node-canvas\n img._src = url;\n callback && callback.call(context, img);\n }\n else {\n img = null;\n callback && callback.call(context, null, true);\n }\n }\n var img = new Image();\n if (url && (url instanceof Buffer || url.indexOf('data') === 0)) {\n img.src = img._src = url;\n callback && callback.call(context, img);\n }\n else if (url && url.indexOf('http') !== 0) {\n requestFs(url, createImageAndCallBack);\n }\n else if (url) {\n request(url, 'binary', createImageAndCallBack);\n }\n else {\n callback && callback.call(context, url);\n }\n };\n\n fabric.loadSVGFromURL = function(url, callback, reviver) {\n url = url.replace(/^\\n\\s*/, '').replace(/\\?.*$/, '').trim();\n if (url.indexOf('http') !== 0) {\n requestFs(url, function(body) {\n fabric.loadSVGFromString(body.toString(), callback, reviver);\n });\n }\n else {\n request(url, '', function(body) {\n fabric.loadSVGFromString(body, callback, reviver);\n });\n }\n };\n\n fabric.loadSVGFromString = function(string, callback, reviver) {\n var doc = new DOMParser().parseFromString(string);\n fabric.parseSVGDocument(doc.documentElement, function(results, options) {\n callback && callback(results, options);\n }, reviver);\n };\n\n fabric.util.getScript = function(url, callback) {\n request(url, '', function(body) {\n eval(body);\n callback && callback();\n });\n };\n\n fabric.Image.fromObject = function(object, callback) {\n fabric.util.loadImage(object.src, function(img) {\n var oImg = new fabric.Image(img);\n\n oImg._initConfig(object);\n oImg._initFilters(object.filters, function(filters) {\n oImg.filters = filters || [ ];\n oImg._initFilters(object.resizeFilters, function(resizeFilters) {\n oImg.resizeFilters = resizeFilters || [ ];\n callback && callback(oImg);\n });\n });\n });\n };\n /**\n * Only available when running fabric on node.js\n * @param {Number} width Canvas width\n * @param {Number} height Canvas height\n * @param {Object} [options] Options to pass to FabricCanvas.\n * @param {Object} [nodeCanvasOptions] Options to pass to NodeCanvas.\n * @return {Object} wrapped canvas instance\n */\n fabric.createCanvasForNode = function(width, height, options, nodeCanvasOptions) {\n nodeCanvasOptions = nodeCanvasOptions || options;\n\n var canvasEl = fabric.document.createElement('canvas'),\n nodeCanvas = new Canvas(width || 600, height || 600, nodeCanvasOptions);\n\n // jsdom doesn't create style on canvas element, so here be temp. workaround\n canvasEl.style = { };\n\n canvasEl.width = nodeCanvas.width;\n canvasEl.height = nodeCanvas.height;\n\n var FabricCanvas = fabric.Canvas || fabric.StaticCanvas,\n fabricCanvas = new FabricCanvas(canvasEl, options);\n\n fabricCanvas.contextContainer = nodeCanvas.getContext('2d');\n fabricCanvas.nodeCanvas = nodeCanvas;\n fabricCanvas.Font = Canvas.Font;\n\n return fabricCanvas;\n };\n\n /** @ignore */\n fabric.StaticCanvas.prototype.createPNGStream = function() {\n return this.nodeCanvas.createPNGStream();\n };\n\n fabric.StaticCanvas.prototype.createJPEGStream = function(opts) {\n return this.nodeCanvas.createJPEGStream(opts);\n };\n\n var origSetWidth = fabric.StaticCanvas.prototype.setWidth;\n fabric.StaticCanvas.prototype.setWidth = function(width, options) {\n origSetWidth.call(this, width, options);\n this.nodeCanvas.width = width;\n return this;\n };\n if (fabric.Canvas) {\n fabric.Canvas.prototype.setWidth = fabric.StaticCanvas.prototype.setWidth;\n }\n\n var origSetHeight = fabric.StaticCanvas.prototype.setHeight;\n fabric.StaticCanvas.prototype.setHeight = function(height, options) {\n origSetHeight.call(this, height, options);\n this.nodeCanvas.height = height;\n return this;\n };\n if (fabric.Canvas) {\n fabric.Canvas.prototype.setHeight = fabric.StaticCanvas.prototype.setHeight;\n }\n\n})();\n\n","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\n// If obj.hasOwnProperty has been overridden, then calling\n// obj.hasOwnProperty(prop) will break.\n// See: https://github.com/joyent/node/issues/1707\nfunction hasOwnProperty(obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\nmodule.exports = function(qs, sep, eq, options) {\n sep = sep || '&';\n eq = eq || '=';\n var obj = {};\n\n if (typeof qs !== 'string' || qs.length === 0) {\n return obj;\n }\n\n var regexp = /\\+/g;\n qs = qs.split(sep);\n\n var maxKeys = 1000;\n if (options && typeof options.maxKeys === 'number') {\n maxKeys = options.maxKeys;\n }\n\n var len = qs.length;\n // maxKeys <= 0 means that we should not limit keys count\n if (maxKeys > 0 && len > maxKeys) {\n len = maxKeys;\n }\n\n for (var i = 0; i < len; ++i) {\n var x = qs[i].replace(regexp, '%20'),\n idx = x.indexOf(eq),\n kstr, vstr, k, v;\n\n if (idx >= 0) {\n kstr = x.substr(0, idx);\n vstr = x.substr(idx + 1);\n } else {\n kstr = x;\n vstr = '';\n }\n\n k = decodeURIComponent(kstr);\n v = decodeURIComponent(vstr);\n\n if (!hasOwnProperty(obj, k)) {\n obj[k] = v;\n } else if (Array.isArray(obj[k])) {\n obj[k].push(v);\n } else {\n obj[k] = [obj[k], v];\n }\n }\n\n return obj;\n};\n","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nvar stringifyPrimitive = function(v) {\n switch (typeof v) {\n case 'string':\n return v;\n\n case 'boolean':\n return v ? 'true' : 'false';\n\n case 'number':\n return isFinite(v) ? v : '';\n\n default:\n return '';\n }\n};\n\nmodule.exports = function(obj, sep, eq, name) {\n sep = sep || '&';\n eq = eq || '=';\n if (obj === null) {\n obj = undefined;\n }\n\n if (typeof obj === 'object') {\n return Object.keys(obj).map(function(k) {\n var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;\n if (Array.isArray(obj[k])) {\n return obj[k].map(function(v) {\n return ks + encodeURIComponent(stringifyPrimitive(v));\n }).join(sep);\n } else {\n return ks + encodeURIComponent(stringifyPrimitive(obj[k]));\n }\n }).join(sep);\n\n }\n\n if (!name) return '';\n return encodeURIComponent(stringifyPrimitive(name)) + eq +\n encodeURIComponent(stringifyPrimitive(obj));\n};\n","'use strict';\n\nexports.decode = exports.parse = require('./decode');\nexports.encode = exports.stringify = require('./encode');\n","/*! https://mths.be/punycode v1.3.2 by @mathias */\n;(function(root) {\n\n\t/** Detect free variables */\n\tvar freeExports = typeof exports == 'object' && exports &&\n\t\t!exports.nodeType && exports;\n\tvar freeModule = typeof module == 'object' && module &&\n\t\t!module.nodeType && module;\n\tvar freeGlobal = typeof global == 'object' && global;\n\tif (\n\t\tfreeGlobal.global === freeGlobal ||\n\t\tfreeGlobal.window === freeGlobal ||\n\t\tfreeGlobal.self === freeGlobal\n\t) {\n\t\troot = freeGlobal;\n\t}\n\n\t/**\n\t * The `punycode` object.\n\t * @name punycode\n\t * @type Object\n\t */\n\tvar punycode,\n\n\t/** Highest positive signed 32-bit float value */\n\tmaxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1\n\n\t/** Bootstring parameters */\n\tbase = 36,\n\ttMin = 1,\n\ttMax = 26,\n\tskew = 38,\n\tdamp = 700,\n\tinitialBias = 72,\n\tinitialN = 128, // 0x80\n\tdelimiter = '-', // '\\x2D'\n\n\t/** Regular expressions */\n\tregexPunycode = /^xn--/,\n\tregexNonASCII = /[^\\x20-\\x7E]/, // unprintable ASCII chars + non-ASCII chars\n\tregexSeparators = /[\\x2E\\u3002\\uFF0E\\uFF61]/g, // RFC 3490 separators\n\n\t/** Error messages */\n\terrors = {\n\t\t'overflow': 'Overflow: input needs wider integers to process',\n\t\t'not-basic': 'Illegal input >= 0x80 (not a basic code point)',\n\t\t'invalid-input': 'Invalid input'\n\t},\n\n\t/** Convenience shortcuts */\n\tbaseMinusTMin = base - tMin,\n\tfloor = Math.floor,\n\tstringFromCharCode = String.fromCharCode,\n\n\t/** Temporary variable */\n\tkey;\n\n\t/*--------------------------------------------------------------------------*/\n\n\t/**\n\t * A generic error utility function.\n\t * @private\n\t * @param {String} type The error type.\n\t * @returns {Error} Throws a `RangeError` with the applicable error message.\n\t */\n\tfunction error(type) {\n\t\tthrow RangeError(errors[type]);\n\t}\n\n\t/**\n\t * A generic `Array#map` utility function.\n\t * @private\n\t * @param {Array} array The array to iterate over.\n\t * @param {Function} callback The function that gets called for every array\n\t * item.\n\t * @returns {Array} A new array of values returned by the callback function.\n\t */\n\tfunction map(array, fn) {\n\t\tvar length = array.length;\n\t\tvar result = [];\n\t\twhile (length--) {\n\t\t\tresult[length] = fn(array[length]);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * A simple `Array#map`-like wrapper to work with domain name strings or email\n\t * addresses.\n\t * @private\n\t * @param {String} domain The domain name or email address.\n\t * @param {Function} callback The function that gets called for every\n\t * character.\n\t * @returns {Array} A new string of characters returned by the callback\n\t * function.\n\t */\n\tfunction mapDomain(string, fn) {\n\t\tvar parts = string.split('@');\n\t\tvar result = '';\n\t\tif (parts.length > 1) {\n\t\t\t// In email addresses, only the domain name should be punycoded. Leave\n\t\t\t// the local part (i.e. everything up to `@`) intact.\n\t\t\tresult = parts[0] + '@';\n\t\t\tstring = parts[1];\n\t\t}\n\t\t// Avoid `split(regex)` for IE8 compatibility. See #17.\n\t\tstring = string.replace(regexSeparators, '\\x2E');\n\t\tvar labels = string.split('.');\n\t\tvar encoded = map(labels, fn).join('.');\n\t\treturn result + encoded;\n\t}\n\n\t/**\n\t * Creates an array containing the numeric code points of each Unicode\n\t * character in the string. While JavaScript uses UCS-2 internally,\n\t * this function will convert a pair of surrogate halves (each of which\n\t * UCS-2 exposes as separate characters) into a single code point,\n\t * matching UTF-16.\n\t * @see `punycode.ucs2.encode`\n\t * @see \n\t * @memberOf punycode.ucs2\n\t * @name decode\n\t * @param {String} string The Unicode input string (UCS-2).\n\t * @returns {Array} The new array of code points.\n\t */\n\tfunction ucs2decode(string) {\n\t\tvar output = [],\n\t\t counter = 0,\n\t\t length = string.length,\n\t\t value,\n\t\t extra;\n\t\twhile (counter < length) {\n\t\t\tvalue = string.charCodeAt(counter++);\n\t\t\tif (value >= 0xD800 && value <= 0xDBFF && counter < length) {\n\t\t\t\t// high surrogate, and there is a next character\n\t\t\t\textra = string.charCodeAt(counter++);\n\t\t\t\tif ((extra & 0xFC00) == 0xDC00) { // low surrogate\n\t\t\t\t\toutput.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);\n\t\t\t\t} else {\n\t\t\t\t\t// unmatched surrogate; only append this code unit, in case the next\n\t\t\t\t\t// code unit is the high surrogate of a surrogate pair\n\t\t\t\t\toutput.push(value);\n\t\t\t\t\tcounter--;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\toutput.push(value);\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t}\n\n\t/**\n\t * Creates a string based on an array of numeric code points.\n\t * @see `punycode.ucs2.decode`\n\t * @memberOf punycode.ucs2\n\t * @name encode\n\t * @param {Array} codePoints The array of numeric code points.\n\t * @returns {String} The new Unicode string (UCS-2).\n\t */\n\tfunction ucs2encode(array) {\n\t\treturn map(array, function(value) {\n\t\t\tvar output = '';\n\t\t\tif (value > 0xFFFF) {\n\t\t\t\tvalue -= 0x10000;\n\t\t\t\toutput += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);\n\t\t\t\tvalue = 0xDC00 | value & 0x3FF;\n\t\t\t}\n\t\t\toutput += stringFromCharCode(value);\n\t\t\treturn output;\n\t\t}).join('');\n\t}\n\n\t/**\n\t * Converts a basic code point into a digit/integer.\n\t * @see `digitToBasic()`\n\t * @private\n\t * @param {Number} codePoint The basic numeric code point value.\n\t * @returns {Number} The numeric value of a basic code point (for use in\n\t * representing integers) in the range `0` to `base - 1`, or `base` if\n\t * the code point does not represent a value.\n\t */\n\tfunction basicToDigit(codePoint) {\n\t\tif (codePoint - 48 < 10) {\n\t\t\treturn codePoint - 22;\n\t\t}\n\t\tif (codePoint - 65 < 26) {\n\t\t\treturn codePoint - 65;\n\t\t}\n\t\tif (codePoint - 97 < 26) {\n\t\t\treturn codePoint - 97;\n\t\t}\n\t\treturn base;\n\t}\n\n\t/**\n\t * Converts a digit/integer into a basic code point.\n\t * @see `basicToDigit()`\n\t * @private\n\t * @param {Number} digit The numeric value of a basic code point.\n\t * @returns {Number} The basic code point whose value (when used for\n\t * representing integers) is `digit`, which needs to be in the range\n\t * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is\n\t * used; else, the lowercase form is used. The behavior is undefined\n\t * if `flag` is non-zero and `digit` has no uppercase form.\n\t */\n\tfunction digitToBasic(digit, flag) {\n\t\t// 0..25 map to ASCII a..z or A..Z\n\t\t// 26..35 map to ASCII 0..9\n\t\treturn digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);\n\t}\n\n\t/**\n\t * Bias adaptation function as per section 3.4 of RFC 3492.\n\t * http://tools.ietf.org/html/rfc3492#section-3.4\n\t * @private\n\t */\n\tfunction adapt(delta, numPoints, firstTime) {\n\t\tvar k = 0;\n\t\tdelta = firstTime ? floor(delta / damp) : delta >> 1;\n\t\tdelta += floor(delta / numPoints);\n\t\tfor (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {\n\t\t\tdelta = floor(delta / baseMinusTMin);\n\t\t}\n\t\treturn floor(k + (baseMinusTMin + 1) * delta / (delta + skew));\n\t}\n\n\t/**\n\t * Converts a Punycode string of ASCII-only symbols to a string of Unicode\n\t * symbols.\n\t * @memberOf punycode\n\t * @param {String} input The Punycode string of ASCII-only symbols.\n\t * @returns {String} The resulting string of Unicode symbols.\n\t */\n\tfunction decode(input) {\n\t\t// Don't use UCS-2\n\t\tvar output = [],\n\t\t inputLength = input.length,\n\t\t out,\n\t\t i = 0,\n\t\t n = initialN,\n\t\t bias = initialBias,\n\t\t basic,\n\t\t j,\n\t\t index,\n\t\t oldi,\n\t\t w,\n\t\t k,\n\t\t digit,\n\t\t t,\n\t\t /** Cached calculation results */\n\t\t baseMinusT;\n\n\t\t// Handle the basic code points: let `basic` be the number of input code\n\t\t// points before the last delimiter, or `0` if there is none, then copy\n\t\t// the first basic code points to the output.\n\n\t\tbasic = input.lastIndexOf(delimiter);\n\t\tif (basic < 0) {\n\t\t\tbasic = 0;\n\t\t}\n\n\t\tfor (j = 0; j < basic; ++j) {\n\t\t\t// if it's not a basic code point\n\t\t\tif (input.charCodeAt(j) >= 0x80) {\n\t\t\t\terror('not-basic');\n\t\t\t}\n\t\t\toutput.push(input.charCodeAt(j));\n\t\t}\n\n\t\t// Main decoding loop: start just after the last delimiter if any basic code\n\t\t// points were copied; start at the beginning otherwise.\n\n\t\tfor (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {\n\n\t\t\t// `index` is the index of the next character to be consumed.\n\t\t\t// Decode a generalized variable-length integer into `delta`,\n\t\t\t// which gets added to `i`. The overflow checking is easier\n\t\t\t// if we increase `i` as we go, then subtract off its starting\n\t\t\t// value at the end to obtain `delta`.\n\t\t\tfor (oldi = i, w = 1, k = base; /* no condition */; k += base) {\n\n\t\t\t\tif (index >= inputLength) {\n\t\t\t\t\terror('invalid-input');\n\t\t\t\t}\n\n\t\t\t\tdigit = basicToDigit(input.charCodeAt(index++));\n\n\t\t\t\tif (digit >= base || digit > floor((maxInt - i) / w)) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\ti += digit * w;\n\t\t\t\tt = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\n\t\t\t\tif (digit < t) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tbaseMinusT = base - t;\n\t\t\t\tif (w > floor(maxInt / baseMinusT)) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\tw *= baseMinusT;\n\n\t\t\t}\n\n\t\t\tout = output.length + 1;\n\t\t\tbias = adapt(i - oldi, out, oldi == 0);\n\n\t\t\t// `i` was supposed to wrap around from `out` to `0`,\n\t\t\t// incrementing `n` each time, so we'll fix that now:\n\t\t\tif (floor(i / out) > maxInt - n) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\tn += floor(i / out);\n\t\t\ti %= out;\n\n\t\t\t// Insert `n` at position `i` of the output\n\t\t\toutput.splice(i++, 0, n);\n\n\t\t}\n\n\t\treturn ucs2encode(output);\n\t}\n\n\t/**\n\t * Converts a string of Unicode symbols (e.g. a domain name label) to a\n\t * Punycode string of ASCII-only symbols.\n\t * @memberOf punycode\n\t * @param {String} input The string of Unicode symbols.\n\t * @returns {String} The resulting Punycode string of ASCII-only symbols.\n\t */\n\tfunction encode(input) {\n\t\tvar n,\n\t\t delta,\n\t\t handledCPCount,\n\t\t basicLength,\n\t\t bias,\n\t\t j,\n\t\t m,\n\t\t q,\n\t\t k,\n\t\t t,\n\t\t currentValue,\n\t\t output = [],\n\t\t /** `inputLength` will hold the number of code points in `input`. */\n\t\t inputLength,\n\t\t /** Cached calculation results */\n\t\t handledCPCountPlusOne,\n\t\t baseMinusT,\n\t\t qMinusT;\n\n\t\t// Convert the input in UCS-2 to Unicode\n\t\tinput = ucs2decode(input);\n\n\t\t// Cache the length\n\t\tinputLength = input.length;\n\n\t\t// Initialize the state\n\t\tn = initialN;\n\t\tdelta = 0;\n\t\tbias = initialBias;\n\n\t\t// Handle the basic code points\n\t\tfor (j = 0; j < inputLength; ++j) {\n\t\t\tcurrentValue = input[j];\n\t\t\tif (currentValue < 0x80) {\n\t\t\t\toutput.push(stringFromCharCode(currentValue));\n\t\t\t}\n\t\t}\n\n\t\thandledCPCount = basicLength = output.length;\n\n\t\t// `handledCPCount` is the number of code points that have been handled;\n\t\t// `basicLength` is the number of basic code points.\n\n\t\t// Finish the basic string - if it is not empty - with a delimiter\n\t\tif (basicLength) {\n\t\t\toutput.push(delimiter);\n\t\t}\n\n\t\t// Main encoding loop:\n\t\twhile (handledCPCount < inputLength) {\n\n\t\t\t// All non-basic code points < n have been handled already. Find the next\n\t\t\t// larger one:\n\t\t\tfor (m = maxInt, j = 0; j < inputLength; ++j) {\n\t\t\t\tcurrentValue = input[j];\n\t\t\t\tif (currentValue >= n && currentValue < m) {\n\t\t\t\t\tm = currentValue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Increase `delta` enough to advance the decoder's state to ,\n\t\t\t// but guard against overflow\n\t\t\thandledCPCountPlusOne = handledCPCount + 1;\n\t\t\tif (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\tdelta += (m - n) * handledCPCountPlusOne;\n\t\t\tn = m;\n\n\t\t\tfor (j = 0; j < inputLength; ++j) {\n\t\t\t\tcurrentValue = input[j];\n\n\t\t\t\tif (currentValue < n && ++delta > maxInt) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\tif (currentValue == n) {\n\t\t\t\t\t// Represent delta as a generalized variable-length integer\n\t\t\t\t\tfor (q = delta, k = base; /* no condition */; k += base) {\n\t\t\t\t\t\tt = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\t\t\t\t\t\tif (q < t) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tqMinusT = q - t;\n\t\t\t\t\t\tbaseMinusT = base - t;\n\t\t\t\t\t\toutput.push(\n\t\t\t\t\t\t\tstringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))\n\t\t\t\t\t\t);\n\t\t\t\t\t\tq = floor(qMinusT / baseMinusT);\n\t\t\t\t\t}\n\n\t\t\t\t\toutput.push(stringFromCharCode(digitToBasic(q, 0)));\n\t\t\t\t\tbias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);\n\t\t\t\t\tdelta = 0;\n\t\t\t\t\t++handledCPCount;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t++delta;\n\t\t\t++n;\n\n\t\t}\n\t\treturn output.join('');\n\t}\n\n\t/**\n\t * Converts a Punycode string representing a domain name or an email address\n\t * to Unicode. Only the Punycoded parts of the input will be converted, i.e.\n\t * it doesn't matter if you call it on a string that has already been\n\t * converted to Unicode.\n\t * @memberOf punycode\n\t * @param {String} input The Punycoded domain name or email address to\n\t * convert to Unicode.\n\t * @returns {String} The Unicode representation of the given Punycode\n\t * string.\n\t */\n\tfunction toUnicode(input) {\n\t\treturn mapDomain(input, function(string) {\n\t\t\treturn regexPunycode.test(string)\n\t\t\t\t? decode(string.slice(4).toLowerCase())\n\t\t\t\t: string;\n\t\t});\n\t}\n\n\t/**\n\t * Converts a Unicode string representing a domain name or an email address to\n\t * Punycode. Only the non-ASCII parts of the domain name will be converted,\n\t * i.e. it doesn't matter if you call it with a domain that's already in\n\t * ASCII.\n\t * @memberOf punycode\n\t * @param {String} input The domain name or email address to convert, as a\n\t * Unicode string.\n\t * @returns {String} The Punycode representation of the given domain name or\n\t * email address.\n\t */\n\tfunction toASCII(input) {\n\t\treturn mapDomain(input, function(string) {\n\t\t\treturn regexNonASCII.test(string)\n\t\t\t\t? 'xn--' + encode(string)\n\t\t\t\t: string;\n\t\t});\n\t}\n\n\t/*--------------------------------------------------------------------------*/\n\n\t/** Define the public API */\n\tpunycode = {\n\t\t/**\n\t\t * A string representing the current Punycode.js version number.\n\t\t * @memberOf punycode\n\t\t * @type String\n\t\t */\n\t\t'version': '1.3.2',\n\t\t/**\n\t\t * An object of methods to convert from JavaScript's internal character\n\t\t * representation (UCS-2) to Unicode code points, and back.\n\t\t * @see \n\t\t * @memberOf punycode\n\t\t * @type Object\n\t\t */\n\t\t'ucs2': {\n\t\t\t'decode': ucs2decode,\n\t\t\t'encode': ucs2encode\n\t\t},\n\t\t'decode': decode,\n\t\t'encode': encode,\n\t\t'toASCII': toASCII,\n\t\t'toUnicode': toUnicode\n\t};\n\n\t/** Expose `punycode` */\n\t// Some AMD build optimizers, like r.js, check for specific condition patterns\n\t// like the following:\n\tif (\n\t\ttypeof define == 'function' &&\n\t\ttypeof define.amd == 'object' &&\n\t\tdefine.amd\n\t) {\n\t\tdefine('punycode', function() {\n\t\t\treturn punycode;\n\t\t});\n\t} else if (freeExports && freeModule) {\n\t\tif (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+\n\t\t\tfreeModule.exports = punycode;\n\t\t} else { // in Narwhal or RingoJS v0.7.0-\n\t\t\tfor (key in punycode) {\n\t\t\t\tpunycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);\n\t\t\t}\n\t\t}\n\t} else { // in Rhino or a web browser\n\t\troot.punycode = punycode;\n\t}\n\n}(this));\n","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nvar punycode = require('punycode');\nvar util = require('./util');\n\nexports.parse = urlParse;\nexports.resolve = urlResolve;\nexports.resolveObject = urlResolveObject;\nexports.format = urlFormat;\n\nexports.Url = Url;\n\nfunction Url() {\n this.protocol = null;\n this.slashes = null;\n this.auth = null;\n this.host = null;\n this.port = null;\n this.hostname = null;\n this.hash = null;\n this.search = null;\n this.query = null;\n this.pathname = null;\n this.path = null;\n this.href = null;\n}\n\n// Reference: RFC 3986, RFC 1808, RFC 2396\n\n// define these here so at least they only have to be\n// compiled once on the first module load.\nvar protocolPattern = /^([a-z0-9.+-]+:)/i,\n portPattern = /:[0-9]*$/,\n\n // Special case for a simple path URL\n simplePathPattern = /^(\\/\\/?(?!\\/)[^\\?\\s]*)(\\?[^\\s]*)?$/,\n\n // RFC 2396: characters reserved for delimiting URLs.\n // We actually just auto-escape these.\n delims = ['<', '>', '\"', '`', ' ', '\\r', '\\n', '\\t'],\n\n // RFC 2396: characters not allowed for various reasons.\n unwise = ['{', '}', '|', '\\\\', '^', '`'].concat(delims),\n\n // Allowed by RFCs, but cause of XSS attacks. Always escape these.\n autoEscape = ['\\''].concat(unwise),\n // Characters that are never ever allowed in a hostname.\n // Note that any invalid chars are also handled, but these\n // are the ones that are *expected* to be seen, so we fast-path\n // them.\n nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),\n hostEndingChars = ['/', '?', '#'],\n hostnameMaxLen = 255,\n hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,\n hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,\n // protocols that can allow \"unsafe\" and \"unwise\" chars.\n unsafeProtocol = {\n 'javascript': true,\n 'javascript:': true\n },\n // protocols that never have a hostname.\n hostlessProtocol = {\n 'javascript': true,\n 'javascript:': true\n },\n // protocols that always contain a // bit.\n slashedProtocol = {\n 'http': true,\n 'https': true,\n 'ftp': true,\n 'gopher': true,\n 'file': true,\n 'http:': true,\n 'https:': true,\n 'ftp:': true,\n 'gopher:': true,\n 'file:': true\n },\n querystring = require('querystring');\n\nfunction urlParse(url, parseQueryString, slashesDenoteHost) {\n if (url && util.isObject(url) && url instanceof Url) return url;\n\n var u = new Url;\n u.parse(url, parseQueryString, slashesDenoteHost);\n return u;\n}\n\nUrl.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {\n if (!util.isString(url)) {\n throw new TypeError(\"Parameter 'url' must be a string, not \" + typeof url);\n }\n\n // Copy chrome, IE, opera backslash-handling behavior.\n // Back slashes before the query string get converted to forward slashes\n // See: https://code.google.com/p/chromium/issues/detail?id=25916\n var queryIndex = url.indexOf('?'),\n splitter =\n (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',\n uSplit = url.split(splitter),\n slashRegex = /\\\\/g;\n uSplit[0] = uSplit[0].replace(slashRegex, '/');\n url = uSplit.join(splitter);\n\n var rest = url;\n\n // trim before proceeding.\n // This is to support parse stuff like \" http://foo.com \\n\"\n rest = rest.trim();\n\n if (!slashesDenoteHost && url.split('#').length === 1) {\n // Try fast path regexp\n var simplePath = simplePathPattern.exec(rest);\n if (simplePath) {\n this.path = rest;\n this.href = rest;\n this.pathname = simplePath[1];\n if (simplePath[2]) {\n this.search = simplePath[2];\n if (parseQueryString) {\n this.query = querystring.parse(this.search.substr(1));\n } else {\n this.query = this.search.substr(1);\n }\n } else if (parseQueryString) {\n this.search = '';\n this.query = {};\n }\n return this;\n }\n }\n\n var proto = protocolPattern.exec(rest);\n if (proto) {\n proto = proto[0];\n var lowerProto = proto.toLowerCase();\n this.protocol = lowerProto;\n rest = rest.substr(proto.length);\n }\n\n // figure out if it's got a host\n // user@server is *always* interpreted as a hostname, and url\n // resolution will treat //foo/bar as host=foo,path=bar because that's\n // how the browser resolves relative URLs.\n if (slashesDenoteHost || proto || rest.match(/^\\/\\/[^@\\/]+@[^@\\/]+/)) {\n var slashes = rest.substr(0, 2) === '//';\n if (slashes && !(proto && hostlessProtocol[proto])) {\n rest = rest.substr(2);\n this.slashes = true;\n }\n }\n\n if (!hostlessProtocol[proto] &&\n (slashes || (proto && !slashedProtocol[proto]))) {\n\n // there's a hostname.\n // the first instance of /, ?, ;, or # ends the host.\n //\n // If there is an @ in the hostname, then non-host chars *are* allowed\n // to the left of the last @ sign, unless some host-ending character\n // comes *before* the @-sign.\n // URLs are obnoxious.\n //\n // ex:\n // http://a@b@c/ => user:a@b host:c\n // http://a@b?@c => user:a host:c path:/?@c\n\n // v0.12 TODO(isaacs): This is not quite how Chrome does things.\n // Review our test case against browsers more comprehensively.\n\n // find the first instance of any hostEndingChars\n var hostEnd = -1;\n for (var i = 0; i < hostEndingChars.length; i++) {\n var hec = rest.indexOf(hostEndingChars[i]);\n if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))\n hostEnd = hec;\n }\n\n // at this point, either we have an explicit point where the\n // auth portion cannot go past, or the last @ char is the decider.\n var auth, atSign;\n if (hostEnd === -1) {\n // atSign can be anywhere.\n atSign = rest.lastIndexOf('@');\n } else {\n // atSign must be in auth portion.\n // http://a@b/c@d => host:b auth:a path:/c@d\n atSign = rest.lastIndexOf('@', hostEnd);\n }\n\n // Now we have a portion which is definitely the auth.\n // Pull that off.\n if (atSign !== -1) {\n auth = rest.slice(0, atSign);\n rest = rest.slice(atSign + 1);\n this.auth = decodeURIComponent(auth);\n }\n\n // the host is the remaining to the left of the first non-host char\n hostEnd = -1;\n for (var i = 0; i < nonHostChars.length; i++) {\n var hec = rest.indexOf(nonHostChars[i]);\n if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))\n hostEnd = hec;\n }\n // if we still have not hit it, then the entire thing is a host.\n if (hostEnd === -1)\n hostEnd = rest.length;\n\n this.host = rest.slice(0, hostEnd);\n rest = rest.slice(hostEnd);\n\n // pull out port.\n this.parseHost();\n\n // we've indicated that there is a hostname,\n // so even if it's empty, it has to be present.\n this.hostname = this.hostname || '';\n\n // if hostname begins with [ and ends with ]\n // assume that it's an IPv6 address.\n var ipv6Hostname = this.hostname[0] === '[' &&\n this.hostname[this.hostname.length - 1] === ']';\n\n // validate a little.\n if (!ipv6Hostname) {\n var hostparts = this.hostname.split(/\\./);\n for (var i = 0, l = hostparts.length; i < l; i++) {\n var part = hostparts[i];\n if (!part) continue;\n if (!part.match(hostnamePartPattern)) {\n var newpart = '';\n for (var j = 0, k = part.length; j < k; j++) {\n if (part.charCodeAt(j) > 127) {\n // we replace non-ASCII char with a temporary placeholder\n // we need this to make sure size of hostname is not\n // broken by replacing non-ASCII by nothing\n newpart += 'x';\n } else {\n newpart += part[j];\n }\n }\n // we test again with ASCII char only\n if (!newpart.match(hostnamePartPattern)) {\n var validParts = hostparts.slice(0, i);\n var notHost = hostparts.slice(i + 1);\n var bit = part.match(hostnamePartStart);\n if (bit) {\n validParts.push(bit[1]);\n notHost.unshift(bit[2]);\n }\n if (notHost.length) {\n rest = '/' + notHost.join('.') + rest;\n }\n this.hostname = validParts.join('.');\n break;\n }\n }\n }\n }\n\n if (this.hostname.length > hostnameMaxLen) {\n this.hostname = '';\n } else {\n // hostnames are always lower case.\n this.hostname = this.hostname.toLowerCase();\n }\n\n if (!ipv6Hostname) {\n // IDNA Support: Returns a punycoded representation of \"domain\".\n // It only converts parts of the domain name that\n // have non-ASCII characters, i.e. it doesn't matter if\n // you call it with a domain that already is ASCII-only.\n this.hostname = punycode.toASCII(this.hostname);\n }\n\n var p = this.port ? ':' + this.port : '';\n var h = this.hostname || '';\n this.host = h + p;\n this.href += this.host;\n\n // strip [ and ] from the hostname\n // the host field still retains them, though\n if (ipv6Hostname) {\n this.hostname = this.hostname.substr(1, this.hostname.length - 2);\n if (rest[0] !== '/') {\n rest = '/' + rest;\n }\n }\n }\n\n // now rest is set to the post-host stuff.\n // chop off any delim chars.\n if (!unsafeProtocol[lowerProto]) {\n\n // First, make 100% sure that any \"autoEscape\" chars get\n // escaped, even if encodeURIComponent doesn't think they\n // need to be.\n for (var i = 0, l = autoEscape.length; i < l; i++) {\n var ae = autoEscape[i];\n if (rest.indexOf(ae) === -1)\n continue;\n var esc = encodeURIComponent(ae);\n if (esc === ae) {\n esc = escape(ae);\n }\n rest = rest.split(ae).join(esc);\n }\n }\n\n\n // chop off from the tail first.\n var hash = rest.indexOf('#');\n if (hash !== -1) {\n // got a fragment string.\n this.hash = rest.substr(hash);\n rest = rest.slice(0, hash);\n }\n var qm = rest.indexOf('?');\n if (qm !== -1) {\n this.search = rest.substr(qm);\n this.query = rest.substr(qm + 1);\n if (parseQueryString) {\n this.query = querystring.parse(this.query);\n }\n rest = rest.slice(0, qm);\n } else if (parseQueryString) {\n // no query string, but parseQueryString still requested\n this.search = '';\n this.query = {};\n }\n if (rest) this.pathname = rest;\n if (slashedProtocol[lowerProto] &&\n this.hostname && !this.pathname) {\n this.pathname = '/';\n }\n\n //to support http.request\n if (this.pathname || this.search) {\n var p = this.pathname || '';\n var s = this.search || '';\n this.path = p + s;\n }\n\n // finally, reconstruct the href based on what has been validated.\n this.href = this.format();\n return this;\n};\n\n// format a parsed object into a url string\nfunction urlFormat(obj) {\n // ensure it's an object, and not a string url.\n // If it's an obj, this is a no-op.\n // this way, you can call url_format() on strings\n // to clean up potentially wonky urls.\n if (util.isString(obj)) obj = urlParse(obj);\n if (!(obj instanceof Url)) return Url.prototype.format.call(obj);\n return obj.format();\n}\n\nUrl.prototype.format = function() {\n var auth = this.auth || '';\n if (auth) {\n auth = encodeURIComponent(auth);\n auth = auth.replace(/%3A/i, ':');\n auth += '@';\n }\n\n var protocol = this.protocol || '',\n pathname = this.pathname || '',\n hash = this.hash || '',\n host = false,\n query = '';\n\n if (this.host) {\n host = auth + this.host;\n } else if (this.hostname) {\n host = auth + (this.hostname.indexOf(':') === -1 ?\n this.hostname :\n '[' + this.hostname + ']');\n if (this.port) {\n host += ':' + this.port;\n }\n }\n\n if (this.query &&\n util.isObject(this.query) &&\n Object.keys(this.query).length) {\n query = querystring.stringify(this.query);\n }\n\n var search = this.search || (query && ('?' + query)) || '';\n\n if (protocol && protocol.substr(-1) !== ':') protocol += ':';\n\n // only the slashedProtocols get the //. Not mailto:, xmpp:, etc.\n // unless they had them to begin with.\n if (this.slashes ||\n (!protocol || slashedProtocol[protocol]) && host !== false) {\n host = '//' + (host || '');\n if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;\n } else if (!host) {\n host = '';\n }\n\n if (hash && hash.charAt(0) !== '#') hash = '#' + hash;\n if (search && search.charAt(0) !== '?') search = '?' + search;\n\n pathname = pathname.replace(/[?#]/g, function(match) {\n return encodeURIComponent(match);\n });\n search = search.replace('#', '%23');\n\n return protocol + host + pathname + search + hash;\n};\n\nfunction urlResolve(source, relative) {\n return urlParse(source, false, true).resolve(relative);\n}\n\nUrl.prototype.resolve = function(relative) {\n return this.resolveObject(urlParse(relative, false, true)).format();\n};\n\nfunction urlResolveObject(source, relative) {\n if (!source) return relative;\n return urlParse(source, false, true).resolveObject(relative);\n}\n\nUrl.prototype.resolveObject = function(relative) {\n if (util.isString(relative)) {\n var rel = new Url();\n rel.parse(relative, false, true);\n relative = rel;\n }\n\n var result = new Url();\n var tkeys = Object.keys(this);\n for (var tk = 0; tk < tkeys.length; tk++) {\n var tkey = tkeys[tk];\n result[tkey] = this[tkey];\n }\n\n // hash is always overridden, no matter what.\n // even href=\"\" will remove it.\n result.hash = relative.hash;\n\n // if the relative url is empty, then there's nothing left to do here.\n if (relative.href === '') {\n result.href = result.format();\n return result;\n }\n\n // hrefs like //foo/bar always cut to the protocol.\n if (relative.slashes && !relative.protocol) {\n // take everything except the protocol from relative\n var rkeys = Object.keys(relative);\n for (var rk = 0; rk < rkeys.length; rk++) {\n var rkey = rkeys[rk];\n if (rkey !== 'protocol')\n result[rkey] = relative[rkey];\n }\n\n //urlParse appends trailing / to urls like http://www.example.com\n if (slashedProtocol[result.protocol] &&\n result.hostname && !result.pathname) {\n result.path = result.pathname = '/';\n }\n\n result.href = result.format();\n return result;\n }\n\n if (relative.protocol && relative.protocol !== result.protocol) {\n // if it's a known url protocol, then changing\n // the protocol does weird things\n // first, if it's not file:, then we MUST have a host,\n // and if there was a path\n // to begin with, then we MUST have a path.\n // if it is file:, then the host is dropped,\n // because that's known to be hostless.\n // anything else is assumed to be absolute.\n if (!slashedProtocol[relative.protocol]) {\n var keys = Object.keys(relative);\n for (var v = 0; v < keys.length; v++) {\n var k = keys[v];\n result[k] = relative[k];\n }\n result.href = result.format();\n return result;\n }\n\n result.protocol = relative.protocol;\n if (!relative.host && !hostlessProtocol[relative.protocol]) {\n var relPath = (relative.pathname || '').split('/');\n while (relPath.length && !(relative.host = relPath.shift()));\n if (!relative.host) relative.host = '';\n if (!relative.hostname) relative.hostname = '';\n if (relPath[0] !== '') relPath.unshift('');\n if (relPath.length < 2) relPath.unshift('');\n result.pathname = relPath.join('/');\n } else {\n result.pathname = relative.pathname;\n }\n result.search = relative.search;\n result.query = relative.query;\n result.host = relative.host || '';\n result.auth = relative.auth;\n result.hostname = relative.hostname || relative.host;\n result.port = relative.port;\n // to support http.request\n if (result.pathname || result.search) {\n var p = result.pathname || '';\n var s = result.search || '';\n result.path = p + s;\n }\n result.slashes = result.slashes || relative.slashes;\n result.href = result.format();\n return result;\n }\n\n var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),\n isRelAbs = (\n relative.host ||\n relative.pathname && relative.pathname.charAt(0) === '/'\n ),\n mustEndAbs = (isRelAbs || isSourceAbs ||\n (result.host && relative.pathname)),\n removeAllDots = mustEndAbs,\n srcPath = result.pathname && result.pathname.split('/') || [],\n relPath = relative.pathname && relative.pathname.split('/') || [],\n psychotic = result.protocol && !slashedProtocol[result.protocol];\n\n // if the url is a non-slashed url, then relative\n // links like ../.. should be able\n // to crawl up to the hostname, as well. This is strange.\n // result.protocol has already been set by now.\n // Later on, put the first path part into the host field.\n if (psychotic) {\n result.hostname = '';\n result.port = null;\n if (result.host) {\n if (srcPath[0] === '') srcPath[0] = result.host;\n else srcPath.unshift(result.host);\n }\n result.host = '';\n if (relative.protocol) {\n relative.hostname = null;\n relative.port = null;\n if (relative.host) {\n if (relPath[0] === '') relPath[0] = relative.host;\n else relPath.unshift(relative.host);\n }\n relative.host = null;\n }\n mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');\n }\n\n if (isRelAbs) {\n // it's absolute.\n result.host = (relative.host || relative.host === '') ?\n relative.host : result.host;\n result.hostname = (relative.hostname || relative.hostname === '') ?\n relative.hostname : result.hostname;\n result.search = relative.search;\n result.query = relative.query;\n srcPath = relPath;\n // fall through to the dot-handling below.\n } else if (relPath.length) {\n // it's relative\n // throw away the existing file, and take the new path instead.\n if (!srcPath) srcPath = [];\n srcPath.pop();\n srcPath = srcPath.concat(relPath);\n result.search = relative.search;\n result.query = relative.query;\n } else if (!util.isNullOrUndefined(relative.search)) {\n // just pull out the search.\n // like href='?foo'.\n // Put this after the other two cases because it simplifies the booleans\n if (psychotic) {\n result.hostname = result.host = srcPath.shift();\n //occationaly the auth can get stuck only in host\n //this especially happens in cases like\n //url.resolveObject('mailto:local1@domain1', 'local2@domain2')\n var authInHost = result.host && result.host.indexOf('@') > 0 ?\n result.host.split('@') : false;\n if (authInHost) {\n result.auth = authInHost.shift();\n result.host = result.hostname = authInHost.shift();\n }\n }\n result.search = relative.search;\n result.query = relative.query;\n //to support http.request\n if (!util.isNull(result.pathname) || !util.isNull(result.search)) {\n result.path = (result.pathname ? result.pathname : '') +\n (result.search ? result.search : '');\n }\n result.href = result.format();\n return result;\n }\n\n if (!srcPath.length) {\n // no path at all. easy.\n // we've already handled the other stuff above.\n result.pathname = null;\n //to support http.request\n if (result.search) {\n result.path = '/' + result.search;\n } else {\n result.path = null;\n }\n result.href = result.format();\n return result;\n }\n\n // if a url ENDs in . or .., then it must get a trailing slash.\n // however, if it ends in anything else non-slashy,\n // then it must NOT get a trailing slash.\n var last = srcPath.slice(-1)[0];\n var hasTrailingSlash = (\n (result.host || relative.host || srcPath.length > 1) &&\n (last === '.' || last === '..') || last === '');\n\n // strip single dots, resolve double dots to parent dir\n // if the path tries to go above the root, `up` ends up > 0\n var up = 0;\n for (var i = srcPath.length; i >= 0; i--) {\n last = srcPath[i];\n if (last === '.') {\n srcPath.splice(i, 1);\n } else if (last === '..') {\n srcPath.splice(i, 1);\n up++;\n } else if (up) {\n srcPath.splice(i, 1);\n up--;\n }\n }\n\n // if the path is allowed to go above the root, restore leading ..s\n if (!mustEndAbs && !removeAllDots) {\n for (; up--; up) {\n srcPath.unshift('..');\n }\n }\n\n if (mustEndAbs && srcPath[0] !== '' &&\n (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {\n srcPath.unshift('');\n }\n\n if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {\n srcPath.push('');\n }\n\n var isAbsolute = srcPath[0] === '' ||\n (srcPath[0] && srcPath[0].charAt(0) === '/');\n\n // put the host back\n if (psychotic) {\n result.hostname = result.host = isAbsolute ? '' :\n srcPath.length ? srcPath.shift() : '';\n //occationaly the auth can get stuck only in host\n //this especially happens in cases like\n //url.resolveObject('mailto:local1@domain1', 'local2@domain2')\n var authInHost = result.host && result.host.indexOf('@') > 0 ?\n result.host.split('@') : false;\n if (authInHost) {\n result.auth = authInHost.shift();\n result.host = result.hostname = authInHost.shift();\n }\n }\n\n mustEndAbs = mustEndAbs || (result.host && srcPath.length);\n\n if (mustEndAbs && !isAbsolute) {\n srcPath.unshift('');\n }\n\n if (!srcPath.length) {\n result.pathname = null;\n result.path = null;\n } else {\n result.pathname = srcPath.join('/');\n }\n\n //to support request.http\n if (!util.isNull(result.pathname) || !util.isNull(result.search)) {\n result.path = (result.pathname ? result.pathname : '') +\n (result.search ? result.search : '');\n }\n result.auth = relative.auth || result.auth;\n result.slashes = result.slashes || relative.slashes;\n result.href = result.format();\n return result;\n};\n\nUrl.prototype.parseHost = function() {\n var host = this.host;\n var port = portPattern.exec(host);\n if (port) {\n port = port[0];\n if (port !== ':') {\n this.port = port.substr(1);\n }\n host = host.substr(0, host.length - port.length);\n }\n if (host) this.hostname = host;\n};\n","'use strict';\n\nmodule.exports = {\n isString: function(arg) {\n return typeof(arg) === 'string';\n },\n isObject: function(arg) {\n return typeof(arg) === 'object' && arg !== null;\n },\n isNull: function(arg) {\n return arg === null;\n },\n isNullOrUndefined: function(arg) {\n return arg == null;\n }\n};\n"],"names":["fabric","version","global","sqrt","atan2","PiBy180","slice","apply","Dummy","parseEl","supportsOpacity","supportsFilters","reOpacity","setOpacity","cursorOffset","addListener","removeListener","min","max","degreesToRadians","originXOffset","originYOffset","clone","toFixed","NUM_FRACTION_DIGITS","override","exports","document","window","createWindow","parentWindow","isTouchSupported","documentElement","isLikelyNode","Buffer","SHARED_ATTRIBUTES","DPI","reNum","devicePixelRatio","webkitDevicePixelRatio","mozDevicePixelRatio","_removeEventListener","eventName","handler","this","__eventListeners","util","removeFromArray","length","observe","arguments","prop","on","push","stopObserving","call","fire","options","listenersForEvent","i","len","Observable","off","trigger","Collection","add","_objects","_onObjectAdded","renderOnAddRemove","renderAll","insertAt","object","index","nonSplicing","objects","getObjects","splice","remove","indexOf","_onObjectRemoved","forEachObject","callback","context","type","filter","o","item","isEmpty","size","contains","complexity","reduce","memo","current","Math","PI","array","value","idx","getRandomInt","floor","random","degrees","radiansToDegrees","radians","rotatePoint","point","origin","subtractEquals","sin","cos","rx","x","y","ry","Point","addEquals","transformPoint","p","t","ignoreOffset","invertTransform","a","r","number","fractionDigits","parseFloat","Number","parseUnit","fontSize","unit","exec","Text","DEFAULT_SVG_FONT_SIZE","falseFunction","getKlass","namespace","string","camelize","charAt","toUpperCase","resolveNamespace","parts","split","obj","loadImage","url","crossOrigin","img","createImage","onload","onerror","log","src","enlivenObjects","reviver","onLoaded","numLoadedObjects","numTotalObjects","enlivenedObjects","forEach","klass","async","fromObject","error","groupSVGElements","elements","path","PathGroup","setSourcePath","populateWithProperties","source","destination","properties","Object","prototype","toString","drawDashedLine","ctx","x2","y2","da","dx","dy","rot","dc","di","draw","save","translate","moveTo","rotate","restore","createCanvasElement","canvasEl","createElement","getContext","G_vmlCanvasManager","initElement","createAccessors","proto","stateProperties","propName","capitalizedPropName","setterName","getterName","Function","property","clipContext","receiver","beginPath","clipTo","clip","multiplyTransformMatrices","b","getFunctionBody","fn","String","match","isTransparent","tolerance","_isTransparent","imageData","getImageData","l","data","arcToSegmentsCache","segmentToBezierCache","boundsOfCurveCache","_join","Array","join","arcToSegments","toX","toY","large","sweep","rotateX","argsString","th","sinTh","cosTh","fromX","fromY","px","py","rx2","abs","ry2","py2","px2","pl","root","s","cx","cy","cx1","cy1","mTheta","calcVectorAngle","dtheta","segments","ceil","result","mDelta","mT","th3","segmentToBezier","th2","argsString2","costh2","sinth2","costh3","sinth3","cp1X","cp1Y","cp2X","cp2Y","ux","uy","vx","vy","ta","tb","getBoundsOfCurve","x0","y0","x1","y1","x3","y3","c","t1","t2","b2ac","sqrtb2ac","tvalues","bounds","mt","j","jlen","drawArc","fx","fy","coords","segs","segsNorm","bezierCurveTo","getBoundsOfArc","tx","ty","bound","boundCopy","find","byProperty","condition","searchElement","TypeError","n","POSITIVE_INFINITY","NEGATIVE_INFINITY","k","map","every","some","val","rv","invoke","method","args","value1","value2","extend","trim","replace","character","capitalize","firstLetterOnly","toLowerCase","escapeXml","bind","thisArg","_this","concat","emptyFunction","IS_DONTENUM_BUGGY","addMethods","parent","superclass","constructor","returnValue","valueOf","Subclass","callSuper","methodName","createClass","initialize","shift","subclasses","areHostMethods","methodNames","test","getElement","setElement","uid","getUniqueId","element","__uniqueID","createWrappedHandler","e","event","shouldUseAddListenerRemoveListener","shouldUseAttachEventDetachEvent","listeners","handlers","addEventListener","removeEventListener","listener","wrappedHandler","createListener","attachEvent","detachEvent","existingHandler","handlersForEvent","createDispatcher","pointerX","clientX","pointerY","clientY","_getPointer","pageProp","clientProp","touchProp","getPointer","target","srcElement","scroll","getScrollLeftTop","left","top","style","opacity","es","currentStyle","hasLayout","zoom","setStyle","styles","elementStyle","cssText","styleFloat","_slice","sliceCanConvertNodelists","getElementStyle","selectProp","toArray","arrayLike","childNodes","err","makeElement","tagName","attributes","el","className","htmlFor","setAttribute","docElement","body","scrollLeft","scrollTop","parentNode","nodeType","arr","defaultView","getComputedStyle","attr","undefined","makeElementUnselectable","onselectstart","unselectable","makeElementSelectable","getScript","headEl","getElementsByTagName","scriptEl","loading","onreadystatechange","readyState","appendChild","getById","id","getElementById","addClass","wrapElement","wrapper","replaceChild","getElementOffset","docElem","scrollLeftTop","doc","ownerDocument","box","offset","offsetAttributes","borderLeftWidth","borderTopWidth","paddingLeft","paddingTop","parseInt","getBoundingClientRect","clientLeft","clientTop","makeXHR","factories","ActiveXObject","XMLHttpRequest","emptyFn","request","onComplete","xhr","parameters","param","addParamToUrl","open","setRequestHeader","send","warn","console","_requestAnimFrame","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","setTimeout","requestAnimFrame","animate","timestamp","time","start","Date","duration","finish","onChange","abort","easing","d","startValue","endValue","byValue","onStart","tick","ticktime","currentTime","normalize","asin","elastic","opts","pow","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","iMatrix","commaWsp","transform","reTransformList","reTransform","reAllowedSVGTagNames","reViewBoxTagNames","reNotAllowedAncestors","reAllowedParents","attributesMap","display","visibility","colorAttributes","stroke","fill","normalizeAttr","normalizeValue","parentAttributes","parsed","isArray","transformMatrix","parseTransformAttribute","visible","isNaN","elementMatchesRule","selectors","firstMatching","parentMatching","selectorMatches","pop","selector","doesSomeParentMatch","matcher","nodeName","classNames","getAttribute","RegExp","elementById","node","nodelist","idAttr","cssRules","gradientDefs","attributeValue","matrix","matrices","m","operation","translateMatrix","angle","rotateMatrix","multiplierX","multiplierY","scaleMatrix","tan","skewXMatrix","skewYMatrix","combinedMatrix","reViewBoxAttrValue","applyViewboxTransform","minX","minY","viewBoxWidth","viewBoxHeight","viewBoxAttr","scaleX","scaleY","widthAttr","heightAttr","missingViewBox","missingDimAttr","toBeParsed","parsedDim","width","height","firstChild","parseSVGDocument","attrs","xlink","substr","el2","cloneNode","currentTrans","oldLength","el3","nodeValue","removeAttribute","parseUseDirectives","startTime","svgUid","__uid","descendants","selectNodes","hasAncestorWithNodeName","getGradientDefs","getCSSRules","parseElements","instances","documentParsingTime","svgCache","name","_createSVGPattern","markup","canvas","toSVG","reFontDeclaration","parseFontDeclaration","oStyle","fontStyle","fontWeight","lineHeight","fontFamily","linearGradientEls","radialGradientEls","elList","idsToXlinkMap","parseAttributes","ownAttributes","rule","getGlobalStylesForElement","parseStyleAttribute","font","color","Color","setAlpha","getAlpha","toRgba","_setStrokeFillOpacity","ElementsParser","parse","chunk","pair","parseStyleString","parseStyleObject","parsePointsAttribute","points","parsedPoints","allRules","styleContents","textContent","ruleObj","propertyValuePairs","_rule","loadSVGFromURL","xml","responseXML","responseText","loadXML","results","hasUrl","cachedObject","enlivedRecord","loadSVGFromString","DOMParser","parser","parseFromString","createSVGFontFacesMarkup","createSVGRefElementsMarkup","numElements","createObjects","createObject","fromElement","_createObject","checkIfDone","createCallback","resolveGradient","instanceFillValue","get","gradientId","set","Gradient","that","scalarAdd","scalar","scalarAddEquals","subtract","scalarSubtract","scalarSubtractEquals","multiply","multiplyEquals","divide","divideEquals","eq","lt","lte","gt","gte","lerp","distanceFrom","midPointFrom","setXY","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","q","colorNameMap","sourceFromHex","sourceFromRgb","sourceFromHsl","_rgbToHsl","g","h","round","getSource","_source","toRgb","toHsl","hsl","toHsla","toHex","alpha","toGrayscale","average","currentAlpha","toBlackWhite","threshold","overlayWith","otherColor","otherSource","reRGBa","reHSLa","reHex","aqua","black","blue","fuchsia","gray","green","lime","maroon","navy","olive","orange","purple","red","silver","teal","white","yellow","fromRgb","fromSource","fromRgba","fromHsl","fromHsla","fromHex","isShortNotation","substring","oColor","getColorStop","colorAlpha","keyValuePairs","key","_convertPercentUnitsToValues","gradientUnits","propValue","addFactor","multFactor","ellipseMatrix","scaleFactor","offsetX","offsetY","colorStops","gradientTransform","addColorStop","colorStop","position","toObject","commonAttributes","sort","group","toLive","gradient","createLinearGradient","createRadialGradient","instance","colorStopEls","getLinearCoords","getRadialCoords","forObject","Pattern","repeat","toDataURL","patternSource","patternWidth","getWidth","patternHeight","getHeight","patternOffsetX","patternOffsetY","patternImgSrc","complete","naturalWidth","naturalHeight","createPattern","Shadow","blur","affectStroke","includeDefaultValues","_parseShadow","shadow","shadowStr","offsetsAndBlur","reOffsetsAndBlur","fBoxX","fBoxY","StaticCanvas","CANVAS_INIT_ERROR","Error","_initStatic","activeInstance","backgroundColor","backgroundImage","overlayColor","overlayImage","stateful","controlsAboveOverlay","allowTouchScrolling","imageSmoothingEnabled","preserveObjectStacking","viewportTransform","onBeforeScaleRotate","enableRetinaScaling","_createLowerCanvas","_initOptions","_setImageSmoothing","interactive","_initRetinaScaling","setOverlayImage","setBackgroundImage","setBackgroundColor","setOverlayColor","calcOffset","lowerCanvasEl","contextContainer","scale","_offset","image","__setBgOverlayImage","__setBgOverlayColor","webkitImageSmoothingEnabled","mozImageSmoothingEnabled","msImageSmoothingEnabled","oImageSmoothingEnabled","Image","setOptions","_createCanvasElement","_initCanvasElement","_applyCanvasStyle","setWidth","setDimensions","setHeight","dimensions","cssValue","cssOnly","_setBackstoreDimension","backstoreOnly","_setCssDimension","upperCanvasEl","cacheCanvasEl","wrapperEl","getZoom","setViewportTransform","vpt","activeGroup","getActiveGroup","setCoords","zoomToPoint","before","after","setZoom","absolutePan","relativePan","getActiveObject","_draw","v","_shouldRenderObject","render","_renderControls","setupState","_set","_discardActiveObject","clearContext","clearRect","clear","discardActiveGroup","discardActiveObject","contextTop","allOnTop","canvasToDrawOn","selection","_groupSelector","_renderBackground","_renderObjects","_renderActiveGroup","_renderOverlay","drawControls","sortedObjects","reverse","fillStyle","fillRect","renderTop","_drawSelection","getCenter","centerObjectH","_centerObject","getCenterPoint","centerObjectV","centerObject","center","setPositionByOrigin","toDatalessJSON","propertiesToInclude","toDatalessObject","_toObjectMethod","_toObjects","__serializeBgOverlay","_toObject","originalValue","originalProperties","_realizeGroupTransformOnObject","_unwindGroupTransformOnObject","originalValues","realizeTransform","background","overlay","svgViewportTransformation","_setSVGPreamble","_setSVGHeader","_setSVGBgOverlayColor","_setSVGBgOverlayImage","_setSVGObjects","suppressPreamble","encoding","viewBox","sendToBack","unshift","bringToFront","sendBackwards","intersecting","newIdx","_findNewLowerIndex","intersectsWithObject","isContainedWithinObject","bringForward","_findNewUpperIndex","dispose","removeListeners","DataURLExporter","EMPTY_JSON","supports","setLineDash","toJSON","BaseBrush","strokeLineCap","strokeLineJoin","strokeDashArray","setShadow","_setBrushStyles","strokeStyle","lineWidth","lineCap","lineJoin","_setShadow","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY","_resetShadow","PencilBrush","_points","onMouseDown","pointer","_prepareForDrawing","_captureDrawingPath","_render","onMouseMove","onMouseUp","_finalizeAndAddPath","_reset","_addPoint","pointerPoint","p1","p2","midPoint","quadraticCurveTo","lineTo","convertPointsToSVGPath","createPath","pathData","Path","strokeWidth","originX","originY","closePath","CircleBrush","drawDot","addPoint","arc","radius","originalRenderOnAddRemove","circles","circle","Circle","Group","circleRadius","circleColor","SprayBrush","density","dotWidth","dotWidthVariance","randomOpacity","optimizeOverlapping","sprayChunks","addSprayChunk","rects","ilen","sprayChunk","rect","Rect","_getOptimizedRects","uniqueRects","uniqueRectsArray","sprayChunkPoints","globalAlpha","PatternBrush","getPatternSrc","patternCanvas","patternCtx","getPatternSrcFunction","getPattern","Canvas","_initInteractive","_createCacheCanvas","uniScaleTransform","centeredScaling","centeredRotation","selectionColor","selectionDashArray","selectionBorderColor","selectionLineWidth","hoverCursor","moveCursor","defaultCursor","freeDrawingCursor","rotationCursor","containerClass","perPixelTargetFind","targetFindTolerance","skipTargetFind","isDrawingMode","_currentTransform","_initWrapperElement","_createUpperCanvas","_initEventListeners","freeDrawingBrush","_resetCurrentTransform","original","_shouldCenterTransform","action","_setOriginToCenter","mouseXSign","mouseYSign","containsPoint","xy","_normalizePointer","_findTargetCorner","isTargetTransparent","hasBorders","transparentCorners","contextCache","_shouldClearSelection","activeObject","shiftKey","evented","selectable","centerTransform","altKey","_getOriginFromCorner","corner","_getActionFromCorner","_setupCurrentTransform","ex","ey","theta","_translateObject","_scaleObject","by","lockScalingX","lockScalingY","lockScalingFlip","constraintPosition","translateToOriginPoint","localMouse","toLocalPoint","_setLocalMouse","_setObjectScale","forbidScalingX","forbidScalingY","dim","_getNonTransformedDimensions","newScaleX","newScaleY","_scaleObjectEqually","_flipObject","dist","lastDist","padding","_rotateObject","lastAngle","curAngle","setCursor","cursor","_resetObjectTransform","setAngle","groupSelector","aleft","atop","strokeRect","_isLastRenderedObject","lastRenderedObjectWithControlsAboveOverlay","findTarget","skipGroup","_searchPossibleTargets","_fireOverOutEvents","_hoveredTarget","_checkTarget","isEditing","relatedTarget","ignoreZoom","cssScale","boundsWidth","boundsHeight","bottom","right","lowerCanvasClass","_copyCanvasStyle","fromEl","toEl","getSelectionContext","getSelectionElement","_setActiveObject","_activeObject","setActiveObject","_setActiveGroup","_activeGroup","setActiveGroup","_discardActiveGroup","destroy","deactivateAll","allObjects","deactivateAllWithDispatch","_drawGroupControls","_drawObjectsControls","active","_setCursorFromEvent","Element","tr","mr","br","mb","bl","ml","tl","cursorMap","_bindEvents","_onResize","_onMouseDown","_onMouseMove","_onMouseWheel","eventjs","_onGesture","_onDrag","_onOrientationChange","_onShake","_onLongPress","_onMouseUp","self","__onTransformGesture","__onDrag","__onMouseWheel","__onOrientationChange","__onShake","__onLongPress","__onMouseDown","__onMouseUp","preventDefault","__onMouseMove","_shouldRender","isMoving","_previousPointer","_isCurrentlyDrawing","_onMouseUpInDrawingMode","_finalizeCurrentTransform","shouldRender","_maybeGroupObjects","_handleCursorAndEvent","_scaling","hasStateChanged","_restoreOriginXY","_previousOriginX","_previousOriginY","originPoint","_onMouseDownInDrawingMode","ivt","_onMouseMoveInDrawingMode","which","button","shouldGroup","_shouldGroup","_clearSelection","_handleGrouping","_beforeTransform","saveState","_setCenterToOrigin","touches","_transformObject","reset","_beforeScaleTransform","_performTransformAction","_fire","_onScale","currentAction","_setCornerCursor","_getRotatedCornerCursor","hasRotatingPoint","getAngle","isType","_updateActiveGroup","_createActiveGroup","saveCoords","removeWithUpdate","addWithUpdate","_createGroup","groupObjects","_groupSelectedObjects","_collectObjects","currentObject","selectionX1Y1","selectionX2Y2","isClick","intersectsWithRect","isContainedWithinRect","setObjectsCoords","format","quality","multiplier","cropping","__toDataURLWithMultiplier","__toDataURL","croppedCanvasEl","__getCroppedCanvas","croppedCtx","drawImage","origWidth","origHeight","scaledWidth","scaledHeight","_tempRemoveBordersControlsFromGroup","_restoreBordersControlsOnGroup","toDataURLWithMultiplier","origHasControls","hasControls","origBorderColor","borderColor","hideControls","origHideControls","loadFromDatalessJSON","json","loadFromJSON","serialized","JSON","_enlivenObjects","_setBgOverlay","loaded","cbIfLoaded","__setBgOverlay","_toDataURL","_toDataURLWithMultiplier","stringify","cloneWithoutData","backgroundImageOpacity","backgroundImageStretch","supportsLineDash","flipX","flipY","cornerSize","cornerColor","fillRule","globalCompositeOperation","strokeMiterLimit","borderOpacityWhenMoving","borderScaleFactor","minScaleLimit","rotatingPointOffset","lockMovementX","lockMovementY","lockRotation","lockUniScaling","_initGradient","_initPattern","_initClipping","functionBody","fromLeft","_getLeftTopCoords","_removeDefaultValues","_setObject","_constrainScale","setOnGroup","toggle","sourcePath","getViewportTransform","noTransform","_setupCompositeOperation","_setStrokeStyles","_setFillStyles","_setOpacity","miterLimit","drawBorders","multX","multY","_removeShadow","_renderFill","_renderStroke","_stroke","_renderDashedStroke","cloneAsImage","dataUrl","boundingRect","getBoundingRect","origParams","getLeft","getTop","originalCanvas","setGradient","setPatternFill","setColor","shouldCenterOrigin","_resetOrigin","centerH","centerV","getLocalPointer","pClicked","objectLeftTop","translateToGivenOrigin","fromOriginX","fromOriginY","toOriginX","toOriginY","_getTransformedDimensions","translateToCenterPoint","leftTop","getPointByOrigin","pos","adjustPosition","to","hypotFull","xFull","yFull","_originalOriginX","_originalOriginY","oCoords","pointTL","pointBR","other","getCoords","thisCoords","otherCoords","point1","point2","lines","_getImageLines","xPoints","_findCrossPoints","topline","rightline","bottomline","leftline","xi","iLine","xcount","lineKey","getBoundingRectWidth","getBoundingRectHeight","xCoords","maxX","yCoords","maxY","scaleToWidth","boundingRectFactor","scaleToHeight","_calculateCurrentDimensions","currentWidth","currentHeight","_angle","atan","_hypotenuse","mtr","_setCornerCoords","_calcDimensionsTransformMatrix","getSvgStyles","getSvgTransform","translatePart","anglePart","scalePart","addTranslateX","flipXPart","addTranslateY","getSvgTransformMatrix","_createBaseSVGMarkup","originalState","_controlsVisibility","isControlVisible","__corner","newTheta","cornerHypotenuse","cosHalfOffset","sinHalfOffset","w","capped","vLine","hLine","sLine","shouldTransform","wh","rotateHeight","scaleOffset","_drawControl","control","controlName","_getControlsVisibility","setControlVisible","setControlsVisibility","FX_DURATION","fxCenterObjectH","callbacks","empty","fxCenterObjectV","fxRemove","skipCallbacks","propsToAnimate","_animate","propPair","currentValue","from","coordProps","makeEdgeToOriginGetter","propertyNames","originValues","axis1","axis2","dimension","nearest","farthest","Line","_setWidthHeight","_getLeftToOriginX","_getTopToOriginY","cp","calcLinePoints","origStrokeStyle","xMult","yMult","ATTRIBUTE_NAMES","parsedAttributes","pi","startAngle","endAngle","setRadius","startX","startY","endX","endY","largeFlag","getRadiusX","getRadiusY","Triangle","widthBy2","heightBy2","piBy2","Ellipse","getRx","getRy","ellipse","_initRxRy","isRounded","Polyline","Polygon","_calcDimensions","_applyPointOffset","commonRender","_toString","commandLengths","repeatedCommands","M","fromArray","_parsePath","_setPositionDimensions","calcDim","_parseDimensions","pathOffset","tempX","tempY","previous","subpathStartX","subpathStartY","controlX","controlY","chunks","addTransform","currentPath","coordsStr","coordsParsed","re","command","commandLength","repeatedCommand","klen","aX","aY","pathUrl","parentToObject","paths","parseDimensionsFromPaths","xC","yC","isSameColor","firstPathFill","total","pathGroup","_lockProperties","isAlreadyGrouped","_updateObjectsCoords","_calcBounds","skipCoordsChange","_updateObjectCoords","__origHasControls","objectLeft","objectTop","originalLeft","originalTop","_restoreObjectsState","_setObjectActive","_moveFlippedObject","delegatedProperties","textDecoration","textAlign","_renderObject","originalHasRotatingPoint","_restoreObjectState","_setObjectPosition","oldOriginX","oldOriginY","_toggleFlipping","newOrigin","rotated","_getRotatedLeftTop","groupAngle","_originalLeft","_originalTop","hasMoved","onlyWidthHeight","props","iLen","jLen","_getBounds","minXY","maxXY","alignX","alignY","meetOrSlice","_lastScaleX","_lastScaleY","filters","resizeFilters","_initElement","_element","_originalElement","_initConfig","applyFilters","setCrossOrigin","getOriginalSize","filterObj","_src","preserveAspectRatio","getSvgSrc","origFill","getSrc","setSrc","imgElement","forResizing","imgEl","replacement","applyTo","toBuffer","pngCompression","_filteredEl","elementToDraw","imageMargins","_findMargins","_needsResize","marginX","marginY","scales","_resetWidthHeight","CSS_CANVAS","_initFilters","fromURL","imgOptions","aspectRatioAttrs","align","_getAngleValueForStraighten","straighten","fxStraighten","straightenObject","fxStraightenObject","BaseFilter","Brightness","brightness","putImageData","Convolute","opaque","tmpCtx","_createImageData","createImageData","weights","pixels","side","halfSide","sw","sh","output","dst","alphaFac","sy","sx","dstOff","scy","scx","srcOff","wt","GradientTransparency","Grayscale","Invert","Mask","mask","channel","maskEl","maskCanvasEl","maskData","Noise","noise","rand","Pixelate","blocksize","_i","_ilen","_j","_jlen","RemoveWhite","distance","limit","Sepia","avg","Sepia2","Tint","tintR","tintG","tintB","alpha1","Multiply","Blend","mode","tg","_r","_g","_b","isImage","_el","tmpCanvas","Resize","resizeType","lanczosLobes","rcpScaleX","rcpScaleY","oW","oH","dW","dH","sliceByTwo","hermiteFastResize","bilinearFiltering","lanczosResize","newWidth","newHeight","multW","multH","signW","signH","doneW","doneH","stepW","stepH","lobes","srcImg","destImg","srcData","destData","lanczos","xx","ratioX","ratioY","rcpRatioX","rcpRatioY","range2X","range2Y","cacheLanc","icenter","process","u","weight","fX","fY","w2","h2","xDiff","yDiff","chnl","origPix","w4","destImage","destPixels","ratioW","ratioH","ratioWHalf","ratioHHalf","img2","data2","weightsAlpha","gxR","gxG","gxB","gxA","centerY","yy","centerX","w0","_dimensionAffectingProps","text","_reNewline","_reSpacesAndTabs","textBackgroundColor","_fontSizeFraction","_fontSizeMult","__skipDimension","_initDimensions","_setTextStyles","_textLines","_splitTextIntoLines","_clearCache","_cacheLinesWidth","_getTextWidth","_getTextHeight","_renderTextBackground","_renderText","_renderTextDecoration","_translateForTextAlign","_renderTextFill","_renderTextStroke","back","sign","textBaseline","skipTextAlign","_getFontDeclaration","_getHeightOfLine","maxWidth","_getLineWidth","currentLineWidth","_renderChars","chars","shortM","_renderTextLine","line","lineIndex","totalWidth","words","spaceWidth","_getWidthOfWords","leftOffset","measureText","_getLeftOffset","_getTopOffset","_skipFillStrokeCheck","lineHeights","heightOfLine","maxHeight","_renderTextBoxBackground","_renderTextLinesBackground","lineLeftOffset","lineTopOffset","_getLineLeftOffset","__lineWidths","__lineHeights","__lineOffsets","_shouldClearCache","shouldClear","_forceClearCache","halfOfVerticalBox","offsets","oLen","renderLinesAtOffset","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","lineTop","textBgRects","textSpans","textTopOffset","textLeftOffset","_setSVGBg","_setSVGTextLineBg","_setSVGTextLineText","yPos","_getFillAttributes","fillColor","offX","IText","selectionStart","selectionEnd","editable","editingBorderColor","cursorWidth","cursorColor","cursorDelay","cursorDuration","caching","_reSpace","_currentCursorOpacity","_selectionDirection","_abortCursorAnimation","_charWidthsCache","initBehavior","__maxFontHeights","__widthOfSpace","isEmptyStyles","p3","setSelectionStart","_updateTextarea","setSelectionEnd","getSelectionStyles","startIndex","endIndex","loc","get2DCursorLocation","_getStyleDeclaration","charIndex","setSelectionStyles","_extendStyles","_getLineStyle","_setLineStyle","_setStyleDeclaration","renderCursorOrSelection","boundaries","_getCursorBoundaries","renderCursor","renderSelection","getCurrentCharStyle","getCurrentCharFontSize","getCurrentCharColor","typeOfBoundaries","_getCursorBoundariesOffsets","lineLeft","topOffset","_getWidthOfChar","_getCachedLineOffset","widthOfLine","cursorLocation","charHeight","__isMousedown","end","startLine","endLine","lineOffset","boxWidth","j2","j2len","_renderCharsFast","prevStyle","charsToRender","thisStyle","_hasStyleChanged","_renderChar","skipFillStrokeCheck","_char","charWidth","decl","shouldStroke","shouldFill","_applyCharStylesGetWidth","_getHeightOfChar","fillText","strokeText","_renderCharDecoration","styleDeclaration","_getWidthOfCharsAt","_getCacheProp","_applyFontStyles","cacheProp","returnCloneOrEmpty","_deleteStyleDeclaration","_deleteLineStyle","_getWidthOfSpace","_getHeightOfCharAt","wordsWidth","currentCharHeight","initAddedHandler","initRemovedHandler","initCursorSelectionHandlers","initDoubleClickSimulation","initSelectedHandler","selected","_hasITextHandlers","_initCanvasHandlers","_iTextInstances","exitEditingOnOthers","_tick","_currentTickState","_animateCursor","targetOpacity","completeMethod","tickState","isAborted","_onTickComplete","_cursorTimeout1","clearTimeout","_currentTickCompleteState","initDelayedCursor","restart","delay","_cursorTimeout2","abortCursorAnimation","selectAll","getSelectedText","findWordBoundaryLeft","startFrom","findWordBoundaryRight","findLineBoundaryLeft","findLineBoundaryRight","getNumNewLinesInSelectedText","selectedText","numNewLines","searchWordBoundary","direction","reNonWord","selectWord","newSelectionStart","newSelectionEnd","selectLine","enterEditing","initHiddenTextarea","hiddenTextarea","focus","_saveEditingProps","_setEditingProps","initMouseMoveHandler","exitEditing","getSelectionStartFromPointer","__selectionStartOnMouseDown","_savedProps","_restoreEditingProps","overCursor","removeChild","_removeExtraneousStyles","_removeCharsFromTo","_removeSingleCharAndStyle","isBeginningOfLine","indexStyle","removeStyleObject","insertChars","_chars","useCopiedStyle","copiedTextStyle","insertChar","skipUpdate","styleObject","isEndOfLine","insertStyleObjects","insertNewlineStyleObject","shiftLineStyles","currentCharStyle","newLineStyles","insertCharStyleObject","currentLineStyles","currentLineStylesCloned","numericIndex","clonedStyles","numericLine","textOnPreviousLine","newCharIndexOnPrevLine","insertNewline","__lastClickTime","__lastLastClickTime","__lastPointer","__newClickTime","newPointer","isTripleClick","_stopEvent","isDoubleClick","__lastIsEditing","__lastSelected","stopPropagation","initMousedownHandler","initMouseupHandler","initClicks","__mousedownX","__mousedownY","setCursorByClick","_isObjectMoved","mouseOffset","prevWidth","_getNewSelectionStartFromOffset","distanceBtwLastCharAndCursor","onKeyDown","onInput","copy","paste","_clickHandlerInitialized","onClick","_keysMap","_ctrlKeysMap","keyCode","ctrlKey","metaKey","stopImmediatePropagation","_cancelOnInput","textLength","diff","charsToInsert","forwardDelete","moveCursorRight","removeChars","clipboardData","_getClipboardData","setData","copiedText","getData","cut","getDownCursorOffset","isRight","selectionProp","textOnSameLineBeforeCursor","textOnSameLineAfterCursor","textOnNextLine","widthOfSameLineBeforeCursor","widthOfCharsOnSameLineBeforeCursor","indexOnNextLine","_getIndexOnNextLine","foundMatch","widthOfNextLine","widthOfCharsOnNextLine","widthOfChar","leftEdge","rightEdge","offsetFromLeftEdge","moveCursorDown","moveCursorDownWithShift","moveCursorDownWithoutShift","swapSelectionPoints","swapSel","getUpCursorOffset","indexOnPrevLine","_getIndexOnPrevLine","widthOfPreviousLine","widthOfCharsOnPreviousLine","moveCursorUp","moveCursorUpWithShift","moveCursorUpWithoutShift","moveCursorLeft","moveCursorLeftWithShift","moveCursorLeftWithoutShift","_move","propMethod","_moveLeft","_moveRight","moveCursorRightWithShift","moveCursorRightWithoutShift","_removeCharsNearCursor","leftLineBoundary","leftWordBoundary","_setSVGTextLineChars","charOffset","_getSVGLineLeftOffset","_getSVGLineTopOffset","styleDecl","_createTextCharSpan","_createTextCharBg","lastHeight","fillStyles","Textbox","minWidth","dynamicMinWidth","__cachedLines","getTextboxControlVisibility","_setLineWidths","_generateStyleMap","realLineCount","realLineCharCount","charCount","_styleMap","_wrapText","wrapped","_wrapLine","_measureText","infix","wordWidth","largestWordWidth","__oldScaleX","numLines","removed","lineLen","lineChars","getMinWidth","setObjectScaleOverridden","_refreshControlsVisibility","_getTextOnPreviousLine","lIndex","tmp","URL","HTTP","HTTPS","createImageAndCallBack","requestFs","eval","oImg","createCanvasForNode","nodeCanvasOptions","nodeCanvas","fabricCanvas","Font","createPNGStream","createJPEGStream","origSetWidth","origSetHeight","oURL","port","protocol","req","hostname","response","setEncoding","statusCode","errno","ECONNREFUSED","message","readFile","hasOwnProperty","module","qs","sep","regexp","maxKeys","kstr","vstr","decodeURIComponent","stringifyPrimitive","isFinite","keys","ks","encodeURIComponent","decode","encode","freeGlobal","punycode","maxInt","regexPunycode","regexNonASCII","regexSeparators","errors","stringFromCharCode","fromCharCode","RangeError","mapDomain","ucs2decode","extra","counter","charCodeAt","ucs2encode","digitToBasic","digit","flag","adapt","delta","numPoints","firstTime","baseMinusTMin","base","input","out","basic","oldi","baseMinusT","codePoint","inputLength","bias","lastIndexOf","handledCPCount","basicLength","handledCPCountPlusOne","qMinusT","Url","slashes","auth","host","hash","search","query","pathname","href","urlParse","resolve","relative","resolveObject","isString","protocolPattern","portPattern","simplePathPattern","unwise","autoEscape","nonHostChars","hostEndingChars","hostnamePartPattern","hostnamePartStart","unsafeProtocol","hostlessProtocol","slashedProtocol","querystring","parseQueryString","slashesDenoteHost","isObject","queryIndex","splitter","uSplit","rest","simplePath","lowerProto","atSign","hostEnd","hec","parseHost","ipv6Hostname","hostparts","part","newpart","validParts","notHost","bit","toASCII","ae","esc","escape","qm","rel","tkeys","tk","tkey","rkeys","rk","rkey","relPath","isSourceAbs","isRelAbs","mustEndAbs","removeAllDots","srcPath","psychotic","isNullOrUndefined","authInHost","isNull","last","hasTrailingSlash","up","isAbsolute","arg"],"sourceRoot":""}