From bf4fa0091fe250e81fabeee195e02eb8ed9ad87e Mon Sep 17 00:00:00 2001 From: asturur Date: Wed, 16 Jul 2014 15:29:41 +0200 Subject: [PATCH 01/21] Update misc.js add parseUnit function to normalize mm,cm,in,pt,pc to pixels. res is setted to 96dpi is not real screen resolution dependant. --- src/util/misc.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/util/misc.js b/src/util/misc.js index b7c7365e8e6..ecf8be8e45c 100644 --- a/src/util/misc.js +++ b/src/util/misc.js @@ -132,6 +132,31 @@ return parseFloat(Number(number).toFixed(fractionDigits)); }, + parseUnit: function(value) { + var DPI = 96; + var unit = /\D{0,2}$/.exec(value); + var number = parseFloat(value.slice(0,-unit[0].length)); + switch(unit[0]){ + case 'mm': + return number * DPI / 25.4; + break; + case 'cm': + return number * DPI / 2.54; + break; + case 'in': + return number * DPI; + break; + case 'pt': + return number * DPI / 72; // or * 4 / 3 + break; + case 'pc': + return number * DPI / 72 * 12; // or * 16 + break; + default: + return number; + } + }, + /** * Function which always returns `false`. * @static From 0d4320c01847d18d2d3dc5c994ca630660a8cddf Mon Sep 17 00:00:00 2001 From: asturur Date: Wed, 16 Jul 2014 15:34:54 +0200 Subject: [PATCH 02/21] Update parser.js Use parseUnit to normalize pt,pc,mm,in,cm to px. --- src/parser.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/parser.js b/src/parser.js index 2f893185ab5..2bbc517c730 100644 --- a/src/parser.js +++ b/src/parser.js @@ -12,6 +12,7 @@ capitalize = fabric.util.string.capitalize, clone = fabric.util.object.clone, toFixed = fabric.util.toFixed, + parseUnit = fabric.util.parseUnit, multiplyTransformMatrices = fabric.util.multiplyTransformMatrices, attributesMap = { @@ -53,7 +54,7 @@ } function normalizeValue(attr, value, parentAttributes) { - var isArray; + var isArray = Object.prototype.toString.call(value) === '[object Array]'; if ((attr === 'fill' || attr === 'stroke') && value === 'none') { value = ''; @@ -82,10 +83,10 @@ } else if (attr === 'originX' /* text-anchor */) { value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center'; + } else { + var parsed = isArray ? value.map(parseUnit) : parseUnit(value); } - isArray = Object.prototype.toString.call(value) === '[object Array]'; - // TODO: need to normalize em, %, pt, etc. to px (!) var parsed = isArray ? value.map(parseFloat) : parseFloat(value); From bd4c7a0c4d85df9eb427d7a74bb073c2440dbabd Mon Sep 17 00:00:00 2001 From: asturur Date: Wed, 16 Jul 2014 18:56:10 +0200 Subject: [PATCH 03/21] Update parser.js --- src/parser.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/parser.js b/src/parser.js index 2bbc517c730..1db6ce25cfb 100644 --- a/src/parser.js +++ b/src/parser.js @@ -84,12 +84,10 @@ else if (attr === 'originX' /* text-anchor */) { value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center'; } else { + // TODO: need to normalize em, %, pt, etc. to px (!) var parsed = isArray ? value.map(parseUnit) : parseUnit(value); } - // TODO: need to normalize em, %, pt, etc. to px (!) - var parsed = isArray ? value.map(parseFloat) : parseFloat(value); - return (!isArray && isNaN(parsed) ? value : parsed); } From d78996194b5f5310888d470b905a5b310af8bd78 Mon Sep 17 00:00:00 2001 From: asturur Date: Thu, 17 Jul 2014 00:37:27 +0200 Subject: [PATCH 04/21] Update misc.js --- src/util/misc.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/util/misc.js b/src/util/misc.js index ecf8be8e45c..21384c455a4 100644 --- a/src/util/misc.js +++ b/src/util/misc.js @@ -133,24 +133,23 @@ }, parseUnit: function(value) { - var DPI = 96; - var unit = /\D{0,2}$/.exec(value); - var number = parseFloat(value.slice(0,-unit[0].length)); - switch(unit[0]){ + var unit = /\D{0,2}$/.exec(value), + number = parseFloat(value.slice(0,-unit[0].length)); + switch (unit[0]) { case 'mm': - return number * DPI / 25.4; + return number * fabric.DPI / 25.4; break; case 'cm': - return number * DPI / 2.54; + return number * fabric.DPI / 2.54; break; case 'in': - return number * DPI; + return number * fabric.DPI; break; case 'pt': - return number * DPI / 72; // or * 4 / 3 + return number * fabric.DPI / 72; // or * 4 / 3 break; case 'pc': - return number * DPI / 72 * 12; // or * 16 + return number * fabric.DPI / 72 * 12; // or * 16 break; default: return number; From 81092715c16b8dac8c9f973c84f1e18f0d7a6d72 Mon Sep 17 00:00:00 2001 From: asturur Date: Thu, 17 Jul 2014 00:38:55 +0200 Subject: [PATCH 05/21] Update misc.js added missing space. --- src/util/misc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/misc.js b/src/util/misc.js index 21384c455a4..654ef0de4c5 100644 --- a/src/util/misc.js +++ b/src/util/misc.js @@ -134,7 +134,7 @@ parseUnit: function(value) { var unit = /\D{0,2}$/.exec(value), - number = parseFloat(value.slice(0,-unit[0].length)); + number = parseFloat(value.slice(0, -unit[0].length)); switch (unit[0]) { case 'mm': return number * fabric.DPI / 25.4; From d34f970ffba4b702fe851af2b91d7e1911a38b1d Mon Sep 17 00:00:00 2001 From: asturur Date: Thu, 17 Jul 2014 00:42:31 +0200 Subject: [PATCH 06/21] Update misc.js --- src/util/misc.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/misc.js b/src/util/misc.js index 654ef0de4c5..31b9cf322c8 100644 --- a/src/util/misc.js +++ b/src/util/misc.js @@ -4,6 +4,7 @@ atan2 = Math.atan2, PiBy180 = Math.PI / 180; + fabric.DPI = 96; /** * @namespace fabric.util */ From 0bb156f30889e2947c25af5a44558188f18154a5 Mon Sep 17 00:00:00 2001 From: asturur Date: Thu, 17 Jul 2014 07:44:03 +0200 Subject: [PATCH 07/21] Update misc.js it had some problem with len of string 0 and slicing from 0 to -0 , or calculating len of ''. now is ok, rects went crazy and i didn't notice. --- src/util/misc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/misc.js b/src/util/misc.js index 31b9cf322c8..0a01d60c833 100644 --- a/src/util/misc.js +++ b/src/util/misc.js @@ -135,7 +135,7 @@ parseUnit: function(value) { var unit = /\D{0,2}$/.exec(value), - number = parseFloat(value.slice(0, -unit[0].length)); + number = parseFloat(value.slice(0, unit.index)); switch (unit[0]) { case 'mm': return number * fabric.DPI / 25.4; From 306a040fef4114478e96f1480bcb8c0f5ce0d2fb Mon Sep 17 00:00:00 2001 From: Stefan Kienzle Date: Thu, 17 Jul 2014 13:28:55 +0200 Subject: [PATCH 08/21] Fix initialization of viewportTransform array Add unit tests JSDoc tweaks --- src/static_canvas.class.js | 15 ++++++++------- test/unit/canvas_static.js | 14 +++++++++++++- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/static_canvas.class.js b/src/static_canvas.class.js index f6ab0fcf41d..841fb68c0ab 100644 --- a/src/static_canvas.class.js +++ b/src/static_canvas.class.js @@ -138,11 +138,10 @@ * @type Array * @default */ - viewportTransform: [1, 0, 0, 1, 0, 0], + viewportTransform: [1, 0, 0, 1, 0, 0], /** * Callback; invoked right before object is about to be scaled/rotated - * @param {fabric.Object} target Object that's about to be scaled/rotated */ onBeforeScaleRotate: function () { /* NOOP */ @@ -429,6 +428,8 @@ this.lowerCanvasEl.style.width = this.width + 'px'; this.lowerCanvasEl.style.height = this.height + 'px'; + + this.viewportTransform = this.viewportTransform.map(function(item) { return item; }); }, /** @@ -471,8 +472,8 @@ * @return {fabric.Canvas} instance * @chainable true */ - setWidth: function (value) { - return this._setDimension('width', value); + setWidth: function (width) { + return this._setDimension('width', width); }, /** @@ -481,8 +482,8 @@ * @return {fabric.Canvas} instance * @chainable true */ - setHeight: function (value) { - return this._setDimension('height', value); + setHeight: function (height) { + return this._setDimension('height', height); }, /** @@ -1399,7 +1400,7 @@ * Provides a way to check support of some of the canvas methods * (either those of HTMLCanvasElement itself, or rendering context) * - * @param methodName {String} Method to check support for; + * @param {String} methodName Method to check support for; * Could be one of "getImageData", "toDataURL", "toDataURLWithQuality" or "setLineDash" * @return {Boolean | null} `true` if method is supported (or at least exists), * `null` if canvas element or context can not be initialized diff --git a/test/unit/canvas_static.js b/test/unit/canvas_static.js index e8aa7aaeb7c..24bf80e98fb 100644 --- a/test/unit/canvas_static.js +++ b/test/unit/canvas_static.js @@ -132,7 +132,8 @@ var el = fabric.document.createElement('canvas'); el.width = 600; el.height = 600; - var canvas = this.canvas = fabric.isLikelyNode ? fabric.createCanvasForNode() : new fabric.StaticCanvas(el); + var canvas = this.canvas = fabric.isLikelyNode ? fabric.createCanvasForNode() : new fabric.StaticCanvas(el), + canvas2 = this.canvas2 = fabric.isLikelyNode ? fabric.createCanvasForNode() : new fabric.StaticCanvas(el); fabric.Canvas = Canvas; var lowerCanvasEl = canvas.lowerCanvasEl; @@ -153,7 +154,18 @@ test('initialProperties', function() { ok('backgroundColor' in canvas); + ok('overlayColor' in canvas); + ok('backgroundImage' in canvas); + ok('overlayImage' in canvas); + ok('clipTo' in canvas); + equal(canvas.includeDefaultValues, true); + equal(canvas.stateful, true); + equal(canvas.renderOnAddRemove, true); + equal(canvas.controlsAboveOverlay, false); + equal(canvas.imageSmoothingEnabled, true); + + notStrictEqual(canvas.viewportTransform, canvas2.viewportTransform); }); test('getObjects', function() { From 43b029e8a496aef7f190e57af92cf8012b65bf6c Mon Sep 17 00:00:00 2001 From: Stefan Kienzle Date: Thu, 17 Jul 2014 14:35:28 +0200 Subject: [PATCH 09/21] Just do `slice()` for cloning --- src/static_canvas.class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/static_canvas.class.js b/src/static_canvas.class.js index 841fb68c0ab..2a554ae8d80 100644 --- a/src/static_canvas.class.js +++ b/src/static_canvas.class.js @@ -429,7 +429,7 @@ this.lowerCanvasEl.style.width = this.width + 'px'; this.lowerCanvasEl.style.height = this.height + 'px'; - this.viewportTransform = this.viewportTransform.map(function(item) { return item; }); + this.viewportTransform = this.viewportTransform.slice(); }, /** From b34387d10e6d267059805ac0f6ee895a091f3903 Mon Sep 17 00:00:00 2001 From: Stefan Kienzle Date: Thu, 17 Jul 2014 16:18:57 +0200 Subject: [PATCH 10/21] JSDoc + JSCS tweaks - Part 1 --- src/canvas.class.js | 15 +++++------ src/parser.js | 46 ++++++++++++++++------------------ src/point.class.js | 2 +- src/shapes/circle.class.js | 3 ++- src/shapes/ellipse.class.js | 7 +++--- src/shapes/group.class.js | 2 +- src/shapes/itext.class.js | 13 ++++++++-- src/shapes/object.class.js | 4 +-- src/shapes/path.class.js | 3 ++- src/shapes/path_group.class.js | 2 +- src/shapes/polygon.class.js | 2 +- src/shapes/polyline.class.js | 2 +- src/shapes/rect.class.js | 6 ++--- src/shapes/text.class.js | 4 +-- src/shapes/triangle.class.js | 6 ++--- 15 files changed, 61 insertions(+), 56 deletions(-) diff --git a/src/canvas.class.js b/src/canvas.class.js index 359658476ee..9a83c2fa261 100644 --- a/src/canvas.class.js +++ b/src/canvas.class.js @@ -444,8 +444,8 @@ /** * Translates object by "setting" its left/top * @private - * @param x {Number} pointer's x coordinate - * @param y {Number} pointer's y coordinate + * @param {Number} x pointer's x coordinate + * @param {Number} y pointer's y coordinate */ _translateObject: function (x, y) { var target = this._currentTransform.target; @@ -461,9 +461,9 @@ /** * Scales object by invoking its scaleX/scaleY methods * @private - * @param x {Number} pointer's x coordinate - * @param y {Number} pointer's y coordinate - * @param by {String} Either 'x' or 'y' - specifies dimension constraint by which to scale an object. + * @param {Number} x pointer's x coordinate + * @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 */ _scaleObject: function (x, y, by) { @@ -843,7 +843,6 @@ /** * @private - * @param {HTMLElement|String} canvasEl Canvas element * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized */ _createUpperCanvas: function () { @@ -871,8 +870,6 @@ /** * @private - * @param {Number} width - * @param {Number} height */ _initWrapperElement: function () { this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', { @@ -888,7 +885,7 @@ /** * @private - * @param {Element} element + * @param {HTMLElement} element canvas element to apply styles on */ _applyCanvasStyle: function (element) { var width = this.getWidth() || element.width, diff --git a/src/parser.js b/src/parser.js index 2f893185ab5..3c51a778308 100644 --- a/src/parser.js +++ b/src/parser.js @@ -368,28 +368,32 @@ * @private */ function parseUseDirectives(doc) { - var nodelist = doc.querySelectorAll("use"); - for (var i = 0; i < nodelist.length; i++) { - var el = nodelist[i]; - var xlink = el.getAttribute('xlink:href').substr(1); - var x = el.getAttribute('x') || 0; - var y = el.getAttribute('y') || 0; - var el2 = doc.getElementById(xlink).cloneNode(true); - var currentTrans = (el.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')'; + var nodelist = doc.querySelectorAll('use'); + for (var i = 0, len = nodelist.length; i < len; i++) { + var el = nodelist[i], + xlink = el.getAttribute('xlink:href').substr(1), + x = el.getAttribute('x') || 0, + y = el.getAttribute('y') || 0, + el2 = doc.getElementById(xlink).cloneNode(true), + currentTrans = (el.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')', + parentNode; + for (var j = 0, attrs = el.attributes, l = attrs.length; j < l; j++) { var attr = attrs.item(j); - if (attr.nodeName !== 'x' && attr.nodeName !== 'y' && attr.nodeName !== 'xlink:href') { - if (attr.nodeName === 'transform') { - currentTrans = currentTrans + ' ' + attr.nodeValue; - } else { - el2.setAttribute(attr.nodeName, attr.nodeValue); - } + if (attr.nodeName === 'x' || attr.nodeName === 'y' || attr.nodeName === 'xlink:href') continue; + + if (attr.nodeName === 'transform') { + currentTrans = currentTrans + ' ' + attr.nodeValue; + } + else { + el2.setAttribute(attr.nodeName, attr.nodeValue); } } + el2.setAttribute('transform', currentTrans); el2.removeAttribute('id'); - var pNode=el.parentNode; - pNode.replaceChild(el2, el); + parentNode = el.parentNode; + parentNode.replaceChild(el2, el); } } @@ -520,18 +524,10 @@ callback(false); }, - /** - * @param {String} url - * @param {Function} callback - */ get: function () { /* NOOP */ }, - /** - * @param {String} url - * @param {Object} object - */ set: function () { /* NOOP */ } @@ -705,7 +701,7 @@ * Parses "points" attribute, returning an array of values * @static * @memberOf fabric - * @param points {String} points attribute string + * @param {String} points points attribute string * @return {Array} array of points */ parsePointsAttribute: function(points) { diff --git a/src/point.class.js b/src/point.class.js index 727be608971..149709152c5 100644 --- a/src/point.class.js +++ b/src/point.class.js @@ -63,7 +63,7 @@ /** * Adds value to this point * @param {Number} scalar - * @param {fabric.Point} thisArg + * @return {fabric.Point} thisArg */ scalarAddEquals: function (scalar) { this.x += scalar; diff --git a/src/shapes/circle.class.js b/src/shapes/circle.class.js index fccffd5882c..36ca968032b 100644 --- a/src/shapes/circle.class.js +++ b/src/shapes/circle.class.js @@ -96,7 +96,8 @@ /** * @private - * @param ctx {CanvasRenderingContext2D} context to render on + * @param {CanvasRenderingContext2D} ctx context to render on + * @param {Boolean} [noTransform] When true, context is not transformed */ _render: function(ctx, noTransform) { ctx.beginPath(); diff --git a/src/shapes/ellipse.class.js b/src/shapes/ellipse.class.js index a1539ca0cf2..b556d97329a 100644 --- a/src/shapes/ellipse.class.js +++ b/src/shapes/ellipse.class.js @@ -94,8 +94,8 @@ /** * Renders this instance on a given context - * @param ctx {CanvasRenderingContext2D} context to render on - * @param noTransform {Boolean} context is not transformed when set to true + * @param {CanvasRenderingContext2D} ctx context to render on + * @param {Boolean} [noTransform] When true, context is not transformed */ render: function(ctx, noTransform) { // do not use `get` for perf. reasons @@ -105,7 +105,8 @@ /** * @private - * @param ctx {CanvasRenderingContext2D} context to render on + * @param {CanvasRenderingContext2D} ctx context to render on + * @param {Boolean} [noTransform] When true, context is not transformed */ _render: function(ctx, noTransform) { ctx.beginPath(); diff --git a/src/shapes/group.class.js b/src/shapes/group.class.js index 04b7c299baa..756af1d889d 100644 --- a/src/shapes/group.class.js +++ b/src/shapes/group.class.js @@ -523,7 +523,7 @@ * @static * @memberOf fabric.Group * @param {Object} object Object to create a group from - * @param {Object} [options] Options object + * @param {Function} [callback] Callback to invoke when an group instance is created * @return {fabric.Group} An instance of fabric.Group */ fabric.Group.fromObject = function(object, callback) { diff --git a/src/shapes/itext.class.js b/src/shapes/itext.class.js index 83713969e16..87af2adc1e0 100644 --- a/src/shapes/itext.class.js +++ b/src/shapes/itext.class.js @@ -635,7 +635,9 @@ * @private * @param {String} method * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {String} line + * @param {String} line Content of the line + * @param {Number} left Left coordinate + * @param {Number} top Top coordinate */ _renderCharsFast: function(method, ctx, line, left, top) { this.skipTextAlign = false; @@ -650,7 +652,14 @@ /** * @private + * @param {String} method * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Number} lineIndex + * @param {Number} i + * @param {String} _char + * @param {Number} left Left coordinate + * @param {Number} top Top coordinate + * @param {Number} lineHeight Height of the line */ _renderChar: function(method, ctx, lineIndex, i, _char, left, top, lineHeight) { var decl, charWidth, charHeight; @@ -1069,6 +1078,7 @@ /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines */ _getTextHeight: function(ctx, textLines) { var height = 0; @@ -1080,7 +1090,6 @@ /** * @private - * @param {CanvasRenderingContext2D} ctx Context to render on */ _getTopOffset: function() { var topOffset = fabric.Text.prototype._getTopOffset.call(this); diff --git a/src/shapes/object.class.js b/src/shapes/object.class.js index 5c839cc2d9b..dee5a77e8c9 100644 --- a/src/shapes/object.class.js +++ b/src/shapes/object.class.js @@ -1125,7 +1125,7 @@ /** * Creates an instance of fabric.Image out of an object - * @param callback {Function} callback, invoked with an instance as a first argument + * @param {Function} callback callback, invoked with an instance as a first argument * @return {fabric.Object} thisArg */ cloneAsImage: function(callback) { @@ -1195,7 +1195,7 @@ /** * Returns true if specified type is identical to the type of an instance - * @param type {String} type Type to check against + * @param {String} type Type to check against * @return {Boolean} */ isType: function(type) { diff --git a/src/shapes/path.class.js b/src/shapes/path.class.js index 47895ce0a8f..abbe42f341c 100644 --- a/src/shapes/path.class.js +++ b/src/shapes/path.class.js @@ -142,7 +142,8 @@ /** * @private - * @param {Boolean} positionSet When false, path offset is returned otherwise 0 + * @param {Number} origLeft Original left position + * @param {Number} origTop Original top position */ _calculatePathOffset: function (origLeft, origTop) { return { diff --git a/src/shapes/path_group.class.js b/src/shapes/path_group.class.js index da89a2c4e78..e81c51a7901 100644 --- a/src/shapes/path_group.class.js +++ b/src/shapes/path_group.class.js @@ -77,7 +77,7 @@ ctx.save(); var m = this.transformMatrix; - + if (m) { ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); } diff --git a/src/shapes/polygon.class.js b/src/shapes/polygon.class.js index 16283dc4fcb..c63c4fd89b5 100644 --- a/src/shapes/polygon.class.js +++ b/src/shapes/polygon.class.js @@ -197,7 +197,7 @@ * Returns fabric.Polygon instance from an object representation * @static * @memberOf fabric.Polygon - * @param object {Object} object Object to create an instance from + * @param {Object} object Object to create an instance from * @return {fabric.Polygon} Instance of fabric.Polygon */ fabric.Polygon.fromObject = function(object) { diff --git a/src/shapes/polyline.class.js b/src/shapes/polyline.class.js index c5a750d04f6..27ac3dd0fd3 100644 --- a/src/shapes/polyline.class.js +++ b/src/shapes/polyline.class.js @@ -179,7 +179,7 @@ * Returns fabric.Polyline instance from an object representation * @static * @memberOf fabric.Polyline - * @param object {Object} object Object to create an instance from + * @param {Object} object Object to create an instance from * @return {fabric.Polyline} Instance of fabric.Polyline */ fabric.Polyline.fromObject = function(object) { diff --git a/src/shapes/rect.class.js b/src/shapes/rect.class.js index 184b90e0b9d..565a7a5134b 100644 --- a/src/shapes/rect.class.js +++ b/src/shapes/rect.class.js @@ -98,7 +98,7 @@ /** * @private - * @param ctx {CanvasRenderingContext2D} context to render on + * @param {CanvasRenderingContext2D} ctx Context to render on */ _render: function(ctx) { @@ -154,7 +154,7 @@ /** * @private - * @param ctx {CanvasRenderingContext2D} context to render on + * @param {CanvasRenderingContext2D} ctx Context to render on */ _renderDashedStroke: function(ctx) { var x = -this.width / 2, @@ -280,7 +280,7 @@ * Returns {@link fabric.Rect} instance from an object representation * @static * @memberOf fabric.Rect - * @param object {Object} object to create an instance from + * @param {Object} object Object to create an instance from * @return {Object} instance of fabric.Rect */ fabric.Rect.fromObject = function(object) { diff --git a/src/shapes/text.class.js b/src/shapes/text.class.js index e164b1a74e3..1a4726e502f 100644 --- a/src/shapes/text.class.js +++ b/src/shapes/text.class.js @@ -484,7 +484,7 @@ * @private * @param {String} method Method name ("fillText" or "strokeText") * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {String} line Chars to render + * @param {String} chars Chars to render * @param {Number} left Left position of text * @param {Number} top Top position of text */ @@ -1107,7 +1107,7 @@ * Returns fabric.Text instance from an object representation * @static * @memberOf fabric.Text - * @param object {Object} object Object to create an instance from + * @param {Object} object Object to create an instance from * @return {fabric.Text} Instance of fabric.Text */ fabric.Text.fromObject = function(object) { diff --git a/src/shapes/triangle.class.js b/src/shapes/triangle.class.js index 12eaebb86ab..fcced7a46b4 100644 --- a/src/shapes/triangle.class.js +++ b/src/shapes/triangle.class.js @@ -41,7 +41,7 @@ /** * @private - * @param ctx {CanvasRenderingContext2D} Context to render on + * @param {CanvasRenderingContext2D} ctx Context to render on */ _render: function(ctx) { var widthBy2 = this.width / 2, @@ -59,7 +59,7 @@ /** * @private - * @param ctx {CanvasRenderingContext2D} Context to render on + * @param {CanvasRenderingContext2D} ctx Context to render on */ _renderDashedStroke: function(ctx) { var widthBy2 = this.width / 2, @@ -114,7 +114,7 @@ * Returns fabric.Triangle instance from an object representation * @static * @memberOf fabric.Triangle - * @param object {Object} object to create an instance from + * @param {Object} object Object to create an instance from * @return {Object} instance of Canvas.Triangle */ fabric.Triangle.fromObject = function(object) { From dfbd1887bf5e380265a27c4be4ada8b2cb33d8f7 Mon Sep 17 00:00:00 2001 From: asturur Date: Thu, 17 Jul 2014 16:24:46 +0200 Subject: [PATCH 11/21] Update misc.js some more polishing --- src/util/misc.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/util/misc.js b/src/util/misc.js index 0a01d60c833..ec46d5d2e4d 100644 --- a/src/util/misc.js +++ b/src/util/misc.js @@ -4,7 +4,6 @@ atan2 = Math.atan2, PiBy180 = Math.PI / 180; - fabric.DPI = 96; /** * @namespace fabric.util */ @@ -133,9 +132,15 @@ return parseFloat(Number(number).toFixed(fractionDigits)); }, + /** + * Converts from attribute value to pixel value if applicable. + * Returns converted pixels or original value not converted. + * @param {Number | String} number to operate on + * @return {Number | String} + */ parseUnit: function(value) { var unit = /\D{0,2}$/.exec(value), - number = parseFloat(value.slice(0, unit.index)); + number = parseFloat(value); switch (unit[0]) { case 'mm': return number * fabric.DPI / 25.4; From 5ca64ad636aff2d3fcd2894cf8a689c7b95c840a Mon Sep 17 00:00:00 2001 From: asturur Date: Thu, 17 Jul 2014 16:25:59 +0200 Subject: [PATCH 12/21] Update parser.js --- src/parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser.js b/src/parser.js index 1db6ce25cfb..c93c93f661b 100644 --- a/src/parser.js +++ b/src/parser.js @@ -84,7 +84,7 @@ else if (attr === 'originX' /* text-anchor */) { value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center'; } else { - // TODO: need to normalize em, %, pt, etc. to px (!) + // TODO: need to normalize em, %, etc. to px (!) var parsed = isArray ? value.map(parseUnit) : parseUnit(value); } From df7671daa331d0f9b0ec8098a7b1a6414894e43d Mon Sep 17 00:00:00 2001 From: asturur Date: Thu, 17 Jul 2014 16:28:42 +0200 Subject: [PATCH 13/21] Update HEADER.js Moved fabric.DPI to proper file. --- HEADER.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/HEADER.js b/HEADER.js index cc4dc696df7..e92cc0243f7 100644 --- a/HEADER.js +++ b/HEADER.js @@ -44,3 +44,8 @@ fabric.SHARED_ATTRIBUTES = [ "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width" ]; + +/** + * Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion. + */ +fabric.DPI = 96; From 795d8a7aa540389325908f414ccc5d1f90230a46 Mon Sep 17 00:00:00 2001 From: asturur Date: Thu, 17 Jul 2014 16:38:09 +0200 Subject: [PATCH 14/21] Update misc.js some more polishing, for me and for toFixed. --- src/util/misc.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util/misc.js b/src/util/misc.js index ec46d5d2e4d..5c25d5385cb 100644 --- a/src/util/misc.js +++ b/src/util/misc.js @@ -124,7 +124,7 @@ * A wrapper around Number#toFixed, which contrary to native method returns number, not string. * @static * @memberOf fabric.util - * @param {Number | String} number number to operate on + * @param {Number|String} number number to operate on * @param {Number} fractionDigits number of fraction digits to "leave" * @return {Number} */ @@ -135,8 +135,8 @@ /** * Converts from attribute value to pixel value if applicable. * Returns converted pixels or original value not converted. - * @param {Number | String} number to operate on - * @return {Number | String} + * @param {Number|String} value number to operate on + * @return {Number|String} */ parseUnit: function(value) { var unit = /\D{0,2}$/.exec(value), From 6b5f049bb0a459dd29e2927ed99094b3e7baec66 Mon Sep 17 00:00:00 2001 From: Stefan Kienzle Date: Fri, 18 Jul 2014 11:16:23 +0200 Subject: [PATCH 15/21] JSDoc + JSCS tweaks - Part 2 --- src/brushes/pencil_brush.class.js | 47 +++++++++++------------- src/brushes/spray_brush.class.js | 6 ++- src/mixins/canvas_events.mixin.js | 20 +++++----- src/mixins/canvas_gestures.mixin.js | 22 +++++------ src/mixins/itext_behavior.mixin.js | 7 +++- src/mixins/itext_click_behavior.mixin.js | 5 +-- src/mixins/itext_key_behavior.mixin.js | 21 +++++++---- src/mixins/object_geometry.mixin.js | 39 ++++++++++---------- src/mixins/object_interactivity.mixin.js | 27 ++++++++------ src/mixins/object_origin.mixin.js | 4 +- src/shapes/object.class.js | 10 +++-- src/util/lang_array.js | 2 +- src/util/misc.js | 15 ++++---- 13 files changed, 119 insertions(+), 106 deletions(-) diff --git a/src/brushes/pencil_brush.class.js b/src/brushes/pencil_brush.class.js index 09fc93f3b6f..bf0cf9e4e5e 100644 --- a/src/brushes/pencil_brush.class.js +++ b/src/brushes/pencil_brush.class.js @@ -52,7 +52,8 @@ }, /** - * @param {Object} pointer + * @private + * @param {Object} pointer Actual mouse position related to the canvas. */ _prepareForDrawing: function(pointer) { @@ -66,18 +67,15 @@ /** * @private - * @param {fabric.Point} point + * @param {fabric.Point} point Point to be added to points array */ _addPoint: function(point) { this._points.push(point); }, /** - * Clear points array and set contextTop canvas - * style. - * + * Clear points array and set contextTop canvas style. * @private - * */ _reset: function() { this._points.length = 0; @@ -88,9 +86,7 @@ /** * @private - * - * @param point {pointer} (fabric.util.pointer) actual mouse position - * related to the canvas. + * @param {Object} pointer Actual mouse position related to the canvas. */ _captureDrawingPath: function(pointer) { var pointerPoint = new fabric.Point(pointer.x, pointer.y); @@ -99,19 +95,18 @@ /** * Draw a smooth path on the topCanvas using quadraticCurveTo - * * @private */ _render: function() { - var ctx = this.canvas.contextTop; - var v = this.canvas.viewportTransform; + 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(); - var p1 = this._points[0], - p2 = this._points[1]; - //if we only have 2 points in the path and they are the same //it means that the user only clicked the canvas without moving the mouse //then we should be drawing a dot. A path isn't drawn between two identical dots @@ -141,19 +136,18 @@ /** * Return an SVG path based on our captured points and their bounding box - * * @private */ _getSVGPathData: function() { this.box = this.getPathBoundingBox(this._points); return this.convertPointsToSVGPath( - this._points, this.box.minx, this.box.maxx, this.box.miny, this.box.maxy); + this._points, this.box.minX, this.box.minY); }, /** * Returns bounding box of a path based on given points - * @param {Array} points - * @return {Object} object with minx, miny, maxx, maxy + * @param {Array} points Array of points + * @return {Object} Object with minX, minY, maxX, maxY */ getPathBoundingBox: function(points) { var xBounds = [], @@ -179,19 +173,21 @@ yBounds.push(p1.y); return { - minx: utilMin(xBounds), - miny: utilMin(yBounds), - maxx: utilMax(xBounds), - maxy: utilMax(yBounds) + minX: utilMin(xBounds), + minY: utilMin(yBounds), + maxX: utilMax(xBounds), + maxY: utilMax(yBounds) }; }, /** * Converts points to SVG path * @param {Array} points Array of points + * @param {Number} minX + * @param {Number} minY * @return {String} SVG path */ - convertPointsToSVGPath: function(points, minX, maxX, minY) { + convertPointsToSVGPath: function(points, minX, minY) { var path = [], p1 = new fabric.Point(points[0].x - minX, points[0].y - minY), p2 = new fabric.Point(points[1].x - minX, points[1].y - minY); @@ -215,7 +211,7 @@ /** * Creates fabric.Path object to add on canvas * @param {String} pathData Path data - * @return {fabric.Path} path to add on canvas + * @return {fabric.Path} Path to add on canvas */ createPath: function(pathData) { var path = new fabric.Path(pathData); @@ -237,7 +233,6 @@ * On mouseup after drawing the path on contextTop canvas * we use the points captured to create an new fabric path object * and add it to the fabric canvas. - * */ _finalizeAndAddPath: function() { var ctx = this.canvas.contextTop; diff --git a/src/brushes/spray_brush.class.js b/src/brushes/spray_brush.class.js index afd9ce26cf1..fd6929f5884 100644 --- a/src/brushes/spray_brush.class.js +++ b/src/brushes/spray_brush.class.js @@ -123,6 +123,10 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric this.canvas.renderAll(); }, + /** + * @private + * @param {Array} rects + */ _getOptimizedRects: function(rects) { // avoid creating duplicate rects at the same coordinates @@ -185,7 +189,7 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric else { width = this.dotWidth; } - + var point = new fabric.Point(x, y); point.width = width; diff --git a/src/mixins/canvas_events.mixin.js b/src/mixins/canvas_events.mixin.js index d2a80719143..09f26a2438e 100644 --- a/src/mixins/canvas_events.mixin.js +++ b/src/mixins/canvas_events.mixin.js @@ -98,8 +98,8 @@ * @param {Event} [e] Event object fired on Event.js gesture * @param {Event} [self] Inner Event object */ - _onGesture: function(e, s) { - this.__onTransformGesture && this.__onTransformGesture(e, s); + _onGesture: function(e, self) { + this.__onTransformGesture && this.__onTransformGesture(e, self); }, /** @@ -107,8 +107,8 @@ * @param {Event} [e] Event object fired on Event.js drag * @param {Event} [self] Inner Event object */ - _onDrag: function(e, s) { - this.__onDrag && this.__onDrag(e, s); + _onDrag: function(e, self) { + this.__onDrag && this.__onDrag(e, self); }, /** @@ -116,8 +116,8 @@ * @param {Event} [e] Event object fired on Event.js wheel event * @param {Event} [self] Inner Event object */ - _onMouseWheel: function(e, s) { - this.__onMouseWheel && this.__onMouseWheel(e, s); + _onMouseWheel: function(e, self) { + this.__onMouseWheel && this.__onMouseWheel(e, self); }, /** @@ -125,8 +125,8 @@ * @param {Event} [e] Event object fired on Event.js orientation change * @param {Event} [self] Inner Event object */ - _onOrientationChange: function(e,s) { - this.__onOrientationChange && this.__onOrientationChange(e,s); + _onOrientationChange: function(e,self) { + this.__onOrientationChange && this.__onOrientationChange(e,self); }, /** @@ -134,8 +134,8 @@ * @param {Event} [e] Event object fired on Event.js shake * @param {Event} [self] Inner Event object */ - _onShake: function(e,s) { - this.__onShake && this.__onShake(e,s); + _onShake: function(e, self) { + this.__onShake && this.__onShake(e,self); }, /** diff --git a/src/mixins/canvas_gestures.mixin.js b/src/mixins/canvas_gestures.mixin.js index fdb18853197..b8dcfcf362c 100644 --- a/src/mixins/canvas_gestures.mixin.js +++ b/src/mixins/canvas_gestures.mixin.js @@ -9,8 +9,8 @@ * Method that defines actions when an Event.js gesture is detected on an object. Currently only supports * 2 finger gestures. * - * @param e Event object by Event.js - * @param self Event proxy object by Event.js + * @param {Event} e Event object by Event.js + * @param {Event} self Event proxy object by Event.js */ __onTransformGesture: function(e, self) { @@ -31,8 +31,8 @@ /** * Method that defines actions when an Event.js drag is detected. * - * @param e Event object by Event.js - * @param self Event proxy object by Event.js + * @param {Event} e Event object by Event.js + * @param {Event} self Event proxy object by Event.js */ __onDrag: function(e, self) { this.fire('touch:drag', { e: e, self: self }); @@ -41,8 +41,8 @@ /** * Method that defines actions when an Event.js orientation event is detected. * - * @param e Event object by Event.js - * @param self Event proxy object by Event.js + * @param {Event} e Event object by Event.js + * @param {Event} self Event proxy object by Event.js */ __onOrientationChange: function(e, self) { this.fire('touch:orientation', { e: e, self: self }); @@ -51,8 +51,8 @@ /** * Method that defines actions when an Event.js shake event is detected. * - * @param e Event object by Event.js - * @param self Event proxy object by Event.js + * @param {Event} e Event object by Event.js + * @param {Event} self Event proxy object by Event.js */ __onShake: function(e, self) { this.fire('touch:shake', { e: e, self: self }); @@ -60,8 +60,8 @@ /** * Scales an object by a factor - * @param s {Number} The scale factor to apply to the current scale level - * @param by {String} Either 'x' or 'y' - specifies dimension constraint by which to scale an object. + * @param {Number} s The scale factor to apply to the current scale level + * @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 */ _scaleObjectBy: function(s, by) { @@ -92,7 +92,7 @@ /** * Rotates object by an angle - * @param curAngle {Number} the angle of rotation in degrees + * @param {Number} curAngle The angle of rotation in degrees */ _rotateObjectByAngle: function(curAngle) { var t = this._currentTransform; diff --git a/src/mixins/itext_behavior.mixin.js b/src/mixins/itext_behavior.mixin.js index d82e029a9ae..044473db515 100644 --- a/src/mixins/itext_behavior.mixin.js +++ b/src/mixins/itext_behavior.mixin.js @@ -216,7 +216,8 @@ /** * Find new selection index representing start of current line according to current selection index - * @param {Number} current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index */ findLineBoundaryLeft: function(startFrom) { var offset = 0, index = startFrom - 1; @@ -231,7 +232,8 @@ /** * Find new selection index representing end of current line according to current selection index - * @param {Number} current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index */ findLineBoundaryRight: function(startFrom) { var offset = 0, index = startFrom; @@ -264,6 +266,7 @@ * Finds index corresponding to beginning or end of a word * @param {Number} selectionStart Index of a character * @param {Number} direction: 1 or -1 + * @return {Number} Index of the beginning or end of a word */ searchWordBoundary: function(selectionStart, direction) { var index = this._reSpace.test(this.text.charAt(selectionStart)) ? selectionStart - 1 : selectionStart, diff --git a/src/mixins/itext_click_behavior.mixin.js b/src/mixins/itext_click_behavior.mixin.js index 9c2c6c248b9..3449b847415 100644 --- a/src/mixins/itext_click_behavior.mixin.js +++ b/src/mixins/itext_click_behavior.mixin.js @@ -155,7 +155,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * Changes cursor location in a text depending on passed pointer (x/y) object - * @param {Object} pointer Pointer object with x and y numeric properties + * @param {Event} e Event object */ setCursorByClick: function(e) { var newSelectionStart = this.getSelectionStartFromPointer(e); @@ -178,7 +178,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private * @param {Event} e Event object - * @param {Object} Object with x/y corresponding to local offset (according to object rotation) + * @return {Object} Coordinates of a pointer (x, y) */ _getLocalRotatedPointer: function(e) { var pointer = this.canvas.getPointer(e), @@ -198,7 +198,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @return {Number} Index of a character */ getSelectionStartFromPointer: function(e) { - var mouseOffset = this._getLocalRotatedPointer(e), textLines = this.text.split(this._reNewline), prevWidth = 0, diff --git a/src/mixins/itext_key_behavior.mixin.js b/src/mixins/itext_key_behavior.mixin.js index 72bbaa7ef0a..45d2dff5d36 100644 --- a/src/mixins/itext_key_behavior.mixin.js +++ b/src/mixins/itext_key_behavior.mixin.js @@ -110,7 +110,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot // Check for backward compatibility with old browsers if (clipboardData) { copiedText = clipboardData.getData('text'); - } else { + } + else { copiedText = this.copiedText; } @@ -135,6 +136,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private * @param {Event} e Event object + * @return {Object} Clipboard data object */ _getClipboardData: function(e) { return e && (e.clipboardData || fabric.window.clipboardData); @@ -156,10 +158,11 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * Gets start offset of a selection + * @param {Event} e Event object + * @param {Boolean} isRight * @return {Number} */ getDownCursorOffset: function(e, isRight) { - var selectionProp = isRight ? this.selectionEnd : this.selectionStart, textLines = this.text.split(this._reNewline), _char, @@ -202,7 +205,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @private */ _getIndexOnNextLine: function(cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor, textLines) { - var lineIndex = cursorLocation.lineIndex + 1, widthOfNextLine = this._getWidthOfLine(this.ctx, lineIndex, textLines), lineLeftOffset = this._getLineLeftOffset(widthOfNextLine), @@ -245,7 +247,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @param {Event} e Event object */ moveCursorDown: function(e) { - this.abortCursorAnimation(); this._currentCursorOpacity = 1; @@ -266,7 +267,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @param {Number} offset */ moveCursorDownWithoutShift: function(offset) { - this._selectionDirection = 'right'; this.selectionStart += offset; @@ -281,7 +281,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @param {Number} offset */ moveCursorDownWithShift: function(offset) { - if (this._selectionDirection === 'left' && (this.selectionStart !== this.selectionEnd)) { this.selectionStart += offset; this._selectionDirection = 'left'; @@ -297,8 +296,12 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot } }, + /** + * @param {Event} e Event object + * @param {Boolean} isRight + * @return {Number} + */ getUpCursorOffset: function(e, isRight) { - var selectionProp = isRight ? this.selectionEnd : this.selectionStart, cursorLocation = this.get2DCursorLocation(selectionProp); @@ -564,7 +567,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * Moves cursor right without keeping selection - * @param {Event} e + * @param {Event} e Event object */ moveCursorRightWithoutShift: function(e) { this._selectionDirection = 'right'; @@ -584,6 +587,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * Inserts a character where cursor is (replacing selection if one exists) + * @param {Event} e Event object */ removeChars: function(e) { if (this.selectionStart === this.selectionEnd) { @@ -610,6 +614,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private + * @param {Event} e Event object */ _removeCharsNearCursor: function(e) { if (this.selectionStart !== 0) { diff --git a/src/mixins/object_geometry.mixin.js b/src/mixins/object_geometry.mixin.js index 2b45b09dce1..f47704f3b48 100644 --- a/src/mixins/object_geometry.mixin.js +++ b/src/mixins/object_geometry.mixin.js @@ -253,7 +253,7 @@ /** * Scales an object (equally by x and y) - * @param value {Number} scale factor + * @param {Number} value Scale factor * @return {fabric.Object} thisArg * @chainable */ @@ -274,7 +274,7 @@ /** * Scales an object to a given width, with respect to bounding box (scaling by x/y equally) - * @param value {Number} new width value + * @param {Number} value New width value * @return {fabric.Object} thisArg * @chainable */ @@ -286,7 +286,7 @@ /** * Scales an object to a given height, with respect to bounding box (scaling by x/y equally) - * @param value {Number} new height value + * @param {Number} value New height value * @return {fabric.Object} thisArg * @chainable */ @@ -302,24 +302,24 @@ * @chainable */ setCoords: function() { - var strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, theta = degreesToRadians(this.angle), - vpt = this.getViewportTransform(); - - var f = function (p) { - return fabric.util.transformPoint(p, vpt); - }; - var w = this.width, + vpt = this.getViewportTransform(), + f = function (p) { + return fabric.util.transformPoint(p, vpt); + }, + w = this.width, h = this.height, - capped = this.strokeLineCap === "round" || this.strokeLineCap === "square", - vLine = this.type === "line" && this.width === 1, - hLine = this.type === "line" && this.height === 1, - strokeW = (capped && hLine) || this.type !== "line", - strokeH = (capped && vLine) || this.type !== "line"; + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; + if (vLine) { w = strokeWidth; - } else if (hLine) { + } + else if (hLine) { h = strokeWidth; } if (strokeW) { @@ -361,11 +361,12 @@ mt = f(_mt), mr = f(new fabric.Point(_tr.x - (wh.y/2 * sinTh), _tr.y + (wh.y/2 * cosTh))), mb = f(new fabric.Point(_bl.x + (wh.x/2 * cosTh), _bl.y + (wh.x/2 * sinTh))), - mtr = f(new fabric.Point(_mt.x, _mt.y)); + mtr = f(new fabric.Point(_mt.x, _mt.y)), - // padding - var padX = Math.cos(_angle + theta) * this.padding * Math.sqrt(2), + // padding + padX = Math.cos(_angle + theta) * this.padding * Math.sqrt(2), padY = Math.sin(_angle + theta) * this.padding * Math.sqrt(2); + tl = tl.add(new fabric.Point(-padX, -padY)); tr = tr.add(new fabric.Point(padY, -padX)); br = br.add(new fabric.Point(padX, padY)); diff --git a/src/mixins/object_interactivity.mixin.js b/src/mixins/object_interactivity.mixin.js index bdc5ed756c3..f212379d496 100644 --- a/src/mixins/object_interactivity.mixin.js +++ b/src/mixins/object_interactivity.mixin.js @@ -281,14 +281,15 @@ var w = this.getWidth(), h = this.getHeight(), strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, - capped = this.strokeLineCap === "round" || this.strokeLineCap === "square", - vLine = this.type === "line" && this.width === 1, - hLine = this.type === "line" && this.height === 1, - strokeW = (capped && hLine) || this.type !== "line", - strokeH = (capped && vLine) || this.type !== "line"; + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; if (vLine) { w = strokeWidth / scaleX; - } else if (hLine) { + } + else if (hLine) { h = strokeWidth / scaleY; } if (strokeW) { @@ -348,14 +349,16 @@ strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, w = this.width, h = this.height, - capped = this.strokeLineCap === "round" || this.strokeLineCap === "square", - vLine = this.type === "line" && this.width === 1, - hLine = this.type === "line" && this.height === 1, - strokeW = (capped && hLine) || this.type !== "line", - strokeH = (capped && vLine) || this.type !== "line"; + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; + if (vLine) { w = strokeWidth; - } else if (hLine) { + } + else if (hLine) { h = strokeWidth; } if (strokeW) { diff --git a/src/mixins/object_origin.mixin.js b/src/mixins/object_origin.mixin.js index d31f4438da5..d14f72b827e 100644 --- a/src/mixins/object_origin.mixin.js +++ b/src/mixins/object_origin.mixin.js @@ -36,7 +36,7 @@ /** * Translates the coordinates from center to origin coordinates (based on the object's dimensions) - * @param {fabric.Point} point The point which corresponds to center of the object + * @param {fabric.Point} center The point which corresponds to center of the object * @param {String} originX Horizontal origin: 'left', 'center' or 'right' * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' * @return {fabric.Point} @@ -146,7 +146,7 @@ /** * Sets the position of the object taking into consideration the object's origin - * @param {fabric.Point} point The new position of the object + * @param {fabric.Point} pos The new position of the object * @param {String} originX Horizontal origin: 'left', 'center' or 'right' * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' * @return {void} diff --git a/src/shapes/object.class.js b/src/shapes/object.class.js index dee5a77e8c9..169dce49de6 100644 --- a/src/shapes/object.class.js +++ b/src/shapes/object.class.js @@ -682,6 +682,7 @@ /** * @private + * @param {Object} [options] Options object */ _initGradient: function(options) { if (options.fill && options.fill.colorStops && !(options.fill instanceof fabric.Gradient)) { @@ -691,6 +692,7 @@ /** * @private + * @param {Object} [options] Options object */ _initPattern: function(options) { if (options.fill && options.fill.source && !(options.fill instanceof fabric.Pattern)) { @@ -703,6 +705,7 @@ /** * @private + * @param {Object} [options] Options object */ _initClipping: function(options) { if (!options.clipTo || typeof options.clipTo !== 'string') return; @@ -752,7 +755,6 @@ * @return {Object} Object representation of an instance */ toObject: function(propertiesToInclude) { - var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, object = { @@ -1006,17 +1008,17 @@ * @param {Boolean} [noTransform] When true, context is not transformed */ _renderControls: function(ctx, noTransform) { - var v = this.getViewportTransform(); + var vpt = this.getViewportTransform(); ctx.save(); if (this.active && !noTransform) { var center; if (this.group) { - center = fabric.util.transformPoint(this.group.getCenterPoint(), v); + center = fabric.util.transformPoint(this.group.getCenterPoint(), vpt); ctx.translate(center.x, center.y); ctx.rotate(degreesToRadians(this.group.angle)); } - center = fabric.util.transformPoint(this.getCenterPoint(), v, null != this.group); + center = fabric.util.transformPoint(this.getCenterPoint(), vpt, null != this.group); if (this.group) { center.x *= this.group.scaleX; center.y *= this.group.scaleY; diff --git a/src/util/lang_array.js b/src/util/lang_array.js index 3832bb929be..2135acc5308 100644 --- a/src/util/lang_array.js +++ b/src/util/lang_array.js @@ -135,7 +135,7 @@ /** * Returns "folded" (reduced) result of iterating over elements in an array * @param {Function} fn Callback to invoke for each element - * @param {Object} [context] Context to invoke callback in + * @param {Object} [initial] Object to use as the first argument to the first call of the callback * @return {Any} */ Array.prototype.reduce = function(fn /*, initial*/) { diff --git a/src/util/misc.js b/src/util/misc.js index 5c25d5385cb..82ed6699743 100644 --- a/src/util/misc.js +++ b/src/util/misc.js @@ -144,19 +144,19 @@ switch (unit[0]) { case 'mm': return number * fabric.DPI / 25.4; - break; + case 'cm': return number * fabric.DPI / 2.54; - break; + case 'in': return number * fabric.DPI; - break; + case 'pt': return number * fabric.DPI / 72; // or * 4 / 3 - break; + case 'pc': - return number * fabric.DPI / 72 * 12; // or * 16 - break; + return number * fabric.DPI / 72 * 12; // or * 16 + default: return number; } @@ -253,7 +253,8 @@ * @memberOf fabric.util * @param {Array} objects Objects to enliven * @param {Function} callback Callback to invoke when all objects are created - * @param {Function} Method for further parsing of object elements, + * @param {String} namespace Namespace to get klass "Class" object from + * @param {Function} reviver Method for further parsing of object elements, * called after each fabric object created. */ enlivenObjects: function(objects, callback, namespace, reviver) { From da0037447bdda599ddeff3bace2e6265b39d4cf3 Mon Sep 17 00:00:00 2001 From: kangax Date: Fri, 18 Jul 2014 12:19:51 +0200 Subject: [PATCH 16/21] Change height in itext test --- test/unit/itext.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/itext.js b/test/unit/itext.js index d7b306eadda..e7361dda984 100644 --- a/test/unit/itext.js +++ b/test/unit/itext.js @@ -8,7 +8,7 @@ 'originY': 'top', 'left': 0, 'top': 0, - 'width': 20, + 'width': 19, 'height': 52, 'fill': 'rgb(0,0,0)', 'stroke': null, From c55b06908b20b8af142e8504ae3f150273af9961 Mon Sep 17 00:00:00 2001 From: kangax Date: Fri, 18 Jul 2014 13:11:06 +0200 Subject: [PATCH 17/21] Remove failing node versions from travis --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 372ce792810..c77e2d5f49e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,6 @@ language: node_js node_js: - - "0.8" - "0.10" - - "0.11" script: 'npm run-script build && npm test' before_install: - sudo apt-get update -qq From 3df3c396a2c4f96957c0e7bc0f9986fa33c19738 Mon Sep 17 00:00:00 2001 From: kangax Date: Fri, 18 Jul 2014 13:11:18 +0200 Subject: [PATCH 18/21] Fix unit tests --- dist/fabric.js | 407 ++++++++++++++++++++---------------- dist/fabric.min.js | 14 +- dist/fabric.min.js.gz | Bin 56161 -> 56257 bytes dist/fabric.require.js | 407 ++++++++++++++++++++---------------- src/parser.js | 15 +- src/shapes/circle.class.js | 4 +- src/shapes/ellipse.class.js | 4 +- src/util/misc.js | 1 + test/unit/parser.js | 3 +- test/unit/text.js | 26 +-- 10 files changed, 501 insertions(+), 380 deletions(-) diff --git a/dist/fabric.js b/dist/fabric.js index 9cc6c37a39d..4ea1645dcf0 100644 --- a/dist/fabric.js +++ b/dist/fabric.js @@ -46,6 +46,11 @@ fabric.SHARED_ATTRIBUTES = [ "stroke-opacity", "stroke-width" ]; +/** + * Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion. + */ +fabric.DPI = 96; + (function(){ @@ -378,9 +383,9 @@ fabric.Collection = { * Rotates `point` around `origin` with `radians` * @static * @memberOf fabric.util - * @param {fabric.Point} The point to rotate - * @param {fabric.Point} The origin of the rotation - * @param {Number} The radians of the angle for the rotation + * @param {fabric.Point} point The point to rotate + * @param {fabric.Point} origin The origin of the rotation + * @param {Number} radians The radians of the angle for the rotation * @return {fabric.Point} The new rotated point */ rotatePoint: function(point, origin, radians) { @@ -416,19 +421,19 @@ fabric.Collection = { t[2] * p.x + t[3] * p.y + t[5] ); }, - + /** * Invert transformation t * @static * @memberOf fabric.util - * @param {Array} t The transform + * @param {Array} t The transform * @return {Array} The inverted transform */ invertTransform: function(t) { var r = t.slice(), a = 1 / (t[0] * t[3] - t[1] * t[2]); r = [a * t[3], -a * t[1], -a * t[2], a * t[0], 0, 0]; - var o = fabric.util.transformPoint({x: t[4], y: t[5]}, r); + var o = fabric.util.transformPoint({ x: t[4], y: t[5] }, r); r[4] = -o.x; r[5] = -o.y; return r; @@ -438,7 +443,7 @@ fabric.Collection = { * A wrapper around Number#toFixed, which contrary to native method returns number, not string. * @static * @memberOf fabric.util - * @param {Number | String} number number to operate on + * @param {Number|String} number number to operate on * @param {Number} fractionDigits number of fraction digits to "leave" * @return {Number} */ @@ -446,6 +451,37 @@ fabric.Collection = { return parseFloat(Number(number).toFixed(fractionDigits)); }, + /** + * Converts from attribute value to pixel value if applicable. + * Returns converted pixels or original value not converted. + * @param {Number|String} value number to operate on + * @return {Number|String} + */ + parseUnit: function(value) { + var unit = /\D{0,2}$/.exec(value), + number = parseFloat(value); + + 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; // or * 4 / 3 + + case 'pc': + return number * fabric.DPI / 72 * 12; // or * 16 + + default: + return number; + } + }, + /** * Function which always returns `false`. * @static @@ -537,7 +573,8 @@ fabric.Collection = { * @memberOf fabric.util * @param {Array} objects Objects to enliven * @param {Function} callback Callback to invoke when all objects are created - * @param {Function} [reviver] Method for further parsing of object elements, + * @param {String} namespace Namespace to get klass "Class" object from + * @param {Function} reviver Method for further parsing of object elements, * called after each fabric object created. */ enlivenObjects: function(objects, callback, namespace, reviver) { @@ -1149,7 +1186,7 @@ fabric.Collection = { /** * Returns "folded" (reduced) result of iterating over elements in an array * @param {Function} fn Callback to invoke for each element - * @param {Object} [context] Context to invoke callback in + * @param {Object} [initial] Object to use as the first argument to the first call of the callback * @return {Any} */ Array.prototype.reduce = function(fn /*, initial*/) { @@ -2687,6 +2724,7 @@ if (typeof console !== 'undefined') { capitalize = fabric.util.string.capitalize, clone = fabric.util.object.clone, toFixed = fabric.util.toFixed, + parseUnit = fabric.util.parseUnit, multiplyTransformMatrices = fabric.util.multiplyTransformMatrices, attributesMap = { @@ -2728,7 +2766,8 @@ if (typeof console !== 'undefined') { } function normalizeValue(attr, value, parentAttributes) { - var isArray; + var isArray = Object.prototype.toString.call(value) === '[object Array]', + parsed; if ((attr === 'fill' || attr === 'stroke') && value === 'none') { value = ''; @@ -2737,7 +2776,9 @@ if (typeof console !== 'undefined') { value = (value === 'evenodd') ? 'destination-over' : value; } else if (attr === 'strokeDashArray') { - value = value.replace(/,/g, ' ').split(/\s+/); + value = value.replace(/,/g, ' ').split(/\s+/).map(function(n) { + return parseInt(n); + }); } else if (attr === 'transformMatrix') { if (parentAttributes && parentAttributes.transformMatrix) { @@ -2758,11 +2799,9 @@ if (typeof console !== 'undefined') { else if (attr === 'originX' /* text-anchor */) { value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center'; } - - isArray = Object.prototype.toString.call(value) === '[object Array]'; - - // TODO: need to normalize em, %, pt, etc. to px (!) - var parsed = isArray ? value.map(parseFloat) : parseFloat(value); + else { + parsed = isArray ? value.map(parseUnit) : parseUnit(value); + } return (!isArray && isNaN(parsed) ? value : parsed); } @@ -3038,33 +3077,37 @@ if (typeof console !== 'undefined') { return styles; } - + /** * @private */ function parseUseDirectives(doc) { - var nodelist = doc.querySelectorAll("use"); - for (var i = 0; i < nodelist.length; i++) { - var el = nodelist[i]; - var xlink = el.getAttribute('xlink:href').substr(1); - var x = el.getAttribute('x') || 0; - var y = el.getAttribute('y') || 0; - var el2 = doc.getElementById(xlink).cloneNode(true); - var currentTrans = (el.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')'; + var nodelist = doc.getElementsByTagName('use'); + for (var i = 0, len = nodelist.length; i < len; i++) { + var el = nodelist[i], + xlink = el.getAttribute('xlink:href').substr(1), + x = el.getAttribute('x') || 0, + y = el.getAttribute('y') || 0, + el2 = doc.getElementById(xlink).cloneNode(true), + currentTrans = (el.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')', + parentNode; + for (var j = 0, attrs = el.attributes, l = attrs.length; j < l; j++) { var attr = attrs.item(j); - if (attr.nodeName !== 'x' && attr.nodeName !== 'y' && attr.nodeName !== 'xlink:href') { - if (attr.nodeName === 'transform') { - currentTrans = currentTrans + ' ' + attr.nodeValue; - } else { - el2.setAttribute(attr.nodeName, attr.nodeValue); - } + if (attr.nodeName === 'x' || attr.nodeName === 'y' || attr.nodeName === 'xlink:href') continue; + + if (attr.nodeName === 'transform') { + currentTrans = currentTrans + ' ' + attr.nodeValue; + } + else { + el2.setAttribute(attr.nodeName, attr.nodeValue); } } + el2.setAttribute('transform', currentTrans); el2.removeAttribute('id'); - var pNode=el.parentNode; - pNode.replaceChild(el2, el); + parentNode = el.parentNode; + parentNode.replaceChild(el2, el); } } @@ -3108,9 +3151,9 @@ if (typeof console !== 'undefined') { return function(doc, callback, reviver) { if (!doc) return; var startTime = new Date(); - + parseUseDirectives(doc); - + var descendants = fabric.util.toArray(doc.getElementsByTagName('*')); if (descendants.length === 0 && fabric.isLikelyNode) { @@ -3195,18 +3238,10 @@ if (typeof console !== 'undefined') { callback(false); }, - /** - * @param {String} url - * @param {Function} callback - */ get: function () { /* NOOP */ }, - /** - * @param {String} url - * @param {Object} object - */ set: function () { /* NOOP */ } @@ -3380,7 +3415,7 @@ if (typeof console !== 'undefined') { * Parses "points" attribute, returning an array of values * @static * @memberOf fabric - * @param points {String} points attribute string + * @param {String} points points attribute string * @return {Array} array of points */ parsePointsAttribute: function(points) { @@ -3717,7 +3752,7 @@ fabric.ElementsParser.prototype.checkIfDone = function() { /** * Adds value to this point * @param {Number} scalar - * @param {fabric.Point} thisArg + * @return {fabric.Point} thisArg */ scalarAddEquals: function (scalar) { this.x += scalar; @@ -5442,11 +5477,10 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ * @type Array * @default */ - viewportTransform: [1, 0, 0, 1, 0, 0], + viewportTransform: [1, 0, 0, 1, 0, 0], /** * Callback; invoked right before object is about to be scaled/rotated - * @param {fabric.Object} target Object that's about to be scaled/rotated */ onBeforeScaleRotate: function () { /* NOOP */ @@ -5733,6 +5767,8 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ this.lowerCanvasEl.style.width = this.width + 'px'; this.lowerCanvasEl.style.height = this.height + 'px'; + + this.viewportTransform = this.viewportTransform.slice(); }, /** @@ -5775,8 +5811,8 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ * @return {fabric.Canvas} instance * @chainable true */ - setWidth: function (value) { - return this._setDimension('width', value); + setWidth: function (width) { + return this._setDimension('width', width); }, /** @@ -5785,8 +5821,8 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ * @return {fabric.Canvas} instance * @chainable true */ - setHeight: function (value) { - return this._setDimension('height', value); + setHeight: function (height) { + return this._setDimension('height', height); }, /** @@ -5955,7 +5991,7 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ */ _draw: function (ctx, object) { if (!object) return; - + ctx.save(); var v = this.viewportTransform; ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); @@ -6703,7 +6739,7 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ * Provides a way to check support of some of the canvas methods * (either those of HTMLCanvasElement itself, or rendering context) * - * @param methodName {String} Method to check support for; + * @param {String} methodName Method to check support for; * Could be one of "getImageData", "toDataURL", "toDataURLWithQuality" or "setLineDash" * @return {Boolean | null} `true` if method is supported (or at least exists), * `null` if canvas element or context can not be initialized @@ -6915,7 +6951,8 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype }, /** - * @param {Object} pointer + * @private + * @param {Object} pointer Actual mouse position related to the canvas. */ _prepareForDrawing: function(pointer) { @@ -6929,18 +6966,15 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype /** * @private - * @param {fabric.Point} point + * @param {fabric.Point} point Point to be added to points array */ _addPoint: function(point) { this._points.push(point); }, /** - * Clear points array and set contextTop canvas - * style. - * + * Clear points array and set contextTop canvas style. * @private - * */ _reset: function() { this._points.length = 0; @@ -6951,9 +6985,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype /** * @private - * - * @param point {pointer} (fabric.util.pointer) actual mouse position - * related to the canvas. + * @param {Object} pointer Actual mouse position related to the canvas. */ _captureDrawingPath: function(pointer) { var pointerPoint = new fabric.Point(pointer.x, pointer.y); @@ -6962,19 +6994,18 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype /** * Draw a smooth path on the topCanvas using quadraticCurveTo - * * @private */ _render: function() { - var ctx = this.canvas.contextTop; - var v = this.canvas.viewportTransform; + 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(); - var p1 = this._points[0], - p2 = this._points[1]; - //if we only have 2 points in the path and they are the same //it means that the user only clicked the canvas without moving the mouse //then we should be drawing a dot. A path isn't drawn between two identical dots @@ -7004,19 +7035,18 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype /** * Return an SVG path based on our captured points and their bounding box - * * @private */ _getSVGPathData: function() { this.box = this.getPathBoundingBox(this._points); return this.convertPointsToSVGPath( - this._points, this.box.minx, this.box.maxx, this.box.miny, this.box.maxy); + this._points, this.box.minX, this.box.minY); }, /** * Returns bounding box of a path based on given points - * @param {Array} points - * @return {Object} object with minx, miny, maxx, maxy + * @param {Array} points Array of points + * @return {Object} Object with minX, minY, maxX, maxY */ getPathBoundingBox: function(points) { var xBounds = [], @@ -7042,19 +7072,21 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype yBounds.push(p1.y); return { - minx: utilMin(xBounds), - miny: utilMin(yBounds), - maxx: utilMax(xBounds), - maxy: utilMax(yBounds) + minX: utilMin(xBounds), + minY: utilMin(yBounds), + maxX: utilMax(xBounds), + maxY: utilMax(yBounds) }; }, /** * Converts points to SVG path * @param {Array} points Array of points + * @param {Number} minX + * @param {Number} minY * @return {String} SVG path */ - convertPointsToSVGPath: function(points, minX, maxX, minY) { + convertPointsToSVGPath: function(points, minX, minY) { var path = [], p1 = new fabric.Point(points[0].x - minX, points[0].y - minY), p2 = new fabric.Point(points[1].x - minX, points[1].y - minY); @@ -7078,7 +7110,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype /** * Creates fabric.Path object to add on canvas * @param {String} pathData Path data - * @return {fabric.Path} path to add on canvas + * @return {fabric.Path} Path to add on canvas */ createPath: function(pathData) { var path = new fabric.Path(pathData); @@ -7100,7 +7132,6 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype * On mouseup after drawing the path on contextTop canvas * we use the points captured to create an new fabric path object * and add it to the fabric canvas. - * */ _finalizeAndAddPath: function() { var ctx = this.canvas.contextTop; @@ -7389,6 +7420,10 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric this.canvas.renderAll(); }, + /** + * @private + * @param {Array} rects + */ _getOptimizedRects: function(rects) { // avoid creating duplicate rects at the same coordinates @@ -7451,7 +7486,7 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric else { width = this.dotWidth; } - + var point = new fabric.Point(x, y); point.width = width; @@ -7970,8 +8005,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab /** * Translates object by "setting" its left/top * @private - * @param x {Number} pointer's x coordinate - * @param y {Number} pointer's y coordinate + * @param {Number} x pointer's x coordinate + * @param {Number} y pointer's y coordinate */ _translateObject: function (x, y) { var target = this._currentTransform.target; @@ -7987,9 +8022,9 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab /** * Scales object by invoking its scaleX/scaleY methods * @private - * @param x {Number} pointer's x coordinate - * @param y {Number} pointer's y coordinate - * @param by {String} Either 'x' or 'y' - specifies dimension constraint by which to scale an object. + * @param {Number} x pointer's x coordinate + * @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 */ _scaleObject: function (x, y, by) { @@ -8369,7 +8404,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab /** * @private - * @param {HTMLElement|String} canvasEl Canvas element * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized */ _createUpperCanvas: function () { @@ -8397,8 +8431,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab /** * @private - * @param {Number} width - * @param {Number} height */ _initWrapperElement: function () { this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', { @@ -8414,7 +8446,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab /** * @private - * @param {Element} element + * @param {HTMLElement} element canvas element to apply styles on */ _applyCanvasStyle: function (element) { var width = this.getWidth() || element.width, @@ -8758,8 +8790,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @param {Event} [e] Event object fired on Event.js gesture * @param {Event} [self] Inner Event object */ - _onGesture: function(e, s) { - this.__onTransformGesture && this.__onTransformGesture(e, s); + _onGesture: function(e, self) { + this.__onTransformGesture && this.__onTransformGesture(e, self); }, /** @@ -8767,8 +8799,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @param {Event} [e] Event object fired on Event.js drag * @param {Event} [self] Inner Event object */ - _onDrag: function(e, s) { - this.__onDrag && this.__onDrag(e, s); + _onDrag: function(e, self) { + this.__onDrag && this.__onDrag(e, self); }, /** @@ -8776,8 +8808,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @param {Event} [e] Event object fired on Event.js wheel event * @param {Event} [self] Inner Event object */ - _onMouseWheel: function(e, s) { - this.__onMouseWheel && this.__onMouseWheel(e, s); + _onMouseWheel: function(e, self) { + this.__onMouseWheel && this.__onMouseWheel(e, self); }, /** @@ -8785,8 +8817,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @param {Event} [e] Event object fired on Event.js orientation change * @param {Event} [self] Inner Event object */ - _onOrientationChange: function(e,s) { - this.__onOrientationChange && this.__onOrientationChange(e,s); + _onOrientationChange: function(e,self) { + this.__onOrientationChange && this.__onOrientationChange(e,self); }, /** @@ -8794,8 +8826,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @param {Event} [e] Event object fired on Event.js shake * @param {Event} [self] Inner Event object */ - _onShake: function(e,s) { - this.__onShake && this.__onShake(e,s); + _onShake: function(e, self) { + this.__onShake && this.__onShake(e,self); }, /** @@ -10688,6 +10720,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * @private + * @param {Object} [options] Options object */ _initGradient: function(options) { if (options.fill && options.fill.colorStops && !(options.fill instanceof fabric.Gradient)) { @@ -10697,6 +10730,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * @private + * @param {Object} [options] Options object */ _initPattern: function(options) { if (options.fill && options.fill.source && !(options.fill instanceof fabric.Pattern)) { @@ -10709,6 +10743,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * @private + * @param {Object} [options] Options object */ _initClipping: function(options) { if (!options.clipTo || typeof options.clipTo !== 'string') return; @@ -10758,7 +10793,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati * @return {Object} Object representation of an instance */ toObject: function(propertiesToInclude) { - var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, object = { @@ -11012,17 +11046,17 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati * @param {Boolean} [noTransform] When true, context is not transformed */ _renderControls: function(ctx, noTransform) { - var v = this.getViewportTransform(); + var vpt = this.getViewportTransform(); ctx.save(); if (this.active && !noTransform) { var center; if (this.group) { - center = fabric.util.transformPoint(this.group.getCenterPoint(), v); + center = fabric.util.transformPoint(this.group.getCenterPoint(), vpt); ctx.translate(center.x, center.y); ctx.rotate(degreesToRadians(this.group.angle)); } - center = fabric.util.transformPoint(this.getCenterPoint(), v, null != this.group); + center = fabric.util.transformPoint(this.getCenterPoint(), vpt, null != this.group); if (this.group) { center.x *= this.group.scaleX; center.y *= this.group.scaleY; @@ -11131,7 +11165,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Creates an instance of fabric.Image out of an object - * @param callback {Function} callback, invoked with an instance as a first argument + * @param {Function} callback callback, invoked with an instance as a first argument * @return {fabric.Object} thisArg */ cloneAsImage: function(callback) { @@ -11201,7 +11235,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Returns true if specified type is identical to the type of an instance - * @param type {String} type Type to check against + * @param {String} type Type to check against * @return {Boolean} */ isType: function(type) { @@ -11536,7 +11570,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Translates the coordinates from center to origin coordinates (based on the object's dimensions) - * @param {fabric.Point} point The point which corresponds to center of the object + * @param {fabric.Point} center The point which corresponds to center of the object * @param {String} originX Horizontal origin: 'left', 'center' or 'right' * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' * @return {fabric.Point} @@ -11646,7 +11680,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Sets the position of the object taking into consideration the object's origin - * @param {fabric.Point} point The new position of the object + * @param {fabric.Point} pos The new position of the object * @param {String} originX Horizontal origin: 'left', 'center' or 'right' * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' * @return {void} @@ -12003,7 +12037,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Scales an object (equally by x and y) - * @param value {Number} scale factor + * @param {Number} value Scale factor * @return {fabric.Object} thisArg * @chainable */ @@ -12024,7 +12058,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Scales an object to a given width, with respect to bounding box (scaling by x/y equally) - * @param value {Number} new width value + * @param {Number} value New width value * @return {fabric.Object} thisArg * @chainable */ @@ -12036,7 +12070,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Scales an object to a given height, with respect to bounding box (scaling by x/y equally) - * @param value {Number} new height value + * @param {Number} value New height value * @return {fabric.Object} thisArg * @chainable */ @@ -12052,24 +12086,24 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati * @chainable */ setCoords: function() { - var strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, theta = degreesToRadians(this.angle), - vpt = this.getViewportTransform(); - - var f = function (p) { - return fabric.util.transformPoint(p, vpt); - }; - var w = this.width, + vpt = this.getViewportTransform(), + f = function (p) { + return fabric.util.transformPoint(p, vpt); + }, + w = this.width, h = this.height, - capped = this.strokeLineCap === "round" || this.strokeLineCap === "square", - vLine = this.type === "line" && this.width === 1, - hLine = this.type === "line" && this.height === 1, - strokeW = (capped && hLine) || this.type !== "line", - strokeH = (capped && vLine) || this.type !== "line"; + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; + if (vLine) { w = strokeWidth; - } else if (hLine) { + } + else if (hLine) { h = strokeWidth; } if (strokeW) { @@ -12111,11 +12145,12 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati mt = f(_mt), mr = f(new fabric.Point(_tr.x - (wh.y/2 * sinTh), _tr.y + (wh.y/2 * cosTh))), mb = f(new fabric.Point(_bl.x + (wh.x/2 * cosTh), _bl.y + (wh.x/2 * sinTh))), - mtr = f(new fabric.Point(_mt.x, _mt.y)); + mtr = f(new fabric.Point(_mt.x, _mt.y)), - // padding - var padX = Math.cos(_angle + theta) * this.padding * Math.sqrt(2), + // padding + padX = Math.cos(_angle + theta) * this.padding * Math.sqrt(2), padY = Math.sin(_angle + theta) * this.padding * Math.sqrt(2); + tl = tl.add(new fabric.Point(-padX, -padY)); tr = tr.add(new fabric.Point(padY, -padX)); br = br.add(new fabric.Point(padX, padY)); @@ -12671,14 +12706,15 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot var w = this.getWidth(), h = this.getHeight(), strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, - capped = this.strokeLineCap === "round" || this.strokeLineCap === "square", - vLine = this.type === "line" && this.width === 1, - hLine = this.type === "line" && this.height === 1, - strokeW = (capped && hLine) || this.type !== "line", - strokeH = (capped && vLine) || this.type !== "line"; + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; if (vLine) { w = strokeWidth / scaleX; - } else if (hLine) { + } + else if (hLine) { h = strokeWidth / scaleY; } if (strokeW) { @@ -12738,14 +12774,16 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, w = this.width, h = this.height, - capped = this.strokeLineCap === "round" || this.strokeLineCap === "square", - vLine = this.type === "line" && this.width === 1, - hLine = this.type === "line" && this.height === 1, - strokeW = (capped && hLine) || this.type !== "line", - strokeH = (capped && vLine) || this.type !== "line"; + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; + if (vLine) { w = strokeWidth; - } else if (hLine) { + } + else if (hLine) { h = strokeWidth; } if (strokeW) { @@ -12756,7 +12794,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot } w *= this.scaleX; h *= this.scaleY; - + var wh = fabric.util.transformPoint(new fabric.Point(w, h), vpt, true), width = wh.x, height = wh.y, @@ -13562,7 +13600,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param ctx {CanvasRenderingContext2D} context to render on + * @param {CanvasRenderingContext2D} ctx context to render on + * @param {Boolean} [noTransform] When true, context is not transformed */ _render: function(ctx, noTransform) { ctx.beginPath(); @@ -13641,8 +13680,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot parsedAttributes.top = 0; } if (!('transformMatrix' in parsedAttributes)) { - parsedAttributes.left -= (options.width / 2); - parsedAttributes.top -= (options.height / 2); + parsedAttributes.left -= options.width ? (options.width / 2) : 0; + parsedAttributes.top -= options.height ? (options.height / 2) : 0; } var obj = new fabric.Circle(extend(parsedAttributes, options)); @@ -13718,7 +13757,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param ctx {CanvasRenderingContext2D} Context to render on + * @param {CanvasRenderingContext2D} ctx Context to render on */ _render: function(ctx) { var widthBy2 = this.width / 2, @@ -13736,7 +13775,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param ctx {CanvasRenderingContext2D} Context to render on + * @param {CanvasRenderingContext2D} ctx Context to render on */ _renderDashedStroke: function(ctx) { var widthBy2 = this.width / 2, @@ -13791,7 +13830,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * Returns fabric.Triangle instance from an object representation * @static * @memberOf fabric.Triangle - * @param object {Object} object to create an instance from + * @param {Object} object Object to create an instance from * @return {Object} instance of Canvas.Triangle */ fabric.Triangle.fromObject = function(object) { @@ -13897,8 +13936,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * Renders this instance on a given context - * @param ctx {CanvasRenderingContext2D} context to render on - * @param noTransform {Boolean} context is not transformed when set to true + * @param {CanvasRenderingContext2D} ctx context to render on + * @param {Boolean} [noTransform] When true, context is not transformed */ render: function(ctx, noTransform) { // do not use `get` for perf. reasons @@ -13908,7 +13947,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param ctx {CanvasRenderingContext2D} context to render on + * @param {CanvasRenderingContext2D} ctx context to render on + * @param {Boolean} [noTransform] When true, context is not transformed */ _render: function(ctx, noTransform) { ctx.beginPath(); @@ -13959,8 +13999,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot parsedAttributes.top = 0; } if (!('transformMatrix' in parsedAttributes)) { - parsedAttributes.left -= (options.width / 2); - parsedAttributes.top -= (options.height / 2); + parsedAttributes.left -= options.width ? (options.width / 2) : 0; + parsedAttributes.top -= options.height ? (options.height / 2) : 0; } var ellipse = new fabric.Ellipse(extend(parsedAttributes, options)); @@ -14085,7 +14125,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param ctx {CanvasRenderingContext2D} context to render on + * @param {CanvasRenderingContext2D} ctx Context to render on */ _render: function(ctx) { @@ -14141,7 +14181,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param ctx {CanvasRenderingContext2D} context to render on + * @param {CanvasRenderingContext2D} ctx Context to render on */ _renderDashedStroke: function(ctx) { var x = -this.width / 2, @@ -14267,7 +14307,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * Returns {@link fabric.Rect} instance from an object representation * @static * @memberOf fabric.Rect - * @param object {Object} object to create an instance from + * @param {Object} object Object to create an instance from * @return {Object} instance of fabric.Rect */ fabric.Rect.fromObject = function(object) { @@ -14458,7 +14498,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * Returns fabric.Polyline instance from an object representation * @static * @memberOf fabric.Polyline - * @param object {Object} object Object to create an instance from + * @param {Object} object Object to create an instance from * @return {fabric.Polyline} Instance of fabric.Polyline */ fabric.Polyline.fromObject = function(object) { @@ -14668,7 +14708,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * Returns fabric.Polygon instance from an object representation * @static * @memberOf fabric.Polygon - * @param object {Object} object Object to create an instance from + * @param {Object} object Object to create an instance from * @return {fabric.Polygon} Instance of fabric.Polygon */ fabric.Polygon.fromObject = function(object) { @@ -14822,7 +14862,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param {Boolean} positionSet When false, path offset is returned otherwise 0 + * @param {Number} origLeft Original left position + * @param {Number} origTop Original top position */ _calculatePathOffset: function (origLeft, origTop) { return { @@ -15503,7 +15544,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot ctx.save(); var m = this.transformMatrix; - + if (m) { ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); } @@ -16192,7 +16233,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @static * @memberOf fabric.Group * @param {Object} object Object to create a group from - * @param {Object} [options] Options object + * @param {Function} [callback] Callback to invoke when an group instance is created * @return {fabric.Group} An instance of fabric.Group */ fabric.Group.fromObject = function(object, callback) { @@ -18535,7 +18576,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {String} method Method name ("fillText" or "strokeText") * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {String} line Chars to render + * @param {String} chars Chars to render * @param {Number} left Left position of text * @param {Number} top Top position of text */ @@ -19158,7 +19199,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * Returns fabric.Text instance from an object representation * @static * @memberOf fabric.Text - * @param object {Object} object Object to create an instance from + * @param {Object} object Object to create an instance from * @return {fabric.Text} Instance of fabric.Text */ fabric.Text.fromObject = function(object) { @@ -19807,7 +19848,9 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {String} method * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {String} line + * @param {String} line Content of the line + * @param {Number} left Left coordinate + * @param {Number} top Top coordinate */ _renderCharsFast: function(method, ctx, line, left, top) { this.skipTextAlign = false; @@ -19822,7 +19865,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private + * @param {String} method * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Number} lineIndex + * @param {Number} i + * @param {String} _char + * @param {Number} left Left coordinate + * @param {Number} top Top coordinate + * @param {Number} lineHeight Height of the line */ _renderChar: function(method, ctx, lineIndex, i, _char, left, top, lineHeight) { var decl, charWidth, charHeight; @@ -20241,6 +20291,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines */ _getTextHeight: function(ctx, textLines) { var height = 0; @@ -20252,7 +20303,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private - * @param {CanvasRenderingContext2D} ctx Context to render on */ _getTopOffset: function() { var topOffset = fabric.Text.prototype._getTopOffset.call(this); @@ -20532,7 +20582,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * Find new selection index representing start of current line according to current selection index - * @param {Number} current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index */ findLineBoundaryLeft: function(startFrom) { var offset = 0, index = startFrom - 1; @@ -20547,7 +20598,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * Find new selection index representing end of current line according to current selection index - * @param {Number} current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index */ findLineBoundaryRight: function(startFrom) { var offset = 0, index = startFrom; @@ -20580,6 +20632,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * Finds index corresponding to beginning or end of a word * @param {Number} selectionStart Index of a character * @param {Number} direction: 1 or -1 + * @return {Number} Index of the beginning or end of a word */ searchWordBoundary: function(selectionStart, direction) { var index = this._reSpace.test(this.text.charAt(selectionStart)) ? selectionStart - 1 : selectionStart, @@ -21161,7 +21214,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * Changes cursor location in a text depending on passed pointer (x/y) object - * @param {Object} pointer Pointer object with x and y numeric properties + * @param {Event} e Event object */ setCursorByClick: function(e) { var newSelectionStart = this.getSelectionStartFromPointer(e); @@ -21184,7 +21237,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private * @param {Event} e Event object - * @param {Object} Object with x/y corresponding to local offset (according to object rotation) + * @return {Object} Coordinates of a pointer (x, y) */ _getLocalRotatedPointer: function(e) { var pointer = this.canvas.getPointer(e), @@ -21204,7 +21257,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @return {Number} Index of a character */ getSelectionStartFromPointer: function(e) { - var mouseOffset = this._getLocalRotatedPointer(e), textLines = this.text.split(this._reNewline), prevWidth = 0, @@ -21396,7 +21448,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot // Check for backward compatibility with old browsers if (clipboardData) { copiedText = clipboardData.getData('text'); - } else { + } + else { copiedText = this.copiedText; } @@ -21421,6 +21474,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private * @param {Event} e Event object + * @return {Object} Clipboard data object */ _getClipboardData: function(e) { return e && (e.clipboardData || fabric.window.clipboardData); @@ -21442,10 +21496,11 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * Gets start offset of a selection + * @param {Event} e Event object + * @param {Boolean} isRight * @return {Number} */ getDownCursorOffset: function(e, isRight) { - var selectionProp = isRight ? this.selectionEnd : this.selectionStart, textLines = this.text.split(this._reNewline), _char, @@ -21488,7 +21543,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @private */ _getIndexOnNextLine: function(cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor, textLines) { - var lineIndex = cursorLocation.lineIndex + 1, widthOfNextLine = this._getWidthOfLine(this.ctx, lineIndex, textLines), lineLeftOffset = this._getLineLeftOffset(widthOfNextLine), @@ -21531,7 +21585,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @param {Event} e Event object */ moveCursorDown: function(e) { - this.abortCursorAnimation(); this._currentCursorOpacity = 1; @@ -21552,7 +21605,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @param {Number} offset */ moveCursorDownWithoutShift: function(offset) { - this._selectionDirection = 'right'; this.selectionStart += offset; @@ -21567,7 +21619,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @param {Number} offset */ moveCursorDownWithShift: function(offset) { - if (this._selectionDirection === 'left' && (this.selectionStart !== this.selectionEnd)) { this.selectionStart += offset; this._selectionDirection = 'left'; @@ -21583,8 +21634,12 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot } }, + /** + * @param {Event} e Event object + * @param {Boolean} isRight + * @return {Number} + */ getUpCursorOffset: function(e, isRight) { - var selectionProp = isRight ? this.selectionEnd : this.selectionStart, cursorLocation = this.get2DCursorLocation(selectionProp); @@ -21850,7 +21905,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * Moves cursor right without keeping selection - * @param {Event} e + * @param {Event} e Event object */ moveCursorRightWithoutShift: function(e) { this._selectionDirection = 'right'; @@ -21870,6 +21925,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * Inserts a character where cursor is (replacing selection if one exists) + * @param {Event} e Event object */ removeChars: function(e) { if (this.selectionStart === this.selectionEnd) { @@ -21896,6 +21952,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private + * @param {Event} e Event object */ _removeCharsNearCursor: function(e) { if (this.selectionStart !== 0) { diff --git a/dist/fabric.min.js b/dist/fabric.min.js index cb3491aaf4f..e871bc6608c 100644 --- a/dist/fabric.min.js +++ b/dist/fabric.min.js @@ -1,7 +1,7 @@ -/* build: `node build.js modules=ALL exclude=gestures,cufon,json minifier=uglifyjs` *//*! Fabric.js Copyright 2008-2014, Printio (Juriy Zaytsev, Maxim Chernyak) */var fabric=fabric||{version:"1.4.8"};typeof exports!="undefined"&&(exports.fabric=fabric),typeof document!="undefined"&&typeof window!="undefined"?(fabric.document=document,fabric.window=window):(fabric.document=require("jsdom").jsdom(""),fabric.window=fabric.document.createWindow()),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"],function(){function e(e,t){if(!this.__eventListeners[e])return;t?fabric.util.removeFromArray(this.__eventListeners[e],t):this.__eventListeners[e].length=0}function t(e,t){this.__eventListeners||(this.__eventListeners={});if(arguments.length===1)for(var n in e)this.on(n,e[n]);else this.__eventListeners[e]||(this.__eventListeners[e]=[]),this.__eventListeners[e].push(t);return this}function n(t,n){if(!this.__eventListeners)return;if(arguments.length===0)this.__eventListeners={};else if(arguments.length===1&&typeof arguments[0]=="object")for(var r in t)e.call(this,r,t[r]);else e.call(this,t,n);return this}function r(e,t){if(!this.__eventListeners)return;var n=this.__eventListeners[e];if(!n)return;for(var r=0,i=n.length;r-1},complexity:function(){return this.getObjects().reduce(function(e,t){return e+=t.complexity?t.complexity():0,e},0)}},function(e){var t=Math.sqrt,n=Math.atan2,r=Math.PI/180;fabric.util={removeFromArray:function(e,t){var n=e.indexOf(t);return n!==-1&&e.splice(n,1),e},getRandomInt:function(e,t){return Math.floor(Math.random()*(t-e+1))+e},degreesToRadians:function(e){return e*r},radiansToDegrees:function(e){return e/r},rotatePoint:function(e,t,n){var r=Math.sin(n),i=Math.cos(n);e.subtractEquals(t);var s=e.x*i-e.y*r,o=e.x*r+e.y*i;return(new fabric.Point(s,o)).addEquals(t)},transformPoint:function(e,t,n){return n?new fabric.Point(t[0]*e.x+t[1]*e.y,t[2]*e.x+t[3]*e.y):new fabric.Point(t[0]*e.x+t[1]*e.y+t[4],t[2]*e.x+t[3]*e.y+t[5])},invertTransform:function(e){var t=e.slice(),n=1/(e[0]*e[3]-e[1]*e[2]);t=[n*e[3],-n*e[1],-n*e[2],n*e[0],0,0];var r=fabric.util.transformPoint({x:e[4],y:e[5]},t);return t[4]=-r.x,t[5]=-r.y,t},toFixed:function(e,t){return parseFloat(Number(e).toFixed(t))},falseFunction:function(){return!1},getKlass:function(e,t){return e=fabric.util.string.camelize(e.charAt(0).toUpperCase()+e.slice(1)),fabric.util.resolveNamespace(t)[e]},resolveNamespace:function(t){if(!t)return fabric;var n=t.split("."),r=n.length,i=e||fabric.window;for(var s=0;s1?r=new fabric.PathGroup(e,t):r=e[0],typeof n!="undefined"&&r.setSourcePath(n),r},populateWithProperties:function(e,t,n){if(n&&Object.prototype.toString.call(n)==="[object Array]")for(var r=0,i=n.length;rr)r+=u[p++%h],r>l&&(r=l),e[d?"lineTo":"moveTo"](r,0),d=!d;e.restore()},createCanvasElement:function(e){return e||(e=fabric.document.createElement("canvas")),!e.getContext&&typeof G_vmlCanvasManager!="undefined"&&G_vmlCanvasManager.initElement(e),e},createImage:function(){return fabric.isLikelyNode?new(require("canvas").Image):fabric.document.createElement("img")},createAccessors:function(e){var t=e.prototype;for(var n=t.stateProperties.length;n--;){var r=t.stateProperties[n],i=r.charAt(0).toUpperCase()+r.slice(1),s="set"+i,o="get"+i;t[o]||(t[o]=function(e){return new Function('return this.get("'+e+'")')}(r)),t[s]||(t[s]=function(e){return new Function("value",'return this.set("'+e+'", value)')}(r))}},clipContext:function(e,t){t.save(),t.beginPath(),e.clipTo(t),t.clip()},multiplyTransformMatrices:function(e,t){var n=[[e[0],e[2],e[4]],[e[1],e[3],e[5]],[0,0,1]],r=[[t[0],t[2],t[4]],[t[1],t[3],t[5]],[0,0,1]],i=[];for(var s=0;s<3;s++){i[s]=[];for(var o=0;o<3;o++){var u=0;for(var a=0;a<3;a++)u+=n[s][a]*r[a][o];i[s][o]=u}}return[i[0][0],i[1][0],i[0][1],i[1][1],i[0][2],i[1][2]]},getFunctionBody:function(e){return(String(e).match(/function[^{]*\{([\s\S]*)\}/)||{})[1]},normalizePoints:function(e,t){var n=fabric.util.array.min(e,"x"),r=fabric.util.array.min(e,"y");n=n<0?n:0,r=n<0?r:0;for(var i=0,s=e.length;i0&&(t>r?t-=r:t=0,n>r?n-=r:n=0);var i=!0,s=e.getImageData(t,n,r*2||1,r*2||1);for(var o=3,u=s.data.length;o0&&f===0&&(E-=2*Math.PI);var S=Math.ceil(Math.abs(E/(Math.PI*.5+.001))),x=[];for(var T=0;T1&&(h=Math.sqrt(h),t*=h,n*=h);var p=f/t,d=a/t,v=-a/n,m=f/n;return{x0:p*r+d*i,y0:v*r+m*i,x1:p*s+d*o,y1:v*s+m*o,sinTh:a,cosTh:f}}function o(e,i,s,o,u,a,f,l){r=n.call(arguments);if(t[r])return t[r];var c=Math.sin(s),h=Math.cos(s),p=Math.sin(o),d=Math.cos(o),v=l*u,m=-f*a,g=f*u,y=l*a,b=.25*(o-s),w=8/3*Math.sin(b)*Math.sin(b)/Math.sin(b*2),E=e+h-w*c,S=i+c+w*h,x=e+d,T=i+p,N=x+w*p,C=T-w*d;return t[r]=[v*E+m*S,g*E+y*S,v*N+m*C,g*N+y*C,v*x+m*T,g*x+y*T],t[r]}var e={},t={},n=Array.prototype.join,r;fabric.util.drawArc=function(e,t,n,r){var s=r[0],u=r[1],a=r[2],f=r[3],l=r[4],c=r[5],h=r[6],p=i(c,h,s,u,f,l,a,t,n);for(var d=0;d=t})}function r(e,t){return i(e,t,function(e,t){return e>>0;if(n===0)return-1;var r=0;arguments.length>0&&(r=Number(arguments[1]),r!==r?r=0:r!==0&&r!==Number.POSITIVE_INFINITY&&r!==Number.NEGATIVE_INFINITY&&(r=(r>0||-1)*Math.floor(Math.abs(r))));if(r>=n)return-1;var i=r>=0?r:Math.max(n-Math.abs(r),0);for(;i>>0;n>>0;r>>0;n>>0;n>>0;i>>0,n=0,r;if(arguments.length>1)r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n/g,">")}String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^[\s\xA0]+/,"").replace(/[\s\xA0]+$/,"")}),fabric.util.string={camelize:e,capitalize:t,escapeXml:n}}(),function(){var e=Array.prototype.slice,t=Function.prototype.apply,n=function(){};Function.prototype.bind||(Function.prototype.bind=function(r){var i=this,s=e.call(arguments,1),o;return s.length?o=function(){return t.call(i,this instanceof n?this:r,s.concat(e.call(arguments)))}:o=function(){return t.call(i,this instanceof n?this:r,arguments)},n.prototype=this.prototype,o.prototype=new n,o})}(),function(){function i(){}function s(t){var n=this.constructor.superclass.prototype[t];return arguments.length>1?n.apply(this,e.call(arguments,1)):n.call(this)}function o(){function u(){this.initialize.apply(this,arguments)}var n=null,o=e.call(arguments,0);typeof o[0]=="function"&&(n=o.shift()),u.superclass=n,u.subclasses=[],n&&(i.prototype=n.prototype,u.prototype=new i,n.subclasses.push(u));for(var a=0,f=o.length;a-1?e.prototype[i]=function(e){return function(){var n=this.constructor.superclass;this.constructor.superclass=r;var i=t[e].apply(this,arguments);this.constructor.superclass=n;if(e!=="initialize")return i}}(i):e.prototype[i]=t[i],n&&(t.toString!==Object.prototype.toString&&(e.prototype.toString=t.toString),t.valueOf!==Object.prototype.valueOf&&(e.prototype.valueOf=t.valueOf))};fabric.util.createClass=o}(),function(){function t(e){var t=Array.prototype.slice.call(arguments,1),n,r,i=t.length;for(r=0;r-1?s(e,t.match(/opacity:\s*(\d?\.?\d*)/)[1]):e;for(var r in t)if(r==="opacity")s(e,t[r]);else{var i=r==="float"||r==="cssFloat"?typeof n.styleFloat=="undefined"?"cssFloat":"styleFloat":r;n[i]=t[r]}return e}var t=fabric.document.createElement("div"),n=typeof t.style.opacity=="string",r=typeof t.style.filter=="string",i=/alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,s=function(e){return e};n?s=function(e,t){return e.style.opacity=t,e}:r&&(s=function(e,t){var n=e.style;return e.currentStyle&&!e.currentStyle.hasLayout&&(n.zoom=1),i.test(n.filter)?(t=t>=.9999?"":"alpha(opacity="+t*100+")",n.filter=n.filter.replace(i,t)):n.filter+=" alpha(opacity="+t*100+")",e}),fabric.util.setStyle=e}(),function(){function t(e){return typeof e=="string"?fabric.document.getElementById(e):e}function s(e,t){var n=fabric.document.createElement(e);for(var r in t)r==="class"?n.className=t[r]:r==="for"?n.htmlFor=t[r]:n.setAttribute(r,t[r]);return n}function o(e,t){e&&(" "+e.className+" ").indexOf(" "+t+" ")===-1&&(e.className+=(e.className?" ":"")+t)}function u(e,t,n){return typeof t=="string"&&(t=s(t,n)),e.parentNode&&e.parentNode.replaceChild(t,e),t.appendChild(e),t}function a(e,t){var n,r,i=0,s=0,o=fabric.document.documentElement,u=fabric.document.body||{scrollLeft:0,scrollTop:0};r=e;while(e&&e.parentNode&&!n)e=e.parentNode,e!==fabric.document&&fabric.util.getElementStyle(e,"position")==="fixed"&&(n=e),e!==fabric.document&&r!==t&&fabric.util.getElementStyle(e,"position")==="absolute"?(i=0,s=0):e===fabric.document?(i=u.scrollLeft||o.scrollLeft||0,s=u.scrollTop||o.scrollTop||0):(i+=e.scrollLeft||0,s+=e.scrollTop||0);return{left:i,top:s}}function f(e){var t,n=e&&e.ownerDocument,r={left:0,top:0},i={left:0,top:0},s,o={borderLeftWidth:"left",borderTopWidth:"top",paddingLeft:"left",paddingTop:"top"};if(!n)return{left:0,top:0};for(var u in o)i[o[u]]+=parseInt(l(e,u),10)||0;return t=n.documentElement,typeof e.getBoundingClientRect!="undefined"&&(r=e.getBoundingClientRect()),s=fabric.util.getScrollLeftTop(e,null),{left:r.left+s.left-(t.clientLeft||0)+i.left,top:r.top+s.top-(t.clientTop||0)+i.top}}var e=Array.prototype.slice,n,r=function(t){return e.call(t,0)};try{n=r(fabric.document.childNodes)instanceof Array}catch(i){}n||(r=function(e){var t=new Array(e.length),n=e.length;while(n--)t[n]=e[n];return t});var l;fabric.document.defaultView&&fabric.document.defaultView.getComputedStyle?l=function(e,t){return fabric.document.defaultView.getComputedStyle(e,null)[t]}:l=function(e,t){var n=e.style[t];return!n&&e.currentStyle&&(n=e.currentStyle[t]),n},function(){function n(e){return typeof e.onselectstart!="undefined"&&(e.onselectstart=fabric.util.falseFunction),t?e.style[t]="none":typeof e.unselectable=="string"&&(e.unselectable="on"),e}function r(e){return typeof e.onselectstart!="undefined"&&(e.onselectstart=null),t?e.style[t]="":typeof e.unselectable=="string"&&(e.unselectable=""),e}var e=fabric.document.documentElement.style,t="userSelect"in e?"userSelect":"MozUserSelect"in e?"MozUserSelect":"WebkitUserSelect"in e?"WebkitUserSelect":"KhtmlUserSelect"in e?"KhtmlUserSelect":"";fabric.util.makeElementUnselectable=n,fabric.util.makeElementSelectable=r}(),function(){function e(e,t){var n=fabric.document.getElementsByTagName("head")[0],r=fabric.document.createElement("script"),i=!0;r.onload=r.onreadystatechange=function(e){if(i){if(typeof this.readyState=="string"&&this.readyState!=="loaded"&&this.readyState!=="complete")return;i=!1,t(e||fabric.window.event),r=r.onload=r.onreadystatechange=null}},r.src=e,n.appendChild(r)}fabric.util.getScript=e}(),fabric.util.getById=t,fabric.util.toArray=r,fabric.util.makeElement=s,fabric.util.addClass=o,fabric.util.wrapElement=u,fabric.util.getScrollLeftTop=a,fabric.util.getElementOffset=f,fabric.util.getElementStyle=l}(),function(){function e(e,t){return e+(/\?/.test(e)?"&":"?")+t}function n(){}function r(r,i){i||(i={});var s=i.method?i.method.toUpperCase():"GET",o=i.onComplete||function(){},u=t(),a;return u.onreadystatechange=function(){u.readyState===4&&(o(u),u.onreadystatechange=n)},s==="GET"&&(a=null,typeof i.parameters=="string"&&(r=e(r,i.parameters))),u.open(s,r,!0),(s==="POST"||s==="PUT")&&u.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),u.send(a),u}var t=function(){var e=[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 t=e.length;t--;)try{var n=e[t]();if(n)return e[t]}catch(r){}}();fabric.util.request=r}(),fabric.log=function(){},fabric.warn=function(){},typeof console!="undefined"&&["log","warn"].forEach(function(e){typeof console[e]!="undefined"&&console[e].apply&&(fabric[e]=function(){return console[e].apply(console,arguments)})}),function(){function e(e){n(function(t){e||(e={});var r=t||+(new Date),i=e.duration||500,s=r+i,o,u=e.onChange||function(){},a=e.abort||function(){return!1},f=e.easing||function(e,t,n,r){return-n*Math.cos(e/r*(Math.PI/2))+n+t},l="startValue"in e?e.startValue:0,c="endValue"in e?e.endValue:100,h=e.byValue||c-l;e.onStart&&e.onStart(),function p(t){o=t||+(new Date);var c=o>s?i:o-r;if(a()){e.onComplete&&e.onComplete();return}u(f(c,l,h,i));if(o>s){e.onComplete&&e.onComplete();return}n(p)}(r)})}function n(){return t.apply(fabric.window,arguments)}var t=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(e){fabric.window.setTimeout(e,1e3/60)};fabric.util.animate=e,fabric.util.requestAnimFrame=n}(),function(){function e(e,t,n,r){return e','')}var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.string.capitalize,i=t.util.object.clone,s=t.util.toFixed,o=t.util.multiplyTransformMatrices,u={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"},a={stroke:"strokeOpacity",fill:"fillOpacity"};t.parseTransformAttribute=function(){function e(e,t){var n=t[0];e[0]=Math.cos(n),e[1]=Math.sin(n),e[2]=-Math.sin(n),e[3]=Math.cos(n)}function n(e,t){var n=t[0],r=t.length===2?t[1]:t[0];e[0]=n,e[3]=r}function r(e,t){e[2]=t[0]}function i(e,t){e[1]=t[0]}function s(e,t){e[4]=t[0],t.length===2&&(e[5]=t[1])}var o=[1,0,0,1,0,0],u="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",a="(?:\\s+,?\\s*|,\\s*)",f="(?:(skewX)\\s*\\(\\s*("+u+")\\s*\\))",l="(?:(skewY)\\s*\\(\\s*("+u+")\\s*\\))",c="(?:(rotate)\\s*\\(\\s*("+u+")(?:"+a+"("+u+")"+a+"("+u+"))?\\s*\\))",h="(?:(scale)\\s*\\(\\s*("+u+")(?:"+a+"("+u+"))?\\s*\\))",p="(?:(translate)\\s*\\(\\s*("+u+")(?:"+a+"("+u+"))?\\s*\\))",d="(?:(matrix)\\s*\\(\\s*("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+"\\s*\\))",v="(?:"+d+"|"+p+"|"+h+"|"+c+"|"+f+"|"+l+")",m="(?:"+v+"(?:"+a+v+")*"+")",g="^\\s*(?:"+m+"?)\\s*$",y=new RegExp(g),b=new RegExp(v,"g");return function(u){var a=o.concat(),f=[];if(!u||u&&!y.test(u))return a;u.replace(b,function(u){var l=(new RegExp(v)).exec(u).filter(function(e){return e!==""&&e!=null}),c=l[1],h=l.slice(2).map(parseFloat);switch(c){case"translate":s(a,h);break;case"rotate":h[0]=t.util.degreesToRadians(h[0]),e(a,h);break;case"scale":n(a,h);break;case"skewX":r(a,h);break;case"skewY":i(a,h);break;case"matrix":a=h}f.push(a.concat()),a=o.concat()});var l=f[0];while(f.length>1)f.shift(),l=t.util.multiplyTransformMatrices(l,f[0]);return l}}(),t.parseSVGDocument=function(){function s(e,t){while(e&&(e=e.parentNode))if(t.test(e.nodeName))return!0;return!1}var e=/^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/,n="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",r=new RegExp("^\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*"+"$");return function(n,o,u){if(!n)return;var a=new Date;m(n);var f=t.util.toArray(n.getElementsByTagName("*"));if(f.length===0&&t.isLikelyNode){f=n.selectNodes('//*[name(.)!="svg"]');var l=[];for(var c=0,h=f.length;c/i,"")));if(!s||!s.documentElement)return;t.parseSVGDocument(s.documentElement,function(r,i){g.set(e,{objects:t.util.array.invoke(r,"toObject"),options:i}),n(r,i)},r)}e=e.replace(/^\n\s*/,"").trim(),g.has(e,function(r){r?g.get(e,function(e){var t=y(e);n(t.objects,t.options)}):new t.util.request(e,{method:"get",onComplete:i})})},loadSVGFromString:function(e,n,r){e=e.trim();var i;if(typeof DOMParser!="undefined"){var s=new DOMParser;s&&s.parseFromString&&(i=s.parseFromString(e,"text/xml"))}else t.window.ActiveXObject&&(i=new ActiveXObject("Microsoft.XMLDOM"),i.async="false",i.loadXML(e.replace(//i,"")));t.parseSVGDocument(i.documentElement,function(e,t){n(e,t)},r)},createSVGFontFacesMarkup:function(e){var t="";for(var n=0,r=e.length;n',"",""].join("")),t},createSVGRefElementsMarkup:function(e){var t=[];return b(t,e,"backgroundColor"),b(t,e,"overlayColor"),t.join("")}})}(typeof exports!="undefined"? -exports:this),fabric.ElementsParser=function(e,t,n,r){this.elements=e,this.callback=t,this.options=n,this.reviver=r},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 e=0,t=this.elements.length;ee.x&&this.y>e.y},gte:function(e){return this.x>=e.x&&this.y>=e.y},lerp:function(e,t){return new n(this.x+(e.x-this.x)*t,this.y+(e.y-this.y)*t)},distanceFrom:function(e){var t=this.x-e.x,n=this.y-e.y;return Math.sqrt(t*t+n*n)},midPointFrom:function(e){return new n(this.x+(e.x-this.x)/2,this.y+(e.y-this.y)/2)},min:function(e){return new n(Math.min(this.x,e.x),Math.min(this.y,e.y))},max:function(e){return new n(Math.max(this.x,e.x),Math.max(this.y,e.y))},toString:function(){return this.x+","+this.y},setXY:function(e,t){this.x=e,this.y=t},setFromPoint:function(e){this.x=e.x,this.y=e.y},swap:function(e){var t=this.x,n=this.y;this.x=e.x,this.y=e.y,e.x=t,e.y=n}}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function n(e){this.status=e,this.points=[]}var t=e.fabric||(e.fabric={});if(t.Intersection){t.warn("fabric.Intersection is already defined");return}t.Intersection=n,t.Intersection.prototype={appendPoint:function(e){this.points.push(e)},appendPoints:function(e){this.points=this.points.concat(e)}},t.Intersection.intersectLineLine=function(e,r,i,s){var o,u=(s.x-i.x)*(e.y-i.y)-(s.y-i.y)*(e.x-i.x),a=(r.x-e.x)*(e.y-i.y)-(r.y-e.y)*(e.x-i.x),f=(s.y-i.y)*(r.x-e.x)-(s.x-i.x)*(r.y-e.y);if(f!==0){var l=u/f,c=a/f;0<=l&&l<=1&&0<=c&&c<=1?(o=new n("Intersection"),o.points.push(new t.Point(e.x+l*(r.x-e.x),e.y+l*(r.y-e.y)))):o=new n}else u===0||a===0?o=new n("Coincident"):o=new n("Parallel");return o},t.Intersection.intersectLinePolygon=function(e,t,r){var i=new n,s=r.length;for(var o=0;o0&&(i.status="Intersection"),i},t.Intersection.intersectPolygonPolygon=function(e,t){var r=new n,i=e.length;for(var s=0;s0&&(r.status="Intersection"),r},t.Intersection.intersectPolygonRectangle=function(e,r,i){var s=r.min(i),o=r.max(i),u=new t.Point(o.x,s.y),a=new t.Point(s.x,o.y),f=n.intersectLinePolygon(s,u,e),l=n.intersectLinePolygon(u,o,e),c=n.intersectLinePolygon(o,a,e),h=n.intersectLinePolygon(a,s,e),p=new n;return p.appendPoints(f.points),p.appendPoints(l.points),p.appendPoints(c.points),p.appendPoints(h.points),p.points.length>0&&(p.status="Intersection"),p}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function n(e){e?this._tryParsingColor(e):this.setSource([0,0,0,1])}function r(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+(t-e)*6*n:n<.5?t:n<2/3?e+(t-e)*(2/3-n)*6:e}var t=e.fabric||(e.fabric={});if(t.Color){t.warn("fabric.Color is already defined.");return}t.Color=n,t.Color.prototype={_tryParsingColor:function(e){var t;e in n.colorNameMap&&(e=n.colorNameMap[e]);if(e==="transparent"){this.setSource([255,255,255,0]);return}t=n.sourceFromHex(e),t||(t=n.sourceFromRgb(e)),t||(t=n.sourceFromHsl(e)),t&&this.setSource(t)},_rgbToHsl:function(e,n,r){e/=255,n/=255,r/=255;var i,s,o,u=t.util.array.max([e,n,r]),a=t.util.array.min([e,n,r]);o=(u+a)/2;if(u===a)i=s=0;else{var f=u-a;s=o>.5?f/(2-u-a):f/(u+a);switch(u){case e:i=(n-r)/f+(n']:this.type==="radial"&&(r=["']);for(var i=0;i');return r.push(this.type==="linear"?"":""),r.join("")},toLive:function(e){var t;if(!this.type)return;this.type==="linear"?t=e.createLinearGradient(this.coords.x1,this.coords.y1,this.coords.x2,this.coords.y2):this.type==="radial"&&(t=e.createRadialGradient(this.coords.x1,this.coords.y1,this.coords.r1,this.coords.x2,this.coords.y2,this.coords.r2));for(var n=0,r=this.colorStops.length;n'+''+""},toLive:function(e){var t=typeof this.source=="function"?this.source():this.source;if(!t)return"";if(typeof t.src!="undefined"){if(!t.complete)return"";if(t.naturalWidth===0||t.naturalHeight===0)return""}return e.createPattern(t,this.repeat)}}),function(e){"use strict";var t=e.fabric||(e.fabric={});if(t.Shadow){t.warn("fabric.Shadow is already defined.");return}t.Shadow=t.util.createClass({color:"rgb(0,0,0)",blur:0,offsetX:0,offsetY:0,affectStroke:!1,includeDefaultValues:!0,initialize:function(e){typeof e=="string"&&(e=this._parseShadow(e));for(var n in e)this[n]=e[n];this.id=t.Object.__uid++},_parseShadow:function(e){var n=e.trim(),r=t.Shadow.reOffsetsAndBlur.exec(n)||[],i=n.replace(t.Shadow.reOffsetsAndBlur,"")||"rgb(0,0,0)";return{color:i.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(e){var t="SourceAlpha";return e&&(e.fill===this.color||e.stroke===this.color)&&(t="SourceGraphic"),''+''+''+""+""+''+""+""},toObject:function(){if(this.includeDefaultValues)return{color:this.color,blur:this.blur,offsetX:this.offsetX,offsetY:this.offsetY};var e={},n=t.Shadow.prototype;return this.color!==n.color&&(e.color=this.color),this.blur!==n.blur&&(e.blur=this.blur),this.offsetX!==n.offsetX&&(e.offsetX=this.offsetX),this.offsetY!==n.offsetY&&(e.offsetY=this.offsetY),e}}),t.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 e=fabric.util.object.extend,t=fabric.util.getElementOffset,n=fabric.util.removeFromArray,r=new Error("Could not initialize `canvas` element");fabric.StaticCanvas=fabric.util.createClass({initialize:function(e,t){t||(t={}),this._initStatic(e,t),fabric.StaticCanvas.activeInstance=this},backgroundColor:"",backgroundImage:null,overlayColor:"",overlayImage:null,includeDefaultValues:!0,stateful:!0,renderOnAddRemove:!0,clipTo:null,controlsAboveOverlay:!1,allowTouchScrolling:!1,imageSmoothingEnabled:!0,viewportTransform:[1,0,0,1,0,0],onBeforeScaleRotate:function(){},_initStatic:function(e,t){this._objects=[],this._createLowerCanvas(e),this._initOptions(t),this._setImageSmoothing(),t.overlayImage&&this.setOverlayImage(t.overlayImage,this.renderAll.bind(this)),t.backgroundImage&&this.setBackgroundImage(t.backgroundImage,this.renderAll.bind(this)),t.backgroundColor&&this.setBackgroundColor(t.backgroundColor,this.renderAll.bind(this)),t.overlayColor&&this.setOverlayColor(t.overlayColor,this.renderAll.bind(this)),this.calcOffset()},calcOffset:function(){return this._offset=t(this.lowerCanvasEl),this},setOverlayImage:function(e,t,n){return this.__setBgOverlayImage("overlayImage",e,t,n)},setBackgroundImage:function(e,t,n){return this.__setBgOverlayImage("backgroundImage",e,t,n)},setOverlayColor:function(e,t){return this.__setBgOverlayColor("overlayColor",e,t)},setBackgroundColor:function(e,t){return this.__setBgOverlayColor("backgroundColor",e,t)},_setImageSmoothing:function(){var e=this.getContext();e.imageSmoothingEnabled=this.imageSmoothingEnabled,e.webkitImageSmoothingEnabled=this.imageSmoothingEnabled,e.mozImageSmoothingEnabled=this.imageSmoothingEnabled,e.msImageSmoothingEnabled=this.imageSmoothingEnabled,e.oImageSmoothingEnabled=this.imageSmoothingEnabled},__setBgOverlayImage:function(e,t,n,r){return typeof t=="string"?fabric.util.loadImage(t,function(t){this[e]=new fabric.Image(t,r),n&&n()},this):(this[e]=t,n&&n()),this},__setBgOverlayColor:function(e,t,n){if(t&&t.source){var r=this;fabric.util.loadImage(t.source,function(i){r[e]=new fabric.Pattern({source:i,repeat:t.repeat,offsetX:t.offsetX,offsetY:t.offsetY}),n&&n()})}else this[e]=t,n&&n();return this},_createCanvasElement:function(){var e=fabric.document.createElement("canvas");e.style||(e.style={});if(!e)throw r;return this._initCanvasElement(e),e},_initCanvasElement:function(e){fabric.util.createCanvasElement(e);if(typeof e.getContext=="undefined")throw r},_initOptions:function(e){for(var t in e)this[t]=e[t];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"},_createLowerCanvas:function(e){this.lowerCanvasEl=fabric.util.getById(e)||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(e){return this._setDimension("width",e)},setHeight:function(e){return this._setDimension("height",e)},setDimensions:function(e){for(var t in e)this._setDimension(t,e[t]);return this},_setDimension:function(e,t){return this.lowerCanvasEl[e]=t,this.lowerCanvasEl.style[e]=t+"px",this.upperCanvasEl&&(this.upperCanvasEl[e]=t,this.upperCanvasEl.style[e]=t+"px"),this.cacheCanvasEl&&(this.cacheCanvasEl[e]=t),this.wrapperEl&&(this.wrapperEl.style[e]=t+"px"),this[e]=t,this.calcOffset(),this.renderAll(),this},getZoom:function(){return Math.sqrt(this.viewportTransform[0]*this.viewportTransform[3])},setViewportTransform:function(e){this.viewportTransform=e,this.renderAll();for(var t=0,n=this._objects.length;t"),n.join("")},_setSVGPreamble:function(e,t){t.suppressPreamble||e.push('','\n')},_setSVGHeader:function(e,t){e.push("',"Created with Fabric.js ",fabric.version,"","",fabric.createSVGFontFacesMarkup(this.getObjects()),fabric.createSVGRefElementsMarkup(this),"")},_setSVGObjects:function(e,t){var n=this.getActiveGroup();n&&this.discardActiveGroup();for(var r=0,i=this.getObjects(),s=i.length;r"):this[t]&&t==="overlayColor"&&e.push('")},sendToBack:function(e){return n(this._objects,e),this._objects.unshift(e),this.renderAll&&this.renderAll()},bringToFront:function(e){return n(this._objects,e),this._objects.push(e),this.renderAll&&this.renderAll()},sendBackwards:function(e,t){var r=this._objects.indexOf(e);if(r!==0){var i=this._findNewLowerIndex(e,r,t);n(this._objects,e),this._objects.splice(i,0,e),this.renderAll&&this.renderAll()}return this},_findNewLowerIndex:function(e,t,n){var r;if(n){r=t;for(var i=t-1;i>=0;--i){var s=e.intersectsWithObject(this._objects[i])||e.isContainedWithinObject(this._objects[i])||this._objects[i].isContainedWithinObject(e);if(s){r=i;break}}}else r=t-1;return r},bringForward:function(e,t){var r=this._objects.indexOf(e);if(r!==this._objects.length-1){var i=this._findNewUpperIndex(e,r,t);n(this._objects,e),this._objects.splice(i,0,e),this.renderAll&&this.renderAll()}return this},_findNewUpperIndex:function(e,t,n){var r;if(n){r=t;for(var i=t+1;i"}}),e(fabric.StaticCanvas.prototype,fabric.Observable),e(fabric.StaticCanvas.prototype,fabric.Collection),e(fabric.StaticCanvas.prototype,fabric.DataURLExporter),e(fabric.StaticCanvas,{EMPTY_JSON:'{"objects": [], "background": "white"}',supports:function(e){var t=fabric.util.createCanvasElement();if(!t||!t.getContext)return null;var n=t.getContext("2d");if(!n)return null;switch(e){case"getImageData":return typeof n.getImageData!="undefined";case"setLineDash":return typeof n.setLineDash!="undefined";case"toDataURL":return typeof t.toDataURL!="undefined";case"toDataURLWithQuality":try{return t.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",setShadow:function(e){return this.shadow=new fabric.Shadow(e),this},_setBrushStyles:function(){var e=this.canvas.contextTop;e.strokeStyle=this.color,e.lineWidth=this.width,e.lineCap=this.strokeLineCap,e.lineJoin=this.strokeLineJoin},_setShadow:function(){if(!this.shadow)return;var e=this.canvas.contextTop;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur,e.shadowOffsetX=this.shadow.offsetX,e.shadowOffsetY=this.shadow.offsetY},_resetShadow:function(){var e=this.canvas.contextTop;e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0}}),function(){var e=fabric.util.array.min,t=fabric.util.array.max;fabric.PencilBrush=fabric.util.createClass(fabric.BaseBrush,{initialize:function(e){this.canvas=e,this._points=[]},onMouseDown:function(e){this._prepareForDrawing(e),this._captureDrawingPath(e),this._render()},onMouseMove:function(e){this._captureDrawingPath(e),this.canvas.clearContext(this.canvas.contextTop),this._render()},onMouseUp:function(){this._finalizeAndAddPath()},_prepareForDrawing:function(e){var t=new fabric.Point(e.x,e.y);this._reset(),this._addPoint(t),this.canvas.contextTop.moveTo(t.x,t.y)},_addPoint:function(e){this._points.push(e)},_reset:function(){this._points.length=0,this._setBrushStyles(),this._setShadow()},_captureDrawingPath:function(e){var t=new fabric.Point(e.x,e.y);this._addPoint(t)},_render:function(){var e=this.canvas.contextTop,t=this.canvas.viewportTransform;e.save(),e.transform(t[0],t[1],t[2],t[3],t[4],t[5]),e.beginPath();var n=this._points[0],r=this._points[1];this._points.length===2&&n.x===r.x&&n.y===r.y&&(n.x-=.5,r.x+=.5),e.moveTo(n.x,n.y);for(var i=1,s=this._points.length;in.padding?e.x<0?e.x+=n.padding:e.x-=n.padding:e.x=0,i(e.y)>n.padding?e.y<0?e.y+=n.padding:e.y-=n.padding:e.y=0},_rotateObject:function(e,t){var i=this._currentTransform;if(i.target.get("lockRotation"))return;var s=r(i.ey-i.top,i.ex-i.left),o=r(t-i.top,e-i.left),u=n(o-s+i.theta);u<0&&(u=360+u),i.target.angle=u},setCursor:function(e){this.upperCanvasEl.style.cursor=e},_resetObjectTransform:function(e){e.scaleX=1,e.scaleY=1,e.setAngle(0)},_drawSelection:function(){var e=this.contextTop,t=this._groupSelector,n=t.left,r=t.top,o=i(n),u=i(r);e.fillStyle=this.selectionColor,e.fillRect(t.ex-(n>0?0:-n),t.ey-(r>0?0:-r),o,u),e.lineWidth=this.selectionLineWidth,e.strokeStyle=this.selectionBorderColor;if(this.selectionDashArray.length>1){var a=t.ex+s-(n>0?0:o),f=t.ey+s-(r>0?0:u);e.beginPath(),fabric.util.drawDashedLine(e,a,f,a+o,f,this.selectionDashArray),fabric.util.drawDashedLine(e,a,f+u-1,a+o,f+u-1,this.selectionDashArray),fabric.util.drawDashedLine(e,a,f,a,f+u,this.selectionDashArray),fabric.util.drawDashedLine(e,a+o-1,f,a+o-1,f+u,this.selectionDashArray),e.closePath(),e.stroke()}else e.strokeRect(t.ex+s-(n>0?0:o),t.ey+s-(r>0?0:u),o,u)},_isLastRenderedObject:function(e){return this.controlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay.visible&&this.containsPoint(e,this.lastRenderedObjectWithControlsAboveOverlay)&&this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(this.getPointer(e,!0))},findTarget:function(e,t){if(this.skipTargetFind)return;if(this._isLastRenderedObject(e))return this.lastRenderedObjectWithControlsAboveOverlay;var n=this.getActiveGroup();if(n&&!t&&this.containsPoint(e,n))return n;var r=this._searchPossibleTargets(e);return this._fireOverOutEvents(r),r},_fireOverOutEvents:function(e){e?this._hoveredTarget!==e&&(this.fire("mouse:over",{target:e}),e.fire("mouseover"),this._hoveredTarget&&(this.fire("mouse:out",{target:this._hoveredTarget}),this._hoveredTarget.fire("mouseout")),this._hoveredTarget=e):this._hoveredTarget&&(this.fire("mouse:out",{target:this._hoveredTarget}),this._hoveredTarget.fire("mouseout"),this._hoveredTarget=null)},_checkTarget:function(e,t,n){if(t&&t.visible&&t.evented&&this.containsPoint(e,t)){if(!this.perPixelTargetFind&&!t.perPixelTargetFind||!!t.isEditing)return!0;var r=this.isTargetTransparent(t,n.x,n.y);if(!r)return!0}},_searchPossibleTargets:function(e){var t,n=this.getPointer(e,!0),r=this._objects.length;while(r--)if(this._checkTarget(e,this._objects[r],n)){this.relatedTarget=this._objects[r],t=this._objects[r];break}return t},getPointer:function(t,n,r){r||(r=this.upperCanvasEl);var i=e(t,r),s=r.getBoundingClientRect(),o;return i.x=i.x-this._offset.left,i.y=i.y-this._offset.top,n||(i=fabric.util.transformPoint(i,fabric.util.invertTransform(this.viewportTransform))),s.width===0||s.height===0?o={width:1,height:1}:o={width:r.width/s.width,height:r.height/s.height},{x:i.x*o.width,y:i.y*o.height}},_createUpperCanvas:function(){var e=this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/,"");this.upperCanvasEl=this._createCanvasElement(),fabric.util.addClass(this.upperCanvasEl,"upper-canvas "+e),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(e){var t=this.getWidth()||e.width,n=this.getHeight()||e.height;fabric.util.setStyle(e,{position:"absolute",width:t+"px",height:n+"px",left:0,top:0}),e.width=t,e.height=n,fabric.util.makeElementUnselectable(e)},_copyCanvasStyle:function(e,t){t.style.cssText=e.style.cssText},getSelectionContext:function(){return this.contextTop},getSelectionElement:function(){return this.upperCanvasEl},_setActiveObject:function(e){this._activeObject&&this._activeObject.set("active",!1),this._activeObject=e,e.set("active",!0)},setActiveObject:function(e,t){return this._setActiveObject(e),this.renderAll(),this.fire("object:selected",{target:e,e:t}),e.fire("selected",{e:t}),this},getActiveObject:function(){return this._activeObject},_discardActiveObject:function(){this._activeObject&&this._activeObject.set("active",!1),this._activeObject=null},discardActiveObject:function(e){return this._discardActiveObject(),this.renderAll(),this.fire("selection:cleared",{e:e}),this},_setActiveGroup:function(e){this._activeGroup=e,e&&e.set("active",!0)},setActiveGroup:function(e,t){return this._setActiveGroup(e),e&&(this.fire("object:selected",{target:e,e:t}),e.fire("selected",{e:t})),this},getActiveGroup:function(){return this._activeGroup},_discardActiveGroup:function(){var e=this.getActiveGroup();e&&e.destroy(),this.setActiveGroup(null)},discardActiveGroup:function(e){return this._discardActiveGroup(),this.fire("selection:cleared",{e:e}),this},deactivateAll:function(){var e=this.getObjects(),t=0,n=e.length;for(;t1&&(t=new fabric.Group(t.reverse(),{originX:"center",originY:"center",canvas:this}),t.addWithUpdate(),this.setActiveGroup(t,e),t.saveCoords(),this.fire("selection:created",{target:t}),this.renderAll())},_collectObjects:function(){var n=[],r,i=this._groupSelector.ex,s=this._groupSelector.ey,o=i+this._groupSelector.left,u=s+this._groupSelector.top,a=new fabric.Point(e(i,o),e(s,u)),f=new fabric.Point(t(i,o),t(s,u)),l=i===o&&s===u;for(var c=this._objects.length;c--;){r=this._objects[c];if(!r||!r.selectable||!r.visible)continue;if(r.intersectsWithRect(a,f)||r.isContainedWithinRect(a,f)||r.containsPoint(a)||r.containsPoint(f)){r.set("active",!0),n.push(r);if(l)break}}return n},_maybeGroupObjects:function(e){this.selection&&this._groupSelector&&this._groupSelectedObjects(e);var t=this.getActiveGroup();t&&(t.setObjectsCoords().setCoords(),t.isMoving=!1,this.setCursor(this.defaultCursor)),this._groupSelector=null,this._currentTransform=null}})}(),fabric.util.object.extend(fabric.StaticCanvas.prototype,{toDataURL:function(e){e||(e={});var t=e.format||"png",n=e.quality||1,r=e.multiplier||1,i={left:e.left,top:e.top,width:e.width,height:e.height};return r!==1?this.__toDataURLWithMultiplier(t,n,i,r):this.__toDataURL(t,n,i)},__toDataURL:function(e,t,n){this.renderAll(!0);var r=this.upperCanvasEl||this.lowerCanvasEl,i=this.__getCroppedCanvas(r,n);e==="jpg"&&(e="jpeg");var s=fabric.StaticCanvas.supports("toDataURLWithQuality")?(i||r).toDataURL("image/"+e,t):(i||r).toDataURL("image/"+e);return this.contextTop&&this.clearContext(this.contextTop),this.renderAll(),i&&(i=null),s},__getCroppedCanvas:function(e,t){var n,r,i="left"in t||"top"in t||"width"in t||"height"in t;return i&&(n=fabric.util.createCanvasElement(),r=n.getContext("2d"),n.width=t.width||this.width,n.height=t.height||this.height,r.drawImage(e,-t.left||0,-t.top||0)),n},__toDataURLWithMultiplier:function(e,t,n,r){var i=this.getWidth(),s=this.getHeight(),o=i*r,u=s*r,a=this.getActiveObject(),f=this.getActiveGroup(),l=this.contextTop||this.contextContainer;r>1&&this.setWidth(o).setHeight(u),l.scale(r,r),n.left&&(n.left*=r),n.top&&(n.top*=r),n.width?n.width*=r:r<1&&(n.width=o),n.height?n.height*=r:r<1&&(n.height=u),f?this._tempRemoveBordersControlsFromGroup(f):a&&this.deactivateAll&&this.deactivateAll(),this.renderAll(!0);var c=this.__toDataURL(e,t,n);return this.width=i,this.height=s,l.scale(1/r,1/r),this.setWidth(i).setHeight(s),f?this._restoreBordersControlsOnGroup(f):a&&this.setActiveObject&&this.setActiveObject(a),this.contextTop&&this.clearContext(this.contextTop),this.renderAll(),c},toDataURLWithMultiplier:function(e,t,n){return this.toDataURL({format:e,multiplier:t,quality:n})},_tempRemoveBordersControlsFromGroup:function(e){e.origHasControls=e.hasControls,e.origBorderColor=e.borderColor,e.hasControls=!0,e.borderColor="rgba(0,0,0,0)",e.forEachObject(function(e){e.origBorderColor=e.borderColor,e.borderColor="rgba(0,0,0,0)"})},_restoreBordersControlsOnGroup:function(e){e.hideControls=e.origHideControls,e.borderColor=e.origBorderColor,e.forEachObject(function(e){e.borderColor=e.origBorderColor,delete e.origBorderColor})}}),fabric.util.object.extend(fabric.StaticCanvas.prototype,{loadFromDatalessJSON:function(e,t,n){return this.loadFromJSON(e,t,n)},loadFromJSON:function(e,t,n){if(!e)return;var r=typeof e=="string"?JSON.parse(e):e;this.clear();var i=this;return this._enlivenObjects(r.objects,function(){i._setBgOverlay(r,t)},n),this},_setBgOverlay:function(e,t){var n=this,r={backgroundColor:!1,overlayColor:!1,backgroundImage:!1,overlayImage:!1};if(!e.backgroundImage&&!e.overlayImage&&!e.background&&!e.overlay){t&&t();return}var i=function(){r.backgroundImage&&r.overlayImage&&r.backgroundColor&&r.overlayColor&&(n.renderAll(),t&&t())};this.__setBgOverlay("backgroundImage",e.backgroundImage,r,i),this.__setBgOverlay("overlayImage",e.overlayImage,r,i),this.__setBgOverlay("backgroundColor",e.background,r,i),this.__setBgOverlay("overlayColor",e.overlay,r,i),i()},__setBgOverlay:function(e,t,n,r){var i=this;if(!t){n[e]=!0;return}e==="backgroundImage"||e==="overlayImage"?fabric.Image.fromObject(t,function(t){i[e]=t,n[e]=!0,r&&r()}):this["set"+fabric.util.string.capitalize(e,!0)](t,function(){n[e]=!0,r&&r()})},_enlivenObjects:function(e,t,n){var r=this;if(!e||e.length===0){t&&t();return}var i=this.renderOnAddRemove;this.renderOnAddRemove=!1,fabric.util.enlivenObjects(e,function(e){e.forEach(function(e,t){r.insertAt(e,t,!0)}),r.renderOnAddRemove=i,t&&t()},null,n)},_toDataURL:function(e,t){this.clone(function(n){t(n.toDataURL(e))})},_toDataURLWithMultiplier:function(e,t,n){this.clone(function(r){n(r.toDataURLWithMultiplier(e,t))})},clone:function(e,t){var n=JSON.stringify(this.toJSON(t));this.cloneWithoutData(function( -t){t.loadFromJSON(n,function(){e&&e(t)})})},cloneWithoutData:function(e){var t=fabric.document.createElement("canvas");t.width=this.getWidth(),t.height=this.getHeight();var n=new fabric.Canvas(t);n.clipTo=this.clipTo,this.backgroundImage?(n.setBackgroundImage(this.backgroundImage.src,function(){n.renderAll(),e&&e(n)}),n.backgroundImageOpacity=this.backgroundImageOpacity,n.backgroundImageStretch=this.backgroundImageStretch):e&&e(n)}}),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.toFixed,i=t.util.string.capitalize,s=t.util.degreesToRadians,o=t.StaticCanvas.supports("setLineDash");if(t.Object)return;t.Object=t.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,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:"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,stateProperties:"top left width height scaleX scaleY flipX flipY originX originY transformMatrix stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit angle opacity fill fillRule shadow clipTo visible backgroundColor".split(" "),initialize:function(e){e&&this.setOptions(e)},_initGradient:function(e){e.fill&&e.fill.colorStops&&!(e.fill instanceof t.Gradient)&&this.set("fill",new t.Gradient(e.fill))},_initPattern:function(e){e.fill&&e.fill.source&&!(e.fill instanceof t.Pattern)&&this.set("fill",new t.Pattern(e.fill)),e.stroke&&e.stroke.source&&!(e.stroke instanceof t.Pattern)&&this.set("stroke",new t.Pattern(e.stroke))},_initClipping:function(e){if(!e.clipTo||typeof e.clipTo!="string")return;var n=t.util.getFunctionBody(e.clipTo);typeof n!="undefined"&&(this.clipTo=new Function("ctx",n))},setOptions:function(e){for(var t in e)this.set(t,e[t]);this._initGradient(e),this._initPattern(e),this._initClipping(e)},transform:function(e,t){this.group&&this.group.transform(e,t),e.globalAlpha=this.opacity;var n=t?this._getLeftTopCoords():this.getCenterPoint();e.translate(n.x,n.y),e.rotate(s(this.angle)),e.scale(this.scaleX*(this.flipX?-1:1),this.scaleY*(this.flipY?-1:1))},toObject:function(e){var n=t.Object.NUM_FRACTION_DIGITS,i={type:this.type,originX:this.originX,originY:this.originY,left:r(this.left,n),top:r(this.top,n),width:r(this.width,n),height:r(this.height,n),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,n),strokeDashArray:this.strokeDashArray,strokeLineCap:this.strokeLineCap,strokeLineJoin:this.strokeLineJoin,strokeMiterLimit:r(this.strokeMiterLimit,n),scaleX:r(this.scaleX,n),scaleY:r(this.scaleY,n),angle:r(this.getAngle(),n),flipX:this.flipX,flipY:this.flipY,opacity:r(this.opacity,n),shadow:this.shadow&&this.shadow.toObject?this.shadow.toObject():this.shadow,visible:this.visible,clipTo:this.clipTo&&String(this.clipTo),backgroundColor:this.backgroundColor};return this.includeDefaultValues||(i=this._removeDefaultValues(i)),t.util.populateWithProperties(this,i,e),i},toDatalessObject:function(e){return this.toObject(e)},_removeDefaultValues:function(e){var n=t.util.getKlass(e.type).prototype,r=n.stateProperties;return r.forEach(function(t){e[t]===n[t]&&delete e[t]}),e},toString:function(){return"#"},get:function(e){return this[e]},_setObject:function(e){for(var t in e)this._set(t,e[t])},set:function(e,t){return typeof e=="object"?this._setObject(e):typeof t=="function"&&e!=="clipTo"?this._set(e,t(this.get(e))):this._set(e,t),this},_set:function(e,n){var i=e==="scaleX"||e==="scaleY";return i&&(n=this._constrainScale(n)),e==="scaleX"&&n<0?(this.flipX=!this.flipX,n*=-1):e==="scaleY"&&n<0?(this.flipY=!this.flipY,n*=-1):e==="width"||e==="height"?this.minScaleLimit=r(Math.min(.1,1/Math.max(this.width,this.height)),2):e==="shadow"&&n&&!(n instanceof t.Shadow)&&(n=new t.Shadow(n)),this[e]=n,this},toggle:function(e){var t=this.get(e);return typeof t=="boolean"&&this.set(e,!t),this},setSourcePath:function(e){return this.sourcePath=e,this},getViewportTransform:function(){return this.canvas&&this.canvas.viewportTransform?this.canvas.viewportTransform:[1,0,0,1,0,0]},render:function(e,n){if(this.width===0||this.height===0||!this.visible)return;e.save(),this._setupFillRule(e),this._transform(e,n),this._setStrokeStyles(e),this._setFillStyles(e);var r=this.transformMatrix;r&&this.group&&(e.translate(-this.group.width/2,-this.group.height/2),e.transform(r[0],r[1],r[2],r[3],r[4],r[5])),this._setShadow(e),this.clipTo&&t.util.clipContext(this,e),this._render(e,n),this.clipTo&&e.restore(),this._removeShadow(e),this._restoreFillRule(e),e.restore()},_transform:function(e,t){var n=this.transformMatrix;n&&!this.group&&e.setTransform(n[0],n[1],n[2],n[3],n[4],n[5]),t||this.transform(e)},_setStrokeStyles:function(e){this.stroke&&(e.lineWidth=this.strokeWidth,e.lineCap=this.strokeLineCap,e.lineJoin=this.strokeLineJoin,e.miterLimit=this.strokeMiterLimit,e.strokeStyle=this.stroke.toLive?this.stroke.toLive(e):this.stroke)},_setFillStyles:function(e){this.fill&&(e.fillStyle=this.fill.toLive?this.fill.toLive(e):this.fill)},_renderControls:function(e,n){var r=this.getViewportTransform();e.save();if(this.active&&!n){var i;this.group&&(i=t.util.transformPoint(this.group.getCenterPoint(),r),e.translate(i.x,i.y),e.rotate(s(this.group.angle))),i=t.util.transformPoint(this.getCenterPoint(),r,null!=this.group),this.group&&(i.x*=this.group.scaleX,i.y*=this.group.scaleY),e.translate(i.x,i.y),e.rotate(s(this.angle)),this.drawBorders(e),this.drawControls(e)}e.restore()},_setShadow:function(e){if(!this.shadow)return;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur,e.shadowOffsetX=this.shadow.offsetX,e.shadowOffsetY=this.shadow.offsetY},_removeShadow:function(e){if(!this.shadow)return;e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0},_renderFill:function(e){if(!this.fill)return;this.fill.toLive&&(e.save(),e.translate(-this.width/2+this.fill.offsetX||0,-this.height/2+this.fill.offsetY||0)),this.fillRule==="destination-over"?e.fill("evenodd"):e.fill(),this.fill.toLive&&e.restore(),this.shadow&&!this.shadow.affectStroke&&this._removeShadow(e)},_renderStroke:function(e){if(!this.stroke)return;e.save(),this.strokeDashArray?(1&this.strokeDashArray.length&&this.strokeDashArray.push.apply(this.strokeDashArray,this.strokeDashArray),o?(e.setLineDash(this.strokeDashArray),this._stroke&&this._stroke(e)):this._renderDashedStroke&&this._renderDashedStroke(e),e.stroke()):this._stroke?this._stroke(e):e.stroke(),this._removeShadow(e),e.restore()},clone:function(e,n){return this.constructor.fromObject?this.constructor.fromObject(this.toObject(n),e):new t.Object(this.toObject(n))},cloneAsImage:function(e){var n=this.toDataURL();return t.util.loadImage(n,function(n){e&&e(new t.Image(n))}),this},toDataURL:function(e){e||(e={});var n=t.util.createCanvasElement(),r=this.getBoundingRect();n.width=r.width,n.height=r.height,t.util.wrapElement(n,"div");var i=new t.Canvas(n);e.format==="jpg"&&(e.format="jpeg"),e.format==="jpeg"&&(i.backgroundColor="#fff");var s={active:this.get("active"),left:this.getLeft(),top:this.getTop()};this.set("active",!1),this.setPositionByOrigin(new t.Point(n.width/2,n.height/2),"center","center");var o=this.canvas;i.add(this);var u=i.toDataURL(e);return this.set(s).setCoords(),this.canvas=o,i.dispose(),i=null,u},isType:function(e){return this.type===e},complexity:function(){return 0},toJSON:function(e){return this.toObject(e)},setGradient:function(e,n){n||(n={});var r={colorStops:[]};r.type=n.type||(n.r1||n.r2?"radial":"linear"),r.coords={x1:n.x1,y1:n.y1,x2:n.x2,y2:n.y2};if(n.r1||n.r2)r.coords.r1=n.r1,r.coords.r2=n.r2;for(var i in n.colorStops){var s=new t.Color(n.colorStops[i]);r.colorStops.push({offset:i,color:s.toRgb(),opacity:s.getAlpha()})}return this.set(e,t.Gradient.forObject(this,r))},setPatternFill:function(e){return this.set("fill",new t.Pattern(e))},setShadow:function(e){return this.set("shadow",e?new t.Shadow(e):null)},setColor:function(e){return this.set("fill",e),this},setAngle:function(e){var t=(this.originX!=="center"||this.originY!=="center")&&this.centeredRotation;return t&&this._setOriginToCenter(),this.set("angle",e),t&&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(e,t){t=t||this.canvas.getPointer(e);var n=this.translateToOriginPoint(this.getCenterPoint(),"left","top");return{x:t.x-n.x,y:t.y-n.y}},_setupFillRule:function(e){this.fillRule&&(this._prevFillRule=e.globalCompositeOperation,e.globalCompositeOperation=this.fillRule)},_restoreFillRule:function(e){this.fillRule&&this._prevFillRule&&(e.globalCompositeOperation=this._prevFillRule)}}),t.util.createAccessors(t.Object),t.Object.prototype.rotate=t.Object.prototype.setAngle,n(t.Object.prototype,t.Observable),t.Object.NUM_FRACTION_DIGITS=2,t.Object.__uid=0}(typeof exports!="undefined"?exports:this),function(){var e=fabric.util.degreesToRadians;fabric.util.object.extend(fabric.Object.prototype,{translateToCenterPoint:function(t,n,r){var i=t.x,s=t.y,o=this.stroke?this.strokeWidth:0;return n==="left"?i=t.x+(this.getWidth()+o*this.scaleX)/2:n==="right"&&(i=t.x-(this.getWidth()+o*this.scaleX)/2),r==="top"?s=t.y+(this.getHeight()+o*this.scaleY)/2:r==="bottom"&&(s=t.y-(this.getHeight()+o*this.scaleY)/2),fabric.util.rotatePoint(new fabric.Point(i,s),t,e(this.angle))},translateToOriginPoint:function(t,n,r){var i=t.x,s=t.y,o=this.stroke?this.strokeWidth:0;return n==="left"?i=t.x-(this.getWidth()+o*this.scaleX)/2:n==="right"&&(i=t.x+(this.getWidth()+o*this.scaleX)/2),r==="top"?s=t.y-(this.getHeight()+o*this.scaleY)/2:r==="bottom"&&(s=t.y+(this.getHeight()+o*this.scaleY)/2),fabric.util.rotatePoint(new fabric.Point(i,s),t,e(this.angle))},getCenterPoint:function(){var e=new fabric.Point(this.left,this.top);return this.translateToCenterPoint(e,this.originX,this.originY)},getPointByOrigin:function(e,t){var n=this.getCenterPoint();return this.translateToOriginPoint(n,e,t)},toLocalPoint:function(t,n,r){var i=this.getCenterPoint(),s=this.stroke?this.strokeWidth:0,o,u;return n&&r?(n==="left"?o=i.x-(this.getWidth()+s*this.scaleX)/2:n==="right"?o=i.x+(this.getWidth()+s*this.scaleX)/2:o=i.x,r==="top"?u=i.y-(this.getHeight()+s*this.scaleY)/2:r==="bottom"?u=i.y+(this.getHeight()+s*this.scaleY)/2:u=i.y):(o=this.left,u=this.top),fabric.util.rotatePoint(new fabric.Point(t.x,t.y),i,-e(this.angle)).subtractEquals(new fabric.Point(o,u))},setPositionByOrigin:function(e,t,n){var r=this.translateToCenterPoint(e,t,n),i=this.translateToOriginPoint(r,this.originX,this.originY);this.set("left",i.x),this.set("top",i.y)},adjustPosition:function(t){var n=e(this.angle),r=this.getWidth()/2,i=Math.cos(n)*r,s=Math.sin(n)*r,o=this.getWidth(),u=Math.cos(n)*o,a=Math.sin(n)*o;this.originX==="center"&&t==="left"||this.originX==="right"&&t==="center"?(this.left-=i,this.top-=s):this.originX==="left"&&t==="center"||this.originX==="center"&&t==="right"?(this.left+=i,this.top+=s):this.originX==="left"&&t==="right"?(this.left+=u,this.top+=a):this.originX==="right"&&t==="left"&&(this.left-=u,this.top-=a),this.setCoords(),this.originX=t},_setOriginToCenter:function(){this._originalOriginX=this.originX,this._originalOriginY=this.originY;var e=this.getCenterPoint();this.originX="center",this.originY="center",this.left=e.x,this.top=e.y},_resetOrigin:function(){var e=this.translateToOriginPoint(this.getCenterPoint(),this._originalOriginX,this._originalOriginY);this.originX=this._originalOriginX,this.originY=this._originalOriginY,this.left=e.x,this.top=e.y,this._originalOriginX=null,this._originalOriginY=null},_getLeftTopCoords:function(){return this.translateToOriginPoint(this.getCenterPoint(),"left","center")}})}(),function(){var e=fabric.util.degreesToRadians;fabric.util.object.extend(fabric.Object.prototype,{oCoords:null,intersectsWithRect:function(e,t){var n=this.oCoords,r=new fabric.Point(n.tl.x,n.tl.y),i=new fabric.Point(n.tr.x,n.tr.y),s=new fabric.Point(n.bl.x,n.bl.y),o=new fabric.Point(n.br.x,n.br.y),u=fabric.Intersection.intersectPolygonRectangle([r,i,o,s],e,t);return u.status==="Intersection"},intersectsWithObject:function(e){function t(e){return{tl:new fabric.Point(e.tl.x,e.tl.y),tr:new fabric.Point(e.tr.x,e.tr.y),bl:new fabric.Point(e.bl.x,e.bl.y),br:new fabric.Point(e.br.x,e.br.y)}}var n=t(this.oCoords),r=t(e.oCoords),i=fabric.Intersection.intersectPolygonPolygon([n.tl,n.tr,n.br,n.bl],[r.tl,r.tr,r.br,r.bl]);return i.status==="Intersection"},isContainedWithinObject:function(e){var t=e.getBoundingRect(),n=new fabric.Point(t.left,t.top),r=new fabric.Point(t.left+t.width,t.top+t.height);return this.isContainedWithinRect(n,r)},isContainedWithinRect:function(e,t){var n=this.getBoundingRect();return n.left>=e.x&&n.left+n.width<=t.x&&n.top>=e.y&&n.top+n.height<=t.y},containsPoint:function(e){var t=this._getImageLines(this.oCoords),n=this._findCrossPoints(e,t);return n!==0&&n%2===1},_getImageLines:function(e){return{topline:{o:e.tl,d:e.tr},rightline:{o:e.tr,d:e.br},bottomline:{o:e.br,d:e.bl},leftline:{o:e.bl,d:e.tl}}},_findCrossPoints:function(e,t){var n,r,i,s,o,u,a=0,f;for(var l in t){f=t[l];if(f.o.y=e.y&&f.d.y>=e.y)continue;f.o.x===f.d.x&&f.o.x>=e.x?(o=f.o.x,u=e.y):(n=0,r=(f.d.y-f.o.y)/(f.d.x-f.o.x),i=e.y-n*e.x,s=f.o.y-r*f.o.x,o=-(i-s)/(n-r),u=i+n*o),o>=e.x&&(a+=1);if(a===2)break}return a},getBoundingRectWidth:function(){return this.getBoundingRect().width},getBoundingRectHeight:function(){return this.getBoundingRect().height},getBoundingRect:function(){this.oCoords||this.setCoords();var e=[this.oCoords.tl.x,this.oCoords.tr.x,this.oCoords.br.x,this.oCoords.bl.x],t=fabric.util.array.min(e),n=fabric.util.array.max(e),r=Math.abs(t-n),i=[this.oCoords.tl.y,this.oCoords.tr.y,this.oCoords.br.y,this.oCoords.bl.y],s=fabric.util.array.min(i),o=fabric.util.array.max(i),u=Math.abs(s-o);return{left:t,top:s,width:r,height:u}},getWidth:function(){return this.width*this.scaleX},getHeight:function(){return this.height*this.scaleY},_constrainScale:function(e){return Math.abs(e)1?this.strokeWidth:0,n=e(this.angle),r=this.getViewportTransform(),i=function(e){return fabric.util.transformPoint(e,r)},s=this.width,o=this.height,u=this.strokeLineCap==="round"||this.strokeLineCap==="square",a=this.type==="line"&&this.width===1,f=this.type==="line"&&this.height===1,l=u&&f||this.type!=="line",c=u&&a||this.type!=="line";a?s=t:f&&(o=t),l&&(s+=t),c&&(o+=t),this.currentWidth=s*this.scaleX,this.currentHeight=o*this.scaleY,this.currentWidth<0&&(this.currentWidth=Math.abs(this.currentWidth));var h=Math.sqrt(Math.pow(this.currentWidth/2,2)+Math.pow(this.currentHeight/2,2)),p=Math.atan(isFinite(this.currentHeight/this.currentWidth)?this.currentHeight/this.currentWidth:0),d=Math.cos(p+n)*h,v=Math.sin(p+n)*h,m=Math.sin(n),g=Math.cos(n),y=this.getCenterPoint(),b=new fabric.Point(this.currentWidth,this.currentHeight),w=new fabric.Point(y.x-d,y.y-v),E=new fabric.Point(w.x+b.x*g,w.y+b.x*m),S=new fabric.Point(w.x-b.y*m,w.y+b.y*g),x=new fabric.Point(w.x+b.x/2*g,w.y+b.x/2*m),T=i(w),N=i(E),C=i(new fabric.Point(E.x-b.y*m,E.y+b.y*g)),k=i(S),L=i(new fabric.Point(w.x-b.y/2*m,w.y+b.y/2*g)),A=i(x),O=i(new fabric.Point(E.x-b.y/2*m,E.y+b.y/2*g)),M=i(new fabric.Point(S.x+b.x/2*g,S.y+b.x/2*m)),_=i(new fabric.Point(x.x,x.y)),D=Math.cos(p+n)*this.padding*Math.sqrt(2),P=Math.sin(p+n)*this.padding*Math.sqrt(2);return T=T.add(new fabric.Point(-D,-P)),N=N.add(new fabric.Point(P,-D)),C=C.add(new fabric.Point(D,P)),k=k.add(new fabric.Point(-P,D)),L=L.add(new fabric.Point((-D-P)/2,(-P+D)/2)),A=A.add(new fabric.Point((P-D)/2,-(P+D)/2)),O=O.add(new fabric.Point((P+D)/2,(P-D)/2)),M=M.add(new fabric.Point((D-P)/2,(D+P)/2)),_=_.add(new fabric.Point((P-D)/2,-(P+D)/2)),this.oCoords={tl:T,tr:N,br:C,bl:k,ml:L,mt:A,mr:O,mb:M,mtr:_},this._setCornerCoords&&this._setCornerCoords(),this}})}(),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(e){return this.group?fabric.StaticCanvas.prototype.sendBackwards.call(this.group,this,e):this.canvas.sendBackwards(this,e),this},bringForward:function(e){return this.group?fabric.StaticCanvas.prototype.bringForward.call(this.group,this,e):this.canvas.bringForward(this,e),this},moveTo:function(e){return this.group?fabric.StaticCanvas.prototype.moveTo.call(this.group,this,e):this.canvas.moveTo(this,e),this}}),fabric.util.object.extend(fabric.Object.prototype,{getSvgStyles:function(){var e=this.fill?this.fill.toLive?"url(#SVGID_"+this.fill.id+")":this.fill:"none",t=this.stroke?this.stroke.toLive?"url(#SVGID_"+this.stroke.id+")":this.stroke:"none",n=this.strokeWidth?this.strokeWidth:"0",r=this.strokeDashArray?this.strokeDashArray.join(" "):"",i=this.strokeLineCap?this.strokeLineCap:"butt",s=this.strokeLineJoin?this.strokeLineJoin:"miter",o=this.strokeMiterLimit?this.strokeMiterLimit:"4",u=typeof this.opacity!="undefined"?this.opacity:"1",a=this.visible?"":" visibility: hidden;",f=this.shadow&&this.type!=="text"?"filter: url(#SVGID_"+this.shadow.id+");":"";return["stroke: ",t,"; ","stroke-width: ",n,"; ","stroke-dasharray: ",r,"; ","stroke-linecap: ",i,"; ","stroke-linejoin: ",s,"; ","stroke-miterlimit: ",o,"; ","fill: ",e,"; ","opacity: ",u,";",f,a].join("")},getSvgTransform:function(){var e=fabric.util.toFixed,t=this.getAngle(),n=this.getViewportTransform(),r=fabric.util.transformPoint(this.getCenterPoint(),n),i=fabric.Object.NUM_FRACTION_DIGITS,s="translate("+e(r.x,i)+" "+e(r.y,i)+")",o=t!==0?" rotate("+e(t,i)+")":"",u=this.scaleX===1&&this.scaleY===1&&n[0]===1&&n[3]===1?"":" scale("+e(this.scaleX*n[0],i)+" "+e(this.scaleY*n[3],i)+")",a=this.flipX?"matrix(-1 0 0 1 0 0) ":"",f=this.flipY?"matrix(1 0 0 -1 0 0)":"";return[s,o,u,a,f].join("")},_createBaseSVGMarkup:function(){var e=[];return this.fill&&this.fill.toLive&&e.push(this.fill.toSVG(this,!1)),this.stroke&&this.stroke.toLive&&e.push(this.stroke.toSVG(this,!1)),this.shadow&&e.push(this.shadow.toSVG(this)),e}}),fabric.util.object.extend(fabric.Object.prototype,{hasStateChanged:function(){return this.stateProperties.some(function(e){return this.get(e)!==this.originalState[e]},this)},saveState:function(e){return this.stateProperties.forEach(function(e){this.originalState[e]=this.get(e)},this),e&&e.stateProperties&&e.stateProperties.forEach(function(e){this.originalState[e]=this.get(e)},this),this},setupState:function(){return this.originalState={},this.saveState(),this}}),function(){var e=fabric.util.degreesToRadians,t=function(){return typeof G_vmlCanvasManager!="undefined"};fabric.util.object.extend(fabric.Object.prototype,{_controlsVisibility:null,_findTargetCorner:function(e){if(!this.hasControls||!this.active)return!1;var t=e.x,n=e.y,r,i;for(var s in this.oCoords){if(!this.isControlVisible(s))continue;if(s==="mtr"&&!this.hasRotatingPoint)continue;if(!(!this.get("lockUniScaling")||s!=="mt"&&s!=="mr"&&s!=="mb"&&s!=="ml"))continue;i=this._getImageLines(this.oCoords[s].corner),r=this._findCrossPoints({x:t,y:n},i);if(r!==0&&r%2===1)return this.__corner=s,s}return!1},_setCornerCoords:function(){var t=this.oCoords,n=e(this.angle),r=e(45-this.angle),i=Math.sqrt(2*Math.pow(this.cornerSize,2))/2,s=i*Math.cos(r),o=i*Math.sin(r),u=Math.sin(n),a=Math.cos(n);t.tl.corner={tl:{x:t.tl.x-o,y:t.tl.y-s},tr:{x:t.tl.x+s,y:t.tl.y-o},bl:{x:t.tl.x-s,y:t.tl.y+o},br:{x:t.tl.x+o,y:t.tl.y+s}},t.tr.corner={tl:{x:t.tr.x-o,y:t.tr.y-s},tr:{x:t.tr.x+s,y:t.tr.y-o},br:{x:t.tr.x+o,y:t.tr.y+s},bl:{x:t.tr.x-s,y:t.tr.y+o}},t.bl.corner={tl:{x:t.bl.x-o,y:t.bl.y-s},bl:{x:t.bl.x-s,y:t.bl.y+o},br:{x:t.bl.x+o,y:t.bl.y+s},tr:{x:t.bl.x+s,y:t.bl.y-o}},t.br.corner={tr:{x:t.br.x+s,y:t.br.y-o},bl:{x:t.br.x-s,y:t.br.y+o},br:{x:t.br.x+o,y:t.br.y+s},tl:{x:t.br.x-o,y:t.br.y-s}},t.ml.corner={tl:{x:t.ml.x-o,y:t.ml.y-s},tr:{x:t.ml.x+s,y:t.ml.y-o},bl:{x:t.ml.x-s,y:t.ml.y+o},br:{x:t.ml.x+o,y:t.ml.y+s}},t.mt.corner={tl:{x:t.mt.x-o,y:t.mt.y-s},tr:{x:t.mt.x+s,y:t.mt.y-o},bl:{x:t.mt.x-s,y:t.mt.y+o},br:{x:t.mt.x+o,y:t.mt.y+s}},t.mr.corner={tl:{x:t.mr.x-o,y:t.mr.y-s},tr:{x:t.mr.x+s,y:t.mr.y-o},bl:{x:t.mr.x-s,y:t.mr.y+o},br:{x:t.mr.x+o,y:t.mr.y+s}},t.mb.corner={tl:{x:t.mb.x-o,y:t.mb.y-s},tr:{x:t.mb.x+s,y:t.mb.y-o},bl:{x:t.mb.x-s,y:t.mb.y+o},br:{x:t.mb.x+o,y:t.mb.y+s}},t.mtr.corner={tl:{x:t.mtr.x-o+u*this.rotatingPointOffset,y:t.mtr.y-s-a*this.rotatingPointOffset},tr:{x:t.mtr.x+s+u*this.rotatingPointOffset,y:t.mtr.y-o-a*this.rotatingPointOffset},bl:{x:t.mtr.x-s+u*this.rotatingPointOffset,y:t.mtr.y+o-a*this.rotatingPointOffset},br:{x:t.mtr.x+o+u*this.rotatingPointOffset,y:t.mtr.y+s-a*this.rotatingPointOffset}}},drawBorders:function(e){if(!this.hasBorders)return this;var t=this.padding,n=t*2,r=this.getViewportTransform();e.save(),e.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1,e.strokeStyle=this.borderColor;var i=1/this._constrainScale(this.scaleX),s=1/this._constrainScale(this.scaleY);e.lineWidth=1/this.borderScaleFactor;var o=this.getWidth(),u=this.getHeight(),a=this.strokeWidth>1?this.strokeWidth:0,f=this.strokeLineCap==="round"||this.strokeLineCap==="square",l=this.type==="line"&&this.width===1,c=this.type==="line"&&this.height===1,h=f&&c||this.type!=="line",p=f&&l||this.type!=="line";l?o=a/i:c&&(u=a/s),h&&(o+=a/i),p&&(u+=a/s);var d=fabric.util.transformPoint(new fabric.Point(o,u),r,!0),v=d.x,m=d.y;this.group&&(v*=this.group.scaleX,m*=this.group.scaleY),e.strokeRect(~~(-(v/2)-t)-.5,~~(-(m/2)-t)-.5,~~(v+n)+1,~~(m+n)+1);if(this.hasRotatingPoint&&this.isControlVisible("mtr")&&!this.get("lockRotation")&&this.hasControls){var g=(this.flipY?m+t*2:-m-t*2)/2;e.beginPath(),e.moveTo(0,g),e.lineTo(0,g+(this.flipY?this.rotatingPointOffset:-this.rotatingPointOffset)),e.closePath(),e.stroke()}return e.restore(),this},drawControls:function(e){if(!this.hasControls)return this;var t=this.cornerSize,n=t/2,r=this.getViewportTransform(),i=this.strokeWidth>1?this.strokeWidth:0,s=this.width,o=this.height,u=this.strokeLineCap==="round"||this.strokeLineCap==="square",a=this.type==="line"&&this.width===1,f=this.type==="line"&&this.height===1,l=u&&f||this.type!=="line",c=u&&a||this.type!=="line";a?s=i:f&&(o=i),l&&(s+=i),c&&(o+=i),s*=this.scaleX,o*=this.scaleY;var h=fabric.util.transformPoint(new fabric.Point(s,o),r,!0),p=h.x,d=h.y,v=-(p/2),m=-(d/2),g=this.padding,y=n,b=n-t,w=this.transparentCorners?"strokeRect":"fillRect";return e.save(),e.lineWidth=1,e.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1,e.strokeStyle=e.fillStyle=this.cornerColor,this._drawControl("tl",e,w,v-y-g,m-y-g),this._drawControl("tr",e,w,v+p-y+g,m-y-g),this._drawControl("bl",e,w,v-y-g,m+d+b+g),this._drawControl("br",e,w,v+p+b+g,m+d+b+g),this.get("lockUniScaling")||(this._drawControl("mt",e,w,v+p/2-y,m-y-g),this._drawControl("mb",e,w,v+p/2-y,m+d+b+g),this._drawControl("mr",e,w,v+p+b+g,m+d/2-y),this._drawControl("ml",e,w,v-y-g,m+d/2-y)),this.hasRotatingPoint&&this._drawControl("mtr",e,w,v+p/2-y,this.flipY?m+d+this.rotatingPointOffset-this.cornerSize/2+g:m-this.rotatingPointOffset-this.cornerSize/2-g),e.restore(),this},_drawControl:function(e,n,r,i,s){var o=this.cornerSize;this.isControlVisible(e)&&(t()||this.transparentCorners||n.clearRect(i,s,o,o),n[r](i,s,o,o))},isControlVisible:function(e){return this._getControlsVisibility()[e]},setControlVisible:function(e,t){return this._getControlsVisibility()[e]=t,this},setControlsVisibility:function(e){e||(e={});for(var t in e)this.setControlVisible(t,e[t]);return this},_getControlsVisibility:function(){return this._controlsVisibility||(this._controlsVisibility={tl:!0,tr:!0,br:!0,bl:!0,ml:!0,mt:!0,mr:!0,mb:!0,mtr:!0}),this._controlsVisibility}})}(),fabric.util.object.extend(fabric.StaticCanvas.prototype,{FX_DURATION:500,fxCenterObjectH:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("left"),endValue:this.getCenter().left,duration:this.FX_DURATION,onChange:function(t){e.set("left",t),s.renderAll(),i()},onComplete:function(){e.setCoords(),r()}}),this},fxCenterObjectV:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("top"),endValue:this.getCenter().top,duration:this.FX_DURATION,onChange:function(t){e.set("top",t),s.renderAll(),i()},onComplete:function(){e.setCoords(),r()}}),this},fxRemove:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("opacity"),endValue:0,duration:this.FX_DURATION,onStart:function(){e.set("active",!1)},onChange:function(t){e.set("opacity",t),s.renderAll(),i()},onComplete:function(){s.remove(e),r()}}),this}}),fabric.util.object.extend(fabric.Object.prototype,{animate:function(){if(arguments[0]&&typeof arguments[0]=="object"){var e=[],t,n;for(t in arguments[0])e.push(t);for(var r=0,i=e.length;r'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Line.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" ")),t.Line.fromElement=function(e,r){var i=t.parseAttributes(e,t.Line.ATTRIBUTE_NAMES),s=[i.x1||0,i.y1||0,i.x2||0,i.y2||0];return new t.Line(s,n(i,r))},t.Line.fromObject=function(e){var n=[e.x1,e.y1,e.x2,e.y2];return new t.Line(n,e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function i(e){return"radius"in e&&e.radius>0}var t=e.fabric||(e.fabric={}),n=Math.PI*2,r=t.util.object.extend;if(t.Circle){t.warn("fabric.Circle is already defined.");return}t.Circle=t.util.createClass(t.Object,{type:"circle",radius:0,initialize:function(e){e=e||{},this.set("radius",e.radius||0),this.callSuper("initialize",e)},_set:function(e,t){return this.callSuper("_set",e,t),e==="radius"&&this.setRadius(t),this},toObject:function(e){return r(this.callSuper("toObject",e),{radius:this.get("radius")})},toSVG:function(e){var t=this._createBaseSVGMarkup();return t.push("'),e?e(t.join("")):t.join("")},_render:function(e,t){e.beginPath(),e.globalAlpha=this.group?e.globalAlpha*this.opacity:this.opacity,e.arc(t?this.left:0,t?this.top:0,this.radius,0,n,!1),this._renderFill(e),this.stroke&&this._renderStroke(e)},getRadiusX:function(){return this.get("radius")*this.get("scaleX")},getRadiusY:function(){return this.get("radius")*this.get("scaleY")},setRadius:function(e){this.radius=e,this.set("width",e*2).set("height",e*2)},complexity:function(){return 1}}),t.Circle.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("cx cy r".split(" ")),t.Circle.fromElement=function(e,n){n||(n={});var s=t.parseAttributes(e,t.Circle.ATTRIBUTE_NAMES);if(!i(s))throw new Error("value of `r` attribute is required and can not be negative");"left"in s||(s.left=0),"top"in s||(s.top=0),"transformMatrix"in s||(s.left-=n.width/2,s.top-=n.height/2);var o=new t.Circle(r(s,n));return o.cx=parseFloat(e.getAttribute("cx"))||0,o.cy=parseFloat(e.getAttribute("cy"))||0,o},t.Circle.fromObject=function(e){return new t.Circle(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={});if(t.Triangle){t.warn("fabric.Triangle is already defined");return}t.Triangle=t.util.createClass(t.Object,{type:"triangle",initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("width",e.width||100).set("height",e.height||100)},_render:function(e){var t=this.width/2,n=this.height/2;e.beginPath(),e.moveTo(-t,n),e.lineTo(0,-n),e.lineTo(t,n),e.closePath(),this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n=this.width/2,r=this.height/2;e.beginPath(),t.util.drawDashedLine(e,-n,r,0,-r,this.strokeDashArray),t.util.drawDashedLine(e,0,-r,n,r,this.strokeDashArray),t.util.drawDashedLine(e,n,r,-n,r,this.strokeDashArray),e.closePath()},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=this.width/2,r=this.height/2,i=[-n+" "+r,"0 "+ -r,n+" "+r].join(",");return t.push("'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Triangle -.fromObject=function(e){return new t.Triangle(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=Math.PI*2,r=t.util.object.extend;if(t.Ellipse){t.warn("fabric.Ellipse is already defined.");return}t.Ellipse=t.util.createClass(t.Object,{type:"ellipse",rx:0,ry:0,initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("rx",e.rx||0),this.set("ry",e.ry||0),this.set("width",this.get("rx")*2),this.set("height",this.get("ry")*2)},toObject:function(e){return r(this.callSuper("toObject",e),{rx:this.get("rx"),ry:this.get("ry")})},toSVG:function(e){var t=this._createBaseSVGMarkup();return t.push("'),e?e(t.join("")):t.join("")},render:function(e,t){if(this.rx===0||this.ry===0)return;return this.callSuper("render",e,t)},_render:function(e,t){e.beginPath(),e.globalAlpha=this.group?e.globalAlpha*this.opacity:this.opacity,e.save(),e.transform(1,0,0,this.ry/this.rx,0,0),e.arc(t?this.left:0,t?this.top*this.rx/this.ry:0,this.rx,0,n,!1),e.restore(),this._renderFill(e),this._renderStroke(e)},complexity:function(){return 1}}),t.Ellipse.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" ")),t.Ellipse.fromElement=function(e,n){n||(n={});var i=t.parseAttributes(e,t.Ellipse.ATTRIBUTE_NAMES);"left"in i||(i.left=0),"top"in i||(i.top=0),"transformMatrix"in i||(i.left-=n.width/2,i.top-=n.height/2);var s=new t.Ellipse(r(i,n));return s.cx=parseFloat(e.getAttribute("cx"))||0,s.cy=parseFloat(e.getAttribute("cy"))||0,s},t.Ellipse.fromObject=function(e){return new t.Ellipse(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function i(e){return e.left=e.left||0,e.top=e.top||0,e}var t=e.fabric||(e.fabric={}),n=t.util.object.extend;if(t.Rect){console.warn("fabric.Rect is already defined");return}var r=t.Object.prototype.stateProperties.concat();r.push("rx","ry","x","y"),t.Rect=t.util.createClass(t.Object,{stateProperties:r,type:"rect",rx:0,ry:0,x:0,y:0,strokeDashArray:null,initialize:function(e){e=e||{},this.callSuper("initialize",e),this._initRxRy(),this.x=e.x||0,this.y=e.y||0},_initRxRy:function(){this.rx&&!this.ry?this.ry=this.rx:this.ry&&!this.rx&&(this.rx=this.ry)},_render:function(e){if(this.width===1&&this.height===1){e.fillRect(0,0,1,1);return}var t=this.rx?Math.min(this.rx,this.width/2):0,n=this.ry?Math.min(this.ry,this.height/2):0,r=this.width,i=this.height,s=-r/2,o=-i/2,u=this.group&&this.group.type==="path-group",a=t!==0||n!==0,f=.4477152502;e.beginPath(),e.globalAlpha=u?e.globalAlpha*this.opacity:this.opacity,this.transformMatrix&&u&&e.translate(this.width/2+this.x,this.height/2+this.y),!this.transformMatrix&&u&&e.translate(-this.group.width/2+this.width/2+this.x,-this.group.height/2+this.height/2+this.y),e.moveTo(s+t,o),e.lineTo(s+r-t,o),a&&e.bezierCurveTo(s+r-f*t,o,s+r,o+f*n,s+r,o+n),e.lineTo(s+r,o+i-n),a&&e.bezierCurveTo(s+r,o+i-f*n,s+r-f*t,o+i,s+r-t,o+i),e.lineTo(s+t,o+i),a&&e.bezierCurveTo(s+f*t,o+i,s,o+i-f*n,s,o+i-n),e.lineTo(s,o+n),a&&e.bezierCurveTo(s,o+f*n,s+f*t,o,s+t,o),e.closePath(),this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n=-this.width/2,r=-this.height/2,i=this.width,s=this.height;e.beginPath(),t.util.drawDashedLine(e,n,r,n+i,r,this.strokeDashArray),t.util.drawDashedLine(e,n+i,r,n+i,r+s,this.strokeDashArray),t.util.drawDashedLine(e,n+i,r+s,n,r+s,this.strokeDashArray),t.util.drawDashedLine(e,n,r+s,n,r,this.strokeDashArray),e.closePath()},_normalizeLeftTopProperties:function(e){return"left"in e&&this.set("left",e.left+this.getWidth()/2),this.set("x",e.left||0),"top"in e&&this.set("top",e.top+this.getHeight()/2),this.set("y",e.top||0),this},toObject:function(e){var t=n(this.callSuper("toObject",e),{rx:this.get("rx")||0,ry:this.get("ry")||0,x:this.get("x"),y:this.get("y")});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=this._createBaseSVGMarkup();return t.push("'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Rect.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" ")),t.Rect.fromElement=function(e,r){if(!e)return null;var s=t.parseAttributes(e,t.Rect.ATTRIBUTE_NAMES);s=i(s);var o=new t.Rect(n(r?t.util.object.clone(r):{},s));return o._normalizeLeftTopProperties(s),o},t.Rect.fromObject=function(e){return new t.Rect(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.toFixed;if(t.Polyline){t.warn("fabric.Polyline is already defined");return}t.Polyline=t.util.createClass(t.Object,{type:"polyline",points:null,initialize:function(e,t,n){t=t||{},this.set("points",e),this.callSuper("initialize",t),this._calcDimensions(n)},_calcDimensions:function(e){return t.Polygon.prototype._calcDimensions.call(this,e)},toObject:function(e){return t.Polygon.prototype.toObject.call(this,e)},toSVG:function(e){var t=[],r=this._createBaseSVGMarkup();for(var i=0,s=this.points.length;i'),e?e(r.join("")):r.join("")},_render:function(e){var t;e.beginPath(),e.moveTo(this.points[0].x,this.points[0].y);for(var n=0,r=this.points.length;n'),e?e(n.join("")):n.join("")},_render:function(e){var t;e.beginPath(),e.globalAlpha=this.group?e.globalAlpha*this.opacity:this.opacity,e.moveTo(this.points[0].x,this.points[0].y);for(var n=0,r=this.points.length;n"},toObject:function(e){var t=i(this.callSuper("toObject",e),{path:this.path.map(function(e){return e.slice()}),pathOffset:this.pathOffset});return this.sourcePath&&(t.sourcePath=this.sourcePath),this.transformMatrix&&(t.transformMatrix=this.transformMatrix),t},toDatalessObject:function(e){var t=this.toObject(e);return this.sourcePath&&(t.path=this.sourcePath),delete t.sourcePath,t},toSVG:function(e){var t=[],n=this._createBaseSVGMarkup();for(var r=0,i=this.path.length;r',"",""),e?e(n.join("")):n.join("")},complexity:function(){return this.path.length},_parsePath:function(){var e=[],t=[],n,r,i=/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/ig,s,o;for(var f=0,l,c=this.path.length;fv)for(var g=1,y=l.length;g"];for(var r=0,i=t.length;r"),e?e(n.join("")):n.join("")},toString:function(){return"#"},isSameColor:function(){var e=(this.getObjects()[0].get("fill")||"").toLowerCase();return this.getObjects().every(function(t){return(t.get("fill")||"").toLowerCase()===e})},complexity:function(){return this.paths.reduce(function(e,t){return e+(t&&t.complexity?t.complexity():0)},0)},getObjects:function(){return this.paths}}),t.PathGroup.fromObject=function(e,n){typeof e.paths=="string"?t.loadSVGFromURL(e.paths,function(r){var i=e.paths;delete e.paths;var s=t.util.groupSVGElements(r,e,i);n(s)}):t.util.enlivenObjects(e.paths,function(r){delete e.paths,n(new t.PathGroup(r,e))})},t.PathGroup.async=!0}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.array.min,i=t.util.array.max,s=t.util.array.invoke;if(t.Group)return;var o={lockMovementX:!0,lockMovementY:!0,lockRotation:!0,lockScalingX:!0,lockScalingY:!0,lockUniScaling:!0};t.Group=t.util.createClass(t.Object,t.Collection,{type:"group",initialize:function(e,t){t=t||{},this._objects=e||[];for(var r=this._objects.length;r--;)this._objects[r].group=this;this.originalState={},this.callSuper("initialize"),this._calcBounds(),this._updateObjectsCoords(),t&&n(this,t),this._setOpacityIfSame(),this.setCoords(),this.saveCoords()},_updateObjectsCoords:function(){this.forEachObject(this._updateObjectCoords,this)},_updateObjectCoords:function(e){var t=e.getLeft(),n=e.getTop();e.set({originalLeft:t,originalTop:n,left:t-this.left,top:n-this.top}),e.setCoords(),e.__origHasControls=e.hasControls,e.hasControls=!1},toString:function(){return"#"},addWithUpdate:function(e){return this._restoreObjectsState(),e&&(this._objects.push(e),e.group=this),this.forEachObject(this._setObjectActive,this),this._calcBounds(),this._updateObjectsCoords(),this},_setObjectActive:function(e){e.set("active",!0),e.group=this},removeWithUpdate:function(e){return this._moveFlippedObject(e),this._restoreObjectsState(),this.forEachObject(this._setObjectActive,this),this.remove(e),this._calcBounds(),this._updateObjectsCoords(),this},_onObjectAdded:function(e){e.group=this},_onObjectRemoved:function(e){delete e.group,e.set("active",!1)},delegatedProperties:{fill:!0,opacity:!0,fontFamily:!0,fontWeight:!0,fontSize:!0,fontStyle:!0,lineHeight:!0,textDecoration:!0,textAlign:!0,backgroundColor:!0},_set:function(e,t){if(e in this.delegatedProperties){var n=this._objects.length;this[e]=t;while(n--)this._objects[n].set(e,t)}else this[e]=t},toObject:function(e){return n(this.callSuper("toObject",e),{objects:s(this._objects,"toObject",e)})},render:function(e){if(!this.visible)return;e.save(),this.clipTo&&t.util.clipContext(this,e);for(var n=0,r=this._objects.length;n'];for(var n=0,r=this._objects.length;n"),e?e(t.join("")):t.join("")},get:function(e){if(e in o){if(this[e])return this[e];for(var t=0,n=this._objects.length;t','");if(this.stroke||this.strokeDashArray){var n=this.fill;this.fill=null,t.push("'),this.fill=n}return t.push(""),e?e(t.join("")):t.join("")},getSrc:function(){if(this.getElement())return this.getElement().src||this.getElement()._src},toString:function(){return'#'},clone:function(e,t){this.constructor.fromObject(this.toObject(t),e)},applyFilters:function(e){if(!this._originalElement)return;if(this.filters.length===0){this._element=this._originalElement,e&&e();return}var t=this._originalElement,n=fabric.util.createCanvasElement(),r=fabric.util.createImage(),i=this;return n.width=t.width,n.height=t.height,n.getContext("2d").drawImage(t,0,0,t.width,t.height),this.filters.forEach(function(e){e&&e.applyTo(n)}),r.width=t.width,r.height=t.height,fabric.isLikelyNode?(r.src=n.toBuffer(undefined,fabric.Image.pngCompression),i._element=r,e&&e()):(r.onload=function(){i._element=r,e&&e(),r.onload=n=t=null},r.src=n.toDataURL("image/png")),this},_render:function(e){this._element&&e.drawImage(this._element,-this.width/2,-this.height/2,this.width,this.height)},_resetWidthHeight:function(){var e=this.getElement();this.set("width",e.width),this.set("height",e.height)},_initElement:function(e){this.setElement(fabric.util.getById(e)),fabric.util.addClass(this.getElement(),fabric.Image.CSS_CANVAS)},_initConfig:function(e){e||(e={}),this.setOptions(e),this._setWidthHeight(e),this._element&&this.crossOrigin&&(this._element.crossOrigin=this.crossOrigin)},_initFilters:function(e,t){e.filters&&e.filters.length?fabric.util.enlivenObjects(e.filters,function(e){t&&t(e)},"fabric.Image.filters"):t&&t()},_setWidthHeight:function(e){this.width="width"in e?e.width:this.getElement()?this.getElement().width||0:0,this.height="height"in e?e.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(e,t){fabric.util.loadImage(e.src,function(n){fabric.Image.prototype._initFilters.call(e,e,function(r){e.filters=r||[];var i=new fabric.Image(n,e);t&&t(i)})},null,e.crossOrigin)},fabric.Image.fromURL=function(e,t,n){fabric.util.loadImage(e,function(e){t(new fabric.Image(e,n))},null,n&&n.crossOrigin)},fabric.Image.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y width height xlink:href".split(" ")),fabric.Image.fromElement=function(e,n,r){var i=fabric.parseAttributes(e,fabric.Image.ATTRIBUTE_NAMES);fabric.Image.fromURL(i["xlink:href"],n,t(r?fabric.util.object.clone(r):{},i))},fabric.Image.async=!0,fabric.Image.pngCompression=1}(typeof exports!="undefined"?exports:this),fabric.util.object.extend(fabric.Object.prototype,{_getAngleValueForStraighten:function(){var e=this.getAngle()%360;return e>0?Math.round((e-1)/90)*90:Math.round(e/90)*90},straighten:function(){return this.setAngle(this._getAngleValueForStraighten()),this},fxStraighten:function(e){e=e||{};var t=function(){},n=e.onComplete||t,r=e.onChange||t,i=this;return fabric.util.animate({startValue:this.get("angle"),endValue:this._getAngleValueForStraighten(),duration:this.FX_DURATION,onChange:function(e){i.setAngle(e),r()},onComplete:function(){i.setCoords(),n()},onStart:function(){i.set("active",!1)}}),this}}),fabric.util.object.extend(fabric.StaticCanvas.prototype,{straightenObject:function(e){return e.straighten(),this.renderAll(),this},fxStraightenObject:function(e){return e.fxStraighten({onChange:this.renderAll.bind(this)}),this}}),fabric.Image.filters=fabric.Image.filters||{},fabric.Image.filters.BaseFilter=fabric.util.createClass({type:"BaseFilter",toObject:function(){return{type:this.type}},toJSON:function(){return this.toObject()}}),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend;t.Image.filters.Brightness=t.util.createClass(t.Image.filters.BaseFilter,{type:"Brightness",initialize:function(e){e=e||{},this.brightness=e.brightness||0},applyTo:function(e){var t=e.getContext("2d"),n=t.getImageData(0,0,e.width,e.height),r=n.data,i=this.brightness;for(var s=0,o=r.length;sa||C<0||C>u)continue;var k=(N*u+C)*4,L=t[x*i+T];b+=o[k]*L,w+=o[k+1]*L,E+=o[k+2]*L,S+=o[k+3]*L}h[y]=b,h[y+1]=w,h[y+2]=E,h[y+3]=S+p*(255-S)}n.putImageData(c,0,0)},toObject:function(){return n(this.callSuper("toObject"),{opaque:this.opaque,matrix:this.matrix})}}),t.Image.filters.Convolute.fromObject=function(e){return new t.Image.filters.Convolute(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend;t.Image.filters.GradientTransparency=t.util.createClass(t.Image.filters.BaseFilter,{type:"GradientTransparency",initialize:function(e){e=e||{},this.threshold=e.threshold||100},applyTo:function(e){var t=e.getContext("2d"),n=t.getImageData(0,0,e.width,e.height),r=n.data,i=this.threshold,s=r.length;for(var o=0,u=r.length;o-1?e.channel:0},applyTo:function(e){if(!this.mask)return;var n=e.getContext("2d"),r=n.getImageData(0,0,e.width,e.height),i=r.data,s=this.mask.getElement(),o=t.util.createCanvasElement(),u=this.channel,a,f=r.width*r.height*4;o.width=s.width,o.height=s.height,o.getContext("2d").drawImage(s,0,0,s.width,s.height);var l=o.getContext("2d").getImageData(0,0,s.width,s.height),c=l.data;for(a=0;ao&&f>o&&l>o&&u(a-f)'},_render:function(e){var t=this.group&&this.group.type==="path-group";t&&!this.transformMatrix?e.translate(-this.group.width/2+this.left,-this.group.height/2+this.top):t&&this.transformMatrix&&e.translate(-this.group.width/2,-this.group.height/2),typeof Cufon=="undefined"||this.useNative===!0?this._renderViaNative(e):this._renderViaCufon(e)},_renderViaNative:function(e){var n=this.text.split(this._reNewline);this.transform(e,t.isLikelyNode),this._setTextStyles(e),this.width=this._getTextWidth(e,n),this.height=this._getTextHeight(e,n),this.clipTo&&t.util.clipContext(this,e),this._renderTextBackground(e,n),this._translateForTextAlign(e),this._renderText(e,n),this.textAlign!=="left"&&this.textAlign!=="justify"&&e.restore(),this._renderTextDecoration(e,n),this.clipTo&&e.restore(),this._setBoundaries(e,n),this._totalLineHeight=0},_renderText:function(e,t){e.save(),this._setShadow(e),this._renderTextFill(e,t),this._renderTextStroke(e,t),this._removeShadow(e),e.restore()},_translateForTextAlign:function(e){this.textAlign!=="left"&&this.textAlign!=="justify"&&(e.save(),e.translate(this.textAlign==="center"?this.width/2:this.width,0))},_setBoundaries:function(e,t){this._boundaries=[];for(var n=0,r=t.length;nn&&(n=s)}return n},_renderChars:function(e,t,n,r,i){t[e](n,r,i)},_renderTextLine:function(e,t,n,r,i,s){i-=this.fontSize/4;if(this.textAlign!=="justify"){this._renderChars(e,t,n,r,i,s);return}var o=t.measureText(n).width,u=this.width;if(u>o){var a=n.split(/\s+/),f=t.measureText(n.replace(/\s+/g,"")).width,l=u-f,c=a.length-1,h=l/c,p=0;for(var d=0,v=a.length;d-1&&i(this.fontSize*this.lineHeight),this.textDecoration.indexOf("line-through")>-1&&i(this.fontSize*this.lineHeight-this.fontSize/2),this.textDecoration.indexOf("overline")>-1&&i(this.fontSize*this.lineHeight-this.fontSize)},_getFontDeclaration:function(){return[t.isLikelyNode?this.fontWeight:this.fontStyle,t.isLikelyNode?this.fontStyle:this.fontWeight,this.fontSize+"px",t.isLikelyNode?'"'+this.fontFamily+'"':this.fontFamily].join(" ")},render:function(e){if(!this.visible)return;e.save();var t=this.transformMatrix;t&&(!this.group||this.group.type==="path-group")&&e.transform(t[0],t[1],t[2],t[3],t[4],t[5]),this._render(e),e.restore()},toObject:function(e){var t=n(this.callSuper("toObject",e),{text:this.text,fontSize:this.fontSize,fontWeight:this.fontWeight,fontFamily:this.fontFamily,fontStyle:this.fontStyle,lineHeight:this.lineHeight,textDecoration:this.textDecoration,textAlign:this.textAlign,path:this.path,textBackgroundColor:this.textBackgroundColor,useNative:this.useNative});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=[],n=this.text.split(this._reNewline),r=this._getSVGLeftTopOffsets(n),i=this._getSVGTextAndBg(r.lineTop,r.textLeft,n),s=this._getSVGShadows(r.lineTop,n);return r.textTop+=this._fontAscent?this._fontAscent/5*this.lineHeight:0,this._wrapSVGTextAndBg(t,i,s,r),e?e(t.join("")):t.join("")},_getSVGLeftTopOffsets:function(e){var t=this.useNative?this.fontSize*this.lineHeight:-this._fontAscent-this._fontAscent/5*this.lineHeight,n=-(this.width/2),r=this.useNative?this.fontSize-1:this.height/2-e.length*this.fontSize-this._totalLineHeight;return{textLeft:n,textTop:r,lineTop:t}},_wrapSVGTextAndBg:function(e,t,n,r){e.push('',t.textBgRects.join(""),"',n.join(""),t.textSpans.join(""),"","")},_getSVGShadows:function(e,n){var r=[],s,o,u=1;if(!this.shadow||!this._boundaries)return r;for(s=0,o=n.length;s",t.util.string.escapeXml(n[s]),""),u=1}else u++;return r},_getSVGTextAndBg:function(e,t,n){var r=[],i=[],s=1;this._setSVGBg(i);for(var o=0,u=n.length;o",t.util.string.escapeXml(e),"")},_setSVGTextLineBg:function(e,t,n,r){e.push("')},_setSVGBg:function(e){this.backgroundColor&&this._boundaries&&e.push("')},_getFillAttributes:function(e){var n=e&&typeof e=="string"?new t.Color(e):"";return!n||!n.getSource()||n.getAlpha()===1?'fill="'+e+'"':'opacity="'+n.getAlpha()+'" fill="'+n.setAlpha(1).toRgb()+'"'},_set:function(e,t){e==="fontFamily"&&this.path&&(this.path=this.path.replace(/(.*?)([^\/]*)(\.font\.js)/,"$1"+t+"$3")),this.callSuper("_set",e,t),e in this._dimensionAffectingProps&&(this._initDimensions(),this.setCoords())},complexity:function(){return 1}}),t.Text.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x y dx dy font-family font-style font-weight font-size text-decoration text-anchor".split(" ")),t.Text.DEFAULT_SVG_FONT_SIZE=16,t.Text.fromElement=function(e,n){if(!e)return null;var r=t.parseAttributes(e,t.Text.ATTRIBUTE_NAMES);n=t.util.object.extend(n?t.util.object.clone(n):{},r),"dx"in r&&(n.left+=r.dx),"dy"in r&&(n.top+=r.dy),"fontSize"in n||(n.fontSize=t.Text.DEFAULT_SVG_FONT_SIZE),n.originX||(n.originX="center");var i=new t.Text(e.textContent,n);return i.set({left:i.getLeft()+i.getWidth()/2,top:i.getTop()-i.getHeight()/2}),i},t.Text.fromObject=function(e){return new t.Text(e.text,r(e))},t.util.createAccessors(t.Text)}(typeof exports!="undefined"?exports:this),function(){var e=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,_skipFillStrokeCheck:!0,_reSpace:/\s|\n/,_fontSizeFraction:4,_currentCursorOpacity:0,_selectionDirection:null,_abortCursorAnimation:!1,_charWidthsCache:{},initialize:function(e,t){this.styles=t?t.styles||{}:{},this.callSuper("initialize",e,t),this.initBehavior(),fabric.IText.instances.push(this),this.__lineWidths={},this.__lineHeights={},this.__lineOffsets={}},isEmptyStyles:function(){if(!this.styles)return!0;var e=this.styles;for(var t in e)for(var n in e[t])for(var r in e[t][n])return!1;return!0},setSelectionStart:function(e){this.selectionStart!==e&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})),this.selectionStart=e,this.hiddenTextarea&&(this.hiddenTextarea.selectionStart=e)},setSelectionEnd:function(e){this.selectionEnd!==e&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})),this.selectionEnd=e,this.hiddenTextarea&&(this.hiddenTextarea.selectionEnd=e)},getSelectionStyles:function(e,t){if(arguments.length===2){var n=[];for(var r=e;r=r.charIndex&&(a!==o||hs&&a-1&&this._renderCharDecorationAtOffset(e,n,r+this.fontSize/this._fontSizeFraction,i,0,this.fontSize/20),u.indexOf("line-through")>-1&&this._renderCharDecorationAtOffset(e,n,r+this.fontSize/this._fontSizeFraction,i,o/2,a/20),u.indexOf("overline")>-1&&this._renderCharDecorationAtOffset(e,n,r,i,s-this.fontSize/this._fontSizeFraction,this.fontSize/20)},_renderCharDecorationAtOffset:function(e,t,n,r,i,s){e.fillRect(t,n-i,r,s)},_renderTextLine:function(e,t,n,r,i,s){i+=this.fontSize/4,this.callSuper("_renderTextLine",e,t,n,r,i,s)},_renderTextDecoration:function(e,t){if(this.isEmptyStyles())return this.callSuper("_renderTextDecoration",e,t)},_renderTextLinesBackground:function(e,t){if(!this.textBackgroundColor&&!this.styles)return;e.save(),this.textBackgroundColor&&(e.fillStyle=this.textBackgroundColor);var n=0,r=this.fontSize/this._fontSizeFraction;for(var i=0,s=t.length;in&&(n=s)}return n},_getHeightOfLine:function(e,t,n){n=n||this.text.split(this._reNewline);var r=this._getHeightOfChar(e,n[t][0],t,0),i=n[t],s=i.split("");for(var o=1,u=s.length;or&&(r=a)}return r*this.lineHeight},_getTextHeight:function(e,t){var n=0;for(var r=0,i=t.length;r-1)t++,n--;return e-t},findWordBoundaryRight:function(e){var t=0,n=e;if(this._reSpace.test(this.text.charAt(n)))while(this._reSpace.test(this.text.charAt(n)))t++,n++;while(/\S/.test(this.text.charAt(n))&&n-1)t++,n--;return e-t},findLineBoundaryRight:function(e){var t=0,n=e;while(!/\n/.test(this.text.charAt(n))&&n0&&nr;s?this.removeStyleObject(s,n+1):this.removeStyleObject(this.get2DCursorLocation(n).charIndex===0,n)}this.text=this.text.slice(0,e)+this.text.slice(t)},insertChars:function(e){var t=this.text.slice(this.selectionStart,this.selectionStart+1)==="\n";this.text=this.text.slice(0,this.selectionStart)+e+this.text.slice(this.selectionEnd),this.selectionStart===this.selectionEnd&&this.insertStyleObjects(e,t,this.copiedStyles),this.selectionStart+=e.length,this.selectionEnd=this.selectionStart,this.canvas&&this.canvas.renderAll().renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this})},insertNewlineStyleObject:function(t,n,r){this.shiftLineStyles(t,1),this.styles[t+1]||(this.styles[t+1]={});var i=this.styles[t][n-1],s={};if(r)s[0]=e(i),this.styles[t+1]=s;else{for(var o in this.styles[t])parseInt(o,10)>=n&&(s[parseInt(o,10)-n]=this.styles[t][o],delete this.styles[t][o]);this.styles[t+1]=s}},insertCharStyleObject:function(t,n,r){var i=this.styles[t],s=e(i);n===0&&!r&&(n=1);for(var o in s){var u=parseInt(o,10);u>=n&&(i[u+1]=s[u])}this.styles[t][n]=r||e(i[n-1])},insertStyleObjects:function(e,t,n){if(this.isEmptyStyles())return;var r=this.get2DCursorLocation(),i=r.lineIndex,s=r.charIndex;this.styles[i]||(this.styles[i]={}),e==="\n"?this.insertNewlineStyleObject(i,s,t):n?this._insertStyles(n):this.insertCharStyleObject(i,s)},_insertStyles:function(e){for(var t=0,n=e.length;tt&&(this.styles[s+n]=r[s])}},removeStyleObject:function(t,n){var r=this.get2DCursorLocation(n),i=r.lineIndex,s=r.charIndex;if(t){var o=this.text.split(this._reNewline),u=o[i-1],a=u?u.length:0;this.styles[i-1]||(this.styles[i-1]={});for(s in this.styles[i])this.styles[i-1][parseInt(s,10)+a]=this.styles[i][s];this.shiftLineStyles(i,-1)}else{var f=this.styles[i];if(f){var l=this.selectionStart===this.selectionEnd?-1:0;delete f[s+l]}var c=e(f);for(var h in c){var p=parseInt(h,10);p>=s&&p!==0&&(f[p-1]=c[p],delete f[p])}}},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(e){this.__newClickTime=+(new Date);var t=this.canvas.getPointer(e.e);this.isTripleClick(t)?(this.fire("tripleclick",e),this._stopEvent(e.e)):this.isDoubleClick(t)&&(this.fire("dblclick",e),this._stopEvent(e.e)),this.__lastLastClickTime=this.__lastClickTime,this.__lastClickTime=this.__newClickTime,this.__lastPointer=t,this.__lastIsEditing=this.isEditing,this.__lastSelected=this.selected},isDoubleClick:function(e){return this.__newClickTime-this.__lastClickTime<500&&this.__lastPointer.x===e.x&&this.__lastPointer.y===e.y&&this.__lastIsEditing},isTripleClick:function(e){return this.__newClickTime-this.__lastClickTime<500&&this.__lastClickTime-this.__lastLastClickTime<500&&this.__lastPointer.x===e.x&&this.__lastPointer.y===e.y},_stopEvent:function(e){e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation()},initCursorSelectionHandlers:function(){this.initSelectedHandler(),this.initMousedownHandler(),this.initMousemoveHandler(),this.initMouseupHandler(),this.initClicks()},initClicks:function(){this.on("dblclick",function(e){this.selectWord(this.getSelectionStartFromPointer(e.e))}),this.on("tripleclick",function(e){this.selectLine(this.getSelectionStartFromPointer(e.e))})},initMousedownHandler:function(){this.on("mousedown",function(e){var t=this.canvas.getPointer(e.e);this.__mousedownX=t.x,this.__mousedownY=t.y,this.__isMousedown=!0,this.hiddenTextarea&&this.canvas&&this.canvas.wrapperEl.appendChild(this.hiddenTextarea),this.selected&&this.setCursorByClick(e.e),this.isEditing&&(this.__selectionStartOnMouseDown=this.selectionStart,this.initDelayedCursor(!0))})},initMousemoveHandler:function(){this.on("mousemove",function(e){if(!this.__isMousedown||!this.isEditing)return;var t=this.getSelectionStartFromPointer(e.e);t>=this.__selectionStartOnMouseDown?(this.setSelectionStart(this.__selectionStartOnMouseDown),this.setSelectionEnd(t)):(this.setSelectionStart(t),this.setSelectionEnd(this.__selectionStartOnMouseDown))})},_isObjectMoved:function(e){var t=this.canvas.getPointer(e);return this.__mousedownX!==t.x||this.__mousedownY!==t.y},initMouseupHandler:function(){this.on("mouseup",function(e){this.__isMousedown=!1;if(this._isObjectMoved(e.e))return;this.__lastSelected&&(this.enterEditing(),this.initDelayedCursor(!0)),this.selected=!0})},setCursorByClick:function(e){var t=this.getSelectionStartFromPointer(e);e.shiftKey?to?0:1,f=r+a;return this.flipX&&(f=i-f),f>this.text.length&&(f=this.text.length),s===i&&f--,f}}),fabric.util.object.extend(fabric.IText.prototype,{initHiddenTextarea:function(){this.hiddenTextarea=fabric.document.createElement("textarea"),this.hiddenTextarea.setAttribute("autocapitalize","off"),this.hiddenTextarea.style.cssText="position: absolute; top: 0; left: -9999px",fabric.document.body.appendChild(this.hiddenTextarea),fabric.util.addListener(this.hiddenTextarea,"keydown",this.onKeyDown.bind(this)),fabric.util.addListener(this.hiddenTextarea,"keypress",this.onKeyPress.bind(this)),fabric.util.addListener(this.hiddenTextarea,"copy",this.copy.bind(this)),fabric.util.addListener(this.hiddenTextarea,"paste",this.paste.bind(this)),!this._clickHandlerInitialized&&this.canvas&&(fabric.util.addListener(this.canvas.upperCanvasEl,"click",this.onClick.bind(this)),this._clickHandlerInitialized=!0)},_keysMap:{8:"removeChars",13:"insertNewline",37:"moveCursorLeft",38:"moveCursorUp",39:"moveCursorRight",40:"moveCursorDown",46:"forwardDelete"},_ctrlKeysMap:{65:"selectAll",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{if(!(e.keyCode in this._ctrlKeysMap&&(e.ctrlKey||e.metaKey)))return;this[this._ctrlKeysMap[e.keyCode]](e)}e.stopPropagation(),this.canvas&&this.canvas.renderAll()},forwardDelete:function(e){this.selectionStart===this.selectionEnd&&this.moveCursorRight(e),this.removeChars(e)},copy:function(e){var t=this.getSelectedText(),n=this._getClipboardData(e);n&&n.setData("text",t),this.copiedText=t,this.copiedStyles=this.getSelectionStyles(this.selectionStart,this.selectionEnd)},paste:function(e){var t=null,n=this._getClipboardData(e);n?t=n.getData("text"):t=this.copiedText,t&&this.insertChars(t)},cut:function(e){if(this.selectionStart===this.selectionEnd)return;this.copy(),this.removeChars(e)},_getClipboardData:function(e){return e&&(e.clipboardData||fabric.window.clipboardData)},onKeyPress:function(e){if(!this.isEditing||e.metaKey||e.ctrlKey||e.keyCode===8||e.keyCode===13)return;this.insertChars(String.fromCharCode(e.which)),e.stopPropagation()},getDownCursorOffset:function(e,t){var n=t?this.selectionEnd:this.selectionStart,r=this.text.split(this._reNewline),i,s,o=this.text.slice(0,n),u=this.text.slice(n),a=o.slice(o.lastIndexOf("\n")+1),f=u.match(/(.*)\n?/)[1],l=(u.match(/.*\n(.*)\n?/)||{})[1]||"",c=this.get2DCursorLocation(n);if(c.lineIndex===r.length-1||e.metaKey)return this.text.length-n;var h=this._getWidthOfLine(this.ctx,c.lineIndex,r);s=this._getLineLeftOffset(h);var p=s,d=c.lineIndex;for(var v=0,m=a.length;vn){f=!0;var d=u-p,v=u,m=Math.abs(d-n),g=Math.abs(v-n);a=gthis.text.length&&(this.selectionStart=this.text.length),this.selectionEnd=this.selectionStart},moveCursorDownWithShift:function(e){if(this._selectionDirection==="left"&&this.selectionStart!==this.selectionEnd){this.selectionStart+=e,this._selectionDirection="left";return}this._selectionDirection="right",this.selectionEnd+=e,this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length)},getUpCursorOffset:function(e,t){var n=t?this.selectionEnd:this.selectionStart,r=this.get2DCursorLocation(n);if(r.lineIndex===0||e.metaKey)return n;var i=this.text.slice(0,n),s=i.slice(i.lastIndexOf("\n")+1),o=(i.match(/\n?(.*)\n.*$/)||{})[1]||"",u=this.text.split(this._reNewline),a,f=this._getWidthOfLine(this.ctx,r.lineIndex,u),l=this._getLineLeftOffset(f),c=l,h=r.lineIndex;for(var p=0,d=s.length;pn){f=!0;var d=u-p,v=u,m=Math.abs(d-n),g=Math.abs(v-n);a=g=this.text.length&&this.selectionEnd>=this.text.length)return;this.abortCursorAnimation(),this._currentCursorOpacity=1,e.shiftKey?this.moveCursorRightWithShift(e):this.moveCursorRightWithoutShift(e),this.initDelayedCursor()},moveCursorRightWithShift:function(e){this._selectionDirection==="left"&&this.selectionStart!==this.selectionEnd?this._moveRight(e,"selectionStart"):(this._selectionDirection="right",this._moveRight(e,"selectionEnd"),this.text.charAt(this.selectionEnd-1)==="\n"&&this.selectionEnd++,this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length))},moveCursorRightWithoutShift:function(e){this._selectionDirection="right",this.selectionStart===this.selectionEnd?(this._moveRight(e,"selectionStart"),this.selectionEnd=this.selectionStart):(this.selectionEnd+=this.getNumNewLinesInSelectedText(),this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length),this.selectionStart=this.selectionEnd)},removeChars:function(e){this.selectionStart===this.selectionEnd?this._removeCharsNearCursor(e):this._removeCharsFromTo(this.selectionStart,this.selectionEnd),this.selectionEnd=this.selectionStart,this._removeExtraneousStyles(),this.canvas&&this.canvas.renderAll().renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this})},_removeCharsNearCursor:function(e){if(this.selectionStart!==0)if(e.metaKey){var t=this.findLineBoundaryLeft(this.selectionStart);this._removeCharsFromTo(t,this.selectionStart),this.selectionStart=t}else if(e.altKey){var n=this.findWordBoundaryLeft(this.selectionStart);this._removeCharsFromTo(n,this.selectionStart),this.selectionStart=n}else{var r=this.text.slice(this.selectionStart-1,this.selectionStart)==="\n";this.removeStyleObject(r),this.selectionStart--,this.text=this.text.slice(0,this.selectionStart)+this.text.slice(this.selectionStart+1)}}}),fabric.util.object.extend(fabric.IText.prototype,{_setSVGTextLineText:function(e,t,n,r,i,s){this.styles[t]?this._setSVGTextLineChars(e,t,n,r,i,s):this.callSuper("_setSVGTextLineText",e,t,n,r,i)},_setSVGTextLineChars:function(e,t,n,r,i,s){var o=t===0||this.useNative?"y":"dy",u=e.split(""),a=0,f=this._getSVGLineLeftOffset(t),l=this._getSVGLineTopOffset(t),c=this._getHeightOfLine(this.ctx,t);for(var h=0,p=u.length;h'].join("")},_createTextCharSpan:function(e,t,n,r,i,s){var o=this.getSvgStyles.call(fabric.util.object.extend({visible:!0,fill:this.fill,stroke:this.stroke,type:"text"},t));return['',fabric.util.string.escapeXml(e),""].join("")}}),function(){function request(e,t,n){var r=URL.parse(e);r.port||(r.port=r.protocol.indexOf("https:")===0?443:80);var i=r.port===443?HTTPS:HTTP,s=i.request({hostname:r.hostname,port:r.port,path:r.path,method:"GET"},function(e){var r="";t&&e.setEncoding(t),e.on("end",function(){n(r)}),e.on("data",function(t){e.statusCode===200&&(r+=t)})});s.on("error",function(e){e.errno===process.ECONNREFUSED?fabric.log("ECONNREFUSED: connection refused to "+r.hostname+":"+r.port):fabric.log(e.message)}),s.end()}function requestFs(e,t){var n=require("fs");n.readFile(e,function(e,n){if(e)throw fabric.log(e),e;t(n)})}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;fabric.util.loadImage=function(e,t,n){function r(r){i.src=new Buffer(r,"binary"),i._src=e,t&&t.call(n,i)}var i=new Image;e&&(e instanceof Buffer||e.indexOf("data")===0)?(i.src=i._src=e,t&&t.call(n,i)):e&&e.indexOf("http")!==0?requestFs(e,r):e?request(e,"binary",r):t&&t.call(n,e)},fabric.loadSVGFromURL=function(e,t,n){e=e.replace(/^\n\s*/,"").replace(/\?.*$/,"").trim(),e.indexOf("http")!==0?requestFs(e,function(e){fabric.loadSVGFromString(e.toString(),t,n)}):request(e,"",function(e){fabric.loadSVGFromString(e,t,n)})},fabric.loadSVGFromString=function(e,t,n){var r=(new DOMParser).parseFromString(e);fabric.parseSVGDocument(r.documentElement,function(e,n){t&&t(e,n)},n)},fabric.util.getScript=function(url,callback){request(url,"",function(body){eval(body),callback&&callback()})},fabric.Image.fromObject=function(e,t){fabric.util.loadImage(e.src,function(n){var r=new fabric.Image(n);r._initConfig(e),r._initFilters(e,function(e){r.filters=e||[],t&&t(r)})})},fabric.createCanvasForNode=function(e,t,n,r){r=r||n;var i=fabric.document.createElement("canvas"),s=new Canvas(e||600,t||600,r);i.style={},i.width=s.width,i.height=s.height;var o=fabric.Canvas||fabric.StaticCanvas,u=new o(i,n);return u.contextContainer=s.getContext("2d"),u.nodeCanvas=s,u.Font=Canvas.Font,u},fabric.StaticCanvas.prototype.createPNGStream=function(){return this.nodeCanvas.createPNGStream()},fabric.StaticCanvas.prototype.createJPEGStream=function(e){return this.nodeCanvas.createJPEGStream(e)};var origSetWidth=fabric.StaticCanvas.prototype.setWidth;fabric.StaticCanvas.prototype.setWidth=function(e){return origSetWidth.call(this,e),this.nodeCanvas.width=e,this},fabric.Canvas&&(fabric.Canvas.prototype.setWidth=fabric.StaticCanvas.prototype.setWidth);var origSetHeight=fabric.StaticCanvas.prototype.setHeight;fabric.StaticCanvas.prototype.setHeight=function(e){return origSetHeight.call(this,e),this.nodeCanvas.height=e,this},fabric.Canvas&&(fabric.Canvas.prototype.setHeight=fabric.StaticCanvas.prototype.setHeight)}(); \ No newline at end of file +/* build: `node build.js modules=ALL exclude=gestures,cufon,json minifier=uglifyjs` *//*! Fabric.js Copyright 2008-2014, Printio (Juriy Zaytsev, Maxim Chernyak) */var fabric=fabric||{version:"1.4.8"};typeof exports!="undefined"&&(exports.fabric=fabric),typeof document!="undefined"&&typeof window!="undefined"?(fabric.document=document,fabric.window=window):(fabric.document=require("jsdom").jsdom(""),fabric.window=fabric.document.createWindow()),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"],fabric.DPI=96,function(){function e(e,t){if(!this.__eventListeners[e])return;t?fabric.util.removeFromArray(this.__eventListeners[e],t):this.__eventListeners[e].length=0}function t(e,t){this.__eventListeners||(this.__eventListeners={});if(arguments.length===1)for(var n in e)this.on(n,e[n]);else this.__eventListeners[e]||(this.__eventListeners[e]=[]),this.__eventListeners[e].push(t);return this}function n(t,n){if(!this.__eventListeners)return;if(arguments.length===0)this.__eventListeners={};else if(arguments.length===1&&typeof arguments[0]=="object")for(var r in t)e.call(this,r,t[r]);else e.call(this,t,n);return this}function r(e,t){if(!this.__eventListeners)return;var n=this.__eventListeners[e];if(!n)return;for(var r=0,i=n.length;r-1},complexity:function(){return this.getObjects().reduce(function(e,t){return e+=t.complexity?t.complexity():0,e},0)}},function(e){var t=Math.sqrt,n=Math.atan2,r=Math.PI/180;fabric.util={removeFromArray:function(e,t){var n=e.indexOf(t);return n!==-1&&e.splice(n,1),e},getRandomInt:function(e,t){return Math.floor(Math.random()*(t-e+1))+e},degreesToRadians:function(e){return e*r},radiansToDegrees:function(e){return e/r},rotatePoint:function(e,t,n){var r=Math.sin(n),i=Math.cos(n);e.subtractEquals(t);var s=e.x*i-e.y*r,o=e.x*r+e.y*i;return(new fabric.Point(s,o)).addEquals(t)},transformPoint:function(e,t,n){return n?new fabric.Point(t[0]*e.x+t[1]*e.y,t[2]*e.x+t[3]*e.y):new fabric.Point(t[0]*e.x+t[1]*e.y+t[4],t[2]*e.x+t[3]*e.y+t[5])},invertTransform:function(e){var t=e.slice(),n=1/(e[0]*e[3]-e[1]*e[2]);t=[n*e[3],-n*e[1],-n*e[2],n*e[0],0,0];var r=fabric.util.transformPoint({x:e[4],y:e[5]},t);return t[4]=-r.x,t[5]=-r.y,t},toFixed:function(e,t){return parseFloat(Number(e).toFixed(t))},parseUnit:function(e){var t=/\D{0,2}$/.exec(e),n=parseFloat(e);switch(t[0]){case"mm":return n*fabric.DPI/25.4;case"cm":return n*fabric.DPI/2.54;case"in":return n*fabric.DPI;case"pt":return n*fabric.DPI/72;case"pc":return n*fabric.DPI/72*12;default:return n}},falseFunction:function(){return!1},getKlass:function(e,t){return e=fabric.util.string.camelize(e.charAt(0).toUpperCase()+e.slice(1)),fabric.util.resolveNamespace(t)[e]},resolveNamespace:function(t){if(!t)return fabric;var n=t.split("."),r=n.length,i=e||fabric.window;for(var s=0;s1?r=new fabric.PathGroup(e,t):r=e[0],typeof n!="undefined"&&r.setSourcePath(n),r},populateWithProperties:function(e,t,n){if(n&&Object.prototype.toString.call(n)==="[object Array]")for(var r=0,i=n.length;rr)r+=u[p++%h],r>l&&(r=l),e[d?"lineTo":"moveTo"](r,0),d=!d;e.restore()},createCanvasElement:function(e){return e||(e=fabric.document.createElement("canvas")),!e.getContext&&typeof G_vmlCanvasManager!="undefined"&&G_vmlCanvasManager.initElement(e),e},createImage:function(){return fabric.isLikelyNode?new(require("canvas").Image):fabric.document.createElement("img")},createAccessors:function(e){var t=e.prototype;for(var n=t.stateProperties.length;n--;){var r=t.stateProperties[n],i=r.charAt(0).toUpperCase()+r.slice(1),s="set"+i,o="get"+i;t[o]||(t[o]=function(e){return new Function('return this.get("'+e+'")')}(r)),t[s]||(t[s]=function(e){return new Function("value",'return this.set("'+e+'", value)')}(r))}},clipContext:function(e,t){t.save(),t.beginPath(),e.clipTo(t),t.clip()},multiplyTransformMatrices:function(e,t){var n=[[e[0],e[2],e[4]],[e[1],e[3],e[5]],[0,0,1]],r=[[t[0],t[2],t[4]],[t[1],t[3],t[5]],[0,0,1]],i=[];for(var s=0;s<3;s++){i[s]=[];for(var o=0;o<3;o++){var u=0;for(var a=0;a<3;a++)u+=n[s][a]*r[a][o];i[s][o]=u}}return[i[0][0],i[1][0],i[0][1],i[1][1],i[0][2],i[1][2]]},getFunctionBody:function(e){return(String(e).match(/function[^{]*\{([\s\S]*)\}/)||{})[1]},normalizePoints:function(e,t){var n=fabric.util.array.min(e,"x"),r=fabric.util.array.min(e,"y");n=n<0?n:0,r=n<0?r:0;for(var i=0,s=e.length;i0&&(t>r?t-=r:t=0,n>r?n-=r:n=0);var i=!0,s=e.getImageData(t,n,r*2||1,r*2||1);for(var o=3,u=s.data.length;o0&&f===0&&(E-=2*Math.PI);var S=Math.ceil(Math.abs(E/(Math.PI*.5+.001))),x=[];for(var T=0;T1&&(h=Math.sqrt(h),t*=h,n*=h);var p=f/t,d=a/t,v=-a/n,m=f/n;return{x0:p*r+d*i,y0:v*r+m*i,x1:p*s+d*o,y1:v*s+m*o,sinTh:a,cosTh:f}}function o(e,i,s,o,u,a,f,l){r=n.call(arguments);if(t[r])return t[r];var c=Math.sin(s),h=Math.cos(s),p=Math.sin(o),d=Math.cos(o),v=l*u,m=-f*a,g=f*u,y=l*a,b=.25*(o-s),w=8/3*Math.sin(b)*Math.sin(b)/Math.sin(b*2),E=e+h-w*c,S=i+c+w*h,x=e+d,T=i+p,N=x+w*p,C=T-w*d;return t[r]=[v*E+m*S,g*E+y*S,v*N+m*C,g*N+y*C,v*x+m*T,g*x+y*T],t[r]}var e={},t={},n=Array.prototype.join,r;fabric.util.drawArc=function(e,t,n,r){var s=r[0],u=r[1],a=r[2],f=r[3],l=r[4],c=r[5],h=r[6],p=i(c,h,s,u,f,l,a,t,n);for(var d=0;d=t})}function r(e,t){return i(e,t,function(e,t){return e>>0;if(n===0)return-1;var r=0;arguments.length>0&&(r=Number(arguments[1]),r!==r?r=0:r!==0&&r!==Number.POSITIVE_INFINITY&&r!==Number.NEGATIVE_INFINITY&&(r=(r>0||-1)*Math.floor(Math.abs(r))));if(r>=n)return-1;var i=r>=0?r:Math.max(n-Math.abs(r),0);for(;i>>0;n>>0;r>>0;n>>0;n>>0;i>>0,n=0,r;if(arguments.length>1)r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n/g,">")}String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^[\s\xA0]+/,"").replace(/[\s\xA0]+$/,"")}),fabric.util.string={camelize:e,capitalize:t,escapeXml:n}}(),function(){var e=Array.prototype.slice,t=Function.prototype.apply,n=function(){};Function.prototype.bind||(Function.prototype.bind=function(r){var i=this,s=e.call(arguments,1),o;return s.length?o=function(){return t.call(i,this instanceof n?this:r,s.concat(e.call(arguments)))}:o=function(){return t.call(i,this instanceof n?this:r,arguments)},n.prototype=this.prototype,o.prototype=new n,o})}(),function(){function i(){}function s(t){var n=this.constructor.superclass.prototype[t];return arguments.length>1?n.apply(this,e.call(arguments,1)):n.call(this)}function o(){function u(){this.initialize.apply(this,arguments)}var n=null,o=e.call(arguments,0);typeof o[0]=="function"&&(n=o.shift()),u.superclass=n,u.subclasses=[],n&&(i.prototype=n.prototype,u.prototype=new i,n.subclasses.push(u));for(var a=0,f=o.length;a-1?e.prototype[i]=function(e){return function(){var n=this.constructor.superclass;this.constructor.superclass=r;var i=t[e].apply(this,arguments);this.constructor.superclass=n;if(e!=="initialize")return i}}(i):e.prototype[i]=t[i],n&&(t.toString!==Object.prototype.toString&&(e.prototype.toString=t.toString),t.valueOf!==Object.prototype.valueOf&&(e.prototype.valueOf=t.valueOf))};fabric.util.createClass=o}(),function(){function t(e){var t=Array.prototype.slice.call(arguments,1),n,r,i=t.length;for(r=0;r-1?s(e,t.match(/opacity:\s*(\d?\.?\d*)/)[1]):e;for(var r in t)if(r==="opacity")s(e,t[r]);else{var i=r==="float"||r==="cssFloat"?typeof n.styleFloat=="undefined"?"cssFloat":"styleFloat":r;n[i]=t[r]}return e}var t=fabric.document.createElement("div"),n=typeof t.style.opacity=="string",r=typeof t.style.filter=="string",i=/alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,s=function(e){return e};n?s=function(e,t){return e.style.opacity=t,e}:r&&(s=function(e,t){var n=e.style;return e.currentStyle&&!e.currentStyle.hasLayout&&(n.zoom=1),i.test(n.filter)?(t=t>=.9999?"":"alpha(opacity="+t*100+")",n.filter=n.filter.replace(i,t)):n.filter+=" alpha(opacity="+t*100+")",e}),fabric.util.setStyle=e}(),function(){function t(e){return typeof e=="string"?fabric.document.getElementById(e):e}function s(e,t){var n=fabric.document.createElement(e);for(var r in t)r==="class"?n.className=t[r]:r==="for"?n.htmlFor=t[r]:n.setAttribute(r,t[r]);return n}function o(e,t){e&&(" "+e.className+" ").indexOf(" "+t+" ")===-1&&(e.className+=(e.className?" ":"")+t)}function u(e,t,n){return typeof t=="string"&&(t=s(t,n)),e.parentNode&&e.parentNode.replaceChild(t,e),t.appendChild(e),t}function a(e,t){var n,r,i=0,s=0,o=fabric.document.documentElement,u=fabric.document.body||{scrollLeft:0,scrollTop:0};r=e;while(e&&e.parentNode&&!n)e=e.parentNode,e!==fabric.document&&fabric.util.getElementStyle(e,"position")==="fixed"&&(n=e),e!==fabric.document&&r!==t&&fabric.util.getElementStyle(e,"position")==="absolute"?(i=0,s=0):e===fabric.document?(i=u.scrollLeft||o.scrollLeft||0,s=u.scrollTop||o.scrollTop||0):(i+=e.scrollLeft||0,s+=e.scrollTop||0);return{left:i,top:s}}function f(e){var t,n=e&&e.ownerDocument,r={left:0,top:0},i={left:0,top:0},s,o={borderLeftWidth:"left",borderTopWidth:"top",paddingLeft:"left",paddingTop:"top"};if(!n)return{left:0,top:0};for(var u in o)i[o[u]]+=parseInt(l(e,u),10)||0;return t=n.documentElement,typeof e.getBoundingClientRect!="undefined"&&(r=e.getBoundingClientRect()),s=fabric.util.getScrollLeftTop(e,null),{left:r.left+s.left-(t.clientLeft||0)+i.left,top:r.top+s.top-(t.clientTop||0)+i.top}}var e=Array.prototype.slice,n,r=function(t){return e.call(t,0)};try{n=r(fabric.document.childNodes)instanceof Array}catch(i){}n||(r=function(e){var t=new Array(e.length),n=e.length;while(n--)t[n]=e[n];return t});var l;fabric.document.defaultView&&fabric.document.defaultView.getComputedStyle?l=function(e,t){return fabric.document.defaultView.getComputedStyle(e,null)[t]}:l=function(e,t){var n=e.style[t];return!n&&e.currentStyle&&(n=e.currentStyle[t]),n},function(){function n(e){return typeof e.onselectstart!="undefined"&&(e.onselectstart=fabric.util.falseFunction),t?e.style[t]="none":typeof e.unselectable=="string"&&(e.unselectable="on"),e}function r(e){return typeof e.onselectstart!="undefined"&&(e.onselectstart=null),t?e.style[t]="":typeof e.unselectable=="string"&&(e.unselectable=""),e}var e=fabric.document.documentElement.style,t="userSelect"in e?"userSelect":"MozUserSelect"in e?"MozUserSelect":"WebkitUserSelect"in e?"WebkitUserSelect":"KhtmlUserSelect"in e?"KhtmlUserSelect":"";fabric.util.makeElementUnselectable=n,fabric.util.makeElementSelectable=r}(),function(){function e(e,t){var n=fabric.document.getElementsByTagName("head")[0],r=fabric.document.createElement("script"),i=!0;r.onload=r.onreadystatechange=function(e){if(i){if(typeof this.readyState=="string"&&this.readyState!=="loaded"&&this.readyState!=="complete")return;i=!1,t(e||fabric.window.event),r=r.onload=r.onreadystatechange=null}},r.src=e,n.appendChild(r)}fabric.util.getScript=e}(),fabric.util.getById=t,fabric.util.toArray=r,fabric.util.makeElement=s,fabric.util.addClass=o,fabric.util.wrapElement=u,fabric.util.getScrollLeftTop=a,fabric.util.getElementOffset=f,fabric.util.getElementStyle=l}(),function(){function e(e,t){return e+(/\?/.test(e)?"&":"?")+t}function n(){}function r(r,i){i||(i={});var s=i.method?i.method.toUpperCase():"GET",o=i.onComplete||function(){},u=t(),a;return u.onreadystatechange=function(){u.readyState===4&&(o(u),u.onreadystatechange=n)},s==="GET"&&(a=null,typeof i.parameters=="string"&&(r=e(r,i.parameters))),u.open(s,r,!0),(s==="POST"||s==="PUT")&&u.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),u.send(a),u}var t=function(){var e=[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 t=e.length;t--;)try{var n=e[t]();if(n)return e[t]}catch(r){}}();fabric.util.request=r}(),fabric.log=function(){},fabric.warn=function(){},typeof console!="undefined"&&["log","warn"].forEach(function(e){typeof console[e]!="undefined"&&console[e].apply&&(fabric[e]=function(){return console[e].apply(console,arguments)})}),function(){function e(e){n(function(t){e||(e={});var r=t||+(new Date),i=e.duration||500,s=r+i,o,u=e.onChange||function(){},a=e.abort||function(){return!1},f=e.easing||function(e,t,n,r){return-n*Math.cos(e/r*(Math.PI/2))+n+t},l="startValue"in e?e.startValue:0,c="endValue"in e?e.endValue:100,h=e.byValue||c-l;e.onStart&&e.onStart(),function p(t){o=t||+(new Date);var c=o>s?i:o-r;if(a()){e.onComplete&&e.onComplete();return}u(f(c,l,h,i));if(o>s){e.onComplete&&e.onComplete();return}n(p)}(r)})}function n(){return t.apply(fabric.window,arguments)}var t=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(e){fabric.window.setTimeout(e,1e3/60)};fabric.util.animate=e,fabric.util.requestAnimFrame=n}(),function(){function e(e,t,n,r){return e','')}var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.string.capitalize,i=t.util.object.clone,s=t.util.toFixed,o=t.util.parseUnit,u=t.util.multiplyTransformMatrices,a={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"},f={stroke:"strokeOpacity",fill:"fillOpacity"};t.parseTransformAttribute=function(){function e(e,t){var n=t[0];e[0]=Math.cos(n),e[1]=Math.sin(n),e[2]=-Math.sin(n),e[3]=Math.cos(n)}function n(e,t){var n=t[0],r=t.length===2?t[1]:t[0];e[0]=n,e[3]=r}function r(e,t){e[2]=t[0]}function i(e,t){e[1]=t[0]}function s(e,t){e[4]=t[0],t.length===2&&(e[5]=t[1])}var o=[1,0,0,1,0,0],u="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",a="(?:\\s+,?\\s*|,\\s*)",f="(?:(skewX)\\s*\\(\\s*("+u+")\\s*\\))",l="(?:(skewY)\\s*\\(\\s*("+u+")\\s*\\))",c="(?:(rotate)\\s*\\(\\s*("+u+")(?:"+a+"("+u+")"+a+"("+u+"))?\\s*\\))",h="(?:(scale)\\s*\\(\\s*("+u+")(?:"+a+"("+u+"))?\\s*\\))",p="(?:(translate)\\s*\\(\\s*("+u+")(?:"+a+"("+u+"))?\\s*\\))",d="(?:(matrix)\\s*\\(\\s*("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+a+"("+u+")"+"\\s*\\))",v="(?:"+d+"|"+p+"|"+h+"|"+c+"|"+f+"|"+l+")",m="(?:"+v+"(?:"+a+v+")*"+")",g="^\\s*(?:"+m+"?)\\s*$",y=new RegExp(g),b=new RegExp(v,"g");return function(u){var a=o.concat(),f=[];if(!u||u&&!y.test(u))return a;u.replace(b,function(u){var l=(new RegExp(v)).exec(u).filter(function(e){return e!==""&&e!=null}),c=l[1],h=l.slice(2).map(parseFloat);switch(c){case"translate":s(a,h);break;case"rotate":h[0]=t.util.degreesToRadians(h[0]),e(a,h);break;case"scale":n(a,h);break;case"skewX":r(a,h);break;case"skewY":i(a,h);break;case"matrix":a=h}f.push(a.concat()),a=o.concat()});var l=f[0];while(f.length>1)f.shift(),l=t.util.multiplyTransformMatrices(l,f[0]);return l}}(),t.parseSVGDocument=function(){function s(e,t){while(e&&(e=e.parentNode))if(t.test(e.nodeName))return!0;return!1}var e=/^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/,n="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",r=new RegExp("^\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*,?"+"\\s*("+n+"+)\\s*"+"$");return function(n,o,u){if(!n)return;var a=new Date;g(n);var f=t.util.toArray(n.getElementsByTagName("*"));if(f.length===0&&t.isLikelyNode){f=n.selectNodes('//*[name(.)!="svg"]');var l=[];for(var c=0,h=f.length;c/i,"")));if(!s||!s.documentElement)return;t.parseSVGDocument(s.documentElement,function(r,i){y.set(e,{objects:t.util.array.invoke(r,"toObject"),options:i}),n(r,i)},r)}e=e.replace(/^\n\s*/,"").trim(),y.has(e,function(r){r?y.get(e,function(e){var t=b(e);n(t.objects,t.options)}):new t.util.request(e,{method:"get",onComplete:i})})},loadSVGFromString:function(e,n,r){e=e.trim();var i;if(typeof DOMParser!="undefined"){var s=new DOMParser;s&&s.parseFromString&&(i=s.parseFromString(e,"text/xml"))}else t.window.ActiveXObject&&(i=new ActiveXObject("Microsoft.XMLDOM"),i.async="false",i.loadXML(e.replace(//i,"")));t.parseSVGDocument(i.documentElement,function(e,t){n(e,t)},r)},createSVGFontFacesMarkup:function(e){var t="";for(var n=0,r=e.length;n',"",""].join("")),t},createSVGRefElementsMarkup:function(e){var t=[];return w(t,e,"backgroundColor"),w(t,e,"overlayColor"),t.join("")}})}(typeof exports!="undefined"?exports:this),fabric.ElementsParser=function(e,t,n,r){this.elements=e,this.callback=t,this.options=n,this.reviver=r},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 e=0,t=this.elements.length;ee.x&&this.y>e.y},gte:function(e){return this.x>=e.x&&this.y>=e.y},lerp:function(e,t){return new n(this.x+(e.x-this.x)*t,this.y+(e.y-this.y)*t)},distanceFrom:function(e){var t=this.x-e.x,n=this.y-e.y;return Math.sqrt(t*t+n*n)},midPointFrom:function(e){return new n(this.x+(e.x-this.x)/2,this.y+(e.y-this.y)/2)},min:function(e){return new n(Math.min(this.x,e.x),Math.min(this.y,e.y))},max:function(e){return new n(Math.max(this.x,e.x),Math.max(this.y,e.y))},toString:function(){return this.x+","+this.y},setXY:function(e,t){this.x=e,this.y=t},setFromPoint:function(e){this.x=e.x,this.y=e.y},swap:function(e){var t=this.x,n=this.y;this.x=e.x,this.y=e.y,e.x=t,e.y=n}}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function n(e){this.status=e,this.points=[]}var t=e.fabric||(e.fabric={});if(t.Intersection){t.warn("fabric.Intersection is already defined");return}t.Intersection=n,t.Intersection.prototype={appendPoint:function(e){this.points.push(e)},appendPoints:function(e){this.points=this.points.concat(e)}},t.Intersection.intersectLineLine=function(e,r,i,s){var o,u=(s.x-i.x)*(e.y-i.y)-(s.y-i.y)*(e.x-i.x),a=(r.x-e.x)*(e.y-i.y)-(r.y-e.y)*(e.x-i.x),f=(s.y-i.y)*(r.x-e.x)-(s.x-i.x)*(r.y-e.y);if(f!==0){var l=u/f,c=a/f;0<=l&&l<=1&&0<=c&&c<=1?(o=new n("Intersection"),o.points.push(new t.Point(e.x+l*(r.x-e.x),e.y+l*(r.y-e.y)))):o=new n}else u===0||a===0?o=new n("Coincident"):o=new n("Parallel");return o},t.Intersection.intersectLinePolygon=function(e,t,r){var i=new n,s=r.length;for(var o=0;o0&&(i.status="Intersection"),i},t.Intersection.intersectPolygonPolygon=function(e,t){var r=new n,i=e.length;for(var s=0;s0&&(r.status="Intersection"),r},t.Intersection.intersectPolygonRectangle=function(e,r,i){var s=r.min(i),o=r.max(i),u=new t.Point(o.x,s.y),a=new t.Point(s.x,o.y),f=n.intersectLinePolygon(s,u,e),l=n.intersectLinePolygon(u,o,e),c=n.intersectLinePolygon(o,a,e),h=n.intersectLinePolygon(a,s,e),p=new n;return p.appendPoints(f.points),p.appendPoints(l.points),p.appendPoints(c.points),p.appendPoints(h.points),p.points.length>0&&(p.status="Intersection"),p}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function n(e){e?this._tryParsingColor(e):this.setSource([0,0,0,1])}function r(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+(t-e)*6*n:n<.5?t:n<2/3?e+(t-e)*(2/3-n)*6:e}var t=e.fabric||(e.fabric={});if(t.Color){t.warn("fabric.Color is already defined.");return}t.Color=n,t.Color.prototype={_tryParsingColor:function(e){var t;e in n.colorNameMap&&(e=n.colorNameMap[e]);if(e==="transparent"){this.setSource([255,255,255,0]);return}t=n.sourceFromHex(e),t||(t=n.sourceFromRgb(e)),t||(t=n.sourceFromHsl(e)),t&&this.setSource(t)},_rgbToHsl:function(e,n,r){e/=255,n/=255,r/=255;var i,s,o,u=t.util.array.max([e,n,r]),a=t.util.array.min([e,n,r]);o=(u+a)/2;if(u===a)i=s=0;else{var f=u-a;s=o>.5?f/(2-u-a):f/(u+a);switch(u){case e:i=(n-r)/f+(n']:this.type==="radial"&&(r=["']);for(var i=0;i');return r.push(this.type==="linear"?"":""),r.join("")},toLive:function(e){var t;if(!this.type)return;this.type==="linear"?t=e.createLinearGradient(this.coords.x1,this.coords.y1,this.coords.x2,this.coords.y2):this.type==="radial"&&(t=e.createRadialGradient(this.coords.x1,this.coords.y1,this.coords.r1,this.coords.x2,this.coords.y2,this.coords.r2));for(var n=0,r=this.colorStops.length;n'+''+""},toLive:function(e){var t=typeof this.source=="function"?this.source():this.source;if(!t)return"";if(typeof t.src!="undefined"){if(!t.complete)return"";if(t.naturalWidth===0||t.naturalHeight===0)return""}return e.createPattern(t,this.repeat)}}),function(e){"use strict";var t=e.fabric||(e.fabric={});if(t.Shadow){t.warn("fabric.Shadow is already defined.");return}t.Shadow=t.util.createClass({color:"rgb(0,0,0)",blur:0,offsetX:0,offsetY:0,affectStroke:!1,includeDefaultValues:!0,initialize:function(e){typeof e=="string"&&(e=this._parseShadow(e));for(var n in e)this[n]=e[n];this.id=t.Object.__uid++},_parseShadow:function(e){var n=e.trim(),r=t.Shadow.reOffsetsAndBlur.exec(n)||[],i=n.replace(t.Shadow.reOffsetsAndBlur,"")||"rgb(0,0,0)";return{color:i.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(e){var t="SourceAlpha";return e&&(e.fill===this.color||e.stroke===this.color)&&(t="SourceGraphic"),''+''+''+""+""+''+""+""},toObject:function(){if(this.includeDefaultValues)return{color:this.color,blur:this.blur,offsetX:this.offsetX,offsetY:this.offsetY};var e={},n=t.Shadow.prototype;return this.color!==n.color&&(e.color=this.color),this.blur!==n.blur&&(e.blur=this.blur),this.offsetX!==n.offsetX&&(e.offsetX=this.offsetX),this.offsetY!==n.offsetY&&(e.offsetY=this.offsetY),e}}),t.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 e=fabric.util.object.extend,t=fabric.util.getElementOffset,n=fabric.util.removeFromArray,r=new Error("Could not initialize `canvas` element");fabric.StaticCanvas=fabric.util.createClass({initialize:function(e,t){t||(t={}),this._initStatic(e,t),fabric.StaticCanvas.activeInstance=this},backgroundColor:"",backgroundImage:null,overlayColor:"",overlayImage:null,includeDefaultValues:!0,stateful:!0,renderOnAddRemove:!0,clipTo:null,controlsAboveOverlay:!1,allowTouchScrolling:!1,imageSmoothingEnabled:!0,viewportTransform:[1,0,0,1,0,0],onBeforeScaleRotate:function(){},_initStatic:function(e,t){this._objects=[],this._createLowerCanvas(e),this._initOptions(t),this._setImageSmoothing(),t.overlayImage&&this.setOverlayImage(t.overlayImage,this.renderAll.bind(this)),t.backgroundImage&&this.setBackgroundImage(t.backgroundImage,this.renderAll.bind(this)),t.backgroundColor&&this.setBackgroundColor(t.backgroundColor,this.renderAll.bind(this)),t.overlayColor&&this.setOverlayColor(t.overlayColor,this.renderAll.bind(this)),this.calcOffset()},calcOffset:function(){return this._offset=t(this.lowerCanvasEl),this},setOverlayImage:function(e,t,n){return this.__setBgOverlayImage("overlayImage",e,t,n)},setBackgroundImage:function(e,t,n){return this.__setBgOverlayImage("backgroundImage",e,t,n)},setOverlayColor:function(e,t){return this.__setBgOverlayColor("overlayColor",e,t)},setBackgroundColor:function(e,t){return this.__setBgOverlayColor("backgroundColor",e,t)},_setImageSmoothing:function(){var e=this.getContext();e.imageSmoothingEnabled=this.imageSmoothingEnabled,e.webkitImageSmoothingEnabled=this.imageSmoothingEnabled,e.mozImageSmoothingEnabled=this.imageSmoothingEnabled,e.msImageSmoothingEnabled=this.imageSmoothingEnabled,e.oImageSmoothingEnabled=this.imageSmoothingEnabled},__setBgOverlayImage:function(e,t,n,r){return typeof t=="string"?fabric.util.loadImage(t,function(t){this[e]=new fabric.Image(t,r),n&&n()},this):(this[e]=t,n&&n()),this},__setBgOverlayColor:function(e,t,n){if(t&&t.source){var r=this;fabric.util.loadImage(t.source,function(i){r[e]=new fabric.Pattern({source:i,repeat:t.repeat,offsetX:t.offsetX,offsetY:t.offsetY}),n&&n()})}else this[e]=t,n&&n();return this},_createCanvasElement:function(){var e=fabric.document.createElement("canvas");e.style||(e.style={});if(!e)throw r;return this._initCanvasElement(e),e},_initCanvasElement:function(e){fabric.util.createCanvasElement(e);if(typeof e.getContext=="undefined")throw r},_initOptions:function(e){for(var t in e)this[t]=e[t];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(e){this.lowerCanvasEl=fabric.util.getById(e)||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(e){return this._setDimension("width",e)},setHeight:function(e){return this._setDimension("height",e)},setDimensions:function(e){for(var t in e)this._setDimension(t,e[t]);return this},_setDimension:function(e,t){return this.lowerCanvasEl[e]=t,this.lowerCanvasEl.style[e]=t+"px",this.upperCanvasEl&&(this.upperCanvasEl[e]=t,this.upperCanvasEl.style[e]=t+"px"),this.cacheCanvasEl&&(this.cacheCanvasEl[e]=t),this.wrapperEl&&(this.wrapperEl.style[e]=t+"px"),this[e]=t,this.calcOffset(),this.renderAll(),this},getZoom:function(){return Math.sqrt(this.viewportTransform[0]*this.viewportTransform[3])},setViewportTransform:function(e){this.viewportTransform=e,this.renderAll();for(var t=0,n=this._objects.length;t"),n.join("")},_setSVGPreamble:function(e,t){t.suppressPreamble||e.push('','\n')},_setSVGHeader:function(e,t){e.push("',"Created with Fabric.js ",fabric.version,"","",fabric.createSVGFontFacesMarkup(this.getObjects()),fabric.createSVGRefElementsMarkup(this),"")},_setSVGObjects:function(e,t){var n=this.getActiveGroup();n&&this.discardActiveGroup();for(var r=0,i=this.getObjects(),s=i.length;r"):this[t]&&t==="overlayColor"&&e.push('")},sendToBack:function(e){return n(this._objects,e),this._objects.unshift(e),this.renderAll&&this.renderAll()},bringToFront:function(e){return n(this._objects,e),this._objects.push(e),this.renderAll&&this.renderAll()},sendBackwards:function(e,t){var r=this._objects.indexOf(e);if(r!==0){var i=this._findNewLowerIndex(e,r,t);n(this._objects,e),this._objects.splice(i,0,e),this.renderAll&&this.renderAll()}return this},_findNewLowerIndex:function(e,t,n){var r;if(n){r=t;for(var i=t-1;i>=0;--i){var s=e.intersectsWithObject(this._objects[i])||e.isContainedWithinObject(this._objects[i])||this._objects[i].isContainedWithinObject(e);if(s){r=i;break}}}else r=t-1;return r},bringForward:function(e,t){var r=this._objects.indexOf(e);if(r!==this._objects.length-1){var i=this._findNewUpperIndex(e,r,t);n(this._objects,e),this._objects.splice(i,0,e),this.renderAll&&this.renderAll()}return this},_findNewUpperIndex:function(e,t,n){var r;if(n){r=t;for(var i=t+1;i"}}),e(fabric.StaticCanvas.prototype,fabric.Observable),e(fabric.StaticCanvas.prototype,fabric.Collection),e(fabric.StaticCanvas.prototype,fabric.DataURLExporter),e(fabric.StaticCanvas,{EMPTY_JSON:'{"objects": [], "background": "white"}',supports:function(e){var t=fabric.util.createCanvasElement();if(!t||!t.getContext)return null;var n=t.getContext("2d");if(!n)return null;switch(e){case"getImageData":return typeof n.getImageData!="undefined";case"setLineDash":return typeof n.setLineDash!="undefined";case"toDataURL":return typeof t.toDataURL!="undefined";case"toDataURLWithQuality":try{return t.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",setShadow:function(e){return this.shadow=new fabric.Shadow(e),this},_setBrushStyles:function(){var e=this.canvas.contextTop;e.strokeStyle=this.color,e.lineWidth=this.width,e.lineCap=this.strokeLineCap,e.lineJoin=this.strokeLineJoin},_setShadow:function(){if(!this.shadow)return;var e=this.canvas.contextTop;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur,e.shadowOffsetX=this.shadow.offsetX,e.shadowOffsetY=this.shadow.offsetY},_resetShadow:function(){var e=this.canvas.contextTop;e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0}}),function(){var e=fabric.util.array.min,t=fabric.util.array.max;fabric.PencilBrush=fabric.util.createClass(fabric.BaseBrush,{initialize:function(e){this.canvas=e,this._points=[]},onMouseDown:function(e){this._prepareForDrawing(e),this._captureDrawingPath(e),this._render()},onMouseMove:function(e){this._captureDrawingPath(e),this.canvas.clearContext(this.canvas.contextTop),this._render()},onMouseUp:function(){this._finalizeAndAddPath()},_prepareForDrawing:function(e){var t=new fabric.Point(e.x,e.y);this._reset(),this._addPoint(t),this.canvas.contextTop.moveTo(t.x,t.y)},_addPoint:function(e){this._points.push(e)},_reset:function(){this._points.length=0,this._setBrushStyles(),this._setShadow()},_captureDrawingPath:function(e){var t=new fabric.Point(e.x,e.y);this._addPoint(t)},_render:function(){var e=this.canvas.contextTop,t=this.canvas.viewportTransform,n=this._points[0],r=this._points[1];e.save(),e.transform(t[0],t[1],t[2],t[3],t[4],t[5]),e.beginPath(),this._points.length===2&&n.x===r.x&&n.y===r.y&&(n.x-=.5,r.x+=.5),e.moveTo(n.x,n.y);for(var i=1,s=this._points.length;in.padding?e.x<0?e.x+=n.padding:e.x-=n.padding:e.x=0,i(e.y)>n.padding?e.y<0?e.y+=n.padding:e.y-=n.padding:e.y=0},_rotateObject:function(e,t){var i=this._currentTransform;if(i.target.get("lockRotation"))return;var s=r(i.ey-i.top,i.ex-i.left),o=r(t-i.top,e-i.left),u=n(o-s+i.theta);u<0&&(u=360+u),i.target.angle=u},setCursor:function(e){this.upperCanvasEl.style.cursor=e},_resetObjectTransform:function(e){e.scaleX=1,e.scaleY=1,e.setAngle(0)},_drawSelection:function(){var e=this.contextTop,t=this._groupSelector,n=t.left,r=t.top,o=i(n),u=i(r);e.fillStyle=this.selectionColor,e.fillRect(t.ex-(n>0?0:-n),t.ey-(r>0?0:-r),o,u),e.lineWidth=this.selectionLineWidth,e.strokeStyle=this.selectionBorderColor;if(this.selectionDashArray.length>1){var a=t.ex+s-(n>0?0:o),f=t.ey+s-(r>0?0:u);e.beginPath(),fabric.util.drawDashedLine(e,a,f,a+o,f,this.selectionDashArray),fabric.util.drawDashedLine(e,a,f+u-1,a+o,f+u-1,this.selectionDashArray),fabric.util.drawDashedLine(e,a,f,a,f+u,this.selectionDashArray),fabric.util.drawDashedLine(e,a+o-1,f,a+o-1,f+u,this.selectionDashArray),e.closePath(),e.stroke()}else e.strokeRect(t.ex+s-(n>0?0:o),t.ey+s-(r>0?0:u),o,u)},_isLastRenderedObject:function(e){return this.controlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay&&this.lastRenderedObjectWithControlsAboveOverlay.visible&&this.containsPoint(e,this.lastRenderedObjectWithControlsAboveOverlay)&&this.lastRenderedObjectWithControlsAboveOverlay._findTargetCorner(this.getPointer(e,!0))},findTarget:function(e,t){if(this.skipTargetFind)return;if(this._isLastRenderedObject(e))return this.lastRenderedObjectWithControlsAboveOverlay;var n=this.getActiveGroup();if(n&&!t&&this.containsPoint(e,n))return n;var r=this._searchPossibleTargets(e);return this._fireOverOutEvents(r),r},_fireOverOutEvents:function(e){e?this._hoveredTarget!==e&&(this.fire("mouse:over",{target:e}),e.fire("mouseover"),this._hoveredTarget&&(this.fire("mouse:out",{target:this._hoveredTarget}),this._hoveredTarget.fire("mouseout")),this._hoveredTarget=e):this._hoveredTarget&&(this.fire("mouse:out",{target:this._hoveredTarget}),this._hoveredTarget.fire("mouseout"),this._hoveredTarget=null)},_checkTarget:function(e,t,n){if(t&&t.visible&&t.evented&&this.containsPoint(e,t)){if(!this.perPixelTargetFind&&!t.perPixelTargetFind||!!t.isEditing)return!0;var r=this.isTargetTransparent(t,n.x,n.y);if(!r)return!0}},_searchPossibleTargets:function(e){var t,n=this.getPointer(e,!0),r=this._objects.length;while(r--)if(this._checkTarget(e,this._objects[r],n)){this.relatedTarget=this._objects[r],t=this._objects[r];break}return t},getPointer:function(t,n,r){r||(r=this.upperCanvasEl);var i=e(t,r),s=r.getBoundingClientRect(),o;return i.x=i.x-this._offset.left,i.y=i.y-this._offset.top,n||(i=fabric.util.transformPoint(i,fabric.util.invertTransform(this.viewportTransform))),s.width===0||s.height===0?o={width:1,height:1}:o={width:r.width/s.width,height:r.height/s.height},{x:i.x*o.width,y:i.y*o.height}},_createUpperCanvas:function(){var e=this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/,"");this.upperCanvasEl=this._createCanvasElement(),fabric.util.addClass(this.upperCanvasEl,"upper-canvas "+e),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(e){var t=this.getWidth()||e.width,n=this.getHeight()||e.height;fabric.util.setStyle(e,{position:"absolute",width:t+"px",height:n+"px",left:0,top:0}),e.width=t,e.height=n,fabric.util.makeElementUnselectable(e)},_copyCanvasStyle:function(e,t){t.style.cssText=e.style.cssText},getSelectionContext:function(){return this.contextTop},getSelectionElement:function(){return this.upperCanvasEl},_setActiveObject:function(e){this._activeObject&&this._activeObject.set("active",!1),this._activeObject=e,e.set("active",!0)},setActiveObject:function(e,t){return this._setActiveObject(e),this.renderAll(),this.fire("object:selected",{target:e,e:t}),e.fire("selected",{e:t}),this},getActiveObject:function(){return this._activeObject},_discardActiveObject:function(){this._activeObject&&this._activeObject.set("active",!1),this._activeObject=null},discardActiveObject:function(e){return this._discardActiveObject(),this.renderAll(),this.fire("selection:cleared",{e:e}),this},_setActiveGroup:function(e){this._activeGroup=e,e&&e.set("active",!0)},setActiveGroup:function(e,t){return this._setActiveGroup(e),e&&(this.fire("object:selected",{target:e,e:t}),e.fire("selected",{e:t})),this},getActiveGroup:function(){return this._activeGroup},_discardActiveGroup:function(){var e=this.getActiveGroup();e&&e.destroy(),this.setActiveGroup(null)},discardActiveGroup:function(e){return this._discardActiveGroup(),this.fire("selection:cleared",{e:e}),this},deactivateAll:function(){var e=this.getObjects(),t=0,n=e.length;for(;t1&&(t=new fabric.Group(t.reverse(),{originX:"center",originY:"center",canvas:this}),t.addWithUpdate(),this.setActiveGroup(t,e),t.saveCoords(),this.fire("selection:created",{target:t}),this.renderAll())},_collectObjects:function(){var n=[],r,i=this._groupSelector.ex,s=this._groupSelector.ey,o=i+this._groupSelector.left,u=s+this._groupSelector.top,a=new fabric.Point(e(i,o),e(s,u)),f=new fabric.Point(t(i,o),t(s,u)),l=i===o&&s===u;for(var c=this._objects.length;c--;){r=this._objects[c];if(!r||!r.selectable||!r.visible)continue;if(r.intersectsWithRect(a,f)||r.isContainedWithinRect(a,f)||r.containsPoint(a)||r.containsPoint(f)){r.set("active",!0),n.push(r);if(l)break}}return n},_maybeGroupObjects:function(e){this.selection&&this._groupSelector&&this._groupSelectedObjects(e);var t=this.getActiveGroup();t&&(t.setObjectsCoords().setCoords(),t.isMoving=!1,this.setCursor(this.defaultCursor)),this._groupSelector=null,this._currentTransform=null}})}(),fabric.util.object.extend(fabric.StaticCanvas.prototype,{toDataURL:function(e){e||(e={});var t=e.format||"png",n=e.quality||1,r=e.multiplier||1,i={left:e.left,top:e.top,width:e.width,height:e.height};return r!==1?this.__toDataURLWithMultiplier(t,n,i,r):this.__toDataURL(t,n,i)},__toDataURL:function(e,t,n){this.renderAll(!0);var r=this.upperCanvasEl||this.lowerCanvasEl,i=this.__getCroppedCanvas(r,n);e==="jpg"&&(e="jpeg");var s=fabric.StaticCanvas.supports("toDataURLWithQuality")?(i||r).toDataURL("image/"+e,t):(i||r).toDataURL("image/"+e);return this.contextTop&&this.clearContext(this.contextTop),this.renderAll(),i&&(i=null),s},__getCroppedCanvas:function(e,t){var n,r,i="left"in t||"top"in t||"width"in t||"height"in t;return i&&(n=fabric.util.createCanvasElement(),r=n.getContext("2d"),n.width=t.width||this.width,n.height=t.height||this.height,r.drawImage(e,-t.left||0,-t.top||0)),n},__toDataURLWithMultiplier:function(e,t,n,r){var i=this.getWidth(),s=this.getHeight(),o=i*r,u=s*r,a=this.getActiveObject(),f=this.getActiveGroup(),l=this.contextTop||this.contextContainer;r>1&&this.setWidth(o).setHeight(u),l.scale(r,r),n.left&&(n.left*=r),n.top&&(n.top*=r),n.width?n.width*=r:r<1&&(n.width=o),n.height?n.height*=r:r<1&&(n.height=u),f?this._tempRemoveBordersControlsFromGroup(f):a&&this.deactivateAll&&this.deactivateAll(),this.renderAll(!0);var c=this.__toDataURL(e,t,n);return this.width=i,this.height=s,l.scale(1/r,1/r),this.setWidth(i).setHeight(s),f?this._restoreBordersControlsOnGroup(f):a&&this.setActiveObject&&this.setActiveObject(a),this.contextTop&&this.clearContext(this.contextTop),this.renderAll(),c},toDataURLWithMultiplier:function(e,t,n){return this.toDataURL({format:e,multiplier:t,quality:n})},_tempRemoveBordersControlsFromGroup:function(e){e.origHasControls=e.hasControls,e.origBorderColor=e.borderColor,e.hasControls=!0,e.borderColor="rgba(0,0,0,0)",e.forEachObject(function(e){e.origBorderColor=e.borderColor,e.borderColor="rgba(0,0,0,0)"})},_restoreBordersControlsOnGroup:function(e){e.hideControls=e.origHideControls,e.borderColor=e.origBorderColor,e.forEachObject(function(e){e.borderColor=e.origBorderColor,delete e.origBorderColor})}}),fabric.util.object.extend(fabric.StaticCanvas.prototype,{loadFromDatalessJSON:function(e,t,n){return this.loadFromJSON(e,t,n)},loadFromJSON:function(e,t,n){if(!e)return;var r=typeof e=="string"?JSON.parse(e):e;this.clear();var i=this;return this._enlivenObjects(r.objects,function(){i._setBgOverlay(r,t)},n),this},_setBgOverlay:function(e,t){var n=this,r={backgroundColor:!1,overlayColor:!1,backgroundImage:!1,overlayImage:!1};if(!e.backgroundImage&&!e.overlayImage&&!e.background&&!e.overlay){t&&t();return}var i=function(){r.backgroundImage&&r.overlayImage&&r.backgroundColor&&r.overlayColor&&(n.renderAll(),t&&t())};this.__setBgOverlay("backgroundImage",e.backgroundImage,r,i),this.__setBgOverlay("overlayImage",e.overlayImage,r,i),this.__setBgOverlay("backgroundColor",e.background,r,i),this.__setBgOverlay("overlayColor",e.overlay,r,i),i()},__setBgOverlay:function(e,t,n,r){var i=this;if(!t){n[e]=!0;return}e==="backgroundImage"||e==="overlayImage"?fabric.Image.fromObject(t,function(t){i[e]=t,n[e]=!0,r&&r()}):this["set"+fabric.util.string.capitalize(e,!0)](t,function(){n[e]=!0,r&&r()})},_enlivenObjects:function(e,t,n){var r=this;if(!e||e.length===0){t&&t();return}var i=this.renderOnAddRemove;this.renderOnAddRemove=!1,fabric.util.enlivenObjects(e +,function(e){e.forEach(function(e,t){r.insertAt(e,t,!0)}),r.renderOnAddRemove=i,t&&t()},null,n)},_toDataURL:function(e,t){this.clone(function(n){t(n.toDataURL(e))})},_toDataURLWithMultiplier:function(e,t,n){this.clone(function(r){n(r.toDataURLWithMultiplier(e,t))})},clone:function(e,t){var n=JSON.stringify(this.toJSON(t));this.cloneWithoutData(function(t){t.loadFromJSON(n,function(){e&&e(t)})})},cloneWithoutData:function(e){var t=fabric.document.createElement("canvas");t.width=this.getWidth(),t.height=this.getHeight();var n=new fabric.Canvas(t);n.clipTo=this.clipTo,this.backgroundImage?(n.setBackgroundImage(this.backgroundImage.src,function(){n.renderAll(),e&&e(n)}),n.backgroundImageOpacity=this.backgroundImageOpacity,n.backgroundImageStretch=this.backgroundImageStretch):e&&e(n)}}),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.toFixed,i=t.util.string.capitalize,s=t.util.degreesToRadians,o=t.StaticCanvas.supports("setLineDash");if(t.Object)return;t.Object=t.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,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:"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,stateProperties:"top left width height scaleX scaleY flipX flipY originX originY transformMatrix stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit angle opacity fill fillRule shadow clipTo visible backgroundColor".split(" "),initialize:function(e){e&&this.setOptions(e)},_initGradient:function(e){e.fill&&e.fill.colorStops&&!(e.fill instanceof t.Gradient)&&this.set("fill",new t.Gradient(e.fill))},_initPattern:function(e){e.fill&&e.fill.source&&!(e.fill instanceof t.Pattern)&&this.set("fill",new t.Pattern(e.fill)),e.stroke&&e.stroke.source&&!(e.stroke instanceof t.Pattern)&&this.set("stroke",new t.Pattern(e.stroke))},_initClipping:function(e){if(!e.clipTo||typeof e.clipTo!="string")return;var n=t.util.getFunctionBody(e.clipTo);typeof n!="undefined"&&(this.clipTo=new Function("ctx",n))},setOptions:function(e){for(var t in e)this.set(t,e[t]);this._initGradient(e),this._initPattern(e),this._initClipping(e)},transform:function(e,t){this.group&&this.group.transform(e,t),e.globalAlpha=this.opacity;var n=t?this._getLeftTopCoords():this.getCenterPoint();e.translate(n.x,n.y),e.rotate(s(this.angle)),e.scale(this.scaleX*(this.flipX?-1:1),this.scaleY*(this.flipY?-1:1))},toObject:function(e){var n=t.Object.NUM_FRACTION_DIGITS,i={type:this.type,originX:this.originX,originY:this.originY,left:r(this.left,n),top:r(this.top,n),width:r(this.width,n),height:r(this.height,n),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,n),strokeDashArray:this.strokeDashArray,strokeLineCap:this.strokeLineCap,strokeLineJoin:this.strokeLineJoin,strokeMiterLimit:r(this.strokeMiterLimit,n),scaleX:r(this.scaleX,n),scaleY:r(this.scaleY,n),angle:r(this.getAngle(),n),flipX:this.flipX,flipY:this.flipY,opacity:r(this.opacity,n),shadow:this.shadow&&this.shadow.toObject?this.shadow.toObject():this.shadow,visible:this.visible,clipTo:this.clipTo&&String(this.clipTo),backgroundColor:this.backgroundColor};return this.includeDefaultValues||(i=this._removeDefaultValues(i)),t.util.populateWithProperties(this,i,e),i},toDatalessObject:function(e){return this.toObject(e)},_removeDefaultValues:function(e){var n=t.util.getKlass(e.type).prototype,r=n.stateProperties;return r.forEach(function(t){e[t]===n[t]&&delete e[t]}),e},toString:function(){return"#"},get:function(e){return this[e]},_setObject:function(e){for(var t in e)this._set(t,e[t])},set:function(e,t){return typeof e=="object"?this._setObject(e):typeof t=="function"&&e!=="clipTo"?this._set(e,t(this.get(e))):this._set(e,t),this},_set:function(e,n){var i=e==="scaleX"||e==="scaleY";return i&&(n=this._constrainScale(n)),e==="scaleX"&&n<0?(this.flipX=!this.flipX,n*=-1):e==="scaleY"&&n<0?(this.flipY=!this.flipY,n*=-1):e==="width"||e==="height"?this.minScaleLimit=r(Math.min(.1,1/Math.max(this.width,this.height)),2):e==="shadow"&&n&&!(n instanceof t.Shadow)&&(n=new t.Shadow(n)),this[e]=n,this},toggle:function(e){var t=this.get(e);return typeof t=="boolean"&&this.set(e,!t),this},setSourcePath:function(e){return this.sourcePath=e,this},getViewportTransform:function(){return this.canvas&&this.canvas.viewportTransform?this.canvas.viewportTransform:[1,0,0,1,0,0]},render:function(e,n){if(this.width===0||this.height===0||!this.visible)return;e.save(),this._setupFillRule(e),this._transform(e,n),this._setStrokeStyles(e),this._setFillStyles(e);var r=this.transformMatrix;r&&this.group&&(e.translate(-this.group.width/2,-this.group.height/2),e.transform(r[0],r[1],r[2],r[3],r[4],r[5])),this._setShadow(e),this.clipTo&&t.util.clipContext(this,e),this._render(e,n),this.clipTo&&e.restore(),this._removeShadow(e),this._restoreFillRule(e),e.restore()},_transform:function(e,t){var n=this.transformMatrix;n&&!this.group&&e.setTransform(n[0],n[1],n[2],n[3],n[4],n[5]),t||this.transform(e)},_setStrokeStyles:function(e){this.stroke&&(e.lineWidth=this.strokeWidth,e.lineCap=this.strokeLineCap,e.lineJoin=this.strokeLineJoin,e.miterLimit=this.strokeMiterLimit,e.strokeStyle=this.stroke.toLive?this.stroke.toLive(e):this.stroke)},_setFillStyles:function(e){this.fill&&(e.fillStyle=this.fill.toLive?this.fill.toLive(e):this.fill)},_renderControls:function(e,n){var r=this.getViewportTransform();e.save();if(this.active&&!n){var i;this.group&&(i=t.util.transformPoint(this.group.getCenterPoint(),r),e.translate(i.x,i.y),e.rotate(s(this.group.angle))),i=t.util.transformPoint(this.getCenterPoint(),r,null!=this.group),this.group&&(i.x*=this.group.scaleX,i.y*=this.group.scaleY),e.translate(i.x,i.y),e.rotate(s(this.angle)),this.drawBorders(e),this.drawControls(e)}e.restore()},_setShadow:function(e){if(!this.shadow)return;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur,e.shadowOffsetX=this.shadow.offsetX,e.shadowOffsetY=this.shadow.offsetY},_removeShadow:function(e){if(!this.shadow)return;e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0},_renderFill:function(e){if(!this.fill)return;this.fill.toLive&&(e.save(),e.translate(-this.width/2+this.fill.offsetX||0,-this.height/2+this.fill.offsetY||0)),this.fillRule==="destination-over"?e.fill("evenodd"):e.fill(),this.fill.toLive&&e.restore(),this.shadow&&!this.shadow.affectStroke&&this._removeShadow(e)},_renderStroke:function(e){if(!this.stroke)return;e.save(),this.strokeDashArray?(1&this.strokeDashArray.length&&this.strokeDashArray.push.apply(this.strokeDashArray,this.strokeDashArray),o?(e.setLineDash(this.strokeDashArray),this._stroke&&this._stroke(e)):this._renderDashedStroke&&this._renderDashedStroke(e),e.stroke()):this._stroke?this._stroke(e):e.stroke(),this._removeShadow(e),e.restore()},clone:function(e,n){return this.constructor.fromObject?this.constructor.fromObject(this.toObject(n),e):new t.Object(this.toObject(n))},cloneAsImage:function(e){var n=this.toDataURL();return t.util.loadImage(n,function(n){e&&e(new t.Image(n))}),this},toDataURL:function(e){e||(e={});var n=t.util.createCanvasElement(),r=this.getBoundingRect();n.width=r.width,n.height=r.height,t.util.wrapElement(n,"div");var i=new t.Canvas(n);e.format==="jpg"&&(e.format="jpeg"),e.format==="jpeg"&&(i.backgroundColor="#fff");var s={active:this.get("active"),left:this.getLeft(),top:this.getTop()};this.set("active",!1),this.setPositionByOrigin(new t.Point(n.width/2,n.height/2),"center","center");var o=this.canvas;i.add(this);var u=i.toDataURL(e);return this.set(s).setCoords(),this.canvas=o,i.dispose(),i=null,u},isType:function(e){return this.type===e},complexity:function(){return 0},toJSON:function(e){return this.toObject(e)},setGradient:function(e,n){n||(n={});var r={colorStops:[]};r.type=n.type||(n.r1||n.r2?"radial":"linear"),r.coords={x1:n.x1,y1:n.y1,x2:n.x2,y2:n.y2};if(n.r1||n.r2)r.coords.r1=n.r1,r.coords.r2=n.r2;for(var i in n.colorStops){var s=new t.Color(n.colorStops[i]);r.colorStops.push({offset:i,color:s.toRgb(),opacity:s.getAlpha()})}return this.set(e,t.Gradient.forObject(this,r))},setPatternFill:function(e){return this.set("fill",new t.Pattern(e))},setShadow:function(e){return this.set("shadow",e?new t.Shadow(e):null)},setColor:function(e){return this.set("fill",e),this},setAngle:function(e){var t=(this.originX!=="center"||this.originY!=="center")&&this.centeredRotation;return t&&this._setOriginToCenter(),this.set("angle",e),t&&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(e,t){t=t||this.canvas.getPointer(e);var n=this.translateToOriginPoint(this.getCenterPoint(),"left","top");return{x:t.x-n.x,y:t.y-n.y}},_setupFillRule:function(e){this.fillRule&&(this._prevFillRule=e.globalCompositeOperation,e.globalCompositeOperation=this.fillRule)},_restoreFillRule:function(e){this.fillRule&&this._prevFillRule&&(e.globalCompositeOperation=this._prevFillRule)}}),t.util.createAccessors(t.Object),t.Object.prototype.rotate=t.Object.prototype.setAngle,n(t.Object.prototype,t.Observable),t.Object.NUM_FRACTION_DIGITS=2,t.Object.__uid=0}(typeof exports!="undefined"?exports:this),function(){var e=fabric.util.degreesToRadians;fabric.util.object.extend(fabric.Object.prototype,{translateToCenterPoint:function(t,n,r){var i=t.x,s=t.y,o=this.stroke?this.strokeWidth:0;return n==="left"?i=t.x+(this.getWidth()+o*this.scaleX)/2:n==="right"&&(i=t.x-(this.getWidth()+o*this.scaleX)/2),r==="top"?s=t.y+(this.getHeight()+o*this.scaleY)/2:r==="bottom"&&(s=t.y-(this.getHeight()+o*this.scaleY)/2),fabric.util.rotatePoint(new fabric.Point(i,s),t,e(this.angle))},translateToOriginPoint:function(t,n,r){var i=t.x,s=t.y,o=this.stroke?this.strokeWidth:0;return n==="left"?i=t.x-(this.getWidth()+o*this.scaleX)/2:n==="right"&&(i=t.x+(this.getWidth()+o*this.scaleX)/2),r==="top"?s=t.y-(this.getHeight()+o*this.scaleY)/2:r==="bottom"&&(s=t.y+(this.getHeight()+o*this.scaleY)/2),fabric.util.rotatePoint(new fabric.Point(i,s),t,e(this.angle))},getCenterPoint:function(){var e=new fabric.Point(this.left,this.top);return this.translateToCenterPoint(e,this.originX,this.originY)},getPointByOrigin:function(e,t){var n=this.getCenterPoint();return this.translateToOriginPoint(n,e,t)},toLocalPoint:function(t,n,r){var i=this.getCenterPoint(),s=this.stroke?this.strokeWidth:0,o,u;return n&&r?(n==="left"?o=i.x-(this.getWidth()+s*this.scaleX)/2:n==="right"?o=i.x+(this.getWidth()+s*this.scaleX)/2:o=i.x,r==="top"?u=i.y-(this.getHeight()+s*this.scaleY)/2:r==="bottom"?u=i.y+(this.getHeight()+s*this.scaleY)/2:u=i.y):(o=this.left,u=this.top),fabric.util.rotatePoint(new fabric.Point(t.x,t.y),i,-e(this.angle)).subtractEquals(new fabric.Point(o,u))},setPositionByOrigin:function(e,t,n){var r=this.translateToCenterPoint(e,t,n),i=this.translateToOriginPoint(r,this.originX,this.originY);this.set("left",i.x),this.set("top",i.y)},adjustPosition:function(t){var n=e(this.angle),r=this.getWidth()/2,i=Math.cos(n)*r,s=Math.sin(n)*r,o=this.getWidth(),u=Math.cos(n)*o,a=Math.sin(n)*o;this.originX==="center"&&t==="left"||this.originX==="right"&&t==="center"?(this.left-=i,this.top-=s):this.originX==="left"&&t==="center"||this.originX==="center"&&t==="right"?(this.left+=i,this.top+=s):this.originX==="left"&&t==="right"?(this.left+=u,this.top+=a):this.originX==="right"&&t==="left"&&(this.left-=u,this.top-=a),this.setCoords(),this.originX=t},_setOriginToCenter:function(){this._originalOriginX=this.originX,this._originalOriginY=this.originY;var e=this.getCenterPoint();this.originX="center",this.originY="center",this.left=e.x,this.top=e.y},_resetOrigin:function(){var e=this.translateToOriginPoint(this.getCenterPoint(),this._originalOriginX,this._originalOriginY);this.originX=this._originalOriginX,this.originY=this._originalOriginY,this.left=e.x,this.top=e.y,this._originalOriginX=null,this._originalOriginY=null},_getLeftTopCoords:function(){return this.translateToOriginPoint(this.getCenterPoint(),"left","center")}})}(),function(){var e=fabric.util.degreesToRadians;fabric.util.object.extend(fabric.Object.prototype,{oCoords:null,intersectsWithRect:function(e,t){var n=this.oCoords,r=new fabric.Point(n.tl.x,n.tl.y),i=new fabric.Point(n.tr.x,n.tr.y),s=new fabric.Point(n.bl.x,n.bl.y),o=new fabric.Point(n.br.x,n.br.y),u=fabric.Intersection.intersectPolygonRectangle([r,i,o,s],e,t);return u.status==="Intersection"},intersectsWithObject:function(e){function t(e){return{tl:new fabric.Point(e.tl.x,e.tl.y),tr:new fabric.Point(e.tr.x,e.tr.y),bl:new fabric.Point(e.bl.x,e.bl.y),br:new fabric.Point(e.br.x,e.br.y)}}var n=t(this.oCoords),r=t(e.oCoords),i=fabric.Intersection.intersectPolygonPolygon([n.tl,n.tr,n.br,n.bl],[r.tl,r.tr,r.br,r.bl]);return i.status==="Intersection"},isContainedWithinObject:function(e){var t=e.getBoundingRect(),n=new fabric.Point(t.left,t.top),r=new fabric.Point(t.left+t.width,t.top+t.height);return this.isContainedWithinRect(n,r)},isContainedWithinRect:function(e,t){var n=this.getBoundingRect();return n.left>=e.x&&n.left+n.width<=t.x&&n.top>=e.y&&n.top+n.height<=t.y},containsPoint:function(e){var t=this._getImageLines(this.oCoords),n=this._findCrossPoints(e,t);return n!==0&&n%2===1},_getImageLines:function(e){return{topline:{o:e.tl,d:e.tr},rightline:{o:e.tr,d:e.br},bottomline:{o:e.br,d:e.bl},leftline:{o:e.bl,d:e.tl}}},_findCrossPoints:function(e,t){var n,r,i,s,o,u,a=0,f;for(var l in t){f=t[l];if(f.o.y=e.y&&f.d.y>=e.y)continue;f.o.x===f.d.x&&f.o.x>=e.x?(o=f.o.x,u=e.y):(n=0,r=(f.d.y-f.o.y)/(f.d.x-f.o.x),i=e.y-n*e.x,s=f.o.y-r*f.o.x,o=-(i-s)/(n-r),u=i+n*o),o>=e.x&&(a+=1);if(a===2)break}return a},getBoundingRectWidth:function(){return this.getBoundingRect().width},getBoundingRectHeight:function(){return this.getBoundingRect().height},getBoundingRect:function(){this.oCoords||this.setCoords();var e=[this.oCoords.tl.x,this.oCoords.tr.x,this.oCoords.br.x,this.oCoords.bl.x],t=fabric.util.array.min(e),n=fabric.util.array.max(e),r=Math.abs(t-n),i=[this.oCoords.tl.y,this.oCoords.tr.y,this.oCoords.br.y,this.oCoords.bl.y],s=fabric.util.array.min(i),o=fabric.util.array.max(i),u=Math.abs(s-o);return{left:t,top:s,width:r,height:u}},getWidth:function(){return this.width*this.scaleX},getHeight:function(){return this.height*this.scaleY},_constrainScale:function(e){return Math.abs(e)1?this.strokeWidth:0,n=e(this.angle),r=this.getViewportTransform(),i=function(e){return fabric.util.transformPoint(e,r)},s=this.width,o=this.height,u=this.strokeLineCap==="round"||this.strokeLineCap==="square",a=this.type==="line"&&this.width===1,f=this.type==="line"&&this.height===1,l=u&&f||this.type!=="line",c=u&&a||this.type!=="line";a?s=t:f&&(o=t),l&&(s+=t),c&&(o+=t),this.currentWidth=s*this.scaleX,this.currentHeight=o*this.scaleY,this.currentWidth<0&&(this.currentWidth=Math.abs(this.currentWidth));var h=Math.sqrt(Math.pow(this.currentWidth/2,2)+Math.pow(this.currentHeight/2,2)),p=Math.atan(isFinite(this.currentHeight/this.currentWidth)?this.currentHeight/this.currentWidth:0),d=Math.cos(p+n)*h,v=Math.sin(p+n)*h,m=Math.sin(n),g=Math.cos(n),y=this.getCenterPoint(),b=new fabric.Point(this.currentWidth,this.currentHeight),w=new fabric.Point(y.x-d,y.y-v),E=new fabric.Point(w.x+b.x*g,w.y+b.x*m),S=new fabric.Point(w.x-b.y*m,w.y+b.y*g),x=new fabric.Point(w.x+b.x/2*g,w.y+b.x/2*m),T=i(w),N=i(E),C=i(new fabric.Point(E.x-b.y*m,E.y+b.y*g)),k=i(S),L=i(new fabric.Point(w.x-b.y/2*m,w.y+b.y/2*g)),A=i(x),O=i(new fabric.Point(E.x-b.y/2*m,E.y+b.y/2*g)),M=i(new fabric.Point(S.x+b.x/2*g,S.y+b.x/2*m)),_=i(new fabric.Point(x.x,x.y)),D=Math.cos(p+n)*this.padding*Math.sqrt(2),P=Math.sin(p+n)*this.padding*Math.sqrt(2);return T=T.add(new fabric.Point(-D,-P)),N=N.add(new fabric.Point(P,-D)),C=C.add(new fabric.Point(D,P)),k=k.add(new fabric.Point(-P,D)),L=L.add(new fabric.Point((-D-P)/2,(-P+D)/2)),A=A.add(new fabric.Point((P-D)/2,-(P+D)/2)),O=O.add(new fabric.Point((P+D)/2,(P-D)/2)),M=M.add(new fabric.Point((D-P)/2,(D+P)/2)),_=_.add(new fabric.Point((P-D)/2,-(P+D)/2)),this.oCoords={tl:T,tr:N,br:C,bl:k,ml:L,mt:A,mr:O,mb:M,mtr:_},this._setCornerCoords&&this._setCornerCoords(),this}})}(),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(e){return this.group?fabric.StaticCanvas.prototype.sendBackwards.call(this.group,this,e):this.canvas.sendBackwards(this,e),this},bringForward:function(e){return this.group?fabric.StaticCanvas.prototype.bringForward.call(this.group,this,e):this.canvas.bringForward(this,e),this},moveTo:function(e){return this.group?fabric.StaticCanvas.prototype.moveTo.call(this.group,this,e):this.canvas.moveTo(this,e),this}}),fabric.util.object.extend(fabric.Object.prototype,{getSvgStyles:function(){var e=this.fill?this.fill.toLive?"url(#SVGID_"+this.fill.id+")":this.fill:"none",t=this.stroke?this.stroke.toLive?"url(#SVGID_"+this.stroke.id+")":this.stroke:"none",n=this.strokeWidth?this.strokeWidth:"0",r=this.strokeDashArray?this.strokeDashArray.join(" "):"",i=this.strokeLineCap?this.strokeLineCap:"butt",s=this.strokeLineJoin?this.strokeLineJoin:"miter",o=this.strokeMiterLimit?this.strokeMiterLimit:"4",u=typeof this.opacity!="undefined"?this.opacity:"1",a=this.visible?"":" visibility: hidden;",f=this.shadow&&this.type!=="text"?"filter: url(#SVGID_"+this.shadow.id+");":"";return["stroke: ",t,"; ","stroke-width: ",n,"; ","stroke-dasharray: ",r,"; ","stroke-linecap: ",i,"; ","stroke-linejoin: ",s,"; ","stroke-miterlimit: ",o,"; ","fill: ",e,"; ","opacity: ",u,";",f,a].join("")},getSvgTransform:function(){var e=fabric.util.toFixed,t=this.getAngle(),n=this.getViewportTransform(),r=fabric.util.transformPoint(this.getCenterPoint(),n),i=fabric.Object.NUM_FRACTION_DIGITS,s="translate("+e(r.x,i)+" "+e(r.y,i)+")",o=t!==0?" rotate("+e(t,i)+")":"",u=this.scaleX===1&&this.scaleY===1&&n[0]===1&&n[3]===1?"":" scale("+e(this.scaleX*n[0],i)+" "+e(this.scaleY*n[3],i)+")",a=this.flipX?"matrix(-1 0 0 1 0 0) ":"",f=this.flipY?"matrix(1 0 0 -1 0 0)":"";return[s,o,u,a,f].join("")},_createBaseSVGMarkup:function(){var e=[];return this.fill&&this.fill.toLive&&e.push(this.fill.toSVG(this,!1)),this.stroke&&this.stroke.toLive&&e.push(this.stroke.toSVG(this,!1)),this.shadow&&e.push(this.shadow.toSVG(this)),e}}),fabric.util.object.extend(fabric.Object.prototype,{hasStateChanged:function(){return this.stateProperties.some(function(e){return this.get(e)!==this.originalState[e]},this)},saveState:function(e){return this.stateProperties.forEach(function(e){this.originalState[e]=this.get(e)},this),e&&e.stateProperties&&e.stateProperties.forEach(function(e){this.originalState[e]=this.get(e)},this),this},setupState:function(){return this.originalState={},this.saveState(),this}}),function(){var e=fabric.util.degreesToRadians,t=function(){return typeof G_vmlCanvasManager!="undefined"};fabric.util.object.extend(fabric.Object.prototype,{_controlsVisibility:null,_findTargetCorner:function(e){if(!this.hasControls||!this.active)return!1;var t=e.x,n=e.y,r,i;for(var s in this.oCoords){if(!this.isControlVisible(s))continue;if(s==="mtr"&&!this.hasRotatingPoint)continue;if(!(!this.get("lockUniScaling")||s!=="mt"&&s!=="mr"&&s!=="mb"&&s!=="ml"))continue;i=this._getImageLines(this.oCoords[s].corner),r=this._findCrossPoints({x:t,y:n},i);if(r!==0&&r%2===1)return this.__corner=s,s}return!1},_setCornerCoords:function(){var t=this.oCoords,n=e(this.angle),r=e(45-this.angle),i=Math.sqrt(2*Math.pow(this.cornerSize,2))/2,s=i*Math.cos(r),o=i*Math.sin(r),u=Math.sin(n),a=Math.cos(n);t.tl.corner={tl:{x:t.tl.x-o,y:t.tl.y-s},tr:{x:t.tl.x+s,y:t.tl.y-o},bl:{x:t.tl.x-s,y:t.tl.y+o},br:{x:t.tl.x+o,y:t.tl.y+s}},t.tr.corner={tl:{x:t.tr.x-o,y:t.tr.y-s},tr:{x:t.tr.x+s,y:t.tr.y-o},br:{x:t.tr.x+o,y:t.tr.y+s},bl:{x:t.tr.x-s,y:t.tr.y+o}},t.bl.corner={tl:{x:t.bl.x-o,y:t.bl.y-s},bl:{x:t.bl.x-s,y:t.bl.y+o},br:{x:t.bl.x+o,y:t.bl.y+s},tr:{x:t.bl.x+s,y:t.bl.y-o}},t.br.corner={tr:{x:t.br.x+s,y:t.br.y-o},bl:{x:t.br.x-s,y:t.br.y+o},br:{x:t.br.x+o,y:t.br.y+s},tl:{x:t.br.x-o,y:t.br.y-s}},t.ml.corner={tl:{x:t.ml.x-o,y:t.ml.y-s},tr:{x:t.ml.x+s,y:t.ml.y-o},bl:{x:t.ml.x-s,y:t.ml.y+o},br:{x:t.ml.x+o,y:t.ml.y+s}},t.mt.corner={tl:{x:t.mt.x-o,y:t.mt.y-s},tr:{x:t.mt.x+s,y:t.mt.y-o},bl:{x:t.mt.x-s,y:t.mt.y+o},br:{x:t.mt.x+o,y:t.mt.y+s}},t.mr.corner={tl:{x:t.mr.x-o,y:t.mr.y-s},tr:{x:t.mr.x+s,y:t.mr.y-o},bl:{x:t.mr.x-s,y:t.mr.y+o},br:{x:t.mr.x+o,y:t.mr.y+s}},t.mb.corner={tl:{x:t.mb.x-o,y:t.mb.y-s},tr:{x:t.mb.x+s,y:t.mb.y-o},bl:{x:t.mb.x-s,y:t.mb.y+o},br:{x:t.mb.x+o,y:t.mb.y+s}},t.mtr.corner={tl:{x:t.mtr.x-o+u*this.rotatingPointOffset,y:t.mtr.y-s-a*this.rotatingPointOffset},tr:{x:t.mtr.x+s+u*this.rotatingPointOffset,y:t.mtr.y-o-a*this.rotatingPointOffset},bl:{x:t.mtr.x-s+u*this.rotatingPointOffset,y:t.mtr.y+o-a*this.rotatingPointOffset},br:{x:t.mtr.x+o+u*this.rotatingPointOffset,y:t.mtr.y+s-a*this.rotatingPointOffset}}},drawBorders:function(e){if(!this.hasBorders)return this;var t=this.padding,n=t*2,r=this.getViewportTransform();e.save(),e.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1,e.strokeStyle=this.borderColor;var i=1/this._constrainScale(this.scaleX),s=1/this._constrainScale(this.scaleY);e.lineWidth=1/this.borderScaleFactor;var o=this.getWidth(),u=this.getHeight(),a=this.strokeWidth>1?this.strokeWidth:0,f=this.strokeLineCap==="round"||this.strokeLineCap==="square",l=this.type==="line"&&this.width===1,c=this.type==="line"&&this.height===1,h=f&&c||this.type!=="line",p=f&&l||this.type!=="line";l?o=a/i:c&&(u=a/s),h&&(o+=a/i),p&&(u+=a/s);var d=fabric.util.transformPoint(new fabric.Point(o,u),r,!0),v=d.x,m=d.y;this.group&&(v*=this.group.scaleX,m*=this.group.scaleY),e.strokeRect(~~(-(v/2)-t)-.5,~~(-(m/2)-t)-.5,~~(v+n)+1,~~(m+n)+1);if(this.hasRotatingPoint&&this.isControlVisible("mtr")&&!this.get("lockRotation")&&this.hasControls){var g=(this.flipY?m+t*2:-m-t*2)/2;e.beginPath(),e.moveTo(0,g),e.lineTo(0,g+(this.flipY?this.rotatingPointOffset:-this.rotatingPointOffset)),e.closePath(),e.stroke()}return e.restore(),this},drawControls:function(e){if(!this.hasControls)return this;var t=this.cornerSize,n=t/2,r=this.getViewportTransform(),i=this.strokeWidth>1?this.strokeWidth:0,s=this.width,o=this.height,u=this.strokeLineCap==="round"||this.strokeLineCap==="square",a=this.type==="line"&&this.width===1,f=this.type==="line"&&this.height===1,l=u&&f||this.type!=="line",c=u&&a||this.type!=="line";a?s=i:f&&(o=i),l&&(s+=i),c&&(o+=i),s*=this.scaleX,o*=this.scaleY;var h=fabric.util.transformPoint(new fabric.Point(s,o),r,!0),p=h.x,d=h.y,v=-(p/2),m=-(d/2),g=this.padding,y=n,b=n-t,w=this.transparentCorners?"strokeRect":"fillRect";return e.save(),e.lineWidth=1,e.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1,e.strokeStyle=e.fillStyle=this.cornerColor,this._drawControl("tl",e,w,v-y-g,m-y-g),this._drawControl("tr",e,w,v+p-y+g,m-y-g),this._drawControl("bl",e,w,v-y-g,m+d+b+g),this._drawControl("br",e,w,v+p+b+g,m+d+b+g),this.get("lockUniScaling")||(this._drawControl("mt",e,w,v+p/2-y,m-y-g),this._drawControl("mb",e,w,v+p/2-y,m+d+b+g),this._drawControl("mr",e,w,v+p+b+g,m+d/2-y),this._drawControl("ml",e,w,v-y-g,m+d/2-y)),this.hasRotatingPoint&&this._drawControl("mtr",e,w,v+p/2-y,this.flipY?m+d+this.rotatingPointOffset-this.cornerSize/2+g:m-this.rotatingPointOffset-this.cornerSize/2-g),e.restore(),this},_drawControl:function(e,n,r,i,s){var o=this.cornerSize;this.isControlVisible(e)&&(t()||this.transparentCorners||n.clearRect(i,s,o,o),n[r](i,s,o,o))},isControlVisible:function(e){return this._getControlsVisibility()[e]},setControlVisible:function(e,t){return this._getControlsVisibility()[e]=t,this},setControlsVisibility:function(e){e||(e={});for(var t in e)this.setControlVisible(t,e[t]);return this},_getControlsVisibility:function(){return this._controlsVisibility||(this._controlsVisibility={tl:!0,tr:!0,br:!0,bl:!0,ml:!0,mt:!0,mr:!0,mb:!0,mtr:!0}),this._controlsVisibility}})}(),fabric.util.object.extend(fabric.StaticCanvas.prototype,{FX_DURATION:500,fxCenterObjectH:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("left"),endValue:this.getCenter().left,duration:this.FX_DURATION,onChange:function(t){e.set("left",t),s.renderAll(),i()},onComplete:function(){e.setCoords(),r()}}),this},fxCenterObjectV:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("top"),endValue:this.getCenter().top,duration:this.FX_DURATION,onChange:function(t){e.set("top",t),s.renderAll(),i()},onComplete:function(){e.setCoords(),r()}}),this},fxRemove:function(e,t){t=t||{};var n=function(){},r=t.onComplete||n,i=t.onChange||n,s=this;return fabric.util.animate({startValue:e.get("opacity"),endValue:0,duration:this.FX_DURATION,onStart:function(){e.set("active",!1)},onChange:function(t){e.set("opacity",t),s.renderAll(),i()},onComplete:function(){s.remove(e),r()}}),this}}),fabric.util.object.extend(fabric.Object.prototype,{animate:function(){if(arguments[0]&&typeof arguments[0]=="object"){var e=[],t,n;for(t in arguments[0])e.push(t);for(var r=0,i=e.length;r'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Line.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" ")),t.Line.fromElement=function(e,r){var i=t.parseAttributes(e,t.Line.ATTRIBUTE_NAMES),s=[i.x1||0,i.y1||0,i.x2||0,i.y2||0];return new t.Line(s,n(i,r))},t.Line.fromObject=function(e){var n=[e.x1,e.y1,e.x2,e.y2];return new t.Line(n,e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function i(e){return"radius"in e&&e.radius>0}var t=e.fabric||(e.fabric={}),n=Math.PI*2,r=t.util.object.extend;if(t.Circle){t.warn("fabric.Circle is already defined.");return}t.Circle=t.util.createClass(t.Object,{type:"circle",radius:0,initialize:function(e){e=e||{},this.set("radius",e.radius||0),this.callSuper("initialize",e)},_set:function(e,t){return this.callSuper("_set",e,t),e==="radius"&&this.setRadius(t),this},toObject:function(e){return r(this.callSuper("toObject",e),{radius:this.get("radius")})},toSVG:function(e){var t=this._createBaseSVGMarkup();return t.push("'),e?e(t.join("")):t.join("")},_render:function(e,t){e.beginPath(),e.globalAlpha=this.group?e.globalAlpha*this.opacity:this.opacity,e.arc(t?this.left:0,t?this.top:0,this.radius,0,n,!1),this._renderFill(e),this.stroke&&this._renderStroke(e)},getRadiusX:function(){return this.get("radius")*this.get("scaleX")},getRadiusY:function(){return this.get("radius")*this.get("scaleY")},setRadius:function(e){this.radius=e,this.set("width",e*2).set("height",e*2)},complexity:function(){return 1}}),t.Circle.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("cx cy r".split(" ")),t.Circle.fromElement=function(e,n){n||(n={});var s=t.parseAttributes(e,t.Circle.ATTRIBUTE_NAMES);if(!i(s))throw new Error("value of `r` attribute is required and can not be negative");"left"in s||(s.left=0),"top"in s||(s.top=0),"transformMatrix"in s||(s.left-=n.width?n.width/2:0,s.top-=n.height?n.height/2:0);var o=new t.Circle(r(s,n));return o.cx=parseFloat(e.getAttribute("cx"))||0,o.cy=parseFloat(e.getAttribute("cy"))||0,o},t.Circle.fromObject=function(e){return new t.Circle(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={});if(t.Triangle){t.warn("fabric.Triangle is already defined");return}t.Triangle=t.util.createClass(t.Object,{type:"triangle",initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("width",e.width||100).set("height",e.height||100)},_render:function(e){var t=this.width/2,n=this.height/2;e.beginPath(),e.moveTo(-t,n),e.lineTo(0,-n),e.lineTo(t,n),e.closePath(),this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n=this.width/2,r=this.height/2;e.beginPath(),t.util.drawDashedLine(e,-n,r,0,-r,this.strokeDashArray),t.util.drawDashedLine(e,0,-r,n,r,this.strokeDashArray),t. +util.drawDashedLine(e,n,r,-n,r,this.strokeDashArray),e.closePath()},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=this.width/2,r=this.height/2,i=[-n+" "+r,"0 "+ -r,n+" "+r].join(",");return t.push("'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Triangle.fromObject=function(e){return new t.Triangle(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=Math.PI*2,r=t.util.object.extend;if(t.Ellipse){t.warn("fabric.Ellipse is already defined.");return}t.Ellipse=t.util.createClass(t.Object,{type:"ellipse",rx:0,ry:0,initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("rx",e.rx||0),this.set("ry",e.ry||0),this.set("width",this.get("rx")*2),this.set("height",this.get("ry")*2)},toObject:function(e){return r(this.callSuper("toObject",e),{rx:this.get("rx"),ry:this.get("ry")})},toSVG:function(e){var t=this._createBaseSVGMarkup();return t.push("'),e?e(t.join("")):t.join("")},render:function(e,t){if(this.rx===0||this.ry===0)return;return this.callSuper("render",e,t)},_render:function(e,t){e.beginPath(),e.globalAlpha=this.group?e.globalAlpha*this.opacity:this.opacity,e.save(),e.transform(1,0,0,this.ry/this.rx,0,0),e.arc(t?this.left:0,t?this.top*this.rx/this.ry:0,this.rx,0,n,!1),e.restore(),this._renderFill(e),this._renderStroke(e)},complexity:function(){return 1}}),t.Ellipse.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" ")),t.Ellipse.fromElement=function(e,n){n||(n={});var i=t.parseAttributes(e,t.Ellipse.ATTRIBUTE_NAMES);"left"in i||(i.left=0),"top"in i||(i.top=0),"transformMatrix"in i||(i.left-=n.width?n.width/2:0,i.top-=n.height?n.height/2:0);var s=new t.Ellipse(r(i,n));return s.cx=parseFloat(e.getAttribute("cx"))||0,s.cy=parseFloat(e.getAttribute("cy"))||0,s},t.Ellipse.fromObject=function(e){return new t.Ellipse(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function i(e){return e.left=e.left||0,e.top=e.top||0,e}var t=e.fabric||(e.fabric={}),n=t.util.object.extend;if(t.Rect){console.warn("fabric.Rect is already defined");return}var r=t.Object.prototype.stateProperties.concat();r.push("rx","ry","x","y"),t.Rect=t.util.createClass(t.Object,{stateProperties:r,type:"rect",rx:0,ry:0,x:0,y:0,strokeDashArray:null,initialize:function(e){e=e||{},this.callSuper("initialize",e),this._initRxRy(),this.x=e.x||0,this.y=e.y||0},_initRxRy:function(){this.rx&&!this.ry?this.ry=this.rx:this.ry&&!this.rx&&(this.rx=this.ry)},_render:function(e){if(this.width===1&&this.height===1){e.fillRect(0,0,1,1);return}var t=this.rx?Math.min(this.rx,this.width/2):0,n=this.ry?Math.min(this.ry,this.height/2):0,r=this.width,i=this.height,s=-r/2,o=-i/2,u=this.group&&this.group.type==="path-group",a=t!==0||n!==0,f=.4477152502;e.beginPath(),e.globalAlpha=u?e.globalAlpha*this.opacity:this.opacity,this.transformMatrix&&u&&e.translate(this.width/2+this.x,this.height/2+this.y),!this.transformMatrix&&u&&e.translate(-this.group.width/2+this.width/2+this.x,-this.group.height/2+this.height/2+this.y),e.moveTo(s+t,o),e.lineTo(s+r-t,o),a&&e.bezierCurveTo(s+r-f*t,o,s+r,o+f*n,s+r,o+n),e.lineTo(s+r,o+i-n),a&&e.bezierCurveTo(s+r,o+i-f*n,s+r-f*t,o+i,s+r-t,o+i),e.lineTo(s+t,o+i),a&&e.bezierCurveTo(s+f*t,o+i,s,o+i-f*n,s,o+i-n),e.lineTo(s,o+n),a&&e.bezierCurveTo(s,o+f*n,s+f*t,o,s+t,o),e.closePath(),this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n=-this.width/2,r=-this.height/2,i=this.width,s=this.height;e.beginPath(),t.util.drawDashedLine(e,n,r,n+i,r,this.strokeDashArray),t.util.drawDashedLine(e,n+i,r,n+i,r+s,this.strokeDashArray),t.util.drawDashedLine(e,n+i,r+s,n,r+s,this.strokeDashArray),t.util.drawDashedLine(e,n,r+s,n,r,this.strokeDashArray),e.closePath()},_normalizeLeftTopProperties:function(e){return"left"in e&&this.set("left",e.left+this.getWidth()/2),this.set("x",e.left||0),"top"in e&&this.set("top",e.top+this.getHeight()/2),this.set("y",e.top||0),this},toObject:function(e){var t=n(this.callSuper("toObject",e),{rx:this.get("rx")||0,ry:this.get("ry")||0,x:this.get("x"),y:this.get("y")});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=this._createBaseSVGMarkup();return t.push("'),e?e(t.join("")):t.join("")},complexity:function(){return 1}}),t.Rect.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" ")),t.Rect.fromElement=function(e,r){if(!e)return null;var s=t.parseAttributes(e,t.Rect.ATTRIBUTE_NAMES);s=i(s);var o=new t.Rect(n(r?t.util.object.clone(r):{},s));return o._normalizeLeftTopProperties(s),o},t.Rect.fromObject=function(e){return new t.Rect(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.toFixed;if(t.Polyline){t.warn("fabric.Polyline is already defined");return}t.Polyline=t.util.createClass(t.Object,{type:"polyline",points:null,initialize:function(e,t,n){t=t||{},this.set("points",e),this.callSuper("initialize",t),this._calcDimensions(n)},_calcDimensions:function(e){return t.Polygon.prototype._calcDimensions.call(this,e)},toObject:function(e){return t.Polygon.prototype.toObject.call(this,e)},toSVG:function(e){var t=[],r=this._createBaseSVGMarkup();for(var i=0,s=this.points.length;i'),e?e(r.join("")):r.join("")},_render:function(e){var t;e.beginPath(),e.moveTo(this.points[0].x,this.points[0].y);for(var n=0,r=this.points.length;n'),e?e(n.join("")):n.join("")},_render:function(e){var t;e.beginPath(),e.globalAlpha=this.group?e.globalAlpha*this.opacity:this.opacity,e.moveTo(this.points[0].x,this.points[0].y);for(var n=0,r=this.points.length;n"},toObject:function(e){var t=i(this.callSuper("toObject",e),{path:this.path.map(function(e){return e.slice()}),pathOffset:this.pathOffset});return this.sourcePath&&(t.sourcePath=this.sourcePath),this.transformMatrix&&(t.transformMatrix=this.transformMatrix),t},toDatalessObject:function(e){var t=this.toObject(e);return this.sourcePath&&(t.path=this.sourcePath),delete t.sourcePath,t},toSVG:function(e){var t=[],n=this._createBaseSVGMarkup();for(var r=0,i=this.path.length;r',"",""),e?e(n.join("")):n.join("")},complexity:function(){return this.path.length},_parsePath:function(){var e=[],t=[],n,r,i=/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/ig,s,o;for(var f=0,l,c=this.path.length;fv)for(var g=1,y=l.length;g"];for(var r=0,i=t.length;r"),e?e(n.join("")):n.join("")},toString:function(){return"#"},isSameColor:function(){var e=(this.getObjects()[0].get("fill")||"").toLowerCase();return this.getObjects().every(function(t){return(t.get("fill")||"").toLowerCase()===e})},complexity:function(){return this.paths.reduce(function(e,t){return e+(t&&t.complexity?t.complexity():0)},0)},getObjects:function(){return this.paths}}),t.PathGroup.fromObject=function(e,n){typeof e.paths=="string"?t.loadSVGFromURL(e.paths,function(r){var i=e.paths;delete e.paths;var s=t.util.groupSVGElements(r,e,i);n(s)}):t.util.enlivenObjects(e.paths,function(r){delete e.paths,n(new t.PathGroup(r,e))})},t.PathGroup.async=!0}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.array.min,i=t.util.array.max,s=t.util.array.invoke;if(t.Group)return;var o={lockMovementX:!0,lockMovementY:!0,lockRotation:!0,lockScalingX:!0,lockScalingY:!0,lockUniScaling:!0};t.Group=t.util.createClass(t.Object,t.Collection,{type:"group",initialize:function(e,t){t=t||{},this._objects=e||[];for(var r=this._objects.length;r--;)this._objects[r].group=this;this.originalState={},this.callSuper("initialize"),this._calcBounds(),this._updateObjectsCoords(),t&&n(this,t),this._setOpacityIfSame(),this.setCoords(),this.saveCoords()},_updateObjectsCoords:function(){this.forEachObject(this._updateObjectCoords,this)},_updateObjectCoords:function(e){var t=e.getLeft(),n=e.getTop();e.set({originalLeft:t,originalTop:n,left:t-this.left,top:n-this.top}),e.setCoords(),e.__origHasControls=e.hasControls,e.hasControls=!1},toString:function(){return"#"},addWithUpdate:function(e){return this._restoreObjectsState(),e&&(this._objects.push(e),e.group=this),this.forEachObject(this._setObjectActive,this),this._calcBounds(),this._updateObjectsCoords(),this},_setObjectActive:function(e){e.set("active",!0),e.group=this},removeWithUpdate:function(e){return this._moveFlippedObject(e),this._restoreObjectsState(),this.forEachObject(this._setObjectActive,this),this.remove(e),this._calcBounds(),this._updateObjectsCoords(),this},_onObjectAdded:function(e){e.group=this},_onObjectRemoved:function(e){delete e.group,e.set("active",!1)},delegatedProperties:{fill:!0,opacity:!0,fontFamily:!0,fontWeight:!0,fontSize:!0,fontStyle:!0,lineHeight:!0,textDecoration:!0,textAlign:!0,backgroundColor:!0},_set:function(e,t){if(e in this.delegatedProperties){var n=this._objects.length;this[e]=t;while(n--)this._objects[n].set(e,t)}else this[e]=t},toObject:function(e){return n(this.callSuper("toObject",e),{objects:s(this._objects,"toObject",e)})},render:function(e){if(!this.visible)return;e.save(),this.clipTo&&t.util.clipContext(this,e);for(var n=0,r=this._objects.length;n'];for(var n=0,r=this._objects.length;n"),e?e(t.join("")):t.join("")},get:function(e){if(e in o){if(this[e])return this[e];for(var t=0,n=this._objects.length;t','");if(this.stroke||this.strokeDashArray){var n=this.fill;this.fill=null,t.push("'),this.fill=n}return t.push(""),e?e(t.join("")):t.join("")},getSrc:function(){if(this.getElement())return this.getElement().src||this.getElement()._src},toString:function(){return'#'},clone:function(e,t){this.constructor.fromObject(this.toObject(t),e)},applyFilters:function(e){if(!this._originalElement)return;if(this.filters.length===0){this._element=this._originalElement,e&&e();return}var t=this._originalElement,n=fabric.util.createCanvasElement(),r=fabric.util.createImage(),i=this;return n.width=t.width,n.height=t.height,n.getContext("2d").drawImage(t,0,0,t.width,t.height),this.filters.forEach(function(e){e&&e.applyTo(n)}),r.width=t.width,r.height=t.height,fabric.isLikelyNode?(r.src=n.toBuffer(undefined,fabric.Image.pngCompression),i._element=r,e&&e()):(r.onload=function(){i._element=r,e&&e(),r.onload=n=t=null},r.src=n.toDataURL("image/png")),this},_render:function(e){this._element&&e.drawImage(this._element,-this.width/2,-this.height/2,this.width,this.height)},_resetWidthHeight:function(){var e=this.getElement();this.set("width",e.width),this.set("height",e.height)},_initElement:function(e){this.setElement(fabric.util.getById(e)),fabric.util.addClass(this.getElement(),fabric.Image.CSS_CANVAS)},_initConfig:function(e){e||(e={}),this.setOptions(e),this._setWidthHeight(e),this._element&&this.crossOrigin&&(this._element.crossOrigin=this.crossOrigin)},_initFilters:function(e,t){e.filters&&e.filters.length?fabric.util.enlivenObjects(e.filters,function(e){t&&t(e)},"fabric.Image.filters"):t&&t()},_setWidthHeight:function(e){this.width="width"in e?e.width:this.getElement()?this.getElement().width||0:0,this.height="height"in e?e.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(e,t){fabric.util.loadImage(e.src,function(n){fabric.Image.prototype._initFilters.call(e,e,function(r){e.filters=r||[];var i=new fabric.Image(n,e);t&&t(i)})},null,e.crossOrigin)},fabric.Image.fromURL=function(e,t,n){fabric.util.loadImage(e,function(e){t(new fabric.Image(e,n))},null,n&&n.crossOrigin)},fabric.Image.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y width height xlink:href".split(" ")),fabric.Image.fromElement=function(e,n,r){var i=fabric.parseAttributes(e,fabric.Image.ATTRIBUTE_NAMES);fabric.Image.fromURL(i["xlink:href"],n,t(r?fabric.util.object.clone(r):{},i))},fabric.Image.async=!0,fabric.Image.pngCompression=1}(typeof exports!="undefined"?exports:this),fabric.util.object.extend(fabric.Object.prototype,{_getAngleValueForStraighten:function(){var e=this.getAngle()%360;return e>0?Math.round((e-1)/90)*90:Math.round(e/90)*90},straighten:function(){return this.setAngle(this._getAngleValueForStraighten()),this},fxStraighten:function(e){e=e||{};var t=function(){},n=e.onComplete||t,r=e.onChange||t,i=this;return fabric.util.animate({startValue:this.get("angle"),endValue:this._getAngleValueForStraighten(),duration:this.FX_DURATION,onChange:function(e){i.setAngle(e),r()},onComplete:function(){i.setCoords(),n()},onStart:function(){i.set("active",!1)}}),this}}),fabric.util.object.extend(fabric.StaticCanvas.prototype,{straightenObject:function(e){return e.straighten(),this.renderAll(),this},fxStraightenObject:function(e){return e.fxStraighten({onChange:this.renderAll.bind(this)}),this}}),fabric.Image.filters=fabric.Image.filters||{},fabric.Image.filters.BaseFilter=fabric.util.createClass({type:"BaseFilter",toObject:function(){return{type:this.type}},toJSON:function(){return this.toObject()}}),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend;t.Image.filters.Brightness=t.util.createClass(t.Image.filters.BaseFilter,{type:"Brightness",initialize:function(e){e=e||{},this.brightness=e.brightness||0},applyTo:function(e){var t=e.getContext("2d"),n=t.getImageData(0,0,e.width,e.height),r=n.data,i=this.brightness;for(var s=0,o=r.length;sa||C<0||C>u)continue;var k=(N*u+C)*4,L=t[x*i+T];b+=o[k]*L,w+=o[k+1]*L,E+=o[k+2]*L,S+=o[k+3]*L}h[y]=b,h[y+1]=w,h[y+2]=E,h[y+3]=S+p*(255-S)}n.putImageData(c,0,0)},toObject:function(){return n(this.callSuper("toObject"),{opaque:this.opaque,matrix:this.matrix})}}),t.Image.filters.Convolute.fromObject=function(e){return new t.Image.filters.Convolute(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend;t.Image.filters.GradientTransparency=t.util.createClass(t.Image.filters.BaseFilter,{type:"GradientTransparency",initialize:function(e){e=e||{},this.threshold=e.threshold||100},applyTo:function(e){var t=e.getContext("2d"),n=t.getImageData(0,0,e.width,e.height),r=n.data,i=this.threshold,s=r.length;for(var o=0,u=r.length;o-1?e.channel:0},applyTo:function(e){if(!this.mask)return;var n=e.getContext("2d"),r=n.getImageData(0,0,e.width,e.height),i=r.data,s=this.mask.getElement(),o=t.util.createCanvasElement(),u=this.channel,a,f=r.width*r.height*4;o.width=s.width,o.height=s.height,o.getContext("2d").drawImage(s,0,0,s.width,s.height);var l=o.getContext("2d").getImageData(0,0,s.width,s.height),c=l.data;for(a=0;ao&&f>o&&l>o&&u(a-f)'},_render:function(e){var t=this.group&&this.group.type==="path-group";t&&!this.transformMatrix?e.translate(-this.group.width/2+this.left,-this.group.height/2+this.top):t&&this.transformMatrix&&e.translate(-this.group.width/2,-this.group.height/2),typeof Cufon=="undefined"||this.useNative===!0?this._renderViaNative(e):this._renderViaCufon(e)},_renderViaNative:function(e){var n=this.text.split(this._reNewline);this.transform(e,t.isLikelyNode),this._setTextStyles(e),this.width=this._getTextWidth(e,n),this.height=this._getTextHeight(e,n),this.clipTo&&t.util.clipContext(this,e),this._renderTextBackground(e,n),this._translateForTextAlign(e),this._renderText(e,n),this.textAlign!=="left"&&this.textAlign!=="justify"&&e.restore(),this._renderTextDecoration(e,n),this.clipTo&&e.restore(),this._setBoundaries(e,n),this._totalLineHeight=0},_renderText:function(e,t){e.save(),this._setShadow(e),this._renderTextFill(e,t),this._renderTextStroke(e,t),this._removeShadow(e),e.restore()},_translateForTextAlign:function(e){this.textAlign!=="left"&&this.textAlign!=="justify"&&(e.save(),e.translate(this.textAlign==="center"?this.width/2:this.width,0))},_setBoundaries:function(e,t){this._boundaries=[];for(var n=0,r=t.length;nn&&(n=s)}return n},_renderChars:function(e,t,n,r,i){t[e](n,r,i)},_renderTextLine:function(e,t,n,r,i,s){i-=this.fontSize/4;if(this.textAlign!=="justify"){this._renderChars(e,t,n,r,i,s);return}var o=t.measureText(n).width,u=this.width;if(u>o){var a=n.split(/\s+/),f=t.measureText(n.replace(/\s+/g,"")).width,l=u-f,c=a.length-1,h=l/c,p=0;for(var d=0,v=a.length;d-1&&i(this.fontSize*this.lineHeight),this.textDecoration.indexOf("line-through")>-1&&i(this.fontSize*this.lineHeight-this.fontSize/2),this.textDecoration.indexOf("overline")>-1&&i(this.fontSize*this.lineHeight-this.fontSize)},_getFontDeclaration:function(){return[t.isLikelyNode?this.fontWeight:this.fontStyle,t.isLikelyNode?this.fontStyle:this.fontWeight,this.fontSize+"px",t.isLikelyNode?'"'+this.fontFamily+'"':this.fontFamily].join(" ")},render:function(e){if(!this.visible)return;e.save();var t=this.transformMatrix;t&&(!this.group||this.group.type==="path-group")&&e.transform(t[0],t[1],t[2],t[3],t[4],t[5]),this._render(e),e.restore()},toObject:function(e){var t=n(this.callSuper("toObject",e),{text:this.text,fontSize:this.fontSize,fontWeight:this.fontWeight,fontFamily:this.fontFamily,fontStyle:this.fontStyle,lineHeight:this.lineHeight,textDecoration:this.textDecoration,textAlign:this.textAlign,path:this.path,textBackgroundColor:this.textBackgroundColor,useNative:this.useNative});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=[],n=this.text.split(this._reNewline),r=this._getSVGLeftTopOffsets(n),i=this._getSVGTextAndBg(r.lineTop,r.textLeft,n),s=this._getSVGShadows(r.lineTop,n);return r.textTop+=this._fontAscent?this._fontAscent/5*this.lineHeight:0,this._wrapSVGTextAndBg(t,i,s,r),e?e(t.join("")):t.join("")},_getSVGLeftTopOffsets:function(e){var t=this.useNative?this.fontSize*this.lineHeight:-this._fontAscent-this._fontAscent/5*this.lineHeight,n=-(this.width/2),r=this.useNative?this.fontSize-1:this.height/2-e.length*this.fontSize-this._totalLineHeight;return{textLeft:n,textTop:r,lineTop:t}},_wrapSVGTextAndBg:function(e,t,n,r){e.push('',t.textBgRects.join(""),"',n.join(""),t.textSpans.join(""),"","")},_getSVGShadows:function(e,n){var r=[],s,o,u=1;if(!this.shadow||!this._boundaries)return r;for(s=0,o=n.length;s",t.util.string.escapeXml(n[s]),""),u=1}else u++;return r},_getSVGTextAndBg:function(e,t,n){var r=[],i=[],s=1;this._setSVGBg(i);for(var o=0,u=n.length;o",t.util.string.escapeXml(e),"")},_setSVGTextLineBg:function(e,t,n,r){e.push("')},_setSVGBg:function(e){this.backgroundColor&&this._boundaries&&e.push("')},_getFillAttributes:function(e){var n=e&&typeof e=="string"?new t.Color(e):"";return!n||!n.getSource()||n.getAlpha()===1?'fill="'+e+'"':'opacity="'+n.getAlpha()+'" fill="'+n.setAlpha(1).toRgb()+'"'},_set:function(e,t){e==="fontFamily"&&this.path&&(this.path=this.path.replace(/(.*?)([^\/]*)(\.font\.js)/,"$1"+t+"$3")),this.callSuper("_set",e,t),e in this._dimensionAffectingProps&&(this._initDimensions(),this.setCoords())},complexity:function(){return 1}}),t.Text.ATTRIBUTE_NAMES=t.SHARED_ATTRIBUTES.concat("x y dx dy font-family font-style font-weight font-size text-decoration text-anchor".split(" ")),t.Text.DEFAULT_SVG_FONT_SIZE=16,t.Text.fromElement=function(e,n){if(!e)return null;var r=t.parseAttributes(e,t.Text.ATTRIBUTE_NAMES);n=t.util.object.extend(n?t.util.object.clone(n):{},r),"dx"in r&&(n.left+=r.dx),"dy"in r&&(n.top+=r.dy),"fontSize"in n||(n.fontSize=t.Text.DEFAULT_SVG_FONT_SIZE),n.originX||(n.originX="center");var i=new t.Text(e.textContent,n);return i.set({left:i.getLeft()+i.getWidth()/2,top:i.getTop()-i.getHeight()/2}),i},t.Text.fromObject=function(e){return new t.Text(e.text,r(e))},t.util.createAccessors(t.Text)}(typeof exports!="undefined"?exports:this),function(){var e=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,_skipFillStrokeCheck:!0,_reSpace:/\s|\n/,_fontSizeFraction:4,_currentCursorOpacity:0,_selectionDirection:null,_abortCursorAnimation:!1,_charWidthsCache:{},initialize:function(e,t){this.styles=t?t.styles||{}:{},this.callSuper("initialize",e,t),this.initBehavior(),fabric.IText.instances.push(this),this.__lineWidths={},this.__lineHeights={},this.__lineOffsets={}},isEmptyStyles:function(){if(!this.styles)return!0;var e=this.styles;for(var t in e)for(var n in e[t])for(var r in e[t][n])return!1;return!0},setSelectionStart:function(e){this.selectionStart!==e&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})),this.selectionStart=e,this.hiddenTextarea&&(this.hiddenTextarea.selectionStart=e)},setSelectionEnd:function(e){this.selectionEnd!==e&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})),this.selectionEnd=e,this.hiddenTextarea&&(this.hiddenTextarea.selectionEnd=e)},getSelectionStyles:function(e,t){if(arguments.length===2){var n=[];for(var r=e;r=r.charIndex&&(a!==o||hs&&a-1&&this._renderCharDecorationAtOffset(e,n,r+this.fontSize/this._fontSizeFraction,i,0,this.fontSize/20),u.indexOf("line-through")>-1&&this._renderCharDecorationAtOffset(e,n,r+this.fontSize/this._fontSizeFraction,i,o/2,a/20),u.indexOf("overline")>-1&&this._renderCharDecorationAtOffset(e,n,r,i,s-this.fontSize/this._fontSizeFraction,this.fontSize/20)},_renderCharDecorationAtOffset:function(e,t,n,r,i,s){e.fillRect(t,n-i,r,s)},_renderTextLine:function(e,t,n,r,i,s){i+=this.fontSize/4,this.callSuper("_renderTextLine",e,t,n,r,i,s)},_renderTextDecoration:function(e,t){if(this.isEmptyStyles())return this.callSuper("_renderTextDecoration",e,t)},_renderTextLinesBackground:function(e,t){if(!this.textBackgroundColor&&!this.styles)return;e.save(),this.textBackgroundColor&&(e.fillStyle=this.textBackgroundColor);var n=0,r=this.fontSize/this._fontSizeFraction;for(var i=0,s=t.length;in&&(n=s)}return n},_getHeightOfLine:function(e,t,n){n=n||this.text.split(this._reNewline);var r=this._getHeightOfChar(e,n[t][0],t,0),i=n[t],s=i.split("");for(var o=1,u=s.length;or&&(r=a)}return r*this.lineHeight},_getTextHeight:function(e,t){var n=0;for(var r=0,i=t.length;r-1)t++,n--;return e-t},findWordBoundaryRight:function(e){var t=0,n=e;if(this._reSpace.test(this.text.charAt(n)))while(this._reSpace.test(this.text.charAt(n)))t++,n++;while(/\S/.test(this.text.charAt(n))&&n-1)t++,n--;return e-t},findLineBoundaryRight:function(e){var t=0,n=e;while(!/\n/.test(this.text.charAt(n))&&n0&&nr;s?this.removeStyleObject(s,n+1):this.removeStyleObject(this.get2DCursorLocation(n).charIndex===0,n)}this.text=this.text.slice(0,e)+this.text.slice(t)},insertChars:function(e){var t=this.text.slice(this.selectionStart,this.selectionStart+1)==="\n";this.text=this.text.slice(0,this.selectionStart)+e+this.text.slice(this.selectionEnd),this.selectionStart===this.selectionEnd&&this.insertStyleObjects(e,t,this.copiedStyles),this.selectionStart+=e.length,this.selectionEnd=this.selectionStart,this.canvas&&this.canvas.renderAll().renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this})},insertNewlineStyleObject:function(t,n,r){this.shiftLineStyles(t,1),this.styles[t+1]||(this.styles[t+1]={});var i=this.styles[t][n-1],s={};if(r)s[0]=e(i),this.styles[t+1]=s;else{for(var o in this.styles[t])parseInt(o,10)>=n&&(s[parseInt(o,10)-n]=this.styles[t][o],delete this.styles[t][o]);this.styles[t+1]=s}},insertCharStyleObject:function(t,n,r){var i=this.styles[t],s=e(i);n===0&&!r&&(n=1);for(var o in s){var u=parseInt(o,10);u>=n&&(i[u+1]=s[u])}this.styles[t][n]=r||e(i[n-1])},insertStyleObjects:function(e,t,n){if(this.isEmptyStyles())return;var r=this.get2DCursorLocation(),i=r.lineIndex,s=r.charIndex;this.styles[i]||(this.styles[i]={}),e==="\n"?this.insertNewlineStyleObject(i,s,t):n?this._insertStyles(n):this.insertCharStyleObject(i,s)},_insertStyles:function(e){for(var t=0,n=e.length;tt&&(this.styles[s+n]=r[s])}},removeStyleObject:function(t,n){var r=this.get2DCursorLocation(n),i=r.lineIndex,s=r.charIndex;if(t){var o=this.text.split(this._reNewline),u=o[i-1],a=u?u.length:0;this.styles[i-1]||(this.styles[i-1]={});for(s in this.styles[i])this.styles[i-1][parseInt(s,10)+a]=this.styles[i][s];this.shiftLineStyles(i,-1)}else{var f=this.styles[i];if(f){var l=this.selectionStart===this.selectionEnd?-1:0;delete f[s+l]}var c=e(f);for(var h in c){var p=parseInt(h,10);p>=s&&p!==0&&(f[p-1]=c[p],delete f[p])}}},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(e){this.__newClickTime=+(new Date);var t=this.canvas.getPointer(e.e);this.isTripleClick(t)?(this.fire("tripleclick",e),this._stopEvent(e.e)):this.isDoubleClick(t)&&(this.fire("dblclick",e),this._stopEvent(e.e)),this.__lastLastClickTime=this.__lastClickTime,this.__lastClickTime=this.__newClickTime,this.__lastPointer=t,this.__lastIsEditing=this.isEditing,this.__lastSelected=this.selected},isDoubleClick:function(e){return this.__newClickTime-this.__lastClickTime<500&&this.__lastPointer.x===e.x&&this.__lastPointer.y===e.y&&this.__lastIsEditing},isTripleClick:function(e){return this.__newClickTime-this.__lastClickTime<500&&this.__lastClickTime-this.__lastLastClickTime<500&&this.__lastPointer.x===e.x&&this.__lastPointer.y===e.y},_stopEvent:function(e){e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation()},initCursorSelectionHandlers:function(){this.initSelectedHandler(),this.initMousedownHandler(),this.initMousemoveHandler(),this.initMouseupHandler(),this.initClicks()},initClicks:function(){this.on("dblclick",function(e){this.selectWord(this.getSelectionStartFromPointer(e.e))}),this.on("tripleclick",function(e){this.selectLine(this.getSelectionStartFromPointer(e.e))})},initMousedownHandler:function(){this.on("mousedown",function(e){var t=this.canvas.getPointer(e.e);this.__mousedownX=t.x,this.__mousedownY=t.y,this.__isMousedown=!0,this.hiddenTextarea&&this.canvas&&this.canvas.wrapperEl.appendChild(this.hiddenTextarea),this.selected&&this.setCursorByClick(e.e),this.isEditing&&(this.__selectionStartOnMouseDown=this.selectionStart,this.initDelayedCursor(!0))})},initMousemoveHandler:function(){this.on("mousemove",function(e){if(!this.__isMousedown||!this.isEditing)return;var t=this.getSelectionStartFromPointer(e.e);t>=this.__selectionStartOnMouseDown?(this.setSelectionStart(this.__selectionStartOnMouseDown),this.setSelectionEnd(t)):(this.setSelectionStart(t),this.setSelectionEnd(this.__selectionStartOnMouseDown))})},_isObjectMoved:function(e){var t=this.canvas.getPointer(e);return this.__mousedownX!==t.x||this.__mousedownY!==t.y},initMouseupHandler:function(){this.on("mouseup",function(e){this.__isMousedown=!1;if(this._isObjectMoved(e.e))return;this.__lastSelected&&(this.enterEditing(),this.initDelayedCursor(!0)),this.selected=!0})},setCursorByClick:function(e){var t=this.getSelectionStartFromPointer(e);e.shiftKey?to?0:1,f=r+a;return this.flipX&&(f=i-f),f>this.text.length&&(f=this.text.length),s===i&&f--,f}}),fabric.util.object.extend(fabric.IText.prototype,{initHiddenTextarea:function(){this.hiddenTextarea=fabric.document.createElement("textarea"),this.hiddenTextarea.setAttribute("autocapitalize","off"),this.hiddenTextarea.style.cssText="position: absolute; top: 0; left: -9999px",fabric.document.body.appendChild(this.hiddenTextarea),fabric.util.addListener(this.hiddenTextarea,"keydown",this.onKeyDown.bind(this)),fabric.util.addListener(this.hiddenTextarea,"keypress",this.onKeyPress.bind(this)),fabric.util.addListener(this.hiddenTextarea,"copy",this.copy.bind(this)),fabric.util.addListener(this.hiddenTextarea,"paste",this.paste.bind(this)),!this._clickHandlerInitialized&&this.canvas&&(fabric.util.addListener(this.canvas.upperCanvasEl,"click",this.onClick.bind(this)),this._clickHandlerInitialized=!0)},_keysMap:{8:"removeChars",13:"insertNewline",37:"moveCursorLeft",38:"moveCursorUp",39:"moveCursorRight",40:"moveCursorDown",46:"forwardDelete"},_ctrlKeysMap:{65:"selectAll",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{if(!(e.keyCode in this._ctrlKeysMap&&(e.ctrlKey||e.metaKey)))return;this[this._ctrlKeysMap[e.keyCode]](e)}e.stopPropagation(),this.canvas&&this.canvas.renderAll()},forwardDelete:function(e){this.selectionStart===this.selectionEnd&&this.moveCursorRight(e),this.removeChars(e)},copy:function(e){var t=this.getSelectedText(),n=this._getClipboardData(e);n&&n.setData("text",t),this.copiedText=t,this.copiedStyles=this.getSelectionStyles(this.selectionStart,this.selectionEnd)},paste:function(e){var t=null,n=this._getClipboardData(e);n?t=n.getData("text"):t=this.copiedText,t&&this.insertChars(t)},cut:function(e){if(this.selectionStart===this.selectionEnd)return;this.copy(),this.removeChars(e)},_getClipboardData:function(e){return e&&(e.clipboardData||fabric.window.clipboardData)},onKeyPress:function(e){if(!this.isEditing||e.metaKey||e.ctrlKey||e.keyCode===8||e.keyCode===13)return;this.insertChars(String.fromCharCode(e.which)),e.stopPropagation()},getDownCursorOffset:function(e,t){var n=t?this.selectionEnd:this.selectionStart,r=this.text.split(this._reNewline),i,s,o=this.text.slice(0,n),u=this.text.slice(n),a=o.slice(o.lastIndexOf("\n")+1),f=u.match(/(.*)\n?/)[1],l=(u.match(/.*\n(.*)\n?/)||{})[1]||"",c=this.get2DCursorLocation(n);if(c.lineIndex===r.length-1||e.metaKey)return this.text.length-n;var h=this._getWidthOfLine(this.ctx,c.lineIndex,r);s=this._getLineLeftOffset(h);var p=s,d=c.lineIndex;for(var v=0,m=a.length;vn){f=!0;var d=u-p,v=u,m=Math.abs(d-n),g=Math.abs(v-n);a=gthis.text.length&&(this.selectionStart=this.text.length),this.selectionEnd=this.selectionStart},moveCursorDownWithShift:function(e){if(this._selectionDirection==="left"&&this.selectionStart!==this.selectionEnd){this.selectionStart+=e,this._selectionDirection="left";return}this._selectionDirection="right",this.selectionEnd+=e,this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length)},getUpCursorOffset:function(e,t){var n=t?this.selectionEnd:this.selectionStart,r=this.get2DCursorLocation(n);if(r.lineIndex===0||e.metaKey)return n;var i=this.text.slice(0,n),s=i.slice(i.lastIndexOf("\n")+1),o=(i.match(/\n?(.*)\n.*$/)||{})[1]||"",u=this.text.split(this._reNewline),a,f=this._getWidthOfLine(this.ctx,r.lineIndex,u),l=this._getLineLeftOffset(f),c=l,h=r.lineIndex;for(var p=0,d=s.length;pn){f=!0;var d=u-p,v=u,m=Math.abs(d-n),g=Math.abs(v-n);a=g=this.text.length&&this.selectionEnd>=this.text.length)return;this.abortCursorAnimation(),this._currentCursorOpacity=1,e.shiftKey?this.moveCursorRightWithShift(e):this.moveCursorRightWithoutShift(e),this.initDelayedCursor()},moveCursorRightWithShift:function(e){this._selectionDirection==="left"&&this.selectionStart!==this.selectionEnd?this._moveRight(e,"selectionStart"):(this._selectionDirection="right",this._moveRight(e,"selectionEnd"),this.text.charAt(this.selectionEnd-1)==="\n"&&this.selectionEnd++,this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length))},moveCursorRightWithoutShift:function(e){this._selectionDirection="right",this.selectionStart===this.selectionEnd?(this._moveRight(e,"selectionStart"),this.selectionEnd=this.selectionStart):(this.selectionEnd+=this.getNumNewLinesInSelectedText(),this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length),this.selectionStart=this.selectionEnd)},removeChars:function(e){this.selectionStart===this.selectionEnd?this._removeCharsNearCursor(e):this._removeCharsFromTo(this.selectionStart,this.selectionEnd),this.selectionEnd=this.selectionStart,this._removeExtraneousStyles(),this.canvas&&this.canvas.renderAll().renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this})},_removeCharsNearCursor:function(e){if(this.selectionStart!==0)if(e.metaKey){var t=this.findLineBoundaryLeft(this.selectionStart);this._removeCharsFromTo(t,this.selectionStart),this.selectionStart=t}else if(e.altKey){var n=this.findWordBoundaryLeft(this.selectionStart);this._removeCharsFromTo(n,this.selectionStart),this.selectionStart=n}else{var r=this.text.slice(this.selectionStart-1,this.selectionStart)==="\n";this.removeStyleObject(r),this.selectionStart--,this.text=this.text.slice(0,this.selectionStart)+this.text.slice(this.selectionStart+1)}}}),fabric.util.object.extend(fabric.IText.prototype,{_setSVGTextLineText:function(e,t,n,r,i,s){this.styles[t]?this._setSVGTextLineChars(e,t,n,r,i,s):this.callSuper("_setSVGTextLineText",e,t,n,r,i)},_setSVGTextLineChars:function(e,t,n,r,i,s){var o=t===0||this.useNative?"y":"dy",u=e.split(""),a=0,f=this._getSVGLineLeftOffset(t),l=this._getSVGLineTopOffset(t),c=this._getHeightOfLine(this.ctx,t);for(var h=0,p=u.length;h'].join("")},_createTextCharSpan:function(e,t,n,r,i,s){var o=this.getSvgStyles.call(fabric.util.object.extend({visible:!0,fill:this.fill,stroke:this.stroke,type:"text"},t));return['',fabric.util.string.escapeXml(e),""].join("")}}),function(){function request(e,t,n){var r=URL.parse(e);r.port||(r.port=r.protocol.indexOf("https:")===0?443:80);var i=r.port===443?HTTPS:HTTP,s=i.request({hostname:r.hostname,port:r.port,path:r.path,method:"GET"},function(e){var r="";t&&e.setEncoding(t),e.on("end",function(){n(r)}),e.on("data",function(t){e.statusCode===200&&(r+=t)})});s.on("error",function(e){e.errno===process.ECONNREFUSED?fabric.log("ECONNREFUSED: connection refused to "+r.hostname+":"+r.port):fabric.log(e.message)}),s.end()}function requestFs(e,t){var n=require("fs");n.readFile(e,function(e,n){if(e)throw fabric.log(e),e;t(n)})}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;fabric.util.loadImage=function(e,t,n){function r(r){i.src=new Buffer(r,"binary"),i._src=e,t&&t.call(n,i)}var i=new Image;e&&(e instanceof Buffer||e.indexOf("data")===0)?(i.src=i._src=e,t&&t.call(n,i)):e&&e.indexOf("http")!==0?requestFs(e,r):e?request(e,"binary",r):t&&t.call(n,e)},fabric.loadSVGFromURL=function(e,t,n){e=e.replace(/^\n\s*/,"").replace(/\?.*$/,"").trim(),e.indexOf("http")!==0?requestFs(e,function(e){fabric.loadSVGFromString(e.toString(),t,n)}):request(e,"",function(e){fabric.loadSVGFromString(e,t,n)})},fabric.loadSVGFromString=function(e,t,n){var r=(new DOMParser).parseFromString(e);fabric.parseSVGDocument(r.documentElement,function(e,n){t&&t(e,n)},n)},fabric.util.getScript=function(url,callback){request(url,"",function(body){eval(body),callback&&callback()})},fabric.Image.fromObject=function(e,t){fabric.util.loadImage(e.src,function(n){var r=new fabric.Image(n);r._initConfig(e),r._initFilters(e,function(e){r.filters=e||[],t&&t(r)})})},fabric.createCanvasForNode=function(e,t,n,r){r=r||n;var i=fabric.document.createElement("canvas"),s=new Canvas(e||600,t||600,r);i.style={},i.width=s.width,i.height=s.height;var o=fabric.Canvas||fabric.StaticCanvas,u=new o(i,n);return u.contextContainer=s.getContext("2d"),u.nodeCanvas=s,u.Font=Canvas.Font,u},fabric.StaticCanvas.prototype.createPNGStream=function(){return this.nodeCanvas.createPNGStream()},fabric.StaticCanvas.prototype.createJPEGStream=function(e){return this.nodeCanvas.createJPEGStream(e)};var origSetWidth=fabric.StaticCanvas.prototype.setWidth;fabric.StaticCanvas.prototype.setWidth=function(e){return origSetWidth.call(this,e),this.nodeCanvas.width=e,this},fabric.Canvas&&(fabric.Canvas.prototype.setWidth=fabric.StaticCanvas.prototype.setWidth);var origSetHeight=fabric.StaticCanvas.prototype.setHeight;fabric.StaticCanvas.prototype.setHeight=function(e){return origSetHeight.call(this,e),this.nodeCanvas.height=e,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 dc758bad9c521e97fb0a0b0fa288b87eada9c36a..807e2c508494187bfe6dd4c6072986546a2cb34b 100644 GIT binary patch delta 55312 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 JsB8>R0|22Q;WPjM delta 55212 zcmV()K;OT?w*%p}1AiZj2ng4*#Zv$SW?^D-X=5&JX>KlRa{$!6Yh&Ctk|_H9{0fOP zW0T$NmmFs^Y|(uj*~xg=F?KgzwUd{M7h8NYn{c7KoE&R6w<#TTrs>VlQw zyk6#6_>VHr_O8+_U8byv>x)&o-29{buf5)A)Z5?tE;%pKIaYO)uQx?{aarvhjK|*$ z4#tzO!o8o0G^^5l&;R$jNH=@`C)rdbyAJn$NN&@sy`xK3WSivo04lpqioGRO7W1F` z`@3salxdzt-hX8H)$ki{JFPZrmM@{F>%6GS{n)Fs1zV;WTX;{N_#%2}R1<`v&?2AL zS1hZnQX=&x%@+BMkv8*r4MSNnmLH)=;DuuT6GW~21^c5;3+8+OC>Qya7Yymw_YU`8 zy*oNS`RVoEWp%ZBaVY+>Wbxu~#DC87#RdZ6hcbA9)qk$l+;Cp7q+)-kL_biu)ABg4 z=a(PqHG+pNVlU4sj47+6sJt}Wvn!GxuUAYTZd$%ge`l-BkFbPd0k?1K<&qVfUb zvZ@b%d-?wLt4}YFkKe!f_UGf*AL3JQk(TRKvhhN%Dw3>R=EW6!FVodZ{0#DSGEb|G z3>L6-;eWe{Evq8`ovDw(A}KGEqDY#w!3w%DPu6C{Kk_tdVy@DP6{{3}nmD_S!A-iT zF1@pGS!Z)t;F%xX$a>uc(i3nP?jaTrtSUJ~nwYo?j0l1KOy*TRjK^UbXJTyA;xL^S{eF-^AN9Tg zO5R$%BHDxeT zQ9gS|HN0Fb*rJ(o+^_nmVV?p*E8b<0?>%i;N_c&y7dzc-S(U0#IM>INQIgDEU2`dG`41XY4 zv>})s7SjwN7_%YZdv^Oy+boC3zjbAE`MKNt*ebb-Cg-LoVX3k^q=fA3T?wV5Ecn6`A2n4 ztrix%7)-G6)q2Hl(?@o+V2c`-k~z5|H|xhh4XOHOdcY4N*ht%O9Bj9t-cMW@Rs2Iz zT@K4X3Yc>Kom5G70IP!nKfM`Ez8O!oGdsSs4sGXhYqmynfMsG^s9llau76;(sNN?) zIbFTU?8PgJQeT#<9Cjvs7L?r&dVV!v{Yen?p_&D|C>R6U?|rgJ6ZfRBUIEB}ryu99 zcnN355oXLQpf7&{VyO$CapvN#%=GE&z>SR?SAh1jcu(|D} z12)|B;Ao&w(Z^6K0Oe=wMt@SM)V5!Sc@PZYXi!ycLq#&WyQk1>jk*uTCfU zv4NBMK*l_ym>_z%6nuPj)-DPk&(CnfW^k9Oj%6pK_QC@I(JBaF;Y~(9qXwXs0izb6 z;$T|Erx`_t1N@zc--ELdf5vBUM2yd-d@6Lh(gcowcN;P6?FN3H1Al(dh$@JV2gUF< z#D3!!fCDn*-=()~;a-gEq$t^Ut30XvAM2}gKwm5viV`q2F!&`*68lb+ZEx=V39b46 zSS4lYZh{%30SX-G3Bb%(Yy}t!j+Hr3`7bMfjP3rsUbEsTDFKpw3DZe)84`4MnXj(d zk5EGiggqQc98ucwk$;YeiSQDHlUNLr)}kF;`QFge&k@)G?Ec=kvZ=$gjK|XwPR@S6 z4AM9~%}&d+GdTy5 zz?#DS@y>P{eCaI!0eb=9%CRE1?dztW!XWdqdy_sxP;S&j|pm4jbwlq?{c_cl}J0n@SZ%u zO9O^r13+urAmV9e4S|spGX_XxToie|{_xB9f(u|nPvCsHXeCTuOlB~P8oq=>;Crlz zU=S5CAu2JGnKhF@?Xv1aUKewQlJY}s(;I$iX8TLm9lns0KD0gCwx%D zH5^tswgM>OgG3m({sNd`@01f(Aq3*4t{h=j*+?gQ4x5I>&%IpUzPAYxZ9ilFGn_366b|H~ziurF3H zh$3D=fz!pzL+;0M?nNH2$~%Lqp)zQB0WAYQtnvaH2kMNl$WfAAC#6^rPC5ZrAM0RD ziDJGtr&>H%ldu(FogV?&$ZjjOzrX)SBv`IR=lNHt^Diu854IK{WI$ow1$|Ac)125b@Dn@c5;w6twf(0SA?|xm`>g-e z3xA#lTfcy*tl$Kr%F2f;^RAOs&Aia4v}`I3_b7v`8wmCJDqV|ZVvz`y+#l8OoB{eL zyn)*Ri@@fnFa^JH6<^h>DqXKOiVy=56=s#$bO)c5(^JA#L|`GobQYcx(M1#(l1>l- zdoP^8M*+Dj!fcqk;<=GH43QKha!Sjc!hcy}(E`t=C19Gn6yc{O!hti*Au-29jHn?( zCMNKmKw<)kbw5TT;xswy74Qerp!RK;0e|=t zB;bfBbAy@UJviTDY$CGiYskaCEWksLvOSi=&D zzfva+rP3mZlS5c0a5$!L^6gK8b3jqQiv`}lGqi2lj)s8ms33K z!X#XVt8gA(0s!DFrDIp)$U#pS@;>E>0pA3NbzJ%@ssM@t1XDbQ{Ppm5GJk+SW4PQl z-+lPr;P-~d%kS_S?oNxr@ZkCM`Ve7%EunnX-0b~pfF-~pf%L0*aK$rR#KY&*#JG>` z1cNK1;*Ch&VDe@X^sn^(gy$NwfN~8sA*Kv2g7C&loA9&=roE1D2Ite)*jMb*WcIor zAM^yTA$t8n#N$w251JI-<$n+2hRxCy=L00?rT=>5i%h-Y^Zsx=hRaV7-s(8z7}mq_ z;fLw5#3?_<=l$c}>(Phs2)_K|{v^QA^!D@^kkLiB34aWaXlmAYyFUi<1n>37muFjT z7USFSwqaM7avN|WNFp!R^EFON5GD=JpoWFj@C<6a?y6B$f#S!U6MsJeYg@(3o?i^g zpr7>obdVz@wd7xegr@*Wwd$=#e$}gj{=7FI`B@K2U-n{HBOws00N6`yXNU)2NkYE=rw|@<^a)6c~7Ww|^+&h)FcPhDe<_#2S%nFJSS~qDqZYh|S{~k5py#rj&tbaMU>CM9raoV5v zZ+e%o_E>)r9z%E?{utjv+#1%|G2~iIwSmN^*S*&OrVrr-{C{rX_qz8ZgpVNnBZQA2 zd<)@Y2;V~Z_>A6Aww!Z)w+$=&lf^{SYxF-p?uCWUvl}AG{t_;TZH&#&;{wmd8h+qN zOyCDj#3lT|Ilh9Qug+kd6>y*fpo`P5&j7-yk2tG@$wSna@K+qU-4?Lj7KdwzsuyzC zUBfl3dA$hNr+*845CSUZpD9pqb%6xA$iTwuV9Vb~9H_VQH5MGR7EO2%w8#yh0V~;^ z@-QdLg9wj8#Lke61L{)t4?+N)NXBxeI0S-*WuZOA>8zWSVC&}Uyof8fXW9>3k0^L( zluNY>Al|Q;{;;P#iWTa>A4~uw)eMmq+;}58f^cgE4S(l9^F=D0L&#x>MNmB1*%|d* z8c_J!v{xh%F=eLw z`XTQ8{2b5JGI;Ug1(z(onj#kbzUIwlat37CejFDwC>0f)YlA;L z=kTX@AAjB)zxn0$r#C--_vXhp$0tVWkFURfX{ACVK2TBj_k)Q*I~v;?j{>+J1cVoh z7jb5G9BxK0Vx;>h^Hp-|X9KMq+;eG90QHv<^@k)9z0|@*6evD?Ymtan@}dWmZ4lbi zBbYsoi4!TYxr)sPHM;v~lOW&I=xrSn@r6LVLVsZp?|d131&+R4C2L1NAU1YhaL%k3 zV7oJt0a7%b@saNln_Z%}G3rwDy5Z;?yJp44(LIX)A|T<4ZMwGK1*kwWnnmyS$By2W z`4w|?4x|4CeS4^DW7#$53ZrL1*8-!2j=9A{&$#c{J(bsM>Gq)Ym6Z zGJh_GQS6>){xs+4E>DQtOcASRAwkw9tnp$JXm8MfZ#X($8?)T58{K5n2 z{eA{Vjte<%IX>T)C?Pwn>`myaqm^zB1%DLJRhRM6&PN}qp?_ej_kuG#<2!a+v1}2saK6ej=+3S#G!??k ztylO^G8**#VK5tAxKHM4R+%iQ$n*50x-!r4PR5lFhqK~cMa?H^xO)2p zI_f=1uGUj8XktBz{iDt+Bl;=Nyv|D_`jDbmX5JSRd4Z8z!Cuxl&P93!tKS)~KYyH< z!VRM4-;i5!`*M8NABCRYq>BGDC0MJBKZ?b7@>L9HI9aC^aads0u@Zvp*Q-@~)$Jfs zfTot*A1#T9LfE5P9owlR-#HL20Edp0rnsQH`SC-n5Q~JJ1Ys`Myu<{v+yzQrlH)7b zG$q`*=k(A(Vi&OQO1S!D^Q7|aMt^{e*hXJgXHy5avcz;d-Mo)7Y zJp^hX)<9odpig0*n$rAGtAjvitl~qBydx!tOX9H>ejVng$(bexR2y`BjB7Im!1Mvf8^g77*F^&MsJ;=+eW}FXVBy}$m#_$E4CKP$OPGxF95fP1MHzSG zqN$M+4V-q+-Za!BjuuD6w0|+LNMH96yQybhHCzv+fo4`|$Af}}z;5jCx5SN7t zg-o3*cxQ2vDP?ep@tRro)V%?4ZHfn&F&Z2_E!RptPD1(4hf9*2Ye&aTX?)_K7n65O zS4ASpsz=1eswg19Xh5>;K3h$Wmu77ctN!fBhWBA5O zuk54W{F&mg-*al_zRrHn@|!I9^JrMHvhuTr(%-68Y;q*!`nkJIvc-xOa5UZ&Fzamb zHxZFjHj6h`wbxyNZ%>>cq$hMs)MH4Zw|YIbyB^NCn8WIO@&x}PlR@xuM9?DR3;Wrk z!1swpOgHQ5Nz;`D=YJSg_+S^iGEe1;V+B*kC?B7b3MDJVt0$~AHq#>_Vm^eaEy(a; zUgWFQTehr@^R=&uQQqA~*KoA;Qy9{+3OCUe4^{bE>+OXpWX7Z@q(@o|K+bwI4=Bm( zf-OkXft6k)(n?R!%CMB+8irh)@!3rL0&oYu_ANiNv*7+7$$#w#{|M~siRI>r72G1B zxxEFd{zR`>gP~gQ_H;*q02kT=xQdPxT1$0ZbjO(PN{y#lnGHgMmAv$bCV5n&=U=NR}-!tR76 z;@1`Jj+NkXYLCxh9gA4=sj(lFG66aj!Uee;3Y3aWNPjwOw0V%7EA7sOO(mRli84xV z@bUgm=THEEgg;VAWq&R@ekVR+C9}m&dCOP0nXuk+}iwu#X>H!_|g(%#AT=w*Hiwg;KDuAZw7Q--^&HY;W*(CkrAf(cHf(jcbyM492d zERUfl{n(r0E~py1S1Ohf)k_qLl%fzR(Z{mqe}7!eJ`QIe7rkJF!V^GIHjGO@NcbOth#f2tsaq}Lw3LMYmTpe4r8fD^f_W){KtY;vUWC|Rv96M)u7AO46s;44M|p8obRIO_)= zgMSeaP%gPOI9g|=vDr0#lG&{)WZS5KC2r?8*Ga?Vstc44`GB#UNv%Zy(k$O5o4l^@ zx;y-5o?pci6kz29tr%!913ImG5fA?g|C@O*0W?@&b_o_$Z!#YDy#R<42^{&MSV$>! z67Tjr8W!VTcP-53FEQTVnC-j?v^8JE1b@x!r2rdOtb=biZ%~IRVl7hL5CZC0L@cnk z0$g@r& z*0j)vuy&<|#EPO~rT^4qjrGtBaz$_*?pJ|zUC?wF+E@l}kU$z>CZq+p7!pb{;(v2P z6O!|PbeXP@@JDqqyyya64t%rU2CGr+vgOW|1aJWRq7b zyirB4yT<*U2kB{kTA!WuV}H^-c>_3L z1#<%A@MH|PHgyTB00G)dRPm-@PQT6JY=b@=5oPfnhy`1%polv%A~&+!eaU4ZzYFuB z6m-Asm-I96B?%=aQQd!WyairTfOlHE$ejr&Y1J%i^MS z3!5W4z`a%m8lRim+0Kb7Nq>X8Z3fhLVH~3Tut&x!*ISoz7I?NRAxpl`v%w(1CoB}8 zS3K%!D+IcxEgZv^NxiCmN!g9sl&(ZBMt-%1UAUlKI$OC9^UtY6P9k2fBfCE1uy6S7 z`x(9U8b>~&8zYL;EV8Zh7V8(L;B%w%I-8md=-=6`2Rhhs0xGv-CA zky_M3YTWuEV!HkQ%zq9k-)2fxN6&-p1fh0#Oqa6#RfWe5pN`9B*&d>UAv#=xAhbB+) zsJl%!aaMl2IZiH+NPqD?v`pd!C>vKiMA^fMl&+Ecg3`^?Lh5};{7 zlnXZrYKOm#LWvJpLZ5sq2|4iC1~)*`PU9NDmEz4$p=Xm2=tnoV6o$CF*QBVn4GXSm z7G?%TRhWd=eGaQ#Tk3jJ0jelt5wa5as-K=q5#fhCP z%Dr1Ifi8}h9m)JouzFyTDYa~W^l>J5^(>fqPhhFfknGhT^7VJmf;64(QaEu^V)k$b zOFFz_)n&ez$q!rT;QQCd9#AQ$R(K@l9i~}-C97jN#lxg|#@n?pgS*;Tgz;B^dvfH! zIm;pA2u1Oz8-I{9;g6qUNvBBD!hWjI!ibK{fZV|0YRLh;dgidMd^8z?N|QcS{L{M+ z$8dw^-#;HCPqfDS%X{`m4Z!^y^oSL{M;bF(H9$ERFZA$nD}{3$hBUez+}zv@Pz7dC z7jQz)bKE)f$cp@uBoL2|Rh!Ly+I}OaqaWg~*{?#t(0}_OMV-uiSq*>v;qBj!kAFfw z&*Ms#w^yr!|7Nk_v*EbAC}ygvwE)+)VbxU)y;7m(6;ev#q=!SvC!Sx!{6WHi(?tcW zDP-E4>^Z7kpkSpWYrfV>+>;chJcV2>`0ALin00`j0;;=!8O37WnM2()xHHS2vNNlS zCV@YC!hZtfeL+J!ZK&DVeG#EQ^b>EcOOz-xtXgnALAj&h3VwgzCq@5Pu#NE4V8caS z&{Dm>e?F#XuRf`l#7H|F(MGejbOK2UTtF%#zR@vXLOM%I*lk*dMpuUmcxF8%AJ0Zb zqpWZc1pN#URk*?}3pC3wq{2oAI8rS#25v3$*nfj9WTeY*G=ZU9LO;$o6u!To4^~qg z(Fd%7Ze#pYL#TUegjjCDNXY%?FUnaO?cRDQC?>070vi}i2v+k`G%;e_m9bXmH+cm z`G4}q)mC<8({`I#1TgV&dd2b@<=rOi+34%B^|qc+T?_~Z2gbmLsEs(=d9dmWcaI%v z$}%(9TzHkwMqi=IbvE)F)gk_Y`@pY8u-EPqlogAra2;h~iKduLaXpO%1^bJaUgtOd z0o=FI;7B|PG>s6y>SY7i5J6A1IAX)KDSxVGbv^6(&|lbYDCEt0Xu(7$35xbuM{zMa z2-)FemW>Xu2o$O!{Dzta@d2;qz^Ep5wTm?cvI2+ll7<(|KK9ta>}CF_UQ#~?R!5;O zv#a$3T{SzKJP1$+P?wMFt_!dZ;I2L!k*cC|NB7loY8BNAUbfrBeyV1r8XVLSSbvkX zZjT-nA7(IAdx3K(8l@M`(#5RmXHecBXf+I=3T)qk{&i>jO-;TvA$GrbulU^9O%4Vu zpc&Hk-IZ%iH=1vgfm~rWur4|$NS0Ge%_z6owZyc!64fx-a@0zaOV0-5xi9n!<@@?% z_;2IM^KXDk7y~(w+8Ql;#WWkmrGJc`sOWw=tx;w#E_=gg{AdMg!B3#>I?UzaH>mt2 zjHe9xMbn2HUuZeX*I(HO{_0ETa;5hnn^q&hswCf zUSi^4obAfQzv&<`@oxh7x1S8>eeD(F^_PKebRZKB+`#KihR-_zxR>F~kAH{HdkrL` zWqUw=W}hlquN*ARQ7vIqsN%YWfob#cq0u{Sbji@Fi==%?PfLt82sOm&`zb2EvO#Jr zvfIzDP{+Np(tc_$-s8`!*MXjWsJsU`o*z69nx0$Ox|IogVj}M!+Z%jvx1Xw;9!RbGTs*n*fHo0MPqO9hvyWLR^Ef*ftLBN z&v znqKjUB2@4w@ZqT$D+Ehp3=om4+-R(Pb9-u|k7a+vpMO#tlh9kf#^irsdzBI4=8OlS%yV7~<*J+ua<4AomR00El1ivrS#e!wtY=08%kI9tQ zP~<0r8}$COk6IN}RZd3Ae&w&w8HWj);hyoA(TGEmWLn9Zx)*tKhVo4wcGW{kmoG7K zB{`?F47EZ1#(!vE5NQVdlwj_D`s7Jk{+Rsem%%KHN`qXt6w?x+d3~Cl-QO$G?F52n zh5%83=0Ve}X50iwcGieW)WyoDxAbw7i8F?f-%+7SU}#ZTm&VsaG8Fcbq*qFq@e3IM zT*X@s;j#d5d4F*Zk>P?N7en@{ky0}663wHY5W(`fjenYZQlpv&Gn6C}Q6>CY4d%(Z zG@{S*)q?)8;(mqG2fvf?`2GO?J%fK=!N2G5?`!z?Z}9IM`1jZGnAh=f(GS+Q{w(^a zT0Z@__&7Z42biJn4^jThwBRhDM8AQ zQ&E2>tA92zpKon7q|j^{nGq=IDQiM~7A>_zZnaANF1boqo45|boZ`^Z*xz_VIp0Az zKyNmQ^1!;7DdCf;rphZ7^XjA34iq$*FK=0x%-2qc67wJN;c~jojc%L zT_{8s8cZexqBv{SOi7XNPsYxbz$yt+q0}Pc_fpz!!9|4o@jbhM^V9c!`}lF_^$Xl+ z_@a{s_xGut2UONYvk*U0uKM#%c(*&?Xc{)Ff zFMqenzL9bNZEUdpQL|#hpGk8v9gWAQ7wE>WQ3+UCVUspH3evwNqiZG*Z()7^9$gk} ziEFezhl7rrU2A3ZP)G%~r=76j2{oS|T{bQahNP{Fk{PI@4EHnNF5S3HfLc(L%-d_s z1$zCm?}d9_KS$X$k4Mv(a~(G&hf1DqmxIsV=%PKW81HrqyX7Yt zYK+pY&hQWnSzLu^rUDL8IQ)P4o}}kcX#MHo8m5y$JGZen_VzaPH(kWuQ=sym{=^f# zy{F+*vT=s-R82`%H@V@n@Ts@QO`X}vJQmYMGe2i(RSF>rG@1J@`x!RU3#k4uMPp`0 zH~!m=HVetlQxt zVS>1A2oRUwmZ)`OXnAsxSUM1gt6t*Nl4~6$!I$4L=On>(?S1ih6Ff};`i{U2NVu| z2N1_7kwUWoP8BNf5yigrq zy{4gSYRKy^`rf_QU(?@9`a7q;OZvMa{e~-%_qy+iuEST*^CB@5)GR3Us*^&vp@u1d(wDGJzSJBmwajedhktS;~8X)#~1`*ptBT;v)3 z;-PrYR;zSfvVZ#mmFOvksHS^7jRLr5XP=7|$3gPRnDq4VQ{M=RY^$>+nN(JH=P8MZ6FkxFSHaiXZd} z7i47c)_;sTI72g~M%1%2v_@(~eT8liZk{~3e)8l7u;KO0-^4f2f!9F=E)AkILXqFSSd-k|;r?SClv*QD_%PG-E6HZ?L7xt{wO_c0}a3^^G!B?mfxW@*MO3IJ;SW$hvqBS0=Xm?69`58M?Kn>stKy6vVv`y#;A()Du34jU`lJnCXh(!gDkE4%0 z;mct5vG;L=;2}Q*xqL7Z9uHKe?dXDQl63F_nE)+N<3;ClMx{MS$(jSa^xXNUziowI zg(;)UtrVw*6H(4u8W&x!C@_t^DS!Nf;u&|%ia#WlZCZ;?ZEMluMF5RPYjs6b7f{$W zUci^|13khjPZOYTw%b6mkkx7OA&4B;ussuUg4tWk69*B{=ZJ&*m; zR_j7iO$gx{>H$xlG=-1J*9@SghqM-6z54-QM!46d*dtv!55m}WNcPPtHGhkd(!H~s zE&t=G`22Vl^ky$cDNX_>H22H<`}R1Lf8f^r!Efbl$OJ-37jzb~hLv3D4l=kIQpo95 z`8(mKR%128exX{n$o4jn!EYZkoLyQyVr5;R@dDie6^f3`F6g9Z4&RE%JV#W3o=8Qoq1sRK|XZ^#|15-NDyDom|an5tFCzGUG!)>YcQ zu83abKeRA}nxya(^ihdLH^o!$`cy zHl$(Ik59e-Ett`Bws&W;rlUQNs5x-q3prmsfA=ospLS zAI+-DbBBy8oIX9IbA;4ddB;XTz~lRdcesCg^y=mD%Tu5@L+|YD1=MsnqUV5Y+U69S)so~F7O$;rqSG`Z%AM@PeKQI;O>B~fX@6IX%FDFn4^UGR(dsjs zg6%D9LuUlI0mp#(gzeVP?6*^eU1)tdJ#5M+FMO~RtOnv+W@rjryIhf;9Cu}GbUq6S zXDA&x%~fO}F(b{!C7b{LX89`5*kk76Q|F+B8wkd+Wx&iEpg#3SV$}+QSzEZ8#U#X5 zjv7=(eSs^jV}A;v-E>i{TEC5>-?2(GNB-F9l%01@DAwCzmI3gyrl*wE~84t_p~&qV zipZ|lf5@x9*iropE&B_Rdq?#z^y*)T-m_wDv0_~t2T;f@$Cvq)25KeL!)F>^{PI)MuU};E`JE)v}$~)m!kt$FGmMdXVzU6ch8f` zIzy;32+hb%h&vf8N^T#jD7kf1BqLQt$`*QC)m;n?$oW1mLplDCj2sPUU zeUn$A7rqqAo5Xbi5Z#v(Hg%T9(V;0q2xVXBy>Zt$C;E(LEow#SuZfok7nH{wcyCZ> zy?W9!`06CXJK^sIQNFe3CLksDy?06y5{UsZEQP}dyJ6MQF$R4mY%K)tb5!wb)M&&5yt z;k)I-fHQ)*4-U&qyY(7Bie`0I@VWc4rmk)rZ6$0 z5##0<-I`cAV07<@cDuXM>yYev&wslCmSFm2S9%iSjXqrS36o2F-La5DD`C}@Fz-sZ z)DqfrwCpE+Zeta7RV~@HYT@}A%nyw*42?<|D@QIgKVeTeXMG zZXeS+z0oVvxQrgU#eW^hpL|W-Yee2AGj9y-MPwtGG~@KFnUXwFSpk#c(+)j5>sbp$ zU8$@^RD_n7z{R<$-%01Yi}E5CWWYA>|C3WdS=qfWD>XA`6PVBQl6E7*$V1$-0P_x75(xa(9#+=K8sJT_9qXE0u zhtH-pkh($^MSsVqr}bISpP=~+G%ejr19MdrU8`cNPVR!e|Nh$~9{q;+YDO*y{Ev&f zN%(AwBD6!2l>PV@65I&CI1wXMmVT3rX^;tJcbg9V?ZaE_5aJWFLv}MC|Kg7Myw=z) zH1?+%5NLzHCWGbK-PhZD^$m^wd6cT`I(-5c_dn_+@_+s`9)Ab_^TKmn)fC46VYp@@ zh{?-(ep#ki;Jfd5%te6;QGfbojQ?Sfv5X3QL*-ZL6%*BC@G2?tJfr-){w%rPi2AX3 zzDlo|s1B3!0&NXab1$D`#JVolD<&$y5(Qg`-e7W>u3)i4#L*c4^TLWHE72XyeM9>d z^Yh_u*neu3--rmPpjlH(PE@)4Rq)q0u^JsjSW}6SGMV*^URa5TPdvy^aG%9S0qC95i*5dL7Rkbv)~+TIS-r(rmVCTH8$9N{fle195AaL#|$^a)DYHGOtf?dih}&t-}# zLvl0rjWNLF`~@h=K2nwVF@k>*#4-;6ziXBN#~N9m*;$*(Kvqb(RWUr@(Myo~dP z&R)g&Az<=Z-XnfPl=sU)-a|Fyymv5IP3yQIJC$jFGJ1wYy$IqhU3?BO#X&XKJ(zfd zMt@FPF-soPInDM|%2|d_GYN3tXU#HQq1>}{NBf&Nf4@hIZ$vn|APt42*;a9|DX)+&ZnGej&Uxi<{cOY!J zugxu|2XhLx_8Ny~hxY-+G^w<+n!KBQ5r50VHess?oVLYt9fG?#+0N#Y-qXy`iZHfJ zCijbmdQnETC8SxNmP!;JU5BAQ7c!{V8l{tKj>eP-ejTHMgf2-j9nC-mHk1Q4=Y3Vo8Q=87PYj1$l>P14-3`_6hKsNPL_CxtnC&+gU<+v%)n^e1B%0 zyW$tp#*2@d^8{_Uhfp(c$&e1ToOVqnrd<=$=&5oNdOL~ie%(&EorX<2X(N(u589;; zXxuQ(e}NOfoxY*;@pfyn#k#w(Bs&rZ@r+;?Npz?-Jrby(S5rH7>6yk&lLrpLV;;R5~Q}w3N zeSQNH_6T~#2(2|AaB-kLS=~lex7l3@R}NCOY*R86$@Ha`Y9dRO>T4zX8lZjgfwT6E zcX4!}cdt_2t7P|f)xi5lRkXCITazOC{^dZ$gpq_She+T1i}yva6?F*!H-D9FrHwu* z17wue+!_0Kjjv|&I%=3DM|}+b_?j+cRl@exr%!dd==b@(kQlbyqz5c>t`Y=ff6Vvo zJkN_oIlP@HtRZ4H6NM~fo&(CG#cVKUt2KjgCPgCh{xvKnvC3OeeGqq`#bJ3V`b1Gu zN>eIBaRVOA48t(EjJEWBgn#;fvKGLu9{@R*)QSuUT7-)g9m!~?l2|27BynlA7E&kg zI8&=Fp*|vTd?j#vrm(-n^_j*bXw(fPzl2X-n}{D9$krDaaU*BXbzuLX}12o_76ROys(C=Dv{v27Ud=6|HeExRoT)J;>h z@4w&8`K{iS`9|vs9DjBcC@8SJ)yK2kXybuC2fEhNG(EJ}kko-f7vg+_d51`L;Q;v3 zQC)0Gp|5eC$bCh^i4RQ^5v-Gok+UF$oHg?OJM*SG-52c%5gcdc$eUu@qZdyVw@wVh zxuCqmk-3~+coD>zbN2$N^+t>yHtt*G2DRVb=$0*;QQA7Lc7O54z|WqyM)Ud(#|hMf z8#8!&V5Z7V<~R{lWABY|eMV!&18tj`4}!qb@90=%O5204M|)Z`xj0H!l9+KcspLqc z)i@PYV`=*uOC1*nRLyJ*NH&Hd$up*Qe(AS{JV3oDrIu*)qDQu*56ORR3LkM6^zkgoH7vQgObK+ko@bwUZDNhAA zT}kitf-4kgrX)p_=4iS}v>bGOCtCeBUu>GXOiefbs==#7$jCDOqw3Q1B=~F7RIjfM zy*FrM#BzUzN^Cq{R%;nOP%qKCx`>PvAKXkRG$GXqcqo?9D1|2GNahg1SS2)hPRu+f zD$hyarhg&n2~csKG{1FfvSem7oGczkwG2VjE<|4C3{Qu#l^TS1JP@%^EJ$taYE9~+ zRm)Q!o`X77FNnLxqQ(1COovY)n$+X;A#no89-7bDl7dX6cy11sUh_OpW8D?=8Ja{u zl|6hYew9?o&+p$7D%Zk@ts85H8o|{UTdR*m9e+?TeH{iExv?ToFj5*O>}P%55MjUQ zBQ4c;m@|aPrj!`4Sym3WZ<{Xcr+v*>;nTj?*emq9iH#d;DVH#+e>}bs)-8;WV=7g}Q7j*d0xk$cp9G9gXOK z=y*{PP$}!nbnYRp=LW{2Z6=E^zGlHZ{@k5%(IGPVqIQoG z05ybwsHOc_3U<_!;(rHa#E)2|1^P<=m2x(uk)noTJ(E%7L@RQl6*_l#P!+^^DuYqub8uEEh`6+=V?)NM~KK$oNn|0Gl{U4qwC})AHB*QE^G@DnVrH%9NtZlw;^Mr`|?7VDdtBuR&GeYsi<&(mx{_>_ORD%Mms zHGXR*_^qsut@ntd#&*4&<|orq>*YWZ1+Vgdeo3kF3kv0* zTLvK5UK`yG$K<6{vuo#O7HPJL1Rg}YWg2r&WA#)QMHeRA-hpn=-c8p427LoH!46JyjDdt26Qe&+pfq@6&wV-!~GfEo?3P zTZr2#rHeb7_Px6X;R1hySJ6B^nVAUm##@x58(OEs&W7}kxpGlUt@`?KIrh4r$x99c(C7q^xioYN$V_pau7<1b#e&no?Tn#E!GYWe(%uhjXHMb@ z%Hb0^Mdzi+259Gzj%w!8{$v8HRovW6aB7E*cd+oddJJ*ox@dn1njXr=nRH$G__WZ0 zYSqVVEizWUN&$W)CJNinWRI$Bx3Rmdum~*+tCR)@B&*@oq5CsN+Ioj-6 z$CRoq^_uG`@htM~z=+i9Gve*~6rni3WOju{Boz_4ZwgfEEt;Gv!d<=A8J!}v$X8z; zi?C$=Pp%sRQE-3LY=>ac);$MRjXF}Eo$HRQTaztg!O_{{Sm!3+DGI+Vc5sHZB9b-5;!%l^UBYTFoa+rku(Fkq8UU7$mCVQ z1xq<;E@;M;u=~2RKOJpOJF5NatRH8?+d(1CjU~o>=DZj-O4nUrCgxEhb!^?4?bD)2 zZmfN2Xuf{{C7N6_Vf9r2zBQOBYqp7>p*}8o(#-I2ft+cQD@}Byi97*5twgG#wYe%U zn6Dk%Hn#|$#y;^fM7il?9iiKIF-uZSdfopJ_0opMXSFKOT z9$HJ6p^pLs6BiOQmjNEJclhWP0Z44NkD%0_XrI*!~_D=y5}o+Y^!0ck5-XhMG?SwdzL5NH}iAA*Yv3kxCKfak0xfM}nw zD1O-QXX1>-en^T)9k}FN8d)cwRaH|OR|UGPzU{~8}w9eyC9&n2MJQbV> z;Wa>PY*Tnjbq4)#WXkv%o@JlNVTx$pYnF!W9hy07Ev@$P&|<%fcW&-w+LdLn3FFEH1cXip%0oKT+vzL?74%_16kx>Z~ly^vSoP7Oc!Cg*Kq{bOTC` z1O+1F3BrbtQP2jCBk>WCaXbqdVA0b9iPn$vb(^_pp-YJ?E&M%gV^H~;rJ?9<3{9Q; zAanXsv1j**z_Fhs_FUMHJ&e1MSYUsM0bTkg01(*)DFrt=2+{qkiWgFIqXXE9bE=5% z@xOI5R`hJBT47WDvTEKhKNw3qZ{6{;aTI_j|Ies9&8h+yiB;@7INEF{9mfRo@$j)Q~#vR;JeQ2g@Bl~4o)+Rjx@K-pknbsQ{EeavT=#b+O+U2gK&>bD` zPvnY01~Gbs)VtWxNJm`-2a;ncwGX(vhD30ZGh&6eX&?@nE(%Fr;hcYUZjG_EC=L9LmuBz4!C+cY|+)B4Ls(64Zc=y)5_kW-p$GPnBPzJ?P@zPd|VA_RZ0rHyDln z{_JQpdUgD25Bj(_8BRu{*FSoDP{O;cs&zCP-Q3&^Z=MbF;$nX!gha~`R>z`W7X6Z$`z6Lzbo(LuYdjPh*BxH z2CxZ5NDTu3m~g~8Q(v4+k2H$?DV0$g2+l&nm8nMD^I~oswZH2U_f+V8HpxQ!b5F?p zTIEn8_$imKYkGh7RD5ua3E9irzK7bMD!j46;>FpBYqTvyBMAJcME&O2!*$9EI6KLC z(}I=r7f19^yx6;e<9_cuetiFqPlID!43Ps2p96u>96J8MKPDd_i$> zG2R+B(k#av43G}`DceOq$v2529*1e%>S|av4*!b7a$0}%`+->d>1jb09)J1Xhbtkr z@;GuRGhu;9=JQCM1{OPniG(Onb;bvePbkz^fM+TSEtAxqKYtDbk5UexqAD-D4MCA)gT^P6FISRBL=ie21=Jp};P-}vH_lTx& zSU9Mg1hr^gHsQ^hrTs82KUFk70t9mSw1gZ#vKxPr(0PNI$>@4T-W+##TDX%+!*TeS zuA9Oet!6uJ3ur$E;22lhqjNQwOw$+fcsdv;zRY)5sLL zHZ3cb0c`z-U)7~y=l$tWT3z4@GQKkBfx4x)X|?f#KAZ?Z#CdmnlAR-sei&Q^KFL7u zZC`k(TEtvBI*t02B(~n2Bh81h$d4`pCy{^P7C*X(&`5qw>P7fy>MR%Dz5d~+N$@q1#HOciw20dnC+0`p24GcqlWpKW~uOVGzD5^-#HD#nScfHhJfRMd=8H>|s>+m!jJ(b41)s`otjty0Yt z$)rLmQ{U;jm?DF`SD1ND9C=RYLDD&-&*;17nVq%!X7^)k=<-{71g1X@OXGi0`S6gc z6hEyo|7Zyd6KpVn{-N(u(#*sCJBAs63@ z^`5L@IWQ3q7oJP|#Sjl(QT-43waeMYjymM@w8c#9dFyQSXXEKr5q<=sm)YXwVnHq9 zRk$@y$C=}J$h#$nETIR} z;q$OS53a-K0coev^k(SK5aH91@)IQ$Y&4*Rf`w(QY^Xb=gcBIX|3{rH3OYFJLa#o| zr4uh}bZKjJX@7FIWlZ9)0B>AFbzG{M zN?@jz%Hzv4Ib2Q?IX$bmG^Zy=hj6q#YxMpnzE}92%J_}?Ug0;kobZ;DKDE8le8*w7 zQY%iL+wKq+5rf5mo<%qCl?Lb<^fsy}4#ppGtInYt#10iiz9@e=BwD*0jbz^rP{Ra1 zHiH5!pF46*WUdL%H5Hxqe%SLuRf#79kOc#}my$`CG=BQ(!-O1`2$xiCP|NE76KX{N zbsqh0=yxf?OCAm!cKFXDw_9q(1IQjtXWhU!xiLhb1oz+62ySL?>xmy#7n5F^#wgJ3wv3bAhrot_nUh zlyRqEy0z>S9;F3z<#P#SaUblqL)E5~H9{Gs>0afX;#P|8Vd@BO(>KKf^i3w|n@po` z3ZhW(Y$AWlPh{k&K>DU2`XNFYLasqM*kwN$Nee8jIkY%q3j;HrYw#ctgyKJYvODxS zSiHoJA6?ej?~mYlXqo@@xC|E52UWlIqWK`Z9r(LE?(%crAvbObmbD_9q-~VqgP-MP;SldXvYZ-sJyv)Y}G<0|}!AK})2EHR3xdiSM9i z(c+9`+WQ{*k0mi4xcR^`L<4TzdMG+a=Ic?ca^e3)VnR}p61Y?8?0v@V#Zq{o)un%5 zWB!#auid-!rw3^iJ1?15XyEA`9V#;O0v_;bi25p!j#l|Izq!Bm$>_r}koXGAW zXjF!M+Ww@`5_zy~9T$zq3cF08ksU&o>QRJ;_Hq*5aV{X1{ZP!?dld+gDt_L~?L)Sn z(9~r6wOBbkUF-jw4PL(_Q^8gF8-X|Xp8_)ZOUE9viDuZmbU zCz%!NS#iP89dLP^lRuQKv<-i$^4R1270(CDo0eTtCD{QWQXV)j;i5WxE?*`eu$Af* z{rF=0sZH#gMkGhQT}iPIWgJLj5ACqET4yQQ8*L2lzzu_wQEY)J!m6o^BDINBARR$aMz>yL~NPKkAwnu-^Q~2I^_$=_6oG9i&Mr+2)T` z%UdZ809U6=6e&HbixSHsh2@c$l^G+1H)Ny;0__W{K)n6Qw0V)2K;ou=5()taN77ts ztkNQg1i~DsXfK2f^HX}uR>!1-^B$ovD>U&!`dwle z%~mR>rjM-Qbz!F#9Hy1fd*jUE5*I$%Ql$GsvKsQ3kbX{D2`54=w~6MOp{T;!#6eJP z;qnqKFmt`r#^e(VWj}&hMcXpxZWGDoukhZ0NSv#P9_K=FRh55=eAyn_?UuJ5asw!$ zsXDTz1}$9SHTc&L=|vU~CXo@IkcC@*eR5ZIf>oX8Rh3_~5%AngGmpViEIRHuf<3K(8W-tYWeq}Nde(Jn3s`rb4Z1bpZQp-{F1Eo4ESS?SU>}xBgLNgyI{0-44nUyZ9|6m)+ zxnB(#Vr;gML4J0kXzY_G1^ge&HT^b`*Dga_x-f~2dc&f*8Z;P>&?X7mbV96){suuE15xk!EpP7Glqe0=B2%sHK~cbGzI z8})s%RWGquE9s)QQeWpQFF>Ihfxb#jHnGkD(_sIr%aTvx^yx z#0sL@-zPGWwu3kjhMSc%^VBpuppJ`x{ModTzVloOl<<-RBz_jAf%H}AS~!$p+CjBR zi)LBKmvU5wf@H}oN+pv7inI@13~vYGNRS4ii{WNK$AjYgl8lsKodUKG*)5g}VYQ#uk_Bjobwv4`ng~FAEqV~vnWtG3pp`8v>o^&;Km7OXwnu^m~ke`Hw_87%MME74z z3Cl1?(;lhQP)qG>g`*v8}AaMqb)?G)0$*W^8P@!M22kw$)f+Hg=*nb`sFd;c>lwbc?%(_fUt# zT3W8swbT}~HlUcAPEvW(XLJ+rm5YBsLw+p)lxp2V`@VEB_(0BI0WUSsYNhsyQ5t3% zoLVhWj>?2irbDMPL8DcMP-viH+|XH5!{L})_Gm7xgeqrElpup5*1p*qMR`Fq{n7Nn zsGaVyh(TvfjHH7i=D6${WvQgp5^wN{`>1HPdHXgFlilMtXDzL{byKo_L+^hb;G+wT z#JtGsp+LLE>(_NyT}ERkc4HgW*okUvqc?V9Gyt9E9=JreS= z%^)SB13qsDDUl+0^Z^Yh5}1FAt>etk2W21Pkv0mZH36`WpM5><*La$UmWg1BYcgFe z*oLj=Jcm{I;hgfuOtQcD_}$zuCiZqb3B~6L{{-3;oA<|ou$b()igwuJ3)MTl&N?Jt zbwr{Sr2b`b7*@he|Obmh$?Gp6e#^`4{-*y4Wy3w1l}(ym&ypi=13zoNkKIxSOTsi;mgY(*jH@%Y+;&u{;+ z_t$OMWOP`WrD-+ZASAk!sm|Fz=d^|m_(ykqx`P=;mH?1v)dAH^HELY$;m}Ts`6ZC_ zG$ni}rEl@_KB4>%cH&*l-!w{8At^{u-%2oXuAs;1wTTHx?zex8qtgi*VIH@wa!RLU zNmUvZIxDNIrY=XBt+OVhy}D9n)y-V7v@82R)(vMb@PUey@h;i?cgG^topCigPI5TA zHeaA=^R^%3h$-5RzQ5mx__TbzfQw;vAy(S{SYK%lCON(@NS!xqv`_`NL{2(ZX8S=a zeCSofGJ$b(nZkczUknC;+NBxZ_LT)848DYPONcV1J zwXsd=D7%c@QyWlWJzKlMWJ>8iV1V`w)d)l5gNpCy7Y;}9i zGU^CD3W~<|yuK9cYP=WWZ?-ssCB1M|pdP97^#hKz!tTOuw_L8Q4PES5#tw&EZNUtO z=#J*mX(xY7+u4b-uc{(FuPdh9Z*c$$PRK)Lq}wgZsJpo^-m+pxJ&w_~r3hNXRTFD$ zM2zir#1?vs^coHskJhUfsqQs`7F%=4q10_Nld4TAfiJPCu&vF#cG<)1UaV;2v zktcobcvh2F$?sB3?&qv|RI_?OitW~N+hMd?bP#_H6!D$koCLCen8v$4bwYrJcTMM| zGazXXq%ww{@epy~$HaUe6Nw@m{DsPQU-qbx6MNm-m~G3U{FYmm$LODtnPECjJ~UUy z$M{@2NYe- zjhOOlq^};^Z-+TnO2suGoI7RZ)H`*wx0)nKm3IJ#K$q7mUUShqB?C$R0{#I+eS5Q~DPud$0Vv zG2zqASklu+_IJmkwYrH{>{lt=L#lbF2(JzPMg-R>Zn7u0=VLv7!I{x`{W5xoeKsn4 za0)b^L605IRM;^mo+rgM9@y}ytVt9zXF6zWm1><{PQPxB`iu@g(iLF8UuhRr%^!at z8gjFugm`a&XJDGuLW@n$(C+Eya-m|oPPB5Sv`TVR5psw;2RVwhDU)XS@?Z!ipXO&S zBWMsENO}gY)p zpd>>P9fapa^entOkG=}eSJCtEY88Kd9agL8-?p|PtHnZ!#oEH=h6P1~YU98i0vQ8S z(lyHPjz0?gkgTIqFB=rBO#ca3#LHOot$mjIxAu9{d~2VX`aTOC629%z`#jASf@212 zN_P4NV)Gl+Vc_+O#go0KFlKb!28ka8<+7%L(oWr3hD&oBWl)G>XPKKz##Vn;p}%8X zSE&k@VF{?M`i$;Tq3-T+RWgE~rACJC89mrklm=^_eo1rD)yxGPnRTHx@;#3T!rkRa zLQ55T1)+yZyVCHF`e0eUdLA0m6fmK*bINVGKzVKt*|RALO<36u1o}}*a*3@wI(F)OzDIKZHBlV zr4>N!Ps1LpK55xwkwNwa$Y4jA&fT`7%noGWF7*I1*iq<-VH-Bysio{O{)ZhO~HR=k#rSra%hz_ zkxf-CFm=_~%BWS`N^9yT7)p$(KRlBU5@H<|z zTIDzV`ZI?M*@|puFt`iQ8>ete){ar!0=;_ab)28NE*)ZB*^VoKytiySJfyJl00Uuv z-{Z@dP&L>?my%=$H{7TJjOqSHz z9th-9f08X$LLGnirJ(ucq2o$(o?h+yKBa17>e#JWXW4D|Tv~6?!U=oFZ8Gfs;Rc zl`qm|YOwCeKeQa2NLA7z!bS;~j{o&U8aOs0jZLE@5#)bX6S?f|{7#703$`BX(jjO& zjt!mlJ7Z5!Y)>hnI*T>Zzs?F!B9SdCQshKC{cBR@bXKLSSzER6M+=k4GVp@qNN=MS zvNeinF4iy$95yB&CMcsP5Ei7 zHlcR>bpwA^lVxk8?f*{=n~w2JT91+V%eTw$Xa{sS)nh})I*cB<=qBc3vervu#mH?D zVAxQmUC37UvhxbUrv`nb%rEg~jIP)y0HoU_V#D*gsz?WP!abk>P0_(pwxt@4L*2oB z>N>m|c`FNL3V-0>}(4lm%zx_q$Eylh(fVe zk|ck#C16`mZT}B>@7~_Fk>m^izn?o7;&!nfNF?T8M-s zY$$*MKv`T#^V#33>RWZAK~i#($@{)DPb{ME_pYk0`jtE{tkgio5Scq`H%>U(GTHB~eqc>^%_$Iv`<-!yd!Tf(o4@D}a+$obg3me1ltHZj3HGwxw}U0+l1iOWN^E3d(bc{{Ml_icVUY zZK-Cv)A`?^CD{4T)y}O&JuW9fs}`^5B6`gz`{{L5Qa^Kq)9ZrxzO@{F&i?o1ylYaJ$nQ zX_j2=Tf?O)zc8of81~*s%e2HG9rx1Qj!I|JM(y-xXfX!O$q+OrNEl^Ah~NPd$zoh^ zkRW+(a+A0KZH<*hDvhf^smjkg5juYj3`d0l-B1M-xv+o6mNfE9CbOCSN1dOUx?=rN z=eo0F86VoqSZ^*PVC#Ibq5GFKy&_lSTh|5+EDWWchyU`kIOR?^wH9-3_~aDVZ_ell z2VAXbU*kbTX@vdg3;fWru?eUPO>%-q6w~ponx9qMq9^{e4vfhMJ)gWYH1(A%_LK{Mo zbZ3h*?e)|kor(0arKMKPVy%DgGcZ57CRhl0W{ljDEb|kw-B3p<4Shp{@GOG%o?ETK ztRW%gPyvr51`UnCMN)k)k67yB{f6F`%ElF>=K+7aoW6-0gg`3ETchx^E^L0oe}DSf z;NaPFGw@`gTz2EXz#MmD)JBZTe~p7g`76uHVk{k3CG3#uxYQ3GCNn}c_@Di##gBzL~)H`I-6Rsbqg<>_p>^^49xi=9WCdmfOL<>joF3I zG*UGnJd-A%fIRmoZ#O5a#jw`Vdr$Ri6c2YGh^T0#>pgaR*P<`osxRN70^QQvJD;jL zZ_)-T-DpOmd_?&v_jLEDW?sw@WqNYlOckZm(Q)eO)l{RDxt@Om${johM8XV>_8d`h zjD=I$v8}qtCo|zNTK9BZ8()dT7MTb_*W)JF$OGgUq3QOZkFUFBg)@BLZbbD?i$t6! z)?u;Z>d+RxjQJ6kKYTpgSFap>>}ia8n^{ICxbjD=5on_8iy~>rDz3bdX#Saa+|&eF zRG^#gDq4kz?$Ce4g%>GmnPL$m;8F4TaRq-?TKReA*W#Y_dSmij&m)g#Q(*}VG(^b= zH~N%D%tntJQkISvd$NR0qBFSO%BJgiE7mrBPCQ{}aE6zSZ4Kud!O@p=GA}~uyPhEc zHlBYy&Iyc|&od>SK)uEAXxpgOPkf9%zbmz1?T1kQ4()&C|7@B}9g?jO$zEJ#+Z9_o z_0!@w{zf|+w?PGNZ-W%Uz_nBnD@=g2=q!SJ(8YDv%l0fI97IjcbY_eq>rqV6U$}#*SZ=q>dqo95HjgR487d=y2lu6b7Ckx z1fO}hB=~=AlTdYVAc6da0qc{LDncJfs%vk+Grk>2&KxB;@8UDtPaw?@Qt1>55;Ae`nqmQU0 z;F&LR7@;dYVcmawJHVgNeE1a#mhs1aOkp*yrGWm* z5E_5qiGt;f%TakWq$FZ8icpXJME&5Y#@ie*0i!z`(NFp>@*PvhP8=AH!^Ot9#?v(h6iN?{~0<*jBLh7wlaN_57kb`zRerm za;P_dsBtUxi5q=(7wxvLZBs`xZa3o27^Q!axf@1xB<~F=r`$fV4#F4`n_nb4nSlFN zU-C7Fp>09@sribm)F^qkqGRFWVGz;(Lwpp2KD({+tI81D>%o#UuESsg5PT@QWwVoxB-$8C`R#2Vc zom3vN$F$>Ah?~|4;x9{1X5KV<7H8iZvN=7l>)c+Q&LqD@j*P@(?Tf;tAcV9pyvdK# zDI8^LPKfe!2j%vbg01dO|65({AGbEzAkAZ(LuRC1} z_k%W7f0it>n$%B)XmZL+)os?LLC5V4wE;O=EMtTn(c+DPe_^sat>IzQ=UUS`%bX3K zM)r{@kJG^3w#X}2X<5Id*JzSZ;rn{CvP`aOI1Z4*Baa?_W<_boFN!=hwIK&XB$uXA zLNScH-r2rFOEj4)`)v#ty{~^`C6vv3V9`-3mOys44kSfD2X?Jgw<$LkU94*I60ZyT zH?nEBj`^Ig8pLKmO<&UpR*Xk3wxch(ajlpHhc2%*gW!W<+s8T|X;|`*#KBHR={zv@6)NMJncjcZu#09F-b^wM zu1Q%b_lO1q-&s}Z9xi}c-7&%g8Y7e`$e-kA3?o{mt>4%Ygi|=UIe+ja$C7}W=pDB(> z!N)*}JO;|6z)-mofYW~m*2<4~apR8X~Un{aBvt6pFfSzo7tfM=jUNZ*3q7b(l`!JyiVE%!i6uE5h#+HaCcYG zmyU3{*AtkOE``(SL;{*s^nf9a=`7sE;(Ak3#m&ju|{-m-kQSj|&ur1e9x zSfy03IHg3pEjND>n8|Vop#r!kKJKHz`PS);Y6OOm^6GbG0j;bvXaeq+J=`dJv`zNJ zCfO5PMEv=%N85w`{jewZo&5V@&zXTeF~NIm+3Y!sX3ttLd-g)va~H@S?Y}*_ANOz( z@2Qo%Csxj$7{om}nR_mc*stIggrNLvMi$dC*r z9OAEV5c&?rvI3$#5P^G{bh!vjPu*9gnD=OC5hm+Ic$t|5GIyw|Z#Wxm)-LvQTg|e7 z){2#1PF1hQY9@p#`eoH1XLxHJB3-i<5w8393MS8ahL`N4yuxp973U}e9%%;B(XH2> zK;O!uJ}-af>p*1-mG|b{_1etn1)?leb|6&h>kjIH5HOcq8Gb|`Tfqb$)sE|_(z@r% z$UH=|*|h`JkkA^eTa?HIWyGHT={NI^O&(Hght!l#ZY4En6RidF6&wTai=}!;(Rhfi zQnS{-3lzXDR3j7;0}1shoCJjmj9$V?3-=S!W(9xGlu2(mQkZVi^@NH2AYyR{iWXf^ zoO1~j_s!qGK6(57%UAEe{PvrZ*I)ka%lGf_Erf^$K@6klLs1Q4AfzI)q8(VEbonTs zi-e24kjRQsk=9ELk!Y>~mu-g{%{AacZ3w43Sw5|5@hI(J)x$|MNKFI=s+(C1nB1i7 z!zq8q2~;JCVC!a=O=UsYUiY?VX>_1-`?Dl6$fX3F6d2Z|3as{+aB7sG-b%ivbod7= z`~!vy`pxL1N!=)#4E%yEXA`r zj^iBuJbtW%u84C6Cm8ldjC&ISvGb=R$%S^hS)h-Zu-kdjA^gO)jvuE}?m=qnm2!W= z?i9LFj&8cf&)51OyEO+R4V)(eaQTbLihG!ce(D6}i#0WANFLTOtk zvPFC=`3*y*)jlf`0$$dBXbjLIM!Z!{akPqy)OT?Br*X-tIReZu+KFFydhn zJpM3LE^(=aC90a0$3y(*5dV3K|2)Hgo=-#Gc(LMCv$c6|iY4(} z6W*yvJ;(83W?8vSP`k#eJC1)EMnn!IX)rQ=q=(=Y)X<_L${p#!{O+1@zBjl;+cFT7oVRm zR(A9$1n5{HWc$%dAf11xI%z(5(tOYq=0n@v>DUc*+vT=lpqDuAB!7Lh6_ohf*)O!e z`|~Q4oGR%SpZ{#KRM@!GjJ8O^f-w1H_C7 zVYzj48wbAPjQH60le06RMBj1t)x8+>z=>2XQzgzS@5SwKsgr+T_}CXNA2J{NBT*B! zPd*z0U%a=bFe)YiT{h~e!<$!MyVfX3A8Dzkvc(_>7i{i;xiR9}RBqNZolf5qr~Hvg z*m5&lo4xVum^U0SKyfQlxHiw(lMQi7ilU4-LR5wqgl|g%)r^;wP^<7Th9ZZ0mo+4? zIEnFfQ#|ysr_Fy{zHN%CWi-CEYEpZ}LS4Ul5F zxsQ}wxI|IvF{0h_4KyeBi=_L-m0(qn)P;@gG$|#@T#-TC`P13inbw@W5m&3032LSB zP)N#DILZ(MAt_TqWV(K*t=>HD9DHtj|&tTBWtZnV0KgvnRCj6)y_rm%jC%jF`yMuAe3 zJsRL*b9AXT2uq-mo`(tCnCR>(*Nd}^Z_MMw=y-ZJE=7xS`h#ivbxh}ay%XpMi@!|3`DzYn7|{#_s52~#drR;V&UNQ}Xe2{^=n zLv2Hmp`asYZz#%fwp`p89`N|%Yzh;{0))-Njkw!JSwt}-9I@}uPf@2=it&U15Jlmn z`r^(#TJfqu#XZ7KqNtRQ08(JzxX|6Q{7)>h5D$L=(#S8x1yMS&vcQo5l*K#&*u19tMx`!`5YxuQ>Uu)sWkO@fqY$C>Jz#qhCQORTVI`s+; zM!W#hZ*;eM14m-THLSfY zSHO;*&vvu#Mn`VgB4i7$;Ve?B5cbIwu#a|sjDqIE3-NZP^e^{v<4B&eclGjC-rkCR zkz2U2KY)wNaw|`{dRucLNvE93QwvQ++I1Yy^8srrZ5Q*DueUv)t>rD2kR*y+gT;R= z!c!wkE$&{vA2)XXZ#L-LhtD_Y+o!5A=sOIachGm3tWO_w`$%o#zBa8*F}s2Fsu6b6 zqW!#EM>%x0P|V~-9U6zMim2Xb?{B~Ix75w=4mhJps~(tteM7Y^EAKT^ZCPUI^;<8q z$Bzj|OE0#9e84uAO|@aMi9F4v*2sTD>DYQ(kyqK~x~Vp;H<8P;+8VhiVK@rpmXqep zdL8V(7;*R3DC*0ip1mUb)#?u_Ql^uaf*N_-2*Hj*CYhNa7x zML~+dd~lMHlss|J?xJM=->XVDnyo*zzO8{^%($F=U@9|#Wil&}gWfM;UDAJdg1l+_z_z86>F$jwj1+S!|x*e#L! z!c@{_m2|gN;>o>YxszsYtBbNI-oq8^VPYoS=EgOu;ATKbjonA_$-=^ev|%6ZBp-MZ zf$o^LoRU_1v^;`mcS0q8|}0up{N0^Zwme`lReY{+S&H9Ey?=$^kd z+`ir&e~H=Xs-(4XPY>d46c5{mbo6V}zJ=@qb-M}c(0(<`jHuM&9@=@oUXTVJ{8^Jk z%9ElLDbTY)RQXbziZV{AjKZ5jlyORBtklqasX76zHb52M6^r$GL12FrbmRudi0oHH z)s)Bub)Te8E}6iKLar`}Rd zMJZy0PQ9g^ic)BZ?(XFD1$+YO?tzs0Guvq(<)7dfXPG9FW`ZVc8XcDyT4HF4p(Tdu zLC!V|vWp(linf_HCD(sZ?jc|$^(sgf&teq`y0y}gp-V#9`Pc-fAKC=zNl(K!@1CaA zT@jSjoELanAucqvP0E>%kR!oBXdxz8%imokeZ~Z96z4KLl~!;dXaPMd;B!#rtOzAv zKsd2iWl@Qugo{$$&_{7RfEN7wA)*P1W6>1o5&qpkQ&D_7x+#AU`ePBz@lSad(e2A( zN{Ts!7(ud{s8bmQr!Wo-i;$%)?(T%23*PKD{E4VSN*;)$L3E~tzNn@`nrF{-I=10YdCs@)Yle?JLFt{)%l6fxz2De6pZNAnIF&+j+tBjVKW$yk zlyo_nDZzh_Qa@34Tz@(2glypZ!WsOAPGw`q0`KVXh4y2j=*@wdyaSY$$lBa_+gP0v z9q9VBHEe5z@|m<&??f*B%qn9tmls2y7^aRgDA z@4b$C--S5N-vC`eqQCePd>8dzhd2SR{PC}&?`Y6}ZYlq}2(y0`f8~#d20;C=2O(wm zHNIzm;9R_HN&H<8lSI8hr~Nkmwk<6siDVv{tgl;=swTYdekYQi#3wtqfYV|zvi9$h zdH)7^?^np9{~TQ|Mqfpj_2^}ES&qJqE>A~a!)G} z&=y|K4z1zIt@dCuv5_AWi}XkzHafZ_Z<91!HX9ca{Cg4R%`&n6N-XMUR_X9YsffTlTPu8b-sR&II+*@R?@MGhISEoTh6GRVV|& zV~Hd%+Jj{fb;j^VhV%p*4FS0wK8NWbo*d&!I}WMx8H_muWz86zK8&jDC>rhs4I+dV zGLjZ3{7B`u8Z-F4f*=@=D4EI?(Gl0?bFA+1UjT24B9(&7Z;YZ;6CLa}s$PY2#gDc}oM zodVE8OZ|FEzr?~5Y%Y~(%Gf7+F5MPZ*glzd$%e^=EU*VUmt-jx^oDx__&@y{?os>B zOu7#`ok%89hkSiX@n&?!=USqFC~l&=iAb*=QucwMDOtK0`(7>-ZkHbTX*-tJe$Wg4{Jj%4tvd?={L zM5>1Dtf|RBkSJe`?FzF_txcpkB@}h);D)!dzDUBSSS5ObKCKc(YSpWMrPDRLXI5G9 zjUxpi;h0^5i@%ty|{qA&;miD{qPYJS9$dZymG`@F#^a|35#)pO;S`3vY zs#}?;;tn}ilgmVPF^cCh1$JRi;!|nathqEbmrl*4skxLj^C*+6Td_u!rcos|3Tr-X z_W9KG`Be7#lt)!Mig)bPbnH}gOt<&cjMS+ZDXN+EStT?bJ1y-YJvFUAEuET8pHF3< zYo5zQ^~7jjHv4>kY5IKW%=4vb{iQR{mu5IFo#D7N!*OZm`Lb@-T$`F}r{>z!Tst+_ zrsmqIxi&S|rsn1fyEKDy>8!9zGZB~0L|mGQxO67s(oDoMMV@;?v8pByW;6 zc1ml@p?HLFpDY<8f;v`PQ;~CIgAXCoH}EaFIisa~szS8Sie$%^yt7YwN?Yvmls4Px zDeWRYd;EBR=6yl(v`@adME2@a1d;zkmR~5RYgO8b%0|uN3=@CyH`ZR(aZ7j}gItg6KMrIq2SH7dG6eciDqKKr_Kg zJxx)kGNHw%!ho~YoTALL8(eKu!>uGqxp zT*eoFusP@O?;190FIb|z&L#Yq z?Y5*eWnvm9Z40v+cnSjERTXq_*jsOC9B{OMcFGOSyKFWO^Z3)cou-sBY0Hu8_Mx~c z%dSBqe{$49_nT1hMCVe+pTMCM6BQI-z zCTRiqXaV?j#!JEdvX%%<-A(m44R6Y}^xkPk5y$dqfJ_Gbdn*2=kW29|L6l!o_~oex z!4KuJ(^KT9Iy8LyP$s)AgG>X`{}@=Ffb zYxuQB?Ry7f;a@ad@)eK|*~3n zZX%%PQAC~fq!-u|HEVUmi-nV$eIq1fC|rnJnHUh5N$sBajbZS3kBX`>Iyh0N!ub9= zu@&6qmvT&6NgD8giIJExj|WXCu>Q!zYo zJ<1dWka*fquyVOR5YP%p{chh@Ja1;5RyjLtWLffycHc&SKHB81;ucP+eAgp4z{z!1 z4QVgnFMR7r`|}J|X@$dvUU?AF35Z5yKP6BN@{;{Cn4Sv=*T)GRVJ|<-zbmVTpz`d;6OBQ9C%-4JB1ys9C6Zw2Tj})3qB%L1# z)*Ko-z%~xBwF7ME!0*?D-G7mwXpf~I%&A5;1J-l3gloKGO6VwmSZ{H=Tn~ZGIo4Sy zY)xT9EA09Z!w&6q6!uhwohX;AQgT^KAW;_PC&MEq-msO}uMY)-bUh5w{WX_x*a_D% z;hH5Rdu8n%Ih_cn*(1$J2=ilUv8?Q>(X3f{QN}D9>+VE=-Kh*86ijM6w<4JmaW9te z<#;CX4w`28+y;(+s^CT(2&0a)=k7#wER1Lp>0B7mJn4gBB!SQGq8oWUD34ka?@HUR zt7Bp$t@vS5+zvMz@Ig0VZ5pt)8z8~fc?*axY;S->*uWMvz`x06gs2Xv^k&GEElAy6gwFDzb$8K&%AJF1suc=nW=@++LhYqf5NogqkhM z8%uaLZiTu=CzV>R=24Hb;AJ^-swk<@0JI!owGDH$G5V!{^p)(G4^?iDQx!KysUlgMe=lg{4S317?b z>q95~p-k_DuVr{eONB*gRpWu=!l9px_ zJ5CXQbTmc8(G=lE;n$(B*gQgLzK6iwwG!Kz*#m@(x~k~TC!A~gd@?HDBh_=n58p^a zrdx?0o)c4cBH^)&Ucy9m##71n6cA`?_dtyb1`$%cK^A9K>DQAH+ zK#&et<(F{E%KJWuasvX*kn*($f{j-;>C=mK@#6;E12esbuT=hoco`oaRK|ynu&@?? zWi*jTMLuSH9!P>aO7{;#5g-X*3fb*e5Ig=}_rmNNR^eXh-U+g#mRq5LCSA4M5B>%b zSNteLRoMEXEI!h4{iZAn*pgQ$_Su7z`oGHm+DlYvc+{2YFRQFf=X*&$-lvCz+((!T+*Bphno5rlz4%K zdeawu*yBtJMnYgcIymky(0C(4!u7_4YnAZMo)^!}Xx)CYUBA}txA8&~x7GVH6WX`# zeWfC{h&xoWU9PNJrtR!>SG8V7p8Y50{q}Y^7`Pizt^g6|J2|aeL4(tC+Pz(WbEZe& zh)i{+$3JBx*Mw<39-AlPJ(w2N>T+YN+qjD!J}X1h%NFjUEgxmUy!Xq7IeP8c8obQC z@9=2zs35FNFDL7wGU^QA&mQ(e1SqqgsM90`mIA&DX@Mmv(c>MS{f@W(F4u|LkN>vQ zd81PQJ}1u3B=nobB3o9?Gf9SjZzG~*vR#g(R3rs5`WgtDa=jxRz028DUK5FZZOCg8 zyr$r_6D&_MMy0@I14IN%qK-6{W=&~6k%Yb;*|p*@*me9`#Izi3+(G5F&4^RQuvN;n z6TaSwLI1V3n3t|r+MDGy^F9a-g%9;S)WQpi;yMyt`FEn)Z7);Qcj0A!QMUU)b_T=3 zEmXc#4ZoIo)|%?S))c?bGvE%_+b)Nh+{h0hj;~=QxdgH*ZdVGqO@h+WEJn*_=!3UG z%Zktqw5-X-Y1zzA%POBLvNb@=W}KLuU;2E|Bciy6P$4dVyg}Xn0tk5PD#ECZq_LFfdptxqMx%1!q8A)-Oyb2s*F*<@ z;Q1$7viUx9iXD}axZz4V=*{(pKk%>X5L|-Ue)8Q%UhluZ{(h~FgKMS zFE|ZV!Uj%Zd95C8N{P%+N^B=}SCwm>;##3&!RajHTF89YkL<92p+t>`u~HfigkRdB zHKDa?#>9U7F0a|ECTvhbT2no6lCJp!ibz{>{qoGxFR$WW31>hN_cHjiy2tAmDg->D z`-)&kqqDgG?Af3HJbZrme9&ZQ_^q?r`LYq$gnf`be!N1ds(C=;BO^3vuk9fafk69v zU+Nm=`5xqab$B0t==>FHhOX+?sQao}xT;(BC?vr)oTmSirRA$td8Ojc_G<)022P^r zp6%!IS8kU8AsI4;{xT?5<`w02vq;w4&8(7Sh_@V_)0C&`H6@6)`SR=bs~*X5_)VEt z%lRej0^8H2^~7esrtQetBA1!NnB1F1r9AX+x9!bsV_wLAl|Lk}%DEeFe3GN@KRkXV zwmLiho0qcDjbKj0rGh{z0i7k?to8ypPYHVq~Q19?JZICvW3b8PJDe70E4)7R-)vRVkWHwB(6eQa7$^rG?W zFiLo7)3Yakax?DxJ3eFbaJ^rUeYz)GCGJ8MC3YGF%PUcZ%e&~0CF#IR`hL%;dy+2@ zy_TJHnFK1f{bd!U;0j`54{4^2vUFb?!*La(9NiK~3sm%=oYWq*(J~wX@l|m_^@gnv zMGLvJ?#VVf{d?(%@^_H{)fOa@ptBJef8o=&QxRK#gwQJ4E)t)mOxuZs5N`wFD}3ZA ztvhpiiHwHi-J*GS0`argN=XU6K;R=##2Q}YUO-TcbSL_qZzQH(2pnNbZVLuT*&)7A^upSHeDBsx%uFIUQK zvnT?ceEG~sQ0RolymxNrTeW~vInB1>kFE!O(P4SN=WXOFkk^iz02*N1JplPu^j~Fg z%6e}yd_3BIk)0Q=6Y|!343a+V8j}ZQ`kUNe9QlLlLED|6j)>x}#7`tY3m}7J=t}&5 zgwQb)(G`z!^`nh`<&T)9SgfE&uOeJti)YfS@%)NuH!~b<2uea zK9c^Xw{gyH-PpGDQ^S@aA1S3`I*`tx0sV7ktt z6Ma4EeAT&=9Bw& z2<7XUDZ)b^NR<+$~y4*pivi5m2<0^up3BEj59aGEgReb>Q(Mn88Q+ zB*=s)fpwk{k2nPC#ZFLpvU1omDqPZfN_7wJ^`KJYif_9X=@v$%ilc{MPVlMm#>o%} zEV1*g#JNb$uJCo~I~_$RVv^EzqP&XmH&VDv&-bbQv>_=5e8;ctM~=Gh0$CuNwGA%~KQnD$AQ)YyYk{A_&Ege*W^CsB+8u+Pa?Lt_qeWbG>*MEB#QB0B zpG{$bV93)ctP%`)hAnpA3$Z3D59{h)MG1VI!QTb^ok1nA+7{4~8L#Y>XyS9xM5;(u zfArn=9-CD8TPj>)mkcMKA4yU}rU;Mpxo0|52Staw54A-5SH%-?6cDv&# z=b0NuhK0gEPyD)crk2KYh_@X|#7g3iR9 z;SZw=;JcUc*?k72Ih?#3@5K-e#Sk6(X8b`zpL9kATn%!6rANn91yw-vL9;>I2scr; zq8a$}vrPQkk;IMv4E^8PVVWgFCxKIgInj40PLzFh@yd%2BH#XUNm(&#-Acnp~_O8UO5pt&S93!jMe1*Ew4s`D!g3^>Q_%HTK3^=!cdpCPT3y$`lbQL+%eG=^nYEg%hCP8QK z?nP(gqkgtcDuz_8Awe#arO#;uthGfp!~TVlp=CyY4sGMS>vKxmqN`&kTA@U^3Q0lj zhIv=HR0nvS)CsJ?s&y#jV2XH@;%sQ_(%Z~=ir6!Iyf2$n5gsHuWQ3q2I5fndwx8Hj zAVw&K&_Ry0@X67+PuNF$sngM_84c0jiziX%2I*Y?sVlRb%SN*$URIciAg zZH9_}=RSuN!s{Ni<={mJ8gy{}qO(~dxr4~b3^MQqnsM|wn~B6UA|hmb5FGcq(@7Bg zH1Gb@hkwFb`VD`?XBY;PQA&yMa}pk8=cpg1Ct9)-&8a>+nvKt3s&8^e^Pf$D7tH0> z8-}p%vr7_miA?ce{P7|~zZr4XPp{KiP=s24$c#+Fco84x{n7t za>f@&%kc$NURu~x#}{xVWYssxH$fTR-Y!JJr2>jx;9YVRua4*FF{k(l^ct-0Ae=^* zadJGL-rmwv%|eTEUR;H${_}Vktz#86K0jKI&%5!J0xN^uO02h#y+4o6fd~lEd+FtW zn2^R~+J(V7R#WMFFL5U{i*N3XWTN>3K>%c8>z*q>s<&lv`Kq|QO!7I#qqRYlDZesG zR~+wy0#&K-wS}&o1fOC;B#e4hw1|^l0Sn;9pytp)j+%v}yQPqE@X!y6?g9ga&#p7& z`g(DvHuy{-W;)GlfT=|i`=p8=4aX>dZ+k={IymaGJ{+oOVlhD}-sp^-GIeh_MT}{g z{0EVIEtBK*Ia>IWLjwF`FARcTdo)lAIeKt^{D8Dpgl@pcE3pE2XjBUB&ehBaAX4{!U;g7RelL2AspcfB#h=QW(*z#+o1s z4spsbek|`JnY!iO82jP~xvCHWCEzk2<$;tFW3VhI6*v>rm3v6wk2~|u)EWcdyS#$U zXce1#Y7NKvXOHw#$~k;oz`=8w_Ec01A0@jQTTi`{uKVmgK&cC1bDjQ zVnhHF?XKZna+wmUdk|WN*j9T54FpThS#c){obry7eqIEXEo#x3rMV|~rfO7bL`9Jm zSCz$FeF8i5oA5JLOGO)h^r)@QxqBC{Zq{{%wo4>|| zD10iWVN)k!J7=&fZ!Qj8FN5A81|7+?y^dkeJJB8ybSjK9=WH1_>CxsILb{3cA+4haK8On<0Wk>R=+D>0p9s*0o*rZjZd2BjW=`MrPBz=Q=d@1_(%Ym@E zLk)XMmFA1=D$UjG_^Pxki8zTvUB!Y!p`FC~|A(VapVMKeiqX*V+I zM2wb8DJiXP8LJODO)RMxJmy?_$?uNTuTsbr3O`5jNu{sm)p8E`<(f3a5R%v8HJOnX z(h5^>sxGI%uRp7ZrWI zFP6g78615#YW%(;zB^K%kY@rD)S2J*4x- zEx^OZqL8=5%lVu;c&3ry-PQ?(-v&FWzDy`b~?c3>22w%J$g|o+!uTWR5OMmkF~|3x4eWZD%v;l*qMg8#Brs1GpZn zghE_@a~j-qaJtg~5PytloXr$DwV-j@wE8ttT~%Uf&v``!urmm1XdHEI*JPlv&h=dx zX!LP%8SR7WX4mMC24Y-hGXZp$qKYuyp=E!q-6z$>`T0UL5Pf*0O5>I)qiQ~13siJM zbYsrsc*V7@QC{1btSZx0!BE(BH8Cd9<=BsZa2ui=4pRbagdv?Uvb+=ZEI&vx@+Bd8 zi74?qR0?q9$*fWA2U9FrZuhv8piPCktHxP0?p3ERsPBp@lPMa6%Y{XS_?*}#wot$w)=1MpL30K%%U^BRNGx-*pT+x z7z+@a_DUybcAED}|CPD(66+Z@(APG9?X{trM{%Pfr3%YxvQkl91d!XxMDgluO0_{m zYtGD~yE$Xmlu0!ue>FYlO;RnJ(hj>uL%Km6!4p>;vD3%U)jN965tA(=;##Qy3$nRQ znF4L2ea0^?ae(G8-EIcWu;a-BhL4LbtUxle>=zfiNZCp_Bd^LI`C_qoLj224_M+Jb=Vq$P^wBy8RicltbVe0@orC zO5dP7BW2CI36fttncj4M11KHw7L#+?7iE*0PMUk&LCq%kF8_A{$DeN{0Y>Vhq zF+g77r;22cybbB+ZzlO{b=)`Jfak2f`(Iur=TNTvvL0?JYBPi?PiZxOgo`CD|A9&z znPHYrG%Jg$`c}FR+9aJs(+%Sk3OIfs)hkklX_q1zSs(^VSvQr(f`K?Z%g)6Ut}Ip^ z?Wz_XA+nKAz_%hK2*tjUg|}X*sfedrv5~gv&sHW^cGvoN!KlZ+vtfC?;=XvYfYwmL#s*AWTH5#rKyiPrQQ6n(iG#Dfyz>FisGxEoShL{ zXS-~$AJ2JdJ7_37Z|zNkVq1>nQ|xxtu#L0#z*gdP6gW*BA5j;7-OeW~+Gzb;JNR|E zi(l6c>o~q|XZh4N?4OaC1MV@(TVUfhXBHW|0`Kmj1z^?(7of85f_mrbv~NH>+9C_B z%Gty8{JcQGv33v-l#Y2*OY#8M0fJu z^&-oE9$l2_nX4avQO<(<;xaJ(>F%Dj3kXJk&)x`KsX={Tu(>77bXs1eFRLX!Eug?Y z?&L+Dc2GOx=zu!*qO&9F0hh?*)52K)5>}R<4!-v*gXs~%1#9HpgGhgvUdN|xVBqS=P;BMRNJkg>rT6NtgsEYD`MJDNGENHlUoPD3teyLwS(KqtV@G`V8=G?T7K87XM*W2Y1vgUWK60A8(dyBK zYonQl#xV%xEn+l`#FCTxhmnE^*UE+vLTcE84(J@tJ0YFFqPSY1!mF#%)=5-j;l;qg zLyd;}eSvU)K+tBVC1s-}vQJs{RrYhbSbtN@(@9X`3X5}?%FkCoa+HDQmLk4@`pf(r z9W29nfa>$8H>_u*l%pSxQ2LRhJ`Hyb?@1ZybZ{Eb-oJ}XLr}X7HE{$ha{x7WLM@~6 zJd0WD1ILApFOP~ILZS#kdy7-ucA{I0eH;flK5r6#DXWX|Q_Vga7AN5A6Xi$iFXt$m zuziNl=Td#eZJs@~uim{odG+#}A6~vwEfAc~Cg;ISN0+Oda?iRtT+fVq*J_;uAIIY+ zR&8q@FT#a`W-(Le5Sj2XX^0;b18NO6G?m^4Erwks?Z5$#3AT7!HtUJwKuqL17&Yc( z(mdpUrAwuOa`~XHF@_v5QHy7%0+k~sC~+5r*OpZhcV={6_Oi?Kj&n+AC3a2O#2XSI zC1;JWS9nxwDGE&?o*QC!r+uOYwPB7<=hnp+j>IF0QcL2bXE!cMF-r)MQR2jlB)6Dj zn*EHVPeit)&N6Lu2@W%>KT+P=BYPbNjRv59C{5LiLa|L%y9OFEax*+H2j*oItBujy z=;0=Fj!aeDwCUK?+;Hq0#~?fIuvVe@T^*Fx7WV-6qAPp5G9@nDbjiiTdkGWUq=mMa z&aBGl=0rX15qkC80-5*(2R_Z)?-= zMl3v)VRz_x!c&i>Bd#ja&lW8W4fNG~cI|7v@m-;$s;0s_dLSzDS9B89$TpCM0fby6 z`8j>tDoK>~?T;s~|Ni~U_g{Yd zO{7|66SZcP=phBxnCXi}@mo*fxk&hb4qM$wWou=rr@6ZwmKQ#EW-~#_@**>b@YfUcy=Fo8V1l@pQqB9y+_!{%Hnnr>)cMrFGxNzChBb^+oj2kXjt|t#WfI zDK{xQ9x;Xn6{5s~-GN_s$aVe4yKlc~+c`|qaQ7=KSC4DAuO*Ih4#$;WYq@QIWYk-M z$-kRJ$Wv2a%09@MjATaI6pJhli24VC)IKEl$<>RJO>24>4uiZuhiE0bGga!>F+^l4 z;!?ecRY%3R>c-E)^0=CI<1B)|-J$+$u6jqc(z(2;d6Z@Zcm$={p&OTIq%@!@8r?@azp#iiU05 zKv~T0f1#iAOIZiXii$8QDfnyw*He(;8wc(t+H|W}$`sH}T?-N76+%JuZmv9=iT=`LM#5} zXmES`&5Pvr_7(nm^*MSFtowdCKJCWE@z2x! zucD9i3l16h{YLyg#NY44@2Bwl?&5eojZY)^1L@+A^y6?Ezo8#br}4Y)az8kH{=5e) zcy6Cgvrj#p#NdzEL_}g`jo2#lA5?l%KH!|vdH-0))ZfsDIBau&lF|c5lIFAZ!%i$; zNxL0hHSjLgMX{Kpk3998+#~-!*Ql-&vA{LVh|+c3&f4 zitwQN)o)VWvXR|T|MK+BzynsQubAIw(fU^Bnv^6Tyd*{T&TqYrq}+R7$-CijBuY%d z&KzZ75eGzsNeWDVkYC}!QzXQuaUm%)`Qs3OAmP@sr2MllI_sVCZ8I*i{wwDAOVZ&y_=FpLrtRm?hdDFHdV;sboUt*y}SQ(ihO^dOXlmO z`uSlKj5&9^L@u$8l>SJS4`8$NbP*pTxqBEro%VslPOrazMV&Mm7ry8XC;DsDa^2|1 zIxL%8;(i(>DyhmU)@9po62(TMTshv9ZI2KkQj(|pr9Onlg%r7~r<_6w&GoBqvFSao zA}&EYJXEcx-Y;TL)<(}8d4W=1P|s;AC9steAaN7iO4)IOSLzJ@tfpg!?khj_F2xZZ znXxu2JMg2{&ytry-v+h7^d3xIQFE@5? z?E7zu%`{QAnir^#zK`OUV%m)> z{7V8E@e2hqzdjjBO&yt5`xiHj_yg!g%J;|OYQD>Vu2WP7df26-a_=YvMC^nLlAsJw z{l2|@_M5LlMQg$plB?rATH#F~aM)>OuHb-O0j+}Ay;f^ObNp6#{5r8WMZDU7wqJD< zAZ6idfz=ulS$I^5Ukmx`O#TWm6RiJX_`69R zBGvbiH4^@P!B)Wowg$`nFA_bxOP5*lunj<2e@CWNqUKs`X%Y9I?vuQs|NO7}Qs&Sf z4)+BUDuoW+;b5Qz58dYjEqg$z*6xfdb@={#DrNhZ&F$eQOzz?DI=gtO`(~IV4y#yy z3L27_Pi;`__n-dtX?L~X|MO>mgxHJ5N zd+CCHz+S>&AZHi*%Sc24(K?eKushDW7yHX!T~a~)ADN-hctgAs{#zH9*#oW@Tg>*y zqC&r3E$R#w`fNUy2{DkneXllHGs z0q2uQu(SbLv;DA*0RdFAi?X}{0{io8S5-MB#R{H{}aYNG#gG z-bkXX7mpDfTO%I%=21=!6D2!i9eL(cOg@tsyGOGleD*ABCXKcazsUBC?iED0-D*sK zC{0Q9r{fYZ%V&$#Jbj&>C98!%H>eaOo{+9sQ6yj9#ohP@fgZ=whhiiwy*L`HAXm^= zDxP@yeE#`4oTHc@(nckfk2z5wRaxnUG^k>!jVA|@55lBg<_S*W%L*^Hi5qb6+&xDW zKF-O9=Yho?jMw5DOvl{`;ejt9O1wX2%q@~v0aAYxp zz0?wQ=wza5M>42@VbzR{#DYgp1Z5{O-+lK+K;|Ogdf0Jsoc{_{b;=*tUf=2X~eZ!)*#d zPePn9<1bUr-Mb}}!e{OPLtk_viHxZCmfZUmz`b&|4QCVSe8t1DVa+N1?d>C15}|++ zOQj!%9@Smi5Q@ox3S^u?61xR|DNJ1x0y!q0FnazO4aTKf;dKSQ-XmzrEJ(Ui_gljD z7Ib?2h+|eEdZGJXGePvqCnNZGzJ?hQg*Zvl{mMb_Y}W8$ly(EEVd9G%gfwe7>-q>r z*#<*j;@O1S1^Qc6p2CHD%zj$Ul4bhi<$?xO%rJHzQ7>V_gfMK??do%XT+evhVZmlS zqp62!m+}|N2ZweRIyNS`ZDRt&e|}tu>74{Tv*J>P3=uV)iU=KWk_&mLDICG_7;oZK zeM?Tm0r;xI_ChT+;$N}@m39W4qwIu3NAQuSp|;nD5;ue5ZgyC-`E()|kR2*sEf2$% zmAev)BloV+&bl+|%-5ZNmi1ZfJMza-wO{PE-jMa$yv|ZdRzC!UC& zsQsLG8)I4PvDDDBa60bS4t}JF)&R7gNr8fdv_&K}ptSz9(%6L(zc@O;zP)&2M&xsk z?T)~tXCmTxB8k(KPW#d4!_Po(dpQ0M{S}II`F*m#h3L!i#-o+|qPS{`+K17Gg-=CjSf+t>I zhQh_U(TI=}x0Eir)ob$r>mu+^;{IZ*)~tnL!l~%`?SZ~25oL|GOxyPu$Jwul5 zF|GbHZpQ-pZutUMn zD=vNy^@zsOv9AaB(BJ=X>{rAK@`*0T9Qt6ahpb8F5z?*!|Kc$vj zd4389)1RZ^@UIc7%ntfbLm>LAH}k9}f7rt)g`Zdz>dvJi_;c9e=slAaF*uBd&!5UN z4xd9IvsDQrCW+*$4TgT6UL;o; z++GHMB$1YVmJ6e_%DAo4nuZG{7O%8da1kiBkQ*u`9}s$nOW|@^uU-8R>-7|)jE^aX zQYxa111r29eQDZj=NCbfV_UC7kZJ+=V^}fl)%nbEwV!! zSwp+SZ=6>{yE=&d7j_nEe^^&3qx6noy6@;B$yY^azzXkM<`m#i5qnJUs*KZdc~sLw zcFugbHLD0pb%ds8IpAmh)8-*@FTkEsyu= zQEeJuK7KhHKlDu262*Y%o00Ir$Gx=>D;<^C4zjyb8T{$Lxo4Z6tvgyfbyi=ijifJO zxlN^#k+`)=y>tTotkj6|9@hd^*ijIFSNyP|gz=mh@3{OX0n^hHZLkzlJK|nfM-Ojn zP@}JiE!lNlb_r$xaCM0z#9dVO*c)chkZ!0f>e~kPvm1@fA_F#SfHQ^Ed5bEva>c9G z#V9w*X?lH(@?#S`mA~$&2d^Y;0!hU?R_h*;YcQQ^bt3tFT$40#Fsh+&)gb+U%0^i6 z>PrfI%%dBsjENNROT}jBk;n70MG3v4vo`sP`_`sQFkvh+dw^q4e!2tVn{|P`0m_#{ zo%SEn-+?1|XYYk(T=0_*480#J6A?`1acyK-&9FrO5RMyIN(yPr^;6Ai+i8dT5H4A^ZKvCA%GSiWbd7JB44PRC~`tVge?$7fS)(ob-In%^Kqj{sDw zx`EZw;b;(QY#tg164M_0_6%EZdWSWWNIfc0^zSQLPCdR8 z-|_W+GFzmuD==Mv3JfrriBO_nMQZ+pP~RlvckicjVZI?~RSB~Sg^i~uA2+;3ztfDE za!PG#-li7DJK3mN2RCMa%Bfe}=f1gVKM6eTq%`AZ^W?xb+GoOBH3Z4$3a4P&v;&|Y z@@nRy5FuI$phFt;3x;VA8!V`^Nx>Y1L4 zLbRdopD&8jWI>{CIesTu^>wkT(s}VQpGXY_uk=MY1{S(_sXQ5f(VnDOcIjWynuy&N zG{Fbrq(S`FA5mey<{C;4mDs*=aH?{pkD9w3wgqNNl-o9yK1wp$z*IJQIf2Bi*Fq69 zMpD^PY_i2uM{yEYMxG$ z^3Hb4C)i$W_>1cCNm%=}Ny(N@%&{@^aGWy@W3klF zP>BMTdd-&l4AJvhKsR38KOyiKZ_Sr8K7gIRP13v&qr zId9l6(Y!%_0cZn7^Phy&5!kXu5$)|Wo#dZ){>4^f+)Xc~H zT|l_QFzd@-uRXHt(UV>MO}%cRW+FB<3Hj-(R10Q5!anCT&jHC*7 zR|qpJuHhuYaXE`t;+SDJ#mr##48c+86x=phXoe`O-Ly7XvK>cdOE&~!gXoFfcH3|- z3$;ZrEEs2B`N>&f9RT-LEvGis?6L^dtaR#=bWj?vY$SDL8#*PIfuu~Jp{r8@kCaI; zbfl7haHK|PVcID~8p=yMg{yU(a=8SH`G;k$VUK*vKGVudlV*oJLLINBbrJ`d-H5AT zhC@eOL3&#&CBa;^+eoypotNtTCrv9`^;1xljh92{^JgiOjaF1Wg4AL6f${%8sgWw%u+t zLw=mB^)eCyb;298A{{He$~&&?=n#4$Hz)L(7G0k>8e6R=yGe`jU$=ytvKRZVY5{otR*fdEtJwEdVdFNA-DYZy4ZuELv0Xqyq*T>{kFKe2iGlTr$ z86z)ylmf{uGIobBhIhCkn%0oSq@e~{%Wd7|S7g^*AYFbtcG-0ZzlF{-l;1*xn5x)0 zBvyE(2|yap(wU%g3PU_DCPkbEMK~&djAW0hdaD{yLG0LB^tz|OI2L9_IVX}j<{b@` zVdY{j{}X1DI+_T=3x8| z4YBxtyCwFu+x`;BJ>!n6qg+@-`Gu4(Ybii7DCC!)i|%&Ka_tX zRk^LpI23@%mL9WDeZRKU_j&R_h?*j#0K>Z$jp+DzdKWxEFW=Kgs{*~wq8qN6-FW)P z$d~hZI{zX8@)iy0$>)o-4468%co5Xjlrlxdle{igr;GH}BAfmEF1uVUe>4IfMv9!e z=tkY}OKQ-e7H?w+FwGb-0JF=qSk(bbkoHwRbgdQ*2LtlJ=61$gV}c2+>g3`OYR8Y* z7rk@Pc&ffDo#D24jjBsVNCMB+j2ku56Vqs?EZz(d={utWhtqWbocGbNNor_*n}1th zAYM0}FyWo0Wlc3);yd_gf3<8c*y!)Wk@*HlyTGR1t=IJU(eTb!jaaNB&xEJAEe~k+pM@isQI=LZ- zj~~;LRQuDHL^Fz3Xxz4|x6Q#|^BkZaT-z+*8u>lPp3WpXk;sZDoo`giiSif$7I~jA z*H{}(cq_uw<~~!<7}0pxZgas#z&neF+o%7~pRr~7>$XlpBhCEfYCc?}r-oA7CydyA zI@TQ2!A^rZ-r<&Oe;W{7USxuUXX#6hrRg;_iZ#?bGi@;hzvO|WcD&eu zXo9#&y>?HBn%zMHE6eBqD9X9iNL`caV{^L=aIf`-=4OzFc~E6l8}ob8qIpSbb)oPV zzH92b+l}&GPkI?Y`03q2d*a8B^B29L&SFUaW_P}CC|0umfBeS1>2`PR&5^sTbOA;j zF8W4D3A;^|sQb~uPx-@#l2^BRD0i)Gx30o^|7LXwTr@qjeVMl{erE0BY!Rfl8Mi8) z#8RdgWE_)?bKqSOcd|Url`b=ER@0;!4~?XpUGSB)L34HU`bfiYg7{9UrPi(o2^w~A zy!TW7Q$HF%fBI?iQ*U~p1~(HWmNaVv?_eVP?Jw8ZXX`>xsX=r$zT2sp#R?9gMj*VcH zYRFOuBZ7Mo@P-RAW2Xz8UzpPPd_-fj^L6RwaxP0M1ID{KM5BjtYKCndMkzPrvv@6% zv!E=KQf}gbxx*8&F&(*s99d&DY7U!~;6pRPhls6+k-J19YXyv2 zH;I)jGK-@H*%S{&^p-K*Z_WBxtGF_a{*$XxAHkY_Q6F1Xf7>h zpDq*R^$=jUFVIb20WmZ8fe3`Y8e&ojr3fEe$K35S)^4y1zvh(sp;JtQGr zf8SiADl71+RTFr_Z?dhr)i4C9HKvo4xg);D?d?28`Hk~>uIm?C;bn1YxqxJZtE4ee zdo@)^eu}PcSh?gOGnYWVVGGm(Pmd2=FUoNxUXi6cA#AUBBM2&B28PnVRWo*{D$r;O zMIL%cy;k2{H?StrQe<=+5BiV}arY3oEhTXK;%mx?l1uF3v_REzl z`p8CAShZJ;QvBHy-deYbR_o z43q){ZOK=0%Q$QNGIwoc0+J+^e`mskZOZ17B>Rdw9OcpqlywY|yGJauGc$qIlIA(A zGtI!pkO)UfL+YcP@L{%H0=~nc-eFi;8ygXH6awkk8_rP^laN5xv$N4-b}vV%|Dl&u zMoX%CQ7a}(PD<6qHH1*OcW7$r+&kVTY`BXyjsh+`OS5{jnOt$4;c=0~f2+w#&e3RK zudrU@{J|hPe+W$3JvFjv=q5G?Muj8PP3!|Bo1$Kt_c+W@=tE{j+$vS)!|tAm?k;>6 zgcpIPH-s+ACW`!y3~FU=HR&=fCU#Beh#AJK^uoE*rWI@>+&{B3lxq zeI;GXs`q8Kl;Z)LV#2Y`YKod+lz~$^0V;p_<_bOCVlnFctJt_ge>pa2+Wd5}rIhwT z^-V|Qog>eX_@<%efnRFA%x2Sg8YR@`yCj_>jvwpu2IvUhpq{VgN6!ZXrG3tu+DAG% z?O%K2))cq4;&gAYacp9L)y8>~fAwqi2Sr9|X*jCZ%QD4K>6?S#maPy{1H;V7dnV_! zvB{O29i-HJTGWKRf2u}~N)T5i(h4MPad?rn#jTb;{Usd7N;i|fyedIvTeW}~qUhg; z)CY$?a-#e=(5f$3u(k19$~FKayOb^Z;*OQKSL|qPLju`wpq-rP{6EHZ|2lF*KS1bO zg>5@snfp5tr7m#+zRb1 zpZ6Wao(r}%+vfrk*>hp!kbDHyyNPZ+C**N^Q>nVWXCLOGAO=Q?uyvDrieA0Tz$B-PpzdrXQ&EWEzUgB zTfGrm+wy8^e_fYq?ecdwO9!*DH0^DIuNnfc)!HU)gSdHRp>H}OoBuOiPh31sO72-y zdY)bQnbx%;siEcqyZ`!9cumODEWR&lpz7wbJNH>fz*jN_UkVTCSnRI}B&iXH1(8n% z!59@wWTiN%T~b>_YP8|war5-NOw;Op@qIGSlDv`*e+!cQe36FsnpR!YO(p1wO|#h6 z?UqquFU*_RJE29-K;9VM&mcN84pNe%GlBe5wJF$(NvN-*BowOsgroFf%s8)Bgsudg zdd*r*aTnn@i)XA<`D${u$d*5%Eaw>5Mf}I;SM-rM0){LIjc=~8jWCpZ5Qc69Bu_5T ze#T{-e?=`8E~fGGC}GW+EPEHD3qAxt;t^6E;rVoXo8jN<@CGsCw3)JN_X5+?TnBP2 zYBC%xx=FMQ(NQFndQ^oEEFroOWeA(im4##)HZ;2=u4uHSf);~&A#eZ!xL2d+ogVx` zp~8y-bv|IJmEFYJB5HEa;;eTD{O$|4Ar$8Ze+utN+2hA&y9KdUMX zi95@p%7~xeOHQj|0i})i5L<9>Fy13{!M)yJ;eY6Q(rxf*F<);d=~O zf4;;~=jU{7vG{QJxD5Wi3j~&@s(6XtVZg(SoE6KpQhk7*4=-p5SAQx?qTg0gl3XN~ zLQ*APYCQhALu3aVE0(w13Tba)kML#z{SeHG92cS#tOjhXKPCmC6Byp=>ts2)`OB!o z9_>2O@ad>y$*4Nf(?5?o=2aL^Y6$xae-HaR&{j|X%0o!8sS`aL@W9u!LY{p#>cH9j zF)8P-NjTO)=*zlX{HJQuXU|6+tvK6>{sMK)R&|Fo!)?0AyFvX=!)LJiE1_O47pLF+ zszK7DeQY1b>s2vl9&Y3Sl4$eT3Od%Qr_(^9rc?30VpzWkXF`4>vd(2%C-5`0e+bXx zMmDFqJC6`xr)ROd$eNUGz7aM&`8lgVyE|v=3>zBZCfrKmY6VM<)CrfxX@N~m>I8>a zU?!(EeJd5GP;d226cT%$9eo6KD+GR{!_W!Z|2{vqs7bJ~%@at3HM2$oO&vRpj%w>6 zRg4}!9>b1!DB?e7WN;FKmI-RKf7>TqOU1h7$!>4usrC_0B}6;mk!lChVZLPxvTcAr z+2)W-9=i7z`*Zlz>K-4pcfv^=ng|N`(Rm6j|9Fwj5FOGhJj3aMlR_$UYygp+G)8&k zTS2>EOCuPT=fOS?Z2(US&Jok5kRL^#1fvSr37-$TLj+4(^)Hipc0pdgf5M;g$w7#2 zn-_7QBl`P4bfG(pTI|YM>&lRWj5~u<(eqwJoSq(# z1$@nnUG?Hu4NXG z?a}CxR`HK~*PxHA(Y^PM8dV_o_1!%O7iw${Ed*{KSf44FxSRgI{IzeU_H(|p&iR4o zc+a{1k$ZO$(gb~G{%fj;Ax2(Da1DvusK5Weocm}yh;@{3#9r@F$<-xR7ILa{Xr7^< zYJU-3a0Lqo%(pUNz5>fPi7R~gZv%8@Vz7(j|9y8nQY0nHmeY1Gdr4%HM;=ed$>rMkuHvIn!zMQJc5MQ6nl*30 zZ4S;ZGyrR-RqRf*+nLF>n_SKBvyl@<)twhdhhjT~!~ToNZ(ae2oL&RGwgyyvxqk}y zwpH)}0c)0Adtv9AlVRJ&$X-(S{GZhEo_rooVVqXWwH|FfawLq8OYL0q(@L_vnZ>ASS((~I3-$!X(PD>o zXqQ5#wc0q@f;m((_5E`fky^~%^na;!VCQM~VTbS->?t}d9;mxtyO;fOO)+%{fqJ8F zC=vwb+hju7pq)@?>bW(0?RO|KxJzE1)|q1)gPBKGp%yXX7_!{F1^c>wkk$%oe*VQs*XkK?WYD+YA(0?j>Im2{i zv{KYMt9yX8yh-0nb8)-5wfxZWU;F>KDb_-`qBXfEzCNjg_RdHHE(RSpz8I$yn46s* zRX!u74p~7cTyb6Y!zF2tOQOyHt?TqAC%M6)vv12uuI~GnIR{s}>OM|&El}(qqHn-c ztQSN~=|A46Gy!(V63ZfkhJRH~OcNzaO=$V$$AD7K+&XM(eY{FS9Y>d2ZA1#XO%emG zbAA?Kg5e4K%mOz1jQ2fe92K%tBHZU8SXOeW-~e&p3IfSmUs0;ursynpe`ouVLb9`)6{ zN5f714G!o>{ct0LG}j2&Y(D?7%p$6kcU^MLZzd-17U^mHi7U%ds~s8Kz3_sOg@GeB ztB(0&2G$uTM>5IYRJ02Gii_CWgU@1 z2(Vp-OlK47`ZT)CY=7pn4)aZX`kBu>hTxyD^P->Q^Jjd;XHN z`>e~nK6Vf==Ie|OvWFal(U}m^kpRMOPBH3b`+wB?vC~Ir2qc8g z_%i9@@4>7rAV|AW3EfrLfb@Wu-?jD(O1?1U`7~PbKbH$U+OVSoLF8j*Fvz17&sIHl zGXD3Pt2BPf^MCN_-ETwT?j}sNhbuU(Jv{X2A=m~72?mZh0(Y0igGn4|y#w3?y`+sRLF&(7YRoL*g=yjFs9kOG)cI6Gq-4^-YL=!>ub97VVCR^S-imL2vx>BkLDcbgLdgNILlUF^J#8=D8fRa z&EDn=^M6c&0GXX)lm>20M!GU{4--|D=G0F;4Ir(DP$Z#-Nr9 zdmoa%2`W^yZV-qD7Unh`6+{Y%NPXewxN-ps))mXooAhYZhVH$9%ZP7@AK~td@|&gh3_Z$?N5|}P+JOz zw|`w|I>Hqjc#!!I#wAYWqepoWyug^6Gw89S7YXW`Fg2;onFJE~tt#&INV1w8dy2P2 z4RrZht|1V)YB@<;S5G~Y41!6WQP_p3aV{HpC4a!1dd!kmX1I3I5EVKZw>wR4VfjwsWz$bqTH(##IdkVQPDLbSGrG1FdbsDHof zA$lL6G6?@75VToHNo1+C$6nwq$9kB++@(N-j)s_zCZylu*=K zrK7lkFmVHyVV$hEu5HG*jNJ-F&nP4TouGC@QoG$mQ2jMhff{TlgIokppu>LC!59nU Ne*sU8=M0Wb0{{-~r}h8< diff --git a/dist/fabric.require.js b/dist/fabric.require.js index fe3f9275ad5..0b245194051 100644 --- a/dist/fabric.require.js +++ b/dist/fabric.require.js @@ -46,6 +46,11 @@ fabric.SHARED_ATTRIBUTES = [ "stroke-opacity", "stroke-width" ]; +/** + * Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion. + */ +fabric.DPI = 96; + (function(){ @@ -378,9 +383,9 @@ fabric.Collection = { * Rotates `point` around `origin` with `radians` * @static * @memberOf fabric.util - * @param {fabric.Point} The point to rotate - * @param {fabric.Point} The origin of the rotation - * @param {Number} The radians of the angle for the rotation + * @param {fabric.Point} point The point to rotate + * @param {fabric.Point} origin The origin of the rotation + * @param {Number} radians The radians of the angle for the rotation * @return {fabric.Point} The new rotated point */ rotatePoint: function(point, origin, radians) { @@ -416,19 +421,19 @@ fabric.Collection = { t[2] * p.x + t[3] * p.y + t[5] ); }, - + /** * Invert transformation t * @static * @memberOf fabric.util - * @param {Array} t The transform + * @param {Array} t The transform * @return {Array} The inverted transform */ invertTransform: function(t) { var r = t.slice(), a = 1 / (t[0] * t[3] - t[1] * t[2]); r = [a * t[3], -a * t[1], -a * t[2], a * t[0], 0, 0]; - var o = fabric.util.transformPoint({x: t[4], y: t[5]}, r); + var o = fabric.util.transformPoint({ x: t[4], y: t[5] }, r); r[4] = -o.x; r[5] = -o.y; return r; @@ -438,7 +443,7 @@ fabric.Collection = { * A wrapper around Number#toFixed, which contrary to native method returns number, not string. * @static * @memberOf fabric.util - * @param {Number | String} number number to operate on + * @param {Number|String} number number to operate on * @param {Number} fractionDigits number of fraction digits to "leave" * @return {Number} */ @@ -446,6 +451,37 @@ fabric.Collection = { return parseFloat(Number(number).toFixed(fractionDigits)); }, + /** + * Converts from attribute value to pixel value if applicable. + * Returns converted pixels or original value not converted. + * @param {Number|String} value number to operate on + * @return {Number|String} + */ + parseUnit: function(value) { + var unit = /\D{0,2}$/.exec(value), + number = parseFloat(value); + + 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; // or * 4 / 3 + + case 'pc': + return number * fabric.DPI / 72 * 12; // or * 16 + + default: + return number; + } + }, + /** * Function which always returns `false`. * @static @@ -537,7 +573,8 @@ fabric.Collection = { * @memberOf fabric.util * @param {Array} objects Objects to enliven * @param {Function} callback Callback to invoke when all objects are created - * @param {Function} [reviver] Method for further parsing of object elements, + * @param {String} namespace Namespace to get klass "Class" object from + * @param {Function} reviver Method for further parsing of object elements, * called after each fabric object created. */ enlivenObjects: function(objects, callback, namespace, reviver) { @@ -1149,7 +1186,7 @@ fabric.Collection = { /** * Returns "folded" (reduced) result of iterating over elements in an array * @param {Function} fn Callback to invoke for each element - * @param {Object} [context] Context to invoke callback in + * @param {Object} [initial] Object to use as the first argument to the first call of the callback * @return {Any} */ Array.prototype.reduce = function(fn /*, initial*/) { @@ -2687,6 +2724,7 @@ if (typeof console !== 'undefined') { capitalize = fabric.util.string.capitalize, clone = fabric.util.object.clone, toFixed = fabric.util.toFixed, + parseUnit = fabric.util.parseUnit, multiplyTransformMatrices = fabric.util.multiplyTransformMatrices, attributesMap = { @@ -2728,7 +2766,8 @@ if (typeof console !== 'undefined') { } function normalizeValue(attr, value, parentAttributes) { - var isArray; + var isArray = Object.prototype.toString.call(value) === '[object Array]', + parsed; if ((attr === 'fill' || attr === 'stroke') && value === 'none') { value = ''; @@ -2737,7 +2776,9 @@ if (typeof console !== 'undefined') { value = (value === 'evenodd') ? 'destination-over' : value; } else if (attr === 'strokeDashArray') { - value = value.replace(/,/g, ' ').split(/\s+/); + value = value.replace(/,/g, ' ').split(/\s+/).map(function(n) { + return parseInt(n); + }); } else if (attr === 'transformMatrix') { if (parentAttributes && parentAttributes.transformMatrix) { @@ -2758,11 +2799,9 @@ if (typeof console !== 'undefined') { else if (attr === 'originX' /* text-anchor */) { value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center'; } - - isArray = Object.prototype.toString.call(value) === '[object Array]'; - - // TODO: need to normalize em, %, pt, etc. to px (!) - var parsed = isArray ? value.map(parseFloat) : parseFloat(value); + else { + parsed = isArray ? value.map(parseUnit) : parseUnit(value); + } return (!isArray && isNaN(parsed) ? value : parsed); } @@ -3038,33 +3077,37 @@ if (typeof console !== 'undefined') { return styles; } - + /** * @private */ function parseUseDirectives(doc) { - var nodelist = doc.querySelectorAll("use"); - for (var i = 0; i < nodelist.length; i++) { - var el = nodelist[i]; - var xlink = el.getAttribute('xlink:href').substr(1); - var x = el.getAttribute('x') || 0; - var y = el.getAttribute('y') || 0; - var el2 = doc.getElementById(xlink).cloneNode(true); - var currentTrans = (el.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')'; + var nodelist = doc.getElementsByTagName('use'); + for (var i = 0, len = nodelist.length; i < len; i++) { + var el = nodelist[i], + xlink = el.getAttribute('xlink:href').substr(1), + x = el.getAttribute('x') || 0, + y = el.getAttribute('y') || 0, + el2 = doc.getElementById(xlink).cloneNode(true), + currentTrans = (el.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')', + parentNode; + for (var j = 0, attrs = el.attributes, l = attrs.length; j < l; j++) { var attr = attrs.item(j); - if (attr.nodeName !== 'x' && attr.nodeName !== 'y' && attr.nodeName !== 'xlink:href') { - if (attr.nodeName === 'transform') { - currentTrans = currentTrans + ' ' + attr.nodeValue; - } else { - el2.setAttribute(attr.nodeName, attr.nodeValue); - } + if (attr.nodeName === 'x' || attr.nodeName === 'y' || attr.nodeName === 'xlink:href') continue; + + if (attr.nodeName === 'transform') { + currentTrans = currentTrans + ' ' + attr.nodeValue; + } + else { + el2.setAttribute(attr.nodeName, attr.nodeValue); } } + el2.setAttribute('transform', currentTrans); el2.removeAttribute('id'); - var pNode=el.parentNode; - pNode.replaceChild(el2, el); + parentNode = el.parentNode; + parentNode.replaceChild(el2, el); } } @@ -3108,9 +3151,9 @@ if (typeof console !== 'undefined') { return function(doc, callback, reviver) { if (!doc) return; var startTime = new Date(); - + parseUseDirectives(doc); - + var descendants = fabric.util.toArray(doc.getElementsByTagName('*')); if (descendants.length === 0 && fabric.isLikelyNode) { @@ -3195,18 +3238,10 @@ if (typeof console !== 'undefined') { callback(false); }, - /** - * @param {String} url - * @param {Function} callback - */ get: function () { /* NOOP */ }, - /** - * @param {String} url - * @param {Object} object - */ set: function () { /* NOOP */ } @@ -3380,7 +3415,7 @@ if (typeof console !== 'undefined') { * Parses "points" attribute, returning an array of values * @static * @memberOf fabric - * @param points {String} points attribute string + * @param {String} points points attribute string * @return {Array} array of points */ parsePointsAttribute: function(points) { @@ -3717,7 +3752,7 @@ fabric.ElementsParser.prototype.checkIfDone = function() { /** * Adds value to this point * @param {Number} scalar - * @param {fabric.Point} thisArg + * @return {fabric.Point} thisArg */ scalarAddEquals: function (scalar) { this.x += scalar; @@ -5442,11 +5477,10 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ * @type Array * @default */ - viewportTransform: [1, 0, 0, 1, 0, 0], + viewportTransform: [1, 0, 0, 1, 0, 0], /** * Callback; invoked right before object is about to be scaled/rotated - * @param {fabric.Object} target Object that's about to be scaled/rotated */ onBeforeScaleRotate: function () { /* NOOP */ @@ -5733,6 +5767,8 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ this.lowerCanvasEl.style.width = this.width + 'px'; this.lowerCanvasEl.style.height = this.height + 'px'; + + this.viewportTransform = this.viewportTransform.slice(); }, /** @@ -5775,8 +5811,8 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ * @return {fabric.Canvas} instance * @chainable true */ - setWidth: function (value) { - return this._setDimension('width', value); + setWidth: function (width) { + return this._setDimension('width', width); }, /** @@ -5785,8 +5821,8 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ * @return {fabric.Canvas} instance * @chainable true */ - setHeight: function (value) { - return this._setDimension('height', value); + setHeight: function (height) { + return this._setDimension('height', height); }, /** @@ -5955,7 +5991,7 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ */ _draw: function (ctx, object) { if (!object) return; - + ctx.save(); var v = this.viewportTransform; ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); @@ -6703,7 +6739,7 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ * Provides a way to check support of some of the canvas methods * (either those of HTMLCanvasElement itself, or rendering context) * - * @param methodName {String} Method to check support for; + * @param {String} methodName Method to check support for; * Could be one of "getImageData", "toDataURL", "toDataURLWithQuality" or "setLineDash" * @return {Boolean | null} `true` if method is supported (or at least exists), * `null` if canvas element or context can not be initialized @@ -6915,7 +6951,8 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype }, /** - * @param {Object} pointer + * @private + * @param {Object} pointer Actual mouse position related to the canvas. */ _prepareForDrawing: function(pointer) { @@ -6929,18 +6966,15 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype /** * @private - * @param {fabric.Point} point + * @param {fabric.Point} point Point to be added to points array */ _addPoint: function(point) { this._points.push(point); }, /** - * Clear points array and set contextTop canvas - * style. - * + * Clear points array and set contextTop canvas style. * @private - * */ _reset: function() { this._points.length = 0; @@ -6951,9 +6985,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype /** * @private - * - * @param point {pointer} (fabric.util.pointer) actual mouse position - * related to the canvas. + * @param {Object} pointer Actual mouse position related to the canvas. */ _captureDrawingPath: function(pointer) { var pointerPoint = new fabric.Point(pointer.x, pointer.y); @@ -6962,19 +6994,18 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype /** * Draw a smooth path on the topCanvas using quadraticCurveTo - * * @private */ _render: function() { - var ctx = this.canvas.contextTop; - var v = this.canvas.viewportTransform; + 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(); - var p1 = this._points[0], - p2 = this._points[1]; - //if we only have 2 points in the path and they are the same //it means that the user only clicked the canvas without moving the mouse //then we should be drawing a dot. A path isn't drawn between two identical dots @@ -7004,19 +7035,18 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype /** * Return an SVG path based on our captured points and their bounding box - * * @private */ _getSVGPathData: function() { this.box = this.getPathBoundingBox(this._points); return this.convertPointsToSVGPath( - this._points, this.box.minx, this.box.maxx, this.box.miny, this.box.maxy); + this._points, this.box.minX, this.box.minY); }, /** * Returns bounding box of a path based on given points - * @param {Array} points - * @return {Object} object with minx, miny, maxx, maxy + * @param {Array} points Array of points + * @return {Object} Object with minX, minY, maxX, maxY */ getPathBoundingBox: function(points) { var xBounds = [], @@ -7042,19 +7072,21 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype yBounds.push(p1.y); return { - minx: utilMin(xBounds), - miny: utilMin(yBounds), - maxx: utilMax(xBounds), - maxy: utilMax(yBounds) + minX: utilMin(xBounds), + minY: utilMin(yBounds), + maxX: utilMax(xBounds), + maxY: utilMax(yBounds) }; }, /** * Converts points to SVG path * @param {Array} points Array of points + * @param {Number} minX + * @param {Number} minY * @return {String} SVG path */ - convertPointsToSVGPath: function(points, minX, maxX, minY) { + convertPointsToSVGPath: function(points, minX, minY) { var path = [], p1 = new fabric.Point(points[0].x - minX, points[0].y - minY), p2 = new fabric.Point(points[1].x - minX, points[1].y - minY); @@ -7078,7 +7110,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype /** * Creates fabric.Path object to add on canvas * @param {String} pathData Path data - * @return {fabric.Path} path to add on canvas + * @return {fabric.Path} Path to add on canvas */ createPath: function(pathData) { var path = new fabric.Path(pathData); @@ -7100,7 +7132,6 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype * On mouseup after drawing the path on contextTop canvas * we use the points captured to create an new fabric path object * and add it to the fabric canvas. - * */ _finalizeAndAddPath: function() { var ctx = this.canvas.contextTop; @@ -7389,6 +7420,10 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric this.canvas.renderAll(); }, + /** + * @private + * @param {Array} rects + */ _getOptimizedRects: function(rects) { // avoid creating duplicate rects at the same coordinates @@ -7451,7 +7486,7 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric else { width = this.dotWidth; } - + var point = new fabric.Point(x, y); point.width = width; @@ -7970,8 +8005,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab /** * Translates object by "setting" its left/top * @private - * @param x {Number} pointer's x coordinate - * @param y {Number} pointer's y coordinate + * @param {Number} x pointer's x coordinate + * @param {Number} y pointer's y coordinate */ _translateObject: function (x, y) { var target = this._currentTransform.target; @@ -7987,9 +8022,9 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab /** * Scales object by invoking its scaleX/scaleY methods * @private - * @param x {Number} pointer's x coordinate - * @param y {Number} pointer's y coordinate - * @param by {String} Either 'x' or 'y' - specifies dimension constraint by which to scale an object. + * @param {Number} x pointer's x coordinate + * @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 */ _scaleObject: function (x, y, by) { @@ -8369,7 +8404,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab /** * @private - * @param {HTMLElement|String} canvasEl Canvas element * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized */ _createUpperCanvas: function () { @@ -8397,8 +8431,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab /** * @private - * @param {Number} width - * @param {Number} height */ _initWrapperElement: function () { this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', { @@ -8414,7 +8446,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab /** * @private - * @param {Element} element + * @param {HTMLElement} element canvas element to apply styles on */ _applyCanvasStyle: function (element) { var width = this.getWidth() || element.width, @@ -8758,8 +8790,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @param {Event} [e] Event object fired on Event.js gesture * @param {Event} [self] Inner Event object */ - _onGesture: function(e, s) { - this.__onTransformGesture && this.__onTransformGesture(e, s); + _onGesture: function(e, self) { + this.__onTransformGesture && this.__onTransformGesture(e, self); }, /** @@ -8767,8 +8799,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @param {Event} [e] Event object fired on Event.js drag * @param {Event} [self] Inner Event object */ - _onDrag: function(e, s) { - this.__onDrag && this.__onDrag(e, s); + _onDrag: function(e, self) { + this.__onDrag && this.__onDrag(e, self); }, /** @@ -8776,8 +8808,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @param {Event} [e] Event object fired on Event.js wheel event * @param {Event} [self] Inner Event object */ - _onMouseWheel: function(e, s) { - this.__onMouseWheel && this.__onMouseWheel(e, s); + _onMouseWheel: function(e, self) { + this.__onMouseWheel && this.__onMouseWheel(e, self); }, /** @@ -8785,8 +8817,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @param {Event} [e] Event object fired on Event.js orientation change * @param {Event} [self] Inner Event object */ - _onOrientationChange: function(e,s) { - this.__onOrientationChange && this.__onOrientationChange(e,s); + _onOrientationChange: function(e,self) { + this.__onOrientationChange && this.__onOrientationChange(e,self); }, /** @@ -8794,8 +8826,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab * @param {Event} [e] Event object fired on Event.js shake * @param {Event} [self] Inner Event object */ - _onShake: function(e,s) { - this.__onShake && this.__onShake(e,s); + _onShake: function(e, self) { + this.__onShake && this.__onShake(e,self); }, /** @@ -10688,6 +10720,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * @private + * @param {Object} [options] Options object */ _initGradient: function(options) { if (options.fill && options.fill.colorStops && !(options.fill instanceof fabric.Gradient)) { @@ -10697,6 +10730,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * @private + * @param {Object} [options] Options object */ _initPattern: function(options) { if (options.fill && options.fill.source && !(options.fill instanceof fabric.Pattern)) { @@ -10709,6 +10743,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * @private + * @param {Object} [options] Options object */ _initClipping: function(options) { if (!options.clipTo || typeof options.clipTo !== 'string') return; @@ -10758,7 +10793,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati * @return {Object} Object representation of an instance */ toObject: function(propertiesToInclude) { - var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, object = { @@ -11012,17 +11046,17 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati * @param {Boolean} [noTransform] When true, context is not transformed */ _renderControls: function(ctx, noTransform) { - var v = this.getViewportTransform(); + var vpt = this.getViewportTransform(); ctx.save(); if (this.active && !noTransform) { var center; if (this.group) { - center = fabric.util.transformPoint(this.group.getCenterPoint(), v); + center = fabric.util.transformPoint(this.group.getCenterPoint(), vpt); ctx.translate(center.x, center.y); ctx.rotate(degreesToRadians(this.group.angle)); } - center = fabric.util.transformPoint(this.getCenterPoint(), v, null != this.group); + center = fabric.util.transformPoint(this.getCenterPoint(), vpt, null != this.group); if (this.group) { center.x *= this.group.scaleX; center.y *= this.group.scaleY; @@ -11131,7 +11165,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Creates an instance of fabric.Image out of an object - * @param callback {Function} callback, invoked with an instance as a first argument + * @param {Function} callback callback, invoked with an instance as a first argument * @return {fabric.Object} thisArg */ cloneAsImage: function(callback) { @@ -11201,7 +11235,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Returns true if specified type is identical to the type of an instance - * @param type {String} type Type to check against + * @param {String} type Type to check against * @return {Boolean} */ isType: function(type) { @@ -11536,7 +11570,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Translates the coordinates from center to origin coordinates (based on the object's dimensions) - * @param {fabric.Point} point The point which corresponds to center of the object + * @param {fabric.Point} center The point which corresponds to center of the object * @param {String} originX Horizontal origin: 'left', 'center' or 'right' * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' * @return {fabric.Point} @@ -11646,7 +11680,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Sets the position of the object taking into consideration the object's origin - * @param {fabric.Point} point The new position of the object + * @param {fabric.Point} pos The new position of the object * @param {String} originX Horizontal origin: 'left', 'center' or 'right' * @param {String} originY Vertical origin: 'top', 'center' or 'bottom' * @return {void} @@ -12003,7 +12037,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Scales an object (equally by x and y) - * @param value {Number} scale factor + * @param {Number} value Scale factor * @return {fabric.Object} thisArg * @chainable */ @@ -12024,7 +12058,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Scales an object to a given width, with respect to bounding box (scaling by x/y equally) - * @param value {Number} new width value + * @param {Number} value New width value * @return {fabric.Object} thisArg * @chainable */ @@ -12036,7 +12070,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati /** * Scales an object to a given height, with respect to bounding box (scaling by x/y equally) - * @param value {Number} new height value + * @param {Number} value New height value * @return {fabric.Object} thisArg * @chainable */ @@ -12052,24 +12086,24 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati * @chainable */ setCoords: function() { - var strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, theta = degreesToRadians(this.angle), - vpt = this.getViewportTransform(); - - var f = function (p) { - return fabric.util.transformPoint(p, vpt); - }; - var w = this.width, + vpt = this.getViewportTransform(), + f = function (p) { + return fabric.util.transformPoint(p, vpt); + }, + w = this.width, h = this.height, - capped = this.strokeLineCap === "round" || this.strokeLineCap === "square", - vLine = this.type === "line" && this.width === 1, - hLine = this.type === "line" && this.height === 1, - strokeW = (capped && hLine) || this.type !== "line", - strokeH = (capped && vLine) || this.type !== "line"; + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; + if (vLine) { w = strokeWidth; - } else if (hLine) { + } + else if (hLine) { h = strokeWidth; } if (strokeW) { @@ -12111,11 +12145,12 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati mt = f(_mt), mr = f(new fabric.Point(_tr.x - (wh.y/2 * sinTh), _tr.y + (wh.y/2 * cosTh))), mb = f(new fabric.Point(_bl.x + (wh.x/2 * cosTh), _bl.y + (wh.x/2 * sinTh))), - mtr = f(new fabric.Point(_mt.x, _mt.y)); + mtr = f(new fabric.Point(_mt.x, _mt.y)), - // padding - var padX = Math.cos(_angle + theta) * this.padding * Math.sqrt(2), + // padding + padX = Math.cos(_angle + theta) * this.padding * Math.sqrt(2), padY = Math.sin(_angle + theta) * this.padding * Math.sqrt(2); + tl = tl.add(new fabric.Point(-padX, -padY)); tr = tr.add(new fabric.Point(padY, -padX)); br = br.add(new fabric.Point(padX, padY)); @@ -12671,14 +12706,15 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot var w = this.getWidth(), h = this.getHeight(), strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, - capped = this.strokeLineCap === "round" || this.strokeLineCap === "square", - vLine = this.type === "line" && this.width === 1, - hLine = this.type === "line" && this.height === 1, - strokeW = (capped && hLine) || this.type !== "line", - strokeH = (capped && vLine) || this.type !== "line"; + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; if (vLine) { w = strokeWidth / scaleX; - } else if (hLine) { + } + else if (hLine) { h = strokeWidth / scaleY; } if (strokeW) { @@ -12738,14 +12774,16 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0, w = this.width, h = this.height, - capped = this.strokeLineCap === "round" || this.strokeLineCap === "square", - vLine = this.type === "line" && this.width === 1, - hLine = this.type === "line" && this.height === 1, - strokeW = (capped && hLine) || this.type !== "line", - strokeH = (capped && vLine) || this.type !== "line"; + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 1, + hLine = this.type === 'line' && this.height === 1, + strokeW = (capped && hLine) || this.type !== 'line', + strokeH = (capped && vLine) || this.type !== 'line'; + if (vLine) { w = strokeWidth; - } else if (hLine) { + } + else if (hLine) { h = strokeWidth; } if (strokeW) { @@ -12756,7 +12794,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot } w *= this.scaleX; h *= this.scaleY; - + var wh = fabric.util.transformPoint(new fabric.Point(w, h), vpt, true), width = wh.x, height = wh.y, @@ -13562,7 +13600,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param ctx {CanvasRenderingContext2D} context to render on + * @param {CanvasRenderingContext2D} ctx context to render on + * @param {Boolean} [noTransform] When true, context is not transformed */ _render: function(ctx, noTransform) { ctx.beginPath(); @@ -13641,8 +13680,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot parsedAttributes.top = 0; } if (!('transformMatrix' in parsedAttributes)) { - parsedAttributes.left -= (options.width / 2); - parsedAttributes.top -= (options.height / 2); + parsedAttributes.left -= options.width ? (options.width / 2) : 0; + parsedAttributes.top -= options.height ? (options.height / 2) : 0; } var obj = new fabric.Circle(extend(parsedAttributes, options)); @@ -13718,7 +13757,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param ctx {CanvasRenderingContext2D} Context to render on + * @param {CanvasRenderingContext2D} ctx Context to render on */ _render: function(ctx) { var widthBy2 = this.width / 2, @@ -13736,7 +13775,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param ctx {CanvasRenderingContext2D} Context to render on + * @param {CanvasRenderingContext2D} ctx Context to render on */ _renderDashedStroke: function(ctx) { var widthBy2 = this.width / 2, @@ -13791,7 +13830,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * Returns fabric.Triangle instance from an object representation * @static * @memberOf fabric.Triangle - * @param object {Object} object to create an instance from + * @param {Object} object Object to create an instance from * @return {Object} instance of Canvas.Triangle */ fabric.Triangle.fromObject = function(object) { @@ -13897,8 +13936,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * Renders this instance on a given context - * @param ctx {CanvasRenderingContext2D} context to render on - * @param noTransform {Boolean} context is not transformed when set to true + * @param {CanvasRenderingContext2D} ctx context to render on + * @param {Boolean} [noTransform] When true, context is not transformed */ render: function(ctx, noTransform) { // do not use `get` for perf. reasons @@ -13908,7 +13947,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param ctx {CanvasRenderingContext2D} context to render on + * @param {CanvasRenderingContext2D} ctx context to render on + * @param {Boolean} [noTransform] When true, context is not transformed */ _render: function(ctx, noTransform) { ctx.beginPath(); @@ -13959,8 +13999,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot parsedAttributes.top = 0; } if (!('transformMatrix' in parsedAttributes)) { - parsedAttributes.left -= (options.width / 2); - parsedAttributes.top -= (options.height / 2); + parsedAttributes.left -= options.width ? (options.width / 2) : 0; + parsedAttributes.top -= options.height ? (options.height / 2) : 0; } var ellipse = new fabric.Ellipse(extend(parsedAttributes, options)); @@ -14085,7 +14125,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param ctx {CanvasRenderingContext2D} context to render on + * @param {CanvasRenderingContext2D} ctx Context to render on */ _render: function(ctx) { @@ -14141,7 +14181,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param ctx {CanvasRenderingContext2D} context to render on + * @param {CanvasRenderingContext2D} ctx Context to render on */ _renderDashedStroke: function(ctx) { var x = -this.width / 2, @@ -14267,7 +14307,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * Returns {@link fabric.Rect} instance from an object representation * @static * @memberOf fabric.Rect - * @param object {Object} object to create an instance from + * @param {Object} object Object to create an instance from * @return {Object} instance of fabric.Rect */ fabric.Rect.fromObject = function(object) { @@ -14458,7 +14498,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * Returns fabric.Polyline instance from an object representation * @static * @memberOf fabric.Polyline - * @param object {Object} object Object to create an instance from + * @param {Object} object Object to create an instance from * @return {fabric.Polyline} Instance of fabric.Polyline */ fabric.Polyline.fromObject = function(object) { @@ -14668,7 +14708,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * Returns fabric.Polygon instance from an object representation * @static * @memberOf fabric.Polygon - * @param object {Object} object Object to create an instance from + * @param {Object} object Object to create an instance from * @return {fabric.Polygon} Instance of fabric.Polygon */ fabric.Polygon.fromObject = function(object) { @@ -14822,7 +14862,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * @private - * @param {Boolean} positionSet When false, path offset is returned otherwise 0 + * @param {Number} origLeft Original left position + * @param {Number} origTop Original top position */ _calculatePathOffset: function (origLeft, origTop) { return { @@ -15503,7 +15544,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot ctx.save(); var m = this.transformMatrix; - + if (m) { ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); } @@ -16192,7 +16233,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @static * @memberOf fabric.Group * @param {Object} object Object to create a group from - * @param {Object} [options] Options object + * @param {Function} [callback] Callback to invoke when an group instance is created * @return {fabric.Group} An instance of fabric.Group */ fabric.Group.fromObject = function(object, callback) { @@ -18535,7 +18576,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {String} method Method name ("fillText" or "strokeText") * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {String} line Chars to render + * @param {String} chars Chars to render * @param {Number} left Left position of text * @param {Number} top Top position of text */ @@ -19158,7 +19199,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * Returns fabric.Text instance from an object representation * @static * @memberOf fabric.Text - * @param object {Object} object Object to create an instance from + * @param {Object} object Object to create an instance from * @return {fabric.Text} Instance of fabric.Text */ fabric.Text.fromObject = function(object) { @@ -19807,7 +19848,9 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {String} method * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {String} line + * @param {String} line Content of the line + * @param {Number} left Left coordinate + * @param {Number} top Top coordinate */ _renderCharsFast: function(method, ctx, line, left, top) { this.skipTextAlign = false; @@ -19822,7 +19865,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private + * @param {String} method * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Number} lineIndex + * @param {Number} i + * @param {String} _char + * @param {Number} left Left coordinate + * @param {Number} top Top coordinate + * @param {Number} lineHeight Height of the line */ _renderChar: function(method, ctx, lineIndex, i, _char, left, top, lineHeight) { var decl, charWidth, charHeight; @@ -20241,6 +20291,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on + * @param {Array} textLines Array of all text lines */ _getTextHeight: function(ctx, textLines) { var height = 0; @@ -20252,7 +20303,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private - * @param {CanvasRenderingContext2D} ctx Context to render on */ _getTopOffset: function() { var topOffset = fabric.Text.prototype._getTopOffset.call(this); @@ -20532,7 +20582,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * Find new selection index representing start of current line according to current selection index - * @param {Number} current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index */ findLineBoundaryLeft: function(startFrom) { var offset = 0, index = startFrom - 1; @@ -20547,7 +20598,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * Find new selection index representing end of current line according to current selection index - * @param {Number} current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index */ findLineBoundaryRight: function(startFrom) { var offset = 0, index = startFrom; @@ -20580,6 +20632,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * Finds index corresponding to beginning or end of a word * @param {Number} selectionStart Index of a character * @param {Number} direction: 1 or -1 + * @return {Number} Index of the beginning or end of a word */ searchWordBoundary: function(selectionStart, direction) { var index = this._reSpace.test(this.text.charAt(selectionStart)) ? selectionStart - 1 : selectionStart, @@ -21161,7 +21214,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * Changes cursor location in a text depending on passed pointer (x/y) object - * @param {Object} pointer Pointer object with x and y numeric properties + * @param {Event} e Event object */ setCursorByClick: function(e) { var newSelectionStart = this.getSelectionStartFromPointer(e); @@ -21184,7 +21237,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private * @param {Event} e Event object - * @param {Object} Object with x/y corresponding to local offset (according to object rotation) + * @return {Object} Coordinates of a pointer (x, y) */ _getLocalRotatedPointer: function(e) { var pointer = this.canvas.getPointer(e), @@ -21204,7 +21257,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @return {Number} Index of a character */ getSelectionStartFromPointer: function(e) { - var mouseOffset = this._getLocalRotatedPointer(e), textLines = this.text.split(this._reNewline), prevWidth = 0, @@ -21396,7 +21448,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot // Check for backward compatibility with old browsers if (clipboardData) { copiedText = clipboardData.getData('text'); - } else { + } + else { copiedText = this.copiedText; } @@ -21421,6 +21474,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private * @param {Event} e Event object + * @return {Object} Clipboard data object */ _getClipboardData: function(e) { return e && (e.clipboardData || fabric.window.clipboardData); @@ -21442,10 +21496,11 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * Gets start offset of a selection + * @param {Event} e Event object + * @param {Boolean} isRight * @return {Number} */ getDownCursorOffset: function(e, isRight) { - var selectionProp = isRight ? this.selectionEnd : this.selectionStart, textLines = this.text.split(this._reNewline), _char, @@ -21488,7 +21543,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @private */ _getIndexOnNextLine: function(cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor, textLines) { - var lineIndex = cursorLocation.lineIndex + 1, widthOfNextLine = this._getWidthOfLine(this.ctx, lineIndex, textLines), lineLeftOffset = this._getLineLeftOffset(widthOfNextLine), @@ -21531,7 +21585,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @param {Event} e Event object */ moveCursorDown: function(e) { - this.abortCursorAnimation(); this._currentCursorOpacity = 1; @@ -21552,7 +21605,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @param {Number} offset */ moveCursorDownWithoutShift: function(offset) { - this._selectionDirection = 'right'; this.selectionStart += offset; @@ -21567,7 +21619,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @param {Number} offset */ moveCursorDownWithShift: function(offset) { - if (this._selectionDirection === 'left' && (this.selectionStart !== this.selectionEnd)) { this.selectionStart += offset; this._selectionDirection = 'left'; @@ -21583,8 +21634,12 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot } }, + /** + * @param {Event} e Event object + * @param {Boolean} isRight + * @return {Number} + */ getUpCursorOffset: function(e, isRight) { - var selectionProp = isRight ? this.selectionEnd : this.selectionStart, cursorLocation = this.get2DCursorLocation(selectionProp); @@ -21850,7 +21905,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * Moves cursor right without keeping selection - * @param {Event} e + * @param {Event} e Event object */ moveCursorRightWithoutShift: function(e) { this._selectionDirection = 'right'; @@ -21870,6 +21925,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * Inserts a character where cursor is (replacing selection if one exists) + * @param {Event} e Event object */ removeChars: function(e) { if (this.selectionStart === this.selectionEnd) { @@ -21896,6 +21952,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private + * @param {Event} e Event object */ _removeCharsNearCursor: function(e) { if (this.selectionStart !== 0) { diff --git a/src/parser.js b/src/parser.js index bc3d6d5a738..3b45a6142b2 100644 --- a/src/parser.js +++ b/src/parser.js @@ -54,7 +54,8 @@ } function normalizeValue(attr, value, parentAttributes) { - var isArray = Object.prototype.toString.call(value) === '[object Array]'; + var isArray = Object.prototype.toString.call(value) === '[object Array]', + parsed; if ((attr === 'fill' || attr === 'stroke') && value === 'none') { value = ''; @@ -63,7 +64,9 @@ value = (value === 'evenodd') ? 'destination-over' : value; } else if (attr === 'strokeDashArray') { - value = value.replace(/,/g, ' ').split(/\s+/); + value = value.replace(/,/g, ' ').split(/\s+/).map(function(n) { + return parseInt(n); + }); } else if (attr === 'transformMatrix') { if (parentAttributes && parentAttributes.transformMatrix) { @@ -83,9 +86,9 @@ } else if (attr === 'originX' /* text-anchor */) { value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center'; - } else { - // TODO: need to normalize em, %, etc. to px (!) - var parsed = isArray ? value.map(parseUnit) : parseUnit(value); + } + else { + parsed = isArray ? value.map(parseUnit) : parseUnit(value); } return (!isArray && isNaN(parsed) ? value : parsed); @@ -367,7 +370,7 @@ * @private */ function parseUseDirectives(doc) { - var nodelist = doc.querySelectorAll('use'); + var nodelist = doc.getElementsByTagName('use'); for (var i = 0, len = nodelist.length; i < len; i++) { var el = nodelist[i], xlink = el.getAttribute('xlink:href').substr(1), diff --git a/src/shapes/circle.class.js b/src/shapes/circle.class.js index 36ca968032b..a03bfc22c70 100644 --- a/src/shapes/circle.class.js +++ b/src/shapes/circle.class.js @@ -176,8 +176,8 @@ parsedAttributes.top = 0; } if (!('transformMatrix' in parsedAttributes)) { - parsedAttributes.left -= (options.width / 2); - parsedAttributes.top -= (options.height / 2); + parsedAttributes.left -= options.width ? (options.width / 2) : 0; + parsedAttributes.top -= options.height ? (options.height / 2) : 0; } var obj = new fabric.Circle(extend(parsedAttributes, options)); diff --git a/src/shapes/ellipse.class.js b/src/shapes/ellipse.class.js index b556d97329a..931168154db 100644 --- a/src/shapes/ellipse.class.js +++ b/src/shapes/ellipse.class.js @@ -157,8 +157,8 @@ parsedAttributes.top = 0; } if (!('transformMatrix' in parsedAttributes)) { - parsedAttributes.left -= (options.width / 2); - parsedAttributes.top -= (options.height / 2); + parsedAttributes.left -= options.width ? (options.width / 2) : 0; + parsedAttributes.top -= options.height ? (options.height / 2) : 0; } var ellipse = new fabric.Ellipse(extend(parsedAttributes, options)); diff --git a/src/util/misc.js b/src/util/misc.js index 82ed6699743..7f51fdbcf18 100644 --- a/src/util/misc.js +++ b/src/util/misc.js @@ -141,6 +141,7 @@ parseUnit: function(value) { var unit = /\D{0,2}$/.exec(value), number = parseFloat(value); + switch (unit[0]) { case 'mm': return number * fabric.DPI / 25.4; diff --git a/test/unit/parser.js b/test/unit/parser.js index fa971613658..0bc86b35794 100644 --- a/test/unit/parser.js +++ b/test/unit/parser.js @@ -126,10 +126,11 @@ var element = fabric.document.createElement('path'); element.setAttribute('style', 'left:10px;top:22.3em;width:103.45pt;height:20%;'); + // TODO: looks like this still fails with % and em values var expectedObject = { 'left': 10, 'top': 22.3, - 'width': 103.45, + 'width': 137.93333333333334, 'height': 20 }; deepEqual(fabric.parseStyleAttribute(element), expectedObject); diff --git a/test/unit/text.js b/test/unit/text.js index 73b35dfb128..ac43cfb7986 100644 --- a/test/unit/text.js +++ b/test/unit/text.js @@ -6,13 +6,15 @@ return new fabric.Text('x'); } + var CHAR_WIDTH = 19; + var REFERENCE_TEXT_OBJECT = { 'type': 'text', 'originX': 'left', 'originY': 'top', 'left': 0, 'top': 0, - 'width': 20, + 'width': CHAR_WIDTH, 'height': 52, 'fill': 'rgb(0,0,0)', 'stroke': null, @@ -30,6 +32,7 @@ 'shadow': null, 'visible': true, 'clipTo': null, + 'backgroundColor': '', 'text': 'x', 'fontSize': 40, 'fontWeight': 'normal', @@ -39,12 +42,11 @@ 'textDecoration': '', 'textAlign': 'left', 'path': null, - 'backgroundColor': '', 'textBackgroundColor': '', 'useNative': true }; - var TEXT_SVG = 'x'; + var TEXT_SVG = 'x'; test('constructor', function() { ok(fabric.Text); @@ -148,12 +150,12 @@ ok(text instanceof fabric.Text); // temp workaround for text objects not obtaining width under node - // text.width = 20; + // text.width = CHAR_WIDTH; var expectedObject = fabric.util.object.extend(fabric.util.object.clone(REFERENCE_TEXT_OBJECT), { - left: 4, + left: 3.5, top: -10.4, - width: 8, + width: 7, height: 20.8, fontSize: 16, originX: 'center' @@ -185,7 +187,7 @@ var textWithAttrs = fabric.Text.fromElement(elTextWithAttrs); // temp workaround for text objects not obtaining width under node - textWithAttrs.width = 20; + textWithAttrs.width = CHAR_WIDTH; ok(textWithAttrs instanceof fabric.Text); @@ -193,7 +195,7 @@ /* left varies slightly due to node-canvas rendering */ left: fabric.util.toFixed(textWithAttrs.left + '', 2), top: -59.95, - width: 20, + width: CHAR_WIDTH, height: 159.9, fill: 'rgb(255,255,255)', opacity: 0.45, @@ -220,10 +222,10 @@ test('dimensions after text change', function() { var text = new fabric.Text('x'); - equal(text.width, 20); + equal(text.width, CHAR_WIDTH); text.setText('xx'); - equal(text.width, 40); + equal(text.width, CHAR_WIDTH * 2); }); test('setting fontFamily', function() { @@ -241,13 +243,13 @@ var text = new fabric.Text('x'); // temp workaround for text objects not obtaining width under node - text.width = 20; + text.width = CHAR_WIDTH; equal(text.toSVG(), TEXT_SVG); text.setFontFamily('"Arial Black", Arial'); // temp workaround for text objects not obtaining width under node - text.width = 20; + text.width = CHAR_WIDTH; equal(text.toSVG(), TEXT_SVG.replace('font-family="Times New Roman"', 'font-family="\'Arial Black\', Arial"')); }); From 3e294fee9479ee14b21552d12ed784831b829631 Mon Sep 17 00:00:00 2001 From: kangax Date: Fri, 18 Jul 2014 14:27:25 +0200 Subject: [PATCH 19/21] Try fixing char width for travis --- test/unit/text.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/text.js b/test/unit/text.js index ac43cfb7986..440342cbc98 100644 --- a/test/unit/text.js +++ b/test/unit/text.js @@ -6,7 +6,7 @@ return new fabric.Text('x'); } - var CHAR_WIDTH = 19; + var CHAR_WIDTH = 20; var REFERENCE_TEXT_OBJECT = { 'type': 'text', From 7de2aedf7c82c622266c140c5cf3b81476ef18cb Mon Sep 17 00:00:00 2001 From: kangax Date: Fri, 18 Jul 2014 14:33:50 +0200 Subject: [PATCH 20/21] Try fixing char width for travis again --- test/unit/text.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/text.js b/test/unit/text.js index 440342cbc98..7548d343a3d 100644 --- a/test/unit/text.js +++ b/test/unit/text.js @@ -46,7 +46,7 @@ 'useNative': true }; - var TEXT_SVG = 'x'; + var TEXT_SVG = 'x'; test('constructor', function() { ok(fabric.Text); @@ -153,7 +153,7 @@ // text.width = CHAR_WIDTH; var expectedObject = fabric.util.object.extend(fabric.util.object.clone(REFERENCE_TEXT_OBJECT), { - left: 3.5, + left: 4, top: -10.4, width: 7, height: 20.8, From 17bf29616d30f21f654f19b0b5382ef0844d235b Mon Sep 17 00:00:00 2001 From: kangax Date: Fri, 18 Jul 2014 14:43:54 +0200 Subject: [PATCH 21/21] Try fixing char width for travis again --- test/unit/itext.js | 2 +- test/unit/text.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/itext.js b/test/unit/itext.js index e7361dda984..d7b306eadda 100644 --- a/test/unit/itext.js +++ b/test/unit/itext.js @@ -8,7 +8,7 @@ 'originY': 'top', 'left': 0, 'top': 0, - 'width': 19, + 'width': 20, 'height': 52, 'fill': 'rgb(0,0,0)', 'stroke': null, diff --git a/test/unit/text.js b/test/unit/text.js index 7548d343a3d..467975e73e2 100644 --- a/test/unit/text.js +++ b/test/unit/text.js @@ -46,7 +46,7 @@ 'useNative': true }; - var TEXT_SVG = 'x'; + var TEXT_SVG = 'x'; test('constructor', function() { ok(fabric.Text); @@ -155,7 +155,7 @@ var expectedObject = fabric.util.object.extend(fabric.util.object.clone(REFERENCE_TEXT_OBJECT), { left: 4, top: -10.4, - width: 7, + width: 8, height: 20.8, fontSize: 16, originX: 'center'