diff --git a/dist/fabric.js b/dist/fabric.js index ece84aff..1528cbc5 100644 --- a/dist/fabric.js +++ b/dist/fabric.js @@ -1,7 +1,7 @@ -/* build: `node build.js modules=ALL exclude=gestures minifier=uglifyjs` */ +/* build: `node build.js modules=ALL exclude=gestures,json minifier=uglifyjs` */ /*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */ -var fabric = fabric || { version: "1.6.0" }; +var fabric = fabric || { version: "1.6.0-rc.1" }; if (typeof exports !== 'undefined') { exports.fabric = fabric; } @@ -71,497 +71,6 @@ fabric.devicePixelRatio = fabric.window.devicePixelRatio || 1; -/* - json2.js - 2014-02-04 - - Public Domain. - - NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. - - See http://www.JSON.org/js.html - - - This code should be minified before deployment. - See http://javascript.crockford.com/jsmin.html - - USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO - NOT CONTROL. - - - This file creates a global JSON object containing two methods: stringify - and parse. - - JSON.stringify(value, replacer, space) - value any JavaScript value, usually an object or array. - - replacer an optional parameter that determines how object - values are stringified for objects. It can be a - function or an array of strings. - - space an optional parameter that specifies the indentation - of nested structures. If it is omitted, the text will - be packed without extra whitespace. If it is a number, - it will specify the number of spaces to indent at each - level. If it is a string (such as '\t' or ' '), - it contains the characters used to indent at each level. - - This method produces a JSON text from a JavaScript value. - - When an object value is found, if the object contains a toJSON - method, its toJSON method will be called and the result will be - stringified. A toJSON method does not serialize: it returns the - value represented by the name/value pair that should be serialized, - or undefined if nothing should be serialized. The toJSON method - will be passed the key associated with the value, and this will be - bound to the value - - For example, this would serialize Dates as ISO strings. - - Date.prototype.toJSON = function (key) { - function f(n) { - // Format integers to have at least two digits. - return n < 10 ? '0' + n : n; - } - - return this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z'; - }; - - You can provide an optional replacer method. It will be passed the - key and value of each member, with this bound to the containing - object. The value that is returned from your method will be - serialized. If your method returns undefined, then the member will - be excluded from the serialization. - - If the replacer parameter is an array of strings, then it will be - used to select the members to be serialized. It filters the results - such that only members with keys listed in the replacer array are - stringified. - - Values that do not have JSON representations, such as undefined or - functions, will not be serialized. Such values in objects will be - dropped; in arrays they will be replaced with null. You can use - a replacer function to replace those with JSON values. - JSON.stringify(undefined) returns undefined. - - The optional space parameter produces a stringification of the - value that is filled with line breaks and indentation to make it - easier to read. - - If the space parameter is a non-empty string, then that string will - be used for indentation. If the space parameter is a number, then - the indentation will be that many spaces. - - Example: - - text = JSON.stringify(['e', {pluribus: 'unum'}]); - // text is '["e",{"pluribus":"unum"}]' - - - text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); - // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' - - text = JSON.stringify([new Date()], function (key, value) { - return this[key] instanceof Date ? - 'Date(' + this[key] + ')' : value; - }); - // text is '["Date(---current time---)"]' - - - JSON.parse(text, reviver) - This method parses a JSON text to produce an object or array. - It can throw a SyntaxError exception. - - The optional reviver parameter is a function that can filter and - transform the results. It receives each of the keys and values, - and its return value is used instead of the original value. - If it returns what it received, then the structure is not modified. - If it returns undefined then the member is deleted. - - Example: - - // Parse the text. Values that look like ISO date strings will - // be converted to Date objects. - - myData = JSON.parse(text, function (key, value) { - var a; - if (typeof value === 'string') { - a = -/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); - if (a) { - return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], - +a[5], +a[6])); - } - } - return value; - }); - - myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { - var d; - if (typeof value === 'string' && - value.slice(0, 5) === 'Date(' && - value.slice(-1) === ')') { - d = new Date(value.slice(5, -1)); - if (d) { - return d; - } - } - return value; - }); - - - This is a reference implementation. You are free to copy, modify, or - redistribute. -*/ - -/*jslint evil: true, regexp: true */ - -/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, - call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, - getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, - lastIndex, length, parse, prototype, push, replace, slice, stringify, - test, toJSON, toString, valueOf -*/ - - -// Create a JSON object only if one does not already exist. We create the -// methods in a closure to avoid creating global variables. - -if (typeof JSON !== 'object') { - JSON = {}; -} - -(function () { - 'use strict'; - - function f(n) { - // Format integers to have at least two digits. - return n < 10 ? '0' + n : n; - } - - if (typeof Date.prototype.toJSON !== 'function') { - - Date.prototype.toJSON = function () { - - return isFinite(this.valueOf()) - ? this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z' - : null; - }; - - String.prototype.toJSON = - Number.prototype.toJSON = - Boolean.prototype.toJSON = function () { - return this.valueOf(); - }; - } - - var cx, - escapable, - gap, - indent, - meta, - rep; - - - function quote(string) { - -// If the string contains no control characters, no quote characters, and no -// backslash characters, then we can safely slap some quotes around it. -// Otherwise we must also replace the offending characters with safe escape -// sequences. - - escapable.lastIndex = 0; - return escapable.test(string) ? '"' + string.replace(escapable, function (a) { - var c = meta[a]; - return typeof c === 'string' - ? c - : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }) + '"' : '"' + string + '"'; - } - - - function str(key, holder) { - -// Produce a string from holder[key]. - - var i, // The loop counter. - k, // The member key. - v, // The member value. - length, - mind = gap, - partial, - value = holder[key]; - -// If the value has a toJSON method, call it to obtain a replacement value. - - if (value && typeof value === 'object' && - typeof value.toJSON === 'function') { - value = value.toJSON(key); - } - -// If we were called with a replacer function, then call the replacer to -// obtain a replacement value. - - if (typeof rep === 'function') { - value = rep.call(holder, key, value); - } - -// What happens next depends on the value's type. - - switch (typeof value) { - case 'string': - return quote(value); - - case 'number': - -// JSON numbers must be finite. Encode non-finite numbers as null. - - return isFinite(value) ? String(value) : 'null'; - - case 'boolean': - case 'null': - -// If the value is a boolean or null, convert it to a string. Note: -// typeof null does not produce 'null'. The case is included here in -// the remote chance that this gets fixed someday. - - return String(value); - -// If the type is 'object', we might be dealing with an object or an array or -// null. - - case 'object': - -// Due to a specification blunder in ECMAScript, typeof null is 'object', -// so watch out for that case. - - if (!value) { - return 'null'; - } - -// Make an array to hold the partial results of stringifying this object value. - - gap += indent; - partial = []; - -// Is the value an array? - - if (Object.prototype.toString.apply(value) === '[object Array]') { - -// The value is an array. Stringify every element. Use null as a placeholder -// for non-JSON values. - - length = value.length; - for (i = 0; i < length; i += 1) { - partial[i] = str(i, value) || 'null'; - } - -// Join all of the elements together, separated with commas, and wrap them in -// brackets. - - v = partial.length === 0 - ? '[]' - : gap - ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' - : '[' + partial.join(',') + ']'; - gap = mind; - return v; - } - -// If the replacer is an array, use it to select the members to be stringified. - - if (rep && typeof rep === 'object') { - length = rep.length; - for (i = 0; i < length; i += 1) { - if (typeof rep[i] === 'string') { - k = rep[i]; - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } else { - -// Otherwise, iterate through all of the keys in the object. - - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } - -// Join all of the member texts together, separated with commas, -// and wrap them in braces. - - v = partial.length === 0 - ? '{}' - : gap - ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' - : '{' + partial.join(',') + '}'; - gap = mind; - return v; - } - } - -// If the JSON object does not yet have a stringify method, give it one. - - if (typeof JSON.stringify !== 'function') { - escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; - meta = { // table of character substitutions - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"' : '\\"', - '\\': '\\\\' - }; - JSON.stringify = function (value, replacer, space) { - -// The stringify method takes a value and an optional replacer, and an optional -// space parameter, and returns a JSON text. The replacer can be a function -// that can replace values, or an array of strings that will select the keys. -// A default replacer method can be provided. Use of the space parameter can -// produce text that is more easily readable. - - var i; - gap = ''; - indent = ''; - -// If the space parameter is a number, make an indent string containing that -// many spaces. - - if (typeof space === 'number') { - for (i = 0; i < space; i += 1) { - indent += ' '; - } - -// If the space parameter is a string, it will be used as the indent string. - - } else if (typeof space === 'string') { - indent = space; - } - -// If there is a replacer, it must be a function or an array. -// Otherwise, throw an error. - - rep = replacer; - if (replacer && typeof replacer !== 'function' && - (typeof replacer !== 'object' || - typeof replacer.length !== 'number')) { - throw new Error('JSON.stringify'); - } - -// Make a fake root object containing our value under the key of ''. -// Return the result of stringifying the value. - - return str('', {'': value}); - }; - } - - -// If the JSON object does not yet have a parse method, give it one. - - if (typeof JSON.parse !== 'function') { - cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; - JSON.parse = function (text, reviver) { - -// The parse method takes a text and an optional reviver function, and returns -// a JavaScript value if the text is a valid JSON text. - - var j; - - function walk(holder, key) { - -// The walk method is used to recursively walk the resulting structure so -// that modifications can be made. - - var k, v, value = holder[key]; - if (value && typeof value === 'object') { - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = walk(value, k); - if (v !== undefined) { - value[k] = v; - } else { - delete value[k]; - } - } - } - } - return reviver.call(holder, key, value); - } - - -// Parsing happens in four stages. In the first stage, we replace certain -// Unicode characters with escape sequences. JavaScript handles many characters -// incorrectly, either silently deleting them, or treating them as line endings. - - text = String(text); - cx.lastIndex = 0; - if (cx.test(text)) { - text = text.replace(cx, function (a) { - return '\\u' + - ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }); - } - -// In the second stage, we run the text against regular expressions that look -// for non-JSON patterns. We are especially concerned with '()' and 'new' -// because they can cause invocation, and '=' because it can cause mutation. -// But just to be safe, we want to reject all unexpected forms. - -// We split the second stage into 4 regexp operations in order to work around -// crippling inefficiencies in IE's and Safari's regexp engines. First we -// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we -// replace all simple value tokens with ']' characters. Third, we delete all -// open brackets that follow a colon or comma or that begin the text. Finally, -// we look to see that the remaining characters are only whitespace or ']' or -// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. - - if (/^[\],:{}\s]*$/ - .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') - .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') - .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { - -// In the third stage we use the eval function to compile the text into a -// JavaScript structure. The '{' operator is subject to a syntactic ambiguity -// in JavaScript: it can begin a block or an object literal. We wrap the text -// in parens to eliminate the ambiguity. - - j = eval('(' + text + ')'); - -// In the optional fourth stage, we recursively walk the new structure, passing -// each name/value pair to a reviver function for possible transformation. - - return typeof reviver === 'function' - ? walk({'': j}, '') - : j; - } - -// If the text is not JSON parseable, then a SyntaxError is thrown. - - throw new SyntaxError('JSON.parse'); - }; - } -}()); - - (function() { /** @@ -573,12 +82,12 @@ if (typeof JSON !== 'object') { if (!this.__eventListeners[eventName]) { return; } - + var eventListener = this.__eventListeners[eventName]; if (handler) { - fabric.util.removeFromArray(this.__eventListeners[eventName], handler); + eventListener[eventListener.indexOf(handler)] = false; } else { - this.__eventListeners[eventName].length = 0; + fabric.util.array.fill(eventListener, false); } } @@ -629,7 +138,9 @@ if (typeof JSON !== 'object') { // remove all key/value pairs (event name -> event handler) if (arguments.length === 0) { - this.__eventListeners = { }; + for (eventName in this.__eventListeners) { + _removeEventListener.call(this, eventName); + } } // one object with key/value pairs was passed else if (arguments.length === 1 && typeof arguments[0] === 'object') { @@ -664,9 +175,11 @@ if (typeof JSON !== 'object') { } for (var i = 0, len = listenersForEvent.length; i < len; i++) { - // avoiding try/catch for perf. reasons - listenersForEvent[i].call(this, options || { }); + listenersForEvent[i] && listenersForEvent[i].call(this, options || { }); } + this.__eventListeners[eventName] = listenersForEvent.filter(function(value) { + return value !== false; + }); return this; } @@ -1956,6 +1469,17 @@ fabric.Collection = { }); } + /** + * @private + */ + function fill(array, value) { + var k = array.length; + while (k--) { + array[k] = value; + } + return array; + } + /** * @private */ @@ -1987,6 +1511,7 @@ fabric.Collection = { * @namespace fabric.util.array */ fabric.util.array = { + fill: fill, invoke: invoke, min: min, max: max @@ -3024,7 +2549,13 @@ if (typeof console !== 'undefined') { s = p / 4; } else { - s = p / (2 * Math.PI) * Math.asin(c / a); + //handle the 0/0 case: + if (c === 0 && a === 0) { + s = p / (2 * Math.PI) * Math.asin(1); + } + else { + s = p / (2 * Math.PI) * Math.asin(c / a); + } } return { a: a, c: c, p: p, s: s }; } @@ -3518,11 +3049,11 @@ if (typeof console !== 'undefined') { function _setStrokeFillOpacity(attributes) { for (var attr in colorAttributes) { - if (typeof attributes[colorAttributes[attr]] === 'undefined') { + if (typeof attributes[colorAttributes[attr]] === 'undefined' || attributes[attr] === '') { continue; } - if (!attributes[attr]) { + if (typeof attributes[attr] === 'undefined') { if (!fabric.Object.prototype[attr]) { continue; } @@ -6703,14 +6234,9 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ _setImageSmoothing: function() { var ctx = this.getContext(); - if (typeof ctx.imageSmoothingEnabled !== 'undefined') { - ctx.imageSmoothingEnabled = this.imageSmoothingEnabled; - return; - } - ctx.webkitImageSmoothingEnabled = this.imageSmoothingEnabled; - ctx.mozImageSmoothingEnabled = this.imageSmoothingEnabled; - ctx.msImageSmoothingEnabled = this.imageSmoothingEnabled; - ctx.oImageSmoothingEnabled = this.imageSmoothingEnabled; + ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled || ctx.webkitImageSmoothingEnabled + || ctx.mozImageSmoothingEnabled || ctx.msImageSmoothingEnabled || ctx.oImageSmoothingEnabled; + ctx.imageSmoothingEnabled = this.imageSmoothingEnabled; }, /** @@ -7181,7 +6707,7 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ renderAll: function () { var canvasToDrawOn = this.contextContainer, objsToRender; - if (this.contextTop && this.selection && !this._groupSelector) { + if (this.contextTop && this.selection && !this._groupSelector && !this.isDrawingMode) { this.clearContext(this.contextTop); } @@ -9103,16 +8629,19 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @private * @param {Number} x pointer's x coordinate * @param {Number} y pointer's y coordinate + * @return {Boolean} true if the translation occurred */ _translateObject: function (x, y) { - var target = this._currentTransform.target; + var transform = this._currentTransform, + target = transform.target, + newLeft = x - transform.offsetX, + newTop = y - transform.offsetY, + moveX = !target.get('lockMovementX') && target.left !== newLeft, + moveY = !target.get('lockMovementY') && target.top !== newTop; - if (!target.get('lockMovementX')) { - target.set('left', x - this._currentTransform.offsetX); - } - if (!target.get('lockMovementY')) { - target.set('top', y - this._currentTransform.offsetY); - } + moveX && target.set('left', newLeft); + moveY && target.set('top', newTop); + return moveX || moveY; }, /** @@ -9156,15 +8685,16 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @param {Number} x pointer's x coordinate * @param {Number} y pointer's y coordinate * @param {String} by Either 'x' or 'y' + * @return {Boolean} true if the skewing occurred */ _skewObject: function (x, y, by) { var t = this._currentTransform, - target = t.target, + target = t.target, skewed = false, lockSkewingX = target.get('lockSkewingX'), lockSkewingY = target.get('lockSkewingY'); if ((lockSkewingX && by === 'x') || (lockSkewingY && by === 'y')) { - return; + return false; } // Get the constraint point @@ -9178,15 +8708,21 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab constraintPosition = target.translateToOriginPoint(center, t.originX, t.originY); // Actually skew the object - this._setObjectSkew(actualMouseByOrigin, t, by, dim); + skewed = this._setObjectSkew(actualMouseByOrigin, t, by, dim); t.lastX = x; t.lastY = y; // Make sure the constraints apply target.setPositionByOrigin(constraintPosition, t.originX, t.originY); + return skewed; }, + /** + * Set object skew + * @private + * @return {Boolean} true if the skewing occurred + */ _setObjectSkew: function(localMouse, transform, by, _dim) { - var target = transform.target, newValue, + var target = transform.target, newValue, skewed = false, skewSign = transform.skewSign, newDim, dimNoSkew, otherBy, _otherBy, _by, newDimMouse, skewX, skewY; @@ -9215,12 +8751,14 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab (dimNoSkew[otherBy] / target['scale' + _otherBy])); newValue = fabric.util.radiansToDegrees(newValue); } + skewed = target['skew' + _by] !== newValue; target.set('skew' + _by, newValue); if (target['skew' + _otherBy] !== 0) { newDim = target._getTransformedDimensions(); newValue = (_dim[otherBy] / newDim[otherBy]) * target['scale' + _otherBy]; target.set('scale' + _otherBy, newValue); } + return skewed; }, /** @@ -9230,6 +8768,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @param {Number} y pointer's y coordinate * @param {String} by Either 'x' or 'y' - specifies dimension constraint by which to scale an object. * When not provided, an object is scaled by both dimensions equally + * @return {Boolean} true if the scaling occurred */ _scaleObject: function (x, y, by) { var t = this._currentTransform, @@ -9239,74 +8778,83 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab lockScalingFlip = target.get('lockScalingFlip'); if (lockScalingX && lockScalingY) { - return; + return false; } // Get the constraint point var constraintPosition = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY), localMouse = target.toLocalPoint(new fabric.Point(x, y), t.originX, t.originY), - dim = target._getTransformedDimensions(); + dim = target._getTransformedDimensions(), scaled = false; this._setLocalMouse(localMouse, t); // Actually scale the object - this._setObjectScale(localMouse, t, lockScalingX, lockScalingY, by, lockScalingFlip, dim); + scaled = this._setObjectScale(localMouse, t, lockScalingX, lockScalingY, by, lockScalingFlip, dim); // Make sure the constraints apply target.setPositionByOrigin(constraintPosition, t.originX, t.originY); + return scaled; }, /** * @private + * @return {Boolean} true if the scaling occurred */ _setObjectScale: function(localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip, _dim) { - var target = transform.target, forbidScalingX = false, forbidScalingY = false; + var target = transform.target, forbidScalingX = false, forbidScalingY = false, scaled = false, + changeX, changeY, scaleX, scaleY; - transform.newScaleX = localMouse.x * target.scaleX / _dim.x; - transform.newScaleY = localMouse.y * target.scaleY / _dim.y; + scaleX = localMouse.x * target.scaleX / _dim.x; + scaleY = localMouse.y * target.scaleY / _dim.y; + changeX = target.scaleX !== scaleX; + changeY = target.scaleY !== scaleY; - if (lockScalingFlip && transform.newScaleX <= 0 && transform.newScaleX < target.scaleX) { + if (lockScalingFlip && scaleX <= 0 && scaleX < target.scaleX) { forbidScalingX = true; } - if (lockScalingFlip && transform.newScaleY <= 0 && transform.newScaleY < target.scaleY) { + if (lockScalingFlip && scaleY <= 0 && scaleY < target.scaleY) { forbidScalingY = true; } if (by === 'equally' && !lockScalingX && !lockScalingY) { - forbidScalingX || forbidScalingY || this._scaleObjectEqually(localMouse, target, transform, _dim); + forbidScalingX || forbidScalingY || (scaled = this._scaleObjectEqually(localMouse, target, transform, _dim)); } else if (!by) { - forbidScalingX || lockScalingX || target.set('scaleX', transform.newScaleX); - forbidScalingY || lockScalingY || target.set('scaleY', transform.newScaleY); + forbidScalingX || lockScalingX || (target.set('scaleX', scaleX) && (scaled = scaled || changeX)); + forbidScalingY || lockScalingY || (target.set('scaleY', scaleY) && (scaled = scaled || changeY)); } else if (by === 'x' && !target.get('lockUniScaling')) { - forbidScalingX || lockScalingX || target.set('scaleX', transform.newScaleX); + forbidScalingX || lockScalingX || (target.set('scaleX', scaleX) && (scaled = scaled || changeX)); } else if (by === 'y' && !target.get('lockUniScaling')) { - forbidScalingY || lockScalingY || target.set('scaleY', transform.newScaleY); + forbidScalingY || lockScalingY || (target.set('scaleY', scaleY) && (scaled = scaled || changeY)); } - + transform.newScaleX = scaleX; + transform.newScaleY = scaleY; forbidScalingX || forbidScalingY || this._flipObject(transform, by); - + return scaled; }, /** * @private + * @return {Boolean} true if the scaling occurred */ _scaleObjectEqually: function(localMouse, target, transform, _dim) { var dist = localMouse.y + localMouse.x, lastDist = _dim.y * transform.original.scaleY / target.scaleY + - _dim.x * transform.original.scaleX / target.scaleX; + _dim.x * transform.original.scaleX / target.scaleX, + scaled; // We use transform.scaleX/Y instead of target.scaleX/Y // because the object may have a min scale and we'll loose the proportions transform.newScaleX = transform.original.scaleX * dist / lastDist; transform.newScaleY = transform.original.scaleY * dist / lastDist; - + scaled = transform.newScaleX !== target.scaleX || transform.newScaleY !== target.scaleY; target.set('scaleX', transform.newScaleX); target.set('scaleY', transform.newScaleY); + return scaled; }, /** @@ -9391,13 +8939,14 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @private * @param {Number} x pointer's x coordinate * @param {Number} y pointer's y coordinate + * @return {Boolean} true if the rotation occurred */ _rotateObject: function (x, y) { var t = this._currentTransform; if (t.target.get('lockRotation')) { - return; + return false; } var lastAngle = atan2(t.ey - t.top, t.ex - t.left), @@ -9410,6 +8959,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab } t.target.angle = angle % 360; + return true; }, /** @@ -10243,14 +9793,12 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab } target.setCoords(); + this._restoreOriginXY(target); - // only fire :modified event if target coordinates were changed during mousedown-mouseup - if (this.stateful && target.hasStateChanged()) { + if (transform.actionPerformed || (this.stateful && target.hasStateChanged())) { this.fire('object:modified', { target: target }); target.fire('modified'); } - - this._restoreOriginXY(target); }, /** @@ -10508,6 +10056,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab } } else { + this._transformObject(e); } @@ -10539,37 +10088,32 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab var x = pointer.x, y = pointer.y, target = transform.target, - action = transform.action; + action = transform.action, + actionPerformed = false; if (action === 'rotate') { - this._rotateObject(x, y); - this._fire('rotating', target, e); + (actionPerformed = this._rotateObject(x, y)) && this._fire('rotating', target, e); } else if (action === 'scale') { - this._onScale(e, transform, x, y); - this._fire('scaling', target, e); + (actionPerformed = this._onScale(e, transform, x, y)) && this._fire('scaling', target, e); } else if (action === 'scaleX') { - this._scaleObject(x, y, 'x'); - this._fire('scaling', target, e); + (actionPerformed = this._scaleObject(x, y, 'x')) && this._fire('scaling', target, e); } else if (action === 'scaleY') { - this._scaleObject(x, y, 'y'); - this._fire('scaling', target, e); + (actionPerformed = this._scaleObject(x, y, 'y')) && this._fire('scaling', target, e); } else if (action === 'skewX') { - this._skewObject(x, y, 'x'); - this._fire('skewing', target, e); + (actionPerformed = this._skewObject(x, y, 'x')) && this._fire('skewing', target, e); } else if (action === 'skewY') { - this._skewObject(x, y, 'y'); - this._fire('skewing', target, e); + (actionPerformed = this._skewObject(x, y, 'y')) && this._fire('skewing', target, e); } else { - this._translateObject(x, y); - this._fire('moving', target, e); + (actionPerformed = this._translateObject(x, y)) && this._fire('moving', target, e); this.setCursor(this.moveCursor); } + transform.actionPerformed = actionPerformed; }, /** @@ -10600,13 +10144,14 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab /** * @private + * @return {Boolean} true if the scaling occurred */ _onScale: function(e, transform, x, y) { // rotate object only if shift key is not pressed // and if it is not a group we are transforming if ((e.shiftKey || this.uniScaleTransform) && !transform.target.get('lockUniScaling')) { transform.currentAction = 'scale'; - this._scaleObject(x, y); + return this._scaleObject(x, y); } else { // Switch from a normal resize to proportional @@ -10615,7 +10160,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab } transform.currentAction = 'scaleEqually'; - this._scaleObject(x, y, 'equally'); + return this._scaleObject(x, y, 'equally'); } }, @@ -15701,8 +15246,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _render: function(ctx) { - if (!fabric.Polygon.prototype.commonRender.call(this, ctx)) { + _render: function(ctx, noTransform) { + if (!fabric.Polygon.prototype.commonRender.call(this, ctx, noTransform)) { return; } this._renderFill(ctx); @@ -17998,14 +17543,14 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @return {Object} Object representation of an instance */ toObject: function(propertiesToInclude) { - var filters = [ ]; + var filters = [ ], element = this._originalElement; this.filters.forEach(function(filterObj) { if (filterObj) { filters.push(filterObj.toObject()); } }); var object = extend(this.callSuper('toObject', propertiesToInclude), { - src: this._originalElement.src || this._originalElement._src, + src: element ? element.src || element._src : '', filters: filters, crossOrigin: this.crossOrigin, alignX: this.alignX, @@ -24835,10 +24380,11 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot var w = t.width * ((localMouse.x / transform.scaleX) / (t.width + t.strokeWidth)); if (w >= t.getMinWidth()) { t.set('width', w); + return true; } } else { - setObjectScaleOverridden.call(fabric.Canvas.prototype, localMouse, transform, + return setObjectScaleOverridden.call(fabric.Canvas.prototype, localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip, _dim); } }; diff --git a/dist/fabric.min.js b/dist/fabric.min.js index 1d9a3e36..b749434a 100644 --- a/dist/fabric.min.js +++ b/dist/fabric.min.js @@ -1,11 +1,12 @@ -var fabric=fabric||{version:"1.6.0"};if(typeof exports!=="undefined"){exports.fabric=fabric}if(typeof document!=="undefined"&&typeof window!=="undefined"){fabric.document=document;fabric.window=window;window.fabric=fabric}else{fabric.document=require("jsdom").jsdom("");if(fabric.document.createWindow){fabric.window=fabric.document.createWindow()}else{fabric.window=fabric.document.parentWindow}}fabric.isTouchSupported="ontouchstart"in fabric.document.documentElement;fabric.isLikelyNode=typeof Buffer!=="undefined"&&typeof window==="undefined";fabric.SHARED_ATTRIBUTES=["display","transform","fill","fill-opacity","fill-rule","opacity","stroke","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","id"];fabric.DPI=96;fabric.reNum="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)";fabric.fontPaths={};fabric.devicePixelRatio=fabric.window.devicePixelRatio||fabric.window.webkitDevicePixelRatio||fabric.window.mozDevicePixelRatio||1;if(typeof JSON!=="object"){JSON={}}(function(){"use strict";function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()}}var cx,escapable,gap,indent,meta,rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i-1},complexity:function(){return this.getObjects().reduce(function(memo,current){memo+=current.complexity?current.complexity():0;return memo},0)}};(function(global){var sqrt=Math.sqrt,atan2=Math.atan2,pow=Math.pow,abs=Math.abs,PiBy180=Math.PI/180;fabric.util={removeFromArray:function(array,value){var idx=array.indexOf(value);if(idx!==-1){array.splice(idx,1)}return array},getRandomInt:function(min,max){return Math.floor(Math.random()*(max-min+1))+min},degreesToRadians:function(degrees){return degrees*PiBy180},radiansToDegrees:function(radians){return radians/PiBy180},rotatePoint:function(point,origin,radians){point.subtractEquals(origin);var v=fabric.util.rotateVector(point,radians);return new fabric.Point(v.x,v.y).addEquals(origin)},rotateVector:function(vector,radians){var sin=Math.sin(radians),cos=Math.cos(radians),rx=vector.x*cos-vector.y*sin,ry=vector.x*sin+vector.y*cos;return{x:rx,y:ry}},transformPoint:function(p,t,ignoreOffset){if(ignoreOffset){return new fabric.Point(t[0]*p.x+t[2]*p.y,t[1]*p.x+t[3]*p.y)}return new fabric.Point(t[0]*p.x+t[2]*p.y+t[4],t[1]*p.x+t[3]*p.y+t[5])},makeBoundingBoxFromPoints:function(points){var xPoints=[points[0].x,points[1].x,points[2].x,points[3].x],minX=fabric.util.array.min(xPoints),maxX=fabric.util.array.max(xPoints),width=Math.abs(minX-maxX),yPoints=[points[0].y,points[1].y,points[2].y,points[3].y],minY=fabric.util.array.min(yPoints),maxY=fabric.util.array.max(yPoints),height=Math.abs(minY-maxY);return{left:minX,top:minY,width:width,height:height}},invertTransform:function(t){var a=1/(t[0]*t[3]-t[1]*t[2]),r=[a*t[3],-a*t[1],-a*t[2],a*t[0]],o=fabric.util.transformPoint({x:t[4],y:t[5]},r,true);r[4]=-o.x;r[5]=-o.y;return r},toFixed:function(number,fractionDigits){return parseFloat(Number(number).toFixed(fractionDigits))},parseUnit:function(value,fontSize){var unit=/\D{0,2}$/.exec(value),number=parseFloat(value);if(!fontSize){fontSize=fabric.Text.DEFAULT_SVG_FONT_SIZE}switch(unit[0]){case"mm":return number*fabric.DPI/25.4;case"cm":return number*fabric.DPI/2.54;case"in":return number*fabric.DPI;case"pt":return number*fabric.DPI/72;case"pc":return number*fabric.DPI/72*12;case"em":return number*fontSize;default:return number}},falseFunction:function(){return false},getKlass:function(type,namespace){type=fabric.util.string.camelize(type.charAt(0).toUpperCase()+type.slice(1));return fabric.util.resolveNamespace(namespace)[type]},resolveNamespace:function(namespace){if(!namespace){return fabric}var parts=namespace.split("."),len=parts.length,obj=global||fabric.window;for(var i=0;ix){x+=da[di++%dc];if(x>len){x=len}ctx[draw?"lineTo":"moveTo"](x,0);draw=!draw}ctx.restore()},createCanvasElement:function(canvasEl){canvasEl||(canvasEl=fabric.document.createElement("canvas"));if(!canvasEl.getContext&&typeof G_vmlCanvasManager!=="undefined"){G_vmlCanvasManager.initElement(canvasEl)}return canvasEl},createImage:function(){return fabric.isLikelyNode?new(require("canvas").Image):fabric.document.createElement("img")},createAccessors:function(klass){var proto=klass.prototype;for(var i=proto.stateProperties.length;i--;){var propName=proto.stateProperties[i],capitalizedPropName=propName.charAt(0).toUpperCase()+propName.slice(1),setterName="set"+capitalizedPropName,getterName="get"+capitalizedPropName;if(!proto[getterName]){proto[getterName]=function(property){return new Function('return this.get("'+property+'")')}(propName)}if(!proto[setterName]){proto[setterName]=function(property){return new Function("value",'return this.set("'+property+'", value)')}(propName)}}},clipContext:function(receiver,ctx){ctx.save();ctx.beginPath();receiver.clipTo(ctx);ctx.clip()},multiplyTransformMatrices:function(a,b,is2x2){return[a[0]*b[0]+a[2]*b[1],a[1]*b[0]+a[3]*b[1],a[0]*b[2]+a[2]*b[3],a[1]*b[2]+a[3]*b[3],is2x2?0:a[0]*b[4]+a[2]*b[5]+a[4],is2x2?0:a[1]*b[4]+a[3]*b[5]+a[5]]},qrDecompose:function(a){var angle=atan2(a[1],a[0]),denom=pow(a[0],2)+pow(a[1],2),scaleX=sqrt(denom),scaleY=(a[0]*a[3]-a[2]*a[1])/scaleX,skewX=atan2(a[0]*a[2]+a[1]*a[3],denom);return{angle:angle/PiBy180,scaleX:scaleX,scaleY:scaleY,skewX:skewX/PiBy180,skewY:0,translateX:a[4],translateY:a[5]}},customTransformMatrix:function(scaleX,scaleY,skewX){var skewMatrixX=[1,0,abs(Math.tan(skewX*PiBy180)),1],scaleMatrix=[abs(scaleX),0,0,abs(scaleY)];return fabric.util.multiplyTransformMatrices(scaleMatrix,skewMatrixX,true)},resetObjectTransform:function(target){target.scaleX=1;target.scaleY=1;target.skewX=0;target.skewY=0;target.flipX=false;target.flipY=false;target.setAngle(0)},getFunctionBody:function(fn){return(String(fn).match(/function[^{]*\{([\s\S]*)\}/)||{})[1]},isTransparent:function(ctx,x,y,tolerance){if(tolerance>0){if(x>tolerance){x-=tolerance}else{x=0}if(y>tolerance){y-=tolerance}else{y=0}}var _isTransparent=true,imageData=ctx.getImageData(x,y,tolerance*2||1,tolerance*2||1);for(var i=3,l=imageData.data.length;i0){dtheta-=2*PI}else if(sweep===1&&dtheta<0){dtheta+=2*PI}var segments=Math.ceil(Math.abs(dtheta/PI*2)),result=[],mDelta=dtheta/segments,mT=8/3*Math.sin(mDelta/4)*Math.sin(mDelta/4)/Math.sin(mDelta/2),th3=mTheta+mDelta;for(var i=0;i=ta){return tb-ta}else{return 2*Math.PI-(ta-tb)}}fabric.util.drawArc=function(ctx,fx,fy,coords){var rx=coords[0],ry=coords[1],rot=coords[2],large=coords[3],sweep=coords[4],tx=coords[5],ty=coords[6],segs=[[],[],[],[]],segsNorm=arcToSegments(tx-fx,ty-fy,rx,ry,large,sweep,rot);for(var i=0,len=segsNorm.length;i0){b=6*y0-12*y1+6*y2;a=-3*y0+9*y1-9*y2+3*y3;c=3*y1-3*y0}if(abs(a)<1e-12){if(abs(b)<1e-12){continue}t=-c/b;if(0>>0;if(len===0){return-1}var n=0;if(arguments.length>0){n=Number(arguments[1]);if(n!==n){n=0}else if(n!==0&&n!==Number.POSITIVE_INFINITY&&n!==Number.NEGATIVE_INFINITY){n=(n>0||-1)*Math.floor(Math.abs(n))}}if(n>=len){return-1}var k=n>=0?n:Math.max(len-Math.abs(n),0);for(;k>>0;i>>0;i>>0;i>>0;i>>0;i>>0,i=0,rv;if(arguments.length>1){rv=arguments[1]}else{do{if(i in this){rv=this[i++];break}if(++i>=len){throw new TypeError}}while(true)}for(;i=value2})}function min(array,byProperty){return find(array,byProperty,function(value1,value2){return value1/g,">")}fabric.util.string={camelize:camelize,capitalize:capitalize,escapeXml:escapeXml}})();(function(){var slice=Array.prototype.slice,apply=Function.prototype.apply,Dummy=function(){};if(!Function.prototype.bind){Function.prototype.bind=function(thisArg){var _this=this,args=slice.call(arguments,1),bound;if(args.length){bound=function(){return apply.call(_this,this instanceof Dummy?this:thisArg,args.concat(slice.call(arguments)))}}else{bound=function(){return apply.call(_this,this instanceof Dummy?this:thisArg,arguments)}}Dummy.prototype=this.prototype;bound.prototype=new Dummy;return bound}}})();(function(){var slice=Array.prototype.slice,emptyFunction=function(){},IS_DONTENUM_BUGGY=function(){for(var p in{toString:1}){if(p==="toString"){return false}}return true}(),addMethods=function(klass,source,parent){for(var property in source){if(property in klass.prototype&&typeof klass.prototype[property]==="function"&&(source[property]+"").indexOf("callSuper")>-1){klass.prototype[property]=function(property){return function(){var superclass=this.constructor.superclass;this.constructor.superclass=parent;var returnValue=source[property].apply(this,arguments);this.constructor.superclass=superclass;if(property!=="initialize"){return returnValue}}}(property)}else{klass.prototype[property]=source[property]}if(IS_DONTENUM_BUGGY){if(source.toString!==Object.prototype.toString){klass.prototype.toString=source.toString}if(source.valueOf!==Object.prototype.valueOf){klass.prototype.valueOf=source.valueOf}}}};function Subclass(){}function callSuper(methodName){var fn=this.constructor.superclass.prototype[methodName];return arguments.length>1?fn.apply(this,slice.call(arguments,1)):fn.call(this)}function createClass(){var parent=null,properties=slice.call(arguments,0);if(typeof properties[0]==="function"){parent=properties.shift()}function klass(){this.initialize.apply(this,arguments)}klass.superclass=parent;klass.subclasses=[];if(parent){Subclass.prototype=parent.prototype;klass.prototype=new Subclass;parent.subclasses.push(klass)}for(var i=0,length=properties.length;i-1?setOpacity(element,styles.match(/opacity:\s*(\d?\.?\d*)/)[1]):element}for(var property in styles){if(property==="opacity"){setOpacity(element,styles[property])}else{var normalizedProperty=property==="float"||property==="cssFloat"?typeof elementStyle.styleFloat==="undefined"?"cssFloat":"styleFloat":property;elementStyle[normalizedProperty]=styles[property]}}return element}var parseEl=fabric.document.createElement("div"),supportsOpacity=typeof parseEl.style.opacity==="string",supportsFilters=typeof parseEl.style.filter==="string",reOpacity=/alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,setOpacity=function(element){return element};if(supportsOpacity){setOpacity=function(element,value){element.style.opacity=value;return element}}else if(supportsFilters){setOpacity=function(element,value){var es=element.style;if(element.currentStyle&&!element.currentStyle.hasLayout){es.zoom=1}if(reOpacity.test(es.filter)){value=value>=.9999?"":"alpha(opacity="+value*100+")";es.filter=es.filter.replace(reOpacity,value)}else{es.filter+=" alpha(opacity="+value*100+")"}return element}}fabric.util.setStyle=setStyle})();(function(){var _slice=Array.prototype.slice;function getById(id){return typeof id==="string"?fabric.document.getElementById(id):id}var sliceCanConvertNodelists,toArray=function(arrayLike){return _slice.call(arrayLike,0)};try{sliceCanConvertNodelists=toArray(fabric.document.childNodes)instanceof Array}catch(err){}if(!sliceCanConvertNodelists){toArray=function(arrayLike){var arr=new Array(arrayLike.length),i=arrayLike.length;while(i--){arr[i]=arrayLike[i]}return arr}}function makeElement(tagName,attributes){var el=fabric.document.createElement(tagName);for(var prop in attributes){if(prop==="class"){el.className=attributes[prop]}else if(prop==="for"){el.htmlFor=attributes[prop]}else{el.setAttribute(prop,attributes[prop])}}return el}function addClass(element,className){if(element&&(" "+element.className+" ").indexOf(" "+className+" ")===-1){element.className+=(element.className?" ":"")+className}}function wrapElement(element,wrapper,attributes){if(typeof wrapper==="string"){wrapper=makeElement(wrapper,attributes)}if(element.parentNode){element.parentNode.replaceChild(wrapper,element)}wrapper.appendChild(element);return wrapper}function getScrollLeftTop(element){var left=0,top=0,docElement=fabric.document.documentElement,body=fabric.document.body||{scrollLeft:0,scrollTop:0};while(element&&(element.parentNode||element.host)){element=element.parentNode||element.host;if(element===fabric.document){left=body.scrollLeft||docElement.scrollLeft||0;top=body.scrollTop||docElement.scrollTop||0}else{left+=element.scrollLeft||0;top+=element.scrollTop||0}if(element.nodeType===1&&fabric.util.getElementStyle(element,"position")==="fixed"){break}}return{left:left,top:top}}function getElementOffset(element){var docElem,doc=element&&element.ownerDocument,box={left:0,top:0},offset={left:0,top:0},scrollLeftTop,offsetAttributes={borderLeftWidth:"left",borderTopWidth:"top",paddingLeft:"left",paddingTop:"top"};if(!doc){return offset}for(var attr in offsetAttributes){offset[offsetAttributes[attr]]+=parseInt(getElementStyle(element,attr),10)||0}docElem=doc.documentElement;if(typeof element.getBoundingClientRect!=="undefined"){box=element.getBoundingClientRect() -}scrollLeftTop=getScrollLeftTop(element);return{left:box.left+scrollLeftTop.left-(docElem.clientLeft||0)+offset.left,top:box.top+scrollLeftTop.top-(docElem.clientTop||0)+offset.top}}var getElementStyle;if(fabric.document.defaultView&&fabric.document.defaultView.getComputedStyle){getElementStyle=function(element,attr){var style=fabric.document.defaultView.getComputedStyle(element,null);return style?style[attr]:undefined}}else{getElementStyle=function(element,attr){var value=element.style[attr];if(!value&&element.currentStyle){value=element.currentStyle[attr]}return value}}(function(){var style=fabric.document.documentElement.style,selectProp="userSelect"in style?"userSelect":"MozUserSelect"in style?"MozUserSelect":"WebkitUserSelect"in style?"WebkitUserSelect":"KhtmlUserSelect"in style?"KhtmlUserSelect":"";function makeElementUnselectable(element){if(typeof element.onselectstart!=="undefined"){element.onselectstart=fabric.util.falseFunction}if(selectProp){element.style[selectProp]="none"}else if(typeof element.unselectable==="string"){element.unselectable="on"}return element}function makeElementSelectable(element){if(typeof element.onselectstart!=="undefined"){element.onselectstart=null}if(selectProp){element.style[selectProp]=""}else if(typeof element.unselectable==="string"){element.unselectable=""}return element}fabric.util.makeElementUnselectable=makeElementUnselectable;fabric.util.makeElementSelectable=makeElementSelectable})();(function(){function getScript(url,callback){var headEl=fabric.document.getElementsByTagName("head")[0],scriptEl=fabric.document.createElement("script"),loading=true;scriptEl.onload=scriptEl.onreadystatechange=function(e){if(loading){if(typeof this.readyState==="string"&&this.readyState!=="loaded"&&this.readyState!=="complete"){return}loading=false;callback(e||fabric.window.event);scriptEl=scriptEl.onload=scriptEl.onreadystatechange=null}};scriptEl.src=url;headEl.appendChild(scriptEl)}fabric.util.getScript=getScript})();fabric.util.getById=getById;fabric.util.toArray=toArray;fabric.util.makeElement=makeElement;fabric.util.addClass=addClass;fabric.util.wrapElement=wrapElement;fabric.util.getScrollLeftTop=getScrollLeftTop;fabric.util.getElementOffset=getElementOffset;fabric.util.getElementStyle=getElementStyle})();(function(){function addParamToUrl(url,param){return url+(/\?/.test(url)?"&":"?")+param}var makeXHR=function(){var factories=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP.3.0")},function(){return new XMLHttpRequest}];for(var i=factories.length;i--;){try{var req=factories[i]();if(req){return factories[i]}}catch(err){}}}();function emptyFn(){}function request(url,options){options||(options={});var method=options.method?options.method.toUpperCase():"GET",onComplete=options.onComplete||function(){},xhr=makeXHR(),body;xhr.onreadystatechange=function(){if(xhr.readyState===4){onComplete(xhr);xhr.onreadystatechange=emptyFn}};if(method==="GET"){body=null;if(typeof options.parameters==="string"){url=addParamToUrl(url,options.parameters)}}xhr.open(method,url,true);if(method==="POST"||method==="PUT"){xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")}xhr.send(body);return xhr}fabric.util.request=request})();fabric.log=function(){};fabric.warn=function(){};if(typeof console!=="undefined"){["log","warn"].forEach(function(methodName){if(typeof console[methodName]!=="undefined"&&typeof console[methodName].apply==="function"){fabric[methodName]=function(){return console[methodName].apply(console,arguments)}}})}(function(){function animate(options){requestAnimFrame(function(timestamp){options||(options={});var start=timestamp||+new Date,duration=options.duration||500,finish=start+duration,time,onChange=options.onChange||function(){},abort=options.abort||function(){return false},easing=options.easing||function(t,b,c,d){return-c*Math.cos(t/d*(Math.PI/2))+c+b},startValue="startValue"in options?options.startValue:0,endValue="endValue"in options?options.endValue:100,byValue=options.byValue||endValue-startValue;options.onStart&&options.onStart();(function tick(ticktime){time=ticktime||+new Date;var currentTime=time>finish?duration:time-start;if(abort()){options.onComplete&&options.onComplete();return}onChange(easing(currentTime,startValue,byValue,duration));if(time>finish){options.onComplete&&options.onComplete();return}requestAnimFrame(tick)})(start)})}var _requestAnimFrame=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(callback){fabric.window.setTimeout(callback,1e3/60)};function requestAnimFrame(){return _requestAnimFrame.apply(fabric.window,arguments)}fabric.util.animate=animate;fabric.util.requestAnimFrame=requestAnimFrame})();(function(){function normalize(a,c,p,s){if(a1){matrices.shift();combinedMatrix=fabric.util.multiplyTransformMatrices(combinedMatrix,matrices[0])}return combinedMatrix}}();function parseStyleString(style,oStyle){var attr,value;style.replace(/;\s*$/,"").split(";").forEach(function(chunk){var pair=chunk.split(":");attr=normalizeAttr(pair[0].trim().toLowerCase());value=normalizeValue(attr,pair[1].trim());oStyle[attr]=value})}function parseStyleObject(style,oStyle){var attr,value;for(var prop in style){if(typeof style[prop]==="undefined"){continue}attr=normalizeAttr(prop.toLowerCase());value=normalizeValue(attr,style[prop]);oStyle[attr]=value}}function getGlobalStylesForElement(element,svgUid){var styles={};for(var rule in fabric.cssRules[svgUid]){if(elementMatchesRule(element,rule.split(" "))){for(var property in fabric.cssRules[svgUid][rule]){styles[property]=fabric.cssRules[svgUid][rule][property]}}}return styles}function elementMatchesRule(element,selectors){var firstMatching,parentMatching=true;firstMatching=selectorMatches(element,selectors.pop());if(firstMatching&&selectors.length){parentMatching=doesSomeParentMatch(element,selectors)}return firstMatching&&parentMatching&&selectors.length===0}function doesSomeParentMatch(element,selectors){var selector,parentMatching=true;while(element.parentNode&&element.parentNode.nodeType===1&&selectors.length){if(parentMatching){selector=selectors.pop()}element=element.parentNode;parentMatching=selectorMatches(element,selector)}return selectors.length===0}function selectorMatches(element,selector){var nodeName=element.nodeName,classNames=element.getAttribute("class"),id=element.getAttribute("id"),matcher;matcher=new RegExp("^"+nodeName,"i");selector=selector.replace(matcher,"");if(id&&selector.length){matcher=new RegExp("#"+id+"(?![a-zA-Z\\-]+)","i");selector=selector.replace(matcher,"")}if(classNames&&selector.length){classNames=classNames.split(" ");for(var i=classNames.length;i--;){matcher=new RegExp("\\."+classNames[i]+"(?![a-zA-Z\\-]+)","i");selector=selector.replace(matcher,"")}}return selector.length===0}function elementById(doc,id){var el;doc.getElementById&&(el=doc.getElementById(id));if(el){return el}var node,i,nodelist=doc.getElementsByTagName("*");for(i=0;iscaleY?scaleY:scaleX}if(scaleX===1&&scaleY===1&&minX===0&&minY===0&&x===0&&y===0){return parsedDim}if(x||y){translateMatrix=" translate("+parseUnit(x)+" "+parseUnit(y)+") "}matrix=translateMatrix+" matrix("+scaleX+" 0"+" 0 "+scaleY+" "+minX*scaleX+" "+minY*scaleY+") ";if(element.tagName==="svg"){el=element.ownerDocument.createElement("g");while(element.firstChild!=null){el.appendChild(element.firstChild)}element.appendChild(el)}else{el=element;matrix=el.getAttribute("transform")+matrix}el.setAttribute("transform",matrix);return parsedDim}fabric.parseSVGDocument=function(){function hasAncestorWithNodeName(element,nodeName){while(element&&(element=element.parentNode)){if(nodeName.test(element.nodeName)&&!element.getAttribute("instantiated_by_use")){return true}}return false}return function(doc,callback,reviver){if(!doc){return}parseUseDirectives(doc);var startTime=new Date,svgUid=fabric.Object.__uid++,options=applyViewboxTransform(doc),descendants=fabric.util.toArray(doc.getElementsByTagName("*"));options.svgUid=svgUid;if(descendants.length===0&&fabric.isLikelyNode){descendants=doc.selectNodes('//*[name(.)!="svg"]');var arr=[];for(var i=0,len=descendants.length;i\n',' \n \n')}}var reFontDeclaration=new RegExp("(normal|italic)?\\s*(normal|small-caps)?\\s*"+"(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\\s*("+fabric.reNum+"(?:px|cm|mm|em|pt|pc|in)*)(?:\\/(normal|"+fabric.reNum+"))?\\s+(.*)");extend(fabric,{parseFontDeclaration:function(value,oStyle){var match=value.match(reFontDeclaration);if(!match){return}var fontStyle=match[1],fontWeight=match[3],fontSize=match[4],lineHeight=match[5],fontFamily=match[6];if(fontStyle){oStyle.fontStyle=fontStyle}if(fontWeight){oStyle.fontWeight=isNaN(parseFloat(fontWeight))?fontWeight:parseFloat(fontWeight)}if(fontSize){oStyle.fontSize=parseUnit(fontSize)}if(fontFamily){oStyle.fontFamily=fontFamily}if(lineHeight){oStyle.lineHeight=lineHeight==="normal"?1:lineHeight}},getGradientDefs:function(doc){var linearGradientEls=doc.getElementsByTagName("linearGradient"),radialGradientEls=doc.getElementsByTagName("radialGradient"),el,i,j=0,id,xlink,elList=[],gradientDefs={},idsToXlinkMap={};elList.length=linearGradientEls.length+radialGradientEls.length;i=linearGradientEls.length;while(i--){elList[j++]=linearGradientEls[i]}i=radialGradientEls.length;while(i--){elList[j++]=radialGradientEls[i]}while(j--){el=elList[j];xlink=el.getAttribute("xlink:href");id=el.getAttribute("id");if(xlink){idsToXlinkMap[id]=xlink.substr(1)}gradientDefs[id]=el}for(id in idsToXlinkMap){var el2=gradientDefs[idsToXlinkMap[id]].cloneNode(true);el=gradientDefs[id];while(el2.firstChild){el.appendChild(el2.firstChild)}}return gradientDefs},parseAttributes:function(element,attributes,svgUid){if(!element){return}var value,parentAttributes={},fontSize;if(typeof svgUid==="undefined"){svgUid=element.getAttribute("svgUid")}if(element.parentNode&&reAllowedParents.test(element.parentNode.nodeName)){parentAttributes=fabric.parseAttributes(element.parentNode,attributes,svgUid)}fontSize=parentAttributes&&parentAttributes.fontSize||element.getAttribute("font-size")||fabric.Text.DEFAULT_SVG_FONT_SIZE;var ownAttributes=attributes.reduce(function(memo,attr){value=element.getAttribute(attr);if(value){attr=normalizeAttr(attr);value=normalizeValue(attr,value,parentAttributes,fontSize);memo[attr]=value}return memo},{});ownAttributes=extend(ownAttributes,extend(getGlobalStylesForElement(element,svgUid),fabric.parseStyleAttribute(element)));if(ownAttributes.font){fabric.parseFontDeclaration(ownAttributes.font,ownAttributes)}return _setStrokeFillOpacity(extend(parentAttributes,ownAttributes))},parseElements:function(elements,callback,options,reviver){new fabric.ElementsParser(elements,callback,options,reviver).parse()},parseStyleAttribute:function(element){var oStyle={},style=element.getAttribute("style");if(!style){return oStyle}if(typeof style==="string"){parseStyleString(style,oStyle)}else{parseStyleObject(style,oStyle)}return oStyle},parsePointsAttribute:function(points){if(!points){return null}points=points.replace(/,/g," ").trim();points=points.split(/\s+/);var parsedPoints=[],i,len;i=0;len=points.length;for(;i/i,""))}if(!xml||!xml.documentElement){return}fabric.parseSVGDocument(xml.documentElement,function(results,options){svgCache.set(url,{objects:fabric.util.array.invoke(results,"toObject"),options:options});callback(results,options)},reviver)}},loadSVGFromString:function(string,callback,reviver){string=string.trim();var doc;if(typeof DOMParser!=="undefined"){var parser=new DOMParser;if(parser&&parser.parseFromString){doc=parser.parseFromString(string,"text/xml")}}else if(fabric.window.ActiveXObject){doc=new ActiveXObject("Microsoft.XMLDOM");doc.async="false";doc.loadXML(string.replace(//i,""))}fabric.parseSVGDocument(doc.documentElement,function(results,options){callback(results,options)},reviver)},createSVGFontFacesMarkup:function(objects){var markup="",fontList={},obj,fontFamily,style,row,rowIndex,char,charIndex,fontPaths=fabric.fontPaths;for(var i=0,len=objects.length;i',"","\n"].join("")}return markup},createSVGRefElementsMarkup:function(canvas){var markup=[];_createSVGPattern(markup,canvas,"backgroundColor");_createSVGPattern(markup,canvas,"overlayColor");return markup.join("")}})})(typeof exports!=="undefined"?exports:this);fabric.ElementsParser=function(elements,callback,options,reviver){this.elements=elements;this.callback=callback;this.options=options;this.reviver=reviver;this.svgUid=options&&options.svgUid||0};fabric.ElementsParser.prototype.parse=function(){this.instances=new Array(this.elements.length);this.numElements=this.elements.length;this.createObjects()};fabric.ElementsParser.prototype.createObjects=function(){for(var i=0,len=this.elements.length;ithat.x&&this.y>that.y},gte:function(that){return this.x>=that.x&&this.y>=that.y},lerp:function(that,t){return new Point(this.x+(that.x-this.x)*t,this.y+(that.y-this.y)*t)},distanceFrom:function(that){var dx=this.x-that.x,dy=this.y-that.y;return Math.sqrt(dx*dx+dy*dy)},midPointFrom:function(that){return new Point(this.x+(that.x-this.x)/2,this.y+(that.y-this.y)/2)},min:function(that){return new Point(Math.min(this.x,that.x),Math.min(this.y,that.y))},max:function(that){return new Point(Math.max(this.x,that.x),Math.max(this.y,that.y))},toString:function(){return this.x+","+this.y},setXY:function(x,y){this.x=x; -this.y=y},setFromPoint:function(that){this.x=that.x;this.y=that.y},swap:function(that){var x=this.x,y=this.y;this.x=that.x;this.y=that.y;that.x=x;that.y=y}}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={});if(fabric.Intersection){fabric.warn("fabric.Intersection is already defined");return}function Intersection(status){this.status=status;this.points=[]}fabric.Intersection=Intersection;fabric.Intersection.prototype={appendPoint:function(point){this.points.push(point)},appendPoints:function(points){this.points=this.points.concat(points)}};fabric.Intersection.intersectLineLine=function(a1,a2,b1,b2){var result,uaT=(b2.x-b1.x)*(a1.y-b1.y)-(b2.y-b1.y)*(a1.x-b1.x),ubT=(a2.x-a1.x)*(a1.y-b1.y)-(a2.y-a1.y)*(a1.x-b1.x),uB=(b2.y-b1.y)*(a2.x-a1.x)-(b2.x-b1.x)*(a2.y-a1.y);if(uB!==0){var ua=uaT/uB,ub=ubT/uB;if(0<=ua&&ua<=1&&0<=ub&&ub<=1){result=new Intersection("Intersection");result.points.push(new fabric.Point(a1.x+ua*(a2.x-a1.x),a1.y+ua*(a2.y-a1.y)))}else{result=new Intersection}}else{if(uaT===0||ubT===0){result=new Intersection("Coincident")}else{result=new Intersection("Parallel")}}return result};fabric.Intersection.intersectLinePolygon=function(a1,a2,points){var result=new Intersection,length=points.length;for(var i=0;i0){result.status="Intersection"}return result};fabric.Intersection.intersectPolygonPolygon=function(points1,points2){var result=new Intersection,length=points1.length;for(var i=0;i0){result.status="Intersection"}return result};fabric.Intersection.intersectPolygonRectangle=function(points,r1,r2){var min=r1.min(r2),max=r1.max(r2),topRight=new fabric.Point(max.x,min.y),bottomLeft=new fabric.Point(min.x,max.y),inter1=Intersection.intersectLinePolygon(min,topRight,points),inter2=Intersection.intersectLinePolygon(topRight,max,points),inter3=Intersection.intersectLinePolygon(max,bottomLeft,points),inter4=Intersection.intersectLinePolygon(bottomLeft,min,points),result=new Intersection;result.appendPoints(inter1.points);result.appendPoints(inter2.points);result.appendPoints(inter3.points);result.appendPoints(inter4.points);if(result.points.length>0){result.status="Intersection"}return result}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={});if(fabric.Color){fabric.warn("fabric.Color is already defined.");return}function Color(color){if(!color){this.setSource([0,0,0,1])}else{this._tryParsingColor(color)}}fabric.Color=Color;fabric.Color.prototype={_tryParsingColor:function(color){var source;if(color in Color.colorNameMap){color=Color.colorNameMap[color]}if(color==="transparent"){this.setSource([255,255,255,0]);return}source=Color.sourceFromHex(color);if(!source){source=Color.sourceFromRgb(color)}if(!source){source=Color.sourceFromHsl(color)}if(source){this.setSource(source)}},_rgbToHsl:function(r,g,b){r/=255,g/=255,b/=255;var h,s,l,max=fabric.util.array.max([r,g,b]),min=fabric.util.array.min([r,g,b]);l=(max+min)/2;if(max===min){h=s=0}else{var d=max-min;s=l>.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g1){t-=1}if(t<1/6){return p+(q-p)*6*t}if(t<1/2){return q}if(t<2/3){return p+(q-p)*(2/3-t)*6}return p}fabric.Color.fromRgb=function(color){return Color.fromSource(Color.sourceFromRgb(color))};fabric.Color.sourceFromRgb=function(color){var match=color.match(Color.reRGBa);if(match){var r=parseInt(match[1],10)/(/%$/.test(match[1])?100:1)*(/%$/.test(match[1])?255:1),g=parseInt(match[2],10)/(/%$/.test(match[2])?100:1)*(/%$/.test(match[2])?255:1),b=parseInt(match[3],10)/(/%$/.test(match[3])?100:1)*(/%$/.test(match[3])?255:1);return[parseInt(r,10),parseInt(g,10),parseInt(b,10),match[4]?parseFloat(match[4]):1]}};fabric.Color.fromRgba=Color.fromRgb;fabric.Color.fromHsl=function(color){return Color.fromSource(Color.sourceFromHsl(color))};fabric.Color.sourceFromHsl=function(color){var match=color.match(Color.reHSLa);if(!match){return}var h=(parseFloat(match[1])%360+360)%360/360,s=parseFloat(match[2])/(/%$/.test(match[2])?100:1),l=parseFloat(match[3])/(/%$/.test(match[3])?100:1),r,g,b;if(s===0){r=g=b=l}else{var q=l<=.5?l*(s+1):l+s-l*s,p=l*2-q;r=hue2rgb(p,q,h+1/3);g=hue2rgb(p,q,h);b=hue2rgb(p,q,h-1/3)}return[Math.round(r*255),Math.round(g*255),Math.round(b*255),match[4]?parseFloat(match[4]):1]};fabric.Color.fromHsla=Color.fromHsl;fabric.Color.fromHex=function(color){return Color.fromSource(Color.sourceFromHex(color))};fabric.Color.sourceFromHex=function(color){if(color.match(Color.reHex)){var value=color.slice(color.indexOf("#")+1),isShortNotation=value.length===3,r=isShortNotation?value.charAt(0)+value.charAt(0):value.substring(0,2),g=isShortNotation?value.charAt(1)+value.charAt(1):value.substring(2,4),b=isShortNotation?value.charAt(2)+value.charAt(2):value.substring(4,6);return[parseInt(r,16),parseInt(g,16),parseInt(b,16),1]}};fabric.Color.fromSource=function(source){var oColor=new Color;oColor.setSource(source);return oColor}})(typeof exports!=="undefined"?exports:this);(function(){function getColorStop(el){var style=el.getAttribute("style"),offset=el.getAttribute("offset")||0,color,colorAlpha,opacity;offset=parseFloat(offset)/(/%$/.test(offset)?100:1);offset=offset<0?0:offset>1?1:offset;if(style){var keyValuePairs=style.split(/\s*;\s*/);if(keyValuePairs[keyValuePairs.length-1]===""){keyValuePairs.pop()}for(var i=keyValuePairs.length;i--;){var split=keyValuePairs[i].split(/\s*:\s*/),key=split[0].trim(),value=split[1].trim();if(key==="stop-color"){color=value}else if(key==="stop-opacity"){opacity=value}}}if(!color){color=el.getAttribute("stop-color")||"rgb(0,0,0)"}if(!opacity){opacity=el.getAttribute("stop-opacity")}color=new fabric.Color(color);colorAlpha=color.getAlpha();opacity=isNaN(parseFloat(opacity))?1:parseFloat(opacity);opacity*=colorAlpha;return{offset:offset,color:color.toRgb(),opacity:opacity}}function getLinearCoords(el){return{x1:el.getAttribute("x1")||0,y1:el.getAttribute("y1")||0,x2:el.getAttribute("x2")||"100%",y2:el.getAttribute("y2")||0}}function getRadialCoords(el){return{x1:el.getAttribute("fx")||el.getAttribute("cx")||"50%",y1:el.getAttribute("fy")||el.getAttribute("cy")||"50%",r1:0,x2:el.getAttribute("cx")||"50%",y2:el.getAttribute("cy")||"50%",r2:el.getAttribute("r")||"50%"}}fabric.Gradient=fabric.util.createClass({offsetX:0,offsetY:0,initialize:function(options){options||(options={});var coords={};this.id=fabric.Object.__uid++;this.type=options.type||"linear";coords={x1:options.coords.x1||0,y1:options.coords.y1||0,x2:options.coords.x2||0,y2:options.coords.y2||0};if(this.type==="radial"){coords.r1=options.coords.r1||0;coords.r2=options.coords.r2||0}this.coords=coords;this.colorStops=options.colorStops.slice();if(options.gradientTransform){this.gradientTransform=options.gradientTransform}this.offsetX=options.offsetX||this.offsetX;this.offsetY=options.offsetY||this.offsetY},addColorStop:function(colorStop){for(var position in colorStop){var color=new fabric.Color(colorStop[position]);this.colorStops.push({offset:position,color:color.toRgb(),opacity:color.getAlpha()})}return this},toObject:function(){return{type:this.type,coords:this.coords,colorStops:this.colorStops,offsetX:this.offsetX,offsetY:this.offsetY,gradientTransform:this.gradientTransform?this.gradientTransform.concat():this.gradientTransform}},toSVG:function(object){var coords=fabric.util.object.clone(this.coords),markup,commonAttributes;this.colorStops.sort(function(a,b){return a.offset-b.offset});if(!(object.group&&object.group.type==="path-group")){for(var prop in coords){if(prop==="x1"||prop==="x2"||prop==="r2"){coords[prop]+=this.offsetX-object.width/2}else if(prop==="y1"||prop==="y2"){coords[prop]+=this.offsetY-object.height/2}}}commonAttributes='id="SVGID_'+this.id+'" gradientUnits="userSpaceOnUse"';if(this.gradientTransform){commonAttributes+=' gradientTransform="matrix('+this.gradientTransform.join(" ")+')" '}if(this.type==="linear"){markup=["\n']}else if(this.type==="radial"){markup=["\n']}for(var i=0;i\n')}markup.push(this.type==="linear"?"\n":"\n");return markup.join("")},toLive:function(ctx,object){var gradient,prop,coords=fabric.util.object.clone(this.coords);if(!this.type){return}if(object.group&&object.group.type==="path-group"){for(prop in coords){if(prop==="x1"||prop==="x2"){coords[prop]+=-this.offsetX+object.width/2}else if(prop==="y1"||prop==="y2"){coords[prop]+=-this.offsetY+object.height/2}}}if(this.type==="linear"){gradient=ctx.createLinearGradient(coords.x1,coords.y1,coords.x2,coords.y2)}else if(this.type==="radial"){gradient=ctx.createRadialGradient(coords.x1,coords.y1,coords.r1,coords.x2,coords.y2,coords.r2)}for(var i=0,len=this.colorStops.length;i\n'+'\n'+"\n"},toLive:function(ctx){var source=typeof this.source==="function"?this.source():this.source;if(!source){return""}if(typeof source.src!=="undefined"){if(!source.complete){return""}if(source.naturalWidth===0||source.naturalHeight===0){return""}}return ctx.createPattern(source,this.repeat)}});(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),toFixed=fabric.util.toFixed;if(fabric.Shadow){fabric.warn("fabric.Shadow is already defined.");return}fabric.Shadow=fabric.util.createClass({color:"rgb(0,0,0)",blur:0,offsetX:0,offsetY:0,affectStroke:false,includeDefaultValues:true,initialize:function(options){if(typeof options==="string"){options=this._parseShadow(options)}for(var prop in options){this[prop]=options[prop]}this.id=fabric.Object.__uid++},_parseShadow:function(shadow){var shadowStr=shadow.trim(),offsetsAndBlur=fabric.Shadow.reOffsetsAndBlur.exec(shadowStr)||[],color=shadowStr.replace(fabric.Shadow.reOffsetsAndBlur,"")||"rgb(0,0,0)";return{color:color.trim(),offsetX:parseInt(offsetsAndBlur[1],10)||0,offsetY:parseInt(offsetsAndBlur[2],10)||0,blur:parseInt(offsetsAndBlur[3],10)||0}},toString:function(){return[this.offsetX,this.offsetY,this.blur,this.color].join("px ")},toSVG:function(object){var fBoxX=40,fBoxY=40,NUM_FRACTION_DIGITS=fabric.Object.NUM_FRACTION_DIGITS,offset=fabric.util.rotateVector({x:this.offsetX,y:this.offsetY},fabric.util.degreesToRadians(-object.angle)),BLUR_BOX=20;if(object.width&&object.height){fBoxX=toFixed((Math.abs(offset.x)+this.blur)/object.width,NUM_FRACTION_DIGITS)*100+BLUR_BOX;fBoxY=toFixed((Math.abs(offset.y)+this.blur)/object.height,NUM_FRACTION_DIGITS)*100+BLUR_BOX}if(object.flipX){offset.x*=-1}if(object.flipY){offset.y*=-1}return'\n"+' \n'+' \n'+' \n'+' \n'+" \n"+" \n"+' \n'+" \n"+"\n"},toObject:function(){if(this.includeDefaultValues){return{color:this.color,blur:this.blur,offsetX:this.offsetX,offsetY:this.offsetY,affectStroke:this.affectStroke}}var obj={},proto=fabric.Shadow.prototype;["color","blur","offsetX","offsetY","affectStroke"].forEach(function(prop){if(this[prop]!==proto[prop]){obj[prop]=this[prop]}},this);return obj}});fabric.Shadow.reOffsetsAndBlur=/(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/})(typeof exports!=="undefined"?exports:this);(function(){"use strict";if(fabric.StaticCanvas){fabric.warn("fabric.StaticCanvas is already defined.");return}var extend=fabric.util.object.extend,getElementOffset=fabric.util.getElementOffset,removeFromArray=fabric.util.removeFromArray,toFixed=fabric.util.toFixed,CANVAS_INIT_ERROR=new Error("Could not initialize `canvas` element");fabric.StaticCanvas=fabric.util.createClass({initialize:function(el,options){options||(options={});this._initStatic(el,options)},backgroundColor:"",backgroundImage:null,overlayColor:"",overlayImage:null,includeDefaultValues:true,stateful:true,renderOnAddRemove:true,clipTo:null,controlsAboveOverlay:false,allowTouchScrolling:false,imageSmoothingEnabled:true,preserveObjectStacking:false,viewportTransform:[1,0,0,1,0,0],onBeforeScaleRotate:function(){},enableRetinaScaling:true,_initStatic:function(el,options){this._objects=[];this._createLowerCanvas(el);this._initOptions(options);this._setImageSmoothing();if(!this.interactive){this._initRetinaScaling()}if(options.overlayImage){this.setOverlayImage(options.overlayImage,this.renderAll.bind(this))}if(options.backgroundImage){this.setBackgroundImage(options.backgroundImage,this.renderAll.bind(this))}if(options.backgroundColor){this.setBackgroundColor(options.backgroundColor,this.renderAll.bind(this))}if(options.overlayColor){this.setOverlayColor(options.overlayColor,this.renderAll.bind(this))}this.calcOffset()},_isRetinaScaling:function(){return fabric.devicePixelRatio!==1&&this.enableRetinaScaling},_initRetinaScaling:function(){if(!this._isRetinaScaling()){return}this.lowerCanvasEl.setAttribute("width",this.width*fabric.devicePixelRatio);this.lowerCanvasEl.setAttribute("height",this.height*fabric.devicePixelRatio);this.contextContainer.scale(fabric.devicePixelRatio,fabric.devicePixelRatio)},calcOffset:function(){this._offset=getElementOffset(this.lowerCanvasEl);return this},setOverlayImage:function(image,callback,options){return this.__setBgOverlayImage("overlayImage",image,callback,options)},setBackgroundImage:function(image,callback,options){return this.__setBgOverlayImage("backgroundImage",image,callback,options)},setOverlayColor:function(overlayColor,callback){return this.__setBgOverlayColor("overlayColor",overlayColor,callback)},setBackgroundColor:function(backgroundColor,callback){return this.__setBgOverlayColor("backgroundColor",backgroundColor,callback)},_setImageSmoothing:function(){var ctx=this.getContext();if(typeof ctx.imageSmoothingEnabled!=="undefined"){ctx.imageSmoothingEnabled=this.imageSmoothingEnabled;return}ctx.webkitImageSmoothingEnabled=this.imageSmoothingEnabled;ctx.mozImageSmoothingEnabled=this.imageSmoothingEnabled;ctx.msImageSmoothingEnabled=this.imageSmoothingEnabled;ctx.oImageSmoothingEnabled=this.imageSmoothingEnabled},__setBgOverlayImage:function(property,image,callback,options){if(typeof image==="string"){fabric.util.loadImage(image,function(img){this[property]=new fabric.Image(img,options);callback&&callback(img)},this,options&&options.crossOrigin)}else{options&&image.setOptions(options);this[property]=image;callback&&callback(image)}return this},__setBgOverlayColor:function(property,color,callback){if(color&&color.source){var _this=this;fabric.util.loadImage(color.source,function(img){_this[property]=new fabric.Pattern({source:img,repeat:color.repeat,offsetX:color.offsetX,offsetY:color.offsetY});callback&&callback()})}else{this[property]=color;callback&&callback()}return this},_createCanvasElement:function(){var element=fabric.document.createElement("canvas");if(!element.style){element.style={}}if(!element){throw CANVAS_INIT_ERROR}this._initCanvasElement(element);return element},_initCanvasElement:function(element){fabric.util.createCanvasElement(element);if(typeof element.getContext==="undefined"){throw CANVAS_INIT_ERROR}},_initOptions:function(options){for(var prop in options){this[prop]=options[prop]}this.width=this.width||parseInt(this.lowerCanvasEl.width,10)||0;this.height=this.height||parseInt(this.lowerCanvasEl.height,10)||0;if(!this.lowerCanvasEl.style){return}this.lowerCanvasEl.width=this.width;this.lowerCanvasEl.height=this.height;this.lowerCanvasEl.style.width=this.width+"px";this.lowerCanvasEl.style.height=this.height+"px";this.viewportTransform=this.viewportTransform.slice()},_createLowerCanvas:function(canvasEl){this.lowerCanvasEl=fabric.util.getById(canvasEl)||this._createCanvasElement();this._initCanvasElement(this.lowerCanvasEl);fabric.util.addClass(this.lowerCanvasEl,"lower-canvas");if(this.interactive){this._applyCanvasStyle(this.lowerCanvasEl)}this.contextContainer=this.lowerCanvasEl.getContext("2d")},getWidth:function(){return this.width},getHeight:function(){return this.height},setWidth:function(value,options){return this.setDimensions({width:value},options)},setHeight:function(value,options){return this.setDimensions({height:value},options)},setDimensions:function(dimensions,options){var cssValue;options=options||{};for(var prop in dimensions){cssValue=dimensions[prop];if(!options.cssOnly){this._setBackstoreDimension(prop,dimensions[prop]);cssValue+="px"}if(!options.backstoreOnly){this._setCssDimension(prop,cssValue)}}this._initRetinaScaling();this._setImageSmoothing();this.calcOffset();if(!options.cssOnly){this.renderAll()}return this},_setBackstoreDimension:function(prop,value){this.lowerCanvasEl[prop]=value;if(this.upperCanvasEl){this.upperCanvasEl[prop]=value}if(this.cacheCanvasEl){this.cacheCanvasEl[prop]=value}this[prop]=value;return this},_setCssDimension:function(prop,value){this.lowerCanvasEl.style[prop]=value;if(this.upperCanvasEl){this.upperCanvasEl.style[prop]=value}if(this.wrapperEl){this.wrapperEl.style[prop]=value}return this},getZoom:function(){return Math.sqrt(this.viewportTransform[0]*this.viewportTransform[3])},setViewportTransform:function(vpt){var activeGroup=this.getActiveGroup();this.viewportTransform=vpt;this.renderAll();for(var i=0,len=this._objects.length;i");return markup.join("")},_setSVGPreamble:function(markup,options){if(options.suppressPreamble){return}markup.push('\n','\n')},_setSVGHeader:function(markup,options){var width=options.width||this.width,height=options.height||this.height,vpt,viewBox='viewBox="0 0 '+this.width+" "+this.height+'" ',NUM_FRACTION_DIGITS=fabric.Object.NUM_FRACTION_DIGITS;if(options.viewBox){viewBox='viewBox="'+options.viewBox.x+" "+options.viewBox.y+" "+options.viewBox.width+" "+options.viewBox.height+'" '}else{if(this.svgViewportTransformation){vpt=this.viewportTransform;viewBox='viewBox="'+toFixed(-vpt[4]/vpt[0],NUM_FRACTION_DIGITS)+" "+toFixed(-vpt[5]/vpt[3],NUM_FRACTION_DIGITS)+" "+toFixed(this.width/vpt[0],NUM_FRACTION_DIGITS)+" "+toFixed(this.height/vpt[3],NUM_FRACTION_DIGITS)+'" '}}markup.push("\n',"Created with Fabric.js ",fabric.version,"\n","",fabric.createSVGFontFacesMarkup(this.getObjects()),fabric.createSVGRefElementsMarkup(this),"\n")},_setSVGObjects:function(markup,reviver){for(var i=0,objects=this.getObjects(),len=objects.length;i\n")}else if(this[property]&&property==="overlayColor"){markup.push('\n")}},sendToBack:function(object){removeFromArray(this._objects,object);this._objects.unshift(object);return this.renderAll&&this.renderAll()},bringToFront:function(object){removeFromArray(this._objects,object);this._objects.push(object);return this.renderAll&&this.renderAll()},sendBackwards:function(object,intersecting){var idx=this._objects.indexOf(object);if(idx!==0){var newIdx=this._findNewLowerIndex(object,idx,intersecting);removeFromArray(this._objects,object);this._objects.splice(newIdx,0,object);this.renderAll&&this.renderAll()}return this},_findNewLowerIndex:function(object,idx,intersecting){var newIdx;if(intersecting){newIdx=idx;for(var i=idx-1;i>=0;--i){var isIntersecting=object.intersectsWithObject(this._objects[i])||object.isContainedWithinObject(this._objects[i])||this._objects[i].isContainedWithinObject(object);if(isIntersecting){newIdx=i;break}}}else{newIdx=idx-1}return newIdx},bringForward:function(object,intersecting){var idx=this._objects.indexOf(object);if(idx!==this._objects.length-1){var newIdx=this._findNewUpperIndex(object,idx,intersecting);removeFromArray(this._objects,object);this._objects.splice(newIdx,0,object);this.renderAll&&this.renderAll()}return this},_findNewUpperIndex:function(object,idx,intersecting){var newIdx;if(intersecting){newIdx=idx;for(var i=idx+1;i"}});extend(fabric.StaticCanvas.prototype,fabric.Observable);extend(fabric.StaticCanvas.prototype,fabric.Collection);extend(fabric.StaticCanvas.prototype,fabric.DataURLExporter);extend(fabric.StaticCanvas,{EMPTY_JSON:'{"objects": [], "background": "white"}',supports:function(methodName){var el=fabric.util.createCanvasElement();if(!el||!el.getContext){return null}var ctx=el.getContext("2d");if(!ctx){return null}switch(methodName){case"getImageData":return typeof ctx.getImageData!=="undefined";case"setLineDash":return typeof ctx.setLineDash!=="undefined";case"toDataURL":return typeof el.toDataURL!=="undefined";case"toDataURLWithQuality":try{el.toDataURL("image/jpeg",0);return true}catch(e){}return false;default:return null}}});fabric.StaticCanvas.prototype.toJSON=fabric.StaticCanvas.prototype.toObject})();fabric.BaseBrush=fabric.util.createClass({color:"rgb(0, 0, 0)",width:1,shadow:null,strokeLineCap:"round",strokeLineJoin:"round",strokeDashArray:null,setShadow:function(options){this.shadow=new fabric.Shadow(options);return this},_setBrushStyles:function(){var ctx=this.canvas.contextTop;ctx.strokeStyle=this.color;ctx.lineWidth=this.width;ctx.lineCap=this.strokeLineCap;ctx.lineJoin=this.strokeLineJoin;if(this.strokeDashArray&&fabric.StaticCanvas.supports("setLineDash")){ctx.setLineDash(this.strokeDashArray)}},_setShadow:function(){if(!this.shadow){return}var ctx=this.canvas.contextTop;ctx.shadowColor=this.shadow.color;ctx.shadowBlur=this.shadow.blur;ctx.shadowOffsetX=this.shadow.offsetX;ctx.shadowOffsetY=this.shadow.offsetY},_resetShadow:function(){var ctx=this.canvas.contextTop;ctx.shadowColor="";ctx.shadowBlur=ctx.shadowOffsetX=ctx.shadowOffsetY=0}});(function(){fabric.PencilBrush=fabric.util.createClass(fabric.BaseBrush,{initialize:function(canvas){this.canvas=canvas;this._points=[]},onMouseDown:function(pointer){this._prepareForDrawing(pointer);this._captureDrawingPath(pointer);this._render()},onMouseMove:function(pointer){this._captureDrawingPath(pointer);this.canvas.clearContext(this.canvas.contextTop);this._render()},onMouseUp:function(){this._finalizeAndAddPath()},_prepareForDrawing:function(pointer){var p=new fabric.Point(pointer.x,pointer.y);this._reset();this._addPoint(p);this.canvas.contextTop.moveTo(p.x,p.y)},_addPoint:function(point){this._points.push(point)},_reset:function(){this._points.length=0;this._setBrushStyles();this._setShadow()},_captureDrawingPath:function(pointer){var pointerPoint=new fabric.Point(pointer.x,pointer.y);this._addPoint(pointerPoint)},_render:function(){var ctx=this.canvas.contextTop,v=this.canvas.viewportTransform,p1=this._points[0],p2=this._points[1];ctx.save();ctx.transform(v[0],v[1],v[2],v[3],v[4],v[5]);ctx.beginPath();if(this._points.length===2&&p1.x===p2.x&&p1.y===p2.y){p1.x-=.5;p2.x+=.5}ctx.moveTo(p1.x,p1.y);for(var i=1,len=this._points.length;i0?1:-1;if(by==="y"){skew=t.target.skewY;originA="top";originB="bottom";property="originY"}origins[-1]=originA;origins[1]=originB;t.target.flipX&&(flipSign*=-1);t.target.flipY&&(flipSign*=-1);if(skew===0){t.skewSign=-corner*mouseMove*flipSign;t[property]=origins[-mouseMove]}else{skew=skew>0?1:-1;t.skewSign=skew;t[property]=origins[skew*corner*flipSign]}},_skewObject:function(x,y,by){var t=this._currentTransform,target=t.target,lockSkewingX=target.get("lockSkewingX"),lockSkewingY=target.get("lockSkewingY");if(lockSkewingX&&by==="x"||lockSkewingY&&by==="y"){return}var center=target.getCenterPoint(),actualMouseByCenter=target.toLocalPoint(new fabric.Point(x,y),"center","center")[by],lastMouseByCenter=target.toLocalPoint(new fabric.Point(t.lastX,t.lastY),"center","center")[by],actualMouseByOrigin,constraintPosition,dim=target._getTransformedDimensions();this._changeSkewTransformOrigin(actualMouseByCenter-lastMouseByCenter,t,by);actualMouseByOrigin=target.toLocalPoint(new fabric.Point(x,y),t.originX,t.originY)[by],constraintPosition=target.translateToOriginPoint(center,t.originX,t.originY);this._setObjectSkew(actualMouseByOrigin,t,by,dim);t.lastX=x;t.lastY=y;target.setPositionByOrigin(constraintPosition,t.originX,t.originY)},_setObjectSkew:function(localMouse,transform,by,_dim){var target=transform.target,newValue,skewSign=transform.skewSign,newDim,dimNoSkew,otherBy,_otherBy,_by,newDimMouse,skewX,skewY;if(by==="x"){otherBy="y";_otherBy="Y";_by="X";skewX=0;skewY=target.skewY}else{otherBy="x";_otherBy="X";_by="Y";skewX=target.skewX;skewY=0}dimNoSkew=target._getTransformedDimensions(skewX,skewY);newDimMouse=2*Math.abs(localMouse)-dimNoSkew[by];if(newDimMouse<=2){newValue=0}else{newValue=skewSign*Math.atan(newDimMouse/target["scale"+_by]/(dimNoSkew[otherBy]/target["scale"+_otherBy]));newValue=fabric.util.radiansToDegrees(newValue)}target.set("skew"+_by,newValue);if(target["skew"+_otherBy]!==0){newDim=target._getTransformedDimensions();newValue=_dim[otherBy]/newDim[otherBy]*target["scale"+_otherBy];target.set("scale"+_otherBy,newValue)}},_scaleObject:function(x,y,by){var t=this._currentTransform,target=t.target,lockScalingX=target.get("lockScalingX"),lockScalingY=target.get("lockScalingY"),lockScalingFlip=target.get("lockScalingFlip");if(lockScalingX&&lockScalingY){return}var constraintPosition=target.translateToOriginPoint(target.getCenterPoint(),t.originX,t.originY),localMouse=target.toLocalPoint(new fabric.Point(x,y),t.originX,t.originY),dim=target._getTransformedDimensions();this._setLocalMouse(localMouse,t);this._setObjectScale(localMouse,t,lockScalingX,lockScalingY,by,lockScalingFlip,dim);target.setPositionByOrigin(constraintPosition,t.originX,t.originY)},_setObjectScale:function(localMouse,transform,lockScalingX,lockScalingY,by,lockScalingFlip,_dim){var target=transform.target,forbidScalingX=false,forbidScalingY=false;transform.newScaleX=localMouse.x*target.scaleX/_dim.x;transform.newScaleY=localMouse.y*target.scaleY/_dim.y;if(lockScalingFlip&&transform.newScaleX<=0&&transform.newScaleXtarget.padding){if(localMouse.x<0){localMouse.x+=target.padding}else{localMouse.x-=target.padding}}else{localMouse.x=0}if(abs(localMouse.y)>target.padding){if(localMouse.y<0){localMouse.y+=target.padding}else{localMouse.y-=target.padding}}else{localMouse.y=0}},_rotateObject:function(x,y){var t=this._currentTransform;if(t.target.get("lockRotation")){return}var lastAngle=atan2(t.ey-t.top,t.ex-t.left),curAngle=atan2(y-t.top,x-t.left),angle=radiansToDegrees(curAngle-lastAngle+t.theta);if(angle<0){angle=360+angle}t.target.angle=angle%360},setCursor:function(value){this.upperCanvasEl.style.cursor=value},_resetObjectTransform:function(target){target.scaleX=1;target.scaleY=1;target.skewX=0;target.skewY=0;target.setAngle(0)},_drawSelection:function(){var ctx=this.contextTop,groupSelector=this._groupSelector,left=groupSelector.left,top=groupSelector.top,aleft=abs(left),atop=abs(top);ctx.fillStyle=this.selectionColor;ctx.fillRect(groupSelector.ex-(left>0?0:-left),groupSelector.ey-(top>0?0:-top),aleft,atop);ctx.lineWidth=this.selectionLineWidth;ctx.strokeStyle=this.selectionBorderColor;if(this.selectionDashArray.length>1){var px=groupSelector.ex+STROKE_OFFSET-(left>0?0:aleft),py=groupSelector.ey+STROKE_OFFSET-(top>0?0:atop);ctx.beginPath();fabric.util.drawDashedLine(ctx,px,py,px+aleft,py,this.selectionDashArray);fabric.util.drawDashedLine(ctx,px,py+atop-1,px+aleft,py+atop-1,this.selectionDashArray);fabric.util.drawDashedLine(ctx,px,py,px,py+atop,this.selectionDashArray);fabric.util.drawDashedLine(ctx,px+aleft-1,py,px+aleft-1,py+atop,this.selectionDashArray);ctx.closePath();ctx.stroke()}else{ctx.strokeRect(groupSelector.ex+STROKE_OFFSET-(left>0?0:aleft),groupSelector.ey+STROKE_OFFSET-(top>0?0:atop),aleft,atop)}},_isLastRenderedObject:function(e){return this.controlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay.visible&&this.containsPoint(e,this.lastRenderedObjectWithControlsAboveOverlay)&&this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(this.getPointer(e,true))},findTarget:function(e,skipGroup){if(this.skipTargetFind){return}if(this._isLastRenderedObject(e)){return this.lastRenderedObjectWithControlsAboveOverlay}var activeGroup=this.getActiveGroup();if(activeGroup&&!skipGroup&&this.containsPoint(e,activeGroup)){return activeGroup}var target=this._searchPossibleTargets(e,skipGroup);this._fireOverOutEvents(target,e);return target},_fireOverOutEvents:function(target,e){if(target){if(this._hoveredTarget!==target){if(this._hoveredTarget){this.fire("mouse:out",{target:this._hoveredTarget,e:e});this._hoveredTarget.fire("mouseout")}this.fire("mouse:over",{target:target,e:e});target.fire("mouseover");this._hoveredTarget=target}}else if(this._hoveredTarget){this.fire("mouse:out",{target:this._hoveredTarget,e:e});this._hoveredTarget.fire("mouseout");this._hoveredTarget=null}},_checkTarget:function(e,obj,pointer){if(obj&&obj.visible&&obj.evented&&this.containsPoint(e,obj)){if((this.perPixelTargetFind||obj.perPixelTargetFind)&&!obj.isEditing){var isTransparent=this.isTargetTransparent(obj,pointer.x,pointer.y);if(!isTransparent){return true}}else{return true}}},_searchPossibleTargets:function(e,skipGroup){var target,pointer=this.getPointer(e,true),i=this._objects.length;while(i--){if((!this._objects[i].group||skipGroup)&&this._checkTarget(e,this._objects[i],pointer)){this.relatedTarget=this._objects[i];target=this._objects[i];break}}return target},getPointer:function(e,ignoreZoom,upperCanvasEl){if(!upperCanvasEl){upperCanvasEl=this.upperCanvasEl}var pointer=getPointer(e),bounds=upperCanvasEl.getBoundingClientRect(),boundsWidth=bounds.width||0,boundsHeight=bounds.height||0,cssScale;if(!boundsWidth||!boundsHeight){if("top"in bounds&&"bottom"in bounds){boundsHeight=Math.abs(bounds.top-bounds.bottom)}if("right"in bounds&&"left"in bounds){boundsWidth=Math.abs(bounds.right-bounds.left)}}this.calcOffset();pointer.x=pointer.x-this._offset.left;pointer.y=pointer.y-this._offset.top;if(!ignoreZoom){pointer=fabric.util.transformPoint(pointer,fabric.util.invertTransform(this.viewportTransform))}if(boundsWidth===0||boundsHeight===0){cssScale={width:1,height:1}}else{cssScale={width:upperCanvasEl.width/boundsWidth,height:upperCanvasEl.height/boundsHeight}}return{x:pointer.x*cssScale.width,y:pointer.y*cssScale.height}},_createUpperCanvas:function(){var lowerCanvasClass=this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/,"");this.upperCanvasEl=this._createCanvasElement();fabric.util.addClass(this.upperCanvasEl,"upper-canvas "+lowerCanvasClass);this.wrapperEl.appendChild(this.upperCanvasEl);this._copyCanvasStyle(this.lowerCanvasEl,this.upperCanvasEl);this._applyCanvasStyle(this.upperCanvasEl);this.contextTop=this.upperCanvasEl.getContext("2d")},_createCacheCanvas:function(){this.cacheCanvasEl=this._createCanvasElement();this.cacheCanvasEl.setAttribute("width",this.width);this.cacheCanvasEl.setAttribute("height",this.height);this.contextCache=this.cacheCanvasEl.getContext("2d")},_initWrapperElement:function(){this.wrapperEl=fabric.util.wrapElement(this.lowerCanvasEl,"div",{"class":this.containerClass});fabric.util.setStyle(this.wrapperEl,{width:this.getWidth()+"px",height:this.getHeight()+"px",position:"relative"});fabric.util.makeElementUnselectable(this.wrapperEl)},_applyCanvasStyle:function(element){var width=this.getWidth()||element.width,height=this.getHeight()||element.height;fabric.util.setStyle(element,{position:"absolute",width:width+"px",height:height+"px",left:0,top:0});element.width=width;element.height=height;fabric.util.makeElementUnselectable(element)},_copyCanvasStyle:function(fromEl,toEl){toEl.style.cssText=fromEl.style.cssText},getSelectionContext:function(){return this.contextTop},getSelectionElement:function(){return this.upperCanvasEl},_setActiveObject:function(object){if(this._activeObject){this._activeObject.set("active",false)}this._activeObject=object;object.set("active",true)},setActiveObject:function(object,e){this._setActiveObject(object);this.renderAll();this.fire("object:selected",{target:object,e:e});object.fire("selected",{e:e});return this},getActiveObject:function(){return this._activeObject},_discardActiveObject:function(){if(this._activeObject){this._activeObject.set("active",false)}this._activeObject=null},discardActiveObject:function(e){this._discardActiveObject();this.renderAll();this.fire("selection:cleared",{e:e});return this},_setActiveGroup:function(group){this._activeGroup=group;if(group){group.set("active",true)}},setActiveGroup:function(group,e){this._setActiveGroup(group);if(group){this.fire("object:selected",{target:group,e:e});group.fire("selected",{e:e})}return this},getActiveGroup:function(){return this._activeGroup},_discardActiveGroup:function(){var g=this.getActiveGroup();if(g){g.destroy()}this.setActiveGroup(null)},discardActiveGroup:function(e){this._discardActiveGroup();this.fire("selection:cleared",{e:e});return this},deactivateAll:function(){var allObjects=this.getObjects(),i=0,len=allObjects.length;for(;i1){return}var groupSelector=this._groupSelector;if(groupSelector){pointer=this.getPointer(e,true);groupSelector.left=pointer.x-groupSelector.ex;groupSelector.top=pointer.y-groupSelector.ey;this.renderTop()}else if(!this._currentTransform){target=this.findTarget(e);if(!target||target&&!target.selectable){this.setCursor(this.defaultCursor)}else{this._setCursorFromEvent(e,target)}}else{this._transformObject(e)}this.fire("mouse:move",{target:target,e:e});target&&target.fire("mousemove",{e:e})},_transformObject:function(e){var pointer=this.getPointer(e),transform=this._currentTransform;transform.reset=false,transform.target.isMoving=true;this._beforeScaleTransform(e,transform);this._performTransformAction(e,transform,pointer);this.renderAll()},_performTransformAction:function(e,transform,pointer){var x=pointer.x,y=pointer.y,target=transform.target,action=transform.action;if(action==="rotate"){this._rotateObject(x,y);this._fire("rotating",target,e)}else if(action==="scale"){this._onScale(e,transform,x,y);this._fire("scaling",target,e)}else if(action==="scaleX"){this._scaleObject(x,y,"x");this._fire("scaling",target,e)}else if(action==="scaleY"){this._scaleObject(x,y,"y");this._fire("scaling",target,e)}else if(action==="skewX"){this._skewObject(x,y,"x");this._fire("skewing",target,e)}else if(action==="skewY"){this._skewObject(x,y,"y");this._fire("skewing",target,e)}else{this._translateObject(x,y);this._fire("moving",target,e);this.setCursor(this.moveCursor)}},_fire:function(eventName,target,e){this.fire("object:"+eventName,{target:target,e:e});target.fire(eventName,{e:e})},_beforeScaleTransform:function(e,transform){if(transform.action==="scale"||transform.action==="scaleX"||transform.action==="scaleY"){var centerTransform=this._shouldCenterTransform(transform.target);if(centerTransform&&(transform.originX!=="center"||transform.originY!=="center")||!centerTransform&&transform.originX==="center"&&transform.originY==="center"){this._resetCurrentTransform();transform.reset=true}}},_onScale:function(e,transform,x,y){if((e.shiftKey||this.uniScaleTransform)&&!transform.target.get("lockUniScaling")){transform.currentAction="scale";this._scaleObject(x,y)}else{if(!transform.reset&&transform.currentAction==="scale"){this._resetCurrentTransform()}transform.currentAction="scaleEqually";this._scaleObject(x,y,"equally")}},_setCursorFromEvent:function(e,target){if(!target||!target.selectable){this.setCursor(this.defaultCursor);return false}else{var activeGroup=this.getActiveGroup(),corner=target._findTargetCorner&&(!activeGroup||!activeGroup.contains(target))&&target._findTargetCorner(this.getPointer(e,true));if(!corner){this.setCursor(target.hoverCursor||this.hoverCursor)}else{this._setCornerCursor(corner,target,e)}}return true},_setCornerCursor:function(corner,target,e){if(corner in cursorOffset){this.setCursor(this._getRotatedCornerCursor(corner,target,e))}else if(corner==="mtr"&&target.hasRotatingPoint){this.setCursor(this.rotationCursor)}else{this.setCursor(this.defaultCursor);return false}},_getRotatedCornerCursor:function(corner,target,e){var n=Math.round(target.getAngle()%360/45);if(n<0){n+=8}n+=cursorOffset[corner];if(e.shiftKey&&cursorOffset[corner]%2===0){n+=2}n%=8;return this.cursorMap[n]}})})();(function(){var min=Math.min,max=Math.max;fabric.util.object.extend(fabric.Canvas.prototype,{_shouldGroup:function(e,target){var activeObject=this.getActiveObject();return e.shiftKey&&target&&target.selectable&&(this.getActiveGroup()||activeObject&&activeObject!==target)&&this.selection},_handleGrouping:function(e,target){if(target===this.getActiveGroup()){target=this.findTarget(e,true);if(!target||target.isType("group")){return}}if(this.getActiveGroup()){this._updateActiveGroup(target,e)}else{this._createActiveGroup(target,e)}if(this._activeGroup){this._activeGroup.saveCoords()}},_updateActiveGroup:function(target,e){var activeGroup=this.getActiveGroup();if(activeGroup.contains(target)){activeGroup.removeWithUpdate(target);target.set("active",false);if(activeGroup.size()===1){this.discardActiveGroup(e);this.setActiveObject(activeGroup.item(0));return}}else{activeGroup.addWithUpdate(target)}this.fire("selection:created",{target:activeGroup,e:e});activeGroup.set("active",true)},_createActiveGroup:function(target,e){if(this._activeObject&&target!==this._activeObject){var group=this._createGroup(target);group.addWithUpdate();this.setActiveGroup(group);this._activeObject=null;this.fire("selection:created",{target:group,e:e})}target.set("active",true)},_createGroup:function(target){var objects=this.getObjects(),isActiveLower=objects.indexOf(this._activeObject)1){group=new fabric.Group(group.reverse(),{canvas:this});group.addWithUpdate();this.setActiveGroup(group,e);group.saveCoords();this.fire("selection:created",{target:group});this.renderAll()}},_collectObjects:function(){var group=[],currentObject,x1=this._groupSelector.ex,y1=this._groupSelector.ey,x2=x1+this._groupSelector.left,y2=y1+this._groupSelector.top,selectionX1Y1=new fabric.Point(min(x1,x2),min(y1,y2)),selectionX2Y2=new fabric.Point(max(x1,x2),max(y1,y2)),isClick=x1===x2&&y1===y2;for(var i=this._objects.length;i--;){currentObject=this._objects[i];if(!currentObject||!currentObject.selectable||!currentObject.visible){continue}if(currentObject.intersectsWithRect(selectionX1Y1,selectionX2Y2)||currentObject.isContainedWithinRect(selectionX1Y1,selectionX2Y2)||currentObject.containsPoint(selectionX1Y1)||currentObject.containsPoint(selectionX2Y2)){currentObject.set("active",true);group.push(currentObject);if(isClick){break}}}return group},_maybeGroupObjects:function(e){if(this.selection&&this._groupSelector){this._groupSelectedObjects(e)}var activeGroup=this.getActiveGroup();if(activeGroup){activeGroup.setObjectsCoords().setCoords();activeGroup.isMoving=false;this.setCursor(this.defaultCursor)}this._groupSelector=null;this._currentTransform=null}})})();fabric.util.object.extend(fabric.StaticCanvas.prototype,{toDataURL:function(options){options||(options={});var format=options.format||"png",quality=options.quality||1,multiplier=options.multiplier||1,cropping={left:options.left,top:options.top,width:options.width,height:options.height};if(this._isRetinaScaling()){multiplier*=fabric.devicePixelRatio}if(multiplier!==1){return this.__toDataURLWithMultiplier(format,quality,cropping,multiplier)}else{return this.__toDataURL(format,quality,cropping)}},__toDataURL:function(format,quality,cropping){this.renderAll();var canvasEl=this.contextContainer.canvas,croppedCanvasEl=this.__getCroppedCanvas(canvasEl,cropping);if(format==="jpg"){format="jpeg"}var data=fabric.StaticCanvas.supports("toDataURLWithQuality")?(croppedCanvasEl||canvasEl).toDataURL("image/"+format,quality):(croppedCanvasEl||canvasEl).toDataURL("image/"+format);if(croppedCanvasEl){croppedCanvasEl=null}return data},__getCroppedCanvas:function(canvasEl,cropping){var croppedCanvasEl,croppedCtx,shouldCrop="left"in cropping||"top"in cropping||"width"in cropping||"height"in cropping;if(shouldCrop){croppedCanvasEl=fabric.util.createCanvasElement();croppedCtx=croppedCanvasEl.getContext("2d");croppedCanvasEl.width=cropping.width||this.width;croppedCanvasEl.height=cropping.height||this.height;croppedCtx.drawImage(canvasEl,-cropping.left||0,-cropping.top||0)}return croppedCanvasEl},__toDataURLWithMultiplier:function(format,quality,cropping,multiplier){var origWidth=this.getWidth(),origHeight=this.getHeight(),scaledWidth=origWidth*multiplier,scaledHeight=origHeight*multiplier,activeObject=this.getActiveObject(),activeGroup=this.getActiveGroup(),ctx=this.contextContainer;if(multiplier>1){this.setDimensions({width:scaledWidth,height:scaledHeight})}ctx.save();ctx.scale(multiplier/fabric.devicePixelRatio,multiplier/fabric.devicePixelRatio);if(cropping.left){cropping.left*=multiplier}if(cropping.top){cropping.top*=multiplier}if(cropping.width){cropping.width*=multiplier}else if(multiplier<1){cropping.width=scaledWidth}if(cropping.height){cropping.height*=multiplier}else if(multiplier<1){cropping.height=scaledHeight}if(activeGroup){this._tempRemoveBordersControlsFromGroup(activeGroup)}else if(activeObject&&this.deactivateAll){this.deactivateAll()}var data=this.__toDataURL(format,quality,cropping);this.width=origWidth;this.height=origHeight;this.setDimensions({width:origWidth,height:origHeight});if(activeGroup){this._restoreBordersControlsOnGroup(activeGroup)}else if(activeObject&&this.setActiveObject){this.setActiveObject(activeObject)}this.contextTop&&this.clearContext(this.contextTop);this.renderAll();return data},toDataURLWithMultiplier:function(format,multiplier,quality){return this.toDataURL({format:format,multiplier:multiplier,quality:quality})},_tempRemoveBordersControlsFromGroup:function(group){group.origHasControls=group.hasControls;group.origBorderColor=group.borderColor;group.hasControls=true;group.borderColor="rgba(0,0,0,0)";group.forEachObject(function(o){o.origBorderColor=o.borderColor;o.borderColor="rgba(0,0,0,0)"})},_restoreBordersControlsOnGroup:function(group){group.hideControls=group.origHideControls;group.borderColor=group.origBorderColor;group.forEachObject(function(o){o.borderColor=o.origBorderColor;delete o.origBorderColor})}});fabric.util.object.extend(fabric.StaticCanvas.prototype,{loadFromDatalessJSON:function(json,callback,reviver){return this.loadFromJSON(json,callback,reviver)},loadFromJSON:function(json,callback,reviver){if(!json){return}var serialized=typeof json==="string"?JSON.parse(json):json;this.clear();var _this=this;this._enlivenObjects(serialized.objects,function(){_this._setBgOverlay(serialized,callback)},reviver);return this},_setBgOverlay:function(serialized,callback){var _this=this,loaded={backgroundColor:false,overlayColor:false,backgroundImage:false,overlayImage:false};if(!serialized.backgroundImage&&!serialized.overlayImage&&!serialized.background&&!serialized.overlay){callback&&callback();return}var cbIfLoaded=function(){if(loaded.backgroundImage&&loaded.overlayImage&&loaded.backgroundColor&&loaded.overlayColor){_this.renderAll();callback&&callback()}};this.__setBgOverlay("backgroundImage",serialized.backgroundImage,loaded,cbIfLoaded);this.__setBgOverlay("overlayImage",serialized.overlayImage,loaded,cbIfLoaded);this.__setBgOverlay("backgroundColor",serialized.background,loaded,cbIfLoaded);this.__setBgOverlay("overlayColor",serialized.overlay,loaded,cbIfLoaded);cbIfLoaded()},__setBgOverlay:function(property,value,loaded,callback){var _this=this;if(!value){loaded[property]=true;return}if(property==="backgroundImage"||property==="overlayImage"){fabric.Image.fromObject(value,function(img){_this[property]=img;loaded[property]=true;callback&&callback()})}else{this["set"+fabric.util.string.capitalize(property,true)](value,function(){loaded[property]=true;callback&&callback()})}},_enlivenObjects:function(objects,callback,reviver){var _this=this;if(!objects||objects.length===0){callback&&callback();return}var renderOnAddRemove=this.renderOnAddRemove;this.renderOnAddRemove=false;fabric.util.enlivenObjects(objects,function(enlivenedObjects){enlivenedObjects.forEach(function(obj,index){_this.insertAt(obj,index,true)});_this.renderOnAddRemove=renderOnAddRemove;callback&&callback()},null,reviver)},_toDataURL:function(format,callback){this.clone(function(clone){callback(clone.toDataURL(format))})},_toDataURLWithMultiplier:function(format,multiplier,callback){this.clone(function(clone){callback(clone.toDataURLWithMultiplier(format,multiplier))})},clone:function(callback,properties){var data=JSON.stringify(this.toJSON(properties));this.cloneWithoutData(function(clone){clone.loadFromJSON(data,function(){callback&&callback(clone)})})},cloneWithoutData:function(callback){var el=fabric.document.createElement("canvas");el.width=this.getWidth();el.height=this.getHeight();var clone=new fabric.Canvas(el);clone.clipTo=this.clipTo;if(this.backgroundImage){clone.setBackgroundImage(this.backgroundImage.src,function(){clone.renderAll();callback&&callback(clone)});clone.backgroundImageOpacity=this.backgroundImageOpacity;clone.backgroundImageStretch=this.backgroundImageStretch}else{callback&&callback(clone)}}});(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),extend=fabric.util.object.extend,toFixed=fabric.util.toFixed,capitalize=fabric.util.string.capitalize,degreesToRadians=fabric.util.degreesToRadians,supportsLineDash=fabric.StaticCanvas.supports("setLineDash");if(fabric.Object){return}fabric.Object=fabric.util.createClass({type:"object",originX:"left",originY:"top",top:0,left:0,width:0,height:0,scaleX:1,scaleY:1,flipX:false,flipY:false,opacity:1,angle:0,skewX:0,skewY:0,cornerSize:12,transparentCorners:true,hoverCursor:null,padding:0,borderColor:"rgba(102,153,255,0.75)",cornerColor:"rgba(102,153,255,0.5)",centeredScaling:false,centeredRotation:true,fill:"rgb(0,0,0)",fillRule:"nonzero",globalCompositeOperation:"source-over",backgroundColor:"",stroke:null,strokeWidth:1,strokeDashArray:null,strokeLineCap:"butt",strokeLineJoin:"miter",strokeMiterLimit:10,shadow:null,borderOpacityWhenMoving:.4,borderScaleFactor:1,transformMatrix:null,minScaleLimit:.01,selectable:true,evented:true,visible:true,hasControls:true,hasBorders:true,hasRotatingPoint:true,rotatingPointOffset:40,perPixelTargetFind:false,includeDefaultValues:true,clipTo:null,lockMovementX:false,lockMovementY:false,lockRotation:false,lockScalingX:false,lockScalingY:false,lockUniScaling:false,lockSkewingX:false,lockSkewingY:false,lockScalingFlip:false,stateProperties:("top left width height scaleX scaleY flipX flipY originX originY transformMatrix "+"stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit "+"angle opacity fill fillRule globalCompositeOperation shadow clipTo visible backgroundColor "+"alignX alignY meetOrSlice skewX skewY").split(" "),initialize:function(options){if(options){this.setOptions(options)}},_initGradient:function(options){if(options.fill&&options.fill.colorStops&&!(options.fill instanceof fabric.Gradient)){this.set("fill",new fabric.Gradient(options.fill))}if(options.stroke&&options.stroke.colorStops&&!(options.stroke instanceof fabric.Gradient)){this.set("stroke",new fabric.Gradient(options.stroke))}},_initPattern:function(options){if(options.fill&&options.fill.source&&!(options.fill instanceof fabric.Pattern)){this.set("fill",new fabric.Pattern(options.fill))}if(options.stroke&&options.stroke.source&&!(options.stroke instanceof fabric.Pattern)){this.set("stroke",new fabric.Pattern(options.stroke))}},_initClipping:function(options){if(!options.clipTo||typeof options.clipTo!=="string"){return}var functionBody=fabric.util.getFunctionBody(options.clipTo);if(typeof functionBody!=="undefined"){this.clipTo=new Function("ctx",functionBody)}},setOptions:function(options){for(var prop in options){this.set(prop,options[prop])}this._initGradient(options);this._initPattern(options);this._initClipping(options)},transform:function(ctx,fromLeft){if(this.group&&this.canvas.preserveObjectStacking&&this.group===this.canvas._activeGroup){this.group.transform(ctx)}var center=fromLeft?this._getLeftTopCoords():this.getCenterPoint();ctx.translate(center.x,center.y);ctx.rotate(degreesToRadians(this.angle));ctx.scale(this.scaleX*(this.flipX?-1:1),this.scaleY*(this.flipY?-1:1));ctx.transform(1,0,Math.tan(degreesToRadians(this.skewX)),1,0,0);ctx.transform(1,Math.tan(degreesToRadians(this.skewY)),0,1,0,0)},toObject:function(propertiesToInclude){var NUM_FRACTION_DIGITS=fabric.Object.NUM_FRACTION_DIGITS,object={type:this.type,originX:this.originX,originY:this.originY,left:toFixed(this.left,NUM_FRACTION_DIGITS),top:toFixed(this.top,NUM_FRACTION_DIGITS),width:toFixed(this.width,NUM_FRACTION_DIGITS),height:toFixed(this.height,NUM_FRACTION_DIGITS),fill:this.fill&&this.fill.toObject?this.fill.toObject():this.fill,stroke:this.stroke&&this.stroke.toObject?this.stroke.toObject():this.stroke,strokeWidth:toFixed(this.strokeWidth,NUM_FRACTION_DIGITS),strokeDashArray:this.strokeDashArray?this.strokeDashArray.concat():this.strokeDashArray,strokeLineCap:this.strokeLineCap,strokeLineJoin:this.strokeLineJoin,strokeMiterLimit:toFixed(this.strokeMiterLimit,NUM_FRACTION_DIGITS),scaleX:toFixed(this.scaleX,NUM_FRACTION_DIGITS),scaleY:toFixed(this.scaleY,NUM_FRACTION_DIGITS),angle:toFixed(this.getAngle(),NUM_FRACTION_DIGITS),flipX:this.flipX,flipY:this.flipY,opacity:toFixed(this.opacity,NUM_FRACTION_DIGITS),shadow:this.shadow&&this.shadow.toObject?this.shadow.toObject():this.shadow,visible:this.visible,clipTo:this.clipTo&&String(this.clipTo),backgroundColor:this.backgroundColor,fillRule:this.fillRule,globalCompositeOperation:this.globalCompositeOperation,transformMatrix:this.transformMatrix?this.transformMatrix.concat():this.transformMatrix,skewX:toFixed(this.skewX,NUM_FRACTION_DIGITS),skewY:toFixed(this.skewY,NUM_FRACTION_DIGITS)};if(!this.includeDefaultValues){object=this._removeDefaultValues(object)}fabric.util.populateWithProperties(this,object,propertiesToInclude);return object},toDatalessObject:function(propertiesToInclude){return this.toObject(propertiesToInclude)},_removeDefaultValues:function(object){var prototype=fabric.util.getKlass(object.type).prototype,stateProperties=prototype.stateProperties;stateProperties.forEach(function(prop){if(object[prop]===prototype[prop]){delete object[prop]}var isArray=Object.prototype.toString.call(object[prop])==="[object Array]"&&Object.prototype.toString.call(prototype[prop])==="[object Array]";if(isArray&&object[prop].length===0&&prototype[prop].length===0){delete object[prop]}});return object},toString:function(){return"#"},get:function(property){return this[property]},_setObject:function(obj){for(var prop in obj){this._set(prop,obj[prop])}},set:function(key,value){if(typeof key==="object"){this._setObject(key)}else{if(typeof value==="function"&&key!=="clipTo"){this._set(key,value(this.get(key)))}else{this._set(key,value)}}return this},_set:function(key,value){var shouldConstrainValue=key==="scaleX"||key==="scaleY";if(shouldConstrainValue){value=this._constrainScale(value)}if(key==="scaleX"&&value<0){this.flipX=!this.flipX;value*=-1}else if(key==="scaleY"&&value<0){this.flipY=!this.flipY;value*=-1}else if(key==="width"||key==="height"){this.minScaleLimit=toFixed(Math.min(.1,1/Math.max(this.width,this.height)),2)}else if(key==="shadow"&&value&&!(value instanceof fabric.Shadow)){value=new fabric.Shadow(value)}this[key]=value;return this},setOnGroup:function(){},toggle:function(property){var value=this.get(property);if(typeof value==="boolean"){this.set(property,!value)}return this},setSourcePath:function(value){this.sourcePath=value;return this},getViewportTransform:function(){if(this.canvas&&this.canvas.viewportTransform){return this.canvas.viewportTransform}return[1,0,0,1,0,0]},render:function(ctx,noTransform){if(this.width===0&&this.height===0||!this.visible){return}ctx.save();this._setupCompositeOperation(ctx);if(!noTransform){this.transform(ctx)}this._setStrokeStyles(ctx);this._setFillStyles(ctx);if(this.transformMatrix){ctx.transform.apply(ctx,this.transformMatrix)}this._setOpacity(ctx);this._setShadow(ctx);this.clipTo&&fabric.util.clipContext(this,ctx);this._render(ctx,noTransform);this.clipTo&&ctx.restore();ctx.restore()},_setOpacity:function(ctx){if(this.group){this.group._setOpacity(ctx)}ctx.globalAlpha*=this.opacity},_setStrokeStyles:function(ctx){if(this.stroke){ctx.lineWidth=this.strokeWidth;ctx.lineCap=this.strokeLineCap;ctx.lineJoin=this.strokeLineJoin;ctx.miterLimit=this.strokeMiterLimit;ctx.strokeStyle=this.stroke.toLive?this.stroke.toLive(ctx,this):this.stroke}},_setFillStyles:function(ctx){if(this.fill){ctx.fillStyle=this.fill.toLive?this.fill.toLive(ctx,this):this.fill}},_renderControls:function(ctx,noTransform){if(!this.active||noTransform||this.group&&this.group!==this.canvas.getActiveGroup()){return}var vpt=this.getViewportTransform(),matrix=this.calcTransformMatrix(),options;matrix=fabric.util.multiplyTransformMatrices(vpt,matrix);options=fabric.util.qrDecompose(matrix);ctx.save();ctx.translate(options.translateX,options.translateY);if(this.group&&this.group===this.canvas.getActiveGroup()){ctx.rotate(degreesToRadians(options.angle));this.drawBordersInGroup(ctx,options)}else{ctx.rotate(degreesToRadians(this.angle));this.drawBorders(ctx)}this.drawControls(ctx);ctx.restore()},_setShadow:function(ctx){if(!this.shadow){return}var multX=this.canvas&&this.canvas.viewportTransform[0]||1,multY=this.canvas&&this.canvas.viewportTransform[3]||1;if(this.canvas&&this.canvas._isRetinaScaling()){multX*=fabric.devicePixelRatio;multY*=fabric.devicePixelRatio}ctx.shadowColor=this.shadow.color;ctx.shadowBlur=this.shadow.blur*(multX+multY)*(this.scaleX+this.scaleY)/4;ctx.shadowOffsetX=this.shadow.offsetX*multX*this.scaleX;ctx.shadowOffsetY=this.shadow.offsetY*multY*this.scaleY},_removeShadow:function(ctx){if(!this.shadow){return}ctx.shadowColor="";ctx.shadowBlur=ctx.shadowOffsetX=ctx.shadowOffsetY=0},_renderFill:function(ctx){if(!this.fill){return}ctx.save();if(this.fill.gradientTransform){var g=this.fill.gradientTransform;ctx.transform.apply(ctx,g)}if(this.fill.toLive){ctx.translate(-this.width/2+this.fill.offsetX||0,-this.height/2+this.fill.offsetY||0)}if(this.fillRule==="evenodd"){ctx.fill("evenodd")}else{ctx.fill()}ctx.restore()},_renderStroke:function(ctx){if(!this.stroke||this.strokeWidth===0){return}if(this.shadow&&!this.shadow.affectStroke){this._removeShadow(ctx)}ctx.save();if(this.strokeDashArray){if(1&this.strokeDashArray.length){this.strokeDashArray.push.apply(this.strokeDashArray,this.strokeDashArray) -}if(supportsLineDash){ctx.setLineDash(this.strokeDashArray);this._stroke&&this._stroke(ctx)}else{this._renderDashedStroke&&this._renderDashedStroke(ctx)}ctx.stroke()}else{if(this.stroke.gradientTransform){var g=this.stroke.gradientTransform;ctx.transform.apply(ctx,g)}this._stroke?this._stroke(ctx):ctx.stroke()}ctx.restore()},clone:function(callback,propertiesToInclude){if(this.constructor.fromObject){return this.constructor.fromObject(this.toObject(propertiesToInclude),callback)}return new fabric.Object(this.toObject(propertiesToInclude))},cloneAsImage:function(callback){var dataUrl=this.toDataURL();fabric.util.loadImage(dataUrl,function(img){if(callback){callback(new fabric.Image(img))}});return this},toDataURL:function(options){options||(options={});var el=fabric.util.createCanvasElement(),boundingRect=this.getBoundingRect();el.width=boundingRect.width;el.height=boundingRect.height;fabric.util.wrapElement(el,"div");var canvas=new fabric.StaticCanvas(el);if(options.format==="jpg"){options.format="jpeg"}if(options.format==="jpeg"){canvas.backgroundColor="#fff"}var origParams={active:this.get("active"),left:this.getLeft(),top:this.getTop()};this.set("active",false);this.setPositionByOrigin(new fabric.Point(el.width/2,el.height/2),"center","center");var originalCanvas=this.canvas;canvas.add(this);var data=canvas.toDataURL(options);this.set(origParams).setCoords();this.canvas=originalCanvas;canvas.dispose();canvas=null;return data},isType:function(type){return this.type===type},complexity:function(){return 0},toJSON:function(propertiesToInclude){return this.toObject(propertiesToInclude)},setGradient:function(property,options){options||(options={});var gradient={colorStops:[]};gradient.type=options.type||(options.r1||options.r2?"radial":"linear");gradient.coords={x1:options.x1,y1:options.y1,x2:options.x2,y2:options.y2};if(options.r1||options.r2){gradient.coords.r1=options.r1;gradient.coords.r2=options.r2}options.gradientTransform&&(gradient.gradientTransform=options.gradientTransform);for(var position in options.colorStops){var color=new fabric.Color(options.colorStops[position]);gradient.colorStops.push({offset:position,color:color.toRgb(),opacity:color.getAlpha()})}return this.set(property,fabric.Gradient.forObject(this,gradient))},setPatternFill:function(options){return this.set("fill",new fabric.Pattern(options))},setShadow:function(options){return this.set("shadow",options?new fabric.Shadow(options):null)},setColor:function(color){this.set("fill",color);return this},setAngle:function(angle){var shouldCenterOrigin=(this.originX!=="center"||this.originY!=="center")&&this.centeredRotation;if(shouldCenterOrigin){this._setOriginToCenter()}this.set("angle",angle);if(shouldCenterOrigin){this._resetOrigin()}return this},centerH:function(){this.canvas.centerObjectH(this);return this},centerV:function(){this.canvas.centerObjectV(this);return this},center:function(){this.canvas.centerObject(this);return this},remove:function(){this.canvas.remove(this);return this},getLocalPointer:function(e,pointer){pointer=pointer||this.canvas.getPointer(e);var pClicked=new fabric.Point(pointer.x,pointer.y),objectLeftTop=this._getLeftTopCoords();if(this.angle){pClicked=fabric.util.rotatePoint(pClicked,objectLeftTop,fabric.util.degreesToRadians(-this.angle))}return{x:pClicked.x-objectLeftTop.x,y:pClicked.y-objectLeftTop.y}},_setupCompositeOperation:function(ctx){if(this.globalCompositeOperation){ctx.globalCompositeOperation=this.globalCompositeOperation}}});fabric.util.createAccessors(fabric.Object);fabric.Object.prototype.rotate=fabric.Object.prototype.setAngle;extend(fabric.Object.prototype,fabric.Observable);fabric.Object.NUM_FRACTION_DIGITS=2;fabric.Object.__uid=0})(typeof exports!=="undefined"?exports:this);(function(){var degreesToRadians=fabric.util.degreesToRadians,originXOffset={left:-.5,center:0,right:.5},originYOffset={top:-.5,center:0,bottom:.5};fabric.util.object.extend(fabric.Object.prototype,{translateToGivenOrigin:function(point,fromOriginX,fromOriginY,toOriginX,toOriginY){var x=point.x,y=point.y,offsetX=originXOffset[toOriginX]-originXOffset[fromOriginX],offsetY=originYOffset[toOriginY]-originYOffset[fromOriginY],dim;if(offsetX||offsetY){dim=this._getTransformedDimensions();x=point.x+offsetX*dim.x;y=point.y+offsetY*dim.y}return new fabric.Point(x,y)},translateToCenterPoint:function(point,originX,originY){var p=this.translateToGivenOrigin(point,originX,originY,"center","center");if(this.angle){return fabric.util.rotatePoint(p,point,degreesToRadians(this.angle))}return p},translateToOriginPoint:function(center,originX,originY){var p=this.translateToGivenOrigin(center,"center","center",originX,originY);if(this.angle){return fabric.util.rotatePoint(p,center,degreesToRadians(this.angle))}return p},getCenterPoint:function(){var leftTop=new fabric.Point(this.left,this.top);return this.translateToCenterPoint(leftTop,this.originX,this.originY)},getPointByOrigin:function(originX,originY){var center=this.getCenterPoint();return this.translateToOriginPoint(center,originX,originY)},toLocalPoint:function(point,originX,originY){var center=this.getCenterPoint(),p,p2;if(originX&&originY){p=this.translateToGivenOrigin(center,"center","center",originX,originY)}else{p=new fabric.Point(this.left,this.top)}p2=new fabric.Point(point.x,point.y);if(this.angle){p2=fabric.util.rotatePoint(p2,center,-degreesToRadians(this.angle))}return p2.subtractEquals(p)},setPositionByOrigin:function(pos,originX,originY){var center=this.translateToCenterPoint(pos,originX,originY),position=this.translateToOriginPoint(center,this.originX,this.originY);this.set("left",position.x);this.set("top",position.y)},adjustPosition:function(to){var angle=degreesToRadians(this.angle),hypotFull=this.getWidth(),xFull=Math.cos(angle)*hypotFull,yFull=Math.sin(angle)*hypotFull;this.left+=xFull*(originXOffset[to]-originXOffset[this.originX]);this.top+=yFull*(originXOffset[to]-originXOffset[this.originX]);this.setCoords();this.originX=to},_setOriginToCenter:function(){this._originalOriginX=this.originX;this._originalOriginY=this.originY;var center=this.getCenterPoint();this.originX="center";this.originY="center";this.left=center.x;this.top=center.y},_resetOrigin:function(){var originPoint=this.translateToOriginPoint(this.getCenterPoint(),this._originalOriginX,this._originalOriginY);this.originX=this._originalOriginX;this.originY=this._originalOriginY;this.left=originPoint.x;this.top=originPoint.y;this._originalOriginX=null;this._originalOriginY=null},_getLeftTopCoords:function(){return this.translateToOriginPoint(this.getCenterPoint(),"left","top")}})})();(function(){function getCoords(oCoords){return[new fabric.Point(oCoords.tl.x,oCoords.tl.y),new fabric.Point(oCoords.tr.x,oCoords.tr.y),new fabric.Point(oCoords.br.x,oCoords.br.y),new fabric.Point(oCoords.bl.x,oCoords.bl.y)]}var degreesToRadians=fabric.util.degreesToRadians,multiplyMatrices=fabric.util.multiplyTransformMatrices;fabric.util.object.extend(fabric.Object.prototype,{oCoords:null,intersectsWithRect:function(pointTL,pointBR){var oCoords=getCoords(this.oCoords),intersection=fabric.Intersection.intersectPolygonRectangle(oCoords,pointTL,pointBR);return intersection.status==="Intersection"},intersectsWithObject:function(other){var intersection=fabric.Intersection.intersectPolygonPolygon(getCoords(this.oCoords),getCoords(other.oCoords));return intersection.status==="Intersection"},isContainedWithinObject:function(other){var boundingRect=other.getBoundingRect(),point1=new fabric.Point(boundingRect.left,boundingRect.top),point2=new fabric.Point(boundingRect.left+boundingRect.width,boundingRect.top+boundingRect.height);return this.isContainedWithinRect(point1,point2)},isContainedWithinRect:function(pointTL,pointBR){var boundingRect=this.getBoundingRect();return boundingRect.left>=pointTL.x&&boundingRect.left+boundingRect.width<=pointBR.x&&boundingRect.top>=pointTL.y&&boundingRect.top+boundingRect.height<=pointBR.y},containsPoint:function(point){var lines=this._getImageLines(this.oCoords),xPoints=this._findCrossPoints(point,lines);return xPoints!==0&&xPoints%2===1},_getImageLines:function(oCoords){return{topline:{o:oCoords.tl,d:oCoords.tr},rightline:{o:oCoords.tr,d:oCoords.br},bottomline:{o:oCoords.br,d:oCoords.bl},leftline:{o:oCoords.bl,d:oCoords.tl}}},_findCrossPoints:function(point,oCoords){var b1,b2,a1,a2,xi,yi,xcount=0,iLine;for(var lineKey in oCoords){iLine=oCoords[lineKey];if(iLine.o.y=point.y&&iLine.d.y>=point.y){continue}if(iLine.o.x===iLine.d.x&&iLine.o.x>=point.x){xi=iLine.o.x;yi=point.y}else{b1=0;b2=(iLine.d.y-iLine.o.y)/(iLine.d.x-iLine.o.x);a1=point.y-b1*point.x;a2=iLine.o.y-b2*iLine.o.x;xi=-(a1-a2)/(b1-b2);yi=a1+b1*xi}if(xi>=point.x){xcount+=1}if(xcount===2){break}}return xcount},getBoundingRectWidth:function(){return this.getBoundingRect().width},getBoundingRectHeight:function(){return this.getBoundingRect().height},getBoundingRect:function(){this.oCoords||this.setCoords();return fabric.util.makeBoundingBoxFromPoints([this.oCoords.tl,this.oCoords.tr,this.oCoords.br,this.oCoords.bl])},getWidth:function(){return this._getTransformedDimensions().x},getHeight:function(){return this._getTransformedDimensions().y},_constrainScale:function(value){if(Math.abs(value)0?Math.atan(currentHeight/currentWidth):0,_hypotenuse=currentWidth/Math.cos(_angle)/2,offsetX=Math.cos(_angle+theta)*_hypotenuse,offsetY=Math.sin(_angle+theta)*_hypotenuse,coords=fabric.util.transformPoint(this.getCenterPoint(),vpt),tl=new fabric.Point(coords.x-offsetX,coords.y-offsetY),tr=new fabric.Point(tl.x+currentWidth*cosTh,tl.y+currentWidth*sinTh),bl=new fabric.Point(tl.x-currentHeight*sinTh,tl.y+currentHeight*cosTh),br=new fabric.Point(coords.x+offsetX,coords.y+offsetY),ml=new fabric.Point((tl.x+bl.x)/2,(tl.y+bl.y)/2),mt=new fabric.Point((tr.x+tl.x)/2,(tr.y+tl.y)/2),mr=new fabric.Point((br.x+tr.x)/2,(br.y+tr.y)/2),mb=new fabric.Point((br.x+bl.x)/2,(br.y+bl.y)/2),mtr=new fabric.Point(mt.x+sinTh*this.rotatingPointOffset,mt.y-cosTh*this.rotatingPointOffset);this.oCoords={tl:tl,tr:tr,br:br,bl:bl,ml:ml,mt:mt,mr:mr,mb:mb,mtr:mtr};this._setCornerCoords&&this._setCornerCoords();return this},_calcRotateMatrix:function(){if(this.angle){var theta=degreesToRadians(this.angle),cos=Math.cos(theta),sin=Math.sin(theta);return[cos,sin,-sin,cos,0,0]}return[1,0,0,1,0,0]},calcTransformMatrix:function(){var center=this.getCenterPoint(),translateMatrix=[1,0,0,1,center.x,center.y],rotateMatrix=this._calcRotateMatrix(),dimensionMatrix=this._calcDimensionsTransformMatrix(this.skewX,this.skewY,true),matrix=this.group?this.group.calcTransformMatrix():[1,0,0,1,0,0];matrix=multiplyMatrices(matrix,translateMatrix);matrix=multiplyMatrices(matrix,rotateMatrix);matrix=multiplyMatrices(matrix,dimensionMatrix);return matrix},_calcDimensionsTransformMatrix:function(skewX,skewY,flipping){var skewMatrixX=[1,0,Math.tan(degreesToRadians(skewX)),1],skewMatrixY=[1,Math.tan(degreesToRadians(skewY)),0,1],scaleX=this.scaleX*(flipping&&this.flipX?-1:1),scaleY=this.scaleY*(flipping&&this.flipY?-1:1),scaleMatrix=[scaleX,0,0,scaleY],m=multiplyMatrices(scaleMatrix,skewMatrixX,true);return multiplyMatrices(m,skewMatrixY,true)}})})();fabric.util.object.extend(fabric.Object.prototype,{sendToBack:function(){if(this.group){fabric.StaticCanvas.prototype.sendToBack.call(this.group,this)}else{this.canvas.sendToBack(this)}return this},bringToFront:function(){if(this.group){fabric.StaticCanvas.prototype.bringToFront.call(this.group,this)}else{this.canvas.bringToFront(this)}return this},sendBackwards:function(intersecting){if(this.group){fabric.StaticCanvas.prototype.sendBackwards.call(this.group,this,intersecting)}else{this.canvas.sendBackwards(this,intersecting)}return this},bringForward:function(intersecting){if(this.group){fabric.StaticCanvas.prototype.bringForward.call(this.group,this,intersecting)}else{this.canvas.bringForward(this,intersecting)}return this},moveTo:function(index){if(this.group){fabric.StaticCanvas.prototype.moveTo.call(this.group,this,index)}else{this.canvas.moveTo(this,index)}return this}});fabric.util.object.extend(fabric.Object.prototype,{getSvgStyles:function(skipShadow){var fill=this.fill?this.fill.toLive?"url(#SVGID_"+this.fill.id+")":this.fill:"none",fillRule=this.fillRule,stroke=this.stroke?this.stroke.toLive?"url(#SVGID_"+this.stroke.id+")":this.stroke:"none",strokeWidth=this.strokeWidth?this.strokeWidth:"0",strokeDashArray=this.strokeDashArray?this.strokeDashArray.join(" "):"none",strokeLineCap=this.strokeLineCap?this.strokeLineCap:"butt",strokeLineJoin=this.strokeLineJoin?this.strokeLineJoin:"miter",strokeMiterLimit=this.strokeMiterLimit?this.strokeMiterLimit:"4",opacity=typeof this.opacity!=="undefined"?this.opacity:"1",visibility=this.visible?"":" visibility: hidden;",filter=skipShadow?"":this.getSvgFilter();return["stroke: ",stroke,"; ","stroke-width: ",strokeWidth,"; ","stroke-dasharray: ",strokeDashArray,"; ","stroke-linecap: ",strokeLineCap,"; ","stroke-linejoin: ",strokeLineJoin,"; ","stroke-miterlimit: ",strokeMiterLimit,"; ","fill: ",fill,"; ","fill-rule: ",fillRule,"; ","opacity: ",opacity,";",filter,visibility].join("")},getSvgFilter:function(){return this.shadow?"filter: url(#SVGID_"+this.shadow.id+");":""},getSvgTransform:function(){if(this.group&&this.group.type==="path-group"){return""}var toFixed=fabric.util.toFixed,angle=this.getAngle(),skewX=this.getSkewX()%360,skewY=this.getSkewY()%360,center=this.getCenterPoint(),NUM_FRACTION_DIGITS=fabric.Object.NUM_FRACTION_DIGITS,translatePart=this.type==="path-group"?"":"translate("+toFixed(center.x,NUM_FRACTION_DIGITS)+" "+toFixed(center.y,NUM_FRACTION_DIGITS)+")",anglePart=angle!==0?" rotate("+toFixed(angle,NUM_FRACTION_DIGITS)+")":"",scalePart=this.scaleX===1&&this.scaleY===1?"":" scale("+toFixed(this.scaleX,NUM_FRACTION_DIGITS)+" "+toFixed(this.scaleY,NUM_FRACTION_DIGITS)+")",skewXPart=skewX!==0?" skewX("+toFixed(skewX,NUM_FRACTION_DIGITS)+")":"",skewYPart=skewY!==0?" skewY("+toFixed(skewY,NUM_FRACTION_DIGITS)+")":"",addTranslateX=this.type==="path-group"?this.width:0,flipXPart=this.flipX?" matrix(-1 0 0 1 "+addTranslateX+" 0) ":"",addTranslateY=this.type==="path-group"?this.height:0,flipYPart=this.flipY?" matrix(1 0 0 -1 0 "+addTranslateY+")":"";return[translatePart,anglePart,scalePart,flipXPart,flipYPart,skewXPart,skewYPart].join("")},getSvgTransformMatrix:function(){return this.transformMatrix?" matrix("+this.transformMatrix.join(" ")+") ":""},_createBaseSVGMarkup:function(){var markup=[];if(this.fill&&this.fill.toLive){markup.push(this.fill.toSVG(this,false))}if(this.stroke&&this.stroke.toLive){markup.push(this.stroke.toSVG(this,false))}if(this.shadow){markup.push(this.shadow.toSVG(this))}return markup}});fabric.util.object.extend(fabric.Object.prototype,{hasStateChanged:function(){return this.stateProperties.some(function(prop){return this.get(prop)!==this.originalState[prop]},this)},saveState:function(options){this.stateProperties.forEach(function(prop){this.originalState[prop]=this.get(prop)},this);if(options&&options.stateProperties){options.stateProperties.forEach(function(prop){this.originalState[prop]=this.get(prop)},this)}return this},setupState:function(){this.originalState={};this.saveState();return this}});(function(){var degreesToRadians=fabric.util.degreesToRadians,isVML=function(){return typeof G_vmlCanvasManager!=="undefined"};fabric.util.object.extend(fabric.Object.prototype,{_controlsVisibility:null,_findTargetCorner:function(pointer){if(!this.hasControls||!this.active){return false}var ex=pointer.x,ey=pointer.y,xPoints,lines;this.__corner=0;for(var i in this.oCoords){if(!this.isControlVisible(i)){continue}if(i==="mtr"&&!this.hasRotatingPoint){continue}if(this.get("lockUniScaling")&&(i==="mt"||i==="mr"||i==="mb"||i==="ml")){continue}lines=this._getImageLines(this.oCoords[i].corner);xPoints=this._findCrossPoints({x:ex,y:ey},lines);if(xPoints!==0&&xPoints%2===1){this.__corner=i;return i}}return false},_setCornerCoords:function(){var coords=this.oCoords,newTheta=degreesToRadians(45-this.angle),cornerHypotenuse=this.cornerSize*.707106,cosHalfOffset=cornerHypotenuse*Math.cos(newTheta),sinHalfOffset=cornerHypotenuse*Math.sin(newTheta),x,y;for(var point in coords){x=coords[point].x;y=coords[point].y;coords[point].corner={tl:{x:x-sinHalfOffset,y:y-cosHalfOffset},tr:{x:x+cosHalfOffset,y:y-sinHalfOffset},bl:{x:x-cosHalfOffset,y:y+sinHalfOffset},br:{x:x+sinHalfOffset,y:y+cosHalfOffset}}}},_getNonTransformedDimensions:function(){var strokeWidth=this.strokeWidth,w=this.width,h=this.height,addStrokeToW=true,addStrokeToH=true;if(this.type==="line"&&this.strokeLineCap==="butt"){addStrokeToH=w;addStrokeToW=h}if(addStrokeToH){h+=h<0?-strokeWidth:strokeWidth}if(addStrokeToW){w+=w<0?-strokeWidth:strokeWidth}return{x:w,y:h}},_getTransformedDimensions:function(skewX,skewY){if(typeof skewX==="undefined"){skewX=this.skewX}if(typeof skewY==="undefined"){skewY=this.skewY}var dimensions=this._getNonTransformedDimensions(),dimX=dimensions.x/2,dimY=dimensions.y/2,points=[{x:-dimX,y:-dimY},{x:dimX,y:-dimY},{x:-dimX,y:dimY},{x:dimX,y:dimY}],i,transformMatrix=this._calcDimensionsTransformMatrix(skewX,skewY,false),bbox;for(i=0;i\n');return reviver?reviver(markup.join("")):markup.join("")},complexity:function(){return 1}});fabric.Line.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" "));fabric.Line.fromElement=function(element,options){var parsedAttributes=fabric.parseAttributes(element,fabric.Line.ATTRIBUTE_NAMES),points=[parsedAttributes.x1||0,parsedAttributes.y1||0,parsedAttributes.x2||0,parsedAttributes.y2||0];return new fabric.Line(points,extend(parsedAttributes,options))};fabric.Line.fromObject=function(object){var points=[object.x1,object.y1,object.x2,object.y2];return new fabric.Line(points,object)};function makeEdgeToOriginGetter(propertyNames,originValues){var origin=propertyNames.origin,axis1=propertyNames.axis1,axis2=propertyNames.axis2,dimension=propertyNames.dimension,nearest=originValues.nearest,center=originValues.center,farthest=originValues.farthest;return function(){switch(this.get(origin)){case nearest:return Math.min(this.get(axis1),this.get(axis2));case center:return Math.min(this.get(axis1),this.get(axis2))+.5*this.get(dimension);case farthest:return Math.max(this.get(axis1),this.get(axis2))}}}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),pi=Math.PI,extend=fabric.util.object.extend;if(fabric.Circle){fabric.warn("fabric.Circle is already defined.");return}fabric.Circle=fabric.util.createClass(fabric.Object,{type:"circle",radius:0,startAngle:0,endAngle:pi*2,initialize:function(options){options=options||{};this.callSuper("initialize",options);this.set("radius",options.radius||0);this.startAngle=options.startAngle||this.startAngle;this.endAngle=options.endAngle||this.endAngle},_set:function(key,value){this.callSuper("_set",key,value);if(key==="radius"){this.setRadius(value)}return this},toObject:function(propertiesToInclude){return extend(this.callSuper("toObject",propertiesToInclude),{radius:this.get("radius"),startAngle:this.startAngle,endAngle:this.endAngle})},toSVG:function(reviver){var markup=this._createBaseSVGMarkup(),x=0,y=0,angle=(this.endAngle-this.startAngle)%(2*pi);if(angle===0){if(this.group&&this.group.type==="path-group"){x=this.left+this.radius;y=this.top+this.radius}markup.push("\n')}else{var startX=Math.cos(this.startAngle)*this.radius,startY=Math.sin(this.startAngle)*this.radius,endX=Math.cos(this.endAngle)*this.radius,endY=Math.sin(this.endAngle)*this.radius,largeFlag=angle>pi?"1":"0";markup.push('\n')}return reviver?reviver(markup.join("")):markup.join("")},_render:function(ctx,noTransform){ctx.beginPath();ctx.arc(noTransform?this.left+this.radius:0,noTransform?this.top+this.radius:0,this.radius,this.startAngle,this.endAngle,false);this._renderFill(ctx);this._renderStroke(ctx)},getRadiusX:function(){return this.get("radius")*this.get("scaleX")},getRadiusY:function(){return this.get("radius")*this.get("scaleY")},setRadius:function(value){this.radius=value;return this.set("width",value*2).set("height",value*2)},complexity:function(){return 1}});fabric.Circle.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("cx cy r".split(" "));fabric.Circle.fromElement=function(element,options){options||(options={});var parsedAttributes=fabric.parseAttributes(element,fabric.Circle.ATTRIBUTE_NAMES);if(!isValidRadius(parsedAttributes)){throw new Error("value of `r` attribute is required and can not be negative")}parsedAttributes.left=parsedAttributes.left||0;parsedAttributes.top=parsedAttributes.top||0;var obj=new fabric.Circle(extend(parsedAttributes,options));obj.left-=obj.radius;obj.top-=obj.radius;return obj};function isValidRadius(attributes){return"radius"in attributes&&attributes.radius>=0}fabric.Circle.fromObject=function(object){return new fabric.Circle(object)}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={});if(fabric.Triangle){fabric.warn("fabric.Triangle is already defined");return}fabric.Triangle=fabric.util.createClass(fabric.Object,{type:"triangle",initialize:function(options){options=options||{};this.callSuper("initialize",options);this.set("width",options.width||100).set("height",options.height||100)},_render:function(ctx){var widthBy2=this.width/2,heightBy2=this.height/2;ctx.beginPath();ctx.moveTo(-widthBy2,heightBy2);ctx.lineTo(0,-heightBy2);ctx.lineTo(widthBy2,heightBy2);ctx.closePath();this._renderFill(ctx);this._renderStroke(ctx)},_renderDashedStroke:function(ctx){var widthBy2=this.width/2,heightBy2=this.height/2;ctx.beginPath();fabric.util.drawDashedLine(ctx,-widthBy2,heightBy2,0,-heightBy2,this.strokeDashArray);fabric.util.drawDashedLine(ctx,0,-heightBy2,widthBy2,heightBy2,this.strokeDashArray);fabric.util.drawDashedLine(ctx,widthBy2,heightBy2,-widthBy2,heightBy2,this.strokeDashArray); -ctx.closePath()},toSVG:function(reviver){var markup=this._createBaseSVGMarkup(),widthBy2=this.width/2,heightBy2=this.height/2,points=[-widthBy2+" "+heightBy2,"0 "+-heightBy2,widthBy2+" "+heightBy2].join(",");markup.push("');return reviver?reviver(markup.join("")):markup.join("")},complexity:function(){return 1}});fabric.Triangle.fromObject=function(object){return new fabric.Triangle(object)}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),piBy2=Math.PI*2,extend=fabric.util.object.extend;if(fabric.Ellipse){fabric.warn("fabric.Ellipse is already defined.");return}fabric.Ellipse=fabric.util.createClass(fabric.Object,{type:"ellipse",rx:0,ry:0,initialize:function(options){options=options||{};this.callSuper("initialize",options);this.set("rx",options.rx||0);this.set("ry",options.ry||0)},_set:function(key,value){this.callSuper("_set",key,value);switch(key){case"rx":this.rx=value;this.set("width",value*2);break;case"ry":this.ry=value;this.set("height",value*2);break}return this},getRx:function(){return this.get("rx")*this.get("scaleX")},getRy:function(){return this.get("ry")*this.get("scaleY")},toObject:function(propertiesToInclude){return extend(this.callSuper("toObject",propertiesToInclude),{rx:this.get("rx"),ry:this.get("ry")})},toSVG:function(reviver){var markup=this._createBaseSVGMarkup(),x=0,y=0;if(this.group&&this.group.type==="path-group"){x=this.left+this.rx;y=this.top+this.ry}markup.push("\n');return reviver?reviver(markup.join("")):markup.join("")},_render:function(ctx,noTransform){ctx.beginPath();ctx.save();ctx.transform(1,0,0,this.ry/this.rx,0,0);ctx.arc(noTransform?this.left+this.rx:0,noTransform?(this.top+this.ry)*this.rx/this.ry:0,this.rx,0,piBy2,false);ctx.restore();this._renderFill(ctx);this._renderStroke(ctx)},complexity:function(){return 1}});fabric.Ellipse.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" "));fabric.Ellipse.fromElement=function(element,options){options||(options={});var parsedAttributes=fabric.parseAttributes(element,fabric.Ellipse.ATTRIBUTE_NAMES);parsedAttributes.left=parsedAttributes.left||0;parsedAttributes.top=parsedAttributes.top||0;var ellipse=new fabric.Ellipse(extend(parsedAttributes,options));ellipse.top-=ellipse.ry;ellipse.left-=ellipse.rx;return ellipse};fabric.Ellipse.fromObject=function(object){return new fabric.Ellipse(object)}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),extend=fabric.util.object.extend;if(fabric.Rect){fabric.warn("fabric.Rect is already defined");return}var stateProperties=fabric.Object.prototype.stateProperties.concat();stateProperties.push("rx","ry","x","y");fabric.Rect=fabric.util.createClass(fabric.Object,{stateProperties:stateProperties,type:"rect",rx:0,ry:0,strokeDashArray:null,initialize:function(options){options=options||{};this.callSuper("initialize",options);this._initRxRy()},_initRxRy:function(){if(this.rx&&!this.ry){this.ry=this.rx}else if(this.ry&&!this.rx){this.rx=this.ry}},_render:function(ctx,noTransform){if(this.width===1&&this.height===1){ctx.fillRect(-.5,-.5,1,1);return}var rx=this.rx?Math.min(this.rx,this.width/2):0,ry=this.ry?Math.min(this.ry,this.height/2):0,w=this.width,h=this.height,x=noTransform?this.left:-this.width/2,y=noTransform?this.top:-this.height/2,isRounded=rx!==0||ry!==0,k=1-.5522847498;ctx.beginPath();ctx.moveTo(x+rx,y);ctx.lineTo(x+w-rx,y);isRounded&&ctx.bezierCurveTo(x+w-k*rx,y,x+w,y+k*ry,x+w,y+ry);ctx.lineTo(x+w,y+h-ry);isRounded&&ctx.bezierCurveTo(x+w,y+h-k*ry,x+w-k*rx,y+h,x+w-rx,y+h);ctx.lineTo(x+rx,y+h);isRounded&&ctx.bezierCurveTo(x+k*rx,y+h,x,y+h-k*ry,x,y+h-ry);ctx.lineTo(x,y+ry);isRounded&&ctx.bezierCurveTo(x,y+k*ry,x+k*rx,y,x+rx,y);ctx.closePath();this._renderFill(ctx);this._renderStroke(ctx)},_renderDashedStroke:function(ctx){var x=-this.width/2,y=-this.height/2,w=this.width,h=this.height;ctx.beginPath();fabric.util.drawDashedLine(ctx,x,y,x+w,y,this.strokeDashArray);fabric.util.drawDashedLine(ctx,x+w,y,x+w,y+h,this.strokeDashArray);fabric.util.drawDashedLine(ctx,x+w,y+h,x,y+h,this.strokeDashArray);fabric.util.drawDashedLine(ctx,x,y+h,x,y,this.strokeDashArray);ctx.closePath()},toObject:function(propertiesToInclude){var object=extend(this.callSuper("toObject",propertiesToInclude),{rx:this.get("rx")||0,ry:this.get("ry")||0});if(!this.includeDefaultValues){this._removeDefaultValues(object)}return object},toSVG:function(reviver){var markup=this._createBaseSVGMarkup(),x=this.left,y=this.top;if(!(this.group&&this.group.type==="path-group")){x=-this.width/2;y=-this.height/2}markup.push("\n');return reviver?reviver(markup.join("")):markup.join("")},complexity:function(){return 1}});fabric.Rect.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" "));fabric.Rect.fromElement=function(element,options){if(!element){return null}options=options||{};var parsedAttributes=fabric.parseAttributes(element,fabric.Rect.ATTRIBUTE_NAMES);parsedAttributes.left=parsedAttributes.left||0;parsedAttributes.top=parsedAttributes.top||0;var rect=new fabric.Rect(extend(options?fabric.util.object.clone(options):{},parsedAttributes));rect.visible=rect.width>0&&rect.height>0;return rect};fabric.Rect.fromObject=function(object){return new fabric.Rect(object)}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={});if(fabric.Polyline){fabric.warn("fabric.Polyline is already defined");return}fabric.Polyline=fabric.util.createClass(fabric.Object,{type:"polyline",points:null,minX:0,minY:0,initialize:function(points,options){return fabric.Polygon.prototype.initialize.call(this,points,options)},_calcDimensions:function(){return fabric.Polygon.prototype._calcDimensions.call(this)},_applyPointOffset:function(){return fabric.Polygon.prototype._applyPointOffset.call(this)},toObject:function(propertiesToInclude){return fabric.Polygon.prototype.toObject.call(this,propertiesToInclude)},toSVG:function(reviver){return fabric.Polygon.prototype.toSVG.call(this,reviver)},_render:function(ctx){if(!fabric.Polygon.prototype.commonRender.call(this,ctx)){return}this._renderFill(ctx);this._renderStroke(ctx)},_renderDashedStroke:function(ctx){var p1,p2;ctx.beginPath();for(var i=0,len=this.points.length;i\n');return reviver?reviver(markup.join("")):markup.join("")},_render:function(ctx,noTransform){if(!this.commonRender(ctx,noTransform)){return}this._renderFill(ctx);if(this.stroke||this.strokeDashArray){ctx.closePath();this._renderStroke(ctx)}},commonRender:function(ctx,noTransform){var point,len=this.points.length;if(!len||isNaN(this.points[len-1].y)){return false}noTransform||ctx.translate(-this.pathOffset.x,-this.pathOffset.y);ctx.beginPath();ctx.moveTo(this.points[0].x,this.points[0].y);for(var i=0;i"},toObject:function(propertiesToInclude){var o=extend(this.callSuper("toObject",propertiesToInclude),{path:this.path.map(function(item){return item.slice()}),pathOffset:this.pathOffset});if(this.sourcePath){o.sourcePath=this.sourcePath}if(this.transformMatrix){o.transformMatrix=this.transformMatrix}return o},toDatalessObject:function(propertiesToInclude){var o=this.toObject(propertiesToInclude);if(this.sourcePath){o.path=this.sourcePath}delete o.sourcePath;return o},toSVG:function(reviver){var chunks=[],markup=this._createBaseSVGMarkup(),addTransform="";for(var i=0,len=this.path.length;i\n");return reviver?reviver(markup.join("")):markup.join("")},complexity:function(){return this.path.length},_parsePath:function(){var result=[],coords=[],currentPath,parsed,re=/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/gi,match,coordsStr;for(var i=0,coordsParsed,len=this.path.length;icommandLength){for(var k=1,klen=coordsParsed.length;k\n");for(var i=0,len=objects.length;i\n");return reviver?reviver(markup.join("")):markup.join("")},toString:function(){return"#"},isSameColor:function(){var firstPathFill=this.getObjects()[0].get("fill")||"";if(typeof firstPathFill!=="string"){return false}firstPathFill=firstPathFill.toLowerCase();return this.getObjects().every(function(path){var pathFill=path.get("fill")||"";return typeof pathFill==="string"&&pathFill.toLowerCase()===firstPathFill})},complexity:function(){return this.paths.reduce(function(total,path){return total+(path&&path.complexity?path.complexity():0)},0)},getObjects:function(){return this.paths}});fabric.PathGroup.fromObject=function(object,callback){if(typeof object.paths==="string"){fabric.loadSVGFromURL(object.paths,function(elements){var pathUrl=object.paths;delete object.paths;var pathGroup=fabric.util.groupSVGElements(elements,object,pathUrl);callback(pathGroup)})}else{fabric.util.enlivenObjects(object.paths,function(enlivenedObjects){delete object.paths;callback(new fabric.PathGroup(enlivenedObjects,object))})}};fabric.PathGroup.async=true})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),extend=fabric.util.object.extend,min=fabric.util.array.min,max=fabric.util.array.max,invoke=fabric.util.array.invoke;if(fabric.Group){return}var _lockProperties={lockMovementX:true,lockMovementY:true,lockRotation:true,lockScalingX:true,lockScalingY:true,lockUniScaling:true};fabric.Group=fabric.util.createClass(fabric.Object,fabric.Collection,{type:"group",strokeWidth:0,initialize:function(objects,options,isAlreadyGrouped){options=options||{};this._objects=[];isAlreadyGrouped&&this.callSuper("initialize",options);this._objects=objects||[];for(var i=this._objects.length;i--;){this._objects[i].group=this}this.originalState={};if(options.originX){this.originX=options.originX}if(options.originY){this.originY=options.originY}if(isAlreadyGrouped){this._updateObjectsCoords(true)}else{this._calcBounds();this._updateObjectsCoords();this.callSuper("initialize",options)}this.setCoords();this.saveCoords()},_updateObjectsCoords:function(skipCoordsChange){for(var i=this._objects.length;i--;){this._updateObjectCoords(this._objects[i],skipCoordsChange)}},_updateObjectCoords:function(object,skipCoordsChange){object.__origHasControls=object.hasControls;object.hasControls=false;if(skipCoordsChange){return}var objectLeft=object.getLeft(),objectTop=object.getTop(),center=this.getCenterPoint();object.set({originalLeft:objectLeft,originalTop:objectTop,left:objectLeft-center.x,top:objectTop-center.y});object.setCoords()},toString:function(){return"#"},addWithUpdate:function(object){this._restoreObjectsState();fabric.util.resetObjectTransform(this);if(object){this._objects.push(object);object.group=this;object._set("canvas",this.canvas)}this.forEachObject(this._setObjectActive,this);this._calcBounds();this._updateObjectsCoords();return this},_setObjectActive:function(object){object.set("active",true);object.group=this},removeWithUpdate:function(object){this._restoreObjectsState();fabric.util.resetObjectTransform(this);this.forEachObject(this._setObjectActive,this);this.remove(object);this._calcBounds();this._updateObjectsCoords();return this},_onObjectAdded:function(object){object.group=this;object._set("canvas",this.canvas)},_onObjectRemoved:function(object){delete object.group;object.set("active",false)},delegatedProperties:{fill:true,stroke:true,strokeWidth:true,fontFamily:true,fontWeight:true,fontSize:true,fontStyle:true,lineHeight:true,textDecoration:true,textAlign:true,backgroundColor:true},_set:function(key,value){var i=this._objects.length;if(this.delegatedProperties[key]||key==="canvas"){while(i--){this._objects[i].set(key,value)}}else{while(i--){this._objects[i].setOnGroup(key,value)}}this.callSuper("_set",key,value)},toObject:function(propertiesToInclude){return extend(this.callSuper("toObject",propertiesToInclude),{objects:invoke(this._objects,"toObject",propertiesToInclude)})},render:function(ctx){if(!this.visible){return}ctx.save();if(this.transformMatrix){ctx.transform.apply(ctx,this.transformMatrix)}this.transform(ctx);this._setShadow(ctx);this.clipTo&&fabric.util.clipContext(this,ctx);for(var i=0,len=this._objects.length;i\n');for(var i=0,len=this._objects.length;i\n");return reviver?reviver(markup.join("")):markup.join("")},get:function(prop){if(prop in _lockProperties){if(this[prop]){return this[prop]}else{for(var i=0,len=this._objects.length;i0){object.resizeFilters=this.resizeFilters.map(function(filterObj){return filterObj&&filterObj.toObject()})}if(!this.includeDefaultValues){this._removeDefaultValues(object)}return object},toSVG:function(reviver){var markup=this._createBaseSVGMarkup(),x=-this.width/2,y=-this.height/2,preserveAspectRatio="none";if(this.group&&this.group.type==="path-group"){x=this.left;y=this.top}if(this.alignX!=="none"&&this.alignY!=="none"){preserveAspectRatio="x"+this.alignX+"Y"+this.alignY+" "+this.meetOrSlice}markup.push('\n','\n");if(this.stroke||this.strokeDashArray){var origFill=this.fill;this.fill=null;markup.push("\n');this.fill=origFill}markup.push("\n");return reviver?reviver(markup.join("")):markup.join("")},getSrc:function(){if(this.getElement()){return this.getElement().src||this.getElement()._src}},setSrc:function(src,callback,options){fabric.util.loadImage(src,function(img){return this.setElement(img,callback,options)},this,options&&options.crossOrigin)},toString:function(){return'#'},clone:function(callback,propertiesToInclude){this.constructor.fromObject(this.toObject(propertiesToInclude),callback)},applyFilters:function(callback,filters,imgElement,forResizing){filters=filters||this.filters;imgElement=imgElement||this._originalElement;if(!imgElement){return}var imgEl=imgElement,canvasEl=fabric.util.createCanvasElement(),replacement=fabric.util.createImage(),_this=this;canvasEl.width=imgEl.width;canvasEl.height=imgEl.height;canvasEl.getContext("2d").drawImage(imgEl,0,0,imgEl.width,imgEl.height);if(filters.length===0){this._element=imgElement;callback&&callback();return canvasEl}filters.forEach(function(filter){filter&&filter.applyTo(canvasEl,filter.scaleX||_this.scaleX,filter.scaleY||_this.scaleY);if(!forResizing&&filter&&filter.type==="Resize"){_this.width*=filter.scaleX;_this.height*=filter.scaleY}});replacement.width=canvasEl.width;replacement.height=canvasEl.height;if(fabric.isLikelyNode){replacement.src=canvasEl.toBuffer(undefined,fabric.Image.pngCompression);_this._element=replacement;!forResizing&&(_this._filteredEl=replacement);callback&&callback()}else{replacement.onload=function(){_this._element=replacement;!forResizing&&(_this._filteredEl=replacement);callback&&callback();replacement.onload=canvasEl=imgEl=null};replacement.src=canvasEl.toDataURL("image/png")}return canvasEl},_render:function(ctx,noTransform){var x,y,imageMargins=this._findMargins(),elementToDraw;x=noTransform?this.left:-this.width/2;y=noTransform?this.top:-this.height/2;if(this.meetOrSlice==="slice"){ctx.beginPath();ctx.rect(x,y,this.width,this.height);ctx.clip()}if(this.isMoving===false&&this.resizeFilters.length&&this._needsResize()){this._lastScaleX=this.scaleX;this._lastScaleY=this.scaleY;elementToDraw=this.applyFilters(null,this.resizeFilters,this._filteredEl||this._originalElement,true)}else{elementToDraw=this._element}elementToDraw&&ctx.drawImage(elementToDraw,x+imageMargins.marginX,y+imageMargins.marginY,imageMargins.width,imageMargins.height);this._renderStroke(ctx)},_needsResize:function(){return this.scaleX!==this._lastScaleX||this.scaleY!==this._lastScaleY},_findMargins:function(){var width=this.width,height=this.height,scales,scale,marginX=0,marginY=0;if(this.alignX!=="none"||this.alignY!=="none"){scales=[this.width/this._element.width,this.height/this._element.height];scale=this.meetOrSlice==="meet"?Math.min.apply(null,scales):Math.max.apply(null,scales);width=this._element.width*scale;height=this._element.height*scale;if(this.alignX==="Mid"){marginX=(this.width-width)/2}if(this.alignX==="Max"){marginX=this.width-width}if(this.alignY==="Mid"){marginY=(this.height-height)/2}if(this.alignY==="Max"){marginY=this.height-height}}return{width:width,height:height,marginX:marginX,marginY:marginY}},_resetWidthHeight:function(){var element=this.getElement();this.set("width",element.width);this.set("height",element.height)},_initElement:function(element,options){this.setElement(fabric.util.getById(element),null,options);fabric.util.addClass(this.getElement(),fabric.Image.CSS_CANVAS)},_initConfig:function(options){options||(options={});this.setOptions(options);this._setWidthHeight(options);if(this._element&&this.crossOrigin){this._element.crossOrigin=this.crossOrigin}},_initFilters:function(filters,callback){if(filters&&filters.length){fabric.util.enlivenObjects(filters,function(enlivenedObjects){callback&&callback(enlivenedObjects)},"fabric.Image.filters")}else{callback&&callback()}},_setWidthHeight:function(options){this.width="width"in options?options.width:this.getElement()?this.getElement().width||0:0;this.height="height"in options?options.height:this.getElement()?this.getElement().height||0:0},complexity:function(){return 1}});fabric.Image.CSS_CANVAS="canvas-img";fabric.Image.prototype.getSvgSrc=fabric.Image.prototype.getSrc;fabric.Image.fromObject=function(object,callback){fabric.util.loadImage(object.src,function(img){fabric.Image.prototype._initFilters.call(object,object.filters,function(filters){object.filters=filters||[];fabric.Image.prototype._initFilters.call(object,object.resizeFilters,function(resizeFilters){object.resizeFilters=resizeFilters||[];var instance=new fabric.Image(img,object);callback&&callback(instance)})})},null,object.crossOrigin)};fabric.Image.fromURL=function(url,callback,imgOptions){fabric.util.loadImage(url,function(img){callback&&callback(new fabric.Image(img,imgOptions))},null,imgOptions&&imgOptions.crossOrigin)};fabric.Image.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y width height preserveAspectRatio xlink:href".split(" "));fabric.Image.fromElement=function(element,callback,options){var parsedAttributes=fabric.parseAttributes(element,fabric.Image.ATTRIBUTE_NAMES),preserveAR;if(parsedAttributes.preserveAspectRatio){preserveAR=fabric.util.parsePreserveAspectRatioAttribute(parsedAttributes.preserveAspectRatio);extend(parsedAttributes,preserveAR)}fabric.Image.fromURL(parsedAttributes["xlink:href"],callback,extend(options?fabric.util.object.clone(options):{},parsedAttributes))};fabric.Image.async=true;fabric.Image.pngCompression=1})(typeof exports!=="undefined"?exports:this);fabric.util.object.extend(fabric.Object.prototype,{_getAngleValueForStraighten:function(){var angle=this.getAngle()%360;if(angle>0){return Math.round((angle-1)/90)*90}return Math.round(angle/90)*90},straighten:function(){this.setAngle(this._getAngleValueForStraighten());return this},fxStraighten:function(callbacks){callbacks=callbacks||{};var empty=function(){},onComplete=callbacks.onComplete||empty,onChange=callbacks.onChange||empty,_this=this;fabric.util.animate({startValue:this.get("angle"),endValue:this._getAngleValueForStraighten(),duration:this.FX_DURATION,onChange:function(value){_this.setAngle(value);onChange()},onComplete:function(){_this.setCoords();onComplete()},onStart:function(){_this.set("active",false)}});return this}});fabric.util.object.extend(fabric.StaticCanvas.prototype,{straightenObject:function(object){object.straighten();this.renderAll();return this},fxStraightenObject:function(object){object.fxStraighten({onChange:this.renderAll.bind(this)});return this}});fabric.Image.filters=fabric.Image.filters||{};fabric.Image.filters.BaseFilter=fabric.util.createClass({type:"BaseFilter",initialize:function(options){if(options){this.setOptions(options)}},setOptions:function(options){for(var prop in options){this[prop]=options[prop]}},toObject:function(){return{type:this.type}},toJSON:function(){return this.toObject()}});(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),extend=fabric.util.object.extend;fabric.Image.filters.Brightness=fabric.util.createClass(fabric.Image.filters.BaseFilter,{type:"Brightness",initialize:function(options){options=options||{};this.brightness=options.brightness||0},applyTo:function(canvasEl){var context=canvasEl.getContext("2d"),imageData=context.getImageData(0,0,canvasEl.width,canvasEl.height),data=imageData.data,brightness=this.brightness;for(var i=0,len=data.length;ish||scx<0||scx>sw){continue}srcOff=(scy*sw+scx)*4;wt=weights[cy*side+cx];r+=src[srcOff]*wt;g+=src[srcOff+1]*wt;b+=src[srcOff+2]*wt;a+=src[srcOff+3]*wt}}dst[dstOff]=r;dst[dstOff+1]=g;dst[dstOff+2]=b;dst[dstOff+3]=a+alphaFac*(255-a)}}context.putImageData(output,0,0)},toObject:function(){return extend(this.callSuper("toObject"),{opaque:this.opaque,matrix:this.matrix})}});fabric.Image.filters.Convolute.fromObject=function(object){return new fabric.Image.filters.Convolute(object)}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),extend=fabric.util.object.extend;fabric.Image.filters.GradientTransparency=fabric.util.createClass(fabric.Image.filters.BaseFilter,{type:"GradientTransparency",initialize:function(options){options=options||{};this.threshold=options.threshold||100},applyTo:function(canvasEl){var context=canvasEl.getContext("2d"),imageData=context.getImageData(0,0,canvasEl.width,canvasEl.height),data=imageData.data,threshold=this.threshold,total=data.length;for(var i=0,len=data.length;i-1?options.channel:0},applyTo:function(canvasEl){if(!this.mask){return}var context=canvasEl.getContext("2d"),imageData=context.getImageData(0,0,canvasEl.width,canvasEl.height),data=imageData.data,maskEl=this.mask.getElement(),maskCanvasEl=fabric.util.createCanvasElement(),channel=this.channel,i,iLen=imageData.width*imageData.height*4;maskCanvasEl.width=canvasEl.width;maskCanvasEl.height=canvasEl.height;maskCanvasEl.getContext("2d").drawImage(maskEl,0,0,canvasEl.width,canvasEl.height);var maskImageData=maskCanvasEl.getContext("2d").getImageData(0,0,canvasEl.width,canvasEl.height),maskData=maskImageData.data;for(i=0;ilimit&&g>limit&&b>limit&&abs(r-g)width){multW=2;signW=-1}if(newHeight>height){multH=2;signH=-1}imageData=context.getImageData(0,0,width,height);canvasEl.width=max(newWidth,width);canvasEl.height=max(newHeight,height);context.putImageData(imageData,0,0);while(!doneW||!doneH){width=stepW;height=stepH;if(newWidth*signWlobes){return 0}x*=Math.PI;if(abs(x)<1e-16){return 1}var xx=x/lobes;return sin(x)*sin(xx)/x/xx}}function process(u){var v,i,weight,idx,a,red,green,blue,alpha,fX,fY;center.x=(u+.5)*ratioX;icenter.x=floor(center.x);for(v=0;v=oW){continue}fX=floor(1e3*abs(i-center.x));if(!cacheLanc[fX]){cacheLanc[fX]={}}for(var j=icenter.y-range2Y;j<=icenter.y+range2Y;j++){if(j<0||j>=oH){continue}fY=floor(1e3*abs(j-center.y));if(!cacheLanc[fX][fY]){cacheLanc[fX][fY]=lanczos(sqrt(pow(fX*rcpRatioX,2)+pow(fY*rcpRatioY,2))/1e3)}weight=cacheLanc[fX][fY];if(weight>0){idx=(j*oW+i)*4;a+=weight;red+=weight*srcData[idx];green+=weight*srcData[idx+1];blue+=weight*srcData[idx+2];alpha+=weight*srcData[idx+3]}}}idx=(v*dW+u)*4;destData[idx]=red/a;destData[idx+1]=green/a;destData[idx+2]=blue/a;destData[idx+3]=alpha/a}if(++u1&&w<-1){continue}weight=2*w*w*w-3*w*w+1;if(weight>0){dx=4*(xx+yy*oW);gxA+=weight*data[dx+3];weightsAlpha+=weight;if(data[dx+3]<255){weight=weight*data[dx+3]/250}gxR+=weight*data[dx];gxG+=weight*data[dx+1];gxB+=weight*data[dx+2];weights+=weight}}}data2[x2]=gxR/weights;data2[x2+1]=gxG/weights;data2[x2+2]=gxB/weights;data2[x2+3]=gxA/weightsAlpha}}return img2},toObject:function(){return{type:this.type,scaleX:this.scaleX,scaleY:this.scaleY,resizeType:this.resizeType,lanczosLobes:this.lanczosLobes}}});fabric.Image.filters.Resize.fromObject=function(object){return new fabric.Image.filters.Resize(object)}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),extend=fabric.util.object.extend,clone=fabric.util.object.clone,toFixed=fabric.util.toFixed,supportsLineDash=fabric.StaticCanvas.supports("setLineDash"),NUM_FRACTION_DIGITS=fabric.Object.NUM_FRACTION_DIGITS;if(fabric.Text){fabric.warn("fabric.Text is already defined");return}var stateProperties=fabric.Object.prototype.stateProperties.concat();stateProperties.push("fontFamily","fontWeight","fontSize","text","textDecoration","textAlign","fontStyle","lineHeight","textBackgroundColor");fabric.Text=fabric.util.createClass(fabric.Object,{_dimensionAffectingProps:{fontSize:true,fontWeight:true,fontFamily:true,fontStyle:true,lineHeight:true,stroke:true,strokeWidth:true,text:true,textAlign:true},_reNewline:/\r?\n/,_reSpacesAndTabs:/[ \t\r]+/g,type:"text",fontSize:40,fontWeight:"normal",fontFamily:"Times New Roman",textDecoration:"",textAlign:"left",fontStyle:"",lineHeight:1.16,textBackgroundColor:"",stateProperties:stateProperties,stroke:null,shadow:null,_fontSizeFraction:.25,_fontSizeMult:1.13,initialize:function(text,options){options=options||{};this.text=text;this.__skipDimension=true;this.setOptions(options);this.__skipDimension=false;this._initDimensions()},_initDimensions:function(ctx){if(this.__skipDimension){return}if(!ctx){ctx=fabric.util.createCanvasElement().getContext("2d");this._setTextStyles(ctx)}this._textLines=this._splitTextIntoLines();this._clearCache();this._cacheLinesWidth=this.textAlign!=="justify";this.width=this._getTextWidth(ctx);this._cacheLinesWidth=true;this.height=this._getTextHeight(ctx)},toString:function(){return"#'},_render:function(ctx){this.clipTo&&fabric.util.clipContext(this,ctx);this._setOpacity(ctx);this._setShadow(ctx);this._setupCompositeOperation(ctx);this._renderTextBackground(ctx);this._setStrokeStyles(ctx);this._setFillStyles(ctx);this._renderText(ctx);this._renderTextDecoration(ctx);this.clipTo&&ctx.restore()},_renderText:function(ctx){this._translateForTextAlign(ctx);this._renderTextFill(ctx);this._renderTextStroke(ctx);this._translateForTextAlign(ctx,true)},_translateForTextAlign:function(ctx,back){if(this.textAlign!=="left"&&this.textAlign!=="justify"){var sign=back?-1:1;ctx.translate(this.textAlign==="center"?sign*this.width/2:sign*this.width,0)}},_setTextStyles:function(ctx){ctx.textBaseline="alphabetic";if(!this.skipTextAlign){ctx.textAlign=this.textAlign}ctx.font=this._getFontDeclaration()},_getTextHeight:function(){return this._textLines.length*this._getHeightOfLine()},_getTextWidth:function(ctx){var maxWidth=this._getLineWidth(ctx,0);for(var i=1,len=this._textLines.length;imaxWidth){maxWidth=currentLineWidth}}return maxWidth},_renderChars:function(method,ctx,chars,left,top){var shortM=method.slice(0,-4); -if(this[shortM].toLive){var offsetX=-this.width/2+this[shortM].offsetX||0,offsetY=-this.height/2+this[shortM].offsetY||0;ctx.save();ctx.translate(offsetX,offsetY);left-=offsetX;top-=offsetY}ctx[method](chars,left,top);this[shortM].toLive&&ctx.restore()},_renderTextLine:function(method,ctx,line,left,top,lineIndex){top-=this.fontSize*this._fontSizeFraction;var lineWidth=this._getLineWidth(ctx,lineIndex);if(this.textAlign!=="justify"||this.width0?widthDiff/numSpaces:0,leftOffset=0,word;for(var i=0,len=words.length;i1){width=this.width}else{width=ctx.measureText(line).width}}else{width=ctx.measureText(line).width}this._cacheLinesWidth&&(this.__lineWidths[lineIndex]=width);return width},_renderTextDecoration:function(ctx){if(!this.textDecoration){return}var halfOfVerticalBox=this.height/2,_this=this,offsets=[];function renderLinesAtOffset(offsets){var i,lineHeight=0,len,j,oLen,lineWidth,lineLeftOffset,heightOfLine;for(i=0,len=_this._textLines.length;i-1){offsets.push(.85)}if(this.textDecoration.indexOf("line-through")>-1){offsets.push(.43)}if(this.textDecoration.indexOf("overline")>-1){offsets.push(-.12)}if(offsets.length>0){renderLinesAtOffset(offsets)}},_getFontDeclaration:function(){return[fabric.isLikelyNode?this.fontWeight:this.fontStyle,fabric.isLikelyNode?this.fontStyle:this.fontWeight,this.fontSize+"px",fabric.isLikelyNode?'"'+this.fontFamily+'"':this.fontFamily].join(" ")},render:function(ctx,noTransform){if(!this.visible){return}ctx.save();this._setTextStyles(ctx);if(this._shouldClearCache()){this._initDimensions(ctx)}if(!noTransform){this.transform(ctx)}if(this.transformMatrix){ctx.transform.apply(ctx,this.transformMatrix)}if(this.group&&this.group.type==="path-group"){ctx.translate(this.left,this.top)}this._render(ctx);ctx.restore()},_splitTextIntoLines:function(){return this.text.split(this._reNewline)},toObject:function(propertiesToInclude){var object=extend(this.callSuper("toObject",propertiesToInclude),{text:this.text,fontSize:this.fontSize,fontWeight:this.fontWeight,fontFamily:this.fontFamily,fontStyle:this.fontStyle,lineHeight:this.lineHeight,textDecoration:this.textDecoration,textAlign:this.textAlign,textBackgroundColor:this.textBackgroundColor});if(!this.includeDefaultValues){this._removeDefaultValues(object)}return object},toSVG:function(reviver){var markup=this._createBaseSVGMarkup(),offsets=this._getSVGLeftTopOffsets(this.ctx),textAndBg=this._getSVGTextAndBg(offsets.textTop,offsets.textLeft);this._wrapSVGTextAndBg(markup,textAndBg);return reviver?reviver(markup.join("")):markup.join("")},_getSVGLeftTopOffsets:function(ctx){var lineTop=this._getHeightOfLine(ctx,0),textLeft=-this.width/2,textTop=0;return{textLeft:textLeft+(this.group&&this.group.type==="path-group"?this.left:0),textTop:textTop+(this.group&&this.group.type==="path-group"?-this.top:0),lineTop:lineTop}},_wrapSVGTextAndBg:function(markup,textAndBg){var noShadow=true,filter=this.getSvgFilter(),style=filter===""?"":' style="'+filter+'"';markup.push(' \n",textAndBg.textBgRects.join("")," \n',textAndBg.textSpans.join("")," \n"," \n")},_getSVGTextAndBg:function(textTopOffset,textLeftOffset){var textSpans=[],textBgRects=[],height=0;this._setSVGBg(textBgRects);for(var i=0,len=this._textLines.length;i",fabric.util.string.escapeXml(this._textLines[i]),"\n")},_setSVGTextLineJustifed:function(i,textSpans,yPos,textLeftOffset){var ctx=fabric.util.createCanvasElement().getContext("2d");this._setTextStyles(ctx);var line=this._textLines[i],words=line.split(/\s+/),wordsWidth=this._getWidthOfWords(ctx,line),widthDiff=this.width-wordsWidth,numSpaces=words.length-1,spaceWidth=numSpaces>0?widthDiff/numSpaces:0,word,attributes=this._getFillAttributes(this.fill),len;textLeftOffset+=this._getLineLeftOffset(this._getLineWidth(ctx,i));for(i=0,len=words.length;i",fabric.util.string.escapeXml(word),"\n");textLeftOffset+=this._getWidthOfWords(ctx,word)+spaceWidth}},_setSVGTextLineBg:function(textBgRects,i,textLeftOffset,textTopOffset,height){textBgRects.push(" \n')},_setSVGBg:function(textBgRects){if(this.backgroundColor){textBgRects.push(" \n')}},_getFillAttributes:function(value){var fillColor=value&&typeof value==="string"?new fabric.Color(value):"";if(!fillColor||!fillColor.getSource()||fillColor.getAlpha()===1){return'fill="'+value+'"'}return'opacity="'+fillColor.getAlpha()+'" fill="'+fillColor.setAlpha(1).toRgb()+'"'},_set:function(key,value){this.callSuper("_set",key,value);if(key in this._dimensionAffectingProps){this._initDimensions();this.setCoords()}},complexity:function(){return 1}});fabric.Text.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y dx dy font-family font-style font-weight font-size text-decoration text-anchor".split(" "));fabric.Text.DEFAULT_SVG_FONT_SIZE=16;fabric.Text.fromElement=function(element,options){if(!element){return null}var parsedAttributes=fabric.parseAttributes(element,fabric.Text.ATTRIBUTE_NAMES);options=fabric.util.object.extend(options?fabric.util.object.clone(options):{},parsedAttributes);options.top=options.top||0;options.left=options.left||0;if("dx"in parsedAttributes){options.left+=parsedAttributes.dx}if("dy"in parsedAttributes){options.top+=parsedAttributes.dy}if(!("fontSize"in options)){options.fontSize=fabric.Text.DEFAULT_SVG_FONT_SIZE}if(!options.originX){options.originX="left"}var textContent="";if(!("textContent"in element)){if("firstChild"in element&&element.firstChild!==null){if("data"in element.firstChild&&element.firstChild.data!==null){textContent=element.firstChild.data}}}else{textContent=element.textContent}textContent=textContent.replace(/^\s+|\s+$|\n+/g,"").replace(/\s+/g," ");var text=new fabric.Text(textContent,options),offX=0;if(text.originX==="left"){offX=text.getWidth()/2}if(text.originX==="right"){offX=-text.getWidth()/2}text.set({left:text.getLeft()+offX,top:text.getTop()-text.getHeight()/2+text.fontSize*(.18+text._fontSizeFraction)});return text};fabric.Text.fromObject=function(object){return new fabric.Text(object.text,clone(object))};fabric.util.createAccessors(fabric.Text)})(typeof exports!=="undefined"?exports:this);(function(){var clone=fabric.util.object.clone;fabric.IText=fabric.util.createClass(fabric.Text,fabric.Observable,{type:"i-text",selectionStart:0,selectionEnd:0,selectionColor:"rgba(17,119,255,0.3)",isEditing:false,editable:true,editingBorderColor:"rgba(102,153,255,0.25)",cursorWidth:2,cursorColor:"#333",cursorDelay:1e3,cursorDuration:600,styles:null,caching:true,_reSpace:/\s|\n/,_currentCursorOpacity:0,_selectionDirection:null,_abortCursorAnimation:false,_charWidthsCache:{},__widthOfSpace:[],initialize:function(text,options){this.styles=options?options.styles||{}:{};this.callSuper("initialize",text,options);this.initBehavior()},_clearCache:function(){this.callSuper("_clearCache");this.__widthOfSpace=[]},isEmptyStyles:function(){if(!this.styles){return true}var obj=this.styles;for(var p1 in obj){for(var p2 in obj[p1]){for(var p3 in obj[p1][p2]){return false}}}return true},setSelectionStart:function(index){index=Math.max(index,0);if(this.selectionStart!==index){this.fire("selection:changed");this.canvas&&this.canvas.fire("text:selection:changed",{target:this});this.selectionStart=index}this._updateTextarea()},setSelectionEnd:function(index){index=Math.min(index,this.text.length);if(this.selectionEnd!==index){this.fire("selection:changed");this.canvas&&this.canvas.fire("text:selection:changed",{target:this});this.selectionEnd=index}this._updateTextarea()},getSelectionStyles:function(startIndex,endIndex){if(arguments.length===2){var styles=[];for(var i=startIndex;i=start.charIndex&&(i!==endLine||jstartLine&&i0||this.skipFillStrokeCheck)){this.callSuper("_renderChars",method,ctx,line,left,top)}},_renderChar:function(method,ctx,lineIndex,i,_char,left,top,lineHeight){var charWidth,charHeight,shouldFill,shouldStroke,decl=this._getStyleDeclaration(lineIndex,i),offset,textDecoration;if(decl){charHeight=this._getHeightOfChar(ctx,_char,lineIndex,i);shouldStroke=decl.stroke;shouldFill=decl.fill;textDecoration=decl.textDecoration}else{charHeight=this.fontSize}shouldStroke=(shouldStroke||this.stroke)&&method==="strokeText";shouldFill=(shouldFill||this.fill)&&method==="fillText";decl&&ctx.save();charWidth=this._applyCharStylesGetWidth(ctx,_char,lineIndex,i,decl||{});textDecoration=textDecoration||this.textDecoration;if(decl&&decl.textBackgroundColor){this._removeShadow(ctx)}shouldFill&&ctx.fillText(_char,left,top);shouldStroke&&ctx.strokeText(_char,left,top);if(textDecoration||textDecoration!==""){offset=this._fontSizeFraction*lineHeight/this.lineHeight;this._renderCharDecoration(ctx,textDecoration,left,top,offset,charWidth,charHeight)}decl&&ctx.restore();ctx.translate(charWidth,0)},_hasStyleChanged:function(prevStyle,thisStyle){return prevStyle.fill!==thisStyle.fill||prevStyle.fontSize!==thisStyle.fontSize||prevStyle.textBackgroundColor!==thisStyle.textBackgroundColor||prevStyle.textDecoration!==thisStyle.textDecoration||prevStyle.fontFamily!==thisStyle.fontFamily||prevStyle.fontWeight!==thisStyle.fontWeight||prevStyle.fontStyle!==thisStyle.fontStyle||prevStyle.stroke!==thisStyle.stroke||prevStyle.strokeWidth!==thisStyle.strokeWidth},_renderCharDecoration:function(ctx,textDecoration,left,top,offset,charWidth,charHeight){if(!textDecoration){return}var decorationWeight=charHeight/15,positions={underline:top+charHeight/10,"line-through":top-charHeight*(this._fontSizeFraction+this._fontSizeMult-1)+decorationWeight,overline:top-(this._fontSizeMult-this._fontSizeFraction)*charHeight},decorations=["underline","line-through","overline"],i,decoration;for(i=0;i-1){ctx.fillRect(left,positions[decoration],charWidth,decorationWeight)}}},_renderTextLine:function(method,ctx,line,left,top,lineIndex){if(!this.isEmptyStyles()){top+=this.fontSize*(this._fontSizeFraction+.03)}this.callSuper("_renderTextLine",method,ctx,line,left,top,lineIndex)},_renderTextDecoration:function(ctx){if(this.isEmptyStyles()){return this.callSuper("_renderTextDecoration",ctx)}},_renderTextLinesBackground:function(ctx){this.callSuper("_renderTextLinesBackground",ctx);var lineTopOffset=0,heightOfLine,lineWidth,lineLeftOffset,leftOffset=this._getLeftOffset(),topOffset=this._getTopOffset(),line,_char,style;for(var i=0,len=this._textLines.length;imaxHeight){maxHeight=currentCharHeight}}this.__lineHeights[lineIndex]=maxHeight*this.lineHeight*this._fontSizeMult;return this.__lineHeights[lineIndex]},_getTextHeight:function(ctx){var height=0;for(var i=0,len=this._textLines.length;i-1){offset++;index--}return startFrom-offset},findWordBoundaryRight:function(startFrom){var offset=0,index=startFrom;if(this._reSpace.test(this.text.charAt(index))){while(this._reSpace.test(this.text.charAt(index))){offset++;index++}}while(/\S/.test(this.text.charAt(index))&&index-1){offset++;index--}return startFrom-offset},findLineBoundaryRight:function(startFrom){var offset=0,index=startFrom;while(!/\n/.test(this.text.charAt(index))&&index0&&index=_this.__selectionStartOnMouseDown){_this.setSelectionStart(_this.__selectionStartOnMouseDown);_this.setSelectionEnd(newSelectionStart)}else{_this.setSelectionStart(newSelectionStart);_this.setSelectionEnd(_this.__selectionStartOnMouseDown)}})},_setEditingProps:function(){this.hoverCursor="text";if(this.canvas){this.canvas.defaultCursor=this.canvas.moveCursor="text"}this.borderColor=this.editingBorderColor;this.hasControls=this.selectable=false;this.lockMovementX=this.lockMovementY=true},_updateTextarea:function(){if(!this.hiddenTextarea||this.inCompositionMode){return}this.hiddenTextarea.value=this.text;this.hiddenTextarea.selectionStart=this.selectionStart;this.hiddenTextarea.selectionEnd=this.selectionEnd;if(this.selectionStart===this.selectionEnd){var p=this._calcTextareaPosition();this.hiddenTextarea.style.left=p.x+"px";this.hiddenTextarea.style.top=p.y+"px"}},_calcTextareaPosition:function(){var chars=this.text.split(""),boundaries=this._getCursorBoundaries(chars,"cursor"),cursorLocation=this.get2DCursorLocation(),lineIndex=cursorLocation.lineIndex,charIndex=cursorLocation.charIndex,charHeight=this.getCurrentCharFontSize(lineIndex,charIndex),leftOffset=lineIndex===0&&charIndex===0?this._getLineLeftOffset(this._getLineWidth(this.ctx,lineIndex)):boundaries.leftOffset,m=this.calcTransformMatrix(),p={x:boundaries.left+leftOffset,y:boundaries.top+boundaries.topOffset+charHeight};this.hiddenTextarea.style.fontSize=charHeight+"px";return fabric.util.transformPoint(p,m)},_saveEditingProps:function(){this._savedProps={hasControls:this.hasControls,borderColor:this.borderColor,lockMovementX:this.lockMovementX,lockMovementY:this.lockMovementY,hoverCursor:this.hoverCursor,defaultCursor:this.canvas&&this.canvas.defaultCursor,moveCursor:this.canvas&&this.canvas.moveCursor}},_restoreEditingProps:function(){if(!this._savedProps){return}this.hoverCursor=this._savedProps.overCursor;this.hasControls=this._savedProps.hasControls;this.borderColor=this._savedProps.borderColor;this.lockMovementX=this._savedProps.lockMovementX;this.lockMovementY=this._savedProps.lockMovementY;if(this.canvas){this.canvas.defaultCursor=this._savedProps.defaultCursor;this.canvas.moveCursor=this._savedProps.moveCursor}},exitEditing:function(){this.selected=false;this.isEditing=false;this.selectable=true;this.selectionEnd=this.selectionStart;this.hiddenTextarea&&this.canvas&&this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea);this.hiddenTextarea=null;this.abortCursorAnimation();this._restoreEditingProps();this._currentCursorOpacity=0;this.fire("editing:exited");this.canvas&&this.canvas.fire("text:editing:exited",{target:this});return this},_removeExtraneousStyles:function(){for(var prop in this.styles){if(!this._textLines[prop]){delete this.styles[prop]}}},_removeCharsFromTo:function(start,end){while(end!==start){this._removeSingleCharAndStyle(start+1);end--}this.setSelectionStart(start)},_removeSingleCharAndStyle:function(index){var isBeginningOfLine=this.text[index-1]==="\n",indexStyle=isBeginningOfLine?index:index-1;this.removeStyleObject(isBeginningOfLine,indexStyle);this.text=this.text.slice(0,index-1)+this.text.slice(index);this._textLines=this._splitTextIntoLines()},insertChars:function(_chars,useCopiedStyle){var style;if(this.selectionEnd-this.selectionStart>1){this._removeCharsFromTo(this.selectionStart,this.selectionEnd);this.setSelectionEnd(this.selectionStart)}if(!useCopiedStyle&&this.isEmptyStyles()){this.insertChar(_chars,false);return}for(var i=0,len=_chars.length;i=charIndex){newLineStyles[parseInt(index,10)-charIndex]=this.styles[lineIndex][index];delete this.styles[lineIndex][index]}}this.styles[lineIndex+1]=newLineStyles}this._forceClearCache=true},insertCharStyleObject:function(lineIndex,charIndex,style){var currentLineStyles=this.styles[lineIndex],currentLineStylesCloned=clone(currentLineStyles);if(charIndex===0&&!style){charIndex=1}for(var index in currentLineStylesCloned){var numericIndex=parseInt(index,10);if(numericIndex>=charIndex){currentLineStyles[numericIndex+1]=currentLineStylesCloned[numericIndex];if(!currentLineStylesCloned[numericIndex-1]){delete currentLineStyles[numericIndex]}}}this.styles[lineIndex][charIndex]=style||clone(currentLineStyles[charIndex-1]);this._forceClearCache=true},insertStyleObjects:function(_chars,isEndOfLine,styleObject){var cursorLocation=this.get2DCursorLocation(),lineIndex=cursorLocation.lineIndex,charIndex=cursorLocation.charIndex;if(!this._getLineStyle(lineIndex)){this._setLineStyle(lineIndex,{})}if(_chars==="\n"){this.insertNewlineStyleObject(lineIndex,charIndex,isEndOfLine)}else{this.insertCharStyleObject(lineIndex,charIndex,styleObject)}},shiftLineStyles:function(lineIndex,offset){var clonedStyles=clone(this.styles);for(var line in this.styles){var numericLine=parseInt(line,10);if(numericLine>lineIndex){this.styles[numericLine+offset]=clonedStyles[numericLine];if(!clonedStyles[numericLine-offset]){delete this.styles[numericLine]}}}},removeStyleObject:function(isBeginningOfLine,index){var cursorLocation=this.get2DCursorLocation(index),lineIndex=cursorLocation.lineIndex,charIndex=cursorLocation.charIndex;this._removeStyleObject(isBeginningOfLine,cursorLocation,lineIndex,charIndex)},_getTextOnPreviousLine:function(lIndex){return this._textLines[lIndex-1]},_removeStyleObject:function(isBeginningOfLine,cursorLocation,lineIndex,charIndex){if(isBeginningOfLine){var textOnPreviousLine=this._getTextOnPreviousLine(cursorLocation.lineIndex),newCharIndexOnPrevLine=textOnPreviousLine?textOnPreviousLine.length:0;if(!this.styles[lineIndex-1]){this.styles[lineIndex-1]={}}for(charIndex in this.styles[lineIndex]){this.styles[lineIndex-1][parseInt(charIndex,10)+newCharIndexOnPrevLine]=this.styles[lineIndex][charIndex]}this.shiftLineStyles(cursorLocation.lineIndex,-1)}else{var currentLineStyles=this.styles[lineIndex];if(currentLineStyles){delete currentLineStyles[charIndex]}var currentLineStylesCloned=clone(currentLineStyles);for(var i in currentLineStylesCloned){var numericIndex=parseInt(i,10);if(numericIndex>=charIndex&&numericIndex!==0){currentLineStyles[numericIndex-1]=currentLineStylesCloned[numericIndex];delete currentLineStyles[numericIndex]}}}},insertNewline:function(){this.insertChars("\n")}})})();fabric.util.object.extend(fabric.IText.prototype,{initDoubleClickSimulation:function(){this.__lastClickTime=+new Date;this.__lastLastClickTime=+new Date;this.__lastPointer={};this.on("mousedown",this.onMouseDown.bind(this))},onMouseDown:function(options){this.__newClickTime=+new Date;var newPointer=this.canvas.getPointer(options.e);if(this.isTripleClick(newPointer)){this.fire("tripleclick",options);this._stopEvent(options.e)}else if(this.isDoubleClick(newPointer)){this.fire("dblclick",options);this._stopEvent(options.e)}this.__lastLastClickTime=this.__lastClickTime;this.__lastClickTime=this.__newClickTime;this.__lastPointer=newPointer;this.__lastIsEditing=this.isEditing;this.__lastSelected=this.selected},isDoubleClick:function(newPointer){return this.__newClickTime-this.__lastClickTime<500&&this.__lastPointer.x===newPointer.x&&this.__lastPointer.y===newPointer.y&&this.__lastIsEditing},isTripleClick:function(newPointer){return this.__newClickTime-this.__lastClickTime<500&&this.__lastClickTime-this.__lastLastClickTime<500&&this.__lastPointer.x===newPointer.x&&this.__lastPointer.y===newPointer.y},_stopEvent:function(e){e.preventDefault&&e.preventDefault();e.stopPropagation&&e.stopPropagation()},initCursorSelectionHandlers:function(){this.initSelectedHandler();this.initMousedownHandler();this.initMouseupHandler();this.initClicks()},initClicks:function(){this.on("dblclick",function(options){this.selectWord(this.getSelectionStartFromPointer(options.e))});this.on("tripleclick",function(options){this.selectLine(this.getSelectionStartFromPointer(options.e))})},initMousedownHandler:function(){this.on("mousedown",function(options){if(!this.editable){return}var pointer=this.canvas.getPointer(options.e);this.__mousedownX=pointer.x;this.__mousedownY=pointer.y;this.__isMousedown=true;if(this.hiddenTextarea&&this.canvas){this.canvas.wrapperEl.appendChild(this.hiddenTextarea)}if(this.selected){this.setCursorByClick(options.e)}if(this.isEditing){this.__selectionStartOnMouseDown=this.selectionStart;this.initDelayedCursor(true)}})},_isObjectMoved:function(e){var pointer=this.canvas.getPointer(e);return this.__mousedownX!==pointer.x||this.__mousedownY!==pointer.y},initMouseupHandler:function(){this.on("mouseup",function(options){this.__isMousedown=false;if(!this.editable||this._isObjectMoved(options.e)){return}if(this.__lastSelected&&!this.__corner){this.enterEditing(options.e);this.initDelayedCursor(true)}this.selected=true})},setCursorByClick:function(e){var newSelectionStart=this.getSelectionStartFromPointer(e);if(e.shiftKey){if(newSelectionStartdistanceBtwLastCharAndCursor?0:1,newSelectionStart=index+offset;if(this.flipX){newSelectionStart=jlen-newSelectionStart}if(newSelectionStart>this.text.length){newSelectionStart=this.text.length}return newSelectionStart}});fabric.util.object.extend(fabric.IText.prototype,{initHiddenTextarea:function(e){var p;if(e&&this.canvas){p=this.canvas.getPointer(e)}else{this.oCoords||this.setCoords();p=this.oCoords.tl}this.hiddenTextarea=fabric.document.createElement("textarea");this.hiddenTextarea.setAttribute("autocapitalize","off");this.hiddenTextarea.style.cssText="position: absolute; top: "+p.y+"px; left: "+p.x+"px; opacity: 0;"+" width: 0px; height: 0px; z-index: -999;";if(this.canvas){this.canvas.lowerCanvasEl.parentNode.appendChild(this.hiddenTextarea)}else{fabric.document.body.appendChild(this.hiddenTextarea)}fabric.util.addListener(this.hiddenTextarea,"keydown",this.onKeyDown.bind(this));fabric.util.addListener(this.hiddenTextarea,"keyup",this.onKeyUp.bind(this));fabric.util.addListener(this.hiddenTextarea,"input",this.onInput.bind(this));fabric.util.addListener(this.hiddenTextarea,"copy",this.copy.bind(this));fabric.util.addListener(this.hiddenTextarea,"cut",this.cut.bind(this));fabric.util.addListener(this.hiddenTextarea,"paste",this.paste.bind(this));fabric.util.addListener(this.hiddenTextarea,"compositionstart",this.onCompositionStart.bind(this));fabric.util.addListener(this.hiddenTextarea,"compositionupdate",this.onCompositionUpdate.bind(this));fabric.util.addListener(this.hiddenTextarea,"compositionend",this.onCompositionEnd.bind(this));if(!this._clickHandlerInitialized&&this.canvas){fabric.util.addListener(this.canvas.upperCanvasEl,"click",this.onClick.bind(this));this._clickHandlerInitialized=true}},_keysMap:{8:"removeChars",9:"exitEditing",27:"exitEditing",13:"insertNewline",33:"moveCursorUp",34:"moveCursorDown",35:"moveCursorRight",36:"moveCursorLeft",37:"moveCursorLeft",38:"moveCursorUp",39:"moveCursorRight",40:"moveCursorDown",46:"forwardDelete"},_ctrlKeysMap:{65:"selectAll",67:"copy",88:"cut"},onClick:function(){this.hiddenTextarea&&this.hiddenTextarea.focus()},onKeyDown:function(e){if(!this.isEditing){return}if(e.keyCode in this._keysMap){this[this._keysMap[e.keyCode]](e)}else{return}e.stopImmediatePropagation();e.preventDefault();this.canvas&&this.canvas.renderAll()},onKeyUp:function(e){if(!this.isEditing||this._copyDone){this._copyDone=false;return}if(e.keyCode in this._ctrlKeysMap&&(e.ctrlKey||e.metaKey)){this[this._ctrlKeysMap[e.keyCode]](e)}else{return}e.stopImmediatePropagation();e.preventDefault();this.canvas&&this.canvas.renderAll()},onInput:function(e){if(!this.isEditing||this.inCompositionMode){return}var offset=this.selectionStart||0,offsetEnd=this.selectionEnd||0,textLength=this.text.length,newTextLength=this.hiddenTextarea.value.length,diff,charsToInsert,start;if(newTextLength>textLength){start=this._selectionDirection==="left"?offsetEnd:offset;diff=newTextLength-textLength;charsToInsert=this.hiddenTextarea.value.slice(start,start+diff)}else{diff=newTextLength-textLength+offsetEnd-offset;charsToInsert=this.hiddenTextarea.value.slice(offset,offset+diff)}this.insertChars(charsToInsert);e.stopPropagation()},onCompositionStart:function(){this.inCompositionMode=true;this.prevCompositionLength=0;this.compositionStart=this.selectionStart},onCompositionEnd:function(){this.inCompositionMode=false},onCompositionUpdate:function(e){var data=e.data;this.selectionStart=this.compositionStart;this.selectionEnd=this.selectionEnd===this.selectionStart?this.compositionStart+this.prevCompositionLength:this.selectionEnd;this.insertChars(data,false);this.prevCompositionLength=data.length},forwardDelete:function(e){if(this.selectionStart===this.selectionEnd){if(this.selectionStart===this.text.length){return}this.moveCursorRight(e)}this.removeChars(e)},copy:function(e){if(this.selectionStart===this.selectionEnd){return}var selectedText=this.getSelectedText(),clipboardData=this._getClipboardData(e);if(clipboardData){clipboardData.setData("text",selectedText)}fabric.copiedText=selectedText;fabric.copiedTextStyle=this.getSelectionStyles(this.selectionStart,this.selectionEnd);e.stopImmediatePropagation();e.preventDefault();this._copyDone=true},paste:function(e){var copiedText=null,clipboardData=this._getClipboardData(e),useCopiedStyle=true;if(clipboardData){copiedText=clipboardData.getData("text").replace(/\r/g,"");if(!fabric.copiedTextStyle||fabric.copiedText!==copiedText){useCopiedStyle=false}}else{copiedText=fabric.copiedText}if(copiedText){this.insertChars(copiedText,useCopiedStyle)}e.stopImmediatePropagation();e.preventDefault()},cut:function(e){if(this.selectionStart===this.selectionEnd){return}this.copy(e);this.removeChars(e)},_getClipboardData:function(e){return e&&e.clipboardData||fabric.window.clipboardData},getDownCursorOffset:function(e,isRight){var selectionProp=isRight?this.selectionEnd:this.selectionStart,cursorLocation=this.get2DCursorLocation(selectionProp),_char,lineLeftOffset,lineIndex=cursorLocation.lineIndex,textOnSameLineBeforeCursor=this._textLines[lineIndex].slice(0,cursorLocation.charIndex),textOnSameLineAfterCursor=this._textLines[lineIndex].slice(cursorLocation.charIndex),textOnNextLine=this._textLines[lineIndex+1]||"";if(lineIndex===this._textLines.length-1||e.metaKey||e.keyCode===34){return this.text.length-selectionProp}var widthOfSameLineBeforeCursor=this._getLineWidth(this.ctx,lineIndex);lineLeftOffset=this._getLineLeftOffset(widthOfSameLineBeforeCursor);var widthOfCharsOnSameLineBeforeCursor=lineLeftOffset;for(var i=0,len=textOnSameLineBeforeCursor.length;iwidthOfCharsOnSameLineBeforeCursor){foundMatch=true;var leftEdge=widthOfCharsOnNextLine-widthOfChar,rightEdge=widthOfCharsOnNextLine,offsetFromLeftEdge=Math.abs(leftEdge-widthOfCharsOnSameLineBeforeCursor),offsetFromRightEdge=Math.abs(rightEdge-widthOfCharsOnSameLineBeforeCursor);indexOnNextLine=offsetFromRightEdgethis.text.length){this.setSelectionEnd(this.text.length)}},getUpCursorOffset:function(e,isRight){var selectionProp=isRight?this.selectionEnd:this.selectionStart,cursorLocation=this.get2DCursorLocation(selectionProp),lineIndex=cursorLocation.lineIndex;if(lineIndex===0||e.metaKey||e.keyCode===33){return selectionProp}var textOnSameLineBeforeCursor=this._textLines[lineIndex].slice(0,cursorLocation.charIndex),textOnPreviousLine=this._textLines[lineIndex-1]||"",_char,widthOfSameLineBeforeCursor=this._getLineWidth(this.ctx,cursorLocation.lineIndex),lineLeftOffset=this._getLineLeftOffset(widthOfSameLineBeforeCursor),widthOfCharsOnSameLineBeforeCursor=lineLeftOffset;for(var i=0,len=textOnSameLineBeforeCursor.length;iwidthOfCharsOnSameLineBeforeCursor){foundMatch=true;var leftEdge=widthOfCharsOnPreviousLine-widthOfChar,rightEdge=widthOfCharsOnPreviousLine,offsetFromLeftEdge=Math.abs(leftEdge-widthOfCharsOnSameLineBeforeCursor),offsetFromRightEdge=Math.abs(rightEdge-widthOfCharsOnSameLineBeforeCursor);indexOnPrevLine=offsetFromRightEdge=this.text.length&&this.selectionEnd>=this.text.length){return}this.abortCursorAnimation();this._currentCursorOpacity=1;if(e.shiftKey){this.moveCursorRightWithShift(e)}else{this.moveCursorRightWithoutShift(e)}this.initDelayedCursor()},moveCursorRightWithShift:function(e){if(this._selectionDirection==="left"&&this.selectionStart!==this.selectionEnd){this._moveRight(e,"selectionStart")}else{this._selectionDirection="right";this._moveRight(e,"selectionEnd")}},moveCursorRightWithoutShift:function(e){this._selectionDirection="right";if(this.selectionStart===this.selectionEnd){this._moveRight(e,"selectionStart");this.setSelectionEnd(this.selectionStart)}else{this.setSelectionEnd(this.selectionEnd+this.getNumNewLinesInSelectedText());this.setSelectionStart(this.selectionEnd)}},removeChars:function(e){if(this.selectionStart===this.selectionEnd){this._removeCharsNearCursor(e)}else{this._removeCharsFromTo(this.selectionStart,this.selectionEnd)}this.setSelectionEnd(this.selectionStart);this._removeExtraneousStyles();this.canvas&&this.canvas.renderAll();this.setCoords();this.fire("changed");this.canvas&&this.canvas.fire("text:changed",{target:this})},_removeCharsNearCursor:function(e){if(this.selectionStart===0){return}if(e.metaKey){var leftLineBoundary=this.findLineBoundaryLeft(this.selectionStart);this._removeCharsFromTo(leftLineBoundary,this.selectionStart);this.setSelectionStart(leftLineBoundary)}else if(e.altKey){var leftWordBoundary=this.findWordBoundaryLeft(this.selectionStart);this._removeCharsFromTo(leftWordBoundary,this.selectionStart);this.setSelectionStart(leftWordBoundary)}else{this._removeSingleCharAndStyle(this.selectionStart);this.setSelectionStart(this.selectionStart-1)}}});(function(){var toFixed=fabric.util.toFixed,NUM_FRACTION_DIGITS=fabric.Object.NUM_FRACTION_DIGITS;fabric.util.object.extend(fabric.IText.prototype,{_setSVGTextLineText:function(lineIndex,textSpans,height,textLeftOffset,textTopOffset,textBgRects){if(!this._getLineStyle(lineIndex)){fabric.Text.prototype._setSVGTextLineText.call(this,lineIndex,textSpans,height,textLeftOffset,textTopOffset)}else{this._setSVGTextLineChars(lineIndex,textSpans,height,textLeftOffset,textBgRects)}},_setSVGTextLineChars:function(lineIndex,textSpans,height,textLeftOffset,textBgRects){var chars=this._textLines[lineIndex],charOffset=0,lineLeftOffset=this._getLineLeftOffset(this._getLineWidth(this.ctx,lineIndex))-this.width/2,lineOffset=this._getSVGLineTopOffset(lineIndex),heightOfLine=this._getHeightOfLine(this.ctx,lineIndex);for(var i=0,len=chars.length;i\n'].join("")},_createTextCharSpan:function(_char,styleDecl,lineLeftOffset,lineTopOffset,charOffset){var fillStyles=this.getSvgStyles.call(fabric.util.object.extend({visible:true,fill:this.fill,stroke:this.stroke,type:"text",getSvgFilter:fabric.Object.prototype.getSvgFilter},styleDecl));return[' ',fabric.util.string.escapeXml(_char),"\n"].join("")}})})();(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),clone=fabric.util.object.clone;fabric.Textbox=fabric.util.createClass(fabric.IText,fabric.Observable,{type:"textbox",minWidth:20,dynamicMinWidth:0,__cachedLines:null,initialize:function(text,options){this.ctx=fabric.util.createCanvasElement().getContext("2d");this.callSuper("initialize",text,options);this.set({lockUniScaling:false,lockScalingY:true,lockScalingFlip:true,hasBorders:true});this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());this._dimensionAffectingProps.width=true},_initDimensions:function(ctx){if(this.__skipDimension){return}if(!ctx){ctx=fabric.util.createCanvasElement().getContext("2d");this._setTextStyles(ctx)}this.dynamicMinWidth=0;this._textLines=this._splitTextIntoLines();if(this.dynamicMinWidth>this.width){this._set("width",this.dynamicMinWidth)}this._clearCache();this.height=this._getTextHeight(ctx)},_generateStyleMap:function(){var realLineCount=0,realLineCharCount=0,charCount=0,map={};for(var i=0;i=this.width&&!lineJustStarted){lines.push(line);line="";lineWidth=wordWidth;lineJustStarted=true}if(!lineJustStarted){line+=infix}line+=word;infixWidth=this._measureText(ctx,infix,lineIndex,offset);offset++;lineJustStarted=false;if(wordWidth>largestWordWidth){largestWordWidth=wordWidth}}i&&lines.push(line);if(largestWordWidth>this.dynamicMinWidth){this.dynamicMinWidth=largestWordWidth}return lines},_splitTextIntoLines:function(){var originalAlign=this.textAlign;this.ctx.save();this._setTextStyles(this.ctx);this.textAlign="left";var lines=this._wrapText(this.ctx,this.text);this.textAlign=originalAlign;this.ctx.restore();this._textLines=lines;this._styleMap=this._generateStyleMap();return lines},setOnGroup:function(key,value){if(key==="scaleX"){this.set("scaleX",Math.abs(1/value));this.set("width",this.get("width")*value/(typeof this.__oldScaleX==="undefined"?1:this.__oldScaleX));this.__oldScaleX=value}},get2DCursorLocation:function(selectionStart){if(typeof selectionStart==="undefined"){selectionStart=this.selectionStart}var numLines=this._textLines.length,removed=0;for(var i=0;i=t.getMinWidth()){t.set("width",w)}}else{setObjectScaleOverridden.call(fabric.Canvas.prototype,localMouse,transform,lockScalingX,lockScalingY,by,lockScalingFlip,_dim)}};fabric.Group.prototype._refreshControlsVisibility=function(){if(typeof fabric.Textbox==="undefined"){return}for(var i=this._objects.length;i--;){if(this._objects[i]instanceof fabric.Textbox){this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());return}}};var clone=fabric.util.object.clone;fabric.util.object.extend(fabric.Textbox.prototype,{_removeExtraneousStyles:function(){for(var prop in this._styleMap){if(!this._textLines[prop]){delete this.styles[this._styleMap[prop].line]}}},insertCharStyleObject:function(lineIndex,charIndex,style){var map=this._styleMap[lineIndex];lineIndex=map.line;charIndex=map.offset+charIndex;fabric.IText.prototype.insertCharStyleObject.apply(this,[lineIndex,charIndex,style])},insertNewlineStyleObject:function(lineIndex,charIndex,isEndOfLine){var map=this._styleMap[lineIndex];lineIndex=map.line;charIndex=map.offset+charIndex;fabric.IText.prototype.insertNewlineStyleObject.apply(this,[lineIndex,charIndex,isEndOfLine])},shiftLineStyles:function(lineIndex,offset){var clonedStyles=clone(this.styles),map=this._styleMap[lineIndex];lineIndex=map.line;for(var line in this.styles){var numericLine=parseInt(line,10);if(numericLine>lineIndex){this.styles[numericLine+offset]=clonedStyles[numericLine];if(!clonedStyles[numericLine-offset]){delete this.styles[numericLine]}}}},_getTextOnPreviousLine:function(lIndex){var textOnPreviousLine=this._textLines[lIndex-1];while(this._styleMap[lIndex-2]&&this._styleMap[lIndex-2].line===this._styleMap[lIndex-1].line){textOnPreviousLine=this._textLines[lIndex-2]+textOnPreviousLine;lIndex--}return textOnPreviousLine},removeStyleObject:function(isBeginningOfLine,index){var cursorLocation=this.get2DCursorLocation(index),map=this._styleMap[cursorLocation.lineIndex],lineIndex=map.line,charIndex=map.offset+cursorLocation.charIndex;this._removeStyleObject(isBeginningOfLine,cursorLocation,lineIndex,charIndex)}})})();(function(){var override=fabric.IText.prototype._getNewSelectionStartFromOffset;fabric.IText.prototype._getNewSelectionStartFromOffset=function(mouseOffset,prevWidth,width,index,jlen){index=override.call(this,mouseOffset,prevWidth,width,index,jlen);var tmp=0,removed=0;for(var i=0;i=index){break}if(this.text[tmp+removed]==="\n"||this.text[tmp+removed]===" "){removed++}}return index-i+removed}})();(function(){if(typeof document!=="undefined"&&typeof window!=="undefined"){return}var DOMParser=require("xmldom").DOMParser,URL=require("url"),HTTP=require("http"),HTTPS=require("https"),Canvas=require("canvas"),Image=require("canvas").Image;function request(url,encoding,callback){var oURL=URL.parse(url);if(!oURL.port){oURL.port=oURL.protocol.indexOf("https:")===0?443:80}var reqHandler=oURL.protocol.indexOf("https:")===0?HTTPS:HTTP,req=reqHandler.request({hostname:oURL.hostname,port:oURL.port,path:oURL.path,method:"GET"},function(response){var body="";if(encoding){response.setEncoding(encoding)}response.on("end",function(){callback(body)});response.on("data",function(chunk){if(response.statusCode===200){body+=chunk}})});req.on("error",function(err){if(err.errno===process.ECONNREFUSED){fabric.log("ECONNREFUSED: connection refused to "+oURL.hostname+":"+oURL.port)}else{fabric.log(err.message)}callback(null)});req.end()}function requestFs(path,callback){var fs=require("fs");fs.readFile(path,function(err,data){if(err){fabric.log(err);throw err}else{callback(data)}})}fabric.util.loadImage=function(url,callback,context){function createImageAndCallBack(data){if(data){img.src=new Buffer(data,"binary");img._src=url;callback&&callback.call(context,img)}else{img=null;callback&&callback.call(context,null,true)}}var img=new Image;if(url&&(url instanceof Buffer||url.indexOf("data")===0)){img.src=img._src=url;callback&&callback.call(context,img)}else if(url&&url.indexOf("http")!==0){requestFs(url,createImageAndCallBack)}else if(url){request(url,"binary",createImageAndCallBack)}else{callback&&callback.call(context,url)}};fabric.loadSVGFromURL=function(url,callback,reviver){url=url.replace(/^\n\s*/,"").replace(/\?.*$/,"").trim();if(url.indexOf("http")!==0){requestFs(url,function(body){fabric.loadSVGFromString(body.toString(),callback,reviver)})}else{request(url,"",function(body){fabric.loadSVGFromString(body,callback,reviver)})}};fabric.loadSVGFromString=function(string,callback,reviver){var doc=(new DOMParser).parseFromString(string);fabric.parseSVGDocument(doc.documentElement,function(results,options){callback&&callback(results,options)},reviver)};fabric.util.getScript=function(url,callback){request(url,"",function(body){eval(body);callback&&callback()})};fabric.Image.fromObject=function(object,callback){fabric.util.loadImage(object.src,function(img){var oImg=new fabric.Image(img);oImg._initConfig(object);oImg._initFilters(object.filters,function(filters){oImg.filters=filters||[];oImg._initFilters(object.resizeFilters,function(resizeFilters){oImg.resizeFilters=resizeFilters||[];callback&&callback(oImg)})})})};fabric.createCanvasForNode=function(width,height,options,nodeCanvasOptions){nodeCanvasOptions=nodeCanvasOptions||options;var canvasEl=fabric.document.createElement("canvas"),nodeCanvas=new Canvas(width||600,height||600,nodeCanvasOptions);canvasEl.style={};canvasEl.width=nodeCanvas.width;canvasEl.height=nodeCanvas.height;var FabricCanvas=fabric.Canvas||fabric.StaticCanvas,fabricCanvas=new FabricCanvas(canvasEl,options);fabricCanvas.contextContainer=nodeCanvas.getContext("2d");fabricCanvas.nodeCanvas=nodeCanvas;fabricCanvas.Font=Canvas.Font;return fabricCanvas};fabric.StaticCanvas.prototype.createPNGStream=function(){return this.nodeCanvas.createPNGStream()};fabric.StaticCanvas.prototype.createJPEGStream=function(opts){return this.nodeCanvas.createJPEGStream(opts)};var origSetWidth=fabric.StaticCanvas.prototype.setWidth;fabric.StaticCanvas.prototype.setWidth=function(width,options){origSetWidth.call(this,width,options);this.nodeCanvas.width=width;return this};if(fabric.Canvas){fabric.Canvas.prototype.setWidth=fabric.StaticCanvas.prototype.setWidth}var origSetHeight=fabric.StaticCanvas.prototype.setHeight;fabric.StaticCanvas.prototype.setHeight=function(height,options){origSetHeight.call(this,height,options);this.nodeCanvas.height=height;return this};if(fabric.Canvas){fabric.Canvas.prototype.setHeight=fabric.StaticCanvas.prototype.setHeight}})(); \ No newline at end of file +var fabric=fabric||{version:"1.6.0-rc.1"};"undefined"!=typeof exports&&(exports.fabric=fabric),"undefined"!=typeof document&&"undefined"!=typeof window?(fabric.document=document,fabric.window=window,window.fabric=fabric):(fabric.document=require("jsdom").jsdom(""),fabric.window=fabric.document.createWindow?fabric.document.createWindow():fabric.document.parentWindow),fabric.isTouchSupported="ontouchstart"in fabric.document.documentElement,fabric.isLikelyNode="undefined"!=typeof Buffer&&"undefined"==typeof window,fabric.SHARED_ATTRIBUTES=["display","transform","fill","fill-opacity","fill-rule","opacity","stroke","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","id"],fabric.DPI=96,fabric.reNum="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",fabric.fontPaths={},fabric.devicePixelRatio=fabric.window.devicePixelRatio||fabric.window.webkitDevicePixelRatio||fabric.window.mozDevicePixelRatio||1,function(){function t(t,e){if(this.__eventListeners[t]){var i=this.__eventListeners[t];e?i[i.indexOf(e)]=!1:fabric.util.array.fill(i,!1)}}function e(t,e){if(this.__eventListeners||(this.__eventListeners={}),1===arguments.length)for(var i in t)this.on(i,t[i]);else this.__eventListeners[t]||(this.__eventListeners[t]=[]),this.__eventListeners[t].push(e);return this}function i(e,i){if(this.__eventListeners){if(0===arguments.length)for(e in this.__eventListeners)t.call(this,e);else if(1===arguments.length&&"object"==typeof arguments[0])for(var r in e)t.call(this,r,e[r]);else t.call(this,e,i);return this}}function r(t,e){if(this.__eventListeners){var i=this.__eventListeners[t];if(i){for(var r=0,n=i.length;n>r;r++)i[r]&&i[r].call(this,e||{});return this.__eventListeners[t]=i.filter(function(t){return t!==!1}),this}}}fabric.Observable={observe:e,stopObserving:i,fire:r,on:e,off:i,trigger:r}}(),fabric.Collection={add:function(){this._objects.push.apply(this._objects,arguments);for(var t=0,e=arguments.length;e>t;t++)this._onObjectAdded(arguments[t]);return this.renderOnAddRemove&&this.renderAll(),this},insertAt:function(t,e,i){var r=this.getObjects();return i?r[e]=t:r.splice(e,0,t),this._onObjectAdded(t),this.renderOnAddRemove&&this.renderAll(),this},remove:function(){for(var t,e=this.getObjects(),i=0,r=arguments.length;r>i;i++)t=e.indexOf(arguments[i]),-1!==t&&(e.splice(t,1),this._onObjectRemoved(arguments[i]));return this.renderOnAddRemove&&this.renderAll(),this},forEachObject:function(t,e){for(var i=this.getObjects(),r=i.length;r--;)t.call(e,i[r],r,i);return this},getObjects:function(t){return"undefined"==typeof t?this._objects:this._objects.filter(function(e){return e.type===t})},item:function(t){return this.getObjects()[t]},isEmpty:function(){return 0===this.getObjects().length},size:function(){return this.getObjects().length},contains:function(t){return this.getObjects().indexOf(t)>-1},complexity:function(){return this.getObjects().reduce(function(t,e){return t+=e.complexity?e.complexity():0},0)}},function(t){var e=Math.sqrt,i=Math.atan2,r=Math.pow,n=Math.abs,s=Math.PI/180;fabric.util={removeFromArray:function(t,e){var i=t.indexOf(e);return-1!==i&&t.splice(i,1),t},getRandomInt:function(t,e){return Math.floor(Math.random()*(e-t+1))+t},degreesToRadians:function(t){return t*s},radiansToDegrees:function(t){return t/s},rotatePoint:function(t,e,i){t.subtractEquals(e);var r=fabric.util.rotateVector(t,i);return new fabric.Point(r.x,r.y).addEquals(e)},rotateVector:function(t,e){var i=Math.sin(e),r=Math.cos(e),n=t.x*r-t.y*i,s=t.x*i+t.y*r;return{x:n,y:s}},transformPoint:function(t,e,i){return i?new fabric.Point(e[0]*t.x+e[2]*t.y,e[1]*t.x+e[3]*t.y):new fabric.Point(e[0]*t.x+e[2]*t.y+e[4],e[1]*t.x+e[3]*t.y+e[5])},makeBoundingBoxFromPoints:function(t){var e=[t[0].x,t[1].x,t[2].x,t[3].x],i=fabric.util.array.min(e),r=fabric.util.array.max(e),n=Math.abs(i-r),s=[t[0].y,t[1].y,t[2].y,t[3].y],o=fabric.util.array.min(s),a=fabric.util.array.max(s),h=Math.abs(o-a);return{left:i,top:o,width:n,height:h}},invertTransform:function(t){var e=1/(t[0]*t[3]-t[1]*t[2]),i=[e*t[3],-e*t[1],-e*t[2],e*t[0]],r=fabric.util.transformPoint({x:t[4],y:t[5]},i,!0);return i[4]=-r.x,i[5]=-r.y,i},toFixed:function(t,e){return parseFloat(Number(t).toFixed(e))},parseUnit:function(t,e){var i=/\D{0,2}$/.exec(t),r=parseFloat(t);switch(e||(e=fabric.Text.DEFAULT_SVG_FONT_SIZE),i[0]){case"mm":return r*fabric.DPI/25.4;case"cm":return r*fabric.DPI/2.54;case"in":return r*fabric.DPI;case"pt":return r*fabric.DPI/72;case"pc":return r*fabric.DPI/72*12;case"em":return r*e;default:return r}},falseFunction:function(){return!1},getKlass:function(t,e){return t=fabric.util.string.camelize(t.charAt(0).toUpperCase()+t.slice(1)),fabric.util.resolveNamespace(e)[t]},resolveNamespace:function(e){if(!e)return fabric;for(var i=e.split("."),r=i.length,n=t||fabric.window,s=0;r>s;++s)n=n[i[s]];return n},loadImage:function(t,e,i,r){if(!t)return void(e&&e.call(i,t));var n=fabric.util.createImage();n.onload=function(){e&&e.call(i,n),n=n.onload=n.onerror=null},n.onerror=function(){fabric.log("Error loading "+n.src),e&&e.call(i,null,!0),n=n.onload=n.onerror=null},0!==t.indexOf("data")&&r&&(n.crossOrigin=r),n.src=t},enlivenObjects:function(t,e,i,r){function n(){++o===a&&e&&e(s)}t=t||[];var s=[],o=0,a=t.length;return a?void t.forEach(function(t,e){if(!t||!t.type)return void n();var o=fabric.util.getKlass(t.type,i);o.async?o.fromObject(t,function(i,o){o||(s[e]=i,r&&r(t,s[e])),n()}):(s[e]=o.fromObject(t),r&&r(t,s[e]),n())}):void(e&&e(s))},groupSVGElements:function(t,e,i){var r;return r=new fabric.PathGroup(t,e),"undefined"!=typeof i&&r.setSourcePath(i),r},populateWithProperties:function(t,e,i){if(i&&"[object Array]"===Object.prototype.toString.call(i))for(var r=0,n=i.length;n>r;r++)i[r]in t&&(e[i[r]]=t[i[r]])},drawDashedLine:function(t,r,n,s,o,a){var h=s-r,c=o-n,l=e(h*h+c*c),u=i(c,h),f=a.length,d=0,g=!0;for(t.save(),t.translate(r,n),t.moveTo(0,0),t.rotate(u),r=0;l>r;)r+=a[d++%f],r>l&&(r=l),t[g?"lineTo":"moveTo"](r,0),g=!g;t.restore()},createCanvasElement:function(t){return t||(t=fabric.document.createElement("canvas")),t.getContext||"undefined"==typeof G_vmlCanvasManager||G_vmlCanvasManager.initElement(t),t},createImage:function(){return fabric.isLikelyNode?new(require("canvas").Image):fabric.document.createElement("img")},createAccessors:function(t){for(var e=t.prototype,i=e.stateProperties.length;i--;){var r=e.stateProperties[i],n=r.charAt(0).toUpperCase()+r.slice(1),s="set"+n,o="get"+n;e[o]||(e[o]=function(t){return new Function('return this.get("'+t+'")')}(r)),e[s]||(e[s]=function(t){return new Function("value",'return this.set("'+t+'", value)')}(r))}},clipContext:function(t,e){e.save(),e.beginPath(),t.clipTo(e),e.clip()},multiplyTransformMatrices:function(t,e,i){return[t[0]*e[0]+t[2]*e[1],t[1]*e[0]+t[3]*e[1],t[0]*e[2]+t[2]*e[3],t[1]*e[2]+t[3]*e[3],i?0:t[0]*e[4]+t[2]*e[5]+t[4],i?0:t[1]*e[4]+t[3]*e[5]+t[5]]},qrDecompose:function(t){var n=i(t[1],t[0]),o=r(t[0],2)+r(t[1],2),a=e(o),h=(t[0]*t[3]-t[2]*t[1])/a,c=i(t[0]*t[2]+t[1]*t[3],o);return{angle:n/s,scaleX:a,scaleY:h,skewX:c/s,skewY:0,translateX:t[4],translateY:t[5]}},customTransformMatrix:function(t,e,i){var r=[1,0,n(Math.tan(i*s)),1],o=[n(t),0,0,n(e)];return fabric.util.multiplyTransformMatrices(o,r,!0)},resetObjectTransform:function(t){t.scaleX=1,t.scaleY=1,t.skewX=0,t.skewY=0,t.flipX=!1,t.flipY=!1,t.setAngle(0)},getFunctionBody:function(t){return(String(t).match(/function[^{]*\{([\s\S]*)\}/)||{})[1]},isTransparent:function(t,e,i,r){r>0&&(e>r?e-=r:e=0,i>r?i-=r:i=0);for(var n=!0,s=t.getImageData(e,i,2*r||1,2*r||1),o=3,a=s.data.length;a>o;o+=4){var h=s.data[o];if(n=0>=h,n===!1)break}return s=null,n},parsePreserveAspectRatioAttribute:function(t){var e,i="meet",r="Mid",n="Mid",s=t.split(" ");return s&&s.length&&(i=s.pop(),"meet"!==i&&"slice"!==i?(e=i,i="meet"):s.length&&(e=s.pop())),r="none"!==e?e.slice(1,4):"none",n="none"!==e?e.slice(5,8):"none",{meetOrSlice:i,alignX:r,alignY:n}}}}("undefined"!=typeof exports?exports:this),function(){function t(t,r,s,o,h,c,l){var u=a.call(arguments);if(n[u])return n[u];var f=Math.PI,d=l*f/180,g=Math.sin(d),p=Math.cos(d),v=0,m=0;s=Math.abs(s),o=Math.abs(o);var b=-p*t*.5-g*r*.5,y=-p*r*.5+g*t*.5,_=s*s,x=o*o,S=y*y,C=b*b,w=_*x-_*S-x*C,O=0;if(0>w){var T=Math.sqrt(1-w/(_*x));s*=T,o*=T}else O=(h===c?-1:1)*Math.sqrt(w/(_*S+x*C));var k=O*s*y/o,j=-O*o*b/s,A=p*k-g*j+.5*t,P=g*k+p*j+.5*r,M=i(1,0,(b-k)/s,(y-j)/o),L=i((b-k)/s,(y-j)/o,(-b-k)/s,(-y-j)/o);0===c&&L>0?L-=2*f:1===c&&0>L&&(L+=2*f);for(var D=Math.ceil(Math.abs(L/f*2)),E=[],I=L/D,R=8/3*Math.sin(I/4)*Math.sin(I/4)/Math.sin(I/2),F=M+I,B=0;D>B;B++)E[B]=e(M,F,p,g,s,o,A,P,R,v,m),v=E[B][4],m=E[B][5],M=F,F+=I;return n[u]=E,E}function e(t,e,i,r,n,o,h,c,l,u,f){var d=a.call(arguments);if(s[d])return s[d];var g=Math.cos(t),p=Math.sin(t),v=Math.cos(e),m=Math.sin(e),b=i*n*v-r*o*m+h,y=r*n*v+i*o*m+c,_=u+l*(-i*n*p-r*o*g),x=f+l*(-r*n*p+i*o*g),S=b+l*(i*n*m+r*o*v),C=y+l*(r*n*m-i*o*v);return s[d]=[_,x,S,C,b,y],s[d]}function i(t,e,i,r){var n=Math.atan2(e,t),s=Math.atan2(r,i);return s>=n?s-n:2*Math.PI-(n-s)}function r(t,e,i,r,n,s,h,c){var l=a.call(arguments);if(o[l])return o[l];var u,f,d,g,p,v,m,b,y=Math.sqrt,_=Math.min,x=Math.max,S=Math.abs,C=[],w=[[],[]];f=6*t-12*i+6*n,u=-3*t+9*i-9*n+3*h,d=3*i-3*t;for(var O=0;2>O;++O)if(O>0&&(f=6*e-12*r+6*s,u=-3*e+9*r-9*s+3*c,d=3*r-3*e),S(u)<1e-12){if(S(f)<1e-12)continue;g=-d/f,g>0&&1>g&&C.push(g)}else m=f*f-4*d*u,0>m||(b=y(m),p=(-f+b)/(2*u),p>0&&1>p&&C.push(p),v=(-f-b)/(2*u),v>0&&1>v&&C.push(v));for(var T,k,j,A=C.length,P=A;A--;)g=C[A],j=1-g,T=j*j*j*t+3*j*j*g*i+3*j*g*g*n+g*g*g*h,w[0][A]=T,k=j*j*j*e+3*j*j*g*r+3*j*g*g*s+g*g*g*c,w[1][A]=k;w[0][P]=t,w[1][P]=e,w[0][P+1]=h,w[1][P+1]=c;var M=[{x:_.apply(null,w[0]),y:_.apply(null,w[1])},{x:x.apply(null,w[0]),y:x.apply(null,w[1])}];return o[l]=M,M}var n={},s={},o={},a=Array.prototype.join;fabric.util.drawArc=function(e,i,r,n){for(var s=n[0],o=n[1],a=n[2],h=n[3],c=n[4],l=n[5],u=n[6],f=[[],[],[],[]],d=t(l-i,u-r,s,o,h,c,a),g=0,p=d.length;p>g;g++)f[g][0]=d[g][0]+i,f[g][1]=d[g][1]+r,f[g][2]=d[g][2]+i,f[g][3]=d[g][3]+r,f[g][4]=d[g][4]+i,f[g][5]=d[g][5]+r,e.bezierCurveTo.apply(e,f[g])},fabric.util.getBoundsOfArc=function(e,i,n,s,o,a,h,c,l){for(var u=0,f=0,d=[],g=[],p=t(c-e,l-i,n,s,a,h,o),v=[[],[]],m=0,b=p.length;b>m;m++)d=r(u,f,p[m][0],p[m][1],p[m][2],p[m][3],p[m][4],p[m][5]),v[0].x=d[0].x+e,v[0].y=d[0].y+i,v[1].x=d[1].x+e,v[1].y=d[1].y+i,g.push(v[0]),g.push(v[1]),u=p[m][4],f=p[m][5];return g},fabric.util.getBoundsOfCurve=r}(),function(){function t(t,e){for(var i=s.call(arguments,2),r=[],n=0,o=t.length;o>n;n++)r[n]=i.length?t[n][e].apply(t[n],i):t[n][e].call(t[n]);return r}function e(t,e){return n(t,e,function(t,e){return t>=e})}function i(t,e){return n(t,e,function(t,e){return e>t})}function r(t,e){for(var i=t.length;i--;)t[i]=e;return t}function n(t,e,i){if(t&&0!==t.length){var r=t.length-1,n=e?t[r][e]:t[r];if(e)for(;r--;)i(t[r][e],n)&&(n=t[r][e]);else for(;r--;)i(t[r],n)&&(n=t[r]);return n}}var s=Array.prototype.slice;Array.prototype.indexOf||(Array.prototype.indexOf=function(t){if(void 0===this||null===this)throw new TypeError;var e=Object(this),i=e.length>>>0;if(0===i)return-1;var r=0;if(arguments.length>0&&(r=Number(arguments[1]),r!==r?r=0:0!==r&&r!==Number.POSITIVE_INFINITY&&r!==Number.NEGATIVE_INFINITY&&(r=(r>0||-1)*Math.floor(Math.abs(r)))),r>=i)return-1;for(var n=r>=0?r:Math.max(i-Math.abs(r),0);i>n;n++)if(n in e&&e[n]===t)return n;return-1}),Array.prototype.forEach||(Array.prototype.forEach=function(t,e){for(var i=0,r=this.length>>>0;r>i;i++)i in this&&t.call(e,this[i],i,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){for(var i=[],r=0,n=this.length>>>0;n>r;r++)r in this&&(i[r]=t.call(e,this[r],r,this));return i}),Array.prototype.every||(Array.prototype.every=function(t,e){for(var i=0,r=this.length>>>0;r>i;i++)if(i in this&&!t.call(e,this[i],i,this))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(t,e){for(var i=0,r=this.length>>>0;r>i;i++)if(i in this&&t.call(e,this[i],i,this))return!0;return!1}),Array.prototype.filter||(Array.prototype.filter=function(t,e){for(var i,r=[],n=0,s=this.length>>>0;s>n;n++)n in this&&(i=this[n],t.call(e,i,n,this)&&r.push(i));return r}),Array.prototype.reduce||(Array.prototype.reduce=function(t){var e,i=this.length>>>0,r=0;if(arguments.length>1)e=arguments[1];else for(;;){if(r in this){e=this[r++];break}if(++r>=i)throw new TypeError}for(;i>r;r++)r in this&&(e=t.call(null,e,this[r],r,this));return e}),fabric.util.array={fill:r,invoke:t,min:i,max:e}}(),function(){function t(t,e){for(var i in e)t[i]=e[i];return t}function e(e){return t({},e)}fabric.util.object={extend:t,clone:e}}(),function(){function t(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})}function e(t,e){return t.charAt(0).toUpperCase()+(e?t.slice(1):t.slice(1).toLowerCase())}function i(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")}String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^[\s\xA0]+/,"").replace(/[\s\xA0]+$/,"")}),fabric.util.string={camelize:t,capitalize:e,escapeXml:i}}(),function(){var t=Array.prototype.slice,e=Function.prototype.apply,i=function(){};Function.prototype.bind||(Function.prototype.bind=function(r){var n,s=this,o=t.call(arguments,1);return n=o.length?function(){return e.call(s,this instanceof i?this:r,o.concat(t.call(arguments)))}:function(){return e.call(s,this instanceof i?this:r,arguments)},i.prototype=this.prototype,n.prototype=new i,n})}(),function(){function t(){}function e(t){var e=this.constructor.superclass.prototype[t];return arguments.length>1?e.apply(this,r.call(arguments,1)):e.call(this)}function i(){function i(){this.initialize.apply(this,arguments)}var s=null,a=r.call(arguments,0);"function"==typeof a[0]&&(s=a.shift()),i.superclass=s,i.subclasses=[],s&&(t.prototype=s.prototype,i.prototype=new t,s.subclasses.push(i));for(var h=0,c=a.length;c>h;h++)o(i,a[h],s);return i.prototype.initialize||(i.prototype.initialize=n),i.prototype.constructor=i,i.prototype.callSuper=e,i}var r=Array.prototype.slice,n=function(){},s=function(){for(var t in{toString:1})if("toString"===t)return!1;return!0}(),o=function(t,e,i){for(var r in e)t.prototype[r]=r in t.prototype&&"function"==typeof t.prototype[r]&&(e[r]+"").indexOf("callSuper")>-1?function(t){return function(){var r=this.constructor.superclass;this.constructor.superclass=i;var n=e[t].apply(this,arguments);return this.constructor.superclass=r,"initialize"!==t?n:void 0}}(r):e[r],s&&(e.toString!==Object.prototype.toString&&(t.prototype.toString=e.toString),e.valueOf!==Object.prototype.valueOf&&(t.prototype.valueOf=e.valueOf))};fabric.util.createClass=i}(),function(){function t(t){var e,i,r=Array.prototype.slice.call(arguments,1),n=r.length;for(i=0;n>i;i++)if(e=typeof t[r[i]],!/^(?:function|object|unknown)$/.test(e))return!1;return!0}function e(t,e){return{handler:e,wrappedHandler:i(t,e)}}function i(t,e){return function(i){e.call(o(t),i||fabric.window.event)}}function r(t,e){return function(i){if(p[t]&&p[t][e])for(var r=p[t][e],n=0,s=r.length;s>n;n++)r[n].call(this,i||fabric.window.event)}}function n(t){t||(t=fabric.window.event);var e=t.target||(typeof t.srcElement!==h?t.srcElement:null),i=fabric.util.getScrollLeftTop(e);return{x:v(t)+i.left,y:m(t)+i.top}}function s(t,e,i){var r="touchend"===t.type?"changedTouches":"touches";return t[r]&&t[r][0]?t[r][0][e]-(t[r][0][e]-t[r][0][i])||t[i]:t[i]}var o,a,h="unknown",c=function(){var t=0;return function(e){return e.__uniqueID||(e.__uniqueID="uniqueID__"+t++)}}();!function(){var t={};o=function(e){return t[e]},a=function(e,i){t[e]=i}}();var l,u,f=t(fabric.document.documentElement,"addEventListener","removeEventListener")&&t(fabric.window,"addEventListener","removeEventListener"),d=t(fabric.document.documentElement,"attachEvent","detachEvent")&&t(fabric.window,"attachEvent","detachEvent"),g={},p={};f?(l=function(t,e,i){t.addEventListener(e,i,!1)},u=function(t,e,i){t.removeEventListener(e,i,!1)}):d?(l=function(t,i,r){var n=c(t);a(n,t),g[n]||(g[n]={}),g[n][i]||(g[n][i]=[]);var s=e(n,r);g[n][i].push(s),t.attachEvent("on"+i,s.wrappedHandler)},u=function(t,e,i){var r,n=c(t);if(g[n]&&g[n][e])for(var s=0,o=g[n][e].length;o>s;s++)r=g[n][e][s],r&&r.handler===i&&(t.detachEvent("on"+e,r.wrappedHandler),g[n][e][s]=null)}):(l=function(t,e,i){var n=c(t);if(p[n]||(p[n]={}),!p[n][e]){p[n][e]=[];var s=t["on"+e];s&&p[n][e].push(s),t["on"+e]=r(n,e)}p[n][e].push(i)},u=function(t,e,i){var r=c(t);if(p[r]&&p[r][e])for(var n=p[r][e],s=0,o=n.length;o>s;s++)n[s]===i&&n.splice(s,1)}),fabric.util.addListener=l,fabric.util.removeListener=u;var v=function(t){return typeof t.clientX!==h?t.clientX:0},m=function(t){return typeof t.clientY!==h?t.clientY:0};fabric.isTouchSupported&&(v=function(t){return s(t,"pageX","clientX")},m=function(t){return s(t,"pageY","clientY")}),fabric.util.getPointer=n,fabric.util.object.extend(fabric.util,fabric.Observable)}(),function(){function t(t,e){var i=t.style;if(!i)return t;if("string"==typeof e)return t.style.cssText+=";"+e,e.indexOf("opacity")>-1?s(t,e.match(/opacity:\s*(\d?\.?\d*)/)[1]):t;for(var r in e)if("opacity"===r)s(t,e[r]);else{var n="float"===r||"cssFloat"===r?"undefined"==typeof i.styleFloat?"cssFloat":"styleFloat":r;i[n]=e[r]}return t}var e=fabric.document.createElement("div"),i="string"==typeof e.style.opacity,r="string"==typeof e.style.filter,n=/alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,s=function(t){return t};i?s=function(t,e){return t.style.opacity=e,t}:r&&(s=function(t,e){var i=t.style;return t.currentStyle&&!t.currentStyle.hasLayout&&(i.zoom=1),n.test(i.filter)?(e=e>=.9999?"":"alpha(opacity="+100*e+")",i.filter=i.filter.replace(n,e)):i.filter+=" alpha(opacity="+100*e+")",t}),fabric.util.setStyle=t}(),function(){function t(t){return"string"==typeof t?fabric.document.getElementById(t):t}function e(t,e){var i=fabric.document.createElement(t);for(var r in e)"class"===r?i.className=e[r]:"for"===r?i.htmlFor=e[r]:i.setAttribute(r,e[r]);return i}function i(t,e){t&&-1===(" "+t.className+" ").indexOf(" "+e+" ")&&(t.className+=(t.className?" ":"")+e)}function r(t,i,r){return"string"==typeof i&&(i=e(i,r)),t.parentNode&&t.parentNode.replaceChild(i,t),i.appendChild(t),i}function n(t){for(var e=0,i=0,r=fabric.document.documentElement,n=fabric.document.body||{scrollLeft:0,scrollTop:0};t&&(t.parentNode||t.host)&&(t=t.parentNode||t.host,t===fabric.document?(e=n.scrollLeft||r.scrollLeft||0,i=n.scrollTop||r.scrollTop||0):(e+=t.scrollLeft||0,i+=t.scrollTop||0),1!==t.nodeType||"fixed"!==fabric.util.getElementStyle(t,"position")););return{left:e,top:i}}function s(t){var e,i,r=t&&t.ownerDocument,s={left:0,top:0},o={left:0,top:0},a={borderLeftWidth:"left",borderTopWidth:"top",paddingLeft:"left",paddingTop:"top"};if(!r)return o;for(var h in a)o[a[h]]+=parseInt(l(t,h),10)||0;return e=r.documentElement,"undefined"!=typeof t.getBoundingClientRect&&(s=t.getBoundingClientRect()),i=n(t),{left:s.left+i.left-(e.clientLeft||0)+o.left,top:s.top+i.top-(e.clientTop||0)+o.top}}var o,a=Array.prototype.slice,h=function(t){return a.call(t,0)};try{o=h(fabric.document.childNodes)instanceof Array}catch(c){}o||(h=function(t){for(var e=new Array(t.length),i=t.length;i--;)e[i]=t[i];return e});var l;l=fabric.document.defaultView&&fabric.document.defaultView.getComputedStyle?function(t,e){var i=fabric.document.defaultView.getComputedStyle(t,null);return i?i[e]:void 0}:function(t,e){var i=t.style[e];return!i&&t.currentStyle&&(i=t.currentStyle[e]),i},function(){function t(t){return"undefined"!=typeof t.onselectstart&&(t.onselectstart=fabric.util.falseFunction),r?t.style[r]="none":"string"==typeof t.unselectable&&(t.unselectable="on"),t}function e(t){return"undefined"!=typeof t.onselectstart&&(t.onselectstart=null),r?t.style[r]="":"string"==typeof t.unselectable&&(t.unselectable=""),t}var i=fabric.document.documentElement.style,r="userSelect"in i?"userSelect":"MozUserSelect"in i?"MozUserSelect":"WebkitUserSelect"in i?"WebkitUserSelect":"KhtmlUserSelect"in i?"KhtmlUserSelect":"";fabric.util.makeElementUnselectable=t,fabric.util.makeElementSelectable=e}(),function(){function t(t,e){var i=fabric.document.getElementsByTagName("head")[0],r=fabric.document.createElement("script"),n=!0;r.onload=r.onreadystatechange=function(t){if(n){if("string"==typeof this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)return;n=!1,e(t||fabric.window.event),r=r.onload=r.onreadystatechange=null}},r.src=t,i.appendChild(r)}fabric.util.getScript=t}(),fabric.util.getById=t,fabric.util.toArray=h,fabric.util.makeElement=e,fabric.util.addClass=i,fabric.util.wrapElement=r,fabric.util.getScrollLeftTop=n,fabric.util.getElementOffset=s,fabric.util.getElementStyle=l}(),function(){function t(t,e){return t+(/\?/.test(t)?"&":"?")+e}function e(){}function i(i,n){n||(n={});var s,o=n.method?n.method.toUpperCase():"GET",a=n.onComplete||function(){},h=r();return h.onreadystatechange=function(){4===h.readyState&&(a(h),h.onreadystatechange=e)},"GET"===o&&(s=null,"string"==typeof n.parameters&&(i=t(i,n.parameters))),h.open(o,i,!0),("POST"===o||"PUT"===o)&&h.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),h.send(s),h}var r=function(){for(var t=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP.3.0")},function(){return new XMLHttpRequest}],e=t.length;e--;)try{var i=t[e]();if(i)return t[e]}catch(r){}}();fabric.util.request=i}(),fabric.log=function(){},fabric.warn=function(){},"undefined"!=typeof console&&["log","warn"].forEach(function(t){"undefined"!=typeof console[t]&&"function"==typeof console[t].apply&&(fabric[t]=function(){return console[t].apply(console,arguments)})}),function(){function t(t){e(function(i){t||(t={});var r,n=i||+new Date,s=t.duration||500,o=n+s,a=t.onChange||function(){},h=t.abort||function(){return!1},c=t.easing||function(t,e,i,r){return-i*Math.cos(t/r*(Math.PI/2))+i+e},l="startValue"in t?t.startValue:0,u="endValue"in t?t.endValue:100,f=t.byValue||u-l;t.onStart&&t.onStart(),function d(i){r=i||+new Date;var u=r>o?s:r-n;return h()?void(t.onComplete&&t.onComplete()):(a(c(u,l,f,s)),r>o?void(t.onComplete&&t.onComplete()):void e(d))}(n)})}function e(){return i.apply(fabric.window,arguments)}var i=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(t){fabric.window.setTimeout(t,1e3/60)};fabric.util.animate=t,fabric.util.requestAnimFrame=e}(),function(){function t(t,e,i,r){return tt?i/2*t*t*t+e:i/2*((t-=2)*t*t+2)+e}function n(t,e,i,r){return i*(t/=r)*t*t*t+e}function s(t,e,i,r){return-i*((t=t/r-1)*t*t*t-1)+e}function o(t,e,i,r){return t/=r/2,1>t?i/2*t*t*t*t+e:-i/2*((t-=2)*t*t*t-2)+e}function a(t,e,i,r){return i*(t/=r)*t*t*t*t+e}function h(t,e,i,r){return i*((t=t/r-1)*t*t*t*t+1)+e}function c(t,e,i,r){return t/=r/2,1>t?i/2*t*t*t*t*t+e:i/2*((t-=2)*t*t*t*t+2)+e}function l(t,e,i,r){return-i*Math.cos(t/r*(Math.PI/2))+i+e}function u(t,e,i,r){return i*Math.sin(t/r*(Math.PI/2))+e}function f(t,e,i,r){return-i/2*(Math.cos(Math.PI*t/r)-1)+e}function d(t,e,i,r){return 0===t?e:i*Math.pow(2,10*(t/r-1))+e}function g(t,e,i,r){return t===r?e+i:i*(-Math.pow(2,-10*t/r)+1)+e}function p(t,e,i,r){return 0===t?e:t===r?e+i:(t/=r/2,1>t?i/2*Math.pow(2,10*(t-1))+e:i/2*(-Math.pow(2,-10*--t)+2)+e)}function v(t,e,i,r){return-i*(Math.sqrt(1-(t/=r)*t)-1)+e}function m(t,e,i,r){return i*Math.sqrt(1-(t=t/r-1)*t)+e}function b(t,e,i,r){return t/=r/2,1>t?-i/2*(Math.sqrt(1-t*t)-1)+e:i/2*(Math.sqrt(1-(t-=2)*t)+1)+e}function y(i,r,n,s){var o=1.70158,a=0,h=n;if(0===i)return r;if(i/=s,1===i)return r+n;a||(a=.3*s);var c=t(h,n,a,o);return-e(c,i,s)+r}function _(e,i,r,n){var s=1.70158,o=0,a=r;if(0===e)return i;if(e/=n,1===e)return i+r;o||(o=.3*n);var h=t(a,r,o,s);return h.a*Math.pow(2,-10*e)*Math.sin(2*(e*n-h.s)*Math.PI/h.p)+h.c+i}function x(i,r,n,s){var o=1.70158,a=0,h=n;if(0===i)return r;if(i/=s/2,2===i)return r+n;a||(a=.3*s*1.5);var c=t(h,n,a,o);return 1>i?-.5*e(c,i,s)+r:c.a*Math.pow(2,-10*(i-=1))*Math.sin(2*(i*s-c.s)*Math.PI/c.p)*.5+c.c+r}function S(t,e,i,r,n){return void 0===n&&(n=1.70158),i*(t/=r)*t*((n+1)*t-n)+e}function C(t,e,i,r,n){return void 0===n&&(n=1.70158),i*((t=t/r-1)*t*((n+1)*t+n)+1)+e}function w(t,e,i,r,n){return void 0===n&&(n=1.70158),t/=r/2,1>t?i/2*t*t*(((n*=1.525)+1)*t-n)+e:i/2*((t-=2)*t*(((n*=1.525)+1)*t+n)+2)+e}function O(t,e,i,r){return i-T(r-t,0,i,r)+e}function T(t,e,i,r){return(t/=r)<1/2.75?7.5625*i*t*t+e:2/2.75>t?i*(7.5625*(t-=1.5/2.75)*t+.75)+e:2.5/2.75>t?i*(7.5625*(t-=2.25/2.75)*t+.9375)+e:i*(7.5625*(t-=2.625/2.75)*t+.984375)+e}function k(t,e,i,r){return r/2>t?.5*O(2*t,0,i,r)+e:.5*T(2*t-r,0,i,r)+.5*i+e}fabric.util.ease={easeInQuad:function(t,e,i,r){return i*(t/=r)*t+e},easeOutQuad:function(t,e,i,r){return-i*(t/=r)*(t-2)+e},easeInOutQuad:function(t,e,i,r){return t/=r/2,1>t?i/2*t*t+e:-i/2*(--t*(t-2)-1)+e},easeInCubic:function(t,e,i,r){return i*(t/=r)*t*t+e},easeOutCubic:i,easeInOutCubic:r,easeInQuart:n,easeOutQuart:s,easeInOutQuart:o,easeInQuint:a,easeOutQuint:h,easeInOutQuint:c,easeInSine:l,easeOutSine:u,easeInOutSine:f,easeInExpo:d,easeOutExpo:g,easeInOutExpo:p,easeInCirc:v,easeOutCirc:m,easeInOutCirc:b,easeInElastic:y,easeOutElastic:_,easeInOutElastic:x,easeInBack:S,easeOutBack:C,easeInOutBack:w,easeInBounce:O,easeOutBounce:T,easeInOutBounce:k}}(),function(t){"use strict";function e(t){return t in T?T[t]:t}function i(t,e,i,r){var n,s="[object Array]"===Object.prototype.toString.call(e);return"fill"!==t&&"stroke"!==t||"none"!==e?"strokeDashArray"===t?e=e.replace(/,/g," ").split(/\s+/).map(function(t){return parseFloat(t)}):"transformMatrix"===t?e=i&&i.transformMatrix?x(i.transformMatrix,p.parseTransformAttribute(e)):p.parseTransformAttribute(e):"visible"===t?(e="none"===e||"hidden"===e?!1:!0,i&&i.visible===!1&&(e=!1)):"originX"===t?e="start"===e?"left":"end"===e?"right":"center":n=s?e.map(_):_(e,r):e="",!s&&isNaN(n)?e:n}function r(t){for(var e in k)if("undefined"!=typeof t[k[e]]&&""!==t[e]){if("undefined"==typeof t[e]){if(!p.Object.prototype[e])continue;t[e]=p.Object.prototype[e]}if(0!==t[e].indexOf("url(")){var i=new p.Color(t[e]);t[e]=i.setAlpha(y(i.getAlpha()*t[k[e]],2)).toRgba()}}return t}function n(t,r){var n,s;t.replace(/;\s*$/,"").split(";").forEach(function(t){var o=t.split(":");n=e(o[0].trim().toLowerCase()),s=i(n,o[1].trim()),r[n]=s})}function s(t,r){var n,s;for(var o in t)"undefined"!=typeof t[o]&&(n=e(o.toLowerCase()),s=i(n,t[o]),r[n]=s)}function o(t,e){var i={};for(var r in p.cssRules[e])if(a(t,r.split(" ")))for(var n in p.cssRules[e][r])i[n]=p.cssRules[e][r][n];return i}function a(t,e){var i,r=!0;return i=c(t,e.pop()),i&&e.length&&(r=h(t,e)),i&&r&&0===e.length}function h(t,e){for(var i,r=!0;t.parentNode&&1===t.parentNode.nodeType&&e.length;)r&&(i=e.pop()),t=t.parentNode,r=c(t,i);return 0===e.length}function c(t,e){var i,r=t.nodeName,n=t.getAttribute("class"),s=t.getAttribute("id");if(i=new RegExp("^"+r,"i"),e=e.replace(i,""),s&&e.length&&(i=new RegExp("#"+s+"(?![a-zA-Z\\-]+)","i"),e=e.replace(i,"")),n&&e.length){n=n.split(" ");for(var o=n.length;o--;)i=new RegExp("\\."+n[o]+"(?![a-zA-Z\\-]+)","i"),e=e.replace(i,"")}return 0===e.length}function l(t,e){var i;if(t.getElementById&&(i=t.getElementById(e)),i)return i;var r,n,s=t.getElementsByTagName("*");for(n=0;ns;s++)n=o.item(s),m.setAttribute(n.nodeName,n.nodeValue);for(;null!=g.firstChild;)m.appendChild(g.firstChild);g=m}for(s=0,o=h.attributes,a=o.length;a>s;s++)n=o.item(s),"x"!==n.nodeName&&"y"!==n.nodeName&&"xlink:href"!==n.nodeName&&("transform"===n.nodeName?p=n.nodeValue+" "+p:g.setAttribute(n.nodeName,n.nodeValue));g.setAttribute("transform",p),g.setAttribute("instantiated_by_use","1"),g.removeAttribute("id"),r=h.parentNode,r.replaceChild(g,h),e.length===v&&i++}}function f(t){var e,i,r,n,s=t.getAttribute("viewBox"),o=1,a=1,h=0,c=0,l=t.getAttribute("width"),u=t.getAttribute("height"),f=t.getAttribute("x")||0,d=t.getAttribute("y")||0,g=t.getAttribute("preserveAspectRatio")||"",v=!s||!C.test(t.tagName)||!(s=s.match(j)),m=!l||!u||"100%"===l||"100%"===u,b=v&&m,y={},x="";if(y.width=0,y.height=0,y.toBeParsed=b,b)return y;if(v)return y.width=_(l),y.height=_(u),y;if(h=-parseFloat(s[1]),c=-parseFloat(s[2]),e=parseFloat(s[3]),i=parseFloat(s[4]),m?(y.width=e,y.height=i):(y.width=_(l),y.height=_(u),o=y.width/e,a=y.height/i),g=p.util.parsePreserveAspectRatioAttribute(g),"none"!==g.alignX&&(a=o=o>a?a:o),1===o&&1===a&&0===h&&0===c&&0===f&&0===d)return y;if((f||d)&&(x=" translate("+_(f)+" "+_(d)+") "),r=x+" matrix("+o+" 0 0 "+a+" "+h*o+" "+c*a+") ","svg"===t.tagName){for(n=t.ownerDocument.createElement("g");null!=t.firstChild;)n.appendChild(t.firstChild);t.appendChild(n)}else n=t,r=n.getAttribute("transform")+r;return n.setAttribute("transform",r),y}function d(t){var e=t.objects,i=t.options;return e=e.map(function(t){return p[m(t.type)].fromObject(t)}),{objects:e,options:i}}function g(t,e,i){e[i]&&e[i].toSVG&&t.push(' \n',' \n \n')}var p=t.fabric||(t.fabric={}),v=p.util.object.extend,m=p.util.string.capitalize,b=p.util.object.clone,y=p.util.toFixed,_=p.util.parseUnit,x=p.util.multiplyTransformMatrices,S=/^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/i,C=/^(symbol|image|marker|pattern|view|svg)$/i,w=/^(?:pattern|defs|symbol|metadata)$/i,O=/^(symbol|g|a|svg)$/i,T={cx:"left",x:"left",r:"radius",cy:"top",y:"top",display:"visible",visibility:"visible",transform:"transformMatrix","fill-opacity":"fillOpacity","fill-rule":"fillRule","font-family":"fontFamily","font-size":"fontSize","font-style":"fontStyle","font-weight":"fontWeight","stroke-dasharray":"strokeDashArray","stroke-linecap":"strokeLineCap","stroke-linejoin":"strokeLineJoin","stroke-miterlimit":"strokeMiterLimit","stroke-opacity":"strokeOpacity","stroke-width":"strokeWidth","text-decoration":"textDecoration","text-anchor":"originX"},k={stroke:"strokeOpacity",fill:"fillOpacity"};p.cssRules={},p.gradientDefs={},p.parseTransformAttribute=function(){function t(t,e){var i=e[0],r=3===e.length?e[1]:0,n=3===e.length?e[2]:0;t[0]=Math.cos(i),t[1]=Math.sin(i),t[2]=-Math.sin(i),t[3]=Math.cos(i),t[4]=r-(t[0]*r+t[2]*n),t[5]=n-(t[1]*r+t[3]*n)}function e(t,e){var i=e[0],r=2===e.length?e[1]:e[0];t[0]=i,t[3]=r}function i(t,e){t[2]=Math.tan(p.util.degreesToRadians(e[0]))}function r(t,e){t[1]=Math.tan(p.util.degreesToRadians(e[0]))}function n(t,e){t[4]=e[0],2===e.length&&(t[5]=e[1])}var s=[1,0,0,1,0,0],o=p.reNum,a="(?:\\s+,?\\s*|,\\s*)",h="(?:(skewX)\\s*\\(\\s*("+o+")\\s*\\))",c="(?:(skewY)\\s*\\(\\s*("+o+")\\s*\\))",l="(?:(rotate)\\s*\\(\\s*("+o+")(?:"+a+"("+o+")"+a+"("+o+"))?\\s*\\))",u="(?:(scale)\\s*\\(\\s*("+o+")(?:"+a+"("+o+"))?\\s*\\))",f="(?:(translate)\\s*\\(\\s*("+o+")(?:"+a+"("+o+"))?\\s*\\))",d="(?:(matrix)\\s*\\(\\s*("+o+")"+a+"("+o+")"+a+"("+o+")"+a+"("+o+")"+a+"("+o+")"+a+"("+o+")\\s*\\))",g="(?:"+d+"|"+f+"|"+u+"|"+l+"|"+h+"|"+c+")",v="(?:"+g+"(?:"+a+"*"+g+")*)",m="^\\s*(?:"+v+"?)\\s*$",b=new RegExp(m),y=new RegExp(g,"g"); + +return function(o){var a=s.concat(),h=[];if(!o||o&&!b.test(o))return a;o.replace(y,function(o){var c=new RegExp(g).exec(o).filter(function(t){return""!==t&&null!=t}),l=c[1],u=c.slice(2).map(parseFloat);switch(l){case"translate":n(a,u);break;case"rotate":u[0]=p.util.degreesToRadians(u[0]),t(a,u);break;case"scale":e(a,u);break;case"skewX":i(a,u);break;case"skewY":r(a,u);break;case"matrix":a=u}h.push(a.concat()),a=s.concat()});for(var c=h[0];h.length>1;)h.shift(),c=p.util.multiplyTransformMatrices(c,h[0]);return c}}();var j=new RegExp("^\\s*("+p.reNum+"+)\\s*,?\\s*("+p.reNum+"+)\\s*,?\\s*("+p.reNum+"+)\\s*,?\\s*("+p.reNum+"+)\\s*$");p.parseSVGDocument=function(){function t(t,e){for(;t&&(t=t.parentNode);)if(e.test(t.nodeName)&&!t.getAttribute("instantiated_by_use"))return!0;return!1}return function(e,i,r){if(e){u(e);var n=new Date,s=p.Object.__uid++,o=f(e),a=p.util.toArray(e.getElementsByTagName("*"));if(o.svgUid=s,0===a.length&&p.isLikelyNode){a=e.selectNodes('//*[name(.)!="svg"]');for(var h=[],c=0,l=a.length;l>c;c++)h[c]=a[c];a=h}var d=a.filter(function(e){return f(e),S.test(e.tagName)&&!t(e,w)});if(!d||d&&!d.length)return void(i&&i([],{}));p.gradientDefs[s]=p.getGradientDefs(e),p.cssRules[s]=p.getCSSRules(e),p.parseElements(d,function(t){p.documentParsingTime=new Date-n,i&&i(t,o)},b(o),r)}}}();var A={has:function(t,e){e(!1)},get:function(){},set:function(){}},P=new RegExp("(normal|italic)?\\s*(normal|small-caps)?\\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\\s*("+p.reNum+"(?:px|cm|mm|em|pt|pc|in)*)(?:\\/(normal|"+p.reNum+"))?\\s+(.*)");v(p,{parseFontDeclaration:function(t,e){var i=t.match(P);if(i){var r=i[1],n=i[3],s=i[4],o=i[5],a=i[6];r&&(e.fontStyle=r),n&&(e.fontWeight=isNaN(parseFloat(n))?n:parseFloat(n)),s&&(e.fontSize=_(s)),a&&(e.fontFamily=a),o&&(e.lineHeight="normal"===o?1:o)}},getGradientDefs:function(t){var e,i,r,n,s=t.getElementsByTagName("linearGradient"),o=t.getElementsByTagName("radialGradient"),a=0,h=[],c={},l={};for(h.length=s.length+o.length,i=s.length;i--;)h[a++]=s[i];for(i=o.length;i--;)h[a++]=o[i];for(;a--;)e=h[a],n=e.getAttribute("xlink:href"),r=e.getAttribute("id"),n&&(l[r]=n.substr(1)),c[r]=e;for(r in l){var u=c[l[r]].cloneNode(!0);for(e=c[r];u.firstChild;)e.appendChild(u.firstChild)}return c},parseAttributes:function(t,n,s){if(t){var a,h,c={};"undefined"==typeof s&&(s=t.getAttribute("svgUid")),t.parentNode&&O.test(t.parentNode.nodeName)&&(c=p.parseAttributes(t.parentNode,n,s)),h=c&&c.fontSize||t.getAttribute("font-size")||p.Text.DEFAULT_SVG_FONT_SIZE;var l=n.reduce(function(r,n){return a=t.getAttribute(n),a&&(n=e(n),a=i(n,a,c,h),r[n]=a),r},{});return l=v(l,v(o(t,s),p.parseStyleAttribute(t))),l.font&&p.parseFontDeclaration(l.font,l),r(v(c,l))}},parseElements:function(t,e,i,r){new p.ElementsParser(t,e,i,r).parse()},parseStyleAttribute:function(t){var e={},i=t.getAttribute("style");return i?("string"==typeof i?n(i,e):s(i,e),e):e},parsePointsAttribute:function(t){if(!t)return null;t=t.replace(/,/g," ").trim(),t=t.split(/\s+/);var e,i,r=[];for(e=0,i=t.length;i>e;e+=2)r.push({x:parseFloat(t[e]),y:parseFloat(t[e+1])});return r},getCSSRules:function(t){for(var r,n=t.getElementsByTagName("style"),s={},o=0,a=n.length;a>o;o++){var h=n[o].textContent||n[o].text;h=h.replace(/\/\*[\s\S]*?\*\//g,""),""!==h.trim()&&(r=h.match(/[^{]*\{[\s\S]*?\}/g),r=r.map(function(t){return t.trim()}),r.forEach(function(t){for(var r=t.match(/([\s\S]*?)\s*\{([^}]*)\}/),n={},o=r[2].trim(),a=o.replace(/;$/,"").split(/\s*;\s*/),h=0,c=a.length;c>h;h++){var l=a[h].split(/\s*:\s*/),u=e(l[0]),f=i(u,l[1],l[0]);n[u]=f}t=r[1],t.split(",").forEach(function(t){t=t.replace(/^svg/i,"").trim(),""!==t&&(s[t]=p.util.object.clone(n))})}))}return s},loadSVGFromURL:function(t,e,i){function r(r){var n=r.responseXML;n&&!n.documentElement&&p.window.ActiveXObject&&r.responseText&&(n=new ActiveXObject("Microsoft.XMLDOM"),n.async="false",n.loadXML(r.responseText.replace(//i,""))),n&&n.documentElement&&p.parseSVGDocument(n.documentElement,function(i,r){A.set(t,{objects:p.util.array.invoke(i,"toObject"),options:r}),e(i,r)},i)}t=t.replace(/^\n\s*/,"").trim(),A.has(t,function(i){i?A.get(t,function(t){var i=d(t);e(i.objects,i.options)}):new p.util.request(t,{method:"get",onComplete:r})})},loadSVGFromString:function(t,e,i){t=t.trim();var r;if("undefined"!=typeof DOMParser){var n=new DOMParser;n&&n.parseFromString&&(r=n.parseFromString(t,"text/xml"))}else p.window.ActiveXObject&&(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(t.replace(//i,"")));p.parseSVGDocument(r.documentElement,function(t,i){e(t,i)},i)},createSVGFontFacesMarkup:function(t){for(var e,i,r,n,s,o,a,h="",c={},l=p.fontPaths,u=0,f=t.length;f>u;u++)if(e=t[u],i=e.fontFamily,-1!==e.type.indexOf("text")&&!c[i]&&l[i]&&(c[i]=!0,e.styles)){r=e.styles;for(s in r){o=r[s];for(a in n)o=n[a],i=o.fontFamily,!c[i]&&l[i]&&(c[i]=!0)}}for(var d in c)h+=[" @font-face {\n"," font-family: '",d,"';\n"," src: url('",l[d],"');\n"," }\n"].join("");return h&&(h=[' \n"].join("")),h},createSVGRefElementsMarkup:function(t){var e=[];return g(e,t,"backgroundColor"),g(e,t,"overlayColor"),e.join("")}})}("undefined"!=typeof exports?exports:this),fabric.ElementsParser=function(t,e,i,r){this.elements=t,this.callback=e,this.options=i,this.reviver=r,this.svgUid=i&&i.svgUid||0},fabric.ElementsParser.prototype.parse=function(){this.instances=new Array(this.elements.length),this.numElements=this.elements.length,this.createObjects()},fabric.ElementsParser.prototype.createObjects=function(){for(var t=0,e=this.elements.length;e>t;t++)this.elements[t].setAttribute("svgUid",this.svgUid),function(t,e){setTimeout(function(){t.createObject(t.elements[e],e)},0)}(this,t)},fabric.ElementsParser.prototype.createObject=function(t,e){var i=fabric[fabric.util.string.capitalize(t.tagName)];if(i&&i.fromElement)try{this._createObject(i,t,e)}catch(r){fabric.log(r)}else this.checkIfDone()},fabric.ElementsParser.prototype._createObject=function(t,e,i){if(t.async)t.fromElement(e,this.createCallback(i,e),this.options);else{var r=t.fromElement(e,this.options);this.resolveGradient(r,"fill"),this.resolveGradient(r,"stroke"),this.reviver&&this.reviver(e,r),this.instances[i]=r,this.checkIfDone()}},fabric.ElementsParser.prototype.createCallback=function(t,e){var i=this;return function(r){i.resolveGradient(r,"fill"),i.resolveGradient(r,"stroke"),i.reviver&&i.reviver(e,r),i.instances[t]=r,i.checkIfDone()}},fabric.ElementsParser.prototype.resolveGradient=function(t,e){var i=t.get(e);if(/^url\(/.test(i)){var r=i.slice(5,i.length-1);fabric.gradientDefs[this.svgUid][r]&&t.set(e,fabric.Gradient.fromElement(fabric.gradientDefs[this.svgUid][r],t))}},fabric.ElementsParser.prototype.checkIfDone=function(){0===--this.numElements&&(this.instances=this.instances.filter(function(t){return null!=t}),this.callback(this.instances))},function(t){"use strict";function e(t,e){this.x=t,this.y=e}var i=t.fabric||(t.fabric={});return i.Point?void i.warn("fabric.Point is already defined"):(i.Point=e,void(e.prototype={constructor:e,add:function(t){return new e(this.x+t.x,this.y+t.y)},addEquals:function(t){return this.x+=t.x,this.y+=t.y,this},scalarAdd:function(t){return new e(this.x+t,this.y+t)},scalarAddEquals:function(t){return this.x+=t,this.y+=t,this},subtract:function(t){return new e(this.x-t.x,this.y-t.y)},subtractEquals:function(t){return this.x-=t.x,this.y-=t.y,this},scalarSubtract:function(t){return new e(this.x-t,this.y-t)},scalarSubtractEquals:function(t){return this.x-=t,this.y-=t,this},multiply:function(t){return new e(this.x*t,this.y*t)},multiplyEquals:function(t){return this.x*=t,this.y*=t,this},divide:function(t){return new e(this.x/t,this.y/t)},divideEquals:function(t){return this.x/=t,this.y/=t,this},eq:function(t){return this.x===t.x&&this.y===t.y},lt:function(t){return this.xt.x&&this.y>t.y},gte:function(t){return this.x>=t.x&&this.y>=t.y},lerp:function(t,i){return new e(this.x+(t.x-this.x)*i,this.y+(t.y-this.y)*i)},distanceFrom:function(t){var e=this.x-t.x,i=this.y-t.y;return Math.sqrt(e*e+i*i)},midPointFrom:function(t){return new e(this.x+(t.x-this.x)/2,this.y+(t.y-this.y)/2)},min:function(t){return new e(Math.min(this.x,t.x),Math.min(this.y,t.y))},max:function(t){return new e(Math.max(this.x,t.x),Math.max(this.y,t.y))},toString:function(){return this.x+","+this.y},setXY:function(t,e){this.x=t,this.y=e},setFromPoint:function(t){this.x=t.x,this.y=t.y},swap:function(t){var e=this.x,i=this.y;this.x=t.x,this.y=t.y,t.x=e,t.y=i}}))}("undefined"!=typeof exports?exports:this),function(t){"use strict";function e(t){this.status=t,this.points=[]}var i=t.fabric||(t.fabric={});return i.Intersection?void i.warn("fabric.Intersection is already defined"):(i.Intersection=e,i.Intersection.prototype={appendPoint:function(t){this.points.push(t)},appendPoints:function(t){this.points=this.points.concat(t)}},i.Intersection.intersectLineLine=function(t,r,n,s){var o,a=(s.x-n.x)*(t.y-n.y)-(s.y-n.y)*(t.x-n.x),h=(r.x-t.x)*(t.y-n.y)-(r.y-t.y)*(t.x-n.x),c=(s.y-n.y)*(r.x-t.x)-(s.x-n.x)*(r.y-t.y);if(0!==c){var l=a/c,u=h/c;l>=0&&1>=l&&u>=0&&1>=u?(o=new e("Intersection"),o.points.push(new i.Point(t.x+l*(r.x-t.x),t.y+l*(r.y-t.y)))):o=new e}else o=new e(0===a||0===h?"Coincident":"Parallel");return o},i.Intersection.intersectLinePolygon=function(t,i,r){for(var n=new e,s=r.length,o=0;s>o;o++){var a=r[o],h=r[(o+1)%s],c=e.intersectLineLine(t,i,a,h);n.appendPoints(c.points)}return n.points.length>0&&(n.status="Intersection"),n},i.Intersection.intersectPolygonPolygon=function(t,i){for(var r=new e,n=t.length,s=0;n>s;s++){var o=t[s],a=t[(s+1)%n],h=e.intersectLinePolygon(o,a,i);r.appendPoints(h.points)}return r.points.length>0&&(r.status="Intersection"),r},void(i.Intersection.intersectPolygonRectangle=function(t,r,n){var s=r.min(n),o=r.max(n),a=new i.Point(o.x,s.y),h=new i.Point(s.x,o.y),c=e.intersectLinePolygon(s,a,t),l=e.intersectLinePolygon(a,o,t),u=e.intersectLinePolygon(o,h,t),f=e.intersectLinePolygon(h,s,t),d=new e;return d.appendPoints(c.points),d.appendPoints(l.points),d.appendPoints(u.points),d.appendPoints(f.points),d.points.length>0&&(d.status="Intersection"),d}))}("undefined"!=typeof exports?exports:this),function(t){"use strict";function e(t){t?this._tryParsingColor(t):this.setSource([0,0,0,1])}function i(t,e,i){return 0>i&&(i+=1),i>1&&(i-=1),1/6>i?t+6*(e-t)*i:.5>i?e:2/3>i?t+(e-t)*(2/3-i)*6:t}var r=t.fabric||(t.fabric={});return r.Color?void r.warn("fabric.Color is already defined."):(r.Color=e,r.Color.prototype={_tryParsingColor:function(t){var i;return t in e.colorNameMap&&(t=e.colorNameMap[t]),"transparent"===t?void this.setSource([255,255,255,0]):(i=e.sourceFromHex(t),i||(i=e.sourceFromRgb(t)),i||(i=e.sourceFromHsl(t)),void(i&&this.setSource(i)))},_rgbToHsl:function(t,e,i){t/=255,e/=255,i/=255;var n,s,o,a=r.util.array.max([t,e,i]),h=r.util.array.min([t,e,i]);if(o=(a+h)/2,a===h)n=s=0;else{var c=a-h;switch(s=o>.5?c/(2-a-h):c/(a+h),a){case t:n=(e-i)/c+(i>e?6:0);break;case e:n=(i-t)/c+2;break;case i:n=(t-e)/c+4}n/=6}return[Math.round(360*n),Math.round(100*s),Math.round(100*o)]},getSource:function(){return this._source},setSource:function(t){this._source=t},toRgb:function(){var t=this.getSource();return"rgb("+t[0]+","+t[1]+","+t[2]+")"},toRgba:function(){var t=this.getSource();return"rgba("+t[0]+","+t[1]+","+t[2]+","+t[3]+")"},toHsl:function(){var t=this.getSource(),e=this._rgbToHsl(t[0],t[1],t[2]);return"hsl("+e[0]+","+e[1]+"%,"+e[2]+"%)"},toHsla:function(){var t=this.getSource(),e=this._rgbToHsl(t[0],t[1],t[2]);return"hsla("+e[0]+","+e[1]+"%,"+e[2]+"%,"+t[3]+")"},toHex:function(){var t,e,i,r=this.getSource();return t=r[0].toString(16),t=1===t.length?"0"+t:t,e=r[1].toString(16),e=1===e.length?"0"+e:e,i=r[2].toString(16),i=1===i.length?"0"+i:i,t.toUpperCase()+e.toUpperCase()+i.toUpperCase()},getAlpha:function(){return this.getSource()[3]},setAlpha:function(t){var e=this.getSource();return e[3]=t,this.setSource(e),this},toGrayscale:function(){var t=this.getSource(),e=parseInt((.3*t[0]+.59*t[1]+.11*t[2]).toFixed(0),10),i=t[3];return this.setSource([e,e,e,i]),this},toBlackWhite:function(t){var e=this.getSource(),i=(.3*e[0]+.59*e[1]+.11*e[2]).toFixed(0),r=e[3];return t=t||127,i=Number(i)a;a++)i.push(Math.round(s[a]*(1-n)+o[a]*n));return i[3]=r,this.setSource(i),this}},r.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*)?\)$/,r.Color.reHSLa=/^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/,r.Color.reHex=/^#?([0-9a-f]{6}|[0-9a-f]{3})$/i,r.Color.colorNameMap={aqua:"#00FFFF",black:"#000000",blue:"#0000FF",fuchsia:"#FF00FF",gray:"#808080",green:"#008000",lime:"#00FF00",maroon:"#800000",navy:"#000080",olive:"#808000",orange:"#FFA500",purple:"#800080",red:"#FF0000",silver:"#C0C0C0",teal:"#008080",white:"#FFFFFF",yellow:"#FFFF00"},r.Color.fromRgb=function(t){return e.fromSource(e.sourceFromRgb(t))},r.Color.sourceFromRgb=function(t){var i=t.match(e.reRGBa);if(i){var r=parseInt(i[1],10)/(/%$/.test(i[1])?100:1)*(/%$/.test(i[1])?255:1),n=parseInt(i[2],10)/(/%$/.test(i[2])?100:1)*(/%$/.test(i[2])?255:1),s=parseInt(i[3],10)/(/%$/.test(i[3])?100:1)*(/%$/.test(i[3])?255:1);return[parseInt(r,10),parseInt(n,10),parseInt(s,10),i[4]?parseFloat(i[4]):1]}},r.Color.fromRgba=e.fromRgb,r.Color.fromHsl=function(t){return e.fromSource(e.sourceFromHsl(t))},r.Color.sourceFromHsl=function(t){var r=t.match(e.reHSLa);if(r){var n,s,o,a=(parseFloat(r[1])%360+360)%360/360,h=parseFloat(r[2])/(/%$/.test(r[2])?100:1),c=parseFloat(r[3])/(/%$/.test(r[3])?100:1);if(0===h)n=s=o=c;else{var l=.5>=c?c*(h+1):c+h-c*h,u=2*c-l;n=i(u,l,a+1/3),s=i(u,l,a),o=i(u,l,a-1/3)}return[Math.round(255*n),Math.round(255*s),Math.round(255*o),r[4]?parseFloat(r[4]):1]}},r.Color.fromHsla=e.fromHsl,r.Color.fromHex=function(t){return e.fromSource(e.sourceFromHex(t))},r.Color.sourceFromHex=function(t){if(t.match(e.reHex)){var i=t.slice(t.indexOf("#")+1),r=3===i.length,n=r?i.charAt(0)+i.charAt(0):i.substring(0,2),s=r?i.charAt(1)+i.charAt(1):i.substring(2,4),o=r?i.charAt(2)+i.charAt(2):i.substring(4,6);return[parseInt(n,16),parseInt(s,16),parseInt(o,16),1]}},void(r.Color.fromSource=function(t){var i=new e;return i.setSource(t),i}))}("undefined"!=typeof exports?exports:this),function(){function t(t){var e,i,r,n=t.getAttribute("style"),s=t.getAttribute("offset")||0;if(s=parseFloat(s)/(/%$/.test(s)?100:1),s=0>s?0:s>1?1:s,n){var o=n.split(/\s*;\s*/);""===o[o.length-1]&&o.pop();for(var a=o.length;a--;){var h=o[a].split(/\s*:\s*/),c=h[0].trim(),l=h[1].trim();"stop-color"===c?e=l:"stop-opacity"===c&&(r=l)}}return e||(e=t.getAttribute("stop-color")||"rgb(0,0,0)"),r||(r=t.getAttribute("stop-opacity")),e=new fabric.Color(e),i=e.getAlpha(),r=isNaN(parseFloat(r))?1:parseFloat(r),r*=i,{offset:s,color:e.toRgb(),opacity:r}}function e(t){return{x1:t.getAttribute("x1")||0,y1:t.getAttribute("y1")||0,x2:t.getAttribute("x2")||"100%",y2:t.getAttribute("y2")||0}}function i(t){return{x1:t.getAttribute("fx")||t.getAttribute("cx")||"50%",y1:t.getAttribute("fy")||t.getAttribute("cy")||"50%",r1:0,x2:t.getAttribute("cx")||"50%",y2:t.getAttribute("cy")||"50%",r2:t.getAttribute("r")||"50%"}}function r(t,e,i){var r,n=0,s=1,o="";for(var a in e)r=parseFloat(e[a],10),s="string"==typeof e[a]&&/^\d+%$/.test(e[a])?.01:1,"x1"===a||"x2"===a||"r2"===a?(s*="objectBoundingBox"===i?t.width:1,n="objectBoundingBox"===i?t.left||0:0):("y1"===a||"y2"===a)&&(s*="objectBoundingBox"===i?t.height:1,n="objectBoundingBox"===i?t.top||0:0),e[a]=r*s+n;if("ellipse"===t.type&&null!==e.r2&&"objectBoundingBox"===i&&t.rx!==t.ry){var h=t.ry/t.rx;o=" scale(1, "+h+")",e.y1&&(e.y1/=h),e.y2&&(e.y2/=h)}return o}fabric.Gradient=fabric.util.createClass({offsetX:0,offsetY:0,initialize:function(t){t||(t={});var e={};this.id=fabric.Object.__uid++,this.type=t.type||"linear",e={x1:t.coords.x1||0,y1:t.coords.y1||0,x2:t.coords.x2||0,y2:t.coords.y2||0},"radial"===this.type&&(e.r1=t.coords.r1||0,e.r2=t.coords.r2||0),this.coords=e,this.colorStops=t.colorStops.slice(),t.gradientTransform&&(this.gradientTransform=t.gradientTransform),this.offsetX=t.offsetX||this.offsetX,this.offsetY=t.offsetY||this.offsetY},addColorStop:function(t){for(var e in t){var i=new fabric.Color(t[e]);this.colorStops.push({offset:e,color:i.toRgb(),opacity:i.getAlpha()})}return this},toObject:function(){return{type:this.type,coords:this.coords,colorStops:this.colorStops,offsetX:this.offsetX,offsetY:this.offsetY,gradientTransform:this.gradientTransform?this.gradientTransform.concat():this.gradientTransform}},toSVG:function(t){var e,i,r=fabric.util.object.clone(this.coords);if(this.colorStops.sort(function(t,e){return t.offset-e.offset}),!t.group||"path-group"!==t.group.type)for(var n in r)"x1"===n||"x2"===n||"r2"===n?r[n]+=this.offsetX-t.width/2:("y1"===n||"y2"===n)&&(r[n]+=this.offsetY-t.height/2);i='id="SVGID_'+this.id+'" gradientUnits="userSpaceOnUse"',this.gradientTransform&&(i+=' gradientTransform="matrix('+this.gradientTransform.join(" ")+')" '),"linear"===this.type?e=["\n']:"radial"===this.type&&(e=["\n']);for(var s=0;s\n');return e.push("linear"===this.type?"\n":"\n"),e.join("")},toLive:function(t,e){var i,r,n=fabric.util.object.clone(this.coords);if(this.type){if(e.group&&"path-group"===e.group.type)for(r in n)"x1"===r||"x2"===r?n[r]+=-this.offsetX+e.width/2:("y1"===r||"y2"===r)&&(n[r]+=-this.offsetY+e.height/2);"linear"===this.type?i=t.createLinearGradient(n.x1,n.y1,n.x2,n.y2):"radial"===this.type&&(i=t.createRadialGradient(n.x1,n.y1,n.r1,n.x2,n.y2,n.r2));for(var s=0,o=this.colorStops.length;o>s;s++){var a=this.colorStops[s].color,h=this.colorStops[s].opacity,c=this.colorStops[s].offset;"undefined"!=typeof h&&(a=new fabric.Color(a).setAlpha(h).toRgba()),i.addColorStop(parseFloat(c),a)}return i}}}),fabric.util.object.extend(fabric.Gradient,{fromElement:function(n,s){var o,a=n.getElementsByTagName("stop"),h="linearGradient"===n.nodeName?"linear":"radial",c=n.getAttribute("gradientUnits")||"objectBoundingBox",l=n.getAttribute("gradientTransform"),u=[],f={};"linear"===h?f=e(n):"radial"===h&&(f=i(n));for(var d=a.length;d--;)u.push(t(a[d]));o=r(s,f,c);var g=new fabric.Gradient({type:h,coords:f,colorStops:u,offsetX:-s.left,offsetY:-s.top});return(l||""!==o)&&(g.gradientTransform=fabric.parseTransformAttribute((l||"")+o)),g},forObject:function(t,e){return e||(e={}),r(t,e.coords,"userSpaceOnUse"),new fabric.Gradient(e)}})}(),fabric.Pattern=fabric.util.createClass({repeat:"repeat",offsetX:0,offsetY:0,initialize:function(t){if(t||(t={}),this.id=fabric.Object.__uid++,t.source)if("string"==typeof t.source)if("undefined"!=typeof fabric.util.getFunctionBody(t.source))this.source=new Function(fabric.util.getFunctionBody(t.source));else{var e=this;this.source=fabric.util.createImage(),fabric.util.loadImage(t.source,function(t){e.source=t})}else this.source=t.source;t.repeat&&(this.repeat=t.repeat),t.offsetX&&(this.offsetX=t.offsetX),t.offsetY&&(this.offsetY=t.offsetY)},toObject:function(){var t;return"function"==typeof this.source?t=String(this.source):"string"==typeof this.source.src?t=this.source.src:"object"==typeof this.source&&this.source.toDataURL&&(t=this.source.toDataURL()),{source:t,repeat:this.repeat,offsetX:this.offsetX,offsetY:this.offsetY}},toSVG:function(t){var e="function"==typeof this.source?this.source():this.source,i=e.width/t.getWidth(),r=e.height/t.getHeight(),n=this.offsetX/t.getWidth(),s=this.offsetY/t.getHeight(),o="";return("repeat-x"===this.repeat||"no-repeat"===this.repeat)&&(r=1),("repeat-y"===this.repeat||"no-repeat"===this.repeat)&&(i=1),e.src?o=e.src:e.toDataURL&&(o=e.toDataURL()),'\n\n\n'},toLive:function(t){var e="function"==typeof this.source?this.source():this.source;if(!e)return"";if("undefined"!=typeof e.src){if(!e.complete)return"";if(0===e.naturalWidth||0===e.naturalHeight)return""}return t.createPattern(e,this.repeat)}}),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.toFixed;return e.Shadow?void e.warn("fabric.Shadow is already defined."):(e.Shadow=e.util.createClass({color:"rgb(0,0,0)",blur:0,offsetX:0,offsetY:0,affectStroke:!1,includeDefaultValues:!0,initialize:function(t){"string"==typeof t&&(t=this._parseShadow(t));for(var i in t)this[i]=t[i];this.id=e.Object.__uid++},_parseShadow:function(t){var i=t.trim(),r=e.Shadow.reOffsetsAndBlur.exec(i)||[],n=i.replace(e.Shadow.reOffsetsAndBlur,"")||"rgb(0,0,0)";return{color:n.trim(),offsetX:parseInt(r[1],10)||0,offsetY:parseInt(r[2],10)||0,blur:parseInt(r[3],10)||0}},toString:function(){return[this.offsetX,this.offsetY,this.blur,this.color].join("px ")},toSVG:function(t){var r=40,n=40,s=e.Object.NUM_FRACTION_DIGITS,o=e.util.rotateVector({x:this.offsetX,y:this.offsetY},e.util.degreesToRadians(-t.angle)),a=20;return t.width&&t.height&&(r=100*i((Math.abs(o.x)+this.blur)/t.width,s)+a,n=100*i((Math.abs(o.y)+this.blur)/t.height,s)+a),t.flipX&&(o.x*=-1),t.flipY&&(o.y*=-1),'\n \n \n \n \n \n \n \n \n\n'},toObject:function(){if(this.includeDefaultValues)return{color:this.color,blur:this.blur,offsetX:this.offsetX,offsetY:this.offsetY,affectStroke:this.affectStroke};var t={},i=e.Shadow.prototype;return["color","blur","offsetX","offsetY","affectStroke"].forEach(function(e){this[e]!==i[e]&&(t[e]=this[e])},this),t}}),void(e.Shadow.reOffsetsAndBlur=/(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/))}("undefined"!=typeof exports?exports:this),function(){"use strict";if(fabric.StaticCanvas)return void fabric.warn("fabric.StaticCanvas is already defined.");var t=fabric.util.object.extend,e=fabric.util.getElementOffset,i=fabric.util.removeFromArray,r=fabric.util.toFixed,n=new Error("Could not initialize `canvas` element");fabric.StaticCanvas=fabric.util.createClass({initialize:function(t,e){e||(e={}),this._initStatic(t,e)},backgroundColor:"",backgroundImage:null,overlayColor:"",overlayImage:null,includeDefaultValues:!0,stateful:!0,renderOnAddRemove:!0,clipTo:null,controlsAboveOverlay:!1,allowTouchScrolling:!1,imageSmoothingEnabled:!0,preserveObjectStacking:!1,viewportTransform:[1,0,0,1,0,0],onBeforeScaleRotate:function(){},enableRetinaScaling:!0,_initStatic:function(t,e){this._objects=[],this._createLowerCanvas(t),this._initOptions(e),this._setImageSmoothing(),this.interactive||this._initRetinaScaling(),e.overlayImage&&this.setOverlayImage(e.overlayImage,this.renderAll.bind(this)),e.backgroundImage&&this.setBackgroundImage(e.backgroundImage,this.renderAll.bind(this)),e.backgroundColor&&this.setBackgroundColor(e.backgroundColor,this.renderAll.bind(this)),e.overlayColor&&this.setOverlayColor(e.overlayColor,this.renderAll.bind(this)),this.calcOffset()},_isRetinaScaling:function(){return 1!==fabric.devicePixelRatio&&this.enableRetinaScaling},_initRetinaScaling:function(){this._isRetinaScaling()&&(this.lowerCanvasEl.setAttribute("width",this.width*fabric.devicePixelRatio),this.lowerCanvasEl.setAttribute("height",this.height*fabric.devicePixelRatio),this.contextContainer.scale(fabric.devicePixelRatio,fabric.devicePixelRatio))},calcOffset:function(){return this._offset=e(this.lowerCanvasEl),this},setOverlayImage:function(t,e,i){return this.__setBgOverlayImage("overlayImage",t,e,i)},setBackgroundImage:function(t,e,i){return this.__setBgOverlayImage("backgroundImage",t,e,i)},setOverlayColor:function(t,e){return this.__setBgOverlayColor("overlayColor",t,e)},setBackgroundColor:function(t,e){return this.__setBgOverlayColor("backgroundColor",t,e)},_setImageSmoothing:function(){var t=this.getContext();t.imageSmoothingEnabled=t.imageSmoothingEnabled||t.webkitImageSmoothingEnabled||t.mozImageSmoothingEnabled||t.msImageSmoothingEnabled||t.oImageSmoothingEnabled,t.imageSmoothingEnabled=this.imageSmoothingEnabled},__setBgOverlayImage:function(t,e,i,r){return"string"==typeof e?fabric.util.loadImage(e,function(e){this[t]=new fabric.Image(e,r),i&&i(e)},this,r&&r.crossOrigin):(r&&e.setOptions(r),this[t]=e,i&&i(e)),this},__setBgOverlayColor:function(t,e,i){if(e&&e.source){var r=this;fabric.util.loadImage(e.source,function(n){r[t]=new fabric.Pattern({source:n,repeat:e.repeat,offsetX:e.offsetX,offsetY:e.offsetY}),i&&i()})}else this[t]=e,i&&i();return this},_createCanvasElement:function(){var t=fabric.document.createElement("canvas");if(t.style||(t.style={}),!t)throw n;return this._initCanvasElement(t),t},_initCanvasElement:function(t){if(fabric.util.createCanvasElement(t),"undefined"==typeof t.getContext)throw n},_initOptions:function(t){for(var e in t)this[e]=t[e];this.width=this.width||parseInt(this.lowerCanvasEl.width,10)||0,this.height=this.height||parseInt(this.lowerCanvasEl.height,10)||0,this.lowerCanvasEl.style&&(this.lowerCanvasEl.width=this.width,this.lowerCanvasEl.height=this.height,this.lowerCanvasEl.style.width=this.width+"px",this.lowerCanvasEl.style.height=this.height+"px",this.viewportTransform=this.viewportTransform.slice())},_createLowerCanvas:function(t){this.lowerCanvasEl=fabric.util.getById(t)||this._createCanvasElement(),this._initCanvasElement(this.lowerCanvasEl),fabric.util.addClass(this.lowerCanvasEl,"lower-canvas"),this.interactive&&this._applyCanvasStyle(this.lowerCanvasEl),this.contextContainer=this.lowerCanvasEl.getContext("2d")},getWidth:function(){return this.width},getHeight:function(){return this.height},setWidth:function(t,e){return this.setDimensions({width:t},e)},setHeight:function(t,e){return this.setDimensions({height:t},e)},setDimensions:function(t,e){var i;e=e||{};for(var r in t)i=t[r],e.cssOnly||(this._setBackstoreDimension(r,t[r]),i+="px"),e.backstoreOnly||this._setCssDimension(r,i);return this._initRetinaScaling(),this._setImageSmoothing(),this.calcOffset(),e.cssOnly||this.renderAll(),this},_setBackstoreDimension:function(t,e){return this.lowerCanvasEl[t]=e,this.upperCanvasEl&&(this.upperCanvasEl[t]=e),this.cacheCanvasEl&&(this.cacheCanvasEl[t]=e),this[t]=e,this},_setCssDimension:function(t,e){return this.lowerCanvasEl.style[t]=e,this.upperCanvasEl&&(this.upperCanvasEl.style[t]=e),this.wrapperEl&&(this.wrapperEl.style[t]=e),this},getZoom:function(){return Math.sqrt(this.viewportTransform[0]*this.viewportTransform[3])},setViewportTransform:function(t){var e=this.getActiveGroup();this.viewportTransform=t,this.renderAll();for(var i=0,r=this._objects.length;r>i;i++)this._objects[i].setCoords();return e&&e.setCoords(),this},zoomToPoint:function(t,e){var i=t;t=fabric.util.transformPoint(t,fabric.util.invertTransform(this.viewportTransform)),this.viewportTransform[0]=e,this.viewportTransform[3]=e;var r=fabric.util.transformPoint(t,this.viewportTransform);this.viewportTransform[4]+=i.x-r.x,this.viewportTransform[5]+=i.y-r.y,this.renderAll();for(var n=0,s=this._objects.length;s>n;n++)this._objects[n].setCoords();return this},setZoom:function(t){return this.zoomToPoint(new fabric.Point(0,0),t),this},absolutePan:function(t){this.viewportTransform[4]=-t.x,this.viewportTransform[5]=-t.y,this.renderAll();for(var e=0,i=this._objects.length;i>e;e++)this._objects[e].setCoords();return this},relativePan:function(t){return this.absolutePan(new fabric.Point(-t.x-this.viewportTransform[4],-t.y-this.viewportTransform[5]))},getElement:function(){return this.lowerCanvasEl},getActiveObject:function(){return null},getActiveGroup:function(){return null},_onObjectAdded:function(t){this.stateful&&t.setupState(),t._set("canvas",this),t.setCoords(),this.fire("object:added",{target:t}),t.fire("added")},_onObjectRemoved:function(t){this.getActiveObject()===t&&(this.fire("before:selection:cleared",{target:t}),this._discardActiveObject(),this.fire("selection:cleared")),this.fire("object:removed",{target:t}),t.fire("removed")},clearContext:function(t){return t.clearRect(0,0,this.width,this.height),this},getContext:function(){return this.contextContainer},clear:function(){return this._objects.length=0,this.discardActiveGroup&&this.discardActiveGroup(),this.discardActiveObject&&this.discardActiveObject(),this.clearContext(this.contextContainer),this.contextTop&&this.clearContext(this.contextTop),this.fire("canvas:cleared"),this.renderAll(),this},_chooseObjectsToRender:function(){var t,e=this.getActiveGroup(),i=[],r=[];if(e&&!this.preserveObjectStacking){for(var n=0,s=this._objects.length;s>n;n++)t=this._objects[n],e.contains(t)?r.push(t):i.push(t);e._set("_objects",r)}else i=this._objects;return i},renderAll:function(){var t,e=this.contextContainer;return this.contextTop&&this.selection&&!this._groupSelector&&!this.isDrawingMode&&this.clearContext(this.contextTop),this.clearContext(e),this.fire("before:render"),this.clipTo&&fabric.util.clipContext(this,e),this._renderBackground(e),e.save(),t=this._chooseObjectsToRender(),e.transform.apply(e,this.viewportTransform),this._renderObjects(e,t),this.preserveObjectStacking||this._renderObjects(e,[this.getActiveGroup()]),e.restore(),!this.controlsAboveOverlay&&this.interactive&&this.drawControls(e),this.clipTo&&e.restore(),this._renderOverlay(e),this.controlsAboveOverlay&&this.interactive&&this.drawControls(e),this.fire("after:render"),this},_renderObjects:function(t,e){for(var i=0,r=e.length;r>i;++i)e[i]&&e[i].render(t)},_renderBackgroundOrOverlay:function(t,e){var i=this[e+"Color"];i&&(t.fillStyle=i.toLive?i.toLive(t):i,t.fillRect(i.offsetX||0,i.offsetY||0,this.width,this.height)),i=this[e+"Image"],i&&i.render(t)},_renderBackground:function(t){this._renderBackgroundOrOverlay(t,"background")},_renderOverlay:function(t){this._renderBackgroundOrOverlay(t,"overlay")},renderTop:function(){var t=this.contextTop||this.contextContainer;return this.clearContext(t),this.selection&&this._groupSelector&&this._drawSelection(),this.fire("after:render"),this},getCenter:function(){return{top:this.getHeight()/2,left:this.getWidth()/2}},centerObjectH:function(t){return this._centerObject(t,new fabric.Point(this.getCenter().left,t.getCenterPoint().y)),this.renderAll(),this},centerObjectV:function(t){return this._centerObject(t,new fabric.Point(t.getCenterPoint().x,this.getCenter().top)),this.renderAll(),this},centerObject:function(t){var e=this.getCenter();return this._centerObject(t,new fabric.Point(e.left,e.top)),this.renderAll(),this},_centerObject:function(t,e){return t.setPositionByOrigin(e,"center","center"),this},toDatalessJSON:function(t){return this.toDatalessObject(t)},toObject:function(t){return this._toObjectMethod("toObject",t)},toDatalessObject:function(t){return this._toObjectMethod("toDatalessObject",t)},_toObjectMethod:function(e,i){var r={objects:this._toObjects(e,i)};return t(r,this.__serializeBgOverlay()),fabric.util.populateWithProperties(this,r,i),r},_toObjects:function(t,e){return this.getObjects().map(function(i){ +return this._toObject(i,t,e)},this)},_toObject:function(t,e,i){var r;this.includeDefaultValues||(r=t.includeDefaultValues,t.includeDefaultValues=!1);var n=this._realizeGroupTransformOnObject(t),s=t[e](i);return this.includeDefaultValues||(t.includeDefaultValues=r),this._unwindGroupTransformOnObject(t,n),s},_realizeGroupTransformOnObject:function(t){var e=["angle","flipX","flipY","height","left","scaleX","scaleY","top","width"];if(t.group&&t.group===this.getActiveGroup()){var i={};return e.forEach(function(e){i[e]=t[e]}),this.getActiveGroup().realizeTransform(t),i}return null},_unwindGroupTransformOnObject:function(t,e){e&&t.set(e)},__serializeBgOverlay:function(){var t={background:this.backgroundColor&&this.backgroundColor.toObject?this.backgroundColor.toObject():this.backgroundColor};return this.overlayColor&&(t.overlay=this.overlayColor.toObject?this.overlayColor.toObject():this.overlayColor),this.backgroundImage&&(t.backgroundImage=this.backgroundImage.toObject()),this.overlayImage&&(t.overlayImage=this.overlayImage.toObject()),t},svgViewportTransformation:!0,toSVG:function(t,e){t||(t={});var i=[];return this._setSVGPreamble(i,t),this._setSVGHeader(i,t),this._setSVGBgOverlayColor(i,"backgroundColor"),this._setSVGBgOverlayImage(i,"backgroundImage"),this._setSVGObjects(i,e),this._setSVGBgOverlayColor(i,"overlayColor"),this._setSVGBgOverlayImage(i,"overlayImage"),i.push(""),i.join("")},_setSVGPreamble:function(t,e){e.suppressPreamble||t.push('\n','\n')},_setSVGHeader:function(t,e){var i,n=e.width||this.width,s=e.height||this.height,o='viewBox="0 0 '+this.width+" "+this.height+'" ',a=fabric.Object.NUM_FRACTION_DIGITS;e.viewBox?o='viewBox="'+e.viewBox.x+" "+e.viewBox.y+" "+e.viewBox.width+" "+e.viewBox.height+'" ':this.svgViewportTransformation&&(i=this.viewportTransform,o='viewBox="'+r(-i[4]/i[0],a)+" "+r(-i[5]/i[3],a)+" "+r(this.width/i[0],a)+" "+r(this.height/i[3],a)+'" '),t.push("\n',"Created with Fabric.js ",fabric.version,"\n","",fabric.createSVGFontFacesMarkup(this.getObjects()),fabric.createSVGRefElementsMarkup(this),"\n")},_setSVGObjects:function(t,e){for(var i=0,r=this.getObjects(),n=r.length;n>i;i++){var s=r[i],o=this._realizeGroupTransformOnObject(s);t.push(s.toSVG(e)),this._unwindGroupTransformOnObject(s,o)}},_setSVGBgOverlayImage:function(t,e){this[e]&&this[e].toSVG&&t.push(this[e].toSVG())},_setSVGBgOverlayColor:function(t,e){this[e]&&this[e].source?t.push('\n"):this[e]&&"overlayColor"===e&&t.push('\n")},sendToBack:function(t){return i(this._objects,t),this._objects.unshift(t),this.renderAll&&this.renderAll()},bringToFront:function(t){return i(this._objects,t),this._objects.push(t),this.renderAll&&this.renderAll()},sendBackwards:function(t,e){var r=this._objects.indexOf(t);if(0!==r){var n=this._findNewLowerIndex(t,r,e);i(this._objects,t),this._objects.splice(n,0,t),this.renderAll&&this.renderAll()}return this},_findNewLowerIndex:function(t,e,i){var r;if(i){r=e;for(var n=e-1;n>=0;--n){var s=t.intersectsWithObject(this._objects[n])||t.isContainedWithinObject(this._objects[n])||this._objects[n].isContainedWithinObject(t);if(s){r=n;break}}}else r=e-1;return r},bringForward:function(t,e){var r=this._objects.indexOf(t);if(r!==this._objects.length-1){var n=this._findNewUpperIndex(t,r,e);i(this._objects,t),this._objects.splice(n,0,t),this.renderAll&&this.renderAll()}return this},_findNewUpperIndex:function(t,e,i){var r;if(i){r=e;for(var n=e+1;n"}}),t(fabric.StaticCanvas.prototype,fabric.Observable),t(fabric.StaticCanvas.prototype,fabric.Collection),t(fabric.StaticCanvas.prototype,fabric.DataURLExporter),t(fabric.StaticCanvas,{EMPTY_JSON:'{"objects": [], "background": "white"}',supports:function(t){var e=fabric.util.createCanvasElement();if(!e||!e.getContext)return null;var i=e.getContext("2d");if(!i)return null;switch(t){case"getImageData":return"undefined"!=typeof i.getImageData;case"setLineDash":return"undefined"!=typeof i.setLineDash;case"toDataURL":return"undefined"!=typeof e.toDataURL;case"toDataURLWithQuality":try{return e.toDataURL("image/jpeg",0),!0}catch(r){}return!1;default:return null}}}),fabric.StaticCanvas.prototype.toJSON=fabric.StaticCanvas.prototype.toObject}(),fabric.BaseBrush=fabric.util.createClass({color:"rgb(0, 0, 0)",width:1,shadow:null,strokeLineCap:"round",strokeLineJoin:"round",strokeDashArray:null,setShadow:function(t){return this.shadow=new fabric.Shadow(t),this},_setBrushStyles:function(){var t=this.canvas.contextTop;t.strokeStyle=this.color,t.lineWidth=this.width,t.lineCap=this.strokeLineCap,t.lineJoin=this.strokeLineJoin,this.strokeDashArray&&fabric.StaticCanvas.supports("setLineDash")&&t.setLineDash(this.strokeDashArray)},_setShadow:function(){if(this.shadow){var t=this.canvas.contextTop;t.shadowColor=this.shadow.color,t.shadowBlur=this.shadow.blur,t.shadowOffsetX=this.shadow.offsetX,t.shadowOffsetY=this.shadow.offsetY}},_resetShadow:function(){var t=this.canvas.contextTop;t.shadowColor="",t.shadowBlur=t.shadowOffsetX=t.shadowOffsetY=0}}),function(){fabric.PencilBrush=fabric.util.createClass(fabric.BaseBrush,{initialize:function(t){this.canvas=t,this._points=[]},onMouseDown:function(t){this._prepareForDrawing(t),this._captureDrawingPath(t),this._render()},onMouseMove:function(t){this._captureDrawingPath(t),this.canvas.clearContext(this.canvas.contextTop),this._render()},onMouseUp:function(){this._finalizeAndAddPath()},_prepareForDrawing:function(t){var e=new fabric.Point(t.x,t.y);this._reset(),this._addPoint(e),this.canvas.contextTop.moveTo(e.x,e.y)},_addPoint:function(t){this._points.push(t)},_reset:function(){this._points.length=0,this._setBrushStyles(),this._setShadow()},_captureDrawingPath:function(t){var e=new fabric.Point(t.x,t.y);this._addPoint(e)},_render:function(){var t=this.canvas.contextTop,e=this.canvas.viewportTransform,i=this._points[0],r=this._points[1];t.save(),t.transform(e[0],e[1],e[2],e[3],e[4],e[5]),t.beginPath(),2===this._points.length&&i.x===r.x&&i.y===r.y&&(i.x-=.5,r.x+=.5),t.moveTo(i.x,i.y);for(var n=1,s=this._points.length;s>n;n++){var o=i.midPointFrom(r);t.quadraticCurveTo(i.x,i.y,o.x,o.y),i=this._points[n],r=this._points[n+1]}t.lineTo(i.x,i.y),t.stroke(),t.restore()},convertPointsToSVGPath:function(t){var e=[],i=new fabric.Point(t[0].x,t[0].y),r=new fabric.Point(t[1].x,t[1].y);e.push("M ",t[0].x," ",t[0].y," ");for(var n=1,s=t.length;s>n;n++){var o=i.midPointFrom(r);e.push("Q ",i.x," ",i.y," ",o.x," ",o.y," "),i=new fabric.Point(t[n].x,t[n].y),n+1i;i++){var n=this.points[i],s=new fabric.Circle({radius:n.radius,left:n.x,top:n.y,originX:"center",originY:"center",fill:n.fill});this.shadow&&s.setShadow(this.shadow),e.push(s)}var o=new fabric.Group(e,{originX:"center",originY:"center"});o.canvas=this.canvas,this.canvas.add(o),this.canvas.fire("path:created",{path:o}),this.canvas.clearContext(this.canvas.contextTop),this._resetShadow(),this.canvas.renderOnAddRemove=t,this.canvas.renderAll()},addPoint:function(t){var e=new fabric.Point(t.x,t.y),i=fabric.util.getRandomInt(Math.max(0,this.width-20),this.width+20)/2,r=new fabric.Color(this.color).setAlpha(fabric.util.getRandomInt(0,100)/100).toRgba();return e.radius=i,e.fill=r,this.points.push(e),e}}),fabric.SprayBrush=fabric.util.createClass(fabric.BaseBrush,{width:10,density:20,dotWidth:1,dotWidthVariance:1,randomOpacity:!1,optimizeOverlapping:!0,initialize:function(t){this.canvas=t,this.sprayChunks=[]},onMouseDown:function(t){this.sprayChunks.length=0,this.canvas.clearContext(this.canvas.contextTop),this._setShadow(),this.addSprayChunk(t),this.render()},onMouseMove:function(t){this.addSprayChunk(t),this.render()},onMouseUp:function(){var t=this.canvas.renderOnAddRemove;this.canvas.renderOnAddRemove=!1;for(var e=[],i=0,r=this.sprayChunks.length;r>i;i++)for(var n=this.sprayChunks[i],s=0,o=n.length;o>s;s++){var a=new fabric.Rect({width:n[s].width,height:n[s].width,left:n[s].x+1,top:n[s].y+1,originX:"center",originY:"center",fill:this.color});this.shadow&&a.setShadow(this.shadow),e.push(a)}this.optimizeOverlapping&&(e=this._getOptimizedRects(e));var h=new fabric.Group(e,{originX:"center",originY:"center"});h.canvas=this.canvas,this.canvas.add(h),this.canvas.fire("path:created",{path:h}),this.canvas.clearContext(this.canvas.contextTop),this._resetShadow(),this.canvas.renderOnAddRemove=t,this.canvas.renderAll()},_getOptimizedRects:function(t){for(var e,i={},r=0,n=t.length;n>r;r++)e=t[r].left+""+t[r].top,i[e]||(i[e]=t[r]);var s=[];for(e in i)s.push(i[e]);return s},render:function(){var t=this.canvas.contextTop;t.fillStyle=this.color;var e=this.canvas.viewportTransform;t.save(),t.transform(e[0],e[1],e[2],e[3],e[4],e[5]);for(var i=0,r=this.sprayChunkPoints.length;r>i;i++){var n=this.sprayChunkPoints[i];"undefined"!=typeof n.opacity&&(t.globalAlpha=n.opacity),t.fillRect(n.x,n.y,n.width,n.width)}t.restore()},addSprayChunk:function(t){this.sprayChunkPoints=[];for(var e,i,r,n=this.width/2,s=0;s0?1:-1,"y"===i&&(s=e.target.skewY,o="top",a="bottom",r="originY"),n[-1]=o,n[1]=a,e.target.flipX&&(c*=-1),e.target.flipY&&(c*=-1),0===s?(e.skewSign=-h*t*c,e[r]=n[-t]):(s=s>0?1:-1,e.skewSign=s,e[r]=n[s*h*c])},_skewObject:function(t,e,i){var r=this._currentTransform,n=r.target,s=!1,o=n.get("lockSkewingX"),a=n.get("lockSkewingY");if(o&&"x"===i||a&&"y"===i)return!1;var h,c,l=n.getCenterPoint(),u=n.toLocalPoint(new fabric.Point(t,e),"center","center")[i],f=n.toLocalPoint(new fabric.Point(r.lastX,r.lastY),"center","center")[i],d=n._getTransformedDimensions();return this._changeSkewTransformOrigin(u-f,r,i),h=n.toLocalPoint(new fabric.Point(t,e),r.originX,r.originY)[i],c=n.translateToOriginPoint(l,r.originX,r.originY),s=this._setObjectSkew(h,r,i,d),r.lastX=t,r.lastY=e,n.setPositionByOrigin(c,r.originX,r.originY),s},_setObjectSkew:function(t,e,i,r){var n,s,o,a,h,c,l,u,f,d=e.target,g=!1,p=e.skewSign;return"x"===i?(a="y",h="Y",c="X",u=0,f=d.skewY):(a="x",h="X",c="Y",u=d.skewX,f=0),o=d._getTransformedDimensions(u,f),l=2*Math.abs(t)-o[i],2>=l?n=0:(n=p*Math.atan(l/d["scale"+c]/(o[a]/d["scale"+h])),n=fabric.util.radiansToDegrees(n)),g=d["skew"+c]!==n,d.set("skew"+c,n),0!==d["skew"+h]&&(s=d._getTransformedDimensions(),n=r[a]/s[a]*d["scale"+h],d.set("scale"+h,n)),g},_scaleObject:function(t,e,i){var r=this._currentTransform,n=r.target,s=n.get("lockScalingX"),o=n.get("lockScalingY"),a=n.get("lockScalingFlip");if(s&&o)return!1;var h=n.translateToOriginPoint(n.getCenterPoint(),r.originX,r.originY),c=n.toLocalPoint(new fabric.Point(t,e),r.originX,r.originY),l=n._getTransformedDimensions(),u=!1;return this._setLocalMouse(c,r),u=this._setObjectScale(c,r,s,o,i,a,l),n.setPositionByOrigin(h,r.originX,r.originY),u},_setObjectScale:function(t,e,i,r,n,s,o){var a,h,c,l,u=e.target,f=!1,d=!1,g=!1;return c=t.x*u.scaleX/o.x,l=t.y*u.scaleY/o.y,a=u.scaleX!==c,h=u.scaleY!==l,s&&0>=c&&c=l&&li.padding?t.x<0?t.x+=i.padding:t.x-=i.padding:t.x=0,n(t.y)>i.padding?t.y<0?t.y+=i.padding:t.y-=i.padding:t.y=0},_rotateObject:function(t,e){var n=this._currentTransform;if(n.target.get("lockRotation"))return!1;var s=r(n.ey-n.top,n.ex-n.left),o=r(e-n.top,t-n.left),a=i(o-s+n.theta);return 0>a&&(a=360+a),n.target.angle=a%360,!0},setCursor:function(t){this.upperCanvasEl.style.cursor=t},_resetObjectTransform:function(t){t.scaleX=1,t.scaleY=1,t.skewX=0,t.skewY=0,t.setAngle(0)},_drawSelection:function(){var t=this.contextTop,e=this._groupSelector,i=e.left,r=e.top,o=n(i),a=n(r);if(t.fillStyle=this.selectionColor,t.fillRect(e.ex-(i>0?0:-i),e.ey-(r>0?0:-r),o,a),t.lineWidth=this.selectionLineWidth,t.strokeStyle=this.selectionBorderColor,this.selectionDashArray.length>1){var h=e.ex+s-(i>0?0:o),c=e.ey+s-(r>0?0:a);t.beginPath(),fabric.util.drawDashedLine(t,h,c,h+o,c,this.selectionDashArray),fabric.util.drawDashedLine(t,h,c+a-1,h+o,c+a-1,this.selectionDashArray),fabric.util.drawDashedLine(t,h,c,h,c+a,this.selectionDashArray),fabric.util.drawDashedLine(t,h+o-1,c,h+o-1,c+a,this.selectionDashArray),t.closePath(),t.stroke()}else t.strokeRect(e.ex+s-(i>0?0:o),e.ey+s-(r>0?0:a),o,a)},_isLastRenderedObject:function(t){return this.controlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay.visible&&this.containsPoint(t,this.lastRenderedObjectWithControlsAboveOverlay)&&this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(this.getPointer(t,!0))},findTarget:function(t,e){if(!this.skipTargetFind){if(this._isLastRenderedObject(t))return this.lastRenderedObjectWithControlsAboveOverlay;var i=this.getActiveGroup();if(i&&!e&&this.containsPoint(t,i))return i;var r=this._searchPossibleTargets(t,e);return this._fireOverOutEvents(r,t),r}},_fireOverOutEvents:function(t,e){t?this._hoveredTarget!==t&&(this._hoveredTarget&&(this.fire("mouse:out",{target:this._hoveredTarget,e:e}),this._hoveredTarget.fire("mouseout")),this.fire("mouse:over",{target:t,e:e}),t.fire("mouseover"),this._hoveredTarget=t):this._hoveredTarget&&(this.fire("mouse:out",{target:this._hoveredTarget,e:e}),this._hoveredTarget.fire("mouseout"),this._hoveredTarget=null)},_checkTarget:function(t,e,i){if(e&&e.visible&&e.evented&&this.containsPoint(t,e)){if(!this.perPixelTargetFind&&!e.perPixelTargetFind||e.isEditing)return!0;var r=this.isTargetTransparent(e,i.x,i.y);if(!r)return!0}},_searchPossibleTargets:function(t,e){for(var i,r=this.getPointer(t,!0),n=this._objects.length;n--;)if((!this._objects[n].group||e)&&this._checkTarget(t,this._objects[n],r)){this.relatedTarget=this._objects[n],i=this._objects[n];break}return i},getPointer:function(e,i,r){r||(r=this.upperCanvasEl);var n,s=t(e),o=r.getBoundingClientRect(),a=o.width||0,h=o.height||0;return a&&h||("top"in o&&"bottom"in o&&(h=Math.abs(o.top-o.bottom)),"right"in o&&"left"in o&&(a=Math.abs(o.right-o.left))),this.calcOffset(),s.x=s.x-this._offset.left,s.y=s.y-this._offset.top,i||(s=fabric.util.transformPoint(s,fabric.util.invertTransform(this.viewportTransform))),n=0===a||0===h?{width:1,height:1}:{width:r.width/a,height:r.height/h},{x:s.x*n.width,y:s.y*n.height}},_createUpperCanvas:function(){var t=this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/,"");this.upperCanvasEl=this._createCanvasElement(),fabric.util.addClass(this.upperCanvasEl,"upper-canvas "+t),this.wrapperEl.appendChild(this.upperCanvasEl),this._copyCanvasStyle(this.lowerCanvasEl,this.upperCanvasEl),this._applyCanvasStyle(this.upperCanvasEl),this.contextTop=this.upperCanvasEl.getContext("2d")},_createCacheCanvas:function(){this.cacheCanvasEl=this._createCanvasElement(),this.cacheCanvasEl.setAttribute("width",this.width),this.cacheCanvasEl.setAttribute("height",this.height),this.contextCache=this.cacheCanvasEl.getContext("2d")},_initWrapperElement:function(){this.wrapperEl=fabric.util.wrapElement(this.lowerCanvasEl,"div",{"class":this.containerClass}),fabric.util.setStyle(this.wrapperEl,{width:this.getWidth()+"px",height:this.getHeight()+"px",position:"relative"}),fabric.util.makeElementUnselectable(this.wrapperEl)},_applyCanvasStyle:function(t){var e=this.getWidth()||t.width,i=this.getHeight()||t.height;fabric.util.setStyle(t,{position:"absolute",width:e+"px",height:i+"px",left:0,top:0}),t.width=e,t.height=i,fabric.util.makeElementUnselectable(t)},_copyCanvasStyle:function(t,e){e.style.cssText=t.style.cssText},getSelectionContext:function(){return this.contextTop},getSelectionElement:function(){return this.upperCanvasEl},_setActiveObject:function(t){this._activeObject&&this._activeObject.set("active",!1),this._activeObject=t,t.set("active",!0)},setActiveObject:function(t,e){return this._setActiveObject(t),this.renderAll(),this.fire("object:selected",{target:t,e:e}),t.fire("selected",{e:e}),this},getActiveObject:function(){return this._activeObject},_discardActiveObject:function(){this._activeObject&&this._activeObject.set("active",!1),this._activeObject=null},discardActiveObject:function(t){return this._discardActiveObject(),this.renderAll(),this.fire("selection:cleared",{e:t}),this},_setActiveGroup:function(t){this._activeGroup=t,t&&t.set("active",!0)},setActiveGroup:function(t,e){return this._setActiveGroup(t),t&&(this.fire("object:selected",{target:t,e:e}),t.fire("selected",{e:e})),this},getActiveGroup:function(){return this._activeGroup},_discardActiveGroup:function(){var t=this.getActiveGroup();t&&t.destroy(),this.setActiveGroup(null)},discardActiveGroup:function(t){return this._discardActiveGroup(),this.fire("selection:cleared",{e:t}),this},deactivateAll:function(){for(var t=this.getObjects(),e=0,i=t.length;i>e;e++)t[e].set("active",!1);return this._discardActiveGroup(),this._discardActiveObject(),this},deactivateAllWithDispatch:function(t){var e=this.getActiveGroup()||this.getActiveObject();return e&&this.fire("before:selection:cleared",{target:e,e:t}),this.deactivateAll(),e&&this.fire("selection:cleared",{e:t}),this},dispose:function(){this.callSuper("dispose");var t=this.wrapperEl;return this.removeListeners(),t.removeChild(this.upperCanvasEl),t.removeChild(this.lowerCanvasEl),delete this.upperCanvasEl,t.parentNode&&t.parentNode.replaceChild(this.lowerCanvasEl,this.wrapperEl),delete this.wrapperEl,this},drawControls:function(t){var e=this.getActiveGroup();e?e._renderControls(t):this._drawObjectsControls(t)},_drawObjectsControls:function(t){for(var e=0,i=this._objects.length;i>e;++e)this._objects[e]&&this._objects[e].active&&(this._objects[e]._renderControls(t),this.lastRenderedObjectWithControlsAboveOverlay=this._objects[e])}});for(var o in fabric.StaticCanvas)"prototype"!==o&&(fabric.Canvas[o]=fabric.StaticCanvas[o]);fabric.isTouchSupported&&(fabric.Canvas.prototype._setCursorFromEvent=function(){}),fabric.Element=fabric.Canvas}(),function(){var t={mt:0,tr:1,mr:2,br:3,mb:4,bl:5,ml:6,tl:7},e=fabric.util.addListener,i=fabric.util.removeListener;fabric.util.object.extend(fabric.Canvas.prototype,{cursorMap:["n-resize","ne-resize","e-resize","se-resize","s-resize","sw-resize","w-resize","nw-resize"],_initEventListeners:function(){this._bindEvents(),e(fabric.window,"resize",this._onResize),e(this.upperCanvasEl,"mousedown",this._onMouseDown),e(this.upperCanvasEl,"mousemove",this._onMouseMove),e(this.upperCanvasEl,"mousewheel",this._onMouseWheel),e(this.upperCanvasEl,"touchstart",this._onMouseDown),e(this.upperCanvasEl,"touchmove",this._onMouseMove),"undefined"!=typeof eventjs&&"add"in eventjs&&(eventjs.add(this.upperCanvasEl,"gesture",this._onGesture),eventjs.add(this.upperCanvasEl,"drag",this._onDrag),eventjs.add(this.upperCanvasEl,"orientation",this._onOrientationChange),eventjs.add(this.upperCanvasEl,"shake",this._onShake),eventjs.add(this.upperCanvasEl,"longpress",this._onLongPress))},_bindEvents:function(){this._onMouseDown=this._onMouseDown.bind(this),this._onMouseMove=this._onMouseMove.bind(this),this._onMouseUp=this._onMouseUp.bind(this),this._onResize=this._onResize.bind(this),this._onGesture=this._onGesture.bind(this),this._onDrag=this._onDrag.bind(this),this._onShake=this._onShake.bind(this),this._onLongPress=this._onLongPress.bind(this),this._onOrientationChange=this._onOrientationChange.bind(this),this._onMouseWheel=this._onMouseWheel.bind(this)},removeListeners:function(){i(fabric.window,"resize",this._onResize),i(this.upperCanvasEl,"mousedown",this._onMouseDown),i(this.upperCanvasEl,"mousemove",this._onMouseMove),i(this.upperCanvasEl,"mousewheel",this._onMouseWheel),i(this.upperCanvasEl,"touchstart",this._onMouseDown),i(this.upperCanvasEl,"touchmove",this._onMouseMove),"undefined"!=typeof eventjs&&"remove"in eventjs&&(eventjs.remove(this.upperCanvasEl,"gesture",this._onGesture),eventjs.remove(this.upperCanvasEl,"drag",this._onDrag),eventjs.remove(this.upperCanvasEl,"orientation",this._onOrientationChange),eventjs.remove(this.upperCanvasEl,"shake",this._onShake),eventjs.remove(this.upperCanvasEl,"longpress",this._onLongPress))},_onGesture:function(t,e){this.__onTransformGesture&&this.__onTransformGesture(t,e)},_onDrag:function(t,e){this.__onDrag&&this.__onDrag(t,e)},_onMouseWheel:function(t,e){this.__onMouseWheel&&this.__onMouseWheel(t,e)},_onOrientationChange:function(t,e){this.__onOrientationChange&&this.__onOrientationChange(t,e)},_onShake:function(t,e){this.__onShake&&this.__onShake(t,e)},_onLongPress:function(t,e){this.__onLongPress&&this.__onLongPress(t,e)},_onMouseDown:function(t){this.__onMouseDown(t),e(fabric.document,"touchend",this._onMouseUp),e(fabric.document,"touchmove",this._onMouseMove),i(this.upperCanvasEl,"mousemove",this._onMouseMove),i(this.upperCanvasEl,"touchmove",this._onMouseMove),"touchstart"===t.type?i(this.upperCanvasEl,"mousedown",this._onMouseDown):(e(fabric.document,"mouseup",this._onMouseUp),e(fabric.document,"mousemove",this._onMouseMove))},_onMouseUp:function(t){if(this.__onMouseUp(t),i(fabric.document,"mouseup",this._onMouseUp),i(fabric.document,"touchend",this._onMouseUp),i(fabric.document,"mousemove",this._onMouseMove),i(fabric.document,"touchmove",this._onMouseMove),e(this.upperCanvasEl,"mousemove",this._onMouseMove),e(this.upperCanvasEl,"touchmove",this._onMouseMove),"touchend"===t.type){var r=this;setTimeout(function(){e(r.upperCanvasEl,"mousedown",r._onMouseDown)},400)}},_onMouseMove:function(t){!this.allowTouchScrolling&&t.preventDefault&&t.preventDefault(),this.__onMouseMove(t)},_onResize:function(){this.calcOffset()},_shouldRender:function(t,e){var i=this.getActiveGroup()||this.getActiveObject();return!!(t&&(t.isMoving||t!==i)||!t&&i||!t&&!i&&!this._groupSelector||e&&this._previousPointer&&this.selection&&(e.x!==this._previousPointer.x||e.y!==this._previousPointer.y))},__onMouseUp:function(t){var e;if(this.isDrawingMode&&this._isCurrentlyDrawing)return void this._onMouseUpInDrawingMode(t);this._currentTransform?(this._finalizeCurrentTransform(),e=this._currentTransform.target):e=this.findTarget(t,!0);var i=this._shouldRender(e,this.getPointer(t));this._maybeGroupObjects(t),e&&(e.isMoving=!1),i&&this.renderAll(),this._handleCursorAndEvent(t,e)},_handleCursorAndEvent:function(t,e){this._setCursorFromEvent(t,e);var i=this;setTimeout(function(){i._setCursorFromEvent(t,e)},50),this.fire("mouse:up",{target:e,e:t}),e&&e.fire("mouseup",{e:t})},_finalizeCurrentTransform:function(){var t=this._currentTransform,e=t.target;e._scaling&&(e._scaling=!1),e.setCoords(),this._restoreOriginXY(e),(t.actionPerformed||this.stateful&&e.hasStateChanged())&&(this.fire("object:modified",{target:e}),e.fire("modified"))},_restoreOriginXY:function(t){if(this._previousOriginX&&this._previousOriginY){var e=t.translateToOriginPoint(t.getCenterPoint(),this._previousOriginX,this._previousOriginY); + +t.originX=this._previousOriginX,t.originY=this._previousOriginY,t.left=e.x,t.top=e.y,this._previousOriginX=null,this._previousOriginY=null}},_onMouseDownInDrawingMode:function(t){this._isCurrentlyDrawing=!0,this.discardActiveObject(t).renderAll(),this.clipTo&&fabric.util.clipContext(this,this.contextTop);var e=fabric.util.invertTransform(this.viewportTransform),i=fabric.util.transformPoint(this.getPointer(t,!0),e);this.freeDrawingBrush.onMouseDown(i),this.fire("mouse:down",{e:t});var r=this.findTarget(t);"undefined"!=typeof r&&r.fire("mousedown",{e:t,target:r})},_onMouseMoveInDrawingMode:function(t){if(this._isCurrentlyDrawing){var e=fabric.util.invertTransform(this.viewportTransform),i=fabric.util.transformPoint(this.getPointer(t,!0),e);this.freeDrawingBrush.onMouseMove(i)}this.setCursor(this.freeDrawingCursor),this.fire("mouse:move",{e:t});var r=this.findTarget(t);"undefined"!=typeof r&&r.fire("mousemove",{e:t,target:r})},_onMouseUpInDrawingMode:function(t){this._isCurrentlyDrawing=!1,this.clipTo&&this.contextTop.restore(),this.freeDrawingBrush.onMouseUp(),this.fire("mouse:up",{e:t});var e=this.findTarget(t);"undefined"!=typeof e&&e.fire("mouseup",{e:t,target:e})},__onMouseDown:function(t){var e="which"in t?1===t.which:0===t.button;if(e||fabric.isTouchSupported){if(this.isDrawingMode)return void this._onMouseDownInDrawingMode(t);if(!this._currentTransform){var i=this.findTarget(t),r=this.getPointer(t,!0);this._previousPointer=r;var n=this._shouldRender(i,r),s=this._shouldGroup(t,i);this._shouldClearSelection(t,i)?this._clearSelection(t,i,r):s&&(this._handleGrouping(t,i),i=this.getActiveGroup()),i&&i.selectable&&(i.__corner||!s)&&(this._beforeTransform(t,i),this._setupCurrentTransform(t,i)),n&&this.renderAll(),this.fire("mouse:down",{target:i,e:t}),i&&i.fire("mousedown",{e:t})}}},_beforeTransform:function(t,e){this.stateful&&e.saveState(),e._findTargetCorner(this.getPointer(t))&&this.onBeforeScaleRotate(e),e!==this.getActiveGroup()&&e!==this.getActiveObject()&&(this.deactivateAll(),this.setActiveObject(e,t))},_clearSelection:function(t,e,i){this.deactivateAllWithDispatch(t),e&&e.selectable?this.setActiveObject(e,t):this.selection&&(this._groupSelector={ex:i.x,ey:i.y,top:0,left:0})},_setOriginToCenter:function(t){this._previousOriginX=this._currentTransform.target.originX,this._previousOriginY=this._currentTransform.target.originY;var e=t.getCenterPoint();t.originX="center",t.originY="center",t.left=e.x,t.top=e.y,this._currentTransform.left=t.left,this._currentTransform.top=t.top},_setCenterToOrigin:function(t){var e=t.translateToOriginPoint(t.getCenterPoint(),this._previousOriginX,this._previousOriginY);t.originX=this._previousOriginX,t.originY=this._previousOriginY,t.left=e.x,t.top=e.y,this._previousOriginX=null,this._previousOriginY=null},__onMouseMove:function(t){var e,i;if(this.isDrawingMode)return void this._onMouseMoveInDrawingMode(t);if(!("undefined"!=typeof t.touches&&t.touches.length>1)){var r=this._groupSelector;r?(i=this.getPointer(t,!0),r.left=i.x-r.ex,r.top=i.y-r.ey,this.renderTop()):this._currentTransform?this._transformObject(t):(e=this.findTarget(t),!e||e&&!e.selectable?this.setCursor(this.defaultCursor):this._setCursorFromEvent(t,e)),this.fire("mouse:move",{target:e,e:t}),e&&e.fire("mousemove",{e:t})}},_transformObject:function(t){var e=this.getPointer(t),i=this._currentTransform;i.reset=!1,i.target.isMoving=!0,this._beforeScaleTransform(t,i),this._performTransformAction(t,i,e),this.renderAll()},_performTransformAction:function(t,e,i){var r=i.x,n=i.y,s=e.target,o=e.action,a=!1;"rotate"===o?(a=this._rotateObject(r,n))&&this._fire("rotating",s,t):"scale"===o?(a=this._onScale(t,e,r,n))&&this._fire("scaling",s,t):"scaleX"===o?(a=this._scaleObject(r,n,"x"))&&this._fire("scaling",s,t):"scaleY"===o?(a=this._scaleObject(r,n,"y"))&&this._fire("scaling",s,t):"skewX"===o?(a=this._skewObject(r,n,"x"))&&this._fire("skewing",s,t):"skewY"===o?(a=this._skewObject(r,n,"y"))&&this._fire("skewing",s,t):((a=this._translateObject(r,n))&&this._fire("moving",s,t),this.setCursor(this.moveCursor)),e.actionPerformed=a},_fire:function(t,e,i){this.fire("object:"+t,{target:e,e:i}),e.fire(t,{e:i})},_beforeScaleTransform:function(t,e){if("scale"===e.action||"scaleX"===e.action||"scaleY"===e.action){var i=this._shouldCenterTransform(e.target);(i&&("center"!==e.originX||"center"!==e.originY)||!i&&"center"===e.originX&&"center"===e.originY)&&(this._resetCurrentTransform(),e.reset=!0)}},_onScale:function(t,e,i,r){return!t.shiftKey&&!this.uniScaleTransform||e.target.get("lockUniScaling")?(e.reset||"scale"!==e.currentAction||this._resetCurrentTransform(),e.currentAction="scaleEqually",this._scaleObject(i,r,"equally")):(e.currentAction="scale",this._scaleObject(i,r))},_setCursorFromEvent:function(t,e){if(!e||!e.selectable)return this.setCursor(this.defaultCursor),!1;var i=this.getActiveGroup(),r=e._findTargetCorner&&(!i||!i.contains(e))&&e._findTargetCorner(this.getPointer(t,!0));return r?this._setCornerCursor(r,e,t):this.setCursor(e.hoverCursor||this.hoverCursor),!0},_setCornerCursor:function(e,i,r){if(e in t)this.setCursor(this._getRotatedCornerCursor(e,i,r));else{if("mtr"!==e||!i.hasRotatingPoint)return this.setCursor(this.defaultCursor),!1;this.setCursor(this.rotationCursor)}},_getRotatedCornerCursor:function(e,i,r){var n=Math.round(i.getAngle()%360/45);return 0>n&&(n+=8),n+=t[e],r.shiftKey&&t[e]%2===0&&(n+=2),n%=8,this.cursorMap[n]}})}(),function(){var t=Math.min,e=Math.max;fabric.util.object.extend(fabric.Canvas.prototype,{_shouldGroup:function(t,e){var i=this.getActiveObject();return t.shiftKey&&e&&e.selectable&&(this.getActiveGroup()||i&&i!==e)&&this.selection},_handleGrouping:function(t,e){(e!==this.getActiveGroup()||(e=this.findTarget(t,!0),e&&!e.isType("group")))&&(this.getActiveGroup()?this._updateActiveGroup(e,t):this._createActiveGroup(e,t),this._activeGroup&&this._activeGroup.saveCoords())},_updateActiveGroup:function(t,e){var i=this.getActiveGroup();if(i.contains(t)){if(i.removeWithUpdate(t),t.set("active",!1),1===i.size())return this.discardActiveGroup(e),void this.setActiveObject(i.item(0))}else i.addWithUpdate(t);this.fire("selection:created",{target:i,e:e}),i.set("active",!0)},_createActiveGroup:function(t,e){if(this._activeObject&&t!==this._activeObject){var i=this._createGroup(t);i.addWithUpdate(),this.setActiveGroup(i),this._activeObject=null,this.fire("selection:created",{target:i,e:e})}t.set("active",!0)},_createGroup:function(t){var e=this.getObjects(),i=e.indexOf(this._activeObject)1&&(e=new fabric.Group(e.reverse(),{canvas:this}),e.addWithUpdate(),this.setActiveGroup(e,t),e.saveCoords(),this.fire("selection:created",{target:e}),this.renderAll())},_collectObjects:function(){for(var i,r=[],n=this._groupSelector.ex,s=this._groupSelector.ey,o=n+this._groupSelector.left,a=s+this._groupSelector.top,h=new fabric.Point(t(n,o),t(s,a)),c=new fabric.Point(e(n,o),e(s,a)),l=n===o&&s===a,u=this._objects.length;u--&&(i=this._objects[u],!(i&&i.selectable&&i.visible&&(i.intersectsWithRect(h,c)||i.isContainedWithinRect(h,c)||i.containsPoint(h)||i.containsPoint(c))&&(i.set("active",!0),r.push(i),l))););return r},_maybeGroupObjects:function(t){this.selection&&this._groupSelector&&this._groupSelectedObjects(t);var e=this.getActiveGroup();e&&(e.setObjectsCoords().setCoords(),e.isMoving=!1,this.setCursor(this.defaultCursor)),this._groupSelector=null,this._currentTransform=null}})}(),fabric.util.object.extend(fabric.StaticCanvas.prototype,{toDataURL:function(t){t||(t={});var e=t.format||"png",i=t.quality||1,r=t.multiplier||1,n={left:t.left,top:t.top,width:t.width,height:t.height};return this._isRetinaScaling()&&(r*=fabric.devicePixelRatio),1!==r?this.__toDataURLWithMultiplier(e,i,n,r):this.__toDataURL(e,i,n)},__toDataURL:function(t,e,i){this.renderAll();var r=this.contextContainer.canvas,n=this.__getCroppedCanvas(r,i);"jpg"===t&&(t="jpeg");var s=fabric.StaticCanvas.supports("toDataURLWithQuality")?(n||r).toDataURL("image/"+t,e):(n||r).toDataURL("image/"+t);return n&&(n=null),s},__getCroppedCanvas:function(t,e){var i,r,n="left"in e||"top"in e||"width"in e||"height"in e;return n&&(i=fabric.util.createCanvasElement(),r=i.getContext("2d"),i.width=e.width||this.width,i.height=e.height||this.height,r.drawImage(t,-e.left||0,-e.top||0)),i},__toDataURLWithMultiplier:function(t,e,i,r){var n=this.getWidth(),s=this.getHeight(),o=n*r,a=s*r,h=this.getActiveObject(),c=this.getActiveGroup(),l=this.contextContainer;r>1&&this.setDimensions({width:o,height:a}),l.save(),l.scale(r/fabric.devicePixelRatio,r/fabric.devicePixelRatio),i.left&&(i.left*=r),i.top&&(i.top*=r),i.width?i.width*=r:1>r&&(i.width=o),i.height?i.height*=r:1>r&&(i.height=a),c?this._tempRemoveBordersControlsFromGroup(c):h&&this.deactivateAll&&this.deactivateAll();var u=this.__toDataURL(t,e,i);return this.width=n,this.height=s,this.setDimensions({width:n,height:s}),c?this._restoreBordersControlsOnGroup(c):h&&this.setActiveObject&&this.setActiveObject(h),this.contextTop&&this.clearContext(this.contextTop),this.renderAll(),u},toDataURLWithMultiplier:function(t,e,i){return this.toDataURL({format:t,multiplier:e,quality:i})},_tempRemoveBordersControlsFromGroup:function(t){t.origHasControls=t.hasControls,t.origBorderColor=t.borderColor,t.hasControls=!0,t.borderColor="rgba(0,0,0,0)",t.forEachObject(function(t){t.origBorderColor=t.borderColor,t.borderColor="rgba(0,0,0,0)"})},_restoreBordersControlsOnGroup:function(t){t.hideControls=t.origHideControls,t.borderColor=t.origBorderColor,t.forEachObject(function(t){t.borderColor=t.origBorderColor,delete t.origBorderColor})}}),fabric.util.object.extend(fabric.StaticCanvas.prototype,{loadFromDatalessJSON:function(t,e,i){return this.loadFromJSON(t,e,i)},loadFromJSON:function(t,e,i){if(t){var r="string"==typeof t?JSON.parse(t):t;this.clear();var n=this;return this._enlivenObjects(r.objects,function(){n._setBgOverlay(r,e)},i),this}},_setBgOverlay:function(t,e){var i=this,r={backgroundColor:!1,overlayColor:!1,backgroundImage:!1,overlayImage:!1};if(!(t.backgroundImage||t.overlayImage||t.background||t.overlay))return void(e&&e());var n=function(){r.backgroundImage&&r.overlayImage&&r.backgroundColor&&r.overlayColor&&(i.renderAll(),e&&e())};this.__setBgOverlay("backgroundImage",t.backgroundImage,r,n),this.__setBgOverlay("overlayImage",t.overlayImage,r,n),this.__setBgOverlay("backgroundColor",t.background,r,n),this.__setBgOverlay("overlayColor",t.overlay,r,n),n()},__setBgOverlay:function(t,e,i,r){var n=this;return e?void("backgroundImage"===t||"overlayImage"===t?fabric.Image.fromObject(e,function(e){n[t]=e,i[t]=!0,r&&r()}):this["set"+fabric.util.string.capitalize(t,!0)](e,function(){i[t]=!0,r&&r()})):void(i[t]=!0)},_enlivenObjects:function(t,e,i){var r=this;if(!t||0===t.length)return void(e&&e());var n=this.renderOnAddRemove;this.renderOnAddRemove=!1,fabric.util.enlivenObjects(t,function(t){t.forEach(function(t,e){r.insertAt(t,e,!0)}),r.renderOnAddRemove=n,e&&e()},null,i)},_toDataURL:function(t,e){this.clone(function(i){e(i.toDataURL(t))})},_toDataURLWithMultiplier:function(t,e,i){this.clone(function(r){i(r.toDataURLWithMultiplier(t,e))})},clone:function(t,e){var i=JSON.stringify(this.toJSON(e));this.cloneWithoutData(function(e){e.loadFromJSON(i,function(){t&&t(e)})})},cloneWithoutData:function(t){var e=fabric.document.createElement("canvas");e.width=this.getWidth(),e.height=this.getHeight();var i=new fabric.Canvas(e);i.clipTo=this.clipTo,this.backgroundImage?(i.setBackgroundImage(this.backgroundImage.src,function(){i.renderAll(),t&&t(i)}),i.backgroundImageOpacity=this.backgroundImageOpacity,i.backgroundImageStretch=this.backgroundImageStretch):t&&t(i)}}),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend,r=e.util.toFixed,n=e.util.string.capitalize,s=e.util.degreesToRadians,o=e.StaticCanvas.supports("setLineDash");e.Object||(e.Object=e.util.createClass({type:"object",originX:"left",originY:"top",top:0,left:0,width:0,height:0,scaleX:1,scaleY:1,flipX:!1,flipY:!1,opacity:1,angle:0,skewX:0,skewY:0,cornerSize:12,transparentCorners:!0,hoverCursor:null,padding:0,borderColor:"rgba(102,153,255,0.75)",cornerColor:"rgba(102,153,255,0.5)",centeredScaling:!1,centeredRotation:!0,fill:"rgb(0,0,0)",fillRule:"nonzero",globalCompositeOperation:"source-over",backgroundColor:"",stroke:null,strokeWidth:1,strokeDashArray:null,strokeLineCap:"butt",strokeLineJoin:"miter",strokeMiterLimit:10,shadow:null,borderOpacityWhenMoving:.4,borderScaleFactor:1,transformMatrix:null,minScaleLimit:.01,selectable:!0,evented:!0,visible:!0,hasControls:!0,hasBorders:!0,hasRotatingPoint:!0,rotatingPointOffset:40,perPixelTargetFind:!1,includeDefaultValues:!0,clipTo:null,lockMovementX:!1,lockMovementY:!1,lockRotation:!1,lockScalingX:!1,lockScalingY:!1,lockUniScaling:!1,lockSkewingX:!1,lockSkewingY:!1,lockScalingFlip:!1,stateProperties:"top left width height scaleX scaleY flipX flipY originX originY transformMatrix stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit angle opacity fill fillRule globalCompositeOperation shadow clipTo visible backgroundColor alignX alignY meetOrSlice skewX skewY".split(" "),initialize:function(t){t&&this.setOptions(t)},_initGradient:function(t){!t.fill||!t.fill.colorStops||t.fill instanceof e.Gradient||this.set("fill",new e.Gradient(t.fill)),!t.stroke||!t.stroke.colorStops||t.stroke instanceof e.Gradient||this.set("stroke",new e.Gradient(t.stroke))},_initPattern:function(t){!t.fill||!t.fill.source||t.fill instanceof e.Pattern||this.set("fill",new e.Pattern(t.fill)),!t.stroke||!t.stroke.source||t.stroke instanceof e.Pattern||this.set("stroke",new e.Pattern(t.stroke))},_initClipping:function(t){if(t.clipTo&&"string"==typeof t.clipTo){var i=e.util.getFunctionBody(t.clipTo);"undefined"!=typeof i&&(this.clipTo=new Function("ctx",i))}},setOptions:function(t){for(var e in t)this.set(e,t[e]);this._initGradient(t),this._initPattern(t),this._initClipping(t)},transform:function(t,e){this.group&&this.canvas.preserveObjectStacking&&this.group===this.canvas._activeGroup&&this.group.transform(t);var i=e?this._getLeftTopCoords():this.getCenterPoint();t.translate(i.x,i.y),t.rotate(s(this.angle)),t.scale(this.scaleX*(this.flipX?-1:1),this.scaleY*(this.flipY?-1:1)),t.transform(1,0,Math.tan(s(this.skewX)),1,0,0),t.transform(1,Math.tan(s(this.skewY)),0,1,0,0)},toObject:function(t){var i=e.Object.NUM_FRACTION_DIGITS,n={type:this.type,originX:this.originX,originY:this.originY,left:r(this.left,i),top:r(this.top,i),width:r(this.width,i),height:r(this.height,i),fill:this.fill&&this.fill.toObject?this.fill.toObject():this.fill,stroke:this.stroke&&this.stroke.toObject?this.stroke.toObject():this.stroke,strokeWidth:r(this.strokeWidth,i),strokeDashArray:this.strokeDashArray?this.strokeDashArray.concat():this.strokeDashArray,strokeLineCap:this.strokeLineCap,strokeLineJoin:this.strokeLineJoin,strokeMiterLimit:r(this.strokeMiterLimit,i),scaleX:r(this.scaleX,i),scaleY:r(this.scaleY,i),angle:r(this.getAngle(),i),flipX:this.flipX,flipY:this.flipY,opacity:r(this.opacity,i),shadow:this.shadow&&this.shadow.toObject?this.shadow.toObject():this.shadow,visible:this.visible,clipTo:this.clipTo&&String(this.clipTo),backgroundColor:this.backgroundColor,fillRule:this.fillRule,globalCompositeOperation:this.globalCompositeOperation,transformMatrix:this.transformMatrix?this.transformMatrix.concat():this.transformMatrix,skewX:r(this.skewX,i),skewY:r(this.skewY,i)};return this.includeDefaultValues||(n=this._removeDefaultValues(n)),e.util.populateWithProperties(this,n,t),n},toDatalessObject:function(t){return this.toObject(t)},_removeDefaultValues:function(t){var i=e.util.getKlass(t.type).prototype,r=i.stateProperties;return r.forEach(function(e){t[e]===i[e]&&delete t[e];var r="[object Array]"===Object.prototype.toString.call(t[e])&&"[object Array]"===Object.prototype.toString.call(i[e]);r&&0===t[e].length&&0===i[e].length&&delete t[e]}),t},toString:function(){return"#"},get:function(t){return this[t]},_setObject:function(t){for(var e in t)this._set(e,t[e])},set:function(t,e){return"object"==typeof t?this._setObject(t):"function"==typeof e&&"clipTo"!==t?this._set(t,e(this.get(t))):this._set(t,e),this},_set:function(t,i){var n="scaleX"===t||"scaleY"===t;return n&&(i=this._constrainScale(i)),"scaleX"===t&&0>i?(this.flipX=!this.flipX,i*=-1):"scaleY"===t&&0>i?(this.flipY=!this.flipY,i*=-1):"width"===t||"height"===t?this.minScaleLimit=r(Math.min(.1,1/Math.max(this.width,this.height)),2):"shadow"!==t||!i||i instanceof e.Shadow||(i=new e.Shadow(i)),this[t]=i,this},setOnGroup:function(){},toggle:function(t){var e=this.get(t);return"boolean"==typeof e&&this.set(t,!e),this},setSourcePath:function(t){return this.sourcePath=t,this},getViewportTransform:function(){return this.canvas&&this.canvas.viewportTransform?this.canvas.viewportTransform:[1,0,0,1,0,0]},render:function(t,i){0===this.width&&0===this.height||!this.visible||(t.save(),this._setupCompositeOperation(t),i||this.transform(t),this._setStrokeStyles(t),this._setFillStyles(t),this.transformMatrix&&t.transform.apply(t,this.transformMatrix),this._setOpacity(t),this._setShadow(t),this.clipTo&&e.util.clipContext(this,t),this._render(t,i),this.clipTo&&t.restore(),t.restore())},_setOpacity:function(t){this.group&&this.group._setOpacity(t),t.globalAlpha*=this.opacity},_setStrokeStyles:function(t){this.stroke&&(t.lineWidth=this.strokeWidth,t.lineCap=this.strokeLineCap,t.lineJoin=this.strokeLineJoin,t.miterLimit=this.strokeMiterLimit,t.strokeStyle=this.stroke.toLive?this.stroke.toLive(t,this):this.stroke)},_setFillStyles:function(t){this.fill&&(t.fillStyle=this.fill.toLive?this.fill.toLive(t,this):this.fill)},_renderControls:function(t,i){if(!(!this.active||i||this.group&&this.group!==this.canvas.getActiveGroup())){var r,n=this.getViewportTransform(),o=this.calcTransformMatrix();o=e.util.multiplyTransformMatrices(n,o),r=e.util.qrDecompose(o),t.save(),t.translate(r.translateX,r.translateY),this.group&&this.group===this.canvas.getActiveGroup()?(t.rotate(s(r.angle)),this.drawBordersInGroup(t,r)):(t.rotate(s(this.angle)),this.drawBorders(t)),this.drawControls(t),t.restore()}},_setShadow:function(t){if(this.shadow){var i=this.canvas&&this.canvas.viewportTransform[0]||1,r=this.canvas&&this.canvas.viewportTransform[3]||1;this.canvas&&this.canvas._isRetinaScaling()&&(i*=e.devicePixelRatio,r*=e.devicePixelRatio),t.shadowColor=this.shadow.color,t.shadowBlur=this.shadow.blur*(i+r)*(this.scaleX+this.scaleY)/4,t.shadowOffsetX=this.shadow.offsetX*i*this.scaleX,t.shadowOffsetY=this.shadow.offsetY*r*this.scaleY}},_removeShadow:function(t){this.shadow&&(t.shadowColor="",t.shadowBlur=t.shadowOffsetX=t.shadowOffsetY=0)},_renderFill:function(t){if(this.fill){if(t.save(),this.fill.gradientTransform){var e=this.fill.gradientTransform;t.transform.apply(t,e)}this.fill.toLive&&t.translate(-this.width/2+this.fill.offsetX||0,-this.height/2+this.fill.offsetY||0),"evenodd"===this.fillRule?t.fill("evenodd"):t.fill(),t.restore()}},_renderStroke:function(t){if(this.stroke&&0!==this.strokeWidth){if(this.shadow&&!this.shadow.affectStroke&&this._removeShadow(t),t.save(),this.strokeDashArray)1&this.strokeDashArray.length&&this.strokeDashArray.push.apply(this.strokeDashArray,this.strokeDashArray),o?(t.setLineDash(this.strokeDashArray),this._stroke&&this._stroke(t)):this._renderDashedStroke&&this._renderDashedStroke(t),t.stroke();else{if(this.stroke.gradientTransform){var e=this.stroke.gradientTransform;t.transform.apply(t,e)}this._stroke?this._stroke(t):t.stroke()}t.restore()}},clone:function(t,i){return this.constructor.fromObject?this.constructor.fromObject(this.toObject(i),t):new e.Object(this.toObject(i))},cloneAsImage:function(t){var i=this.toDataURL();return e.util.loadImage(i,function(i){t&&t(new e.Image(i))}),this},toDataURL:function(t){t||(t={});var i=e.util.createCanvasElement(),r=this.getBoundingRect();i.width=r.width,i.height=r.height,e.util.wrapElement(i,"div");var n=new e.StaticCanvas(i);"jpg"===t.format&&(t.format="jpeg"),"jpeg"===t.format&&(n.backgroundColor="#fff");var s={active:this.get("active"),left:this.getLeft(),top:this.getTop()};this.set("active",!1),this.setPositionByOrigin(new e.Point(i.width/2,i.height/2),"center","center");var o=this.canvas;n.add(this);var a=n.toDataURL(t);return this.set(s).setCoords(),this.canvas=o,n.dispose(),n=null,a},isType:function(t){return this.type===t},complexity:function(){return 0},toJSON:function(t){return this.toObject(t)},setGradient:function(t,i){i||(i={});var r={colorStops:[]};r.type=i.type||(i.r1||i.r2?"radial":"linear"),r.coords={x1:i.x1,y1:i.y1,x2:i.x2,y2:i.y2},(i.r1||i.r2)&&(r.coords.r1=i.r1,r.coords.r2=i.r2),i.gradientTransform&&(r.gradientTransform=i.gradientTransform);for(var n in i.colorStops){var s=new e.Color(i.colorStops[n]);r.colorStops.push({offset:n,color:s.toRgb(),opacity:s.getAlpha()})}return this.set(t,e.Gradient.forObject(this,r))},setPatternFill:function(t){return this.set("fill",new e.Pattern(t))},setShadow:function(t){return this.set("shadow",t?new e.Shadow(t):null)},setColor:function(t){return this.set("fill",t),this},setAngle:function(t){var e=("center"!==this.originX||"center"!==this.originY)&&this.centeredRotation;return e&&this._setOriginToCenter(),this.set("angle",t),e&&this._resetOrigin(),this},centerH:function(){return this.canvas.centerObjectH(this),this},centerV:function(){return this.canvas.centerObjectV(this),this},center:function(){return this.canvas.centerObject(this),this},remove:function(){return this.canvas.remove(this),this},getLocalPointer:function(t,i){i=i||this.canvas.getPointer(t);var r=new e.Point(i.x,i.y),n=this._getLeftTopCoords();return this.angle&&(r=e.util.rotatePoint(r,n,e.util.degreesToRadians(-this.angle))),{x:r.x-n.x,y:r.y-n.y}},_setupCompositeOperation:function(t){this.globalCompositeOperation&&(t.globalCompositeOperation=this.globalCompositeOperation)}}),e.util.createAccessors(e.Object),e.Object.prototype.rotate=e.Object.prototype.setAngle,i(e.Object.prototype,e.Observable),e.Object.NUM_FRACTION_DIGITS=2,e.Object.__uid=0)}("undefined"!=typeof exports?exports:this),function(){var t=fabric.util.degreesToRadians,e={left:-.5,center:0,right:.5},i={top:-.5,center:0,bottom:.5};fabric.util.object.extend(fabric.Object.prototype,{translateToGivenOrigin:function(t,r,n,s,o){var a,h=t.x,c=t.y,l=e[s]-e[r],u=i[o]-i[n];return(l||u)&&(a=this._getTransformedDimensions(),h=t.x+l*a.x,c=t.y+u*a.y),new fabric.Point(h,c)},translateToCenterPoint:function(e,i,r){var n=this.translateToGivenOrigin(e,i,r,"center","center");return this.angle?fabric.util.rotatePoint(n,e,t(this.angle)):n},translateToOriginPoint:function(e,i,r){var n=this.translateToGivenOrigin(e,"center","center",i,r);return this.angle?fabric.util.rotatePoint(n,e,t(this.angle)):n},getCenterPoint:function(){var t=new fabric.Point(this.left,this.top);return this.translateToCenterPoint(t,this.originX,this.originY)},getPointByOrigin:function(t,e){var i=this.getCenterPoint();return this.translateToOriginPoint(i,t,e)},toLocalPoint:function(e,i,r){var n,s,o=this.getCenterPoint();return n=i&&r?this.translateToGivenOrigin(o,"center","center",i,r):new fabric.Point(this.left,this.top),s=new fabric.Point(e.x,e.y),this.angle&&(s=fabric.util.rotatePoint(s,o,-t(this.angle))),s.subtractEquals(n)},setPositionByOrigin:function(t,e,i){var r=this.translateToCenterPoint(t,e,i),n=this.translateToOriginPoint(r,this.originX,this.originY);this.set("left",n.x),this.set("top",n.y)},adjustPosition:function(i){var r=t(this.angle),n=this.getWidth(),s=Math.cos(r)*n,o=Math.sin(r)*n;this.left+=s*(e[i]-e[this.originX]),this.top+=o*(e[i]-e[this.originX]),this.setCoords(),this.originX=i},_setOriginToCenter:function(){this._originalOriginX=this.originX,this._originalOriginY=this.originY;var t=this.getCenterPoint();this.originX="center",this.originY="center",this.left=t.x,this.top=t.y},_resetOrigin:function(){var t=this.translateToOriginPoint(this.getCenterPoint(),this._originalOriginX,this._originalOriginY);this.originX=this._originalOriginX,this.originY=this._originalOriginY,this.left=t.x,this.top=t.y,this._originalOriginX=null,this._originalOriginY=null},_getLeftTopCoords:function(){return this.translateToOriginPoint(this.getCenterPoint(),"left","top")}})}(),function(){function t(t){return[new fabric.Point(t.tl.x,t.tl.y),new fabric.Point(t.tr.x,t.tr.y),new fabric.Point(t.br.x,t.br.y),new fabric.Point(t.bl.x,t.bl.y)]}var e=fabric.util.degreesToRadians,i=fabric.util.multiplyTransformMatrices;fabric.util.object.extend(fabric.Object.prototype,{oCoords:null,intersectsWithRect:function(e,i){var r=t(this.oCoords),n=fabric.Intersection.intersectPolygonRectangle(r,e,i);return"Intersection"===n.status},intersectsWithObject:function(e){var i=fabric.Intersection.intersectPolygonPolygon(t(this.oCoords),t(e.oCoords));return"Intersection"===i.status},isContainedWithinObject:function(t){var e=t.getBoundingRect(),i=new fabric.Point(e.left,e.top),r=new fabric.Point(e.left+e.width,e.top+e.height);return this.isContainedWithinRect(i,r)},isContainedWithinRect:function(t,e){var i=this.getBoundingRect();return i.left>=t.x&&i.left+i.width<=e.x&&i.top>=t.y&&i.top+i.height<=e.y},containsPoint:function(t){var e=this._getImageLines(this.oCoords),i=this._findCrossPoints(t,e);return 0!==i&&i%2===1},_getImageLines:function(t){return{topline:{o:t.tl,d:t.tr},rightline:{o:t.tr,d:t.br},bottomline:{o:t.br,d:t.bl},leftline:{o:t.bl,d:t.tl}}},_findCrossPoints:function(t,e){var i,r,n,s,o,a,h,c=0;for(var l in e)if(h=e[l],!(h.o.y=t.y&&h.d.y>=t.y||(h.o.x===h.d.x&&h.o.x>=t.x?(o=h.o.x,a=t.y):(i=0,r=(h.d.y-h.o.y)/(h.d.x-h.o.x),n=t.y-i*t.x,s=h.o.y-r*h.o.x,o=-(n-s)/(i-r),a=n+i*o),o>=t.x&&(c+=1),2!==c)))break;return c},getBoundingRectWidth:function(){return this.getBoundingRect().width},getBoundingRectHeight:function(){return this.getBoundingRect().height},getBoundingRect:function(){return this.oCoords||this.setCoords(),fabric.util.makeBoundingBoxFromPoints([this.oCoords.tl,this.oCoords.tr,this.oCoords.br,this.oCoords.bl])},getWidth:function(){return this._getTransformedDimensions().x},getHeight:function(){return this._getTransformedDimensions().y},_constrainScale:function(t){return Math.abs(t)t?-this.minScaleLimit:this.minScaleLimit:t},scale:function(t){return t=this._constrainScale(t),0>t&&(this.flipX=!this.flipX,this.flipY=!this.flipY,t*=-1),this.scaleX=t,this.scaleY=t,this.setCoords(),this},scaleToWidth:function(t){var e=this.getBoundingRect().width/this.getWidth();return this.scale(t/this.width/e)},scaleToHeight:function(t){var e=this.getBoundingRect().height/this.getHeight();return this.scale(t/this.height/e)},setCoords:function(){var t=e(this.angle),i=this.getViewportTransform(),r=this._calculateCurrentDimensions(),n=r.x,s=r.y;0>n&&(n=Math.abs(n));var o=Math.sin(t),a=Math.cos(t),h=n>0?Math.atan(s/n):0,c=n/Math.cos(h)/2,l=Math.cos(h+t)*c,u=Math.sin(h+t)*c,f=fabric.util.transformPoint(this.getCenterPoint(),i),d=new fabric.Point(f.x-l,f.y-u),g=new fabric.Point(d.x+n*a,d.y+n*o),p=new fabric.Point(d.x-s*o,d.y+s*a),v=new fabric.Point(f.x+l,f.y+u),m=new fabric.Point((d.x+p.x)/2,(d.y+p.y)/2),b=new fabric.Point((g.x+d.x)/2,(g.y+d.y)/2),y=new fabric.Point((v.x+g.x)/2,(v.y+g.y)/2),_=new fabric.Point((v.x+p.x)/2,(v.y+p.y)/2),x=new fabric.Point(b.x+o*this.rotatingPointOffset,b.y-a*this.rotatingPointOffset);return this.oCoords={tl:d,tr:g,br:v,bl:p,ml:m,mt:b,mr:y,mb:_,mtr:x},this._setCornerCoords&&this._setCornerCoords(),this},_calcRotateMatrix:function(){if(this.angle){var t=e(this.angle),i=Math.cos(t),r=Math.sin(t);return[i,r,-r,i,0,0]}return[1,0,0,1,0,0]},calcTransformMatrix:function(){var t=this.getCenterPoint(),e=[1,0,0,1,t.x,t.y],r=this._calcRotateMatrix(),n=this._calcDimensionsTransformMatrix(this.skewX,this.skewY,!0),s=this.group?this.group.calcTransformMatrix():[1,0,0,1,0,0];return s=i(s,e),s=i(s,r),s=i(s,n)},_calcDimensionsTransformMatrix:function(t,r,n){var s=[1,0,Math.tan(e(t)),1],o=[1,Math.tan(e(r)),0,1],a=this.scaleX*(n&&this.flipX?-1:1),h=this.scaleY*(n&&this.flipY?-1:1),c=[a,0,0,h],l=i(c,s,!0);return i(l,o,!0)}})}(),fabric.util.object.extend(fabric.Object.prototype,{sendToBack:function(){return this.group?fabric.StaticCanvas.prototype.sendToBack.call(this.group,this):this.canvas.sendToBack(this),this},bringToFront:function(){return this.group?fabric.StaticCanvas.prototype.bringToFront.call(this.group,this):this.canvas.bringToFront(this),this},sendBackwards:function(t){return this.group?fabric.StaticCanvas.prototype.sendBackwards.call(this.group,this,t):this.canvas.sendBackwards(this,t),this},bringForward:function(t){return this.group?fabric.StaticCanvas.prototype.bringForward.call(this.group,this,t):this.canvas.bringForward(this,t),this},moveTo:function(t){return this.group?fabric.StaticCanvas.prototype.moveTo.call(this.group,this,t):this.canvas.moveTo(this,t),this}}),fabric.util.object.extend(fabric.Object.prototype,{getSvgStyles:function(t){var e=this.fill?this.fill.toLive?"url(#SVGID_"+this.fill.id+")":this.fill:"none",i=this.fillRule,r=this.stroke?this.stroke.toLive?"url(#SVGID_"+this.stroke.id+")":this.stroke:"none",n=this.strokeWidth?this.strokeWidth:"0",s=this.strokeDashArray?this.strokeDashArray.join(" "):"none",o=this.strokeLineCap?this.strokeLineCap:"butt",a=this.strokeLineJoin?this.strokeLineJoin:"miter",h=this.strokeMiterLimit?this.strokeMiterLimit:"4",c="undefined"!=typeof this.opacity?this.opacity:"1",l=this.visible?"":" visibility: hidden;",u=t?"":this.getSvgFilter();return["stroke: ",r,"; ","stroke-width: ",n,"; ","stroke-dasharray: ",s,"; ","stroke-linecap: ",o,"; ","stroke-linejoin: ",a,"; ","stroke-miterlimit: ",h,"; ","fill: ",e,"; ","fill-rule: ",i,"; ","opacity: ",c,";",u,l].join("")},getSvgFilter:function(){return this.shadow?"filter: url(#SVGID_"+this.shadow.id+");":""},getSvgTransform:function(){if(this.group&&"path-group"===this.group.type)return"";var t=fabric.util.toFixed,e=this.getAngle(),i=this.getSkewX()%360,r=this.getSkewY()%360,n=this.getCenterPoint(),s=fabric.Object.NUM_FRACTION_DIGITS,o="path-group"===this.type?"":"translate("+t(n.x,s)+" "+t(n.y,s)+")",a=0!==e?" rotate("+t(e,s)+")":"",h=1===this.scaleX&&1===this.scaleY?"":" scale("+t(this.scaleX,s)+" "+t(this.scaleY,s)+")",c=0!==i?" skewX("+t(i,s)+")":"",l=0!==r?" skewY("+t(r,s)+")":"",u="path-group"===this.type?this.width:0,f=this.flipX?" matrix(-1 0 0 1 "+u+" 0) ":"",d="path-group"===this.type?this.height:0,g=this.flipY?" matrix(1 0 0 -1 0 "+d+")":"";return[o,a,h,f,g,c,l].join("")},getSvgTransformMatrix:function(){return this.transformMatrix?" matrix("+this.transformMatrix.join(" ")+") ":""},_createBaseSVGMarkup:function(){var t=[];return this.fill&&this.fill.toLive&&t.push(this.fill.toSVG(this,!1)),this.stroke&&this.stroke.toLive&&t.push(this.stroke.toSVG(this,!1)),this.shadow&&t.push(this.shadow.toSVG(this)),t}}),fabric.util.object.extend(fabric.Object.prototype,{hasStateChanged:function(){return this.stateProperties.some(function(t){return this.get(t)!==this.originalState[t]},this)},saveState:function(t){return this.stateProperties.forEach(function(t){this.originalState[t]=this.get(t)},this),t&&t.stateProperties&&t.stateProperties.forEach(function(t){this.originalState[t]=this.get(t)},this),this},setupState:function(){return this.originalState={},this.saveState(),this}}),function(){var t=fabric.util.degreesToRadians,e=function(){return"undefined"!=typeof G_vmlCanvasManager};fabric.util.object.extend(fabric.Object.prototype,{_controlsVisibility:null,_findTargetCorner:function(t){if(!this.hasControls||!this.active)return!1;var e,i,r=t.x,n=t.y;this.__corner=0;for(var s in this.oCoords)if(this.isControlVisible(s)&&("mtr"!==s||this.hasRotatingPoint)&&(!this.get("lockUniScaling")||"mt"!==s&&"mr"!==s&&"mb"!==s&&"ml"!==s)&&(i=this._getImageLines(this.oCoords[s].corner),e=this._findCrossPoints({ +x:r,y:n},i),0!==e&&e%2===1))return this.__corner=s,s;return!1},_setCornerCoords:function(){var e,i,r=this.oCoords,n=t(45-this.angle),s=.707106*this.cornerSize,o=s*Math.cos(n),a=s*Math.sin(n);for(var h in r)e=r[h].x,i=r[h].y,r[h].corner={tl:{x:e-a,y:i-o},tr:{x:e+o,y:i-a},bl:{x:e-o,y:i+a},br:{x:e+a,y:i+o}}},_getNonTransformedDimensions:function(){var t=this.strokeWidth,e=this.width,i=this.height,r=!0,n=!0;return"line"===this.type&&"butt"===this.strokeLineCap&&(n=e,r=i),n&&(i+=0>i?-t:t),r&&(e+=0>e?-t:t),{x:e,y:i}},_getTransformedDimensions:function(t,e){"undefined"==typeof t&&(t=this.skewX),"undefined"==typeof e&&(e=this.skewY);var i,r,n=this._getNonTransformedDimensions(),s=n.x/2,o=n.y/2,a=[{x:-s,y:-o},{x:s,y:-o},{x:-s,y:o},{x:s,y:o}],h=this._calcDimensionsTransformMatrix(t,e,!1);for(i=0;ir;r++)t=i[r],e=r!==n-1,this._animate(t,arguments[0][t],arguments[1],e)}else this._animate.apply(this,arguments);return this},_animate:function(t,e,i,r){var n,s=this;e=e.toString(),i=i?fabric.util.object.clone(i):{},~t.indexOf(".")&&(n=t.split("."));var o=n?this.get(n[0])[n[1]]:this.get(t);"from"in i||(i.from=o),e=~e.indexOf("=")?o+parseFloat(e.replace("=","")):parseFloat(e),fabric.util.animate({startValue:i.from,endValue:e,byValue:i.by,easing:i.easing,duration:i.duration,abort:i.abort&&function(){return i.abort.call(s)},onChange:function(e){n?s[n[0]][n[1]]=e:s.set(t,e),r||i.onChange&&i.onChange()},onComplete:function(){r||(s.setCoords(),i.onComplete&&i.onComplete())}})}}),function(t){"use strict";function e(t,e){var i=t.origin,r=t.axis1,n=t.axis2,s=t.dimension,o=e.nearest,a=e.center,h=e.farthest;return function(){switch(this.get(i)){case o:return Math.min(this.get(r),this.get(n));case a:return Math.min(this.get(r),this.get(n))+.5*this.get(s);case h:return Math.max(this.get(r),this.get(n))}}}var i=t.fabric||(t.fabric={}),r=i.util.object.extend,n={x1:1,x2:1,y1:1,y2:1},s=i.StaticCanvas.supports("setLineDash");return i.Line?void i.warn("fabric.Line is already defined"):(i.Line=i.util.createClass(i.Object,{type:"line",x1:0,y1:0,x2:0,y2:0,initialize:function(t,e){e=e||{},t||(t=[0,0,0,0]),this.callSuper("initialize",e),this.set("x1",t[0]),this.set("y1",t[1]),this.set("x2",t[2]),this.set("y2",t[3]),this._setWidthHeight(e)},_setWidthHeight:function(t){t||(t={}),this.width=Math.abs(this.x2-this.x1),this.height=Math.abs(this.y2-this.y1),this.left="left"in t?t.left:this._getLeftToOriginX(),this.top="top"in t?t.top:this._getTopToOriginY()},_set:function(t,e){return this.callSuper("_set",t,e),"undefined"!=typeof n[t]&&this._setWidthHeight(),this},_getLeftToOriginX:e({origin:"originX",axis1:"x1",axis2:"x2",dimension:"width"},{nearest:"left",center:"center",farthest:"right"}),_getTopToOriginY:e({origin:"originY",axis1:"y1",axis2:"y2",dimension:"height"},{nearest:"top",center:"center",farthest:"bottom"}),_render:function(t,e){if(t.beginPath(),e){var i=this.getCenterPoint();t.translate(i.x-this.strokeWidth/2,i.y-this.strokeWidth/2)}if(!this.strokeDashArray||this.strokeDashArray&&s){var r=this.calcLinePoints();t.moveTo(r.x1,r.y1),t.lineTo(r.x2,r.y2)}t.lineWidth=this.strokeWidth;var n=t.strokeStyle;t.strokeStyle=this.stroke||t.fillStyle,this.stroke&&this._renderStroke(t),t.strokeStyle=n},_renderDashedStroke:function(t){var e=this.calcLinePoints();t.beginPath(),i.util.drawDashedLine(t,e.x1,e.y1,e.x2,e.y2,this.strokeDashArray),t.closePath()},toObject:function(t){return r(this.callSuper("toObject",t),this.calcLinePoints())},calcLinePoints:function(){var t=this.x1<=this.x2?-1:1,e=this.y1<=this.y2?-1:1,i=t*this.width*.5,r=e*this.height*.5,n=t*this.width*-.5,s=e*this.height*-.5;return{x1:i,x2:n,y1:r,y2:s}},toSVG:function(t){var e=this._createBaseSVGMarkup(),i={x1:this.x1,x2:this.x2,y1:this.y1,y2:this.y2};return this.group&&"path-group"===this.group.type||(i=this.calcLinePoints()),e.push("\n'),t?t(e.join("")):e.join("")},complexity:function(){return 1}}),i.Line.ATTRIBUTE_NAMES=i.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" ")),i.Line.fromElement=function(t,e){var n=i.parseAttributes(t,i.Line.ATTRIBUTE_NAMES),s=[n.x1||0,n.y1||0,n.x2||0,n.y2||0];return new i.Line(s,r(n,e))},void(i.Line.fromObject=function(t){var e=[t.x1,t.y1,t.x2,t.y2];return new i.Line(e,t)}))}("undefined"!=typeof exports?exports:this),function(t){"use strict";function e(t){return"radius"in t&&t.radius>=0}var i=t.fabric||(t.fabric={}),r=Math.PI,n=i.util.object.extend;return i.Circle?void i.warn("fabric.Circle is already defined."):(i.Circle=i.util.createClass(i.Object,{type:"circle",radius:0,startAngle:0,endAngle:2*r,initialize:function(t){t=t||{},this.callSuper("initialize",t),this.set("radius",t.radius||0),this.startAngle=t.startAngle||this.startAngle,this.endAngle=t.endAngle||this.endAngle},_set:function(t,e){return this.callSuper("_set",t,e),"radius"===t&&this.setRadius(e),this},toObject:function(t){return n(this.callSuper("toObject",t),{radius:this.get("radius"),startAngle:this.startAngle,endAngle:this.endAngle})},toSVG:function(t){var e=this._createBaseSVGMarkup(),i=0,n=0,s=(this.endAngle-this.startAngle)%(2*r);if(0===s)this.group&&"path-group"===this.group.type&&(i=this.left+this.radius,n=this.top+this.radius),e.push("\n');else{var o=Math.cos(this.startAngle)*this.radius,a=Math.sin(this.startAngle)*this.radius,h=Math.cos(this.endAngle)*this.radius,c=Math.sin(this.endAngle)*this.radius,l=s>r?"1":"0";e.push('\n')}return t?t(e.join("")):e.join("")},_render:function(t,e){t.beginPath(),t.arc(e?this.left+this.radius:0,e?this.top+this.radius:0,this.radius,this.startAngle,this.endAngle,!1),this._renderFill(t),this._renderStroke(t)},getRadiusX:function(){return this.get("radius")*this.get("scaleX")},getRadiusY:function(){return this.get("radius")*this.get("scaleY")},setRadius:function(t){return this.radius=t,this.set("width",2*t).set("height",2*t)},complexity:function(){return 1}}),i.Circle.ATTRIBUTE_NAMES=i.SHARED_ATTRIBUTES.concat("cx cy r".split(" ")),i.Circle.fromElement=function(t,r){r||(r={});var s=i.parseAttributes(t,i.Circle.ATTRIBUTE_NAMES);if(!e(s))throw new Error("value of `r` attribute is required and can not be negative");s.left=s.left||0,s.top=s.top||0;var o=new i.Circle(n(s,r));return o.left-=o.radius,o.top-=o.radius,o},void(i.Circle.fromObject=function(t){return new i.Circle(t)}))}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={});return e.Triangle?void e.warn("fabric.Triangle is already defined"):(e.Triangle=e.util.createClass(e.Object,{type:"triangle",initialize:function(t){t=t||{},this.callSuper("initialize",t),this.set("width",t.width||100).set("height",t.height||100)},_render:function(t){var e=this.width/2,i=this.height/2;t.beginPath(),t.moveTo(-e,i),t.lineTo(0,-i),t.lineTo(e,i),t.closePath(),this._renderFill(t),this._renderStroke(t)},_renderDashedStroke:function(t){var i=this.width/2,r=this.height/2;t.beginPath(),e.util.drawDashedLine(t,-i,r,0,-r,this.strokeDashArray),e.util.drawDashedLine(t,0,-r,i,r,this.strokeDashArray),e.util.drawDashedLine(t,i,r,-i,r,this.strokeDashArray),t.closePath()},toSVG:function(t){var e=this._createBaseSVGMarkup(),i=this.width/2,r=this.height/2,n=[-i+" "+r,"0 "+-r,i+" "+r].join(",");return e.push("'),t?t(e.join("")):e.join("")},complexity:function(){return 1}}),void(e.Triangle.fromObject=function(t){return new e.Triangle(t)}))}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=2*Math.PI,r=e.util.object.extend;return e.Ellipse?void e.warn("fabric.Ellipse is already defined."):(e.Ellipse=e.util.createClass(e.Object,{type:"ellipse",rx:0,ry:0,initialize:function(t){t=t||{},this.callSuper("initialize",t),this.set("rx",t.rx||0),this.set("ry",t.ry||0)},_set:function(t,e){switch(this.callSuper("_set",t,e),t){case"rx":this.rx=e,this.set("width",2*e);break;case"ry":this.ry=e,this.set("height",2*e)}return this},getRx:function(){return this.get("rx")*this.get("scaleX")},getRy:function(){return this.get("ry")*this.get("scaleY")},toObject:function(t){return r(this.callSuper("toObject",t),{rx:this.get("rx"),ry:this.get("ry")})},toSVG:function(t){var e=this._createBaseSVGMarkup(),i=0,r=0;return this.group&&"path-group"===this.group.type&&(i=this.left+this.rx,r=this.top+this.ry),e.push("\n'),t?t(e.join("")):e.join("")},_render:function(t,e){t.beginPath(),t.save(),t.transform(1,0,0,this.ry/this.rx,0,0),t.arc(e?this.left+this.rx:0,e?(this.top+this.ry)*this.rx/this.ry:0,this.rx,0,i,!1),t.restore(),this._renderFill(t),this._renderStroke(t)},complexity:function(){return 1}}),e.Ellipse.ATTRIBUTE_NAMES=e.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" ")),e.Ellipse.fromElement=function(t,i){i||(i={});var n=e.parseAttributes(t,e.Ellipse.ATTRIBUTE_NAMES);n.left=n.left||0,n.top=n.top||0;var s=new e.Ellipse(r(n,i));return s.top-=s.ry,s.left-=s.rx,s},void(e.Ellipse.fromObject=function(t){return new e.Ellipse(t)}))}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend;if(e.Rect)return void e.warn("fabric.Rect is already defined");var r=e.Object.prototype.stateProperties.concat();r.push("rx","ry","x","y"),e.Rect=e.util.createClass(e.Object,{stateProperties:r,type:"rect",rx:0,ry:0,strokeDashArray:null,initialize:function(t){t=t||{},this.callSuper("initialize",t),this._initRxRy()},_initRxRy:function(){this.rx&&!this.ry?this.ry=this.rx:this.ry&&!this.rx&&(this.rx=this.ry)},_render:function(t,e){if(1===this.width&&1===this.height)return void t.fillRect(-.5,-.5,1,1);var i=this.rx?Math.min(this.rx,this.width/2):0,r=this.ry?Math.min(this.ry,this.height/2):0,n=this.width,s=this.height,o=e?this.left:-this.width/2,a=e?this.top:-this.height/2,h=0!==i||0!==r,c=.4477152502;t.beginPath(),t.moveTo(o+i,a),t.lineTo(o+n-i,a),h&&t.bezierCurveTo(o+n-c*i,a,o+n,a+c*r,o+n,a+r),t.lineTo(o+n,a+s-r),h&&t.bezierCurveTo(o+n,a+s-c*r,o+n-c*i,a+s,o+n-i,a+s),t.lineTo(o+i,a+s),h&&t.bezierCurveTo(o+c*i,a+s,o,a+s-c*r,o,a+s-r),t.lineTo(o,a+r),h&&t.bezierCurveTo(o,a+c*r,o+c*i,a,o+i,a),t.closePath(),this._renderFill(t),this._renderStroke(t)},_renderDashedStroke:function(t){var i=-this.width/2,r=-this.height/2,n=this.width,s=this.height;t.beginPath(),e.util.drawDashedLine(t,i,r,i+n,r,this.strokeDashArray),e.util.drawDashedLine(t,i+n,r,i+n,r+s,this.strokeDashArray),e.util.drawDashedLine(t,i+n,r+s,i,r+s,this.strokeDashArray),e.util.drawDashedLine(t,i,r+s,i,r,this.strokeDashArray),t.closePath()},toObject:function(t){var e=i(this.callSuper("toObject",t),{rx:this.get("rx")||0,ry:this.get("ry")||0});return this.includeDefaultValues||this._removeDefaultValues(e),e},toSVG:function(t){var e=this._createBaseSVGMarkup(),i=this.left,r=this.top;return this.group&&"path-group"===this.group.type||(i=-this.width/2,r=-this.height/2),e.push("\n'),t?t(e.join("")):e.join("")},complexity:function(){return 1}}),e.Rect.ATTRIBUTE_NAMES=e.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" ")),e.Rect.fromElement=function(t,r){if(!t)return null;r=r||{};var n=e.parseAttributes(t,e.Rect.ATTRIBUTE_NAMES);n.left=n.left||0,n.top=n.top||0;var s=new e.Rect(i(r?e.util.object.clone(r):{},n));return s.visible=s.width>0&&s.height>0,s},e.Rect.fromObject=function(t){return new e.Rect(t)}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={});return e.Polyline?void e.warn("fabric.Polyline is already defined"):(e.Polyline=e.util.createClass(e.Object,{type:"polyline",points:null,minX:0,minY:0,initialize:function(t,i){return e.Polygon.prototype.initialize.call(this,t,i)},_calcDimensions:function(){return e.Polygon.prototype._calcDimensions.call(this)},_applyPointOffset:function(){return e.Polygon.prototype._applyPointOffset.call(this)},toObject:function(t){return e.Polygon.prototype.toObject.call(this,t)},toSVG:function(t){return e.Polygon.prototype.toSVG.call(this,t)},_render:function(t,i){e.Polygon.prototype.commonRender.call(this,t,i)&&(this._renderFill(t),this._renderStroke(t))},_renderDashedStroke:function(t){var i,r;t.beginPath();for(var n=0,s=this.points.length;s>n;n++)i=this.points[n],r=this.points[n+1]||i,e.util.drawDashedLine(t,i.x,i.y,r.x,r.y,this.strokeDashArray)},complexity:function(){return this.get("points").length}}),e.Polyline.ATTRIBUTE_NAMES=e.SHARED_ATTRIBUTES.concat(),e.Polyline.fromElement=function(t,i){if(!t)return null;i||(i={});var r=e.parsePointsAttribute(t.getAttribute("points")),n=e.parseAttributes(t,e.Polyline.ATTRIBUTE_NAMES);return new e.Polyline(r,e.util.object.extend(n,i))},void(e.Polyline.fromObject=function(t){var i=t.points;return new e.Polyline(i,t,!0)}))}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend,r=e.util.array.min,n=e.util.array.max,s=e.util.toFixed;return e.Polygon?void e.warn("fabric.Polygon is already defined"):(e.Polygon=e.util.createClass(e.Object,{type:"polygon",points:null,minX:0,minY:0,initialize:function(t,e){e=e||{},this.points=t||[],this.callSuper("initialize",e),this._calcDimensions(),"top"in e||(this.top=this.minY),"left"in e||(this.left=this.minX),this.pathOffset={x:this.minX+this.width/2,y:this.minY+this.height/2}},_calcDimensions:function(){var t=this.points,e=r(t,"x"),i=r(t,"y"),s=n(t,"x"),o=n(t,"y");this.width=s-e||0,this.height=o-i||0,this.minX=e||0,this.minY=i||0},toObject:function(t){return i(this.callSuper("toObject",t),{points:this.points.concat()})},toSVG:function(t){for(var e,i=[],r=this._createBaseSVGMarkup(),n=0,o=this.points.length;o>n;n++)i.push(s(this.points[n].x,2),",",s(this.points[n].y,2)," ");return this.group&&"path-group"===this.group.type||(e=" translate("+-this.pathOffset.x+", "+-this.pathOffset.y+") "),r.push("<",this.type," ",'points="',i.join(""),'" style="',this.getSvgStyles(),'" transform="',this.getSvgTransform(),e," ",this.getSvgTransformMatrix(),'"/>\n'),t?t(r.join("")):r.join("")},_render:function(t,e){this.commonRender(t,e)&&(this._renderFill(t),(this.stroke||this.strokeDashArray)&&(t.closePath(),this._renderStroke(t)))},commonRender:function(t,e){var i,r=this.points.length;if(!r||isNaN(this.points[r-1].y))return!1;e||t.translate(-this.pathOffset.x,-this.pathOffset.y),t.beginPath(),t.moveTo(this.points[0].x,this.points[0].y);for(var n=0;r>n;n++)i=this.points[n],t.lineTo(i.x,i.y);return!0},_renderDashedStroke:function(t){e.Polyline.prototype._renderDashedStroke.call(this,t),t.closePath()},complexity:function(){return this.points.length}}),e.Polygon.ATTRIBUTE_NAMES=e.SHARED_ATTRIBUTES.concat(),e.Polygon.fromElement=function(t,r){if(!t)return null;r||(r={});var n=e.parsePointsAttribute(t.getAttribute("points")),s=e.parseAttributes(t,e.Polygon.ATTRIBUTE_NAMES);return new e.Polygon(n,i(s,r))},void(e.Polygon.fromObject=function(t){return new e.Polygon(t.points,t,!0)}))}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.array.min,r=e.util.array.max,n=e.util.object.extend,s=Object.prototype.toString,o=e.util.drawArc,a={m:2,l:2,h:1,v:1,c:6,s:4,q:4,t:2,a:7},h={m:"l",M:"L"};return e.Path?void e.warn("fabric.Path is already defined"):(e.Path=e.util.createClass(e.Object,{type:"path",path:null,minX:0,minY:0,initialize:function(t,e){e=e||{},this.setOptions(e),t||(t=[]);var i="[object Array]"===s.call(t);this.path=i?t:t.match&&t.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi),this.path&&(i||(this.path=this._parsePath()),this._setPositionDimensions(e),e.sourcePath&&this.setSourcePath(e.sourcePath))},_setPositionDimensions:function(t){var e=this._parseDimensions();this.minX=e.left,this.minY=e.top,this.width=e.width,this.height=e.height,"undefined"==typeof t.left&&(this.left=e.left+("center"===this.originX?this.width/2:"right"===this.originX?this.width:0)),"undefined"==typeof t.top&&(this.top=e.top+("center"===this.originY?this.height/2:"bottom"===this.originY?this.height:0)),this.pathOffset=this.pathOffset||{x:this.minX+this.width/2,y:this.minY+this.height/2}},_render:function(t){var e,i,r,n=null,s=0,a=0,h=0,c=0,l=0,u=0,f=-this.pathOffset.x,d=-this.pathOffset.y;this.group&&"path-group"===this.group.type&&(f=0,d=0),t.beginPath();for(var g=0,p=this.path.length;p>g;++g){switch(e=this.path[g],e[0]){case"l":h+=e[1],c+=e[2],t.lineTo(h+f,c+d);break;case"L":h=e[1],c=e[2],t.lineTo(h+f,c+d);break;case"h":h+=e[1],t.lineTo(h+f,c+d);break;case"H":h=e[1],t.lineTo(h+f,c+d);break;case"v":c+=e[1],t.lineTo(h+f,c+d);break;case"V":c=e[1],t.lineTo(h+f,c+d);break;case"m":h+=e[1],c+=e[2],s=h,a=c,t.moveTo(h+f,c+d);break;case"M":h=e[1],c=e[2],s=h,a=c,t.moveTo(h+f,c+d);break;case"c":i=h+e[5],r=c+e[6],l=h+e[3],u=c+e[4],t.bezierCurveTo(h+e[1]+f,c+e[2]+d,l+f,u+d,i+f,r+d),h=i,c=r;break;case"C":h=e[5],c=e[6],l=e[3],u=e[4],t.bezierCurveTo(e[1]+f,e[2]+d,l+f,u+d,h+f,c+d);break;case"s":i=h+e[3],r=c+e[4],null===n[0].match(/[CcSs]/)?(l=h,u=c):(l=2*h-l,u=2*c-u),t.bezierCurveTo(l+f,u+d,h+e[1]+f,c+e[2]+d,i+f,r+d),l=h+e[1],u=c+e[2],h=i,c=r;break;case"S":i=e[3],r=e[4],null===n[0].match(/[CcSs]/)?(l=h,u=c):(l=2*h-l,u=2*c-u),t.bezierCurveTo(l+f,u+d,e[1]+f,e[2]+d,i+f,r+d),h=i,c=r,l=e[1],u=e[2];break;case"q":i=h+e[3],r=c+e[4],l=h+e[1],u=c+e[2],t.quadraticCurveTo(l+f,u+d,i+f,r+d),h=i,c=r;break;case"Q":i=e[3],r=e[4],t.quadraticCurveTo(e[1]+f,e[2]+d,i+f,r+d),h=i,c=r,l=e[1],u=e[2];break;case"t":i=h+e[1],r=c+e[2],null===n[0].match(/[QqTt]/)?(l=h,u=c):(l=2*h-l,u=2*c-u),t.quadraticCurveTo(l+f,u+d,i+f,r+d),h=i,c=r;break;case"T":i=e[1],r=e[2],null===n[0].match(/[QqTt]/)?(l=h,u=c):(l=2*h-l,u=2*c-u),t.quadraticCurveTo(l+f,u+d,i+f,r+d),h=i,c=r;break;case"a":o(t,h+f,c+d,[e[1],e[2],e[3],e[4],e[5],e[6]+h+f,e[7]+c+d]),h+=e[6],c+=e[7];break;case"A":o(t,h+f,c+d,[e[1],e[2],e[3],e[4],e[5],e[6]+f,e[7]+d]),h=e[6],c=e[7];break;case"z":case"Z":h=s,c=a,t.closePath()}n=e}this._renderFill(t),this._renderStroke(t)},toString:function(){return"#"},toObject:function(t){var e=n(this.callSuper("toObject",t),{path:this.path.map(function(t){return t.slice()}),pathOffset:this.pathOffset});return this.sourcePath&&(e.sourcePath=this.sourcePath),this.transformMatrix&&(e.transformMatrix=this.transformMatrix),e},toDatalessObject:function(t){var e=this.toObject(t);return this.sourcePath&&(e.path=this.sourcePath),delete e.sourcePath,e},toSVG:function(t){for(var e=[],i=this._createBaseSVGMarkup(),r="",n=0,s=this.path.length;s>n;n++)e.push(this.path[n].join(" "));var o=e.join(" ");return this.group&&"path-group"===this.group.type||(r=" translate("+-this.pathOffset.x+", "+-this.pathOffset.y+") "),i.push("\n"),t?t(i.join("")):i.join("")},complexity:function(){return this.path.length},_parsePath:function(){for(var t,e,i,r,n,s=[],o=[],c=/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/gi,l=0,u=this.path.length;u>l;l++){for(t=this.path[l],r=t.slice(1).trim(),o.length=0;i=c.exec(r);)o.push(i[0]);n=[t.charAt(0)];for(var f=0,d=o.length;d>f;f++)e=parseFloat(o[f]),isNaN(e)||n.push(e);var g=n[0],p=a[g.toLowerCase()],v=h[g]||g;if(n.length-1>p)for(var m=1,b=n.length;b>m;m+=p)s.push([g].concat(n.slice(m,m+p))),g=v;else s.push(n)}return s},_parseDimensions:function(){for(var t,n,s,o,a=[],h=[],c=null,l=0,u=0,f=0,d=0,g=0,p=0,v=0,m=this.path.length;m>v;++v){switch(t=this.path[v],t[0]){case"l":f+=t[1],d+=t[2],o=[];break;case"L":f=t[1],d=t[2],o=[];break;case"h":f+=t[1],o=[];break;case"H":f=t[1],o=[];break;case"v":d+=t[1],o=[];break;case"V":d=t[1],o=[];break;case"m":f+=t[1],d+=t[2],l=f,u=d,o=[];break;case"M":f=t[1],d=t[2],l=f,u=d,o=[];break;case"c":n=f+t[5],s=d+t[6],g=f+t[3],p=d+t[4],o=e.util.getBoundsOfCurve(f,d,f+t[1],d+t[2],g,p,n,s),f=n,d=s;break;case"C":f=t[5],d=t[6],g=t[3],p=t[4],o=e.util.getBoundsOfCurve(f,d,t[1],t[2],g,p,f,d);break;case"s":n=f+t[3],s=d+t[4],null===c[0].match(/[CcSs]/)?(g=f,p=d):(g=2*f-g,p=2*d-p),o=e.util.getBoundsOfCurve(f,d,g,p,f+t[1],d+t[2],n,s),g=f+t[1],p=d+t[2],f=n,d=s;break;case"S":n=t[3],s=t[4],null===c[0].match(/[CcSs]/)?(g=f,p=d):(g=2*f-g,p=2*d-p),o=e.util.getBoundsOfCurve(f,d,g,p,t[1],t[2],n,s),f=n,d=s,g=t[1],p=t[2];break;case"q":n=f+t[3],s=d+t[4],g=f+t[1],p=d+t[2],o=e.util.getBoundsOfCurve(f,d,g,p,g,p,n,s),f=n,d=s;break;case"Q":g=t[1],p=t[2],o=e.util.getBoundsOfCurve(f,d,g,p,g,p,t[3],t[4]),f=t[3],d=t[4];break;case"t":n=f+t[1],s=d+t[2],null===c[0].match(/[QqTt]/)?(g=f,p=d):(g=2*f-g,p=2*d-p),o=e.util.getBoundsOfCurve(f,d,g,p,g,p,n,s),f=n,d=s;break;case"T":n=t[1],s=t[2],null===c[0].match(/[QqTt]/)?(g=f,p=d):(g=2*f-g,p=2*d-p),o=e.util.getBoundsOfCurve(f,d,g,p,g,p,n,s),f=n,d=s;break;case"a":o=e.util.getBoundsOfArc(f,d,t[1],t[2],t[3],t[4],t[5],t[6]+f,t[7]+d),f+=t[6],d+=t[7];break;case"A":o=e.util.getBoundsOfArc(f,d,t[1],t[2],t[3],t[4],t[5],t[6],t[7]),f=t[6],d=t[7];break;case"z":case"Z":f=l,d=u}c=t,o.forEach(function(t){a.push(t.x),h.push(t.y)}),a.push(f),h.push(d)}var b=i(a)||0,y=i(h)||0,_=r(a)||0,x=r(h)||0,S=_-b,C=x-y,w={left:b,top:y,width:S,height:C};return w}}),e.Path.fromObject=function(t,i){"string"==typeof t.path?e.loadSVGFromURL(t.path,function(r){var n=r[0],s=t.path;delete t.path,e.util.object.extend(n,t),n.setSourcePath(s),i(n)}):i(new e.Path(t.path,t))},e.Path.ATTRIBUTE_NAMES=e.SHARED_ATTRIBUTES.concat(["d"]),e.Path.fromElement=function(t,i,r){var s=e.parseAttributes(t,e.Path.ATTRIBUTE_NAMES);i&&i(new e.Path(s.d,n(s,r)))},void(e.Path.async=!0))}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend,r=e.util.array.invoke,n=e.Object.prototype.toObject;return e.PathGroup?void e.warn("fabric.PathGroup is already defined"):(e.PathGroup=e.util.createClass(e.Path,{type:"path-group",fill:"",initialize:function(t,e){e=e||{},this.paths=t||[];for(var i=this.paths.length;i--;)this.paths[i].group=this;e.toBeParsed&&(this.parseDimensionsFromPaths(e),delete e.toBeParsed),this.setOptions(e),this.setCoords(),e.sourcePath&&this.setSourcePath(e.sourcePath)},parseDimensionsFromPaths:function(t){for(var i,r,n,s,o,a,h=[],c=[],l=this.paths.length;l--;){n=this.paths[l],s=n.height+n.strokeWidth,o=n.width+n.strokeWidth,i=[{x:n.left,y:n.top},{x:n.left+o,y:n.top},{x:n.left,y:n.top+s},{x:n.left+o,y:n.top+s}],a=this.paths[l].transformMatrix;for(var u=0;ui;++i)this.paths[i].render(t,!0);this.clipTo&&t.restore(),t.restore()}},_set:function(t,e){if("fill"===t&&e&&this.isSameColor())for(var i=this.paths.length;i--;)this.paths[i]._set(t,e);return this.callSuper("_set",t,e)},toObject:function(t){var e=i(n.call(this,t),{paths:r(this.getObjects(),"toObject",t)});return this.sourcePath&&(e.sourcePath=this.sourcePath),e},toDatalessObject:function(t){var e=this.toObject(t);return this.sourcePath&&(e.paths=this.sourcePath),e},toSVG:function(t){var e=this.getObjects(),i=this.getPointByOrigin("left","top"),r="translate("+i.x+" "+i.y+")",n=this._createBaseSVGMarkup();n.push("\n");for(var s=0,o=e.length;o>s;s++)n.push(" ",e[s].toSVG(t));return n.push("\n"),t?t(n.join("")):n.join("")},toString:function(){return"#"},isSameColor:function(){var t=this.getObjects()[0].get("fill")||"";return"string"!=typeof t?!1:(t=t.toLowerCase(),this.getObjects().every(function(e){var i=e.get("fill")||"";return"string"==typeof i&&i.toLowerCase()===t}))},complexity:function(){return this.paths.reduce(function(t,e){return t+(e&&e.complexity?e.complexity():0)},0)},getObjects:function(){return this.paths}}),e.PathGroup.fromObject=function(t,i){"string"==typeof t.paths?e.loadSVGFromURL(t.paths,function(r){var n=t.paths;delete t.paths;var s=e.util.groupSVGElements(r,t,n);i(s)}):e.util.enlivenObjects(t.paths,function(r){delete t.paths,i(new e.PathGroup(r,t))})},void(e.PathGroup.async=!0))}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend,r=e.util.array.min,n=e.util.array.max,s=e.util.array.invoke;if(!e.Group){var o={lockMovementX:!0,lockMovementY:!0,lockRotation:!0,lockScalingX:!0,lockScalingY:!0,lockUniScaling:!0};e.Group=e.util.createClass(e.Object,e.Collection,{type:"group",strokeWidth:0,initialize:function(t,e,i){e=e||{},this._objects=[],i&&this.callSuper("initialize",e),this._objects=t||[];for(var r=this._objects.length;r--;)this._objects[r].group=this;this.originalState={},e.originX&&(this.originX=e.originX),e.originY&&(this.originY=e.originY),i?this._updateObjectsCoords(!0):(this._calcBounds(),this._updateObjectsCoords(),this.callSuper("initialize",e)),this.setCoords(),this.saveCoords()},_updateObjectsCoords:function(t){for(var e=this._objects.length;e--;)this._updateObjectCoords(this._objects[e],t)},_updateObjectCoords:function(t,e){if(t.__origHasControls=t.hasControls,t.hasControls=!1,!e){var i=t.getLeft(),r=t.getTop(),n=this.getCenterPoint();t.set({originalLeft:i,originalTop:r,left:i-n.x,top:r-n.y}),t.setCoords()}},toString:function(){return"#"},addWithUpdate:function(t){return this._restoreObjectsState(),e.util.resetObjectTransform(this),t&&(this._objects.push(t),t.group=this,t._set("canvas",this.canvas)),this.forEachObject(this._setObjectActive,this),this._calcBounds(),this._updateObjectsCoords(),this},_setObjectActive:function(t){t.set("active",!0),t.group=this},removeWithUpdate:function(t){return this._restoreObjectsState(),e.util.resetObjectTransform(this),this.forEachObject(this._setObjectActive,this),this.remove(t),this._calcBounds(),this._updateObjectsCoords(),this},_onObjectAdded:function(t){t.group=this,t._set("canvas",this.canvas)},_onObjectRemoved:function(t){delete t.group,t.set("active",!1)},delegatedProperties:{fill:!0,stroke:!0,strokeWidth:!0,fontFamily:!0,fontWeight:!0,fontSize:!0,fontStyle:!0,lineHeight:!0,textDecoration:!0,textAlign:!0,backgroundColor:!0},_set:function(t,e){var i=this._objects.length;if(this.delegatedProperties[t]||"canvas"===t)for(;i--;)this._objects[i].set(t,e);else for(;i--;)this._objects[i].setOnGroup(t,e);this.callSuper("_set",t,e)},toObject:function(t){return i(this.callSuper("toObject",t),{objects:s(this._objects,"toObject",t)})},render:function(t){if(this.visible){t.save(),this.transformMatrix&&t.transform.apply(t,this.transformMatrix),this.transform(t),this._setShadow(t),this.clipTo&&e.util.clipContext(this,t);for(var i=0,r=this._objects.length;r>i;i++)this._renderObject(this._objects[i],t);this.clipTo&&t.restore(),t.restore()}},_renderControls:function(t,e){this.callSuper("_renderControls",t,e);for(var i=0,r=this._objects.length;r>i;i++)this._objects[i]._renderControls(t)},_renderObject:function(t,e){if(t.visible){var i=t.hasRotatingPoint;t.hasRotatingPoint=!1,t.render(e),t.hasRotatingPoint=i}},_restoreObjectsState:function(){return this._objects.forEach(this._restoreObjectState,this), +this},realizeTransform:function(t){var i=t.calcTransformMatrix(),r=e.util.qrDecompose(i),n=new e.Point(r.translateX,r.translateY);return t.scaleX=r.scaleX,t.scaleY=r.scaleY,t.skewX=r.skewX,t.skewY=r.skewY,t.angle=r.angle,t.flipX=!1,t.flipY=!1,t.setPositionByOrigin(n,"center","center"),t},_restoreObjectState:function(t){return this.realizeTransform(t),t.setCoords(),t.hasControls=t.__origHasControls,delete t.__origHasControls,t.set("active",!1),delete t.group,this},destroy:function(){return this._restoreObjectsState()},saveCoords:function(){return this._originalLeft=this.get("left"),this._originalTop=this.get("top"),this},hasMoved:function(){return this._originalLeft!==this.get("left")||this._originalTop!==this.get("top")},setObjectsCoords:function(){return this.forEachObject(function(t){t.setCoords()}),this},_calcBounds:function(t){for(var e,i,r,n=[],s=[],o=["tr","br","bl","tl"],a=0,h=this._objects.length,c=o.length;h>a;++a)for(e=this._objects[a],e.setCoords(),r=0;c>r;r++)i=o[r],n.push(e.oCoords[i].x),s.push(e.oCoords[i].y);this.set(this._getBounds(n,s,t))},_getBounds:function(t,i,s){var o=e.util.invertTransform(this.getViewportTransform()),a=e.util.transformPoint(new e.Point(r(t),r(i)),o),h=e.util.transformPoint(new e.Point(n(t),n(i)),o),c={width:h.x-a.x||0,height:h.y-a.y||0};return s||(c.left=a.x||0,c.top=a.y||0,"center"===this.originX&&(c.left+=c.width/2),"right"===this.originX&&(c.left+=c.width),"center"===this.originY&&(c.top+=c.height/2),"bottom"===this.originY&&(c.top+=c.height)),c},toSVG:function(t){var e=this._createBaseSVGMarkup();e.push('\n');for(var i=0,r=this._objects.length;r>i;i++)e.push(" ",this._objects[i].toSVG(t));return e.push("\n"),t?t(e.join("")):e.join("")},get:function(t){if(t in o){if(this[t])return this[t];for(var e=0,i=this._objects.length;i>e;e++)if(this._objects[e][t])return!0;return!1}return t in this.delegatedProperties?this._objects[0]&&this._objects[0].get(t):this[t]}}),e.Group.fromObject=function(t,i){e.util.enlivenObjects(t.objects,function(r){delete t.objects,i&&i(new e.Group(r,t,!0))})},e.Group.async=!0}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=fabric.util.object.extend;return t.fabric||(t.fabric={}),t.fabric.Image?void fabric.warn("fabric.Image is already defined."):(fabric.Image=fabric.util.createClass(fabric.Object,{type:"image",crossOrigin:"",alignX:"none",alignY:"none",meetOrSlice:"meet",strokeWidth:0,_lastScaleX:1,_lastScaleY:1,initialize:function(t,e){e||(e={}),this.filters=[],this.resizeFilters=[],this.callSuper("initialize",e),this._initElement(t,e)},getElement:function(){return this._element},setElement:function(t,e,i){return this._element=t,this._originalElement=t,this._initConfig(i),0!==this.filters.length?this.applyFilters(e):e&&e(),this},setCrossOrigin:function(t){return this.crossOrigin=t,this._element.crossOrigin=t,this},getOriginalSize:function(){var t=this.getElement();return{width:t.width,height:t.height}},_stroke:function(t){t.save(),this._setStrokeStyles(t),t.beginPath(),t.strokeRect(-this.width/2,-this.height/2,this.width,this.height),t.closePath(),t.restore()},_renderDashedStroke:function(t){var e=-this.width/2,i=-this.height/2,r=this.width,n=this.height;t.save(),this._setStrokeStyles(t),t.beginPath(),fabric.util.drawDashedLine(t,e,i,e+r,i,this.strokeDashArray),fabric.util.drawDashedLine(t,e+r,i,e+r,i+n,this.strokeDashArray),fabric.util.drawDashedLine(t,e+r,i+n,e,i+n,this.strokeDashArray),fabric.util.drawDashedLine(t,e,i+n,e,i,this.strokeDashArray),t.closePath(),t.restore()},toObject:function(t){var i=[],r=this._originalElement;this.filters.forEach(function(t){t&&i.push(t.toObject())});var n=e(this.callSuper("toObject",t),{src:r?r.src||r._src:"",filters:i,crossOrigin:this.crossOrigin,alignX:this.alignX,alignY:this.alignY,meetOrSlice:this.meetOrSlice});return this.resizeFilters.length>0&&(n.resizeFilters=this.resizeFilters.map(function(t){return t&&t.toObject()})),this.includeDefaultValues||this._removeDefaultValues(n),n},toSVG:function(t){var e=this._createBaseSVGMarkup(),i=-this.width/2,r=-this.height/2,n="none";if(this.group&&"path-group"===this.group.type&&(i=this.left,r=this.top),"none"!==this.alignX&&"none"!==this.alignY&&(n="x"+this.alignX+"Y"+this.alignY+" "+this.meetOrSlice),e.push('\n','\n"),this.stroke||this.strokeDashArray){var s=this.fill;this.fill=null,e.push("\n'),this.fill=s}return e.push("\n"),t?t(e.join("")):e.join("")},getSrc:function(){return this.getElement()?this.getElement().src||this.getElement()._src:void 0},setSrc:function(t,e,i){fabric.util.loadImage(t,function(t){return this.setElement(t,e,i)},this,i&&i.crossOrigin)},toString:function(){return'#'},clone:function(t,e){this.constructor.fromObject(this.toObject(e),t)},applyFilters:function(t,e,i,r){if(e=e||this.filters,i=i||this._originalElement){var n=i,s=fabric.util.createCanvasElement(),o=fabric.util.createImage(),a=this;return s.width=n.width,s.height=n.height,s.getContext("2d").drawImage(n,0,0,n.width,n.height),0===e.length?(this._element=i,t&&t(),s):(e.forEach(function(t){t&&t.applyTo(s,t.scaleX||a.scaleX,t.scaleY||a.scaleY),!r&&t&&"Resize"===t.type&&(a.width*=t.scaleX,a.height*=t.scaleY)}),o.width=s.width,o.height=s.height,fabric.isLikelyNode?(o.src=s.toBuffer(void 0,fabric.Image.pngCompression),a._element=o,!r&&(a._filteredEl=o),t&&t()):(o.onload=function(){a._element=o,!r&&(a._filteredEl=o),t&&t(),o.onload=s=n=null},o.src=s.toDataURL("image/png")),s)}},_render:function(t,e){var i,r,n,s=this._findMargins();i=e?this.left:-this.width/2,r=e?this.top:-this.height/2,"slice"===this.meetOrSlice&&(t.beginPath(),t.rect(i,r,this.width,this.height),t.clip()),this.isMoving===!1&&this.resizeFilters.length&&this._needsResize()?(this._lastScaleX=this.scaleX,this._lastScaleY=this.scaleY,n=this.applyFilters(null,this.resizeFilters,this._filteredEl||this._originalElement,!0)):n=this._element,n&&t.drawImage(n,i+s.marginX,r+s.marginY,s.width,s.height),this._renderStroke(t)},_needsResize:function(){return this.scaleX!==this._lastScaleX||this.scaleY!==this._lastScaleY},_findMargins:function(){var t,e,i=this.width,r=this.height,n=0,s=0;return("none"!==this.alignX||"none"!==this.alignY)&&(t=[this.width/this._element.width,this.height/this._element.height],e="meet"===this.meetOrSlice?Math.min.apply(null,t):Math.max.apply(null,t),i=this._element.width*e,r=this._element.height*e,"Mid"===this.alignX&&(n=(this.width-i)/2),"Max"===this.alignX&&(n=this.width-i),"Mid"===this.alignY&&(s=(this.height-r)/2),"Max"===this.alignY&&(s=this.height-r)),{width:i,height:r,marginX:n,marginY:s}},_resetWidthHeight:function(){var t=this.getElement();this.set("width",t.width),this.set("height",t.height)},_initElement:function(t,e){this.setElement(fabric.util.getById(t),null,e),fabric.util.addClass(this.getElement(),fabric.Image.CSS_CANVAS)},_initConfig:function(t){t||(t={}),this.setOptions(t),this._setWidthHeight(t),this._element&&this.crossOrigin&&(this._element.crossOrigin=this.crossOrigin)},_initFilters:function(t,e){t&&t.length?fabric.util.enlivenObjects(t,function(t){e&&e(t)},"fabric.Image.filters"):e&&e()},_setWidthHeight:function(t){this.width="width"in t?t.width:this.getElement()?this.getElement().width||0:0,this.height="height"in t?t.height:this.getElement()?this.getElement().height||0:0},complexity:function(){return 1}}),fabric.Image.CSS_CANVAS="canvas-img",fabric.Image.prototype.getSvgSrc=fabric.Image.prototype.getSrc,fabric.Image.fromObject=function(t,e){fabric.util.loadImage(t.src,function(i){fabric.Image.prototype._initFilters.call(t,t.filters,function(r){t.filters=r||[],fabric.Image.prototype._initFilters.call(t,t.resizeFilters,function(r){t.resizeFilters=r||[];var n=new fabric.Image(i,t);e&&e(n)})})},null,t.crossOrigin)},fabric.Image.fromURL=function(t,e,i){fabric.util.loadImage(t,function(t){e&&e(new fabric.Image(t,i))},null,i&&i.crossOrigin)},fabric.Image.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y width height preserveAspectRatio xlink:href".split(" ")),fabric.Image.fromElement=function(t,i,r){var n,s=fabric.parseAttributes(t,fabric.Image.ATTRIBUTE_NAMES);s.preserveAspectRatio&&(n=fabric.util.parsePreserveAspectRatioAttribute(s.preserveAspectRatio),e(s,n)),fabric.Image.fromURL(s["xlink:href"],i,e(r?fabric.util.object.clone(r):{},s))},fabric.Image.async=!0,void(fabric.Image.pngCompression=1))}("undefined"!=typeof exports?exports:this),fabric.util.object.extend(fabric.Object.prototype,{_getAngleValueForStraighten:function(){var t=this.getAngle()%360;return t>0?90*Math.round((t-1)/90):90*Math.round(t/90)},straighten:function(){return this.setAngle(this._getAngleValueForStraighten()),this},fxStraighten:function(t){t=t||{};var e=function(){},i=t.onComplete||e,r=t.onChange||e,n=this;return fabric.util.animate({startValue:this.get("angle"),endValue:this._getAngleValueForStraighten(),duration:this.FX_DURATION,onChange:function(t){n.setAngle(t),r()},onComplete:function(){n.setCoords(),i()},onStart:function(){n.set("active",!1)}}),this}}),fabric.util.object.extend(fabric.StaticCanvas.prototype,{straightenObject:function(t){return t.straighten(),this.renderAll(),this},fxStraightenObject:function(t){return t.fxStraighten({onChange:this.renderAll.bind(this)}),this}}),fabric.Image.filters=fabric.Image.filters||{},fabric.Image.filters.BaseFilter=fabric.util.createClass({type:"BaseFilter",initialize:function(t){t&&this.setOptions(t)},setOptions:function(t){for(var e in t)this[e]=t[e]},toObject:function(){return{type:this.type}},toJSON:function(){return this.toObject()}}),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend;e.Image.filters.Brightness=e.util.createClass(e.Image.filters.BaseFilter,{type:"Brightness",initialize:function(t){t=t||{},this.brightness=t.brightness||0},applyTo:function(t){for(var e=t.getContext("2d"),i=e.getImageData(0,0,t.width,t.height),r=i.data,n=this.brightness,s=0,o=r.length;o>s;s+=4)r[s]+=n,r[s+1]+=n,r[s+2]+=n;e.putImageData(i,0,0)},toObject:function(){return i(this.callSuper("toObject"),{brightness:this.brightness})}}),e.Image.filters.Brightness.fromObject=function(t){return new e.Image.filters.Brightness(t)}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend;e.Image.filters.Convolute=e.util.createClass(e.Image.filters.BaseFilter,{type:"Convolute",initialize:function(t){t=t||{},this.opaque=t.opaque,this.matrix=t.matrix||[0,0,0,0,1,0,0,0,0]},applyTo:function(t){for(var e,i,r,n,s,o,a,h,c,l=this.matrix,u=t.getContext("2d"),f=u.getImageData(0,0,t.width,t.height),d=Math.round(Math.sqrt(l.length)),g=Math.floor(d/2),p=f.data,v=f.width,m=f.height,b=u.createImageData(v,m),y=b.data,_=this.opaque?1:0,x=0;m>x;x++)for(var S=0;v>S;S++){s=4*(x*v+S),e=0,i=0,r=0,n=0;for(var C=0;d>C;C++)for(var w=0;d>w;w++)a=x+C-g,o=S+w-g,0>a||a>m||0>o||o>v||(h=4*(a*v+o),c=l[C*d+w],e+=p[h]*c,i+=p[h+1]*c,r+=p[h+2]*c,n+=p[h+3]*c);y[s]=e,y[s+1]=i,y[s+2]=r,y[s+3]=n+_*(255-n)}u.putImageData(b,0,0)},toObject:function(){return i(this.callSuper("toObject"),{opaque:this.opaque,matrix:this.matrix})}}),e.Image.filters.Convolute.fromObject=function(t){return new e.Image.filters.Convolute(t)}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend;e.Image.filters.GradientTransparency=e.util.createClass(e.Image.filters.BaseFilter,{type:"GradientTransparency",initialize:function(t){t=t||{},this.threshold=t.threshold||100},applyTo:function(t){for(var e=t.getContext("2d"),i=e.getImageData(0,0,t.width,t.height),r=i.data,n=this.threshold,s=r.length,o=0,a=r.length;a>o;o+=4)r[o+3]=n+255*(s-o)/s;e.putImageData(i,0,0)},toObject:function(){return i(this.callSuper("toObject"),{threshold:this.threshold})}}),e.Image.filters.GradientTransparency.fromObject=function(t){return new e.Image.filters.GradientTransparency(t)}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={});e.Image.filters.Grayscale=e.util.createClass(e.Image.filters.BaseFilter,{type:"Grayscale",applyTo:function(t){for(var e,i=t.getContext("2d"),r=i.getImageData(0,0,t.width,t.height),n=r.data,s=r.width*r.height*4,o=0;s>o;)e=(n[o]+n[o+1]+n[o+2])/3,n[o]=e,n[o+1]=e,n[o+2]=e,o+=4;i.putImageData(r,0,0)}}),e.Image.filters.Grayscale.fromObject=function(){return new e.Image.filters.Grayscale}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={});e.Image.filters.Invert=e.util.createClass(e.Image.filters.BaseFilter,{type:"Invert",applyTo:function(t){var e,i=t.getContext("2d"),r=i.getImageData(0,0,t.width,t.height),n=r.data,s=n.length;for(e=0;s>e;e+=4)n[e]=255-n[e],n[e+1]=255-n[e+1],n[e+2]=255-n[e+2];i.putImageData(r,0,0)}}),e.Image.filters.Invert.fromObject=function(){return new e.Image.filters.Invert}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend;e.Image.filters.Mask=e.util.createClass(e.Image.filters.BaseFilter,{type:"Mask",initialize:function(t){t=t||{},this.mask=t.mask,this.channel=[0,1,2,3].indexOf(t.channel)>-1?t.channel:0},applyTo:function(t){if(this.mask){var i,r=t.getContext("2d"),n=r.getImageData(0,0,t.width,t.height),s=n.data,o=this.mask.getElement(),a=e.util.createCanvasElement(),h=this.channel,c=n.width*n.height*4;a.width=t.width,a.height=t.height,a.getContext("2d").drawImage(o,0,0,t.width,t.height);var l=a.getContext("2d").getImageData(0,0,t.width,t.height),u=l.data;for(i=0;c>i;i+=4)s[i+3]=u[i+h];r.putImageData(n,0,0)}},toObject:function(){return i(this.callSuper("toObject"),{mask:this.mask.toObject(),channel:this.channel})}}),e.Image.filters.Mask.fromObject=function(t,i){e.util.loadImage(t.mask.src,function(r){t.mask=new e.Image(r,t.mask),i&&i(new e.Image.filters.Mask(t))})},e.Image.filters.Mask.async=!0}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend;e.Image.filters.Noise=e.util.createClass(e.Image.filters.BaseFilter,{type:"Noise",initialize:function(t){t=t||{},this.noise=t.noise||0},applyTo:function(t){for(var e,i=t.getContext("2d"),r=i.getImageData(0,0,t.width,t.height),n=r.data,s=this.noise,o=0,a=n.length;a>o;o+=4)e=(.5-Math.random())*s,n[o]+=e,n[o+1]+=e,n[o+2]+=e;i.putImageData(r,0,0)},toObject:function(){return i(this.callSuper("toObject"),{noise:this.noise})}}),e.Image.filters.Noise.fromObject=function(t){return new e.Image.filters.Noise(t)}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend;e.Image.filters.Pixelate=e.util.createClass(e.Image.filters.BaseFilter,{type:"Pixelate",initialize:function(t){t=t||{},this.blocksize=t.blocksize||4},applyTo:function(t){var e,i,r,n,s,o,a,h=t.getContext("2d"),c=h.getImageData(0,0,t.width,t.height),l=c.data,u=c.height,f=c.width;for(i=0;u>i;i+=this.blocksize)for(r=0;f>r;r+=this.blocksize){e=4*i*f+4*r,n=l[e],s=l[e+1],o=l[e+2],a=l[e+3];for(var d=i,g=i+this.blocksize;g>d;d++)for(var p=r,v=r+this.blocksize;v>p;p++)e=4*d*f+4*p,l[e]=n,l[e+1]=s,l[e+2]=o,l[e+3]=a}h.putImageData(c,0,0)},toObject:function(){return i(this.callSuper("toObject"),{blocksize:this.blocksize})}}),e.Image.filters.Pixelate.fromObject=function(t){return new e.Image.filters.Pixelate(t)}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend;e.Image.filters.RemoveWhite=e.util.createClass(e.Image.filters.BaseFilter,{type:"RemoveWhite",initialize:function(t){t=t||{},this.threshold=t.threshold||30,this.distance=t.distance||20},applyTo:function(t){for(var e,i,r,n=t.getContext("2d"),s=n.getImageData(0,0,t.width,t.height),o=s.data,a=this.threshold,h=this.distance,c=255-a,l=Math.abs,u=0,f=o.length;f>u;u+=4)e=o[u],i=o[u+1],r=o[u+2],e>c&&i>c&&r>c&&l(e-i)e;e+=4)i=.3*s[e]+.59*s[e+1]+.11*s[e+2],s[e]=i+100,s[e+1]=i+50,s[e+2]=i+255;r.putImageData(n,0,0)}}),e.Image.filters.Sepia.fromObject=function(){return new e.Image.filters.Sepia}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={});e.Image.filters.Sepia2=e.util.createClass(e.Image.filters.BaseFilter,{type:"Sepia2",applyTo:function(t){var e,i,r,n,s=t.getContext("2d"),o=s.getImageData(0,0,t.width,t.height),a=o.data,h=a.length;for(e=0;h>e;e+=4)i=a[e],r=a[e+1],n=a[e+2],a[e]=(.393*i+.769*r+.189*n)/1.351,a[e+1]=(.349*i+.686*r+.168*n)/1.203,a[e+2]=(.272*i+.534*r+.131*n)/2.14;s.putImageData(o,0,0)}}),e.Image.filters.Sepia2.fromObject=function(){return new e.Image.filters.Sepia2}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend;e.Image.filters.Tint=e.util.createClass(e.Image.filters.BaseFilter,{type:"Tint",initialize:function(t){t=t||{},this.color=t.color||"#000000",this.opacity="undefined"!=typeof t.opacity?t.opacity:new e.Color(this.color).getAlpha()},applyTo:function(t){var i,r,n,s,o,a,h,c,l,u=t.getContext("2d"),f=u.getImageData(0,0,t.width,t.height),d=f.data,g=d.length;for(l=new e.Color(this.color).getSource(),r=l[0]*this.opacity,n=l[1]*this.opacity,s=l[2]*this.opacity,c=1-this.opacity,i=0;g>i;i+=4)o=d[i],a=d[i+1],h=d[i+2],d[i]=r+o*c,d[i+1]=n+a*c,d[i+2]=s+h*c;u.putImageData(f,0,0)},toObject:function(){return i(this.callSuper("toObject"),{color:this.color,opacity:this.opacity})}}),e.Image.filters.Tint.fromObject=function(t){return new e.Image.filters.Tint(t)}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend;e.Image.filters.Multiply=e.util.createClass(e.Image.filters.BaseFilter,{type:"Multiply",initialize:function(t){t=t||{},this.color=t.color||"#000000"},applyTo:function(t){var i,r,n=t.getContext("2d"),s=n.getImageData(0,0,t.width,t.height),o=s.data,a=o.length;for(r=new e.Color(this.color).getSource(),i=0;a>i;i+=4)o[i]*=r[0]/255,o[i+1]*=r[1]/255,o[i+2]*=r[2]/255;n.putImageData(s,0,0)},toObject:function(){return i(this.callSuper("toObject"),{color:this.color})}}),e.Image.filters.Multiply.fromObject=function(t){return new e.Image.filters.Multiply(t)}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric;e.Image.filters.Blend=e.util.createClass({type:"Blend",initialize:function(t){t=t||{},this.color=t.color||"#000",this.image=t.image||!1,this.mode=t.mode||"multiply",this.alpha=t.alpha||1},applyTo:function(t){var i,r,n,s,o,a,h,c,l,u,f=t.getContext("2d"),d=f.getImageData(0,0,t.width,t.height),g=d.data,p=!1;if(this.image){p=!0;var v=e.util.createCanvasElement();v.width=this.image.width,v.height=this.image.height;var m=new e.StaticCanvas(v);m.add(this.image);var b=m.getContext("2d");u=b.getImageData(0,0,m.width,m.height).data}else u=new e.Color(this.color).getSource(),i=u[0]*this.alpha,r=u[1]*this.alpha,n=u[2]*this.alpha;for(var y=0,_=g.length;_>y;y+=4)switch(s=g[y],o=g[y+1],a=g[y+2],p&&(i=u[y]*this.alpha,r=u[y+1]*this.alpha,n=u[y+2]*this.alpha),this.mode){case"multiply":g[y]=s*i/255,g[y+1]=o*r/255,g[y+2]=a*n/255;break;case"screen":g[y]=1-(1-s)*(1-i),g[y+1]=1-(1-o)*(1-r),g[y+2]=1-(1-a)*(1-n);break;case"add":g[y]=Math.min(255,s+i),g[y+1]=Math.min(255,o+r),g[y+2]=Math.min(255,a+n);break;case"diff":case"difference":g[y]=Math.abs(s-i),g[y+1]=Math.abs(o-r),g[y+2]=Math.abs(a-n);break;case"subtract":h=s-i,c=o-r,l=a-n,g[y]=0>h?0:h,g[y+1]=0>c?0:c,g[y+2]=0>l?0:l;break;case"darken":g[y]=Math.min(s,i),g[y+1]=Math.min(o,r),g[y+2]=Math.min(a,n);break;case"lighten":g[y]=Math.max(s,i),g[y+1]=Math.max(o,r),g[y+2]=Math.max(a,n)}f.putImageData(d,0,0)},toObject:function(){return{color:this.color,image:this.image,mode:this.mode,alpha:this.alpha}}}),e.Image.filters.Blend.fromObject=function(t){return new e.Image.filters.Blend(t)}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=Math.pow,r=Math.floor,n=Math.sqrt,s=Math.abs,o=Math.max,a=Math.round,h=Math.sin,c=Math.ceil;e.Image.filters.Resize=e.util.createClass(e.Image.filters.BaseFilter,{type:"Resize",resizeType:"hermite",scaleX:0,scaleY:0,lanczosLobes:3,applyTo:function(t,e,i){this.rcpScaleX=1/e,this.rcpScaleY=1/i;var r,n=t.width,s=t.height,o=a(n*e),h=a(s*i);"sliceHack"===this.resizeType&&(r=this.sliceByTwo(t,n,s,o,h)),"hermite"===this.resizeType&&(r=this.hermiteFastResize(t,n,s,o,h)),"bilinear"===this.resizeType&&(r=this.bilinearFiltering(t,n,s,o,h)),"lanczos"===this.resizeType&&(r=this.lanczosResize(t,n,s,o,h)),t.width=o,t.height=h,t.getContext("2d").putImageData(r,0,0)},sliceByTwo:function(t,i,n,s,a){var h,c=t.getContext("2d"),l=.5,u=.5,f=1,d=1,g=!1,p=!1,v=i,m=n,b=e.util.createCanvasElement(),y=b.getContext("2d");for(s=r(s),a=r(a),b.width=o(s,i),b.height=o(a,n),s>i&&(l=2,f=-1),a>n&&(u=2,d=-1),h=c.getImageData(0,0,i,n),t.width=o(s,i),t.height=o(a,n),c.putImageData(h,0,0);!g||!p;)i=v,n=m,s*ft)return 0;if(e*=Math.PI,s(e)<1e-16)return 1;var i=e/t;return h(e)*h(i)/e/i}}function f(t){var h,c,u,d,g,j,A,P,M,L,D;for(T.x=(t+.5)*y,k.x=r(T.x),h=0;l>h;h++){for(T.y=(h+.5)*_,k.y=r(T.y),g=0,j=0,A=0,P=0,M=0,c=k.x-C;c<=k.x+C;c++)if(!(0>c||c>=e)){L=r(1e3*s(c-T.x)),O[L]||(O[L]={});for(var E=k.y-w;E<=k.y+w;E++)0>E||E>=o||(D=r(1e3*s(E-T.y)),O[L][D]||(O[L][D]=b(n(i(L*x,2)+i(D*S,2))/1e3)),u=O[L][D],u>0&&(d=4*(E*e+c),g+=u,j+=u*v[d],A+=u*v[d+1],P+=u*v[d+2],M+=u*v[d+3]))}d=4*(h*a+t),m[d]=j/g,m[d+1]=A/g,m[d+2]=P/g,m[d+3]=M/g}return++tf;f++)for(d=0;n>d;d++)for(l=r(_*d),u=r(x*f),g=_*d-l,p=x*f-u,b=4*(u*e+l),v=0;4>v;v++)o=O[b+v],a=O[b+4+v],h=O[b+C+v],c=O[b+C+4+v],m=o*(1-g)*(1-p)+a*g*(1-p)+h*p*(1-g)+c*g*p,k[y++]=m;return T},hermiteFastResize:function(t,e,i,o,a){for(var h=this.rcpScaleX,l=this.rcpScaleY,u=c(h/2),f=c(l/2),d=t.getContext("2d"),g=d.getImageData(0,0,e,i),p=g.data,v=d.getImageData(0,0,o,a),m=v.data,b=0;a>b;b++)for(var y=0;o>y;y++){for(var _=4*(y+b*o),x=0,S=0,C=0,w=0,O=0,T=0,k=0,j=(b+.5)*l,A=r(b*l);(b+1)*l>A;A++)for(var P=s(j-(A+.5))/f,M=(y+.5)*h,L=P*P,D=r(y*h);(y+1)*h>D;D++){var E=s(M-(D+.5))/u,I=n(L+E*E);I>1&&-1>I||(x=2*I*I*I-3*I*I+1,x>0&&(E=4*(D+A*e),k+=x*p[E+3],C+=x,p[E+3]<255&&(x=x*p[E+3]/250),w+=x*p[E],O+=x*p[E+1],T+=x*p[E+2],S+=x))}m[_]=w/S,m[_+1]=O/S,m[_+2]=T/S,m[_+3]=k/C}return v},toObject:function(){return{type:this.type,scaleX:this.scaleX,scaleY:this.scaleY,resizeType:this.resizeType,lanczosLobes:this.lanczosLobes}}}),e.Image.filters.Resize.fromObject=function(t){return new e.Image.filters.Resize(t)}}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend,r=e.util.object.clone,n=e.util.toFixed,s=e.StaticCanvas.supports("setLineDash"),o=e.Object.NUM_FRACTION_DIGITS;if(e.Text)return void e.warn("fabric.Text is already defined");var a=e.Object.prototype.stateProperties.concat();a.push("fontFamily","fontWeight","fontSize","text","textDecoration","textAlign","fontStyle","lineHeight","textBackgroundColor"),e.Text=e.util.createClass(e.Object,{_dimensionAffectingProps:{fontSize:!0,fontWeight:!0,fontFamily:!0,fontStyle:!0,lineHeight:!0,stroke:!0,strokeWidth:!0,text:!0,textAlign:!0},_reNewline:/\r?\n/,_reSpacesAndTabs:/[ \t\r]+/g,type:"text",fontSize:40,fontWeight:"normal",fontFamily:"Times New Roman",textDecoration:"",textAlign:"left",fontStyle:"",lineHeight:1.16,textBackgroundColor:"",stateProperties:a,stroke:null,shadow:null,_fontSizeFraction:.25,_fontSizeMult:1.13,initialize:function(t,e){e=e||{},this.text=t,this.__skipDimension=!0,this.setOptions(e),this.__skipDimension=!1,this._initDimensions()},_initDimensions:function(t){this.__skipDimension||(t||(t=e.util.createCanvasElement().getContext("2d"),this._setTextStyles(t)),this._textLines=this._splitTextIntoLines(),this._clearCache(),this._cacheLinesWidth="justify"!==this.textAlign,this.width=this._getTextWidth(t),this._cacheLinesWidth=!0,this.height=this._getTextHeight(t))},toString:function(){return"#'},_render:function(t){this.clipTo&&e.util.clipContext(this,t),this._setOpacity(t),this._setShadow(t),this._setupCompositeOperation(t),this._renderTextBackground(t),this._setStrokeStyles(t),this._setFillStyles(t),this._renderText(t),this._renderTextDecoration(t),this.clipTo&&t.restore()},_renderText:function(t){this._translateForTextAlign(t),this._renderTextFill(t),this._renderTextStroke(t),this._translateForTextAlign(t,!0)},_translateForTextAlign:function(t,e){if("left"!==this.textAlign&&"justify"!==this.textAlign){var i=e?-1:1;t.translate("center"===this.textAlign?i*this.width/2:i*this.width,0)}},_setTextStyles:function(t){t.textBaseline="alphabetic",this.skipTextAlign||(t.textAlign=this.textAlign),t.font=this._getFontDeclaration()},_getTextHeight:function(){return this._textLines.length*this._getHeightOfLine()},_getTextWidth:function(t){for(var e=this._getLineWidth(t,0),i=1,r=this._textLines.length;r>i;i++){var n=this._getLineWidth(t,i);n>e&&(e=n)}return e},_renderChars:function(t,e,i,r,n){var s=t.slice(0,-4);if(this[s].toLive){var o=-this.width/2+this[s].offsetX||0,a=-this.height/2+this[s].offsetY||0;e.save(),e.translate(o,a),r-=o,n-=a}e[t](i,r,n),this[s].toLive&&e.restore()},_renderTextLine:function(t,e,i,r,n,s){n-=this.fontSize*this._fontSizeFraction;var o=this._getLineWidth(e,s);if("justify"!==this.textAlign||this.width0?u/f:0,g=0,p=0,v=h.length;v>p;p++){for(;" "===i[c]&&ci;i++){var n=this._getHeightOfLine(t,i),s=n/this.lineHeight;this._renderTextLine("fillText",t,this._textLines[i],this._getLeftOffset(),this._getTopOffset()+e+s,i),e+=n}},_renderTextStroke:function(t){if(this.stroke&&0!==this.strokeWidth||!this.isEmptyStyles()){var e=0;this.shadow&&!this.shadow.affectStroke&&this._removeShadow(t),t.save(),this.strokeDashArray&&(1&this.strokeDashArray.length&&this.strokeDashArray.push.apply(this.strokeDashArray,this.strokeDashArray),s&&t.setLineDash(this.strokeDashArray)),t.beginPath();for(var i=0,r=this._textLines.length;r>i;i++){var n=this._getHeightOfLine(t,i),o=n/this.lineHeight;this._renderTextLine("strokeText",t,this._textLines[i],this._getLeftOffset(),this._getTopOffset()+e+o,i),e+=n}t.closePath(),t.restore()}},_getHeightOfLine:function(){return this.fontSize*this._fontSizeMult*this.lineHeight},_renderTextBackground:function(t){this._renderTextBoxBackground(t),this._renderTextLinesBackground(t)},_renderTextBoxBackground:function(t){this.backgroundColor&&(t.fillStyle=this.backgroundColor,t.fillRect(this._getLeftOffset(),this._getTopOffset(),this.width,this.height),this._removeShadow(t))},_renderTextLinesBackground:function(t){if(this.textBackgroundColor){var e,i,r,n=0;t.fillStyle=this.textBackgroundColor;for(var s=0,o=this._textLines.length;o>s;s++)e=this._getHeightOfLine(t,s),""!==this._textLines[s]&&(i="justify"===this.textAlign?this.width:this._getLineWidth(t,s),r=this._getLineLeftOffset(i),t.fillRect(this._getLeftOffset()+r,this._getTopOffset()+n,i,e/this.lineHeight)),n+=e;this._removeShadow(t)}},_getLineLeftOffset:function(t){return"center"===this.textAlign?(this.width-t)/2:"right"===this.textAlign?this.width-t:0},_clearCache:function(){this.__lineWidths=[],this.__lineHeights=[]},_shouldClearCache:function(){var t=!1;if(this._forceClearCache)return this._forceClearCache=!1,!0;for(var e in this._dimensionAffectingProps)this["__"+e]!==this[e]&&(this["__"+e]=this[e],t=!0);return t},_getLineWidth:function(t,e){if(this.__lineWidths[e])return this.__lineWidths[e];var i,r,n=this._textLines[e];return""===n?i=0:"justify"===this.textAlign&&this._cacheLinesWidth?(r=n.split(/\s+/),i=r.length>1?this.width:t.measureText(n).width):i=t.measureText(n).width,this._cacheLinesWidth&&(this.__lineWidths[e]=i),i},_renderTextDecoration:function(t){function e(e){var n,s,o,a,h,c,l,u=0;for(n=0,s=r._textLines.length;s>n;n++){for(h=r._getLineWidth(t,n),c=r._getLineLeftOffset(h),l=r._getHeightOfLine(t,n),o=0,a=e.length;a>o;o++)t.fillRect(r._getLeftOffset()+c,u+(r._fontSizeMult-1+e[o])*r.fontSize-i,h,r.fontSize/15);u+=l}}if(this.textDecoration){var i=this.height/2,r=this,n=[];this.textDecoration.indexOf("underline")>-1&&n.push(.85),this.textDecoration.indexOf("line-through")>-1&&n.push(.43),this.textDecoration.indexOf("overline")>-1&&n.push(-.12),n.length>0&&e(n)}},_getFontDeclaration:function(){return[e.isLikelyNode?this.fontWeight:this.fontStyle,e.isLikelyNode?this.fontStyle:this.fontWeight,this.fontSize+"px",e.isLikelyNode?'"'+this.fontFamily+'"':this.fontFamily].join(" ")},render:function(t,e){this.visible&&(t.save(),this._setTextStyles(t),this._shouldClearCache()&&this._initDimensions(t),e||this.transform(t),this.transformMatrix&&t.transform.apply(t,this.transformMatrix),this.group&&"path-group"===this.group.type&&t.translate(this.left,this.top),this._render(t),t.restore())},_splitTextIntoLines:function(){return this.text.split(this._reNewline)},toObject:function(t){var e=i(this.callSuper("toObject",t),{text:this.text,fontSize:this.fontSize,fontWeight:this.fontWeight,fontFamily:this.fontFamily,fontStyle:this.fontStyle,lineHeight:this.lineHeight,textDecoration:this.textDecoration,textAlign:this.textAlign,textBackgroundColor:this.textBackgroundColor});return this.includeDefaultValues||this._removeDefaultValues(e),e},toSVG:function(t){var e=this._createBaseSVGMarkup(),i=this._getSVGLeftTopOffsets(this.ctx),r=this._getSVGTextAndBg(i.textTop,i.textLeft);return this._wrapSVGTextAndBg(e,r),t?t(e.join("")):e.join("")},_getSVGLeftTopOffsets:function(t){var e=this._getHeightOfLine(t,0),i=-this.width/2,r=0;return{textLeft:i+(this.group&&"path-group"===this.group.type?this.left:0),textTop:r+(this.group&&"path-group"===this.group.type?-this.top:0),lineTop:e}},_wrapSVGTextAndBg:function(t,e){var i=!0,r=this.getSvgFilter(),n=""===r?"":' style="'+r+'"';t.push(' \n",e.textBgRects.join("")," \n',e.textSpans.join("")," \n"," \n"); + +},_getSVGTextAndBg:function(t,e){var i=[],r=[],n=0;this._setSVGBg(r);for(var s=0,o=this._textLines.length;o>s;s++)this.textBackgroundColor&&this._setSVGTextLineBg(r,s,e,t,n),this._setSVGTextLineText(s,i,n,e,t,r),n+=this._getHeightOfLine(this.ctx,s);return{textSpans:i,textBgRects:r}},_setSVGTextLineText:function(t,i,r,s,a){var h=this.fontSize*(this._fontSizeMult-this._fontSizeFraction)-a+r-this.height/2;return"justify"===this.textAlign?void this._setSVGTextLineJustifed(t,i,h,s):void i.push(' ",e.util.string.escapeXml(this._textLines[t]),"\n")},_setSVGTextLineJustifed:function(t,i,r,s){var a=e.util.createCanvasElement().getContext("2d");this._setTextStyles(a);var h,c,l=this._textLines[t],u=l.split(/\s+/),f=this._getWidthOfWords(a,l),d=this.width-f,g=u.length-1,p=g>0?d/g:0,v=this._getFillAttributes(this.fill);for(s+=this._getLineLeftOffset(this._getLineWidth(a,t)),t=0,c=u.length;c>t;t++)h=u[t],i.push(' ",e.util.string.escapeXml(h),"\n"),s+=this._getWidthOfWords(a,h)+p},_setSVGTextLineBg:function(t,e,i,r,s){t.push(" \n')},_setSVGBg:function(t){this.backgroundColor&&t.push(" \n')},_getFillAttributes:function(t){var i=t&&"string"==typeof t?new e.Color(t):"";return i&&i.getSource()&&1!==i.getAlpha()?'opacity="'+i.getAlpha()+'" fill="'+i.setAlpha(1).toRgb()+'"':'fill="'+t+'"'},_set:function(t,e){this.callSuper("_set",t,e),t in this._dimensionAffectingProps&&(this._initDimensions(),this.setCoords())},complexity:function(){return 1}}),e.Text.ATTRIBUTE_NAMES=e.SHARED_ATTRIBUTES.concat("x y dx dy font-family font-style font-weight font-size text-decoration text-anchor".split(" ")),e.Text.DEFAULT_SVG_FONT_SIZE=16,e.Text.fromElement=function(t,i){if(!t)return null;var r=e.parseAttributes(t,e.Text.ATTRIBUTE_NAMES);i=e.util.object.extend(i?e.util.object.clone(i):{},r),i.top=i.top||0,i.left=i.left||0,"dx"in r&&(i.left+=r.dx),"dy"in r&&(i.top+=r.dy),"fontSize"in i||(i.fontSize=e.Text.DEFAULT_SVG_FONT_SIZE),i.originX||(i.originX="left");var n="";"textContent"in t?n=t.textContent:"firstChild"in t&&null!==t.firstChild&&"data"in t.firstChild&&null!==t.firstChild.data&&(n=t.firstChild.data),n=n.replace(/^\s+|\s+$|\n+/g,"").replace(/\s+/g," ");var s=new e.Text(n,i),o=0;return"left"===s.originX&&(o=s.getWidth()/2),"right"===s.originX&&(o=-s.getWidth()/2),s.set({left:s.getLeft()+o,top:s.getTop()-s.getHeight()/2+s.fontSize*(.18+s._fontSizeFraction)}),s},e.Text.fromObject=function(t){return new e.Text(t.text,r(t))},e.util.createAccessors(e.Text)}("undefined"!=typeof exports?exports:this),function(){var t=fabric.util.object.clone;fabric.IText=fabric.util.createClass(fabric.Text,fabric.Observable,{type:"i-text",selectionStart:0,selectionEnd:0,selectionColor:"rgba(17,119,255,0.3)",isEditing:!1,editable:!0,editingBorderColor:"rgba(102,153,255,0.25)",cursorWidth:2,cursorColor:"#333",cursorDelay:1e3,cursorDuration:600,styles:null,caching:!0,_reSpace:/\s|\n/,_currentCursorOpacity:0,_selectionDirection:null,_abortCursorAnimation:!1,_charWidthsCache:{},__widthOfSpace:[],initialize:function(t,e){this.styles=e?e.styles||{}:{},this.callSuper("initialize",t,e),this.initBehavior()},_clearCache:function(){this.callSuper("_clearCache"),this.__widthOfSpace=[]},isEmptyStyles:function(){if(!this.styles)return!0;var t=this.styles;for(var e in t)for(var i in t[e])for(var r in t[e][i])return!1;return!0},setSelectionStart:function(t){t=Math.max(t,0),this.selectionStart!==t&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this}),this.selectionStart=t),this._updateTextarea()},setSelectionEnd:function(t){t=Math.min(t,this.text.length),this.selectionEnd!==t&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this}),this.selectionEnd=t),this._updateTextarea()},getSelectionStyles:function(t,e){if(2===arguments.length){for(var i=[],r=t;e>r;r++)i.push(this.getSelectionStyles(r));return i}var n=this.get2DCursorLocation(t),s=this._getStyleDeclaration(n.lineIndex,n.charIndex);return s||{}},setSelectionStyles:function(t){if(this.selectionStart===this.selectionEnd)this._extendStyles(this.selectionStart,t);else for(var e=this.selectionStart;ei;i++){if(t<=this._textLines[i].length)return{lineIndex:i,charIndex:t};t-=this._textLines[i].length+1}return{lineIndex:i-1,charIndex:this._textLines[i-1].length=a;a++){var h=this._getLineLeftOffset(this._getLineWidth(i,a))||0,c=this._getHeightOfLine(this.ctx,a),l=0,u=this._textLines[a];if(a===s)for(var f=0,d=u.length;d>f;f++)f>=r.charIndex&&(a!==o||fs&&o>a)l+=this._getLineWidth(i,a)||5;else if(a===o)for(var g=0,p=n.charIndex;p>g;g++)l+=this._getWidthOfChar(i,u[g],a,g);i.fillRect(e.left+h,e.top+e.topOffset,l,c),e.topOffset+=c}},_renderChars:function(t,e,i,r,n,s,o){if(this.isEmptyStyles())return this._renderCharsFast(t,e,i,r,n);o=o||0,this.skipTextAlign=!0,r-="center"===this.textAlign?this.width/2:"right"===this.textAlign?this.width:0;var a,h,c=this._getHeightOfLine(e,s),l=this._getLineLeftOffset(this._getLineWidth(e,s)),u="";r+=l||0,e.save(),n-=c/this.lineHeight*this._fontSizeFraction;for(var f=o,d=i.length+o;d>=f;f++)a=a||this.getCurrentCharStyle(s,f),h=this.getCurrentCharStyle(s,f+1),(this._hasStyleChanged(a,h)||f===d)&&(this._renderChar(t,e,s,f-1,u,r,n,c),u="",a=h),u+=i[f-o];e.restore()},_renderCharsFast:function(t,e,i,r,n){this.skipTextAlign=!1,"fillText"===t&&this.fill&&this.callSuper("_renderChars",t,e,i,r,n),"strokeText"===t&&(this.stroke&&this.strokeWidth>0||this.skipFillStrokeCheck)&&this.callSuper("_renderChars",t,e,i,r,n)},_renderChar:function(t,e,i,r,n,s,o,a){var h,c,l,u,f,d,g=this._getStyleDeclaration(i,r);g?(c=this._getHeightOfChar(e,n,i,r),u=g.stroke,l=g.fill,d=g.textDecoration):c=this.fontSize,u=(u||this.stroke)&&"strokeText"===t,l=(l||this.fill)&&"fillText"===t,g&&e.save(),h=this._applyCharStylesGetWidth(e,n,i,r,g||{}),d=d||this.textDecoration,g&&g.textBackgroundColor&&this._removeShadow(e),l&&e.fillText(n,s,o),u&&e.strokeText(n,s,o),(d||""!==d)&&(f=this._fontSizeFraction*a/this.lineHeight,this._renderCharDecoration(e,d,s,o,f,h,c)),g&&e.restore(),e.translate(h,0)},_hasStyleChanged:function(t,e){return t.fill!==e.fill||t.fontSize!==e.fontSize||t.textBackgroundColor!==e.textBackgroundColor||t.textDecoration!==e.textDecoration||t.fontFamily!==e.fontFamily||t.fontWeight!==e.fontWeight||t.fontStyle!==e.fontStyle||t.stroke!==e.stroke||t.strokeWidth!==e.strokeWidth},_renderCharDecoration:function(t,e,i,r,n,s,o){if(e){var a,h,c=o/15,l={underline:r+o/10,"line-through":r-o*(this._fontSizeFraction+this._fontSizeMult-1)+c,overline:r-(this._fontSizeMult-this._fontSizeFraction)*o},u=["underline","line-through","overline"];for(a=0;a-1&&t.fillRect(i,l[h],s,c)}},_renderTextLine:function(t,e,i,r,n,s){this.isEmptyStyles()||(n+=this.fontSize*(this._fontSizeFraction+.03)),this.callSuper("_renderTextLine",t,e,i,r,n,s)},_renderTextDecoration:function(t){return this.isEmptyStyles()?this.callSuper("_renderTextDecoration",t):void 0},_renderTextLinesBackground:function(t){this.callSuper("_renderTextLinesBackground",t);for(var e,i,r,n,s,o,a=0,h=this._getLeftOffset(),c=this._getTopOffset(),l=0,u=this._textLines.length;u>l;l++)if(e=this._getHeightOfLine(t,l),n=this._textLines[l],""!==n&&this.styles&&this._getLineStyle(l)){i=this._getLineWidth(t,l),r=this._getLineLeftOffset(i);for(var f=0,d=n.length;d>f;f++)o=this._getStyleDeclaration(l,f),o&&o.textBackgroundColor&&(s=n[f],t.fillStyle=o.textBackgroundColor,t.fillRect(h+r+this._getWidthOfCharsAt(t,l,f),c+a,this._getWidthOfChar(t,s,l,f)+1,e/this.lineHeight));a+=e}else a+=e},_getCacheProp:function(t,e){return t+e.fontFamily+e.fontSize+e.fontWeight+e.fontStyle+e.shadow},_applyCharStylesGetWidth:function(e,i,r,n,s){var o,a=this._getStyleDeclaration(r,n),h=s&&t(s)||t(a);this._applyFontStyles(h);var c=this._getCacheProp(i,h);if(!a&&this._charWidthsCache[c]&&this.caching)return this._charWidthsCache[c];"string"==typeof h.shadow&&(h.shadow=new fabric.Shadow(h.shadow));var l=h.fill||this.fill;return e.fillStyle=l.toLive?l.toLive(e,this):l,h.stroke&&(e.strokeStyle=h.stroke&&h.stroke.toLive?h.stroke.toLive(e,this):h.stroke),e.lineWidth=h.strokeWidth||this.strokeWidth,e.font=this._getFontDeclaration.call(h),h.shadow&&(h.scaleX=this.scaleX,h.scaleY=this.scaleY,h.canvas=this.canvas,this._setShadow.call(h,e)),this.caching&&this._charWidthsCache[c]||(o=e.measureText(i).width,this.caching&&(this._charWidthsCache[c]=o)),this._charWidthsCache[c]},_applyFontStyles:function(t){t.fontFamily||(t.fontFamily=this.fontFamily),t.fontSize||(t.fontSize=this.fontSize),t.fontWeight||(t.fontWeight=this.fontWeight),t.fontStyle||(t.fontStyle=this.fontStyle)},_getStyleDeclaration:function(e,i,r){return r?this.styles[e]&&this.styles[e][i]?t(this.styles[e][i]):{}:this.styles[e]&&this.styles[e][i]?this.styles[e][i]:null},_setStyleDeclaration:function(t,e,i){this.styles[t][e]=i},_deleteStyleDeclaration:function(t,e){delete this.styles[t][e]},_getLineStyle:function(t){return this.styles[t]},_setLineStyle:function(t,e){this.styles[t]=e},_deleteLineStyle:function(t){delete this.styles[t]},_getWidthOfChar:function(t,e,i,r){if("justify"===this.textAlign&&this._reSpacesAndTabs.test(e))return this._getWidthOfSpace(t,i);var n=this._getStyleDeclaration(i,r,!0);this._applyFontStyles(n);var s=this._getCacheProp(e,n);if(this._charWidthsCache[s]&&this.caching)return this._charWidthsCache[s];if(t){t.save();var o=this._applyCharStylesGetWidth(t,e,i,r);return t.restore(),o}},_getHeightOfChar:function(t,e,i){var r=this._getStyleDeclaration(e,i);return r&&r.fontSize?r.fontSize:this.fontSize},_getWidthOfCharsAt:function(t,e,i){var r,n,s=0;for(r=0;i>r;r++)n=this._textLines[e][r],s+=this._getWidthOfChar(t,n,e,r);return s},_getLineWidth:function(t,e){return this.__lineWidths[e]?this.__lineWidths[e]:(this.__lineWidths[e]=this._getWidthOfCharsAt(t,e,this._textLines[e].length),this.__lineWidths[e])},_getWidthOfSpace:function(t,e){if(this.__widthOfSpace[e])return this.__widthOfSpace[e];var i=this._textLines[e],r=this._getWidthOfWords(t,i,e,0),n=this.width-r,s=i.length-i.replace(this._reSpacesAndTabs,"").length,o=n/s;return this.__widthOfSpace[e]=o,o},_getWidthOfWords:function(t,e,i,r){for(var n=0,s=0;sn;n++){var o=this._getHeightOfChar(t,e,n);o>r&&(r=o)}return this.__lineHeights[e]=r*this.lineHeight*this._fontSizeMult,this.__lineHeights[e]},_getTextHeight:function(t){for(var e=0,i=0,r=this._textLines.length;r>i;i++)e+=this._getHeightOfLine(t,i);return e},toObject:function(e){var i,r,n,s={};for(i in this.styles){n=this.styles[i],s[i]={};for(r in n)s[i][r]=t(n[r])}return fabric.util.object.extend(this.callSuper("toObject",e),{styles:s})}}),fabric.IText.fromObject=function(e){return new fabric.IText(e.text,t(e))}}(),function(){var t=fabric.util.object.clone;fabric.util.object.extend(fabric.IText.prototype,{initBehavior:function(){this.initAddedHandler(),this.initRemovedHandler(),this.initCursorSelectionHandlers(),this.initDoubleClickSimulation()},initSelectedHandler:function(){this.on("selected",function(){var t=this;setTimeout(function(){t.selected=!0},100)})},initAddedHandler:function(){var t=this;this.on("added",function(){this.canvas&&!this.canvas._hasITextHandlers&&(this.canvas._hasITextHandlers=!0,this._initCanvasHandlers()),t.canvas&&(t.canvas._iTextInstances=t.canvas._iTextInstances||[],t.canvas._iTextInstances.push(t))})},initRemovedHandler:function(){var t=this;this.on("removed",function(){t.canvas&&(t.canvas._iTextInstances=t.canvas._iTextInstances||[],fabric.util.removeFromArray(t.canvas._iTextInstances,t))})},_initCanvasHandlers:function(){var t=this;this.canvas.on("selection:cleared",function(){fabric.IText.prototype.exitEditingOnOthers(t.canvas)}),this.canvas.on("mouse:up",function(){t.canvas._iTextInstances&&t.canvas._iTextInstances.forEach(function(t){t.__isMousedown=!1})}),this.canvas.on("object:selected",function(){fabric.IText.prototype.exitEditingOnOthers(t.canvas)})},_tick:function(){this._currentTickState=this._animateCursor(this,1,this.cursorDuration,"_onTickComplete")},_animateCursor:function(t,e,i,r){var n;return n={isAborted:!1,abort:function(){this.isAborted=!0}},t.animate("_currentCursorOpacity",e,{duration:i,onComplete:function(){n.isAborted||t[r]()},onChange:function(){t.canvas&&(t.canvas.clearContext(t.canvas.contextTop||t.ctx),t.renderCursorOrSelection())},abort:function(){return n.isAborted}}),n},_onTickComplete:function(){var t=this;this._cursorTimeout1&&clearTimeout(this._cursorTimeout1),this._cursorTimeout1=setTimeout(function(){t._currentTickCompleteState=t._animateCursor(t,0,this.cursorDuration/2,"_tick")},100)},initDelayedCursor:function(t){var e=this,i=t?0:this.cursorDelay;this._currentTickState&&this._currentTickState.abort(),this._currentTickCompleteState&&this._currentTickCompleteState.abort(),clearTimeout(this._cursorTimeout1),this._currentCursorOpacity=1,this.canvas&&(this.canvas.clearContext(this.canvas.contextTop||this.ctx),this.renderCursorOrSelection()),this._cursorTimeout2&&clearTimeout(this._cursorTimeout2),this._cursorTimeout2=setTimeout(function(){e._tick()},i)},abortCursorAnimation:function(){this._currentTickState&&this._currentTickState.abort(),this._currentTickCompleteState&&this._currentTickCompleteState.abort(),clearTimeout(this._cursorTimeout1),clearTimeout(this._cursorTimeout2),this._currentCursorOpacity=0,this.canvas&&this.canvas.clearContext(this.canvas.contextTop||this.ctx)},selectAll:function(){this.setSelectionStart(0),this.setSelectionEnd(this.text.length)},getSelectedText:function(){return this.text.slice(this.selectionStart,this.selectionEnd)},findWordBoundaryLeft:function(t){var e=0,i=t-1;if(this._reSpace.test(this.text.charAt(i)))for(;this._reSpace.test(this.text.charAt(i));)e++,i--;for(;/\S/.test(this.text.charAt(i))&&i>-1;)e++,i--;return t-e},findWordBoundaryRight:function(t){var e=0,i=t;if(this._reSpace.test(this.text.charAt(i)))for(;this._reSpace.test(this.text.charAt(i));)e++,i++;for(;/\S/.test(this.text.charAt(i))&&i-1;)e++,i--;return t-e},findLineBoundaryRight:function(t){for(var e=0,i=t;!/\n/.test(this.text.charAt(i))&&ii;i++)"\n"===t[i]&&e++;return e},searchWordBoundary:function(t,e){for(var i=this._reSpace.test(this.text.charAt(t))?t-1:t,r=this.text.charAt(i),n=/[ \n\.,;!\?\-]/;!n.test(r)&&i>0&&i=t.__selectionStartOnMouseDown?(t.setSelectionStart(t.__selectionStartOnMouseDown),t.setSelectionEnd(i)):(t.setSelectionStart(i),t.setSelectionEnd(t.__selectionStartOnMouseDown))}})},_setEditingProps:function(){this.hoverCursor="text",this.canvas&&(this.canvas.defaultCursor=this.canvas.moveCursor="text"),this.borderColor=this.editingBorderColor,this.hasControls=this.selectable=!1,this.lockMovementX=this.lockMovementY=!0},_updateTextarea:function(){if(this.hiddenTextarea&&!this.inCompositionMode&&(this.hiddenTextarea.value=this.text,this.hiddenTextarea.selectionStart=this.selectionStart,this.hiddenTextarea.selectionEnd=this.selectionEnd,this.selectionStart===this.selectionEnd)){var t=this._calcTextareaPosition();this.hiddenTextarea.style.left=t.x+"px",this.hiddenTextarea.style.top=t.y+"px"}},_calcTextareaPosition:function(){var t=this.text.split(""),e=this._getCursorBoundaries(t,"cursor"),i=this.get2DCursorLocation(),r=i.lineIndex,n=i.charIndex,s=this.getCurrentCharFontSize(r,n),o=0===r&&0===n?this._getLineLeftOffset(this._getLineWidth(this.ctx,r)):e.leftOffset,a=this.calcTransformMatrix(),h={x:e.left+o,y:e.top+e.topOffset+s};return this.hiddenTextarea.style.fontSize=s+"px",fabric.util.transformPoint(h,a)},_saveEditingProps:function(){this._savedProps={hasControls:this.hasControls,borderColor:this.borderColor,lockMovementX:this.lockMovementX,lockMovementY:this.lockMovementY,hoverCursor:this.hoverCursor,defaultCursor:this.canvas&&this.canvas.defaultCursor,moveCursor:this.canvas&&this.canvas.moveCursor}},_restoreEditingProps:function(){this._savedProps&&(this.hoverCursor=this._savedProps.overCursor,this.hasControls=this._savedProps.hasControls,this.borderColor=this._savedProps.borderColor,this.lockMovementX=this._savedProps.lockMovementX,this.lockMovementY=this._savedProps.lockMovementY,this.canvas&&(this.canvas.defaultCursor=this._savedProps.defaultCursor,this.canvas.moveCursor=this._savedProps.moveCursor))},exitEditing:function(){return this.selected=!1,this.isEditing=!1,this.selectable=!0,this.selectionEnd=this.selectionStart,this.hiddenTextarea&&this.canvas&&this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea),this.hiddenTextarea=null,this.abortCursorAnimation(),this._restoreEditingProps(),this._currentCursorOpacity=0,this.fire("editing:exited"),this.canvas&&this.canvas.fire("text:editing:exited",{target:this}),this},_removeExtraneousStyles:function(){for(var t in this.styles)this._textLines[t]||delete this.styles[t]},_removeCharsFromTo:function(t,e){for(;e!==t;)this._removeSingleCharAndStyle(t+1),e--;this.setSelectionStart(t)},_removeSingleCharAndStyle:function(t){var e="\n"===this.text[t-1],i=e?t:t-1;this.removeStyleObject(e,i),this.text=this.text.slice(0,t-1)+this.text.slice(t),this._textLines=this._splitTextIntoLines()},insertChars:function(t,e){var i;if(this.selectionEnd-this.selectionStart>1&&(this._removeCharsFromTo(this.selectionStart,this.selectionEnd),this.setSelectionEnd(this.selectionStart)),!e&&this.isEmptyStyles())return void this.insertChar(t,!1);for(var r=0,n=t.length;n>r;r++)e&&(i=fabric.copiedTextStyle[r]),this.insertChar(t[r],n-1>r,i)},insertChar:function(t,e,i){var r="\n"===this.text[this.selectionStart];this.text=this.text.slice(0,this.selectionStart)+t+this.text.slice(this.selectionEnd),this._textLines=this._splitTextIntoLines(),this.insertStyleObjects(t,r,i),this.selectionStart+=t.length,this.selectionEnd=this.selectionStart,e||(this._updateTextarea(),this.canvas&&this.canvas.renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this}))},insertNewlineStyleObject:function(e,i,r){this.shiftLineStyles(e,1),this.styles[e+1]||(this.styles[e+1]={});var n={},s={};if(this.styles[e]&&this.styles[e][i-1]&&(n=this.styles[e][i-1]),r)s[0]=t(n),this.styles[e+1]=s;else{for(var o in this.styles[e])parseInt(o,10)>=i&&(s[parseInt(o,10)-i]=this.styles[e][o],delete this.styles[e][o]);this.styles[e+1]=s}this._forceClearCache=!0},insertCharStyleObject:function(e,i,r){var n=this.styles[e],s=t(n);0!==i||r||(i=1);for(var o in s){var a=parseInt(o,10);a>=i&&(n[a+1]=s[a],s[a-1]||delete n[a])}this.styles[e][i]=r||t(n[i-1]),this._forceClearCache=!0},insertStyleObjects:function(t,e,i){var r=this.get2DCursorLocation(),n=r.lineIndex,s=r.charIndex;this._getLineStyle(n)||this._setLineStyle(n,{}),"\n"===t?this.insertNewlineStyleObject(n,s,e):this.insertCharStyleObject(n,s,i)},shiftLineStyles:function(e,i){var r=t(this.styles);for(var n in this.styles){var s=parseInt(n,10);s>e&&(this.styles[s+i]=r[s],r[s-i]||delete this.styles[s])}},removeStyleObject:function(t,e){var i=this.get2DCursorLocation(e),r=i.lineIndex,n=i.charIndex;this._removeStyleObject(t,i,r,n)},_getTextOnPreviousLine:function(t){return this._textLines[t-1]},_removeStyleObject:function(e,i,r,n){if(e){var s=this._getTextOnPreviousLine(i.lineIndex),o=s?s.length:0;this.styles[r-1]||(this.styles[r-1]={});for(n in this.styles[r])this.styles[r-1][parseInt(n,10)+o]=this.styles[r][n];this.shiftLineStyles(i.lineIndex,-1)}else{var a=this.styles[r];a&&delete a[n];var h=t(a);for(var c in h){var l=parseInt(c,10);l>=n&&0!==l&&(a[l-1]=h[l],delete a[l])}}},insertNewline:function(){this.insertChars("\n")}})}(),fabric.util.object.extend(fabric.IText.prototype,{initDoubleClickSimulation:function(){this.__lastClickTime=+new Date,this.__lastLastClickTime=+new Date,this.__lastPointer={},this.on("mousedown",this.onMouseDown.bind(this))},onMouseDown:function(t){this.__newClickTime=+new Date;var e=this.canvas.getPointer(t.e);this.isTripleClick(e)?(this.fire("tripleclick",t),this._stopEvent(t.e)):this.isDoubleClick(e)&&(this.fire("dblclick",t),this._stopEvent(t.e)),this.__lastLastClickTime=this.__lastClickTime,this.__lastClickTime=this.__newClickTime,this.__lastPointer=e,this.__lastIsEditing=this.isEditing,this.__lastSelected=this.selected},isDoubleClick:function(t){return this.__newClickTime-this.__lastClickTime<500&&this.__lastPointer.x===t.x&&this.__lastPointer.y===t.y&&this.__lastIsEditing},isTripleClick:function(t){return this.__newClickTime-this.__lastClickTime<500&&this.__lastClickTime-this.__lastLastClickTime<500&&this.__lastPointer.x===t.x&&this.__lastPointer.y===t.y},_stopEvent:function(t){t.preventDefault&&t.preventDefault(),t.stopPropagation&&t.stopPropagation()},initCursorSelectionHandlers:function(){this.initSelectedHandler(),this.initMousedownHandler(),this.initMouseupHandler(),this.initClicks()},initClicks:function(){this.on("dblclick",function(t){this.selectWord(this.getSelectionStartFromPointer(t.e))}),this.on("tripleclick",function(t){this.selectLine(this.getSelectionStartFromPointer(t.e))})},initMousedownHandler:function(){this.on("mousedown",function(t){if(this.editable){var e=this.canvas.getPointer(t.e);this.__mousedownX=e.x,this.__mousedownY=e.y,this.__isMousedown=!0,this.hiddenTextarea&&this.canvas&&this.canvas.wrapperEl.appendChild(this.hiddenTextarea),this.selected&&this.setCursorByClick(t.e),this.isEditing&&(this.__selectionStartOnMouseDown=this.selectionStart,this.initDelayedCursor(!0))}})},_isObjectMoved:function(t){var e=this.canvas.getPointer(t);return this.__mousedownX!==e.x||this.__mousedownY!==e.y},initMouseupHandler:function(){this.on("mouseup",function(t){this.__isMousedown=!1,this.editable&&!this._isObjectMoved(t.e)&&(this.__lastSelected&&!this.__corner&&(this.enterEditing(t.e),this.initDelayedCursor(!0)),this.selected=!0)})},setCursorByClick:function(t){var e=this.getSelectionStartFromPointer(t);t.shiftKey?eh;h++){i=this._textLines[h],o+=this._getHeightOfLine(this.ctx,h)*this.scaleY;var l=this._getLineWidth(this.ctx,h),u=this._getLineLeftOffset(l);s=u*this.scaleX;for(var f=0,d=i.length;d>f;f++){if(n=s,s+=this._getWidthOfChar(this.ctx,i[f],h,this.flipX?d-f:f)*this.scaleX,!(o<=r.y||s<=r.x))return this._getNewSelectionStartFromOffset(r,n,s,a+h,d);a++}if(r.ys?0:1,h=r+a;return this.flipX&&(h=n-h),h>this.text.length&&(h=this.text.length),h}}),fabric.util.object.extend(fabric.IText.prototype,{initHiddenTextarea:function(t){var e;t&&this.canvas?e=this.canvas.getPointer(t):(this.oCoords||this.setCoords(),e=this.oCoords.tl),this.hiddenTextarea=fabric.document.createElement("textarea"),this.hiddenTextarea.setAttribute("autocapitalize","off"),this.hiddenTextarea.style.cssText="position: absolute; top: "+e.y+"px; left: "+e.x+"px; opacity: 0; width: 0px; height: 0px; z-index: -999;",this.canvas?this.canvas.lowerCanvasEl.parentNode.appendChild(this.hiddenTextarea):fabric.document.body.appendChild(this.hiddenTextarea),fabric.util.addListener(this.hiddenTextarea,"keydown",this.onKeyDown.bind(this)),fabric.util.addListener(this.hiddenTextarea,"keyup",this.onKeyUp.bind(this)),fabric.util.addListener(this.hiddenTextarea,"input",this.onInput.bind(this)),fabric.util.addListener(this.hiddenTextarea,"copy",this.copy.bind(this)),fabric.util.addListener(this.hiddenTextarea,"cut",this.cut.bind(this)),fabric.util.addListener(this.hiddenTextarea,"paste",this.paste.bind(this)),fabric.util.addListener(this.hiddenTextarea,"compositionstart",this.onCompositionStart.bind(this)),fabric.util.addListener(this.hiddenTextarea,"compositionupdate",this.onCompositionUpdate.bind(this)),fabric.util.addListener(this.hiddenTextarea,"compositionend",this.onCompositionEnd.bind(this)),!this._clickHandlerInitialized&&this.canvas&&(fabric.util.addListener(this.canvas.upperCanvasEl,"click",this.onClick.bind(this)),this._clickHandlerInitialized=!0)},_keysMap:{8:"removeChars",9:"exitEditing",27:"exitEditing",13:"insertNewline",33:"moveCursorUp",34:"moveCursorDown",35:"moveCursorRight",36:"moveCursorLeft",37:"moveCursorLeft",38:"moveCursorUp",39:"moveCursorRight",40:"moveCursorDown",46:"forwardDelete"},_ctrlKeysMap:{65:"selectAll",67:"copy",88:"cut"},onClick:function(){this.hiddenTextarea&&this.hiddenTextarea.focus()},onKeyDown:function(t){this.isEditing&&t.keyCode in this._keysMap&&(this[this._keysMap[t.keyCode]](t),t.stopImmediatePropagation(),t.preventDefault(),this.canvas&&this.canvas.renderAll())},onKeyUp:function(t){return!this.isEditing||this._copyDone?void(this._copyDone=!1):void(t.keyCode in this._ctrlKeysMap&&(t.ctrlKey||t.metaKey)&&(this[this._ctrlKeysMap[t.keyCode]](t),t.stopImmediatePropagation(),t.preventDefault(),this.canvas&&this.canvas.renderAll()))},onInput:function(t){if(this.isEditing&&!this.inCompositionMode){var e,i,r,n=this.selectionStart||0,s=this.selectionEnd||0,o=this.text.length,a=this.hiddenTextarea.value.length;a>o?(r="left"===this._selectionDirection?s:n,e=a-o,i=this.hiddenTextarea.value.slice(r,r+e)):(e=a-o+s-n,i=this.hiddenTextarea.value.slice(n,n+e)),this.insertChars(i),t.stopPropagation()}},onCompositionStart:function(){this.inCompositionMode=!0,this.prevCompositionLength=0,this.compositionStart=this.selectionStart},onCompositionEnd:function(){this.inCompositionMode=!1},onCompositionUpdate:function(t){var e=t.data;this.selectionStart=this.compositionStart,this.selectionEnd=this.selectionEnd===this.selectionStart?this.compositionStart+this.prevCompositionLength:this.selectionEnd,this.insertChars(e,!1),this.prevCompositionLength=e.length},forwardDelete:function(t){if(this.selectionStart===this.selectionEnd){if(this.selectionStart===this.text.length)return;this.moveCursorRight(t)}this.removeChars(t)},copy:function(t){if(this.selectionStart!==this.selectionEnd){var e=this.getSelectedText(),i=this._getClipboardData(t);i&&i.setData("text",e),fabric.copiedText=e,fabric.copiedTextStyle=this.getSelectionStyles(this.selectionStart,this.selectionEnd),t.stopImmediatePropagation(),t.preventDefault(),this._copyDone=!0}},paste:function(t){var e=null,i=this._getClipboardData(t),r=!0;i?(e=i.getData("text").replace(/\r/g,""),fabric.copiedTextStyle&&fabric.copiedText===e||(r=!1)):e=fabric.copiedText,e&&this.insertChars(e,r),t.stopImmediatePropagation(),t.preventDefault(); + +},cut:function(t){this.selectionStart!==this.selectionEnd&&(this.copy(t),this.removeChars(t))},_getClipboardData:function(t){return t&&t.clipboardData||fabric.window.clipboardData},getDownCursorOffset:function(t,e){var i,r,n=e?this.selectionEnd:this.selectionStart,s=this.get2DCursorLocation(n),o=s.lineIndex,a=this._textLines[o].slice(0,s.charIndex),h=this._textLines[o].slice(s.charIndex),c=this._textLines[o+1]||"";if(o===this._textLines.length-1||t.metaKey||34===t.keyCode)return this.text.length-n;var l=this._getLineWidth(this.ctx,o);r=this._getLineLeftOffset(l);for(var u=r,f=0,d=a.length;d>f;f++)i=a[f],u+=this._getWidthOfChar(this.ctx,i,o,f);var g=this._getIndexOnNextLine(s,c,u);return h.length+1+g},_getIndexOnNextLine:function(t,e,i){for(var r,n=t.lineIndex+1,s=this._getLineWidth(this.ctx,n),o=this._getLineLeftOffset(s),a=o,h=0,c=0,l=e.length;l>c;c++){var u=e[c],f=this._getWidthOfChar(this.ctx,u,n,c);if(a+=f,a>i){r=!0;var d=a-f,g=a,p=Math.abs(d-i),v=Math.abs(g-i);h=p>v?c+1:c;break}}return r||(h=e.length),h},moveCursorDown:function(t){this.abortCursorAnimation(),this._currentCursorOpacity=1;var e=this.getDownCursorOffset(t,"right"===this._selectionDirection);t.shiftKey?this.moveCursorDownWithShift(e):this.moveCursorDownWithoutShift(e),this.initDelayedCursor()},moveCursorDownWithoutShift:function(t){this._selectionDirection="right",this.setSelectionStart(this.selectionStart+t),this.setSelectionEnd(this.selectionStart)},swapSelectionPoints:function(){var t=this.selectionEnd;this.setSelectionEnd(this.selectionStart),this.setSelectionStart(t)},moveCursorDownWithShift:function(t){this.selectionEnd===this.selectionStart&&(this._selectionDirection="right"),"right"===this._selectionDirection?this.setSelectionEnd(this.selectionEnd+t):this.setSelectionStart(this.selectionStart+t),this.selectionEndthis.text.length&&this.setSelectionEnd(this.text.length)},getUpCursorOffset:function(t,e){var i=e?this.selectionEnd:this.selectionStart,r=this.get2DCursorLocation(i),n=r.lineIndex;if(0===n||t.metaKey||33===t.keyCode)return i;for(var s,o=this._textLines[n].slice(0,r.charIndex),a=this._textLines[n-1]||"",h=this._getLineWidth(this.ctx,r.lineIndex),c=this._getLineLeftOffset(h),l=c,u=0,f=o.length;f>u;u++)s=o[u],l+=this._getWidthOfChar(this.ctx,s,n,u);var d=this._getIndexOnPrevLine(r,a,l);return a.length-d+o.length},_getIndexOnPrevLine:function(t,e,i){for(var r,n=t.lineIndex-1,s=this._getLineWidth(this.ctx,n),o=this._getLineLeftOffset(s),a=o,h=0,c=0,l=e.length;l>c;c++){var u=e[c],f=this._getWidthOfChar(this.ctx,u,n,c);if(a+=f,a>i){r=!0;var d=a-f,g=a,p=Math.abs(d-i),v=Math.abs(g-i);h=p>v?c:c-1;break}}return r||(h=e.length-1),h},moveCursorUp:function(t){this.abortCursorAnimation(),this._currentCursorOpacity=1;var e=this.getUpCursorOffset(t,"right"===this._selectionDirection);t.shiftKey?this.moveCursorUpWithShift(e):this.moveCursorUpWithoutShift(e),this.initDelayedCursor()},moveCursorUpWithShift:function(t){this.selectionEnd===this.selectionStart&&(this._selectionDirection="left"),"right"===this._selectionDirection?this.setSelectionEnd(this.selectionEnd-t):this.setSelectionStart(this.selectionStart-t),this.selectionEnd=this.text.length&&this.selectionEnd>=this.text.length||(this.abortCursorAnimation(),this._currentCursorOpacity=1,t.shiftKey?this.moveCursorRightWithShift(t):this.moveCursorRightWithoutShift(t),this.initDelayedCursor())},moveCursorRightWithShift:function(t){"left"===this._selectionDirection&&this.selectionStart!==this.selectionEnd?this._moveRight(t,"selectionStart"):(this._selectionDirection="right",this._moveRight(t,"selectionEnd"))},moveCursorRightWithoutShift:function(t){this._selectionDirection="right",this.selectionStart===this.selectionEnd?(this._moveRight(t,"selectionStart"),this.setSelectionEnd(this.selectionStart)):(this.setSelectionEnd(this.selectionEnd+this.getNumNewLinesInSelectedText()),this.setSelectionStart(this.selectionEnd))},removeChars:function(t){this.selectionStart===this.selectionEnd?this._removeCharsNearCursor(t):this._removeCharsFromTo(this.selectionStart,this.selectionEnd),this.setSelectionEnd(this.selectionStart),this._removeExtraneousStyles(),this.canvas&&this.canvas.renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this})},_removeCharsNearCursor:function(t){if(0!==this.selectionStart)if(t.metaKey){var e=this.findLineBoundaryLeft(this.selectionStart);this._removeCharsFromTo(e,this.selectionStart),this.setSelectionStart(e)}else if(t.altKey){var i=this.findWordBoundaryLeft(this.selectionStart);this._removeCharsFromTo(i,this.selectionStart),this.setSelectionStart(i)}else this._removeSingleCharAndStyle(this.selectionStart),this.setSelectionStart(this.selectionStart-1)}}),function(){var t=fabric.util.toFixed,e=fabric.Object.NUM_FRACTION_DIGITS;fabric.util.object.extend(fabric.IText.prototype,{_setSVGTextLineText:function(t,e,i,r,n,s){this._getLineStyle(t)?this._setSVGTextLineChars(t,e,i,r,s):fabric.Text.prototype._setSVGTextLineText.call(this,t,e,i,r,n)},_setSVGTextLineChars:function(t,e,i,r,n){for(var s=this._textLines[t],o=0,a=this._getLineLeftOffset(this._getLineWidth(this.ctx,t))-this.width/2,h=this._getSVGLineTopOffset(t),c=this._getHeightOfLine(this.ctx,t),l=0,u=s.length;u>l;l++){var f=this._getStyleDeclaration(t,l)||{};e.push(this._createTextCharSpan(s[l],f,a,h.lineTop+h.offset,o));var d=this._getWidthOfChar(this.ctx,s[l],t,l);f.textBackgroundColor&&n.push(this._createTextCharBg(f,a,h.lineTop,c,d,o)),o+=d}},_getSVGLineTopOffset:function(t){for(var e=0,i=0,r=0;t>r;r++)e+=this._getHeightOfLine(this.ctx,r);return i=this._getHeightOfLine(this.ctx,r),{lineTop:e,offset:(this._fontSizeMult-this._fontSizeFraction)*i/(this.lineHeight*this._fontSizeMult)}},_createTextCharBg:function(i,r,n,s,o,a){return[' \n'].join("")},_createTextCharSpan:function(i,r,n,s,o){var a=this.getSvgStyles.call(fabric.util.object.extend({visible:!0,fill:this.fill,stroke:this.stroke,type:"text",getSvgFilter:fabric.Object.prototype.getSvgFilter},r));return[' ',fabric.util.string.escapeXml(i),"\n"].join("")}})}(),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.clone;e.Textbox=e.util.createClass(e.IText,e.Observable,{type:"textbox",minWidth:20,dynamicMinWidth:0,__cachedLines:null,initialize:function(t,i){this.ctx=e.util.createCanvasElement().getContext("2d"),this.callSuper("initialize",t,i),this.set({lockUniScaling:!1,lockScalingY:!0,lockScalingFlip:!0,hasBorders:!0}),this.setControlsVisibility(e.Textbox.getTextboxControlVisibility()),this._dimensionAffectingProps.width=!0},_initDimensions:function(t){this.__skipDimension||(t||(t=e.util.createCanvasElement().getContext("2d"),this._setTextStyles(t)),this.dynamicMinWidth=0,this._textLines=this._splitTextIntoLines(),this.dynamicMinWidth>this.width&&this._set("width",this.dynamicMinWidth),this._clearCache(),this.height=this._getTextHeight(t))},_generateStyleMap:function(){for(var t=0,e=0,i=0,r={},n=0;ns;s++)n+=this._getWidthOfChar(t,e[s],i,s+r);return n},_wrapLine:function(t,e,i){for(var r=0,n=[],s="",o=e.split(" "),a="",h=0,c=" ",l=0,u=0,f=0,d=!0,g=0;g=this.width&&!d&&(n.push(s),s="",r=l,d=!0),d||(s+=c),s+=a,u=this._measureText(t,c,i,h),h++,d=!1,l>f&&(f=l);return g&&n.push(s),f>this.dynamicMinWidth&&(this.dynamicMinWidth=f),n},_splitTextIntoLines:function(){var t=this.textAlign;this.ctx.save(),this._setTextStyles(this.ctx),this.textAlign="left";var e=this._wrapText(this.ctx,this.text);return this.textAlign=t,this.ctx.restore(),this._textLines=e,this._styleMap=this._generateStyleMap(),e},setOnGroup:function(t,e){"scaleX"===t&&(this.set("scaleX",Math.abs(1/e)),this.set("width",this.get("width")*e/("undefined"==typeof this.__oldScaleX?1:this.__oldScaleX)),this.__oldScaleX=e)},get2DCursorLocation:function(t){"undefined"==typeof t&&(t=this.selectionStart);for(var e=this._textLines.length,i=0,r=0;e>r;r++){var n=this._textLines[r],s=n.length;if(i+s>=t)return{lineIndex:r,charIndex:t-i};i+=s,("\n"===this.text[i]||" "===this.text[i])&&i++}return{lineIndex:e-1,charIndex:this._textLines[e-1].length}},_getCursorBoundariesOffsets:function(t,e){for(var i=0,r=0,n=this.get2DCursorLocation(),s=this._textLines[n.lineIndex].split(""),o=this._getLineLeftOffset(this._getLineWidth(this.ctx,n.lineIndex)),a=0;a=h.getMinWidth()?(h.set("width",c),!0):void 0},fabric.Group.prototype._refreshControlsVisibility=function(){if("undefined"!=typeof fabric.Textbox)for(var t=this._objects.length;t--;)if(this._objects[t]instanceof fabric.Textbox)return void this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility())};var e=fabric.util.object.clone;fabric.util.object.extend(fabric.Textbox.prototype,{_removeExtraneousStyles:function(){for(var t in this._styleMap)this._textLines[t]||delete this.styles[this._styleMap[t].line]},insertCharStyleObject:function(t,e,i){var r=this._styleMap[t];t=r.line,e=r.offset+e,fabric.IText.prototype.insertCharStyleObject.apply(this,[t,e,i])},insertNewlineStyleObject:function(t,e,i){var r=this._styleMap[t];t=r.line,e=r.offset+e,fabric.IText.prototype.insertNewlineStyleObject.apply(this,[t,e,i])},shiftLineStyles:function(t,i){var r=e(this.styles),n=this._styleMap[t];t=n.line;for(var s in this.styles){var o=parseInt(s,10);o>t&&(this.styles[o+i]=r[o],r[o-i]||delete this.styles[o])}},_getTextOnPreviousLine:function(t){for(var e=this._textLines[t-1];this._styleMap[t-2]&&this._styleMap[t-2].line===this._styleMap[t-1].line;)e=this._textLines[t-2]+e,t--;return e},removeStyleObject:function(t,e){var i=this.get2DCursorLocation(e),r=this._styleMap[i.lineIndex],n=r.line,s=r.offset+i.charIndex;this._removeStyleObject(t,i,n,s)}})}(),function(){var t=fabric.IText.prototype._getNewSelectionStartFromOffset;fabric.IText.prototype._getNewSelectionStartFromOffset=function(e,i,r,n,s){n=t.call(this,e,i,r,n,s);for(var o=0,a=0,h=0;h=n));h++)("\n"===this.text[o+a]||" "===this.text[o+a])&&a++;return n-h+a}}(),function(){function request(t,e,i){var r=URL.parse(t);r.port||(r.port=0===r.protocol.indexOf("https:")?443:80);var n=0===r.protocol.indexOf("https:")?HTTPS:HTTP,s=n.request({hostname:r.hostname,port:r.port,path:r.path,method:"GET"},function(t){var r="";e&&t.setEncoding(e),t.on("end",function(){i(r)}),t.on("data",function(e){200===t.statusCode&&(r+=e)})});s.on("error",function(t){fabric.log(t.errno===process.ECONNREFUSED?"ECONNREFUSED: connection refused to "+r.hostname+":"+r.port:t.message),i(null)}),s.end()}function requestFs(t,e){var i=require("fs");i.readFile(t,function(t,i){if(t)throw fabric.log(t),t;e(i)})}if("undefined"==typeof document||"undefined"==typeof window){var DOMParser=require("xmldom").DOMParser,URL=require("url"),HTTP=require("http"),HTTPS=require("https"),Canvas=require("canvas"),Image=require("canvas").Image;fabric.util.loadImage=function(t,e,i){function r(r){r?(n.src=new Buffer(r,"binary"),n._src=t,e&&e.call(i,n)):(n=null,e&&e.call(i,null,!0))}var n=new Image;t&&(t instanceof Buffer||0===t.indexOf("data"))?(n.src=n._src=t,e&&e.call(i,n)):t&&0!==t.indexOf("http")?requestFs(t,r):t?request(t,"binary",r):e&&e.call(i,t)},fabric.loadSVGFromURL=function(t,e,i){t=t.replace(/^\n\s*/,"").replace(/\?.*$/,"").trim(),0!==t.indexOf("http")?requestFs(t,function(t){fabric.loadSVGFromString(t.toString(),e,i)}):request(t,"",function(t){fabric.loadSVGFromString(t,e,i)})},fabric.loadSVGFromString=function(t,e,i){var r=(new DOMParser).parseFromString(t);fabric.parseSVGDocument(r.documentElement,function(t,i){e&&e(t,i)},i)},fabric.util.getScript=function(url,callback){request(url,"",function(body){eval(body),callback&&callback()})},fabric.Image.fromObject=function(t,e){fabric.util.loadImage(t.src,function(i){var r=new fabric.Image(i);r._initConfig(t),r._initFilters(t.filters,function(i){r.filters=i||[],r._initFilters(t.resizeFilters,function(t){r.resizeFilters=t||[],e&&e(r)})})})},fabric.createCanvasForNode=function(t,e,i,r){r=r||i;var n=fabric.document.createElement("canvas"),s=new Canvas(t||600,e||600,r);n.style={},n.width=s.width,n.height=s.height;var o=fabric.Canvas||fabric.StaticCanvas,a=new o(n,i);return a.contextContainer=s.getContext("2d"),a.nodeCanvas=s,a.Font=Canvas.Font,a},fabric.StaticCanvas.prototype.createPNGStream=function(){return this.nodeCanvas.createPNGStream()},fabric.StaticCanvas.prototype.createJPEGStream=function(t){return this.nodeCanvas.createJPEGStream(t)};var origSetWidth=fabric.StaticCanvas.prototype.setWidth;fabric.StaticCanvas.prototype.setWidth=function(t,e){return origSetWidth.call(this,t,e),this.nodeCanvas.width=t,this},fabric.Canvas&&(fabric.Canvas.prototype.setWidth=fabric.StaticCanvas.prototype.setWidth);var origSetHeight=fabric.StaticCanvas.prototype.setHeight;fabric.StaticCanvas.prototype.setHeight=function(t,e){return origSetHeight.call(this,t,e),this.nodeCanvas.height=t,this},fabric.Canvas&&(fabric.Canvas.prototype.setHeight=fabric.StaticCanvas.prototype.setHeight)}}(); \ No newline at end of file diff --git a/dist/fabric.min.js.gz b/dist/fabric.min.js.gz index f1b66aef..4f04c711 100644 Binary files a/dist/fabric.min.js.gz and b/dist/fabric.min.js.gz differ diff --git a/dist/fabric.require.js b/dist/fabric.require.js index f07e6a86..24244cf3 100644 --- a/dist/fabric.require.js +++ b/dist/fabric.require.js @@ -1,11 +1,11895 @@ -var fabric=fabric||{version:"1.6.0"};if(typeof exports!=="undefined"){exports.fabric=fabric}if(typeof document!=="undefined"&&typeof window!=="undefined"){fabric.document=document;fabric.window=window;window.fabric=fabric}else{fabric.document=require("jsdom").jsdom("");if(fabric.document.createWindow){fabric.window=fabric.document.createWindow()}else{fabric.window=fabric.document.parentWindow}}fabric.isTouchSupported="ontouchstart"in fabric.document.documentElement;fabric.isLikelyNode=typeof Buffer!=="undefined"&&typeof window==="undefined";fabric.SHARED_ATTRIBUTES=["display","transform","fill","fill-opacity","fill-rule","opacity","stroke","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","id"];fabric.DPI=96;fabric.reNum="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)";fabric.fontPaths={};fabric.devicePixelRatio=fabric.window.devicePixelRatio||fabric.window.webkitDevicePixelRatio||fabric.window.mozDevicePixelRatio||1;if(typeof JSON!=="object"){JSON={}}(function(){"use strict";function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()}}var cx,escapable,gap,indent,meta,rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i-1},complexity:function(){return this.getObjects().reduce(function(memo,current){memo+=current.complexity?current.complexity():0;return memo},0)}};(function(global){var sqrt=Math.sqrt,atan2=Math.atan2,pow=Math.pow,abs=Math.abs,PiBy180=Math.PI/180;fabric.util={removeFromArray:function(array,value){var idx=array.indexOf(value);if(idx!==-1){array.splice(idx,1)}return array},getRandomInt:function(min,max){return Math.floor(Math.random()*(max-min+1))+min},degreesToRadians:function(degrees){return degrees*PiBy180},radiansToDegrees:function(radians){return radians/PiBy180},rotatePoint:function(point,origin,radians){point.subtractEquals(origin);var v=fabric.util.rotateVector(point,radians);return new fabric.Point(v.x,v.y).addEquals(origin)},rotateVector:function(vector,radians){var sin=Math.sin(radians),cos=Math.cos(radians),rx=vector.x*cos-vector.y*sin,ry=vector.x*sin+vector.y*cos;return{x:rx,y:ry}},transformPoint:function(p,t,ignoreOffset){if(ignoreOffset){return new fabric.Point(t[0]*p.x+t[2]*p.y,t[1]*p.x+t[3]*p.y)}return new fabric.Point(t[0]*p.x+t[2]*p.y+t[4],t[1]*p.x+t[3]*p.y+t[5])},makeBoundingBoxFromPoints:function(points){var xPoints=[points[0].x,points[1].x,points[2].x,points[3].x],minX=fabric.util.array.min(xPoints),maxX=fabric.util.array.max(xPoints),width=Math.abs(minX-maxX),yPoints=[points[0].y,points[1].y,points[2].y,points[3].y],minY=fabric.util.array.min(yPoints),maxY=fabric.util.array.max(yPoints),height=Math.abs(minY-maxY);return{left:minX,top:minY,width:width,height:height}},invertTransform:function(t){var a=1/(t[0]*t[3]-t[1]*t[2]),r=[a*t[3],-a*t[1],-a*t[2],a*t[0]],o=fabric.util.transformPoint({x:t[4],y:t[5]},r,true);r[4]=-o.x;r[5]=-o.y;return r},toFixed:function(number,fractionDigits){return parseFloat(Number(number).toFixed(fractionDigits))},parseUnit:function(value,fontSize){var unit=/\D{0,2}$/.exec(value),number=parseFloat(value);if(!fontSize){fontSize=fabric.Text.DEFAULT_SVG_FONT_SIZE}switch(unit[0]){case"mm":return number*fabric.DPI/25.4;case"cm":return number*fabric.DPI/2.54;case"in":return number*fabric.DPI;case"pt":return number*fabric.DPI/72;case"pc":return number*fabric.DPI/72*12;case"em":return number*fontSize;default:return number}},falseFunction:function(){return false},getKlass:function(type,namespace){type=fabric.util.string.camelize(type.charAt(0).toUpperCase()+type.slice(1));return fabric.util.resolveNamespace(namespace)[type]},resolveNamespace:function(namespace){if(!namespace){return fabric}var parts=namespace.split("."),len=parts.length,obj=global||fabric.window;for(var i=0;ix){x+=da[di++%dc];if(x>len){x=len}ctx[draw?"lineTo":"moveTo"](x,0);draw=!draw}ctx.restore()},createCanvasElement:function(canvasEl){canvasEl||(canvasEl=fabric.document.createElement("canvas"));if(!canvasEl.getContext&&typeof G_vmlCanvasManager!=="undefined"){G_vmlCanvasManager.initElement(canvasEl)}return canvasEl},createImage:function(){return fabric.isLikelyNode?new(require("canvas").Image):fabric.document.createElement("img")},createAccessors:function(klass){var proto=klass.prototype;for(var i=proto.stateProperties.length;i--;){var propName=proto.stateProperties[i],capitalizedPropName=propName.charAt(0).toUpperCase()+propName.slice(1),setterName="set"+capitalizedPropName,getterName="get"+capitalizedPropName;if(!proto[getterName]){proto[getterName]=function(property){return new Function('return this.get("'+property+'")')}(propName)}if(!proto[setterName]){proto[setterName]=function(property){return new Function("value",'return this.set("'+property+'", value)')}(propName)}}},clipContext:function(receiver,ctx){ctx.save();ctx.beginPath();receiver.clipTo(ctx);ctx.clip()},multiplyTransformMatrices:function(a,b,is2x2){return[a[0]*b[0]+a[2]*b[1],a[1]*b[0]+a[3]*b[1],a[0]*b[2]+a[2]*b[3],a[1]*b[2]+a[3]*b[3],is2x2?0:a[0]*b[4]+a[2]*b[5]+a[4],is2x2?0:a[1]*b[4]+a[3]*b[5]+a[5]]},qrDecompose:function(a){var angle=atan2(a[1],a[0]),denom=pow(a[0],2)+pow(a[1],2),scaleX=sqrt(denom),scaleY=(a[0]*a[3]-a[2]*a[1])/scaleX,skewX=atan2(a[0]*a[2]+a[1]*a[3],denom);return{angle:angle/PiBy180,scaleX:scaleX,scaleY:scaleY,skewX:skewX/PiBy180,skewY:0,translateX:a[4],translateY:a[5]}},customTransformMatrix:function(scaleX,scaleY,skewX){var skewMatrixX=[1,0,abs(Math.tan(skewX*PiBy180)),1],scaleMatrix=[abs(scaleX),0,0,abs(scaleY)];return fabric.util.multiplyTransformMatrices(scaleMatrix,skewMatrixX,true)},resetObjectTransform:function(target){target.scaleX=1;target.scaleY=1;target.skewX=0;target.skewY=0;target.flipX=false;target.flipY=false;target.setAngle(0)},getFunctionBody:function(fn){return(String(fn).match(/function[^{]*\{([\s\S]*)\}/)||{})[1]},isTransparent:function(ctx,x,y,tolerance){if(tolerance>0){if(x>tolerance){x-=tolerance}else{x=0}if(y>tolerance){y-=tolerance}else{y=0}}var _isTransparent=true,imageData=ctx.getImageData(x,y,tolerance*2||1,tolerance*2||1);for(var i=3,l=imageData.data.length;i0){dtheta-=2*PI}else if(sweep===1&&dtheta<0){dtheta+=2*PI}var segments=Math.ceil(Math.abs(dtheta/PI*2)),result=[],mDelta=dtheta/segments,mT=8/3*Math.sin(mDelta/4)*Math.sin(mDelta/4)/Math.sin(mDelta/2),th3=mTheta+mDelta;for(var i=0;i=ta){return tb-ta}else{return 2*Math.PI-(ta-tb)}}fabric.util.drawArc=function(ctx,fx,fy,coords){var rx=coords[0],ry=coords[1],rot=coords[2],large=coords[3],sweep=coords[4],tx=coords[5],ty=coords[6],segs=[[],[],[],[]],segsNorm=arcToSegments(tx-fx,ty-fy,rx,ry,large,sweep,rot);for(var i=0,len=segsNorm.length;i0){b=6*y0-12*y1+6*y2;a=-3*y0+9*y1-9*y2+3*y3;c=3*y1-3*y0}if(abs(a)<1e-12){if(abs(b)<1e-12){continue}t=-c/b;if(0>>0;if(len===0){return-1}var n=0;if(arguments.length>0){n=Number(arguments[1]);if(n!==n){n=0}else if(n!==0&&n!==Number.POSITIVE_INFINITY&&n!==Number.NEGATIVE_INFINITY){n=(n>0||-1)*Math.floor(Math.abs(n))}}if(n>=len){return-1}var k=n>=0?n:Math.max(len-Math.abs(n),0);for(;k>>0;i>>0;i>>0;i>>0;i>>0;i>>0,i=0,rv;if(arguments.length>1){rv=arguments[1]}else{do{if(i in this){rv=this[i++];break}if(++i>=len){throw new TypeError}}while(true)}for(;i=value2})}function min(array,byProperty){return find(array,byProperty,function(value1,value2){return value1/g,">")}fabric.util.string={camelize:camelize,capitalize:capitalize,escapeXml:escapeXml}})();(function(){var slice=Array.prototype.slice,apply=Function.prototype.apply,Dummy=function(){};if(!Function.prototype.bind){Function.prototype.bind=function(thisArg){var _this=this,args=slice.call(arguments,1),bound;if(args.length){bound=function(){return apply.call(_this,this instanceof Dummy?this:thisArg,args.concat(slice.call(arguments)))}}else{bound=function(){return apply.call(_this,this instanceof Dummy?this:thisArg,arguments)}}Dummy.prototype=this.prototype;bound.prototype=new Dummy;return bound}}})();(function(){var slice=Array.prototype.slice,emptyFunction=function(){},IS_DONTENUM_BUGGY=function(){for(var p in{toString:1}){if(p==="toString"){return false}}return true}(),addMethods=function(klass,source,parent){for(var property in source){if(property in klass.prototype&&typeof klass.prototype[property]==="function"&&(source[property]+"").indexOf("callSuper")>-1){klass.prototype[property]=function(property){return function(){var superclass=this.constructor.superclass;this.constructor.superclass=parent;var returnValue=source[property].apply(this,arguments);this.constructor.superclass=superclass;if(property!=="initialize"){return returnValue}}}(property)}else{klass.prototype[property]=source[property]}if(IS_DONTENUM_BUGGY){if(source.toString!==Object.prototype.toString){klass.prototype.toString=source.toString}if(source.valueOf!==Object.prototype.valueOf){klass.prototype.valueOf=source.valueOf}}}};function Subclass(){}function callSuper(methodName){var fn=this.constructor.superclass.prototype[methodName];return arguments.length>1?fn.apply(this,slice.call(arguments,1)):fn.call(this)}function createClass(){var parent=null,properties=slice.call(arguments,0);if(typeof properties[0]==="function"){parent=properties.shift()}function klass(){this.initialize.apply(this,arguments)}klass.superclass=parent;klass.subclasses=[];if(parent){Subclass.prototype=parent.prototype;klass.prototype=new Subclass;parent.subclasses.push(klass)}for(var i=0,length=properties.length;i-1?setOpacity(element,styles.match(/opacity:\s*(\d?\.?\d*)/)[1]):element}for(var property in styles){if(property==="opacity"){setOpacity(element,styles[property])}else{var normalizedProperty=property==="float"||property==="cssFloat"?typeof elementStyle.styleFloat==="undefined"?"cssFloat":"styleFloat":property;elementStyle[normalizedProperty]=styles[property]}}return element}var parseEl=fabric.document.createElement("div"),supportsOpacity=typeof parseEl.style.opacity==="string",supportsFilters=typeof parseEl.style.filter==="string",reOpacity=/alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,setOpacity=function(element){return element};if(supportsOpacity){setOpacity=function(element,value){element.style.opacity=value;return element}}else if(supportsFilters){setOpacity=function(element,value){var es=element.style;if(element.currentStyle&&!element.currentStyle.hasLayout){es.zoom=1}if(reOpacity.test(es.filter)){value=value>=.9999?"":"alpha(opacity="+value*100+")";es.filter=es.filter.replace(reOpacity,value)}else{es.filter+=" alpha(opacity="+value*100+")"}return element}}fabric.util.setStyle=setStyle})();(function(){var _slice=Array.prototype.slice;function getById(id){return typeof id==="string"?fabric.document.getElementById(id):id}var sliceCanConvertNodelists,toArray=function(arrayLike){return _slice.call(arrayLike,0)};try{sliceCanConvertNodelists=toArray(fabric.document.childNodes)instanceof Array}catch(err){}if(!sliceCanConvertNodelists){toArray=function(arrayLike){var arr=new Array(arrayLike.length),i=arrayLike.length;while(i--){arr[i]=arrayLike[i]}return arr}}function makeElement(tagName,attributes){var el=fabric.document.createElement(tagName);for(var prop in attributes){if(prop==="class"){el.className=attributes[prop]}else if(prop==="for"){el.htmlFor=attributes[prop]}else{el.setAttribute(prop,attributes[prop])}}return el}function addClass(element,className){if(element&&(" "+element.className+" ").indexOf(" "+className+" ")===-1){element.className+=(element.className?" ":"")+className}}function wrapElement(element,wrapper,attributes){if(typeof wrapper==="string"){wrapper=makeElement(wrapper,attributes)}if(element.parentNode){element.parentNode.replaceChild(wrapper,element)}wrapper.appendChild(element);return wrapper}function getScrollLeftTop(element){var left=0,top=0,docElement=fabric.document.documentElement,body=fabric.document.body||{scrollLeft:0,scrollTop:0};while(element&&(element.parentNode||element.host)){element=element.parentNode||element.host;if(element===fabric.document){left=body.scrollLeft||docElement.scrollLeft||0;top=body.scrollTop||docElement.scrollTop||0}else{left+=element.scrollLeft||0;top+=element.scrollTop||0}if(element.nodeType===1&&fabric.util.getElementStyle(element,"position")==="fixed"){break}}return{left:left,top:top}}function getElementOffset(element){var docElem,doc=element&&element.ownerDocument,box={left:0,top:0},offset={left:0,top:0},scrollLeftTop,offsetAttributes={borderLeftWidth:"left",borderTopWidth:"top",paddingLeft:"left",paddingTop:"top"};if(!doc){return offset}for(var attr in offsetAttributes){offset[offsetAttributes[attr]]+=parseInt(getElementStyle(element,attr),10)||0}docElem=doc.documentElement;if(typeof element.getBoundingClientRect!=="undefined"){box=element.getBoundingClientRect() -}scrollLeftTop=getScrollLeftTop(element);return{left:box.left+scrollLeftTop.left-(docElem.clientLeft||0)+offset.left,top:box.top+scrollLeftTop.top-(docElem.clientTop||0)+offset.top}}var getElementStyle;if(fabric.document.defaultView&&fabric.document.defaultView.getComputedStyle){getElementStyle=function(element,attr){var style=fabric.document.defaultView.getComputedStyle(element,null);return style?style[attr]:undefined}}else{getElementStyle=function(element,attr){var value=element.style[attr];if(!value&&element.currentStyle){value=element.currentStyle[attr]}return value}}(function(){var style=fabric.document.documentElement.style,selectProp="userSelect"in style?"userSelect":"MozUserSelect"in style?"MozUserSelect":"WebkitUserSelect"in style?"WebkitUserSelect":"KhtmlUserSelect"in style?"KhtmlUserSelect":"";function makeElementUnselectable(element){if(typeof element.onselectstart!=="undefined"){element.onselectstart=fabric.util.falseFunction}if(selectProp){element.style[selectProp]="none"}else if(typeof element.unselectable==="string"){element.unselectable="on"}return element}function makeElementSelectable(element){if(typeof element.onselectstart!=="undefined"){element.onselectstart=null}if(selectProp){element.style[selectProp]=""}else if(typeof element.unselectable==="string"){element.unselectable=""}return element}fabric.util.makeElementUnselectable=makeElementUnselectable;fabric.util.makeElementSelectable=makeElementSelectable})();(function(){function getScript(url,callback){var headEl=fabric.document.getElementsByTagName("head")[0],scriptEl=fabric.document.createElement("script"),loading=true;scriptEl.onload=scriptEl.onreadystatechange=function(e){if(loading){if(typeof this.readyState==="string"&&this.readyState!=="loaded"&&this.readyState!=="complete"){return}loading=false;callback(e||fabric.window.event);scriptEl=scriptEl.onload=scriptEl.onreadystatechange=null}};scriptEl.src=url;headEl.appendChild(scriptEl)}fabric.util.getScript=getScript})();fabric.util.getById=getById;fabric.util.toArray=toArray;fabric.util.makeElement=makeElement;fabric.util.addClass=addClass;fabric.util.wrapElement=wrapElement;fabric.util.getScrollLeftTop=getScrollLeftTop;fabric.util.getElementOffset=getElementOffset;fabric.util.getElementStyle=getElementStyle})();(function(){function addParamToUrl(url,param){return url+(/\?/.test(url)?"&":"?")+param}var makeXHR=function(){var factories=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP.3.0")},function(){return new XMLHttpRequest}];for(var i=factories.length;i--;){try{var req=factories[i]();if(req){return factories[i]}}catch(err){}}}();function emptyFn(){}function request(url,options){options||(options={});var method=options.method?options.method.toUpperCase():"GET",onComplete=options.onComplete||function(){},xhr=makeXHR(),body;xhr.onreadystatechange=function(){if(xhr.readyState===4){onComplete(xhr);xhr.onreadystatechange=emptyFn}};if(method==="GET"){body=null;if(typeof options.parameters==="string"){url=addParamToUrl(url,options.parameters)}}xhr.open(method,url,true);if(method==="POST"||method==="PUT"){xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")}xhr.send(body);return xhr}fabric.util.request=request})();fabric.log=function(){};fabric.warn=function(){};if(typeof console!=="undefined"){["log","warn"].forEach(function(methodName){if(typeof console[methodName]!=="undefined"&&typeof console[methodName].apply==="function"){fabric[methodName]=function(){return console[methodName].apply(console,arguments)}}})}(function(){function animate(options){requestAnimFrame(function(timestamp){options||(options={});var start=timestamp||+new Date,duration=options.duration||500,finish=start+duration,time,onChange=options.onChange||function(){},abort=options.abort||function(){return false},easing=options.easing||function(t,b,c,d){return-c*Math.cos(t/d*(Math.PI/2))+c+b},startValue="startValue"in options?options.startValue:0,endValue="endValue"in options?options.endValue:100,byValue=options.byValue||endValue-startValue;options.onStart&&options.onStart();(function tick(ticktime){time=ticktime||+new Date;var currentTime=time>finish?duration:time-start;if(abort()){options.onComplete&&options.onComplete();return}onChange(easing(currentTime,startValue,byValue,duration));if(time>finish){options.onComplete&&options.onComplete();return}requestAnimFrame(tick)})(start)})}var _requestAnimFrame=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(callback){fabric.window.setTimeout(callback,1e3/60)};function requestAnimFrame(){return _requestAnimFrame.apply(fabric.window,arguments)}fabric.util.animate=animate;fabric.util.requestAnimFrame=requestAnimFrame})();(function(){function normalize(a,c,p,s){if(a1){matrices.shift();combinedMatrix=fabric.util.multiplyTransformMatrices(combinedMatrix,matrices[0])}return combinedMatrix}}();function parseStyleString(style,oStyle){var attr,value;style.replace(/;\s*$/,"").split(";").forEach(function(chunk){var pair=chunk.split(":");attr=normalizeAttr(pair[0].trim().toLowerCase());value=normalizeValue(attr,pair[1].trim());oStyle[attr]=value})}function parseStyleObject(style,oStyle){var attr,value;for(var prop in style){if(typeof style[prop]==="undefined"){continue}attr=normalizeAttr(prop.toLowerCase());value=normalizeValue(attr,style[prop]);oStyle[attr]=value}}function getGlobalStylesForElement(element,svgUid){var styles={};for(var rule in fabric.cssRules[svgUid]){if(elementMatchesRule(element,rule.split(" "))){for(var property in fabric.cssRules[svgUid][rule]){styles[property]=fabric.cssRules[svgUid][rule][property]}}}return styles}function elementMatchesRule(element,selectors){var firstMatching,parentMatching=true;firstMatching=selectorMatches(element,selectors.pop());if(firstMatching&&selectors.length){parentMatching=doesSomeParentMatch(element,selectors)}return firstMatching&&parentMatching&&selectors.length===0}function doesSomeParentMatch(element,selectors){var selector,parentMatching=true;while(element.parentNode&&element.parentNode.nodeType===1&&selectors.length){if(parentMatching){selector=selectors.pop()}element=element.parentNode;parentMatching=selectorMatches(element,selector)}return selectors.length===0}function selectorMatches(element,selector){var nodeName=element.nodeName,classNames=element.getAttribute("class"),id=element.getAttribute("id"),matcher;matcher=new RegExp("^"+nodeName,"i");selector=selector.replace(matcher,"");if(id&&selector.length){matcher=new RegExp("#"+id+"(?![a-zA-Z\\-]+)","i");selector=selector.replace(matcher,"")}if(classNames&&selector.length){classNames=classNames.split(" ");for(var i=classNames.length;i--;){matcher=new RegExp("\\."+classNames[i]+"(?![a-zA-Z\\-]+)","i");selector=selector.replace(matcher,"")}}return selector.length===0}function elementById(doc,id){var el;doc.getElementById&&(el=doc.getElementById(id));if(el){return el}var node,i,nodelist=doc.getElementsByTagName("*");for(i=0;iscaleY?scaleY:scaleX}if(scaleX===1&&scaleY===1&&minX===0&&minY===0&&x===0&&y===0){return parsedDim}if(x||y){translateMatrix=" translate("+parseUnit(x)+" "+parseUnit(y)+") "}matrix=translateMatrix+" matrix("+scaleX+" 0"+" 0 "+scaleY+" "+minX*scaleX+" "+minY*scaleY+") ";if(element.tagName==="svg"){el=element.ownerDocument.createElement("g");while(element.firstChild!=null){el.appendChild(element.firstChild)}element.appendChild(el)}else{el=element;matrix=el.getAttribute("transform")+matrix}el.setAttribute("transform",matrix);return parsedDim}fabric.parseSVGDocument=function(){function hasAncestorWithNodeName(element,nodeName){while(element&&(element=element.parentNode)){if(nodeName.test(element.nodeName)&&!element.getAttribute("instantiated_by_use")){return true}}return false}return function(doc,callback,reviver){if(!doc){return}parseUseDirectives(doc);var startTime=new Date,svgUid=fabric.Object.__uid++,options=applyViewboxTransform(doc),descendants=fabric.util.toArray(doc.getElementsByTagName("*"));options.svgUid=svgUid;if(descendants.length===0&&fabric.isLikelyNode){descendants=doc.selectNodes('//*[name(.)!="svg"]');var arr=[];for(var i=0,len=descendants.length;i\n',' \n \n')}}var reFontDeclaration=new RegExp("(normal|italic)?\\s*(normal|small-caps)?\\s*"+"(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\\s*("+fabric.reNum+"(?:px|cm|mm|em|pt|pc|in)*)(?:\\/(normal|"+fabric.reNum+"))?\\s+(.*)");extend(fabric,{parseFontDeclaration:function(value,oStyle){var match=value.match(reFontDeclaration);if(!match){return}var fontStyle=match[1],fontWeight=match[3],fontSize=match[4],lineHeight=match[5],fontFamily=match[6];if(fontStyle){oStyle.fontStyle=fontStyle}if(fontWeight){oStyle.fontWeight=isNaN(parseFloat(fontWeight))?fontWeight:parseFloat(fontWeight)}if(fontSize){oStyle.fontSize=parseUnit(fontSize)}if(fontFamily){oStyle.fontFamily=fontFamily}if(lineHeight){oStyle.lineHeight=lineHeight==="normal"?1:lineHeight}},getGradientDefs:function(doc){var linearGradientEls=doc.getElementsByTagName("linearGradient"),radialGradientEls=doc.getElementsByTagName("radialGradient"),el,i,j=0,id,xlink,elList=[],gradientDefs={},idsToXlinkMap={};elList.length=linearGradientEls.length+radialGradientEls.length;i=linearGradientEls.length;while(i--){elList[j++]=linearGradientEls[i]}i=radialGradientEls.length;while(i--){elList[j++]=radialGradientEls[i]}while(j--){el=elList[j];xlink=el.getAttribute("xlink:href");id=el.getAttribute("id");if(xlink){idsToXlinkMap[id]=xlink.substr(1)}gradientDefs[id]=el}for(id in idsToXlinkMap){var el2=gradientDefs[idsToXlinkMap[id]].cloneNode(true);el=gradientDefs[id];while(el2.firstChild){el.appendChild(el2.firstChild)}}return gradientDefs},parseAttributes:function(element,attributes,svgUid){if(!element){return}var value,parentAttributes={},fontSize;if(typeof svgUid==="undefined"){svgUid=element.getAttribute("svgUid")}if(element.parentNode&&reAllowedParents.test(element.parentNode.nodeName)){parentAttributes=fabric.parseAttributes(element.parentNode,attributes,svgUid)}fontSize=parentAttributes&&parentAttributes.fontSize||element.getAttribute("font-size")||fabric.Text.DEFAULT_SVG_FONT_SIZE;var ownAttributes=attributes.reduce(function(memo,attr){value=element.getAttribute(attr);if(value){attr=normalizeAttr(attr);value=normalizeValue(attr,value,parentAttributes,fontSize);memo[attr]=value}return memo},{});ownAttributes=extend(ownAttributes,extend(getGlobalStylesForElement(element,svgUid),fabric.parseStyleAttribute(element)));if(ownAttributes.font){fabric.parseFontDeclaration(ownAttributes.font,ownAttributes)}return _setStrokeFillOpacity(extend(parentAttributes,ownAttributes))},parseElements:function(elements,callback,options,reviver){new fabric.ElementsParser(elements,callback,options,reviver).parse()},parseStyleAttribute:function(element){var oStyle={},style=element.getAttribute("style");if(!style){return oStyle}if(typeof style==="string"){parseStyleString(style,oStyle)}else{parseStyleObject(style,oStyle)}return oStyle},parsePointsAttribute:function(points){if(!points){return null}points=points.replace(/,/g," ").trim();points=points.split(/\s+/);var parsedPoints=[],i,len;i=0;len=points.length;for(;i/i,""))}if(!xml||!xml.documentElement){return}fabric.parseSVGDocument(xml.documentElement,function(results,options){svgCache.set(url,{objects:fabric.util.array.invoke(results,"toObject"),options:options});callback(results,options)},reviver)}},loadSVGFromString:function(string,callback,reviver){string=string.trim();var doc;if(typeof DOMParser!=="undefined"){var parser=new DOMParser;if(parser&&parser.parseFromString){doc=parser.parseFromString(string,"text/xml")}}else if(fabric.window.ActiveXObject){doc=new ActiveXObject("Microsoft.XMLDOM");doc.async="false";doc.loadXML(string.replace(//i,""))}fabric.parseSVGDocument(doc.documentElement,function(results,options){callback(results,options)},reviver)},createSVGFontFacesMarkup:function(objects){var markup="",fontList={},obj,fontFamily,style,row,rowIndex,char,charIndex,fontPaths=fabric.fontPaths;for(var i=0,len=objects.length;i',"","\n"].join("")}return markup},createSVGRefElementsMarkup:function(canvas){var markup=[];_createSVGPattern(markup,canvas,"backgroundColor");_createSVGPattern(markup,canvas,"overlayColor");return markup.join("")}})})(typeof exports!=="undefined"?exports:this);fabric.ElementsParser=function(elements,callback,options,reviver){this.elements=elements;this.callback=callback;this.options=options;this.reviver=reviver;this.svgUid=options&&options.svgUid||0};fabric.ElementsParser.prototype.parse=function(){this.instances=new Array(this.elements.length);this.numElements=this.elements.length;this.createObjects()};fabric.ElementsParser.prototype.createObjects=function(){for(var i=0,len=this.elements.length;ithat.x&&this.y>that.y},gte:function(that){return this.x>=that.x&&this.y>=that.y},lerp:function(that,t){return new Point(this.x+(that.x-this.x)*t,this.y+(that.y-this.y)*t)},distanceFrom:function(that){var dx=this.x-that.x,dy=this.y-that.y;return Math.sqrt(dx*dx+dy*dy)},midPointFrom:function(that){return new Point(this.x+(that.x-this.x)/2,this.y+(that.y-this.y)/2)},min:function(that){return new Point(Math.min(this.x,that.x),Math.min(this.y,that.y))},max:function(that){return new Point(Math.max(this.x,that.x),Math.max(this.y,that.y))},toString:function(){return this.x+","+this.y},setXY:function(x,y){this.x=x; -this.y=y},setFromPoint:function(that){this.x=that.x;this.y=that.y},swap:function(that){var x=this.x,y=this.y;this.x=that.x;this.y=that.y;that.x=x;that.y=y}}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={});if(fabric.Intersection){fabric.warn("fabric.Intersection is already defined");return}function Intersection(status){this.status=status;this.points=[]}fabric.Intersection=Intersection;fabric.Intersection.prototype={appendPoint:function(point){this.points.push(point)},appendPoints:function(points){this.points=this.points.concat(points)}};fabric.Intersection.intersectLineLine=function(a1,a2,b1,b2){var result,uaT=(b2.x-b1.x)*(a1.y-b1.y)-(b2.y-b1.y)*(a1.x-b1.x),ubT=(a2.x-a1.x)*(a1.y-b1.y)-(a2.y-a1.y)*(a1.x-b1.x),uB=(b2.y-b1.y)*(a2.x-a1.x)-(b2.x-b1.x)*(a2.y-a1.y);if(uB!==0){var ua=uaT/uB,ub=ubT/uB;if(0<=ua&&ua<=1&&0<=ub&&ub<=1){result=new Intersection("Intersection");result.points.push(new fabric.Point(a1.x+ua*(a2.x-a1.x),a1.y+ua*(a2.y-a1.y)))}else{result=new Intersection}}else{if(uaT===0||ubT===0){result=new Intersection("Coincident")}else{result=new Intersection("Parallel")}}return result};fabric.Intersection.intersectLinePolygon=function(a1,a2,points){var result=new Intersection,length=points.length;for(var i=0;i0){result.status="Intersection"}return result};fabric.Intersection.intersectPolygonPolygon=function(points1,points2){var result=new Intersection,length=points1.length;for(var i=0;i0){result.status="Intersection"}return result};fabric.Intersection.intersectPolygonRectangle=function(points,r1,r2){var min=r1.min(r2),max=r1.max(r2),topRight=new fabric.Point(max.x,min.y),bottomLeft=new fabric.Point(min.x,max.y),inter1=Intersection.intersectLinePolygon(min,topRight,points),inter2=Intersection.intersectLinePolygon(topRight,max,points),inter3=Intersection.intersectLinePolygon(max,bottomLeft,points),inter4=Intersection.intersectLinePolygon(bottomLeft,min,points),result=new Intersection;result.appendPoints(inter1.points);result.appendPoints(inter2.points);result.appendPoints(inter3.points);result.appendPoints(inter4.points);if(result.points.length>0){result.status="Intersection"}return result}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={});if(fabric.Color){fabric.warn("fabric.Color is already defined.");return}function Color(color){if(!color){this.setSource([0,0,0,1])}else{this._tryParsingColor(color)}}fabric.Color=Color;fabric.Color.prototype={_tryParsingColor:function(color){var source;if(color in Color.colorNameMap){color=Color.colorNameMap[color]}if(color==="transparent"){this.setSource([255,255,255,0]);return}source=Color.sourceFromHex(color);if(!source){source=Color.sourceFromRgb(color)}if(!source){source=Color.sourceFromHsl(color)}if(source){this.setSource(source)}},_rgbToHsl:function(r,g,b){r/=255,g/=255,b/=255;var h,s,l,max=fabric.util.array.max([r,g,b]),min=fabric.util.array.min([r,g,b]);l=(max+min)/2;if(max===min){h=s=0}else{var d=max-min;s=l>.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g1){t-=1}if(t<1/6){return p+(q-p)*6*t}if(t<1/2){return q}if(t<2/3){return p+(q-p)*(2/3-t)*6}return p}fabric.Color.fromRgb=function(color){return Color.fromSource(Color.sourceFromRgb(color))};fabric.Color.sourceFromRgb=function(color){var match=color.match(Color.reRGBa);if(match){var r=parseInt(match[1],10)/(/%$/.test(match[1])?100:1)*(/%$/.test(match[1])?255:1),g=parseInt(match[2],10)/(/%$/.test(match[2])?100:1)*(/%$/.test(match[2])?255:1),b=parseInt(match[3],10)/(/%$/.test(match[3])?100:1)*(/%$/.test(match[3])?255:1);return[parseInt(r,10),parseInt(g,10),parseInt(b,10),match[4]?parseFloat(match[4]):1]}};fabric.Color.fromRgba=Color.fromRgb;fabric.Color.fromHsl=function(color){return Color.fromSource(Color.sourceFromHsl(color))};fabric.Color.sourceFromHsl=function(color){var match=color.match(Color.reHSLa);if(!match){return}var h=(parseFloat(match[1])%360+360)%360/360,s=parseFloat(match[2])/(/%$/.test(match[2])?100:1),l=parseFloat(match[3])/(/%$/.test(match[3])?100:1),r,g,b;if(s===0){r=g=b=l}else{var q=l<=.5?l*(s+1):l+s-l*s,p=l*2-q;r=hue2rgb(p,q,h+1/3);g=hue2rgb(p,q,h);b=hue2rgb(p,q,h-1/3)}return[Math.round(r*255),Math.round(g*255),Math.round(b*255),match[4]?parseFloat(match[4]):1]};fabric.Color.fromHsla=Color.fromHsl;fabric.Color.fromHex=function(color){return Color.fromSource(Color.sourceFromHex(color))};fabric.Color.sourceFromHex=function(color){if(color.match(Color.reHex)){var value=color.slice(color.indexOf("#")+1),isShortNotation=value.length===3,r=isShortNotation?value.charAt(0)+value.charAt(0):value.substring(0,2),g=isShortNotation?value.charAt(1)+value.charAt(1):value.substring(2,4),b=isShortNotation?value.charAt(2)+value.charAt(2):value.substring(4,6);return[parseInt(r,16),parseInt(g,16),parseInt(b,16),1]}};fabric.Color.fromSource=function(source){var oColor=new Color;oColor.setSource(source);return oColor}})(typeof exports!=="undefined"?exports:this);(function(){function getColorStop(el){var style=el.getAttribute("style"),offset=el.getAttribute("offset")||0,color,colorAlpha,opacity;offset=parseFloat(offset)/(/%$/.test(offset)?100:1);offset=offset<0?0:offset>1?1:offset;if(style){var keyValuePairs=style.split(/\s*;\s*/);if(keyValuePairs[keyValuePairs.length-1]===""){keyValuePairs.pop()}for(var i=keyValuePairs.length;i--;){var split=keyValuePairs[i].split(/\s*:\s*/),key=split[0].trim(),value=split[1].trim();if(key==="stop-color"){color=value}else if(key==="stop-opacity"){opacity=value}}}if(!color){color=el.getAttribute("stop-color")||"rgb(0,0,0)"}if(!opacity){opacity=el.getAttribute("stop-opacity")}color=new fabric.Color(color);colorAlpha=color.getAlpha();opacity=isNaN(parseFloat(opacity))?1:parseFloat(opacity);opacity*=colorAlpha;return{offset:offset,color:color.toRgb(),opacity:opacity}}function getLinearCoords(el){return{x1:el.getAttribute("x1")||0,y1:el.getAttribute("y1")||0,x2:el.getAttribute("x2")||"100%",y2:el.getAttribute("y2")||0}}function getRadialCoords(el){return{x1:el.getAttribute("fx")||el.getAttribute("cx")||"50%",y1:el.getAttribute("fy")||el.getAttribute("cy")||"50%",r1:0,x2:el.getAttribute("cx")||"50%",y2:el.getAttribute("cy")||"50%",r2:el.getAttribute("r")||"50%"}}fabric.Gradient=fabric.util.createClass({offsetX:0,offsetY:0,initialize:function(options){options||(options={});var coords={};this.id=fabric.Object.__uid++;this.type=options.type||"linear";coords={x1:options.coords.x1||0,y1:options.coords.y1||0,x2:options.coords.x2||0,y2:options.coords.y2||0};if(this.type==="radial"){coords.r1=options.coords.r1||0;coords.r2=options.coords.r2||0}this.coords=coords;this.colorStops=options.colorStops.slice();if(options.gradientTransform){this.gradientTransform=options.gradientTransform}this.offsetX=options.offsetX||this.offsetX;this.offsetY=options.offsetY||this.offsetY},addColorStop:function(colorStop){for(var position in colorStop){var color=new fabric.Color(colorStop[position]);this.colorStops.push({offset:position,color:color.toRgb(),opacity:color.getAlpha()})}return this},toObject:function(){return{type:this.type,coords:this.coords,colorStops:this.colorStops,offsetX:this.offsetX,offsetY:this.offsetY,gradientTransform:this.gradientTransform?this.gradientTransform.concat():this.gradientTransform}},toSVG:function(object){var coords=fabric.util.object.clone(this.coords),markup,commonAttributes;this.colorStops.sort(function(a,b){return a.offset-b.offset});if(!(object.group&&object.group.type==="path-group")){for(var prop in coords){if(prop==="x1"||prop==="x2"||prop==="r2"){coords[prop]+=this.offsetX-object.width/2}else if(prop==="y1"||prop==="y2"){coords[prop]+=this.offsetY-object.height/2}}}commonAttributes='id="SVGID_'+this.id+'" gradientUnits="userSpaceOnUse"';if(this.gradientTransform){commonAttributes+=' gradientTransform="matrix('+this.gradientTransform.join(" ")+')" '}if(this.type==="linear"){markup=["\n']}else if(this.type==="radial"){markup=["\n']}for(var i=0;i\n')}markup.push(this.type==="linear"?"\n":"\n");return markup.join("")},toLive:function(ctx,object){var gradient,prop,coords=fabric.util.object.clone(this.coords);if(!this.type){return}if(object.group&&object.group.type==="path-group"){for(prop in coords){if(prop==="x1"||prop==="x2"){coords[prop]+=-this.offsetX+object.width/2}else if(prop==="y1"||prop==="y2"){coords[prop]+=-this.offsetY+object.height/2}}}if(this.type==="linear"){gradient=ctx.createLinearGradient(coords.x1,coords.y1,coords.x2,coords.y2)}else if(this.type==="radial"){gradient=ctx.createRadialGradient(coords.x1,coords.y1,coords.r1,coords.x2,coords.y2,coords.r2)}for(var i=0,len=this.colorStops.length;i\n'+'\n'+"\n"},toLive:function(ctx){var source=typeof this.source==="function"?this.source():this.source;if(!source){return""}if(typeof source.src!=="undefined"){if(!source.complete){return""}if(source.naturalWidth===0||source.naturalHeight===0){return""}}return ctx.createPattern(source,this.repeat)}});(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),toFixed=fabric.util.toFixed;if(fabric.Shadow){fabric.warn("fabric.Shadow is already defined.");return}fabric.Shadow=fabric.util.createClass({color:"rgb(0,0,0)",blur:0,offsetX:0,offsetY:0,affectStroke:false,includeDefaultValues:true,initialize:function(options){if(typeof options==="string"){options=this._parseShadow(options)}for(var prop in options){this[prop]=options[prop]}this.id=fabric.Object.__uid++},_parseShadow:function(shadow){var shadowStr=shadow.trim(),offsetsAndBlur=fabric.Shadow.reOffsetsAndBlur.exec(shadowStr)||[],color=shadowStr.replace(fabric.Shadow.reOffsetsAndBlur,"")||"rgb(0,0,0)";return{color:color.trim(),offsetX:parseInt(offsetsAndBlur[1],10)||0,offsetY:parseInt(offsetsAndBlur[2],10)||0,blur:parseInt(offsetsAndBlur[3],10)||0}},toString:function(){return[this.offsetX,this.offsetY,this.blur,this.color].join("px ")},toSVG:function(object){var fBoxX=40,fBoxY=40,NUM_FRACTION_DIGITS=fabric.Object.NUM_FRACTION_DIGITS,offset=fabric.util.rotateVector({x:this.offsetX,y:this.offsetY},fabric.util.degreesToRadians(-object.angle)),BLUR_BOX=20;if(object.width&&object.height){fBoxX=toFixed((Math.abs(offset.x)+this.blur)/object.width,NUM_FRACTION_DIGITS)*100+BLUR_BOX;fBoxY=toFixed((Math.abs(offset.y)+this.blur)/object.height,NUM_FRACTION_DIGITS)*100+BLUR_BOX}if(object.flipX){offset.x*=-1}if(object.flipY){offset.y*=-1}return'\n"+' \n'+' \n'+' \n'+' \n'+" \n"+" \n"+' \n'+" \n"+"\n"},toObject:function(){if(this.includeDefaultValues){return{color:this.color,blur:this.blur,offsetX:this.offsetX,offsetY:this.offsetY,affectStroke:this.affectStroke}}var obj={},proto=fabric.Shadow.prototype;["color","blur","offsetX","offsetY","affectStroke"].forEach(function(prop){if(this[prop]!==proto[prop]){obj[prop]=this[prop]}},this);return obj}});fabric.Shadow.reOffsetsAndBlur=/(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/})(typeof exports!=="undefined"?exports:this);(function(){"use strict";if(fabric.StaticCanvas){fabric.warn("fabric.StaticCanvas is already defined.");return}var extend=fabric.util.object.extend,getElementOffset=fabric.util.getElementOffset,removeFromArray=fabric.util.removeFromArray,toFixed=fabric.util.toFixed,CANVAS_INIT_ERROR=new Error("Could not initialize `canvas` element");fabric.StaticCanvas=fabric.util.createClass({initialize:function(el,options){options||(options={});this._initStatic(el,options)},backgroundColor:"",backgroundImage:null,overlayColor:"",overlayImage:null,includeDefaultValues:true,stateful:true,renderOnAddRemove:true,clipTo:null,controlsAboveOverlay:false,allowTouchScrolling:false,imageSmoothingEnabled:true,preserveObjectStacking:false,viewportTransform:[1,0,0,1,0,0],onBeforeScaleRotate:function(){},enableRetinaScaling:true,_initStatic:function(el,options){this._objects=[];this._createLowerCanvas(el);this._initOptions(options);this._setImageSmoothing();if(!this.interactive){this._initRetinaScaling()}if(options.overlayImage){this.setOverlayImage(options.overlayImage,this.renderAll.bind(this))}if(options.backgroundImage){this.setBackgroundImage(options.backgroundImage,this.renderAll.bind(this))}if(options.backgroundColor){this.setBackgroundColor(options.backgroundColor,this.renderAll.bind(this))}if(options.overlayColor){this.setOverlayColor(options.overlayColor,this.renderAll.bind(this))}this.calcOffset()},_isRetinaScaling:function(){return fabric.devicePixelRatio!==1&&this.enableRetinaScaling},_initRetinaScaling:function(){if(!this._isRetinaScaling()){return}this.lowerCanvasEl.setAttribute("width",this.width*fabric.devicePixelRatio);this.lowerCanvasEl.setAttribute("height",this.height*fabric.devicePixelRatio);this.contextContainer.scale(fabric.devicePixelRatio,fabric.devicePixelRatio)},calcOffset:function(){this._offset=getElementOffset(this.lowerCanvasEl);return this},setOverlayImage:function(image,callback,options){return this.__setBgOverlayImage("overlayImage",image,callback,options)},setBackgroundImage:function(image,callback,options){return this.__setBgOverlayImage("backgroundImage",image,callback,options)},setOverlayColor:function(overlayColor,callback){return this.__setBgOverlayColor("overlayColor",overlayColor,callback)},setBackgroundColor:function(backgroundColor,callback){return this.__setBgOverlayColor("backgroundColor",backgroundColor,callback)},_setImageSmoothing:function(){var ctx=this.getContext();if(typeof ctx.imageSmoothingEnabled!=="undefined"){ctx.imageSmoothingEnabled=this.imageSmoothingEnabled;return}ctx.webkitImageSmoothingEnabled=this.imageSmoothingEnabled;ctx.mozImageSmoothingEnabled=this.imageSmoothingEnabled;ctx.msImageSmoothingEnabled=this.imageSmoothingEnabled;ctx.oImageSmoothingEnabled=this.imageSmoothingEnabled},__setBgOverlayImage:function(property,image,callback,options){if(typeof image==="string"){fabric.util.loadImage(image,function(img){this[property]=new fabric.Image(img,options);callback&&callback(img)},this,options&&options.crossOrigin)}else{options&&image.setOptions(options);this[property]=image;callback&&callback(image)}return this},__setBgOverlayColor:function(property,color,callback){if(color&&color.source){var _this=this;fabric.util.loadImage(color.source,function(img){_this[property]=new fabric.Pattern({source:img,repeat:color.repeat,offsetX:color.offsetX,offsetY:color.offsetY});callback&&callback()})}else{this[property]=color;callback&&callback()}return this},_createCanvasElement:function(){var element=fabric.document.createElement("canvas");if(!element.style){element.style={}}if(!element){throw CANVAS_INIT_ERROR}this._initCanvasElement(element);return element},_initCanvasElement:function(element){fabric.util.createCanvasElement(element);if(typeof element.getContext==="undefined"){throw CANVAS_INIT_ERROR}},_initOptions:function(options){for(var prop in options){this[prop]=options[prop]}this.width=this.width||parseInt(this.lowerCanvasEl.width,10)||0;this.height=this.height||parseInt(this.lowerCanvasEl.height,10)||0;if(!this.lowerCanvasEl.style){return}this.lowerCanvasEl.width=this.width;this.lowerCanvasEl.height=this.height;this.lowerCanvasEl.style.width=this.width+"px";this.lowerCanvasEl.style.height=this.height+"px";this.viewportTransform=this.viewportTransform.slice()},_createLowerCanvas:function(canvasEl){this.lowerCanvasEl=fabric.util.getById(canvasEl)||this._createCanvasElement();this._initCanvasElement(this.lowerCanvasEl);fabric.util.addClass(this.lowerCanvasEl,"lower-canvas");if(this.interactive){this._applyCanvasStyle(this.lowerCanvasEl)}this.contextContainer=this.lowerCanvasEl.getContext("2d")},getWidth:function(){return this.width},getHeight:function(){return this.height},setWidth:function(value,options){return this.setDimensions({width:value},options)},setHeight:function(value,options){return this.setDimensions({height:value},options)},setDimensions:function(dimensions,options){var cssValue;options=options||{};for(var prop in dimensions){cssValue=dimensions[prop];if(!options.cssOnly){this._setBackstoreDimension(prop,dimensions[prop]);cssValue+="px"}if(!options.backstoreOnly){this._setCssDimension(prop,cssValue)}}this._initRetinaScaling();this._setImageSmoothing();this.calcOffset();if(!options.cssOnly){this.renderAll()}return this},_setBackstoreDimension:function(prop,value){this.lowerCanvasEl[prop]=value;if(this.upperCanvasEl){this.upperCanvasEl[prop]=value}if(this.cacheCanvasEl){this.cacheCanvasEl[prop]=value}this[prop]=value;return this},_setCssDimension:function(prop,value){this.lowerCanvasEl.style[prop]=value;if(this.upperCanvasEl){this.upperCanvasEl.style[prop]=value}if(this.wrapperEl){this.wrapperEl.style[prop]=value}return this},getZoom:function(){return Math.sqrt(this.viewportTransform[0]*this.viewportTransform[3])},setViewportTransform:function(vpt){var activeGroup=this.getActiveGroup();this.viewportTransform=vpt;this.renderAll();for(var i=0,len=this._objects.length;i");return markup.join("")},_setSVGPreamble:function(markup,options){if(options.suppressPreamble){return}markup.push('\n','\n')},_setSVGHeader:function(markup,options){var width=options.width||this.width,height=options.height||this.height,vpt,viewBox='viewBox="0 0 '+this.width+" "+this.height+'" ',NUM_FRACTION_DIGITS=fabric.Object.NUM_FRACTION_DIGITS;if(options.viewBox){viewBox='viewBox="'+options.viewBox.x+" "+options.viewBox.y+" "+options.viewBox.width+" "+options.viewBox.height+'" '}else{if(this.svgViewportTransformation){vpt=this.viewportTransform;viewBox='viewBox="'+toFixed(-vpt[4]/vpt[0],NUM_FRACTION_DIGITS)+" "+toFixed(-vpt[5]/vpt[3],NUM_FRACTION_DIGITS)+" "+toFixed(this.width/vpt[0],NUM_FRACTION_DIGITS)+" "+toFixed(this.height/vpt[3],NUM_FRACTION_DIGITS)+'" '}}markup.push("\n',"Created with Fabric.js ",fabric.version,"\n","",fabric.createSVGFontFacesMarkup(this.getObjects()),fabric.createSVGRefElementsMarkup(this),"\n")},_setSVGObjects:function(markup,reviver){for(var i=0,objects=this.getObjects(),len=objects.length;i\n")}else if(this[property]&&property==="overlayColor"){markup.push('\n")}},sendToBack:function(object){removeFromArray(this._objects,object);this._objects.unshift(object);return this.renderAll&&this.renderAll()},bringToFront:function(object){removeFromArray(this._objects,object);this._objects.push(object);return this.renderAll&&this.renderAll()},sendBackwards:function(object,intersecting){var idx=this._objects.indexOf(object);if(idx!==0){var newIdx=this._findNewLowerIndex(object,idx,intersecting);removeFromArray(this._objects,object);this._objects.splice(newIdx,0,object);this.renderAll&&this.renderAll()}return this},_findNewLowerIndex:function(object,idx,intersecting){var newIdx;if(intersecting){newIdx=idx;for(var i=idx-1;i>=0;--i){var isIntersecting=object.intersectsWithObject(this._objects[i])||object.isContainedWithinObject(this._objects[i])||this._objects[i].isContainedWithinObject(object);if(isIntersecting){newIdx=i;break}}}else{newIdx=idx-1}return newIdx},bringForward:function(object,intersecting){var idx=this._objects.indexOf(object);if(idx!==this._objects.length-1){var newIdx=this._findNewUpperIndex(object,idx,intersecting);removeFromArray(this._objects,object);this._objects.splice(newIdx,0,object);this.renderAll&&this.renderAll()}return this},_findNewUpperIndex:function(object,idx,intersecting){var newIdx;if(intersecting){newIdx=idx;for(var i=idx+1;i"}});extend(fabric.StaticCanvas.prototype,fabric.Observable);extend(fabric.StaticCanvas.prototype,fabric.Collection);extend(fabric.StaticCanvas.prototype,fabric.DataURLExporter);extend(fabric.StaticCanvas,{EMPTY_JSON:'{"objects": [], "background": "white"}',supports:function(methodName){var el=fabric.util.createCanvasElement();if(!el||!el.getContext){return null}var ctx=el.getContext("2d");if(!ctx){return null}switch(methodName){case"getImageData":return typeof ctx.getImageData!=="undefined";case"setLineDash":return typeof ctx.setLineDash!=="undefined";case"toDataURL":return typeof el.toDataURL!=="undefined";case"toDataURLWithQuality":try{el.toDataURL("image/jpeg",0);return true}catch(e){}return false;default:return null}}});fabric.StaticCanvas.prototype.toJSON=fabric.StaticCanvas.prototype.toObject})();fabric.BaseBrush=fabric.util.createClass({color:"rgb(0, 0, 0)",width:1,shadow:null,strokeLineCap:"round",strokeLineJoin:"round",strokeDashArray:null,setShadow:function(options){this.shadow=new fabric.Shadow(options);return this},_setBrushStyles:function(){var ctx=this.canvas.contextTop;ctx.strokeStyle=this.color;ctx.lineWidth=this.width;ctx.lineCap=this.strokeLineCap;ctx.lineJoin=this.strokeLineJoin;if(this.strokeDashArray&&fabric.StaticCanvas.supports("setLineDash")){ctx.setLineDash(this.strokeDashArray)}},_setShadow:function(){if(!this.shadow){return}var ctx=this.canvas.contextTop;ctx.shadowColor=this.shadow.color;ctx.shadowBlur=this.shadow.blur;ctx.shadowOffsetX=this.shadow.offsetX;ctx.shadowOffsetY=this.shadow.offsetY},_resetShadow:function(){var ctx=this.canvas.contextTop;ctx.shadowColor="";ctx.shadowBlur=ctx.shadowOffsetX=ctx.shadowOffsetY=0}});(function(){fabric.PencilBrush=fabric.util.createClass(fabric.BaseBrush,{initialize:function(canvas){this.canvas=canvas;this._points=[]},onMouseDown:function(pointer){this._prepareForDrawing(pointer);this._captureDrawingPath(pointer);this._render()},onMouseMove:function(pointer){this._captureDrawingPath(pointer);this.canvas.clearContext(this.canvas.contextTop);this._render()},onMouseUp:function(){this._finalizeAndAddPath()},_prepareForDrawing:function(pointer){var p=new fabric.Point(pointer.x,pointer.y);this._reset();this._addPoint(p);this.canvas.contextTop.moveTo(p.x,p.y)},_addPoint:function(point){this._points.push(point)},_reset:function(){this._points.length=0;this._setBrushStyles();this._setShadow()},_captureDrawingPath:function(pointer){var pointerPoint=new fabric.Point(pointer.x,pointer.y);this._addPoint(pointerPoint)},_render:function(){var ctx=this.canvas.contextTop,v=this.canvas.viewportTransform,p1=this._points[0],p2=this._points[1];ctx.save();ctx.transform(v[0],v[1],v[2],v[3],v[4],v[5]);ctx.beginPath();if(this._points.length===2&&p1.x===p2.x&&p1.y===p2.y){p1.x-=.5;p2.x+=.5}ctx.moveTo(p1.x,p1.y);for(var i=1,len=this._points.length;i0?1:-1;if(by==="y"){skew=t.target.skewY;originA="top";originB="bottom";property="originY"}origins[-1]=originA;origins[1]=originB;t.target.flipX&&(flipSign*=-1);t.target.flipY&&(flipSign*=-1);if(skew===0){t.skewSign=-corner*mouseMove*flipSign;t[property]=origins[-mouseMove]}else{skew=skew>0?1:-1;t.skewSign=skew;t[property]=origins[skew*corner*flipSign]}},_skewObject:function(x,y,by){var t=this._currentTransform,target=t.target,lockSkewingX=target.get("lockSkewingX"),lockSkewingY=target.get("lockSkewingY");if(lockSkewingX&&by==="x"||lockSkewingY&&by==="y"){return}var center=target.getCenterPoint(),actualMouseByCenter=target.toLocalPoint(new fabric.Point(x,y),"center","center")[by],lastMouseByCenter=target.toLocalPoint(new fabric.Point(t.lastX,t.lastY),"center","center")[by],actualMouseByOrigin,constraintPosition,dim=target._getTransformedDimensions();this._changeSkewTransformOrigin(actualMouseByCenter-lastMouseByCenter,t,by);actualMouseByOrigin=target.toLocalPoint(new fabric.Point(x,y),t.originX,t.originY)[by],constraintPosition=target.translateToOriginPoint(center,t.originX,t.originY);this._setObjectSkew(actualMouseByOrigin,t,by,dim);t.lastX=x;t.lastY=y;target.setPositionByOrigin(constraintPosition,t.originX,t.originY)},_setObjectSkew:function(localMouse,transform,by,_dim){var target=transform.target,newValue,skewSign=transform.skewSign,newDim,dimNoSkew,otherBy,_otherBy,_by,newDimMouse,skewX,skewY;if(by==="x"){otherBy="y";_otherBy="Y";_by="X";skewX=0;skewY=target.skewY}else{otherBy="x";_otherBy="X";_by="Y";skewX=target.skewX;skewY=0}dimNoSkew=target._getTransformedDimensions(skewX,skewY);newDimMouse=2*Math.abs(localMouse)-dimNoSkew[by];if(newDimMouse<=2){newValue=0}else{newValue=skewSign*Math.atan(newDimMouse/target["scale"+_by]/(dimNoSkew[otherBy]/target["scale"+_otherBy]));newValue=fabric.util.radiansToDegrees(newValue)}target.set("skew"+_by,newValue);if(target["skew"+_otherBy]!==0){newDim=target._getTransformedDimensions();newValue=_dim[otherBy]/newDim[otherBy]*target["scale"+_otherBy];target.set("scale"+_otherBy,newValue)}},_scaleObject:function(x,y,by){var t=this._currentTransform,target=t.target,lockScalingX=target.get("lockScalingX"),lockScalingY=target.get("lockScalingY"),lockScalingFlip=target.get("lockScalingFlip");if(lockScalingX&&lockScalingY){return}var constraintPosition=target.translateToOriginPoint(target.getCenterPoint(),t.originX,t.originY),localMouse=target.toLocalPoint(new fabric.Point(x,y),t.originX,t.originY),dim=target._getTransformedDimensions();this._setLocalMouse(localMouse,t);this._setObjectScale(localMouse,t,lockScalingX,lockScalingY,by,lockScalingFlip,dim);target.setPositionByOrigin(constraintPosition,t.originX,t.originY)},_setObjectScale:function(localMouse,transform,lockScalingX,lockScalingY,by,lockScalingFlip,_dim){var target=transform.target,forbidScalingX=false,forbidScalingY=false;transform.newScaleX=localMouse.x*target.scaleX/_dim.x;transform.newScaleY=localMouse.y*target.scaleY/_dim.y;if(lockScalingFlip&&transform.newScaleX<=0&&transform.newScaleXtarget.padding){if(localMouse.x<0){localMouse.x+=target.padding}else{localMouse.x-=target.padding}}else{localMouse.x=0}if(abs(localMouse.y)>target.padding){if(localMouse.y<0){localMouse.y+=target.padding}else{localMouse.y-=target.padding}}else{localMouse.y=0}},_rotateObject:function(x,y){var t=this._currentTransform;if(t.target.get("lockRotation")){return}var lastAngle=atan2(t.ey-t.top,t.ex-t.left),curAngle=atan2(y-t.top,x-t.left),angle=radiansToDegrees(curAngle-lastAngle+t.theta);if(angle<0){angle=360+angle}t.target.angle=angle%360},setCursor:function(value){this.upperCanvasEl.style.cursor=value},_resetObjectTransform:function(target){target.scaleX=1;target.scaleY=1;target.skewX=0;target.skewY=0;target.setAngle(0)},_drawSelection:function(){var ctx=this.contextTop,groupSelector=this._groupSelector,left=groupSelector.left,top=groupSelector.top,aleft=abs(left),atop=abs(top);ctx.fillStyle=this.selectionColor;ctx.fillRect(groupSelector.ex-(left>0?0:-left),groupSelector.ey-(top>0?0:-top),aleft,atop);ctx.lineWidth=this.selectionLineWidth;ctx.strokeStyle=this.selectionBorderColor;if(this.selectionDashArray.length>1){var px=groupSelector.ex+STROKE_OFFSET-(left>0?0:aleft),py=groupSelector.ey+STROKE_OFFSET-(top>0?0:atop);ctx.beginPath();fabric.util.drawDashedLine(ctx,px,py,px+aleft,py,this.selectionDashArray);fabric.util.drawDashedLine(ctx,px,py+atop-1,px+aleft,py+atop-1,this.selectionDashArray);fabric.util.drawDashedLine(ctx,px,py,px,py+atop,this.selectionDashArray);fabric.util.drawDashedLine(ctx,px+aleft-1,py,px+aleft-1,py+atop,this.selectionDashArray);ctx.closePath();ctx.stroke()}else{ctx.strokeRect(groupSelector.ex+STROKE_OFFSET-(left>0?0:aleft),groupSelector.ey+STROKE_OFFSET-(top>0?0:atop),aleft,atop)}},_isLastRenderedObject:function(e){return this.controlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay.visible&&this.containsPoint(e,this.lastRenderedObjectWithControlsAboveOverlay)&&this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(this.getPointer(e,true))},findTarget:function(e,skipGroup){if(this.skipTargetFind){return}if(this._isLastRenderedObject(e)){return this.lastRenderedObjectWithControlsAboveOverlay}var activeGroup=this.getActiveGroup();if(activeGroup&&!skipGroup&&this.containsPoint(e,activeGroup)){return activeGroup}var target=this._searchPossibleTargets(e,skipGroup);this._fireOverOutEvents(target,e);return target},_fireOverOutEvents:function(target,e){if(target){if(this._hoveredTarget!==target){if(this._hoveredTarget){this.fire("mouse:out",{target:this._hoveredTarget,e:e});this._hoveredTarget.fire("mouseout")}this.fire("mouse:over",{target:target,e:e});target.fire("mouseover");this._hoveredTarget=target}}else if(this._hoveredTarget){this.fire("mouse:out",{target:this._hoveredTarget,e:e});this._hoveredTarget.fire("mouseout");this._hoveredTarget=null}},_checkTarget:function(e,obj,pointer){if(obj&&obj.visible&&obj.evented&&this.containsPoint(e,obj)){if((this.perPixelTargetFind||obj.perPixelTargetFind)&&!obj.isEditing){var isTransparent=this.isTargetTransparent(obj,pointer.x,pointer.y);if(!isTransparent){return true}}else{return true}}},_searchPossibleTargets:function(e,skipGroup){var target,pointer=this.getPointer(e,true),i=this._objects.length;while(i--){if((!this._objects[i].group||skipGroup)&&this._checkTarget(e,this._objects[i],pointer)){this.relatedTarget=this._objects[i];target=this._objects[i];break}}return target},getPointer:function(e,ignoreZoom,upperCanvasEl){if(!upperCanvasEl){upperCanvasEl=this.upperCanvasEl}var pointer=getPointer(e),bounds=upperCanvasEl.getBoundingClientRect(),boundsWidth=bounds.width||0,boundsHeight=bounds.height||0,cssScale;if(!boundsWidth||!boundsHeight){if("top"in bounds&&"bottom"in bounds){boundsHeight=Math.abs(bounds.top-bounds.bottom)}if("right"in bounds&&"left"in bounds){boundsWidth=Math.abs(bounds.right-bounds.left)}}this.calcOffset();pointer.x=pointer.x-this._offset.left;pointer.y=pointer.y-this._offset.top;if(!ignoreZoom){pointer=fabric.util.transformPoint(pointer,fabric.util.invertTransform(this.viewportTransform))}if(boundsWidth===0||boundsHeight===0){cssScale={width:1,height:1}}else{cssScale={width:upperCanvasEl.width/boundsWidth,height:upperCanvasEl.height/boundsHeight}}return{x:pointer.x*cssScale.width,y:pointer.y*cssScale.height}},_createUpperCanvas:function(){var lowerCanvasClass=this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/,"");this.upperCanvasEl=this._createCanvasElement();fabric.util.addClass(this.upperCanvasEl,"upper-canvas "+lowerCanvasClass);this.wrapperEl.appendChild(this.upperCanvasEl);this._copyCanvasStyle(this.lowerCanvasEl,this.upperCanvasEl);this._applyCanvasStyle(this.upperCanvasEl);this.contextTop=this.upperCanvasEl.getContext("2d")},_createCacheCanvas:function(){this.cacheCanvasEl=this._createCanvasElement();this.cacheCanvasEl.setAttribute("width",this.width);this.cacheCanvasEl.setAttribute("height",this.height);this.contextCache=this.cacheCanvasEl.getContext("2d")},_initWrapperElement:function(){this.wrapperEl=fabric.util.wrapElement(this.lowerCanvasEl,"div",{"class":this.containerClass});fabric.util.setStyle(this.wrapperEl,{width:this.getWidth()+"px",height:this.getHeight()+"px",position:"relative"});fabric.util.makeElementUnselectable(this.wrapperEl)},_applyCanvasStyle:function(element){var width=this.getWidth()||element.width,height=this.getHeight()||element.height;fabric.util.setStyle(element,{position:"absolute",width:width+"px",height:height+"px",left:0,top:0});element.width=width;element.height=height;fabric.util.makeElementUnselectable(element)},_copyCanvasStyle:function(fromEl,toEl){toEl.style.cssText=fromEl.style.cssText},getSelectionContext:function(){return this.contextTop},getSelectionElement:function(){return this.upperCanvasEl},_setActiveObject:function(object){if(this._activeObject){this._activeObject.set("active",false)}this._activeObject=object;object.set("active",true)},setActiveObject:function(object,e){this._setActiveObject(object);this.renderAll();this.fire("object:selected",{target:object,e:e});object.fire("selected",{e:e});return this},getActiveObject:function(){return this._activeObject},_discardActiveObject:function(){if(this._activeObject){this._activeObject.set("active",false)}this._activeObject=null},discardActiveObject:function(e){this._discardActiveObject();this.renderAll();this.fire("selection:cleared",{e:e});return this},_setActiveGroup:function(group){this._activeGroup=group;if(group){group.set("active",true)}},setActiveGroup:function(group,e){this._setActiveGroup(group);if(group){this.fire("object:selected",{target:group,e:e});group.fire("selected",{e:e})}return this},getActiveGroup:function(){return this._activeGroup},_discardActiveGroup:function(){var g=this.getActiveGroup();if(g){g.destroy()}this.setActiveGroup(null)},discardActiveGroup:function(e){this._discardActiveGroup();this.fire("selection:cleared",{e:e});return this},deactivateAll:function(){var allObjects=this.getObjects(),i=0,len=allObjects.length;for(;i1){return}var groupSelector=this._groupSelector;if(groupSelector){pointer=this.getPointer(e,true);groupSelector.left=pointer.x-groupSelector.ex;groupSelector.top=pointer.y-groupSelector.ey;this.renderTop()}else if(!this._currentTransform){target=this.findTarget(e);if(!target||target&&!target.selectable){this.setCursor(this.defaultCursor)}else{this._setCursorFromEvent(e,target)}}else{this._transformObject(e)}this.fire("mouse:move",{target:target,e:e});target&&target.fire("mousemove",{e:e})},_transformObject:function(e){var pointer=this.getPointer(e),transform=this._currentTransform;transform.reset=false,transform.target.isMoving=true;this._beforeScaleTransform(e,transform);this._performTransformAction(e,transform,pointer);this.renderAll()},_performTransformAction:function(e,transform,pointer){var x=pointer.x,y=pointer.y,target=transform.target,action=transform.action;if(action==="rotate"){this._rotateObject(x,y);this._fire("rotating",target,e)}else if(action==="scale"){this._onScale(e,transform,x,y);this._fire("scaling",target,e)}else if(action==="scaleX"){this._scaleObject(x,y,"x");this._fire("scaling",target,e)}else if(action==="scaleY"){this._scaleObject(x,y,"y");this._fire("scaling",target,e)}else if(action==="skewX"){this._skewObject(x,y,"x");this._fire("skewing",target,e)}else if(action==="skewY"){this._skewObject(x,y,"y");this._fire("skewing",target,e)}else{this._translateObject(x,y);this._fire("moving",target,e);this.setCursor(this.moveCursor)}},_fire:function(eventName,target,e){this.fire("object:"+eventName,{target:target,e:e});target.fire(eventName,{e:e})},_beforeScaleTransform:function(e,transform){if(transform.action==="scale"||transform.action==="scaleX"||transform.action==="scaleY"){var centerTransform=this._shouldCenterTransform(transform.target);if(centerTransform&&(transform.originX!=="center"||transform.originY!=="center")||!centerTransform&&transform.originX==="center"&&transform.originY==="center"){this._resetCurrentTransform();transform.reset=true}}},_onScale:function(e,transform,x,y){if((e.shiftKey||this.uniScaleTransform)&&!transform.target.get("lockUniScaling")){transform.currentAction="scale";this._scaleObject(x,y)}else{if(!transform.reset&&transform.currentAction==="scale"){this._resetCurrentTransform()}transform.currentAction="scaleEqually";this._scaleObject(x,y,"equally")}},_setCursorFromEvent:function(e,target){if(!target||!target.selectable){this.setCursor(this.defaultCursor);return false}else{var activeGroup=this.getActiveGroup(),corner=target._findTargetCorner&&(!activeGroup||!activeGroup.contains(target))&&target._findTargetCorner(this.getPointer(e,true));if(!corner){this.setCursor(target.hoverCursor||this.hoverCursor)}else{this._setCornerCursor(corner,target,e)}}return true},_setCornerCursor:function(corner,target,e){if(corner in cursorOffset){this.setCursor(this._getRotatedCornerCursor(corner,target,e))}else if(corner==="mtr"&&target.hasRotatingPoint){this.setCursor(this.rotationCursor)}else{this.setCursor(this.defaultCursor);return false}},_getRotatedCornerCursor:function(corner,target,e){var n=Math.round(target.getAngle()%360/45);if(n<0){n+=8}n+=cursorOffset[corner];if(e.shiftKey&&cursorOffset[corner]%2===0){n+=2}n%=8;return this.cursorMap[n]}})})();(function(){var min=Math.min,max=Math.max;fabric.util.object.extend(fabric.Canvas.prototype,{_shouldGroup:function(e,target){var activeObject=this.getActiveObject();return e.shiftKey&&target&&target.selectable&&(this.getActiveGroup()||activeObject&&activeObject!==target)&&this.selection},_handleGrouping:function(e,target){if(target===this.getActiveGroup()){target=this.findTarget(e,true);if(!target||target.isType("group")){return}}if(this.getActiveGroup()){this._updateActiveGroup(target,e)}else{this._createActiveGroup(target,e)}if(this._activeGroup){this._activeGroup.saveCoords()}},_updateActiveGroup:function(target,e){var activeGroup=this.getActiveGroup();if(activeGroup.contains(target)){activeGroup.removeWithUpdate(target);target.set("active",false);if(activeGroup.size()===1){this.discardActiveGroup(e);this.setActiveObject(activeGroup.item(0));return}}else{activeGroup.addWithUpdate(target)}this.fire("selection:created",{target:activeGroup,e:e});activeGroup.set("active",true)},_createActiveGroup:function(target,e){if(this._activeObject&&target!==this._activeObject){var group=this._createGroup(target);group.addWithUpdate();this.setActiveGroup(group);this._activeObject=null;this.fire("selection:created",{target:group,e:e})}target.set("active",true)},_createGroup:function(target){var objects=this.getObjects(),isActiveLower=objects.indexOf(this._activeObject)1){group=new fabric.Group(group.reverse(),{canvas:this});group.addWithUpdate();this.setActiveGroup(group,e);group.saveCoords();this.fire("selection:created",{target:group});this.renderAll()}},_collectObjects:function(){var group=[],currentObject,x1=this._groupSelector.ex,y1=this._groupSelector.ey,x2=x1+this._groupSelector.left,y2=y1+this._groupSelector.top,selectionX1Y1=new fabric.Point(min(x1,x2),min(y1,y2)),selectionX2Y2=new fabric.Point(max(x1,x2),max(y1,y2)),isClick=x1===x2&&y1===y2;for(var i=this._objects.length;i--;){currentObject=this._objects[i];if(!currentObject||!currentObject.selectable||!currentObject.visible){continue}if(currentObject.intersectsWithRect(selectionX1Y1,selectionX2Y2)||currentObject.isContainedWithinRect(selectionX1Y1,selectionX2Y2)||currentObject.containsPoint(selectionX1Y1)||currentObject.containsPoint(selectionX2Y2)){currentObject.set("active",true);group.push(currentObject);if(isClick){break}}}return group},_maybeGroupObjects:function(e){if(this.selection&&this._groupSelector){this._groupSelectedObjects(e)}var activeGroup=this.getActiveGroup();if(activeGroup){activeGroup.setObjectsCoords().setCoords();activeGroup.isMoving=false;this.setCursor(this.defaultCursor)}this._groupSelector=null;this._currentTransform=null}})})();fabric.util.object.extend(fabric.StaticCanvas.prototype,{toDataURL:function(options){options||(options={});var format=options.format||"png",quality=options.quality||1,multiplier=options.multiplier||1,cropping={left:options.left,top:options.top,width:options.width,height:options.height};if(this._isRetinaScaling()){multiplier*=fabric.devicePixelRatio}if(multiplier!==1){return this.__toDataURLWithMultiplier(format,quality,cropping,multiplier)}else{return this.__toDataURL(format,quality,cropping)}},__toDataURL:function(format,quality,cropping){this.renderAll();var canvasEl=this.contextContainer.canvas,croppedCanvasEl=this.__getCroppedCanvas(canvasEl,cropping);if(format==="jpg"){format="jpeg"}var data=fabric.StaticCanvas.supports("toDataURLWithQuality")?(croppedCanvasEl||canvasEl).toDataURL("image/"+format,quality):(croppedCanvasEl||canvasEl).toDataURL("image/"+format);if(croppedCanvasEl){croppedCanvasEl=null}return data},__getCroppedCanvas:function(canvasEl,cropping){var croppedCanvasEl,croppedCtx,shouldCrop="left"in cropping||"top"in cropping||"width"in cropping||"height"in cropping;if(shouldCrop){croppedCanvasEl=fabric.util.createCanvasElement();croppedCtx=croppedCanvasEl.getContext("2d");croppedCanvasEl.width=cropping.width||this.width;croppedCanvasEl.height=cropping.height||this.height;croppedCtx.drawImage(canvasEl,-cropping.left||0,-cropping.top||0)}return croppedCanvasEl},__toDataURLWithMultiplier:function(format,quality,cropping,multiplier){var origWidth=this.getWidth(),origHeight=this.getHeight(),scaledWidth=origWidth*multiplier,scaledHeight=origHeight*multiplier,activeObject=this.getActiveObject(),activeGroup=this.getActiveGroup(),ctx=this.contextContainer;if(multiplier>1){this.setDimensions({width:scaledWidth,height:scaledHeight})}ctx.save();ctx.scale(multiplier/fabric.devicePixelRatio,multiplier/fabric.devicePixelRatio);if(cropping.left){cropping.left*=multiplier}if(cropping.top){cropping.top*=multiplier}if(cropping.width){cropping.width*=multiplier}else if(multiplier<1){cropping.width=scaledWidth}if(cropping.height){cropping.height*=multiplier}else if(multiplier<1){cropping.height=scaledHeight}if(activeGroup){this._tempRemoveBordersControlsFromGroup(activeGroup)}else if(activeObject&&this.deactivateAll){this.deactivateAll()}var data=this.__toDataURL(format,quality,cropping);this.width=origWidth;this.height=origHeight;this.setDimensions({width:origWidth,height:origHeight});if(activeGroup){this._restoreBordersControlsOnGroup(activeGroup)}else if(activeObject&&this.setActiveObject){this.setActiveObject(activeObject)}this.contextTop&&this.clearContext(this.contextTop);this.renderAll();return data},toDataURLWithMultiplier:function(format,multiplier,quality){return this.toDataURL({format:format,multiplier:multiplier,quality:quality})},_tempRemoveBordersControlsFromGroup:function(group){group.origHasControls=group.hasControls;group.origBorderColor=group.borderColor;group.hasControls=true;group.borderColor="rgba(0,0,0,0)";group.forEachObject(function(o){o.origBorderColor=o.borderColor;o.borderColor="rgba(0,0,0,0)"})},_restoreBordersControlsOnGroup:function(group){group.hideControls=group.origHideControls;group.borderColor=group.origBorderColor;group.forEachObject(function(o){o.borderColor=o.origBorderColor;delete o.origBorderColor})}});fabric.util.object.extend(fabric.StaticCanvas.prototype,{loadFromDatalessJSON:function(json,callback,reviver){return this.loadFromJSON(json,callback,reviver)},loadFromJSON:function(json,callback,reviver){if(!json){return}var serialized=typeof json==="string"?JSON.parse(json):json;this.clear();var _this=this;this._enlivenObjects(serialized.objects,function(){_this._setBgOverlay(serialized,callback)},reviver);return this},_setBgOverlay:function(serialized,callback){var _this=this,loaded={backgroundColor:false,overlayColor:false,backgroundImage:false,overlayImage:false};if(!serialized.backgroundImage&&!serialized.overlayImage&&!serialized.background&&!serialized.overlay){callback&&callback();return}var cbIfLoaded=function(){if(loaded.backgroundImage&&loaded.overlayImage&&loaded.backgroundColor&&loaded.overlayColor){_this.renderAll();callback&&callback()}};this.__setBgOverlay("backgroundImage",serialized.backgroundImage,loaded,cbIfLoaded);this.__setBgOverlay("overlayImage",serialized.overlayImage,loaded,cbIfLoaded);this.__setBgOverlay("backgroundColor",serialized.background,loaded,cbIfLoaded);this.__setBgOverlay("overlayColor",serialized.overlay,loaded,cbIfLoaded);cbIfLoaded()},__setBgOverlay:function(property,value,loaded,callback){var _this=this;if(!value){loaded[property]=true;return}if(property==="backgroundImage"||property==="overlayImage"){fabric.Image.fromObject(value,function(img){_this[property]=img;loaded[property]=true;callback&&callback()})}else{this["set"+fabric.util.string.capitalize(property,true)](value,function(){loaded[property]=true;callback&&callback()})}},_enlivenObjects:function(objects,callback,reviver){var _this=this;if(!objects||objects.length===0){callback&&callback();return}var renderOnAddRemove=this.renderOnAddRemove;this.renderOnAddRemove=false;fabric.util.enlivenObjects(objects,function(enlivenedObjects){enlivenedObjects.forEach(function(obj,index){_this.insertAt(obj,index,true)});_this.renderOnAddRemove=renderOnAddRemove;callback&&callback()},null,reviver)},_toDataURL:function(format,callback){this.clone(function(clone){callback(clone.toDataURL(format))})},_toDataURLWithMultiplier:function(format,multiplier,callback){this.clone(function(clone){callback(clone.toDataURLWithMultiplier(format,multiplier))})},clone:function(callback,properties){var data=JSON.stringify(this.toJSON(properties));this.cloneWithoutData(function(clone){clone.loadFromJSON(data,function(){callback&&callback(clone)})})},cloneWithoutData:function(callback){var el=fabric.document.createElement("canvas");el.width=this.getWidth();el.height=this.getHeight();var clone=new fabric.Canvas(el);clone.clipTo=this.clipTo;if(this.backgroundImage){clone.setBackgroundImage(this.backgroundImage.src,function(){clone.renderAll();callback&&callback(clone)});clone.backgroundImageOpacity=this.backgroundImageOpacity;clone.backgroundImageStretch=this.backgroundImageStretch}else{callback&&callback(clone)}}});(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),extend=fabric.util.object.extend,toFixed=fabric.util.toFixed,capitalize=fabric.util.string.capitalize,degreesToRadians=fabric.util.degreesToRadians,supportsLineDash=fabric.StaticCanvas.supports("setLineDash");if(fabric.Object){return}fabric.Object=fabric.util.createClass({type:"object",originX:"left",originY:"top",top:0,left:0,width:0,height:0,scaleX:1,scaleY:1,flipX:false,flipY:false,opacity:1,angle:0,skewX:0,skewY:0,cornerSize:12,transparentCorners:true,hoverCursor:null,padding:0,borderColor:"rgba(102,153,255,0.75)",cornerColor:"rgba(102,153,255,0.5)",centeredScaling:false,centeredRotation:true,fill:"rgb(0,0,0)",fillRule:"nonzero",globalCompositeOperation:"source-over",backgroundColor:"",stroke:null,strokeWidth:1,strokeDashArray:null,strokeLineCap:"butt",strokeLineJoin:"miter",strokeMiterLimit:10,shadow:null,borderOpacityWhenMoving:.4,borderScaleFactor:1,transformMatrix:null,minScaleLimit:.01,selectable:true,evented:true,visible:true,hasControls:true,hasBorders:true,hasRotatingPoint:true,rotatingPointOffset:40,perPixelTargetFind:false,includeDefaultValues:true,clipTo:null,lockMovementX:false,lockMovementY:false,lockRotation:false,lockScalingX:false,lockScalingY:false,lockUniScaling:false,lockSkewingX:false,lockSkewingY:false,lockScalingFlip:false,stateProperties:("top left width height scaleX scaleY flipX flipY originX originY transformMatrix "+"stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit "+"angle opacity fill fillRule globalCompositeOperation shadow clipTo visible backgroundColor "+"alignX alignY meetOrSlice skewX skewY").split(" "),initialize:function(options){if(options){this.setOptions(options)}},_initGradient:function(options){if(options.fill&&options.fill.colorStops&&!(options.fill instanceof fabric.Gradient)){this.set("fill",new fabric.Gradient(options.fill))}if(options.stroke&&options.stroke.colorStops&&!(options.stroke instanceof fabric.Gradient)){this.set("stroke",new fabric.Gradient(options.stroke))}},_initPattern:function(options){if(options.fill&&options.fill.source&&!(options.fill instanceof fabric.Pattern)){this.set("fill",new fabric.Pattern(options.fill))}if(options.stroke&&options.stroke.source&&!(options.stroke instanceof fabric.Pattern)){this.set("stroke",new fabric.Pattern(options.stroke))}},_initClipping:function(options){if(!options.clipTo||typeof options.clipTo!=="string"){return}var functionBody=fabric.util.getFunctionBody(options.clipTo);if(typeof functionBody!=="undefined"){this.clipTo=new Function("ctx",functionBody)}},setOptions:function(options){for(var prop in options){this.set(prop,options[prop])}this._initGradient(options);this._initPattern(options);this._initClipping(options)},transform:function(ctx,fromLeft){if(this.group&&this.canvas.preserveObjectStacking&&this.group===this.canvas._activeGroup){this.group.transform(ctx)}var center=fromLeft?this._getLeftTopCoords():this.getCenterPoint();ctx.translate(center.x,center.y);ctx.rotate(degreesToRadians(this.angle));ctx.scale(this.scaleX*(this.flipX?-1:1),this.scaleY*(this.flipY?-1:1));ctx.transform(1,0,Math.tan(degreesToRadians(this.skewX)),1,0,0);ctx.transform(1,Math.tan(degreesToRadians(this.skewY)),0,1,0,0)},toObject:function(propertiesToInclude){var NUM_FRACTION_DIGITS=fabric.Object.NUM_FRACTION_DIGITS,object={type:this.type,originX:this.originX,originY:this.originY,left:toFixed(this.left,NUM_FRACTION_DIGITS),top:toFixed(this.top,NUM_FRACTION_DIGITS),width:toFixed(this.width,NUM_FRACTION_DIGITS),height:toFixed(this.height,NUM_FRACTION_DIGITS),fill:this.fill&&this.fill.toObject?this.fill.toObject():this.fill,stroke:this.stroke&&this.stroke.toObject?this.stroke.toObject():this.stroke,strokeWidth:toFixed(this.strokeWidth,NUM_FRACTION_DIGITS),strokeDashArray:this.strokeDashArray?this.strokeDashArray.concat():this.strokeDashArray,strokeLineCap:this.strokeLineCap,strokeLineJoin:this.strokeLineJoin,strokeMiterLimit:toFixed(this.strokeMiterLimit,NUM_FRACTION_DIGITS),scaleX:toFixed(this.scaleX,NUM_FRACTION_DIGITS),scaleY:toFixed(this.scaleY,NUM_FRACTION_DIGITS),angle:toFixed(this.getAngle(),NUM_FRACTION_DIGITS),flipX:this.flipX,flipY:this.flipY,opacity:toFixed(this.opacity,NUM_FRACTION_DIGITS),shadow:this.shadow&&this.shadow.toObject?this.shadow.toObject():this.shadow,visible:this.visible,clipTo:this.clipTo&&String(this.clipTo),backgroundColor:this.backgroundColor,fillRule:this.fillRule,globalCompositeOperation:this.globalCompositeOperation,transformMatrix:this.transformMatrix?this.transformMatrix.concat():this.transformMatrix,skewX:toFixed(this.skewX,NUM_FRACTION_DIGITS),skewY:toFixed(this.skewY,NUM_FRACTION_DIGITS)};if(!this.includeDefaultValues){object=this._removeDefaultValues(object)}fabric.util.populateWithProperties(this,object,propertiesToInclude);return object},toDatalessObject:function(propertiesToInclude){return this.toObject(propertiesToInclude)},_removeDefaultValues:function(object){var prototype=fabric.util.getKlass(object.type).prototype,stateProperties=prototype.stateProperties;stateProperties.forEach(function(prop){if(object[prop]===prototype[prop]){delete object[prop]}var isArray=Object.prototype.toString.call(object[prop])==="[object Array]"&&Object.prototype.toString.call(prototype[prop])==="[object Array]";if(isArray&&object[prop].length===0&&prototype[prop].length===0){delete object[prop]}});return object},toString:function(){return"#"},get:function(property){return this[property]},_setObject:function(obj){for(var prop in obj){this._set(prop,obj[prop])}},set:function(key,value){if(typeof key==="object"){this._setObject(key)}else{if(typeof value==="function"&&key!=="clipTo"){this._set(key,value(this.get(key)))}else{this._set(key,value)}}return this},_set:function(key,value){var shouldConstrainValue=key==="scaleX"||key==="scaleY";if(shouldConstrainValue){value=this._constrainScale(value)}if(key==="scaleX"&&value<0){this.flipX=!this.flipX;value*=-1}else if(key==="scaleY"&&value<0){this.flipY=!this.flipY;value*=-1}else if(key==="width"||key==="height"){this.minScaleLimit=toFixed(Math.min(.1,1/Math.max(this.width,this.height)),2)}else if(key==="shadow"&&value&&!(value instanceof fabric.Shadow)){value=new fabric.Shadow(value)}this[key]=value;return this},setOnGroup:function(){},toggle:function(property){var value=this.get(property);if(typeof value==="boolean"){this.set(property,!value)}return this},setSourcePath:function(value){this.sourcePath=value;return this},getViewportTransform:function(){if(this.canvas&&this.canvas.viewportTransform){return this.canvas.viewportTransform}return[1,0,0,1,0,0]},render:function(ctx,noTransform){if(this.width===0&&this.height===0||!this.visible){return}ctx.save();this._setupCompositeOperation(ctx);if(!noTransform){this.transform(ctx)}this._setStrokeStyles(ctx);this._setFillStyles(ctx);if(this.transformMatrix){ctx.transform.apply(ctx,this.transformMatrix)}this._setOpacity(ctx);this._setShadow(ctx);this.clipTo&&fabric.util.clipContext(this,ctx);this._render(ctx,noTransform);this.clipTo&&ctx.restore();ctx.restore()},_setOpacity:function(ctx){if(this.group){this.group._setOpacity(ctx)}ctx.globalAlpha*=this.opacity},_setStrokeStyles:function(ctx){if(this.stroke){ctx.lineWidth=this.strokeWidth;ctx.lineCap=this.strokeLineCap;ctx.lineJoin=this.strokeLineJoin;ctx.miterLimit=this.strokeMiterLimit;ctx.strokeStyle=this.stroke.toLive?this.stroke.toLive(ctx,this):this.stroke}},_setFillStyles:function(ctx){if(this.fill){ctx.fillStyle=this.fill.toLive?this.fill.toLive(ctx,this):this.fill}},_renderControls:function(ctx,noTransform){if(!this.active||noTransform||this.group&&this.group!==this.canvas.getActiveGroup()){return}var vpt=this.getViewportTransform(),matrix=this.calcTransformMatrix(),options;matrix=fabric.util.multiplyTransformMatrices(vpt,matrix);options=fabric.util.qrDecompose(matrix);ctx.save();ctx.translate(options.translateX,options.translateY);if(this.group&&this.group===this.canvas.getActiveGroup()){ctx.rotate(degreesToRadians(options.angle));this.drawBordersInGroup(ctx,options)}else{ctx.rotate(degreesToRadians(this.angle));this.drawBorders(ctx)}this.drawControls(ctx);ctx.restore()},_setShadow:function(ctx){if(!this.shadow){return}var multX=this.canvas&&this.canvas.viewportTransform[0]||1,multY=this.canvas&&this.canvas.viewportTransform[3]||1;if(this.canvas&&this.canvas._isRetinaScaling()){multX*=fabric.devicePixelRatio;multY*=fabric.devicePixelRatio}ctx.shadowColor=this.shadow.color;ctx.shadowBlur=this.shadow.blur*(multX+multY)*(this.scaleX+this.scaleY)/4;ctx.shadowOffsetX=this.shadow.offsetX*multX*this.scaleX;ctx.shadowOffsetY=this.shadow.offsetY*multY*this.scaleY},_removeShadow:function(ctx){if(!this.shadow){return}ctx.shadowColor="";ctx.shadowBlur=ctx.shadowOffsetX=ctx.shadowOffsetY=0},_renderFill:function(ctx){if(!this.fill){return}ctx.save();if(this.fill.gradientTransform){var g=this.fill.gradientTransform;ctx.transform.apply(ctx,g)}if(this.fill.toLive){ctx.translate(-this.width/2+this.fill.offsetX||0,-this.height/2+this.fill.offsetY||0)}if(this.fillRule==="evenodd"){ctx.fill("evenodd")}else{ctx.fill()}ctx.restore()},_renderStroke:function(ctx){if(!this.stroke||this.strokeWidth===0){return}if(this.shadow&&!this.shadow.affectStroke){this._removeShadow(ctx)}ctx.save();if(this.strokeDashArray){if(1&this.strokeDashArray.length){this.strokeDashArray.push.apply(this.strokeDashArray,this.strokeDashArray) -}if(supportsLineDash){ctx.setLineDash(this.strokeDashArray);this._stroke&&this._stroke(ctx)}else{this._renderDashedStroke&&this._renderDashedStroke(ctx)}ctx.stroke()}else{if(this.stroke.gradientTransform){var g=this.stroke.gradientTransform;ctx.transform.apply(ctx,g)}this._stroke?this._stroke(ctx):ctx.stroke()}ctx.restore()},clone:function(callback,propertiesToInclude){if(this.constructor.fromObject){return this.constructor.fromObject(this.toObject(propertiesToInclude),callback)}return new fabric.Object(this.toObject(propertiesToInclude))},cloneAsImage:function(callback){var dataUrl=this.toDataURL();fabric.util.loadImage(dataUrl,function(img){if(callback){callback(new fabric.Image(img))}});return this},toDataURL:function(options){options||(options={});var el=fabric.util.createCanvasElement(),boundingRect=this.getBoundingRect();el.width=boundingRect.width;el.height=boundingRect.height;fabric.util.wrapElement(el,"div");var canvas=new fabric.StaticCanvas(el);if(options.format==="jpg"){options.format="jpeg"}if(options.format==="jpeg"){canvas.backgroundColor="#fff"}var origParams={active:this.get("active"),left:this.getLeft(),top:this.getTop()};this.set("active",false);this.setPositionByOrigin(new fabric.Point(el.width/2,el.height/2),"center","center");var originalCanvas=this.canvas;canvas.add(this);var data=canvas.toDataURL(options);this.set(origParams).setCoords();this.canvas=originalCanvas;canvas.dispose();canvas=null;return data},isType:function(type){return this.type===type},complexity:function(){return 0},toJSON:function(propertiesToInclude){return this.toObject(propertiesToInclude)},setGradient:function(property,options){options||(options={});var gradient={colorStops:[]};gradient.type=options.type||(options.r1||options.r2?"radial":"linear");gradient.coords={x1:options.x1,y1:options.y1,x2:options.x2,y2:options.y2};if(options.r1||options.r2){gradient.coords.r1=options.r1;gradient.coords.r2=options.r2}options.gradientTransform&&(gradient.gradientTransform=options.gradientTransform);for(var position in options.colorStops){var color=new fabric.Color(options.colorStops[position]);gradient.colorStops.push({offset:position,color:color.toRgb(),opacity:color.getAlpha()})}return this.set(property,fabric.Gradient.forObject(this,gradient))},setPatternFill:function(options){return this.set("fill",new fabric.Pattern(options))},setShadow:function(options){return this.set("shadow",options?new fabric.Shadow(options):null)},setColor:function(color){this.set("fill",color);return this},setAngle:function(angle){var shouldCenterOrigin=(this.originX!=="center"||this.originY!=="center")&&this.centeredRotation;if(shouldCenterOrigin){this._setOriginToCenter()}this.set("angle",angle);if(shouldCenterOrigin){this._resetOrigin()}return this},centerH:function(){this.canvas.centerObjectH(this);return this},centerV:function(){this.canvas.centerObjectV(this);return this},center:function(){this.canvas.centerObject(this);return this},remove:function(){this.canvas.remove(this);return this},getLocalPointer:function(e,pointer){pointer=pointer||this.canvas.getPointer(e);var pClicked=new fabric.Point(pointer.x,pointer.y),objectLeftTop=this._getLeftTopCoords();if(this.angle){pClicked=fabric.util.rotatePoint(pClicked,objectLeftTop,fabric.util.degreesToRadians(-this.angle))}return{x:pClicked.x-objectLeftTop.x,y:pClicked.y-objectLeftTop.y}},_setupCompositeOperation:function(ctx){if(this.globalCompositeOperation){ctx.globalCompositeOperation=this.globalCompositeOperation}}});fabric.util.createAccessors(fabric.Object);fabric.Object.prototype.rotate=fabric.Object.prototype.setAngle;extend(fabric.Object.prototype,fabric.Observable);fabric.Object.NUM_FRACTION_DIGITS=2;fabric.Object.__uid=0})(typeof exports!=="undefined"?exports:this);(function(){var degreesToRadians=fabric.util.degreesToRadians,originXOffset={left:-.5,center:0,right:.5},originYOffset={top:-.5,center:0,bottom:.5};fabric.util.object.extend(fabric.Object.prototype,{translateToGivenOrigin:function(point,fromOriginX,fromOriginY,toOriginX,toOriginY){var x=point.x,y=point.y,offsetX=originXOffset[toOriginX]-originXOffset[fromOriginX],offsetY=originYOffset[toOriginY]-originYOffset[fromOriginY],dim;if(offsetX||offsetY){dim=this._getTransformedDimensions();x=point.x+offsetX*dim.x;y=point.y+offsetY*dim.y}return new fabric.Point(x,y)},translateToCenterPoint:function(point,originX,originY){var p=this.translateToGivenOrigin(point,originX,originY,"center","center");if(this.angle){return fabric.util.rotatePoint(p,point,degreesToRadians(this.angle))}return p},translateToOriginPoint:function(center,originX,originY){var p=this.translateToGivenOrigin(center,"center","center",originX,originY);if(this.angle){return fabric.util.rotatePoint(p,center,degreesToRadians(this.angle))}return p},getCenterPoint:function(){var leftTop=new fabric.Point(this.left,this.top);return this.translateToCenterPoint(leftTop,this.originX,this.originY)},getPointByOrigin:function(originX,originY){var center=this.getCenterPoint();return this.translateToOriginPoint(center,originX,originY)},toLocalPoint:function(point,originX,originY){var center=this.getCenterPoint(),p,p2;if(originX&&originY){p=this.translateToGivenOrigin(center,"center","center",originX,originY)}else{p=new fabric.Point(this.left,this.top)}p2=new fabric.Point(point.x,point.y);if(this.angle){p2=fabric.util.rotatePoint(p2,center,-degreesToRadians(this.angle))}return p2.subtractEquals(p)},setPositionByOrigin:function(pos,originX,originY){var center=this.translateToCenterPoint(pos,originX,originY),position=this.translateToOriginPoint(center,this.originX,this.originY);this.set("left",position.x);this.set("top",position.y)},adjustPosition:function(to){var angle=degreesToRadians(this.angle),hypotFull=this.getWidth(),xFull=Math.cos(angle)*hypotFull,yFull=Math.sin(angle)*hypotFull;this.left+=xFull*(originXOffset[to]-originXOffset[this.originX]);this.top+=yFull*(originXOffset[to]-originXOffset[this.originX]);this.setCoords();this.originX=to},_setOriginToCenter:function(){this._originalOriginX=this.originX;this._originalOriginY=this.originY;var center=this.getCenterPoint();this.originX="center";this.originY="center";this.left=center.x;this.top=center.y},_resetOrigin:function(){var originPoint=this.translateToOriginPoint(this.getCenterPoint(),this._originalOriginX,this._originalOriginY);this.originX=this._originalOriginX;this.originY=this._originalOriginY;this.left=originPoint.x;this.top=originPoint.y;this._originalOriginX=null;this._originalOriginY=null},_getLeftTopCoords:function(){return this.translateToOriginPoint(this.getCenterPoint(),"left","top")}})})();(function(){function getCoords(oCoords){return[new fabric.Point(oCoords.tl.x,oCoords.tl.y),new fabric.Point(oCoords.tr.x,oCoords.tr.y),new fabric.Point(oCoords.br.x,oCoords.br.y),new fabric.Point(oCoords.bl.x,oCoords.bl.y)]}var degreesToRadians=fabric.util.degreesToRadians,multiplyMatrices=fabric.util.multiplyTransformMatrices;fabric.util.object.extend(fabric.Object.prototype,{oCoords:null,intersectsWithRect:function(pointTL,pointBR){var oCoords=getCoords(this.oCoords),intersection=fabric.Intersection.intersectPolygonRectangle(oCoords,pointTL,pointBR);return intersection.status==="Intersection"},intersectsWithObject:function(other){var intersection=fabric.Intersection.intersectPolygonPolygon(getCoords(this.oCoords),getCoords(other.oCoords));return intersection.status==="Intersection"},isContainedWithinObject:function(other){var boundingRect=other.getBoundingRect(),point1=new fabric.Point(boundingRect.left,boundingRect.top),point2=new fabric.Point(boundingRect.left+boundingRect.width,boundingRect.top+boundingRect.height);return this.isContainedWithinRect(point1,point2)},isContainedWithinRect:function(pointTL,pointBR){var boundingRect=this.getBoundingRect();return boundingRect.left>=pointTL.x&&boundingRect.left+boundingRect.width<=pointBR.x&&boundingRect.top>=pointTL.y&&boundingRect.top+boundingRect.height<=pointBR.y},containsPoint:function(point){var lines=this._getImageLines(this.oCoords),xPoints=this._findCrossPoints(point,lines);return xPoints!==0&&xPoints%2===1},_getImageLines:function(oCoords){return{topline:{o:oCoords.tl,d:oCoords.tr},rightline:{o:oCoords.tr,d:oCoords.br},bottomline:{o:oCoords.br,d:oCoords.bl},leftline:{o:oCoords.bl,d:oCoords.tl}}},_findCrossPoints:function(point,oCoords){var b1,b2,a1,a2,xi,yi,xcount=0,iLine;for(var lineKey in oCoords){iLine=oCoords[lineKey];if(iLine.o.y=point.y&&iLine.d.y>=point.y){continue}if(iLine.o.x===iLine.d.x&&iLine.o.x>=point.x){xi=iLine.o.x;yi=point.y}else{b1=0;b2=(iLine.d.y-iLine.o.y)/(iLine.d.x-iLine.o.x);a1=point.y-b1*point.x;a2=iLine.o.y-b2*iLine.o.x;xi=-(a1-a2)/(b1-b2);yi=a1+b1*xi}if(xi>=point.x){xcount+=1}if(xcount===2){break}}return xcount},getBoundingRectWidth:function(){return this.getBoundingRect().width},getBoundingRectHeight:function(){return this.getBoundingRect().height},getBoundingRect:function(){this.oCoords||this.setCoords();return fabric.util.makeBoundingBoxFromPoints([this.oCoords.tl,this.oCoords.tr,this.oCoords.br,this.oCoords.bl])},getWidth:function(){return this._getTransformedDimensions().x},getHeight:function(){return this._getTransformedDimensions().y},_constrainScale:function(value){if(Math.abs(value)0?Math.atan(currentHeight/currentWidth):0,_hypotenuse=currentWidth/Math.cos(_angle)/2,offsetX=Math.cos(_angle+theta)*_hypotenuse,offsetY=Math.sin(_angle+theta)*_hypotenuse,coords=fabric.util.transformPoint(this.getCenterPoint(),vpt),tl=new fabric.Point(coords.x-offsetX,coords.y-offsetY),tr=new fabric.Point(tl.x+currentWidth*cosTh,tl.y+currentWidth*sinTh),bl=new fabric.Point(tl.x-currentHeight*sinTh,tl.y+currentHeight*cosTh),br=new fabric.Point(coords.x+offsetX,coords.y+offsetY),ml=new fabric.Point((tl.x+bl.x)/2,(tl.y+bl.y)/2),mt=new fabric.Point((tr.x+tl.x)/2,(tr.y+tl.y)/2),mr=new fabric.Point((br.x+tr.x)/2,(br.y+tr.y)/2),mb=new fabric.Point((br.x+bl.x)/2,(br.y+bl.y)/2),mtr=new fabric.Point(mt.x+sinTh*this.rotatingPointOffset,mt.y-cosTh*this.rotatingPointOffset);this.oCoords={tl:tl,tr:tr,br:br,bl:bl,ml:ml,mt:mt,mr:mr,mb:mb,mtr:mtr};this._setCornerCoords&&this._setCornerCoords();return this},_calcRotateMatrix:function(){if(this.angle){var theta=degreesToRadians(this.angle),cos=Math.cos(theta),sin=Math.sin(theta);return[cos,sin,-sin,cos,0,0]}return[1,0,0,1,0,0]},calcTransformMatrix:function(){var center=this.getCenterPoint(),translateMatrix=[1,0,0,1,center.x,center.y],rotateMatrix=this._calcRotateMatrix(),dimensionMatrix=this._calcDimensionsTransformMatrix(this.skewX,this.skewY,true),matrix=this.group?this.group.calcTransformMatrix():[1,0,0,1,0,0];matrix=multiplyMatrices(matrix,translateMatrix);matrix=multiplyMatrices(matrix,rotateMatrix);matrix=multiplyMatrices(matrix,dimensionMatrix);return matrix},_calcDimensionsTransformMatrix:function(skewX,skewY,flipping){var skewMatrixX=[1,0,Math.tan(degreesToRadians(skewX)),1],skewMatrixY=[1,Math.tan(degreesToRadians(skewY)),0,1],scaleX=this.scaleX*(flipping&&this.flipX?-1:1),scaleY=this.scaleY*(flipping&&this.flipY?-1:1),scaleMatrix=[scaleX,0,0,scaleY],m=multiplyMatrices(scaleMatrix,skewMatrixX,true);return multiplyMatrices(m,skewMatrixY,true)}})})();fabric.util.object.extend(fabric.Object.prototype,{sendToBack:function(){if(this.group){fabric.StaticCanvas.prototype.sendToBack.call(this.group,this)}else{this.canvas.sendToBack(this)}return this},bringToFront:function(){if(this.group){fabric.StaticCanvas.prototype.bringToFront.call(this.group,this)}else{this.canvas.bringToFront(this)}return this},sendBackwards:function(intersecting){if(this.group){fabric.StaticCanvas.prototype.sendBackwards.call(this.group,this,intersecting)}else{this.canvas.sendBackwards(this,intersecting)}return this},bringForward:function(intersecting){if(this.group){fabric.StaticCanvas.prototype.bringForward.call(this.group,this,intersecting)}else{this.canvas.bringForward(this,intersecting)}return this},moveTo:function(index){if(this.group){fabric.StaticCanvas.prototype.moveTo.call(this.group,this,index)}else{this.canvas.moveTo(this,index)}return this}});fabric.util.object.extend(fabric.Object.prototype,{getSvgStyles:function(skipShadow){var fill=this.fill?this.fill.toLive?"url(#SVGID_"+this.fill.id+")":this.fill:"none",fillRule=this.fillRule,stroke=this.stroke?this.stroke.toLive?"url(#SVGID_"+this.stroke.id+")":this.stroke:"none",strokeWidth=this.strokeWidth?this.strokeWidth:"0",strokeDashArray=this.strokeDashArray?this.strokeDashArray.join(" "):"none",strokeLineCap=this.strokeLineCap?this.strokeLineCap:"butt",strokeLineJoin=this.strokeLineJoin?this.strokeLineJoin:"miter",strokeMiterLimit=this.strokeMiterLimit?this.strokeMiterLimit:"4",opacity=typeof this.opacity!=="undefined"?this.opacity:"1",visibility=this.visible?"":" visibility: hidden;",filter=skipShadow?"":this.getSvgFilter();return["stroke: ",stroke,"; ","stroke-width: ",strokeWidth,"; ","stroke-dasharray: ",strokeDashArray,"; ","stroke-linecap: ",strokeLineCap,"; ","stroke-linejoin: ",strokeLineJoin,"; ","stroke-miterlimit: ",strokeMiterLimit,"; ","fill: ",fill,"; ","fill-rule: ",fillRule,"; ","opacity: ",opacity,";",filter,visibility].join("")},getSvgFilter:function(){return this.shadow?"filter: url(#SVGID_"+this.shadow.id+");":""},getSvgTransform:function(){if(this.group&&this.group.type==="path-group"){return""}var toFixed=fabric.util.toFixed,angle=this.getAngle(),skewX=this.getSkewX()%360,skewY=this.getSkewY()%360,center=this.getCenterPoint(),NUM_FRACTION_DIGITS=fabric.Object.NUM_FRACTION_DIGITS,translatePart=this.type==="path-group"?"":"translate("+toFixed(center.x,NUM_FRACTION_DIGITS)+" "+toFixed(center.y,NUM_FRACTION_DIGITS)+")",anglePart=angle!==0?" rotate("+toFixed(angle,NUM_FRACTION_DIGITS)+")":"",scalePart=this.scaleX===1&&this.scaleY===1?"":" scale("+toFixed(this.scaleX,NUM_FRACTION_DIGITS)+" "+toFixed(this.scaleY,NUM_FRACTION_DIGITS)+")",skewXPart=skewX!==0?" skewX("+toFixed(skewX,NUM_FRACTION_DIGITS)+")":"",skewYPart=skewY!==0?" skewY("+toFixed(skewY,NUM_FRACTION_DIGITS)+")":"",addTranslateX=this.type==="path-group"?this.width:0,flipXPart=this.flipX?" matrix(-1 0 0 1 "+addTranslateX+" 0) ":"",addTranslateY=this.type==="path-group"?this.height:0,flipYPart=this.flipY?" matrix(1 0 0 -1 0 "+addTranslateY+")":"";return[translatePart,anglePart,scalePart,flipXPart,flipYPart,skewXPart,skewYPart].join("")},getSvgTransformMatrix:function(){return this.transformMatrix?" matrix("+this.transformMatrix.join(" ")+") ":""},_createBaseSVGMarkup:function(){var markup=[];if(this.fill&&this.fill.toLive){markup.push(this.fill.toSVG(this,false))}if(this.stroke&&this.stroke.toLive){markup.push(this.stroke.toSVG(this,false))}if(this.shadow){markup.push(this.shadow.toSVG(this))}return markup}});fabric.util.object.extend(fabric.Object.prototype,{hasStateChanged:function(){return this.stateProperties.some(function(prop){return this.get(prop)!==this.originalState[prop]},this)},saveState:function(options){this.stateProperties.forEach(function(prop){this.originalState[prop]=this.get(prop)},this);if(options&&options.stateProperties){options.stateProperties.forEach(function(prop){this.originalState[prop]=this.get(prop)},this)}return this},setupState:function(){this.originalState={};this.saveState();return this}});(function(){var degreesToRadians=fabric.util.degreesToRadians,isVML=function(){return typeof G_vmlCanvasManager!=="undefined"};fabric.util.object.extend(fabric.Object.prototype,{_controlsVisibility:null,_findTargetCorner:function(pointer){if(!this.hasControls||!this.active){return false}var ex=pointer.x,ey=pointer.y,xPoints,lines;this.__corner=0;for(var i in this.oCoords){if(!this.isControlVisible(i)){continue}if(i==="mtr"&&!this.hasRotatingPoint){continue}if(this.get("lockUniScaling")&&(i==="mt"||i==="mr"||i==="mb"||i==="ml")){continue}lines=this._getImageLines(this.oCoords[i].corner);xPoints=this._findCrossPoints({x:ex,y:ey},lines);if(xPoints!==0&&xPoints%2===1){this.__corner=i;return i}}return false},_setCornerCoords:function(){var coords=this.oCoords,newTheta=degreesToRadians(45-this.angle),cornerHypotenuse=this.cornerSize*.707106,cosHalfOffset=cornerHypotenuse*Math.cos(newTheta),sinHalfOffset=cornerHypotenuse*Math.sin(newTheta),x,y;for(var point in coords){x=coords[point].x;y=coords[point].y;coords[point].corner={tl:{x:x-sinHalfOffset,y:y-cosHalfOffset},tr:{x:x+cosHalfOffset,y:y-sinHalfOffset},bl:{x:x-cosHalfOffset,y:y+sinHalfOffset},br:{x:x+sinHalfOffset,y:y+cosHalfOffset}}}},_getNonTransformedDimensions:function(){var strokeWidth=this.strokeWidth,w=this.width,h=this.height,addStrokeToW=true,addStrokeToH=true;if(this.type==="line"&&this.strokeLineCap==="butt"){addStrokeToH=w;addStrokeToW=h}if(addStrokeToH){h+=h<0?-strokeWidth:strokeWidth}if(addStrokeToW){w+=w<0?-strokeWidth:strokeWidth}return{x:w,y:h}},_getTransformedDimensions:function(skewX,skewY){if(typeof skewX==="undefined"){skewX=this.skewX}if(typeof skewY==="undefined"){skewY=this.skewY}var dimensions=this._getNonTransformedDimensions(),dimX=dimensions.x/2,dimY=dimensions.y/2,points=[{x:-dimX,y:-dimY},{x:dimX,y:-dimY},{x:-dimX,y:dimY},{x:dimX,y:dimY}],i,transformMatrix=this._calcDimensionsTransformMatrix(skewX,skewY,false),bbox;for(i=0;i\n');return reviver?reviver(markup.join("")):markup.join("")},complexity:function(){return 1}});fabric.Line.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" "));fabric.Line.fromElement=function(element,options){var parsedAttributes=fabric.parseAttributes(element,fabric.Line.ATTRIBUTE_NAMES),points=[parsedAttributes.x1||0,parsedAttributes.y1||0,parsedAttributes.x2||0,parsedAttributes.y2||0];return new fabric.Line(points,extend(parsedAttributes,options))};fabric.Line.fromObject=function(object){var points=[object.x1,object.y1,object.x2,object.y2];return new fabric.Line(points,object)};function makeEdgeToOriginGetter(propertyNames,originValues){var origin=propertyNames.origin,axis1=propertyNames.axis1,axis2=propertyNames.axis2,dimension=propertyNames.dimension,nearest=originValues.nearest,center=originValues.center,farthest=originValues.farthest;return function(){switch(this.get(origin)){case nearest:return Math.min(this.get(axis1),this.get(axis2));case center:return Math.min(this.get(axis1),this.get(axis2))+.5*this.get(dimension);case farthest:return Math.max(this.get(axis1),this.get(axis2))}}}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),pi=Math.PI,extend=fabric.util.object.extend;if(fabric.Circle){fabric.warn("fabric.Circle is already defined.");return}fabric.Circle=fabric.util.createClass(fabric.Object,{type:"circle",radius:0,startAngle:0,endAngle:pi*2,initialize:function(options){options=options||{};this.callSuper("initialize",options);this.set("radius",options.radius||0);this.startAngle=options.startAngle||this.startAngle;this.endAngle=options.endAngle||this.endAngle},_set:function(key,value){this.callSuper("_set",key,value);if(key==="radius"){this.setRadius(value)}return this},toObject:function(propertiesToInclude){return extend(this.callSuper("toObject",propertiesToInclude),{radius:this.get("radius"),startAngle:this.startAngle,endAngle:this.endAngle})},toSVG:function(reviver){var markup=this._createBaseSVGMarkup(),x=0,y=0,angle=(this.endAngle-this.startAngle)%(2*pi);if(angle===0){if(this.group&&this.group.type==="path-group"){x=this.left+this.radius;y=this.top+this.radius}markup.push("\n')}else{var startX=Math.cos(this.startAngle)*this.radius,startY=Math.sin(this.startAngle)*this.radius,endX=Math.cos(this.endAngle)*this.radius,endY=Math.sin(this.endAngle)*this.radius,largeFlag=angle>pi?"1":"0";markup.push('\n')}return reviver?reviver(markup.join("")):markup.join("")},_render:function(ctx,noTransform){ctx.beginPath();ctx.arc(noTransform?this.left+this.radius:0,noTransform?this.top+this.radius:0,this.radius,this.startAngle,this.endAngle,false);this._renderFill(ctx);this._renderStroke(ctx)},getRadiusX:function(){return this.get("radius")*this.get("scaleX")},getRadiusY:function(){return this.get("radius")*this.get("scaleY")},setRadius:function(value){this.radius=value;return this.set("width",value*2).set("height",value*2)},complexity:function(){return 1}});fabric.Circle.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("cx cy r".split(" "));fabric.Circle.fromElement=function(element,options){options||(options={});var parsedAttributes=fabric.parseAttributes(element,fabric.Circle.ATTRIBUTE_NAMES);if(!isValidRadius(parsedAttributes)){throw new Error("value of `r` attribute is required and can not be negative")}parsedAttributes.left=parsedAttributes.left||0;parsedAttributes.top=parsedAttributes.top||0;var obj=new fabric.Circle(extend(parsedAttributes,options));obj.left-=obj.radius;obj.top-=obj.radius;return obj};function isValidRadius(attributes){return"radius"in attributes&&attributes.radius>=0}fabric.Circle.fromObject=function(object){return new fabric.Circle(object)}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={});if(fabric.Triangle){fabric.warn("fabric.Triangle is already defined");return}fabric.Triangle=fabric.util.createClass(fabric.Object,{type:"triangle",initialize:function(options){options=options||{};this.callSuper("initialize",options);this.set("width",options.width||100).set("height",options.height||100)},_render:function(ctx){var widthBy2=this.width/2,heightBy2=this.height/2;ctx.beginPath();ctx.moveTo(-widthBy2,heightBy2);ctx.lineTo(0,-heightBy2);ctx.lineTo(widthBy2,heightBy2);ctx.closePath();this._renderFill(ctx);this._renderStroke(ctx)},_renderDashedStroke:function(ctx){var widthBy2=this.width/2,heightBy2=this.height/2;ctx.beginPath();fabric.util.drawDashedLine(ctx,-widthBy2,heightBy2,0,-heightBy2,this.strokeDashArray);fabric.util.drawDashedLine(ctx,0,-heightBy2,widthBy2,heightBy2,this.strokeDashArray);fabric.util.drawDashedLine(ctx,widthBy2,heightBy2,-widthBy2,heightBy2,this.strokeDashArray); -ctx.closePath()},toSVG:function(reviver){var markup=this._createBaseSVGMarkup(),widthBy2=this.width/2,heightBy2=this.height/2,points=[-widthBy2+" "+heightBy2,"0 "+-heightBy2,widthBy2+" "+heightBy2].join(",");markup.push("');return reviver?reviver(markup.join("")):markup.join("")},complexity:function(){return 1}});fabric.Triangle.fromObject=function(object){return new fabric.Triangle(object)}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),piBy2=Math.PI*2,extend=fabric.util.object.extend;if(fabric.Ellipse){fabric.warn("fabric.Ellipse is already defined.");return}fabric.Ellipse=fabric.util.createClass(fabric.Object,{type:"ellipse",rx:0,ry:0,initialize:function(options){options=options||{};this.callSuper("initialize",options);this.set("rx",options.rx||0);this.set("ry",options.ry||0)},_set:function(key,value){this.callSuper("_set",key,value);switch(key){case"rx":this.rx=value;this.set("width",value*2);break;case"ry":this.ry=value;this.set("height",value*2);break}return this},getRx:function(){return this.get("rx")*this.get("scaleX")},getRy:function(){return this.get("ry")*this.get("scaleY")},toObject:function(propertiesToInclude){return extend(this.callSuper("toObject",propertiesToInclude),{rx:this.get("rx"),ry:this.get("ry")})},toSVG:function(reviver){var markup=this._createBaseSVGMarkup(),x=0,y=0;if(this.group&&this.group.type==="path-group"){x=this.left+this.rx;y=this.top+this.ry}markup.push("\n');return reviver?reviver(markup.join("")):markup.join("")},_render:function(ctx,noTransform){ctx.beginPath();ctx.save();ctx.transform(1,0,0,this.ry/this.rx,0,0);ctx.arc(noTransform?this.left+this.rx:0,noTransform?(this.top+this.ry)*this.rx/this.ry:0,this.rx,0,piBy2,false);ctx.restore();this._renderFill(ctx);this._renderStroke(ctx)},complexity:function(){return 1}});fabric.Ellipse.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" "));fabric.Ellipse.fromElement=function(element,options){options||(options={});var parsedAttributes=fabric.parseAttributes(element,fabric.Ellipse.ATTRIBUTE_NAMES);parsedAttributes.left=parsedAttributes.left||0;parsedAttributes.top=parsedAttributes.top||0;var ellipse=new fabric.Ellipse(extend(parsedAttributes,options));ellipse.top-=ellipse.ry;ellipse.left-=ellipse.rx;return ellipse};fabric.Ellipse.fromObject=function(object){return new fabric.Ellipse(object)}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),extend=fabric.util.object.extend;if(fabric.Rect){fabric.warn("fabric.Rect is already defined");return}var stateProperties=fabric.Object.prototype.stateProperties.concat();stateProperties.push("rx","ry","x","y");fabric.Rect=fabric.util.createClass(fabric.Object,{stateProperties:stateProperties,type:"rect",rx:0,ry:0,strokeDashArray:null,initialize:function(options){options=options||{};this.callSuper("initialize",options);this._initRxRy()},_initRxRy:function(){if(this.rx&&!this.ry){this.ry=this.rx}else if(this.ry&&!this.rx){this.rx=this.ry}},_render:function(ctx,noTransform){if(this.width===1&&this.height===1){ctx.fillRect(-.5,-.5,1,1);return}var rx=this.rx?Math.min(this.rx,this.width/2):0,ry=this.ry?Math.min(this.ry,this.height/2):0,w=this.width,h=this.height,x=noTransform?this.left:-this.width/2,y=noTransform?this.top:-this.height/2,isRounded=rx!==0||ry!==0,k=1-.5522847498;ctx.beginPath();ctx.moveTo(x+rx,y);ctx.lineTo(x+w-rx,y);isRounded&&ctx.bezierCurveTo(x+w-k*rx,y,x+w,y+k*ry,x+w,y+ry);ctx.lineTo(x+w,y+h-ry);isRounded&&ctx.bezierCurveTo(x+w,y+h-k*ry,x+w-k*rx,y+h,x+w-rx,y+h);ctx.lineTo(x+rx,y+h);isRounded&&ctx.bezierCurveTo(x+k*rx,y+h,x,y+h-k*ry,x,y+h-ry);ctx.lineTo(x,y+ry);isRounded&&ctx.bezierCurveTo(x,y+k*ry,x+k*rx,y,x+rx,y);ctx.closePath();this._renderFill(ctx);this._renderStroke(ctx)},_renderDashedStroke:function(ctx){var x=-this.width/2,y=-this.height/2,w=this.width,h=this.height;ctx.beginPath();fabric.util.drawDashedLine(ctx,x,y,x+w,y,this.strokeDashArray);fabric.util.drawDashedLine(ctx,x+w,y,x+w,y+h,this.strokeDashArray);fabric.util.drawDashedLine(ctx,x+w,y+h,x,y+h,this.strokeDashArray);fabric.util.drawDashedLine(ctx,x,y+h,x,y,this.strokeDashArray);ctx.closePath()},toObject:function(propertiesToInclude){var object=extend(this.callSuper("toObject",propertiesToInclude),{rx:this.get("rx")||0,ry:this.get("ry")||0});if(!this.includeDefaultValues){this._removeDefaultValues(object)}return object},toSVG:function(reviver){var markup=this._createBaseSVGMarkup(),x=this.left,y=this.top;if(!(this.group&&this.group.type==="path-group")){x=-this.width/2;y=-this.height/2}markup.push("\n');return reviver?reviver(markup.join("")):markup.join("")},complexity:function(){return 1}});fabric.Rect.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" "));fabric.Rect.fromElement=function(element,options){if(!element){return null}options=options||{};var parsedAttributes=fabric.parseAttributes(element,fabric.Rect.ATTRIBUTE_NAMES);parsedAttributes.left=parsedAttributes.left||0;parsedAttributes.top=parsedAttributes.top||0;var rect=new fabric.Rect(extend(options?fabric.util.object.clone(options):{},parsedAttributes));rect.visible=rect.width>0&&rect.height>0;return rect};fabric.Rect.fromObject=function(object){return new fabric.Rect(object)}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={});if(fabric.Polyline){fabric.warn("fabric.Polyline is already defined");return}fabric.Polyline=fabric.util.createClass(fabric.Object,{type:"polyline",points:null,minX:0,minY:0,initialize:function(points,options){return fabric.Polygon.prototype.initialize.call(this,points,options)},_calcDimensions:function(){return fabric.Polygon.prototype._calcDimensions.call(this)},_applyPointOffset:function(){return fabric.Polygon.prototype._applyPointOffset.call(this)},toObject:function(propertiesToInclude){return fabric.Polygon.prototype.toObject.call(this,propertiesToInclude)},toSVG:function(reviver){return fabric.Polygon.prototype.toSVG.call(this,reviver)},_render:function(ctx){if(!fabric.Polygon.prototype.commonRender.call(this,ctx)){return}this._renderFill(ctx);this._renderStroke(ctx)},_renderDashedStroke:function(ctx){var p1,p2;ctx.beginPath();for(var i=0,len=this.points.length;i\n');return reviver?reviver(markup.join("")):markup.join("")},_render:function(ctx,noTransform){if(!this.commonRender(ctx,noTransform)){return}this._renderFill(ctx);if(this.stroke||this.strokeDashArray){ctx.closePath();this._renderStroke(ctx)}},commonRender:function(ctx,noTransform){var point,len=this.points.length;if(!len||isNaN(this.points[len-1].y)){return false}noTransform||ctx.translate(-this.pathOffset.x,-this.pathOffset.y);ctx.beginPath();ctx.moveTo(this.points[0].x,this.points[0].y);for(var i=0;i"},toObject:function(propertiesToInclude){var o=extend(this.callSuper("toObject",propertiesToInclude),{path:this.path.map(function(item){return item.slice()}),pathOffset:this.pathOffset});if(this.sourcePath){o.sourcePath=this.sourcePath}if(this.transformMatrix){o.transformMatrix=this.transformMatrix}return o},toDatalessObject:function(propertiesToInclude){var o=this.toObject(propertiesToInclude);if(this.sourcePath){o.path=this.sourcePath}delete o.sourcePath;return o},toSVG:function(reviver){var chunks=[],markup=this._createBaseSVGMarkup(),addTransform="";for(var i=0,len=this.path.length;i\n");return reviver?reviver(markup.join("")):markup.join("")},complexity:function(){return this.path.length},_parsePath:function(){var result=[],coords=[],currentPath,parsed,re=/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/gi,match,coordsStr;for(var i=0,coordsParsed,len=this.path.length;icommandLength){for(var k=1,klen=coordsParsed.length;k\n");for(var i=0,len=objects.length;i\n");return reviver?reviver(markup.join("")):markup.join("")},toString:function(){return"#"},isSameColor:function(){var firstPathFill=this.getObjects()[0].get("fill")||"";if(typeof firstPathFill!=="string"){return false}firstPathFill=firstPathFill.toLowerCase();return this.getObjects().every(function(path){var pathFill=path.get("fill")||"";return typeof pathFill==="string"&&pathFill.toLowerCase()===firstPathFill})},complexity:function(){return this.paths.reduce(function(total,path){return total+(path&&path.complexity?path.complexity():0)},0)},getObjects:function(){return this.paths}});fabric.PathGroup.fromObject=function(object,callback){if(typeof object.paths==="string"){fabric.loadSVGFromURL(object.paths,function(elements){var pathUrl=object.paths;delete object.paths;var pathGroup=fabric.util.groupSVGElements(elements,object,pathUrl);callback(pathGroup)})}else{fabric.util.enlivenObjects(object.paths,function(enlivenedObjects){delete object.paths;callback(new fabric.PathGroup(enlivenedObjects,object))})}};fabric.PathGroup.async=true})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),extend=fabric.util.object.extend,min=fabric.util.array.min,max=fabric.util.array.max,invoke=fabric.util.array.invoke;if(fabric.Group){return}var _lockProperties={lockMovementX:true,lockMovementY:true,lockRotation:true,lockScalingX:true,lockScalingY:true,lockUniScaling:true};fabric.Group=fabric.util.createClass(fabric.Object,fabric.Collection,{type:"group",strokeWidth:0,initialize:function(objects,options,isAlreadyGrouped){options=options||{};this._objects=[];isAlreadyGrouped&&this.callSuper("initialize",options);this._objects=objects||[];for(var i=this._objects.length;i--;){this._objects[i].group=this}this.originalState={};if(options.originX){this.originX=options.originX}if(options.originY){this.originY=options.originY}if(isAlreadyGrouped){this._updateObjectsCoords(true)}else{this._calcBounds();this._updateObjectsCoords();this.callSuper("initialize",options)}this.setCoords();this.saveCoords()},_updateObjectsCoords:function(skipCoordsChange){for(var i=this._objects.length;i--;){this._updateObjectCoords(this._objects[i],skipCoordsChange)}},_updateObjectCoords:function(object,skipCoordsChange){object.__origHasControls=object.hasControls;object.hasControls=false;if(skipCoordsChange){return}var objectLeft=object.getLeft(),objectTop=object.getTop(),center=this.getCenterPoint();object.set({originalLeft:objectLeft,originalTop:objectTop,left:objectLeft-center.x,top:objectTop-center.y});object.setCoords()},toString:function(){return"#"},addWithUpdate:function(object){this._restoreObjectsState();fabric.util.resetObjectTransform(this);if(object){this._objects.push(object);object.group=this;object._set("canvas",this.canvas)}this.forEachObject(this._setObjectActive,this);this._calcBounds();this._updateObjectsCoords();return this},_setObjectActive:function(object){object.set("active",true);object.group=this},removeWithUpdate:function(object){this._restoreObjectsState();fabric.util.resetObjectTransform(this);this.forEachObject(this._setObjectActive,this);this.remove(object);this._calcBounds();this._updateObjectsCoords();return this},_onObjectAdded:function(object){object.group=this;object._set("canvas",this.canvas)},_onObjectRemoved:function(object){delete object.group;object.set("active",false)},delegatedProperties:{fill:true,stroke:true,strokeWidth:true,fontFamily:true,fontWeight:true,fontSize:true,fontStyle:true,lineHeight:true,textDecoration:true,textAlign:true,backgroundColor:true},_set:function(key,value){var i=this._objects.length;if(this.delegatedProperties[key]||key==="canvas"){while(i--){this._objects[i].set(key,value)}}else{while(i--){this._objects[i].setOnGroup(key,value)}}this.callSuper("_set",key,value)},toObject:function(propertiesToInclude){return extend(this.callSuper("toObject",propertiesToInclude),{objects:invoke(this._objects,"toObject",propertiesToInclude)})},render:function(ctx){if(!this.visible){return}ctx.save();if(this.transformMatrix){ctx.transform.apply(ctx,this.transformMatrix)}this.transform(ctx);this._setShadow(ctx);this.clipTo&&fabric.util.clipContext(this,ctx);for(var i=0,len=this._objects.length;i\n');for(var i=0,len=this._objects.length;i\n");return reviver?reviver(markup.join("")):markup.join("")},get:function(prop){if(prop in _lockProperties){if(this[prop]){return this[prop]}else{for(var i=0,len=this._objects.length;i0){object.resizeFilters=this.resizeFilters.map(function(filterObj){return filterObj&&filterObj.toObject()})}if(!this.includeDefaultValues){this._removeDefaultValues(object)}return object},toSVG:function(reviver){var markup=this._createBaseSVGMarkup(),x=-this.width/2,y=-this.height/2,preserveAspectRatio="none";if(this.group&&this.group.type==="path-group"){x=this.left;y=this.top}if(this.alignX!=="none"&&this.alignY!=="none"){preserveAspectRatio="x"+this.alignX+"Y"+this.alignY+" "+this.meetOrSlice}markup.push('\n','\n");if(this.stroke||this.strokeDashArray){var origFill=this.fill;this.fill=null;markup.push("\n');this.fill=origFill}markup.push("\n");return reviver?reviver(markup.join("")):markup.join("")},getSrc:function(){if(this.getElement()){return this.getElement().src||this.getElement()._src}},setSrc:function(src,callback,options){fabric.util.loadImage(src,function(img){return this.setElement(img,callback,options)},this,options&&options.crossOrigin)},toString:function(){return'#'},clone:function(callback,propertiesToInclude){this.constructor.fromObject(this.toObject(propertiesToInclude),callback)},applyFilters:function(callback,filters,imgElement,forResizing){filters=filters||this.filters;imgElement=imgElement||this._originalElement;if(!imgElement){return}var imgEl=imgElement,canvasEl=fabric.util.createCanvasElement(),replacement=fabric.util.createImage(),_this=this;canvasEl.width=imgEl.width;canvasEl.height=imgEl.height;canvasEl.getContext("2d").drawImage(imgEl,0,0,imgEl.width,imgEl.height);if(filters.length===0){this._element=imgElement;callback&&callback();return canvasEl}filters.forEach(function(filter){filter&&filter.applyTo(canvasEl,filter.scaleX||_this.scaleX,filter.scaleY||_this.scaleY);if(!forResizing&&filter&&filter.type==="Resize"){_this.width*=filter.scaleX;_this.height*=filter.scaleY}});replacement.width=canvasEl.width;replacement.height=canvasEl.height;if(fabric.isLikelyNode){replacement.src=canvasEl.toBuffer(undefined,fabric.Image.pngCompression);_this._element=replacement;!forResizing&&(_this._filteredEl=replacement);callback&&callback()}else{replacement.onload=function(){_this._element=replacement;!forResizing&&(_this._filteredEl=replacement);callback&&callback();replacement.onload=canvasEl=imgEl=null};replacement.src=canvasEl.toDataURL("image/png")}return canvasEl},_render:function(ctx,noTransform){var x,y,imageMargins=this._findMargins(),elementToDraw;x=noTransform?this.left:-this.width/2;y=noTransform?this.top:-this.height/2;if(this.meetOrSlice==="slice"){ctx.beginPath();ctx.rect(x,y,this.width,this.height);ctx.clip()}if(this.isMoving===false&&this.resizeFilters.length&&this._needsResize()){this._lastScaleX=this.scaleX;this._lastScaleY=this.scaleY;elementToDraw=this.applyFilters(null,this.resizeFilters,this._filteredEl||this._originalElement,true)}else{elementToDraw=this._element}elementToDraw&&ctx.drawImage(elementToDraw,x+imageMargins.marginX,y+imageMargins.marginY,imageMargins.width,imageMargins.height);this._renderStroke(ctx)},_needsResize:function(){return this.scaleX!==this._lastScaleX||this.scaleY!==this._lastScaleY},_findMargins:function(){var width=this.width,height=this.height,scales,scale,marginX=0,marginY=0;if(this.alignX!=="none"||this.alignY!=="none"){scales=[this.width/this._element.width,this.height/this._element.height];scale=this.meetOrSlice==="meet"?Math.min.apply(null,scales):Math.max.apply(null,scales);width=this._element.width*scale;height=this._element.height*scale;if(this.alignX==="Mid"){marginX=(this.width-width)/2}if(this.alignX==="Max"){marginX=this.width-width}if(this.alignY==="Mid"){marginY=(this.height-height)/2}if(this.alignY==="Max"){marginY=this.height-height}}return{width:width,height:height,marginX:marginX,marginY:marginY}},_resetWidthHeight:function(){var element=this.getElement();this.set("width",element.width);this.set("height",element.height)},_initElement:function(element,options){this.setElement(fabric.util.getById(element),null,options);fabric.util.addClass(this.getElement(),fabric.Image.CSS_CANVAS)},_initConfig:function(options){options||(options={});this.setOptions(options);this._setWidthHeight(options);if(this._element&&this.crossOrigin){this._element.crossOrigin=this.crossOrigin}},_initFilters:function(filters,callback){if(filters&&filters.length){fabric.util.enlivenObjects(filters,function(enlivenedObjects){callback&&callback(enlivenedObjects)},"fabric.Image.filters")}else{callback&&callback()}},_setWidthHeight:function(options){this.width="width"in options?options.width:this.getElement()?this.getElement().width||0:0;this.height="height"in options?options.height:this.getElement()?this.getElement().height||0:0},complexity:function(){return 1}});fabric.Image.CSS_CANVAS="canvas-img";fabric.Image.prototype.getSvgSrc=fabric.Image.prototype.getSrc;fabric.Image.fromObject=function(object,callback){fabric.util.loadImage(object.src,function(img){fabric.Image.prototype._initFilters.call(object,object.filters,function(filters){object.filters=filters||[];fabric.Image.prototype._initFilters.call(object,object.resizeFilters,function(resizeFilters){object.resizeFilters=resizeFilters||[];var instance=new fabric.Image(img,object);callback&&callback(instance)})})},null,object.crossOrigin)};fabric.Image.fromURL=function(url,callback,imgOptions){fabric.util.loadImage(url,function(img){callback&&callback(new fabric.Image(img,imgOptions))},null,imgOptions&&imgOptions.crossOrigin)};fabric.Image.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y width height preserveAspectRatio xlink:href".split(" "));fabric.Image.fromElement=function(element,callback,options){var parsedAttributes=fabric.parseAttributes(element,fabric.Image.ATTRIBUTE_NAMES),preserveAR;if(parsedAttributes.preserveAspectRatio){preserveAR=fabric.util.parsePreserveAspectRatioAttribute(parsedAttributes.preserveAspectRatio);extend(parsedAttributes,preserveAR)}fabric.Image.fromURL(parsedAttributes["xlink:href"],callback,extend(options?fabric.util.object.clone(options):{},parsedAttributes))};fabric.Image.async=true;fabric.Image.pngCompression=1})(typeof exports!=="undefined"?exports:this);fabric.util.object.extend(fabric.Object.prototype,{_getAngleValueForStraighten:function(){var angle=this.getAngle()%360;if(angle>0){return Math.round((angle-1)/90)*90}return Math.round(angle/90)*90},straighten:function(){this.setAngle(this._getAngleValueForStraighten());return this},fxStraighten:function(callbacks){callbacks=callbacks||{};var empty=function(){},onComplete=callbacks.onComplete||empty,onChange=callbacks.onChange||empty,_this=this;fabric.util.animate({startValue:this.get("angle"),endValue:this._getAngleValueForStraighten(),duration:this.FX_DURATION,onChange:function(value){_this.setAngle(value);onChange()},onComplete:function(){_this.setCoords();onComplete()},onStart:function(){_this.set("active",false)}});return this}});fabric.util.object.extend(fabric.StaticCanvas.prototype,{straightenObject:function(object){object.straighten();this.renderAll();return this},fxStraightenObject:function(object){object.fxStraighten({onChange:this.renderAll.bind(this)});return this}});fabric.Image.filters=fabric.Image.filters||{};fabric.Image.filters.BaseFilter=fabric.util.createClass({type:"BaseFilter",initialize:function(options){if(options){this.setOptions(options)}},setOptions:function(options){for(var prop in options){this[prop]=options[prop]}},toObject:function(){return{type:this.type}},toJSON:function(){return this.toObject()}});(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),extend=fabric.util.object.extend;fabric.Image.filters.Brightness=fabric.util.createClass(fabric.Image.filters.BaseFilter,{type:"Brightness",initialize:function(options){options=options||{};this.brightness=options.brightness||0},applyTo:function(canvasEl){var context=canvasEl.getContext("2d"),imageData=context.getImageData(0,0,canvasEl.width,canvasEl.height),data=imageData.data,brightness=this.brightness;for(var i=0,len=data.length;ish||scx<0||scx>sw){continue}srcOff=(scy*sw+scx)*4;wt=weights[cy*side+cx];r+=src[srcOff]*wt;g+=src[srcOff+1]*wt;b+=src[srcOff+2]*wt;a+=src[srcOff+3]*wt}}dst[dstOff]=r;dst[dstOff+1]=g;dst[dstOff+2]=b;dst[dstOff+3]=a+alphaFac*(255-a)}}context.putImageData(output,0,0)},toObject:function(){return extend(this.callSuper("toObject"),{opaque:this.opaque,matrix:this.matrix})}});fabric.Image.filters.Convolute.fromObject=function(object){return new fabric.Image.filters.Convolute(object)}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),extend=fabric.util.object.extend;fabric.Image.filters.GradientTransparency=fabric.util.createClass(fabric.Image.filters.BaseFilter,{type:"GradientTransparency",initialize:function(options){options=options||{};this.threshold=options.threshold||100},applyTo:function(canvasEl){var context=canvasEl.getContext("2d"),imageData=context.getImageData(0,0,canvasEl.width,canvasEl.height),data=imageData.data,threshold=this.threshold,total=data.length;for(var i=0,len=data.length;i-1?options.channel:0},applyTo:function(canvasEl){if(!this.mask){return}var context=canvasEl.getContext("2d"),imageData=context.getImageData(0,0,canvasEl.width,canvasEl.height),data=imageData.data,maskEl=this.mask.getElement(),maskCanvasEl=fabric.util.createCanvasElement(),channel=this.channel,i,iLen=imageData.width*imageData.height*4;maskCanvasEl.width=canvasEl.width;maskCanvasEl.height=canvasEl.height;maskCanvasEl.getContext("2d").drawImage(maskEl,0,0,canvasEl.width,canvasEl.height);var maskImageData=maskCanvasEl.getContext("2d").getImageData(0,0,canvasEl.width,canvasEl.height),maskData=maskImageData.data;for(i=0;ilimit&&g>limit&&b>limit&&abs(r-g)width){multW=2;signW=-1}if(newHeight>height){multH=2;signH=-1}imageData=context.getImageData(0,0,width,height);canvasEl.width=max(newWidth,width);canvasEl.height=max(newHeight,height);context.putImageData(imageData,0,0);while(!doneW||!doneH){width=stepW;height=stepH;if(newWidth*signWlobes){return 0}x*=Math.PI;if(abs(x)<1e-16){return 1}var xx=x/lobes;return sin(x)*sin(xx)/x/xx}}function process(u){var v,i,weight,idx,a,red,green,blue,alpha,fX,fY;center.x=(u+.5)*ratioX;icenter.x=floor(center.x);for(v=0;v=oW){continue}fX=floor(1e3*abs(i-center.x));if(!cacheLanc[fX]){cacheLanc[fX]={}}for(var j=icenter.y-range2Y;j<=icenter.y+range2Y;j++){if(j<0||j>=oH){continue}fY=floor(1e3*abs(j-center.y));if(!cacheLanc[fX][fY]){cacheLanc[fX][fY]=lanczos(sqrt(pow(fX*rcpRatioX,2)+pow(fY*rcpRatioY,2))/1e3)}weight=cacheLanc[fX][fY];if(weight>0){idx=(j*oW+i)*4;a+=weight;red+=weight*srcData[idx];green+=weight*srcData[idx+1];blue+=weight*srcData[idx+2];alpha+=weight*srcData[idx+3]}}}idx=(v*dW+u)*4;destData[idx]=red/a;destData[idx+1]=green/a;destData[idx+2]=blue/a;destData[idx+3]=alpha/a}if(++u1&&w<-1){continue}weight=2*w*w*w-3*w*w+1;if(weight>0){dx=4*(xx+yy*oW);gxA+=weight*data[dx+3];weightsAlpha+=weight;if(data[dx+3]<255){weight=weight*data[dx+3]/250}gxR+=weight*data[dx];gxG+=weight*data[dx+1];gxB+=weight*data[dx+2];weights+=weight}}}data2[x2]=gxR/weights;data2[x2+1]=gxG/weights;data2[x2+2]=gxB/weights;data2[x2+3]=gxA/weightsAlpha}}return img2},toObject:function(){return{type:this.type,scaleX:this.scaleX,scaleY:this.scaleY,resizeType:this.resizeType,lanczosLobes:this.lanczosLobes}}});fabric.Image.filters.Resize.fromObject=function(object){return new fabric.Image.filters.Resize(object)}})(typeof exports!=="undefined"?exports:this);(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),extend=fabric.util.object.extend,clone=fabric.util.object.clone,toFixed=fabric.util.toFixed,supportsLineDash=fabric.StaticCanvas.supports("setLineDash"),NUM_FRACTION_DIGITS=fabric.Object.NUM_FRACTION_DIGITS;if(fabric.Text){fabric.warn("fabric.Text is already defined");return}var stateProperties=fabric.Object.prototype.stateProperties.concat();stateProperties.push("fontFamily","fontWeight","fontSize","text","textDecoration","textAlign","fontStyle","lineHeight","textBackgroundColor");fabric.Text=fabric.util.createClass(fabric.Object,{_dimensionAffectingProps:{fontSize:true,fontWeight:true,fontFamily:true,fontStyle:true,lineHeight:true,stroke:true,strokeWidth:true,text:true,textAlign:true},_reNewline:/\r?\n/,_reSpacesAndTabs:/[ \t\r]+/g,type:"text",fontSize:40,fontWeight:"normal",fontFamily:"Times New Roman",textDecoration:"",textAlign:"left",fontStyle:"",lineHeight:1.16,textBackgroundColor:"",stateProperties:stateProperties,stroke:null,shadow:null,_fontSizeFraction:.25,_fontSizeMult:1.13,initialize:function(text,options){options=options||{};this.text=text;this.__skipDimension=true;this.setOptions(options);this.__skipDimension=false;this._initDimensions()},_initDimensions:function(ctx){if(this.__skipDimension){return}if(!ctx){ctx=fabric.util.createCanvasElement().getContext("2d");this._setTextStyles(ctx)}this._textLines=this._splitTextIntoLines();this._clearCache();this._cacheLinesWidth=this.textAlign!=="justify";this.width=this._getTextWidth(ctx);this._cacheLinesWidth=true;this.height=this._getTextHeight(ctx)},toString:function(){return"#'},_render:function(ctx){this.clipTo&&fabric.util.clipContext(this,ctx);this._setOpacity(ctx);this._setShadow(ctx);this._setupCompositeOperation(ctx);this._renderTextBackground(ctx);this._setStrokeStyles(ctx);this._setFillStyles(ctx);this._renderText(ctx);this._renderTextDecoration(ctx);this.clipTo&&ctx.restore()},_renderText:function(ctx){this._translateForTextAlign(ctx);this._renderTextFill(ctx);this._renderTextStroke(ctx);this._translateForTextAlign(ctx,true)},_translateForTextAlign:function(ctx,back){if(this.textAlign!=="left"&&this.textAlign!=="justify"){var sign=back?-1:1;ctx.translate(this.textAlign==="center"?sign*this.width/2:sign*this.width,0)}},_setTextStyles:function(ctx){ctx.textBaseline="alphabetic";if(!this.skipTextAlign){ctx.textAlign=this.textAlign}ctx.font=this._getFontDeclaration()},_getTextHeight:function(){return this._textLines.length*this._getHeightOfLine()},_getTextWidth:function(ctx){var maxWidth=this._getLineWidth(ctx,0);for(var i=1,len=this._textLines.length;imaxWidth){maxWidth=currentLineWidth}}return maxWidth},_renderChars:function(method,ctx,chars,left,top){var shortM=method.slice(0,-4); -if(this[shortM].toLive){var offsetX=-this.width/2+this[shortM].offsetX||0,offsetY=-this.height/2+this[shortM].offsetY||0;ctx.save();ctx.translate(offsetX,offsetY);left-=offsetX;top-=offsetY}ctx[method](chars,left,top);this[shortM].toLive&&ctx.restore()},_renderTextLine:function(method,ctx,line,left,top,lineIndex){top-=this.fontSize*this._fontSizeFraction;var lineWidth=this._getLineWidth(ctx,lineIndex);if(this.textAlign!=="justify"||this.width0?widthDiff/numSpaces:0,leftOffset=0,word;for(var i=0,len=words.length;i1){width=this.width}else{width=ctx.measureText(line).width}}else{width=ctx.measureText(line).width}this._cacheLinesWidth&&(this.__lineWidths[lineIndex]=width);return width},_renderTextDecoration:function(ctx){if(!this.textDecoration){return}var halfOfVerticalBox=this.height/2,_this=this,offsets=[];function renderLinesAtOffset(offsets){var i,lineHeight=0,len,j,oLen,lineWidth,lineLeftOffset,heightOfLine;for(i=0,len=_this._textLines.length;i-1){offsets.push(.85)}if(this.textDecoration.indexOf("line-through")>-1){offsets.push(.43)}if(this.textDecoration.indexOf("overline")>-1){offsets.push(-.12)}if(offsets.length>0){renderLinesAtOffset(offsets)}},_getFontDeclaration:function(){return[fabric.isLikelyNode?this.fontWeight:this.fontStyle,fabric.isLikelyNode?this.fontStyle:this.fontWeight,this.fontSize+"px",fabric.isLikelyNode?'"'+this.fontFamily+'"':this.fontFamily].join(" ")},render:function(ctx,noTransform){if(!this.visible){return}ctx.save();this._setTextStyles(ctx);if(this._shouldClearCache()){this._initDimensions(ctx)}if(!noTransform){this.transform(ctx)}if(this.transformMatrix){ctx.transform.apply(ctx,this.transformMatrix)}if(this.group&&this.group.type==="path-group"){ctx.translate(this.left,this.top)}this._render(ctx);ctx.restore()},_splitTextIntoLines:function(){return this.text.split(this._reNewline)},toObject:function(propertiesToInclude){var object=extend(this.callSuper("toObject",propertiesToInclude),{text:this.text,fontSize:this.fontSize,fontWeight:this.fontWeight,fontFamily:this.fontFamily,fontStyle:this.fontStyle,lineHeight:this.lineHeight,textDecoration:this.textDecoration,textAlign:this.textAlign,textBackgroundColor:this.textBackgroundColor});if(!this.includeDefaultValues){this._removeDefaultValues(object)}return object},toSVG:function(reviver){var markup=this._createBaseSVGMarkup(),offsets=this._getSVGLeftTopOffsets(this.ctx),textAndBg=this._getSVGTextAndBg(offsets.textTop,offsets.textLeft);this._wrapSVGTextAndBg(markup,textAndBg);return reviver?reviver(markup.join("")):markup.join("")},_getSVGLeftTopOffsets:function(ctx){var lineTop=this._getHeightOfLine(ctx,0),textLeft=-this.width/2,textTop=0;return{textLeft:textLeft+(this.group&&this.group.type==="path-group"?this.left:0),textTop:textTop+(this.group&&this.group.type==="path-group"?-this.top:0),lineTop:lineTop}},_wrapSVGTextAndBg:function(markup,textAndBg){var noShadow=true,filter=this.getSvgFilter(),style=filter===""?"":' style="'+filter+'"';markup.push(' \n",textAndBg.textBgRects.join("")," \n',textAndBg.textSpans.join("")," \n"," \n")},_getSVGTextAndBg:function(textTopOffset,textLeftOffset){var textSpans=[],textBgRects=[],height=0;this._setSVGBg(textBgRects);for(var i=0,len=this._textLines.length;i",fabric.util.string.escapeXml(this._textLines[i]),"\n")},_setSVGTextLineJustifed:function(i,textSpans,yPos,textLeftOffset){var ctx=fabric.util.createCanvasElement().getContext("2d");this._setTextStyles(ctx);var line=this._textLines[i],words=line.split(/\s+/),wordsWidth=this._getWidthOfWords(ctx,line),widthDiff=this.width-wordsWidth,numSpaces=words.length-1,spaceWidth=numSpaces>0?widthDiff/numSpaces:0,word,attributes=this._getFillAttributes(this.fill),len;textLeftOffset+=this._getLineLeftOffset(this._getLineWidth(ctx,i));for(i=0,len=words.length;i",fabric.util.string.escapeXml(word),"\n");textLeftOffset+=this._getWidthOfWords(ctx,word)+spaceWidth}},_setSVGTextLineBg:function(textBgRects,i,textLeftOffset,textTopOffset,height){textBgRects.push(" \n')},_setSVGBg:function(textBgRects){if(this.backgroundColor){textBgRects.push(" \n')}},_getFillAttributes:function(value){var fillColor=value&&typeof value==="string"?new fabric.Color(value):"";if(!fillColor||!fillColor.getSource()||fillColor.getAlpha()===1){return'fill="'+value+'"'}return'opacity="'+fillColor.getAlpha()+'" fill="'+fillColor.setAlpha(1).toRgb()+'"'},_set:function(key,value){this.callSuper("_set",key,value);if(key in this._dimensionAffectingProps){this._initDimensions();this.setCoords()}},complexity:function(){return 1}});fabric.Text.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y dx dy font-family font-style font-weight font-size text-decoration text-anchor".split(" "));fabric.Text.DEFAULT_SVG_FONT_SIZE=16;fabric.Text.fromElement=function(element,options){if(!element){return null}var parsedAttributes=fabric.parseAttributes(element,fabric.Text.ATTRIBUTE_NAMES);options=fabric.util.object.extend(options?fabric.util.object.clone(options):{},parsedAttributes);options.top=options.top||0;options.left=options.left||0;if("dx"in parsedAttributes){options.left+=parsedAttributes.dx}if("dy"in parsedAttributes){options.top+=parsedAttributes.dy}if(!("fontSize"in options)){options.fontSize=fabric.Text.DEFAULT_SVG_FONT_SIZE}if(!options.originX){options.originX="left"}var textContent="";if(!("textContent"in element)){if("firstChild"in element&&element.firstChild!==null){if("data"in element.firstChild&&element.firstChild.data!==null){textContent=element.firstChild.data}}}else{textContent=element.textContent}textContent=textContent.replace(/^\s+|\s+$|\n+/g,"").replace(/\s+/g," ");var text=new fabric.Text(textContent,options),offX=0;if(text.originX==="left"){offX=text.getWidth()/2}if(text.originX==="right"){offX=-text.getWidth()/2}text.set({left:text.getLeft()+offX,top:text.getTop()-text.getHeight()/2+text.fontSize*(.18+text._fontSizeFraction)});return text};fabric.Text.fromObject=function(object){return new fabric.Text(object.text,clone(object))};fabric.util.createAccessors(fabric.Text)})(typeof exports!=="undefined"?exports:this);(function(){var clone=fabric.util.object.clone;fabric.IText=fabric.util.createClass(fabric.Text,fabric.Observable,{type:"i-text",selectionStart:0,selectionEnd:0,selectionColor:"rgba(17,119,255,0.3)",isEditing:false,editable:true,editingBorderColor:"rgba(102,153,255,0.25)",cursorWidth:2,cursorColor:"#333",cursorDelay:1e3,cursorDuration:600,styles:null,caching:true,_reSpace:/\s|\n/,_currentCursorOpacity:0,_selectionDirection:null,_abortCursorAnimation:false,_charWidthsCache:{},__widthOfSpace:[],initialize:function(text,options){this.styles=options?options.styles||{}:{};this.callSuper("initialize",text,options);this.initBehavior()},_clearCache:function(){this.callSuper("_clearCache");this.__widthOfSpace=[]},isEmptyStyles:function(){if(!this.styles){return true}var obj=this.styles;for(var p1 in obj){for(var p2 in obj[p1]){for(var p3 in obj[p1][p2]){return false}}}return true},setSelectionStart:function(index){index=Math.max(index,0);if(this.selectionStart!==index){this.fire("selection:changed");this.canvas&&this.canvas.fire("text:selection:changed",{target:this});this.selectionStart=index}this._updateTextarea()},setSelectionEnd:function(index){index=Math.min(index,this.text.length);if(this.selectionEnd!==index){this.fire("selection:changed");this.canvas&&this.canvas.fire("text:selection:changed",{target:this});this.selectionEnd=index}this._updateTextarea()},getSelectionStyles:function(startIndex,endIndex){if(arguments.length===2){var styles=[];for(var i=startIndex;i=start.charIndex&&(i!==endLine||jstartLine&&i0||this.skipFillStrokeCheck)){this.callSuper("_renderChars",method,ctx,line,left,top)}},_renderChar:function(method,ctx,lineIndex,i,_char,left,top,lineHeight){var charWidth,charHeight,shouldFill,shouldStroke,decl=this._getStyleDeclaration(lineIndex,i),offset,textDecoration;if(decl){charHeight=this._getHeightOfChar(ctx,_char,lineIndex,i);shouldStroke=decl.stroke;shouldFill=decl.fill;textDecoration=decl.textDecoration}else{charHeight=this.fontSize}shouldStroke=(shouldStroke||this.stroke)&&method==="strokeText";shouldFill=(shouldFill||this.fill)&&method==="fillText";decl&&ctx.save();charWidth=this._applyCharStylesGetWidth(ctx,_char,lineIndex,i,decl||{});textDecoration=textDecoration||this.textDecoration;if(decl&&decl.textBackgroundColor){this._removeShadow(ctx)}shouldFill&&ctx.fillText(_char,left,top);shouldStroke&&ctx.strokeText(_char,left,top);if(textDecoration||textDecoration!==""){offset=this._fontSizeFraction*lineHeight/this.lineHeight;this._renderCharDecoration(ctx,textDecoration,left,top,offset,charWidth,charHeight)}decl&&ctx.restore();ctx.translate(charWidth,0)},_hasStyleChanged:function(prevStyle,thisStyle){return prevStyle.fill!==thisStyle.fill||prevStyle.fontSize!==thisStyle.fontSize||prevStyle.textBackgroundColor!==thisStyle.textBackgroundColor||prevStyle.textDecoration!==thisStyle.textDecoration||prevStyle.fontFamily!==thisStyle.fontFamily||prevStyle.fontWeight!==thisStyle.fontWeight||prevStyle.fontStyle!==thisStyle.fontStyle||prevStyle.stroke!==thisStyle.stroke||prevStyle.strokeWidth!==thisStyle.strokeWidth},_renderCharDecoration:function(ctx,textDecoration,left,top,offset,charWidth,charHeight){if(!textDecoration){return}var decorationWeight=charHeight/15,positions={underline:top+charHeight/10,"line-through":top-charHeight*(this._fontSizeFraction+this._fontSizeMult-1)+decorationWeight,overline:top-(this._fontSizeMult-this._fontSizeFraction)*charHeight},decorations=["underline","line-through","overline"],i,decoration;for(i=0;i-1){ctx.fillRect(left,positions[decoration],charWidth,decorationWeight)}}},_renderTextLine:function(method,ctx,line,left,top,lineIndex){if(!this.isEmptyStyles()){top+=this.fontSize*(this._fontSizeFraction+.03)}this.callSuper("_renderTextLine",method,ctx,line,left,top,lineIndex)},_renderTextDecoration:function(ctx){if(this.isEmptyStyles()){return this.callSuper("_renderTextDecoration",ctx)}},_renderTextLinesBackground:function(ctx){this.callSuper("_renderTextLinesBackground",ctx);var lineTopOffset=0,heightOfLine,lineWidth,lineLeftOffset,leftOffset=this._getLeftOffset(),topOffset=this._getTopOffset(),line,_char,style;for(var i=0,len=this._textLines.length;imaxHeight){maxHeight=currentCharHeight}}this.__lineHeights[lineIndex]=maxHeight*this.lineHeight*this._fontSizeMult;return this.__lineHeights[lineIndex]},_getTextHeight:function(ctx){var height=0;for(var i=0,len=this._textLines.length;i-1){offset++;index--}return startFrom-offset},findWordBoundaryRight:function(startFrom){var offset=0,index=startFrom;if(this._reSpace.test(this.text.charAt(index))){while(this._reSpace.test(this.text.charAt(index))){offset++;index++}}while(/\S/.test(this.text.charAt(index))&&index-1){offset++;index--}return startFrom-offset},findLineBoundaryRight:function(startFrom){var offset=0,index=startFrom;while(!/\n/.test(this.text.charAt(index))&&index0&&index=_this.__selectionStartOnMouseDown){_this.setSelectionStart(_this.__selectionStartOnMouseDown);_this.setSelectionEnd(newSelectionStart)}else{_this.setSelectionStart(newSelectionStart);_this.setSelectionEnd(_this.__selectionStartOnMouseDown)}})},_setEditingProps:function(){this.hoverCursor="text";if(this.canvas){this.canvas.defaultCursor=this.canvas.moveCursor="text"}this.borderColor=this.editingBorderColor;this.hasControls=this.selectable=false;this.lockMovementX=this.lockMovementY=true},_updateTextarea:function(){if(!this.hiddenTextarea||this.inCompositionMode){return}this.hiddenTextarea.value=this.text;this.hiddenTextarea.selectionStart=this.selectionStart;this.hiddenTextarea.selectionEnd=this.selectionEnd;if(this.selectionStart===this.selectionEnd){var p=this._calcTextareaPosition();this.hiddenTextarea.style.left=p.x+"px";this.hiddenTextarea.style.top=p.y+"px"}},_calcTextareaPosition:function(){var chars=this.text.split(""),boundaries=this._getCursorBoundaries(chars,"cursor"),cursorLocation=this.get2DCursorLocation(),lineIndex=cursorLocation.lineIndex,charIndex=cursorLocation.charIndex,charHeight=this.getCurrentCharFontSize(lineIndex,charIndex),leftOffset=lineIndex===0&&charIndex===0?this._getLineLeftOffset(this._getLineWidth(this.ctx,lineIndex)):boundaries.leftOffset,m=this.calcTransformMatrix(),p={x:boundaries.left+leftOffset,y:boundaries.top+boundaries.topOffset+charHeight};this.hiddenTextarea.style.fontSize=charHeight+"px";return fabric.util.transformPoint(p,m)},_saveEditingProps:function(){this._savedProps={hasControls:this.hasControls,borderColor:this.borderColor,lockMovementX:this.lockMovementX,lockMovementY:this.lockMovementY,hoverCursor:this.hoverCursor,defaultCursor:this.canvas&&this.canvas.defaultCursor,moveCursor:this.canvas&&this.canvas.moveCursor}},_restoreEditingProps:function(){if(!this._savedProps){return}this.hoverCursor=this._savedProps.overCursor;this.hasControls=this._savedProps.hasControls;this.borderColor=this._savedProps.borderColor;this.lockMovementX=this._savedProps.lockMovementX;this.lockMovementY=this._savedProps.lockMovementY;if(this.canvas){this.canvas.defaultCursor=this._savedProps.defaultCursor;this.canvas.moveCursor=this._savedProps.moveCursor}},exitEditing:function(){this.selected=false;this.isEditing=false;this.selectable=true;this.selectionEnd=this.selectionStart;this.hiddenTextarea&&this.canvas&&this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea);this.hiddenTextarea=null;this.abortCursorAnimation();this._restoreEditingProps();this._currentCursorOpacity=0;this.fire("editing:exited");this.canvas&&this.canvas.fire("text:editing:exited",{target:this});return this},_removeExtraneousStyles:function(){for(var prop in this.styles){if(!this._textLines[prop]){delete this.styles[prop]}}},_removeCharsFromTo:function(start,end){while(end!==start){this._removeSingleCharAndStyle(start+1);end--}this.setSelectionStart(start)},_removeSingleCharAndStyle:function(index){var isBeginningOfLine=this.text[index-1]==="\n",indexStyle=isBeginningOfLine?index:index-1;this.removeStyleObject(isBeginningOfLine,indexStyle);this.text=this.text.slice(0,index-1)+this.text.slice(index);this._textLines=this._splitTextIntoLines()},insertChars:function(_chars,useCopiedStyle){var style;if(this.selectionEnd-this.selectionStart>1){this._removeCharsFromTo(this.selectionStart,this.selectionEnd);this.setSelectionEnd(this.selectionStart)}if(!useCopiedStyle&&this.isEmptyStyles()){this.insertChar(_chars,false);return}for(var i=0,len=_chars.length;i=charIndex){newLineStyles[parseInt(index,10)-charIndex]=this.styles[lineIndex][index];delete this.styles[lineIndex][index]}}this.styles[lineIndex+1]=newLineStyles}this._forceClearCache=true},insertCharStyleObject:function(lineIndex,charIndex,style){var currentLineStyles=this.styles[lineIndex],currentLineStylesCloned=clone(currentLineStyles);if(charIndex===0&&!style){charIndex=1}for(var index in currentLineStylesCloned){var numericIndex=parseInt(index,10);if(numericIndex>=charIndex){currentLineStyles[numericIndex+1]=currentLineStylesCloned[numericIndex];if(!currentLineStylesCloned[numericIndex-1]){delete currentLineStyles[numericIndex]}}}this.styles[lineIndex][charIndex]=style||clone(currentLineStyles[charIndex-1]);this._forceClearCache=true},insertStyleObjects:function(_chars,isEndOfLine,styleObject){var cursorLocation=this.get2DCursorLocation(),lineIndex=cursorLocation.lineIndex,charIndex=cursorLocation.charIndex;if(!this._getLineStyle(lineIndex)){this._setLineStyle(lineIndex,{})}if(_chars==="\n"){this.insertNewlineStyleObject(lineIndex,charIndex,isEndOfLine)}else{this.insertCharStyleObject(lineIndex,charIndex,styleObject)}},shiftLineStyles:function(lineIndex,offset){var clonedStyles=clone(this.styles);for(var line in this.styles){var numericLine=parseInt(line,10);if(numericLine>lineIndex){this.styles[numericLine+offset]=clonedStyles[numericLine];if(!clonedStyles[numericLine-offset]){delete this.styles[numericLine]}}}},removeStyleObject:function(isBeginningOfLine,index){var cursorLocation=this.get2DCursorLocation(index),lineIndex=cursorLocation.lineIndex,charIndex=cursorLocation.charIndex;this._removeStyleObject(isBeginningOfLine,cursorLocation,lineIndex,charIndex)},_getTextOnPreviousLine:function(lIndex){return this._textLines[lIndex-1]},_removeStyleObject:function(isBeginningOfLine,cursorLocation,lineIndex,charIndex){if(isBeginningOfLine){var textOnPreviousLine=this._getTextOnPreviousLine(cursorLocation.lineIndex),newCharIndexOnPrevLine=textOnPreviousLine?textOnPreviousLine.length:0;if(!this.styles[lineIndex-1]){this.styles[lineIndex-1]={}}for(charIndex in this.styles[lineIndex]){this.styles[lineIndex-1][parseInt(charIndex,10)+newCharIndexOnPrevLine]=this.styles[lineIndex][charIndex]}this.shiftLineStyles(cursorLocation.lineIndex,-1)}else{var currentLineStyles=this.styles[lineIndex];if(currentLineStyles){delete currentLineStyles[charIndex]}var currentLineStylesCloned=clone(currentLineStyles);for(var i in currentLineStylesCloned){var numericIndex=parseInt(i,10);if(numericIndex>=charIndex&&numericIndex!==0){currentLineStyles[numericIndex-1]=currentLineStylesCloned[numericIndex];delete currentLineStyles[numericIndex]}}}},insertNewline:function(){this.insertChars("\n")}})})();fabric.util.object.extend(fabric.IText.prototype,{initDoubleClickSimulation:function(){this.__lastClickTime=+new Date;this.__lastLastClickTime=+new Date;this.__lastPointer={};this.on("mousedown",this.onMouseDown.bind(this))},onMouseDown:function(options){this.__newClickTime=+new Date;var newPointer=this.canvas.getPointer(options.e);if(this.isTripleClick(newPointer)){this.fire("tripleclick",options);this._stopEvent(options.e)}else if(this.isDoubleClick(newPointer)){this.fire("dblclick",options);this._stopEvent(options.e)}this.__lastLastClickTime=this.__lastClickTime;this.__lastClickTime=this.__newClickTime;this.__lastPointer=newPointer;this.__lastIsEditing=this.isEditing;this.__lastSelected=this.selected},isDoubleClick:function(newPointer){return this.__newClickTime-this.__lastClickTime<500&&this.__lastPointer.x===newPointer.x&&this.__lastPointer.y===newPointer.y&&this.__lastIsEditing},isTripleClick:function(newPointer){return this.__newClickTime-this.__lastClickTime<500&&this.__lastClickTime-this.__lastLastClickTime<500&&this.__lastPointer.x===newPointer.x&&this.__lastPointer.y===newPointer.y},_stopEvent:function(e){e.preventDefault&&e.preventDefault();e.stopPropagation&&e.stopPropagation()},initCursorSelectionHandlers:function(){this.initSelectedHandler();this.initMousedownHandler();this.initMouseupHandler();this.initClicks()},initClicks:function(){this.on("dblclick",function(options){this.selectWord(this.getSelectionStartFromPointer(options.e))});this.on("tripleclick",function(options){this.selectLine(this.getSelectionStartFromPointer(options.e))})},initMousedownHandler:function(){this.on("mousedown",function(options){if(!this.editable){return}var pointer=this.canvas.getPointer(options.e);this.__mousedownX=pointer.x;this.__mousedownY=pointer.y;this.__isMousedown=true;if(this.hiddenTextarea&&this.canvas){this.canvas.wrapperEl.appendChild(this.hiddenTextarea)}if(this.selected){this.setCursorByClick(options.e)}if(this.isEditing){this.__selectionStartOnMouseDown=this.selectionStart;this.initDelayedCursor(true)}})},_isObjectMoved:function(e){var pointer=this.canvas.getPointer(e);return this.__mousedownX!==pointer.x||this.__mousedownY!==pointer.y},initMouseupHandler:function(){this.on("mouseup",function(options){this.__isMousedown=false;if(!this.editable||this._isObjectMoved(options.e)){return}if(this.__lastSelected&&!this.__corner){this.enterEditing(options.e);this.initDelayedCursor(true)}this.selected=true})},setCursorByClick:function(e){var newSelectionStart=this.getSelectionStartFromPointer(e);if(e.shiftKey){if(newSelectionStartdistanceBtwLastCharAndCursor?0:1,newSelectionStart=index+offset;if(this.flipX){newSelectionStart=jlen-newSelectionStart}if(newSelectionStart>this.text.length){newSelectionStart=this.text.length}return newSelectionStart}});fabric.util.object.extend(fabric.IText.prototype,{initHiddenTextarea:function(e){var p;if(e&&this.canvas){p=this.canvas.getPointer(e)}else{this.oCoords||this.setCoords();p=this.oCoords.tl}this.hiddenTextarea=fabric.document.createElement("textarea");this.hiddenTextarea.setAttribute("autocapitalize","off");this.hiddenTextarea.style.cssText="position: absolute; top: "+p.y+"px; left: "+p.x+"px; opacity: 0;"+" width: 0px; height: 0px; z-index: -999;";if(this.canvas){this.canvas.lowerCanvasEl.parentNode.appendChild(this.hiddenTextarea)}else{fabric.document.body.appendChild(this.hiddenTextarea)}fabric.util.addListener(this.hiddenTextarea,"keydown",this.onKeyDown.bind(this));fabric.util.addListener(this.hiddenTextarea,"keyup",this.onKeyUp.bind(this));fabric.util.addListener(this.hiddenTextarea,"input",this.onInput.bind(this));fabric.util.addListener(this.hiddenTextarea,"copy",this.copy.bind(this));fabric.util.addListener(this.hiddenTextarea,"cut",this.cut.bind(this));fabric.util.addListener(this.hiddenTextarea,"paste",this.paste.bind(this));fabric.util.addListener(this.hiddenTextarea,"compositionstart",this.onCompositionStart.bind(this));fabric.util.addListener(this.hiddenTextarea,"compositionupdate",this.onCompositionUpdate.bind(this));fabric.util.addListener(this.hiddenTextarea,"compositionend",this.onCompositionEnd.bind(this));if(!this._clickHandlerInitialized&&this.canvas){fabric.util.addListener(this.canvas.upperCanvasEl,"click",this.onClick.bind(this));this._clickHandlerInitialized=true}},_keysMap:{8:"removeChars",9:"exitEditing",27:"exitEditing",13:"insertNewline",33:"moveCursorUp",34:"moveCursorDown",35:"moveCursorRight",36:"moveCursorLeft",37:"moveCursorLeft",38:"moveCursorUp",39:"moveCursorRight",40:"moveCursorDown",46:"forwardDelete"},_ctrlKeysMap:{65:"selectAll",67:"copy",88:"cut"},onClick:function(){this.hiddenTextarea&&this.hiddenTextarea.focus()},onKeyDown:function(e){if(!this.isEditing){return}if(e.keyCode in this._keysMap){this[this._keysMap[e.keyCode]](e)}else{return}e.stopImmediatePropagation();e.preventDefault();this.canvas&&this.canvas.renderAll()},onKeyUp:function(e){if(!this.isEditing||this._copyDone){this._copyDone=false;return}if(e.keyCode in this._ctrlKeysMap&&(e.ctrlKey||e.metaKey)){this[this._ctrlKeysMap[e.keyCode]](e)}else{return}e.stopImmediatePropagation();e.preventDefault();this.canvas&&this.canvas.renderAll()},onInput:function(e){if(!this.isEditing||this.inCompositionMode){return}var offset=this.selectionStart||0,offsetEnd=this.selectionEnd||0,textLength=this.text.length,newTextLength=this.hiddenTextarea.value.length,diff,charsToInsert,start;if(newTextLength>textLength){start=this._selectionDirection==="left"?offsetEnd:offset;diff=newTextLength-textLength;charsToInsert=this.hiddenTextarea.value.slice(start,start+diff)}else{diff=newTextLength-textLength+offsetEnd-offset;charsToInsert=this.hiddenTextarea.value.slice(offset,offset+diff)}this.insertChars(charsToInsert);e.stopPropagation()},onCompositionStart:function(){this.inCompositionMode=true;this.prevCompositionLength=0;this.compositionStart=this.selectionStart},onCompositionEnd:function(){this.inCompositionMode=false},onCompositionUpdate:function(e){var data=e.data;this.selectionStart=this.compositionStart;this.selectionEnd=this.selectionEnd===this.selectionStart?this.compositionStart+this.prevCompositionLength:this.selectionEnd;this.insertChars(data,false);this.prevCompositionLength=data.length},forwardDelete:function(e){if(this.selectionStart===this.selectionEnd){if(this.selectionStart===this.text.length){return}this.moveCursorRight(e)}this.removeChars(e)},copy:function(e){if(this.selectionStart===this.selectionEnd){return}var selectedText=this.getSelectedText(),clipboardData=this._getClipboardData(e);if(clipboardData){clipboardData.setData("text",selectedText)}fabric.copiedText=selectedText;fabric.copiedTextStyle=this.getSelectionStyles(this.selectionStart,this.selectionEnd);e.stopImmediatePropagation();e.preventDefault();this._copyDone=true},paste:function(e){var copiedText=null,clipboardData=this._getClipboardData(e),useCopiedStyle=true;if(clipboardData){copiedText=clipboardData.getData("text").replace(/\r/g,"");if(!fabric.copiedTextStyle||fabric.copiedText!==copiedText){useCopiedStyle=false}}else{copiedText=fabric.copiedText}if(copiedText){this.insertChars(copiedText,useCopiedStyle)}e.stopImmediatePropagation();e.preventDefault()},cut:function(e){if(this.selectionStart===this.selectionEnd){return}this.copy(e);this.removeChars(e)},_getClipboardData:function(e){return e&&e.clipboardData||fabric.window.clipboardData},getDownCursorOffset:function(e,isRight){var selectionProp=isRight?this.selectionEnd:this.selectionStart,cursorLocation=this.get2DCursorLocation(selectionProp),_char,lineLeftOffset,lineIndex=cursorLocation.lineIndex,textOnSameLineBeforeCursor=this._textLines[lineIndex].slice(0,cursorLocation.charIndex),textOnSameLineAfterCursor=this._textLines[lineIndex].slice(cursorLocation.charIndex),textOnNextLine=this._textLines[lineIndex+1]||"";if(lineIndex===this._textLines.length-1||e.metaKey||e.keyCode===34){return this.text.length-selectionProp}var widthOfSameLineBeforeCursor=this._getLineWidth(this.ctx,lineIndex);lineLeftOffset=this._getLineLeftOffset(widthOfSameLineBeforeCursor);var widthOfCharsOnSameLineBeforeCursor=lineLeftOffset;for(var i=0,len=textOnSameLineBeforeCursor.length;iwidthOfCharsOnSameLineBeforeCursor){foundMatch=true;var leftEdge=widthOfCharsOnNextLine-widthOfChar,rightEdge=widthOfCharsOnNextLine,offsetFromLeftEdge=Math.abs(leftEdge-widthOfCharsOnSameLineBeforeCursor),offsetFromRightEdge=Math.abs(rightEdge-widthOfCharsOnSameLineBeforeCursor);indexOnNextLine=offsetFromRightEdgethis.text.length){this.setSelectionEnd(this.text.length)}},getUpCursorOffset:function(e,isRight){var selectionProp=isRight?this.selectionEnd:this.selectionStart,cursorLocation=this.get2DCursorLocation(selectionProp),lineIndex=cursorLocation.lineIndex;if(lineIndex===0||e.metaKey||e.keyCode===33){return selectionProp}var textOnSameLineBeforeCursor=this._textLines[lineIndex].slice(0,cursorLocation.charIndex),textOnPreviousLine=this._textLines[lineIndex-1]||"",_char,widthOfSameLineBeforeCursor=this._getLineWidth(this.ctx,cursorLocation.lineIndex),lineLeftOffset=this._getLineLeftOffset(widthOfSameLineBeforeCursor),widthOfCharsOnSameLineBeforeCursor=lineLeftOffset;for(var i=0,len=textOnSameLineBeforeCursor.length;iwidthOfCharsOnSameLineBeforeCursor){foundMatch=true;var leftEdge=widthOfCharsOnPreviousLine-widthOfChar,rightEdge=widthOfCharsOnPreviousLine,offsetFromLeftEdge=Math.abs(leftEdge-widthOfCharsOnSameLineBeforeCursor),offsetFromRightEdge=Math.abs(rightEdge-widthOfCharsOnSameLineBeforeCursor);indexOnPrevLine=offsetFromRightEdge=this.text.length&&this.selectionEnd>=this.text.length){return}this.abortCursorAnimation();this._currentCursorOpacity=1;if(e.shiftKey){this.moveCursorRightWithShift(e)}else{this.moveCursorRightWithoutShift(e)}this.initDelayedCursor()},moveCursorRightWithShift:function(e){if(this._selectionDirection==="left"&&this.selectionStart!==this.selectionEnd){this._moveRight(e,"selectionStart")}else{this._selectionDirection="right";this._moveRight(e,"selectionEnd")}},moveCursorRightWithoutShift:function(e){this._selectionDirection="right";if(this.selectionStart===this.selectionEnd){this._moveRight(e,"selectionStart");this.setSelectionEnd(this.selectionStart)}else{this.setSelectionEnd(this.selectionEnd+this.getNumNewLinesInSelectedText());this.setSelectionStart(this.selectionEnd)}},removeChars:function(e){if(this.selectionStart===this.selectionEnd){this._removeCharsNearCursor(e)}else{this._removeCharsFromTo(this.selectionStart,this.selectionEnd)}this.setSelectionEnd(this.selectionStart);this._removeExtraneousStyles();this.canvas&&this.canvas.renderAll();this.setCoords();this.fire("changed");this.canvas&&this.canvas.fire("text:changed",{target:this})},_removeCharsNearCursor:function(e){if(this.selectionStart===0){return}if(e.metaKey){var leftLineBoundary=this.findLineBoundaryLeft(this.selectionStart);this._removeCharsFromTo(leftLineBoundary,this.selectionStart);this.setSelectionStart(leftLineBoundary)}else if(e.altKey){var leftWordBoundary=this.findWordBoundaryLeft(this.selectionStart);this._removeCharsFromTo(leftWordBoundary,this.selectionStart);this.setSelectionStart(leftWordBoundary)}else{this._removeSingleCharAndStyle(this.selectionStart);this.setSelectionStart(this.selectionStart-1)}}});(function(){var toFixed=fabric.util.toFixed,NUM_FRACTION_DIGITS=fabric.Object.NUM_FRACTION_DIGITS;fabric.util.object.extend(fabric.IText.prototype,{_setSVGTextLineText:function(lineIndex,textSpans,height,textLeftOffset,textTopOffset,textBgRects){if(!this._getLineStyle(lineIndex)){fabric.Text.prototype._setSVGTextLineText.call(this,lineIndex,textSpans,height,textLeftOffset,textTopOffset)}else{this._setSVGTextLineChars(lineIndex,textSpans,height,textLeftOffset,textBgRects)}},_setSVGTextLineChars:function(lineIndex,textSpans,height,textLeftOffset,textBgRects){var chars=this._textLines[lineIndex],charOffset=0,lineLeftOffset=this._getLineLeftOffset(this._getLineWidth(this.ctx,lineIndex))-this.width/2,lineOffset=this._getSVGLineTopOffset(lineIndex),heightOfLine=this._getHeightOfLine(this.ctx,lineIndex);for(var i=0,len=chars.length;i\n'].join("")},_createTextCharSpan:function(_char,styleDecl,lineLeftOffset,lineTopOffset,charOffset){var fillStyles=this.getSvgStyles.call(fabric.util.object.extend({visible:true,fill:this.fill,stroke:this.stroke,type:"text",getSvgFilter:fabric.Object.prototype.getSvgFilter},styleDecl));return[' ',fabric.util.string.escapeXml(_char),"\n"].join("")}})})();(function(global){"use strict";var fabric=global.fabric||(global.fabric={}),clone=fabric.util.object.clone;fabric.Textbox=fabric.util.createClass(fabric.IText,fabric.Observable,{type:"textbox",minWidth:20,dynamicMinWidth:0,__cachedLines:null,initialize:function(text,options){this.ctx=fabric.util.createCanvasElement().getContext("2d");this.callSuper("initialize",text,options);this.set({lockUniScaling:false,lockScalingY:true,lockScalingFlip:true,hasBorders:true});this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());this._dimensionAffectingProps.width=true},_initDimensions:function(ctx){if(this.__skipDimension){return}if(!ctx){ctx=fabric.util.createCanvasElement().getContext("2d");this._setTextStyles(ctx)}this.dynamicMinWidth=0;this._textLines=this._splitTextIntoLines();if(this.dynamicMinWidth>this.width){this._set("width",this.dynamicMinWidth)}this._clearCache();this.height=this._getTextHeight(ctx)},_generateStyleMap:function(){var realLineCount=0,realLineCharCount=0,charCount=0,map={};for(var i=0;i=this.width&&!lineJustStarted){lines.push(line);line="";lineWidth=wordWidth;lineJustStarted=true}if(!lineJustStarted){line+=infix}line+=word;infixWidth=this._measureText(ctx,infix,lineIndex,offset);offset++;lineJustStarted=false;if(wordWidth>largestWordWidth){largestWordWidth=wordWidth}}i&&lines.push(line);if(largestWordWidth>this.dynamicMinWidth){this.dynamicMinWidth=largestWordWidth}return lines},_splitTextIntoLines:function(){var originalAlign=this.textAlign;this.ctx.save();this._setTextStyles(this.ctx);this.textAlign="left";var lines=this._wrapText(this.ctx,this.text);this.textAlign=originalAlign;this.ctx.restore();this._textLines=lines;this._styleMap=this._generateStyleMap();return lines},setOnGroup:function(key,value){if(key==="scaleX"){this.set("scaleX",Math.abs(1/value));this.set("width",this.get("width")*value/(typeof this.__oldScaleX==="undefined"?1:this.__oldScaleX));this.__oldScaleX=value}},get2DCursorLocation:function(selectionStart){if(typeof selectionStart==="undefined"){selectionStart=this.selectionStart}var numLines=this._textLines.length,removed=0;for(var i=0;i=t.getMinWidth()){t.set("width",w)}}else{setObjectScaleOverridden.call(fabric.Canvas.prototype,localMouse,transform,lockScalingX,lockScalingY,by,lockScalingFlip,_dim)}};fabric.Group.prototype._refreshControlsVisibility=function(){if(typeof fabric.Textbox==="undefined"){return}for(var i=this._objects.length;i--;){if(this._objects[i]instanceof fabric.Textbox){this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());return}}};var clone=fabric.util.object.clone;fabric.util.object.extend(fabric.Textbox.prototype,{_removeExtraneousStyles:function(){for(var prop in this._styleMap){if(!this._textLines[prop]){delete this.styles[this._styleMap[prop].line]}}},insertCharStyleObject:function(lineIndex,charIndex,style){var map=this._styleMap[lineIndex];lineIndex=map.line;charIndex=map.offset+charIndex;fabric.IText.prototype.insertCharStyleObject.apply(this,[lineIndex,charIndex,style])},insertNewlineStyleObject:function(lineIndex,charIndex,isEndOfLine){var map=this._styleMap[lineIndex];lineIndex=map.line;charIndex=map.offset+charIndex;fabric.IText.prototype.insertNewlineStyleObject.apply(this,[lineIndex,charIndex,isEndOfLine])},shiftLineStyles:function(lineIndex,offset){var clonedStyles=clone(this.styles),map=this._styleMap[lineIndex];lineIndex=map.line;for(var line in this.styles){var numericLine=parseInt(line,10);if(numericLine>lineIndex){this.styles[numericLine+offset]=clonedStyles[numericLine];if(!clonedStyles[numericLine-offset]){delete this.styles[numericLine]}}}},_getTextOnPreviousLine:function(lIndex){var textOnPreviousLine=this._textLines[lIndex-1];while(this._styleMap[lIndex-2]&&this._styleMap[lIndex-2].line===this._styleMap[lIndex-1].line){textOnPreviousLine=this._textLines[lIndex-2]+textOnPreviousLine;lIndex--}return textOnPreviousLine},removeStyleObject:function(isBeginningOfLine,index){var cursorLocation=this.get2DCursorLocation(index),map=this._styleMap[cursorLocation.lineIndex],lineIndex=map.line,charIndex=map.offset+cursorLocation.charIndex;this._removeStyleObject(isBeginningOfLine,cursorLocation,lineIndex,charIndex)}})})();(function(){var override=fabric.IText.prototype._getNewSelectionStartFromOffset;fabric.IText.prototype._getNewSelectionStartFromOffset=function(mouseOffset,prevWidth,width,index,jlen){index=override.call(this,mouseOffset,prevWidth,width,index,jlen);var tmp=0,removed=0;for(var i=0;i=index){break}if(this.text[tmp+removed]==="\n"||this.text[tmp+removed]===" "){removed++}}return index-i+removed}})();(function(){if(typeof document!=="undefined"&&typeof window!=="undefined"){return}var DOMParser=require("xmldom").DOMParser,URL=require("url"),HTTP=require("http"),HTTPS=require("https"),Canvas=require("canvas"),Image=require("canvas").Image;function request(url,encoding,callback){var oURL=URL.parse(url);if(!oURL.port){oURL.port=oURL.protocol.indexOf("https:")===0?443:80}var reqHandler=oURL.protocol.indexOf("https:")===0?HTTPS:HTTP,req=reqHandler.request({hostname:oURL.hostname,port:oURL.port,path:oURL.path,method:"GET"},function(response){var body="";if(encoding){response.setEncoding(encoding)}response.on("end",function(){callback(body)});response.on("data",function(chunk){if(response.statusCode===200){body+=chunk}})});req.on("error",function(err){if(err.errno===process.ECONNREFUSED){fabric.log("ECONNREFUSED: connection refused to "+oURL.hostname+":"+oURL.port)}else{fabric.log(err.message)}callback(null)});req.end()}function requestFs(path,callback){var fs=require("fs");fs.readFile(path,function(err,data){if(err){fabric.log(err);throw err}else{callback(data)}})}fabric.util.loadImage=function(url,callback,context){function createImageAndCallBack(data){if(data){img.src=new Buffer(data,"binary");img._src=url;callback&&callback.call(context,img)}else{img=null;callback&&callback.call(context,null,true)}}var img=new Image;if(url&&(url instanceof Buffer||url.indexOf("data")===0)){img.src=img._src=url;callback&&callback.call(context,img)}else if(url&&url.indexOf("http")!==0){requestFs(url,createImageAndCallBack)}else if(url){request(url,"binary",createImageAndCallBack)}else{callback&&callback.call(context,url)}};fabric.loadSVGFromURL=function(url,callback,reviver){url=url.replace(/^\n\s*/,"").replace(/\?.*$/,"").trim();if(url.indexOf("http")!==0){requestFs(url,function(body){fabric.loadSVGFromString(body.toString(),callback,reviver)})}else{request(url,"",function(body){fabric.loadSVGFromString(body,callback,reviver)})}};fabric.loadSVGFromString=function(string,callback,reviver){var doc=(new DOMParser).parseFromString(string);fabric.parseSVGDocument(doc.documentElement,function(results,options){callback&&callback(results,options)},reviver)};fabric.util.getScript=function(url,callback){request(url,"",function(body){eval(body);callback&&callback()})};fabric.Image.fromObject=function(object,callback){fabric.util.loadImage(object.src,function(img){var oImg=new fabric.Image(img);oImg._initConfig(object);oImg._initFilters(object.filters,function(filters){oImg.filters=filters||[];oImg._initFilters(object.resizeFilters,function(resizeFilters){oImg.resizeFilters=resizeFilters||[];callback&&callback(oImg)})})})};fabric.createCanvasForNode=function(width,height,options,nodeCanvasOptions){nodeCanvasOptions=nodeCanvasOptions||options;var canvasEl=fabric.document.createElement("canvas"),nodeCanvas=new Canvas(width||600,height||600,nodeCanvasOptions);canvasEl.style={};canvasEl.width=nodeCanvas.width;canvasEl.height=nodeCanvas.height;var FabricCanvas=fabric.Canvas||fabric.StaticCanvas,fabricCanvas=new FabricCanvas(canvasEl,options);fabricCanvas.contextContainer=nodeCanvas.getContext("2d");fabricCanvas.nodeCanvas=nodeCanvas;fabricCanvas.Font=Canvas.Font;return fabricCanvas};fabric.StaticCanvas.prototype.createPNGStream=function(){return this.nodeCanvas.createPNGStream()};fabric.StaticCanvas.prototype.createJPEGStream=function(opts){return this.nodeCanvas.createJPEGStream(opts)};var origSetWidth=fabric.StaticCanvas.prototype.setWidth;fabric.StaticCanvas.prototype.setWidth=function(width,options){origSetWidth.call(this,width,options);this.nodeCanvas.width=width;return this};if(fabric.Canvas){fabric.Canvas.prototype.setWidth=fabric.StaticCanvas.prototype.setWidth}var origSetHeight=fabric.StaticCanvas.prototype.setHeight;fabric.StaticCanvas.prototype.setHeight=function(height,options){origSetHeight.call(this,height,options);this.nodeCanvas.height=height;return this};if(fabric.Canvas){fabric.Canvas.prototype.setHeight=fabric.StaticCanvas.prototype.setHeight}})();window.fabric=fabric;if(typeof define==="function"&&define.amd){define([],function(){return fabric})} \ No newline at end of file +var fabric = fabric || { + version: "1.6.0-rc.1" +}; + +if (typeof exports !== "undefined") { + exports.fabric = fabric; +} + +if (typeof document !== "undefined" && typeof window !== "undefined") { + fabric.document = document; + fabric.window = window; + window.fabric = fabric; +} else { + fabric.document = require("jsdom").jsdom(""); + if (fabric.document.createWindow) { + fabric.window = fabric.document.createWindow(); + } else { + fabric.window = fabric.document.parentWindow; + } +} + +fabric.isTouchSupported = "ontouchstart" in fabric.document.documentElement; + +fabric.isLikelyNode = typeof Buffer !== "undefined" && typeof window === "undefined"; + +fabric.SHARED_ATTRIBUTES = [ "display", "transform", "fill", "fill-opacity", "fill-rule", "opacity", "stroke", "stroke-dasharray", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "id" ]; + +fabric.DPI = 96; + +fabric.reNum = "(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)"; + +fabric.fontPaths = {}; + +fabric.devicePixelRatio = fabric.window.devicePixelRatio || fabric.window.webkitDevicePixelRatio || fabric.window.mozDevicePixelRatio || 1; + +(function() { + function _removeEventListener(eventName, handler) { + if (!this.__eventListeners[eventName]) { + return; + } + var eventListener = this.__eventListeners[eventName]; + if (handler) { + eventListener[eventListener.indexOf(handler)] = false; + } else { + fabric.util.array.fill(eventListener, false); + } + } + function observe(eventName, handler) { + if (!this.__eventListeners) { + this.__eventListeners = {}; + } + if (arguments.length === 1) { + for (var prop in eventName) { + this.on(prop, eventName[prop]); + } + } else { + if (!this.__eventListeners[eventName]) { + this.__eventListeners[eventName] = []; + } + this.__eventListeners[eventName].push(handler); + } + return this; + } + function stopObserving(eventName, handler) { + if (!this.__eventListeners) { + return; + } + if (arguments.length === 0) { + for (eventName in this.__eventListeners) { + _removeEventListener.call(this, eventName); + } + } else if (arguments.length === 1 && typeof arguments[0] === "object") { + for (var prop in eventName) { + _removeEventListener.call(this, prop, eventName[prop]); + } + } else { + _removeEventListener.call(this, eventName, handler); + } + return this; + } + function fire(eventName, options) { + if (!this.__eventListeners) { + return; + } + var listenersForEvent = this.__eventListeners[eventName]; + if (!listenersForEvent) { + return; + } + for (var i = 0, len = listenersForEvent.length; i < len; i++) { + listenersForEvent[i] && listenersForEvent[i].call(this, options || {}); + } + this.__eventListeners[eventName] = listenersForEvent.filter(function(value) { + return value !== false; + }); + return this; + } + fabric.Observable = { + observe: observe, + stopObserving: stopObserving, + fire: fire, + on: observe, + off: stopObserving, + trigger: fire + }; +})(); + +fabric.Collection = { + add: function() { + this._objects.push.apply(this._objects, arguments); + for (var i = 0, length = arguments.length; i < length; i++) { + this._onObjectAdded(arguments[i]); + } + this.renderOnAddRemove && this.renderAll(); + return this; + }, + insertAt: function(object, index, nonSplicing) { + var objects = this.getObjects(); + if (nonSplicing) { + objects[index] = object; + } else { + objects.splice(index, 0, object); + } + this._onObjectAdded(object); + this.renderOnAddRemove && this.renderAll(); + return this; + }, + remove: function() { + var objects = this.getObjects(), index; + for (var i = 0, length = arguments.length; i < length; i++) { + index = objects.indexOf(arguments[i]); + if (index !== -1) { + objects.splice(index, 1); + this._onObjectRemoved(arguments[i]); + } + } + this.renderOnAddRemove && this.renderAll(); + return this; + }, + forEachObject: function(callback, context) { + var objects = this.getObjects(), i = objects.length; + while (i--) { + callback.call(context, objects[i], i, objects); + } + return this; + }, + getObjects: function(type) { + if (typeof type === "undefined") { + return this._objects; + } + return this._objects.filter(function(o) { + return o.type === type; + }); + }, + item: function(index) { + return this.getObjects()[index]; + }, + isEmpty: function() { + return this.getObjects().length === 0; + }, + size: function() { + return this.getObjects().length; + }, + contains: function(object) { + return this.getObjects().indexOf(object) > -1; + }, + complexity: function() { + return this.getObjects().reduce(function(memo, current) { + memo += current.complexity ? current.complexity() : 0; + return memo; + }, 0); + } +}; + +(function(global) { + var sqrt = Math.sqrt, atan2 = Math.atan2, pow = Math.pow, abs = Math.abs, PiBy180 = Math.PI / 180; + fabric.util = { + removeFromArray: function(array, value) { + var idx = array.indexOf(value); + if (idx !== -1) { + array.splice(idx, 1); + } + return array; + }, + getRandomInt: function(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; + }, + degreesToRadians: function(degrees) { + return degrees * PiBy180; + }, + radiansToDegrees: function(radians) { + return radians / PiBy180; + }, + rotatePoint: function(point, origin, radians) { + point.subtractEquals(origin); + var v = fabric.util.rotateVector(point, radians); + return new fabric.Point(v.x, v.y).addEquals(origin); + }, + rotateVector: function(vector, radians) { + var sin = Math.sin(radians), cos = Math.cos(radians), rx = vector.x * cos - vector.y * sin, ry = vector.x * sin + vector.y * cos; + return { + x: rx, + y: ry + }; + }, + transformPoint: function(p, t, ignoreOffset) { + if (ignoreOffset) { + return new fabric.Point(t[0] * p.x + t[2] * p.y, t[1] * p.x + t[3] * p.y); + } + return new fabric.Point(t[0] * p.x + t[2] * p.y + t[4], t[1] * p.x + t[3] * p.y + t[5]); + }, + makeBoundingBoxFromPoints: function(points) { + var xPoints = [ points[0].x, points[1].x, points[2].x, points[3].x ], minX = fabric.util.array.min(xPoints), maxX = fabric.util.array.max(xPoints), width = Math.abs(minX - maxX), yPoints = [ points[0].y, points[1].y, points[2].y, points[3].y ], minY = fabric.util.array.min(yPoints), maxY = fabric.util.array.max(yPoints), height = Math.abs(minY - maxY); + return { + left: minX, + top: minY, + width: width, + height: height + }; + }, + invertTransform: function(t) { + var a = 1 / (t[0] * t[3] - t[1] * t[2]), r = [ a * t[3], -a * t[1], -a * t[2], a * t[0] ], o = fabric.util.transformPoint({ + x: t[4], + y: t[5] + }, r, true); + r[4] = -o.x; + r[5] = -o.y; + return r; + }, + toFixed: function(number, fractionDigits) { + return parseFloat(Number(number).toFixed(fractionDigits)); + }, + parseUnit: function(value, fontSize) { + var unit = /\D{0,2}$/.exec(value), number = parseFloat(value); + if (!fontSize) { + fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE; + } + switch (unit[0]) { + case "mm": + return number * fabric.DPI / 25.4; + + case "cm": + return number * fabric.DPI / 2.54; + + case "in": + return number * fabric.DPI; + + case "pt": + return number * fabric.DPI / 72; + + case "pc": + return number * fabric.DPI / 72 * 12; + + case "em": + return number * fontSize; + + default: + return number; + } + }, + falseFunction: function() { + return false; + }, + getKlass: function(type, namespace) { + type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1)); + return fabric.util.resolveNamespace(namespace)[type]; + }, + resolveNamespace: function(namespace) { + if (!namespace) { + return fabric; + } + var parts = namespace.split("."), len = parts.length, obj = global || fabric.window; + for (var i = 0; i < len; ++i) { + obj = obj[parts[i]]; + } + return obj; + }, + loadImage: function(url, callback, context, crossOrigin) { + if (!url) { + callback && callback.call(context, url); + return; + } + var img = fabric.util.createImage(); + img.onload = function() { + callback && callback.call(context, img); + img = img.onload = img.onerror = null; + }; + img.onerror = function() { + fabric.log("Error loading " + img.src); + callback && callback.call(context, null, true); + img = img.onload = img.onerror = null; + }; + if (url.indexOf("data") !== 0 && crossOrigin) { + img.crossOrigin = crossOrigin; + } + img.src = url; + }, + enlivenObjects: function(objects, callback, namespace, reviver) { + objects = objects || []; + function onLoaded() { + if (++numLoadedObjects === numTotalObjects) { + callback && callback(enlivenedObjects); + } + } + var enlivenedObjects = [], numLoadedObjects = 0, numTotalObjects = objects.length; + if (!numTotalObjects) { + callback && callback(enlivenedObjects); + return; + } + objects.forEach(function(o, index) { + if (!o || !o.type) { + onLoaded(); + return; + } + var klass = fabric.util.getKlass(o.type, namespace); + if (klass.async) { + klass.fromObject(o, function(obj, error) { + if (!error) { + enlivenedObjects[index] = obj; + reviver && reviver(o, enlivenedObjects[index]); + } + onLoaded(); + }); + } else { + enlivenedObjects[index] = klass.fromObject(o); + reviver && reviver(o, enlivenedObjects[index]); + onLoaded(); + } + }); + }, + groupSVGElements: function(elements, options, path) { + var object; + object = new fabric.PathGroup(elements, options); + if (typeof path !== "undefined") { + object.setSourcePath(path); + } + return object; + }, + populateWithProperties: function(source, destination, properties) { + if (properties && Object.prototype.toString.call(properties) === "[object Array]") { + for (var i = 0, len = properties.length; i < len; i++) { + if (properties[i] in source) { + destination[properties[i]] = source[properties[i]]; + } + } + } + }, + drawDashedLine: function(ctx, x, y, x2, y2, da) { + var dx = x2 - x, dy = y2 - y, len = sqrt(dx * dx + dy * dy), rot = atan2(dy, dx), dc = da.length, di = 0, draw = true; + ctx.save(); + ctx.translate(x, y); + ctx.moveTo(0, 0); + ctx.rotate(rot); + x = 0; + while (len > x) { + x += da[di++ % dc]; + if (x > len) { + x = len; + } + ctx[draw ? "lineTo" : "moveTo"](x, 0); + draw = !draw; + } + ctx.restore(); + }, + createCanvasElement: function(canvasEl) { + canvasEl || (canvasEl = fabric.document.createElement("canvas")); + if (!canvasEl.getContext && typeof G_vmlCanvasManager !== "undefined") { + G_vmlCanvasManager.initElement(canvasEl); + } + return canvasEl; + }, + createImage: function() { + return fabric.isLikelyNode ? new (require("canvas").Image)() : fabric.document.createElement("img"); + }, + createAccessors: function(klass) { + var proto = klass.prototype; + for (var i = proto.stateProperties.length; i--; ) { + var propName = proto.stateProperties[i], capitalizedPropName = propName.charAt(0).toUpperCase() + propName.slice(1), setterName = "set" + capitalizedPropName, getterName = "get" + capitalizedPropName; + if (!proto[getterName]) { + proto[getterName] = function(property) { + return new Function('return this.get("' + property + '")'); + }(propName); + } + if (!proto[setterName]) { + proto[setterName] = function(property) { + return new Function("value", 'return this.set("' + property + '", value)'); + }(propName); + } + } + }, + clipContext: function(receiver, ctx) { + ctx.save(); + ctx.beginPath(); + receiver.clipTo(ctx); + ctx.clip(); + }, + multiplyTransformMatrices: function(a, b, is2x2) { + return [ a[0] * b[0] + a[2] * b[1], a[1] * b[0] + a[3] * b[1], a[0] * b[2] + a[2] * b[3], a[1] * b[2] + a[3] * b[3], is2x2 ? 0 : a[0] * b[4] + a[2] * b[5] + a[4], is2x2 ? 0 : a[1] * b[4] + a[3] * b[5] + a[5] ]; + }, + qrDecompose: function(a) { + var angle = atan2(a[1], a[0]), denom = pow(a[0], 2) + pow(a[1], 2), scaleX = sqrt(denom), scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX, skewX = atan2(a[0] * a[2] + a[1] * a[3], denom); + return { + angle: angle / PiBy180, + scaleX: scaleX, + scaleY: scaleY, + skewX: skewX / PiBy180, + skewY: 0, + translateX: a[4], + translateY: a[5] + }; + }, + customTransformMatrix: function(scaleX, scaleY, skewX) { + var skewMatrixX = [ 1, 0, abs(Math.tan(skewX * PiBy180)), 1 ], scaleMatrix = [ abs(scaleX), 0, 0, abs(scaleY) ]; + return fabric.util.multiplyTransformMatrices(scaleMatrix, skewMatrixX, true); + }, + resetObjectTransform: function(target) { + target.scaleX = 1; + target.scaleY = 1; + target.skewX = 0; + target.skewY = 0; + target.flipX = false; + target.flipY = false; + target.setAngle(0); + }, + getFunctionBody: function(fn) { + return (String(fn).match(/function[^{]*\{([\s\S]*)\}/) || {})[1]; + }, + isTransparent: function(ctx, x, y, tolerance) { + if (tolerance > 0) { + if (x > tolerance) { + x -= tolerance; + } else { + x = 0; + } + if (y > tolerance) { + y -= tolerance; + } else { + y = 0; + } + } + var _isTransparent = true, imageData = ctx.getImageData(x, y, tolerance * 2 || 1, tolerance * 2 || 1); + for (var i = 3, l = imageData.data.length; i < l; i += 4) { + var temp = imageData.data[i]; + _isTransparent = temp <= 0; + if (_isTransparent === false) { + break; + } + } + imageData = null; + return _isTransparent; + }, + parsePreserveAspectRatioAttribute: function(attribute) { + var meetOrSlice = "meet", alignX = "Mid", alignY = "Mid", aspectRatioAttrs = attribute.split(" "), align; + if (aspectRatioAttrs && aspectRatioAttrs.length) { + meetOrSlice = aspectRatioAttrs.pop(); + if (meetOrSlice !== "meet" && meetOrSlice !== "slice") { + align = meetOrSlice; + meetOrSlice = "meet"; + } else if (aspectRatioAttrs.length) { + align = aspectRatioAttrs.pop(); + } + } + alignX = align !== "none" ? align.slice(1, 4) : "none"; + alignY = align !== "none" ? align.slice(5, 8) : "none"; + return { + meetOrSlice: meetOrSlice, + alignX: alignX, + alignY: alignY + }; + } + }; +})(typeof exports !== "undefined" ? exports : this); + +(function() { + var arcToSegmentsCache = {}, segmentToBezierCache = {}, boundsOfCurveCache = {}, _join = Array.prototype.join; + function arcToSegments(toX, toY, rx, ry, large, sweep, rotateX) { + var argsString = _join.call(arguments); + if (arcToSegmentsCache[argsString]) { + return arcToSegmentsCache[argsString]; + } + var PI = Math.PI, th = rotateX * PI / 180, sinTh = Math.sin(th), cosTh = Math.cos(th), fromX = 0, fromY = 0; + rx = Math.abs(rx); + ry = Math.abs(ry); + var px = -cosTh * toX * .5 - sinTh * toY * .5, py = -cosTh * toY * .5 + sinTh * toX * .5, rx2 = rx * rx, ry2 = ry * ry, py2 = py * py, px2 = px * px, pl = rx2 * ry2 - rx2 * py2 - ry2 * px2, root = 0; + if (pl < 0) { + var s = Math.sqrt(1 - pl / (rx2 * ry2)); + rx *= s; + ry *= s; + } else { + root = (large === sweep ? -1 : 1) * Math.sqrt(pl / (rx2 * py2 + ry2 * px2)); + } + var cx = root * rx * py / ry, cy = -root * ry * px / rx, cx1 = cosTh * cx - sinTh * cy + toX * .5, cy1 = sinTh * cx + cosTh * cy + toY * .5, mTheta = calcVectorAngle(1, 0, (px - cx) / rx, (py - cy) / ry), dtheta = calcVectorAngle((px - cx) / rx, (py - cy) / ry, (-px - cx) / rx, (-py - cy) / ry); + if (sweep === 0 && dtheta > 0) { + dtheta -= 2 * PI; + } else if (sweep === 1 && dtheta < 0) { + dtheta += 2 * PI; + } + var segments = Math.ceil(Math.abs(dtheta / PI * 2)), result = [], mDelta = dtheta / segments, mT = 8 / 3 * Math.sin(mDelta / 4) * Math.sin(mDelta / 4) / Math.sin(mDelta / 2), th3 = mTheta + mDelta; + for (var i = 0; i < segments; i++) { + result[i] = segmentToBezier(mTheta, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY); + fromX = result[i][4]; + fromY = result[i][5]; + mTheta = th3; + th3 += mDelta; + } + arcToSegmentsCache[argsString] = result; + return result; + } + function segmentToBezier(th2, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY) { + var argsString2 = _join.call(arguments); + if (segmentToBezierCache[argsString2]) { + return segmentToBezierCache[argsString2]; + } + var costh2 = Math.cos(th2), sinth2 = Math.sin(th2), costh3 = Math.cos(th3), sinth3 = Math.sin(th3), toX = cosTh * rx * costh3 - sinTh * ry * sinth3 + cx1, toY = sinTh * rx * costh3 + cosTh * ry * sinth3 + cy1, cp1X = fromX + mT * (-cosTh * rx * sinth2 - sinTh * ry * costh2), cp1Y = fromY + mT * (-sinTh * rx * sinth2 + cosTh * ry * costh2), cp2X = toX + mT * (cosTh * rx * sinth3 + sinTh * ry * costh3), cp2Y = toY + mT * (sinTh * rx * sinth3 - cosTh * ry * costh3); + segmentToBezierCache[argsString2] = [ cp1X, cp1Y, cp2X, cp2Y, toX, toY ]; + return segmentToBezierCache[argsString2]; + } + function calcVectorAngle(ux, uy, vx, vy) { + var ta = Math.atan2(uy, ux), tb = Math.atan2(vy, vx); + if (tb >= ta) { + return tb - ta; + } else { + return 2 * Math.PI - (ta - tb); + } + } + fabric.util.drawArc = function(ctx, fx, fy, coords) { + var rx = coords[0], ry = coords[1], rot = coords[2], large = coords[3], sweep = coords[4], tx = coords[5], ty = coords[6], segs = [ [], [], [], [] ], segsNorm = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot); + for (var i = 0, len = segsNorm.length; i < len; i++) { + segs[i][0] = segsNorm[i][0] + fx; + segs[i][1] = segsNorm[i][1] + fy; + segs[i][2] = segsNorm[i][2] + fx; + segs[i][3] = segsNorm[i][3] + fy; + segs[i][4] = segsNorm[i][4] + fx; + segs[i][5] = segsNorm[i][5] + fy; + ctx.bezierCurveTo.apply(ctx, segs[i]); + } + }; + fabric.util.getBoundsOfArc = function(fx, fy, rx, ry, rot, large, sweep, tx, ty) { + var fromX = 0, fromY = 0, bound = [], bounds = [], segs = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot), boundCopy = [ [], [] ]; + for (var i = 0, len = segs.length; i < len; i++) { + bound = getBoundsOfCurve(fromX, fromY, segs[i][0], segs[i][1], segs[i][2], segs[i][3], segs[i][4], segs[i][5]); + boundCopy[0].x = bound[0].x + fx; + boundCopy[0].y = bound[0].y + fy; + boundCopy[1].x = bound[1].x + fx; + boundCopy[1].y = bound[1].y + fy; + bounds.push(boundCopy[0]); + bounds.push(boundCopy[1]); + fromX = segs[i][4]; + fromY = segs[i][5]; + } + return bounds; + }; + function getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3) { + var argsString = _join.call(arguments); + if (boundsOfCurveCache[argsString]) { + return boundsOfCurveCache[argsString]; + } + var sqrt = Math.sqrt, min = Math.min, max = Math.max, abs = Math.abs, tvalues = [], bounds = [ [], [] ], a, b, c, t, t1, t2, b2ac, sqrtb2ac; + b = 6 * x0 - 12 * x1 + 6 * x2; + a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3; + c = 3 * x1 - 3 * x0; + for (var i = 0; i < 2; ++i) { + if (i > 0) { + b = 6 * y0 - 12 * y1 + 6 * y2; + a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3; + c = 3 * y1 - 3 * y0; + } + if (abs(a) < 1e-12) { + if (abs(b) < 1e-12) { + continue; + } + t = -c / b; + if (0 < t && t < 1) { + tvalues.push(t); + } + continue; + } + b2ac = b * b - 4 * c * a; + if (b2ac < 0) { + continue; + } + sqrtb2ac = sqrt(b2ac); + t1 = (-b + sqrtb2ac) / (2 * a); + if (0 < t1 && t1 < 1) { + tvalues.push(t1); + } + t2 = (-b - sqrtb2ac) / (2 * a); + if (0 < t2 && t2 < 1) { + tvalues.push(t2); + } + } + var x, y, j = tvalues.length, jlen = j, mt; + while (j--) { + t = tvalues[j]; + mt = 1 - t; + x = mt * mt * mt * x0 + 3 * mt * mt * t * x1 + 3 * mt * t * t * x2 + t * t * t * x3; + bounds[0][j] = x; + y = mt * mt * mt * y0 + 3 * mt * mt * t * y1 + 3 * mt * t * t * y2 + t * t * t * y3; + bounds[1][j] = y; + } + bounds[0][jlen] = x0; + bounds[1][jlen] = y0; + bounds[0][jlen + 1] = x3; + bounds[1][jlen + 1] = y3; + var result = [ { + x: min.apply(null, bounds[0]), + y: min.apply(null, bounds[1]) + }, { + x: max.apply(null, bounds[0]), + y: max.apply(null, bounds[1]) + } ]; + boundsOfCurveCache[argsString] = result; + return result; + } + fabric.util.getBoundsOfCurve = getBoundsOfCurve; +})(); + +(function() { + var slice = Array.prototype.slice; + if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function(searchElement) { + if (this === void 0 || this === null) { + throw new TypeError(); + } + var t = Object(this), len = t.length >>> 0; + if (len === 0) { + return -1; + } + var n = 0; + if (arguments.length > 0) { + n = Number(arguments[1]); + if (n !== n) { + n = 0; + } else if (n !== 0 && n !== Number.POSITIVE_INFINITY && n !== Number.NEGATIVE_INFINITY) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + } + if (n >= len) { + return -1; + } + var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); + for (;k < len; k++) { + if (k in t && t[k] === searchElement) { + return k; + } + } + return -1; + }; + } + if (!Array.prototype.forEach) { + Array.prototype.forEach = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + fn.call(context, this[i], i, this); + } + } + }; + } + if (!Array.prototype.map) { + Array.prototype.map = function(fn, context) { + var result = []; + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + result[i] = fn.call(context, this[i], i, this); + } + } + return result; + }; + } + if (!Array.prototype.every) { + Array.prototype.every = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this && !fn.call(context, this[i], i, this)) { + return false; + } + } + return true; + }; + } + if (!Array.prototype.some) { + Array.prototype.some = function(fn, context) { + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this && fn.call(context, this[i], i, this)) { + return true; + } + } + return false; + }; + } + if (!Array.prototype.filter) { + Array.prototype.filter = function(fn, context) { + var result = [], val; + for (var i = 0, len = this.length >>> 0; i < len; i++) { + if (i in this) { + val = this[i]; + if (fn.call(context, val, i, this)) { + result.push(val); + } + } + } + return result; + }; + } + if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fn) { + var len = this.length >>> 0, i = 0, rv; + if (arguments.length > 1) { + rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + if (++i >= len) { + throw new TypeError(); + } + } while (true); + } + for (;i < len; i++) { + if (i in this) { + rv = fn.call(null, rv, this[i], i, this); + } + } + return rv; + }; + } + function invoke(array, method) { + var args = slice.call(arguments, 2), result = []; + for (var i = 0, len = array.length; i < len; i++) { + result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]); + } + return result; + } + function max(array, byProperty) { + return find(array, byProperty, function(value1, value2) { + return value1 >= value2; + }); + } + function min(array, byProperty) { + return find(array, byProperty, function(value1, value2) { + return value1 < value2; + }); + } + function fill(array, value) { + var k = array.length; + while (k--) { + array[k] = value; + } + return array; + } + function find(array, byProperty, condition) { + if (!array || array.length === 0) { + return; + } + var i = array.length - 1, result = byProperty ? array[i][byProperty] : array[i]; + if (byProperty) { + while (i--) { + if (condition(array[i][byProperty], result)) { + result = array[i][byProperty]; + } + } + } else { + while (i--) { + if (condition(array[i], result)) { + result = array[i]; + } + } + } + return result; + } + fabric.util.array = { + fill: fill, + invoke: invoke, + min: min, + max: max + }; +})(); + +(function() { + function extend(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; + } + function clone(object) { + return extend({}, object); + } + fabric.util.object = { + extend: extend, + clone: clone + }; +})(); + +(function() { + if (!String.prototype.trim) { + String.prototype.trim = function() { + return this.replace(/^[\s\xA0]+/, "").replace(/[\s\xA0]+$/, ""); + }; + } + function camelize(string) { + return string.replace(/-+(.)?/g, function(match, character) { + return character ? character.toUpperCase() : ""; + }); + } + function capitalize(string, firstLetterOnly) { + return string.charAt(0).toUpperCase() + (firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase()); + } + function escapeXml(string) { + return string.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(//g, ">"); + } + fabric.util.string = { + camelize: camelize, + capitalize: capitalize, + escapeXml: escapeXml + }; +})(); + +(function() { + var slice = Array.prototype.slice, apply = Function.prototype.apply, Dummy = function() {}; + if (!Function.prototype.bind) { + Function.prototype.bind = function(thisArg) { + var _this = this, args = slice.call(arguments, 1), bound; + if (args.length) { + bound = function() { + return apply.call(_this, this instanceof Dummy ? this : thisArg, args.concat(slice.call(arguments))); + }; + } else { + bound = function() { + return apply.call(_this, this instanceof Dummy ? this : thisArg, arguments); + }; + } + Dummy.prototype = this.prototype; + bound.prototype = new Dummy(); + return bound; + }; + } +})(); + +(function() { + var slice = Array.prototype.slice, emptyFunction = function() {}, IS_DONTENUM_BUGGY = function() { + for (var p in { + toString: 1 + }) { + if (p === "toString") { + return false; + } + } + return true; + }(), addMethods = function(klass, source, parent) { + for (var property in source) { + if (property in klass.prototype && typeof klass.prototype[property] === "function" && (source[property] + "").indexOf("callSuper") > -1) { + klass.prototype[property] = function(property) { + return function() { + var superclass = this.constructor.superclass; + this.constructor.superclass = parent; + var returnValue = source[property].apply(this, arguments); + this.constructor.superclass = superclass; + if (property !== "initialize") { + return returnValue; + } + }; + }(property); + } else { + klass.prototype[property] = source[property]; + } + if (IS_DONTENUM_BUGGY) { + if (source.toString !== Object.prototype.toString) { + klass.prototype.toString = source.toString; + } + if (source.valueOf !== Object.prototype.valueOf) { + klass.prototype.valueOf = source.valueOf; + } + } + } + }; + function Subclass() {} + function callSuper(methodName) { + var fn = this.constructor.superclass.prototype[methodName]; + return arguments.length > 1 ? fn.apply(this, slice.call(arguments, 1)) : fn.call(this); + } + function createClass() { + var parent = null, properties = slice.call(arguments, 0); + if (typeof properties[0] === "function") { + parent = properties.shift(); + } + function klass() { + this.initialize.apply(this, arguments); + } + klass.superclass = parent; + klass.subclasses = []; + if (parent) { + Subclass.prototype = parent.prototype; + klass.prototype = new Subclass(); + parent.subclasses.push(klass); + } + for (var i = 0, length = properties.length; i < length; i++) { + addMethods(klass, properties[i], parent); + } + if (!klass.prototype.initialize) { + klass.prototype.initialize = emptyFunction; + } + klass.prototype.constructor = klass; + klass.prototype.callSuper = callSuper; + return klass; + } + fabric.util.createClass = createClass; +})(); + +(function() { + var unknown = "unknown"; + function areHostMethods(object) { + var methodNames = Array.prototype.slice.call(arguments, 1), t, i, len = methodNames.length; + for (i = 0; i < len; i++) { + t = typeof object[methodNames[i]]; + if (!/^(?:function|object|unknown)$/.test(t)) { + return false; + } + } + return true; + } + var getElement, setElement, getUniqueId = function() { + var uid = 0; + return function(element) { + return element.__uniqueID || (element.__uniqueID = "uniqueID__" + uid++); + }; + }(); + (function() { + var elements = {}; + getElement = function(uid) { + return elements[uid]; + }; + setElement = function(uid, element) { + elements[uid] = element; + }; + })(); + function createListener(uid, handler) { + return { + handler: handler, + wrappedHandler: createWrappedHandler(uid, handler) + }; + } + function createWrappedHandler(uid, handler) { + return function(e) { + handler.call(getElement(uid), e || fabric.window.event); + }; + } + function createDispatcher(uid, eventName) { + return function(e) { + if (handlers[uid] && handlers[uid][eventName]) { + var handlersForEvent = handlers[uid][eventName]; + for (var i = 0, len = handlersForEvent.length; i < len; i++) { + handlersForEvent[i].call(this, e || fabric.window.event); + } + } + }; + } + var shouldUseAddListenerRemoveListener = areHostMethods(fabric.document.documentElement, "addEventListener", "removeEventListener") && areHostMethods(fabric.window, "addEventListener", "removeEventListener"), shouldUseAttachEventDetachEvent = areHostMethods(fabric.document.documentElement, "attachEvent", "detachEvent") && areHostMethods(fabric.window, "attachEvent", "detachEvent"), listeners = {}, handlers = {}, addListener, removeListener; + if (shouldUseAddListenerRemoveListener) { + addListener = function(element, eventName, handler) { + element.addEventListener(eventName, handler, false); + }; + removeListener = function(element, eventName, handler) { + element.removeEventListener(eventName, handler, false); + }; + } else if (shouldUseAttachEventDetachEvent) { + addListener = function(element, eventName, handler) { + var uid = getUniqueId(element); + setElement(uid, element); + if (!listeners[uid]) { + listeners[uid] = {}; + } + if (!listeners[uid][eventName]) { + listeners[uid][eventName] = []; + } + var listener = createListener(uid, handler); + listeners[uid][eventName].push(listener); + element.attachEvent("on" + eventName, listener.wrappedHandler); + }; + removeListener = function(element, eventName, handler) { + var uid = getUniqueId(element), listener; + if (listeners[uid] && listeners[uid][eventName]) { + for (var i = 0, len = listeners[uid][eventName].length; i < len; i++) { + listener = listeners[uid][eventName][i]; + if (listener && listener.handler === handler) { + element.detachEvent("on" + eventName, listener.wrappedHandler); + listeners[uid][eventName][i] = null; + } + } + } + }; + } else { + addListener = function(element, eventName, handler) { + var uid = getUniqueId(element); + if (!handlers[uid]) { + handlers[uid] = {}; + } + if (!handlers[uid][eventName]) { + handlers[uid][eventName] = []; + var existingHandler = element["on" + eventName]; + if (existingHandler) { + handlers[uid][eventName].push(existingHandler); + } + element["on" + eventName] = createDispatcher(uid, eventName); + } + handlers[uid][eventName].push(handler); + }; + removeListener = function(element, eventName, handler) { + var uid = getUniqueId(element); + if (handlers[uid] && handlers[uid][eventName]) { + var handlersForEvent = handlers[uid][eventName]; + for (var i = 0, len = handlersForEvent.length; i < len; i++) { + if (handlersForEvent[i] === handler) { + handlersForEvent.splice(i, 1); + } + } + } + }; + } + fabric.util.addListener = addListener; + fabric.util.removeListener = removeListener; + function getPointer(event) { + event || (event = fabric.window.event); + var element = event.target || (typeof event.srcElement !== unknown ? event.srcElement : null), scroll = fabric.util.getScrollLeftTop(element); + return { + x: pointerX(event) + scroll.left, + y: pointerY(event) + scroll.top + }; + } + var pointerX = function(event) { + return typeof event.clientX !== unknown ? event.clientX : 0; + }, pointerY = function(event) { + return typeof event.clientY !== unknown ? event.clientY : 0; + }; + function _getPointer(event, pageProp, clientProp) { + var touchProp = event.type === "touchend" ? "changedTouches" : "touches"; + return event[touchProp] && event[touchProp][0] ? event[touchProp][0][pageProp] - (event[touchProp][0][pageProp] - event[touchProp][0][clientProp]) || event[clientProp] : event[clientProp]; + } + if (fabric.isTouchSupported) { + pointerX = function(event) { + return _getPointer(event, "pageX", "clientX"); + }; + pointerY = function(event) { + return _getPointer(event, "pageY", "clientY"); + }; + } + fabric.util.getPointer = getPointer; + fabric.util.object.extend(fabric.util, fabric.Observable); +})(); + +(function() { + function setStyle(element, styles) { + var elementStyle = element.style; + if (!elementStyle) { + return element; + } + if (typeof styles === "string") { + element.style.cssText += ";" + styles; + return styles.indexOf("opacity") > -1 ? setOpacity(element, styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; + } + for (var property in styles) { + if (property === "opacity") { + setOpacity(element, styles[property]); + } else { + var normalizedProperty = property === "float" || property === "cssFloat" ? typeof elementStyle.styleFloat === "undefined" ? "cssFloat" : "styleFloat" : property; + elementStyle[normalizedProperty] = styles[property]; + } + } + return element; + } + var parseEl = fabric.document.createElement("div"), supportsOpacity = typeof parseEl.style.opacity === "string", supportsFilters = typeof parseEl.style.filter === "string", reOpacity = /alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/, setOpacity = function(element) { + return element; + }; + if (supportsOpacity) { + setOpacity = function(element, value) { + element.style.opacity = value; + return element; + }; + } else if (supportsFilters) { + setOpacity = function(element, value) { + var es = element.style; + if (element.currentStyle && !element.currentStyle.hasLayout) { + es.zoom = 1; + } + if (reOpacity.test(es.filter)) { + value = value >= .9999 ? "" : "alpha(opacity=" + value * 100 + ")"; + es.filter = es.filter.replace(reOpacity, value); + } else { + es.filter += " alpha(opacity=" + value * 100 + ")"; + } + return element; + }; + } + fabric.util.setStyle = setStyle; +})(); + +(function() { + var _slice = Array.prototype.slice; + function getById(id) { + return typeof id === "string" ? fabric.document.getElementById(id) : id; + } + var sliceCanConvertNodelists, toArray = function(arrayLike) { + return _slice.call(arrayLike, 0); + }; + try { + sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array; + } catch (err) {} + if (!sliceCanConvertNodelists) { + toArray = function(arrayLike) { + var arr = new Array(arrayLike.length), i = arrayLike.length; + while (i--) { + arr[i] = arrayLike[i]; + } + return arr; + }; + } + function makeElement(tagName, attributes) { + var el = fabric.document.createElement(tagName); + for (var prop in attributes) { + if (prop === "class") { + el.className = attributes[prop]; + } else if (prop === "for") { + el.htmlFor = attributes[prop]; + } else { + el.setAttribute(prop, attributes[prop]); + } + } + return el; + } + function addClass(element, className) { + if (element && (" " + element.className + " ").indexOf(" " + className + " ") === -1) { + element.className += (element.className ? " " : "") + className; + } + } + function wrapElement(element, wrapper, attributes) { + if (typeof wrapper === "string") { + wrapper = makeElement(wrapper, attributes); + } + if (element.parentNode) { + element.parentNode.replaceChild(wrapper, element); + } + wrapper.appendChild(element); + return wrapper; + } + function getScrollLeftTop(element) { + var left = 0, top = 0, docElement = fabric.document.documentElement, body = fabric.document.body || { + scrollLeft: 0, + scrollTop: 0 + }; + while (element && (element.parentNode || element.host)) { + element = element.parentNode || element.host; + if (element === fabric.document) { + left = body.scrollLeft || docElement.scrollLeft || 0; + top = body.scrollTop || docElement.scrollTop || 0; + } else { + left += element.scrollLeft || 0; + top += element.scrollTop || 0; + } + if (element.nodeType === 1 && fabric.util.getElementStyle(element, "position") === "fixed") { + break; + } + } + return { + left: left, + top: top + }; + } + function getElementOffset(element) { + var docElem, doc = element && element.ownerDocument, box = { + left: 0, + top: 0 + }, offset = { + left: 0, + top: 0 + }, scrollLeftTop, offsetAttributes = { + borderLeftWidth: "left", + borderTopWidth: "top", + paddingLeft: "left", + paddingTop: "top" + }; + if (!doc) { + return offset; + } + for (var attr in offsetAttributes) { + offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0; + } + docElem = doc.documentElement; + if (typeof element.getBoundingClientRect !== "undefined") { + box = element.getBoundingClientRect(); + } + scrollLeftTop = getScrollLeftTop(element); + return { + left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left, + top: box.top + scrollLeftTop.top - (docElem.clientTop || 0) + offset.top + }; + } + var getElementStyle; + if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) { + getElementStyle = function(element, attr) { + var style = fabric.document.defaultView.getComputedStyle(element, null); + return style ? style[attr] : undefined; + }; + } else { + getElementStyle = function(element, attr) { + var value = element.style[attr]; + if (!value && element.currentStyle) { + value = element.currentStyle[attr]; + } + return value; + }; + } + (function() { + var style = fabric.document.documentElement.style, selectProp = "userSelect" in style ? "userSelect" : "MozUserSelect" in style ? "MozUserSelect" : "WebkitUserSelect" in style ? "WebkitUserSelect" : "KhtmlUserSelect" in style ? "KhtmlUserSelect" : ""; + function makeElementUnselectable(element) { + if (typeof element.onselectstart !== "undefined") { + element.onselectstart = fabric.util.falseFunction; + } + if (selectProp) { + element.style[selectProp] = "none"; + } else if (typeof element.unselectable === "string") { + element.unselectable = "on"; + } + return element; + } + function makeElementSelectable(element) { + if (typeof element.onselectstart !== "undefined") { + element.onselectstart = null; + } + if (selectProp) { + element.style[selectProp] = ""; + } else if (typeof element.unselectable === "string") { + element.unselectable = ""; + } + return element; + } + fabric.util.makeElementUnselectable = makeElementUnselectable; + fabric.util.makeElementSelectable = makeElementSelectable; + })(); + (function() { + function getScript(url, callback) { + var headEl = fabric.document.getElementsByTagName("head")[0], scriptEl = fabric.document.createElement("script"), loading = true; + scriptEl.onload = scriptEl.onreadystatechange = function(e) { + if (loading) { + if (typeof this.readyState === "string" && this.readyState !== "loaded" && this.readyState !== "complete") { + return; + } + loading = false; + callback(e || fabric.window.event); + scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null; + } + }; + scriptEl.src = url; + headEl.appendChild(scriptEl); + } + fabric.util.getScript = getScript; + })(); + fabric.util.getById = getById; + fabric.util.toArray = toArray; + fabric.util.makeElement = makeElement; + fabric.util.addClass = addClass; + fabric.util.wrapElement = wrapElement; + fabric.util.getScrollLeftTop = getScrollLeftTop; + fabric.util.getElementOffset = getElementOffset; + fabric.util.getElementStyle = getElementStyle; +})(); + +(function() { + function addParamToUrl(url, param) { + return url + (/\?/.test(url) ? "&" : "?") + param; + } + var makeXHR = function() { + var factories = [ function() { + return new ActiveXObject("Microsoft.XMLHTTP"); + }, function() { + return new ActiveXObject("Msxml2.XMLHTTP"); + }, function() { + return new ActiveXObject("Msxml2.XMLHTTP.3.0"); + }, function() { + return new XMLHttpRequest(); + } ]; + for (var i = factories.length; i--; ) { + try { + var req = factories[i](); + if (req) { + return factories[i]; + } + } catch (err) {} + } + }(); + function emptyFn() {} + function request(url, options) { + options || (options = {}); + var method = options.method ? options.method.toUpperCase() : "GET", onComplete = options.onComplete || function() {}, xhr = makeXHR(), body; + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + onComplete(xhr); + xhr.onreadystatechange = emptyFn; + } + }; + if (method === "GET") { + body = null; + if (typeof options.parameters === "string") { + url = addParamToUrl(url, options.parameters); + } + } + xhr.open(method, url, true); + if (method === "POST" || method === "PUT") { + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + } + xhr.send(body); + return xhr; + } + fabric.util.request = request; +})(); + +fabric.log = function() {}; + +fabric.warn = function() {}; + +if (typeof console !== "undefined") { + [ "log", "warn" ].forEach(function(methodName) { + if (typeof console[methodName] !== "undefined" && typeof console[methodName].apply === "function") { + fabric[methodName] = function() { + return console[methodName].apply(console, arguments); + }; + } + }); +} + +(function() { + function animate(options) { + requestAnimFrame(function(timestamp) { + options || (options = {}); + var start = timestamp || +new Date(), duration = options.duration || 500, finish = start + duration, time, onChange = options.onChange || function() {}, abort = options.abort || function() { + return false; + }, easing = options.easing || function(t, b, c, d) { + return -c * Math.cos(t / d * (Math.PI / 2)) + c + b; + }, startValue = "startValue" in options ? options.startValue : 0, endValue = "endValue" in options ? options.endValue : 100, byValue = options.byValue || endValue - startValue; + options.onStart && options.onStart(); + (function tick(ticktime) { + time = ticktime || +new Date(); + var currentTime = time > finish ? duration : time - start; + if (abort()) { + options.onComplete && options.onComplete(); + return; + } + onChange(easing(currentTime, startValue, byValue, duration)); + if (time > finish) { + options.onComplete && options.onComplete(); + return; + } + requestAnimFrame(tick); + })(start); + }); + } + var _requestAnimFrame = fabric.window.requestAnimationFrame || fabric.window.webkitRequestAnimationFrame || fabric.window.mozRequestAnimationFrame || fabric.window.oRequestAnimationFrame || fabric.window.msRequestAnimationFrame || function(callback) { + fabric.window.setTimeout(callback, 1e3 / 60); + }; + function requestAnimFrame() { + return _requestAnimFrame.apply(fabric.window, arguments); + } + fabric.util.animate = animate; + fabric.util.requestAnimFrame = requestAnimFrame; +})(); + +(function() { + function normalize(a, c, p, s) { + if (a < Math.abs(c)) { + a = c; + s = p / 4; + } else { + if (c === 0 && a === 0) { + s = p / (2 * Math.PI) * Math.asin(1); + } else { + s = p / (2 * Math.PI) * Math.asin(c / a); + } + } + return { + a: a, + c: c, + p: p, + s: s + }; + } + function elastic(opts, t, d) { + return opts.a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p); + } + function easeOutCubic(t, b, c, d) { + return c * ((t = t / d - 1) * t * t + 1) + b; + } + function easeInOutCubic(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return c / 2 * t * t * t + b; + } + return c / 2 * ((t -= 2) * t * t + 2) + b; + } + function easeInQuart(t, b, c, d) { + return c * (t /= d) * t * t * t + b; + } + function easeOutQuart(t, b, c, d) { + return -c * ((t = t / d - 1) * t * t * t - 1) + b; + } + function easeInOutQuart(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return c / 2 * t * t * t * t + b; + } + return -c / 2 * ((t -= 2) * t * t * t - 2) + b; + } + function easeInQuint(t, b, c, d) { + return c * (t /= d) * t * t * t * t + b; + } + function easeOutQuint(t, b, c, d) { + return c * ((t = t / d - 1) * t * t * t * t + 1) + b; + } + function easeInOutQuint(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return c / 2 * t * t * t * t * t + b; + } + return c / 2 * ((t -= 2) * t * t * t * t + 2) + b; + } + function easeInSine(t, b, c, d) { + return -c * Math.cos(t / d * (Math.PI / 2)) + c + b; + } + function easeOutSine(t, b, c, d) { + return c * Math.sin(t / d * (Math.PI / 2)) + b; + } + function easeInOutSine(t, b, c, d) { + return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b; + } + function easeInExpo(t, b, c, d) { + return t === 0 ? b : c * Math.pow(2, 10 * (t / d - 1)) + b; + } + function easeOutExpo(t, b, c, d) { + return t === d ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b; + } + function easeInOutExpo(t, b, c, d) { + if (t === 0) { + return b; + } + if (t === d) { + return b + c; + } + t /= d / 2; + if (t < 1) { + return c / 2 * Math.pow(2, 10 * (t - 1)) + b; + } + return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b; + } + function easeInCirc(t, b, c, d) { + return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b; + } + function easeOutCirc(t, b, c, d) { + return c * Math.sqrt(1 - (t = t / d - 1) * t) + b; + } + function easeInOutCirc(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b; + } + return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b; + } + function easeInElastic(t, b, c, d) { + var s = 1.70158, p = 0, a = c; + if (t === 0) { + return b; + } + t /= d; + if (t === 1) { + return b + c; + } + if (!p) { + p = d * .3; + } + var opts = normalize(a, c, p, s); + return -elastic(opts, t, d) + b; + } + function easeOutElastic(t, b, c, d) { + var s = 1.70158, p = 0, a = c; + if (t === 0) { + return b; + } + t /= d; + if (t === 1) { + return b + c; + } + if (!p) { + p = d * .3; + } + var opts = normalize(a, c, p, s); + return opts.a * Math.pow(2, -10 * t) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p) + opts.c + b; + } + function easeInOutElastic(t, b, c, d) { + var s = 1.70158, p = 0, a = c; + if (t === 0) { + return b; + } + t /= d / 2; + if (t === 2) { + return b + c; + } + if (!p) { + p = d * (.3 * 1.5); + } + var opts = normalize(a, c, p, s); + if (t < 1) { + return -.5 * elastic(opts, t, d) + b; + } + return opts.a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p) * .5 + opts.c + b; + } + function easeInBack(t, b, c, d, s) { + if (s === undefined) { + s = 1.70158; + } + return c * (t /= d) * t * ((s + 1) * t - s) + b; + } + function easeOutBack(t, b, c, d, s) { + if (s === undefined) { + s = 1.70158; + } + return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; + } + function easeInOutBack(t, b, c, d, s) { + if (s === undefined) { + s = 1.70158; + } + t /= d / 2; + if (t < 1) { + return c / 2 * (t * t * (((s *= 1.525) + 1) * t - s)) + b; + } + return c / 2 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2) + b; + } + function easeInBounce(t, b, c, d) { + return c - easeOutBounce(d - t, 0, c, d) + b; + } + function easeOutBounce(t, b, c, d) { + if ((t /= d) < 1 / 2.75) { + return c * (7.5625 * t * t) + b; + } else if (t < 2 / 2.75) { + return c * (7.5625 * (t -= 1.5 / 2.75) * t + .75) + b; + } else if (t < 2.5 / 2.75) { + return c * (7.5625 * (t -= 2.25 / 2.75) * t + .9375) + b; + } else { + return c * (7.5625 * (t -= 2.625 / 2.75) * t + .984375) + b; + } + } + function easeInOutBounce(t, b, c, d) { + if (t < d / 2) { + return easeInBounce(t * 2, 0, c, d) * .5 + b; + } + return easeOutBounce(t * 2 - d, 0, c, d) * .5 + c * .5 + b; + } + fabric.util.ease = { + easeInQuad: function(t, b, c, d) { + return c * (t /= d) * t + b; + }, + easeOutQuad: function(t, b, c, d) { + return -c * (t /= d) * (t - 2) + b; + }, + easeInOutQuad: function(t, b, c, d) { + t /= d / 2; + if (t < 1) { + return c / 2 * t * t + b; + } + return -c / 2 * (--t * (t - 2) - 1) + b; + }, + easeInCubic: function(t, b, c, d) { + return c * (t /= d) * t * t + b; + }, + easeOutCubic: easeOutCubic, + easeInOutCubic: easeInOutCubic, + easeInQuart: easeInQuart, + easeOutQuart: easeOutQuart, + easeInOutQuart: easeInOutQuart, + easeInQuint: easeInQuint, + easeOutQuint: easeOutQuint, + easeInOutQuint: easeInOutQuint, + easeInSine: easeInSine, + easeOutSine: easeOutSine, + easeInOutSine: easeInOutSine, + easeInExpo: easeInExpo, + easeOutExpo: easeOutExpo, + easeInOutExpo: easeInOutExpo, + easeInCirc: easeInCirc, + easeOutCirc: easeOutCirc, + easeInOutCirc: easeInOutCirc, + easeInElastic: easeInElastic, + easeOutElastic: easeOutElastic, + easeInOutElastic: easeInOutElastic, + easeInBack: easeInBack, + easeOutBack: easeOutBack, + easeInOutBack: easeInOutBack, + easeInBounce: easeInBounce, + easeOutBounce: easeOutBounce, + easeInOutBounce: easeInOutBounce + }; +})(); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, capitalize = fabric.util.string.capitalize, clone = fabric.util.object.clone, toFixed = fabric.util.toFixed, parseUnit = fabric.util.parseUnit, multiplyTransformMatrices = fabric.util.multiplyTransformMatrices, reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/i, reViewBoxTagNames = /^(symbol|image|marker|pattern|view|svg)$/i, reNotAllowedAncestors = /^(?:pattern|defs|symbol|metadata)$/i, reAllowedParents = /^(symbol|g|a|svg)$/i, attributesMap = { + cx: "left", + x: "left", + r: "radius", + cy: "top", + y: "top", + display: "visible", + visibility: "visible", + transform: "transformMatrix", + "fill-opacity": "fillOpacity", + "fill-rule": "fillRule", + "font-family": "fontFamily", + "font-size": "fontSize", + "font-style": "fontStyle", + "font-weight": "fontWeight", + "stroke-dasharray": "strokeDashArray", + "stroke-linecap": "strokeLineCap", + "stroke-linejoin": "strokeLineJoin", + "stroke-miterlimit": "strokeMiterLimit", + "stroke-opacity": "strokeOpacity", + "stroke-width": "strokeWidth", + "text-decoration": "textDecoration", + "text-anchor": "originX" + }, colorAttributes = { + stroke: "strokeOpacity", + fill: "fillOpacity" + }; + fabric.cssRules = {}; + fabric.gradientDefs = {}; + function normalizeAttr(attr) { + if (attr in attributesMap) { + return attributesMap[attr]; + } + return attr; + } + function normalizeValue(attr, value, parentAttributes, fontSize) { + var isArray = Object.prototype.toString.call(value) === "[object Array]", parsed; + if ((attr === "fill" || attr === "stroke") && value === "none") { + value = ""; + } else if (attr === "strokeDashArray") { + value = value.replace(/,/g, " ").split(/\s+/).map(function(n) { + return parseFloat(n); + }); + } else if (attr === "transformMatrix") { + if (parentAttributes && parentAttributes.transformMatrix) { + value = multiplyTransformMatrices(parentAttributes.transformMatrix, fabric.parseTransformAttribute(value)); + } else { + value = fabric.parseTransformAttribute(value); + } + } else if (attr === "visible") { + value = value === "none" || value === "hidden" ? false : true; + if (parentAttributes && parentAttributes.visible === false) { + value = false; + } + } else if (attr === "originX") { + value = value === "start" ? "left" : value === "end" ? "right" : "center"; + } else { + parsed = isArray ? value.map(parseUnit) : parseUnit(value, fontSize); + } + return !isArray && isNaN(parsed) ? value : parsed; + } + function _setStrokeFillOpacity(attributes) { + for (var attr in colorAttributes) { + if (typeof attributes[colorAttributes[attr]] === "undefined" || attributes[attr] === "") { + continue; + } + if (typeof attributes[attr] === "undefined") { + if (!fabric.Object.prototype[attr]) { + continue; + } + attributes[attr] = fabric.Object.prototype[attr]; + } + if (attributes[attr].indexOf("url(") === 0) { + continue; + } + var color = new fabric.Color(attributes[attr]); + attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba(); + } + return attributes; + } + fabric.parseTransformAttribute = function() { + function rotateMatrix(matrix, args) { + var angle = args[0], x = args.length === 3 ? args[1] : 0, y = args.length === 3 ? args[2] : 0; + matrix[0] = Math.cos(angle); + matrix[1] = Math.sin(angle); + matrix[2] = -Math.sin(angle); + matrix[3] = Math.cos(angle); + matrix[4] = x - (matrix[0] * x + matrix[2] * y); + matrix[5] = y - (matrix[1] * x + matrix[3] * y); + } + function scaleMatrix(matrix, args) { + var multiplierX = args[0], multiplierY = args.length === 2 ? args[1] : args[0]; + matrix[0] = multiplierX; + matrix[3] = multiplierY; + } + function skewXMatrix(matrix, args) { + matrix[2] = Math.tan(fabric.util.degreesToRadians(args[0])); + } + function skewYMatrix(matrix, args) { + matrix[1] = Math.tan(fabric.util.degreesToRadians(args[0])); + } + function translateMatrix(matrix, args) { + matrix[4] = args[0]; + if (args.length === 2) { + matrix[5] = args[1]; + } + } + var iMatrix = [ 1, 0, 0, 1, 0, 0 ], number = fabric.reNum, commaWsp = "(?:\\s+,?\\s*|,\\s*)", skewX = "(?:(skewX)\\s*\\(\\s*(" + number + ")\\s*\\))", skewY = "(?:(skewY)\\s*\\(\\s*(" + number + ")\\s*\\))", rotate = "(?:(rotate)\\s*\\(\\s*(" + number + ")(?:" + commaWsp + "(" + number + ")" + commaWsp + "(" + number + "))?\\s*\\))", scale = "(?:(scale)\\s*\\(\\s*(" + number + ")(?:" + commaWsp + "(" + number + "))?\\s*\\))", translate = "(?:(translate)\\s*\\(\\s*(" + number + ")(?:" + commaWsp + "(" + number + "))?\\s*\\))", matrix = "(?:(matrix)\\s*\\(\\s*" + "(" + number + ")" + commaWsp + "(" + number + ")" + commaWsp + "(" + number + ")" + commaWsp + "(" + number + ")" + commaWsp + "(" + number + ")" + commaWsp + "(" + number + ")" + "\\s*\\))", transform = "(?:" + matrix + "|" + translate + "|" + scale + "|" + rotate + "|" + skewX + "|" + skewY + ")", transforms = "(?:" + transform + "(?:" + commaWsp + "*" + transform + ")*" + ")", transformList = "^\\s*(?:" + transforms + "?)\\s*$", reTransformList = new RegExp(transformList), reTransform = new RegExp(transform, "g"); + return function(attributeValue) { + var matrix = iMatrix.concat(), matrices = []; + if (!attributeValue || attributeValue && !reTransformList.test(attributeValue)) { + return matrix; + } + attributeValue.replace(reTransform, function(match) { + var m = new RegExp(transform).exec(match).filter(function(match) { + return match !== "" && match != null; + }), operation = m[1], args = m.slice(2).map(parseFloat); + switch (operation) { + case "translate": + translateMatrix(matrix, args); + break; + + case "rotate": + args[0] = fabric.util.degreesToRadians(args[0]); + rotateMatrix(matrix, args); + break; + + case "scale": + scaleMatrix(matrix, args); + break; + + case "skewX": + skewXMatrix(matrix, args); + break; + + case "skewY": + skewYMatrix(matrix, args); + break; + + case "matrix": + matrix = args; + break; + } + matrices.push(matrix.concat()); + matrix = iMatrix.concat(); + }); + var combinedMatrix = matrices[0]; + while (matrices.length > 1) { + matrices.shift(); + combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]); + } + return combinedMatrix; + }; + }(); + function parseStyleString(style, oStyle) { + var attr, value; + style.replace(/;\s*$/, "").split(";").forEach(function(chunk) { + var pair = chunk.split(":"); + attr = normalizeAttr(pair[0].trim().toLowerCase()); + value = normalizeValue(attr, pair[1].trim()); + oStyle[attr] = value; + }); + } + function parseStyleObject(style, oStyle) { + var attr, value; + for (var prop in style) { + if (typeof style[prop] === "undefined") { + continue; + } + attr = normalizeAttr(prop.toLowerCase()); + value = normalizeValue(attr, style[prop]); + oStyle[attr] = value; + } + } + function getGlobalStylesForElement(element, svgUid) { + var styles = {}; + for (var rule in fabric.cssRules[svgUid]) { + if (elementMatchesRule(element, rule.split(" "))) { + for (var property in fabric.cssRules[svgUid][rule]) { + styles[property] = fabric.cssRules[svgUid][rule][property]; + } + } + } + return styles; + } + function elementMatchesRule(element, selectors) { + var firstMatching, parentMatching = true; + firstMatching = selectorMatches(element, selectors.pop()); + if (firstMatching && selectors.length) { + parentMatching = doesSomeParentMatch(element, selectors); + } + return firstMatching && parentMatching && selectors.length === 0; + } + function doesSomeParentMatch(element, selectors) { + var selector, parentMatching = true; + while (element.parentNode && element.parentNode.nodeType === 1 && selectors.length) { + if (parentMatching) { + selector = selectors.pop(); + } + element = element.parentNode; + parentMatching = selectorMatches(element, selector); + } + return selectors.length === 0; + } + function selectorMatches(element, selector) { + var nodeName = element.nodeName, classNames = element.getAttribute("class"), id = element.getAttribute("id"), matcher; + matcher = new RegExp("^" + nodeName, "i"); + selector = selector.replace(matcher, ""); + if (id && selector.length) { + matcher = new RegExp("#" + id + "(?![a-zA-Z\\-]+)", "i"); + selector = selector.replace(matcher, ""); + } + if (classNames && selector.length) { + classNames = classNames.split(" "); + for (var i = classNames.length; i--; ) { + matcher = new RegExp("\\." + classNames[i] + "(?![a-zA-Z\\-]+)", "i"); + selector = selector.replace(matcher, ""); + } + } + return selector.length === 0; + } + function elementById(doc, id) { + var el; + doc.getElementById && (el = doc.getElementById(id)); + if (el) { + return el; + } + var node, i, nodelist = doc.getElementsByTagName("*"); + for (i = 0; i < nodelist.length; i++) { + node = nodelist[i]; + if (id === node.getAttribute("id")) { + return node; + } + } + } + function parseUseDirectives(doc) { + var nodelist = doc.getElementsByTagName("use"), i = 0; + while (nodelist.length && i < nodelist.length) { + var el = nodelist[i], xlink = el.getAttribute("xlink:href").substr(1), x = el.getAttribute("x") || 0, y = el.getAttribute("y") || 0, el2 = elementById(doc, xlink).cloneNode(true), currentTrans = (el2.getAttribute("transform") || "") + " translate(" + x + ", " + y + ")", parentNode, oldLength = nodelist.length, attr, j, attrs, l; + applyViewboxTransform(el2); + if (/^svg$/i.test(el2.nodeName)) { + var el3 = el2.ownerDocument.createElement("g"); + for (j = 0, attrs = el2.attributes, l = attrs.length; j < l; j++) { + attr = attrs.item(j); + el3.setAttribute(attr.nodeName, attr.nodeValue); + } + while (el2.firstChild != null) { + el3.appendChild(el2.firstChild); + } + el2 = el3; + } + for (j = 0, attrs = el.attributes, l = attrs.length; j < l; j++) { + attr = attrs.item(j); + if (attr.nodeName === "x" || attr.nodeName === "y" || attr.nodeName === "xlink:href") { + continue; + } + if (attr.nodeName === "transform") { + currentTrans = attr.nodeValue + " " + currentTrans; + } else { + el2.setAttribute(attr.nodeName, attr.nodeValue); + } + } + el2.setAttribute("transform", currentTrans); + el2.setAttribute("instantiated_by_use", "1"); + el2.removeAttribute("id"); + parentNode = el.parentNode; + parentNode.replaceChild(el2, el); + if (nodelist.length === oldLength) { + i++; + } + } + } + var reViewBoxAttrValue = new RegExp("^" + "\\s*(" + fabric.reNum + "+)\\s*,?" + "\\s*(" + fabric.reNum + "+)\\s*,?" + "\\s*(" + fabric.reNum + "+)\\s*,?" + "\\s*(" + fabric.reNum + "+)\\s*" + "$"); + function applyViewboxTransform(element) { + var viewBoxAttr = element.getAttribute("viewBox"), scaleX = 1, scaleY = 1, minX = 0, minY = 0, viewBoxWidth, viewBoxHeight, matrix, el, widthAttr = element.getAttribute("width"), heightAttr = element.getAttribute("height"), x = element.getAttribute("x") || 0, y = element.getAttribute("y") || 0, preserveAspectRatio = element.getAttribute("preserveAspectRatio") || "", missingViewBox = !viewBoxAttr || !reViewBoxTagNames.test(element.tagName) || !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue)), missingDimAttr = !widthAttr || !heightAttr || widthAttr === "100%" || heightAttr === "100%", toBeParsed = missingViewBox && missingDimAttr, parsedDim = {}, translateMatrix = ""; + parsedDim.width = 0; + parsedDim.height = 0; + parsedDim.toBeParsed = toBeParsed; + if (toBeParsed) { + return parsedDim; + } + if (missingViewBox) { + parsedDim.width = parseUnit(widthAttr); + parsedDim.height = parseUnit(heightAttr); + return parsedDim; + } + minX = -parseFloat(viewBoxAttr[1]), minY = -parseFloat(viewBoxAttr[2]), viewBoxWidth = parseFloat(viewBoxAttr[3]), + viewBoxHeight = parseFloat(viewBoxAttr[4]); + if (!missingDimAttr) { + parsedDim.width = parseUnit(widthAttr); + parsedDim.height = parseUnit(heightAttr); + scaleX = parsedDim.width / viewBoxWidth; + scaleY = parsedDim.height / viewBoxHeight; + } else { + parsedDim.width = viewBoxWidth; + parsedDim.height = viewBoxHeight; + } + preserveAspectRatio = fabric.util.parsePreserveAspectRatioAttribute(preserveAspectRatio); + if (preserveAspectRatio.alignX !== "none") { + scaleY = scaleX = scaleX > scaleY ? scaleY : scaleX; + } + if (scaleX === 1 && scaleY === 1 && minX === 0 && minY === 0 && x === 0 && y === 0) { + return parsedDim; + } + if (x || y) { + translateMatrix = " translate(" + parseUnit(x) + " " + parseUnit(y) + ") "; + } + matrix = translateMatrix + " matrix(" + scaleX + " 0" + " 0 " + scaleY + " " + minX * scaleX + " " + minY * scaleY + ") "; + if (element.tagName === "svg") { + el = element.ownerDocument.createElement("g"); + while (element.firstChild != null) { + el.appendChild(element.firstChild); + } + element.appendChild(el); + } else { + el = element; + matrix = el.getAttribute("transform") + matrix; + } + el.setAttribute("transform", matrix); + return parsedDim; + } + fabric.parseSVGDocument = function() { + function hasAncestorWithNodeName(element, nodeName) { + while (element && (element = element.parentNode)) { + if (nodeName.test(element.nodeName) && !element.getAttribute("instantiated_by_use")) { + return true; + } + } + return false; + } + return function(doc, callback, reviver) { + if (!doc) { + return; + } + parseUseDirectives(doc); + var startTime = new Date(), svgUid = fabric.Object.__uid++, options = applyViewboxTransform(doc), descendants = fabric.util.toArray(doc.getElementsByTagName("*")); + options.svgUid = svgUid; + if (descendants.length === 0 && fabric.isLikelyNode) { + descendants = doc.selectNodes('//*[name(.)!="svg"]'); + var arr = []; + for (var i = 0, len = descendants.length; i < len; i++) { + arr[i] = descendants[i]; + } + descendants = arr; + } + var elements = descendants.filter(function(el) { + applyViewboxTransform(el); + return reAllowedSVGTagNames.test(el.tagName) && !hasAncestorWithNodeName(el, reNotAllowedAncestors); + }); + if (!elements || elements && !elements.length) { + callback && callback([], {}); + return; + } + fabric.gradientDefs[svgUid] = fabric.getGradientDefs(doc); + fabric.cssRules[svgUid] = fabric.getCSSRules(doc); + fabric.parseElements(elements, function(instances) { + fabric.documentParsingTime = new Date() - startTime; + if (callback) { + callback(instances, options); + } + }, clone(options), reviver); + }; + }(); + var svgCache = { + has: function(name, callback) { + callback(false); + }, + get: function() {}, + set: function() {} + }; + function _enlivenCachedObject(cachedObject) { + var objects = cachedObject.objects, options = cachedObject.options; + objects = objects.map(function(o) { + return fabric[capitalize(o.type)].fromObject(o); + }); + return { + objects: objects, + options: options + }; + } + function _createSVGPattern(markup, canvas, property) { + if (canvas[property] && canvas[property].toSVG) { + markup.push(' \n', ' \n \n'); + } + } + var reFontDeclaration = new RegExp("(normal|italic)?\\s*(normal|small-caps)?\\s*" + "(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\\s*(" + fabric.reNum + "(?:px|cm|mm|em|pt|pc|in)*)(?:\\/(normal|" + fabric.reNum + "))?\\s+(.*)"); + extend(fabric, { + parseFontDeclaration: function(value, oStyle) { + var match = value.match(reFontDeclaration); + if (!match) { + return; + } + var fontStyle = match[1], fontWeight = match[3], fontSize = match[4], lineHeight = match[5], fontFamily = match[6]; + if (fontStyle) { + oStyle.fontStyle = fontStyle; + } + if (fontWeight) { + oStyle.fontWeight = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight); + } + if (fontSize) { + oStyle.fontSize = parseUnit(fontSize); + } + if (fontFamily) { + oStyle.fontFamily = fontFamily; + } + if (lineHeight) { + oStyle.lineHeight = lineHeight === "normal" ? 1 : lineHeight; + } + }, + getGradientDefs: function(doc) { + var linearGradientEls = doc.getElementsByTagName("linearGradient"), radialGradientEls = doc.getElementsByTagName("radialGradient"), el, i, j = 0, id, xlink, elList = [], gradientDefs = {}, idsToXlinkMap = {}; + elList.length = linearGradientEls.length + radialGradientEls.length; + i = linearGradientEls.length; + while (i--) { + elList[j++] = linearGradientEls[i]; + } + i = radialGradientEls.length; + while (i--) { + elList[j++] = radialGradientEls[i]; + } + while (j--) { + el = elList[j]; + xlink = el.getAttribute("xlink:href"); + id = el.getAttribute("id"); + if (xlink) { + idsToXlinkMap[id] = xlink.substr(1); + } + gradientDefs[id] = el; + } + for (id in idsToXlinkMap) { + var el2 = gradientDefs[idsToXlinkMap[id]].cloneNode(true); + el = gradientDefs[id]; + while (el2.firstChild) { + el.appendChild(el2.firstChild); + } + } + return gradientDefs; + }, + parseAttributes: function(element, attributes, svgUid) { + if (!element) { + return; + } + var value, parentAttributes = {}, fontSize; + if (typeof svgUid === "undefined") { + svgUid = element.getAttribute("svgUid"); + } + if (element.parentNode && reAllowedParents.test(element.parentNode.nodeName)) { + parentAttributes = fabric.parseAttributes(element.parentNode, attributes, svgUid); + } + fontSize = parentAttributes && parentAttributes.fontSize || element.getAttribute("font-size") || fabric.Text.DEFAULT_SVG_FONT_SIZE; + var ownAttributes = attributes.reduce(function(memo, attr) { + value = element.getAttribute(attr); + if (value) { + attr = normalizeAttr(attr); + value = normalizeValue(attr, value, parentAttributes, fontSize); + memo[attr] = value; + } + return memo; + }, {}); + ownAttributes = extend(ownAttributes, extend(getGlobalStylesForElement(element, svgUid), fabric.parseStyleAttribute(element))); + if (ownAttributes.font) { + fabric.parseFontDeclaration(ownAttributes.font, ownAttributes); + } + return _setStrokeFillOpacity(extend(parentAttributes, ownAttributes)); + }, + parseElements: function(elements, callback, options, reviver) { + new fabric.ElementsParser(elements, callback, options, reviver).parse(); + }, + parseStyleAttribute: function(element) { + var oStyle = {}, style = element.getAttribute("style"); + if (!style) { + return oStyle; + } + if (typeof style === "string") { + parseStyleString(style, oStyle); + } else { + parseStyleObject(style, oStyle); + } + return oStyle; + }, + parsePointsAttribute: function(points) { + if (!points) { + return null; + } + points = points.replace(/,/g, " ").trim(); + points = points.split(/\s+/); + var parsedPoints = [], i, len; + i = 0; + len = points.length; + for (;i < len; i += 2) { + parsedPoints.push({ + x: parseFloat(points[i]), + y: parseFloat(points[i + 1]) + }); + } + return parsedPoints; + }, + getCSSRules: function(doc) { + var styles = doc.getElementsByTagName("style"), allRules = {}, rules; + for (var i = 0, len = styles.length; i < len; i++) { + var styleContents = styles[i].textContent || styles[i].text; + styleContents = styleContents.replace(/\/\*[\s\S]*?\*\//g, ""); + if (styleContents.trim() === "") { + continue; + } + rules = styleContents.match(/[^{]*\{[\s\S]*?\}/g); + rules = rules.map(function(rule) { + return rule.trim(); + }); + rules.forEach(function(rule) { + var match = rule.match(/([\s\S]*?)\s*\{([^}]*)\}/), ruleObj = {}, declaration = match[2].trim(), propertyValuePairs = declaration.replace(/;$/, "").split(/\s*;\s*/); + for (var i = 0, len = propertyValuePairs.length; i < len; i++) { + var pair = propertyValuePairs[i].split(/\s*:\s*/), property = normalizeAttr(pair[0]), value = normalizeValue(property, pair[1], pair[0]); + ruleObj[property] = value; + } + rule = match[1]; + rule.split(",").forEach(function(_rule) { + _rule = _rule.replace(/^svg/i, "").trim(); + if (_rule === "") { + return; + } + allRules[_rule] = fabric.util.object.clone(ruleObj); + }); + }); + } + return allRules; + }, + loadSVGFromURL: function(url, callback, reviver) { + url = url.replace(/^\n\s*/, "").trim(); + svgCache.has(url, function(hasUrl) { + if (hasUrl) { + svgCache.get(url, function(value) { + var enlivedRecord = _enlivenCachedObject(value); + callback(enlivedRecord.objects, enlivedRecord.options); + }); + } else { + new fabric.util.request(url, { + method: "get", + onComplete: onComplete + }); + } + }); + function onComplete(r) { + var xml = r.responseXML; + if (xml && !xml.documentElement && fabric.window.ActiveXObject && r.responseText) { + xml = new ActiveXObject("Microsoft.XMLDOM"); + xml.async = "false"; + xml.loadXML(r.responseText.replace(//i, "")); + } + if (!xml || !xml.documentElement) { + return; + } + fabric.parseSVGDocument(xml.documentElement, function(results, options) { + svgCache.set(url, { + objects: fabric.util.array.invoke(results, "toObject"), + options: options + }); + callback(results, options); + }, reviver); + } + }, + loadSVGFromString: function(string, callback, reviver) { + string = string.trim(); + var doc; + if (typeof DOMParser !== "undefined") { + var parser = new DOMParser(); + if (parser && parser.parseFromString) { + doc = parser.parseFromString(string, "text/xml"); + } + } else if (fabric.window.ActiveXObject) { + doc = new ActiveXObject("Microsoft.XMLDOM"); + doc.async = "false"; + doc.loadXML(string.replace(//i, "")); + } + fabric.parseSVGDocument(doc.documentElement, function(results, options) { + callback(results, options); + }, reviver); + }, + createSVGFontFacesMarkup: function(objects) { + var markup = "", fontList = {}, obj, fontFamily, style, row, rowIndex, char, charIndex, fontPaths = fabric.fontPaths; + for (var i = 0, len = objects.length; i < len; i++) { + obj = objects[i]; + fontFamily = obj.fontFamily; + if (obj.type.indexOf("text") === -1 || fontList[fontFamily] || !fontPaths[fontFamily]) { + continue; + } + fontList[fontFamily] = true; + if (!obj.styles) { + continue; + } + style = obj.styles; + for (rowIndex in style) { + char = style[rowIndex]; + for (charIndex in row) { + char = row[charIndex]; + fontFamily = char.fontFamily; + if (!fontList[fontFamily] && fontPaths[fontFamily]) { + fontList[fontFamily] = true; + } + } + } + } + for (var j in fontList) { + markup += [ " @font-face {\n", " font-family: '", j, "';\n", " src: url('", fontPaths[j], "');\n", " }\n" ].join(""); + } + if (markup) { + markup = [ ' \n" ].join(""); + } + return markup; + }, + createSVGRefElementsMarkup: function(canvas) { + var markup = []; + _createSVGPattern(markup, canvas, "backgroundColor"); + _createSVGPattern(markup, canvas, "overlayColor"); + return markup.join(""); + } + }); +})(typeof exports !== "undefined" ? exports : this); + +fabric.ElementsParser = function(elements, callback, options, reviver) { + this.elements = elements; + this.callback = callback; + this.options = options; + this.reviver = reviver; + this.svgUid = options && options.svgUid || 0; +}; + +fabric.ElementsParser.prototype.parse = function() { + this.instances = new Array(this.elements.length); + this.numElements = this.elements.length; + this.createObjects(); +}; + +fabric.ElementsParser.prototype.createObjects = function() { + for (var i = 0, len = this.elements.length; i < len; i++) { + this.elements[i].setAttribute("svgUid", this.svgUid); + (function(_this, i) { + setTimeout(function() { + _this.createObject(_this.elements[i], i); + }, 0); + })(this, i); + } +}; + +fabric.ElementsParser.prototype.createObject = function(el, index) { + var klass = fabric[fabric.util.string.capitalize(el.tagName)]; + if (klass && klass.fromElement) { + try { + this._createObject(klass, el, index); + } catch (err) { + fabric.log(err); + } + } else { + this.checkIfDone(); + } +}; + +fabric.ElementsParser.prototype._createObject = function(klass, el, index) { + if (klass.async) { + klass.fromElement(el, this.createCallback(index, el), this.options); + } else { + var obj = klass.fromElement(el, this.options); + this.resolveGradient(obj, "fill"); + this.resolveGradient(obj, "stroke"); + this.reviver && this.reviver(el, obj); + this.instances[index] = obj; + this.checkIfDone(); + } +}; + +fabric.ElementsParser.prototype.createCallback = function(index, el) { + var _this = this; + return function(obj) { + _this.resolveGradient(obj, "fill"); + _this.resolveGradient(obj, "stroke"); + _this.reviver && _this.reviver(el, obj); + _this.instances[index] = obj; + _this.checkIfDone(); + }; +}; + +fabric.ElementsParser.prototype.resolveGradient = function(obj, property) { + var instanceFillValue = obj.get(property); + if (!/^url\(/.test(instanceFillValue)) { + return; + } + var gradientId = instanceFillValue.slice(5, instanceFillValue.length - 1); + if (fabric.gradientDefs[this.svgUid][gradientId]) { + obj.set(property, fabric.Gradient.fromElement(fabric.gradientDefs[this.svgUid][gradientId], obj)); + } +}; + +fabric.ElementsParser.prototype.checkIfDone = function() { + if (--this.numElements === 0) { + this.instances = this.instances.filter(function(el) { + return el != null; + }); + this.callback(this.instances); + } +}; + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}); + if (fabric.Point) { + fabric.warn("fabric.Point is already defined"); + return; + } + fabric.Point = Point; + function Point(x, y) { + this.x = x; + this.y = y; + } + Point.prototype = { + constructor: Point, + add: function(that) { + return new Point(this.x + that.x, this.y + that.y); + }, + addEquals: function(that) { + this.x += that.x; + this.y += that.y; + return this; + }, + scalarAdd: function(scalar) { + return new Point(this.x + scalar, this.y + scalar); + }, + scalarAddEquals: function(scalar) { + this.x += scalar; + this.y += scalar; + return this; + }, + subtract: function(that) { + return new Point(this.x - that.x, this.y - that.y); + }, + subtractEquals: function(that) { + this.x -= that.x; + this.y -= that.y; + return this; + }, + scalarSubtract: function(scalar) { + return new Point(this.x - scalar, this.y - scalar); + }, + scalarSubtractEquals: function(scalar) { + this.x -= scalar; + this.y -= scalar; + return this; + }, + multiply: function(scalar) { + return new Point(this.x * scalar, this.y * scalar); + }, + multiplyEquals: function(scalar) { + this.x *= scalar; + this.y *= scalar; + return this; + }, + divide: function(scalar) { + return new Point(this.x / scalar, this.y / scalar); + }, + divideEquals: function(scalar) { + this.x /= scalar; + this.y /= scalar; + return this; + }, + eq: function(that) { + return this.x === that.x && this.y === that.y; + }, + lt: function(that) { + return this.x < that.x && this.y < that.y; + }, + lte: function(that) { + return this.x <= that.x && this.y <= that.y; + }, + gt: function(that) { + return this.x > that.x && this.y > that.y; + }, + gte: function(that) { + return this.x >= that.x && this.y >= that.y; + }, + lerp: function(that, t) { + return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t); + }, + distanceFrom: function(that) { + var dx = this.x - that.x, dy = this.y - that.y; + return Math.sqrt(dx * dx + dy * dy); + }, + midPointFrom: function(that) { + return new Point(this.x + (that.x - this.x) / 2, this.y + (that.y - this.y) / 2); + }, + min: function(that) { + return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y)); + }, + max: function(that) { + return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y)); + }, + toString: function() { + return this.x + "," + this.y; + }, + setXY: function(x, y) { + this.x = x; + this.y = y; + }, + setFromPoint: function(that) { + this.x = that.x; + this.y = that.y; + }, + swap: function(that) { + var x = this.x, y = this.y; + this.x = that.x; + this.y = that.y; + that.x = x; + that.y = y; + } + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}); + if (fabric.Intersection) { + fabric.warn("fabric.Intersection is already defined"); + return; + } + function Intersection(status) { + this.status = status; + this.points = []; + } + fabric.Intersection = Intersection; + fabric.Intersection.prototype = { + appendPoint: function(point) { + this.points.push(point); + }, + appendPoints: function(points) { + this.points = this.points.concat(points); + } + }; + fabric.Intersection.intersectLineLine = function(a1, a2, b1, b2) { + var result, uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y); + if (uB !== 0) { + var ua = uaT / uB, ub = ubT / uB; + if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { + result = new Intersection("Intersection"); + result.points.push(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); + } else { + result = new Intersection(); + } + } else { + if (uaT === 0 || ubT === 0) { + result = new Intersection("Coincident"); + } else { + result = new Intersection("Parallel"); + } + } + return result; + }; + fabric.Intersection.intersectLinePolygon = function(a1, a2, points) { + var result = new Intersection(), length = points.length; + for (var i = 0; i < length; i++) { + var b1 = points[i], b2 = points[(i + 1) % length], inter = Intersection.intersectLineLine(a1, a2, b1, b2); + result.appendPoints(inter.points); + } + if (result.points.length > 0) { + result.status = "Intersection"; + } + return result; + }; + fabric.Intersection.intersectPolygonPolygon = function(points1, points2) { + var result = new Intersection(), length = points1.length; + for (var i = 0; i < length; i++) { + var a1 = points1[i], a2 = points1[(i + 1) % length], inter = Intersection.intersectLinePolygon(a1, a2, points2); + result.appendPoints(inter.points); + } + if (result.points.length > 0) { + result.status = "Intersection"; + } + return result; + }; + fabric.Intersection.intersectPolygonRectangle = function(points, r1, r2) { + var min = r1.min(r2), max = r1.max(r2), topRight = new fabric.Point(max.x, min.y), bottomLeft = new fabric.Point(min.x, max.y), inter1 = Intersection.intersectLinePolygon(min, topRight, points), inter2 = Intersection.intersectLinePolygon(topRight, max, points), inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points), inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points), result = new Intersection(); + result.appendPoints(inter1.points); + result.appendPoints(inter2.points); + result.appendPoints(inter3.points); + result.appendPoints(inter4.points); + if (result.points.length > 0) { + result.status = "Intersection"; + } + return result; + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}); + if (fabric.Color) { + fabric.warn("fabric.Color is already defined."); + return; + } + function Color(color) { + if (!color) { + this.setSource([ 0, 0, 0, 1 ]); + } else { + this._tryParsingColor(color); + } + } + fabric.Color = Color; + fabric.Color.prototype = { + _tryParsingColor: function(color) { + var source; + if (color in Color.colorNameMap) { + color = Color.colorNameMap[color]; + } + if (color === "transparent") { + this.setSource([ 255, 255, 255, 0 ]); + return; + } + source = Color.sourceFromHex(color); + if (!source) { + source = Color.sourceFromRgb(color); + } + if (!source) { + source = Color.sourceFromHsl(color); + } + if (source) { + this.setSource(source); + } + }, + _rgbToHsl: function(r, g, b) { + r /= 255, g /= 255, b /= 255; + var h, s, l, max = fabric.util.array.max([ r, g, b ]), min = fabric.util.array.min([ r, g, b ]); + l = (max + min) / 2; + if (max === min) { + h = s = 0; + } else { + var d = max - min; + s = l > .5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + + case g: + h = (b - r) / d + 2; + break; + + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + return [ Math.round(h * 360), Math.round(s * 100), Math.round(l * 100) ]; + }, + getSource: function() { + return this._source; + }, + setSource: function(source) { + this._source = source; + }, + toRgb: function() { + var source = this.getSource(); + return "rgb(" + source[0] + "," + source[1] + "," + source[2] + ")"; + }, + toRgba: function() { + var source = this.getSource(); + return "rgba(" + source[0] + "," + source[1] + "," + source[2] + "," + source[3] + ")"; + }, + toHsl: function() { + var source = this.getSource(), hsl = this._rgbToHsl(source[0], source[1], source[2]); + return "hsl(" + hsl[0] + "," + hsl[1] + "%," + hsl[2] + "%)"; + }, + toHsla: function() { + var source = this.getSource(), hsl = this._rgbToHsl(source[0], source[1], source[2]); + return "hsla(" + hsl[0] + "," + hsl[1] + "%," + hsl[2] + "%," + source[3] + ")"; + }, + toHex: function() { + var source = this.getSource(), r, g, b; + r = source[0].toString(16); + r = r.length === 1 ? "0" + r : r; + g = source[1].toString(16); + g = g.length === 1 ? "0" + g : g; + b = source[2].toString(16); + b = b.length === 1 ? "0" + b : b; + return r.toUpperCase() + g.toUpperCase() + b.toUpperCase(); + }, + getAlpha: function() { + return this.getSource()[3]; + }, + setAlpha: function(alpha) { + var source = this.getSource(); + source[3] = alpha; + this.setSource(source); + return this; + }, + toGrayscale: function() { + var source = this.getSource(), average = parseInt((source[0] * .3 + source[1] * .59 + source[2] * .11).toFixed(0), 10), currentAlpha = source[3]; + this.setSource([ average, average, average, currentAlpha ]); + return this; + }, + toBlackWhite: function(threshold) { + var source = this.getSource(), average = (source[0] * .3 + source[1] * .59 + source[2] * .11).toFixed(0), currentAlpha = source[3]; + threshold = threshold || 127; + average = Number(average) < Number(threshold) ? 0 : 255; + this.setSource([ average, average, average, currentAlpha ]); + return this; + }, + overlayWith: function(otherColor) { + if (!(otherColor instanceof Color)) { + otherColor = new Color(otherColor); + } + var result = [], alpha = this.getAlpha(), otherAlpha = .5, source = this.getSource(), otherSource = otherColor.getSource(); + for (var i = 0; i < 3; i++) { + result.push(Math.round(source[i] * (1 - otherAlpha) + otherSource[i] * otherAlpha)); + } + result[3] = alpha; + this.setSource(result); + return this; + } + }; + 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*)?\)$/; + fabric.Color.reHSLa = /^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/; + fabric.Color.reHex = /^#?([0-9a-f]{6}|[0-9a-f]{3})$/i; + fabric.Color.colorNameMap = { + aqua: "#00FFFF", + black: "#000000", + blue: "#0000FF", + fuchsia: "#FF00FF", + gray: "#808080", + green: "#008000", + lime: "#00FF00", + maroon: "#800000", + navy: "#000080", + olive: "#808000", + orange: "#FFA500", + purple: "#800080", + red: "#FF0000", + silver: "#C0C0C0", + teal: "#008080", + white: "#FFFFFF", + yellow: "#FFFF00" + }; + function hue2rgb(p, q, t) { + if (t < 0) { + t += 1; + } + if (t > 1) { + t -= 1; + } + if (t < 1 / 6) { + return p + (q - p) * 6 * t; + } + if (t < 1 / 2) { + return q; + } + if (t < 2 / 3) { + return p + (q - p) * (2 / 3 - t) * 6; + } + return p; + } + fabric.Color.fromRgb = function(color) { + return Color.fromSource(Color.sourceFromRgb(color)); + }; + fabric.Color.sourceFromRgb = function(color) { + var match = color.match(Color.reRGBa); + if (match) { + var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1), g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1), b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1); + return [ parseInt(r, 10), parseInt(g, 10), parseInt(b, 10), match[4] ? parseFloat(match[4]) : 1 ]; + } + }; + fabric.Color.fromRgba = Color.fromRgb; + fabric.Color.fromHsl = function(color) { + return Color.fromSource(Color.sourceFromHsl(color)); + }; + fabric.Color.sourceFromHsl = function(color) { + var match = color.match(Color.reHSLa); + if (!match) { + return; + } + var h = (parseFloat(match[1]) % 360 + 360) % 360 / 360, s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1), l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1), r, g, b; + if (s === 0) { + r = g = b = l; + } else { + var q = l <= .5 ? l * (s + 1) : l + s - l * s, p = l * 2 - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + } + return [ Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), match[4] ? parseFloat(match[4]) : 1 ]; + }; + fabric.Color.fromHsla = Color.fromHsl; + fabric.Color.fromHex = function(color) { + return Color.fromSource(Color.sourceFromHex(color)); + }; + fabric.Color.sourceFromHex = function(color) { + if (color.match(Color.reHex)) { + var value = color.slice(color.indexOf("#") + 1), isShortNotation = value.length === 3, r = isShortNotation ? value.charAt(0) + value.charAt(0) : value.substring(0, 2), g = isShortNotation ? value.charAt(1) + value.charAt(1) : value.substring(2, 4), b = isShortNotation ? value.charAt(2) + value.charAt(2) : value.substring(4, 6); + return [ parseInt(r, 16), parseInt(g, 16), parseInt(b, 16), 1 ]; + } + }; + fabric.Color.fromSource = function(source) { + var oColor = new Color(); + oColor.setSource(source); + return oColor; + }; +})(typeof exports !== "undefined" ? exports : this); + +(function() { + function getColorStop(el) { + var style = el.getAttribute("style"), offset = el.getAttribute("offset") || 0, color, colorAlpha, opacity; + offset = parseFloat(offset) / (/%$/.test(offset) ? 100 : 1); + offset = offset < 0 ? 0 : offset > 1 ? 1 : offset; + if (style) { + var keyValuePairs = style.split(/\s*;\s*/); + if (keyValuePairs[keyValuePairs.length - 1] === "") { + keyValuePairs.pop(); + } + for (var i = keyValuePairs.length; i--; ) { + var split = keyValuePairs[i].split(/\s*:\s*/), key = split[0].trim(), value = split[1].trim(); + if (key === "stop-color") { + color = value; + } else if (key === "stop-opacity") { + opacity = value; + } + } + } + if (!color) { + color = el.getAttribute("stop-color") || "rgb(0,0,0)"; + } + if (!opacity) { + opacity = el.getAttribute("stop-opacity"); + } + color = new fabric.Color(color); + colorAlpha = color.getAlpha(); + opacity = isNaN(parseFloat(opacity)) ? 1 : parseFloat(opacity); + opacity *= colorAlpha; + return { + offset: offset, + color: color.toRgb(), + opacity: opacity + }; + } + function getLinearCoords(el) { + return { + x1: el.getAttribute("x1") || 0, + y1: el.getAttribute("y1") || 0, + x2: el.getAttribute("x2") || "100%", + y2: el.getAttribute("y2") || 0 + }; + } + function getRadialCoords(el) { + return { + x1: el.getAttribute("fx") || el.getAttribute("cx") || "50%", + y1: el.getAttribute("fy") || el.getAttribute("cy") || "50%", + r1: 0, + x2: el.getAttribute("cx") || "50%", + y2: el.getAttribute("cy") || "50%", + r2: el.getAttribute("r") || "50%" + }; + } + fabric.Gradient = fabric.util.createClass({ + offsetX: 0, + offsetY: 0, + initialize: function(options) { + options || (options = {}); + var coords = {}; + this.id = fabric.Object.__uid++; + this.type = options.type || "linear"; + coords = { + x1: options.coords.x1 || 0, + y1: options.coords.y1 || 0, + x2: options.coords.x2 || 0, + y2: options.coords.y2 || 0 + }; + if (this.type === "radial") { + coords.r1 = options.coords.r1 || 0; + coords.r2 = options.coords.r2 || 0; + } + this.coords = coords; + this.colorStops = options.colorStops.slice(); + if (options.gradientTransform) { + this.gradientTransform = options.gradientTransform; + } + this.offsetX = options.offsetX || this.offsetX; + this.offsetY = options.offsetY || this.offsetY; + }, + addColorStop: function(colorStop) { + for (var position in colorStop) { + var color = new fabric.Color(colorStop[position]); + this.colorStops.push({ + offset: position, + color: color.toRgb(), + opacity: color.getAlpha() + }); + } + return this; + }, + toObject: function() { + return { + type: this.type, + coords: this.coords, + colorStops: this.colorStops, + offsetX: this.offsetX, + offsetY: this.offsetY, + gradientTransform: this.gradientTransform ? this.gradientTransform.concat() : this.gradientTransform + }; + }, + toSVG: function(object) { + var coords = fabric.util.object.clone(this.coords), markup, commonAttributes; + this.colorStops.sort(function(a, b) { + return a.offset - b.offset; + }); + if (!(object.group && object.group.type === "path-group")) { + for (var prop in coords) { + if (prop === "x1" || prop === "x2" || prop === "r2") { + coords[prop] += this.offsetX - object.width / 2; + } else if (prop === "y1" || prop === "y2") { + coords[prop] += this.offsetY - object.height / 2; + } + } + } + commonAttributes = 'id="SVGID_' + this.id + '" gradientUnits="userSpaceOnUse"'; + if (this.gradientTransform) { + commonAttributes += ' gradientTransform="matrix(' + this.gradientTransform.join(" ") + ')" '; + } + if (this.type === "linear") { + markup = [ "\n' ]; + } else if (this.type === "radial") { + markup = [ "\n' ]; + } + for (var i = 0; i < this.colorStops.length; i++) { + markup.push("\n'); + } + markup.push(this.type === "linear" ? "\n" : "\n"); + return markup.join(""); + }, + toLive: function(ctx, object) { + var gradient, prop, coords = fabric.util.object.clone(this.coords); + if (!this.type) { + return; + } + if (object.group && object.group.type === "path-group") { + for (prop in coords) { + if (prop === "x1" || prop === "x2") { + coords[prop] += -this.offsetX + object.width / 2; + } else if (prop === "y1" || prop === "y2") { + coords[prop] += -this.offsetY + object.height / 2; + } + } + } + if (this.type === "linear") { + gradient = ctx.createLinearGradient(coords.x1, coords.y1, coords.x2, coords.y2); + } else if (this.type === "radial") { + gradient = ctx.createRadialGradient(coords.x1, coords.y1, coords.r1, coords.x2, coords.y2, coords.r2); + } + for (var i = 0, len = this.colorStops.length; i < len; i++) { + var color = this.colorStops[i].color, opacity = this.colorStops[i].opacity, offset = this.colorStops[i].offset; + if (typeof opacity !== "undefined") { + color = new fabric.Color(color).setAlpha(opacity).toRgba(); + } + gradient.addColorStop(parseFloat(offset), color); + } + return gradient; + } + }); + fabric.util.object.extend(fabric.Gradient, { + fromElement: function(el, instance) { + var colorStopEls = el.getElementsByTagName("stop"), type = el.nodeName === "linearGradient" ? "linear" : "radial", gradientUnits = el.getAttribute("gradientUnits") || "objectBoundingBox", gradientTransform = el.getAttribute("gradientTransform"), colorStops = [], coords = {}, ellipseMatrix; + if (type === "linear") { + coords = getLinearCoords(el); + } else if (type === "radial") { + coords = getRadialCoords(el); + } + for (var i = colorStopEls.length; i--; ) { + colorStops.push(getColorStop(colorStopEls[i])); + } + ellipseMatrix = _convertPercentUnitsToValues(instance, coords, gradientUnits); + var gradient = new fabric.Gradient({ + type: type, + coords: coords, + colorStops: colorStops, + offsetX: -instance.left, + offsetY: -instance.top + }); + if (gradientTransform || ellipseMatrix !== "") { + gradient.gradientTransform = fabric.parseTransformAttribute((gradientTransform || "") + ellipseMatrix); + } + return gradient; + }, + forObject: function(obj, options) { + options || (options = {}); + _convertPercentUnitsToValues(obj, options.coords, "userSpaceOnUse"); + return new fabric.Gradient(options); + } + }); + function _convertPercentUnitsToValues(object, options, gradientUnits) { + var propValue, addFactor = 0, multFactor = 1, ellipseMatrix = ""; + for (var prop in options) { + propValue = parseFloat(options[prop], 10); + if (typeof options[prop] === "string" && /^\d+%$/.test(options[prop])) { + multFactor = .01; + } else { + multFactor = 1; + } + if (prop === "x1" || prop === "x2" || prop === "r2") { + multFactor *= gradientUnits === "objectBoundingBox" ? object.width : 1; + addFactor = gradientUnits === "objectBoundingBox" ? object.left || 0 : 0; + } else if (prop === "y1" || prop === "y2") { + multFactor *= gradientUnits === "objectBoundingBox" ? object.height : 1; + addFactor = gradientUnits === "objectBoundingBox" ? object.top || 0 : 0; + } + options[prop] = propValue * multFactor + addFactor; + } + if (object.type === "ellipse" && options.r2 !== null && gradientUnits === "objectBoundingBox" && object.rx !== object.ry) { + var scaleFactor = object.ry / object.rx; + ellipseMatrix = " scale(1, " + scaleFactor + ")"; + if (options.y1) { + options.y1 /= scaleFactor; + } + if (options.y2) { + options.y2 /= scaleFactor; + } + } + return ellipseMatrix; + } +})(); + +fabric.Pattern = fabric.util.createClass({ + repeat: "repeat", + offsetX: 0, + offsetY: 0, + initialize: function(options) { + options || (options = {}); + this.id = fabric.Object.__uid++; + if (options.source) { + if (typeof options.source === "string") { + if (typeof fabric.util.getFunctionBody(options.source) !== "undefined") { + this.source = new Function(fabric.util.getFunctionBody(options.source)); + } else { + var _this = this; + this.source = fabric.util.createImage(); + fabric.util.loadImage(options.source, function(img) { + _this.source = img; + }); + } + } else { + this.source = options.source; + } + } + if (options.repeat) { + this.repeat = options.repeat; + } + if (options.offsetX) { + this.offsetX = options.offsetX; + } + if (options.offsetY) { + this.offsetY = options.offsetY; + } + }, + toObject: function() { + var source; + if (typeof this.source === "function") { + source = String(this.source); + } else if (typeof this.source.src === "string") { + source = this.source.src; + } else if (typeof this.source === "object" && this.source.toDataURL) { + source = this.source.toDataURL(); + } + return { + source: source, + repeat: this.repeat, + offsetX: this.offsetX, + offsetY: this.offsetY + }; + }, + toSVG: function(object) { + var patternSource = typeof this.source === "function" ? this.source() : this.source, patternWidth = patternSource.width / object.getWidth(), patternHeight = patternSource.height / object.getHeight(), patternOffsetX = this.offsetX / object.getWidth(), patternOffsetY = this.offsetY / object.getHeight(), patternImgSrc = ""; + if (this.repeat === "repeat-x" || this.repeat === "no-repeat") { + patternHeight = 1; + } + if (this.repeat === "repeat-y" || this.repeat === "no-repeat") { + patternWidth = 1; + } + if (patternSource.src) { + patternImgSrc = patternSource.src; + } else if (patternSource.toDataURL) { + patternImgSrc = patternSource.toDataURL(); + } + return '\n' + '\n' + "\n"; + }, + toLive: function(ctx) { + var source = typeof this.source === "function" ? this.source() : this.source; + if (!source) { + return ""; + } + if (typeof source.src !== "undefined") { + if (!source.complete) { + return ""; + } + if (source.naturalWidth === 0 || source.naturalHeight === 0) { + return ""; + } + } + return ctx.createPattern(source, this.repeat); + } +}); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), toFixed = fabric.util.toFixed; + if (fabric.Shadow) { + fabric.warn("fabric.Shadow is already defined."); + return; + } + fabric.Shadow = fabric.util.createClass({ + color: "rgb(0,0,0)", + blur: 0, + offsetX: 0, + offsetY: 0, + affectStroke: false, + includeDefaultValues: true, + initialize: function(options) { + if (typeof options === "string") { + options = this._parseShadow(options); + } + for (var prop in options) { + this[prop] = options[prop]; + } + this.id = fabric.Object.__uid++; + }, + _parseShadow: function(shadow) { + var shadowStr = shadow.trim(), offsetsAndBlur = fabric.Shadow.reOffsetsAndBlur.exec(shadowStr) || [], color = shadowStr.replace(fabric.Shadow.reOffsetsAndBlur, "") || "rgb(0,0,0)"; + return { + color: color.trim(), + offsetX: parseInt(offsetsAndBlur[1], 10) || 0, + offsetY: parseInt(offsetsAndBlur[2], 10) || 0, + blur: parseInt(offsetsAndBlur[3], 10) || 0 + }; + }, + toString: function() { + return [ this.offsetX, this.offsetY, this.blur, this.color ].join("px "); + }, + toSVG: function(object) { + var fBoxX = 40, fBoxY = 40, NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, offset = fabric.util.rotateVector({ + x: this.offsetX, + y: this.offsetY + }, fabric.util.degreesToRadians(-object.angle)), BLUR_BOX = 20; + if (object.width && object.height) { + fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX; + fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX; + } + if (object.flipX) { + offset.x *= -1; + } + if (object.flipY) { + offset.y *= -1; + } + return '\n" + ' \n' + ' \n' + ' \n' + ' \n' + " \n" + " \n" + ' \n' + " \n" + "\n"; + }, + toObject: function() { + if (this.includeDefaultValues) { + return { + color: this.color, + blur: this.blur, + offsetX: this.offsetX, + offsetY: this.offsetY, + affectStroke: this.affectStroke + }; + } + var obj = {}, proto = fabric.Shadow.prototype; + [ "color", "blur", "offsetX", "offsetY", "affectStroke" ].forEach(function(prop) { + if (this[prop] !== proto[prop]) { + obj[prop] = this[prop]; + } + }, this); + return obj; + } + }); + fabric.Shadow.reOffsetsAndBlur = /(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/; +})(typeof exports !== "undefined" ? exports : this); + +(function() { + "use strict"; + if (fabric.StaticCanvas) { + fabric.warn("fabric.StaticCanvas is already defined."); + return; + } + var extend = fabric.util.object.extend, getElementOffset = fabric.util.getElementOffset, removeFromArray = fabric.util.removeFromArray, toFixed = fabric.util.toFixed, CANVAS_INIT_ERROR = new Error("Could not initialize `canvas` element"); + fabric.StaticCanvas = fabric.util.createClass({ + initialize: function(el, options) { + options || (options = {}); + this._initStatic(el, options); + }, + backgroundColor: "", + backgroundImage: null, + overlayColor: "", + overlayImage: null, + includeDefaultValues: true, + stateful: true, + renderOnAddRemove: true, + clipTo: null, + controlsAboveOverlay: false, + allowTouchScrolling: false, + imageSmoothingEnabled: true, + preserveObjectStacking: false, + viewportTransform: [ 1, 0, 0, 1, 0, 0 ], + onBeforeScaleRotate: function() {}, + enableRetinaScaling: true, + _initStatic: function(el, options) { + this._objects = []; + this._createLowerCanvas(el); + this._initOptions(options); + this._setImageSmoothing(); + if (!this.interactive) { + this._initRetinaScaling(); + } + if (options.overlayImage) { + this.setOverlayImage(options.overlayImage, this.renderAll.bind(this)); + } + if (options.backgroundImage) { + this.setBackgroundImage(options.backgroundImage, this.renderAll.bind(this)); + } + if (options.backgroundColor) { + this.setBackgroundColor(options.backgroundColor, this.renderAll.bind(this)); + } + if (options.overlayColor) { + this.setOverlayColor(options.overlayColor, this.renderAll.bind(this)); + } + this.calcOffset(); + }, + _isRetinaScaling: function() { + return fabric.devicePixelRatio !== 1 && this.enableRetinaScaling; + }, + _initRetinaScaling: function() { + if (!this._isRetinaScaling()) { + return; + } + this.lowerCanvasEl.setAttribute("width", this.width * fabric.devicePixelRatio); + this.lowerCanvasEl.setAttribute("height", this.height * fabric.devicePixelRatio); + this.contextContainer.scale(fabric.devicePixelRatio, fabric.devicePixelRatio); + }, + calcOffset: function() { + this._offset = getElementOffset(this.lowerCanvasEl); + return this; + }, + setOverlayImage: function(image, callback, options) { + return this.__setBgOverlayImage("overlayImage", image, callback, options); + }, + setBackgroundImage: function(image, callback, options) { + return this.__setBgOverlayImage("backgroundImage", image, callback, options); + }, + setOverlayColor: function(overlayColor, callback) { + return this.__setBgOverlayColor("overlayColor", overlayColor, callback); + }, + setBackgroundColor: function(backgroundColor, callback) { + return this.__setBgOverlayColor("backgroundColor", backgroundColor, callback); + }, + _setImageSmoothing: function() { + var ctx = this.getContext(); + ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled || ctx.webkitImageSmoothingEnabled || ctx.mozImageSmoothingEnabled || ctx.msImageSmoothingEnabled || ctx.oImageSmoothingEnabled; + ctx.imageSmoothingEnabled = this.imageSmoothingEnabled; + }, + __setBgOverlayImage: function(property, image, callback, options) { + if (typeof image === "string") { + fabric.util.loadImage(image, function(img) { + this[property] = new fabric.Image(img, options); + callback && callback(img); + }, this, options && options.crossOrigin); + } else { + options && image.setOptions(options); + this[property] = image; + callback && callback(image); + } + return this; + }, + __setBgOverlayColor: function(property, color, callback) { + if (color && color.source) { + var _this = this; + fabric.util.loadImage(color.source, function(img) { + _this[property] = new fabric.Pattern({ + source: img, + repeat: color.repeat, + offsetX: color.offsetX, + offsetY: color.offsetY + }); + callback && callback(); + }); + } else { + this[property] = color; + callback && callback(); + } + return this; + }, + _createCanvasElement: function() { + var element = fabric.document.createElement("canvas"); + if (!element.style) { + element.style = {}; + } + if (!element) { + throw CANVAS_INIT_ERROR; + } + this._initCanvasElement(element); + return element; + }, + _initCanvasElement: function(element) { + fabric.util.createCanvasElement(element); + if (typeof element.getContext === "undefined") { + throw CANVAS_INIT_ERROR; + } + }, + _initOptions: function(options) { + for (var prop in options) { + this[prop] = options[prop]; + } + this.width = this.width || parseInt(this.lowerCanvasEl.width, 10) || 0; + this.height = this.height || parseInt(this.lowerCanvasEl.height, 10) || 0; + if (!this.lowerCanvasEl.style) { + return; + } + this.lowerCanvasEl.width = this.width; + this.lowerCanvasEl.height = this.height; + this.lowerCanvasEl.style.width = this.width + "px"; + this.lowerCanvasEl.style.height = this.height + "px"; + this.viewportTransform = this.viewportTransform.slice(); + }, + _createLowerCanvas: function(canvasEl) { + this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement(); + this._initCanvasElement(this.lowerCanvasEl); + fabric.util.addClass(this.lowerCanvasEl, "lower-canvas"); + if (this.interactive) { + this._applyCanvasStyle(this.lowerCanvasEl); + } + this.contextContainer = this.lowerCanvasEl.getContext("2d"); + }, + getWidth: function() { + return this.width; + }, + getHeight: function() { + return this.height; + }, + setWidth: function(value, options) { + return this.setDimensions({ + width: value + }, options); + }, + setHeight: function(value, options) { + return this.setDimensions({ + height: value + }, options); + }, + setDimensions: function(dimensions, options) { + var cssValue; + options = options || {}; + for (var prop in dimensions) { + cssValue = dimensions[prop]; + if (!options.cssOnly) { + this._setBackstoreDimension(prop, dimensions[prop]); + cssValue += "px"; + } + if (!options.backstoreOnly) { + this._setCssDimension(prop, cssValue); + } + } + this._initRetinaScaling(); + this._setImageSmoothing(); + this.calcOffset(); + if (!options.cssOnly) { + this.renderAll(); + } + return this; + }, + _setBackstoreDimension: function(prop, value) { + this.lowerCanvasEl[prop] = value; + if (this.upperCanvasEl) { + this.upperCanvasEl[prop] = value; + } + if (this.cacheCanvasEl) { + this.cacheCanvasEl[prop] = value; + } + this[prop] = value; + return this; + }, + _setCssDimension: function(prop, value) { + this.lowerCanvasEl.style[prop] = value; + if (this.upperCanvasEl) { + this.upperCanvasEl.style[prop] = value; + } + if (this.wrapperEl) { + this.wrapperEl.style[prop] = value; + } + return this; + }, + getZoom: function() { + return Math.sqrt(this.viewportTransform[0] * this.viewportTransform[3]); + }, + setViewportTransform: function(vpt) { + var activeGroup = this.getActiveGroup(); + this.viewportTransform = vpt; + this.renderAll(); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i].setCoords(); + } + if (activeGroup) { + activeGroup.setCoords(); + } + return this; + }, + zoomToPoint: function(point, value) { + var before = point; + point = fabric.util.transformPoint(point, fabric.util.invertTransform(this.viewportTransform)); + this.viewportTransform[0] = value; + this.viewportTransform[3] = value; + var after = fabric.util.transformPoint(point, this.viewportTransform); + this.viewportTransform[4] += before.x - after.x; + this.viewportTransform[5] += before.y - after.y; + this.renderAll(); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i].setCoords(); + } + return this; + }, + setZoom: function(value) { + this.zoomToPoint(new fabric.Point(0, 0), value); + return this; + }, + absolutePan: function(point) { + this.viewportTransform[4] = -point.x; + this.viewportTransform[5] = -point.y; + this.renderAll(); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i].setCoords(); + } + return this; + }, + relativePan: function(point) { + return this.absolutePan(new fabric.Point(-point.x - this.viewportTransform[4], -point.y - this.viewportTransform[5])); + }, + getElement: function() { + return this.lowerCanvasEl; + }, + getActiveObject: function() { + return null; + }, + getActiveGroup: function() { + return null; + }, + _onObjectAdded: function(obj) { + this.stateful && obj.setupState(); + obj._set("canvas", this); + obj.setCoords(); + this.fire("object:added", { + target: obj + }); + obj.fire("added"); + }, + _onObjectRemoved: function(obj) { + if (this.getActiveObject() === obj) { + this.fire("before:selection:cleared", { + target: obj + }); + this._discardActiveObject(); + this.fire("selection:cleared"); + } + this.fire("object:removed", { + target: obj + }); + obj.fire("removed"); + }, + clearContext: function(ctx) { + ctx.clearRect(0, 0, this.width, this.height); + return this; + }, + getContext: function() { + return this.contextContainer; + }, + clear: function() { + this._objects.length = 0; + if (this.discardActiveGroup) { + this.discardActiveGroup(); + } + if (this.discardActiveObject) { + this.discardActiveObject(); + } + this.clearContext(this.contextContainer); + if (this.contextTop) { + this.clearContext(this.contextTop); + } + this.fire("canvas:cleared"); + this.renderAll(); + return this; + }, + _chooseObjectsToRender: function() { + var activeGroup = this.getActiveGroup(), object, objsToRender = [], activeGroupObjects = []; + if (activeGroup && !this.preserveObjectStacking) { + for (var i = 0, length = this._objects.length; i < length; i++) { + object = this._objects[i]; + if (!activeGroup.contains(object)) { + objsToRender.push(object); + } else { + activeGroupObjects.push(object); + } + } + activeGroup._set("_objects", activeGroupObjects); + } else { + objsToRender = this._objects; + } + return objsToRender; + }, + renderAll: function() { + var canvasToDrawOn = this.contextContainer, objsToRender; + if (this.contextTop && this.selection && !this._groupSelector && !this.isDrawingMode) { + this.clearContext(this.contextTop); + } + this.clearContext(canvasToDrawOn); + this.fire("before:render"); + if (this.clipTo) { + fabric.util.clipContext(this, canvasToDrawOn); + } + this._renderBackground(canvasToDrawOn); + canvasToDrawOn.save(); + objsToRender = this._chooseObjectsToRender(); + canvasToDrawOn.transform.apply(canvasToDrawOn, this.viewportTransform); + this._renderObjects(canvasToDrawOn, objsToRender); + this.preserveObjectStacking || this._renderObjects(canvasToDrawOn, [ this.getActiveGroup() ]); + canvasToDrawOn.restore(); + if (!this.controlsAboveOverlay && this.interactive) { + this.drawControls(canvasToDrawOn); + } + if (this.clipTo) { + canvasToDrawOn.restore(); + } + this._renderOverlay(canvasToDrawOn); + if (this.controlsAboveOverlay && this.interactive) { + this.drawControls(canvasToDrawOn); + } + this.fire("after:render"); + return this; + }, + _renderObjects: function(ctx, objects) { + for (var i = 0, length = objects.length; i < length; ++i) { + objects[i] && objects[i].render(ctx); + } + }, + _renderBackgroundOrOverlay: function(ctx, property) { + var object = this[property + "Color"]; + if (object) { + ctx.fillStyle = object.toLive ? object.toLive(ctx) : object; + ctx.fillRect(object.offsetX || 0, object.offsetY || 0, this.width, this.height); + } + object = this[property + "Image"]; + if (object) { + object.render(ctx); + } + }, + _renderBackground: function(ctx) { + this._renderBackgroundOrOverlay(ctx, "background"); + }, + _renderOverlay: function(ctx) { + this._renderBackgroundOrOverlay(ctx, "overlay"); + }, + renderTop: function() { + var ctx = this.contextTop || this.contextContainer; + this.clearContext(ctx); + if (this.selection && this._groupSelector) { + this._drawSelection(); + } + this.fire("after:render"); + return this; + }, + getCenter: function() { + return { + top: this.getHeight() / 2, + left: this.getWidth() / 2 + }; + }, + centerObjectH: function(object) { + this._centerObject(object, new fabric.Point(this.getCenter().left, object.getCenterPoint().y)); + this.renderAll(); + return this; + }, + centerObjectV: function(object) { + this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenter().top)); + this.renderAll(); + return this; + }, + centerObject: function(object) { + var center = this.getCenter(); + this._centerObject(object, new fabric.Point(center.left, center.top)); + this.renderAll(); + return this; + }, + _centerObject: function(object, center) { + object.setPositionByOrigin(center, "center", "center"); + return this; + }, + toDatalessJSON: function(propertiesToInclude) { + return this.toDatalessObject(propertiesToInclude); + }, + toObject: function(propertiesToInclude) { + return this._toObjectMethod("toObject", propertiesToInclude); + }, + toDatalessObject: function(propertiesToInclude) { + return this._toObjectMethod("toDatalessObject", propertiesToInclude); + }, + _toObjectMethod: function(methodName, propertiesToInclude) { + var data = { + objects: this._toObjects(methodName, propertiesToInclude) + }; + extend(data, this.__serializeBgOverlay()); + fabric.util.populateWithProperties(this, data, propertiesToInclude); + return data; + }, + _toObjects: function(methodName, propertiesToInclude) { + return this.getObjects().map(function(instance) { + return this._toObject(instance, methodName, propertiesToInclude); + }, this); + }, + _toObject: function(instance, methodName, propertiesToInclude) { + var originalValue; + if (!this.includeDefaultValues) { + originalValue = instance.includeDefaultValues; + instance.includeDefaultValues = false; + } + var originalProperties = this._realizeGroupTransformOnObject(instance), object = instance[methodName](propertiesToInclude); + if (!this.includeDefaultValues) { + instance.includeDefaultValues = originalValue; + } + this._unwindGroupTransformOnObject(instance, originalProperties); + return object; + }, + _realizeGroupTransformOnObject: function(instance) { + var layoutProps = [ "angle", "flipX", "flipY", "height", "left", "scaleX", "scaleY", "top", "width" ]; + if (instance.group && instance.group === this.getActiveGroup()) { + var originalValues = {}; + layoutProps.forEach(function(prop) { + originalValues[prop] = instance[prop]; + }); + this.getActiveGroup().realizeTransform(instance); + return originalValues; + } else { + return null; + } + }, + _unwindGroupTransformOnObject: function(instance, originalValues) { + if (originalValues) { + instance.set(originalValues); + } + }, + __serializeBgOverlay: function() { + var data = { + background: this.backgroundColor && this.backgroundColor.toObject ? this.backgroundColor.toObject() : this.backgroundColor + }; + if (this.overlayColor) { + data.overlay = this.overlayColor.toObject ? this.overlayColor.toObject() : this.overlayColor; + } + if (this.backgroundImage) { + data.backgroundImage = this.backgroundImage.toObject(); + } + if (this.overlayImage) { + data.overlayImage = this.overlayImage.toObject(); + } + return data; + }, + svgViewportTransformation: true, + toSVG: function(options, reviver) { + options || (options = {}); + var markup = []; + this._setSVGPreamble(markup, options); + this._setSVGHeader(markup, options); + this._setSVGBgOverlayColor(markup, "backgroundColor"); + this._setSVGBgOverlayImage(markup, "backgroundImage"); + this._setSVGObjects(markup, reviver); + this._setSVGBgOverlayColor(markup, "overlayColor"); + this._setSVGBgOverlayImage(markup, "overlayImage"); + markup.push(""); + return markup.join(""); + }, + _setSVGPreamble: function(markup, options) { + if (options.suppressPreamble) { + return; + } + markup.push('\n', '\n'); + }, + _setSVGHeader: function(markup, options) { + var width = options.width || this.width, height = options.height || this.height, vpt, viewBox = 'viewBox="0 0 ' + this.width + " " + this.height + '" ', NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; + if (options.viewBox) { + viewBox = 'viewBox="' + options.viewBox.x + " " + options.viewBox.y + " " + options.viewBox.width + " " + options.viewBox.height + '" '; + } else { + if (this.svgViewportTransformation) { + vpt = this.viewportTransform; + viewBox = 'viewBox="' + toFixed(-vpt[4] / vpt[0], NUM_FRACTION_DIGITS) + " " + toFixed(-vpt[5] / vpt[3], NUM_FRACTION_DIGITS) + " " + toFixed(this.width / vpt[0], NUM_FRACTION_DIGITS) + " " + toFixed(this.height / vpt[3], NUM_FRACTION_DIGITS) + '" '; + } + } + markup.push("\n', "Created with Fabric.js ", fabric.version, "\n", "", fabric.createSVGFontFacesMarkup(this.getObjects()), fabric.createSVGRefElementsMarkup(this), "\n"); + }, + _setSVGObjects: function(markup, reviver) { + for (var i = 0, objects = this.getObjects(), len = objects.length; i < len; i++) { + var instance = objects[i], originalProperties = this._realizeGroupTransformOnObject(instance); + markup.push(instance.toSVG(reviver)); + this._unwindGroupTransformOnObject(instance, originalProperties); + } + }, + _setSVGBgOverlayImage: function(markup, property) { + if (this[property] && this[property].toSVG) { + markup.push(this[property].toSVG()); + } + }, + _setSVGBgOverlayColor: function(markup, property) { + if (this[property] && this[property].source) { + markup.push('\n"); + } else if (this[property] && property === "overlayColor") { + markup.push('\n"); + } + }, + sendToBack: function(object) { + removeFromArray(this._objects, object); + this._objects.unshift(object); + return this.renderAll && this.renderAll(); + }, + bringToFront: function(object) { + removeFromArray(this._objects, object); + this._objects.push(object); + return this.renderAll && this.renderAll(); + }, + sendBackwards: function(object, intersecting) { + var idx = this._objects.indexOf(object); + if (idx !== 0) { + var newIdx = this._findNewLowerIndex(object, idx, intersecting); + removeFromArray(this._objects, object); + this._objects.splice(newIdx, 0, object); + this.renderAll && this.renderAll(); + } + return this; + }, + _findNewLowerIndex: function(object, idx, intersecting) { + var newIdx; + if (intersecting) { + newIdx = idx; + for (var i = idx - 1; i >= 0; --i) { + var isIntersecting = object.intersectsWithObject(this._objects[i]) || object.isContainedWithinObject(this._objects[i]) || this._objects[i].isContainedWithinObject(object); + if (isIntersecting) { + newIdx = i; + break; + } + } + } else { + newIdx = idx - 1; + } + return newIdx; + }, + bringForward: function(object, intersecting) { + var idx = this._objects.indexOf(object); + if (idx !== this._objects.length - 1) { + var newIdx = this._findNewUpperIndex(object, idx, intersecting); + removeFromArray(this._objects, object); + this._objects.splice(newIdx, 0, object); + this.renderAll && this.renderAll(); + } + return this; + }, + _findNewUpperIndex: function(object, idx, intersecting) { + var newIdx; + if (intersecting) { + newIdx = idx; + for (var i = idx + 1; i < this._objects.length; ++i) { + var isIntersecting = object.intersectsWithObject(this._objects[i]) || object.isContainedWithinObject(this._objects[i]) || this._objects[i].isContainedWithinObject(object); + if (isIntersecting) { + newIdx = i; + break; + } + } + } else { + newIdx = idx + 1; + } + return newIdx; + }, + moveTo: function(object, index) { + removeFromArray(this._objects, object); + this._objects.splice(index, 0, object); + return this.renderAll && this.renderAll(); + }, + dispose: function() { + this.clear(); + return this; + }, + toString: function() { + return "#"; + } + }); + extend(fabric.StaticCanvas.prototype, fabric.Observable); + extend(fabric.StaticCanvas.prototype, fabric.Collection); + extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter); + extend(fabric.StaticCanvas, { + EMPTY_JSON: '{"objects": [], "background": "white"}', + supports: function(methodName) { + var el = fabric.util.createCanvasElement(); + if (!el || !el.getContext) { + return null; + } + var ctx = el.getContext("2d"); + if (!ctx) { + return null; + } + switch (methodName) { + case "getImageData": + return typeof ctx.getImageData !== "undefined"; + + case "setLineDash": + return typeof ctx.setLineDash !== "undefined"; + + case "toDataURL": + return typeof el.toDataURL !== "undefined"; + + case "toDataURLWithQuality": + try { + el.toDataURL("image/jpeg", 0); + return true; + } catch (e) {} + return false; + + default: + return null; + } + } + }); + fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject; +})(); + +fabric.BaseBrush = fabric.util.createClass({ + color: "rgb(0, 0, 0)", + width: 1, + shadow: null, + strokeLineCap: "round", + strokeLineJoin: "round", + strokeDashArray: null, + setShadow: function(options) { + this.shadow = new fabric.Shadow(options); + return this; + }, + _setBrushStyles: function() { + var ctx = this.canvas.contextTop; + ctx.strokeStyle = this.color; + ctx.lineWidth = this.width; + ctx.lineCap = this.strokeLineCap; + ctx.lineJoin = this.strokeLineJoin; + if (this.strokeDashArray && fabric.StaticCanvas.supports("setLineDash")) { + ctx.setLineDash(this.strokeDashArray); + } + }, + _setShadow: function() { + if (!this.shadow) { + return; + } + var ctx = this.canvas.contextTop; + ctx.shadowColor = this.shadow.color; + ctx.shadowBlur = this.shadow.blur; + ctx.shadowOffsetX = this.shadow.offsetX; + ctx.shadowOffsetY = this.shadow.offsetY; + }, + _resetShadow: function() { + var ctx = this.canvas.contextTop; + ctx.shadowColor = ""; + ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; + } +}); + +(function() { + fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush, { + initialize: function(canvas) { + this.canvas = canvas; + this._points = []; + }, + onMouseDown: function(pointer) { + this._prepareForDrawing(pointer); + this._captureDrawingPath(pointer); + this._render(); + }, + onMouseMove: function(pointer) { + this._captureDrawingPath(pointer); + this.canvas.clearContext(this.canvas.contextTop); + this._render(); + }, + onMouseUp: function() { + this._finalizeAndAddPath(); + }, + _prepareForDrawing: function(pointer) { + var p = new fabric.Point(pointer.x, pointer.y); + this._reset(); + this._addPoint(p); + this.canvas.contextTop.moveTo(p.x, p.y); + }, + _addPoint: function(point) { + this._points.push(point); + }, + _reset: function() { + this._points.length = 0; + this._setBrushStyles(); + this._setShadow(); + }, + _captureDrawingPath: function(pointer) { + var pointerPoint = new fabric.Point(pointer.x, pointer.y); + this._addPoint(pointerPoint); + }, + _render: function() { + var ctx = this.canvas.contextTop, v = this.canvas.viewportTransform, p1 = this._points[0], p2 = this._points[1]; + ctx.save(); + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + ctx.beginPath(); + if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) { + p1.x -= .5; + p2.x += .5; + } + ctx.moveTo(p1.x, p1.y); + for (var i = 1, len = this._points.length; i < len; i++) { + var midPoint = p1.midPointFrom(p2); + ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y); + p1 = this._points[i]; + p2 = this._points[i + 1]; + } + ctx.lineTo(p1.x, p1.y); + ctx.stroke(); + ctx.restore(); + }, + convertPointsToSVGPath: function(points) { + var path = [], p1 = new fabric.Point(points[0].x, points[0].y), p2 = new fabric.Point(points[1].x, points[1].y); + path.push("M ", points[0].x, " ", points[0].y, " "); + for (var i = 1, len = points.length; i < len; i++) { + var midPoint = p1.midPointFrom(p2); + path.push("Q ", p1.x, " ", p1.y, " ", midPoint.x, " ", midPoint.y, " "); + p1 = new fabric.Point(points[i].x, points[i].y); + if (i + 1 < points.length) { + p2 = new fabric.Point(points[i + 1].x, points[i + 1].y); + } + } + path.push("L ", p1.x, " ", p1.y, " "); + return path; + }, + createPath: function(pathData) { + var path = new fabric.Path(pathData, { + fill: null, + stroke: this.color, + strokeWidth: this.width, + strokeLineCap: this.strokeLineCap, + strokeLineJoin: this.strokeLineJoin, + strokeDashArray: this.strokeDashArray, + originX: "center", + originY: "center" + }); + if (this.shadow) { + this.shadow.affectStroke = true; + path.setShadow(this.shadow); + } + return path; + }, + _finalizeAndAddPath: function() { + var ctx = this.canvas.contextTop; + ctx.closePath(); + var pathData = this.convertPointsToSVGPath(this._points).join(""); + if (pathData === "M 0 0 Q 0 0 0 0 L 0 0") { + this.canvas.renderAll(); + return; + } + var path = this.createPath(pathData); + this.canvas.add(path); + path.setCoords(); + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderAll(); + this.canvas.fire("path:created", { + path: path + }); + } + }); +})(); + +fabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, { + width: 10, + initialize: function(canvas) { + this.canvas = canvas; + this.points = []; + }, + drawDot: function(pointer) { + var point = this.addPoint(pointer), ctx = this.canvas.contextTop, v = this.canvas.viewportTransform; + ctx.save(); + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + ctx.fillStyle = point.fill; + ctx.beginPath(); + ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false); + ctx.closePath(); + ctx.fill(); + ctx.restore(); + }, + onMouseDown: function(pointer) { + this.points.length = 0; + this.canvas.clearContext(this.canvas.contextTop); + this._setShadow(); + this.drawDot(pointer); + }, + onMouseMove: function(pointer) { + this.drawDot(pointer); + }, + onMouseUp: function() { + var originalRenderOnAddRemove = this.canvas.renderOnAddRemove; + this.canvas.renderOnAddRemove = false; + var circles = []; + for (var i = 0, len = this.points.length; i < len; i++) { + var point = this.points[i], circle = new fabric.Circle({ + radius: point.radius, + left: point.x, + top: point.y, + originX: "center", + originY: "center", + fill: point.fill + }); + this.shadow && circle.setShadow(this.shadow); + circles.push(circle); + } + var group = new fabric.Group(circles, { + originX: "center", + originY: "center" + }); + group.canvas = this.canvas; + this.canvas.add(group); + this.canvas.fire("path:created", { + path: group + }); + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderOnAddRemove = originalRenderOnAddRemove; + this.canvas.renderAll(); + }, + addPoint: function(pointer) { + var pointerPoint = new fabric.Point(pointer.x, pointer.y), circleRadius = fabric.util.getRandomInt(Math.max(0, this.width - 20), this.width + 20) / 2, circleColor = new fabric.Color(this.color).setAlpha(fabric.util.getRandomInt(0, 100) / 100).toRgba(); + pointerPoint.radius = circleRadius; + pointerPoint.fill = circleColor; + this.points.push(pointerPoint); + return pointerPoint; + } +}); + +fabric.SprayBrush = fabric.util.createClass(fabric.BaseBrush, { + width: 10, + density: 20, + dotWidth: 1, + dotWidthVariance: 1, + randomOpacity: false, + optimizeOverlapping: true, + initialize: function(canvas) { + this.canvas = canvas; + this.sprayChunks = []; + }, + onMouseDown: function(pointer) { + this.sprayChunks.length = 0; + this.canvas.clearContext(this.canvas.contextTop); + this._setShadow(); + this.addSprayChunk(pointer); + this.render(); + }, + onMouseMove: function(pointer) { + this.addSprayChunk(pointer); + this.render(); + }, + onMouseUp: function() { + var originalRenderOnAddRemove = this.canvas.renderOnAddRemove; + this.canvas.renderOnAddRemove = false; + var rects = []; + for (var i = 0, ilen = this.sprayChunks.length; i < ilen; i++) { + var sprayChunk = this.sprayChunks[i]; + for (var j = 0, jlen = sprayChunk.length; j < jlen; j++) { + var rect = new fabric.Rect({ + width: sprayChunk[j].width, + height: sprayChunk[j].width, + left: sprayChunk[j].x + 1, + top: sprayChunk[j].y + 1, + originX: "center", + originY: "center", + fill: this.color + }); + this.shadow && rect.setShadow(this.shadow); + rects.push(rect); + } + } + if (this.optimizeOverlapping) { + rects = this._getOptimizedRects(rects); + } + var group = new fabric.Group(rects, { + originX: "center", + originY: "center" + }); + group.canvas = this.canvas; + this.canvas.add(group); + this.canvas.fire("path:created", { + path: group + }); + this.canvas.clearContext(this.canvas.contextTop); + this._resetShadow(); + this.canvas.renderOnAddRemove = originalRenderOnAddRemove; + this.canvas.renderAll(); + }, + _getOptimizedRects: function(rects) { + var uniqueRects = {}, key; + for (var i = 0, len = rects.length; i < len; i++) { + key = rects[i].left + "" + rects[i].top; + if (!uniqueRects[key]) { + uniqueRects[key] = rects[i]; + } + } + var uniqueRectsArray = []; + for (key in uniqueRects) { + uniqueRectsArray.push(uniqueRects[key]); + } + return uniqueRectsArray; + }, + render: function() { + var ctx = this.canvas.contextTop; + ctx.fillStyle = this.color; + var v = this.canvas.viewportTransform; + ctx.save(); + ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); + for (var i = 0, len = this.sprayChunkPoints.length; i < len; i++) { + var point = this.sprayChunkPoints[i]; + if (typeof point.opacity !== "undefined") { + ctx.globalAlpha = point.opacity; + } + ctx.fillRect(point.x, point.y, point.width, point.width); + } + ctx.restore(); + }, + addSprayChunk: function(pointer) { + this.sprayChunkPoints = []; + var x, y, width, radius = this.width / 2; + for (var i = 0; i < this.density; i++) { + x = fabric.util.getRandomInt(pointer.x - radius, pointer.x + radius); + y = fabric.util.getRandomInt(pointer.y - radius, pointer.y + radius); + if (this.dotWidthVariance) { + width = fabric.util.getRandomInt(Math.max(1, this.dotWidth - this.dotWidthVariance), this.dotWidth + this.dotWidthVariance); + } else { + width = this.dotWidth; + } + var point = new fabric.Point(x, y); + point.width = width; + if (this.randomOpacity) { + point.opacity = fabric.util.getRandomInt(0, 100) / 100; + } + this.sprayChunkPoints.push(point); + } + this.sprayChunks.push(this.sprayChunkPoints); + } +}); + +fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, { + getPatternSrc: function() { + var dotWidth = 20, dotDistance = 5, patternCanvas = fabric.document.createElement("canvas"), patternCtx = patternCanvas.getContext("2d"); + patternCanvas.width = patternCanvas.height = dotWidth + dotDistance; + patternCtx.fillStyle = this.color; + patternCtx.beginPath(); + patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false); + patternCtx.closePath(); + patternCtx.fill(); + return patternCanvas; + }, + getPatternSrcFunction: function() { + return String(this.getPatternSrc).replace("this.color", '"' + this.color + '"'); + }, + getPattern: function() { + return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), "repeat"); + }, + _setBrushStyles: function() { + this.callSuper("_setBrushStyles"); + this.canvas.contextTop.strokeStyle = this.getPattern(); + }, + createPath: function(pathData) { + var path = this.callSuper("createPath", pathData); + path.stroke = new fabric.Pattern({ + source: this.source || this.getPatternSrcFunction() + }); + return path; + } +}); + +(function() { + var getPointer = fabric.util.getPointer, degreesToRadians = fabric.util.degreesToRadians, radiansToDegrees = fabric.util.radiansToDegrees, atan2 = Math.atan2, abs = Math.abs, STROKE_OFFSET = .5; + fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, { + initialize: function(el, options) { + options || (options = {}); + this._initStatic(el, options); + this._initInteractive(); + this._createCacheCanvas(); + }, + uniScaleTransform: false, + centeredScaling: false, + centeredRotation: false, + interactive: true, + selection: true, + selectionColor: "rgba(100, 100, 255, 0.3)", + selectionDashArray: [], + selectionBorderColor: "rgba(255, 255, 255, 0.3)", + selectionLineWidth: 1, + hoverCursor: "move", + moveCursor: "move", + defaultCursor: "default", + freeDrawingCursor: "crosshair", + rotationCursor: "crosshair", + containerClass: "canvas-container", + perPixelTargetFind: false, + targetFindTolerance: 0, + skipTargetFind: false, + isDrawingMode: false, + _initInteractive: function() { + this._currentTransform = null; + this._groupSelector = null; + this._initWrapperElement(); + this._createUpperCanvas(); + this._initEventListeners(); + this._initRetinaScaling(); + this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this); + this.calcOffset(); + }, + _resetCurrentTransform: function() { + var t = this._currentTransform; + t.target.set({ + scaleX: t.original.scaleX, + scaleY: t.original.scaleY, + skewX: t.original.skewX, + skewY: t.original.skewY, + left: t.original.left, + top: t.original.top + }); + if (this._shouldCenterTransform(t.target)) { + if (t.action === "rotate") { + this._setOriginToCenter(t.target); + } else { + if (t.originX !== "center") { + if (t.originX === "right") { + t.mouseXSign = -1; + } else { + t.mouseXSign = 1; + } + } + if (t.originY !== "center") { + if (t.originY === "bottom") { + t.mouseYSign = -1; + } else { + t.mouseYSign = 1; + } + } + t.originX = "center"; + t.originY = "center"; + } + } else { + t.originX = t.original.originX; + t.originY = t.original.originY; + } + }, + containsPoint: function(e, target) { + var pointer = this.getPointer(e, true), xy = this._normalizePointer(target, pointer); + return target.containsPoint(xy) || target._findTargetCorner(pointer); + }, + _normalizePointer: function(object, pointer) { + var activeGroup = this.getActiveGroup(), isObjectInGroup = activeGroup && object.type !== "group" && activeGroup.contains(object), lt, m; + if (isObjectInGroup) { + m = fabric.util.multiplyTransformMatrices(this.viewportTransform, activeGroup.calcTransformMatrix()); + m = fabric.util.invertTransform(m); + pointer = fabric.util.transformPoint(pointer, m, false); + lt = fabric.util.transformPoint(activeGroup.getCenterPoint(), m, false); + pointer.x -= lt.x; + pointer.y -= lt.y; + } + return { + x: pointer.x, + y: pointer.y + }; + }, + isTargetTransparent: function(target, x, y) { + var hasBorders = target.hasBorders, transparentCorners = target.transparentCorners; + target.hasBorders = target.transparentCorners = false; + target.render(this.contextCache); + target._renderControls(this.contextCache); + target.hasBorders = hasBorders; + target.transparentCorners = transparentCorners; + var isTransparent = fabric.util.isTransparent(this.contextCache, x, y, this.targetFindTolerance); + this.clearContext(this.contextCache); + return isTransparent; + }, + _shouldClearSelection: function(e, target) { + var activeGroup = this.getActiveGroup(), activeObject = this.getActiveObject(); + return !target || target && activeGroup && !activeGroup.contains(target) && activeGroup !== target && !e.shiftKey || target && !target.evented || target && !target.selectable && activeObject && activeObject !== target; + }, + _shouldCenterTransform: function(target) { + if (!target) { + return; + } + var t = this._currentTransform, centerTransform; + if (t.action === "scale" || t.action === "scaleX" || t.action === "scaleY") { + centerTransform = this.centeredScaling || target.centeredScaling; + } else if (t.action === "rotate") { + centerTransform = this.centeredRotation || target.centeredRotation; + } + return centerTransform ? !t.altKey : t.altKey; + }, + _getOriginFromCorner: function(target, corner) { + var origin = { + x: target.originX, + y: target.originY + }; + if (corner === "ml" || corner === "tl" || corner === "bl") { + origin.x = "right"; + } else if (corner === "mr" || corner === "tr" || corner === "br") { + origin.x = "left"; + } + if (corner === "tl" || corner === "mt" || corner === "tr") { + origin.y = "bottom"; + } else if (corner === "bl" || corner === "mb" || corner === "br") { + origin.y = "top"; + } + return origin; + }, + _getActionFromCorner: function(target, corner, e) { + if (!corner) { + return "drag"; + } + switch (corner) { + case "mtr": + return "rotate"; + + case "ml": + case "mr": + return e.shiftKey ? "skewY" : "scaleX"; + + case "mt": + case "mb": + return e.shiftKey ? "skewX" : "scaleY"; + + default: + return "scale"; + } + }, + _setupCurrentTransform: function(e, target) { + if (!target) { + return; + } + var pointer = this.getPointer(e), corner = target._findTargetCorner(this.getPointer(e, true)), action = this._getActionFromCorner(target, corner, e), origin = this._getOriginFromCorner(target, corner); + this._currentTransform = { + target: target, + action: action, + corner: corner, + scaleX: target.scaleX, + scaleY: target.scaleY, + skewX: target.skewX, + skewY: target.skewY, + offsetX: pointer.x - target.left, + offsetY: pointer.y - target.top, + originX: origin.x, + originY: origin.y, + ex: pointer.x, + ey: pointer.y, + lastX: pointer.x, + lastY: pointer.y, + left: target.left, + top: target.top, + theta: degreesToRadians(target.angle), + width: target.width * target.scaleX, + mouseXSign: 1, + mouseYSign: 1, + shiftKey: e.shiftKey, + altKey: e.altKey + }; + this._currentTransform.original = { + left: target.left, + top: target.top, + scaleX: target.scaleX, + scaleY: target.scaleY, + skewX: target.skewX, + skewY: target.skewY, + originX: origin.x, + originY: origin.y + }; + this._resetCurrentTransform(); + }, + _translateObject: function(x, y) { + var transform = this._currentTransform, target = transform.target, newLeft = x - transform.offsetX, newTop = y - transform.offsetY, moveX = !target.get("lockMovementX") && target.left !== newLeft, moveY = !target.get("lockMovementY") && target.top !== newTop; + moveX && target.set("left", newLeft); + moveY && target.set("top", newTop); + return moveX || moveY; + }, + _changeSkewTransformOrigin: function(mouseMove, t, by) { + var property = "originX", origins = { + 0: "center" + }, skew = t.target.skewX, originA = "left", originB = "right", corner = t.corner === "mt" || t.corner === "ml" ? 1 : -1, flipSign = 1; + mouseMove = mouseMove > 0 ? 1 : -1; + if (by === "y") { + skew = t.target.skewY; + originA = "top"; + originB = "bottom"; + property = "originY"; + } + origins[-1] = originA; + origins[1] = originB; + t.target.flipX && (flipSign *= -1); + t.target.flipY && (flipSign *= -1); + if (skew === 0) { + t.skewSign = -corner * mouseMove * flipSign; + t[property] = origins[-mouseMove]; + } else { + skew = skew > 0 ? 1 : -1; + t.skewSign = skew; + t[property] = origins[skew * corner * flipSign]; + } + }, + _skewObject: function(x, y, by) { + var t = this._currentTransform, target = t.target, skewed = false, lockSkewingX = target.get("lockSkewingX"), lockSkewingY = target.get("lockSkewingY"); + if (lockSkewingX && by === "x" || lockSkewingY && by === "y") { + return false; + } + var center = target.getCenterPoint(), actualMouseByCenter = target.toLocalPoint(new fabric.Point(x, y), "center", "center")[by], lastMouseByCenter = target.toLocalPoint(new fabric.Point(t.lastX, t.lastY), "center", "center")[by], actualMouseByOrigin, constraintPosition, dim = target._getTransformedDimensions(); + this._changeSkewTransformOrigin(actualMouseByCenter - lastMouseByCenter, t, by); + actualMouseByOrigin = target.toLocalPoint(new fabric.Point(x, y), t.originX, t.originY)[by], + constraintPosition = target.translateToOriginPoint(center, t.originX, t.originY); + skewed = this._setObjectSkew(actualMouseByOrigin, t, by, dim); + t.lastX = x; + t.lastY = y; + target.setPositionByOrigin(constraintPosition, t.originX, t.originY); + return skewed; + }, + _setObjectSkew: function(localMouse, transform, by, _dim) { + var target = transform.target, newValue, skewed = false, skewSign = transform.skewSign, newDim, dimNoSkew, otherBy, _otherBy, _by, newDimMouse, skewX, skewY; + if (by === "x") { + otherBy = "y"; + _otherBy = "Y"; + _by = "X"; + skewX = 0; + skewY = target.skewY; + } else { + otherBy = "x"; + _otherBy = "X"; + _by = "Y"; + skewX = target.skewX; + skewY = 0; + } + dimNoSkew = target._getTransformedDimensions(skewX, skewY); + newDimMouse = 2 * Math.abs(localMouse) - dimNoSkew[by]; + if (newDimMouse <= 2) { + newValue = 0; + } else { + newValue = skewSign * Math.atan(newDimMouse / target["scale" + _by] / (dimNoSkew[otherBy] / target["scale" + _otherBy])); + newValue = fabric.util.radiansToDegrees(newValue); + } + skewed = target["skew" + _by] !== newValue; + target.set("skew" + _by, newValue); + if (target["skew" + _otherBy] !== 0) { + newDim = target._getTransformedDimensions(); + newValue = _dim[otherBy] / newDim[otherBy] * target["scale" + _otherBy]; + target.set("scale" + _otherBy, newValue); + } + return skewed; + }, + _scaleObject: function(x, y, by) { + var t = this._currentTransform, target = t.target, lockScalingX = target.get("lockScalingX"), lockScalingY = target.get("lockScalingY"), lockScalingFlip = target.get("lockScalingFlip"); + if (lockScalingX && lockScalingY) { + return false; + } + var constraintPosition = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY), localMouse = target.toLocalPoint(new fabric.Point(x, y), t.originX, t.originY), dim = target._getTransformedDimensions(), scaled = false; + this._setLocalMouse(localMouse, t); + scaled = this._setObjectScale(localMouse, t, lockScalingX, lockScalingY, by, lockScalingFlip, dim); + target.setPositionByOrigin(constraintPosition, t.originX, t.originY); + return scaled; + }, + _setObjectScale: function(localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip, _dim) { + var target = transform.target, forbidScalingX = false, forbidScalingY = false, scaled = false, changeX, changeY, scaleX, scaleY; + scaleX = localMouse.x * target.scaleX / _dim.x; + scaleY = localMouse.y * target.scaleY / _dim.y; + changeX = target.scaleX !== scaleX; + changeY = target.scaleY !== scaleY; + if (lockScalingFlip && scaleX <= 0 && scaleX < target.scaleX) { + forbidScalingX = true; + } + if (lockScalingFlip && scaleY <= 0 && scaleY < target.scaleY) { + forbidScalingY = true; + } + if (by === "equally" && !lockScalingX && !lockScalingY) { + forbidScalingX || forbidScalingY || (scaled = this._scaleObjectEqually(localMouse, target, transform, _dim)); + } else if (!by) { + forbidScalingX || lockScalingX || target.set("scaleX", scaleX) && (scaled = scaled || changeX); + forbidScalingY || lockScalingY || target.set("scaleY", scaleY) && (scaled = scaled || changeY); + } else if (by === "x" && !target.get("lockUniScaling")) { + forbidScalingX || lockScalingX || target.set("scaleX", scaleX) && (scaled = scaled || changeX); + } else if (by === "y" && !target.get("lockUniScaling")) { + forbidScalingY || lockScalingY || target.set("scaleY", scaleY) && (scaled = scaled || changeY); + } + transform.newScaleX = scaleX; + transform.newScaleY = scaleY; + forbidScalingX || forbidScalingY || this._flipObject(transform, by); + return scaled; + }, + _scaleObjectEqually: function(localMouse, target, transform, _dim) { + var dist = localMouse.y + localMouse.x, lastDist = _dim.y * transform.original.scaleY / target.scaleY + _dim.x * transform.original.scaleX / target.scaleX, scaled; + transform.newScaleX = transform.original.scaleX * dist / lastDist; + transform.newScaleY = transform.original.scaleY * dist / lastDist; + scaled = transform.newScaleX !== target.scaleX || transform.newScaleY !== target.scaleY; + target.set("scaleX", transform.newScaleX); + target.set("scaleY", transform.newScaleY); + return scaled; + }, + _flipObject: function(transform, by) { + if (transform.newScaleX < 0 && by !== "y") { + if (transform.originX === "left") { + transform.originX = "right"; + } else if (transform.originX === "right") { + transform.originX = "left"; + } + } + if (transform.newScaleY < 0 && by !== "x") { + if (transform.originY === "top") { + transform.originY = "bottom"; + } else if (transform.originY === "bottom") { + transform.originY = "top"; + } + } + }, + _setLocalMouse: function(localMouse, t) { + var target = t.target; + if (t.originX === "right") { + localMouse.x *= -1; + } else if (t.originX === "center") { + localMouse.x *= t.mouseXSign * 2; + if (localMouse.x < 0) { + t.mouseXSign = -t.mouseXSign; + } + } + if (t.originY === "bottom") { + localMouse.y *= -1; + } else if (t.originY === "center") { + localMouse.y *= t.mouseYSign * 2; + if (localMouse.y < 0) { + t.mouseYSign = -t.mouseYSign; + } + } + if (abs(localMouse.x) > target.padding) { + if (localMouse.x < 0) { + localMouse.x += target.padding; + } else { + localMouse.x -= target.padding; + } + } else { + localMouse.x = 0; + } + if (abs(localMouse.y) > target.padding) { + if (localMouse.y < 0) { + localMouse.y += target.padding; + } else { + localMouse.y -= target.padding; + } + } else { + localMouse.y = 0; + } + }, + _rotateObject: function(x, y) { + var t = this._currentTransform; + if (t.target.get("lockRotation")) { + return false; + } + var lastAngle = atan2(t.ey - t.top, t.ex - t.left), curAngle = atan2(y - t.top, x - t.left), angle = radiansToDegrees(curAngle - lastAngle + t.theta); + if (angle < 0) { + angle = 360 + angle; + } + t.target.angle = angle % 360; + return true; + }, + setCursor: function(value) { + this.upperCanvasEl.style.cursor = value; + }, + _resetObjectTransform: function(target) { + target.scaleX = 1; + target.scaleY = 1; + target.skewX = 0; + target.skewY = 0; + target.setAngle(0); + }, + _drawSelection: function() { + var ctx = this.contextTop, groupSelector = this._groupSelector, left = groupSelector.left, top = groupSelector.top, aleft = abs(left), atop = abs(top); + ctx.fillStyle = this.selectionColor; + ctx.fillRect(groupSelector.ex - (left > 0 ? 0 : -left), groupSelector.ey - (top > 0 ? 0 : -top), aleft, atop); + ctx.lineWidth = this.selectionLineWidth; + ctx.strokeStyle = this.selectionBorderColor; + if (this.selectionDashArray.length > 1) { + var px = groupSelector.ex + STROKE_OFFSET - (left > 0 ? 0 : aleft), py = groupSelector.ey + STROKE_OFFSET - (top > 0 ? 0 : atop); + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, px, py, px + aleft, py, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px, py + atop - 1, px + aleft, py + atop - 1, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px, py, px, py + atop, this.selectionDashArray); + fabric.util.drawDashedLine(ctx, px + aleft - 1, py, px + aleft - 1, py + atop, this.selectionDashArray); + ctx.closePath(); + ctx.stroke(); + } else { + ctx.strokeRect(groupSelector.ex + STROKE_OFFSET - (left > 0 ? 0 : aleft), groupSelector.ey + STROKE_OFFSET - (top > 0 ? 0 : atop), aleft, atop); + } + }, + _isLastRenderedObject: function(e) { + return this.controlsAboveOverlay && this.lastRenderedObjectWithControlsAboveOverlay && this.lastRenderedObjectWithControlsAboveOverlay.visible && this.containsPoint(e, this.lastRenderedObjectWithControlsAboveOverlay) && this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(this.getPointer(e, true)); + }, + findTarget: function(e, skipGroup) { + if (this.skipTargetFind) { + return; + } + if (this._isLastRenderedObject(e)) { + return this.lastRenderedObjectWithControlsAboveOverlay; + } + var activeGroup = this.getActiveGroup(); + if (activeGroup && !skipGroup && this.containsPoint(e, activeGroup)) { + return activeGroup; + } + var target = this._searchPossibleTargets(e, skipGroup); + this._fireOverOutEvents(target, e); + return target; + }, + _fireOverOutEvents: function(target, e) { + if (target) { + if (this._hoveredTarget !== target) { + if (this._hoveredTarget) { + this.fire("mouse:out", { + target: this._hoveredTarget, + e: e + }); + this._hoveredTarget.fire("mouseout"); + } + this.fire("mouse:over", { + target: target, + e: e + }); + target.fire("mouseover"); + this._hoveredTarget = target; + } + } else if (this._hoveredTarget) { + this.fire("mouse:out", { + target: this._hoveredTarget, + e: e + }); + this._hoveredTarget.fire("mouseout"); + this._hoveredTarget = null; + } + }, + _checkTarget: function(e, obj, pointer) { + if (obj && obj.visible && obj.evented && this.containsPoint(e, obj)) { + if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) { + var isTransparent = this.isTargetTransparent(obj, pointer.x, pointer.y); + if (!isTransparent) { + return true; + } + } else { + return true; + } + } + }, + _searchPossibleTargets: function(e, skipGroup) { + var target, pointer = this.getPointer(e, true), i = this._objects.length; + while (i--) { + if ((!this._objects[i].group || skipGroup) && this._checkTarget(e, this._objects[i], pointer)) { + this.relatedTarget = this._objects[i]; + target = this._objects[i]; + break; + } + } + return target; + }, + getPointer: function(e, ignoreZoom, upperCanvasEl) { + if (!upperCanvasEl) { + upperCanvasEl = this.upperCanvasEl; + } + var pointer = getPointer(e), bounds = upperCanvasEl.getBoundingClientRect(), boundsWidth = bounds.width || 0, boundsHeight = bounds.height || 0, cssScale; + if (!boundsWidth || !boundsHeight) { + if ("top" in bounds && "bottom" in bounds) { + boundsHeight = Math.abs(bounds.top - bounds.bottom); + } + if ("right" in bounds && "left" in bounds) { + boundsWidth = Math.abs(bounds.right - bounds.left); + } + } + this.calcOffset(); + pointer.x = pointer.x - this._offset.left; + pointer.y = pointer.y - this._offset.top; + if (!ignoreZoom) { + pointer = fabric.util.transformPoint(pointer, fabric.util.invertTransform(this.viewportTransform)); + } + if (boundsWidth === 0 || boundsHeight === 0) { + cssScale = { + width: 1, + height: 1 + }; + } else { + cssScale = { + width: upperCanvasEl.width / boundsWidth, + height: upperCanvasEl.height / boundsHeight + }; + } + return { + x: pointer.x * cssScale.width, + y: pointer.y * cssScale.height + }; + }, + _createUpperCanvas: function() { + var lowerCanvasClass = this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/, ""); + this.upperCanvasEl = this._createCanvasElement(); + fabric.util.addClass(this.upperCanvasEl, "upper-canvas " + lowerCanvasClass); + this.wrapperEl.appendChild(this.upperCanvasEl); + this._copyCanvasStyle(this.lowerCanvasEl, this.upperCanvasEl); + this._applyCanvasStyle(this.upperCanvasEl); + this.contextTop = this.upperCanvasEl.getContext("2d"); + }, + _createCacheCanvas: function() { + this.cacheCanvasEl = this._createCanvasElement(); + this.cacheCanvasEl.setAttribute("width", this.width); + this.cacheCanvasEl.setAttribute("height", this.height); + this.contextCache = this.cacheCanvasEl.getContext("2d"); + }, + _initWrapperElement: function() { + this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, "div", { + "class": this.containerClass + }); + fabric.util.setStyle(this.wrapperEl, { + width: this.getWidth() + "px", + height: this.getHeight() + "px", + position: "relative" + }); + fabric.util.makeElementUnselectable(this.wrapperEl); + }, + _applyCanvasStyle: function(element) { + var width = this.getWidth() || element.width, height = this.getHeight() || element.height; + fabric.util.setStyle(element, { + position: "absolute", + width: width + "px", + height: height + "px", + left: 0, + top: 0 + }); + element.width = width; + element.height = height; + fabric.util.makeElementUnselectable(element); + }, + _copyCanvasStyle: function(fromEl, toEl) { + toEl.style.cssText = fromEl.style.cssText; + }, + getSelectionContext: function() { + return this.contextTop; + }, + getSelectionElement: function() { + return this.upperCanvasEl; + }, + _setActiveObject: function(object) { + if (this._activeObject) { + this._activeObject.set("active", false); + } + this._activeObject = object; + object.set("active", true); + }, + setActiveObject: function(object, e) { + this._setActiveObject(object); + this.renderAll(); + this.fire("object:selected", { + target: object, + e: e + }); + object.fire("selected", { + e: e + }); + return this; + }, + getActiveObject: function() { + return this._activeObject; + }, + _discardActiveObject: function() { + if (this._activeObject) { + this._activeObject.set("active", false); + } + this._activeObject = null; + }, + discardActiveObject: function(e) { + this._discardActiveObject(); + this.renderAll(); + this.fire("selection:cleared", { + e: e + }); + return this; + }, + _setActiveGroup: function(group) { + this._activeGroup = group; + if (group) { + group.set("active", true); + } + }, + setActiveGroup: function(group, e) { + this._setActiveGroup(group); + if (group) { + this.fire("object:selected", { + target: group, + e: e + }); + group.fire("selected", { + e: e + }); + } + return this; + }, + getActiveGroup: function() { + return this._activeGroup; + }, + _discardActiveGroup: function() { + var g = this.getActiveGroup(); + if (g) { + g.destroy(); + } + this.setActiveGroup(null); + }, + discardActiveGroup: function(e) { + this._discardActiveGroup(); + this.fire("selection:cleared", { + e: e + }); + return this; + }, + deactivateAll: function() { + var allObjects = this.getObjects(), i = 0, len = allObjects.length; + for (;i < len; i++) { + allObjects[i].set("active", false); + } + this._discardActiveGroup(); + this._discardActiveObject(); + return this; + }, + deactivateAllWithDispatch: function(e) { + var activeObject = this.getActiveGroup() || this.getActiveObject(); + if (activeObject) { + this.fire("before:selection:cleared", { + target: activeObject, + e: e + }); + } + this.deactivateAll(); + if (activeObject) { + this.fire("selection:cleared", { + e: e + }); + } + return this; + }, + dispose: function() { + this.callSuper("dispose"); + var wrapper = this.wrapperEl; + this.removeListeners(); + wrapper.removeChild(this.upperCanvasEl); + wrapper.removeChild(this.lowerCanvasEl); + delete this.upperCanvasEl; + if (wrapper.parentNode) { + wrapper.parentNode.replaceChild(this.lowerCanvasEl, this.wrapperEl); + } + delete this.wrapperEl; + return this; + }, + drawControls: function(ctx) { + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + activeGroup._renderControls(ctx); + } else { + this._drawObjectsControls(ctx); + } + }, + _drawObjectsControls: function(ctx) { + for (var i = 0, len = this._objects.length; i < len; ++i) { + if (!this._objects[i] || !this._objects[i].active) { + continue; + } + this._objects[i]._renderControls(ctx); + this.lastRenderedObjectWithControlsAboveOverlay = this._objects[i]; + } + } + }); + for (var prop in fabric.StaticCanvas) { + if (prop !== "prototype") { + fabric.Canvas[prop] = fabric.StaticCanvas[prop]; + } + } + if (fabric.isTouchSupported) { + fabric.Canvas.prototype._setCursorFromEvent = function() {}; + } + fabric.Element = fabric.Canvas; +})(); + +(function() { + var cursorOffset = { + mt: 0, + tr: 1, + mr: 2, + br: 3, + mb: 4, + bl: 5, + ml: 6, + tl: 7 + }, addListener = fabric.util.addListener, removeListener = fabric.util.removeListener; + fabric.util.object.extend(fabric.Canvas.prototype, { + cursorMap: [ "n-resize", "ne-resize", "e-resize", "se-resize", "s-resize", "sw-resize", "w-resize", "nw-resize" ], + _initEventListeners: function() { + this._bindEvents(); + addListener(fabric.window, "resize", this._onResize); + addListener(this.upperCanvasEl, "mousedown", this._onMouseDown); + addListener(this.upperCanvasEl, "mousemove", this._onMouseMove); + addListener(this.upperCanvasEl, "mousewheel", this._onMouseWheel); + addListener(this.upperCanvasEl, "touchstart", this._onMouseDown); + addListener(this.upperCanvasEl, "touchmove", this._onMouseMove); + if (typeof eventjs !== "undefined" && "add" in eventjs) { + eventjs.add(this.upperCanvasEl, "gesture", this._onGesture); + eventjs.add(this.upperCanvasEl, "drag", this._onDrag); + eventjs.add(this.upperCanvasEl, "orientation", this._onOrientationChange); + eventjs.add(this.upperCanvasEl, "shake", this._onShake); + eventjs.add(this.upperCanvasEl, "longpress", this._onLongPress); + } + }, + _bindEvents: function() { + this._onMouseDown = this._onMouseDown.bind(this); + this._onMouseMove = this._onMouseMove.bind(this); + this._onMouseUp = this._onMouseUp.bind(this); + this._onResize = this._onResize.bind(this); + this._onGesture = this._onGesture.bind(this); + this._onDrag = this._onDrag.bind(this); + this._onShake = this._onShake.bind(this); + this._onLongPress = this._onLongPress.bind(this); + this._onOrientationChange = this._onOrientationChange.bind(this); + this._onMouseWheel = this._onMouseWheel.bind(this); + }, + removeListeners: function() { + removeListener(fabric.window, "resize", this._onResize); + removeListener(this.upperCanvasEl, "mousedown", this._onMouseDown); + removeListener(this.upperCanvasEl, "mousemove", this._onMouseMove); + removeListener(this.upperCanvasEl, "mousewheel", this._onMouseWheel); + removeListener(this.upperCanvasEl, "touchstart", this._onMouseDown); + removeListener(this.upperCanvasEl, "touchmove", this._onMouseMove); + if (typeof eventjs !== "undefined" && "remove" in eventjs) { + eventjs.remove(this.upperCanvasEl, "gesture", this._onGesture); + eventjs.remove(this.upperCanvasEl, "drag", this._onDrag); + eventjs.remove(this.upperCanvasEl, "orientation", this._onOrientationChange); + eventjs.remove(this.upperCanvasEl, "shake", this._onShake); + eventjs.remove(this.upperCanvasEl, "longpress", this._onLongPress); + } + }, + _onGesture: function(e, self) { + this.__onTransformGesture && this.__onTransformGesture(e, self); + }, + _onDrag: function(e, self) { + this.__onDrag && this.__onDrag(e, self); + }, + _onMouseWheel: function(e, self) { + this.__onMouseWheel && this.__onMouseWheel(e, self); + }, + _onOrientationChange: function(e, self) { + this.__onOrientationChange && this.__onOrientationChange(e, self); + }, + _onShake: function(e, self) { + this.__onShake && this.__onShake(e, self); + }, + _onLongPress: function(e, self) { + this.__onLongPress && this.__onLongPress(e, self); + }, + _onMouseDown: function(e) { + this.__onMouseDown(e); + addListener(fabric.document, "touchend", this._onMouseUp); + addListener(fabric.document, "touchmove", this._onMouseMove); + removeListener(this.upperCanvasEl, "mousemove", this._onMouseMove); + removeListener(this.upperCanvasEl, "touchmove", this._onMouseMove); + if (e.type === "touchstart") { + removeListener(this.upperCanvasEl, "mousedown", this._onMouseDown); + } else { + addListener(fabric.document, "mouseup", this._onMouseUp); + addListener(fabric.document, "mousemove", this._onMouseMove); + } + }, + _onMouseUp: function(e) { + this.__onMouseUp(e); + removeListener(fabric.document, "mouseup", this._onMouseUp); + removeListener(fabric.document, "touchend", this._onMouseUp); + removeListener(fabric.document, "mousemove", this._onMouseMove); + removeListener(fabric.document, "touchmove", this._onMouseMove); + addListener(this.upperCanvasEl, "mousemove", this._onMouseMove); + addListener(this.upperCanvasEl, "touchmove", this._onMouseMove); + if (e.type === "touchend") { + var _this = this; + setTimeout(function() { + addListener(_this.upperCanvasEl, "mousedown", _this._onMouseDown); + }, 400); + } + }, + _onMouseMove: function(e) { + !this.allowTouchScrolling && e.preventDefault && e.preventDefault(); + this.__onMouseMove(e); + }, + _onResize: function() { + this.calcOffset(); + }, + _shouldRender: function(target, pointer) { + var activeObject = this.getActiveGroup() || this.getActiveObject(); + return !!(target && (target.isMoving || target !== activeObject) || !target && !!activeObject || !target && !activeObject && !this._groupSelector || pointer && this._previousPointer && this.selection && (pointer.x !== this._previousPointer.x || pointer.y !== this._previousPointer.y)); + }, + __onMouseUp: function(e) { + var target; + if (this.isDrawingMode && this._isCurrentlyDrawing) { + this._onMouseUpInDrawingMode(e); + return; + } + if (this._currentTransform) { + this._finalizeCurrentTransform(); + target = this._currentTransform.target; + } else { + target = this.findTarget(e, true); + } + var shouldRender = this._shouldRender(target, this.getPointer(e)); + this._maybeGroupObjects(e); + if (target) { + target.isMoving = false; + } + shouldRender && this.renderAll(); + this._handleCursorAndEvent(e, target); + }, + _handleCursorAndEvent: function(e, target) { + this._setCursorFromEvent(e, target); + var _this = this; + setTimeout(function() { + _this._setCursorFromEvent(e, target); + }, 50); + this.fire("mouse:up", { + target: target, + e: e + }); + target && target.fire("mouseup", { + e: e + }); + }, + _finalizeCurrentTransform: function() { + var transform = this._currentTransform, target = transform.target; + if (target._scaling) { + target._scaling = false; + } + target.setCoords(); + this._restoreOriginXY(target); + if (transform.actionPerformed || this.stateful && target.hasStateChanged()) { + this.fire("object:modified", { + target: target + }); + target.fire("modified"); + } + }, + _restoreOriginXY: function(target) { + if (this._previousOriginX && this._previousOriginY) { + var originPoint = target.translateToOriginPoint(target.getCenterPoint(), this._previousOriginX, this._previousOriginY); + target.originX = this._previousOriginX; + target.originY = this._previousOriginY; + target.left = originPoint.x; + target.top = originPoint.y; + this._previousOriginX = null; + this._previousOriginY = null; + } + }, + _onMouseDownInDrawingMode: function(e) { + this._isCurrentlyDrawing = true; + this.discardActiveObject(e).renderAll(); + if (this.clipTo) { + fabric.util.clipContext(this, this.contextTop); + } + var ivt = fabric.util.invertTransform(this.viewportTransform), pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt); + this.freeDrawingBrush.onMouseDown(pointer); + this.fire("mouse:down", { + e: e + }); + var target = this.findTarget(e); + if (typeof target !== "undefined") { + target.fire("mousedown", { + e: e, + target: target + }); + } + }, + _onMouseMoveInDrawingMode: function(e) { + if (this._isCurrentlyDrawing) { + var ivt = fabric.util.invertTransform(this.viewportTransform), pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt); + this.freeDrawingBrush.onMouseMove(pointer); + } + this.setCursor(this.freeDrawingCursor); + this.fire("mouse:move", { + e: e + }); + var target = this.findTarget(e); + if (typeof target !== "undefined") { + target.fire("mousemove", { + e: e, + target: target + }); + } + }, + _onMouseUpInDrawingMode: function(e) { + this._isCurrentlyDrawing = false; + if (this.clipTo) { + this.contextTop.restore(); + } + this.freeDrawingBrush.onMouseUp(); + this.fire("mouse:up", { + e: e + }); + var target = this.findTarget(e); + if (typeof target !== "undefined") { + target.fire("mouseup", { + e: e, + target: target + }); + } + }, + __onMouseDown: function(e) { + var isLeftClick = "which" in e ? e.which === 1 : e.button === 0; + if (!isLeftClick && !fabric.isTouchSupported) { + return; + } + if (this.isDrawingMode) { + this._onMouseDownInDrawingMode(e); + return; + } + if (this._currentTransform) { + return; + } + var target = this.findTarget(e), pointer = this.getPointer(e, true); + this._previousPointer = pointer; + var shouldRender = this._shouldRender(target, pointer), shouldGroup = this._shouldGroup(e, target); + if (this._shouldClearSelection(e, target)) { + this._clearSelection(e, target, pointer); + } else if (shouldGroup) { + this._handleGrouping(e, target); + target = this.getActiveGroup(); + } + if (target && target.selectable && (target.__corner || !shouldGroup)) { + this._beforeTransform(e, target); + this._setupCurrentTransform(e, target); + } + shouldRender && this.renderAll(); + this.fire("mouse:down", { + target: target, + e: e + }); + target && target.fire("mousedown", { + e: e + }); + }, + _beforeTransform: function(e, target) { + this.stateful && target.saveState(); + if (target._findTargetCorner(this.getPointer(e))) { + this.onBeforeScaleRotate(target); + } + if (target !== this.getActiveGroup() && target !== this.getActiveObject()) { + this.deactivateAll(); + this.setActiveObject(target, e); + } + }, + _clearSelection: function(e, target, pointer) { + this.deactivateAllWithDispatch(e); + if (target && target.selectable) { + this.setActiveObject(target, e); + } else if (this.selection) { + this._groupSelector = { + ex: pointer.x, + ey: pointer.y, + top: 0, + left: 0 + }; + } + }, + _setOriginToCenter: function(target) { + this._previousOriginX = this._currentTransform.target.originX; + this._previousOriginY = this._currentTransform.target.originY; + var center = target.getCenterPoint(); + target.originX = "center"; + target.originY = "center"; + target.left = center.x; + target.top = center.y; + this._currentTransform.left = target.left; + this._currentTransform.top = target.top; + }, + _setCenterToOrigin: function(target) { + var originPoint = target.translateToOriginPoint(target.getCenterPoint(), this._previousOriginX, this._previousOriginY); + target.originX = this._previousOriginX; + target.originY = this._previousOriginY; + target.left = originPoint.x; + target.top = originPoint.y; + this._previousOriginX = null; + this._previousOriginY = null; + }, + __onMouseMove: function(e) { + var target, pointer; + if (this.isDrawingMode) { + this._onMouseMoveInDrawingMode(e); + return; + } + if (typeof e.touches !== "undefined" && e.touches.length > 1) { + return; + } + var groupSelector = this._groupSelector; + if (groupSelector) { + pointer = this.getPointer(e, true); + groupSelector.left = pointer.x - groupSelector.ex; + groupSelector.top = pointer.y - groupSelector.ey; + this.renderTop(); + } else if (!this._currentTransform) { + target = this.findTarget(e); + if (!target || target && !target.selectable) { + this.setCursor(this.defaultCursor); + } else { + this._setCursorFromEvent(e, target); + } + } else { + this._transformObject(e); + } + this.fire("mouse:move", { + target: target, + e: e + }); + target && target.fire("mousemove", { + e: e + }); + }, + _transformObject: function(e) { + var pointer = this.getPointer(e), transform = this._currentTransform; + transform.reset = false, transform.target.isMoving = true; + this._beforeScaleTransform(e, transform); + this._performTransformAction(e, transform, pointer); + this.renderAll(); + }, + _performTransformAction: function(e, transform, pointer) { + var x = pointer.x, y = pointer.y, target = transform.target, action = transform.action, actionPerformed = false; + if (action === "rotate") { + (actionPerformed = this._rotateObject(x, y)) && this._fire("rotating", target, e); + } else if (action === "scale") { + (actionPerformed = this._onScale(e, transform, x, y)) && this._fire("scaling", target, e); + } else if (action === "scaleX") { + (actionPerformed = this._scaleObject(x, y, "x")) && this._fire("scaling", target, e); + } else if (action === "scaleY") { + (actionPerformed = this._scaleObject(x, y, "y")) && this._fire("scaling", target, e); + } else if (action === "skewX") { + (actionPerformed = this._skewObject(x, y, "x")) && this._fire("skewing", target, e); + } else if (action === "skewY") { + (actionPerformed = this._skewObject(x, y, "y")) && this._fire("skewing", target, e); + } else { + (actionPerformed = this._translateObject(x, y)) && this._fire("moving", target, e); + this.setCursor(this.moveCursor); + } + transform.actionPerformed = actionPerformed; + }, + _fire: function(eventName, target, e) { + this.fire("object:" + eventName, { + target: target, + e: e + }); + target.fire(eventName, { + e: e + }); + }, + _beforeScaleTransform: function(e, transform) { + if (transform.action === "scale" || transform.action === "scaleX" || transform.action === "scaleY") { + var centerTransform = this._shouldCenterTransform(transform.target); + if (centerTransform && (transform.originX !== "center" || transform.originY !== "center") || !centerTransform && transform.originX === "center" && transform.originY === "center") { + this._resetCurrentTransform(); + transform.reset = true; + } + } + }, + _onScale: function(e, transform, x, y) { + if ((e.shiftKey || this.uniScaleTransform) && !transform.target.get("lockUniScaling")) { + transform.currentAction = "scale"; + return this._scaleObject(x, y); + } else { + if (!transform.reset && transform.currentAction === "scale") { + this._resetCurrentTransform(); + } + transform.currentAction = "scaleEqually"; + return this._scaleObject(x, y, "equally"); + } + }, + _setCursorFromEvent: function(e, target) { + if (!target || !target.selectable) { + this.setCursor(this.defaultCursor); + return false; + } else { + var activeGroup = this.getActiveGroup(), corner = target._findTargetCorner && (!activeGroup || !activeGroup.contains(target)) && target._findTargetCorner(this.getPointer(e, true)); + if (!corner) { + this.setCursor(target.hoverCursor || this.hoverCursor); + } else { + this._setCornerCursor(corner, target, e); + } + } + return true; + }, + _setCornerCursor: function(corner, target, e) { + if (corner in cursorOffset) { + this.setCursor(this._getRotatedCornerCursor(corner, target, e)); + } else if (corner === "mtr" && target.hasRotatingPoint) { + this.setCursor(this.rotationCursor); + } else { + this.setCursor(this.defaultCursor); + return false; + } + }, + _getRotatedCornerCursor: function(corner, target, e) { + var n = Math.round(target.getAngle() % 360 / 45); + if (n < 0) { + n += 8; + } + n += cursorOffset[corner]; + if (e.shiftKey && cursorOffset[corner] % 2 === 0) { + n += 2; + } + n %= 8; + return this.cursorMap[n]; + } + }); +})(); + +(function() { + var min = Math.min, max = Math.max; + fabric.util.object.extend(fabric.Canvas.prototype, { + _shouldGroup: function(e, target) { + var activeObject = this.getActiveObject(); + return e.shiftKey && target && target.selectable && (this.getActiveGroup() || activeObject && activeObject !== target) && this.selection; + }, + _handleGrouping: function(e, target) { + if (target === this.getActiveGroup()) { + target = this.findTarget(e, true); + if (!target || target.isType("group")) { + return; + } + } + if (this.getActiveGroup()) { + this._updateActiveGroup(target, e); + } else { + this._createActiveGroup(target, e); + } + if (this._activeGroup) { + this._activeGroup.saveCoords(); + } + }, + _updateActiveGroup: function(target, e) { + var activeGroup = this.getActiveGroup(); + if (activeGroup.contains(target)) { + activeGroup.removeWithUpdate(target); + target.set("active", false); + if (activeGroup.size() === 1) { + this.discardActiveGroup(e); + this.setActiveObject(activeGroup.item(0)); + return; + } + } else { + activeGroup.addWithUpdate(target); + } + this.fire("selection:created", { + target: activeGroup, + e: e + }); + activeGroup.set("active", true); + }, + _createActiveGroup: function(target, e) { + if (this._activeObject && target !== this._activeObject) { + var group = this._createGroup(target); + group.addWithUpdate(); + this.setActiveGroup(group); + this._activeObject = null; + this.fire("selection:created", { + target: group, + e: e + }); + } + target.set("active", true); + }, + _createGroup: function(target) { + var objects = this.getObjects(), isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target), groupObjects = isActiveLower ? [ this._activeObject, target ] : [ target, this._activeObject ]; + return new fabric.Group(groupObjects, { + canvas: this + }); + }, + _groupSelectedObjects: function(e) { + var group = this._collectObjects(); + if (group.length === 1) { + this.setActiveObject(group[0], e); + } else if (group.length > 1) { + group = new fabric.Group(group.reverse(), { + canvas: this + }); + group.addWithUpdate(); + this.setActiveGroup(group, e); + group.saveCoords(); + this.fire("selection:created", { + target: group + }); + this.renderAll(); + } + }, + _collectObjects: function() { + var group = [], currentObject, x1 = this._groupSelector.ex, y1 = this._groupSelector.ey, x2 = x1 + this._groupSelector.left, y2 = y1 + this._groupSelector.top, selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)), selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)), isClick = x1 === x2 && y1 === y2; + for (var i = this._objects.length; i--; ) { + currentObject = this._objects[i]; + if (!currentObject || !currentObject.selectable || !currentObject.visible) { + continue; + } + if (currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2) || currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) || currentObject.containsPoint(selectionX1Y1) || currentObject.containsPoint(selectionX2Y2)) { + currentObject.set("active", true); + group.push(currentObject); + if (isClick) { + break; + } + } + } + return group; + }, + _maybeGroupObjects: function(e) { + if (this.selection && this._groupSelector) { + this._groupSelectedObjects(e); + } + var activeGroup = this.getActiveGroup(); + if (activeGroup) { + activeGroup.setObjectsCoords().setCoords(); + activeGroup.isMoving = false; + this.setCursor(this.defaultCursor); + } + this._groupSelector = null; + this._currentTransform = null; + } + }); +})(); + +fabric.util.object.extend(fabric.StaticCanvas.prototype, { + toDataURL: function(options) { + options || (options = {}); + var format = options.format || "png", quality = options.quality || 1, multiplier = options.multiplier || 1, cropping = { + left: options.left, + top: options.top, + width: options.width, + height: options.height + }; + if (this._isRetinaScaling()) { + multiplier *= fabric.devicePixelRatio; + } + if (multiplier !== 1) { + return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier); + } else { + return this.__toDataURL(format, quality, cropping); + } + }, + __toDataURL: function(format, quality, cropping) { + this.renderAll(); + var canvasEl = this.contextContainer.canvas, croppedCanvasEl = this.__getCroppedCanvas(canvasEl, cropping); + if (format === "jpg") { + format = "jpeg"; + } + var data = fabric.StaticCanvas.supports("toDataURLWithQuality") ? (croppedCanvasEl || canvasEl).toDataURL("image/" + format, quality) : (croppedCanvasEl || canvasEl).toDataURL("image/" + format); + if (croppedCanvasEl) { + croppedCanvasEl = null; + } + return data; + }, + __getCroppedCanvas: function(canvasEl, cropping) { + var croppedCanvasEl, croppedCtx, shouldCrop = "left" in cropping || "top" in cropping || "width" in cropping || "height" in cropping; + if (shouldCrop) { + croppedCanvasEl = fabric.util.createCanvasElement(); + croppedCtx = croppedCanvasEl.getContext("2d"); + croppedCanvasEl.width = cropping.width || this.width; + croppedCanvasEl.height = cropping.height || this.height; + croppedCtx.drawImage(canvasEl, -cropping.left || 0, -cropping.top || 0); + } + return croppedCanvasEl; + }, + __toDataURLWithMultiplier: function(format, quality, cropping, multiplier) { + var origWidth = this.getWidth(), origHeight = this.getHeight(), scaledWidth = origWidth * multiplier, scaledHeight = origHeight * multiplier, activeObject = this.getActiveObject(), activeGroup = this.getActiveGroup(), ctx = this.contextContainer; + if (multiplier > 1) { + this.setDimensions({ + width: scaledWidth, + height: scaledHeight + }); + } + ctx.save(); + ctx.scale(multiplier / fabric.devicePixelRatio, multiplier / fabric.devicePixelRatio); + if (cropping.left) { + cropping.left *= multiplier; + } + if (cropping.top) { + cropping.top *= multiplier; + } + if (cropping.width) { + cropping.width *= multiplier; + } else if (multiplier < 1) { + cropping.width = scaledWidth; + } + if (cropping.height) { + cropping.height *= multiplier; + } else if (multiplier < 1) { + cropping.height = scaledHeight; + } + if (activeGroup) { + this._tempRemoveBordersControlsFromGroup(activeGroup); + } else if (activeObject && this.deactivateAll) { + this.deactivateAll(); + } + var data = this.__toDataURL(format, quality, cropping); + this.width = origWidth; + this.height = origHeight; + this.setDimensions({ + width: origWidth, + height: origHeight + }); + if (activeGroup) { + this._restoreBordersControlsOnGroup(activeGroup); + } else if (activeObject && this.setActiveObject) { + this.setActiveObject(activeObject); + } + this.contextTop && this.clearContext(this.contextTop); + this.renderAll(); + return data; + }, + toDataURLWithMultiplier: function(format, multiplier, quality) { + return this.toDataURL({ + format: format, + multiplier: multiplier, + quality: quality + }); + }, + _tempRemoveBordersControlsFromGroup: function(group) { + group.origHasControls = group.hasControls; + group.origBorderColor = group.borderColor; + group.hasControls = true; + group.borderColor = "rgba(0,0,0,0)"; + group.forEachObject(function(o) { + o.origBorderColor = o.borderColor; + o.borderColor = "rgba(0,0,0,0)"; + }); + }, + _restoreBordersControlsOnGroup: function(group) { + group.hideControls = group.origHideControls; + group.borderColor = group.origBorderColor; + group.forEachObject(function(o) { + o.borderColor = o.origBorderColor; + delete o.origBorderColor; + }); + } +}); + +fabric.util.object.extend(fabric.StaticCanvas.prototype, { + loadFromDatalessJSON: function(json, callback, reviver) { + return this.loadFromJSON(json, callback, reviver); + }, + loadFromJSON: function(json, callback, reviver) { + if (!json) { + return; + } + var serialized = typeof json === "string" ? JSON.parse(json) : json; + this.clear(); + var _this = this; + this._enlivenObjects(serialized.objects, function() { + _this._setBgOverlay(serialized, callback); + }, reviver); + return this; + }, + _setBgOverlay: function(serialized, callback) { + var _this = this, loaded = { + backgroundColor: false, + overlayColor: false, + backgroundImage: false, + overlayImage: false + }; + if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background && !serialized.overlay) { + callback && callback(); + return; + } + var cbIfLoaded = function() { + if (loaded.backgroundImage && loaded.overlayImage && loaded.backgroundColor && loaded.overlayColor) { + _this.renderAll(); + callback && callback(); + } + }; + this.__setBgOverlay("backgroundImage", serialized.backgroundImage, loaded, cbIfLoaded); + this.__setBgOverlay("overlayImage", serialized.overlayImage, loaded, cbIfLoaded); + this.__setBgOverlay("backgroundColor", serialized.background, loaded, cbIfLoaded); + this.__setBgOverlay("overlayColor", serialized.overlay, loaded, cbIfLoaded); + cbIfLoaded(); + }, + __setBgOverlay: function(property, value, loaded, callback) { + var _this = this; + if (!value) { + loaded[property] = true; + return; + } + if (property === "backgroundImage" || property === "overlayImage") { + fabric.Image.fromObject(value, function(img) { + _this[property] = img; + loaded[property] = true; + callback && callback(); + }); + } else { + this["set" + fabric.util.string.capitalize(property, true)](value, function() { + loaded[property] = true; + callback && callback(); + }); + } + }, + _enlivenObjects: function(objects, callback, reviver) { + var _this = this; + if (!objects || objects.length === 0) { + callback && callback(); + return; + } + var renderOnAddRemove = this.renderOnAddRemove; + this.renderOnAddRemove = false; + fabric.util.enlivenObjects(objects, function(enlivenedObjects) { + enlivenedObjects.forEach(function(obj, index) { + _this.insertAt(obj, index, true); + }); + _this.renderOnAddRemove = renderOnAddRemove; + callback && callback(); + }, null, reviver); + }, + _toDataURL: function(format, callback) { + this.clone(function(clone) { + callback(clone.toDataURL(format)); + }); + }, + _toDataURLWithMultiplier: function(format, multiplier, callback) { + this.clone(function(clone) { + callback(clone.toDataURLWithMultiplier(format, multiplier)); + }); + }, + clone: function(callback, properties) { + var data = JSON.stringify(this.toJSON(properties)); + this.cloneWithoutData(function(clone) { + clone.loadFromJSON(data, function() { + callback && callback(clone); + }); + }); + }, + cloneWithoutData: function(callback) { + var el = fabric.document.createElement("canvas"); + el.width = this.getWidth(); + el.height = this.getHeight(); + var clone = new fabric.Canvas(el); + clone.clipTo = this.clipTo; + if (this.backgroundImage) { + clone.setBackgroundImage(this.backgroundImage.src, function() { + clone.renderAll(); + callback && callback(clone); + }); + clone.backgroundImageOpacity = this.backgroundImageOpacity; + clone.backgroundImageStretch = this.backgroundImageStretch; + } else { + callback && callback(clone); + } + } +}); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, toFixed = fabric.util.toFixed, capitalize = fabric.util.string.capitalize, degreesToRadians = fabric.util.degreesToRadians, supportsLineDash = fabric.StaticCanvas.supports("setLineDash"); + if (fabric.Object) { + return; + } + fabric.Object = fabric.util.createClass({ + type: "object", + originX: "left", + originY: "top", + top: 0, + left: 0, + width: 0, + height: 0, + scaleX: 1, + scaleY: 1, + flipX: false, + flipY: false, + opacity: 1, + angle: 0, + skewX: 0, + skewY: 0, + cornerSize: 12, + transparentCorners: true, + hoverCursor: null, + padding: 0, + borderColor: "rgba(102,153,255,0.75)", + cornerColor: "rgba(102,153,255,0.5)", + centeredScaling: false, + centeredRotation: true, + fill: "rgb(0,0,0)", + fillRule: "nonzero", + globalCompositeOperation: "source-over", + backgroundColor: "", + stroke: null, + strokeWidth: 1, + strokeDashArray: null, + strokeLineCap: "butt", + strokeLineJoin: "miter", + strokeMiterLimit: 10, + shadow: null, + borderOpacityWhenMoving: .4, + borderScaleFactor: 1, + transformMatrix: null, + minScaleLimit: .01, + selectable: true, + evented: true, + visible: true, + hasControls: true, + hasBorders: true, + hasRotatingPoint: true, + rotatingPointOffset: 40, + perPixelTargetFind: false, + includeDefaultValues: true, + clipTo: null, + lockMovementX: false, + lockMovementY: false, + lockRotation: false, + lockScalingX: false, + lockScalingY: false, + lockUniScaling: false, + lockSkewingX: false, + lockSkewingY: false, + lockScalingFlip: false, + stateProperties: ("top left width height scaleX scaleY flipX flipY originX originY transformMatrix " + "stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit " + "angle opacity fill fillRule globalCompositeOperation shadow clipTo visible backgroundColor " + "alignX alignY meetOrSlice skewX skewY").split(" "), + initialize: function(options) { + if (options) { + this.setOptions(options); + } + }, + _initGradient: function(options) { + if (options.fill && options.fill.colorStops && !(options.fill instanceof fabric.Gradient)) { + this.set("fill", new fabric.Gradient(options.fill)); + } + if (options.stroke && options.stroke.colorStops && !(options.stroke instanceof fabric.Gradient)) { + this.set("stroke", new fabric.Gradient(options.stroke)); + } + }, + _initPattern: function(options) { + if (options.fill && options.fill.source && !(options.fill instanceof fabric.Pattern)) { + this.set("fill", new fabric.Pattern(options.fill)); + } + if (options.stroke && options.stroke.source && !(options.stroke instanceof fabric.Pattern)) { + this.set("stroke", new fabric.Pattern(options.stroke)); + } + }, + _initClipping: function(options) { + if (!options.clipTo || typeof options.clipTo !== "string") { + return; + } + var functionBody = fabric.util.getFunctionBody(options.clipTo); + if (typeof functionBody !== "undefined") { + this.clipTo = new Function("ctx", functionBody); + } + }, + setOptions: function(options) { + for (var prop in options) { + this.set(prop, options[prop]); + } + this._initGradient(options); + this._initPattern(options); + this._initClipping(options); + }, + transform: function(ctx, fromLeft) { + if (this.group && this.canvas.preserveObjectStacking && this.group === this.canvas._activeGroup) { + this.group.transform(ctx); + } + var center = fromLeft ? this._getLeftTopCoords() : this.getCenterPoint(); + ctx.translate(center.x, center.y); + ctx.rotate(degreesToRadians(this.angle)); + ctx.scale(this.scaleX * (this.flipX ? -1 : 1), this.scaleY * (this.flipY ? -1 : 1)); + ctx.transform(1, 0, Math.tan(degreesToRadians(this.skewX)), 1, 0, 0); + ctx.transform(1, Math.tan(degreesToRadians(this.skewY)), 0, 1, 0, 0); + }, + toObject: function(propertiesToInclude) { + var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, object = { + type: this.type, + originX: this.originX, + originY: this.originY, + left: toFixed(this.left, NUM_FRACTION_DIGITS), + top: toFixed(this.top, NUM_FRACTION_DIGITS), + width: toFixed(this.width, NUM_FRACTION_DIGITS), + height: toFixed(this.height, NUM_FRACTION_DIGITS), + fill: this.fill && this.fill.toObject ? this.fill.toObject() : this.fill, + stroke: this.stroke && this.stroke.toObject ? this.stroke.toObject() : this.stroke, + strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS), + strokeDashArray: this.strokeDashArray ? this.strokeDashArray.concat() : this.strokeDashArray, + strokeLineCap: this.strokeLineCap, + strokeLineJoin: this.strokeLineJoin, + strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS), + scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS), + scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS), + angle: toFixed(this.getAngle(), NUM_FRACTION_DIGITS), + flipX: this.flipX, + flipY: this.flipY, + opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS), + shadow: this.shadow && this.shadow.toObject ? this.shadow.toObject() : this.shadow, + visible: this.visible, + clipTo: this.clipTo && String(this.clipTo), + backgroundColor: this.backgroundColor, + fillRule: this.fillRule, + globalCompositeOperation: this.globalCompositeOperation, + transformMatrix: this.transformMatrix ? this.transformMatrix.concat() : this.transformMatrix, + skewX: toFixed(this.skewX, NUM_FRACTION_DIGITS), + skewY: toFixed(this.skewY, NUM_FRACTION_DIGITS) + }; + if (!this.includeDefaultValues) { + object = this._removeDefaultValues(object); + } + fabric.util.populateWithProperties(this, object, propertiesToInclude); + return object; + }, + toDatalessObject: function(propertiesToInclude) { + return this.toObject(propertiesToInclude); + }, + _removeDefaultValues: function(object) { + var prototype = fabric.util.getKlass(object.type).prototype, stateProperties = prototype.stateProperties; + stateProperties.forEach(function(prop) { + if (object[prop] === prototype[prop]) { + delete object[prop]; + } + var isArray = Object.prototype.toString.call(object[prop]) === "[object Array]" && Object.prototype.toString.call(prototype[prop]) === "[object Array]"; + if (isArray && object[prop].length === 0 && prototype[prop].length === 0) { + delete object[prop]; + } + }); + return object; + }, + toString: function() { + return "#"; + }, + get: function(property) { + return this[property]; + }, + _setObject: function(obj) { + for (var prop in obj) { + this._set(prop, obj[prop]); + } + }, + set: function(key, value) { + if (typeof key === "object") { + this._setObject(key); + } else { + if (typeof value === "function" && key !== "clipTo") { + this._set(key, value(this.get(key))); + } else { + this._set(key, value); + } + } + return this; + }, + _set: function(key, value) { + var shouldConstrainValue = key === "scaleX" || key === "scaleY"; + if (shouldConstrainValue) { + value = this._constrainScale(value); + } + if (key === "scaleX" && value < 0) { + this.flipX = !this.flipX; + value *= -1; + } else if (key === "scaleY" && value < 0) { + this.flipY = !this.flipY; + value *= -1; + } else if (key === "width" || key === "height") { + this.minScaleLimit = toFixed(Math.min(.1, 1 / Math.max(this.width, this.height)), 2); + } else if (key === "shadow" && value && !(value instanceof fabric.Shadow)) { + value = new fabric.Shadow(value); + } + this[key] = value; + return this; + }, + setOnGroup: function() {}, + toggle: function(property) { + var value = this.get(property); + if (typeof value === "boolean") { + this.set(property, !value); + } + return this; + }, + setSourcePath: function(value) { + this.sourcePath = value; + return this; + }, + getViewportTransform: function() { + if (this.canvas && this.canvas.viewportTransform) { + return this.canvas.viewportTransform; + } + return [ 1, 0, 0, 1, 0, 0 ]; + }, + render: function(ctx, noTransform) { + if (this.width === 0 && this.height === 0 || !this.visible) { + return; + } + ctx.save(); + this._setupCompositeOperation(ctx); + if (!noTransform) { + this.transform(ctx); + } + this._setStrokeStyles(ctx); + this._setFillStyles(ctx); + if (this.transformMatrix) { + ctx.transform.apply(ctx, this.transformMatrix); + } + this._setOpacity(ctx); + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + this._render(ctx, noTransform); + this.clipTo && ctx.restore(); + ctx.restore(); + }, + _setOpacity: function(ctx) { + if (this.group) { + this.group._setOpacity(ctx); + } + ctx.globalAlpha *= this.opacity; + }, + _setStrokeStyles: function(ctx) { + if (this.stroke) { + ctx.lineWidth = this.strokeWidth; + ctx.lineCap = this.strokeLineCap; + ctx.lineJoin = this.strokeLineJoin; + ctx.miterLimit = this.strokeMiterLimit; + ctx.strokeStyle = this.stroke.toLive ? this.stroke.toLive(ctx, this) : this.stroke; + } + }, + _setFillStyles: function(ctx) { + if (this.fill) { + ctx.fillStyle = this.fill.toLive ? this.fill.toLive(ctx, this) : this.fill; + } + }, + _renderControls: function(ctx, noTransform) { + if (!this.active || noTransform || this.group && this.group !== this.canvas.getActiveGroup()) { + return; + } + var vpt = this.getViewportTransform(), matrix = this.calcTransformMatrix(), options; + matrix = fabric.util.multiplyTransformMatrices(vpt, matrix); + options = fabric.util.qrDecompose(matrix); + ctx.save(); + ctx.translate(options.translateX, options.translateY); + if (this.group && this.group === this.canvas.getActiveGroup()) { + ctx.rotate(degreesToRadians(options.angle)); + this.drawBordersInGroup(ctx, options); + } else { + ctx.rotate(degreesToRadians(this.angle)); + this.drawBorders(ctx); + } + this.drawControls(ctx); + ctx.restore(); + }, + _setShadow: function(ctx) { + if (!this.shadow) { + return; + } + var multX = this.canvas && this.canvas.viewportTransform[0] || 1, multY = this.canvas && this.canvas.viewportTransform[3] || 1; + if (this.canvas && this.canvas._isRetinaScaling()) { + multX *= fabric.devicePixelRatio; + multY *= fabric.devicePixelRatio; + } + ctx.shadowColor = this.shadow.color; + ctx.shadowBlur = this.shadow.blur * (multX + multY) * (this.scaleX + this.scaleY) / 4; + ctx.shadowOffsetX = this.shadow.offsetX * multX * this.scaleX; + ctx.shadowOffsetY = this.shadow.offsetY * multY * this.scaleY; + }, + _removeShadow: function(ctx) { + if (!this.shadow) { + return; + } + ctx.shadowColor = ""; + ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; + }, + _renderFill: function(ctx) { + if (!this.fill) { + return; + } + ctx.save(); + if (this.fill.gradientTransform) { + var g = this.fill.gradientTransform; + ctx.transform.apply(ctx, g); + } + if (this.fill.toLive) { + ctx.translate(-this.width / 2 + this.fill.offsetX || 0, -this.height / 2 + this.fill.offsetY || 0); + } + if (this.fillRule === "evenodd") { + ctx.fill("evenodd"); + } else { + ctx.fill(); + } + ctx.restore(); + }, + _renderStroke: function(ctx) { + if (!this.stroke || this.strokeWidth === 0) { + return; + } + if (this.shadow && !this.shadow.affectStroke) { + this._removeShadow(ctx); + } + ctx.save(); + if (this.strokeDashArray) { + if (1 & this.strokeDashArray.length) { + this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray); + } + if (supportsLineDash) { + ctx.setLineDash(this.strokeDashArray); + this._stroke && this._stroke(ctx); + } else { + this._renderDashedStroke && this._renderDashedStroke(ctx); + } + ctx.stroke(); + } else { + if (this.stroke.gradientTransform) { + var g = this.stroke.gradientTransform; + ctx.transform.apply(ctx, g); + } + this._stroke ? this._stroke(ctx) : ctx.stroke(); + } + ctx.restore(); + }, + clone: function(callback, propertiesToInclude) { + if (this.constructor.fromObject) { + return this.constructor.fromObject(this.toObject(propertiesToInclude), callback); + } + return new fabric.Object(this.toObject(propertiesToInclude)); + }, + cloneAsImage: function(callback) { + var dataUrl = this.toDataURL(); + fabric.util.loadImage(dataUrl, function(img) { + if (callback) { + callback(new fabric.Image(img)); + } + }); + return this; + }, + toDataURL: function(options) { + options || (options = {}); + var el = fabric.util.createCanvasElement(), boundingRect = this.getBoundingRect(); + el.width = boundingRect.width; + el.height = boundingRect.height; + fabric.util.wrapElement(el, "div"); + var canvas = new fabric.StaticCanvas(el); + if (options.format === "jpg") { + options.format = "jpeg"; + } + if (options.format === "jpeg") { + canvas.backgroundColor = "#fff"; + } + var origParams = { + active: this.get("active"), + left: this.getLeft(), + top: this.getTop() + }; + this.set("active", false); + this.setPositionByOrigin(new fabric.Point(el.width / 2, el.height / 2), "center", "center"); + var originalCanvas = this.canvas; + canvas.add(this); + var data = canvas.toDataURL(options); + this.set(origParams).setCoords(); + this.canvas = originalCanvas; + canvas.dispose(); + canvas = null; + return data; + }, + isType: function(type) { + return this.type === type; + }, + complexity: function() { + return 0; + }, + toJSON: function(propertiesToInclude) { + return this.toObject(propertiesToInclude); + }, + setGradient: function(property, options) { + options || (options = {}); + var gradient = { + colorStops: [] + }; + gradient.type = options.type || (options.r1 || options.r2 ? "radial" : "linear"); + gradient.coords = { + x1: options.x1, + y1: options.y1, + x2: options.x2, + y2: options.y2 + }; + if (options.r1 || options.r2) { + gradient.coords.r1 = options.r1; + gradient.coords.r2 = options.r2; + } + options.gradientTransform && (gradient.gradientTransform = options.gradientTransform); + for (var position in options.colorStops) { + var color = new fabric.Color(options.colorStops[position]); + gradient.colorStops.push({ + offset: position, + color: color.toRgb(), + opacity: color.getAlpha() + }); + } + return this.set(property, fabric.Gradient.forObject(this, gradient)); + }, + setPatternFill: function(options) { + return this.set("fill", new fabric.Pattern(options)); + }, + setShadow: function(options) { + return this.set("shadow", options ? new fabric.Shadow(options) : null); + }, + setColor: function(color) { + this.set("fill", color); + return this; + }, + setAngle: function(angle) { + var shouldCenterOrigin = (this.originX !== "center" || this.originY !== "center") && this.centeredRotation; + if (shouldCenterOrigin) { + this._setOriginToCenter(); + } + this.set("angle", angle); + if (shouldCenterOrigin) { + this._resetOrigin(); + } + return this; + }, + centerH: function() { + this.canvas.centerObjectH(this); + return this; + }, + centerV: function() { + this.canvas.centerObjectV(this); + return this; + }, + center: function() { + this.canvas.centerObject(this); + return this; + }, + remove: function() { + this.canvas.remove(this); + return this; + }, + getLocalPointer: function(e, pointer) { + pointer = pointer || this.canvas.getPointer(e); + var pClicked = new fabric.Point(pointer.x, pointer.y), objectLeftTop = this._getLeftTopCoords(); + if (this.angle) { + pClicked = fabric.util.rotatePoint(pClicked, objectLeftTop, fabric.util.degreesToRadians(-this.angle)); + } + return { + x: pClicked.x - objectLeftTop.x, + y: pClicked.y - objectLeftTop.y + }; + }, + _setupCompositeOperation: function(ctx) { + if (this.globalCompositeOperation) { + ctx.globalCompositeOperation = this.globalCompositeOperation; + } + } + }); + fabric.util.createAccessors(fabric.Object); + fabric.Object.prototype.rotate = fabric.Object.prototype.setAngle; + extend(fabric.Object.prototype, fabric.Observable); + fabric.Object.NUM_FRACTION_DIGITS = 2; + fabric.Object.__uid = 0; +})(typeof exports !== "undefined" ? exports : this); + +(function() { + var degreesToRadians = fabric.util.degreesToRadians, originXOffset = { + left: -.5, + center: 0, + right: .5 + }, originYOffset = { + top: -.5, + center: 0, + bottom: .5 + }; + fabric.util.object.extend(fabric.Object.prototype, { + translateToGivenOrigin: function(point, fromOriginX, fromOriginY, toOriginX, toOriginY) { + var x = point.x, y = point.y, offsetX = originXOffset[toOriginX] - originXOffset[fromOriginX], offsetY = originYOffset[toOriginY] - originYOffset[fromOriginY], dim; + if (offsetX || offsetY) { + dim = this._getTransformedDimensions(); + x = point.x + offsetX * dim.x; + y = point.y + offsetY * dim.y; + } + return new fabric.Point(x, y); + }, + translateToCenterPoint: function(point, originX, originY) { + var p = this.translateToGivenOrigin(point, originX, originY, "center", "center"); + if (this.angle) { + return fabric.util.rotatePoint(p, point, degreesToRadians(this.angle)); + } + return p; + }, + translateToOriginPoint: function(center, originX, originY) { + var p = this.translateToGivenOrigin(center, "center", "center", originX, originY); + if (this.angle) { + return fabric.util.rotatePoint(p, center, degreesToRadians(this.angle)); + } + return p; + }, + getCenterPoint: function() { + var leftTop = new fabric.Point(this.left, this.top); + return this.translateToCenterPoint(leftTop, this.originX, this.originY); + }, + getPointByOrigin: function(originX, originY) { + var center = this.getCenterPoint(); + return this.translateToOriginPoint(center, originX, originY); + }, + toLocalPoint: function(point, originX, originY) { + var center = this.getCenterPoint(), p, p2; + if (originX && originY) { + p = this.translateToGivenOrigin(center, "center", "center", originX, originY); + } else { + p = new fabric.Point(this.left, this.top); + } + p2 = new fabric.Point(point.x, point.y); + if (this.angle) { + p2 = fabric.util.rotatePoint(p2, center, -degreesToRadians(this.angle)); + } + return p2.subtractEquals(p); + }, + setPositionByOrigin: function(pos, originX, originY) { + var center = this.translateToCenterPoint(pos, originX, originY), position = this.translateToOriginPoint(center, this.originX, this.originY); + this.set("left", position.x); + this.set("top", position.y); + }, + adjustPosition: function(to) { + var angle = degreesToRadians(this.angle), hypotFull = this.getWidth(), xFull = Math.cos(angle) * hypotFull, yFull = Math.sin(angle) * hypotFull; + this.left += xFull * (originXOffset[to] - originXOffset[this.originX]); + this.top += yFull * (originXOffset[to] - originXOffset[this.originX]); + this.setCoords(); + this.originX = to; + }, + _setOriginToCenter: function() { + this._originalOriginX = this.originX; + this._originalOriginY = this.originY; + var center = this.getCenterPoint(); + this.originX = "center"; + this.originY = "center"; + this.left = center.x; + this.top = center.y; + }, + _resetOrigin: function() { + var originPoint = this.translateToOriginPoint(this.getCenterPoint(), this._originalOriginX, this._originalOriginY); + this.originX = this._originalOriginX; + this.originY = this._originalOriginY; + this.left = originPoint.x; + this.top = originPoint.y; + this._originalOriginX = null; + this._originalOriginY = null; + }, + _getLeftTopCoords: function() { + return this.translateToOriginPoint(this.getCenterPoint(), "left", "top"); + } + }); +})(); + +(function() { + function getCoords(oCoords) { + return [ new fabric.Point(oCoords.tl.x, oCoords.tl.y), new fabric.Point(oCoords.tr.x, oCoords.tr.y), new fabric.Point(oCoords.br.x, oCoords.br.y), new fabric.Point(oCoords.bl.x, oCoords.bl.y) ]; + } + var degreesToRadians = fabric.util.degreesToRadians, multiplyMatrices = fabric.util.multiplyTransformMatrices; + fabric.util.object.extend(fabric.Object.prototype, { + oCoords: null, + intersectsWithRect: function(pointTL, pointBR) { + var oCoords = getCoords(this.oCoords), intersection = fabric.Intersection.intersectPolygonRectangle(oCoords, pointTL, pointBR); + return intersection.status === "Intersection"; + }, + intersectsWithObject: function(other) { + var intersection = fabric.Intersection.intersectPolygonPolygon(getCoords(this.oCoords), getCoords(other.oCoords)); + return intersection.status === "Intersection"; + }, + isContainedWithinObject: function(other) { + var boundingRect = other.getBoundingRect(), point1 = new fabric.Point(boundingRect.left, boundingRect.top), point2 = new fabric.Point(boundingRect.left + boundingRect.width, boundingRect.top + boundingRect.height); + return this.isContainedWithinRect(point1, point2); + }, + isContainedWithinRect: function(pointTL, pointBR) { + var boundingRect = this.getBoundingRect(); + return boundingRect.left >= pointTL.x && boundingRect.left + boundingRect.width <= pointBR.x && boundingRect.top >= pointTL.y && boundingRect.top + boundingRect.height <= pointBR.y; + }, + containsPoint: function(point) { + var lines = this._getImageLines(this.oCoords), xPoints = this._findCrossPoints(point, lines); + return xPoints !== 0 && xPoints % 2 === 1; + }, + _getImageLines: function(oCoords) { + return { + topline: { + o: oCoords.tl, + d: oCoords.tr + }, + rightline: { + o: oCoords.tr, + d: oCoords.br + }, + bottomline: { + o: oCoords.br, + d: oCoords.bl + }, + leftline: { + o: oCoords.bl, + d: oCoords.tl + } + }; + }, + _findCrossPoints: function(point, oCoords) { + var b1, b2, a1, a2, xi, yi, xcount = 0, iLine; + for (var lineKey in oCoords) { + iLine = oCoords[lineKey]; + if (iLine.o.y < point.y && iLine.d.y < point.y) { + continue; + } + if (iLine.o.y >= point.y && iLine.d.y >= point.y) { + continue; + } + if (iLine.o.x === iLine.d.x && iLine.o.x >= point.x) { + xi = iLine.o.x; + yi = point.y; + } else { + b1 = 0; + b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x); + a1 = point.y - b1 * point.x; + a2 = iLine.o.y - b2 * iLine.o.x; + xi = -(a1 - a2) / (b1 - b2); + yi = a1 + b1 * xi; + } + if (xi >= point.x) { + xcount += 1; + } + if (xcount === 2) { + break; + } + } + return xcount; + }, + getBoundingRectWidth: function() { + return this.getBoundingRect().width; + }, + getBoundingRectHeight: function() { + return this.getBoundingRect().height; + }, + getBoundingRect: function() { + this.oCoords || this.setCoords(); + return fabric.util.makeBoundingBoxFromPoints([ this.oCoords.tl, this.oCoords.tr, this.oCoords.br, this.oCoords.bl ]); + }, + getWidth: function() { + return this._getTransformedDimensions().x; + }, + getHeight: function() { + return this._getTransformedDimensions().y; + }, + _constrainScale: function(value) { + if (Math.abs(value) < this.minScaleLimit) { + if (value < 0) { + return -this.minScaleLimit; + } else { + return this.minScaleLimit; + } + } + return value; + }, + scale: function(value) { + value = this._constrainScale(value); + if (value < 0) { + this.flipX = !this.flipX; + this.flipY = !this.flipY; + value *= -1; + } + this.scaleX = value; + this.scaleY = value; + this.setCoords(); + return this; + }, + scaleToWidth: function(value) { + var boundingRectFactor = this.getBoundingRect().width / this.getWidth(); + return this.scale(value / this.width / boundingRectFactor); + }, + scaleToHeight: function(value) { + var boundingRectFactor = this.getBoundingRect().height / this.getHeight(); + return this.scale(value / this.height / boundingRectFactor); + }, + setCoords: function() { + var theta = degreesToRadians(this.angle), vpt = this.getViewportTransform(), dim = this._calculateCurrentDimensions(), currentWidth = dim.x, currentHeight = dim.y; + if (currentWidth < 0) { + currentWidth = Math.abs(currentWidth); + } + var sinTh = Math.sin(theta), cosTh = Math.cos(theta), _angle = currentWidth > 0 ? Math.atan(currentHeight / currentWidth) : 0, _hypotenuse = currentWidth / Math.cos(_angle) / 2, offsetX = Math.cos(_angle + theta) * _hypotenuse, offsetY = Math.sin(_angle + theta) * _hypotenuse, coords = fabric.util.transformPoint(this.getCenterPoint(), vpt), tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY), tr = new fabric.Point(tl.x + currentWidth * cosTh, tl.y + currentWidth * sinTh), bl = new fabric.Point(tl.x - currentHeight * sinTh, tl.y + currentHeight * cosTh), br = new fabric.Point(coords.x + offsetX, coords.y + offsetY), ml = new fabric.Point((tl.x + bl.x) / 2, (tl.y + bl.y) / 2), mt = new fabric.Point((tr.x + tl.x) / 2, (tr.y + tl.y) / 2), mr = new fabric.Point((br.x + tr.x) / 2, (br.y + tr.y) / 2), mb = new fabric.Point((br.x + bl.x) / 2, (br.y + bl.y) / 2), mtr = new fabric.Point(mt.x + sinTh * this.rotatingPointOffset, mt.y - cosTh * this.rotatingPointOffset); + this.oCoords = { + tl: tl, + tr: tr, + br: br, + bl: bl, + ml: ml, + mt: mt, + mr: mr, + mb: mb, + mtr: mtr + }; + this._setCornerCoords && this._setCornerCoords(); + return this; + }, + _calcRotateMatrix: function() { + if (this.angle) { + var theta = degreesToRadians(this.angle), cos = Math.cos(theta), sin = Math.sin(theta); + return [ cos, sin, -sin, cos, 0, 0 ]; + } + return [ 1, 0, 0, 1, 0, 0 ]; + }, + calcTransformMatrix: function() { + var center = this.getCenterPoint(), translateMatrix = [ 1, 0, 0, 1, center.x, center.y ], rotateMatrix = this._calcRotateMatrix(), dimensionMatrix = this._calcDimensionsTransformMatrix(this.skewX, this.skewY, true), matrix = this.group ? this.group.calcTransformMatrix() : [ 1, 0, 0, 1, 0, 0 ]; + matrix = multiplyMatrices(matrix, translateMatrix); + matrix = multiplyMatrices(matrix, rotateMatrix); + matrix = multiplyMatrices(matrix, dimensionMatrix); + return matrix; + }, + _calcDimensionsTransformMatrix: function(skewX, skewY, flipping) { + var skewMatrixX = [ 1, 0, Math.tan(degreesToRadians(skewX)), 1 ], skewMatrixY = [ 1, Math.tan(degreesToRadians(skewY)), 0, 1 ], scaleX = this.scaleX * (flipping && this.flipX ? -1 : 1), scaleY = this.scaleY * (flipping && this.flipY ? -1 : 1), scaleMatrix = [ scaleX, 0, 0, scaleY ], m = multiplyMatrices(scaleMatrix, skewMatrixX, true); + return multiplyMatrices(m, skewMatrixY, true); + } + }); +})(); + +fabric.util.object.extend(fabric.Object.prototype, { + sendToBack: function() { + if (this.group) { + fabric.StaticCanvas.prototype.sendToBack.call(this.group, this); + } else { + this.canvas.sendToBack(this); + } + return this; + }, + bringToFront: function() { + if (this.group) { + fabric.StaticCanvas.prototype.bringToFront.call(this.group, this); + } else { + this.canvas.bringToFront(this); + } + return this; + }, + sendBackwards: function(intersecting) { + if (this.group) { + fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting); + } else { + this.canvas.sendBackwards(this, intersecting); + } + return this; + }, + bringForward: function(intersecting) { + if (this.group) { + fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting); + } else { + this.canvas.bringForward(this, intersecting); + } + return this; + }, + moveTo: function(index) { + if (this.group) { + fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index); + } else { + this.canvas.moveTo(this, index); + } + return this; + } +}); + +fabric.util.object.extend(fabric.Object.prototype, { + getSvgStyles: function(skipShadow) { + var fill = this.fill ? this.fill.toLive ? "url(#SVGID_" + this.fill.id + ")" : this.fill : "none", fillRule = this.fillRule, stroke = this.stroke ? this.stroke.toLive ? "url(#SVGID_" + this.stroke.id + ")" : this.stroke : "none", strokeWidth = this.strokeWidth ? this.strokeWidth : "0", strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(" ") : "none", strokeLineCap = this.strokeLineCap ? this.strokeLineCap : "butt", strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : "miter", strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : "4", opacity = typeof this.opacity !== "undefined" ? this.opacity : "1", visibility = this.visible ? "" : " visibility: hidden;", filter = skipShadow ? "" : this.getSvgFilter(); + return [ "stroke: ", stroke, "; ", "stroke-width: ", strokeWidth, "; ", "stroke-dasharray: ", strokeDashArray, "; ", "stroke-linecap: ", strokeLineCap, "; ", "stroke-linejoin: ", strokeLineJoin, "; ", "stroke-miterlimit: ", strokeMiterLimit, "; ", "fill: ", fill, "; ", "fill-rule: ", fillRule, "; ", "opacity: ", opacity, ";", filter, visibility ].join(""); + }, + getSvgFilter: function() { + return this.shadow ? "filter: url(#SVGID_" + this.shadow.id + ");" : ""; + }, + getSvgTransform: function() { + if (this.group && this.group.type === "path-group") { + return ""; + } + var toFixed = fabric.util.toFixed, angle = this.getAngle(), skewX = this.getSkewX() % 360, skewY = this.getSkewY() % 360, center = this.getCenterPoint(), NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, translatePart = this.type === "path-group" ? "" : "translate(" + toFixed(center.x, NUM_FRACTION_DIGITS) + " " + toFixed(center.y, NUM_FRACTION_DIGITS) + ")", anglePart = angle !== 0 ? " rotate(" + toFixed(angle, NUM_FRACTION_DIGITS) + ")" : "", scalePart = this.scaleX === 1 && this.scaleY === 1 ? "" : " scale(" + toFixed(this.scaleX, NUM_FRACTION_DIGITS) + " " + toFixed(this.scaleY, NUM_FRACTION_DIGITS) + ")", skewXPart = skewX !== 0 ? " skewX(" + toFixed(skewX, NUM_FRACTION_DIGITS) + ")" : "", skewYPart = skewY !== 0 ? " skewY(" + toFixed(skewY, NUM_FRACTION_DIGITS) + ")" : "", addTranslateX = this.type === "path-group" ? this.width : 0, flipXPart = this.flipX ? " matrix(-1 0 0 1 " + addTranslateX + " 0) " : "", addTranslateY = this.type === "path-group" ? this.height : 0, flipYPart = this.flipY ? " matrix(1 0 0 -1 0 " + addTranslateY + ")" : ""; + return [ translatePart, anglePart, scalePart, flipXPart, flipYPart, skewXPart, skewYPart ].join(""); + }, + getSvgTransformMatrix: function() { + return this.transformMatrix ? " matrix(" + this.transformMatrix.join(" ") + ") " : ""; + }, + _createBaseSVGMarkup: function() { + var markup = []; + if (this.fill && this.fill.toLive) { + markup.push(this.fill.toSVG(this, false)); + } + if (this.stroke && this.stroke.toLive) { + markup.push(this.stroke.toSVG(this, false)); + } + if (this.shadow) { + markup.push(this.shadow.toSVG(this)); + } + return markup; + } +}); + +fabric.util.object.extend(fabric.Object.prototype, { + hasStateChanged: function() { + return this.stateProperties.some(function(prop) { + return this.get(prop) !== this.originalState[prop]; + }, this); + }, + saveState: function(options) { + this.stateProperties.forEach(function(prop) { + this.originalState[prop] = this.get(prop); + }, this); + if (options && options.stateProperties) { + options.stateProperties.forEach(function(prop) { + this.originalState[prop] = this.get(prop); + }, this); + } + return this; + }, + setupState: function() { + this.originalState = {}; + this.saveState(); + return this; + } +}); + +(function() { + var degreesToRadians = fabric.util.degreesToRadians, isVML = function() { + return typeof G_vmlCanvasManager !== "undefined"; + }; + fabric.util.object.extend(fabric.Object.prototype, { + _controlsVisibility: null, + _findTargetCorner: function(pointer) { + if (!this.hasControls || !this.active) { + return false; + } + var ex = pointer.x, ey = pointer.y, xPoints, lines; + this.__corner = 0; + for (var i in this.oCoords) { + if (!this.isControlVisible(i)) { + continue; + } + if (i === "mtr" && !this.hasRotatingPoint) { + continue; + } + if (this.get("lockUniScaling") && (i === "mt" || i === "mr" || i === "mb" || i === "ml")) { + continue; + } + lines = this._getImageLines(this.oCoords[i].corner); + xPoints = this._findCrossPoints({ + x: ex, + y: ey + }, lines); + if (xPoints !== 0 && xPoints % 2 === 1) { + this.__corner = i; + return i; + } + } + return false; + }, + _setCornerCoords: function() { + var coords = this.oCoords, newTheta = degreesToRadians(45 - this.angle), cornerHypotenuse = this.cornerSize * .707106, cosHalfOffset = cornerHypotenuse * Math.cos(newTheta), sinHalfOffset = cornerHypotenuse * Math.sin(newTheta), x, y; + for (var point in coords) { + x = coords[point].x; + y = coords[point].y; + coords[point].corner = { + tl: { + x: x - sinHalfOffset, + y: y - cosHalfOffset + }, + tr: { + x: x + cosHalfOffset, + y: y - sinHalfOffset + }, + bl: { + x: x - cosHalfOffset, + y: y + sinHalfOffset + }, + br: { + x: x + sinHalfOffset, + y: y + cosHalfOffset + } + }; + } + }, + _getNonTransformedDimensions: function() { + var strokeWidth = this.strokeWidth, w = this.width, h = this.height, addStrokeToW = true, addStrokeToH = true; + if (this.type === "line" && this.strokeLineCap === "butt") { + addStrokeToH = w; + addStrokeToW = h; + } + if (addStrokeToH) { + h += h < 0 ? -strokeWidth : strokeWidth; + } + if (addStrokeToW) { + w += w < 0 ? -strokeWidth : strokeWidth; + } + return { + x: w, + y: h + }; + }, + _getTransformedDimensions: function(skewX, skewY) { + if (typeof skewX === "undefined") { + skewX = this.skewX; + } + if (typeof skewY === "undefined") { + skewY = this.skewY; + } + var dimensions = this._getNonTransformedDimensions(), dimX = dimensions.x / 2, dimY = dimensions.y / 2, points = [ { + x: -dimX, + y: -dimY + }, { + x: dimX, + y: -dimY + }, { + x: -dimX, + y: dimY + }, { + x: dimX, + y: dimY + } ], i, transformMatrix = this._calcDimensionsTransformMatrix(skewX, skewY, false), bbox; + for (i = 0; i < points.length; i++) { + points[i] = fabric.util.transformPoint(points[i], transformMatrix); + } + bbox = fabric.util.makeBoundingBoxFromPoints(points); + return { + x: bbox.width, + y: bbox.height + }; + }, + _calculateCurrentDimensions: function() { + var vpt = this.getViewportTransform(), dim = this._getTransformedDimensions(), w = dim.x, h = dim.y; + w += 2 * this.padding; + h += 2 * this.padding; + return fabric.util.transformPoint(new fabric.Point(w, h), vpt, true); + }, + drawBorders: function(ctx) { + if (!this.hasBorders) { + return this; + } + var wh = this._calculateCurrentDimensions(), strokeWidth = 1 / this.borderScaleFactor, width = wh.x + strokeWidth, height = wh.y + strokeWidth; + ctx.save(); + ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; + ctx.strokeStyle = this.borderColor; + ctx.lineWidth = strokeWidth; + ctx.strokeRect(-width / 2, -height / 2, width, height); + if (this.hasRotatingPoint && this.isControlVisible("mtr") && !this.get("lockRotation") && this.hasControls) { + var rotateHeight = -height / 2; + ctx.beginPath(); + ctx.moveTo(0, rotateHeight); + ctx.lineTo(0, rotateHeight - this.rotatingPointOffset); + ctx.closePath(); + ctx.stroke(); + } + ctx.restore(); + return this; + }, + drawBordersInGroup: function(ctx, options) { + if (!this.hasBorders) { + return this; + } + var p = this._getNonTransformedDimensions(), matrix = fabric.util.customTransformMatrix(options.scaleX, options.scaleY, options.skewX), wh = fabric.util.transformPoint(p, matrix), strokeWidth = 1 / this.borderScaleFactor, width = wh.x + strokeWidth + 2 * this.padding, height = wh.y + strokeWidth + 2 * this.padding; + ctx.save(); + ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; + ctx.strokeStyle = this.borderColor; + ctx.lineWidth = strokeWidth; + ctx.strokeRect(-width / 2, -height / 2, width, height); + ctx.restore(); + return this; + }, + drawControls: function(ctx) { + if (!this.hasControls) { + return this; + } + var wh = this._calculateCurrentDimensions(), width = wh.x, height = wh.y, scaleOffset = this.cornerSize, left = -(width + scaleOffset) / 2, top = -(height + scaleOffset) / 2, methodName = this.transparentCorners ? "strokeRect" : "fillRect"; + ctx.save(); + ctx.lineWidth = 1; + ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; + ctx.strokeStyle = ctx.fillStyle = this.cornerColor; + this._drawControl("tl", ctx, methodName, left, top); + this._drawControl("tr", ctx, methodName, left + width, top); + this._drawControl("bl", ctx, methodName, left, top + height); + this._drawControl("br", ctx, methodName, left + width, top + height); + if (!this.get("lockUniScaling")) { + this._drawControl("mt", ctx, methodName, left + width / 2, top); + this._drawControl("mb", ctx, methodName, left + width / 2, top + height); + this._drawControl("mr", ctx, methodName, left + width, top + height / 2); + this._drawControl("ml", ctx, methodName, left, top + height / 2); + } + if (this.hasRotatingPoint) { + this._drawControl("mtr", ctx, methodName, left + width / 2, top - this.rotatingPointOffset); + } + ctx.restore(); + return this; + }, + _drawControl: function(control, ctx, methodName, left, top) { + if (!this.isControlVisible(control)) { + return; + } + var size = this.cornerSize; + isVML() || this.transparentCorners || ctx.clearRect(left, top, size, size); + ctx[methodName](left, top, size, size); + }, + isControlVisible: function(controlName) { + return this._getControlsVisibility()[controlName]; + }, + setControlVisible: function(controlName, visible) { + this._getControlsVisibility()[controlName] = visible; + return this; + }, + setControlsVisibility: function(options) { + options || (options = {}); + for (var p in options) { + this.setControlVisible(p, options[p]); + } + return this; + }, + _getControlsVisibility: function() { + if (!this._controlsVisibility) { + this._controlsVisibility = { + tl: true, + tr: true, + br: true, + bl: true, + ml: true, + mt: true, + mr: true, + mb: true, + mtr: true + }; + } + return this._controlsVisibility; + } + }); +})(); + +fabric.util.object.extend(fabric.StaticCanvas.prototype, { + FX_DURATION: 500, + fxCenterObjectH: function(object, callbacks) { + callbacks = callbacks || {}; + var empty = function() {}, onComplete = callbacks.onComplete || empty, onChange = callbacks.onChange || empty, _this = this; + fabric.util.animate({ + startValue: object.get("left"), + endValue: this.getCenter().left, + duration: this.FX_DURATION, + onChange: function(value) { + object.set("left", value); + _this.renderAll(); + onChange(); + }, + onComplete: function() { + object.setCoords(); + onComplete(); + } + }); + return this; + }, + fxCenterObjectV: function(object, callbacks) { + callbacks = callbacks || {}; + var empty = function() {}, onComplete = callbacks.onComplete || empty, onChange = callbacks.onChange || empty, _this = this; + fabric.util.animate({ + startValue: object.get("top"), + endValue: this.getCenter().top, + duration: this.FX_DURATION, + onChange: function(value) { + object.set("top", value); + _this.renderAll(); + onChange(); + }, + onComplete: function() { + object.setCoords(); + onComplete(); + } + }); + return this; + }, + fxRemove: function(object, callbacks) { + callbacks = callbacks || {}; + var empty = function() {}, onComplete = callbacks.onComplete || empty, onChange = callbacks.onChange || empty, _this = this; + fabric.util.animate({ + startValue: object.get("opacity"), + endValue: 0, + duration: this.FX_DURATION, + onStart: function() { + object.set("active", false); + }, + onChange: function(value) { + object.set("opacity", value); + _this.renderAll(); + onChange(); + }, + onComplete: function() { + _this.remove(object); + onComplete(); + } + }); + return this; + } +}); + +fabric.util.object.extend(fabric.Object.prototype, { + animate: function() { + if (arguments[0] && typeof arguments[0] === "object") { + var propsToAnimate = [], prop, skipCallbacks; + for (prop in arguments[0]) { + propsToAnimate.push(prop); + } + for (var i = 0, len = propsToAnimate.length; i < len; i++) { + prop = propsToAnimate[i]; + skipCallbacks = i !== len - 1; + this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks); + } + } else { + this._animate.apply(this, arguments); + } + return this; + }, + _animate: function(property, to, options, skipCallbacks) { + var _this = this, propPair; + to = to.toString(); + if (!options) { + options = {}; + } else { + options = fabric.util.object.clone(options); + } + if (~property.indexOf(".")) { + propPair = property.split("."); + } + var currentValue = propPair ? this.get(propPair[0])[propPair[1]] : this.get(property); + if (!("from" in options)) { + options.from = currentValue; + } + if (~to.indexOf("=")) { + to = currentValue + parseFloat(to.replace("=", "")); + } else { + to = parseFloat(to); + } + fabric.util.animate({ + startValue: options.from, + endValue: to, + byValue: options.by, + easing: options.easing, + duration: options.duration, + abort: options.abort && function() { + return options.abort.call(_this); + }, + onChange: function(value) { + if (propPair) { + _this[propPair[0]][propPair[1]] = value; + } else { + _this.set(property, value); + } + if (skipCallbacks) { + return; + } + options.onChange && options.onChange(); + }, + onComplete: function() { + if (skipCallbacks) { + return; + } + _this.setCoords(); + options.onComplete && options.onComplete(); + } + }); + } +}); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, coordProps = { + x1: 1, + x2: 1, + y1: 1, + y2: 1 + }, supportsLineDash = fabric.StaticCanvas.supports("setLineDash"); + if (fabric.Line) { + fabric.warn("fabric.Line is already defined"); + return; + } + fabric.Line = fabric.util.createClass(fabric.Object, { + type: "line", + x1: 0, + y1: 0, + x2: 0, + y2: 0, + initialize: function(points, options) { + options = options || {}; + if (!points) { + points = [ 0, 0, 0, 0 ]; + } + this.callSuper("initialize", options); + this.set("x1", points[0]); + this.set("y1", points[1]); + this.set("x2", points[2]); + this.set("y2", points[3]); + this._setWidthHeight(options); + }, + _setWidthHeight: function(options) { + options || (options = {}); + this.width = Math.abs(this.x2 - this.x1); + this.height = Math.abs(this.y2 - this.y1); + this.left = "left" in options ? options.left : this._getLeftToOriginX(); + this.top = "top" in options ? options.top : this._getTopToOriginY(); + }, + _set: function(key, value) { + this.callSuper("_set", key, value); + if (typeof coordProps[key] !== "undefined") { + this._setWidthHeight(); + } + return this; + }, + _getLeftToOriginX: makeEdgeToOriginGetter({ + origin: "originX", + axis1: "x1", + axis2: "x2", + dimension: "width" + }, { + nearest: "left", + center: "center", + farthest: "right" + }), + _getTopToOriginY: makeEdgeToOriginGetter({ + origin: "originY", + axis1: "y1", + axis2: "y2", + dimension: "height" + }, { + nearest: "top", + center: "center", + farthest: "bottom" + }), + _render: function(ctx, noTransform) { + ctx.beginPath(); + if (noTransform) { + var cp = this.getCenterPoint(); + ctx.translate(cp.x - this.strokeWidth / 2, cp.y - this.strokeWidth / 2); + } + if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) { + var p = this.calcLinePoints(); + ctx.moveTo(p.x1, p.y1); + ctx.lineTo(p.x2, p.y2); + } + ctx.lineWidth = this.strokeWidth; + var origStrokeStyle = ctx.strokeStyle; + ctx.strokeStyle = this.stroke || ctx.fillStyle; + this.stroke && this._renderStroke(ctx); + ctx.strokeStyle = origStrokeStyle; + }, + _renderDashedStroke: function(ctx) { + var p = this.calcLinePoints(); + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, p.x1, p.y1, p.x2, p.y2, this.strokeDashArray); + ctx.closePath(); + }, + toObject: function(propertiesToInclude) { + return extend(this.callSuper("toObject", propertiesToInclude), this.calcLinePoints()); + }, + calcLinePoints: function() { + var xMult = this.x1 <= this.x2 ? -1 : 1, yMult = this.y1 <= this.y2 ? -1 : 1, x1 = xMult * this.width * .5, y1 = yMult * this.height * .5, x2 = xMult * this.width * -.5, y2 = yMult * this.height * -.5; + return { + x1: x1, + x2: x2, + y1: y1, + y2: y2 + }; + }, + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), p = { + x1: this.x1, + x2: this.x2, + y1: this.y1, + y2: this.y2 + }; + if (!(this.group && this.group.type === "path-group")) { + p = this.calcLinePoints(); + } + markup.push("\n'); + return reviver ? reviver(markup.join("")) : markup.join(""); + }, + complexity: function() { + return 1; + } + }); + fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" ")); + fabric.Line.fromElement = function(element, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES), points = [ parsedAttributes.x1 || 0, parsedAttributes.y1 || 0, parsedAttributes.x2 || 0, parsedAttributes.y2 || 0 ]; + return new fabric.Line(points, extend(parsedAttributes, options)); + }; + fabric.Line.fromObject = function(object) { + var points = [ object.x1, object.y1, object.x2, object.y2 ]; + return new fabric.Line(points, object); + }; + function makeEdgeToOriginGetter(propertyNames, originValues) { + var origin = propertyNames.origin, axis1 = propertyNames.axis1, axis2 = propertyNames.axis2, dimension = propertyNames.dimension, nearest = originValues.nearest, center = originValues.center, farthest = originValues.farthest; + return function() { + switch (this.get(origin)) { + case nearest: + return Math.min(this.get(axis1), this.get(axis2)); + + case center: + return Math.min(this.get(axis1), this.get(axis2)) + .5 * this.get(dimension); + + case farthest: + return Math.max(this.get(axis1), this.get(axis2)); + } + }; + } +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), pi = Math.PI, extend = fabric.util.object.extend; + if (fabric.Circle) { + fabric.warn("fabric.Circle is already defined."); + return; + } + fabric.Circle = fabric.util.createClass(fabric.Object, { + type: "circle", + radius: 0, + startAngle: 0, + endAngle: pi * 2, + initialize: function(options) { + options = options || {}; + this.callSuper("initialize", options); + this.set("radius", options.radius || 0); + this.startAngle = options.startAngle || this.startAngle; + this.endAngle = options.endAngle || this.endAngle; + }, + _set: function(key, value) { + this.callSuper("_set", key, value); + if (key === "radius") { + this.setRadius(value); + } + return this; + }, + toObject: function(propertiesToInclude) { + return extend(this.callSuper("toObject", propertiesToInclude), { + radius: this.get("radius"), + startAngle: this.startAngle, + endAngle: this.endAngle + }); + }, + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), x = 0, y = 0, angle = (this.endAngle - this.startAngle) % (2 * pi); + if (angle === 0) { + if (this.group && this.group.type === "path-group") { + x = this.left + this.radius; + y = this.top + this.radius; + } + markup.push("\n'); + } else { + var startX = Math.cos(this.startAngle) * this.radius, startY = Math.sin(this.startAngle) * this.radius, endX = Math.cos(this.endAngle) * this.radius, endY = Math.sin(this.endAngle) * this.radius, largeFlag = angle > pi ? "1" : "0"; + markup.push('\n'); + } + return reviver ? reviver(markup.join("")) : markup.join(""); + }, + _render: function(ctx, noTransform) { + ctx.beginPath(); + ctx.arc(noTransform ? this.left + this.radius : 0, noTransform ? this.top + this.radius : 0, this.radius, this.startAngle, this.endAngle, false); + this._renderFill(ctx); + this._renderStroke(ctx); + }, + getRadiusX: function() { + return this.get("radius") * this.get("scaleX"); + }, + getRadiusY: function() { + return this.get("radius") * this.get("scaleY"); + }, + setRadius: function(value) { + this.radius = value; + return this.set("width", value * 2).set("height", value * 2); + }, + complexity: function() { + return 1; + } + }); + fabric.Circle.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat("cx cy r".split(" ")); + fabric.Circle.fromElement = function(element, options) { + options || (options = {}); + var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES); + if (!isValidRadius(parsedAttributes)) { + throw new Error("value of `r` attribute is required and can not be negative"); + } + parsedAttributes.left = parsedAttributes.left || 0; + parsedAttributes.top = parsedAttributes.top || 0; + var obj = new fabric.Circle(extend(parsedAttributes, options)); + obj.left -= obj.radius; + obj.top -= obj.radius; + return obj; + }; + function isValidRadius(attributes) { + return "radius" in attributes && attributes.radius >= 0; + } + fabric.Circle.fromObject = function(object) { + return new fabric.Circle(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}); + if (fabric.Triangle) { + fabric.warn("fabric.Triangle is already defined"); + return; + } + fabric.Triangle = fabric.util.createClass(fabric.Object, { + type: "triangle", + initialize: function(options) { + options = options || {}; + this.callSuper("initialize", options); + this.set("width", options.width || 100).set("height", options.height || 100); + }, + _render: function(ctx) { + var widthBy2 = this.width / 2, heightBy2 = this.height / 2; + ctx.beginPath(); + ctx.moveTo(-widthBy2, heightBy2); + ctx.lineTo(0, -heightBy2); + ctx.lineTo(widthBy2, heightBy2); + ctx.closePath(); + this._renderFill(ctx); + this._renderStroke(ctx); + }, + _renderDashedStroke: function(ctx) { + var widthBy2 = this.width / 2, heightBy2 = this.height / 2; + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray); + ctx.closePath(); + }, + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), widthBy2 = this.width / 2, heightBy2 = this.height / 2, points = [ -widthBy2 + " " + heightBy2, "0 " + -heightBy2, widthBy2 + " " + heightBy2 ].join(","); + markup.push("'); + return reviver ? reviver(markup.join("")) : markup.join(""); + }, + complexity: function() { + return 1; + } + }); + fabric.Triangle.fromObject = function(object) { + return new fabric.Triangle(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), piBy2 = Math.PI * 2, extend = fabric.util.object.extend; + if (fabric.Ellipse) { + fabric.warn("fabric.Ellipse is already defined."); + return; + } + fabric.Ellipse = fabric.util.createClass(fabric.Object, { + type: "ellipse", + rx: 0, + ry: 0, + initialize: function(options) { + options = options || {}; + this.callSuper("initialize", options); + this.set("rx", options.rx || 0); + this.set("ry", options.ry || 0); + }, + _set: function(key, value) { + this.callSuper("_set", key, value); + switch (key) { + case "rx": + this.rx = value; + this.set("width", value * 2); + break; + + case "ry": + this.ry = value; + this.set("height", value * 2); + break; + } + return this; + }, + getRx: function() { + return this.get("rx") * this.get("scaleX"); + }, + getRy: function() { + return this.get("ry") * this.get("scaleY"); + }, + toObject: function(propertiesToInclude) { + return extend(this.callSuper("toObject", propertiesToInclude), { + rx: this.get("rx"), + ry: this.get("ry") + }); + }, + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), x = 0, y = 0; + if (this.group && this.group.type === "path-group") { + x = this.left + this.rx; + y = this.top + this.ry; + } + markup.push("\n'); + return reviver ? reviver(markup.join("")) : markup.join(""); + }, + _render: function(ctx, noTransform) { + ctx.beginPath(); + ctx.save(); + ctx.transform(1, 0, 0, this.ry / this.rx, 0, 0); + ctx.arc(noTransform ? this.left + this.rx : 0, noTransform ? (this.top + this.ry) * this.rx / this.ry : 0, this.rx, 0, piBy2, false); + ctx.restore(); + this._renderFill(ctx); + this._renderStroke(ctx); + }, + complexity: function() { + return 1; + } + }); + fabric.Ellipse.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" ")); + fabric.Ellipse.fromElement = function(element, options) { + options || (options = {}); + var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES); + parsedAttributes.left = parsedAttributes.left || 0; + parsedAttributes.top = parsedAttributes.top || 0; + var ellipse = new fabric.Ellipse(extend(parsedAttributes, options)); + ellipse.top -= ellipse.ry; + ellipse.left -= ellipse.rx; + return ellipse; + }; + fabric.Ellipse.fromObject = function(object) { + return new fabric.Ellipse(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend; + if (fabric.Rect) { + fabric.warn("fabric.Rect is already defined"); + return; + } + var stateProperties = fabric.Object.prototype.stateProperties.concat(); + stateProperties.push("rx", "ry", "x", "y"); + fabric.Rect = fabric.util.createClass(fabric.Object, { + stateProperties: stateProperties, + type: "rect", + rx: 0, + ry: 0, + strokeDashArray: null, + initialize: function(options) { + options = options || {}; + this.callSuper("initialize", options); + this._initRxRy(); + }, + _initRxRy: function() { + if (this.rx && !this.ry) { + this.ry = this.rx; + } else if (this.ry && !this.rx) { + this.rx = this.ry; + } + }, + _render: function(ctx, noTransform) { + if (this.width === 1 && this.height === 1) { + ctx.fillRect(-.5, -.5, 1, 1); + return; + } + var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0, ry = this.ry ? Math.min(this.ry, this.height / 2) : 0, w = this.width, h = this.height, x = noTransform ? this.left : -this.width / 2, y = noTransform ? this.top : -this.height / 2, isRounded = rx !== 0 || ry !== 0, k = 1 - .5522847498; + ctx.beginPath(); + ctx.moveTo(x + rx, y); + ctx.lineTo(x + w - rx, y); + isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry); + ctx.lineTo(x + w, y + h - ry); + isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h); + ctx.lineTo(x + rx, y + h); + isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry); + ctx.lineTo(x, y + ry); + isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y); + ctx.closePath(); + this._renderFill(ctx); + this._renderStroke(ctx); + }, + _renderDashedStroke: function(ctx) { + var x = -this.width / 2, y = -this.height / 2, w = this.width, h = this.height; + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray); + ctx.closePath(); + }, + toObject: function(propertiesToInclude) { + var object = extend(this.callSuper("toObject", propertiesToInclude), { + rx: this.get("rx") || 0, + ry: this.get("ry") || 0 + }); + if (!this.includeDefaultValues) { + this._removeDefaultValues(object); + } + return object; + }, + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), x = this.left, y = this.top; + if (!(this.group && this.group.type === "path-group")) { + x = -this.width / 2; + y = -this.height / 2; + } + markup.push("\n'); + return reviver ? reviver(markup.join("")) : markup.join(""); + }, + complexity: function() { + return 1; + } + }); + fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" ")); + fabric.Rect.fromElement = function(element, options) { + if (!element) { + return null; + } + options = options || {}; + var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES); + parsedAttributes.left = parsedAttributes.left || 0; + parsedAttributes.top = parsedAttributes.top || 0; + var rect = new fabric.Rect(extend(options ? fabric.util.object.clone(options) : {}, parsedAttributes)); + rect.visible = rect.width > 0 && rect.height > 0; + return rect; + }; + fabric.Rect.fromObject = function(object) { + return new fabric.Rect(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}); + if (fabric.Polyline) { + fabric.warn("fabric.Polyline is already defined"); + return; + } + fabric.Polyline = fabric.util.createClass(fabric.Object, { + type: "polyline", + points: null, + minX: 0, + minY: 0, + initialize: function(points, options) { + return fabric.Polygon.prototype.initialize.call(this, points, options); + }, + _calcDimensions: function() { + return fabric.Polygon.prototype._calcDimensions.call(this); + }, + _applyPointOffset: function() { + return fabric.Polygon.prototype._applyPointOffset.call(this); + }, + toObject: function(propertiesToInclude) { + return fabric.Polygon.prototype.toObject.call(this, propertiesToInclude); + }, + toSVG: function(reviver) { + return fabric.Polygon.prototype.toSVG.call(this, reviver); + }, + _render: function(ctx, noTransform) { + if (!fabric.Polygon.prototype.commonRender.call(this, ctx, noTransform)) { + return; + } + this._renderFill(ctx); + this._renderStroke(ctx); + }, + _renderDashedStroke: function(ctx) { + var p1, p2; + ctx.beginPath(); + for (var i = 0, len = this.points.length; i < len; i++) { + p1 = this.points[i]; + p2 = this.points[i + 1] || p1; + fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray); + } + }, + complexity: function() { + return this.get("points").length; + } + }); + fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); + fabric.Polyline.fromElement = function(element, options) { + if (!element) { + return null; + } + options || (options = {}); + var points = fabric.parsePointsAttribute(element.getAttribute("points")), parsedAttributes = fabric.parseAttributes(element, fabric.Polyline.ATTRIBUTE_NAMES); + return new fabric.Polyline(points, fabric.util.object.extend(parsedAttributes, options)); + }; + fabric.Polyline.fromObject = function(object) { + var points = object.points; + return new fabric.Polyline(points, object, true); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, min = fabric.util.array.min, max = fabric.util.array.max, toFixed = fabric.util.toFixed; + if (fabric.Polygon) { + fabric.warn("fabric.Polygon is already defined"); + return; + } + fabric.Polygon = fabric.util.createClass(fabric.Object, { + type: "polygon", + points: null, + minX: 0, + minY: 0, + initialize: function(points, options) { + options = options || {}; + this.points = points || []; + this.callSuper("initialize", options); + this._calcDimensions(); + if (!("top" in options)) { + this.top = this.minY; + } + if (!("left" in options)) { + this.left = this.minX; + } + this.pathOffset = { + x: this.minX + this.width / 2, + y: this.minY + this.height / 2 + }; + }, + _calcDimensions: function() { + var points = this.points, minX = min(points, "x"), minY = min(points, "y"), maxX = max(points, "x"), maxY = max(points, "y"); + this.width = maxX - minX || 0; + this.height = maxY - minY || 0; + this.minX = minX || 0, this.minY = minY || 0; + }, + toObject: function(propertiesToInclude) { + return extend(this.callSuper("toObject", propertiesToInclude), { + points: this.points.concat() + }); + }, + toSVG: function(reviver) { + var points = [], addTransform, markup = this._createBaseSVGMarkup(); + for (var i = 0, len = this.points.length; i < len; i++) { + points.push(toFixed(this.points[i].x, 2), ",", toFixed(this.points[i].y, 2), " "); + } + if (!(this.group && this.group.type === "path-group")) { + addTransform = " translate(" + -this.pathOffset.x + ", " + -this.pathOffset.y + ") "; + } + markup.push("<", this.type, " ", 'points="', points.join(""), '" style="', this.getSvgStyles(), '" transform="', this.getSvgTransform(), addTransform, " ", this.getSvgTransformMatrix(), '"/>\n'); + return reviver ? reviver(markup.join("")) : markup.join(""); + }, + _render: function(ctx, noTransform) { + if (!this.commonRender(ctx, noTransform)) { + return; + } + this._renderFill(ctx); + if (this.stroke || this.strokeDashArray) { + ctx.closePath(); + this._renderStroke(ctx); + } + }, + commonRender: function(ctx, noTransform) { + var point, len = this.points.length; + if (!len || isNaN(this.points[len - 1].y)) { + return false; + } + noTransform || ctx.translate(-this.pathOffset.x, -this.pathOffset.y); + ctx.beginPath(); + ctx.moveTo(this.points[0].x, this.points[0].y); + for (var i = 0; i < len; i++) { + point = this.points[i]; + ctx.lineTo(point.x, point.y); + } + return true; + }, + _renderDashedStroke: function(ctx) { + fabric.Polyline.prototype._renderDashedStroke.call(this, ctx); + ctx.closePath(); + }, + complexity: function() { + return this.points.length; + } + }); + fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); + fabric.Polygon.fromElement = function(element, options) { + if (!element) { + return null; + } + options || (options = {}); + var points = fabric.parsePointsAttribute(element.getAttribute("points")), parsedAttributes = fabric.parseAttributes(element, fabric.Polygon.ATTRIBUTE_NAMES); + return new fabric.Polygon(points, extend(parsedAttributes, options)); + }; + fabric.Polygon.fromObject = function(object) { + return new fabric.Polygon(object.points, object, true); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), min = fabric.util.array.min, max = fabric.util.array.max, extend = fabric.util.object.extend, _toString = Object.prototype.toString, drawArc = fabric.util.drawArc, commandLengths = { + m: 2, + l: 2, + h: 1, + v: 1, + c: 6, + s: 4, + q: 4, + t: 2, + a: 7 + }, repeatedCommands = { + m: "l", + M: "L" + }; + if (fabric.Path) { + fabric.warn("fabric.Path is already defined"); + return; + } + fabric.Path = fabric.util.createClass(fabric.Object, { + type: "path", + path: null, + minX: 0, + minY: 0, + initialize: function(path, options) { + options = options || {}; + this.setOptions(options); + if (!path) { + path = []; + } + var fromArray = _toString.call(path) === "[object Array]"; + this.path = fromArray ? path : path.match && path.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi); + if (!this.path) { + return; + } + if (!fromArray) { + this.path = this._parsePath(); + } + this._setPositionDimensions(options); + if (options.sourcePath) { + this.setSourcePath(options.sourcePath); + } + }, + _setPositionDimensions: function(options) { + var calcDim = this._parseDimensions(); + this.minX = calcDim.left; + this.minY = calcDim.top; + this.width = calcDim.width; + this.height = calcDim.height; + if (typeof options.left === "undefined") { + this.left = calcDim.left + (this.originX === "center" ? this.width / 2 : this.originX === "right" ? this.width : 0); + } + if (typeof options.top === "undefined") { + this.top = calcDim.top + (this.originY === "center" ? this.height / 2 : this.originY === "bottom" ? this.height : 0); + } + this.pathOffset = this.pathOffset || { + x: this.minX + this.width / 2, + y: this.minY + this.height / 2 + }; + }, + _render: function(ctx) { + var current, previous = null, subpathStartX = 0, subpathStartY = 0, x = 0, y = 0, controlX = 0, controlY = 0, tempX, tempY, l = -this.pathOffset.x, t = -this.pathOffset.y; + if (this.group && this.group.type === "path-group") { + l = 0; + t = 0; + } + ctx.beginPath(); + for (var i = 0, len = this.path.length; i < len; ++i) { + current = this.path[i]; + switch (current[0]) { + case "l": + x += current[1]; + y += current[2]; + ctx.lineTo(x + l, y + t); + break; + + case "L": + x = current[1]; + y = current[2]; + ctx.lineTo(x + l, y + t); + break; + + case "h": + x += current[1]; + ctx.lineTo(x + l, y + t); + break; + + case "H": + x = current[1]; + ctx.lineTo(x + l, y + t); + break; + + case "v": + y += current[1]; + ctx.lineTo(x + l, y + t); + break; + + case "V": + y = current[1]; + ctx.lineTo(x + l, y + t); + break; + + case "m": + x += current[1]; + y += current[2]; + subpathStartX = x; + subpathStartY = y; + ctx.moveTo(x + l, y + t); + break; + + case "M": + x = current[1]; + y = current[2]; + subpathStartX = x; + subpathStartY = y; + ctx.moveTo(x + l, y + t); + break; + + case "c": + tempX = x + current[5]; + tempY = y + current[6]; + controlX = x + current[3]; + controlY = y + current[4]; + ctx.bezierCurveTo(x + current[1] + l, y + current[2] + t, controlX + l, controlY + t, tempX + l, tempY + t); + x = tempX; + y = tempY; + break; + + case "C": + x = current[5]; + y = current[6]; + controlX = current[3]; + controlY = current[4]; + ctx.bezierCurveTo(current[1] + l, current[2] + t, controlX + l, controlY + t, x + l, y + t); + break; + + case "s": + tempX = x + current[3]; + tempY = y + current[4]; + if (previous[0].match(/[CcSs]/) === null) { + controlX = x; + controlY = y; + } else { + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + } + ctx.bezierCurveTo(controlX + l, controlY + t, x + current[1] + l, y + current[2] + t, tempX + l, tempY + t); + controlX = x + current[1]; + controlY = y + current[2]; + x = tempX; + y = tempY; + break; + + case "S": + tempX = current[3]; + tempY = current[4]; + if (previous[0].match(/[CcSs]/) === null) { + controlX = x; + controlY = y; + } else { + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + } + ctx.bezierCurveTo(controlX + l, controlY + t, current[1] + l, current[2] + t, tempX + l, tempY + t); + x = tempX; + y = tempY; + controlX = current[1]; + controlY = current[2]; + break; + + case "q": + tempX = x + current[3]; + tempY = y + current[4]; + controlX = x + current[1]; + controlY = y + current[2]; + ctx.quadraticCurveTo(controlX + l, controlY + t, tempX + l, tempY + t); + x = tempX; + y = tempY; + break; + + case "Q": + tempX = current[3]; + tempY = current[4]; + ctx.quadraticCurveTo(current[1] + l, current[2] + t, tempX + l, tempY + t); + x = tempX; + y = tempY; + controlX = current[1]; + controlY = current[2]; + break; + + case "t": + tempX = x + current[1]; + tempY = y + current[2]; + if (previous[0].match(/[QqTt]/) === null) { + controlX = x; + controlY = y; + } else { + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + } + ctx.quadraticCurveTo(controlX + l, controlY + t, tempX + l, tempY + t); + x = tempX; + y = tempY; + break; + + case "T": + tempX = current[1]; + tempY = current[2]; + if (previous[0].match(/[QqTt]/) === null) { + controlX = x; + controlY = y; + } else { + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + } + ctx.quadraticCurveTo(controlX + l, controlY + t, tempX + l, tempY + t); + x = tempX; + y = tempY; + break; + + case "a": + drawArc(ctx, x + l, y + t, [ current[1], current[2], current[3], current[4], current[5], current[6] + x + l, current[7] + y + t ]); + x += current[6]; + y += current[7]; + break; + + case "A": + drawArc(ctx, x + l, y + t, [ current[1], current[2], current[3], current[4], current[5], current[6] + l, current[7] + t ]); + x = current[6]; + y = current[7]; + break; + + case "z": + case "Z": + x = subpathStartX; + y = subpathStartY; + ctx.closePath(); + break; + } + previous = current; + } + this._renderFill(ctx); + this._renderStroke(ctx); + }, + toString: function() { + return "#"; + }, + toObject: function(propertiesToInclude) { + var o = extend(this.callSuper("toObject", propertiesToInclude), { + path: this.path.map(function(item) { + return item.slice(); + }), + pathOffset: this.pathOffset + }); + if (this.sourcePath) { + o.sourcePath = this.sourcePath; + } + if (this.transformMatrix) { + o.transformMatrix = this.transformMatrix; + } + return o; + }, + toDatalessObject: function(propertiesToInclude) { + var o = this.toObject(propertiesToInclude); + if (this.sourcePath) { + o.path = this.sourcePath; + } + delete o.sourcePath; + return o; + }, + toSVG: function(reviver) { + var chunks = [], markup = this._createBaseSVGMarkup(), addTransform = ""; + for (var i = 0, len = this.path.length; i < len; i++) { + chunks.push(this.path[i].join(" ")); + } + var path = chunks.join(" "); + if (!(this.group && this.group.type === "path-group")) { + addTransform = " translate(" + -this.pathOffset.x + ", " + -this.pathOffset.y + ") "; + } + markup.push("\n"); + return reviver ? reviver(markup.join("")) : markup.join(""); + }, + complexity: function() { + return this.path.length; + }, + _parsePath: function() { + var result = [], coords = [], currentPath, parsed, re = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/gi, match, coordsStr; + for (var i = 0, coordsParsed, len = this.path.length; i < len; i++) { + currentPath = this.path[i]; + coordsStr = currentPath.slice(1).trim(); + coords.length = 0; + while (match = re.exec(coordsStr)) { + coords.push(match[0]); + } + coordsParsed = [ currentPath.charAt(0) ]; + for (var j = 0, jlen = coords.length; j < jlen; j++) { + parsed = parseFloat(coords[j]); + if (!isNaN(parsed)) { + coordsParsed.push(parsed); + } + } + var command = coordsParsed[0], commandLength = commandLengths[command.toLowerCase()], repeatedCommand = repeatedCommands[command] || command; + if (coordsParsed.length - 1 > commandLength) { + for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) { + result.push([ command ].concat(coordsParsed.slice(k, k + commandLength))); + command = repeatedCommand; + } + } else { + result.push(coordsParsed); + } + } + return result; + }, + _parseDimensions: function() { + var aX = [], aY = [], current, previous = null, subpathStartX = 0, subpathStartY = 0, x = 0, y = 0, controlX = 0, controlY = 0, tempX, tempY, bounds; + for (var i = 0, len = this.path.length; i < len; ++i) { + current = this.path[i]; + switch (current[0]) { + case "l": + x += current[1]; + y += current[2]; + bounds = []; + break; + + case "L": + x = current[1]; + y = current[2]; + bounds = []; + break; + + case "h": + x += current[1]; + bounds = []; + break; + + case "H": + x = current[1]; + bounds = []; + break; + + case "v": + y += current[1]; + bounds = []; + break; + + case "V": + y = current[1]; + bounds = []; + break; + + case "m": + x += current[1]; + y += current[2]; + subpathStartX = x; + subpathStartY = y; + bounds = []; + break; + + case "M": + x = current[1]; + y = current[2]; + subpathStartX = x; + subpathStartY = y; + bounds = []; + break; + + case "c": + tempX = x + current[5]; + tempY = y + current[6]; + controlX = x + current[3]; + controlY = y + current[4]; + bounds = fabric.util.getBoundsOfCurve(x, y, x + current[1], y + current[2], controlX, controlY, tempX, tempY); + x = tempX; + y = tempY; + break; + + case "C": + x = current[5]; + y = current[6]; + controlX = current[3]; + controlY = current[4]; + bounds = fabric.util.getBoundsOfCurve(x, y, current[1], current[2], controlX, controlY, x, y); + break; + + case "s": + tempX = x + current[3]; + tempY = y + current[4]; + if (previous[0].match(/[CcSs]/) === null) { + controlX = x; + controlY = y; + } else { + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + } + bounds = fabric.util.getBoundsOfCurve(x, y, controlX, controlY, x + current[1], y + current[2], tempX, tempY); + controlX = x + current[1]; + controlY = y + current[2]; + x = tempX; + y = tempY; + break; + + case "S": + tempX = current[3]; + tempY = current[4]; + if (previous[0].match(/[CcSs]/) === null) { + controlX = x; + controlY = y; + } else { + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + } + bounds = fabric.util.getBoundsOfCurve(x, y, controlX, controlY, current[1], current[2], tempX, tempY); + x = tempX; + y = tempY; + controlX = current[1]; + controlY = current[2]; + break; + + case "q": + tempX = x + current[3]; + tempY = y + current[4]; + controlX = x + current[1]; + controlY = y + current[2]; + bounds = fabric.util.getBoundsOfCurve(x, y, controlX, controlY, controlX, controlY, tempX, tempY); + x = tempX; + y = tempY; + break; + + case "Q": + controlX = current[1]; + controlY = current[2]; + bounds = fabric.util.getBoundsOfCurve(x, y, controlX, controlY, controlX, controlY, current[3], current[4]); + x = current[3]; + y = current[4]; + break; + + case "t": + tempX = x + current[1]; + tempY = y + current[2]; + if (previous[0].match(/[QqTt]/) === null) { + controlX = x; + controlY = y; + } else { + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + } + bounds = fabric.util.getBoundsOfCurve(x, y, controlX, controlY, controlX, controlY, tempX, tempY); + x = tempX; + y = tempY; + break; + + case "T": + tempX = current[1]; + tempY = current[2]; + if (previous[0].match(/[QqTt]/) === null) { + controlX = x; + controlY = y; + } else { + controlX = 2 * x - controlX; + controlY = 2 * y - controlY; + } + bounds = fabric.util.getBoundsOfCurve(x, y, controlX, controlY, controlX, controlY, tempX, tempY); + x = tempX; + y = tempY; + break; + + case "a": + bounds = fabric.util.getBoundsOfArc(x, y, current[1], current[2], current[3], current[4], current[5], current[6] + x, current[7] + y); + x += current[6]; + y += current[7]; + break; + + case "A": + bounds = fabric.util.getBoundsOfArc(x, y, current[1], current[2], current[3], current[4], current[5], current[6], current[7]); + x = current[6]; + y = current[7]; + break; + + case "z": + case "Z": + x = subpathStartX; + y = subpathStartY; + break; + } + previous = current; + bounds.forEach(function(point) { + aX.push(point.x); + aY.push(point.y); + }); + aX.push(x); + aY.push(y); + } + var minX = min(aX) || 0, minY = min(aY) || 0, maxX = max(aX) || 0, maxY = max(aY) || 0, deltaX = maxX - minX, deltaY = maxY - minY, o = { + left: minX, + top: minY, + width: deltaX, + height: deltaY + }; + return o; + } + }); + fabric.Path.fromObject = function(object, callback) { + if (typeof object.path === "string") { + fabric.loadSVGFromURL(object.path, function(elements) { + var path = elements[0], pathUrl = object.path; + delete object.path; + fabric.util.object.extend(path, object); + path.setSourcePath(pathUrl); + callback(path); + }); + } else { + callback(new fabric.Path(object.path, object)); + } + }; + fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat([ "d" ]); + fabric.Path.fromElement = function(element, callback, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES); + callback && callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options))); + }; + fabric.Path.async = true; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, invoke = fabric.util.array.invoke, parentToObject = fabric.Object.prototype.toObject; + if (fabric.PathGroup) { + fabric.warn("fabric.PathGroup is already defined"); + return; + } + fabric.PathGroup = fabric.util.createClass(fabric.Path, { + type: "path-group", + fill: "", + initialize: function(paths, options) { + options = options || {}; + this.paths = paths || []; + for (var i = this.paths.length; i--; ) { + this.paths[i].group = this; + } + if (options.toBeParsed) { + this.parseDimensionsFromPaths(options); + delete options.toBeParsed; + } + this.setOptions(options); + this.setCoords(); + if (options.sourcePath) { + this.setSourcePath(options.sourcePath); + } + }, + parseDimensionsFromPaths: function(options) { + var points, p, xC = [], yC = [], path, height, width, m; + for (var j = this.paths.length; j--; ) { + path = this.paths[j]; + height = path.height + path.strokeWidth; + width = path.width + path.strokeWidth; + points = [ { + x: path.left, + y: path.top + }, { + x: path.left + width, + y: path.top + }, { + x: path.left, + y: path.top + height + }, { + x: path.left + width, + y: path.top + height + } ]; + m = this.paths[j].transformMatrix; + for (var i = 0; i < points.length; i++) { + p = points[i]; + if (m) { + p = fabric.util.transformPoint(p, m, false); + } + xC.push(p.x); + yC.push(p.y); + } + } + options.width = Math.max.apply(null, xC); + options.height = Math.max.apply(null, yC); + }, + render: function(ctx) { + if (!this.visible) { + return; + } + ctx.save(); + if (this.transformMatrix) { + ctx.transform.apply(ctx, this.transformMatrix); + } + this.transform(ctx); + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + ctx.translate(-this.width / 2, -this.height / 2); + for (var i = 0, l = this.paths.length; i < l; ++i) { + this.paths[i].render(ctx, true); + } + this.clipTo && ctx.restore(); + ctx.restore(); + }, + _set: function(prop, value) { + if (prop === "fill" && value && this.isSameColor()) { + var i = this.paths.length; + while (i--) { + this.paths[i]._set(prop, value); + } + } + return this.callSuper("_set", prop, value); + }, + toObject: function(propertiesToInclude) { + var o = extend(parentToObject.call(this, propertiesToInclude), { + paths: invoke(this.getObjects(), "toObject", propertiesToInclude) + }); + if (this.sourcePath) { + o.sourcePath = this.sourcePath; + } + return o; + }, + toDatalessObject: function(propertiesToInclude) { + var o = this.toObject(propertiesToInclude); + if (this.sourcePath) { + o.paths = this.sourcePath; + } + return o; + }, + toSVG: function(reviver) { + var objects = this.getObjects(), p = this.getPointByOrigin("left", "top"), translatePart = "translate(" + p.x + " " + p.y + ")", markup = this._createBaseSVGMarkup(); + markup.push("\n"); + for (var i = 0, len = objects.length; i < len; i++) { + markup.push(" ", objects[i].toSVG(reviver)); + } + markup.push("\n"); + return reviver ? reviver(markup.join("")) : markup.join(""); + }, + toString: function() { + return "#"; + }, + isSameColor: function() { + var firstPathFill = this.getObjects()[0].get("fill") || ""; + if (typeof firstPathFill !== "string") { + return false; + } + firstPathFill = firstPathFill.toLowerCase(); + return this.getObjects().every(function(path) { + var pathFill = path.get("fill") || ""; + return typeof pathFill === "string" && pathFill.toLowerCase() === firstPathFill; + }); + }, + complexity: function() { + return this.paths.reduce(function(total, path) { + return total + (path && path.complexity ? path.complexity() : 0); + }, 0); + }, + getObjects: function() { + return this.paths; + } + }); + fabric.PathGroup.fromObject = function(object, callback) { + if (typeof object.paths === "string") { + fabric.loadSVGFromURL(object.paths, function(elements) { + var pathUrl = object.paths; + delete object.paths; + var pathGroup = fabric.util.groupSVGElements(elements, object, pathUrl); + callback(pathGroup); + }); + } else { + fabric.util.enlivenObjects(object.paths, function(enlivenedObjects) { + delete object.paths; + callback(new fabric.PathGroup(enlivenedObjects, object)); + }); + } + }; + fabric.PathGroup.async = true; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, min = fabric.util.array.min, max = fabric.util.array.max, invoke = fabric.util.array.invoke; + if (fabric.Group) { + return; + } + var _lockProperties = { + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + lockUniScaling: true + }; + fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection, { + type: "group", + strokeWidth: 0, + initialize: function(objects, options, isAlreadyGrouped) { + options = options || {}; + this._objects = []; + isAlreadyGrouped && this.callSuper("initialize", options); + this._objects = objects || []; + for (var i = this._objects.length; i--; ) { + this._objects[i].group = this; + } + this.originalState = {}; + if (options.originX) { + this.originX = options.originX; + } + if (options.originY) { + this.originY = options.originY; + } + if (isAlreadyGrouped) { + this._updateObjectsCoords(true); + } else { + this._calcBounds(); + this._updateObjectsCoords(); + this.callSuper("initialize", options); + } + this.setCoords(); + this.saveCoords(); + }, + _updateObjectsCoords: function(skipCoordsChange) { + for (var i = this._objects.length; i--; ) { + this._updateObjectCoords(this._objects[i], skipCoordsChange); + } + }, + _updateObjectCoords: function(object, skipCoordsChange) { + object.__origHasControls = object.hasControls; + object.hasControls = false; + if (skipCoordsChange) { + return; + } + var objectLeft = object.getLeft(), objectTop = object.getTop(), center = this.getCenterPoint(); + object.set({ + originalLeft: objectLeft, + originalTop: objectTop, + left: objectLeft - center.x, + top: objectTop - center.y + }); + object.setCoords(); + }, + toString: function() { + return "#"; + }, + addWithUpdate: function(object) { + this._restoreObjectsState(); + fabric.util.resetObjectTransform(this); + if (object) { + this._objects.push(object); + object.group = this; + object._set("canvas", this.canvas); + } + this.forEachObject(this._setObjectActive, this); + this._calcBounds(); + this._updateObjectsCoords(); + return this; + }, + _setObjectActive: function(object) { + object.set("active", true); + object.group = this; + }, + removeWithUpdate: function(object) { + this._restoreObjectsState(); + fabric.util.resetObjectTransform(this); + this.forEachObject(this._setObjectActive, this); + this.remove(object); + this._calcBounds(); + this._updateObjectsCoords(); + return this; + }, + _onObjectAdded: function(object) { + object.group = this; + object._set("canvas", this.canvas); + }, + _onObjectRemoved: function(object) { + delete object.group; + object.set("active", false); + }, + delegatedProperties: { + fill: true, + stroke: true, + strokeWidth: true, + fontFamily: true, + fontWeight: true, + fontSize: true, + fontStyle: true, + lineHeight: true, + textDecoration: true, + textAlign: true, + backgroundColor: true + }, + _set: function(key, value) { + var i = this._objects.length; + if (this.delegatedProperties[key] || key === "canvas") { + while (i--) { + this._objects[i].set(key, value); + } + } else { + while (i--) { + this._objects[i].setOnGroup(key, value); + } + } + this.callSuper("_set", key, value); + }, + toObject: function(propertiesToInclude) { + return extend(this.callSuper("toObject", propertiesToInclude), { + objects: invoke(this._objects, "toObject", propertiesToInclude) + }); + }, + render: function(ctx) { + if (!this.visible) { + return; + } + ctx.save(); + if (this.transformMatrix) { + ctx.transform.apply(ctx, this.transformMatrix); + } + this.transform(ctx); + this._setShadow(ctx); + this.clipTo && fabric.util.clipContext(this, ctx); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._renderObject(this._objects[i], ctx); + } + this.clipTo && ctx.restore(); + ctx.restore(); + }, + _renderControls: function(ctx, noTransform) { + this.callSuper("_renderControls", ctx, noTransform); + for (var i = 0, len = this._objects.length; i < len; i++) { + this._objects[i]._renderControls(ctx); + } + }, + _renderObject: function(object, ctx) { + if (!object.visible) { + return; + } + var originalHasRotatingPoint = object.hasRotatingPoint; + object.hasRotatingPoint = false; + object.render(ctx); + object.hasRotatingPoint = originalHasRotatingPoint; + }, + _restoreObjectsState: function() { + this._objects.forEach(this._restoreObjectState, this); + return this; + }, + realizeTransform: function(object) { + var matrix = object.calcTransformMatrix(), options = fabric.util.qrDecompose(matrix), center = new fabric.Point(options.translateX, options.translateY); + object.scaleX = options.scaleX; + object.scaleY = options.scaleY; + object.skewX = options.skewX; + object.skewY = options.skewY; + object.angle = options.angle; + object.flipX = false; + object.flipY = false; + object.setPositionByOrigin(center, "center", "center"); + return object; + }, + _restoreObjectState: function(object) { + this.realizeTransform(object); + object.setCoords(); + object.hasControls = object.__origHasControls; + delete object.__origHasControls; + object.set("active", false); + delete object.group; + return this; + }, + destroy: function() { + return this._restoreObjectsState(); + }, + saveCoords: function() { + this._originalLeft = this.get("left"); + this._originalTop = this.get("top"); + return this; + }, + hasMoved: function() { + return this._originalLeft !== this.get("left") || this._originalTop !== this.get("top"); + }, + setObjectsCoords: function() { + this.forEachObject(function(object) { + object.setCoords(); + }); + return this; + }, + _calcBounds: function(onlyWidthHeight) { + var aX = [], aY = [], o, prop, props = [ "tr", "br", "bl", "tl" ], i = 0, iLen = this._objects.length, j, jLen = props.length; + for (;i < iLen; ++i) { + o = this._objects[i]; + o.setCoords(); + for (j = 0; j < jLen; j++) { + prop = props[j]; + aX.push(o.oCoords[prop].x); + aY.push(o.oCoords[prop].y); + } + } + this.set(this._getBounds(aX, aY, onlyWidthHeight)); + }, + _getBounds: function(aX, aY, onlyWidthHeight) { + var ivt = fabric.util.invertTransform(this.getViewportTransform()), minXY = fabric.util.transformPoint(new fabric.Point(min(aX), min(aY)), ivt), maxXY = fabric.util.transformPoint(new fabric.Point(max(aX), max(aY)), ivt), obj = { + width: maxXY.x - minXY.x || 0, + height: maxXY.y - minXY.y || 0 + }; + if (!onlyWidthHeight) { + obj.left = minXY.x || 0; + obj.top = minXY.y || 0; + if (this.originX === "center") { + obj.left += obj.width / 2; + } + if (this.originX === "right") { + obj.left += obj.width; + } + if (this.originY === "center") { + obj.top += obj.height / 2; + } + if (this.originY === "bottom") { + obj.top += obj.height; + } + } + return obj; + }, + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(); + markup.push('\n'); + for (var i = 0, len = this._objects.length; i < len; i++) { + markup.push(" ", this._objects[i].toSVG(reviver)); + } + markup.push("\n"); + return reviver ? reviver(markup.join("")) : markup.join(""); + }, + get: function(prop) { + if (prop in _lockProperties) { + if (this[prop]) { + return this[prop]; + } else { + for (var i = 0, len = this._objects.length; i < len; i++) { + if (this._objects[i][prop]) { + return true; + } + } + return false; + } + } else { + if (prop in this.delegatedProperties) { + return this._objects[0] && this._objects[0].get(prop); + } + return this[prop]; + } + } + }); + fabric.Group.fromObject = function(object, callback) { + fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) { + delete object.objects; + callback && callback(new fabric.Group(enlivenedObjects, object, true)); + }); + }; + fabric.Group.async = true; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var extend = fabric.util.object.extend; + if (!global.fabric) { + global.fabric = {}; + } + if (global.fabric.Image) { + fabric.warn("fabric.Image is already defined."); + return; + } + fabric.Image = fabric.util.createClass(fabric.Object, { + type: "image", + crossOrigin: "", + alignX: "none", + alignY: "none", + meetOrSlice: "meet", + strokeWidth: 0, + _lastScaleX: 1, + _lastScaleY: 1, + initialize: function(element, options) { + options || (options = {}); + this.filters = []; + this.resizeFilters = []; + this.callSuper("initialize", options); + this._initElement(element, options); + }, + getElement: function() { + return this._element; + }, + setElement: function(element, callback, options) { + this._element = element; + this._originalElement = element; + this._initConfig(options); + if (this.filters.length !== 0) { + this.applyFilters(callback); + } else if (callback) { + callback(); + } + return this; + }, + setCrossOrigin: function(value) { + this.crossOrigin = value; + this._element.crossOrigin = value; + return this; + }, + getOriginalSize: function() { + var element = this.getElement(); + return { + width: element.width, + height: element.height + }; + }, + _stroke: function(ctx) { + ctx.save(); + this._setStrokeStyles(ctx); + ctx.beginPath(); + ctx.strokeRect(-this.width / 2, -this.height / 2, this.width, this.height); + ctx.closePath(); + ctx.restore(); + }, + _renderDashedStroke: function(ctx) { + var x = -this.width / 2, y = -this.height / 2, w = this.width, h = this.height; + ctx.save(); + this._setStrokeStyles(ctx); + ctx.beginPath(); + fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray); + fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray); + ctx.closePath(); + ctx.restore(); + }, + toObject: function(propertiesToInclude) { + var filters = [], element = this._originalElement; + this.filters.forEach(function(filterObj) { + if (filterObj) { + filters.push(filterObj.toObject()); + } + }); + var object = extend(this.callSuper("toObject", propertiesToInclude), { + src: element ? element.src || element._src : "", + filters: filters, + crossOrigin: this.crossOrigin, + alignX: this.alignX, + alignY: this.alignY, + meetOrSlice: this.meetOrSlice + }); + if (this.resizeFilters.length > 0) { + object.resizeFilters = this.resizeFilters.map(function(filterObj) { + return filterObj && filterObj.toObject(); + }); + } + if (!this.includeDefaultValues) { + this._removeDefaultValues(object); + } + return object; + }, + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), x = -this.width / 2, y = -this.height / 2, preserveAspectRatio = "none"; + if (this.group && this.group.type === "path-group") { + x = this.left; + y = this.top; + } + if (this.alignX !== "none" && this.alignY !== "none") { + preserveAspectRatio = "x" + this.alignX + "Y" + this.alignY + " " + this.meetOrSlice; + } + markup.push('\n', '\n"); + if (this.stroke || this.strokeDashArray) { + var origFill = this.fill; + this.fill = null; + markup.push("\n'); + this.fill = origFill; + } + markup.push("\n"); + return reviver ? reviver(markup.join("")) : markup.join(""); + }, + getSrc: function() { + if (this.getElement()) { + return this.getElement().src || this.getElement()._src; + } + }, + setSrc: function(src, callback, options) { + fabric.util.loadImage(src, function(img) { + return this.setElement(img, callback, options); + }, this, options && options.crossOrigin); + }, + toString: function() { + return '#'; + }, + clone: function(callback, propertiesToInclude) { + this.constructor.fromObject(this.toObject(propertiesToInclude), callback); + }, + applyFilters: function(callback, filters, imgElement, forResizing) { + filters = filters || this.filters; + imgElement = imgElement || this._originalElement; + if (!imgElement) { + return; + } + var imgEl = imgElement, canvasEl = fabric.util.createCanvasElement(), replacement = fabric.util.createImage(), _this = this; + canvasEl.width = imgEl.width; + canvasEl.height = imgEl.height; + canvasEl.getContext("2d").drawImage(imgEl, 0, 0, imgEl.width, imgEl.height); + if (filters.length === 0) { + this._element = imgElement; + callback && callback(); + return canvasEl; + } + filters.forEach(function(filter) { + filter && filter.applyTo(canvasEl, filter.scaleX || _this.scaleX, filter.scaleY || _this.scaleY); + if (!forResizing && filter && filter.type === "Resize") { + _this.width *= filter.scaleX; + _this.height *= filter.scaleY; + } + }); + replacement.width = canvasEl.width; + replacement.height = canvasEl.height; + if (fabric.isLikelyNode) { + replacement.src = canvasEl.toBuffer(undefined, fabric.Image.pngCompression); + _this._element = replacement; + !forResizing && (_this._filteredEl = replacement); + callback && callback(); + } else { + replacement.onload = function() { + _this._element = replacement; + !forResizing && (_this._filteredEl = replacement); + callback && callback(); + replacement.onload = canvasEl = imgEl = null; + }; + replacement.src = canvasEl.toDataURL("image/png"); + } + return canvasEl; + }, + _render: function(ctx, noTransform) { + var x, y, imageMargins = this._findMargins(), elementToDraw; + x = noTransform ? this.left : -this.width / 2; + y = noTransform ? this.top : -this.height / 2; + if (this.meetOrSlice === "slice") { + ctx.beginPath(); + ctx.rect(x, y, this.width, this.height); + ctx.clip(); + } + if (this.isMoving === false && this.resizeFilters.length && this._needsResize()) { + this._lastScaleX = this.scaleX; + this._lastScaleY = this.scaleY; + elementToDraw = this.applyFilters(null, this.resizeFilters, this._filteredEl || this._originalElement, true); + } else { + elementToDraw = this._element; + } + elementToDraw && ctx.drawImage(elementToDraw, x + imageMargins.marginX, y + imageMargins.marginY, imageMargins.width, imageMargins.height); + this._renderStroke(ctx); + }, + _needsResize: function() { + return this.scaleX !== this._lastScaleX || this.scaleY !== this._lastScaleY; + }, + _findMargins: function() { + var width = this.width, height = this.height, scales, scale, marginX = 0, marginY = 0; + if (this.alignX !== "none" || this.alignY !== "none") { + scales = [ this.width / this._element.width, this.height / this._element.height ]; + scale = this.meetOrSlice === "meet" ? Math.min.apply(null, scales) : Math.max.apply(null, scales); + width = this._element.width * scale; + height = this._element.height * scale; + if (this.alignX === "Mid") { + marginX = (this.width - width) / 2; + } + if (this.alignX === "Max") { + marginX = this.width - width; + } + if (this.alignY === "Mid") { + marginY = (this.height - height) / 2; + } + if (this.alignY === "Max") { + marginY = this.height - height; + } + } + return { + width: width, + height: height, + marginX: marginX, + marginY: marginY + }; + }, + _resetWidthHeight: function() { + var element = this.getElement(); + this.set("width", element.width); + this.set("height", element.height); + }, + _initElement: function(element, options) { + this.setElement(fabric.util.getById(element), null, options); + fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS); + }, + _initConfig: function(options) { + options || (options = {}); + this.setOptions(options); + this._setWidthHeight(options); + if (this._element && this.crossOrigin) { + this._element.crossOrigin = this.crossOrigin; + } + }, + _initFilters: function(filters, callback) { + if (filters && filters.length) { + fabric.util.enlivenObjects(filters, function(enlivenedObjects) { + callback && callback(enlivenedObjects); + }, "fabric.Image.filters"); + } else { + callback && callback(); + } + }, + _setWidthHeight: function(options) { + this.width = "width" in options ? options.width : this.getElement() ? this.getElement().width || 0 : 0; + this.height = "height" in options ? options.height : this.getElement() ? this.getElement().height || 0 : 0; + }, + complexity: function() { + return 1; + } + }); + fabric.Image.CSS_CANVAS = "canvas-img"; + fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc; + fabric.Image.fromObject = function(object, callback) { + fabric.util.loadImage(object.src, function(img) { + fabric.Image.prototype._initFilters.call(object, object.filters, function(filters) { + object.filters = filters || []; + fabric.Image.prototype._initFilters.call(object, object.resizeFilters, function(resizeFilters) { + object.resizeFilters = resizeFilters || []; + var instance = new fabric.Image(img, object); + callback && callback(instance); + }); + }); + }, null, object.crossOrigin); + }; + fabric.Image.fromURL = function(url, callback, imgOptions) { + fabric.util.loadImage(url, function(img) { + callback && callback(new fabric.Image(img, imgOptions)); + }, null, imgOptions && imgOptions.crossOrigin); + }; + fabric.Image.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat("x y width height preserveAspectRatio xlink:href".split(" ")); + fabric.Image.fromElement = function(element, callback, options) { + var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES), preserveAR; + if (parsedAttributes.preserveAspectRatio) { + preserveAR = fabric.util.parsePreserveAspectRatioAttribute(parsedAttributes.preserveAspectRatio); + extend(parsedAttributes, preserveAR); + } + fabric.Image.fromURL(parsedAttributes["xlink:href"], callback, extend(options ? fabric.util.object.clone(options) : {}, parsedAttributes)); + }; + fabric.Image.async = true; + fabric.Image.pngCompression = 1; +})(typeof exports !== "undefined" ? exports : this); + +fabric.util.object.extend(fabric.Object.prototype, { + _getAngleValueForStraighten: function() { + var angle = this.getAngle() % 360; + if (angle > 0) { + return Math.round((angle - 1) / 90) * 90; + } + return Math.round(angle / 90) * 90; + }, + straighten: function() { + this.setAngle(this._getAngleValueForStraighten()); + return this; + }, + fxStraighten: function(callbacks) { + callbacks = callbacks || {}; + var empty = function() {}, onComplete = callbacks.onComplete || empty, onChange = callbacks.onChange || empty, _this = this; + fabric.util.animate({ + startValue: this.get("angle"), + endValue: this._getAngleValueForStraighten(), + duration: this.FX_DURATION, + onChange: function(value) { + _this.setAngle(value); + onChange(); + }, + onComplete: function() { + _this.setCoords(); + onComplete(); + }, + onStart: function() { + _this.set("active", false); + } + }); + return this; + } +}); + +fabric.util.object.extend(fabric.StaticCanvas.prototype, { + straightenObject: function(object) { + object.straighten(); + this.renderAll(); + return this; + }, + fxStraightenObject: function(object) { + object.fxStraighten({ + onChange: this.renderAll.bind(this) + }); + return this; + } +}); + +fabric.Image.filters = fabric.Image.filters || {}; + +fabric.Image.filters.BaseFilter = fabric.util.createClass({ + type: "BaseFilter", + initialize: function(options) { + if (options) { + this.setOptions(options); + } + }, + setOptions: function(options) { + for (var prop in options) { + this[prop] = options[prop]; + } + }, + toObject: function() { + return { + type: this.type + }; + }, + toJSON: function() { + return this.toObject(); + } +}); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend; + fabric.Image.filters.Brightness = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "Brightness", + initialize: function(options) { + options = options || {}; + this.brightness = options.brightness || 0; + }, + applyTo: function(canvasEl) { + var context = canvasEl.getContext("2d"), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, brightness = this.brightness; + for (var i = 0, len = data.length; i < len; i += 4) { + data[i] += brightness; + data[i + 1] += brightness; + data[i + 2] += brightness; + } + context.putImageData(imageData, 0, 0); + }, + toObject: function() { + return extend(this.callSuper("toObject"), { + brightness: this.brightness + }); + } + }); + fabric.Image.filters.Brightness.fromObject = function(object) { + return new fabric.Image.filters.Brightness(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend; + fabric.Image.filters.Convolute = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "Convolute", + initialize: function(options) { + options = options || {}; + this.opaque = options.opaque; + this.matrix = options.matrix || [ 0, 0, 0, 0, 1, 0, 0, 0, 0 ]; + }, + applyTo: function(canvasEl) { + var weights = this.matrix, context = canvasEl.getContext("2d"), pixels = context.getImageData(0, 0, canvasEl.width, canvasEl.height), side = Math.round(Math.sqrt(weights.length)), halfSide = Math.floor(side / 2), src = pixels.data, sw = pixels.width, sh = pixels.height, output = context.createImageData(sw, sh), dst = output.data, alphaFac = this.opaque ? 1 : 0, r, g, b, a, dstOff, scx, scy, srcOff, wt; + for (var y = 0; y < sh; y++) { + for (var x = 0; x < sw; x++) { + dstOff = (y * sw + x) * 4; + r = 0; + g = 0; + b = 0; + a = 0; + for (var cy = 0; cy < side; cy++) { + for (var cx = 0; cx < side; cx++) { + scy = y + cy - halfSide; + scx = x + cx - halfSide; + if (scy < 0 || scy > sh || scx < 0 || scx > sw) { + continue; + } + srcOff = (scy * sw + scx) * 4; + wt = weights[cy * side + cx]; + r += src[srcOff] * wt; + g += src[srcOff + 1] * wt; + b += src[srcOff + 2] * wt; + a += src[srcOff + 3] * wt; + } + } + dst[dstOff] = r; + dst[dstOff + 1] = g; + dst[dstOff + 2] = b; + dst[dstOff + 3] = a + alphaFac * (255 - a); + } + } + context.putImageData(output, 0, 0); + }, + toObject: function() { + return extend(this.callSuper("toObject"), { + opaque: this.opaque, + matrix: this.matrix + }); + } + }); + fabric.Image.filters.Convolute.fromObject = function(object) { + return new fabric.Image.filters.Convolute(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend; + fabric.Image.filters.GradientTransparency = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "GradientTransparency", + initialize: function(options) { + options = options || {}; + this.threshold = options.threshold || 100; + }, + applyTo: function(canvasEl) { + var context = canvasEl.getContext("2d"), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, threshold = this.threshold, total = data.length; + for (var i = 0, len = data.length; i < len; i += 4) { + data[i + 3] = threshold + 255 * (total - i) / total; + } + context.putImageData(imageData, 0, 0); + }, + toObject: function() { + return extend(this.callSuper("toObject"), { + threshold: this.threshold + }); + } + }); + fabric.Image.filters.GradientTransparency.fromObject = function(object) { + return new fabric.Image.filters.GradientTransparency(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}); + fabric.Image.filters.Grayscale = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "Grayscale", + applyTo: function(canvasEl) { + var context = canvasEl.getContext("2d"), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, len = imageData.width * imageData.height * 4, index = 0, average; + while (index < len) { + average = (data[index] + data[index + 1] + data[index + 2]) / 3; + data[index] = average; + data[index + 1] = average; + data[index + 2] = average; + index += 4; + } + context.putImageData(imageData, 0, 0); + } + }); + fabric.Image.filters.Grayscale.fromObject = function() { + return new fabric.Image.filters.Grayscale(); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}); + fabric.Image.filters.Invert = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "Invert", + applyTo: function(canvasEl) { + var context = canvasEl.getContext("2d"), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, iLen = data.length, i; + for (i = 0; i < iLen; i += 4) { + data[i] = 255 - data[i]; + data[i + 1] = 255 - data[i + 1]; + data[i + 2] = 255 - data[i + 2]; + } + context.putImageData(imageData, 0, 0); + } + }); + fabric.Image.filters.Invert.fromObject = function() { + return new fabric.Image.filters.Invert(); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend; + fabric.Image.filters.Mask = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "Mask", + initialize: function(options) { + options = options || {}; + this.mask = options.mask; + this.channel = [ 0, 1, 2, 3 ].indexOf(options.channel) > -1 ? options.channel : 0; + }, + applyTo: function(canvasEl) { + if (!this.mask) { + return; + } + var context = canvasEl.getContext("2d"), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, maskEl = this.mask.getElement(), maskCanvasEl = fabric.util.createCanvasElement(), channel = this.channel, i, iLen = imageData.width * imageData.height * 4; + maskCanvasEl.width = canvasEl.width; + maskCanvasEl.height = canvasEl.height; + maskCanvasEl.getContext("2d").drawImage(maskEl, 0, 0, canvasEl.width, canvasEl.height); + var maskImageData = maskCanvasEl.getContext("2d").getImageData(0, 0, canvasEl.width, canvasEl.height), maskData = maskImageData.data; + for (i = 0; i < iLen; i += 4) { + data[i + 3] = maskData[i + channel]; + } + context.putImageData(imageData, 0, 0); + }, + toObject: function() { + return extend(this.callSuper("toObject"), { + mask: this.mask.toObject(), + channel: this.channel + }); + } + }); + fabric.Image.filters.Mask.fromObject = function(object, callback) { + fabric.util.loadImage(object.mask.src, function(img) { + object.mask = new fabric.Image(img, object.mask); + callback && callback(new fabric.Image.filters.Mask(object)); + }); + }; + fabric.Image.filters.Mask.async = true; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend; + fabric.Image.filters.Noise = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "Noise", + initialize: function(options) { + options = options || {}; + this.noise = options.noise || 0; + }, + applyTo: function(canvasEl) { + var context = canvasEl.getContext("2d"), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, noise = this.noise, rand; + for (var i = 0, len = data.length; i < len; i += 4) { + rand = (.5 - Math.random()) * noise; + data[i] += rand; + data[i + 1] += rand; + data[i + 2] += rand; + } + context.putImageData(imageData, 0, 0); + }, + toObject: function() { + return extend(this.callSuper("toObject"), { + noise: this.noise + }); + } + }); + fabric.Image.filters.Noise.fromObject = function(object) { + return new fabric.Image.filters.Noise(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend; + fabric.Image.filters.Pixelate = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "Pixelate", + initialize: function(options) { + options = options || {}; + this.blocksize = options.blocksize || 4; + }, + applyTo: function(canvasEl) { + var context = canvasEl.getContext("2d"), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, iLen = imageData.height, jLen = imageData.width, index, i, j, r, g, b, a; + for (i = 0; i < iLen; i += this.blocksize) { + for (j = 0; j < jLen; j += this.blocksize) { + index = i * 4 * jLen + j * 4; + r = data[index]; + g = data[index + 1]; + b = data[index + 2]; + a = data[index + 3]; + for (var _i = i, _ilen = i + this.blocksize; _i < _ilen; _i++) { + for (var _j = j, _jlen = j + this.blocksize; _j < _jlen; _j++) { + index = _i * 4 * jLen + _j * 4; + data[index] = r; + data[index + 1] = g; + data[index + 2] = b; + data[index + 3] = a; + } + } + } + } + context.putImageData(imageData, 0, 0); + }, + toObject: function() { + return extend(this.callSuper("toObject"), { + blocksize: this.blocksize + }); + } + }); + fabric.Image.filters.Pixelate.fromObject = function(object) { + return new fabric.Image.filters.Pixelate(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend; + fabric.Image.filters.RemoveWhite = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "RemoveWhite", + initialize: function(options) { + options = options || {}; + this.threshold = options.threshold || 30; + this.distance = options.distance || 20; + }, + applyTo: function(canvasEl) { + var context = canvasEl.getContext("2d"), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, threshold = this.threshold, distance = this.distance, limit = 255 - threshold, abs = Math.abs, r, g, b; + for (var i = 0, len = data.length; i < len; i += 4) { + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + if (r > limit && g > limit && b > limit && abs(r - g) < distance && abs(r - b) < distance && abs(g - b) < distance) { + data[i + 3] = 0; + } + } + context.putImageData(imageData, 0, 0); + }, + toObject: function() { + return extend(this.callSuper("toObject"), { + threshold: this.threshold, + distance: this.distance + }); + } + }); + fabric.Image.filters.RemoveWhite.fromObject = function(object) { + return new fabric.Image.filters.RemoveWhite(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}); + fabric.Image.filters.Sepia = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "Sepia", + applyTo: function(canvasEl) { + var context = canvasEl.getContext("2d"), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, iLen = data.length, i, avg; + for (i = 0; i < iLen; i += 4) { + avg = .3 * data[i] + .59 * data[i + 1] + .11 * data[i + 2]; + data[i] = avg + 100; + data[i + 1] = avg + 50; + data[i + 2] = avg + 255; + } + context.putImageData(imageData, 0, 0); + } + }); + fabric.Image.filters.Sepia.fromObject = function() { + return new fabric.Image.filters.Sepia(); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}); + fabric.Image.filters.Sepia2 = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "Sepia2", + applyTo: function(canvasEl) { + var context = canvasEl.getContext("2d"), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, iLen = data.length, i, r, g, b; + for (i = 0; i < iLen; i += 4) { + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + data[i] = (r * .393 + g * .769 + b * .189) / 1.351; + data[i + 1] = (r * .349 + g * .686 + b * .168) / 1.203; + data[i + 2] = (r * .272 + g * .534 + b * .131) / 2.14; + } + context.putImageData(imageData, 0, 0); + } + }); + fabric.Image.filters.Sepia2.fromObject = function() { + return new fabric.Image.filters.Sepia2(); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend; + fabric.Image.filters.Tint = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "Tint", + initialize: function(options) { + options = options || {}; + this.color = options.color || "#000000"; + this.opacity = typeof options.opacity !== "undefined" ? options.opacity : new fabric.Color(this.color).getAlpha(); + }, + applyTo: function(canvasEl) { + var context = canvasEl.getContext("2d"), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, iLen = data.length, i, tintR, tintG, tintB, r, g, b, alpha1, source; + source = new fabric.Color(this.color).getSource(); + tintR = source[0] * this.opacity; + tintG = source[1] * this.opacity; + tintB = source[2] * this.opacity; + alpha1 = 1 - this.opacity; + for (i = 0; i < iLen; i += 4) { + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + data[i] = tintR + r * alpha1; + data[i + 1] = tintG + g * alpha1; + data[i + 2] = tintB + b * alpha1; + } + context.putImageData(imageData, 0, 0); + }, + toObject: function() { + return extend(this.callSuper("toObject"), { + color: this.color, + opacity: this.opacity + }); + } + }); + fabric.Image.filters.Tint.fromObject = function(object) { + return new fabric.Image.filters.Tint(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend; + fabric.Image.filters.Multiply = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "Multiply", + initialize: function(options) { + options = options || {}; + this.color = options.color || "#000000"; + }, + applyTo: function(canvasEl) { + var context = canvasEl.getContext("2d"), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, iLen = data.length, i, source; + source = new fabric.Color(this.color).getSource(); + for (i = 0; i < iLen; i += 4) { + data[i] *= source[0] / 255; + data[i + 1] *= source[1] / 255; + data[i + 2] *= source[2] / 255; + } + context.putImageData(imageData, 0, 0); + }, + toObject: function() { + return extend(this.callSuper("toObject"), { + color: this.color + }); + } + }); + fabric.Image.filters.Multiply.fromObject = function(object) { + return new fabric.Image.filters.Multiply(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric; + fabric.Image.filters.Blend = fabric.util.createClass({ + type: "Blend", + initialize: function(options) { + options = options || {}; + this.color = options.color || "#000"; + this.image = options.image || false; + this.mode = options.mode || "multiply"; + this.alpha = options.alpha || 1; + }, + applyTo: function(canvasEl) { + var context = canvasEl.getContext("2d"), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, tr, tg, tb, r, g, b, _r, _g, _b, source, isImage = false; + if (this.image) { + isImage = true; + var _el = fabric.util.createCanvasElement(); + _el.width = this.image.width; + _el.height = this.image.height; + var tmpCanvas = new fabric.StaticCanvas(_el); + tmpCanvas.add(this.image); + var context2 = tmpCanvas.getContext("2d"); + source = context2.getImageData(0, 0, tmpCanvas.width, tmpCanvas.height).data; + } else { + source = new fabric.Color(this.color).getSource(); + tr = source[0] * this.alpha; + tg = source[1] * this.alpha; + tb = source[2] * this.alpha; + } + for (var i = 0, len = data.length; i < len; i += 4) { + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + if (isImage) { + tr = source[i] * this.alpha; + tg = source[i + 1] * this.alpha; + tb = source[i + 2] * this.alpha; + } + switch (this.mode) { + case "multiply": + data[i] = r * tr / 255; + data[i + 1] = g * tg / 255; + data[i + 2] = b * tb / 255; + break; + + case "screen": + data[i] = 1 - (1 - r) * (1 - tr); + data[i + 1] = 1 - (1 - g) * (1 - tg); + data[i + 2] = 1 - (1 - b) * (1 - tb); + break; + + case "add": + data[i] = Math.min(255, r + tr); + data[i + 1] = Math.min(255, g + tg); + data[i + 2] = Math.min(255, b + tb); + break; + + case "diff": + case "difference": + data[i] = Math.abs(r - tr); + data[i + 1] = Math.abs(g - tg); + data[i + 2] = Math.abs(b - tb); + break; + + case "subtract": + _r = r - tr; + _g = g - tg; + _b = b - tb; + data[i] = _r < 0 ? 0 : _r; + data[i + 1] = _g < 0 ? 0 : _g; + data[i + 2] = _b < 0 ? 0 : _b; + break; + + case "darken": + data[i] = Math.min(r, tr); + data[i + 1] = Math.min(g, tg); + data[i + 2] = Math.min(b, tb); + break; + + case "lighten": + data[i] = Math.max(r, tr); + data[i + 1] = Math.max(g, tg); + data[i + 2] = Math.max(b, tb); + break; + } + } + context.putImageData(imageData, 0, 0); + }, + toObject: function() { + return { + color: this.color, + image: this.image, + mode: this.mode, + alpha: this.alpha + }; + } + }); + fabric.Image.filters.Blend.fromObject = function(object) { + return new fabric.Image.filters.Blend(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), pow = Math.pow, floor = Math.floor, sqrt = Math.sqrt, abs = Math.abs, max = Math.max, round = Math.round, sin = Math.sin, ceil = Math.ceil; + fabric.Image.filters.Resize = fabric.util.createClass(fabric.Image.filters.BaseFilter, { + type: "Resize", + resizeType: "hermite", + scaleX: 0, + scaleY: 0, + lanczosLobes: 3, + applyTo: function(canvasEl, scaleX, scaleY) { + this.rcpScaleX = 1 / scaleX; + this.rcpScaleY = 1 / scaleY; + var oW = canvasEl.width, oH = canvasEl.height, dW = round(oW * scaleX), dH = round(oH * scaleY), imageData; + if (this.resizeType === "sliceHack") { + imageData = this.sliceByTwo(canvasEl, oW, oH, dW, dH); + } + if (this.resizeType === "hermite") { + imageData = this.hermiteFastResize(canvasEl, oW, oH, dW, dH); + } + if (this.resizeType === "bilinear") { + imageData = this.bilinearFiltering(canvasEl, oW, oH, dW, dH); + } + if (this.resizeType === "lanczos") { + imageData = this.lanczosResize(canvasEl, oW, oH, dW, dH); + } + canvasEl.width = dW; + canvasEl.height = dH; + canvasEl.getContext("2d").putImageData(imageData, 0, 0); + }, + sliceByTwo: function(canvasEl, width, height, newWidth, newHeight) { + var context = canvasEl.getContext("2d"), imageData, multW = .5, multH = .5, signW = 1, signH = 1, doneW = false, doneH = false, stepW = width, stepH = height, tmpCanvas = fabric.util.createCanvasElement(), tmpCtx = tmpCanvas.getContext("2d"); + newWidth = floor(newWidth); + newHeight = floor(newHeight); + tmpCanvas.width = max(newWidth, width); + tmpCanvas.height = max(newHeight, height); + if (newWidth > width) { + multW = 2; + signW = -1; + } + if (newHeight > height) { + multH = 2; + signH = -1; + } + imageData = context.getImageData(0, 0, width, height); + canvasEl.width = max(newWidth, width); + canvasEl.height = max(newHeight, height); + context.putImageData(imageData, 0, 0); + while (!doneW || !doneH) { + width = stepW; + height = stepH; + if (newWidth * signW < floor(stepW * multW * signW)) { + stepW = floor(stepW * multW); + } else { + stepW = newWidth; + doneW = true; + } + if (newHeight * signH < floor(stepH * multH * signH)) { + stepH = floor(stepH * multH); + } else { + stepH = newHeight; + doneH = true; + } + imageData = context.getImageData(0, 0, width, height); + tmpCtx.putImageData(imageData, 0, 0); + context.clearRect(0, 0, stepW, stepH); + context.drawImage(tmpCanvas, 0, 0, width, height, 0, 0, stepW, stepH); + } + return context.getImageData(0, 0, newWidth, newHeight); + }, + lanczosResize: function(canvasEl, oW, oH, dW, dH) { + function lanczosCreate(lobes) { + return function(x) { + if (x > lobes) { + return 0; + } + x *= Math.PI; + if (abs(x) < 1e-16) { + return 1; + } + var xx = x / lobes; + return sin(x) * sin(xx) / x / xx; + }; + } + function process(u) { + var v, i, weight, idx, a, red, green, blue, alpha, fX, fY; + center.x = (u + .5) * ratioX; + icenter.x = floor(center.x); + for (v = 0; v < dH; v++) { + center.y = (v + .5) * ratioY; + icenter.y = floor(center.y); + a = 0, red = 0, green = 0, blue = 0, alpha = 0; + for (i = icenter.x - range2X; i <= icenter.x + range2X; i++) { + if (i < 0 || i >= oW) { + continue; + } + fX = floor(1e3 * abs(i - center.x)); + if (!cacheLanc[fX]) { + cacheLanc[fX] = {}; + } + for (var j = icenter.y - range2Y; j <= icenter.y + range2Y; j++) { + if (j < 0 || j >= oH) { + continue; + } + fY = floor(1e3 * abs(j - center.y)); + if (!cacheLanc[fX][fY]) { + cacheLanc[fX][fY] = lanczos(sqrt(pow(fX * rcpRatioX, 2) + pow(fY * rcpRatioY, 2)) / 1e3); + } + weight = cacheLanc[fX][fY]; + if (weight > 0) { + idx = (j * oW + i) * 4; + a += weight; + red += weight * srcData[idx]; + green += weight * srcData[idx + 1]; + blue += weight * srcData[idx + 2]; + alpha += weight * srcData[idx + 3]; + } + } + } + idx = (v * dW + u) * 4; + destData[idx] = red / a; + destData[idx + 1] = green / a; + destData[idx + 2] = blue / a; + destData[idx + 3] = alpha / a; + } + if (++u < dW) { + return process(u); + } else { + return destImg; + } + } + var context = canvasEl.getContext("2d"), srcImg = context.getImageData(0, 0, oW, oH), destImg = context.getImageData(0, 0, dW, dH), srcData = srcImg.data, destData = destImg.data, lanczos = lanczosCreate(this.lanczosLobes), ratioX = this.rcpScaleX, ratioY = this.rcpScaleY, rcpRatioX = 2 / this.rcpScaleX, rcpRatioY = 2 / this.rcpScaleY, range2X = ceil(ratioX * this.lanczosLobes / 2), range2Y = ceil(ratioY * this.lanczosLobes / 2), cacheLanc = {}, center = {}, icenter = {}; + return process(0); + }, + bilinearFiltering: function(canvasEl, w, h, w2, h2) { + var a, b, c, d, x, y, i, j, xDiff, yDiff, chnl, color, offset = 0, origPix, ratioX = this.rcpScaleX, ratioY = this.rcpScaleY, context = canvasEl.getContext("2d"), w4 = 4 * (w - 1), img = context.getImageData(0, 0, w, h), pixels = img.data, destImage = context.getImageData(0, 0, w2, h2), destPixels = destImage.data; + for (i = 0; i < h2; i++) { + for (j = 0; j < w2; j++) { + x = floor(ratioX * j); + y = floor(ratioY * i); + xDiff = ratioX * j - x; + yDiff = ratioY * i - y; + origPix = 4 * (y * w + x); + for (chnl = 0; chnl < 4; chnl++) { + a = pixels[origPix + chnl]; + b = pixels[origPix + 4 + chnl]; + c = pixels[origPix + w4 + chnl]; + d = pixels[origPix + w4 + 4 + chnl]; + color = a * (1 - xDiff) * (1 - yDiff) + b * xDiff * (1 - yDiff) + c * yDiff * (1 - xDiff) + d * xDiff * yDiff; + destPixels[offset++] = color; + } + } + } + return destImage; + }, + hermiteFastResize: function(canvasEl, oW, oH, dW, dH) { + var ratioW = this.rcpScaleX, ratioH = this.rcpScaleY, ratioWHalf = ceil(ratioW / 2), ratioHHalf = ceil(ratioH / 2), context = canvasEl.getContext("2d"), img = context.getImageData(0, 0, oW, oH), data = img.data, img2 = context.getImageData(0, 0, dW, dH), data2 = img2.data; + for (var j = 0; j < dH; j++) { + for (var i = 0; i < dW; i++) { + var x2 = (i + j * dW) * 4, weight = 0, weights = 0, weightsAlpha = 0, gxR = 0, gxG = 0, gxB = 0, gxA = 0, centerY = (j + .5) * ratioH; + for (var yy = floor(j * ratioH); yy < (j + 1) * ratioH; yy++) { + var dy = abs(centerY - (yy + .5)) / ratioHHalf, centerX = (i + .5) * ratioW, w0 = dy * dy; + for (var xx = floor(i * ratioW); xx < (i + 1) * ratioW; xx++) { + var dx = abs(centerX - (xx + .5)) / ratioWHalf, w = sqrt(w0 + dx * dx); + if (w > 1 && w < -1) { + continue; + } + weight = 2 * w * w * w - 3 * w * w + 1; + if (weight > 0) { + dx = 4 * (xx + yy * oW); + gxA += weight * data[dx + 3]; + weightsAlpha += weight; + if (data[dx + 3] < 255) { + weight = weight * data[dx + 3] / 250; + } + gxR += weight * data[dx]; + gxG += weight * data[dx + 1]; + gxB += weight * data[dx + 2]; + weights += weight; + } + } + } + data2[x2] = gxR / weights; + data2[x2 + 1] = gxG / weights; + data2[x2 + 2] = gxB / weights; + data2[x2 + 3] = gxA / weightsAlpha; + } + } + return img2; + }, + toObject: function() { + return { + type: this.type, + scaleX: this.scaleX, + scaleY: this.scaleY, + resizeType: this.resizeType, + lanczosLobes: this.lanczosLobes + }; + } + }); + fabric.Image.filters.Resize.fromObject = function(object) { + return new fabric.Image.filters.Resize(object); + }; +})(typeof exports !== "undefined" ? exports : this); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, clone = fabric.util.object.clone, toFixed = fabric.util.toFixed, supportsLineDash = fabric.StaticCanvas.supports("setLineDash"), NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; + if (fabric.Text) { + fabric.warn("fabric.Text is already defined"); + return; + } + var stateProperties = fabric.Object.prototype.stateProperties.concat(); + stateProperties.push("fontFamily", "fontWeight", "fontSize", "text", "textDecoration", "textAlign", "fontStyle", "lineHeight", "textBackgroundColor"); + fabric.Text = fabric.util.createClass(fabric.Object, { + _dimensionAffectingProps: { + fontSize: true, + fontWeight: true, + fontFamily: true, + fontStyle: true, + lineHeight: true, + stroke: true, + strokeWidth: true, + text: true, + textAlign: true + }, + _reNewline: /\r?\n/, + _reSpacesAndTabs: /[ \t\r]+/g, + type: "text", + fontSize: 40, + fontWeight: "normal", + fontFamily: "Times New Roman", + textDecoration: "", + textAlign: "left", + fontStyle: "", + lineHeight: 1.16, + textBackgroundColor: "", + stateProperties: stateProperties, + stroke: null, + shadow: null, + _fontSizeFraction: .25, + _fontSizeMult: 1.13, + initialize: function(text, options) { + options = options || {}; + this.text = text; + this.__skipDimension = true; + this.setOptions(options); + this.__skipDimension = false; + this._initDimensions(); + }, + _initDimensions: function(ctx) { + if (this.__skipDimension) { + return; + } + if (!ctx) { + ctx = fabric.util.createCanvasElement().getContext("2d"); + this._setTextStyles(ctx); + } + this._textLines = this._splitTextIntoLines(); + this._clearCache(); + this._cacheLinesWidth = this.textAlign !== "justify"; + this.width = this._getTextWidth(ctx); + this._cacheLinesWidth = true; + this.height = this._getTextHeight(ctx); + }, + toString: function() { + return "#'; + }, + _render: function(ctx) { + this.clipTo && fabric.util.clipContext(this, ctx); + this._setOpacity(ctx); + this._setShadow(ctx); + this._setupCompositeOperation(ctx); + this._renderTextBackground(ctx); + this._setStrokeStyles(ctx); + this._setFillStyles(ctx); + this._renderText(ctx); + this._renderTextDecoration(ctx); + this.clipTo && ctx.restore(); + }, + _renderText: function(ctx) { + this._translateForTextAlign(ctx); + this._renderTextFill(ctx); + this._renderTextStroke(ctx); + this._translateForTextAlign(ctx, true); + }, + _translateForTextAlign: function(ctx, back) { + if (this.textAlign !== "left" && this.textAlign !== "justify") { + var sign = back ? -1 : 1; + ctx.translate(this.textAlign === "center" ? sign * this.width / 2 : sign * this.width, 0); + } + }, + _setTextStyles: function(ctx) { + ctx.textBaseline = "alphabetic"; + if (!this.skipTextAlign) { + ctx.textAlign = this.textAlign; + } + ctx.font = this._getFontDeclaration(); + }, + _getTextHeight: function() { + return this._textLines.length * this._getHeightOfLine(); + }, + _getTextWidth: function(ctx) { + var maxWidth = this._getLineWidth(ctx, 0); + for (var i = 1, len = this._textLines.length; i < len; i++) { + var currentLineWidth = this._getLineWidth(ctx, i); + if (currentLineWidth > maxWidth) { + maxWidth = currentLineWidth; + } + } + return maxWidth; + }, + _renderChars: function(method, ctx, chars, left, top) { + var shortM = method.slice(0, -4); + if (this[shortM].toLive) { + var offsetX = -this.width / 2 + this[shortM].offsetX || 0, offsetY = -this.height / 2 + this[shortM].offsetY || 0; + ctx.save(); + ctx.translate(offsetX, offsetY); + left -= offsetX; + top -= offsetY; + } + ctx[method](chars, left, top); + this[shortM].toLive && ctx.restore(); + }, + _renderTextLine: function(method, ctx, line, left, top, lineIndex) { + top -= this.fontSize * this._fontSizeFraction; + var lineWidth = this._getLineWidth(ctx, lineIndex); + if (this.textAlign !== "justify" || this.width < lineWidth) { + this._renderChars(method, ctx, line, left, top, lineIndex); + return; + } + var words = line.split(/\s+/), charOffset = 0, wordsWidth = this._getWidthOfWords(ctx, line, lineIndex, 0), widthDiff = this.width - wordsWidth, numSpaces = words.length - 1, spaceWidth = numSpaces > 0 ? widthDiff / numSpaces : 0, leftOffset = 0, word; + for (var i = 0, len = words.length; i < len; i++) { + while (line[charOffset] === " " && charOffset < line.length) { + charOffset++; + } + word = words[i]; + this._renderChars(method, ctx, word, left + leftOffset, top, lineIndex, charOffset); + leftOffset += this._getWidthOfWords(ctx, word, lineIndex, charOffset) + spaceWidth; + charOffset += word.length; + } + }, + _getWidthOfWords: function(ctx, line) { + return ctx.measureText(line.replace(/\s+/g, "")).width; + }, + _getLeftOffset: function() { + return -this.width / 2; + }, + _getTopOffset: function() { + return -this.height / 2; + }, + isEmptyStyles: function() { + return true; + }, + _renderTextFill: function(ctx) { + if (!this.fill && this.isEmptyStyles()) { + return; + } + var lineHeights = 0; + for (var i = 0, len = this._textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i), maxHeight = heightOfLine / this.lineHeight; + this._renderTextLine("fillText", ctx, this._textLines[i], this._getLeftOffset(), this._getTopOffset() + lineHeights + maxHeight, i); + lineHeights += heightOfLine; + } + }, + _renderTextStroke: function(ctx) { + if ((!this.stroke || this.strokeWidth === 0) && this.isEmptyStyles()) { + return; + } + var lineHeights = 0; + if (this.shadow && !this.shadow.affectStroke) { + this._removeShadow(ctx); + } + ctx.save(); + if (this.strokeDashArray) { + if (1 & this.strokeDashArray.length) { + this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray); + } + supportsLineDash && ctx.setLineDash(this.strokeDashArray); + } + ctx.beginPath(); + for (var i = 0, len = this._textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i), maxHeight = heightOfLine / this.lineHeight; + this._renderTextLine("strokeText", ctx, this._textLines[i], this._getLeftOffset(), this._getTopOffset() + lineHeights + maxHeight, i); + lineHeights += heightOfLine; + } + ctx.closePath(); + ctx.restore(); + }, + _getHeightOfLine: function() { + return this.fontSize * this._fontSizeMult * this.lineHeight; + }, + _renderTextBackground: function(ctx) { + this._renderTextBoxBackground(ctx); + this._renderTextLinesBackground(ctx); + }, + _renderTextBoxBackground: function(ctx) { + if (!this.backgroundColor) { + return; + } + ctx.fillStyle = this.backgroundColor; + ctx.fillRect(this._getLeftOffset(), this._getTopOffset(), this.width, this.height); + this._removeShadow(ctx); + }, + _renderTextLinesBackground: function(ctx) { + if (!this.textBackgroundColor) { + return; + } + var lineTopOffset = 0, heightOfLine, lineWidth, lineLeftOffset; + ctx.fillStyle = this.textBackgroundColor; + for (var i = 0, len = this._textLines.length; i < len; i++) { + heightOfLine = this._getHeightOfLine(ctx, i); + if (this._textLines[i] !== "") { + lineWidth = this.textAlign === "justify" ? this.width : this._getLineWidth(ctx, i); + lineLeftOffset = this._getLineLeftOffset(lineWidth); + ctx.fillRect(this._getLeftOffset() + lineLeftOffset, this._getTopOffset() + lineTopOffset, lineWidth, heightOfLine / this.lineHeight); + } + lineTopOffset += heightOfLine; + } + this._removeShadow(ctx); + }, + _getLineLeftOffset: function(lineWidth) { + if (this.textAlign === "center") { + return (this.width - lineWidth) / 2; + } + if (this.textAlign === "right") { + return this.width - lineWidth; + } + return 0; + }, + _clearCache: function() { + this.__lineWidths = []; + this.__lineHeights = []; + }, + _shouldClearCache: function() { + var shouldClear = false; + if (this._forceClearCache) { + this._forceClearCache = false; + return true; + } + for (var prop in this._dimensionAffectingProps) { + if (this["__" + prop] !== this[prop]) { + this["__" + prop] = this[prop]; + shouldClear = true; + } + } + return shouldClear; + }, + _getLineWidth: function(ctx, lineIndex) { + if (this.__lineWidths[lineIndex]) { + return this.__lineWidths[lineIndex]; + } + var width, wordCount, line = this._textLines[lineIndex]; + if (line === "") { + width = 0; + } else if (this.textAlign === "justify" && this._cacheLinesWidth) { + wordCount = line.split(/\s+/); + if (wordCount.length > 1) { + width = this.width; + } else { + width = ctx.measureText(line).width; + } + } else { + width = ctx.measureText(line).width; + } + this._cacheLinesWidth && (this.__lineWidths[lineIndex] = width); + return width; + }, + _renderTextDecoration: function(ctx) { + if (!this.textDecoration) { + return; + } + var halfOfVerticalBox = this.height / 2, _this = this, offsets = []; + function renderLinesAtOffset(offsets) { + var i, lineHeight = 0, len, j, oLen, lineWidth, lineLeftOffset, heightOfLine; + for (i = 0, len = _this._textLines.length; i < len; i++) { + lineWidth = _this._getLineWidth(ctx, i), lineLeftOffset = _this._getLineLeftOffset(lineWidth), + heightOfLine = _this._getHeightOfLine(ctx, i); + for (j = 0, oLen = offsets.length; j < oLen; j++) { + ctx.fillRect(_this._getLeftOffset() + lineLeftOffset, lineHeight + (_this._fontSizeMult - 1 + offsets[j]) * _this.fontSize - halfOfVerticalBox, lineWidth, _this.fontSize / 15); + } + lineHeight += heightOfLine; + } + } + if (this.textDecoration.indexOf("underline") > -1) { + offsets.push(.85); + } + if (this.textDecoration.indexOf("line-through") > -1) { + offsets.push(.43); + } + if (this.textDecoration.indexOf("overline") > -1) { + offsets.push(-.12); + } + if (offsets.length > 0) { + renderLinesAtOffset(offsets); + } + }, + _getFontDeclaration: function() { + return [ fabric.isLikelyNode ? this.fontWeight : this.fontStyle, fabric.isLikelyNode ? this.fontStyle : this.fontWeight, this.fontSize + "px", fabric.isLikelyNode ? '"' + this.fontFamily + '"' : this.fontFamily ].join(" "); + }, + render: function(ctx, noTransform) { + if (!this.visible) { + return; + } + ctx.save(); + this._setTextStyles(ctx); + if (this._shouldClearCache()) { + this._initDimensions(ctx); + } + if (!noTransform) { + this.transform(ctx); + } + if (this.transformMatrix) { + ctx.transform.apply(ctx, this.transformMatrix); + } + if (this.group && this.group.type === "path-group") { + ctx.translate(this.left, this.top); + } + this._render(ctx); + ctx.restore(); + }, + _splitTextIntoLines: function() { + return this.text.split(this._reNewline); + }, + toObject: function(propertiesToInclude) { + var object = extend(this.callSuper("toObject", propertiesToInclude), { + text: this.text, + fontSize: this.fontSize, + fontWeight: this.fontWeight, + fontFamily: this.fontFamily, + fontStyle: this.fontStyle, + lineHeight: this.lineHeight, + textDecoration: this.textDecoration, + textAlign: this.textAlign, + textBackgroundColor: this.textBackgroundColor + }); + if (!this.includeDefaultValues) { + this._removeDefaultValues(object); + } + return object; + }, + toSVG: function(reviver) { + var markup = this._createBaseSVGMarkup(), offsets = this._getSVGLeftTopOffsets(this.ctx), textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft); + this._wrapSVGTextAndBg(markup, textAndBg); + return reviver ? reviver(markup.join("")) : markup.join(""); + }, + _getSVGLeftTopOffsets: function(ctx) { + var lineTop = this._getHeightOfLine(ctx, 0), textLeft = -this.width / 2, textTop = 0; + return { + textLeft: textLeft + (this.group && this.group.type === "path-group" ? this.left : 0), + textTop: textTop + (this.group && this.group.type === "path-group" ? -this.top : 0), + lineTop: lineTop + }; + }, + _wrapSVGTextAndBg: function(markup, textAndBg) { + var noShadow = true, filter = this.getSvgFilter(), style = filter === "" ? "" : ' style="' + filter + '"'; + markup.push(' \n", textAndBg.textBgRects.join(""), " \n', textAndBg.textSpans.join(""), " \n", " \n"); + }, + _getSVGTextAndBg: function(textTopOffset, textLeftOffset) { + var textSpans = [], textBgRects = [], height = 0; + this._setSVGBg(textBgRects); + for (var i = 0, len = this._textLines.length; i < len; i++) { + if (this.textBackgroundColor) { + this._setSVGTextLineBg(textBgRects, i, textLeftOffset, textTopOffset, height); + } + this._setSVGTextLineText(i, textSpans, height, textLeftOffset, textTopOffset, textBgRects); + height += this._getHeightOfLine(this.ctx, i); + } + return { + textSpans: textSpans, + textBgRects: textBgRects + }; + }, + _setSVGTextLineText: function(i, textSpans, height, textLeftOffset, textTopOffset) { + var yPos = this.fontSize * (this._fontSizeMult - this._fontSizeFraction) - textTopOffset + height - this.height / 2; + if (this.textAlign === "justify") { + this._setSVGTextLineJustifed(i, textSpans, yPos, textLeftOffset); + return; + } + textSpans.push(' ", fabric.util.string.escapeXml(this._textLines[i]), "\n"); + }, + _setSVGTextLineJustifed: function(i, textSpans, yPos, textLeftOffset) { + var ctx = fabric.util.createCanvasElement().getContext("2d"); + this._setTextStyles(ctx); + var line = this._textLines[i], words = line.split(/\s+/), wordsWidth = this._getWidthOfWords(ctx, line), widthDiff = this.width - wordsWidth, numSpaces = words.length - 1, spaceWidth = numSpaces > 0 ? widthDiff / numSpaces : 0, word, attributes = this._getFillAttributes(this.fill), len; + textLeftOffset += this._getLineLeftOffset(this._getLineWidth(ctx, i)); + for (i = 0, len = words.length; i < len; i++) { + word = words[i]; + textSpans.push(' ", fabric.util.string.escapeXml(word), "\n"); + textLeftOffset += this._getWidthOfWords(ctx, word) + spaceWidth; + } + }, + _setSVGTextLineBg: function(textBgRects, i, textLeftOffset, textTopOffset, height) { + textBgRects.push(" \n'); + }, + _setSVGBg: function(textBgRects) { + if (this.backgroundColor) { + textBgRects.push(" \n'); + } + }, + _getFillAttributes: function(value) { + var fillColor = value && typeof value === "string" ? new fabric.Color(value) : ""; + if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) { + return 'fill="' + value + '"'; + } + return 'opacity="' + fillColor.getAlpha() + '" fill="' + fillColor.setAlpha(1).toRgb() + '"'; + }, + _set: function(key, value) { + this.callSuper("_set", key, value); + if (key in this._dimensionAffectingProps) { + this._initDimensions(); + this.setCoords(); + } + }, + complexity: function() { + return 1; + } + }); + fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat("x y dx dy font-family font-style font-weight font-size text-decoration text-anchor".split(" ")); + fabric.Text.DEFAULT_SVG_FONT_SIZE = 16; + fabric.Text.fromElement = function(element, options) { + if (!element) { + return null; + } + var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES); + options = fabric.util.object.extend(options ? fabric.util.object.clone(options) : {}, parsedAttributes); + options.top = options.top || 0; + options.left = options.left || 0; + if ("dx" in parsedAttributes) { + options.left += parsedAttributes.dx; + } + if ("dy" in parsedAttributes) { + options.top += parsedAttributes.dy; + } + if (!("fontSize" in options)) { + options.fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE; + } + if (!options.originX) { + options.originX = "left"; + } + var textContent = ""; + if (!("textContent" in element)) { + if ("firstChild" in element && element.firstChild !== null) { + if ("data" in element.firstChild && element.firstChild.data !== null) { + textContent = element.firstChild.data; + } + } + } else { + textContent = element.textContent; + } + textContent = textContent.replace(/^\s+|\s+$|\n+/g, "").replace(/\s+/g, " "); + var text = new fabric.Text(textContent, options), offX = 0; + if (text.originX === "left") { + offX = text.getWidth() / 2; + } + if (text.originX === "right") { + offX = -text.getWidth() / 2; + } + text.set({ + left: text.getLeft() + offX, + top: text.getTop() - text.getHeight() / 2 + text.fontSize * (.18 + text._fontSizeFraction) + }); + return text; + }; + fabric.Text.fromObject = function(object) { + return new fabric.Text(object.text, clone(object)); + }; + fabric.util.createAccessors(fabric.Text); +})(typeof exports !== "undefined" ? exports : this); + +(function() { + var clone = fabric.util.object.clone; + fabric.IText = fabric.util.createClass(fabric.Text, fabric.Observable, { + type: "i-text", + selectionStart: 0, + selectionEnd: 0, + selectionColor: "rgba(17,119,255,0.3)", + isEditing: false, + editable: true, + editingBorderColor: "rgba(102,153,255,0.25)", + cursorWidth: 2, + cursorColor: "#333", + cursorDelay: 1e3, + cursorDuration: 600, + styles: null, + caching: true, + _reSpace: /\s|\n/, + _currentCursorOpacity: 0, + _selectionDirection: null, + _abortCursorAnimation: false, + _charWidthsCache: {}, + __widthOfSpace: [], + initialize: function(text, options) { + this.styles = options ? options.styles || {} : {}; + this.callSuper("initialize", text, options); + this.initBehavior(); + }, + _clearCache: function() { + this.callSuper("_clearCache"); + this.__widthOfSpace = []; + }, + isEmptyStyles: function() { + if (!this.styles) { + return true; + } + var obj = this.styles; + for (var p1 in obj) { + for (var p2 in obj[p1]) { + for (var p3 in obj[p1][p2]) { + return false; + } + } + } + return true; + }, + setSelectionStart: function(index) { + index = Math.max(index, 0); + if (this.selectionStart !== index) { + this.fire("selection:changed"); + this.canvas && this.canvas.fire("text:selection:changed", { + target: this + }); + this.selectionStart = index; + } + this._updateTextarea(); + }, + setSelectionEnd: function(index) { + index = Math.min(index, this.text.length); + if (this.selectionEnd !== index) { + this.fire("selection:changed"); + this.canvas && this.canvas.fire("text:selection:changed", { + target: this + }); + this.selectionEnd = index; + } + this._updateTextarea(); + }, + getSelectionStyles: function(startIndex, endIndex) { + if (arguments.length === 2) { + var styles = []; + for (var i = startIndex; i < endIndex; i++) { + styles.push(this.getSelectionStyles(i)); + } + return styles; + } + var loc = this.get2DCursorLocation(startIndex), style = this._getStyleDeclaration(loc.lineIndex, loc.charIndex); + return style || {}; + }, + setSelectionStyles: function(styles) { + if (this.selectionStart === this.selectionEnd) { + this._extendStyles(this.selectionStart, styles); + } else { + for (var i = this.selectionStart; i < this.selectionEnd; i++) { + this._extendStyles(i, styles); + } + } + this._forceClearCache = true; + return this; + }, + _extendStyles: function(index, styles) { + var loc = this.get2DCursorLocation(index); + if (!this._getLineStyle(loc.lineIndex)) { + this._setLineStyle(loc.lineIndex, {}); + } + if (!this._getStyleDeclaration(loc.lineIndex, loc.charIndex)) { + this._setStyleDeclaration(loc.lineIndex, loc.charIndex, {}); + } + fabric.util.object.extend(this._getStyleDeclaration(loc.lineIndex, loc.charIndex), styles); + }, + _render: function(ctx) { + this.callSuper("_render", ctx); + this.ctx = ctx; + this.isEditing && this.renderCursorOrSelection(); + }, + renderCursorOrSelection: function() { + if (!this.active) { + return; + } + var chars = this.text.split(""), boundaries, ctx; + if (this.canvas.contextTop) { + ctx = this.canvas.contextTop; + ctx.save(); + ctx.transform.apply(ctx, this.canvas.viewportTransform); + this.transform(ctx); + this.transformMatrix && ctx.transform.apply(ctx, this.transformMatrix); + } else { + ctx = this.ctx; + ctx.save(); + } + if (this.selectionStart === this.selectionEnd) { + boundaries = this._getCursorBoundaries(chars, "cursor"); + this.renderCursor(boundaries, ctx); + } else { + boundaries = this._getCursorBoundaries(chars, "selection"); + this.renderSelection(chars, boundaries, ctx); + } + ctx.restore(); + }, + get2DCursorLocation: function(selectionStart) { + if (typeof selectionStart === "undefined") { + selectionStart = this.selectionStart; + } + var len = this._textLines.length; + for (var i = 0; i < len; i++) { + if (selectionStart <= this._textLines[i].length) { + return { + lineIndex: i, + charIndex: selectionStart + }; + } + selectionStart -= this._textLines[i].length + 1; + } + return { + lineIndex: i - 1, + charIndex: this._textLines[i - 1].length < selectionStart ? this._textLines[i - 1].length : selectionStart + }; + }, + getCurrentCharStyle: function(lineIndex, charIndex) { + var style = this._getStyleDeclaration(lineIndex, charIndex === 0 ? 0 : charIndex - 1); + return { + fontSize: style && style.fontSize || this.fontSize, + fill: style && style.fill || this.fill, + textBackgroundColor: style && style.textBackgroundColor || this.textBackgroundColor, + textDecoration: style && style.textDecoration || this.textDecoration, + fontFamily: style && style.fontFamily || this.fontFamily, + fontWeight: style && style.fontWeight || this.fontWeight, + fontStyle: style && style.fontStyle || this.fontStyle, + stroke: style && style.stroke || this.stroke, + strokeWidth: style && style.strokeWidth || this.strokeWidth + }; + }, + getCurrentCharFontSize: function(lineIndex, charIndex) { + var style = this._getStyleDeclaration(lineIndex, charIndex === 0 ? 0 : charIndex - 1); + return style && style.fontSize ? style.fontSize : this.fontSize; + }, + getCurrentCharColor: function(lineIndex, charIndex) { + var style = this._getStyleDeclaration(lineIndex, charIndex === 0 ? 0 : charIndex - 1); + return style && style.fill ? style.fill : this.cursorColor; + }, + _getCursorBoundaries: function(chars, typeOfBoundaries) { + var left = Math.round(this._getLeftOffset()), top = this._getTopOffset(), offsets = this._getCursorBoundariesOffsets(chars, typeOfBoundaries); + return { + left: left, + top: top, + leftOffset: offsets.left + offsets.lineLeft, + topOffset: offsets.top + }; + }, + _getCursorBoundariesOffsets: function(chars, typeOfBoundaries) { + var lineLeftOffset = 0, lineIndex = 0, charIndex = 0, topOffset = 0, leftOffset = 0; + for (var i = 0; i < this.selectionStart; i++) { + if (chars[i] === "\n") { + leftOffset = 0; + topOffset += this._getHeightOfLine(this.ctx, lineIndex); + lineIndex++; + charIndex = 0; + } else { + leftOffset += this._getWidthOfChar(this.ctx, chars[i], lineIndex, charIndex); + charIndex++; + } + lineLeftOffset = this._getLineLeftOffset(this._getLineWidth(this.ctx, lineIndex)); + } + if (typeOfBoundaries === "cursor") { + topOffset += (1 - this._fontSizeFraction) * this._getHeightOfLine(this.ctx, lineIndex) / this.lineHeight - this.getCurrentCharFontSize(lineIndex, charIndex) * (1 - this._fontSizeFraction); + } + return { + top: topOffset, + left: leftOffset, + lineLeft: lineLeftOffset + }; + }, + renderCursor: function(boundaries, ctx) { + var cursorLocation = this.get2DCursorLocation(), lineIndex = cursorLocation.lineIndex, charIndex = cursorLocation.charIndex, charHeight = this.getCurrentCharFontSize(lineIndex, charIndex), leftOffset = lineIndex === 0 && charIndex === 0 ? this._getLineLeftOffset(this._getLineWidth(ctx, lineIndex)) : boundaries.leftOffset; + ctx.fillStyle = this.getCurrentCharColor(lineIndex, charIndex); + ctx.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity; + ctx.fillRect(boundaries.left + leftOffset, boundaries.top + boundaries.topOffset, this.cursorWidth / this.scaleX, charHeight); + }, + renderSelection: function(chars, boundaries, ctx) { + ctx.fillStyle = this.selectionColor; + var start = this.get2DCursorLocation(this.selectionStart), end = this.get2DCursorLocation(this.selectionEnd), startLine = start.lineIndex, endLine = end.lineIndex; + for (var i = startLine; i <= endLine; i++) { + var lineOffset = this._getLineLeftOffset(this._getLineWidth(ctx, i)) || 0, lineHeight = this._getHeightOfLine(this.ctx, i), boxWidth = 0, line = this._textLines[i]; + if (i === startLine) { + for (var j = 0, len = line.length; j < len; j++) { + if (j >= start.charIndex && (i !== endLine || j < end.charIndex)) { + boxWidth += this._getWidthOfChar(ctx, line[j], i, j); + } + if (j < start.charIndex) { + lineOffset += this._getWidthOfChar(ctx, line[j], i, j); + } + } + } else if (i > startLine && i < endLine) { + boxWidth += this._getLineWidth(ctx, i) || 5; + } else if (i === endLine) { + for (var j2 = 0, j2len = end.charIndex; j2 < j2len; j2++) { + boxWidth += this._getWidthOfChar(ctx, line[j2], i, j2); + } + } + ctx.fillRect(boundaries.left + lineOffset, boundaries.top + boundaries.topOffset, boxWidth, lineHeight); + boundaries.topOffset += lineHeight; + } + }, + _renderChars: function(method, ctx, line, left, top, lineIndex, charOffset) { + if (this.isEmptyStyles()) { + return this._renderCharsFast(method, ctx, line, left, top); + } + charOffset = charOffset || 0; + this.skipTextAlign = true; + left -= this.textAlign === "center" ? this.width / 2 : this.textAlign === "right" ? this.width : 0; + var lineHeight = this._getHeightOfLine(ctx, lineIndex), lineLeftOffset = this._getLineLeftOffset(this._getLineWidth(ctx, lineIndex)), prevStyle, thisStyle, charsToRender = ""; + left += lineLeftOffset || 0; + ctx.save(); + top -= lineHeight / this.lineHeight * this._fontSizeFraction; + for (var i = charOffset, len = line.length + charOffset; i <= len; i++) { + prevStyle = prevStyle || this.getCurrentCharStyle(lineIndex, i); + thisStyle = this.getCurrentCharStyle(lineIndex, i + 1); + if (this._hasStyleChanged(prevStyle, thisStyle) || i === len) { + this._renderChar(method, ctx, lineIndex, i - 1, charsToRender, left, top, lineHeight); + charsToRender = ""; + prevStyle = thisStyle; + } + charsToRender += line[i - charOffset]; + } + ctx.restore(); + }, + _renderCharsFast: function(method, ctx, line, left, top) { + this.skipTextAlign = false; + if (method === "fillText" && this.fill) { + this.callSuper("_renderChars", method, ctx, line, left, top); + } + if (method === "strokeText" && (this.stroke && this.strokeWidth > 0 || this.skipFillStrokeCheck)) { + this.callSuper("_renderChars", method, ctx, line, left, top); + } + }, + _renderChar: function(method, ctx, lineIndex, i, _char, left, top, lineHeight) { + var charWidth, charHeight, shouldFill, shouldStroke, decl = this._getStyleDeclaration(lineIndex, i), offset, textDecoration; + if (decl) { + charHeight = this._getHeightOfChar(ctx, _char, lineIndex, i); + shouldStroke = decl.stroke; + shouldFill = decl.fill; + textDecoration = decl.textDecoration; + } else { + charHeight = this.fontSize; + } + shouldStroke = (shouldStroke || this.stroke) && method === "strokeText"; + shouldFill = (shouldFill || this.fill) && method === "fillText"; + decl && ctx.save(); + charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i, decl || {}); + textDecoration = textDecoration || this.textDecoration; + if (decl && decl.textBackgroundColor) { + this._removeShadow(ctx); + } + shouldFill && ctx.fillText(_char, left, top); + shouldStroke && ctx.strokeText(_char, left, top); + if (textDecoration || textDecoration !== "") { + offset = this._fontSizeFraction * lineHeight / this.lineHeight; + this._renderCharDecoration(ctx, textDecoration, left, top, offset, charWidth, charHeight); + } + decl && ctx.restore(); + ctx.translate(charWidth, 0); + }, + _hasStyleChanged: function(prevStyle, thisStyle) { + return prevStyle.fill !== thisStyle.fill || prevStyle.fontSize !== thisStyle.fontSize || prevStyle.textBackgroundColor !== thisStyle.textBackgroundColor || prevStyle.textDecoration !== thisStyle.textDecoration || prevStyle.fontFamily !== thisStyle.fontFamily || prevStyle.fontWeight !== thisStyle.fontWeight || prevStyle.fontStyle !== thisStyle.fontStyle || prevStyle.stroke !== thisStyle.stroke || prevStyle.strokeWidth !== thisStyle.strokeWidth; + }, + _renderCharDecoration: function(ctx, textDecoration, left, top, offset, charWidth, charHeight) { + if (!textDecoration) { + return; + } + var decorationWeight = charHeight / 15, positions = { + underline: top + charHeight / 10, + "line-through": top - charHeight * (this._fontSizeFraction + this._fontSizeMult - 1) + decorationWeight, + overline: top - (this._fontSizeMult - this._fontSizeFraction) * charHeight + }, decorations = [ "underline", "line-through", "overline" ], i, decoration; + for (i = 0; i < decorations.length; i++) { + decoration = decorations[i]; + if (textDecoration.indexOf(decoration) > -1) { + ctx.fillRect(left, positions[decoration], charWidth, decorationWeight); + } + } + }, + _renderTextLine: function(method, ctx, line, left, top, lineIndex) { + if (!this.isEmptyStyles()) { + top += this.fontSize * (this._fontSizeFraction + .03); + } + this.callSuper("_renderTextLine", method, ctx, line, left, top, lineIndex); + }, + _renderTextDecoration: function(ctx) { + if (this.isEmptyStyles()) { + return this.callSuper("_renderTextDecoration", ctx); + } + }, + _renderTextLinesBackground: function(ctx) { + this.callSuper("_renderTextLinesBackground", ctx); + var lineTopOffset = 0, heightOfLine, lineWidth, lineLeftOffset, leftOffset = this._getLeftOffset(), topOffset = this._getTopOffset(), line, _char, style; + for (var i = 0, len = this._textLines.length; i < len; i++) { + heightOfLine = this._getHeightOfLine(ctx, i); + line = this._textLines[i]; + if (line === "" || !this.styles || !this._getLineStyle(i)) { + lineTopOffset += heightOfLine; + continue; + } + lineWidth = this._getLineWidth(ctx, i); + lineLeftOffset = this._getLineLeftOffset(lineWidth); + for (var j = 0, jlen = line.length; j < jlen; j++) { + style = this._getStyleDeclaration(i, j); + if (!style || !style.textBackgroundColor) { + continue; + } + _char = line[j]; + ctx.fillStyle = style.textBackgroundColor; + ctx.fillRect(leftOffset + lineLeftOffset + this._getWidthOfCharsAt(ctx, i, j), topOffset + lineTopOffset, this._getWidthOfChar(ctx, _char, i, j) + 1, heightOfLine / this.lineHeight); + } + lineTopOffset += heightOfLine; + } + }, + _getCacheProp: function(_char, styleDeclaration) { + return _char + styleDeclaration.fontFamily + styleDeclaration.fontSize + styleDeclaration.fontWeight + styleDeclaration.fontStyle + styleDeclaration.shadow; + }, + _applyCharStylesGetWidth: function(ctx, _char, lineIndex, charIndex, decl) { + var charDecl = this._getStyleDeclaration(lineIndex, charIndex), styleDeclaration = decl && clone(decl) || clone(charDecl), width; + this._applyFontStyles(styleDeclaration); + var cacheProp = this._getCacheProp(_char, styleDeclaration); + if (!charDecl && this._charWidthsCache[cacheProp] && this.caching) { + return this._charWidthsCache[cacheProp]; + } + if (typeof styleDeclaration.shadow === "string") { + styleDeclaration.shadow = new fabric.Shadow(styleDeclaration.shadow); + } + var fill = styleDeclaration.fill || this.fill; + ctx.fillStyle = fill.toLive ? fill.toLive(ctx, this) : fill; + if (styleDeclaration.stroke) { + ctx.strokeStyle = styleDeclaration.stroke && styleDeclaration.stroke.toLive ? styleDeclaration.stroke.toLive(ctx, this) : styleDeclaration.stroke; + } + ctx.lineWidth = styleDeclaration.strokeWidth || this.strokeWidth; + ctx.font = this._getFontDeclaration.call(styleDeclaration); + if (styleDeclaration.shadow) { + styleDeclaration.scaleX = this.scaleX; + styleDeclaration.scaleY = this.scaleY; + styleDeclaration.canvas = this.canvas; + this._setShadow.call(styleDeclaration, ctx); + } + if (!this.caching || !this._charWidthsCache[cacheProp]) { + width = ctx.measureText(_char).width; + this.caching && (this._charWidthsCache[cacheProp] = width); + } + return this._charWidthsCache[cacheProp]; + }, + _applyFontStyles: function(styleDeclaration) { + if (!styleDeclaration.fontFamily) { + styleDeclaration.fontFamily = this.fontFamily; + } + if (!styleDeclaration.fontSize) { + styleDeclaration.fontSize = this.fontSize; + } + if (!styleDeclaration.fontWeight) { + styleDeclaration.fontWeight = this.fontWeight; + } + if (!styleDeclaration.fontStyle) { + styleDeclaration.fontStyle = this.fontStyle; + } + }, + _getStyleDeclaration: function(lineIndex, charIndex, returnCloneOrEmpty) { + if (returnCloneOrEmpty) { + return this.styles[lineIndex] && this.styles[lineIndex][charIndex] ? clone(this.styles[lineIndex][charIndex]) : {}; + } + return this.styles[lineIndex] && this.styles[lineIndex][charIndex] ? this.styles[lineIndex][charIndex] : null; + }, + _setStyleDeclaration: function(lineIndex, charIndex, style) { + this.styles[lineIndex][charIndex] = style; + }, + _deleteStyleDeclaration: function(lineIndex, charIndex) { + delete this.styles[lineIndex][charIndex]; + }, + _getLineStyle: function(lineIndex) { + return this.styles[lineIndex]; + }, + _setLineStyle: function(lineIndex, style) { + this.styles[lineIndex] = style; + }, + _deleteLineStyle: function(lineIndex) { + delete this.styles[lineIndex]; + }, + _getWidthOfChar: function(ctx, _char, lineIndex, charIndex) { + if (this.textAlign === "justify" && this._reSpacesAndTabs.test(_char)) { + return this._getWidthOfSpace(ctx, lineIndex); + } + var styleDeclaration = this._getStyleDeclaration(lineIndex, charIndex, true); + this._applyFontStyles(styleDeclaration); + var cacheProp = this._getCacheProp(_char, styleDeclaration); + if (this._charWidthsCache[cacheProp] && this.caching) { + return this._charWidthsCache[cacheProp]; + } else if (ctx) { + ctx.save(); + var width = this._applyCharStylesGetWidth(ctx, _char, lineIndex, charIndex); + ctx.restore(); + return width; + } + }, + _getHeightOfChar: function(ctx, lineIndex, charIndex) { + var style = this._getStyleDeclaration(lineIndex, charIndex); + return style && style.fontSize ? style.fontSize : this.fontSize; + }, + _getWidthOfCharsAt: function(ctx, lineIndex, charIndex) { + var width = 0, i, _char; + for (i = 0; i < charIndex; i++) { + _char = this._textLines[lineIndex][i]; + width += this._getWidthOfChar(ctx, _char, lineIndex, i); + } + return width; + }, + _getLineWidth: function(ctx, lineIndex) { + if (this.__lineWidths[lineIndex]) { + return this.__lineWidths[lineIndex]; + } + this.__lineWidths[lineIndex] = this._getWidthOfCharsAt(ctx, lineIndex, this._textLines[lineIndex].length); + return this.__lineWidths[lineIndex]; + }, + _getWidthOfSpace: function(ctx, lineIndex) { + if (this.__widthOfSpace[lineIndex]) { + return this.__widthOfSpace[lineIndex]; + } + var line = this._textLines[lineIndex], wordsWidth = this._getWidthOfWords(ctx, line, lineIndex, 0), widthDiff = this.width - wordsWidth, numSpaces = line.length - line.replace(this._reSpacesAndTabs, "").length, width = widthDiff / numSpaces; + this.__widthOfSpace[lineIndex] = width; + return width; + }, + _getWidthOfWords: function(ctx, line, lineIndex, charOffset) { + var width = 0; + for (var charIndex = 0; charIndex < line.length; charIndex++) { + var _char = line[charIndex]; + if (!_char.match(/\s/)) { + width += this._getWidthOfChar(ctx, _char, lineIndex, charIndex + charOffset); + } + } + return width; + }, + _getHeightOfLine: function(ctx, lineIndex) { + if (this.__lineHeights[lineIndex]) { + return this.__lineHeights[lineIndex]; + } + var line = this._textLines[lineIndex], maxHeight = this._getHeightOfChar(ctx, lineIndex, 0); + for (var i = 1, len = line.length; i < len; i++) { + var currentCharHeight = this._getHeightOfChar(ctx, lineIndex, i); + if (currentCharHeight > maxHeight) { + maxHeight = currentCharHeight; + } + } + this.__lineHeights[lineIndex] = maxHeight * this.lineHeight * this._fontSizeMult; + return this.__lineHeights[lineIndex]; + }, + _getTextHeight: function(ctx) { + var height = 0; + for (var i = 0, len = this._textLines.length; i < len; i++) { + height += this._getHeightOfLine(ctx, i); + } + return height; + }, + toObject: function(propertiesToInclude) { + var clonedStyles = {}, i, j, row; + for (i in this.styles) { + row = this.styles[i]; + clonedStyles[i] = {}; + for (j in row) { + clonedStyles[i][j] = clone(row[j]); + } + } + return fabric.util.object.extend(this.callSuper("toObject", propertiesToInclude), { + styles: clonedStyles + }); + } + }); + fabric.IText.fromObject = function(object) { + return new fabric.IText(object.text, clone(object)); + }; +})(); + +(function() { + var clone = fabric.util.object.clone; + fabric.util.object.extend(fabric.IText.prototype, { + initBehavior: function() { + this.initAddedHandler(); + this.initRemovedHandler(); + this.initCursorSelectionHandlers(); + this.initDoubleClickSimulation(); + }, + initSelectedHandler: function() { + this.on("selected", function() { + var _this = this; + setTimeout(function() { + _this.selected = true; + }, 100); + }); + }, + initAddedHandler: function() { + var _this = this; + this.on("added", function() { + if (this.canvas && !this.canvas._hasITextHandlers) { + this.canvas._hasITextHandlers = true; + this._initCanvasHandlers(); + } + if (_this.canvas) { + _this.canvas._iTextInstances = _this.canvas._iTextInstances || []; + _this.canvas._iTextInstances.push(_this); + } + }); + }, + initRemovedHandler: function() { + var _this = this; + this.on("removed", function() { + if (_this.canvas) { + _this.canvas._iTextInstances = _this.canvas._iTextInstances || []; + fabric.util.removeFromArray(_this.canvas._iTextInstances, _this); + } + }); + }, + _initCanvasHandlers: function() { + var _this = this; + this.canvas.on("selection:cleared", function() { + fabric.IText.prototype.exitEditingOnOthers(_this.canvas); + }); + this.canvas.on("mouse:up", function() { + if (_this.canvas._iTextInstances) { + _this.canvas._iTextInstances.forEach(function(obj) { + obj.__isMousedown = false; + }); + } + }); + this.canvas.on("object:selected", function() { + fabric.IText.prototype.exitEditingOnOthers(_this.canvas); + }); + }, + _tick: function() { + this._currentTickState = this._animateCursor(this, 1, this.cursorDuration, "_onTickComplete"); + }, + _animateCursor: function(obj, targetOpacity, duration, completeMethod) { + var tickState; + tickState = { + isAborted: false, + abort: function() { + this.isAborted = true; + } + }; + obj.animate("_currentCursorOpacity", targetOpacity, { + duration: duration, + onComplete: function() { + if (!tickState.isAborted) { + obj[completeMethod](); + } + }, + onChange: function() { + if (obj.canvas) { + obj.canvas.clearContext(obj.canvas.contextTop || obj.ctx); + obj.renderCursorOrSelection(); + } + }, + abort: function() { + return tickState.isAborted; + } + }); + return tickState; + }, + _onTickComplete: function() { + var _this = this; + if (this._cursorTimeout1) { + clearTimeout(this._cursorTimeout1); + } + this._cursorTimeout1 = setTimeout(function() { + _this._currentTickCompleteState = _this._animateCursor(_this, 0, this.cursorDuration / 2, "_tick"); + }, 100); + }, + initDelayedCursor: function(restart) { + var _this = this, delay = restart ? 0 : this.cursorDelay; + this._currentTickState && this._currentTickState.abort(); + this._currentTickCompleteState && this._currentTickCompleteState.abort(); + clearTimeout(this._cursorTimeout1); + this._currentCursorOpacity = 1; + if (this.canvas) { + this.canvas.clearContext(this.canvas.contextTop || this.ctx); + this.renderCursorOrSelection(); + } + if (this._cursorTimeout2) { + clearTimeout(this._cursorTimeout2); + } + this._cursorTimeout2 = setTimeout(function() { + _this._tick(); + }, delay); + }, + abortCursorAnimation: function() { + this._currentTickState && this._currentTickState.abort(); + this._currentTickCompleteState && this._currentTickCompleteState.abort(); + clearTimeout(this._cursorTimeout1); + clearTimeout(this._cursorTimeout2); + this._currentCursorOpacity = 0; + this.canvas && this.canvas.clearContext(this.canvas.contextTop || this.ctx); + }, + selectAll: function() { + this.setSelectionStart(0); + this.setSelectionEnd(this.text.length); + }, + getSelectedText: function() { + return this.text.slice(this.selectionStart, this.selectionEnd); + }, + findWordBoundaryLeft: function(startFrom) { + var offset = 0, index = startFrom - 1; + if (this._reSpace.test(this.text.charAt(index))) { + while (this._reSpace.test(this.text.charAt(index))) { + offset++; + index--; + } + } + while (/\S/.test(this.text.charAt(index)) && index > -1) { + offset++; + index--; + } + return startFrom - offset; + }, + findWordBoundaryRight: function(startFrom) { + var offset = 0, index = startFrom; + if (this._reSpace.test(this.text.charAt(index))) { + while (this._reSpace.test(this.text.charAt(index))) { + offset++; + index++; + } + } + while (/\S/.test(this.text.charAt(index)) && index < this.text.length) { + offset++; + index++; + } + return startFrom + offset; + }, + findLineBoundaryLeft: function(startFrom) { + var offset = 0, index = startFrom - 1; + while (!/\n/.test(this.text.charAt(index)) && index > -1) { + offset++; + index--; + } + return startFrom - offset; + }, + findLineBoundaryRight: function(startFrom) { + var offset = 0, index = startFrom; + while (!/\n/.test(this.text.charAt(index)) && index < this.text.length) { + offset++; + index++; + } + return startFrom + offset; + }, + getNumNewLinesInSelectedText: function() { + var selectedText = this.getSelectedText(), numNewLines = 0; + for (var i = 0, len = selectedText.length; i < len; i++) { + if (selectedText[i] === "\n") { + numNewLines++; + } + } + return numNewLines; + }, + searchWordBoundary: function(selectionStart, direction) { + var index = this._reSpace.test(this.text.charAt(selectionStart)) ? selectionStart - 1 : selectionStart, _char = this.text.charAt(index), reNonWord = /[ \n\.,;!\?\-]/; + while (!reNonWord.test(_char) && index > 0 && index < this.text.length) { + index += direction; + _char = this.text.charAt(index); + } + if (reNonWord.test(_char) && _char !== "\n") { + index += direction === 1 ? 0 : 1; + } + return index; + }, + selectWord: function(selectionStart) { + var newSelectionStart = this.searchWordBoundary(selectionStart, -1), newSelectionEnd = this.searchWordBoundary(selectionStart, 1); + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(newSelectionEnd); + }, + selectLine: function(selectionStart) { + var newSelectionStart = this.findLineBoundaryLeft(selectionStart), newSelectionEnd = this.findLineBoundaryRight(selectionStart); + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(newSelectionEnd); + }, + enterEditing: function(e) { + if (this.isEditing || !this.editable) { + return; + } + if (this.canvas) { + this.exitEditingOnOthers(this.canvas); + } + this.isEditing = true; + this.initHiddenTextarea(e); + this.hiddenTextarea.focus(); + this._updateTextarea(); + this._saveEditingProps(); + this._setEditingProps(); + this._tick(); + this.fire("editing:entered"); + if (!this.canvas) { + return this; + } + this.canvas.renderAll(); + this.canvas.fire("text:editing:entered", { + target: this + }); + this.initMouseMoveHandler(); + return this; + }, + exitEditingOnOthers: function(canvas) { + if (canvas._iTextInstances) { + canvas._iTextInstances.forEach(function(obj) { + obj.selected = false; + if (obj.isEditing) { + obj.exitEditing(); + } + }); + } + }, + initMouseMoveHandler: function() { + var _this = this; + this.canvas.on("mouse:move", function(options) { + if (!_this.__isMousedown || !_this.isEditing) { + return; + } + var newSelectionStart = _this.getSelectionStartFromPointer(options.e); + if (newSelectionStart >= _this.__selectionStartOnMouseDown) { + _this.setSelectionStart(_this.__selectionStartOnMouseDown); + _this.setSelectionEnd(newSelectionStart); + } else { + _this.setSelectionStart(newSelectionStart); + _this.setSelectionEnd(_this.__selectionStartOnMouseDown); + } + }); + }, + _setEditingProps: function() { + this.hoverCursor = "text"; + if (this.canvas) { + this.canvas.defaultCursor = this.canvas.moveCursor = "text"; + } + this.borderColor = this.editingBorderColor; + this.hasControls = this.selectable = false; + this.lockMovementX = this.lockMovementY = true; + }, + _updateTextarea: function() { + if (!this.hiddenTextarea || this.inCompositionMode) { + return; + } + this.hiddenTextarea.value = this.text; + this.hiddenTextarea.selectionStart = this.selectionStart; + this.hiddenTextarea.selectionEnd = this.selectionEnd; + if (this.selectionStart === this.selectionEnd) { + var p = this._calcTextareaPosition(); + this.hiddenTextarea.style.left = p.x + "px"; + this.hiddenTextarea.style.top = p.y + "px"; + } + }, + _calcTextareaPosition: function() { + var chars = this.text.split(""), boundaries = this._getCursorBoundaries(chars, "cursor"), cursorLocation = this.get2DCursorLocation(), lineIndex = cursorLocation.lineIndex, charIndex = cursorLocation.charIndex, charHeight = this.getCurrentCharFontSize(lineIndex, charIndex), leftOffset = lineIndex === 0 && charIndex === 0 ? this._getLineLeftOffset(this._getLineWidth(this.ctx, lineIndex)) : boundaries.leftOffset, m = this.calcTransformMatrix(), p = { + x: boundaries.left + leftOffset, + y: boundaries.top + boundaries.topOffset + charHeight + }; + this.hiddenTextarea.style.fontSize = charHeight + "px"; + return fabric.util.transformPoint(p, m); + }, + _saveEditingProps: function() { + this._savedProps = { + hasControls: this.hasControls, + borderColor: this.borderColor, + lockMovementX: this.lockMovementX, + lockMovementY: this.lockMovementY, + hoverCursor: this.hoverCursor, + defaultCursor: this.canvas && this.canvas.defaultCursor, + moveCursor: this.canvas && this.canvas.moveCursor + }; + }, + _restoreEditingProps: function() { + if (!this._savedProps) { + return; + } + this.hoverCursor = this._savedProps.overCursor; + this.hasControls = this._savedProps.hasControls; + this.borderColor = this._savedProps.borderColor; + this.lockMovementX = this._savedProps.lockMovementX; + this.lockMovementY = this._savedProps.lockMovementY; + if (this.canvas) { + this.canvas.defaultCursor = this._savedProps.defaultCursor; + this.canvas.moveCursor = this._savedProps.moveCursor; + } + }, + exitEditing: function() { + this.selected = false; + this.isEditing = false; + this.selectable = true; + this.selectionEnd = this.selectionStart; + this.hiddenTextarea && this.canvas && this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea); + this.hiddenTextarea = null; + this.abortCursorAnimation(); + this._restoreEditingProps(); + this._currentCursorOpacity = 0; + this.fire("editing:exited"); + this.canvas && this.canvas.fire("text:editing:exited", { + target: this + }); + return this; + }, + _removeExtraneousStyles: function() { + for (var prop in this.styles) { + if (!this._textLines[prop]) { + delete this.styles[prop]; + } + } + }, + _removeCharsFromTo: function(start, end) { + while (end !== start) { + this._removeSingleCharAndStyle(start + 1); + end--; + } + this.setSelectionStart(start); + }, + _removeSingleCharAndStyle: function(index) { + var isBeginningOfLine = this.text[index - 1] === "\n", indexStyle = isBeginningOfLine ? index : index - 1; + this.removeStyleObject(isBeginningOfLine, indexStyle); + this.text = this.text.slice(0, index - 1) + this.text.slice(index); + this._textLines = this._splitTextIntoLines(); + }, + insertChars: function(_chars, useCopiedStyle) { + var style; + if (this.selectionEnd - this.selectionStart > 1) { + this._removeCharsFromTo(this.selectionStart, this.selectionEnd); + this.setSelectionEnd(this.selectionStart); + } + if (!useCopiedStyle && this.isEmptyStyles()) { + this.insertChar(_chars, false); + return; + } + for (var i = 0, len = _chars.length; i < len; i++) { + if (useCopiedStyle) { + style = fabric.copiedTextStyle[i]; + } + this.insertChar(_chars[i], i < len - 1, style); + } + }, + insertChar: function(_char, skipUpdate, styleObject) { + var isEndOfLine = this.text[this.selectionStart] === "\n"; + this.text = this.text.slice(0, this.selectionStart) + _char + this.text.slice(this.selectionEnd); + this._textLines = this._splitTextIntoLines(); + this.insertStyleObjects(_char, isEndOfLine, styleObject); + this.selectionStart += _char.length; + this.selectionEnd = this.selectionStart; + if (skipUpdate) { + return; + } + this._updateTextarea(); + this.canvas && this.canvas.renderAll(); + this.setCoords(); + this.fire("changed"); + this.canvas && this.canvas.fire("text:changed", { + target: this + }); + }, + insertNewlineStyleObject: function(lineIndex, charIndex, isEndOfLine) { + this.shiftLineStyles(lineIndex, +1); + if (!this.styles[lineIndex + 1]) { + this.styles[lineIndex + 1] = {}; + } + var currentCharStyle = {}, newLineStyles = {}; + if (this.styles[lineIndex] && this.styles[lineIndex][charIndex - 1]) { + currentCharStyle = this.styles[lineIndex][charIndex - 1]; + } + if (isEndOfLine) { + newLineStyles[0] = clone(currentCharStyle); + this.styles[lineIndex + 1] = newLineStyles; + } else { + for (var index in this.styles[lineIndex]) { + if (parseInt(index, 10) >= charIndex) { + newLineStyles[parseInt(index, 10) - charIndex] = this.styles[lineIndex][index]; + delete this.styles[lineIndex][index]; + } + } + this.styles[lineIndex + 1] = newLineStyles; + } + this._forceClearCache = true; + }, + insertCharStyleObject: function(lineIndex, charIndex, style) { + var currentLineStyles = this.styles[lineIndex], currentLineStylesCloned = clone(currentLineStyles); + if (charIndex === 0 && !style) { + charIndex = 1; + } + for (var index in currentLineStylesCloned) { + var numericIndex = parseInt(index, 10); + if (numericIndex >= charIndex) { + currentLineStyles[numericIndex + 1] = currentLineStylesCloned[numericIndex]; + if (!currentLineStylesCloned[numericIndex - 1]) { + delete currentLineStyles[numericIndex]; + } + } + } + this.styles[lineIndex][charIndex] = style || clone(currentLineStyles[charIndex - 1]); + this._forceClearCache = true; + }, + insertStyleObjects: function(_chars, isEndOfLine, styleObject) { + var cursorLocation = this.get2DCursorLocation(), lineIndex = cursorLocation.lineIndex, charIndex = cursorLocation.charIndex; + if (!this._getLineStyle(lineIndex)) { + this._setLineStyle(lineIndex, {}); + } + if (_chars === "\n") { + this.insertNewlineStyleObject(lineIndex, charIndex, isEndOfLine); + } else { + this.insertCharStyleObject(lineIndex, charIndex, styleObject); + } + }, + shiftLineStyles: function(lineIndex, offset) { + var clonedStyles = clone(this.styles); + for (var line in this.styles) { + var numericLine = parseInt(line, 10); + if (numericLine > lineIndex) { + this.styles[numericLine + offset] = clonedStyles[numericLine]; + if (!clonedStyles[numericLine - offset]) { + delete this.styles[numericLine]; + } + } + } + }, + removeStyleObject: function(isBeginningOfLine, index) { + var cursorLocation = this.get2DCursorLocation(index), lineIndex = cursorLocation.lineIndex, charIndex = cursorLocation.charIndex; + this._removeStyleObject(isBeginningOfLine, cursorLocation, lineIndex, charIndex); + }, + _getTextOnPreviousLine: function(lIndex) { + return this._textLines[lIndex - 1]; + }, + _removeStyleObject: function(isBeginningOfLine, cursorLocation, lineIndex, charIndex) { + if (isBeginningOfLine) { + var textOnPreviousLine = this._getTextOnPreviousLine(cursorLocation.lineIndex), newCharIndexOnPrevLine = textOnPreviousLine ? textOnPreviousLine.length : 0; + if (!this.styles[lineIndex - 1]) { + this.styles[lineIndex - 1] = {}; + } + for (charIndex in this.styles[lineIndex]) { + this.styles[lineIndex - 1][parseInt(charIndex, 10) + newCharIndexOnPrevLine] = this.styles[lineIndex][charIndex]; + } + this.shiftLineStyles(cursorLocation.lineIndex, -1); + } else { + var currentLineStyles = this.styles[lineIndex]; + if (currentLineStyles) { + delete currentLineStyles[charIndex]; + } + var currentLineStylesCloned = clone(currentLineStyles); + for (var i in currentLineStylesCloned) { + var numericIndex = parseInt(i, 10); + if (numericIndex >= charIndex && numericIndex !== 0) { + currentLineStyles[numericIndex - 1] = currentLineStylesCloned[numericIndex]; + delete currentLineStyles[numericIndex]; + } + } + } + }, + insertNewline: function() { + this.insertChars("\n"); + } + }); +})(); + +fabric.util.object.extend(fabric.IText.prototype, { + initDoubleClickSimulation: function() { + this.__lastClickTime = +new Date(); + this.__lastLastClickTime = +new Date(); + this.__lastPointer = {}; + this.on("mousedown", this.onMouseDown.bind(this)); + }, + onMouseDown: function(options) { + this.__newClickTime = +new Date(); + var newPointer = this.canvas.getPointer(options.e); + if (this.isTripleClick(newPointer)) { + this.fire("tripleclick", options); + this._stopEvent(options.e); + } else if (this.isDoubleClick(newPointer)) { + this.fire("dblclick", options); + this._stopEvent(options.e); + } + this.__lastLastClickTime = this.__lastClickTime; + this.__lastClickTime = this.__newClickTime; + this.__lastPointer = newPointer; + this.__lastIsEditing = this.isEditing; + this.__lastSelected = this.selected; + }, + isDoubleClick: function(newPointer) { + return this.__newClickTime - this.__lastClickTime < 500 && this.__lastPointer.x === newPointer.x && this.__lastPointer.y === newPointer.y && this.__lastIsEditing; + }, + isTripleClick: function(newPointer) { + return this.__newClickTime - this.__lastClickTime < 500 && this.__lastClickTime - this.__lastLastClickTime < 500 && this.__lastPointer.x === newPointer.x && this.__lastPointer.y === newPointer.y; + }, + _stopEvent: function(e) { + e.preventDefault && e.preventDefault(); + e.stopPropagation && e.stopPropagation(); + }, + initCursorSelectionHandlers: function() { + this.initSelectedHandler(); + this.initMousedownHandler(); + this.initMouseupHandler(); + this.initClicks(); + }, + initClicks: function() { + this.on("dblclick", function(options) { + this.selectWord(this.getSelectionStartFromPointer(options.e)); + }); + this.on("tripleclick", function(options) { + this.selectLine(this.getSelectionStartFromPointer(options.e)); + }); + }, + initMousedownHandler: function() { + this.on("mousedown", function(options) { + if (!this.editable) { + return; + } + var pointer = this.canvas.getPointer(options.e); + this.__mousedownX = pointer.x; + this.__mousedownY = pointer.y; + this.__isMousedown = true; + if (this.hiddenTextarea && this.canvas) { + this.canvas.wrapperEl.appendChild(this.hiddenTextarea); + } + if (this.selected) { + this.setCursorByClick(options.e); + } + if (this.isEditing) { + this.__selectionStartOnMouseDown = this.selectionStart; + this.initDelayedCursor(true); + } + }); + }, + _isObjectMoved: function(e) { + var pointer = this.canvas.getPointer(e); + return this.__mousedownX !== pointer.x || this.__mousedownY !== pointer.y; + }, + initMouseupHandler: function() { + this.on("mouseup", function(options) { + this.__isMousedown = false; + if (!this.editable || this._isObjectMoved(options.e)) { + return; + } + if (this.__lastSelected && !this.__corner) { + this.enterEditing(options.e); + this.initDelayedCursor(true); + } + this.selected = true; + }); + }, + setCursorByClick: function(e) { + var newSelectionStart = this.getSelectionStartFromPointer(e); + if (e.shiftKey) { + if (newSelectionStart < this.selectionStart) { + this.setSelectionEnd(this.selectionStart); + this.setSelectionStart(newSelectionStart); + } else { + this.setSelectionEnd(newSelectionStart); + } + } else { + this.setSelectionStart(newSelectionStart); + this.setSelectionEnd(newSelectionStart); + } + }, + getSelectionStartFromPointer: function(e) { + var mouseOffset = this.getLocalPointer(e), prevWidth = 0, width = 0, height = 0, charIndex = 0, newSelectionStart, line; + for (var i = 0, len = this._textLines.length; i < len; i++) { + line = this._textLines[i]; + height += this._getHeightOfLine(this.ctx, i) * this.scaleY; + var widthOfLine = this._getLineWidth(this.ctx, i), lineLeftOffset = this._getLineLeftOffset(widthOfLine); + width = lineLeftOffset * this.scaleX; + for (var j = 0, jlen = line.length; j < jlen; j++) { + prevWidth = width; + width += this._getWidthOfChar(this.ctx, line[j], i, this.flipX ? jlen - j : j) * this.scaleX; + if (height <= mouseOffset.y || width <= mouseOffset.x) { + charIndex++; + continue; + } + return this._getNewSelectionStartFromOffset(mouseOffset, prevWidth, width, charIndex + i, jlen); + } + if (mouseOffset.y < height) { + return this._getNewSelectionStartFromOffset(mouseOffset, prevWidth, width, charIndex + i - 1, jlen); + } + } + if (typeof newSelectionStart === "undefined") { + return this.text.length; + } + }, + _getNewSelectionStartFromOffset: function(mouseOffset, prevWidth, width, index, jlen) { + var distanceBtwLastCharAndCursor = mouseOffset.x - prevWidth, distanceBtwNextCharAndCursor = width - mouseOffset.x, offset = distanceBtwNextCharAndCursor > distanceBtwLastCharAndCursor ? 0 : 1, newSelectionStart = index + offset; + if (this.flipX) { + newSelectionStart = jlen - newSelectionStart; + } + if (newSelectionStart > this.text.length) { + newSelectionStart = this.text.length; + } + return newSelectionStart; + } +}); + +fabric.util.object.extend(fabric.IText.prototype, { + initHiddenTextarea: function(e) { + var p; + if (e && this.canvas) { + p = this.canvas.getPointer(e); + } else { + this.oCoords || this.setCoords(); + p = this.oCoords.tl; + } + this.hiddenTextarea = fabric.document.createElement("textarea"); + this.hiddenTextarea.setAttribute("autocapitalize", "off"); + this.hiddenTextarea.style.cssText = "position: absolute; top: " + p.y + "px; left: " + p.x + "px; opacity: 0;" + " width: 0px; height: 0px; z-index: -999;"; + if (this.canvas) { + this.canvas.lowerCanvasEl.parentNode.appendChild(this.hiddenTextarea); + } else { + fabric.document.body.appendChild(this.hiddenTextarea); + } + fabric.util.addListener(this.hiddenTextarea, "keydown", this.onKeyDown.bind(this)); + fabric.util.addListener(this.hiddenTextarea, "keyup", this.onKeyUp.bind(this)); + fabric.util.addListener(this.hiddenTextarea, "input", this.onInput.bind(this)); + fabric.util.addListener(this.hiddenTextarea, "copy", this.copy.bind(this)); + fabric.util.addListener(this.hiddenTextarea, "cut", this.cut.bind(this)); + fabric.util.addListener(this.hiddenTextarea, "paste", this.paste.bind(this)); + fabric.util.addListener(this.hiddenTextarea, "compositionstart", this.onCompositionStart.bind(this)); + fabric.util.addListener(this.hiddenTextarea, "compositionupdate", this.onCompositionUpdate.bind(this)); + fabric.util.addListener(this.hiddenTextarea, "compositionend", this.onCompositionEnd.bind(this)); + if (!this._clickHandlerInitialized && this.canvas) { + fabric.util.addListener(this.canvas.upperCanvasEl, "click", this.onClick.bind(this)); + this._clickHandlerInitialized = true; + } + }, + _keysMap: { + 8: "removeChars", + 9: "exitEditing", + 27: "exitEditing", + 13: "insertNewline", + 33: "moveCursorUp", + 34: "moveCursorDown", + 35: "moveCursorRight", + 36: "moveCursorLeft", + 37: "moveCursorLeft", + 38: "moveCursorUp", + 39: "moveCursorRight", + 40: "moveCursorDown", + 46: "forwardDelete" + }, + _ctrlKeysMap: { + 65: "selectAll", + 67: "copy", + 88: "cut" + }, + onClick: function() { + this.hiddenTextarea && this.hiddenTextarea.focus(); + }, + onKeyDown: function(e) { + if (!this.isEditing) { + return; + } + if (e.keyCode in this._keysMap) { + this[this._keysMap[e.keyCode]](e); + } else { + return; + } + e.stopImmediatePropagation(); + e.preventDefault(); + this.canvas && this.canvas.renderAll(); + }, + onKeyUp: function(e) { + if (!this.isEditing || this._copyDone) { + this._copyDone = false; + return; + } + if (e.keyCode in this._ctrlKeysMap && (e.ctrlKey || e.metaKey)) { + this[this._ctrlKeysMap[e.keyCode]](e); + } else { + return; + } + e.stopImmediatePropagation(); + e.preventDefault(); + this.canvas && this.canvas.renderAll(); + }, + onInput: function(e) { + if (!this.isEditing || this.inCompositionMode) { + return; + } + var offset = this.selectionStart || 0, offsetEnd = this.selectionEnd || 0, textLength = this.text.length, newTextLength = this.hiddenTextarea.value.length, diff, charsToInsert, start; + if (newTextLength > textLength) { + start = this._selectionDirection === "left" ? offsetEnd : offset; + diff = newTextLength - textLength; + charsToInsert = this.hiddenTextarea.value.slice(start, start + diff); + } else { + diff = newTextLength - textLength + offsetEnd - offset; + charsToInsert = this.hiddenTextarea.value.slice(offset, offset + diff); + } + this.insertChars(charsToInsert); + e.stopPropagation(); + }, + onCompositionStart: function() { + this.inCompositionMode = true; + this.prevCompositionLength = 0; + this.compositionStart = this.selectionStart; + }, + onCompositionEnd: function() { + this.inCompositionMode = false; + }, + onCompositionUpdate: function(e) { + var data = e.data; + this.selectionStart = this.compositionStart; + this.selectionEnd = this.selectionEnd === this.selectionStart ? this.compositionStart + this.prevCompositionLength : this.selectionEnd; + this.insertChars(data, false); + this.prevCompositionLength = data.length; + }, + forwardDelete: function(e) { + if (this.selectionStart === this.selectionEnd) { + if (this.selectionStart === this.text.length) { + return; + } + this.moveCursorRight(e); + } + this.removeChars(e); + }, + copy: function(e) { + if (this.selectionStart === this.selectionEnd) { + return; + } + var selectedText = this.getSelectedText(), clipboardData = this._getClipboardData(e); + if (clipboardData) { + clipboardData.setData("text", selectedText); + } + fabric.copiedText = selectedText; + fabric.copiedTextStyle = this.getSelectionStyles(this.selectionStart, this.selectionEnd); + e.stopImmediatePropagation(); + e.preventDefault(); + this._copyDone = true; + }, + paste: function(e) { + var copiedText = null, clipboardData = this._getClipboardData(e), useCopiedStyle = true; + if (clipboardData) { + copiedText = clipboardData.getData("text").replace(/\r/g, ""); + if (!fabric.copiedTextStyle || fabric.copiedText !== copiedText) { + useCopiedStyle = false; + } + } else { + copiedText = fabric.copiedText; + } + if (copiedText) { + this.insertChars(copiedText, useCopiedStyle); + } + e.stopImmediatePropagation(); + e.preventDefault(); + }, + cut: function(e) { + if (this.selectionStart === this.selectionEnd) { + return; + } + this.copy(e); + this.removeChars(e); + }, + _getClipboardData: function(e) { + return e && e.clipboardData || fabric.window.clipboardData; + }, + getDownCursorOffset: function(e, isRight) { + var selectionProp = isRight ? this.selectionEnd : this.selectionStart, cursorLocation = this.get2DCursorLocation(selectionProp), _char, lineLeftOffset, lineIndex = cursorLocation.lineIndex, textOnSameLineBeforeCursor = this._textLines[lineIndex].slice(0, cursorLocation.charIndex), textOnSameLineAfterCursor = this._textLines[lineIndex].slice(cursorLocation.charIndex), textOnNextLine = this._textLines[lineIndex + 1] || ""; + if (lineIndex === this._textLines.length - 1 || e.metaKey || e.keyCode === 34) { + return this.text.length - selectionProp; + } + var widthOfSameLineBeforeCursor = this._getLineWidth(this.ctx, lineIndex); + lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor); + var widthOfCharsOnSameLineBeforeCursor = lineLeftOffset; + for (var i = 0, len = textOnSameLineBeforeCursor.length; i < len; i++) { + _char = textOnSameLineBeforeCursor[i]; + widthOfCharsOnSameLineBeforeCursor += this._getWidthOfChar(this.ctx, _char, lineIndex, i); + } + var indexOnNextLine = this._getIndexOnNextLine(cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor); + return textOnSameLineAfterCursor.length + 1 + indexOnNextLine; + }, + _getIndexOnNextLine: function(cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor) { + var lineIndex = cursorLocation.lineIndex + 1, widthOfNextLine = this._getLineWidth(this.ctx, lineIndex), lineLeftOffset = this._getLineLeftOffset(widthOfNextLine), widthOfCharsOnNextLine = lineLeftOffset, indexOnNextLine = 0, foundMatch; + for (var j = 0, jlen = textOnNextLine.length; j < jlen; j++) { + var _char = textOnNextLine[j], widthOfChar = this._getWidthOfChar(this.ctx, _char, lineIndex, j); + widthOfCharsOnNextLine += widthOfChar; + if (widthOfCharsOnNextLine > widthOfCharsOnSameLineBeforeCursor) { + foundMatch = true; + var leftEdge = widthOfCharsOnNextLine - widthOfChar, rightEdge = widthOfCharsOnNextLine, offsetFromLeftEdge = Math.abs(leftEdge - widthOfCharsOnSameLineBeforeCursor), offsetFromRightEdge = Math.abs(rightEdge - widthOfCharsOnSameLineBeforeCursor); + indexOnNextLine = offsetFromRightEdge < offsetFromLeftEdge ? j + 1 : j; + break; + } + } + if (!foundMatch) { + indexOnNextLine = textOnNextLine.length; + } + return indexOnNextLine; + }, + moveCursorDown: function(e) { + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + var offset = this.getDownCursorOffset(e, this._selectionDirection === "right"); + if (e.shiftKey) { + this.moveCursorDownWithShift(offset); + } else { + this.moveCursorDownWithoutShift(offset); + } + this.initDelayedCursor(); + }, + moveCursorDownWithoutShift: function(offset) { + this._selectionDirection = "right"; + this.setSelectionStart(this.selectionStart + offset); + this.setSelectionEnd(this.selectionStart); + }, + swapSelectionPoints: function() { + var swapSel = this.selectionEnd; + this.setSelectionEnd(this.selectionStart); + this.setSelectionStart(swapSel); + }, + moveCursorDownWithShift: function(offset) { + if (this.selectionEnd === this.selectionStart) { + this._selectionDirection = "right"; + } + if (this._selectionDirection === "right") { + this.setSelectionEnd(this.selectionEnd + offset); + } else { + this.setSelectionStart(this.selectionStart + offset); + } + if (this.selectionEnd < this.selectionStart && this._selectionDirection === "left") { + this.swapSelectionPoints(); + this._selectionDirection = "right"; + } + if (this.selectionEnd > this.text.length) { + this.setSelectionEnd(this.text.length); + } + }, + getUpCursorOffset: function(e, isRight) { + var selectionProp = isRight ? this.selectionEnd : this.selectionStart, cursorLocation = this.get2DCursorLocation(selectionProp), lineIndex = cursorLocation.lineIndex; + if (lineIndex === 0 || e.metaKey || e.keyCode === 33) { + return selectionProp; + } + var textOnSameLineBeforeCursor = this._textLines[lineIndex].slice(0, cursorLocation.charIndex), textOnPreviousLine = this._textLines[lineIndex - 1] || "", _char, widthOfSameLineBeforeCursor = this._getLineWidth(this.ctx, cursorLocation.lineIndex), lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor), widthOfCharsOnSameLineBeforeCursor = lineLeftOffset; + for (var i = 0, len = textOnSameLineBeforeCursor.length; i < len; i++) { + _char = textOnSameLineBeforeCursor[i]; + widthOfCharsOnSameLineBeforeCursor += this._getWidthOfChar(this.ctx, _char, lineIndex, i); + } + var indexOnPrevLine = this._getIndexOnPrevLine(cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor); + return textOnPreviousLine.length - indexOnPrevLine + textOnSameLineBeforeCursor.length; + }, + _getIndexOnPrevLine: function(cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor) { + var lineIndex = cursorLocation.lineIndex - 1, widthOfPreviousLine = this._getLineWidth(this.ctx, lineIndex), lineLeftOffset = this._getLineLeftOffset(widthOfPreviousLine), widthOfCharsOnPreviousLine = lineLeftOffset, indexOnPrevLine = 0, foundMatch; + for (var j = 0, jlen = textOnPreviousLine.length; j < jlen; j++) { + var _char = textOnPreviousLine[j], widthOfChar = this._getWidthOfChar(this.ctx, _char, lineIndex, j); + widthOfCharsOnPreviousLine += widthOfChar; + if (widthOfCharsOnPreviousLine > widthOfCharsOnSameLineBeforeCursor) { + foundMatch = true; + var leftEdge = widthOfCharsOnPreviousLine - widthOfChar, rightEdge = widthOfCharsOnPreviousLine, offsetFromLeftEdge = Math.abs(leftEdge - widthOfCharsOnSameLineBeforeCursor), offsetFromRightEdge = Math.abs(rightEdge - widthOfCharsOnSameLineBeforeCursor); + indexOnPrevLine = offsetFromRightEdge < offsetFromLeftEdge ? j : j - 1; + break; + } + } + if (!foundMatch) { + indexOnPrevLine = textOnPreviousLine.length - 1; + } + return indexOnPrevLine; + }, + moveCursorUp: function(e) { + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + var offset = this.getUpCursorOffset(e, this._selectionDirection === "right"); + if (e.shiftKey) { + this.moveCursorUpWithShift(offset); + } else { + this.moveCursorUpWithoutShift(offset); + } + this.initDelayedCursor(); + }, + moveCursorUpWithShift: function(offset) { + if (this.selectionEnd === this.selectionStart) { + this._selectionDirection = "left"; + } + if (this._selectionDirection === "right") { + this.setSelectionEnd(this.selectionEnd - offset); + } else { + this.setSelectionStart(this.selectionStart - offset); + } + if (this.selectionEnd < this.selectionStart && this._selectionDirection === "right") { + this.swapSelectionPoints(); + this._selectionDirection = "left"; + } + }, + moveCursorUpWithoutShift: function(offset) { + if (this.selectionStart === this.selectionEnd) { + this.setSelectionStart(this.selectionStart - offset); + } + this.setSelectionEnd(this.selectionStart); + this._selectionDirection = "left"; + }, + moveCursorLeft: function(e) { + if (this.selectionStart === 0 && this.selectionEnd === 0) { + return; + } + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + if (e.shiftKey) { + this.moveCursorLeftWithShift(e); + } else { + this.moveCursorLeftWithoutShift(e); + } + this.initDelayedCursor(); + }, + _move: function(e, prop, direction) { + var propMethod = prop === "selectionStart" ? "setSelectionStart" : "setSelectionEnd"; + if (e.altKey) { + this[propMethod](this["findWordBoundary" + direction](this[prop])); + } else if (e.metaKey || e.keyCode === 35 || e.keyCode === 36) { + this[propMethod](this["findLineBoundary" + direction](this[prop])); + } else { + this[propMethod](this[prop] + (direction === "Left" ? -1 : 1)); + } + }, + _moveLeft: function(e, prop) { + this._move(e, prop, "Left"); + }, + _moveRight: function(e, prop) { + this._move(e, prop, "Right"); + }, + moveCursorLeftWithoutShift: function(e) { + this._selectionDirection = "left"; + if (this.selectionEnd === this.selectionStart) { + this._moveLeft(e, "selectionStart"); + } + this.setSelectionEnd(this.selectionStart); + }, + moveCursorLeftWithShift: function(e) { + if (this._selectionDirection === "right" && this.selectionStart !== this.selectionEnd) { + this._moveLeft(e, "selectionEnd"); + } else { + this._selectionDirection = "left"; + this._moveLeft(e, "selectionStart"); + } + }, + moveCursorRight: function(e) { + if (this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length) { + return; + } + this.abortCursorAnimation(); + this._currentCursorOpacity = 1; + if (e.shiftKey) { + this.moveCursorRightWithShift(e); + } else { + this.moveCursorRightWithoutShift(e); + } + this.initDelayedCursor(); + }, + moveCursorRightWithShift: function(e) { + if (this._selectionDirection === "left" && this.selectionStart !== this.selectionEnd) { + this._moveRight(e, "selectionStart"); + } else { + this._selectionDirection = "right"; + this._moveRight(e, "selectionEnd"); + } + }, + moveCursorRightWithoutShift: function(e) { + this._selectionDirection = "right"; + if (this.selectionStart === this.selectionEnd) { + this._moveRight(e, "selectionStart"); + this.setSelectionEnd(this.selectionStart); + } else { + this.setSelectionEnd(this.selectionEnd + this.getNumNewLinesInSelectedText()); + this.setSelectionStart(this.selectionEnd); + } + }, + removeChars: function(e) { + if (this.selectionStart === this.selectionEnd) { + this._removeCharsNearCursor(e); + } else { + this._removeCharsFromTo(this.selectionStart, this.selectionEnd); + } + this.setSelectionEnd(this.selectionStart); + this._removeExtraneousStyles(); + this.canvas && this.canvas.renderAll(); + this.setCoords(); + this.fire("changed"); + this.canvas && this.canvas.fire("text:changed", { + target: this + }); + }, + _removeCharsNearCursor: function(e) { + if (this.selectionStart === 0) { + return; + } + if (e.metaKey) { + var leftLineBoundary = this.findLineBoundaryLeft(this.selectionStart); + this._removeCharsFromTo(leftLineBoundary, this.selectionStart); + this.setSelectionStart(leftLineBoundary); + } else if (e.altKey) { + var leftWordBoundary = this.findWordBoundaryLeft(this.selectionStart); + this._removeCharsFromTo(leftWordBoundary, this.selectionStart); + this.setSelectionStart(leftWordBoundary); + } else { + this._removeSingleCharAndStyle(this.selectionStart); + this.setSelectionStart(this.selectionStart - 1); + } + } +}); + +(function() { + var toFixed = fabric.util.toFixed, NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; + fabric.util.object.extend(fabric.IText.prototype, { + _setSVGTextLineText: function(lineIndex, textSpans, height, textLeftOffset, textTopOffset, textBgRects) { + if (!this._getLineStyle(lineIndex)) { + fabric.Text.prototype._setSVGTextLineText.call(this, lineIndex, textSpans, height, textLeftOffset, textTopOffset); + } else { + this._setSVGTextLineChars(lineIndex, textSpans, height, textLeftOffset, textBgRects); + } + }, + _setSVGTextLineChars: function(lineIndex, textSpans, height, textLeftOffset, textBgRects) { + var chars = this._textLines[lineIndex], charOffset = 0, lineLeftOffset = this._getLineLeftOffset(this._getLineWidth(this.ctx, lineIndex)) - this.width / 2, lineOffset = this._getSVGLineTopOffset(lineIndex), heightOfLine = this._getHeightOfLine(this.ctx, lineIndex); + for (var i = 0, len = chars.length; i < len; i++) { + var styleDecl = this._getStyleDeclaration(lineIndex, i) || {}; + textSpans.push(this._createTextCharSpan(chars[i], styleDecl, lineLeftOffset, lineOffset.lineTop + lineOffset.offset, charOffset)); + var charWidth = this._getWidthOfChar(this.ctx, chars[i], lineIndex, i); + if (styleDecl.textBackgroundColor) { + textBgRects.push(this._createTextCharBg(styleDecl, lineLeftOffset, lineOffset.lineTop, heightOfLine, charWidth, charOffset)); + } + charOffset += charWidth; + } + }, + _getSVGLineTopOffset: function(lineIndex) { + var lineTopOffset = 0, lastHeight = 0; + for (var j = 0; j < lineIndex; j++) { + lineTopOffset += this._getHeightOfLine(this.ctx, j); + } + lastHeight = this._getHeightOfLine(this.ctx, j); + return { + lineTop: lineTopOffset, + offset: (this._fontSizeMult - this._fontSizeFraction) * lastHeight / (this.lineHeight * this._fontSizeMult) + }; + }, + _createTextCharBg: function(styleDecl, lineLeftOffset, lineTopOffset, heightOfLine, charWidth, charOffset) { + return [ ' \n' ].join(""); + }, + _createTextCharSpan: function(_char, styleDecl, lineLeftOffset, lineTopOffset, charOffset) { + var fillStyles = this.getSvgStyles.call(fabric.util.object.extend({ + visible: true, + fill: this.fill, + stroke: this.stroke, + type: "text", + getSvgFilter: fabric.Object.prototype.getSvgFilter + }, styleDecl)); + return [ ' ', fabric.util.string.escapeXml(_char), "\n" ].join(""); + } + }); +})(); + +(function(global) { + "use strict"; + var fabric = global.fabric || (global.fabric = {}), clone = fabric.util.object.clone; + fabric.Textbox = fabric.util.createClass(fabric.IText, fabric.Observable, { + type: "textbox", + minWidth: 20, + dynamicMinWidth: 0, + __cachedLines: null, + initialize: function(text, options) { + this.ctx = fabric.util.createCanvasElement().getContext("2d"); + this.callSuper("initialize", text, options); + this.set({ + lockUniScaling: false, + lockScalingY: true, + lockScalingFlip: true, + hasBorders: true + }); + this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility()); + this._dimensionAffectingProps.width = true; + }, + _initDimensions: function(ctx) { + if (this.__skipDimension) { + return; + } + if (!ctx) { + ctx = fabric.util.createCanvasElement().getContext("2d"); + this._setTextStyles(ctx); + } + this.dynamicMinWidth = 0; + this._textLines = this._splitTextIntoLines(); + if (this.dynamicMinWidth > this.width) { + this._set("width", this.dynamicMinWidth); + } + this._clearCache(); + this.height = this._getTextHeight(ctx); + }, + _generateStyleMap: function() { + var realLineCount = 0, realLineCharCount = 0, charCount = 0, map = {}; + for (var i = 0; i < this._textLines.length; i++) { + if (this.text[charCount] === "\n") { + realLineCharCount = 0; + charCount++; + realLineCount++; + } else if (this.text[charCount] === " ") { + realLineCharCount++; + charCount++; + } + map[i] = { + line: realLineCount, + offset: realLineCharCount + }; + charCount += this._textLines[i].length; + realLineCharCount += this._textLines[i].length; + } + return map; + }, + _getStyleDeclaration: function(lineIndex, charIndex, returnCloneOrEmpty) { + if (this._styleMap) { + var map = this._styleMap[lineIndex]; + if (!map) { + return returnCloneOrEmpty ? {} : null; + } + lineIndex = map.line; + charIndex = map.offset + charIndex; + } + return this.callSuper("_getStyleDeclaration", lineIndex, charIndex, returnCloneOrEmpty); + }, + _setStyleDeclaration: function(lineIndex, charIndex, style) { + var map = this._styleMap[lineIndex]; + lineIndex = map.line; + charIndex = map.offset + charIndex; + this.styles[lineIndex][charIndex] = style; + }, + _deleteStyleDeclaration: function(lineIndex, charIndex) { + var map = this._styleMap[lineIndex]; + lineIndex = map.line; + charIndex = map.offset + charIndex; + delete this.styles[lineIndex][charIndex]; + }, + _getLineStyle: function(lineIndex) { + var map = this._styleMap[lineIndex]; + return this.styles[map.line]; + }, + _setLineStyle: function(lineIndex, style) { + var map = this._styleMap[lineIndex]; + this.styles[map.line] = style; + }, + _deleteLineStyle: function(lineIndex) { + var map = this._styleMap[lineIndex]; + delete this.styles[map.line]; + }, + _wrapText: function(ctx, text) { + var lines = text.split(this._reNewline), wrapped = [], i; + for (i = 0; i < lines.length; i++) { + wrapped = wrapped.concat(this._wrapLine(ctx, lines[i], i)); + } + return wrapped; + }, + _measureText: function(ctx, text, lineIndex, charOffset) { + var width = 0; + charOffset = charOffset || 0; + for (var i = 0, len = text.length; i < len; i++) { + width += this._getWidthOfChar(ctx, text[i], lineIndex, i + charOffset); + } + return width; + }, + _wrapLine: function(ctx, text, lineIndex) { + var lineWidth = 0, lines = [], line = "", words = text.split(" "), word = "", offset = 0, infix = " ", wordWidth = 0, infixWidth = 0, largestWordWidth = 0, lineJustStarted = true; + for (var i = 0; i < words.length; i++) { + word = words[i]; + wordWidth = this._measureText(ctx, word, lineIndex, offset); + offset += word.length; + lineWidth += infixWidth + wordWidth; + if (lineWidth >= this.width && !lineJustStarted) { + lines.push(line); + line = ""; + lineWidth = wordWidth; + lineJustStarted = true; + } + if (!lineJustStarted) { + line += infix; + } + line += word; + infixWidth = this._measureText(ctx, infix, lineIndex, offset); + offset++; + lineJustStarted = false; + if (wordWidth > largestWordWidth) { + largestWordWidth = wordWidth; + } + } + i && lines.push(line); + if (largestWordWidth > this.dynamicMinWidth) { + this.dynamicMinWidth = largestWordWidth; + } + return lines; + }, + _splitTextIntoLines: function() { + var originalAlign = this.textAlign; + this.ctx.save(); + this._setTextStyles(this.ctx); + this.textAlign = "left"; + var lines = this._wrapText(this.ctx, this.text); + this.textAlign = originalAlign; + this.ctx.restore(); + this._textLines = lines; + this._styleMap = this._generateStyleMap(); + return lines; + }, + setOnGroup: function(key, value) { + if (key === "scaleX") { + this.set("scaleX", Math.abs(1 / value)); + this.set("width", this.get("width") * value / (typeof this.__oldScaleX === "undefined" ? 1 : this.__oldScaleX)); + this.__oldScaleX = value; + } + }, + get2DCursorLocation: function(selectionStart) { + if (typeof selectionStart === "undefined") { + selectionStart = this.selectionStart; + } + var numLines = this._textLines.length, removed = 0; + for (var i = 0; i < numLines; i++) { + var line = this._textLines[i], lineLen = line.length; + if (selectionStart <= removed + lineLen) { + return { + lineIndex: i, + charIndex: selectionStart - removed + }; + } + removed += lineLen; + if (this.text[removed] === "\n" || this.text[removed] === " ") { + removed++; + } + } + return { + lineIndex: numLines - 1, + charIndex: this._textLines[numLines - 1].length + }; + }, + _getCursorBoundariesOffsets: function(chars, typeOfBoundaries) { + var topOffset = 0, leftOffset = 0, cursorLocation = this.get2DCursorLocation(), lineChars = this._textLines[cursorLocation.lineIndex].split(""), lineLeftOffset = this._getLineLeftOffset(this._getLineWidth(this.ctx, cursorLocation.lineIndex)); + for (var i = 0; i < cursorLocation.charIndex; i++) { + leftOffset += this._getWidthOfChar(this.ctx, lineChars[i], cursorLocation.lineIndex, i); + } + for (i = 0; i < cursorLocation.lineIndex; i++) { + topOffset += this._getHeightOfLine(this.ctx, i); + } + if (typeOfBoundaries === "cursor") { + topOffset += (1 - this._fontSizeFraction) * this._getHeightOfLine(this.ctx, cursorLocation.lineIndex) / this.lineHeight - this.getCurrentCharFontSize(cursorLocation.lineIndex, cursorLocation.charIndex) * (1 - this._fontSizeFraction); + } + return { + top: topOffset, + left: leftOffset, + lineLeft: lineLeftOffset + }; + }, + getMinWidth: function() { + return Math.max(this.minWidth, this.dynamicMinWidth); + }, + toObject: function(propertiesToInclude) { + return fabric.util.object.extend(this.callSuper("toObject", propertiesToInclude), { + minWidth: this.minWidth + }); + } + }); + fabric.Textbox.fromObject = function(object) { + return new fabric.Textbox(object.text, clone(object)); + }; + fabric.Textbox.getTextboxControlVisibility = function() { + return { + tl: false, + tr: false, + br: false, + bl: false, + ml: true, + mt: false, + mr: true, + mb: false, + mtr: true + }; + }; + fabric.Textbox.instances = []; +})(typeof exports !== "undefined" ? exports : this); + +(function() { + var setObjectScaleOverridden = fabric.Canvas.prototype._setObjectScale; + fabric.Canvas.prototype._setObjectScale = function(localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip, _dim) { + var t = transform.target; + if (t instanceof fabric.Textbox) { + var w = t.width * (localMouse.x / transform.scaleX / (t.width + t.strokeWidth)); + if (w >= t.getMinWidth()) { + t.set("width", w); + return true; + } + } else { + return setObjectScaleOverridden.call(fabric.Canvas.prototype, localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip, _dim); + } + }; + fabric.Group.prototype._refreshControlsVisibility = function() { + if (typeof fabric.Textbox === "undefined") { + return; + } + for (var i = this._objects.length; i--; ) { + if (this._objects[i] instanceof fabric.Textbox) { + this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility()); + return; + } + } + }; + var clone = fabric.util.object.clone; + fabric.util.object.extend(fabric.Textbox.prototype, { + _removeExtraneousStyles: function() { + for (var prop in this._styleMap) { + if (!this._textLines[prop]) { + delete this.styles[this._styleMap[prop].line]; + } + } + }, + insertCharStyleObject: function(lineIndex, charIndex, style) { + var map = this._styleMap[lineIndex]; + lineIndex = map.line; + charIndex = map.offset + charIndex; + fabric.IText.prototype.insertCharStyleObject.apply(this, [ lineIndex, charIndex, style ]); + }, + insertNewlineStyleObject: function(lineIndex, charIndex, isEndOfLine) { + var map = this._styleMap[lineIndex]; + lineIndex = map.line; + charIndex = map.offset + charIndex; + fabric.IText.prototype.insertNewlineStyleObject.apply(this, [ lineIndex, charIndex, isEndOfLine ]); + }, + shiftLineStyles: function(lineIndex, offset) { + var clonedStyles = clone(this.styles), map = this._styleMap[lineIndex]; + lineIndex = map.line; + for (var line in this.styles) { + var numericLine = parseInt(line, 10); + if (numericLine > lineIndex) { + this.styles[numericLine + offset] = clonedStyles[numericLine]; + if (!clonedStyles[numericLine - offset]) { + delete this.styles[numericLine]; + } + } + } + }, + _getTextOnPreviousLine: function(lIndex) { + var textOnPreviousLine = this._textLines[lIndex - 1]; + while (this._styleMap[lIndex - 2] && this._styleMap[lIndex - 2].line === this._styleMap[lIndex - 1].line) { + textOnPreviousLine = this._textLines[lIndex - 2] + textOnPreviousLine; + lIndex--; + } + return textOnPreviousLine; + }, + removeStyleObject: function(isBeginningOfLine, index) { + var cursorLocation = this.get2DCursorLocation(index), map = this._styleMap[cursorLocation.lineIndex], lineIndex = map.line, charIndex = map.offset + cursorLocation.charIndex; + this._removeStyleObject(isBeginningOfLine, cursorLocation, lineIndex, charIndex); + } + }); +})(); + +(function() { + var override = fabric.IText.prototype._getNewSelectionStartFromOffset; + fabric.IText.prototype._getNewSelectionStartFromOffset = function(mouseOffset, prevWidth, width, index, jlen) { + index = override.call(this, mouseOffset, prevWidth, width, index, jlen); + var tmp = 0, removed = 0; + for (var i = 0; i < this._textLines.length; i++) { + tmp += this._textLines[i].length; + if (tmp + removed >= index) { + break; + } + if (this.text[tmp + removed] === "\n" || this.text[tmp + removed] === " ") { + removed++; + } + } + return index - i + removed; + }; +})(); + +(function() { + if (typeof document !== "undefined" && typeof window !== "undefined") { + return; + } + var DOMParser = require("xmldom").DOMParser, URL = require("url"), HTTP = require("http"), HTTPS = require("https"), Canvas = require("canvas"), Image = require("canvas").Image; + function request(url, encoding, callback) { + var oURL = URL.parse(url); + if (!oURL.port) { + oURL.port = oURL.protocol.indexOf("https:") === 0 ? 443 : 80; + } + var reqHandler = oURL.protocol.indexOf("https:") === 0 ? HTTPS : HTTP, req = reqHandler.request({ + hostname: oURL.hostname, + port: oURL.port, + path: oURL.path, + method: "GET" + }, function(response) { + var body = ""; + if (encoding) { + response.setEncoding(encoding); + } + response.on("end", function() { + callback(body); + }); + response.on("data", function(chunk) { + if (response.statusCode === 200) { + body += chunk; + } + }); + }); + req.on("error", function(err) { + if (err.errno === process.ECONNREFUSED) { + fabric.log("ECONNREFUSED: connection refused to " + oURL.hostname + ":" + oURL.port); + } else { + fabric.log(err.message); + } + callback(null); + }); + req.end(); + } + function requestFs(path, callback) { + var fs = require("fs"); + fs.readFile(path, function(err, data) { + if (err) { + fabric.log(err); + throw err; + } else { + callback(data); + } + }); + } + fabric.util.loadImage = function(url, callback, context) { + function createImageAndCallBack(data) { + if (data) { + img.src = new Buffer(data, "binary"); + img._src = url; + callback && callback.call(context, img); + } else { + img = null; + callback && callback.call(context, null, true); + } + } + var img = new Image(); + if (url && (url instanceof Buffer || url.indexOf("data") === 0)) { + img.src = img._src = url; + callback && callback.call(context, img); + } else if (url && url.indexOf("http") !== 0) { + requestFs(url, createImageAndCallBack); + } else if (url) { + request(url, "binary", createImageAndCallBack); + } else { + callback && callback.call(context, url); + } + }; + fabric.loadSVGFromURL = function(url, callback, reviver) { + url = url.replace(/^\n\s*/, "").replace(/\?.*$/, "").trim(); + if (url.indexOf("http") !== 0) { + requestFs(url, function(body) { + fabric.loadSVGFromString(body.toString(), callback, reviver); + }); + } else { + request(url, "", function(body) { + fabric.loadSVGFromString(body, callback, reviver); + }); + } + }; + fabric.loadSVGFromString = function(string, callback, reviver) { + var doc = new DOMParser().parseFromString(string); + fabric.parseSVGDocument(doc.documentElement, function(results, options) { + callback && callback(results, options); + }, reviver); + }; + fabric.util.getScript = function(url, callback) { + request(url, "", function(body) { + eval(body); + callback && callback(); + }); + }; + fabric.Image.fromObject = function(object, callback) { + fabric.util.loadImage(object.src, function(img) { + var oImg = new fabric.Image(img); + oImg._initConfig(object); + oImg._initFilters(object.filters, function(filters) { + oImg.filters = filters || []; + oImg._initFilters(object.resizeFilters, function(resizeFilters) { + oImg.resizeFilters = resizeFilters || []; + callback && callback(oImg); + }); + }); + }); + }; + fabric.createCanvasForNode = function(width, height, options, nodeCanvasOptions) { + nodeCanvasOptions = nodeCanvasOptions || options; + var canvasEl = fabric.document.createElement("canvas"), nodeCanvas = new Canvas(width || 600, height || 600, nodeCanvasOptions); + canvasEl.style = {}; + canvasEl.width = nodeCanvas.width; + canvasEl.height = nodeCanvas.height; + var FabricCanvas = fabric.Canvas || fabric.StaticCanvas, fabricCanvas = new FabricCanvas(canvasEl, options); + fabricCanvas.contextContainer = nodeCanvas.getContext("2d"); + fabricCanvas.nodeCanvas = nodeCanvas; + fabricCanvas.Font = Canvas.Font; + return fabricCanvas; + }; + fabric.StaticCanvas.prototype.createPNGStream = function() { + return this.nodeCanvas.createPNGStream(); + }; + fabric.StaticCanvas.prototype.createJPEGStream = function(opts) { + return this.nodeCanvas.createJPEGStream(opts); + }; + var origSetWidth = fabric.StaticCanvas.prototype.setWidth; + fabric.StaticCanvas.prototype.setWidth = function(width, options) { + origSetWidth.call(this, width, options); + this.nodeCanvas.width = width; + return this; + }; + if (fabric.Canvas) { + fabric.Canvas.prototype.setWidth = fabric.StaticCanvas.prototype.setWidth; + } + var origSetHeight = fabric.StaticCanvas.prototype.setHeight; + fabric.StaticCanvas.prototype.setHeight = function(height, options) { + origSetHeight.call(this, height, options); + this.nodeCanvas.height = height; + return this; + }; + if (fabric.Canvas) { + fabric.Canvas.prototype.setHeight = fabric.StaticCanvas.prototype.setHeight; + } +})(); + +window.fabric = fabric; + +if (typeof define === "function" && define.amd) { + define([], function() { + return fabric; + }); +} \ No newline at end of file