From fa7ce9eaafc608965845096fb0393468a9309f76 Mon Sep 17 00:00:00 2001 From: kangax Date: Sat, 7 Feb 2015 02:52:29 +0100 Subject: [PATCH] Update deps --- dist/fabric.js | 1472 +++++++++++++++------------------------- dist/fabric.min.js | 13 +- dist/fabric.min.js.gz | Bin 60731 -> 60003 bytes dist/fabric.require.js | 1472 +++++++++++++++------------------------- package.json | 2 +- 5 files changed, 1081 insertions(+), 1878 deletions(-) diff --git a/dist/fabric.js b/dist/fabric.js index 56b39f56..a3d6f38b 100644 --- a/dist/fabric.js +++ b/dist/fabric.js @@ -5103,14 +5103,14 @@ fabric.ElementsParser.prototype.checkIfDone = function() { * @return {CanvasGradient} */ toLive: function(ctx, object) { - var gradient, coords = fabric.util.object.clone(this.coords); + var gradient, prop, coords = fabric.util.object.clone(this.coords); if (!this.type) { return; } if (object.group && object.group.type === 'path-group') { - for (var prop in coords) { + for (prop in coords) { if (prop === 'x1' || prop === 'x2') { coords[prop] += -this.offsetX + object.width / 2; } @@ -5120,6 +5120,17 @@ fabric.ElementsParser.prototype.checkIfDone = function() { } } + if (object.type === 'text') { + for (prop in coords) { + if (prop === 'x1' || prop === 'x2') { + coords[prop] -= object.width / 2; + } + else if (prop === 'y1' || prop === 'y2') { + coords[prop] -= object.height / 2; + } + } + } + if (this.type === 'linear') { gradient = ctx.createLinearGradient( coords.x1, coords.y1, coords.x2, coords.y2); @@ -5452,7 +5463,8 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ 'use strict'; - var fabric = global.fabric || (global.fabric = { }); + var fabric = global.fabric || (global.fabric = { }), + toFixed = fabric.util.toFixed; if (fabric.Shadow) { fabric.warn('fabric.Shadow is already defined.'); @@ -5569,16 +5581,18 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ if (object.width && object.height) { //http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion // we add some extra space to filter box to contain the blur ( 20 ) - fBoxX = Math.abs(this.offsetX / object.getWidth()) * 100 + 20; - fBoxY = Math.abs(this.offsetY / object.getHeight()) * 100 + 20; + fBoxX = toFixed(Math.abs(this.offsetX / object.getWidth()), 2) * 100 + 20; + fBoxY = toFixed(Math.abs(this.offsetY / object.getHeight()), 2) * 100 + 20; } return ( '\n' + '\t\n' + + toFixed(this.blur ? this.blur / 2 : 0, 3) + + '" result="blurOut">\n' + + '\t\n' + '\t\n' + '\t\n' + '\t\t\n' + @@ -7245,6 +7259,13 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype */ strokeLineJoin: 'round', + /** + * Stroke Dash Array. + * @type Array + * @default + */ + strokeDashArray: null, + /** * Sets shadow of an object * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)") @@ -7267,6 +7288,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype ctx.lineWidth = this.width; ctx.lineCap = this.strokeLineCap; ctx.lineJoin = this.strokeLineJoin; + ctx.setLineDash(this.strokeDashArray); }, /** @@ -7472,6 +7494,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype strokeWidth: this.width, strokeLineCap: this.strokeLineCap, strokeLineJoin: this.strokeLineJoin, + strokeDashArray: this.strokeDashArray, originX: 'center', originY: 'center' }); @@ -12539,35 +12562,13 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati * @chainable */ setCoords: function() { - var strokeWidth = this.strokeWidth, - theta = degreesToRadians(this.angle), + var theta = degreesToRadians(this.angle), vpt = this.getViewportTransform(), f = function (p) { return fabric.util.transformPoint(p, vpt); }, - w = this.width, currentWidth, - h = this.height, currentHeight, - capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', - vLine = this.type === 'line' && this.width === 0, - hLine = this.type === 'line' && this.height === 0, - sLine = vLine || hLine, - strokeW = (capped && hLine) || !sLine, - strokeH = (capped && vLine) || !sLine; - - if (vLine) { - w = strokeWidth; - } - else if (hLine) { - h = strokeWidth; - } - if (strokeW) { - w += w > 0 ? strokeWidth : -strokeWidth; - } - if (strokeH) { - h += h > 0 ? strokeWidth : -strokeWidth; - } - currentWidth = w * this.scaleX + 2 * this.padding; - currentHeight = h * this.scaleY + 2 * this.padding; + p = this._calculateCurrentDimensions(false), + currentWidth = p.x, currentHeight = p.y; // If width is negative, make postive. Fixes path selection issue if (currentWidth < 0) { @@ -12592,31 +12593,29 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati wh = new fabric.Point(currentWidth, currentHeight), _tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY), _tr = new fabric.Point(_tl.x + (wh.x * cosTh), _tl.y + (wh.x * sinTh)), - _bl = new fabric.Point(_tl.x - (wh.y * sinTh), _tl.y + (wh.y * cosTh)), - _mt = new fabric.Point(_tl.x + (wh.x/2 * cosTh), _tl.y + (wh.x/2 * sinTh)), + bl = f(new fabric.Point(_tl.x - (wh.y * sinTh), _tl.y + (wh.y * cosTh))), + br = f(new fabric.Point(_tr.x - (wh.y * sinTh), _tr.y + (wh.y * cosTh))), tl = f(_tl), tr = f(_tr), - br = f(new fabric.Point(_tr.x - (wh.y * sinTh), _tr.y + (wh.y * cosTh))), - bl = f(_bl), - ml = f(new fabric.Point(_tl.x - (wh.y/2 * sinTh), _tl.y + (wh.y/2 * cosTh))), - 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)); - + ml = new fabric.Point((tl.x + bl.x)/2, (tl.y + bl.y)/2), + mt = new fabric.Point((tr.x + tl.x)/2, (tr.y + tl.y)/2), + mr = new fabric.Point((br.x + tr.x)/2, (br.y + tr.y)/2), + mb = new fabric.Point((br.x + bl.x)/2, (br.y + bl.y)/2), + mtr = new fabric.Point(mt.x + sinTh * this.rotatingPointOffset, mt.y - cosTh * this.rotatingPointOffset); // debugging - // setTimeout(function() { - // canvas.contextTop.fillStyle = 'green'; - // canvas.contextTop.fillRect(mb.x, mb.y, 3, 3); - // canvas.contextTop.fillRect(bl.x, bl.y, 3, 3); - // canvas.contextTop.fillRect(br.x, br.y, 3, 3); - // canvas.contextTop.fillRect(tl.x, tl.y, 3, 3); - // canvas.contextTop.fillRect(tr.x, tr.y, 3, 3); - // canvas.contextTop.fillRect(ml.x, ml.y, 3, 3); - // canvas.contextTop.fillRect(mr.x, mr.y, 3, 3); - // canvas.contextTop.fillRect(mt.x, mt.y, 3, 3); - // }, 50); + /* setTimeout(function() { + canvas.contextTop.fillStyle = 'green'; + canvas.contextTop.fillRect(mb.x, mb.y, 3, 3); + canvas.contextTop.fillRect(bl.x, bl.y, 3, 3); + canvas.contextTop.fillRect(br.x, br.y, 3, 3); + canvas.contextTop.fillRect(tl.x, tl.y, 3, 3); + canvas.contextTop.fillRect(tr.x, tr.y, 3, 3); + canvas.contextTop.fillRect(ml.x, ml.y, 3, 3); + canvas.contextTop.fillRect(mr.x, mr.y, 3, 3); + canvas.contextTop.fillRect(mt.x, mt.y, 3, 3); + canvas.contextTop.fillRect(mtr.x, mtr.y, 3, 3); + }, 50); */ this.oCoords = { // corners @@ -12743,7 +12742,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1', visibility = this.visible ? '' : ' visibility: hidden;', - filter = this.shadow && this.type !== 'text' ? 'filter: url(#SVGID_' + this.shadow.id + ');' : ''; + filter = this.shadow ? 'filter: url(#SVGID_' + this.shadow.id + ');' : ''; return [ 'stroke: ', stroke, '; ', @@ -12811,7 +12810,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @return {String} */ getSvgTransformMatrix: function() { - return this.transformMatrix ? ' matrix(' + this.transformMatrix.join(' ') + ')' : ''; + return this.transformMatrix ? ' matrix(' + this.transformMatrix.join(' ') + ') ' : ''; }, /** @@ -12960,185 +12959,70 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot */ _setCornerCoords: function() { var coords = this.oCoords, - theta = degreesToRadians(this.angle), newTheta = degreesToRadians(45 - this.angle), cornerHypotenuse = Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, cosHalfOffset = cornerHypotenuse * Math.cos(newTheta), sinHalfOffset = cornerHypotenuse * Math.sin(newTheta), - sinTh = Math.sin(theta), - cosTh = Math.cos(theta); + x, y; - coords.tl.corner = { - tl: { - x: coords.tl.x - sinHalfOffset, - y: coords.tl.y - cosHalfOffset - }, - tr: { - x: coords.tl.x + cosHalfOffset, - y: coords.tl.y - sinHalfOffset - }, - bl: { - x: coords.tl.x - cosHalfOffset, - y: coords.tl.y + sinHalfOffset - }, - br: { - x: coords.tl.x + sinHalfOffset, - y: coords.tl.y + cosHalfOffset - } - }; - - coords.tr.corner = { - tl: { - x: coords.tr.x - sinHalfOffset, - y: coords.tr.y - cosHalfOffset - }, - tr: { - x: coords.tr.x + cosHalfOffset, - y: coords.tr.y - sinHalfOffset - }, - br: { - x: coords.tr.x + sinHalfOffset, - y: coords.tr.y + cosHalfOffset - }, - bl: { - x: coords.tr.x - cosHalfOffset, - y: coords.tr.y + sinHalfOffset - } - }; - - coords.bl.corner = { - tl: { - x: coords.bl.x - sinHalfOffset, - y: coords.bl.y - cosHalfOffset - }, - bl: { - x: coords.bl.x - cosHalfOffset, - y: coords.bl.y + sinHalfOffset - }, - br: { - x: coords.bl.x + sinHalfOffset, - y: coords.bl.y + cosHalfOffset - }, - tr: { - x: coords.bl.x + cosHalfOffset, - y: coords.bl.y - sinHalfOffset - } - }; - - coords.br.corner = { - tr: { - x: coords.br.x + cosHalfOffset, - y: coords.br.y - sinHalfOffset - }, - bl: { - x: coords.br.x - cosHalfOffset, - y: coords.br.y + sinHalfOffset - }, - br: { - x: coords.br.x + sinHalfOffset, - y: coords.br.y + cosHalfOffset - }, - tl: { - x: coords.br.x - sinHalfOffset, - y: coords.br.y - cosHalfOffset - } - }; - - coords.ml.corner = { - tl: { - x: coords.ml.x - sinHalfOffset, - y: coords.ml.y - cosHalfOffset - }, - tr: { - x: coords.ml.x + cosHalfOffset, - y: coords.ml.y - sinHalfOffset - }, - bl: { - x: coords.ml.x - cosHalfOffset, - y: coords.ml.y + sinHalfOffset - }, - br: { - x: coords.ml.x + sinHalfOffset, - y: coords.ml.y + cosHalfOffset - } - }; - - coords.mt.corner = { - tl: { - x: coords.mt.x - sinHalfOffset, - y: coords.mt.y - cosHalfOffset - }, - tr: { - x: coords.mt.x + cosHalfOffset, - y: coords.mt.y - sinHalfOffset - }, - bl: { - x: coords.mt.x - cosHalfOffset, - y: coords.mt.y + sinHalfOffset - }, - br: { - x: coords.mt.x + sinHalfOffset, - y: coords.mt.y + cosHalfOffset - } - }; - - coords.mr.corner = { - tl: { - x: coords.mr.x - sinHalfOffset, - y: coords.mr.y - cosHalfOffset - }, - tr: { - x: coords.mr.x + cosHalfOffset, - y: coords.mr.y - sinHalfOffset - }, - bl: { - x: coords.mr.x - cosHalfOffset, - y: coords.mr.y + sinHalfOffset - }, - br: { - x: coords.mr.x + sinHalfOffset, - y: coords.mr.y + cosHalfOffset - } - }; - - coords.mb.corner = { - tl: { - x: coords.mb.x - sinHalfOffset, - y: coords.mb.y - cosHalfOffset - }, - tr: { - x: coords.mb.x + cosHalfOffset, - y: coords.mb.y - sinHalfOffset - }, - bl: { - x: coords.mb.x - cosHalfOffset, - y: coords.mb.y + sinHalfOffset - }, - br: { - x: coords.mb.x + sinHalfOffset, - y: coords.mb.y + cosHalfOffset - } - }; - - coords.mtr.corner = { - tl: { - x: coords.mtr.x - sinHalfOffset + (sinTh * this.rotatingPointOffset), - y: coords.mtr.y - cosHalfOffset - (cosTh * this.rotatingPointOffset) - }, - tr: { - x: coords.mtr.x + cosHalfOffset + (sinTh * this.rotatingPointOffset), - y: coords.mtr.y - sinHalfOffset - (cosTh * this.rotatingPointOffset) - }, - bl: { - x: coords.mtr.x - cosHalfOffset + (sinTh * this.rotatingPointOffset), - y: coords.mtr.y + sinHalfOffset - (cosTh * this.rotatingPointOffset) - }, - br: { - x: coords.mtr.x + sinHalfOffset + (sinTh * this.rotatingPointOffset), - y: coords.mtr.y + cosHalfOffset - (cosTh * this.rotatingPointOffset) - } - }; + for (var point in coords) { + x = coords[point].x; + y = coords[point].y; + coords[point].corner = { + tl: { + x: x - sinHalfOffset, + y: y - cosHalfOffset + }, + tr: { + x: x + cosHalfOffset, + y: y - sinHalfOffset + }, + bl: { + x: x - cosHalfOffset, + y: y + sinHalfOffset + }, + br: { + x: x + sinHalfOffset, + y: y + cosHalfOffset + } + }; + } }, + + _calculateCurrentDimensions: function(shouldTransform) { + var vpt = this.getViewportTransform(), + strokeWidth = this.strokeWidth, + w = this.width, + h = this.height, + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 0, + hLine = this.type === 'line' && this.height === 0, + sLine = vLine || hLine, + strokeW = (capped && hLine) || !sLine, + strokeH = (capped && vLine) || !sLine; + + if (vLine) { + w = strokeWidth; + } + else if (hLine) { + h = strokeWidth; + } + if (strokeW) { + w += (w < 0 ? -strokeWidth : strokeWidth); + } + if (strokeH) { + h += (h < 0 ? -strokeWidth : strokeWidth); + } + + w = w * this.scaleX + 2 * this.padding; + h = h * this.scaleY + 2 * this.padding; + + if (shouldTransform) { + return fabric.util.transformPoint(new fabric.Point(w, h), vpt, true); + } + return { x: w, y: h }; + }, + /** * Draws borders of an object's bounding box. * Requires public properties: width, height @@ -13152,43 +13036,13 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot return this; } - var padding = this.padding, - padding2 = padding * 2, - vpt = this.getViewportTransform(); - ctx.save(); ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; ctx.strokeStyle = this.borderColor; - - var scaleX = 1 / this._constrainScale(this.scaleX), - scaleY = 1 / this._constrainScale(this.scaleY); - ctx.lineWidth = 1 / this.borderScaleFactor; - var w = this.getWidth(), - h = this.getHeight(), - strokeWidth = this.strokeWidth, - capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', - vLine = this.type === 'line' && this.width === 0, - hLine = this.type === 'line' && this.height === 0, - sLine = vLine || hLine, - strokeW = (capped && hLine) || !sLine, - strokeH = (capped && vLine) || !sLine; - - if (vLine) { - w = strokeWidth / scaleX; - } - else if (hLine) { - h = strokeWidth / scaleY; - } - if (strokeW) { - w += strokeWidth / scaleX; - } - if (strokeH) { - h += strokeWidth / scaleY; - } - var wh = fabric.util.transformPoint(new fabric.Point(w, h), vpt, true), + var wh = this._calculateCurrentDimensions(true), width = wh.x, height = wh.y; if (this.group) { @@ -13197,15 +13051,15 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot } ctx.strokeRect( - ~~(-(width / 2) - padding) - 0.5, // offset needed to make lines look sharper - ~~(-(height / 2) - padding) - 0.5, - ~~(width + padding2) + 1, // double offset needed to make lines look sharper - ~~(height + padding2) + 1 + ~~(-(width / 2)) - 0.5, // offset needed to make lines look sharper + ~~(-(height / 2)) - 0.5, + ~~(width) + 1, // double offset needed to make lines look sharper + ~~(height) + 1 ); if (this.hasRotatingPoint && this.isControlVisible('mtr') && !this.get('lockRotation') && this.hasControls) { - var rotateHeight = ( -height - (padding * 2)) / 2; + var rotateHeight = -height / 2; ctx.beginPath(); ctx.moveTo(0, rotateHeight); @@ -13231,42 +13085,12 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot return this; } - var size = this.cornerSize, - size2 = size / 2, - vpt = this.getViewportTransform(), - strokeWidth = this.strokeWidth, - w = this.width, - h = this.height, - capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', - vLine = this.type === 'line' && this.width === 0, - hLine = this.type === 'line' && this.height === 0, - sLine = vLine || hLine, - strokeW = (capped && hLine) || !sLine, - strokeH = (capped && vLine) || !sLine; - - if (vLine) { - w = strokeWidth; - } - else if (hLine) { - h = strokeWidth; - } - if (strokeW) { - w += strokeWidth; - } - if (strokeH) { - h += strokeWidth; - } - w *= this.scaleX; - h *= this.scaleY; - - var wh = fabric.util.transformPoint(new fabric.Point(w, h), vpt, true), + var wh = this._calculateCurrentDimensions(true), width = wh.x, height = wh.y, left = -(width / 2), top = -(height / 2), - padding = this.padding, - scaleOffset = size2, - scaleOffsetSize = size2 - size, + scaleOffset = this.cornerSize / 2, methodName = this.transparentCorners ? 'strokeRect' : 'fillRect'; ctx.save(); @@ -13278,44 +13102,44 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot // top-left this._drawControl('tl', ctx, methodName, - left - scaleOffset - padding, - top - scaleOffset - padding); + left - scaleOffset, + top - scaleOffset); // top-right this._drawControl('tr', ctx, methodName, - left + width - scaleOffset + padding, - top - scaleOffset - padding); + left + width - scaleOffset, + top - scaleOffset); // bottom-left this._drawControl('bl', ctx, methodName, - left - scaleOffset - padding, - top + height + scaleOffsetSize + padding); + left - scaleOffset, + top + height - scaleOffset); // bottom-right this._drawControl('br', ctx, methodName, - left + width + scaleOffsetSize + padding, - top + height + scaleOffsetSize + padding); + left + width - scaleOffset, + top + height - scaleOffset); if (!this.get('lockUniScaling')) { // middle-top this._drawControl('mt', ctx, methodName, left + width/2 - scaleOffset, - top - scaleOffset - padding); + top - scaleOffset); // middle-bottom this._drawControl('mb', ctx, methodName, left + width/2 - scaleOffset, - top + height + scaleOffsetSize + padding); + top + height - scaleOffset); // middle-right this._drawControl('mr', ctx, methodName, - left + width + scaleOffsetSize + padding, + left + width - scaleOffset, top + height/2 - scaleOffset); // middle-left this._drawControl('ml', ctx, methodName, - left - scaleOffset - padding, + left - scaleOffset, top + height/2 - scaleOffset); } @@ -13323,7 +13147,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot if (this.hasRotatingPoint) { this._drawControl('mtr', ctx, methodName, left + width/2 - scaleOffset, - top - this.rotatingPointOffset - this.cornerSize/2 - padding); + top - this.rotatingPointOffset - scaleOffset); } ctx.restore(); @@ -14205,7 +14029,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @private */ function isValidRadius(attributes) { - return (('radius' in attributes) && (attributes.radius > 0)); + return (('radius' in attributes) && (attributes.radius >= 0)); } /* _FROM_SVG_END_ */ @@ -14785,8 +14609,9 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot parsedAttributes.left = parsedAttributes.left || 0; parsedAttributes.top = parsedAttributes.top || 0; - - return new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); + var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); + rect.visible = rect.width > 0 && rect.height > 0; + return rect; }; /* _FROM_SVG_END_ */ @@ -14914,7 +14739,9 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @param {CanvasRenderingContext2D} ctx Context to render on */ _render: function(ctx) { - fabric.Polygon.prototype.commonRender.call(this, ctx); + if (!fabric.Polygon.prototype.commonRender.call(this, ctx)) { + return; + } this._renderFill(ctx); this._renderStroke(ctx); }, @@ -14969,10 +14796,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot var points = fabric.parsePointsAttribute(element.getAttribute('points')), parsedAttributes = fabric.parseAttributes(element, fabric.Polyline.ATTRIBUTE_NAMES); - if (points === null) { - return null; - } - return new fabric.Polyline(points, fabric.util.object.extend(parsedAttributes, options)); }; /* _FROM_SVG_END_ */ @@ -15051,7 +14874,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot */ initialize: function(points, options) { options = options || { }; - this.points = points; + this.points = points || [ ]; this.callSuper('initialize', options); this._calcDimensions(); if (!('top' in options)) { @@ -15073,11 +14896,11 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot maxX = max(points, 'x'), maxY = max(points, 'y'); - this.width = (maxX - minX) || 1; - this.height = (maxY - minY) || 1; + this.width = (maxX - minX) || 0; + this.height = (maxY - minY) || 0; - this.minX = minX, - this.minY = minY; + this.minX = minX || 0, + this.minY = minY || 0; }, /** @@ -15135,7 +14958,9 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @param {CanvasRenderingContext2D} ctx Context to render on */ _render: function(ctx) { - this.commonRender(ctx); + if (!this.commonRender(ctx)) { + return; + } this._renderFill(ctx); if (this.stroke || this.strokeDashArray) { ctx.closePath(); @@ -15148,7 +14973,14 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @param {CanvasRenderingContext2D} ctx Context to render on */ commonRender: function(ctx) { - var point; + var point, len = this.points.length; + + if (!len || isNaN(this.points[len - 1].y)) { + // do not draw if no points or odd points + // NaN comes from parseFloat of a empty string in parser + return false; + } + ctx.beginPath(); if (this._applyPointOffset) { @@ -15159,10 +14991,11 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot } ctx.moveTo(this.points[0].x, this.points[0].y); - for (var i = 0, len = this.points.length; i < len; i++) { + for (var i = 0; i < len; i++) { point = this.points[i]; ctx.lineTo(point.x, point.y); } + return true; }, /** @@ -15210,10 +15043,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot var points = fabric.parsePointsAttribute(element.getAttribute('points')), parsedAttributes = fabric.parseAttributes(element, fabric.Polygon.ATTRIBUTE_NAMES); - if (points === null) { - return null; - } - return new fabric.Polygon(points, extend(parsedAttributes, options)); }; /* _FROM_SVG_END_ */ @@ -15755,7 +15584,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot } var path = chunks.join(' '); if (!(this.group && this.group.type === 'path-group')) { - addTransform = 'translate(' + (-this.pathOffset.x) + ', ' + (-this.pathOffset.y) + ')'; + addTransform = ' translate(' + (-this.pathOffset.x) + ', ' + (-this.pathOffset.y) + ') '; } markup.push( //jscs:disable validateIndentation @@ -16371,7 +16200,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot //jscs:disable validateIndentation '\n' //jscs:enable validateIndentation ]; @@ -16890,12 +16719,14 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot _calcBounds: function(onlyWidthHeight) { var aX = [], aY = [], - o; + o, prop, + props = ['tr', 'br', 'bl', 'tl']; for (var i = 0, len = this._objects.length; i < len; ++i) { o = this._objects[i]; o.setCoords(); - for (var prop in o.oCoords) { + for (var j = 0; j < props.length; j++) { + prop = props[j]; aX.push(o.oCoords[prop].x); aY.push(o.oCoords[prop].y); } @@ -19472,9 +19303,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag 'textAlign', 'fontStyle', 'lineHeight', - 'textBackgroundColor', - 'useNative', - 'path' + 'textBackgroundColor' ); /** @@ -19707,7 +19536,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @type Number * @default */ - lineHeight: 1.3, + lineHeight: 1.16, /** * Background color of text lines @@ -19716,20 +19545,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ textBackgroundColor: '', - /** - * URL of a font file, when using Cufon - * @type String | null - * @default - */ - path: null, - - /** - * Indicates whether canvas native text methods should be used to render text (otherwise, Cufon is used) - * @type Boolean - * @default - */ - useNative: true, - /** * List of properties to consider when checking if * state of an object is changed ({@link fabric.Object#hasStateChanged}) @@ -19754,6 +19569,18 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ shadow: null, + /** + * @private + */ + _fontSizeFraction: 0.25, + + /** + * Text Line proportion to font Size (in pixels) + * @type Number + * @default + */ + _fontSizeMult: 1.13, + /** * Constructor * @param {String} text Text string @@ -19762,7 +19589,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ initialize: function(text, options) { options = options || { }; - this.text = text; this.__skipDimension = true; this.setOptions(options); @@ -19778,8 +19604,13 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag if (this.__skipDimension) { return; } - var canvasEl = fabric.util.createCanvasElement(); - this._render(canvasEl.getContext('2d')); + this._clearCache(); + + var ctx = fabric.util.createCanvasElement().getContext('2d'); + this._textLines = this.text.split(this._reNewline); + this._setTextStyles(ctx); + this.width = this._getTextWidth(ctx); + this.height = this._getTextHeight(ctx); }, /** @@ -19797,54 +19628,31 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ _render: function(ctx) { - if (typeof Cufon === 'undefined' || this.useNative === true) { - this._renderViaNative(ctx); - } - else { - this._renderViaCufon(ctx); - } - }, - - /** - * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - */ - _renderViaNative: function(ctx) { - var textLines = this.text.split(this._reNewline); - - this._setTextStyles(ctx); - - this.width = this._getTextWidth(ctx, textLines); - this.height = this._getTextHeight(ctx, textLines); - this.clipTo && fabric.util.clipContext(this, ctx); - this._renderTextBackground(ctx, textLines); + this._renderTextBackground(ctx); this._translateForTextAlign(ctx); - this._renderText(ctx, textLines); + this._renderText(ctx); if (this.textAlign !== 'left' && this.textAlign !== 'justify') { ctx.restore(); } - this._renderTextDecoration(ctx, textLines); + this._renderTextDecoration(ctx); this.clipTo && ctx.restore(); - - this._setBoundaries(ctx, textLines); - this._totalLineHeight = 0; }, /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _renderText: function(ctx, textLines) { + _renderText: function(ctx) { ctx.save(); this._setOpacity(ctx); this._setShadow(ctx); this._setupCompositeOperation(ctx); - this._renderTextFill(ctx, textLines); - this._renderTextStroke(ctx, textLines); + this._renderTextFill(ctx); + this._renderTextStroke(ctx); this._restoreCompositeOperation(ctx); this._removeShadow(ctx); ctx.restore(); @@ -19861,34 +19669,11 @@ 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 - */ - _setBoundaries: function(ctx, textLines) { - this._boundaries = [ ]; - - for (var i = 0, len = textLines.length; i < len; i++) { - - var lineWidth = this._getLineWidth(ctx, textLines[i]), - lineLeftOffset = this._getLineLeftOffset(lineWidth); - - this._boundaries.push({ - height: this.fontSize * this.lineHeight, - width: lineWidth, - left: lineLeftOffset - }); - } - }, - /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ _setTextStyles: function(ctx) { - this._setFillStyles(ctx); - this._setStrokeStyles(ctx); ctx.textBaseline = 'alphabetic'; if (!this.skipTextAlign) { ctx.textAlign = this.textAlign; @@ -19899,24 +19684,22 @@ 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 * @return {Number} Height of fabric.Text object */ - _getTextHeight: function(ctx, textLines) { - return this.fontSize * textLines.length * this.lineHeight; + _getTextHeight: function() { + return this._textLines.length * this._getHeightOfLine(); }, /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {Array} textLines Array of all text lines * @return {Number} Maximum width of fabric.Text object */ - _getTextWidth: function(ctx, textLines) { - var maxWidth = ctx.measureText(textLines[0] || '|').width; + _getTextWidth: function(ctx) { + var maxWidth = this._getLineWidth(ctx, 0); - for (var i = 1, len = textLines.length; i < len; i++) { - var currentLineWidth = ctx.measureText(textLines[i]).width; + for (var i = 1, len = this._textLines.length; i < len; i++) { + var currentLineWidth = this._getLineWidth(ctx, i); if (currentLineWidth > maxWidth) { maxWidth = currentLineWidth; } @@ -19947,7 +19730,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ _renderTextLine: function(method, ctx, line, left, top, lineIndex) { // lift the line by quarter of fontSize - top -= this.fontSize / 4; + top -= this.fontSize * this._fontSizeFraction; // short-circuit if (this.textAlign !== 'justify') { @@ -19955,7 +19738,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag return; } - var lineWidth = ctx.measureText(line).width, + var lineWidth = this._getLineWidth(ctx, i), totalWidth = this.width; if (totalWidth > lineWidth) { @@ -19996,28 +19779,27 @@ 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 */ - _renderTextFill: function(ctx, textLines) { + _renderTextFill: function(ctx) { if (!this.fill && !this._skipFillStrokeCheck) { return; } - this._boundaries = [ ]; var lineHeights = 0; - for (var i = 0, len = textLines.length; i < len; i++) { - var heightOfLine = this._getHeightOfLine(ctx, i, textLines); - lineHeights += heightOfLine; + for (var i = 0, len = this._textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i), + maxHeight = heightOfLine / this.lineHeight; this._renderTextLine( 'fillText', ctx, - textLines[i], + this._textLines[i], this._getLeftOffset(), - this._getTopOffset() + lineHeights, + this._getTopOffset() + lineHeights + maxHeight, i ); + lineHeights += heightOfLine; } if (this.shadow && !this.shadow.affectStroke) { this._removeShadow(ctx); @@ -20027,9 +19809,8 @@ 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 */ - _renderTextStroke: function(ctx, textLines) { + _renderTextStroke: function(ctx) { if ((!this.stroke || this.strokeWidth === 0) && !this._skipFillStrokeCheck) { return; } @@ -20037,6 +19818,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag var lineHeights = 0; ctx.save(); + if (this.strokeDashArray) { // Spec requires the concatenation of two copies the dash list when the number of elements is odd if (1 & this.strokeDashArray.length) { @@ -20046,25 +19828,26 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag } ctx.beginPath(); - for (var i = 0, len = textLines.length; i < len; i++) { - var heightOfLine = this._getHeightOfLine(ctx, i, textLines); - lineHeights += heightOfLine; + for (var i = 0, len = this._textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i), + maxHeight = heightOfLine / this.lineHeight; this._renderTextLine( 'strokeText', ctx, - textLines[i], + this._textLines[i], this._getLeftOffset(), - this._getTopOffset() + lineHeights, + this._getTopOffset() + lineHeights + maxHeight, i ); + lineHeights += heightOfLine; } ctx.closePath(); ctx.restore(); }, _getHeightOfLine: function() { - return this.fontSize * this.lineHeight; + return this.fontSize * this._fontSizeMult * this.lineHeight; }, /** @@ -20072,9 +19855,9 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @param {CanvasRenderingContext2D} ctx Context to render on * @param {Array} textLines Array of all text lines */ - _renderTextBackground: function(ctx, textLines) { + _renderTextBackground: function(ctx) { this._renderTextBoxBackground(ctx); - this._renderTextLinesBackground(ctx, textLines); + this._renderTextLinesBackground(ctx); }, /** @@ -20102,9 +19885,9 @@ 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 */ - _renderTextLinesBackground: function(ctx, textLines) { + _renderTextLinesBackground: function(ctx) { + var lineTopOffset = 0, heightOfLine = this._getHeightOfLine(); if (!this.textBackgroundColor) { return; } @@ -20112,20 +19895,21 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag ctx.save(); ctx.fillStyle = this.textBackgroundColor; - for (var i = 0, len = textLines.length; i < len; i++) { + for (var i = 0, len = this._textLines.length; i < len; i++) { - if (textLines[i] !== '') { + if (this._textLines[i] !== '') { - var lineWidth = this._getLineWidth(ctx, textLines[i]), + var lineWidth = this._getLineWidth(ctx, i), lineLeftOffset = this._getLineLeftOffset(lineWidth); ctx.fillRect( this._getLeftOffset() + lineLeftOffset, - this._getTopOffset() + (i * this.fontSize * this.lineHeight), + this._getTopOffset() + lineTopOffset, lineWidth, - this.fontSize * this.lineHeight + this.fontSize * this._fontSizeMult ); } + lineTopOffset += heightOfLine; } ctx.restore(); }, @@ -20147,53 +19931,85 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {String} line Text line - * @return {Number} Line width */ - _getLineWidth: function(ctx, line) { - return this.textAlign === 'justify' - ? this.width - : ctx.measureText(line).width; + _clearCache: function() { + this.__lineWidths = [ ]; + this.__lineHeights = [ ]; + this.__lineOffsets = [ ]; + }, + + /** + * @private + */ + _shouldClearCache: function() { + var shouldClear = false; + for (var prop in this._dimensionAffectingProps) { + if (this['__' + prop] !== this[prop]) { + this['__' + prop] = this[prop]; + shouldClear = true; + } + } + return shouldClear; }, /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {Array} textLines Array of all text lines + * @return {Number} Line width */ - _renderTextDecoration: function(ctx, textLines) { + _getLineWidth: function(ctx, lineIndex) { + if (this.__lineWidths[lineIndex]) { + return this.__lineWidths[lineIndex]; + } + this.__lineWidths[lineIndex] = this.textAlign === 'justify' ? + this.width : ctx.measureText(this._textLines[lineIndex]).width; + return this.__lineWidths[lineIndex]; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderTextDecoration: function(ctx) { if (!this.textDecoration) { return; } - // var halfOfVerticalBox = this.originY === 'top' ? 0 : this._getTextHeight(ctx, textLines) / 2; - var halfOfVerticalBox = this._getTextHeight(ctx, textLines) / 2, - _this = this; + var halfOfVerticalBox = this.height / 2, + _this = this, offsets = []; /** @ignore */ - function renderLinesAtOffset(offset) { - for (var i = 0, len = textLines.length; i < len; i++) { + function renderLinesAtOffset(offsets) { + var i, lineHeight = 0, len, j, oLen; + for (i = 0, len = _this._textLines.length; i < len; i++) { - var lineWidth = _this._getLineWidth(ctx, textLines[i]), - lineLeftOffset = _this._getLineLeftOffset(lineWidth); + var lineWidth = _this._getLineWidth(ctx, i), + lineLeftOffset = _this._getLineLeftOffset(lineWidth), + heightOfLine = _this._getHeightOfLine(ctx, i); - ctx.fillRect( - _this._getLeftOffset() + lineLeftOffset, - ~~((offset + (i * _this._getHeightOfLine(ctx, i, textLines))) - halfOfVerticalBox), - lineWidth, - 1); + for (j = 0, oLen = offsets.length; j < oLen; j++) { + ctx.fillRect( + _this._getLeftOffset() + lineLeftOffset, + lineHeight + (_this._fontSizeMult - 1 + offsets[j] ) * _this.fontSize - halfOfVerticalBox, + lineWidth, + _this.fontSize / 15); + } + lineHeight += heightOfLine; } } if (this.textDecoration.indexOf('underline') > -1) { - renderLinesAtOffset(this.fontSize * this.lineHeight); + offsets.push(0.85); // 1 - 3/16 } if (this.textDecoration.indexOf('line-through') > -1) { - renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize / 2); + offsets.push(0.43); } if (this.textDecoration.indexOf('overline') > -1) { - renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize); + offsets.push(-0.12); + } + + if (offsets.length > 0) { + renderLinesAtOffset(offsets); } }, @@ -20221,10 +20037,19 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag } ctx.save(); + this._setTextStyles(ctx); + + if (this._shouldClearCache()) { + this._clearCache(); + this._textLines = this.text.split(this._reNewline); + this.width = this._getTextWidth(ctx); + this.height = this._getTextHeight(ctx); + } if (!noTransform) { this.transform(ctx); } - + this._setStrokeStyles(ctx); + this._setFillStyles(ctx); var isInPathGroup = this.group && this.group.type === 'path-group'; if (isInPathGroup) { @@ -20255,9 +20080,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag lineHeight: this.lineHeight, textDecoration: this.textDecoration, textAlign: this.textAlign, - path: this.path, - textBackgroundColor: this.textBackgroundColor, - useNative: this.useNative + textBackgroundColor: this.textBackgroundColor }); if (!this.includeDefaultValues) { this._removeDefaultValues(object); @@ -20272,16 +20095,10 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @return {String} svg representation of an instance */ toSVG: function(reviver) { - var markup = [ ], - textLines = this.text.split(this._reNewline), - offsets = this._getSVGLeftTopOffsets(textLines), - textAndBg = this._getSVGTextAndBg(offsets.lineTop, offsets.textLeft, textLines), - shadowSpans = this._getSVGShadows(offsets.lineTop, textLines); - - // move top offset by an ascent - offsets.textTop += (this._fontAscent ? ((this._fontAscent / 5) * this.lineHeight) : 0); - - this._wrapSVGTextAndBg(markup, textAndBg, shadowSpans, offsets); + var markup = this._createBaseSVGMarkup(), + offsets = this._getSVGLeftTopOffsets(this.ctx), + textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft); + this._wrapSVGTextAndBg(markup, textAndBg); return reviver ? reviver(markup.join('')) : markup.join(''); }, @@ -20289,19 +20106,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private */ - _getSVGLeftTopOffsets: function(textLines) { - var lineTop = this.useNative - ? this.fontSize * this.lineHeight - : (-this._fontAscent - ((this._fontAscent / 5) * this.lineHeight)), - - textLeft = -(this.width/2), - textTop = this.useNative - ? (this.fontSize * this.lineHeight - 0.25 * this.fontSize) // to lift by 1 / 4 of font height. - : (this.height/2) - (textLines.length * this.fontSize) - this._totalLineHeight; + _getSVGLeftTopOffsets: function(ctx) { + var lineTop = this._getHeightOfLine(ctx, 0), + textLeft = -this.width / 2, + textTop = 0; return { textLeft: textLeft + (this.group && this.group.type === 'path-group' ? this.left : 0), - textTop: textTop + (this.group && this.group.type === 'path-group' ? this.top : 0), + textTop: textTop + (this.group && this.group.type === 'path-group' ? -this.top : 0), lineTop: lineTop }; }, @@ -20309,99 +20121,43 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private */ - _wrapSVGTextAndBg: function(markup, textAndBg, shadowSpans, offsets) { + _wrapSVGTextAndBg: function(markup, textAndBg) { markup.push( - '\n', + '\t\n', textAndBg.textBgRects.join(''), - '', - shadowSpans.join(''), + 'style="', this.getSvgStyles(), '" >', textAndBg.textSpans.join(''), '\n', - '\n' + '\t\n' ); }, /** * @private - * @param {Number} lineHeight - * @param {Array} textLines Array of all text lines - * @return {Array} - */ - _getSVGShadows: function(lineHeight, textLines) { - var shadowSpans = [], - i, len, - lineTopOffsetMultiplier = 1; - - if (!this.shadow || !this._boundaries) { - return shadowSpans; - } - - for (i = 0, len = textLines.length; i < len; i++) { - if (textLines[i] !== '') { - var lineLeftOffset = (this._boundaries && this._boundaries[i]) ? this._boundaries[i].left : 0; - shadowSpans.push( - '', - fabric.util.string.escapeXml(textLines[i]), - ''); - lineTopOffsetMultiplier = 1; - } - else { - // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier - // prevents empty tspans - lineTopOffsetMultiplier++; - } - } - - return shadowSpans; - }, - - /** - * @private - * @param {Number} lineHeight + * @param {Number} textTopOffset Text top offset * @param {Number} textLeftOffset Text left offset - * @param {Array} textLines Array of all text lines * @return {Object} */ - _getSVGTextAndBg: function(lineHeight, textLeftOffset, textLines) { + _getSVGTextAndBg: function(textTopOffset, textLeftOffset) { var textSpans = [ ], textBgRects = [ ], - lineTopOffsetMultiplier = 1; - + height = 0; // bounding-box background this._setSVGBg(textBgRects); // text and text-background - for (var i = 0, len = textLines.length; i < len; i++) { - if (textLines[i] !== '') { - this._setSVGTextLineText(textLines[i], i, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects); - lineTopOffsetMultiplier = 1; + for (var i = 0, len = this._textLines.length; i < len; i++) { + if (this.textBackgroundColor) { + this._setSVGTextLineBg(textBgRects, i, textLeftOffset, textTopOffset, height); } - else { - // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier - // prevents empty tspans - lineTopOffsetMultiplier++; - } - - if (!this.textBackgroundColor || !this._boundaries) { - continue; - } - - this._setSVGTextLineBg(textBgRects, i, textLeftOffset, lineHeight); + this._setSVGTextLineText(i, textSpans, height, textLeftOffset, textTopOffset, textBgRects); + height += this._getHeightOfLine(this.ctx, i); } return { @@ -20410,56 +20166,52 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag }; }, - _setSVGTextLineText: function(textLine, i, textSpans, lineHeight, lineTopOffsetMultiplier) { - var lineLeftOffset = (this._boundaries && this._boundaries[i]) - ? toFixed(this._boundaries[i].left, 2) - : 0; - + _setSVGTextLineText: function(i, textSpans, height, textLeftOffset, textTopOffset) { + var yPos = this.fontSize * (this._fontSizeMult - this._fontSizeFraction) + - textTopOffset + height - this.height / 2; textSpans.push( ' elements since setting opacity // on containing one doesn't work in Illustrator this._getFillAttributes(this.fill), '>', - fabric.util.string.escapeXml(textLine), + fabric.util.string.escapeXml(this._textLines[i]), '' ); }, - _setSVGTextLineBg: function(textBgRects, i, textLeftOffset, lineHeight) { + _setSVGTextLineBg: function(textBgRects, i, textLeftOffset, textTopOffset, height) { textBgRects.push( - '\n'); }, _setSVGBg: function(textBgRects) { - if (this.backgroundColor && this._boundaries) { + if (this.backgroundColor) { textBgRects.push( - ''); + toFixed(this.height, 4), + '">\n'); } }, @@ -20488,9 +20240,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @chainable */ _set: function(key, value) { - if (key === 'fontFamily' && this.path) { - this.path = this.path.replace(/(.*?)([^\/]*)(\.font\.js)/, '$1' + value + '$3'); - } this.callSuper('_set', key, value); if (key in this._dimensionAffectingProps) { @@ -20556,7 +20305,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag if (!options.originX) { options.originX = 'left'; } - options.top += options.fontSize / 4; var text = new fabric.Text(element.textContent, options), /* Adjust positioning: @@ -20573,7 +20321,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag } text.set({ left: text.getLeft() + offX, - top: text.getTop() - text.getHeight() / 2 + top: text.getTop() - text.getHeight() / 2 + text.fontSize * (0.18 + text._fontSizeFraction) /* 0.3 is the old lineHeight */ }); return text; @@ -20622,10 +20370,10 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * Select text vertically: shift + up, shift + down * Move cursor by word: alt + left, alt + right * Select words: shift + alt + left, shift + alt + right - * Move cursor to line start/end: cmd + left, cmd + right - * Select till start/end of line: cmd + shift + left, cmd + shift + right + * Move cursor to line start/end: cmd + left, cmd + right or home, end + * Select till start/end of line: cmd + shift + left, cmd + shift + right or shift + home, shift + end * Jump to start/end of text: cmd + up, cmd + down - * Select till start/end of text: cmd + shift + up, cmd + shift + down + * Select till start/end of text: cmd + shift + up, cmd + shift + down or shift + pgUp, shift + pgDown * Delete character: backspace * Delete word: alt + backspace * Delete line: cmd + backspace @@ -20634,6 +20382,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * Paste text: ctrl/cmd + v * Cut text: ctrl/cmd + x * Select entire text: ctrl/cmd + a + * Quit editing tab or esc * * *

Supported mouse/touch combination

@@ -20744,18 +20493,13 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @type Boolean * @default */ - _skipFillStrokeCheck: true, + _skipFillStrokeCheck: false, /** * @private */ _reSpace: /\s|\n/, - /** - * @private - */ - _fontSizeFraction: 4, - /** * @private */ @@ -20789,10 +20533,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag fabric.IText.instances.push(this); - // caching - this.__lineWidths = { }; - this.__lineHeights = { }; - this.__lineOffsets = { }; + }, + + /** + * @private + */ + _clearCache: function() { + this.callSuper('_clearCache'); + this.__maxFontHeights = [ ]; }, /** @@ -20820,12 +20568,13 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @param {Number} index Index to set selection start to */ setSelectionStart: function(index) { + index = Math.max(index, 0); if (this.selectionStart !== index) { this.fire('selection:changed'); this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + this.selectionStart = index; } - this.selectionStart = index; - this.hiddenTextarea && (this.hiddenTextarea.selectionStart = index); + this._updateTextarea(); }, /** @@ -20833,12 +20582,13 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @param {Number} index Index to set selection end to */ setSelectionEnd: function(index) { + index = Math.min(index, this.text.length); if (this.selectionEnd !== index) { this.fire('selection:changed'); this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + this.selectionEnd = index; } - this.selectionEnd = index; - this.hiddenTextarea && (this.hiddenTextarea.selectionEnd = index); + this._updateTextarea(); }, /** @@ -21003,18 +20753,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ _getCursorBoundaries: function(chars, typeOfBoundaries) { - var cursorLocation = this.get2DCursorLocation(), - - textLines = this.text.split(this._reNewline), - // left/top are left/top of entire text box // leftOffset/topOffset are offset from that left/top point of a text box - left = Math.round(this._getLeftOffset()), + var left = Math.round(this._getLeftOffset()), top = this._getTopOffset(), offsets = this._getCursorBoundariesOffsets( - chars, typeOfBoundaries, cursorLocation, textLines); + chars, typeOfBoundaries); return { left: left, @@ -21027,26 +20773,19 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private */ - _getCursorBoundariesOffsets: function(chars, typeOfBoundaries, cursorLocation, textLines) { + _getCursorBoundariesOffsets: function(chars, typeOfBoundaries) { var lineLeftOffset = 0, lineIndex = 0, charIndex = 0, - - leftOffset = 0, - topOffset = typeOfBoundaries === 'cursor' - // selection starts at the very top of the line, - // whereas cursor starts at the padding created by line height - ? (this._getHeightOfLine(this.ctx, 0) - - this.getCurrentCharFontSize(cursorLocation.lineIndex, cursorLocation.charIndex)) - : 0; + topOffset = 0, + leftOffset = 0; for (var i = 0; i < this.selectionStart; i++) { if (chars[i] === '\n') { leftOffset = 0; - var index = lineIndex + (typeOfBoundaries === 'cursor' ? 1 : 0); - topOffset += this._getCachedLineHeight(index); + topOffset += this._getHeightOfLine(this.ctx, lineIndex); lineIndex++; charIndex = 0; @@ -21056,10 +20795,12 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag charIndex++; } - lineLeftOffset = this._getCachedLineOffset(lineIndex, textLines); + lineLeftOffset = this._getCachedLineOffset(lineIndex); + } + if (typeOfBoundaries === 'cursor') { + topOffset += (1 - this._fontSizeFraction) * this._getHeightOfLine(this.ctx, lineIndex) / this.lineHeight + - this.getCurrentCharFontSize(lineIndex, charIndex) * (1 - this._fontSizeFraction); } - - this._clearCache(); return { top: topOffset, @@ -21071,33 +20812,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private */ - _clearCache: function() { - this.__lineWidths = { }; - this.__lineHeights = { }; - this.__lineOffsets = { }; - }, - - /** - * @private - */ - _getCachedLineHeight: function(index) { - return this.__lineHeights[index] || - (this.__lineHeights[index] = this._getHeightOfLine(this.ctx, index)); - }, - - /** - * @private - */ - _getCachedLineWidth: function(lineIndex, textLines) { - return this.__lineWidths[lineIndex] || - (this.__lineWidths[lineIndex] = this._getWidthOfLine(this.ctx, lineIndex, textLines)); - }, - - /** - * @private - */ - _getCachedLineOffset: function(lineIndex, textLines) { - var widthOfLine = this._getCachedLineWidth(lineIndex, textLines); + _getCachedLineOffset: function(lineIndex) { + var widthOfLine = this._getLineWidth(this.ctx, lineIndex); return this.__lineOffsets[lineIndex] || (this.__lineOffsets[lineIndex] = this._getLineLeftOffset(widthOfLine)); @@ -21147,30 +20863,29 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag var start = this.get2DCursorLocation(this.selectionStart), end = this.get2DCursorLocation(this.selectionEnd), startLine = start.lineIndex, - endLine = end.lineIndex, - textLines = this.text.split(this._reNewline); + endLine = end.lineIndex; for (var i = startLine; i <= endLine; i++) { - var lineOffset = this._getCachedLineOffset(i, textLines) || 0, - lineHeight = this._getCachedLineHeight(i), - boxWidth = 0; + var lineOffset = this._getCachedLineOffset(i) || 0, + lineHeight = this._getHeightOfLine(this.ctx, i), + boxWidth = 0, line = this._textLines[i]; if (i === startLine) { - for (var j = 0, len = textLines[i].length; j < len; j++) { + for (var j = 0, len = line.length; j < len; j++) { if (j >= start.charIndex && (i !== endLine || j < end.charIndex)) { - boxWidth += this._getWidthOfChar(ctx, textLines[i][j], i, j); + boxWidth += this._getWidthOfChar(ctx, line[j], i, j); } if (j < start.charIndex) { - lineOffset += this._getWidthOfChar(ctx, textLines[i][j], i, j); + lineOffset += this._getWidthOfChar(ctx, line[j], i, j); } } } else if (i > startLine && i < endLine) { - boxWidth += this._getCachedLineWidth(i, textLines) || 5; + boxWidth += this._getLineWidth(ctx, i) || 5; } else if (i === endLine) { for (var j2 = 0, j2len = end.charIndex; j2 < j2len; j2++) { - boxWidth += this._getWidthOfChar(ctx, textLines[i][j2], i, j2); + boxWidth += this._getWidthOfChar(ctx, line[j2], i, j2); } } @@ -21206,10 +20921,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag : 0; // set proper line offset - var textLines = this.text.split(this._reNewline), - lineWidth = this._getWidthOfLine(ctx, lineIndex, textLines), - lineHeight = this._getHeightOfLine(ctx, lineIndex, textLines), - lineLeftOffset = this._getLineLeftOffset(lineWidth), + var lineHeight = this._getHeightOfLine(ctx, lineIndex), + lineLeftOffset = this._getCachedLineOffset(lineIndex), chars = line.split(''), prevStyle, charsToRender = ''; @@ -21217,7 +20930,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag left += lineLeftOffset || 0; ctx.save(); - + top -= lineHeight / this.lineHeight * this._fontSizeFraction; for (var i = 0, len = chars.length; i <= len; i++) { prevStyle = prevStyle || this.getCurrentCharStyle(lineIndex, i); var thisStyle = this.getCurrentCharStyle(lineIndex, i + 1); @@ -21247,7 +20960,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag if (method === 'fillText' && this.fill) { this.callSuper('_renderChars', method, ctx, line, left, top); } - if (method === 'strokeText' && this.stroke) { + if (method === 'strokeText' && ((this.stroke && this.strokeWidth > 0) || this.skipFillStrokeCheck)) { this.callSuper('_renderChars', method, ctx, line, left, top); } }, @@ -21264,7 +20977,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @param {Number} lineHeight Height of the line */ _renderChar: function(method, ctx, lineIndex, i, _char, left, top, lineHeight) { - var decl, charWidth, charHeight; + var decl, charWidth, charHeight, + offset = this._fontSizeFraction * lineHeight / this.lineHeight; if (this.styles && this.styles[lineIndex] && (decl = this.styles[lineIndex][i])) { @@ -21282,7 +20996,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag ctx.strokeText(_char, left, top); } - this._renderCharDecoration(ctx, decl, left, top, charWidth, lineHeight, charHeight); + this._renderCharDecoration(ctx, decl, left, top, offset, charWidth, charHeight); ctx.restore(); ctx.translate(charWidth, 0); @@ -21295,7 +21009,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag ctx[method](_char, left, top); } charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i); - this._renderCharDecoration(ctx, null, left, top, charWidth, lineHeight); + this._renderCharDecoration(ctx, null, left, top, offset, charWidth, this.fontSize); ctx.translate(ctx.measureText(_char).width, 0); } @@ -21323,58 +21037,42 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _renderCharDecoration: function(ctx, styleDeclaration, left, top, charWidth, lineHeight, charHeight) { + _renderCharDecoration: function(ctx, styleDeclaration, left, top, offset, charWidth, charHeight) { var textDecoration = styleDeclaration ? (styleDeclaration.textDecoration || this.textDecoration) - : this.textDecoration, - - fontSize = (styleDeclaration ? styleDeclaration.fontSize : null) || this.fontSize; + : this.textDecoration; if (!textDecoration) { return; } if (textDecoration.indexOf('underline') > -1) { - this._renderCharDecorationAtOffset( - ctx, + ctx.fillRect( left, - top + (this.fontSize / this._fontSizeFraction), - charWidth, - 0, - this.fontSize / 20 + top + charHeight / 10, + charWidth , + charHeight / 15 ); } if (textDecoration.indexOf('line-through') > -1) { - this._renderCharDecorationAtOffset( - ctx, + ctx.fillRect( left, - top + (this.fontSize / this._fontSizeFraction), + top - charHeight * (this._fontSizeFraction + this._fontSizeMult - 1) + charHeight / 15, charWidth, - charHeight / 2, - fontSize / 20 + charHeight / 15 ); } if (textDecoration.indexOf('overline') > -1) { - this._renderCharDecorationAtOffset( - ctx, + ctx.fillRect( left, - top, + top - (this._fontSizeMult - this._fontSizeFraction) * charHeight, charWidth, - lineHeight - (this.fontSize / this._fontSizeFraction), - this.fontSize / 20 + charHeight / 15 ); } }, - /** - * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - */ - _renderCharDecorationAtOffset: function(ctx, left, top, charWidth, offset, thickness) { - ctx.fillRect(left, top - offset, charWidth, thickness); - }, - /** * @private * @param {String} method @@ -21383,27 +21081,26 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ _renderTextLine: function(method, ctx, line, left, top, lineIndex) { // to "cancel" this.fontSize subtraction in fabric.Text#_renderTextLine - top += this.fontSize / 4; + // the adding 0.03 is just to align text with itext by overlap test + top += this.fontSize * (this._fontSizeFraction + 0.03); this.callSuper('_renderTextLine', method, ctx, line, left, top, lineIndex); }, /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {Array} textLines */ - _renderTextDecoration: function(ctx, textLines) { + _renderTextDecoration: function(ctx) { if (this.isEmptyStyles()) { - return this.callSuper('_renderTextDecoration', ctx, textLines); + return this.callSuper('_renderTextDecoration', ctx); } }, /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {Array} textLines Array of all text lines */ - _renderTextLinesBackground: function(ctx, textLines) { + _renderTextLinesBackground: function(ctx) { if (!this.textBackgroundColor && !this.styles) { return; } @@ -21414,43 +21111,42 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag ctx.fillStyle = this.textBackgroundColor; } - var lineHeights = 0, - fractionOfFontSize = this.fontSize / this._fontSizeFraction; + var lineHeights = 0; - for (var i = 0, len = textLines.length; i < len; i++) { + for (var i = 0, len = this._textLines.length; i < len; i++) { - var heightOfLine = this._getHeightOfLine(ctx, i, textLines); - if (textLines[i] === '') { + var heightOfLine = this._getHeightOfLine(ctx, i); + if (this._textLines[i] === '') { lineHeights += heightOfLine; continue; } - var lineWidth = this._getWidthOfLine(ctx, i, textLines), - lineLeftOffset = this._getLineLeftOffset(lineWidth); + var lineWidth = this._getLineWidth(ctx, i), + lineLeftOffset = this._getCachedLineOffset(i); if (this.textBackgroundColor) { ctx.fillStyle = this.textBackgroundColor; ctx.fillRect( this._getLeftOffset() + lineLeftOffset, - this._getTopOffset() + lineHeights + fractionOfFontSize, + this._getTopOffset() + lineHeights, lineWidth, - heightOfLine + heightOfLine / this.lineHeight ); } if (this.styles[i]) { - for (var j = 0, jlen = textLines[i].length; j < jlen; j++) { + for (var j = 0, jlen = this._textLines[i].length; j < jlen; j++) { if (this.styles[i] && this.styles[i][j] && this.styles[i][j].textBackgroundColor) { - var _char = textLines[i][j]; + var _char = this._textLines[i][j]; ctx.fillStyle = this.styles[i][j].textBackgroundColor; ctx.fillRect( - this._getLeftOffset() + lineLeftOffset + this._getWidthOfCharsAt(ctx, i, j, textLines), - this._getTopOffset() + lineHeights + fractionOfFontSize, - this._getWidthOfChar(ctx, _char, i, j, textLines) + 1, - heightOfLine + this._getLeftOffset() + lineLeftOffset + this._getWidthOfCharsAt(ctx, i, j), + this._getTopOffset() + lineHeights, + this._getWidthOfChar(ctx, _char, i, j) + 1, + heightOfLine / this.lineHeight ); } } @@ -21465,12 +21161,10 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ _getCacheProp: function(_char, styleDeclaration) { return _char + - styleDeclaration.fontFamily + styleDeclaration.fontSize + styleDeclaration.fontWeight + styleDeclaration.fontStyle + - styleDeclaration.shadow; }, @@ -21603,9 +21297,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _getWidthOfCharAt: function(ctx, lineIndex, charIndex, lines) { - lines = lines || this.text.split(this._reNewline); - var _char = lines[lineIndex].split('')[charIndex]; + _getWidthOfCharAt: function(ctx, lineIndex, charIndex) { + var _char = this._textLines[lineIndex].split('')[charIndex]; return this._getWidthOfChar(ctx, _char, lineIndex, charIndex); }, @@ -21613,9 +21306,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _getHeightOfCharAt: function(ctx, lineIndex, charIndex, lines) { - lines = lines || this.text.split(this._reNewline); - var _char = lines[lineIndex].split('')[charIndex]; + _getHeightOfCharAt: function(ctx, lineIndex, charIndex) { + var _char = this._textLines[lineIndex].split('')[charIndex]; return this._getHeightOfChar(ctx, _char, lineIndex, charIndex); }, @@ -21623,10 +21315,10 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _getWidthOfCharsAt: function(ctx, lineIndex, charIndex, lines) { + _getWidthOfCharsAt: function(ctx, lineIndex, charIndex) { var width = 0; for (var i = 0; i < charIndex; i++) { - width += this._getWidthOfCharAt(ctx, lineIndex, i, lines); + width += this._getWidthOfCharAt(ctx, lineIndex, i); } return width; }, @@ -21635,11 +21327,12 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _getWidthOfLine: function(ctx, lineIndex, textLines) { - // if (!this.styles[lineIndex]) { - // return this.callSuper('_getLineWidth', ctx, textLines[lineIndex]); - // } - return this._getWidthOfCharsAt(ctx, lineIndex, textLines[lineIndex].length, textLines); + _getLineWidth: function(ctx, lineIndex) { + if (this.__lineWidths[lineIndex]) { + return this.__lineWidths[lineIndex]; + } + this.__lineWidths[lineIndex] = this._getWidthOfCharsAt(ctx, lineIndex, this._textLines[lineIndex].length); + return this.__lineWidths[lineIndex]; }, /** @@ -21683,33 +21376,13 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _getTextWidth: function(ctx, textLines) { - - if (this.isEmptyStyles()) { - return this.callSuper('_getTextWidth', ctx, textLines); + _getHeightOfLine: function(ctx, lineIndex) { + if (this.__lineHeights[lineIndex]) { + return this.__lineHeights[lineIndex]; } - var maxWidth = this._getWidthOfLine(ctx, 0, textLines); - - for (var i = 1, len = textLines.length; i < len; i++) { - var currentLineWidth = this._getWidthOfLine(ctx, i, textLines); - if (currentLineWidth > maxWidth) { - maxWidth = currentLineWidth; - } - } - return maxWidth; - }, - - /** - * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - */ - _getHeightOfLine: function(ctx, lineIndex, textLines) { - - textLines = textLines || this.text.split(this._reNewline); - - var maxHeight = this._getHeightOfChar(ctx, textLines[lineIndex][0], lineIndex, 0), - line = textLines[lineIndex], + var line = this._textLines[lineIndex], + maxHeight = this._getHeightOfChar(ctx, line[0], lineIndex, 0), chars = line.split(''); for (var i = 1, len = chars.length; i < len; i++) { @@ -21718,31 +21391,23 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag maxHeight = currentCharHeight; } } - - return maxHeight * this.lineHeight; + this.__maxFontHeights[lineIndex] = maxHeight; + this.__lineHeights[lineIndex] = maxHeight * this.lineHeight * this._fontSizeMult; + return this.__lineHeights[lineIndex]; }, /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {Array} textLines Array of all text lines */ - _getTextHeight: function(ctx, textLines) { + _getTextHeight: function(ctx) { var height = 0; - for (var i = 0, len = textLines.length; i < len; i++) { - height += this._getHeightOfLine(ctx, i, textLines); + for (var i = 0, len = this._textLines.length; i < len; i++) { + height += this._getHeightOfLine(ctx, i); } return height; }, - /** - * @private - */ - _getTopOffset: function() { - var topOffset = fabric.Text.prototype._getTopOffset.call(this); - return topOffset - (this.fontSize / this._fontSizeFraction); - }, - /** * This method is overwritten to account for different top offset * @private @@ -21757,7 +21422,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag ctx.fillRect( this._getLeftOffset(), - this._getTopOffset() + (this.fontSize / this._fontSizeFraction), + this._getTopOffset(), this.width, this.height ); @@ -21959,10 +21624,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * Selects entire text */ selectAll: function() { - this.selectionStart = 0; - this.selectionEnd = this.text.length; - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + this.setSelectionStart(0); + this.setSelectionEnd(this.text.length); }, /** @@ -22129,6 +21792,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag this.isEditing = true; this.initHiddenTextarea(); + this.hiddenTextarea.focus(); this._updateTextarea(); this._saveEditingProps(); this._setEditingProps(); @@ -22177,6 +21841,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag this.hiddenTextarea.value = this.text; this.hiddenTextarea.selectionStart = this.selectionStart; + this.hiddenTextarea.selectionEnd = this.selectionEnd; }, /** @@ -22243,9 +21908,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private */ _removeExtraneousStyles: function() { - var textLines = this.text.split(this._reNewline); for (var prop in this.styles) { - if (!textLines[prop]) { + if (!this._textLines[prop]) { delete this.styles[prop]; } } @@ -22276,13 +21940,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag this.text = this.text.slice(0, start) + this.text.slice(end); + this._clearCache(); }, /** * Inserts a character where cursor is (replacing selection if one exists) * @param {String} _chars Characters to insert */ - insertChars: function(_chars) { + insertChars: function(_chars, useCopiedStyle) { var isEndOfLine = this.text.slice(this.selectionStart, this.selectionStart + 1) === '\n'; this.text = this.text.slice(0, this.selectionStart) + @@ -22290,21 +21955,16 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag this.text.slice(this.selectionEnd); if (this.selectionStart === this.selectionEnd) { - this.insertStyleObjects(_chars, isEndOfLine, this.copiedStyles); + this.insertStyleObjects(_chars, isEndOfLine, useCopiedStyle); } // else if (this.selectionEnd - this.selectionStart > 1) { // TODO: replace styles properly // console.log('replacing MORE than 1 char'); // } - - this.selectionStart += _chars.length; - this.selectionEnd = this.selectionStart; - - if (this.canvas) { - // TODO: double renderAll gets rid of text box shift happenning sometimes - // need to find out what exactly causes it and fix it - this.canvas.renderAll().renderAll(); - } + this.setSelectionStart(this.selectionStart + _chars.length); + this.setSelectionEnd(this.selectionStart); + this._clearCache(); + this.canvas && this.canvas.renderAll(); this.setCoords(); this.fire('changed'); @@ -22346,6 +22006,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag } this.styles[lineIndex + 1] = newLineStyles; } + this._clearCache(); }, /** @@ -22375,15 +22036,16 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag this.styles[lineIndex][charIndex] = style || clone(currentLineStyles[charIndex - 1]); + this._clearCache(); }, /** * Inserts style object(s) * @param {String} _chars Characters at the location where style is inserted * @param {Boolean} isEndOfLine True if it's end of line - * @param {Array} [styles] Styles to insert + * @param {Boolean} [useCopiedStyle] Style to insert */ - insertStyleObjects: function(_chars, isEndOfLine, styles) { + insertStyleObjects: function(_chars, isEndOfLine, useCopiedStyle) { // removed shortcircuit over isEmptyStyles var cursorLocation = this.get2DCursorLocation(), @@ -22398,8 +22060,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag this.insertNewlineStyleObject(lineIndex, charIndex, isEndOfLine); } else { - if (styles) { - this._insertStyles(styles); + if (useCopiedStyle) { + this._insertStyles(this.copiedStyles); } else { // TODO: support multiple style insertion if _chars.length > 1 @@ -22451,8 +22113,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag if (isBeginningOfLine) { - var textLines = this.text.split(this._reNewline), - textOnPreviousLine = textLines[lineIndex - 1], + var textOnPreviousLine = this._textLines[lineIndex - 1], newCharIndexOnPrevLine = textOnPreviousLine ? textOnPreviousLine.length : 0; @@ -22705,30 +22366,30 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot */ getSelectionStartFromPointer: function(e) { var mouseOffset = this._getLocalRotatedPointer(e), - textLines = this.text.split(this._reNewline), prevWidth = 0, width = 0, height = 0, charIndex = 0, - newSelectionStart; - - for (var i = 0, len = textLines.length; i < len; i++) { + newSelectionStart, + line; + for (var i = 0, len = this._textLines.length; i < len; i++) { + line = this._textLines[i].split(''); height += this._getHeightOfLine(this.ctx, i) * this.scaleY; - var widthOfLine = this._getWidthOfLine(this.ctx, i, textLines), + var widthOfLine = this._getLineWidth(this.ctx, i), lineLeftOffset = this._getLineLeftOffset(widthOfLine); width = lineLeftOffset * this.scaleX; if (this.flipX) { // when oject is horizontally flipped we reverse chars - textLines[i] = textLines[i].split('').reverse().join(''); + this._textLines[i] = line.split('').reverse().join(''); } - for (var j = 0, jlen = textLines[i].length; j < jlen; j++) { + for (var j = 0, jlen = line.length; j < jlen; j++) { - var _char = textLines[i][j]; + var _char = line[j]; prevWidth = width; width += this._getWidthOfChar(this.ctx, _char, i, this.flipX ? jlen - j : j) * @@ -22796,11 +22457,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot 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)); - - if (!this._clickHandlerInitialized && this.canvas) { - fabric.util.addListener(this.canvas.upperCanvasEl, 'click', this.onClick.bind(this)); - this._clickHandlerInitialized = true; - } }, /** @@ -22830,11 +22486,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot 88: 'cut' }, - onClick: function() { - // No need to trigger click event here, focus is enough to have the keyboard appear on Android - this.hiddenTextarea && this.hiddenTextarea.focus(); - }, - /** * Handles keyup event * @param {Event} e Event object @@ -22843,7 +22494,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot if (!this.isEditing) { return; } - if (e.keyCode in this._keysMap) { this[this._keysMap[e.keyCode]](e); } @@ -22853,10 +22503,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot else { return; } - e.stopImmediatePropagation(); e.preventDefault(); - this.canvas && this.canvas.renderAll(); }, @@ -22906,7 +22554,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot } if (copiedText) { - this.insertChars(copiedText); + this.insertChars(copiedText, true); } }, @@ -22954,10 +22602,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot */ getDownCursorOffset: function(e, isRight) { var selectionProp = isRight ? this.selectionEnd : this.selectionStart, - textLines = this.text.split(this._reNewline), - _char, - lineLeftOffset, - + _char, lineLeftOffset, textBeforeCursor = this.text.slice(0, selectionProp), textAfterCursor = this.text.slice(selectionProp), @@ -22968,13 +22613,13 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot cursorLocation = this.get2DCursorLocation(selectionProp); // if on last line, down cursor goes to end of line - if (cursorLocation.lineIndex === textLines.length - 1 || e.metaKey || e.keyCode === 34) { + if (cursorLocation.lineIndex === this._textLines.length - 1 || e.metaKey || e.keyCode === 34) { // move to the end of a text return this.text.length - selectionProp; } - var widthOfSameLineBeforeCursor = this._getWidthOfLine(this.ctx, cursorLocation.lineIndex, textLines); + var widthOfSameLineBeforeCursor = this._getLineWidth(this.ctx, cursorLocation.lineIndex); lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor); var widthOfCharsOnSameLineBeforeCursor = lineLeftOffset, @@ -22986,7 +22631,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot } var indexOnNextLine = this._getIndexOnNextLine( - cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor, textLines); + cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor); return textOnSameLineAfterCursor.length + 1 + indexOnNextLine; }, @@ -22994,9 +22639,9 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private */ - _getIndexOnNextLine: function(cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor, textLines) { + _getIndexOnNextLine: function(cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor) { var lineIndex = cursorLocation.lineIndex + 1, - widthOfNextLine = this._getWidthOfLine(this.ctx, lineIndex, textLines), + widthOfNextLine = this._getLineWidth(this.ctx, lineIndex), lineLeftOffset = this._getLineLeftOffset(widthOfNextLine), widthOfCharsOnNextLine = lineLeftOffset, indexOnNextLine = 0, @@ -23058,15 +22703,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot */ moveCursorDownWithoutShift: function(offset) { this._selectionDirection = 'right'; - this.selectionStart += offset; - - if (this.selectionStart > this.text.length) { - this.selectionStart = this.text.length; - } - this.selectionEnd = this.selectionStart; - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + this.setSelectionStart(this.selectionStart + offset); + this.setSelectionEnd(this.selectionStart); }, /** @@ -23074,8 +22712,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot */ swapSelectionPoints: function() { var swapSel = this.selectionEnd; - this.selectionEnd = this.selectionStart; - this.selectionStart = swapSel; + this.setSelectionEnd(this.selectionStart); + this.setSelectionStart(swapSel); }, /** @@ -23086,18 +22724,19 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot if (this.selectionEnd === this.selectionStart) { this._selectionDirection = 'right'; } - var prop = this._selectionDirection === 'right' ? 'selectionEnd' : 'selectionStart'; - this[prop] += offset; + if (this._selectionDirection === 'right') { + this.setSelectionEnd(this.selectionEnd + offset); + } + else { + this.setSelectionStart(this.selectionStart + offset); + } if (this.selectionEnd < this.selectionStart && this._selectionDirection === 'left') { this.swapSelectionPoints(); this._selectionDirection = 'right'; } if (this.selectionEnd > this.text.length) { - this.selectionEnd = this.text.length; + this.setSelectionEnd(this.text.length); } - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); }, /** @@ -23116,9 +22755,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot var textBeforeCursor = this.text.slice(0, selectionProp), textOnSameLineBeforeCursor = textBeforeCursor.slice(textBeforeCursor.lastIndexOf('\n') + 1), textOnPreviousLine = (textBeforeCursor.match(/\n?(.*)\n.*$/) || {})[1] || '', - textLines = this.text.split(this._reNewline), _char, - widthOfSameLineBeforeCursor = this._getWidthOfLine(this.ctx, cursorLocation.lineIndex, textLines), + widthOfSameLineBeforeCursor = this._getLineWidth(this.ctx, cursorLocation.lineIndex), lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor), widthOfCharsOnSameLineBeforeCursor = lineLeftOffset, lineIndex = cursorLocation.lineIndex; @@ -23129,7 +22767,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot } var indexOnPrevLine = this._getIndexOnPrevLine( - cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor, textLines); + cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor); return textOnPreviousLine.length - indexOnPrevLine + textOnSameLineBeforeCursor.length; }, @@ -23137,10 +22775,10 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private */ - _getIndexOnPrevLine: function(cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor, textLines) { + _getIndexOnPrevLine: function(cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor) { var lineIndex = cursorLocation.lineIndex - 1, - widthOfPreviousLine = this._getWidthOfLine(this.ctx, lineIndex, textLines), + widthOfPreviousLine = this._getLineWidth(this.ctx, lineIndex), lineLeftOffset = this._getLineLeftOffset(widthOfPreviousLine), widthOfCharsOnPreviousLine = lineLeftOffset, indexOnPrevLine = 0, @@ -23204,18 +22842,16 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot if (this.selectionEnd === this.selectionStart) { this._selectionDirection = 'left'; } - var prop = this._selectionDirection === 'right' ? 'selectionEnd' : 'selectionStart'; - this[prop] -= offset; + if (this._selectionDirection === 'right') { + this.setSelectionEnd(this.selectionEnd - offset); + } + else { + this.setSelectionStart(this.selectionStart - offset); + } if (this.selectionEnd < this.selectionStart && this._selectionDirection === 'right') { this.swapSelectionPoints(); this._selectionDirection = 'left'; } - if (this.selectionStart < 0) { - this.selectionStart = 0; - } - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); }, /** @@ -23224,17 +22860,11 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot */ moveCursorUpWithoutShift: function(offset) { if (this.selectionStart === this.selectionEnd) { - this.selectionStart -= offset; + this.setSelectionStart(this.selectionStart - offset); } - if (this.selectionStart < 0) { - this.selectionStart = 0; - } - this.selectionEnd = this.selectionStart; + this.setSelectionEnd(this.selectionStart); this._selectionDirection = 'left'; - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); }, /** @@ -23263,14 +22893,15 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @private */ _move: function(e, prop, direction) { + var propMethod = (prop === 'selectionStart' ? 'setSelectionStart' : 'setSelectionEnd'); if (e.altKey) { - this[prop] = this['findWordBoundary' + direction](this[prop]); + this[propMethod](this['findWordBoundary' + direction](this[prop])); } else if (e.metaKey || e.keyCode === 35 || e.keyCode === 36 ) { - this[prop] = this['findLineBoundary' + direction](this[prop]); + this[propMethod](this['findLineBoundary' + direction](this[prop])); } else { - this[prop] += (direction === 'Left' ? -1 : 1); + this[propMethod](this[prop] + (direction === 'Left' ? -1 : 1)); } }, @@ -23300,10 +22931,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot if (this.selectionEnd === this.selectionStart) { this._moveLeft(e, 'selectionStart'); } - this.selectionEnd = this.selectionStart; - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + this.setSelectionEnd(this.selectionStart); }, /** @@ -23320,15 +22948,9 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot // increase selection by one if it's a newline if (this.text.charAt(this.selectionStart) === '\n') { - this.selectionStart--; - } - if (this.selectionStart < 0) { - this.selectionStart = 0; + this.setSelectionStart(this.selectionStart - 1); } } - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); }, /** @@ -23367,15 +22989,9 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot // increase selection by one if it's a newline if (this.text.charAt(this.selectionEnd - 1) === '\n') { - this.selectionEnd++; - } - if (this.selectionEnd > this.text.length) { - this.selectionEnd = this.text.length; + this.setSelectionEnd(this.selectionEnd + 1); } } - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); }, /** @@ -23387,22 +23003,16 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot if (this.selectionStart === this.selectionEnd) { this._moveRight(e, 'selectionStart'); - this.selectionEnd = this.selectionStart; + this.setSelectionEnd(this.selectionStart); } else { - this.selectionEnd += this.getNumNewLinesInSelectedText(); - if (this.selectionEnd > this.text.length) { - this.selectionEnd = this.text.length; - } - this.selectionStart = this.selectionEnd; + this.setSelectionEnd(this.selectionEnd + this.getNumNewLinesInSelectedText()); + this.setSelectionStart(this.selectionEnd); } - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); }, /** - * Inserts a character where cursor is (replacing selection if one exists) + * Removes characters selected by selection * @param {Event} e Event object */ removeChars: function(e) { @@ -23413,15 +23023,12 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot this._removeCharsFromTo(this.selectionStart, this.selectionEnd); } - this.selectionEnd = this.selectionStart; + this.setSelectionEnd(this.selectionStart); this._removeExtraneousStyles(); - if (this.canvas) { - // TODO: double renderAll gets rid of text box shift happenning sometimes - // need to find out what exactly causes it and fix it - this.canvas.renderAll().renderAll(); - } + this._clearCache(); + this.canvas && this.canvas.renderAll(); this.setCoords(); this.fire('changed'); @@ -23440,20 +23047,19 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot var leftLineBoundary = this.findLineBoundaryLeft(this.selectionStart); this._removeCharsFromTo(leftLineBoundary, this.selectionStart); - this.selectionStart = leftLineBoundary; + this.setSelectionStart(leftLineBoundary); } else if (e.altKey) { // remove all till the start of current word var leftWordBoundary = this.findWordBoundaryLeft(this.selectionStart); this._removeCharsFromTo(leftWordBoundary, this.selectionStart); - this.selectionStart = leftWordBoundary; + this.setSelectionStart(leftWordBoundary); } else { var isBeginningOfLine = this.text.slice(this.selectionStart - 1, this.selectionStart) === '\n'; this.removeStyleObject(isBeginningOfLine); - - this.selectionStart--; + this.setSelectionStart(this.selectionStart - 1); this.text = this.text.slice(0, this.selectionStart) + this.text.slice(this.selectionStart + 1); } @@ -23468,27 +23074,26 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private */ - _setSVGTextLineText: function(textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects) { + _setSVGTextLineText: function(lineIndex, textSpans, height, textLeftOffset, textTopOffset, textBgRects) { if (!this.styles[lineIndex]) { this.callSuper('_setSVGTextLineText', - textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier); + lineIndex, textSpans, height, textLeftOffset, textTopOffset); } else { this._setSVGTextLineChars( - textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects); + lineIndex, textSpans, height, textLeftOffset, textBgRects); } }, /** * @private */ - _setSVGTextLineChars: function(textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects) { + _setSVGTextLineChars: function(lineIndex, textSpans, height, textLeftOffset, textBgRects) { - var yProp = lineIndex === 0 || this.useNative ? 'y' : 'dy', - chars = textLine.split(''), + var chars = this._textLines[lineIndex].split(''), charOffset = 0, - lineLeftOffset = this._getSVGLineLeftOffset(lineIndex), - lineTopOffset = this._getSVGLineTopOffset(lineIndex), + lineLeftOffset = this._getSVGLineLeftOffset(lineIndex) - this.width / 2, + lineOffset = this._getSVGLineTopOffset(lineIndex), heightOfLine = this._getHeightOfLine(this.ctx, lineIndex); for (var i = 0, len = chars.length; i < len; i++) { @@ -23496,14 +23101,14 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot textSpans.push( this._createTextCharSpan( - chars[i], styleDecl, lineLeftOffset, lineTopOffset, yProp, charOffset)); + chars[i], styleDecl, lineLeftOffset, lineOffset.lineTop + lineOffset.offset, charOffset)); var charWidth = this._getWidthOfChar(this.ctx, chars[i], lineIndex, i); if (styleDecl.textBackgroundColor) { textBgRects.push( this._createTextCharBg( - styleDecl, lineLeftOffset, lineTopOffset, heightOfLine, charWidth, charOffset)); + styleDecl, lineLeftOffset, lineOffset.lineTop, heightOfLine, charWidth, charOffset)); } charOffset += charWidth; @@ -23514,20 +23119,22 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @private */ _getSVGLineLeftOffset: function(lineIndex) { - return (this._boundaries && this._boundaries[lineIndex]) - ? fabric.util.toFixed(this._boundaries[lineIndex].left, 2) - : 0; + return fabric.util.toFixed(this._getLineLeftOffset(this.__lineWidths[lineIndex]), 2); }, /** * @private */ _getSVGLineTopOffset: function(lineIndex) { - var lineTopOffset = 0; - for (var j = 0; j <= lineIndex; j++) { + var lineTopOffset = 0, lastHeight = 0; + for (var j = 0; j < lineIndex; j++) { lineTopOffset += this._getHeightOfLine(this.ctx, j); } - return lineTopOffset - this.height / 2; + lastHeight = this._getHeightOfLine(this.ctx, j); + return { + lineTop: lineTopOffset, + offset: (this._fontSizeMult - this._fontSizeFraction) * lastHeight / (this.lineHeight * this._fontSizeMult) + }; }, /** @@ -23537,13 +23144,10 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot return [ //jscs:disable validateIndentation '' //jscs:enable validateIndentation ].join(''); @@ -23552,7 +23156,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private */ - _createTextCharSpan: function(_char, styleDecl, lineLeftOffset, lineTopOffset, yProp, charOffset) { + _createTextCharSpan: function(_char, styleDecl, lineLeftOffset, lineTopOffset, charOffset) { var fillStyles = this.getSvgStyles.call(fabric.util.object.extend({ visible: true, @@ -23563,16 +23167,14 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot return [ //jscs:disable validateIndentation - '', - fabric.util.string.escapeXml(_char), '' //jscs:enable validateIndentation @@ -23606,7 +23208,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot } // assign request handler based on protocol - var reqHandler = ( oURL.port === 443 ) ? HTTPS : HTTP, + var reqHandler = (oURL.protocol.indexOf('https:') === 0 ) ? HTTPS : HTTP, req = reqHandler.request({ hostname: oURL.hostname, port: oURL.port, diff --git a/dist/fabric.min.js b/dist/fabric.min.js index 00a17219..8fd35eaf 100644 --- a/dist/fabric.min.js +++ b/dist/fabric.min.js @@ -1,8 +1,7 @@ /* build: `node build.js modules=ALL exclude=gestures,cufon,json minifier=uglifyjs` *//*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */var fabric=fabric||{version:"1.4.13"};typeof exports!="undefined"&&(exports.fabric=fabric),typeof document!="undefined"&&typeof window!="undefined"?(fabric.document=document,fabric.window=window,window.fabric=fabric):(fabric.document=require("jsdom").jsdom(""),fabric.document.createWindow?fabric.window=fabric.document.createWindow():fabric.window=fabric.document.parentWindow),fabric.isTouchSupported="ontouchstart"in fabric.document.documentElement,fabric.isLikelyNode=typeof Buffer!="undefined"&&typeof window=="undefined",fabric.SHARED_ATTRIBUTES=["display","transform","fill","fill-opacity","fill-rule","opacity","stroke","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width"],fabric.DPI=96,fabric.reNum="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",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,t){var n=/\D{0,2}$/.exec(e),r=parseFloat(e);t||(t=fabric.Text.DEFAULT_SVG_FONT_SIZE);switch(n[0]){case"mm":return r*fabric.DPI/25.4;case"cm":return r*fabric.DPI/2.54;case"in":return r*fabric.DPI;case"pt":return r*fabric.DPI/72;case"pc":return r*fabric.DPI/72*12;case"em":return r*t;default:return r}},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;sr)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]},isTransparent:function(e,t,n,r){r>0&&(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?_-=2*h:f===1&&_<0&&(_+=2*h);var D=Math.ceil(Math.abs(_/h*2)),P=[],H=_/D,B=8/3*Math.sin(H/4)*Math.sin(H/4)/Math.sin(H/2),j=M+H;for(var F=0;F=i?s-i:2*Math.PI-(i-s)}function u(e,t,i,s,o,u,a,f){var l=r.call(arguments);if(n[l])return n[l];var c=Math.sqrt,h=Math.min,p=Math.max,d=Math.abs,v=[],m=[[],[]],g,y,b,w,E,S,x,T;y=6*e-12*i+6*o,g=-3*e+9*i-9*o+3*a,b=3*i-3*e;for(var N=0;N<2;++N){N>0&&(y=6*t-12*s+6*u,g=-3*t+9*s-9*u+3*f,b=3*s-3*t);if(d(g)<1e-12){if(d(y)<1e-12)continue;w=-b/y,0=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.nodeType===1&&fabric.util.getElementStyle(e,"position")==="fixed"&&(n=e),e.nodeType===1&&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){var n=fabric.document.defaultView.getComputedStyle(e,null);return n?n[t]:undefined}: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"&&typeof console[e].apply=="function"&&(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 eu?u:o;if(o===1&&u===1&&a===0&&f===0)return;h="matrix("+o+" 0"+" 0 "+u+" "+a*o+" "+f*u+")";if(e.tagName==="svg"){p=e.ownerDocument.createElement("g");while(e.firstChild!=null)p.appendChild(e.firstChild);e.appendChild(p)}else p=e,h+=p.getAttribute("transform");p.setAttribute("transform",h)}function S(e){var n=e.objects,i=e.options;return n=n.map(function(e){return t[r(e.type)].fromObject(e)}),{objects:n,options:i}}function x(e,t,n){t[n]&&t[n].toSVG&&e.push('','')}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.cssRules={},t.gradientDefs={},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,n){e[2]=Math.tan(t.util.degreesToRadians(n[0]))}function i(e,n){e[1]=Math.tan(t.util.degreesToRadians(n[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=t.reNum,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 r(e,t){while(e&&(e=e.parentNode))if(t.test(e.nodeName)&&!e.getAttribute("instantiated_by_use"))return!0;return!1}var e=/^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/,n=/^(symbol|image|marker|pattern|view)$/;return function(s,u,a){if(!s)return;b(s);var f=new Date,l=t.Object.__uid++,c=o(s.getAttribute("width")||"100%"),h=o(s.getAttribute("height")||"100%");w(s,c,h);var p=t.util.toArray(s.getElementsByTagName("*"));if(p.length===0&&t.isLikelyNode){p=s.selectNodes('//*[name(.)!="svg"]');var d=[];for(var v=0,m=p.length;v/i,"")));if(!s||!s.documentElement)return;t.parseSVGDocument(s.documentElement,function(r,i){E.set(e,{objects:t.util.array.invoke(r,"toObject"),options:i}),n(r,i)},r)}e=e.replace(/^\n\s*/,"").trim(),E.has(e,function(r){r?E.get(e,function(e){var t=S(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 x(t,e,"backgroundColor"),x(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,this.svgUid=n&&n.svgUid||0},fabric.ElementsParser.prototype.parse=function(){this.instances=new Array(this.elements.length),this.numElements=this.elements.length,this.createObjects()},fabric.ElementsParser.prototype.createObjects=function(){for(var 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+(n1?1:n;if(t){var o=t.split(/\s*;\s*/);o[o.length-1]===""&&o.pop();for(var u=o.length;u--;){var a=o[u].split(/\s*:\s*/),f=a[0].trim(),l=a[1].trim();f==="stop-color"?r=l:f==="stop-opacity"&&(s=l)}}return r||(r=e.getAttribute("stop-color")||"rgb(0,0,0)"),s||(s=e.getAttribute("stop-opacity")),r=new fabric.Color(r),i=r.getAlpha(),s=isNaN(parseFloat(s))?1:parseFloat(s),s*=i,{offset:n,color:r.toRgb(),opacity:s}}function t(e){return{x1:e.getAttribute("x1")||0,y1:e.getAttribute("y1")||0,x2:e.getAttribute("x2")||"100%",y2:e.getAttribute("y2")||0}}function n(e){return{x1:e.getAttribute("fx")||e.getAttribute("cx")||"50%",y1:e.getAttribute("fy")||e.getAttribute("cy")||"50%",r1:0,x2:e.getAttribute("cx")||"50%",y2:e.getAttribute("cy")||"50%",r2:e.getAttribute("r")||"50%"}}function r(e,t,n){var r,i=0,s=1,o="";for(var u in t){r=parseFloat(t[u],10),typeof t[u]=="string"&&/^\d+%$/.test(t[u])?s=.01:s=1;if(u==="x1"||u==="x2"||u==="r2")s*=n==="objectBoundingBox"?e.width:1,i=n==="objectBoundingBox"?e.left||0:0;else if(u==="y1"||u==="y2")s*=n==="objectBoundingBox"?e.height:1,i=n==="objectBoundingBox"?e.top||0:0;t[u]=r*s+i}if(e.type==="ellipse"&&t.r2!==null&&n==="objectBoundingBox"&&e.rx!==e.ry){var a=e.ry/e.rx;o=" scale(1, "+a+")",t.y1&&(t.y1/=a),t.y2&&(t.y2/=a)}return o}fabric.Gradient=fabric.util.createClass({offsetX:0,offsetY:0,initialize:function(e){e||(e={});var t={};this.id=fabric.Object.__uid++,this.type=e.type||"linear",t={x1:e.coords.x1||0,y1:e.coords.y1||0,x2:e.coords.x2||0,y2:e.coords.y2||0},this.type==="radial"&&(t.r1=e.coords.r1||0,t.r2=e.coords.r2||0),this.coords=t,this.colorStops=e.colorStops.slice(),e.gradientTransform&&(this.gradientTransform=e.gradientTransform),this.offsetX=e.offsetX||this.offsetX,this.offsetY=e.offsetY||this.offsetY},addColorStop:function(e){for(var t in e){var n=new fabric.Color(e[t]);this.colorStops.push({offset:t,color:n.toRgb(),opacity:n.getAlpha()})}return this},toObject:function(){return{type:this.type,coords:this.coords,colorStops:this.colorStops,offsetX:this.offsetX,offsetY:this.offsetY}},toSVG:function(e){var t=fabric.util.object.clone(this.coords),n,r;this.colorStops.sort(function(e,t){return e.offset-t.offset});if(!e.group||e.group.type!=="path-group")for(var i in t)if(i==="x1"||i==="x2"||i==="r2")t[i]+=this.offsetX-e.width/2;else if(i==="y1"||i==="y2")t[i]+=this.offsetY-e.height/2;r='id="SVGID_'+this.id+'" gradientUnits="userSpaceOnUse"',this.gradientTransform&&(r+=' gradientTransform="matrix('+this.gradientTransform.join(" ")+')" '),this.type==="linear"?n=["\n']:this.type==="radial"&&(n=["\n']);for(var s=0;s\n');return n.push(this.type==="linear"?"\n":"\n"),n.join("")},toLive:function(e,t){var n,r=fabric.util.object.clone(this.coords);if(!this.type)return;if(t.group&&t.group.type==="path-group")for(var i in r)if(i==="x1"||i==="x2")r[i]+=-this.offsetX+t.width/2;else if(i==="y1"||i==="y2")r[i]+=-this.offsetY+t.height/2;this.type==="linear"?n=e.createLinearGradient(r.x1,r.y1,r.x2,r.y2):this.type==="radial"&&(n=e.createRadialGradient(r.x1,r.y1,r.r1,r.x2,r.y2,r.r2));for(var s=0,o=this.colorStops.length;s\n'+'\n'+"\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",n=40,r=40;return e&&(e.fill===this.color||e.stroke===this.color)&&(t="SourceGraphic"),e.width&&e.height&&(n=Math.abs(this.offsetX/e.getWidth())*100+20,r=Math.abs(this.offsetY/e.getHeight())*100+20),'\n"+' \n'+' \n'+" \n"+" \n"+' \n'+" \n"+"\n"},toObject:function(){if(this.includeDefaultValues)return{color:this.color,blur:this.blur,offsetX:this.offsetX,offsetY:this.offsetY};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,preserveObjectStacking:!1,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,r&&r.crossOrigin):(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,t){return this.setDimensions({width:e},t)},setHeight:function(e,t){return this.setDimensions({height:e},t)},setDimensions:function(e,t){var n;t=t||{};for(var r in e)n=e[r],t.cssOnly||(this._setBackstoreDimension(r,e[r]),n+="px"),t.backstoreOnly||this._setCssDimension(r,n);return t.cssOnly||this.renderAll(),this.calcOffset(),this},_setBackstoreDimension:function(e,t){return this.lowerCanvasEl[e]=t,this.upperCanvasEl&&(this.upperCanvasEl[e]=t),this.cacheCanvasEl&&(this.cacheCanvasEl[e]=t),this[e]=t,this},_setCssDimension:function(e,t){return this.lowerCanvasEl.style[e]=t,this.upperCanvasEl&&(this.upperCanvasEl.style[e]=t),this.wrapperEl&&(this.wrapperEl.style[e]=t),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){var n,r,i;t.viewBox?(n=t.viewBox.width,r=t.viewBox.height):(n=this.width,r=this.height,this.svgViewportTransformation||(i=this.viewportTransform,n/=i[0],r/=i[3])),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(){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%360},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=s.width||0,u=s.height||0,a;if(!o||!u)"top"in s&&"bottom"in s&&(u=Math.abs(s.top-s.bottom)),"right"in s&&"left"in s&&(o=Math.abs(s.right-s.left));return this.calcOffset(),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))),o===0||u===0?a={width:1,height:1}:a={width:r.width/o,height:r.height/u},{x:i.x*a.width,y:i.y*a.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)return;var r=this._groupSelector;r?(n=this.getPointer(e,!0),r.left=n.x-r.ex,r.top=n.y-r.ey,this.renderTop()):this._currentTransform?this._transformObject(e):(t=this.findTarget(e),!t||t&&!t.selectable?this.setCursor(this.defaultCursor):this._setCursorFromEvent(e,t)),this.fire("mouse:move",{target:t,e:e}),t&&t.fire("mousemove",{e:e})},_transformObject:function(e){var t=this.getPointer(e),n=this._currentTransform;n.reset=!1,n.target.isMoving=!0,this._beforeScaleTransform(e,n),this._performTransformAction(e,n,t),this.renderAll()},_performTransformAction:function(e,t,n){var r=n.x,i=n.y,s=t.target,o=t.action;o==="rotate"?(this._rotateObject(r,i),this._fire("rotating",s,e)):o==="scale"?(this._onScale(e,t,r,i),this._fire("scaling",s,e)):o==="scaleX"?(this._scaleObject(r,i,"x"),this._fire("scaling",s,e)):o==="scaleY"?(this._scaleObject(r,i,"y"),this._fire("scaling",s,e)):(this._translateObject(r,i),this._fire("moving",s,e),this.setCursor(this.moveCursor))},_fire:function(e,t,n){this.fire("object:"+e,{target:t,e:n}),t.fire(e,{e:n})},_beforeScaleTransform:function(e,t){if(t.action==="scale"||t.action==="scaleX"||t.action==="scaleY"){var n=this._shouldCenterTransform(e,t.target);if(n&&(t.originX!=="center"||t.originY!=="center")||!n&&t.originX==="center"&&t.originY==="center")this._resetCurrentTransform(e),t.reset=!0}},_onScale:function(e,t,n,r){(e.shiftKey||this.uniScaleTransform)&&!t.target.get("lockUniScaling")?(t.currentAction="scale",this._scaleObject(n,r)):(!t.reset&&t.currentAction==="scale"&&this._resetCurrentTransform(e,t.target),t.currentAction="scaleEqually",this._scaleObject(n,r,"equally"))},_setCursorFromEvent:function(e,t){if(!t||!t.selectable)return this.setCursor(this.defaultCursor),!1;var n=this.getActiveGroup(),r=t._findTargetCorner&&(!n||!n.contains(t))&&t._findTargetCorner(this.getPointer(e,!0));return r?this._setCornerCursor(r,t):this.setCursor(t.hoverCursor||this.hoverCursor),!0},_setCornerCursor:function(t,n){if(t in e)this.setCursor(this._getRotatedCornerCursor(t,n));else{if(t!=="mtr"||!n.hasRotatingPoint)return this.setCursor(this.defaultCursor),!1;this.setCursor(this.rotationCursor)}},_getRotatedCornerCursor:function(t,n){var r=Math.round(n.getAngle()%360/45);return r<0&&(r+=8),r+=e[t],r%=8,this.cursorMap[r]}})}(),function(){var e=Math.min,t=Math.max;fabric.util.object.extend(fabric.Canvas.prototype,{_shouldGroup:function(e,t){var n=this.getActiveObject();return e.shiftKey&&(this.getActiveGroup()||n&&n!==t)&&this.selection},_handleGrouping:function(e,t){if(t===this.getActiveGroup()){t=this.findTarget(e,!0);if(!t||t.isType("group"))return}this.getActiveGroup()?this._updateActiveGroup(t,e):this._createActiveGroup(t,e),this._activeGroup&&this._activeGroup.saveCoords()},_updateActiveGroup:function(e,t){var n=this.getActiveGroup();if(n.contains(e)){n.removeWithUpdate(e),this._resetObjectTransform(n),e.set("active",!1);if(n.size()===1){this.discardActiveGroup(t),this.setActiveObject(n.item(0));return}}else n.addWithUpdate(e),this._resetObjectTransform(n);this.fire("selection:created",{target:n,e:t}),n.set("active",!0)},_createActiveGroup:function(e,t){if(this._activeObject&&e!==this._activeObject){var n=this._createGroup(e);n.addWithUpdate(),this.setActiveGroup(n),this._activeObject=null,this.fire("selection:created",{target:n,e:t})}e.set("active",!0)},_createGroup:function(e){var t=this.getObjects(),n=t.indexOf(this._activeObject)1&&(t=new fabric.Group(t.reverse(),{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:"nonzero",globalCompositeOperation:"source-over",backgroundColor:"",stroke:null,strokeWidth:1,strokeDashArray:null,strokeLineCap:"butt",strokeLineJoin:"miter",strokeMiterLimit:10,shadow:null,borderOpacityWhenMoving:.4,borderScaleFactor:1,transformMatrix:null,minScaleLimit:.01,selectable:!0,evented:!0,visible:!0,hasControls:!0,hasBorders:!0,hasRotatingPoint:!0,rotatingPointOffset:40,perPixelTargetFind:!1,includeDefaultValues:!0,clipTo:null,lockMovementX:!1,lockMovementY:!1,lockRotation:!1,lockScalingX:!1,lockScalingY:!1,lockUniScaling:!1,lockScalingFlip:!1,stateProperties:"top left width height scaleX scaleY flipX flipY originX originY transformMatrix stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit angle opacity fill fillRule globalCompositeOperation shadow clipTo visible backgroundColor".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);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,fillRule:this.fillRule,globalCompositeOperation:this.globalCompositeOperation};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._setupCompositeOperation(e),n||this.transform(e),this._setStrokeStyles(e),this._setFillStyles(e),this.group&&this.group.type==="path-group"&&e.translate(-this.group.width/2,-this.group.height/2),this.transformMatrix&&e.transform.apply(e,this.transformMatrix),this._setOpacity(e),this._setShadow(e),this.clipTo&&t.util.clipContext(this,e),this._render(e,n),this.clipTo&&e.restore(),this._removeShadow(e),this._restoreCompositeOperation(e),e.restore()},_setOpacity:function(e){this.group&&this.group._setOpacity(e),e.globalAlpha*=this.opacity},_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):this.stroke)},_setFillStyles:function(e){this.fill&&(e.fillStyle=this.fill.toLive?this.fill.toLive(e,this):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;var t=this.canvas&&this.canvas._currentMultiplier||1;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur*t*(this.scaleX+this.scaleY)/2,e.shadowOffsetX=this.shadow.offsetX*t*this.scaleX,e.shadowOffsetY=this.shadow.offsetY*t*this.scaleY},_removeShadow:function(e){if(!this.shadow)return;e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0},_renderFill:function(e){if(!this.fill)return;e.save();if(this.fill.gradientTransform){var t=this.fill.gradientTransform;e.transform.apply(e,t)}this.fill.toLive&&e.translate(-this.width/2+this.fill.offsetX||0,-this.height/2+this.fill.offsetY||0),this.fillRule==="evenodd"?e.fill("evenodd"):e.fill(),e.restore(),this.shadow&&!this.shadow.affectStroke&&this._removeShadow(e)},_renderStroke:function(e){if(!this.stroke||this.strokeWidth===0)return;e.save();if(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();else{if(this.stroke.gradientTransform){var t=this.stroke.gradientTransform;e.transform.apply(e,t)}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.StaticCanvas(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}},_setupCompositeOperation:function(e){this.globalCompositeOperation&&(this._prevGlobalCompositeOperation=e.globalCompositeOperation,e.globalCompositeOperation=this.globalCompositeOperation)},_restoreCompositeOperation:function(e){this.globalCompositeOperation&&this._prevGlobalCompositeOperation&&(e.globalCompositeOperation=this._prevGlobalCompositeOperation)}}),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)0?t:-t),d&&(u+=u>0?t:-t),o=s*this.scaleX+2*this.padding,a=u*this.scaleY+2*this.padding,o<0&&(o=Math.abs(o));var v=Math.sqrt(Math.pow(o/2,2)+Math.pow(a/2,2)),m=Math.atan(isFinite(a/o)?a/o:0),g=Math.cos(m+n)*v,y=Math.sin(m+n)*v,b=Math.sin(n),w=Math.cos(n),E=this.getCenterPoint(),S=new fabric.Point(o,a),x=new fabric.Point(E.x-g,E.y-y),T=new fabric.Point(x.x+S.x*w,x.y+S.x*b),N=new fabric.Point(x.x-S.y*b,x.y+S.y*w),C=new fabric.Point(x.x+S.x/2*w,x.y+S.x/2*b),k=i(x),L=i(T),A=i(new fabric.Point(T.x-S.y*b,T.y+S.y*w)),O=i(N),M=i(new fabric.Point(x.x-S.y/2*b,x.y+S.y/2*w)),_=i(C),D=i(new fabric.Point(T.x-S.y/2*b,T.y+S.y/2*w)),P=i(new fabric.Point(N.x+S.x/2*w,N.y+S.x/2*b)),H=i(new fabric.Point(C.x,C.y));return this.oCoords={tl:k,tr:L,br:A,bl:O,ml:M,mt:_,mr:D,mb:P,mtr:H},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.fillRule,n=this.stroke?this.stroke.toLive?"url(#SVGID_"+this.stroke.id+")":this.stroke:"none",r=this.strokeWidth?this.strokeWidth:"0",i=this.strokeDashArray?this.strokeDashArray.join(" "):"",s=this.strokeLineCap?this.strokeLineCap:"butt",o=this.strokeLineJoin?this.strokeLineJoin:"miter",u=this.strokeMiterLimit?this.strokeMiterLimit:"4",a=typeof this.opacity!="undefined"?this.opacity:"1",f=this.visible?"":" visibility: hidden;",l=this.shadow&&this.type!=="text"?"filter: url(#SVGID_"+this.shadow.id+");":"";return["stroke: ",n,"; ","stroke-width: ",r,"; ","stroke-dasharray: ",i,"; ","stroke-linecap: ",s,"; ","stroke-linejoin: ",o,"; ","stroke-miterlimit: ",u,"; ","fill: ",e,"; ","fill-rule: ",t,"; ","opacity: ",a,";",l,f].join("")},getSvgTransform:function(){if(this.group&&this.group.type==="path-group")return"";var e=fabric.util.toFixed,t=this.getAngle(),n=!this.canvas||this.canvas.svgViewportTransformation?this.getViewportTransform():[1,0,0,1,0,0],r=fabric.util.transformPoint(this.getCenterPoint(),n),i=fabric.Object.NUM_FRACTION_DIGITS,s=this.type==="path-group"?"":"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.type==="path-group"?this.width*n[0]:0,f=this.flipX?" matrix(-1 0 0 1 "+a+" 0) ":"",l=this.type==="path-group"?this.height*n[3]:0,c=this.flipY?" matrix(1 0 0 -1 0 "+l+")":"";return[s,o,u,f,c].join("")},getSvgTransformMatrix:function(){return this.transformMatrix?" matrix("+this.transformMatrix.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,f=this.strokeLineCap==="round"||this.strokeLineCap==="square",l=this.type==="line"&&this.width===0,c=this.type==="line"&&this.height===0,h=l||c,p=f&&c||!h,d=f&&l||!h;l?o=a/i:c&&(u=a/s),p&&(o+=a/i),d&&(u+=a/s);var v=fabric.util.transformPoint(new fabric.Point(o,u),r,!0),m=v.x,g=v.y;this.group&&(m*=this.group.scaleX,g*=this.group.scaleY),e.strokeRect(~~(-(m/2)-t)-.5,~~(-(g/2)-t)-.5,~~(m+n)+1,~~(g+n)+1);if(this.hasRotatingPoint&&this.isControlVisible("mtr")&&!this.get("lockRotation")&&this.hasControls){var y=(-g-t*2)/2;e.beginPath(),e.moveTo(0,y),e.lineTo(0,y-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,s=this.width,o=this.height,u=this.strokeLineCap==="round"||this.strokeLineCap==="square",a=this.type==="line"&&this.width===0,f=this.type==="line"&&this.height===0,l=a||f,c=u&&f||!l,h=u&&a||!l;a?s=i:f&&(o=i),c&&(s+=i),h&&(o+=i),s*=this.scaleX,o*=this.scaleY;var p=fabric.util.transformPoint(new fabric.Point(s,o),r,!0),d=p.x,v=p.y,m=-(d/2),g=-(v/2),y=this.padding,b=n,w=n-t,E=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,E,m-b-y,g-b-y),this._drawControl("tr",e,E,m+d-b+y,g-b-y),this._drawControl("bl",e,E,m-b-y,g+v+w+y),this._drawControl("br",e,E,m+d+w+y,g+v+w+y),this.get("lockUniScaling")||(this._drawControl("mt",e,E,m+d/2-b,g-b-y),this._drawControl("mb",e,E,m+d/2-b,g+v+w+y),this._drawControl("mr",e,E,m+d+w+y,g+v/2-b),this._drawControl("ml",e,E,m-b-y,g+v/2-b)),this.hasRotatingPoint&&this._drawControl("mtr",e,E,m+d/2-b,g-this.rotatingPointOffset-this.cornerSize/2-y),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\n'),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,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,startAngle:0,endAngle:n*2,initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("radius",e.radius||0),this.startAngle=e.startAngle||this.startAngle,this.endAngle=e.endAngle||this.endAngle},_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"),startAngle:this.startAngle,endAngle:this.endAngle})},toSVG:function(e){var t=this._createBaseSVGMarkup(),r=0,i=0,s=(this.endAngle-this.startAngle)%(2*n);if(s===0)this.group&&this.group.type==="path-group"&&(r=this.left+this.radius,i=this.top+this.radius),t.push("\n');else{var o=Math.cos(this.startAngle)*this.radius,u=Math.sin(this.startAngle)*this.radius,a=Math.cos(this.endAngle)*this.radius,f=Math.sin(this.endAngle)*this.radius,l=s>n?"1":"0";t.push('\n')}return e?e(t.join("")):t.join("")},_render:function(e,t){e.beginPath(),e.arc(t?this.left+this.radius:0,t?this.top+this.radius:0,this.radius,this.startAngle,this.endAngle,!1),this._renderFill(e),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");s.left=s.left||0,s.top=s.top||0;var o=new t.Circle(r(s,n));return o.left-=o.radius,o.top-=o.radius,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)},_set:function(e,t){this.callSuper("_set",e,t);switch(e){case"rx":this.rx=t,this.set("width",t*2);break;case"ry":this.ry=t,this.set("height",t*2)}return this},getRx:function(){return this.get("rx")*this.get("scaleX")},getRy:function(){return this.get("ry")*this.get("scaleY")},toObject:function(e){return r(this.callSuper("toObject",e),{rx:this.get("rx"),ry:this.get("ry")})},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=0,r=0;return this.group&&this.group.type==="path-group"&&(n=this.left+this.rx,r=this.top+this.ry),t.push("\n'),e?e(t.join("")):t.join("")},_render:function(e,t){e.beginPath(),e.save(),e.transform(1,0,0,this.ry/this.rx,0,0),e.arc(t?this.left+this.rx:0,t?(this.top+this.ry)*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);i.left=i.left||0,i.top=i.top||0;var s=new t.Ellipse(r(i,n));return s.top-=s.ry,s.left-=s.rx,s},t.Ellipse.fromObject=function(e){return new t.Ellipse(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";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,strokeDashArray:null,initialize:function(e){e=e||{},this.callSuper("initialize",e),this._initRxRy()},_initRxRy:function(){this.rx&&!this.ry?this.ry=this.rx:this.ry&&!this.rx&&(this.rx=this.ry)},_render:function(e,t){if(this.width===1&&this.height===1){e.fillRect(0,0,1,1);return}var n=this.rx?Math.min(this.rx,this.width/2):0,r=this.ry?Math.min(this.ry,this.height/2):0,i=this.width,s=this.height,o=t?this.left:-this.width/2,u=t?this.top:-this.height/2,a=n!==0||r!==0,f=.4477152502;e.beginPath(),e.moveTo(o+n,u),e.lineTo(o+i-n,u),a&&e.bezierCurveTo(o+i-f*n,u,o+i,u+f*r,o+i,u+r),e.lineTo(o+i,u+s-r),a&&e.bezierCurveTo(o+i,u+s-f*r,o+i-f*n,u+s,o+i-n,u+s),e.lineTo(o+n,u+s),a&&e.bezierCurveTo(o+f*n,u+s,o,u+s-f*r,o,u+s-r),e.lineTo(o,u+r),a&&e.bezierCurveTo(o,u+f*r,o+f*n,u,o+n,u),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()},toObject:function(e){var t=n(this.callSuper("toObject",e),{rx:this.get("rx")||0,ry:this.get("ry")||0});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=this.left,r=this.top;if(!this.group||this.group.type!=="path-group")n=-this.width/2,r=-this.height/2;return t.push("\n'),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;r=r||{};var i=t.parseAttributes(e,t.Rect.ATTRIBUTE_NAMES);return i.left=i.left||0,i.top=i.top||0,new t.Rect(n(r?t.util.object.clone(r):{},i))},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={});if(t.Polyline){t.warn("fabric.Polyline is already defined");return}t.Polyline=t.util.createClass(t.Object,{type:"polyline",points:null,minX:0,minY:0,initialize:function(e,n){return t.Polygon.prototype.initialize.call(this,e,n)},_calcDimensions:function(){return t.Polygon.prototype._calcDimensions.call(this)},_applyPointOffset:function(){return t.Polygon.prototype._applyPointOffset.call(this)},toObject:function(e){return t.Polygon.prototype.toObject.call(this,e)},toSVG:function(e){return t.Polygon.prototype.toSVG.call(this,e)},_render:function(e){t.Polygon.prototype.commonRender.call(this,e),this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n,r;e.beginPath();for(var i=0,s=this.points.length;i\n'),e?e(n.join("")):n.join("")},_render:function(e){this.commonRender(e),this._renderFill(e);if(this.stroke||this.strokeDashArray)e.closePath(),this._renderStroke(e)},commonRender:function(e){var t;e.beginPath(),this._applyPointOffset&&((!this.group||this.group.type!=="path-group")&&this._applyPointOffset(),this._applyPointOffset=null),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(),r="";for(var i=0,s=this.path.length;i\n"),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\n"];for(var i=0,s=t.length;i\n"),e?e(r.join("")):r.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 n=this._objects.length;n--;)this._objects[n].group=this;this.originalState={},this.callSuper("initialize"),t.originX&&(this.originX=t.originX),t.originY&&(this.originY=t.originY),this._calcBounds(),this._updateObjectsCoords(),this.callSuper("initialize",t),this.setCoords(),this.saveCoords()},_updateObjectsCoords:function(){this.forEachObject(this._updateObjectCoords,this)},_updateObjectCoords:function(e){var t=e.getLeft(),n=e.getTop(),r=this.getCenterPoint();e.set({originalLeft:t,originalTop:n,left:t-r.x,top:n-r.y}),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;while(n--)this._objects[n].set(e,t)}this.callSuper("_set",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\n'];for(var n=0,r=this._objects.length;n\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\n','\n");if(this.stroke||this.strokeDashArray){var s=this.fill;this.fill=null,t.push("\n'),this.fill=s}return t.push("
\n"),e?e(t.join("")):t.join("")},getSrc:function(){if(this.getElement())return this.getElement().src||this.getElement()._src},setSrc:function(e,t,n){fabric.util.loadImage(e,function(e){return this.setElement(e,t,n)},this,n&&n.crossOrigin)},toString:function(){return'#'},clone:function(e,t){this.constructor.fromObject(this.toObject(t),e)},applyFilters:function(e,t,n,r){t=t||this.filters,n=n||this._originalElement;if(!n)return;var i=n,s=fabric.util.createCanvasElement(),o=fabric.util.createImage(),u=this;return s.width=i.width,s.height=i.height,s.getContext("2d").drawImage(i,0,0,i.width,i.height),t.length===0?(this._element=n,e&&e(),s):(t.forEach(function(e){e&&e.applyTo(s,e.scaleX||u.scaleX,e.scaleY||u.scaleY),!r&&e.type==="Resize"&&(u.width*=e.scaleX,u.height*=e.scaleY)}),o.width=s.width,o.height=s.height,fabric.isLikelyNode?(o.src=s.toBuffer(undefined,fabric.Image.pngCompression),u._element=o,!r&&(u._filteredEl=o),e&&e()):(o.onload=function(){u._element=o,!r&&(u._filteredEl=o),e&&e(),o.onload=s=i=null},o.src=s.toDataURL("image/png")),s)},_render:function(e,t){var n,r,i=this._findMargins(),s;n=t?this.left:-this.width/2,r=t?this.top:-this.height/2,this.meetOrSlice==="slice"&&(e.beginPath(),e.rect(n,r,this.width,this.height),e.clip()),this.isMoving===!1&&this.resizeFilters.length&&this._needsResize()?(this._lastScaleX=this.scaleX,this._lastScaleY=this.scaleY,s=this.applyFilters(null,this.resizeFilters,this._filteredEl||this._originalElement,!0)):s=this._element,s&&e.drawImage(s,n+i.marginX,r+i.marginY,i.width,i.height),this._renderStroke(e)},_needsResize:function(){return this.scaleX!==this._lastScaleX||this.scaleY!==this._lastScaleY},_findMargins:function(){var e=this.width,t=this.height,n,r,i=0,s=0;if(this.alignX!=="none"||this.alignY!=="none")n=[this.width/this._element.width,this.height/this._element.height],r=this.meetOrSlice==="meet"?Math.min.apply(null,n):Math.max.apply(null,n),e=this._element.width*r,t=this._element.height*r,this.alignX==="Mid"&&(i=(this.width-e)/2),this.alignX==="Max"&&(i=this.width-e),this.alignY==="Mid"&&(s=(this.height-t)/2),this.alignY==="Max"&&(s=this.height-t);return{width:e,height:t,marginX:i,marginY:s}},_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 preserveAspectRatio xlink:href".split(" ")),fabric.Image.fromElement=function(e,n,r){var i=fabric.parseAttributes(e,fabric.Image.ATTRIBUTE_NAMES),s="xMidYMid",o="meet",u,a,f;i.preserveAspectRatio&&(f=i.preserveAspectRatio.split(" ")),f&&f.length&&(o=f.pop(),o!=="meet"&&o!=="slice"?(s=o,o="meet"):f.length&&(s=f.pop())),u=s!=="none"?s.slice(1,4):"none",a=s!=="none"?s.slice(5,8):"none",i.alignX=u,i.alignY=a,i.meetOrSlice=o,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",initialize:function(e){e&&this.setOptions(e)},setOptions:function(e){for(var t in e)this[t]=e[t]},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)n&&(l=2,h=-1),u>i&&(c=2,p=-1),f=a.getImageData(0,0,n,i),e.width=o(s,n),e.height=o(u,i),a.putImageData(f,0,0);while(!d||!v)n=m,i=g,s*he)return 0;t*=Math.PI;if(s(t)<1e-16)return 1;var n=t/e;return a(t)*a(n)/t/n}}function h(e){var a,f,c,p,d,L,A,O,M,_,D;C.x=(e+.5)*b,k.x=r(C.x);for(a=0;a=t)continue;_=r(1e3*s(f-C.x)),N[_]||(N[_]={});for(var P=k.y-T;P<=k.y+T;P++){if(P<0||P>=o)continue;D=r(1e3*s(P-C.y)),N[_][D]||(N[_][D]=y(i(n(_*E,2)+n(D*S,2))/1e3)),c=N[_][D],c>0&&(p=(P*t+f)*4,d+=c,L+=c*m[p],A+=c*m[p+1],O+=c*m[p+2],M+=c*m[p+3])}}p=(a*u+e)*4,g[p]=L/d,g[p+1]=A/d,g[p+2]=O/d,g[p+3]=M/d}return++e1&&H<-1)continue;E=2*H*H*H-3*H*H+1,E>0&&(P=4*(D+A*t),k+=E*v[P+3],x+=E,v[P+3]<255&&(E=E*v[P+3]/250),T+=E*v[P],N+=E*v[P+1],C+=E*v[P+2],S+=E)}}g[w]=T/S,g[w+1]=N/S,g[w+2]=C/S,g[w+3]=k/x}return m}}),t.Image.filters.Resize.fromObject=function(){return new t.Image.filters.Resize}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.object.clone,i=t.util.toFixed,s=t.StaticCanvas.supports("setLineDash");if(t.Text){t.warn("fabric.Text is already defined");return}var o=t.Object.prototype.stateProperties.concat();o.push("fontFamily","fontWeight","fontSize","text","textDecoration","textAlign","fontStyle","lineHeight","textBackgroundColor","useNative","path"),t.Text=t.util.createClass(t.Object,{_dimensionAffectingProps:{fontSize:!0,fontWeight:!0,fontFamily:!0,textDecoration:!0,fontStyle:!0,lineHeight:!0,stroke:!0,strokeWidth:!0,text:!0},_reNewline:/\r?\n/,type:"text",fontSize:40,fontWeight:"normal",fontFamily:"Times New Roman",textDecoration:"",textAlign:"left",fontStyle:"",lineHeight:1.3,textBackgroundColor:"",path:null,useNative:!0,stateProperties:o,stroke:null,shadow:null,initialize:function(e,t){t=t||{},this.text=e,this.__skipDimension=!0,this.setOptions(t),this.__skipDimension=!1,this._initDimensions()},_initDimensions:function(){if(this.__skipDimension)return;var e=t.util.createCanvasElement();this._render(e.getContext("2d"))},toString:function(){return"#'},_render:function(e){typeof Cufon=="undefined"||this.useNative===!0?this._renderViaNative(e):this._renderViaCufon(e)},_renderViaNative:function(e){var n=this.text.split(this._reNewline);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._setOpacity(e),this._setShadow(e),this._setupCompositeOperation(e),this._renderTextFill(e,t),this._renderTextStroke(e,t),this._restoreCompositeOperation(e),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,t){if(!this.visible)return;e.save(),t||this.transform(e);var n=this.group&&this.group.type==="path-group";n&&e.translate(-this.group.width/2,-this.group.height/2),this.transformMatrix&&e.transform.apply(e,this.transformMatrix),n&&e.translate(this.left,this.top),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*this.lineHeight-.25*this.fontSize:this.height/2-e.length*this.fontSize-this._totalLineHeight;return{textLeft:n+(this.group&&this.group.type==="path-group"?this.left:0),textTop:r+(this.group&&this.group.type==="path-group"?this.top:0),lineTop:t}},_wrapSVGTextAndBg:function(e,t,n,r){e.push('\n',t.textBgRects.join(""),"',n.join(""),t.textSpans.join(""),"\n","\n")},_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("\n')},_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),n.top=n.top||0,n.left=n.left||0,"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="left"),n.top+=n.fontSize/4;var i=new t.Text(e.textContent,n),s=0;return i.originX==="left"&&(s=i.getWidth()/2),i.originX==="right"&&(s=-i.getWidth()/2),i.set({left:i.getLeft()+s,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){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?ts?0:1,a=r+u;return this.flipX&&(a=i-a),a>this.text.length&&(a=this.text.length),a}}),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: fixed; bottom: 20px; left: 0px; opacity: 0; width: 0px; height: 0px; z-index: -999;",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",9:"exitEditing",27:"exitEditing",13:"insertNewline",33:"moveCursorUp",34:"moveCursorDown",35:"moveCursorRight",36:"moveCursorLeft",37:"moveCursorLeft",38:"moveCursorUp",39:"moveCursorRight",40:"moveCursorDown",46:"forwardDelete"},_ctrlKeysMap:{65:"selectAll",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.stopImmediatePropagation(),e.preventDefault(),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)return;e.which!==0&&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||e.keyCode===34)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,this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})},swapSelectionPoints:function(){var e=this.selectionEnd;this.selectionEnd=this.selectionStart,this.selectionStart=e},moveCursorDownWithShift:function(e){this.selectionEnd===this.selectionStart&&(this._selectionDirection="right");var t=this._selectionDirection==="right"?"selectionEnd":"selectionStart";this[t]+=e,this.selectionEndthis.text.length&&(this.selectionEnd=this.text.length),this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})},getUpCursorOffset:function(e,t){var n=t?this.selectionEnd:this.selectionStart,r=this.get2DCursorLocation(n);if(r.lineIndex===0||e.metaKey||e.keyCode===33)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)),this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})},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),this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})},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,t){return origSetWidth.call(this,e,t),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,t){return origSetHeight.call(this,e,t),this.nodeCanvas.height=e,this},fabric.Canvas&&(fabric.Canvas.prototype.setHeight=fabric.StaticCanvas.prototype.setHeight)}(); \ No newline at end of file +e.getAttribute("font-size")||t.Text.DEFAULT_SVG_FONT_SIZE;var a=r.reduce(function(t,n){return s=e.getAttribute(n),s&&(n=l(n),s=c(n,s,o,u),t[n]=s),t},{});return a=n(a,n(v(e,i),t.parseStyleAttribute(e))),a.font&&t.parseFontDeclaration(a.font,a),h(n(o,a))},parseElements:function(e,n,r,i){(new t.ElementsParser(e,n,r,i)).parse()},parseStyleAttribute:function(e){var t={},n=e.getAttribute("style");return n?(typeof n=="string"?p(n,t):d(n,t),t):t},parsePointsAttribute:function(e){if(!e)return null;e=e.replace(/,/g," ").trim(),e=e.split(/\s+/);var t=[],n,r;n=0,r=e.length;for(;n/i,"")));if(!s||!s.documentElement)return;t.parseSVGDocument(s.documentElement,function(r,i){E.set(e,{objects:t.util.array.invoke(r,"toObject"),options:i}),n(r,i)},r)}e=e.replace(/^\n\s*/,"").trim(),E.has(e,function(r){r?E.get(e,function(e){var t=S(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 x(t,e,"backgroundColor"),x(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,this.svgUid=n&&n.svgUid||0},fabric.ElementsParser.prototype.parse=function(){this.instances=new Array(this.elements.length),this.numElements=this.elements.length,this.createObjects()},fabric.ElementsParser.prototype.createObjects=function(){for(var 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+(n1?1:n;if(t){var o=t.split(/\s*;\s*/);o[o.length-1]===""&&o.pop();for(var u=o.length;u--;){var a=o[u].split(/\s*:\s*/),f=a[0].trim(),l=a[1].trim();f==="stop-color"?r=l:f==="stop-opacity"&&(s=l)}}return r||(r=e.getAttribute("stop-color")||"rgb(0,0,0)"),s||(s=e.getAttribute("stop-opacity")),r=new fabric.Color(r),i=r.getAlpha(),s=isNaN(parseFloat(s))?1:parseFloat(s),s*=i,{offset:n,color:r.toRgb(),opacity:s}}function t(e){return{x1:e.getAttribute("x1")||0,y1:e.getAttribute("y1")||0,x2:e.getAttribute("x2")||"100%",y2:e.getAttribute("y2")||0}}function n(e){return{x1:e.getAttribute("fx")||e.getAttribute("cx")||"50%",y1:e.getAttribute("fy")||e.getAttribute("cy")||"50%",r1:0,x2:e.getAttribute("cx")||"50%",y2:e.getAttribute("cy")||"50%",r2:e.getAttribute("r")||"50%"}}function r(e,t,n){var r,i=0,s=1,o="";for(var u in t){r=parseFloat(t[u],10),typeof t[u]=="string"&&/^\d+%$/.test(t[u])?s=.01:s=1;if(u==="x1"||u==="x2"||u==="r2")s*=n==="objectBoundingBox"?e.width:1,i=n==="objectBoundingBox"?e.left||0:0;else if(u==="y1"||u==="y2")s*=n==="objectBoundingBox"?e.height:1,i=n==="objectBoundingBox"?e.top||0:0;t[u]=r*s+i}if(e.type==="ellipse"&&t.r2!==null&&n==="objectBoundingBox"&&e.rx!==e.ry){var a=e.ry/e.rx;o=" scale(1, "+a+")",t.y1&&(t.y1/=a),t.y2&&(t.y2/=a)}return o}fabric.Gradient=fabric.util.createClass({offsetX:0,offsetY:0,initialize:function(e){e||(e={});var t={};this.id=fabric.Object.__uid++,this.type=e.type||"linear",t={x1:e.coords.x1||0,y1:e.coords.y1||0,x2:e.coords.x2||0,y2:e.coords.y2||0},this.type==="radial"&&(t.r1=e.coords.r1||0,t.r2=e.coords.r2||0),this.coords=t,this.colorStops=e.colorStops.slice(),e.gradientTransform&&(this.gradientTransform=e.gradientTransform),this.offsetX=e.offsetX||this.offsetX,this.offsetY=e.offsetY||this.offsetY},addColorStop:function(e){for(var t in e){var n=new fabric.Color(e[t]);this.colorStops.push({offset:t,color:n.toRgb(),opacity:n.getAlpha()})}return this},toObject:function(){return{type:this.type,coords:this.coords,colorStops:this.colorStops,offsetX:this.offsetX,offsetY:this.offsetY}},toSVG:function(e){var t=fabric.util.object.clone(this.coords),n,r;this.colorStops.sort(function(e,t){return e.offset-t.offset});if(!e.group||e.group.type!=="path-group")for(var i in t)if(i==="x1"||i==="x2"||i==="r2")t[i]+=this.offsetX-e.width/2;else if(i==="y1"||i==="y2")t[i]+=this.offsetY-e.height/2;r='id="SVGID_'+this.id+'" gradientUnits="userSpaceOnUse"',this.gradientTransform&&(r+=' gradientTransform="matrix('+this.gradientTransform.join(" ")+')" '),this.type==="linear"?n=["\n']:this.type==="radial"&&(n=["\n']);for(var s=0;s\n');return n.push(this.type==="linear"?"\n":"\n"),n.join("")},toLive:function(e,t){var n,r,i=fabric.util.object.clone(this.coords);if(!this.type)return;if(t.group&&t.group.type==="path-group")for(r in i)if(r==="x1"||r==="x2")i[r]+=-this.offsetX+t.width/2;else if(r==="y1"||r==="y2")i[r]+=-this.offsetY+t.height/2;if(t.type==="text")for(r in i)if(r==="x1"||r==="x2")i[r]-=t.width/2;else if(r==="y1"||r==="y2")i[r]-=t.height/2;this.type==="linear"?n=e.createLinearGradient(i.x1,i.y1,i.x2,i.y2):this.type==="radial"&&(n=e.createRadialGradient(i.x1,i.y1,i.r1,i.x2,i.y2,i.r2));for(var s=0,o=this.colorStops.length;s\n'+'\n'+"\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={}),n=t.util.toFixed;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",r=40,i=40;return e&&(e.fill===this.color||e.stroke===this.color)&&(t="SourceGraphic"),e.width&&e.height&&(r=n(Math.abs(this.offsetX/e.getWidth()),2)*100+20,i=n(Math.abs(this.offsetY/e.getHeight()),2)*100+20),'\n"+' \n'+' \n'+' \n'+" \n"+" \n"+' \n'+" \n"+"\n"},toObject:function(){if(this.includeDefaultValues)return{color:this.color,blur:this.blur,offsetX:this.offsetX,offsetY:this.offsetY};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,preserveObjectStacking:!1,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,r&&r.crossOrigin):(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,t){return this.setDimensions({width:e},t)},setHeight:function(e,t){return this.setDimensions({height:e},t)},setDimensions:function(e,t){var n;t=t||{};for(var r in e)n=e[r],t.cssOnly||(this._setBackstoreDimension(r,e[r]),n+="px"),t.backstoreOnly||this._setCssDimension(r,n);return t.cssOnly||this.renderAll(),this.calcOffset(),this},_setBackstoreDimension:function(e,t){return this.lowerCanvasEl[e]=t,this.upperCanvasEl&&(this.upperCanvasEl[e]=t),this.cacheCanvasEl&&(this.cacheCanvasEl[e]=t),this[e]=t,this},_setCssDimension:function(e,t){return this.lowerCanvasEl.style[e]=t,this.upperCanvasEl&&(this.upperCanvasEl.style[e]=t),this.wrapperEl&&(this.wrapperEl.style[e]=t),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){var n,r,i;t.viewBox?(n=t.viewBox.width,r=t.viewBox.height):(n=this.width,r=this.height,this.svgViewportTransformation||(i=this.viewportTransform,n/=i[0],r/=i[3])),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",strokeDashArray:null,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,e.setLineDash(this.strokeDashArray)},_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(){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%360},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=s.width||0,u=s.height||0,a;if(!o||!u)"top"in s&&"bottom"in s&&(u=Math.abs(s.top-s.bottom)),"right"in s&&"left"in s&&(o=Math.abs(s.right-s.left));return this.calcOffset(),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))),o===0||u===0?a={width:1,height:1}:a={width:r.width/o,height:r.height/u},{x:i.x*a.width,y:i.y*a.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)return;var r=this._groupSelector;r?(n=this.getPointer(e,!0),r.left=n.x-r.ex,r.top=n.y-r.ey,this.renderTop()):this._currentTransform?this._transformObject(e):(t=this.findTarget(e),!t||t&&!t.selectable?this.setCursor(this.defaultCursor):this._setCursorFromEvent(e,t)),this.fire("mouse:move",{target:t,e:e}),t&&t.fire("mousemove",{e:e})},_transformObject:function(e){var t=this.getPointer(e),n=this._currentTransform;n.reset=!1,n.target.isMoving=!0,this._beforeScaleTransform(e,n),this._performTransformAction(e,n,t),this.renderAll()},_performTransformAction:function(e,t,n){var r=n.x,i=n.y,s=t.target,o=t.action;o==="rotate"?(this._rotateObject(r,i),this._fire("rotating",s,e)):o==="scale"?(this._onScale(e,t,r,i),this._fire("scaling",s,e)):o==="scaleX"?(this._scaleObject(r,i,"x"),this._fire("scaling",s,e)):o==="scaleY"?(this._scaleObject(r,i,"y"),this._fire("scaling",s,e)):(this._translateObject(r,i),this._fire("moving",s,e),this.setCursor(this.moveCursor))},_fire:function(e,t,n){this.fire("object:"+e,{target:t,e:n}),t.fire(e,{e:n})},_beforeScaleTransform:function(e,t){if(t.action==="scale"||t.action==="scaleX"||t.action==="scaleY"){var n=this._shouldCenterTransform(e,t.target);if(n&&(t.originX!=="center"||t.originY!=="center")||!n&&t.originX==="center"&&t.originY==="center")this._resetCurrentTransform(e),t.reset=!0}},_onScale:function(e,t,n,r){(e.shiftKey||this.uniScaleTransform)&&!t.target.get("lockUniScaling")?(t.currentAction="scale",this._scaleObject(n,r)):(!t.reset&&t.currentAction==="scale"&&this._resetCurrentTransform(e,t.target),t.currentAction="scaleEqually",this._scaleObject(n,r,"equally"))},_setCursorFromEvent:function(e,t){if(!t||!t.selectable)return this.setCursor(this.defaultCursor),!1;var n=this.getActiveGroup(),r=t._findTargetCorner&&(!n||!n.contains(t))&&t._findTargetCorner(this.getPointer(e,!0));return r?this._setCornerCursor(r,t):this.setCursor(t.hoverCursor||this.hoverCursor),!0},_setCornerCursor:function(t,n){if(t in e)this.setCursor(this._getRotatedCornerCursor(t,n));else{if(t!=="mtr"||!n.hasRotatingPoint)return this.setCursor(this.defaultCursor),!1;this.setCursor(this.rotationCursor)}},_getRotatedCornerCursor:function(t,n){var r=Math.round(n.getAngle()%360/45);return r<0&&(r+=8),r+=e[t],r%=8,this.cursorMap[r]}})}(),function(){var e=Math.min,t=Math.max;fabric.util.object.extend(fabric.Canvas.prototype,{_shouldGroup:function(e,t){var n=this.getActiveObject();return e.shiftKey&&(this.getActiveGroup()||n&&n!==t)&&this.selection},_handleGrouping:function(e,t){if(t===this.getActiveGroup()){t=this.findTarget(e,!0);if(!t||t.isType("group"))return}this.getActiveGroup()?this._updateActiveGroup(t,e):this._createActiveGroup(t,e),this._activeGroup&&this._activeGroup.saveCoords()},_updateActiveGroup:function(e,t){var n=this.getActiveGroup();if(n.contains(e)){n.removeWithUpdate(e),this._resetObjectTransform(n),e.set("active",!1);if(n.size()===1){this.discardActiveGroup(t),this.setActiveObject(n.item(0));return}}else n.addWithUpdate(e),this._resetObjectTransform(n);this.fire("selection:created",{target:n,e:t}),n.set("active",!0)},_createActiveGroup:function(e,t){if(this._activeObject&&e!==this._activeObject){var n=this._createGroup(e);n.addWithUpdate(),this.setActiveGroup(n),this._activeObject=null,this.fire("selection:created",{target:n,e:t})}e.set("active",!0)},_createGroup:function(e){var t=this.getObjects(),n=t.indexOf(this._activeObject)1&&(t=new fabric.Group(t.reverse(),{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:"nonzero",globalCompositeOperation:"source-over",backgroundColor:"",stroke:null,strokeWidth:1,strokeDashArray:null,strokeLineCap:"butt",strokeLineJoin:"miter",strokeMiterLimit:10,shadow:null,borderOpacityWhenMoving:.4,borderScaleFactor:1,transformMatrix:null,minScaleLimit:.01,selectable:!0,evented:!0,visible:!0,hasControls:!0,hasBorders:!0,hasRotatingPoint:!0,rotatingPointOffset:40,perPixelTargetFind:!1,includeDefaultValues:!0,clipTo:null,lockMovementX:!1,lockMovementY:!1,lockRotation:!1,lockScalingX:!1,lockScalingY:!1,lockUniScaling:!1,lockScalingFlip:!1,stateProperties:"top left width height scaleX scaleY flipX flipY originX originY transformMatrix stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit angle opacity fill fillRule globalCompositeOperation shadow clipTo visible backgroundColor".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);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,fillRule:this.fillRule,globalCompositeOperation:this.globalCompositeOperation};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._setupCompositeOperation(e),n||this.transform(e),this._setStrokeStyles(e),this._setFillStyles(e),this.group&&this.group.type==="path-group"&&e.translate(-this.group.width/2,-this.group.height/2),this.transformMatrix&&e.transform.apply(e,this.transformMatrix),this._setOpacity(e),this._setShadow(e),this.clipTo&&t.util.clipContext(this,e),this._render(e,n),this.clipTo&&e.restore(),this._removeShadow(e),this._restoreCompositeOperation(e),e.restore()},_setOpacity:function(e){this.group&&this.group._setOpacity(e),e.globalAlpha*=this.opacity},_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):this.stroke)},_setFillStyles:function(e){this.fill&&(e.fillStyle=this.fill.toLive?this.fill.toLive(e,this):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;var t=this.canvas&&this.canvas._currentMultiplier||1;e.shadowColor=this.shadow.color,e.shadowBlur=this.shadow.blur*t*(this.scaleX+this.scaleY)/2,e.shadowOffsetX=this.shadow.offsetX*t*this.scaleX,e.shadowOffsetY=this.shadow.offsetY*t*this.scaleY},_removeShadow:function(e){if(!this.shadow)return;e.shadowColor="",e.shadowBlur=e.shadowOffsetX=e.shadowOffsetY=0},_renderFill:function(e){if(!this.fill)return;e.save();if(this.fill.gradientTransform){var t=this.fill.gradientTransform;e.transform.apply(e,t)}this.fill.toLive&&e.translate(-this.width/2+this.fill.offsetX||0,-this.height/2+this.fill.offsetY||0),this.fillRule==="evenodd"?e.fill("evenodd"):e.fill(),e.restore(),this.shadow&&!this.shadow.affectStroke&&this._removeShadow(e)},_renderStroke:function(e){if(!this.stroke||this.strokeWidth===0)return;e.save();if(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();else{if(this.stroke.gradientTransform){var t=this.stroke.gradientTransform;e.transform.apply(e,t)}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.StaticCanvas(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}},_setupCompositeOperation:function(e){this.globalCompositeOperation&&(this._prevGlobalCompositeOperation=e.globalCompositeOperation,e.globalCompositeOperation=this.globalCompositeOperation)},_restoreCompositeOperation:function(e){this.globalCompositeOperation&&this._prevGlobalCompositeOperation&&(e.globalCompositeOperation=this._prevGlobalCompositeOperation)}}),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)\n'),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,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,startAngle:0,endAngle:n*2,initialize:function(e){e=e||{},this.callSuper("initialize",e),this.set("radius",e.radius||0),this.startAngle=e.startAngle||this.startAngle,this.endAngle=e.endAngle||this.endAngle},_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"),startAngle:this.startAngle,endAngle:this.endAngle})},toSVG:function(e){var t=this._createBaseSVGMarkup(),r=0,i=0,s=(this.endAngle-this.startAngle)%(2*n);if(s===0)this.group&&this.group.type==="path-group"&&(r=this.left+this.radius,i=this.top+this.radius),t.push("\n');else{var o=Math.cos(this.startAngle)*this.radius,u=Math.sin(this.startAngle)*this.radius,a=Math.cos(this.endAngle)*this.radius,f=Math.sin(this.endAngle)*this.radius,l=s>n?"1":"0";t.push('\n')}return e?e(t.join("")):t.join("")},_render:function(e,t){e.beginPath(),e.arc(t?this.left+this.radius:0,t?this.top+this.radius:0,this.radius,this.startAngle,this.endAngle,!1),this._renderFill(e),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");s.left=s.left||0,s.top=s.top||0;var o=new t.Circle(r(s,n));return o.left-=o.radius,o.top-=o.radius,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)},_set:function(e,t){this.callSuper("_set",e,t);switch(e){case"rx":this.rx=t,this.set("width",t*2);break;case"ry":this.ry=t,this.set("height",t*2)}return this},getRx:function(){return this.get("rx")*this.get("scaleX")},getRy:function(){return this.get("ry")*this.get("scaleY")},toObject:function(e){return r(this.callSuper("toObject",e),{rx:this.get("rx"),ry:this.get("ry")})},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=0,r=0;return this.group&&this.group.type==="path-group"&&(n=this.left+this.rx,r=this.top+this.ry),t.push("\n'),e?e(t.join("")):t.join("")},_render:function(e,t){e.beginPath(),e.save(),e.transform(1,0,0,this.ry/this.rx,0,0),e.arc(t?this.left+this.rx:0,t?(this.top+this.ry)*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);i.left=i.left||0,i.top=i.top||0;var s=new t.Ellipse(r(i,n));return s.top-=s.ry,s.left-=s.rx,s},t.Ellipse.fromObject=function(e){return new t.Ellipse(e)}}(typeof exports!="undefined"?exports:this),function(e){"use strict";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,strokeDashArray:null,initialize:function(e){e=e||{},this.callSuper("initialize",e),this._initRxRy()},_initRxRy:function(){this.rx&&!this.ry?this.ry=this.rx:this.ry&&!this.rx&&(this.rx=this.ry)},_render:function(e,t){if(this.width===1&&this.height===1){e.fillRect(0,0,1,1);return}var n=this.rx?Math.min(this.rx,this.width/2):0,r=this.ry?Math.min(this.ry,this.height/2):0,i=this.width,s=this.height,o=t?this.left:-this.width/2,u=t?this.top:-this.height/2,a=n!==0||r!==0,f=.4477152502;e.beginPath(),e.moveTo(o+n,u),e.lineTo(o+i-n,u),a&&e.bezierCurveTo(o+i-f*n,u,o+i,u+f*r,o+i,u+r),e.lineTo(o+i,u+s-r),a&&e.bezierCurveTo(o+i,u+s-f*r,o+i-f*n,u+s,o+i-n,u+s),e.lineTo(o+n,u+s),a&&e.bezierCurveTo(o+f*n,u+s,o,u+s-f*r,o,u+s-r),e.lineTo(o,u+r),a&&e.bezierCurveTo(o,u+f*r,o+f*n,u,o+n,u),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()},toObject:function(e){var t=n(this.callSuper("toObject",e),{rx:this.get("rx")||0,ry:this.get("ry")||0});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=this.left,r=this.top;if(!this.group||this.group.type!=="path-group")n=-this.width/2,r=-this.height/2;return t.push("\n'),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;r=r||{};var i=t.parseAttributes(e,t.Rect.ATTRIBUTE_NAMES);i.left=i.left||0,i.top=i.top||0;var s=new t.Rect(n(r?t.util.object.clone(r):{},i));return s.visible=s.width>0&&s.height>0,s},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={});if(t.Polyline){t.warn("fabric.Polyline is already defined");return}t.Polyline=t.util.createClass(t.Object,{type:"polyline",points:null,minX:0,minY:0,initialize:function(e,n){return t.Polygon.prototype.initialize.call(this,e,n)},_calcDimensions:function(){return t.Polygon.prototype._calcDimensions.call(this)},_applyPointOffset:function(){return t.Polygon.prototype._applyPointOffset.call(this)},toObject:function(e){return t.Polygon.prototype.toObject.call(this,e)},toSVG:function(e){return t.Polygon.prototype.toSVG.call(this,e)},_render:function(e){if(!t.Polygon.prototype.commonRender.call(this,e))return;this._renderFill(e),this._renderStroke(e)},_renderDashedStroke:function(e){var n,r;e.beginPath();for(var i=0,s=this.points.length;i\n'),e?e(n.join("")):n.join("")},_render:function(e){if(!this.commonRender(e))return;this._renderFill(e);if(this.stroke||this.strokeDashArray)e.closePath(),this._renderStroke(e)},commonRender:function(e){var t,n=this.points.length;if(!n||isNaN(this.points[n-1].y))return!1;e.beginPath(),this._applyPointOffset&&((!this.group||this.group.type!=="path-group")&&this._applyPointOffset(),this._applyPointOffset=null),e.moveTo(this.points[0].x,this.points[0].y);for(var r=0;r"},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(),r="";for(var i=0,s=this.path.length;i\n"),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\n"];for(var i=0,s=t.length;i\n"),e?e(r.join("")):r.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 n=this._objects.length;n--;)this._objects[n].group=this;this.originalState={},this.callSuper("initialize"),t.originX&&(this.originX=t.originX),t.originY&&(this.originY=t.originY),this._calcBounds(),this._updateObjectsCoords(),this.callSuper("initialize",t),this.setCoords(),this.saveCoords()},_updateObjectsCoords:function(){this.forEachObject(this._updateObjectCoords,this)},_updateObjectCoords:function(e){var t=e.getLeft(),n=e.getTop(),r=this.getCenterPoint();e.set({originalLeft:t,originalTop:n,left:t-r.x,top:n-r.y}),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;while(n--)this._objects[n].set(e,t)}this.callSuper("_set",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\n'];for(var n=0,r=this._objects.length;n\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\n','\n");if(this.stroke||this.strokeDashArray){var s=this.fill;this.fill=null,t.push("\n'),this.fill=s}return t.push("\n"),e?e(t.join("")):t.join("")},getSrc:function(){if(this.getElement())return this.getElement().src||this.getElement()._src},setSrc:function(e,t,n){fabric.util.loadImage(e,function(e){return this.setElement(e,t,n)},this,n&&n.crossOrigin)},toString:function(){return'#'},clone:function(e,t){this.constructor.fromObject(this.toObject(t),e)},applyFilters:function(e,t,n,r){t=t||this.filters,n=n||this._originalElement;if(!n)return;var i=n,s=fabric.util.createCanvasElement(),o=fabric.util.createImage(),u=this;return s.width=i.width,s.height=i.height,s.getContext("2d").drawImage(i,0,0,i.width,i.height),t.length===0?(this._element=n,e&&e(),s):(t.forEach(function(e){e&&e.applyTo(s,e.scaleX||u.scaleX,e.scaleY||u.scaleY),!r&&e.type==="Resize"&&(u.width*=e.scaleX,u.height*=e.scaleY)}),o.width=s.width,o.height=s.height,fabric.isLikelyNode?(o.src=s.toBuffer(undefined,fabric.Image.pngCompression),u._element=o,!r&&(u._filteredEl=o),e&&e()):(o.onload=function(){u._element=o,!r&&(u._filteredEl=o),e&&e(),o.onload=s=i=null},o.src=s.toDataURL("image/png")),s)},_render:function(e,t){var n,r,i=this._findMargins(),s;n=t?this.left:-this.width/2,r=t?this.top:-this.height/2,this.meetOrSlice==="slice"&&(e.beginPath(),e.rect(n,r,this.width,this.height),e.clip()),this.isMoving===!1&&this.resizeFilters.length&&this._needsResize()?(this._lastScaleX=this.scaleX,this._lastScaleY=this.scaleY,s=this.applyFilters(null,this.resizeFilters,this._filteredEl||this._originalElement,!0)):s=this._element,s&&e.drawImage(s,n+i.marginX,r+i.marginY,i.width,i.height),this._renderStroke(e)},_needsResize:function(){return this.scaleX!==this._lastScaleX||this.scaleY!==this._lastScaleY},_findMargins:function(){var e=this.width,t=this.height,n,r,i=0,s=0;if(this.alignX!=="none"||this.alignY!=="none")n=[this.width/this._element.width,this.height/this._element.height],r=this.meetOrSlice==="meet"?Math.min.apply(null,n):Math.max.apply(null,n),e=this._element.width*r,t=this._element.height*r,this.alignX==="Mid"&&(i=(this.width-e)/2),this.alignX==="Max"&&(i=this.width-e),this.alignY==="Mid"&&(s=(this.height-t)/2),this.alignY==="Max"&&(s=this.height-t);return{width:e,height:t,marginX:i,marginY:s}},_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 preserveAspectRatio xlink:href".split(" ")),fabric.Image.fromElement=function(e,n,r){var i=fabric.parseAttributes(e,fabric.Image.ATTRIBUTE_NAMES),s="xMidYMid",o="meet",u,a,f;i.preserveAspectRatio&&(f=i.preserveAspectRatio.split(" ")),f&&f.length&&(o=f.pop(),o!=="meet"&&o!=="slice"?(s=o,o="meet"):f.length&&(s=f.pop())),u=s!=="none"?s.slice(1,4):"none",a=s!=="none"?s.slice(5,8):"none",i.alignX=u,i.alignY=a,i.meetOrSlice=o,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",initialize:function(e){e&&this.setOptions(e)},setOptions:function(e){for(var t in e)this[t]=e[t]},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)n&&(l=2,h=-1),u>i&&(c=2,p=-1),f=a.getImageData(0,0,n,i),e.width=o(s,n),e.height=o(u,i),a.putImageData(f,0,0);while(!d||!v)n=m,i=g,s*he)return 0;t*=Math.PI;if(s(t)<1e-16)return 1;var n=t/e;return a(t)*a(n)/t/n}}function h(e){var a,f,c,p,d,L,A,O,M,_,D;C.x=(e+.5)*b,k.x=r(C.x);for(a=0;a=t)continue;_=r(1e3*s(f-C.x)),N[_]||(N[_]={});for(var P=k.y-T;P<=k.y+T;P++){if(P<0||P>=o)continue;D=r(1e3*s(P-C.y)),N[_][D]||(N[_][D]=y(i(n(_*E,2)+n(D*S,2))/1e3)),c=N[_][D],c>0&&(p=(P*t+f)*4,d+=c,L+=c*m[p],A+=c*m[p+1],O+=c*m[p+2],M+=c*m[p+3])}}p=(a*u+e)*4,g[p]=L/d,g[p+1]=A/d,g[p+2]=O/d,g[p+3]=M/d}return++e1&&H<-1)continue;E=2*H*H*H-3*H*H+1,E>0&&(P=4*(D+A*t),k+=E*v[P+3],x+=E,v[P+3]<255&&(E=E*v[P+3]/250),T+=E*v[P],N+=E*v[P+1],C+=E*v[P+2],S+=E)}}g[w]=T/S,g[w+1]=N/S,g[w+2]=C/S,g[w+3]=k/x}return m}}),t.Image.filters.Resize.fromObject=function(){return new t.Image.filters.Resize}}(typeof exports!="undefined"?exports:this),function(e){"use strict";var t=e.fabric||(e.fabric={}),n=t.util.object.extend,r=t.util.object.clone,i=t.util.toFixed,s=t.StaticCanvas.supports("setLineDash");if(t.Text){t.warn("fabric.Text is already defined");return}var o=t.Object.prototype.stateProperties.concat();o.push("fontFamily","fontWeight","fontSize","text","textDecoration","textAlign","fontStyle","lineHeight","textBackgroundColor"),t.Text=t.util.createClass(t.Object,{_dimensionAffectingProps:{fontSize:!0,fontWeight:!0,fontFamily:!0,textDecoration:!0,fontStyle:!0,lineHeight:!0,stroke:!0,strokeWidth:!0,text:!0},_reNewline:/\r?\n/,type:"text",fontSize:40,fontWeight:"normal",fontFamily:"Times New Roman",textDecoration:"",textAlign:"left",fontStyle:"",lineHeight:1.16,textBackgroundColor:"",stateProperties:o,stroke:null,shadow:null,_fontSizeFraction:.25,_fontSizeMult:1.13,initialize:function(e,t){t=t||{},this.text=e,this.__skipDimension=!0,this.setOptions(t),this.__skipDimension=!1,this._initDimensions()},_initDimensions:function(){if(this.__skipDimension)return;this._clearCache();var e=t.util.createCanvasElement().getContext("2d");this._textLines=this.text.split(this._reNewline),this._setTextStyles(e),this.width=this._getTextWidth(e),this.height=this._getTextHeight(e)},toString:function(){return"#'},_render:function(e){this.clipTo&&t.util.clipContext(this,e),this._renderTextBackground(e),this._translateForTextAlign(e),this._renderText(e),this.textAlign!=="left"&&this.textAlign!=="justify"&&e.restore(),this._renderTextDecoration(e),this.clipTo&&e.restore()},_renderText:function(e){e.save(),this._setOpacity(e),this._setShadow(e),this._setupCompositeOperation(e),this._renderTextFill(e),this._renderTextStroke(e),this._restoreCompositeOperation(e),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))},_setTextStyles:function(e){e.textBaseline="alphabetic",this.skipTextAlign||(e.textAlign=this.textAlign),e.font=this._getFontDeclaration()},_getTextHeight:function(){return this._textLines.length*this._getHeightOfLine()},_getTextWidth:function(e){var t=this._getLineWidth(e,0);for(var n=1,r=this._textLines.length;nt&&(t=i)}return t},_renderChars:function(e,t,n,r,i){t[e](n,r,i)},_renderTextLine:function(e,t,n,r,i,s){i-=this.fontSize*this._fontSizeFraction;if(this.textAlign!=="justify"){this._renderChars(e,t,n,r,i,s);return}var o=this._getLineWidth(t,d),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&&r.push(.85),this.textDecoration.indexOf("line-through")>-1&&r.push(.43),this.textDecoration.indexOf("overline")>-1&&r.push(-0.12),r.length>0&&i(r)},_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,t){if(!this.visible)return;e.save(),this._setTextStyles(e),this._shouldClearCache()&&(this._clearCache(),this._textLines=this.text.split(this._reNewline),this.width=this._getTextWidth(e),this.height=this._getTextHeight(e)),t||this.transform(e),this._setStrokeStyles(e),this._setFillStyles(e);var n=this.group&&this.group.type==="path-group";n&&e.translate(-this.group.width/2,-this.group.height/2),this.transformMatrix&&e.transform.apply(e,this.transformMatrix),n&&e.translate(this.left,this.top),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,textBackgroundColor:this.textBackgroundColor});return this.includeDefaultValues||this._removeDefaultValues(t),t},toSVG:function(e){var t=this._createBaseSVGMarkup(),n=this._getSVGLeftTopOffsets(this.ctx),r=this._getSVGTextAndBg(n.textTop,n.textLeft);return this._wrapSVGTextAndBg(t,r),e?e(t.join("")):t.join("")},_getSVGLeftTopOffsets:function(e){var t=this._getHeightOfLine(e,0),n=-this.width/2,r=0;return{textLeft:n+(this.group&&this.group.type==="path-group"?this.left:0),textTop:r+(this.group&&this.group.type==="path-group"?-this.top:0),lineTop:t}},_wrapSVGTextAndBg:function(e,t){e.push(' \n',t.textBgRects.join("")," ',t.textSpans.join(""),"\n"," \n")},_getSVGTextAndBg:function(e,t){var n=[],r=[],i=0;this._setSVGBg(r);for(var s=0,o=this._textLines.length;s",t.util.string.escapeXml(this._textLines[e]),"")},_setSVGTextLineBg:function(e,t,n,r,s){e.push(" \n')},_setSVGBg:function(e){this.backgroundColor&&e.push(" \n')},_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){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),n.top=n.top||0,n.left=n.left||0,"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="left");var i=new t.Text(e.textContent,n),s=0;return i.originX==="left"&&(s=i.getWidth()/2),i.originX==="right"&&(s=-i.getWidth()/2),i.set({left:i.getLeft()+s,top:i.getTop()-i.getHeight()/2+i.fontSize*(.18+i._fontSizeFraction)}),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:!1,_reSpace:/\s|\n/,_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)},_clearCache:function(){this.callSuper("_clearCache"),this.__maxFontHeights=[]},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){e=Math.max(e,0),this.selectionStart!==e&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this}),this.selectionStart=e),this._updateTextarea()},setSelectionEnd:function(e){e=Math.min(e,this.text.length),this.selectionEnd!==e&&(this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this}),this.selectionEnd=e),this._updateTextarea()},getSelectionStyles:function(e,t){if(arguments.length===2){var n=[];for(var r=e;r=r.charIndex&&(u!==o||hs&&u0||this.skipFillStrokeCheck)&&this.callSuper("_renderChars",e,t,n,r,i)},_renderChar:function(e,t,n,r,i,s,o,u){var a,f,l,c=this._fontSizeFraction*u/this.lineHeight;if(this.styles&&this.styles[n]&&(a=this.styles[n][r])){var h=a.stroke||this.stroke,p=a.fill||this.fill;t.save(),f=this._applyCharStylesGetWidth(t,i,n,r,a),l=this._getHeightOfChar(t,i,n,r),p&&t.fillText(i,s,o),h&&t.strokeText(i,s,o),this._renderCharDecoration(t,a,s,o,c,f,l),t.restore(),t.translate(f,0)}else e==="strokeText"&&this.stroke&&t[e](i,s,o),e==="fillText"&&this.fill&&t[e](i,s,o),f=this._applyCharStylesGetWidth(t,i,n,r),this._renderCharDecoration(t,null,s,o,c,f,this.fontSize),t.translate(t.measureText(i).width,0)},_hasStyleChanged:function(e,t){return e.fill!==t.fill||e.fontSize!==t.fontSize||e.textBackgroundColor!==t.textBackgroundColor||e.textDecoration!==t.textDecoration||e.fontFamily!==t.fontFamily||e.fontWeight!==t.fontWeight||e.fontStyle!==t.fontStyle||e.stroke!==t.stroke||e.strokeWidth!==t.strokeWidth +},_renderCharDecoration:function(e,t,n,r,i,s,o){var u=t?t.textDecoration||this.textDecoration:this.textDecoration;if(!u)return;u.indexOf("underline")>-1&&e.fillRect(n,r+o/10,s,o/15),u.indexOf("line-through")>-1&&e.fillRect(n,r-o*(this._fontSizeFraction+this._fontSizeMult-1)+o/15,s,o/15),u.indexOf("overline")>-1&&e.fillRect(n,r-(this._fontSizeMult-this._fontSizeFraction)*o,s,o/15)},_renderTextLine:function(e,t,n,r,i,s){i+=this.fontSize*(this._fontSizeFraction+.03),this.callSuper("_renderTextLine",e,t,n,r,i,s)},_renderTextDecoration:function(e){if(this.isEmptyStyles())return this.callSuper("_renderTextDecoration",e)},_renderTextLinesBackground:function(e){if(!this.textBackgroundColor&&!this.styles)return;e.save(),this.textBackgroundColor&&(e.fillStyle=this.textBackgroundColor);var t=0;for(var n=0,r=this._textLines.length;nr&&(r=u)}return this.__maxFontHeights[t]=r,this.__lineHeights[t]=r*this.lineHeight*this._fontSizeMult,this.__lineHeights[t]},_getTextHeight:function(e){var t=0;for(var n=0,r=this._textLines.length;n-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),this._clearCache()},insertChars:function(e,t){var n=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,n,t),this.setSelectionStart(this.selectionStart+e.length),this.setSelectionEnd(this.selectionStart),this._clearCache(),this.canvas&&this.canvas.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}this._clearCache()},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]),this._clearCache()},insertStyleObjects:function(e,t,n){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(this.copiedStyles):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._textLines[i-1],u=o?o.length:0;this.styles[i-1]||(this.styles[i-1]={});for(s in this.styles[i])this.styles[i-1][parseInt(s,10)+u]=this.styles[i][s];this.shiftLineStyles(i,-1)}else{var a=this.styles[i];if(a){var f=this.selectionStart===this.selectionEnd?-1:0;delete a[s+f]}var l=e(a);for(var c in l){var h=parseInt(c,10);h>=s&&h!==0&&(a[h-1]=l[h],delete a[h])}}},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?ts?0:1,a=r+u;return this.flipX&&(a=i-a),a>this.text.length&&(a=this.text.length),a}}),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: fixed; bottom: 20px; left: 0px; opacity: 0; width: 0px; height: 0px; z-index: -999;",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))},_keysMap:{8:"removeChars",9:"exitEditing",27:"exitEditing",13:"insertNewline",33:"moveCursorUp",34:"moveCursorDown",35:"moveCursorRight",36:"moveCursorLeft",37:"moveCursorLeft",38:"moveCursorUp",39:"moveCursorRight",40:"moveCursorDown",46:"forwardDelete"},_ctrlKeysMap:{65:"selectAll",88:"cut"},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.stopImmediatePropagation(),e.preventDefault(),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,!0)},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)return;e.which!==0&&this.insertChars(String.fromCharCode(e.which)),e.stopPropagation()},getDownCursorOffset:function(e,t){var n=t?this.selectionEnd:this.selectionStart,r,i,s=this.text.slice(0,n),o=this.text.slice(n),u=s.slice(s.lastIndexOf("\n")+1),a=o.match(/(.*)\n?/)[1],f=(o.match(/.*\n(.*)\n?/)||{})[1]||"",l=this.get2DCursorLocation(n);if(l.lineIndex===this._textLines.length-1||e.metaKey||e.keyCode===34)return this.text.length-n;var c=this._getLineWidth(this.ctx,l.lineIndex);i=this._getLineLeftOffset(c);var h=i,p=l.lineIndex;for(var d=0,v=u.length;dn){a=!0;var p=o-h,d=o,v=Math.abs(p-n),m=Math.abs(d-n);u=mthis.text.length&&this.setSelectionEnd(this.text.length)},getUpCursorOffset:function(e,t){var n=t?this.selectionEnd:this.selectionStart,r=this.get2DCursorLocation(n);if(r.lineIndex===0||e.metaKey||e.keyCode===33)return n;var i=this.text.slice(0,n),s=i.slice(i.lastIndexOf("\n")+1),o=(i.match(/\n?(.*)\n.*$/)||{})[1]||"",u,a=this._getLineWidth(this.ctx,r.lineIndex),f=this._getLineLeftOffset(a),l=f,c=r.lineIndex;for(var h=0,p=s.length;hn){a=!0;var p=o-h,d=o,v=Math.abs(p-n),m=Math.abs(d-n);u=m=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.setSelectionEnd(this.selectionEnd+1))},moveCursorRightWithoutShift:function(e){this._selectionDirection="right",this.selectionStart===this.selectionEnd?(this._moveRight(e,"selectionStart"),this.setSelectionEnd(this.selectionStart)):(this.setSelectionEnd(this.selectionEnd+this.getNumNewLinesInSelectedText()),this.setSelectionStart(this.selectionEnd))},removeChars:function(e){this.selectionStart===this.selectionEnd?this._removeCharsNearCursor(e):this._removeCharsFromTo(this.selectionStart,this.selectionEnd),this.setSelectionEnd(this.selectionStart),this._removeExtraneousStyles(),this._clearCache(),this.canvas&&this.canvas.renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this})},_removeCharsNearCursor:function(e){if(this.selectionStart!==0)if(e.metaKey){var t=this.findLineBoundaryLeft(this.selectionStart);this._removeCharsFromTo(t,this.selectionStart),this.setSelectionStart(t)}else if(e.altKey){var n=this.findWordBoundaryLeft(this.selectionStart);this._removeCharsFromTo(n,this.selectionStart),this.setSelectionStart(n)}else{var r=this.text.slice(this.selectionStart-1,this.selectionStart)==="\n";this.removeStyleObject(r),this.setSelectionStart(this.selectionStart-1),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[e]?this._setSVGTextLineChars(e,t,n,r,s):this.callSuper("_setSVGTextLineText",e,t,n,r,i)},_setSVGTextLineChars:function(e,t,n,r,i){var s=this._textLines[e].split(""),o=0,u=this._getSVGLineLeftOffset(e)-this.width/2,a=this._getSVGLineTopOffset(e),f=this._getHeightOfLine(this.ctx,e);for(var l=0,c=s.length;l'].join("")},_createTextCharSpan:function(e,t,n,r,i){var s=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.protocol.indexOf("https:")===0?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,t){return origSetWidth.call(this,e,t),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,t){return origSetHeight.call(this,e,t),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 255fb13dc65b3a376fa2765962ec177aad8df2c7..57fd26a517fb8805632e6da03fdf7bcaf71c585e 100644 GIT binary patch delta 59602 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

Y!Npc}DQ6AMiVPYp5FHSv9qO6INt)pIa)kwnr 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 delta 60265 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 WxCbomHYM;#Gx=}2CG29dgaZKU7lYma diff --git a/dist/fabric.require.js b/dist/fabric.require.js index 8b2d56d9..5000fe86 100644 --- a/dist/fabric.require.js +++ b/dist/fabric.require.js @@ -5103,14 +5103,14 @@ fabric.ElementsParser.prototype.checkIfDone = function() { * @return {CanvasGradient} */ toLive: function(ctx, object) { - var gradient, coords = fabric.util.object.clone(this.coords); + var gradient, prop, coords = fabric.util.object.clone(this.coords); if (!this.type) { return; } if (object.group && object.group.type === 'path-group') { - for (var prop in coords) { + for (prop in coords) { if (prop === 'x1' || prop === 'x2') { coords[prop] += -this.offsetX + object.width / 2; } @@ -5120,6 +5120,17 @@ fabric.ElementsParser.prototype.checkIfDone = function() { } } + if (object.type === 'text') { + for (prop in coords) { + if (prop === 'x1' || prop === 'x2') { + coords[prop] -= object.width / 2; + } + else if (prop === 'y1' || prop === 'y2') { + coords[prop] -= object.height / 2; + } + } + } + if (this.type === 'linear') { gradient = ctx.createLinearGradient( coords.x1, coords.y1, coords.x2, coords.y2); @@ -5452,7 +5463,8 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ 'use strict'; - var fabric = global.fabric || (global.fabric = { }); + var fabric = global.fabric || (global.fabric = { }), + toFixed = fabric.util.toFixed; if (fabric.Shadow) { fabric.warn('fabric.Shadow is already defined.'); @@ -5569,16 +5581,18 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ if (object.width && object.height) { //http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion // we add some extra space to filter box to contain the blur ( 20 ) - fBoxX = Math.abs(this.offsetX / object.getWidth()) * 100 + 20; - fBoxY = Math.abs(this.offsetY / object.getHeight()) * 100 + 20; + fBoxX = toFixed(Math.abs(this.offsetX / object.getWidth()), 2) * 100 + 20; + fBoxY = toFixed(Math.abs(this.offsetY / object.getHeight()), 2) * 100 + 20; } return ( '\n' + '\t\n' + + toFixed(this.blur ? this.blur / 2 : 0, 3) + + '" result="blurOut">\n' + + '\t\n' + '\t\n' + '\t\n' + '\t\t\n' + @@ -7245,6 +7259,13 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype */ strokeLineJoin: 'round', + /** + * Stroke Dash Array. + * @type Array + * @default + */ + strokeDashArray: null, + /** * Sets shadow of an object * @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)") @@ -7267,6 +7288,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype ctx.lineWidth = this.width; ctx.lineCap = this.strokeLineCap; ctx.lineJoin = this.strokeLineJoin; + ctx.setLineDash(this.strokeDashArray); }, /** @@ -7472,6 +7494,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype strokeWidth: this.width, strokeLineCap: this.strokeLineCap, strokeLineJoin: this.strokeLineJoin, + strokeDashArray: this.strokeDashArray, originX: 'center', originY: 'center' }); @@ -12539,35 +12562,13 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati * @chainable */ setCoords: function() { - var strokeWidth = this.strokeWidth, - theta = degreesToRadians(this.angle), + var theta = degreesToRadians(this.angle), vpt = this.getViewportTransform(), f = function (p) { return fabric.util.transformPoint(p, vpt); }, - w = this.width, currentWidth, - h = this.height, currentHeight, - capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', - vLine = this.type === 'line' && this.width === 0, - hLine = this.type === 'line' && this.height === 0, - sLine = vLine || hLine, - strokeW = (capped && hLine) || !sLine, - strokeH = (capped && vLine) || !sLine; - - if (vLine) { - w = strokeWidth; - } - else if (hLine) { - h = strokeWidth; - } - if (strokeW) { - w += w > 0 ? strokeWidth : -strokeWidth; - } - if (strokeH) { - h += h > 0 ? strokeWidth : -strokeWidth; - } - currentWidth = w * this.scaleX + 2 * this.padding; - currentHeight = h * this.scaleY + 2 * this.padding; + p = this._calculateCurrentDimensions(false), + currentWidth = p.x, currentHeight = p.y; // If width is negative, make postive. Fixes path selection issue if (currentWidth < 0) { @@ -12592,31 +12593,29 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati wh = new fabric.Point(currentWidth, currentHeight), _tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY), _tr = new fabric.Point(_tl.x + (wh.x * cosTh), _tl.y + (wh.x * sinTh)), - _bl = new fabric.Point(_tl.x - (wh.y * sinTh), _tl.y + (wh.y * cosTh)), - _mt = new fabric.Point(_tl.x + (wh.x/2 * cosTh), _tl.y + (wh.x/2 * sinTh)), + bl = f(new fabric.Point(_tl.x - (wh.y * sinTh), _tl.y + (wh.y * cosTh))), + br = f(new fabric.Point(_tr.x - (wh.y * sinTh), _tr.y + (wh.y * cosTh))), tl = f(_tl), tr = f(_tr), - br = f(new fabric.Point(_tr.x - (wh.y * sinTh), _tr.y + (wh.y * cosTh))), - bl = f(_bl), - ml = f(new fabric.Point(_tl.x - (wh.y/2 * sinTh), _tl.y + (wh.y/2 * cosTh))), - 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)); - + ml = new fabric.Point((tl.x + bl.x)/2, (tl.y + bl.y)/2), + mt = new fabric.Point((tr.x + tl.x)/2, (tr.y + tl.y)/2), + mr = new fabric.Point((br.x + tr.x)/2, (br.y + tr.y)/2), + mb = new fabric.Point((br.x + bl.x)/2, (br.y + bl.y)/2), + mtr = new fabric.Point(mt.x + sinTh * this.rotatingPointOffset, mt.y - cosTh * this.rotatingPointOffset); // debugging - // setTimeout(function() { - // canvas.contextTop.fillStyle = 'green'; - // canvas.contextTop.fillRect(mb.x, mb.y, 3, 3); - // canvas.contextTop.fillRect(bl.x, bl.y, 3, 3); - // canvas.contextTop.fillRect(br.x, br.y, 3, 3); - // canvas.contextTop.fillRect(tl.x, tl.y, 3, 3); - // canvas.contextTop.fillRect(tr.x, tr.y, 3, 3); - // canvas.contextTop.fillRect(ml.x, ml.y, 3, 3); - // canvas.contextTop.fillRect(mr.x, mr.y, 3, 3); - // canvas.contextTop.fillRect(mt.x, mt.y, 3, 3); - // }, 50); + /* setTimeout(function() { + canvas.contextTop.fillStyle = 'green'; + canvas.contextTop.fillRect(mb.x, mb.y, 3, 3); + canvas.contextTop.fillRect(bl.x, bl.y, 3, 3); + canvas.contextTop.fillRect(br.x, br.y, 3, 3); + canvas.contextTop.fillRect(tl.x, tl.y, 3, 3); + canvas.contextTop.fillRect(tr.x, tr.y, 3, 3); + canvas.contextTop.fillRect(ml.x, ml.y, 3, 3); + canvas.contextTop.fillRect(mr.x, mr.y, 3, 3); + canvas.contextTop.fillRect(mt.x, mt.y, 3, 3); + canvas.contextTop.fillRect(mtr.x, mtr.y, 3, 3); + }, 50); */ this.oCoords = { // corners @@ -12743,7 +12742,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1', visibility = this.visible ? '' : ' visibility: hidden;', - filter = this.shadow && this.type !== 'text' ? 'filter: url(#SVGID_' + this.shadow.id + ');' : ''; + filter = this.shadow ? 'filter: url(#SVGID_' + this.shadow.id + ');' : ''; return [ 'stroke: ', stroke, '; ', @@ -12811,7 +12810,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @return {String} */ getSvgTransformMatrix: function() { - return this.transformMatrix ? ' matrix(' + this.transformMatrix.join(' ') + ')' : ''; + return this.transformMatrix ? ' matrix(' + this.transformMatrix.join(' ') + ') ' : ''; }, /** @@ -12960,185 +12959,70 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot */ _setCornerCoords: function() { var coords = this.oCoords, - theta = degreesToRadians(this.angle), newTheta = degreesToRadians(45 - this.angle), cornerHypotenuse = Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, cosHalfOffset = cornerHypotenuse * Math.cos(newTheta), sinHalfOffset = cornerHypotenuse * Math.sin(newTheta), - sinTh = Math.sin(theta), - cosTh = Math.cos(theta); + x, y; - coords.tl.corner = { - tl: { - x: coords.tl.x - sinHalfOffset, - y: coords.tl.y - cosHalfOffset - }, - tr: { - x: coords.tl.x + cosHalfOffset, - y: coords.tl.y - sinHalfOffset - }, - bl: { - x: coords.tl.x - cosHalfOffset, - y: coords.tl.y + sinHalfOffset - }, - br: { - x: coords.tl.x + sinHalfOffset, - y: coords.tl.y + cosHalfOffset - } - }; - - coords.tr.corner = { - tl: { - x: coords.tr.x - sinHalfOffset, - y: coords.tr.y - cosHalfOffset - }, - tr: { - x: coords.tr.x + cosHalfOffset, - y: coords.tr.y - sinHalfOffset - }, - br: { - x: coords.tr.x + sinHalfOffset, - y: coords.tr.y + cosHalfOffset - }, - bl: { - x: coords.tr.x - cosHalfOffset, - y: coords.tr.y + sinHalfOffset - } - }; - - coords.bl.corner = { - tl: { - x: coords.bl.x - sinHalfOffset, - y: coords.bl.y - cosHalfOffset - }, - bl: { - x: coords.bl.x - cosHalfOffset, - y: coords.bl.y + sinHalfOffset - }, - br: { - x: coords.bl.x + sinHalfOffset, - y: coords.bl.y + cosHalfOffset - }, - tr: { - x: coords.bl.x + cosHalfOffset, - y: coords.bl.y - sinHalfOffset - } - }; - - coords.br.corner = { - tr: { - x: coords.br.x + cosHalfOffset, - y: coords.br.y - sinHalfOffset - }, - bl: { - x: coords.br.x - cosHalfOffset, - y: coords.br.y + sinHalfOffset - }, - br: { - x: coords.br.x + sinHalfOffset, - y: coords.br.y + cosHalfOffset - }, - tl: { - x: coords.br.x - sinHalfOffset, - y: coords.br.y - cosHalfOffset - } - }; - - coords.ml.corner = { - tl: { - x: coords.ml.x - sinHalfOffset, - y: coords.ml.y - cosHalfOffset - }, - tr: { - x: coords.ml.x + cosHalfOffset, - y: coords.ml.y - sinHalfOffset - }, - bl: { - x: coords.ml.x - cosHalfOffset, - y: coords.ml.y + sinHalfOffset - }, - br: { - x: coords.ml.x + sinHalfOffset, - y: coords.ml.y + cosHalfOffset - } - }; - - coords.mt.corner = { - tl: { - x: coords.mt.x - sinHalfOffset, - y: coords.mt.y - cosHalfOffset - }, - tr: { - x: coords.mt.x + cosHalfOffset, - y: coords.mt.y - sinHalfOffset - }, - bl: { - x: coords.mt.x - cosHalfOffset, - y: coords.mt.y + sinHalfOffset - }, - br: { - x: coords.mt.x + sinHalfOffset, - y: coords.mt.y + cosHalfOffset - } - }; - - coords.mr.corner = { - tl: { - x: coords.mr.x - sinHalfOffset, - y: coords.mr.y - cosHalfOffset - }, - tr: { - x: coords.mr.x + cosHalfOffset, - y: coords.mr.y - sinHalfOffset - }, - bl: { - x: coords.mr.x - cosHalfOffset, - y: coords.mr.y + sinHalfOffset - }, - br: { - x: coords.mr.x + sinHalfOffset, - y: coords.mr.y + cosHalfOffset - } - }; - - coords.mb.corner = { - tl: { - x: coords.mb.x - sinHalfOffset, - y: coords.mb.y - cosHalfOffset - }, - tr: { - x: coords.mb.x + cosHalfOffset, - y: coords.mb.y - sinHalfOffset - }, - bl: { - x: coords.mb.x - cosHalfOffset, - y: coords.mb.y + sinHalfOffset - }, - br: { - x: coords.mb.x + sinHalfOffset, - y: coords.mb.y + cosHalfOffset - } - }; - - coords.mtr.corner = { - tl: { - x: coords.mtr.x - sinHalfOffset + (sinTh * this.rotatingPointOffset), - y: coords.mtr.y - cosHalfOffset - (cosTh * this.rotatingPointOffset) - }, - tr: { - x: coords.mtr.x + cosHalfOffset + (sinTh * this.rotatingPointOffset), - y: coords.mtr.y - sinHalfOffset - (cosTh * this.rotatingPointOffset) - }, - bl: { - x: coords.mtr.x - cosHalfOffset + (sinTh * this.rotatingPointOffset), - y: coords.mtr.y + sinHalfOffset - (cosTh * this.rotatingPointOffset) - }, - br: { - x: coords.mtr.x + sinHalfOffset + (sinTh * this.rotatingPointOffset), - y: coords.mtr.y + cosHalfOffset - (cosTh * this.rotatingPointOffset) - } - }; + for (var point in coords) { + x = coords[point].x; + y = coords[point].y; + coords[point].corner = { + tl: { + x: x - sinHalfOffset, + y: y - cosHalfOffset + }, + tr: { + x: x + cosHalfOffset, + y: y - sinHalfOffset + }, + bl: { + x: x - cosHalfOffset, + y: y + sinHalfOffset + }, + br: { + x: x + sinHalfOffset, + y: y + cosHalfOffset + } + }; + } }, + + _calculateCurrentDimensions: function(shouldTransform) { + var vpt = this.getViewportTransform(), + strokeWidth = this.strokeWidth, + w = this.width, + h = this.height, + capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', + vLine = this.type === 'line' && this.width === 0, + hLine = this.type === 'line' && this.height === 0, + sLine = vLine || hLine, + strokeW = (capped && hLine) || !sLine, + strokeH = (capped && vLine) || !sLine; + + if (vLine) { + w = strokeWidth; + } + else if (hLine) { + h = strokeWidth; + } + if (strokeW) { + w += (w < 0 ? -strokeWidth : strokeWidth); + } + if (strokeH) { + h += (h < 0 ? -strokeWidth : strokeWidth); + } + + w = w * this.scaleX + 2 * this.padding; + h = h * this.scaleY + 2 * this.padding; + + if (shouldTransform) { + return fabric.util.transformPoint(new fabric.Point(w, h), vpt, true); + } + return { x: w, y: h }; + }, + /** * Draws borders of an object's bounding box. * Requires public properties: width, height @@ -13152,43 +13036,13 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot return this; } - var padding = this.padding, - padding2 = padding * 2, - vpt = this.getViewportTransform(); - ctx.save(); ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; ctx.strokeStyle = this.borderColor; - - var scaleX = 1 / this._constrainScale(this.scaleX), - scaleY = 1 / this._constrainScale(this.scaleY); - ctx.lineWidth = 1 / this.borderScaleFactor; - var w = this.getWidth(), - h = this.getHeight(), - strokeWidth = this.strokeWidth, - capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', - vLine = this.type === 'line' && this.width === 0, - hLine = this.type === 'line' && this.height === 0, - sLine = vLine || hLine, - strokeW = (capped && hLine) || !sLine, - strokeH = (capped && vLine) || !sLine; - - if (vLine) { - w = strokeWidth / scaleX; - } - else if (hLine) { - h = strokeWidth / scaleY; - } - if (strokeW) { - w += strokeWidth / scaleX; - } - if (strokeH) { - h += strokeWidth / scaleY; - } - var wh = fabric.util.transformPoint(new fabric.Point(w, h), vpt, true), + var wh = this._calculateCurrentDimensions(true), width = wh.x, height = wh.y; if (this.group) { @@ -13197,15 +13051,15 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot } ctx.strokeRect( - ~~(-(width / 2) - padding) - 0.5, // offset needed to make lines look sharper - ~~(-(height / 2) - padding) - 0.5, - ~~(width + padding2) + 1, // double offset needed to make lines look sharper - ~~(height + padding2) + 1 + ~~(-(width / 2)) - 0.5, // offset needed to make lines look sharper + ~~(-(height / 2)) - 0.5, + ~~(width) + 1, // double offset needed to make lines look sharper + ~~(height) + 1 ); if (this.hasRotatingPoint && this.isControlVisible('mtr') && !this.get('lockRotation') && this.hasControls) { - var rotateHeight = ( -height - (padding * 2)) / 2; + var rotateHeight = -height / 2; ctx.beginPath(); ctx.moveTo(0, rotateHeight); @@ -13231,42 +13085,12 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot return this; } - var size = this.cornerSize, - size2 = size / 2, - vpt = this.getViewportTransform(), - strokeWidth = this.strokeWidth, - w = this.width, - h = this.height, - capped = this.strokeLineCap === 'round' || this.strokeLineCap === 'square', - vLine = this.type === 'line' && this.width === 0, - hLine = this.type === 'line' && this.height === 0, - sLine = vLine || hLine, - strokeW = (capped && hLine) || !sLine, - strokeH = (capped && vLine) || !sLine; - - if (vLine) { - w = strokeWidth; - } - else if (hLine) { - h = strokeWidth; - } - if (strokeW) { - w += strokeWidth; - } - if (strokeH) { - h += strokeWidth; - } - w *= this.scaleX; - h *= this.scaleY; - - var wh = fabric.util.transformPoint(new fabric.Point(w, h), vpt, true), + var wh = this._calculateCurrentDimensions(true), width = wh.x, height = wh.y, left = -(width / 2), top = -(height / 2), - padding = this.padding, - scaleOffset = size2, - scaleOffsetSize = size2 - size, + scaleOffset = this.cornerSize / 2, methodName = this.transparentCorners ? 'strokeRect' : 'fillRect'; ctx.save(); @@ -13278,44 +13102,44 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot // top-left this._drawControl('tl', ctx, methodName, - left - scaleOffset - padding, - top - scaleOffset - padding); + left - scaleOffset, + top - scaleOffset); // top-right this._drawControl('tr', ctx, methodName, - left + width - scaleOffset + padding, - top - scaleOffset - padding); + left + width - scaleOffset, + top - scaleOffset); // bottom-left this._drawControl('bl', ctx, methodName, - left - scaleOffset - padding, - top + height + scaleOffsetSize + padding); + left - scaleOffset, + top + height - scaleOffset); // bottom-right this._drawControl('br', ctx, methodName, - left + width + scaleOffsetSize + padding, - top + height + scaleOffsetSize + padding); + left + width - scaleOffset, + top + height - scaleOffset); if (!this.get('lockUniScaling')) { // middle-top this._drawControl('mt', ctx, methodName, left + width/2 - scaleOffset, - top - scaleOffset - padding); + top - scaleOffset); // middle-bottom this._drawControl('mb', ctx, methodName, left + width/2 - scaleOffset, - top + height + scaleOffsetSize + padding); + top + height - scaleOffset); // middle-right this._drawControl('mr', ctx, methodName, - left + width + scaleOffsetSize + padding, + left + width - scaleOffset, top + height/2 - scaleOffset); // middle-left this._drawControl('ml', ctx, methodName, - left - scaleOffset - padding, + left - scaleOffset, top + height/2 - scaleOffset); } @@ -13323,7 +13147,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot if (this.hasRotatingPoint) { this._drawControl('mtr', ctx, methodName, left + width/2 - scaleOffset, - top - this.rotatingPointOffset - this.cornerSize/2 - padding); + top - this.rotatingPointOffset - scaleOffset); } ctx.restore(); @@ -14205,7 +14029,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @private */ function isValidRadius(attributes) { - return (('radius' in attributes) && (attributes.radius > 0)); + return (('radius' in attributes) && (attributes.radius >= 0)); } /* _FROM_SVG_END_ */ @@ -14785,8 +14609,9 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot parsedAttributes.left = parsedAttributes.left || 0; parsedAttributes.top = parsedAttributes.top || 0; - - return new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); + var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); + rect.visible = rect.width > 0 && rect.height > 0; + return rect; }; /* _FROM_SVG_END_ */ @@ -14914,7 +14739,9 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @param {CanvasRenderingContext2D} ctx Context to render on */ _render: function(ctx) { - fabric.Polygon.prototype.commonRender.call(this, ctx); + if (!fabric.Polygon.prototype.commonRender.call(this, ctx)) { + return; + } this._renderFill(ctx); this._renderStroke(ctx); }, @@ -14969,10 +14796,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot var points = fabric.parsePointsAttribute(element.getAttribute('points')), parsedAttributes = fabric.parseAttributes(element, fabric.Polyline.ATTRIBUTE_NAMES); - if (points === null) { - return null; - } - return new fabric.Polyline(points, fabric.util.object.extend(parsedAttributes, options)); }; /* _FROM_SVG_END_ */ @@ -15051,7 +14874,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot */ initialize: function(points, options) { options = options || { }; - this.points = points; + this.points = points || [ ]; this.callSuper('initialize', options); this._calcDimensions(); if (!('top' in options)) { @@ -15073,11 +14896,11 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot maxX = max(points, 'x'), maxY = max(points, 'y'); - this.width = (maxX - minX) || 1; - this.height = (maxY - minY) || 1; + this.width = (maxX - minX) || 0; + this.height = (maxY - minY) || 0; - this.minX = minX, - this.minY = minY; + this.minX = minX || 0, + this.minY = minY || 0; }, /** @@ -15135,7 +14958,9 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @param {CanvasRenderingContext2D} ctx Context to render on */ _render: function(ctx) { - this.commonRender(ctx); + if (!this.commonRender(ctx)) { + return; + } this._renderFill(ctx); if (this.stroke || this.strokeDashArray) { ctx.closePath(); @@ -15148,7 +14973,14 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @param {CanvasRenderingContext2D} ctx Context to render on */ commonRender: function(ctx) { - var point; + var point, len = this.points.length; + + if (!len || isNaN(this.points[len - 1].y)) { + // do not draw if no points or odd points + // NaN comes from parseFloat of a empty string in parser + return false; + } + ctx.beginPath(); if (this._applyPointOffset) { @@ -15159,10 +14991,11 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot } ctx.moveTo(this.points[0].x, this.points[0].y); - for (var i = 0, len = this.points.length; i < len; i++) { + for (var i = 0; i < len; i++) { point = this.points[i]; ctx.lineTo(point.x, point.y); } + return true; }, /** @@ -15210,10 +15043,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot var points = fabric.parsePointsAttribute(element.getAttribute('points')), parsedAttributes = fabric.parseAttributes(element, fabric.Polygon.ATTRIBUTE_NAMES); - if (points === null) { - return null; - } - return new fabric.Polygon(points, extend(parsedAttributes, options)); }; /* _FROM_SVG_END_ */ @@ -15755,7 +15584,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot } var path = chunks.join(' '); if (!(this.group && this.group.type === 'path-group')) { - addTransform = 'translate(' + (-this.pathOffset.x) + ', ' + (-this.pathOffset.y) + ')'; + addTransform = ' translate(' + (-this.pathOffset.x) + ', ' + (-this.pathOffset.y) + ') '; } markup.push( //jscs:disable validateIndentation @@ -16371,7 +16200,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot //jscs:disable validateIndentation '\n' //jscs:enable validateIndentation ]; @@ -16890,12 +16719,14 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot _calcBounds: function(onlyWidthHeight) { var aX = [], aY = [], - o; + o, prop, + props = ['tr', 'br', 'bl', 'tl']; for (var i = 0, len = this._objects.length; i < len; ++i) { o = this._objects[i]; o.setCoords(); - for (var prop in o.oCoords) { + for (var j = 0; j < props.length; j++) { + prop = props[j]; aX.push(o.oCoords[prop].x); aY.push(o.oCoords[prop].y); } @@ -19472,9 +19303,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag 'textAlign', 'fontStyle', 'lineHeight', - 'textBackgroundColor', - 'useNative', - 'path' + 'textBackgroundColor' ); /** @@ -19707,7 +19536,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @type Number * @default */ - lineHeight: 1.3, + lineHeight: 1.16, /** * Background color of text lines @@ -19716,20 +19545,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ textBackgroundColor: '', - /** - * URL of a font file, when using Cufon - * @type String | null - * @default - */ - path: null, - - /** - * Indicates whether canvas native text methods should be used to render text (otherwise, Cufon is used) - * @type Boolean - * @default - */ - useNative: true, - /** * List of properties to consider when checking if * state of an object is changed ({@link fabric.Object#hasStateChanged}) @@ -19754,6 +19569,18 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ shadow: null, + /** + * @private + */ + _fontSizeFraction: 0.25, + + /** + * Text Line proportion to font Size (in pixels) + * @type Number + * @default + */ + _fontSizeMult: 1.13, + /** * Constructor * @param {String} text Text string @@ -19762,7 +19589,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ initialize: function(text, options) { options = options || { }; - this.text = text; this.__skipDimension = true; this.setOptions(options); @@ -19778,8 +19604,13 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag if (this.__skipDimension) { return; } - var canvasEl = fabric.util.createCanvasElement(); - this._render(canvasEl.getContext('2d')); + this._clearCache(); + + var ctx = fabric.util.createCanvasElement().getContext('2d'); + this._textLines = this.text.split(this._reNewline); + this._setTextStyles(ctx); + this.width = this._getTextWidth(ctx); + this.height = this._getTextHeight(ctx); }, /** @@ -19797,54 +19628,31 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ _render: function(ctx) { - if (typeof Cufon === 'undefined' || this.useNative === true) { - this._renderViaNative(ctx); - } - else { - this._renderViaCufon(ctx); - } - }, - - /** - * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - */ - _renderViaNative: function(ctx) { - var textLines = this.text.split(this._reNewline); - - this._setTextStyles(ctx); - - this.width = this._getTextWidth(ctx, textLines); - this.height = this._getTextHeight(ctx, textLines); - this.clipTo && fabric.util.clipContext(this, ctx); - this._renderTextBackground(ctx, textLines); + this._renderTextBackground(ctx); this._translateForTextAlign(ctx); - this._renderText(ctx, textLines); + this._renderText(ctx); if (this.textAlign !== 'left' && this.textAlign !== 'justify') { ctx.restore(); } - this._renderTextDecoration(ctx, textLines); + this._renderTextDecoration(ctx); this.clipTo && ctx.restore(); - - this._setBoundaries(ctx, textLines); - this._totalLineHeight = 0; }, /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _renderText: function(ctx, textLines) { + _renderText: function(ctx) { ctx.save(); this._setOpacity(ctx); this._setShadow(ctx); this._setupCompositeOperation(ctx); - this._renderTextFill(ctx, textLines); - this._renderTextStroke(ctx, textLines); + this._renderTextFill(ctx); + this._renderTextStroke(ctx); this._restoreCompositeOperation(ctx); this._removeShadow(ctx); ctx.restore(); @@ -19861,34 +19669,11 @@ 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 - */ - _setBoundaries: function(ctx, textLines) { - this._boundaries = [ ]; - - for (var i = 0, len = textLines.length; i < len; i++) { - - var lineWidth = this._getLineWidth(ctx, textLines[i]), - lineLeftOffset = this._getLineLeftOffset(lineWidth); - - this._boundaries.push({ - height: this.fontSize * this.lineHeight, - width: lineWidth, - left: lineLeftOffset - }); - } - }, - /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ _setTextStyles: function(ctx) { - this._setFillStyles(ctx); - this._setStrokeStyles(ctx); ctx.textBaseline = 'alphabetic'; if (!this.skipTextAlign) { ctx.textAlign = this.textAlign; @@ -19899,24 +19684,22 @@ 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 * @return {Number} Height of fabric.Text object */ - _getTextHeight: function(ctx, textLines) { - return this.fontSize * textLines.length * this.lineHeight; + _getTextHeight: function() { + return this._textLines.length * this._getHeightOfLine(); }, /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {Array} textLines Array of all text lines * @return {Number} Maximum width of fabric.Text object */ - _getTextWidth: function(ctx, textLines) { - var maxWidth = ctx.measureText(textLines[0] || '|').width; + _getTextWidth: function(ctx) { + var maxWidth = this._getLineWidth(ctx, 0); - for (var i = 1, len = textLines.length; i < len; i++) { - var currentLineWidth = ctx.measureText(textLines[i]).width; + for (var i = 1, len = this._textLines.length; i < len; i++) { + var currentLineWidth = this._getLineWidth(ctx, i); if (currentLineWidth > maxWidth) { maxWidth = currentLineWidth; } @@ -19947,7 +19730,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ _renderTextLine: function(method, ctx, line, left, top, lineIndex) { // lift the line by quarter of fontSize - top -= this.fontSize / 4; + top -= this.fontSize * this._fontSizeFraction; // short-circuit if (this.textAlign !== 'justify') { @@ -19955,7 +19738,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag return; } - var lineWidth = ctx.measureText(line).width, + var lineWidth = this._getLineWidth(ctx, i), totalWidth = this.width; if (totalWidth > lineWidth) { @@ -19996,28 +19779,27 @@ 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 */ - _renderTextFill: function(ctx, textLines) { + _renderTextFill: function(ctx) { if (!this.fill && !this._skipFillStrokeCheck) { return; } - this._boundaries = [ ]; var lineHeights = 0; - for (var i = 0, len = textLines.length; i < len; i++) { - var heightOfLine = this._getHeightOfLine(ctx, i, textLines); - lineHeights += heightOfLine; + for (var i = 0, len = this._textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i), + maxHeight = heightOfLine / this.lineHeight; this._renderTextLine( 'fillText', ctx, - textLines[i], + this._textLines[i], this._getLeftOffset(), - this._getTopOffset() + lineHeights, + this._getTopOffset() + lineHeights + maxHeight, i ); + lineHeights += heightOfLine; } if (this.shadow && !this.shadow.affectStroke) { this._removeShadow(ctx); @@ -20027,9 +19809,8 @@ 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 */ - _renderTextStroke: function(ctx, textLines) { + _renderTextStroke: function(ctx) { if ((!this.stroke || this.strokeWidth === 0) && !this._skipFillStrokeCheck) { return; } @@ -20037,6 +19818,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag var lineHeights = 0; ctx.save(); + if (this.strokeDashArray) { // Spec requires the concatenation of two copies the dash list when the number of elements is odd if (1 & this.strokeDashArray.length) { @@ -20046,25 +19828,26 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag } ctx.beginPath(); - for (var i = 0, len = textLines.length; i < len; i++) { - var heightOfLine = this._getHeightOfLine(ctx, i, textLines); - lineHeights += heightOfLine; + for (var i = 0, len = this._textLines.length; i < len; i++) { + var heightOfLine = this._getHeightOfLine(ctx, i), + maxHeight = heightOfLine / this.lineHeight; this._renderTextLine( 'strokeText', ctx, - textLines[i], + this._textLines[i], this._getLeftOffset(), - this._getTopOffset() + lineHeights, + this._getTopOffset() + lineHeights + maxHeight, i ); + lineHeights += heightOfLine; } ctx.closePath(); ctx.restore(); }, _getHeightOfLine: function() { - return this.fontSize * this.lineHeight; + return this.fontSize * this._fontSizeMult * this.lineHeight; }, /** @@ -20072,9 +19855,9 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @param {CanvasRenderingContext2D} ctx Context to render on * @param {Array} textLines Array of all text lines */ - _renderTextBackground: function(ctx, textLines) { + _renderTextBackground: function(ctx) { this._renderTextBoxBackground(ctx); - this._renderTextLinesBackground(ctx, textLines); + this._renderTextLinesBackground(ctx); }, /** @@ -20102,9 +19885,9 @@ 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 */ - _renderTextLinesBackground: function(ctx, textLines) { + _renderTextLinesBackground: function(ctx) { + var lineTopOffset = 0, heightOfLine = this._getHeightOfLine(); if (!this.textBackgroundColor) { return; } @@ -20112,20 +19895,21 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag ctx.save(); ctx.fillStyle = this.textBackgroundColor; - for (var i = 0, len = textLines.length; i < len; i++) { + for (var i = 0, len = this._textLines.length; i < len; i++) { - if (textLines[i] !== '') { + if (this._textLines[i] !== '') { - var lineWidth = this._getLineWidth(ctx, textLines[i]), + var lineWidth = this._getLineWidth(ctx, i), lineLeftOffset = this._getLineLeftOffset(lineWidth); ctx.fillRect( this._getLeftOffset() + lineLeftOffset, - this._getTopOffset() + (i * this.fontSize * this.lineHeight), + this._getTopOffset() + lineTopOffset, lineWidth, - this.fontSize * this.lineHeight + this.fontSize * this._fontSizeMult ); } + lineTopOffset += heightOfLine; } ctx.restore(); }, @@ -20147,53 +19931,85 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {String} line Text line - * @return {Number} Line width */ - _getLineWidth: function(ctx, line) { - return this.textAlign === 'justify' - ? this.width - : ctx.measureText(line).width; + _clearCache: function() { + this.__lineWidths = [ ]; + this.__lineHeights = [ ]; + this.__lineOffsets = [ ]; + }, + + /** + * @private + */ + _shouldClearCache: function() { + var shouldClear = false; + for (var prop in this._dimensionAffectingProps) { + if (this['__' + prop] !== this[prop]) { + this['__' + prop] = this[prop]; + shouldClear = true; + } + } + return shouldClear; }, /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {Array} textLines Array of all text lines + * @return {Number} Line width */ - _renderTextDecoration: function(ctx, textLines) { + _getLineWidth: function(ctx, lineIndex) { + if (this.__lineWidths[lineIndex]) { + return this.__lineWidths[lineIndex]; + } + this.__lineWidths[lineIndex] = this.textAlign === 'justify' ? + this.width : ctx.measureText(this._textLines[lineIndex]).width; + return this.__lineWidths[lineIndex]; + }, + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _renderTextDecoration: function(ctx) { if (!this.textDecoration) { return; } - // var halfOfVerticalBox = this.originY === 'top' ? 0 : this._getTextHeight(ctx, textLines) / 2; - var halfOfVerticalBox = this._getTextHeight(ctx, textLines) / 2, - _this = this; + var halfOfVerticalBox = this.height / 2, + _this = this, offsets = []; /** @ignore */ - function renderLinesAtOffset(offset) { - for (var i = 0, len = textLines.length; i < len; i++) { + function renderLinesAtOffset(offsets) { + var i, lineHeight = 0, len, j, oLen; + for (i = 0, len = _this._textLines.length; i < len; i++) { - var lineWidth = _this._getLineWidth(ctx, textLines[i]), - lineLeftOffset = _this._getLineLeftOffset(lineWidth); + var lineWidth = _this._getLineWidth(ctx, i), + lineLeftOffset = _this._getLineLeftOffset(lineWidth), + heightOfLine = _this._getHeightOfLine(ctx, i); - ctx.fillRect( - _this._getLeftOffset() + lineLeftOffset, - ~~((offset + (i * _this._getHeightOfLine(ctx, i, textLines))) - halfOfVerticalBox), - lineWidth, - 1); + for (j = 0, oLen = offsets.length; j < oLen; j++) { + ctx.fillRect( + _this._getLeftOffset() + lineLeftOffset, + lineHeight + (_this._fontSizeMult - 1 + offsets[j] ) * _this.fontSize - halfOfVerticalBox, + lineWidth, + _this.fontSize / 15); + } + lineHeight += heightOfLine; } } if (this.textDecoration.indexOf('underline') > -1) { - renderLinesAtOffset(this.fontSize * this.lineHeight); + offsets.push(0.85); // 1 - 3/16 } if (this.textDecoration.indexOf('line-through') > -1) { - renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize / 2); + offsets.push(0.43); } if (this.textDecoration.indexOf('overline') > -1) { - renderLinesAtOffset(this.fontSize * this.lineHeight - this.fontSize); + offsets.push(-0.12); + } + + if (offsets.length > 0) { + renderLinesAtOffset(offsets); } }, @@ -20221,10 +20037,19 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag } ctx.save(); + this._setTextStyles(ctx); + + if (this._shouldClearCache()) { + this._clearCache(); + this._textLines = this.text.split(this._reNewline); + this.width = this._getTextWidth(ctx); + this.height = this._getTextHeight(ctx); + } if (!noTransform) { this.transform(ctx); } - + this._setStrokeStyles(ctx); + this._setFillStyles(ctx); var isInPathGroup = this.group && this.group.type === 'path-group'; if (isInPathGroup) { @@ -20255,9 +20080,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag lineHeight: this.lineHeight, textDecoration: this.textDecoration, textAlign: this.textAlign, - path: this.path, - textBackgroundColor: this.textBackgroundColor, - useNative: this.useNative + textBackgroundColor: this.textBackgroundColor }); if (!this.includeDefaultValues) { this._removeDefaultValues(object); @@ -20272,16 +20095,10 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @return {String} svg representation of an instance */ toSVG: function(reviver) { - var markup = [ ], - textLines = this.text.split(this._reNewline), - offsets = this._getSVGLeftTopOffsets(textLines), - textAndBg = this._getSVGTextAndBg(offsets.lineTop, offsets.textLeft, textLines), - shadowSpans = this._getSVGShadows(offsets.lineTop, textLines); - - // move top offset by an ascent - offsets.textTop += (this._fontAscent ? ((this._fontAscent / 5) * this.lineHeight) : 0); - - this._wrapSVGTextAndBg(markup, textAndBg, shadowSpans, offsets); + var markup = this._createBaseSVGMarkup(), + offsets = this._getSVGLeftTopOffsets(this.ctx), + textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft); + this._wrapSVGTextAndBg(markup, textAndBg); return reviver ? reviver(markup.join('')) : markup.join(''); }, @@ -20289,19 +20106,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private */ - _getSVGLeftTopOffsets: function(textLines) { - var lineTop = this.useNative - ? this.fontSize * this.lineHeight - : (-this._fontAscent - ((this._fontAscent / 5) * this.lineHeight)), - - textLeft = -(this.width/2), - textTop = this.useNative - ? (this.fontSize * this.lineHeight - 0.25 * this.fontSize) // to lift by 1 / 4 of font height. - : (this.height/2) - (textLines.length * this.fontSize) - this._totalLineHeight; + _getSVGLeftTopOffsets: function(ctx) { + var lineTop = this._getHeightOfLine(ctx, 0), + textLeft = -this.width / 2, + textTop = 0; return { textLeft: textLeft + (this.group && this.group.type === 'path-group' ? this.left : 0), - textTop: textTop + (this.group && this.group.type === 'path-group' ? this.top : 0), + textTop: textTop + (this.group && this.group.type === 'path-group' ? -this.top : 0), lineTop: lineTop }; }, @@ -20309,99 +20121,43 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private */ - _wrapSVGTextAndBg: function(markup, textAndBg, shadowSpans, offsets) { + _wrapSVGTextAndBg: function(markup, textAndBg) { markup.push( - '\n', + '\t\n', textAndBg.textBgRects.join(''), - '', - shadowSpans.join(''), + 'style="', this.getSvgStyles(), '" >', textAndBg.textSpans.join(''), '\n', - '\n' + '\t\n' ); }, /** * @private - * @param {Number} lineHeight - * @param {Array} textLines Array of all text lines - * @return {Array} - */ - _getSVGShadows: function(lineHeight, textLines) { - var shadowSpans = [], - i, len, - lineTopOffsetMultiplier = 1; - - if (!this.shadow || !this._boundaries) { - return shadowSpans; - } - - for (i = 0, len = textLines.length; i < len; i++) { - if (textLines[i] !== '') { - var lineLeftOffset = (this._boundaries && this._boundaries[i]) ? this._boundaries[i].left : 0; - shadowSpans.push( - '', - fabric.util.string.escapeXml(textLines[i]), - ''); - lineTopOffsetMultiplier = 1; - } - else { - // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier - // prevents empty tspans - lineTopOffsetMultiplier++; - } - } - - return shadowSpans; - }, - - /** - * @private - * @param {Number} lineHeight + * @param {Number} textTopOffset Text top offset * @param {Number} textLeftOffset Text left offset - * @param {Array} textLines Array of all text lines * @return {Object} */ - _getSVGTextAndBg: function(lineHeight, textLeftOffset, textLines) { + _getSVGTextAndBg: function(textTopOffset, textLeftOffset) { var textSpans = [ ], textBgRects = [ ], - lineTopOffsetMultiplier = 1; - + height = 0; // bounding-box background this._setSVGBg(textBgRects); // text and text-background - for (var i = 0, len = textLines.length; i < len; i++) { - if (textLines[i] !== '') { - this._setSVGTextLineText(textLines[i], i, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects); - lineTopOffsetMultiplier = 1; + for (var i = 0, len = this._textLines.length; i < len; i++) { + if (this.textBackgroundColor) { + this._setSVGTextLineBg(textBgRects, i, textLeftOffset, textTopOffset, height); } - else { - // in some environments (e.g. IE 7 & 8) empty tspans are completely ignored, using a lineTopOffsetMultiplier - // prevents empty tspans - lineTopOffsetMultiplier++; - } - - if (!this.textBackgroundColor || !this._boundaries) { - continue; - } - - this._setSVGTextLineBg(textBgRects, i, textLeftOffset, lineHeight); + this._setSVGTextLineText(i, textSpans, height, textLeftOffset, textTopOffset, textBgRects); + height += this._getHeightOfLine(this.ctx, i); } return { @@ -20410,56 +20166,52 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag }; }, - _setSVGTextLineText: function(textLine, i, textSpans, lineHeight, lineTopOffsetMultiplier) { - var lineLeftOffset = (this._boundaries && this._boundaries[i]) - ? toFixed(this._boundaries[i].left, 2) - : 0; - + _setSVGTextLineText: function(i, textSpans, height, textLeftOffset, textTopOffset) { + var yPos = this.fontSize * (this._fontSizeMult - this._fontSizeFraction) + - textTopOffset + height - this.height / 2; textSpans.push( ' elements since setting opacity // on containing one doesn't work in Illustrator this._getFillAttributes(this.fill), '>', - fabric.util.string.escapeXml(textLine), + fabric.util.string.escapeXml(this._textLines[i]), '' ); }, - _setSVGTextLineBg: function(textBgRects, i, textLeftOffset, lineHeight) { + _setSVGTextLineBg: function(textBgRects, i, textLeftOffset, textTopOffset, height) { textBgRects.push( - '\n'); }, _setSVGBg: function(textBgRects) { - if (this.backgroundColor && this._boundaries) { + if (this.backgroundColor) { textBgRects.push( - ''); + toFixed(this.height, 4), + '">\n'); } }, @@ -20488,9 +20240,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @chainable */ _set: function(key, value) { - if (key === 'fontFamily' && this.path) { - this.path = this.path.replace(/(.*?)([^\/]*)(\.font\.js)/, '$1' + value + '$3'); - } this.callSuper('_set', key, value); if (key in this._dimensionAffectingProps) { @@ -20556,7 +20305,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag if (!options.originX) { options.originX = 'left'; } - options.top += options.fontSize / 4; var text = new fabric.Text(element.textContent, options), /* Adjust positioning: @@ -20573,7 +20321,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag } text.set({ left: text.getLeft() + offX, - top: text.getTop() - text.getHeight() / 2 + top: text.getTop() - text.getHeight() / 2 + text.fontSize * (0.18 + text._fontSizeFraction) /* 0.3 is the old lineHeight */ }); return text; @@ -20622,10 +20370,10 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * Select text vertically: shift + up, shift + down * Move cursor by word: alt + left, alt + right * Select words: shift + alt + left, shift + alt + right - * Move cursor to line start/end: cmd + left, cmd + right - * Select till start/end of line: cmd + shift + left, cmd + shift + right + * Move cursor to line start/end: cmd + left, cmd + right or home, end + * Select till start/end of line: cmd + shift + left, cmd + shift + right or shift + home, shift + end * Jump to start/end of text: cmd + up, cmd + down - * Select till start/end of text: cmd + shift + up, cmd + shift + down + * Select till start/end of text: cmd + shift + up, cmd + shift + down or shift + pgUp, shift + pgDown * Delete character: backspace * Delete word: alt + backspace * Delete line: cmd + backspace @@ -20634,6 +20382,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * Paste text: ctrl/cmd + v * Cut text: ctrl/cmd + x * Select entire text: ctrl/cmd + a + * Quit editing tab or esc * * *

Supported mouse/touch combination

@@ -20744,18 +20493,13 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @type Boolean * @default */ - _skipFillStrokeCheck: true, + _skipFillStrokeCheck: false, /** * @private */ _reSpace: /\s|\n/, - /** - * @private - */ - _fontSizeFraction: 4, - /** * @private */ @@ -20789,10 +20533,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag fabric.IText.instances.push(this); - // caching - this.__lineWidths = { }; - this.__lineHeights = { }; - this.__lineOffsets = { }; + }, + + /** + * @private + */ + _clearCache: function() { + this.callSuper('_clearCache'); + this.__maxFontHeights = [ ]; }, /** @@ -20820,12 +20568,13 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @param {Number} index Index to set selection start to */ setSelectionStart: function(index) { + index = Math.max(index, 0); if (this.selectionStart !== index) { this.fire('selection:changed'); this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + this.selectionStart = index; } - this.selectionStart = index; - this.hiddenTextarea && (this.hiddenTextarea.selectionStart = index); + this._updateTextarea(); }, /** @@ -20833,12 +20582,13 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @param {Number} index Index to set selection end to */ setSelectionEnd: function(index) { + index = Math.min(index, this.text.length); if (this.selectionEnd !== index) { this.fire('selection:changed'); this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + this.selectionEnd = index; } - this.selectionEnd = index; - this.hiddenTextarea && (this.hiddenTextarea.selectionEnd = index); + this._updateTextarea(); }, /** @@ -21003,18 +20753,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ _getCursorBoundaries: function(chars, typeOfBoundaries) { - var cursorLocation = this.get2DCursorLocation(), - - textLines = this.text.split(this._reNewline), - // left/top are left/top of entire text box // leftOffset/topOffset are offset from that left/top point of a text box - left = Math.round(this._getLeftOffset()), + var left = Math.round(this._getLeftOffset()), top = this._getTopOffset(), offsets = this._getCursorBoundariesOffsets( - chars, typeOfBoundaries, cursorLocation, textLines); + chars, typeOfBoundaries); return { left: left, @@ -21027,26 +20773,19 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private */ - _getCursorBoundariesOffsets: function(chars, typeOfBoundaries, cursorLocation, textLines) { + _getCursorBoundariesOffsets: function(chars, typeOfBoundaries) { var lineLeftOffset = 0, lineIndex = 0, charIndex = 0, - - leftOffset = 0, - topOffset = typeOfBoundaries === 'cursor' - // selection starts at the very top of the line, - // whereas cursor starts at the padding created by line height - ? (this._getHeightOfLine(this.ctx, 0) - - this.getCurrentCharFontSize(cursorLocation.lineIndex, cursorLocation.charIndex)) - : 0; + topOffset = 0, + leftOffset = 0; for (var i = 0; i < this.selectionStart; i++) { if (chars[i] === '\n') { leftOffset = 0; - var index = lineIndex + (typeOfBoundaries === 'cursor' ? 1 : 0); - topOffset += this._getCachedLineHeight(index); + topOffset += this._getHeightOfLine(this.ctx, lineIndex); lineIndex++; charIndex = 0; @@ -21056,10 +20795,12 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag charIndex++; } - lineLeftOffset = this._getCachedLineOffset(lineIndex, textLines); + lineLeftOffset = this._getCachedLineOffset(lineIndex); + } + if (typeOfBoundaries === 'cursor') { + topOffset += (1 - this._fontSizeFraction) * this._getHeightOfLine(this.ctx, lineIndex) / this.lineHeight + - this.getCurrentCharFontSize(lineIndex, charIndex) * (1 - this._fontSizeFraction); } - - this._clearCache(); return { top: topOffset, @@ -21071,33 +20812,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag /** * @private */ - _clearCache: function() { - this.__lineWidths = { }; - this.__lineHeights = { }; - this.__lineOffsets = { }; - }, - - /** - * @private - */ - _getCachedLineHeight: function(index) { - return this.__lineHeights[index] || - (this.__lineHeights[index] = this._getHeightOfLine(this.ctx, index)); - }, - - /** - * @private - */ - _getCachedLineWidth: function(lineIndex, textLines) { - return this.__lineWidths[lineIndex] || - (this.__lineWidths[lineIndex] = this._getWidthOfLine(this.ctx, lineIndex, textLines)); - }, - - /** - * @private - */ - _getCachedLineOffset: function(lineIndex, textLines) { - var widthOfLine = this._getCachedLineWidth(lineIndex, textLines); + _getCachedLineOffset: function(lineIndex) { + var widthOfLine = this._getLineWidth(this.ctx, lineIndex); return this.__lineOffsets[lineIndex] || (this.__lineOffsets[lineIndex] = this._getLineLeftOffset(widthOfLine)); @@ -21147,30 +20863,29 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag var start = this.get2DCursorLocation(this.selectionStart), end = this.get2DCursorLocation(this.selectionEnd), startLine = start.lineIndex, - endLine = end.lineIndex, - textLines = this.text.split(this._reNewline); + endLine = end.lineIndex; for (var i = startLine; i <= endLine; i++) { - var lineOffset = this._getCachedLineOffset(i, textLines) || 0, - lineHeight = this._getCachedLineHeight(i), - boxWidth = 0; + var lineOffset = this._getCachedLineOffset(i) || 0, + lineHeight = this._getHeightOfLine(this.ctx, i), + boxWidth = 0, line = this._textLines[i]; if (i === startLine) { - for (var j = 0, len = textLines[i].length; j < len; j++) { + for (var j = 0, len = line.length; j < len; j++) { if (j >= start.charIndex && (i !== endLine || j < end.charIndex)) { - boxWidth += this._getWidthOfChar(ctx, textLines[i][j], i, j); + boxWidth += this._getWidthOfChar(ctx, line[j], i, j); } if (j < start.charIndex) { - lineOffset += this._getWidthOfChar(ctx, textLines[i][j], i, j); + lineOffset += this._getWidthOfChar(ctx, line[j], i, j); } } } else if (i > startLine && i < endLine) { - boxWidth += this._getCachedLineWidth(i, textLines) || 5; + boxWidth += this._getLineWidth(ctx, i) || 5; } else if (i === endLine) { for (var j2 = 0, j2len = end.charIndex; j2 < j2len; j2++) { - boxWidth += this._getWidthOfChar(ctx, textLines[i][j2], i, j2); + boxWidth += this._getWidthOfChar(ctx, line[j2], i, j2); } } @@ -21206,10 +20921,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag : 0; // set proper line offset - var textLines = this.text.split(this._reNewline), - lineWidth = this._getWidthOfLine(ctx, lineIndex, textLines), - lineHeight = this._getHeightOfLine(ctx, lineIndex, textLines), - lineLeftOffset = this._getLineLeftOffset(lineWidth), + var lineHeight = this._getHeightOfLine(ctx, lineIndex), + lineLeftOffset = this._getCachedLineOffset(lineIndex), chars = line.split(''), prevStyle, charsToRender = ''; @@ -21217,7 +20930,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag left += lineLeftOffset || 0; ctx.save(); - + top -= lineHeight / this.lineHeight * this._fontSizeFraction; for (var i = 0, len = chars.length; i <= len; i++) { prevStyle = prevStyle || this.getCurrentCharStyle(lineIndex, i); var thisStyle = this.getCurrentCharStyle(lineIndex, i + 1); @@ -21247,7 +20960,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag if (method === 'fillText' && this.fill) { this.callSuper('_renderChars', method, ctx, line, left, top); } - if (method === 'strokeText' && this.stroke) { + if (method === 'strokeText' && ((this.stroke && this.strokeWidth > 0) || this.skipFillStrokeCheck)) { this.callSuper('_renderChars', method, ctx, line, left, top); } }, @@ -21264,7 +20977,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @param {Number} lineHeight Height of the line */ _renderChar: function(method, ctx, lineIndex, i, _char, left, top, lineHeight) { - var decl, charWidth, charHeight; + var decl, charWidth, charHeight, + offset = this._fontSizeFraction * lineHeight / this.lineHeight; if (this.styles && this.styles[lineIndex] && (decl = this.styles[lineIndex][i])) { @@ -21282,7 +20996,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag ctx.strokeText(_char, left, top); } - this._renderCharDecoration(ctx, decl, left, top, charWidth, lineHeight, charHeight); + this._renderCharDecoration(ctx, decl, left, top, offset, charWidth, charHeight); ctx.restore(); ctx.translate(charWidth, 0); @@ -21295,7 +21009,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag ctx[method](_char, left, top); } charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i); - this._renderCharDecoration(ctx, null, left, top, charWidth, lineHeight); + this._renderCharDecoration(ctx, null, left, top, offset, charWidth, this.fontSize); ctx.translate(ctx.measureText(_char).width, 0); } @@ -21323,58 +21037,42 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _renderCharDecoration: function(ctx, styleDeclaration, left, top, charWidth, lineHeight, charHeight) { + _renderCharDecoration: function(ctx, styleDeclaration, left, top, offset, charWidth, charHeight) { var textDecoration = styleDeclaration ? (styleDeclaration.textDecoration || this.textDecoration) - : this.textDecoration, - - fontSize = (styleDeclaration ? styleDeclaration.fontSize : null) || this.fontSize; + : this.textDecoration; if (!textDecoration) { return; } if (textDecoration.indexOf('underline') > -1) { - this._renderCharDecorationAtOffset( - ctx, + ctx.fillRect( left, - top + (this.fontSize / this._fontSizeFraction), - charWidth, - 0, - this.fontSize / 20 + top + charHeight / 10, + charWidth , + charHeight / 15 ); } if (textDecoration.indexOf('line-through') > -1) { - this._renderCharDecorationAtOffset( - ctx, + ctx.fillRect( left, - top + (this.fontSize / this._fontSizeFraction), + top - charHeight * (this._fontSizeFraction + this._fontSizeMult - 1) + charHeight / 15, charWidth, - charHeight / 2, - fontSize / 20 + charHeight / 15 ); } if (textDecoration.indexOf('overline') > -1) { - this._renderCharDecorationAtOffset( - ctx, + ctx.fillRect( left, - top, + top - (this._fontSizeMult - this._fontSizeFraction) * charHeight, charWidth, - lineHeight - (this.fontSize / this._fontSizeFraction), - this.fontSize / 20 + charHeight / 15 ); } }, - /** - * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - */ - _renderCharDecorationAtOffset: function(ctx, left, top, charWidth, offset, thickness) { - ctx.fillRect(left, top - offset, charWidth, thickness); - }, - /** * @private * @param {String} method @@ -21383,27 +21081,26 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ _renderTextLine: function(method, ctx, line, left, top, lineIndex) { // to "cancel" this.fontSize subtraction in fabric.Text#_renderTextLine - top += this.fontSize / 4; + // the adding 0.03 is just to align text with itext by overlap test + top += this.fontSize * (this._fontSizeFraction + 0.03); this.callSuper('_renderTextLine', method, ctx, line, left, top, lineIndex); }, /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {Array} textLines */ - _renderTextDecoration: function(ctx, textLines) { + _renderTextDecoration: function(ctx) { if (this.isEmptyStyles()) { - return this.callSuper('_renderTextDecoration', ctx, textLines); + return this.callSuper('_renderTextDecoration', ctx); } }, /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {Array} textLines Array of all text lines */ - _renderTextLinesBackground: function(ctx, textLines) { + _renderTextLinesBackground: function(ctx) { if (!this.textBackgroundColor && !this.styles) { return; } @@ -21414,43 +21111,42 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag ctx.fillStyle = this.textBackgroundColor; } - var lineHeights = 0, - fractionOfFontSize = this.fontSize / this._fontSizeFraction; + var lineHeights = 0; - for (var i = 0, len = textLines.length; i < len; i++) { + for (var i = 0, len = this._textLines.length; i < len; i++) { - var heightOfLine = this._getHeightOfLine(ctx, i, textLines); - if (textLines[i] === '') { + var heightOfLine = this._getHeightOfLine(ctx, i); + if (this._textLines[i] === '') { lineHeights += heightOfLine; continue; } - var lineWidth = this._getWidthOfLine(ctx, i, textLines), - lineLeftOffset = this._getLineLeftOffset(lineWidth); + var lineWidth = this._getLineWidth(ctx, i), + lineLeftOffset = this._getCachedLineOffset(i); if (this.textBackgroundColor) { ctx.fillStyle = this.textBackgroundColor; ctx.fillRect( this._getLeftOffset() + lineLeftOffset, - this._getTopOffset() + lineHeights + fractionOfFontSize, + this._getTopOffset() + lineHeights, lineWidth, - heightOfLine + heightOfLine / this.lineHeight ); } if (this.styles[i]) { - for (var j = 0, jlen = textLines[i].length; j < jlen; j++) { + for (var j = 0, jlen = this._textLines[i].length; j < jlen; j++) { if (this.styles[i] && this.styles[i][j] && this.styles[i][j].textBackgroundColor) { - var _char = textLines[i][j]; + var _char = this._textLines[i][j]; ctx.fillStyle = this.styles[i][j].textBackgroundColor; ctx.fillRect( - this._getLeftOffset() + lineLeftOffset + this._getWidthOfCharsAt(ctx, i, j, textLines), - this._getTopOffset() + lineHeights + fractionOfFontSize, - this._getWidthOfChar(ctx, _char, i, j, textLines) + 1, - heightOfLine + this._getLeftOffset() + lineLeftOffset + this._getWidthOfCharsAt(ctx, i, j), + this._getTopOffset() + lineHeights, + this._getWidthOfChar(ctx, _char, i, j) + 1, + heightOfLine / this.lineHeight ); } } @@ -21465,12 +21161,10 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag */ _getCacheProp: function(_char, styleDeclaration) { return _char + - styleDeclaration.fontFamily + styleDeclaration.fontSize + styleDeclaration.fontWeight + styleDeclaration.fontStyle + - styleDeclaration.shadow; }, @@ -21603,9 +21297,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _getWidthOfCharAt: function(ctx, lineIndex, charIndex, lines) { - lines = lines || this.text.split(this._reNewline); - var _char = lines[lineIndex].split('')[charIndex]; + _getWidthOfCharAt: function(ctx, lineIndex, charIndex) { + var _char = this._textLines[lineIndex].split('')[charIndex]; return this._getWidthOfChar(ctx, _char, lineIndex, charIndex); }, @@ -21613,9 +21306,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _getHeightOfCharAt: function(ctx, lineIndex, charIndex, lines) { - lines = lines || this.text.split(this._reNewline); - var _char = lines[lineIndex].split('')[charIndex]; + _getHeightOfCharAt: function(ctx, lineIndex, charIndex) { + var _char = this._textLines[lineIndex].split('')[charIndex]; return this._getHeightOfChar(ctx, _char, lineIndex, charIndex); }, @@ -21623,10 +21315,10 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _getWidthOfCharsAt: function(ctx, lineIndex, charIndex, lines) { + _getWidthOfCharsAt: function(ctx, lineIndex, charIndex) { var width = 0; for (var i = 0; i < charIndex; i++) { - width += this._getWidthOfCharAt(ctx, lineIndex, i, lines); + width += this._getWidthOfCharAt(ctx, lineIndex, i); } return width; }, @@ -21635,11 +21327,12 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _getWidthOfLine: function(ctx, lineIndex, textLines) { - // if (!this.styles[lineIndex]) { - // return this.callSuper('_getLineWidth', ctx, textLines[lineIndex]); - // } - return this._getWidthOfCharsAt(ctx, lineIndex, textLines[lineIndex].length, textLines); + _getLineWidth: function(ctx, lineIndex) { + if (this.__lineWidths[lineIndex]) { + return this.__lineWidths[lineIndex]; + } + this.__lineWidths[lineIndex] = this._getWidthOfCharsAt(ctx, lineIndex, this._textLines[lineIndex].length); + return this.__lineWidths[lineIndex]; }, /** @@ -21683,33 +21376,13 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _getTextWidth: function(ctx, textLines) { - - if (this.isEmptyStyles()) { - return this.callSuper('_getTextWidth', ctx, textLines); + _getHeightOfLine: function(ctx, lineIndex) { + if (this.__lineHeights[lineIndex]) { + return this.__lineHeights[lineIndex]; } - var maxWidth = this._getWidthOfLine(ctx, 0, textLines); - - for (var i = 1, len = textLines.length; i < len; i++) { - var currentLineWidth = this._getWidthOfLine(ctx, i, textLines); - if (currentLineWidth > maxWidth) { - maxWidth = currentLineWidth; - } - } - return maxWidth; - }, - - /** - * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - */ - _getHeightOfLine: function(ctx, lineIndex, textLines) { - - textLines = textLines || this.text.split(this._reNewline); - - var maxHeight = this._getHeightOfChar(ctx, textLines[lineIndex][0], lineIndex, 0), - line = textLines[lineIndex], + var line = this._textLines[lineIndex], + maxHeight = this._getHeightOfChar(ctx, line[0], lineIndex, 0), chars = line.split(''); for (var i = 1, len = chars.length; i < len; i++) { @@ -21718,31 +21391,23 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag maxHeight = currentCharHeight; } } - - return maxHeight * this.lineHeight; + this.__maxFontHeights[lineIndex] = maxHeight; + this.__lineHeights[lineIndex] = maxHeight * this.lineHeight * this._fontSizeMult; + return this.__lineHeights[lineIndex]; }, /** * @private * @param {CanvasRenderingContext2D} ctx Context to render on - * @param {Array} textLines Array of all text lines */ - _getTextHeight: function(ctx, textLines) { + _getTextHeight: function(ctx) { var height = 0; - for (var i = 0, len = textLines.length; i < len; i++) { - height += this._getHeightOfLine(ctx, i, textLines); + for (var i = 0, len = this._textLines.length; i < len; i++) { + height += this._getHeightOfLine(ctx, i); } return height; }, - /** - * @private - */ - _getTopOffset: function() { - var topOffset = fabric.Text.prototype._getTopOffset.call(this); - return topOffset - (this.fontSize / this._fontSizeFraction); - }, - /** * This method is overwritten to account for different top offset * @private @@ -21757,7 +21422,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag ctx.fillRect( this._getLeftOffset(), - this._getTopOffset() + (this.fontSize / this._fontSizeFraction), + this._getTopOffset(), this.width, this.height ); @@ -21959,10 +21624,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * Selects entire text */ selectAll: function() { - this.selectionStart = 0; - this.selectionEnd = this.text.length; - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + this.setSelectionStart(0); + this.setSelectionEnd(this.text.length); }, /** @@ -22129,6 +21792,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag this.isEditing = true; this.initHiddenTextarea(); + this.hiddenTextarea.focus(); this._updateTextarea(); this._saveEditingProps(); this._setEditingProps(); @@ -22177,6 +21841,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag this.hiddenTextarea.value = this.text; this.hiddenTextarea.selectionStart = this.selectionStart; + this.hiddenTextarea.selectionEnd = this.selectionEnd; }, /** @@ -22243,9 +21908,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag * @private */ _removeExtraneousStyles: function() { - var textLines = this.text.split(this._reNewline); for (var prop in this.styles) { - if (!textLines[prop]) { + if (!this._textLines[prop]) { delete this.styles[prop]; } } @@ -22276,13 +21940,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag this.text = this.text.slice(0, start) + this.text.slice(end); + this._clearCache(); }, /** * Inserts a character where cursor is (replacing selection if one exists) * @param {String} _chars Characters to insert */ - insertChars: function(_chars) { + insertChars: function(_chars, useCopiedStyle) { var isEndOfLine = this.text.slice(this.selectionStart, this.selectionStart + 1) === '\n'; this.text = this.text.slice(0, this.selectionStart) + @@ -22290,21 +21955,16 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag this.text.slice(this.selectionEnd); if (this.selectionStart === this.selectionEnd) { - this.insertStyleObjects(_chars, isEndOfLine, this.copiedStyles); + this.insertStyleObjects(_chars, isEndOfLine, useCopiedStyle); } // else if (this.selectionEnd - this.selectionStart > 1) { // TODO: replace styles properly // console.log('replacing MORE than 1 char'); // } - - this.selectionStart += _chars.length; - this.selectionEnd = this.selectionStart; - - if (this.canvas) { - // TODO: double renderAll gets rid of text box shift happenning sometimes - // need to find out what exactly causes it and fix it - this.canvas.renderAll().renderAll(); - } + this.setSelectionStart(this.selectionStart + _chars.length); + this.setSelectionEnd(this.selectionStart); + this._clearCache(); + this.canvas && this.canvas.renderAll(); this.setCoords(); this.fire('changed'); @@ -22346,6 +22006,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag } this.styles[lineIndex + 1] = newLineStyles; } + this._clearCache(); }, /** @@ -22375,15 +22036,16 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag this.styles[lineIndex][charIndex] = style || clone(currentLineStyles[charIndex - 1]); + this._clearCache(); }, /** * Inserts style object(s) * @param {String} _chars Characters at the location where style is inserted * @param {Boolean} isEndOfLine True if it's end of line - * @param {Array} [styles] Styles to insert + * @param {Boolean} [useCopiedStyle] Style to insert */ - insertStyleObjects: function(_chars, isEndOfLine, styles) { + insertStyleObjects: function(_chars, isEndOfLine, useCopiedStyle) { // removed shortcircuit over isEmptyStyles var cursorLocation = this.get2DCursorLocation(), @@ -22398,8 +22060,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag this.insertNewlineStyleObject(lineIndex, charIndex, isEndOfLine); } else { - if (styles) { - this._insertStyles(styles); + if (useCopiedStyle) { + this._insertStyles(this.copiedStyles); } else { // TODO: support multiple style insertion if _chars.length > 1 @@ -22451,8 +22113,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag if (isBeginningOfLine) { - var textLines = this.text.split(this._reNewline), - textOnPreviousLine = textLines[lineIndex - 1], + var textOnPreviousLine = this._textLines[lineIndex - 1], newCharIndexOnPrevLine = textOnPreviousLine ? textOnPreviousLine.length : 0; @@ -22705,30 +22366,30 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot */ getSelectionStartFromPointer: function(e) { var mouseOffset = this._getLocalRotatedPointer(e), - textLines = this.text.split(this._reNewline), prevWidth = 0, width = 0, height = 0, charIndex = 0, - newSelectionStart; - - for (var i = 0, len = textLines.length; i < len; i++) { + newSelectionStart, + line; + for (var i = 0, len = this._textLines.length; i < len; i++) { + line = this._textLines[i].split(''); height += this._getHeightOfLine(this.ctx, i) * this.scaleY; - var widthOfLine = this._getWidthOfLine(this.ctx, i, textLines), + var widthOfLine = this._getLineWidth(this.ctx, i), lineLeftOffset = this._getLineLeftOffset(widthOfLine); width = lineLeftOffset * this.scaleX; if (this.flipX) { // when oject is horizontally flipped we reverse chars - textLines[i] = textLines[i].split('').reverse().join(''); + this._textLines[i] = line.split('').reverse().join(''); } - for (var j = 0, jlen = textLines[i].length; j < jlen; j++) { + for (var j = 0, jlen = line.length; j < jlen; j++) { - var _char = textLines[i][j]; + var _char = line[j]; prevWidth = width; width += this._getWidthOfChar(this.ctx, _char, i, this.flipX ? jlen - j : j) * @@ -22796,11 +22457,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot 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)); - - if (!this._clickHandlerInitialized && this.canvas) { - fabric.util.addListener(this.canvas.upperCanvasEl, 'click', this.onClick.bind(this)); - this._clickHandlerInitialized = true; - } }, /** @@ -22830,11 +22486,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot 88: 'cut' }, - onClick: function() { - // No need to trigger click event here, focus is enough to have the keyboard appear on Android - this.hiddenTextarea && this.hiddenTextarea.focus(); - }, - /** * Handles keyup event * @param {Event} e Event object @@ -22843,7 +22494,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot if (!this.isEditing) { return; } - if (e.keyCode in this._keysMap) { this[this._keysMap[e.keyCode]](e); } @@ -22853,10 +22503,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot else { return; } - e.stopImmediatePropagation(); e.preventDefault(); - this.canvas && this.canvas.renderAll(); }, @@ -22906,7 +22554,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot } if (copiedText) { - this.insertChars(copiedText); + this.insertChars(copiedText, true); } }, @@ -22954,10 +22602,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot */ getDownCursorOffset: function(e, isRight) { var selectionProp = isRight ? this.selectionEnd : this.selectionStart, - textLines = this.text.split(this._reNewline), - _char, - lineLeftOffset, - + _char, lineLeftOffset, textBeforeCursor = this.text.slice(0, selectionProp), textAfterCursor = this.text.slice(selectionProp), @@ -22968,13 +22613,13 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot cursorLocation = this.get2DCursorLocation(selectionProp); // if on last line, down cursor goes to end of line - if (cursorLocation.lineIndex === textLines.length - 1 || e.metaKey || e.keyCode === 34) { + if (cursorLocation.lineIndex === this._textLines.length - 1 || e.metaKey || e.keyCode === 34) { // move to the end of a text return this.text.length - selectionProp; } - var widthOfSameLineBeforeCursor = this._getWidthOfLine(this.ctx, cursorLocation.lineIndex, textLines); + var widthOfSameLineBeforeCursor = this._getLineWidth(this.ctx, cursorLocation.lineIndex); lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor); var widthOfCharsOnSameLineBeforeCursor = lineLeftOffset, @@ -22986,7 +22631,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot } var indexOnNextLine = this._getIndexOnNextLine( - cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor, textLines); + cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor); return textOnSameLineAfterCursor.length + 1 + indexOnNextLine; }, @@ -22994,9 +22639,9 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private */ - _getIndexOnNextLine: function(cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor, textLines) { + _getIndexOnNextLine: function(cursorLocation, textOnNextLine, widthOfCharsOnSameLineBeforeCursor) { var lineIndex = cursorLocation.lineIndex + 1, - widthOfNextLine = this._getWidthOfLine(this.ctx, lineIndex, textLines), + widthOfNextLine = this._getLineWidth(this.ctx, lineIndex), lineLeftOffset = this._getLineLeftOffset(widthOfNextLine), widthOfCharsOnNextLine = lineLeftOffset, indexOnNextLine = 0, @@ -23058,15 +22703,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot */ moveCursorDownWithoutShift: function(offset) { this._selectionDirection = 'right'; - this.selectionStart += offset; - - if (this.selectionStart > this.text.length) { - this.selectionStart = this.text.length; - } - this.selectionEnd = this.selectionStart; - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + this.setSelectionStart(this.selectionStart + offset); + this.setSelectionEnd(this.selectionStart); }, /** @@ -23074,8 +22712,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot */ swapSelectionPoints: function() { var swapSel = this.selectionEnd; - this.selectionEnd = this.selectionStart; - this.selectionStart = swapSel; + this.setSelectionEnd(this.selectionStart); + this.setSelectionStart(swapSel); }, /** @@ -23086,18 +22724,19 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot if (this.selectionEnd === this.selectionStart) { this._selectionDirection = 'right'; } - var prop = this._selectionDirection === 'right' ? 'selectionEnd' : 'selectionStart'; - this[prop] += offset; + if (this._selectionDirection === 'right') { + this.setSelectionEnd(this.selectionEnd + offset); + } + else { + this.setSelectionStart(this.selectionStart + offset); + } if (this.selectionEnd < this.selectionStart && this._selectionDirection === 'left') { this.swapSelectionPoints(); this._selectionDirection = 'right'; } if (this.selectionEnd > this.text.length) { - this.selectionEnd = this.text.length; + this.setSelectionEnd(this.text.length); } - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); }, /** @@ -23116,9 +22755,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot var textBeforeCursor = this.text.slice(0, selectionProp), textOnSameLineBeforeCursor = textBeforeCursor.slice(textBeforeCursor.lastIndexOf('\n') + 1), textOnPreviousLine = (textBeforeCursor.match(/\n?(.*)\n.*$/) || {})[1] || '', - textLines = this.text.split(this._reNewline), _char, - widthOfSameLineBeforeCursor = this._getWidthOfLine(this.ctx, cursorLocation.lineIndex, textLines), + widthOfSameLineBeforeCursor = this._getLineWidth(this.ctx, cursorLocation.lineIndex), lineLeftOffset = this._getLineLeftOffset(widthOfSameLineBeforeCursor), widthOfCharsOnSameLineBeforeCursor = lineLeftOffset, lineIndex = cursorLocation.lineIndex; @@ -23129,7 +22767,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot } var indexOnPrevLine = this._getIndexOnPrevLine( - cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor, textLines); + cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor); return textOnPreviousLine.length - indexOnPrevLine + textOnSameLineBeforeCursor.length; }, @@ -23137,10 +22775,10 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private */ - _getIndexOnPrevLine: function(cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor, textLines) { + _getIndexOnPrevLine: function(cursorLocation, textOnPreviousLine, widthOfCharsOnSameLineBeforeCursor) { var lineIndex = cursorLocation.lineIndex - 1, - widthOfPreviousLine = this._getWidthOfLine(this.ctx, lineIndex, textLines), + widthOfPreviousLine = this._getLineWidth(this.ctx, lineIndex), lineLeftOffset = this._getLineLeftOffset(widthOfPreviousLine), widthOfCharsOnPreviousLine = lineLeftOffset, indexOnPrevLine = 0, @@ -23204,18 +22842,16 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot if (this.selectionEnd === this.selectionStart) { this._selectionDirection = 'left'; } - var prop = this._selectionDirection === 'right' ? 'selectionEnd' : 'selectionStart'; - this[prop] -= offset; + if (this._selectionDirection === 'right') { + this.setSelectionEnd(this.selectionEnd - offset); + } + else { + this.setSelectionStart(this.selectionStart - offset); + } if (this.selectionEnd < this.selectionStart && this._selectionDirection === 'right') { this.swapSelectionPoints(); this._selectionDirection = 'left'; } - if (this.selectionStart < 0) { - this.selectionStart = 0; - } - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); }, /** @@ -23224,17 +22860,11 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot */ moveCursorUpWithoutShift: function(offset) { if (this.selectionStart === this.selectionEnd) { - this.selectionStart -= offset; + this.setSelectionStart(this.selectionStart - offset); } - if (this.selectionStart < 0) { - this.selectionStart = 0; - } - this.selectionEnd = this.selectionStart; + this.setSelectionEnd(this.selectionStart); this._selectionDirection = 'left'; - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); }, /** @@ -23263,14 +22893,15 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @private */ _move: function(e, prop, direction) { + var propMethod = (prop === 'selectionStart' ? 'setSelectionStart' : 'setSelectionEnd'); if (e.altKey) { - this[prop] = this['findWordBoundary' + direction](this[prop]); + this[propMethod](this['findWordBoundary' + direction](this[prop])); } else if (e.metaKey || e.keyCode === 35 || e.keyCode === 36 ) { - this[prop] = this['findLineBoundary' + direction](this[prop]); + this[propMethod](this['findLineBoundary' + direction](this[prop])); } else { - this[prop] += (direction === 'Left' ? -1 : 1); + this[propMethod](this[prop] + (direction === 'Left' ? -1 : 1)); } }, @@ -23300,10 +22931,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot if (this.selectionEnd === this.selectionStart) { this._moveLeft(e, 'selectionStart'); } - this.selectionEnd = this.selectionStart; - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); + this.setSelectionEnd(this.selectionStart); }, /** @@ -23320,15 +22948,9 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot // increase selection by one if it's a newline if (this.text.charAt(this.selectionStart) === '\n') { - this.selectionStart--; - } - if (this.selectionStart < 0) { - this.selectionStart = 0; + this.setSelectionStart(this.selectionStart - 1); } } - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); }, /** @@ -23367,15 +22989,9 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot // increase selection by one if it's a newline if (this.text.charAt(this.selectionEnd - 1) === '\n') { - this.selectionEnd++; - } - if (this.selectionEnd > this.text.length) { - this.selectionEnd = this.text.length; + this.setSelectionEnd(this.selectionEnd + 1); } } - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); }, /** @@ -23387,22 +23003,16 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot if (this.selectionStart === this.selectionEnd) { this._moveRight(e, 'selectionStart'); - this.selectionEnd = this.selectionStart; + this.setSelectionEnd(this.selectionStart); } else { - this.selectionEnd += this.getNumNewLinesInSelectedText(); - if (this.selectionEnd > this.text.length) { - this.selectionEnd = this.text.length; - } - this.selectionStart = this.selectionEnd; + this.setSelectionEnd(this.selectionEnd + this.getNumNewLinesInSelectedText()); + this.setSelectionStart(this.selectionEnd); } - - this.fire('selection:changed'); - this.canvas && this.canvas.fire('text:selection:changed', { target: this }); }, /** - * Inserts a character where cursor is (replacing selection if one exists) + * Removes characters selected by selection * @param {Event} e Event object */ removeChars: function(e) { @@ -23413,15 +23023,12 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot this._removeCharsFromTo(this.selectionStart, this.selectionEnd); } - this.selectionEnd = this.selectionStart; + this.setSelectionEnd(this.selectionStart); this._removeExtraneousStyles(); - if (this.canvas) { - // TODO: double renderAll gets rid of text box shift happenning sometimes - // need to find out what exactly causes it and fix it - this.canvas.renderAll().renderAll(); - } + this._clearCache(); + this.canvas && this.canvas.renderAll(); this.setCoords(); this.fire('changed'); @@ -23440,20 +23047,19 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot var leftLineBoundary = this.findLineBoundaryLeft(this.selectionStart); this._removeCharsFromTo(leftLineBoundary, this.selectionStart); - this.selectionStart = leftLineBoundary; + this.setSelectionStart(leftLineBoundary); } else if (e.altKey) { // remove all till the start of current word var leftWordBoundary = this.findWordBoundaryLeft(this.selectionStart); this._removeCharsFromTo(leftWordBoundary, this.selectionStart); - this.selectionStart = leftWordBoundary; + this.setSelectionStart(leftWordBoundary); } else { var isBeginningOfLine = this.text.slice(this.selectionStart - 1, this.selectionStart) === '\n'; this.removeStyleObject(isBeginningOfLine); - - this.selectionStart--; + this.setSelectionStart(this.selectionStart - 1); this.text = this.text.slice(0, this.selectionStart) + this.text.slice(this.selectionStart + 1); } @@ -23468,27 +23074,26 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private */ - _setSVGTextLineText: function(textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects) { + _setSVGTextLineText: function(lineIndex, textSpans, height, textLeftOffset, textTopOffset, textBgRects) { if (!this.styles[lineIndex]) { this.callSuper('_setSVGTextLineText', - textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier); + lineIndex, textSpans, height, textLeftOffset, textTopOffset); } else { this._setSVGTextLineChars( - textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects); + lineIndex, textSpans, height, textLeftOffset, textBgRects); } }, /** * @private */ - _setSVGTextLineChars: function(textLine, lineIndex, textSpans, lineHeight, lineTopOffsetMultiplier, textBgRects) { + _setSVGTextLineChars: function(lineIndex, textSpans, height, textLeftOffset, textBgRects) { - var yProp = lineIndex === 0 || this.useNative ? 'y' : 'dy', - chars = textLine.split(''), + var chars = this._textLines[lineIndex].split(''), charOffset = 0, - lineLeftOffset = this._getSVGLineLeftOffset(lineIndex), - lineTopOffset = this._getSVGLineTopOffset(lineIndex), + lineLeftOffset = this._getSVGLineLeftOffset(lineIndex) - this.width / 2, + lineOffset = this._getSVGLineTopOffset(lineIndex), heightOfLine = this._getHeightOfLine(this.ctx, lineIndex); for (var i = 0, len = chars.length; i < len; i++) { @@ -23496,14 +23101,14 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot textSpans.push( this._createTextCharSpan( - chars[i], styleDecl, lineLeftOffset, lineTopOffset, yProp, charOffset)); + chars[i], styleDecl, lineLeftOffset, lineOffset.lineTop + lineOffset.offset, charOffset)); var charWidth = this._getWidthOfChar(this.ctx, chars[i], lineIndex, i); if (styleDecl.textBackgroundColor) { textBgRects.push( this._createTextCharBg( - styleDecl, lineLeftOffset, lineTopOffset, heightOfLine, charWidth, charOffset)); + styleDecl, lineLeftOffset, lineOffset.lineTop, heightOfLine, charWidth, charOffset)); } charOffset += charWidth; @@ -23514,20 +23119,22 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot * @private */ _getSVGLineLeftOffset: function(lineIndex) { - return (this._boundaries && this._boundaries[lineIndex]) - ? fabric.util.toFixed(this._boundaries[lineIndex].left, 2) - : 0; + return fabric.util.toFixed(this._getLineLeftOffset(this.__lineWidths[lineIndex]), 2); }, /** * @private */ _getSVGLineTopOffset: function(lineIndex) { - var lineTopOffset = 0; - for (var j = 0; j <= lineIndex; j++) { + var lineTopOffset = 0, lastHeight = 0; + for (var j = 0; j < lineIndex; j++) { lineTopOffset += this._getHeightOfLine(this.ctx, j); } - return lineTopOffset - this.height / 2; + lastHeight = this._getHeightOfLine(this.ctx, j); + return { + lineTop: lineTopOffset, + offset: (this._fontSizeMult - this._fontSizeFraction) * lastHeight / (this.lineHeight * this._fontSizeMult) + }; }, /** @@ -23537,13 +23144,10 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot return [ //jscs:disable validateIndentation '' //jscs:enable validateIndentation ].join(''); @@ -23552,7 +23156,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private */ - _createTextCharSpan: function(_char, styleDecl, lineLeftOffset, lineTopOffset, yProp, charOffset) { + _createTextCharSpan: function(_char, styleDecl, lineLeftOffset, lineTopOffset, charOffset) { var fillStyles = this.getSvgStyles.call(fabric.util.object.extend({ visible: true, @@ -23563,16 +23167,14 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot return [ //jscs:disable validateIndentation - '', - fabric.util.string.escapeXml(_char), '' //jscs:enable validateIndentation @@ -23606,7 +23208,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot } // assign request handler based on protocol - var reqHandler = ( oURL.port === 443 ) ? HTTPS : HTTP, + var reqHandler = (oURL.protocol.indexOf('https:') === 0 ) ? HTTPS : HTTP, req = reqHandler.request({ hostname: oURL.hostname, port: oURL.port, diff --git a/package.json b/package.json index 89f00c6f..20f00b9c 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "devDependencies": { "execSync": "1.0.x", "uglify-js": "2.4.x", - "jscs": "1.10.x", + "jscs": "1.8.x", "jshint": "2.6.x", "qunit": "0.7.2", "istanbul": "0.3.x"