diff --git a/HEADER.js b/HEADER.js
index 90ee7e74..6f654e12 100644
--- a/HEADER.js
+++ b/HEADER.js
@@ -1,6 +1,6 @@
/*! Fabric.js Copyright 2008-2013, Printio (Juriy Zaytsev, Maxim Chernyak) */
-var fabric = fabric || { version: "1.1.10" };
+var fabric = fabric || { version: "1.1.11" };
if (typeof exports !== 'undefined') {
exports.fabric = fabric;
diff --git a/dist/all.js b/dist/all.js
index 4e14c08a..17efa112 100644
--- a/dist/all.js
+++ b/dist/all.js
@@ -1,7 +1,7 @@
/* build: `node build.js modules=ALL exclude=gestures` */
/*! Fabric.js Copyright 2008-2013, Printio (Juriy Zaytsev, Maxim Chernyak) */
-var fabric = fabric || { version: "1.1.10" };
+var fabric = fabric || { version: "1.1.11" };
if (typeof exports !== 'undefined') {
exports.fabric = fabric;
@@ -7129,7 +7129,7 @@ fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ {
* (either those of HTMLCanvasElement itself, or rendering context)
*
* @param methodName {String} Method to check support for;
- * Could be one of "getImageData", "toDataURL" or "toDataURLWithQuality"
+ * Could be one of "getImageData", "toDataURL", "toDataURLWithQuality" or "setLineDash"
* @return {Boolean | null} `true` if method is supported (or at least exists),
* `null` if canvas element or context can not be initialized
*/
@@ -7150,6 +7150,9 @@ fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ {
case 'getImageData':
return typeof ctx.getImageData !== 'undefined';
+ case 'setLineDash':
+ return typeof ctx.setLineDash !== 'undefined';
+
case 'toDataURL':
return typeof el.toDataURL !== 'undefined';
@@ -7240,6 +7243,16 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
ctx.shadowColor = this.shadowColor || this.color;
ctx.shadowOffsetX = this.shadowOffsetX;
ctx.shadowOffsetY = this.shadowOffsetY;
+ },
+
+ /**
+ * Remove brush shadow styles
+ */
+ removeShadowStyles: function() {
+ var ctx = this.canvas.contextTop;
+
+ ctx.shadowColor = '';
+ ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;
}
});
@@ -7496,7 +7509,8 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
this.canvas.add(path);
path.setCoords();
- this.canvas.contextTop && this.canvas.clearContext(this.canvas.contextTop);
+ this.canvas.clearContext(this.canvas.contextTop);
+ this.removeShadowStyles();
this.canvas.renderAll();
// fire event 'path' created
@@ -7576,6 +7590,8 @@ fabric.CircleBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabri
this.canvas.add(circle);
}
+ this.canvas.clearContext(this.canvas.contextTop);
+ this.removeShadowStyles();
this.canvas.renderOnAddition = originalRenderOnAddition;
this.canvas.renderAll();
},
@@ -7701,8 +7717,9 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric
}
}
- this.canvas.renderOnAddition = originalRenderOnAddition;
this.canvas.clearContext(this.canvas.contextTop);
+ this.removeShadowStyles();
+ this.canvas.renderOnAddition = originalRenderOnAddition;
this.canvas.renderAll();
},
@@ -9638,7 +9655,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
extend = fabric.util.object.extend,
toFixed = fabric.util.toFixed,
capitalize = fabric.util.string.capitalize,
- degreesToRadians = fabric.util.degreesToRadians;
+ degreesToRadians = fabric.util.degreesToRadians,
+ supportsLineDash = fabric.StaticCanvas.supports('setLineDash');
if (fabric.Object) {
return;
@@ -10060,7 +10078,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
return [
"stroke: ", (this.stroke ? this.stroke : 'none'), "; ",
"stroke-width: ", (this.strokeWidth ? this.strokeWidth : '0'), "; ",
- "stroke-dasharray: ", (this.strokeDashArray ? this.strokeDashArray.join(' ') : "; "),
+ "stroke-dasharray: ", (this.strokeDashArray ? this.strokeDashArray.join(' ') : ''), "; ",
"fill: ", (this.fill ? (this.fill && this.fill.toLive ? 'url(#SVGID_' + this.fill.id + ')' : this.fill) : 'none'), "; ",
"opacity: ", (typeof this.opacity !== 'undefined' ? this.opacity : '1'), ";",
(this.visible ? '' : " visibility: hidden;")
@@ -10269,6 +10287,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
/**
* @private
+ * @param {CanvasRenderingContext2D} ctx Context to render on
*/
_setShadow: function(ctx) {
if (!this.shadow) return;
@@ -10281,6 +10300,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
/**
* @private
+ * @param {CanvasRenderingContext2D} ctx Context to render on
*/
_removeShadow: function(ctx) {
ctx.shadowColor = '';
@@ -10289,6 +10309,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
/**
* @private
+ * @param {CanvasRenderingContext2D} ctx Context to render on
*/
_renderFill: function(ctx) {
if (!this.fill) return;
@@ -10303,6 +10324,37 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
if (this.fill.toLive) {
ctx.restore();
}
+ if (this.shadow && !this.shadow.affectStroke) {
+ this._removeShadow(ctx);
+ }
+ },
+
+ /**
+ * @private
+ * @param {CanvasRenderingContext2D} ctx Context to render on
+ */
+ _renderStroke: function(ctx) {
+ if (!this.stroke && !this.strokeDashArray) return;
+
+ 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) {
+ this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray);
+ }
+
+ if (supportsLineDash) {
+ ctx.setLineDash(this.strokeDashArray);
+ this._stroke && this._stroke(ctx);
+ }
+ else {
+ this._renderDashedStroke && this._renderDashedStroke(ctx);
+ }
+ ctx.stroke();
+ }
+ else {
+ this._stroke ? this._stroke(ctx) : ctx.stroke();
+ }
+ this._removeShadow(ctx);
},
/**
@@ -11743,7 +11795,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
var fabric = global.fabric || (global.fabric = { }),
extend = fabric.util.object.extend,
- coordProps = { 'x1': 1, 'x2': 1, 'y1': 1, 'y2': 1 };
+ coordProps = { 'x1': 1, 'x2': 1, 'y1': 1, 'y2': 1 },
+ supportsLineDash = fabric.StaticCanvas.supports('setLineDash');
if (fabric.Line) {
fabric.warn('fabric.Line is already defined');
@@ -11828,9 +11881,11 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
ctx.translate(this.left, this.top);
}
- // move from center (of virtual box) to its left/top corner
- ctx.moveTo(this.width === 1 ? 0 : (-this.width / 2), this.height === 1 ? 0 : (-this.height / 2));
- ctx.lineTo(this.width === 1 ? 0 : (this.width / 2), this.height === 1 ? 0 : (this.height / 2));
+ if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) {
+ // move from center (of virtual box) to its left/top corner
+ ctx.moveTo(this.width === 1 ? 0 : (-this.width / 2), this.height === 1 ? 0 : (-this.height / 2));
+ ctx.lineTo(this.width === 1 ? 0 : (this.width / 2), this.height === 1 ? 0 : (this.height / 2));
+ }
ctx.lineWidth = this.strokeWidth;
@@ -11839,10 +11894,23 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
// (by copying fillStyle to strokeStyle, since line is stroked, not filled)
var origStrokeStyle = ctx.strokeStyle;
ctx.strokeStyle = this.stroke || ctx.fillStyle;
- ctx.stroke();
+ this._renderStroke(ctx);
ctx.strokeStyle = origStrokeStyle;
},
+ /**
+ * @private
+ * @param {CanvasRenderingContext2D} ctx Context to render on
+ */
+ _renderDashedStroke: function(ctx) {
+ var x = this.width === 1 ? 0 : -this.width / 2,
+ y = this.height === 1 ? 0 : -this.height / 2;
+
+ ctx.beginPath();
+ fabric.util.drawDashedLine(ctx, x, y, -x, -y, this.strokeDashArray);
+ ctx.closePath();
+ },
+
/**
* Returns complexity of an instance
* @return {Number} complexity
@@ -12017,11 +12085,9 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
ctx.globalAlpha = this.group ? (ctx.globalAlpha * this.opacity) : this.opacity;
ctx.arc(noTransform ? this.left : 0, noTransform ? this.top : 0, this.radius, 0, piBy2, false);
ctx.closePath();
+
this._renderFill(ctx);
- this._removeShadow(ctx);
- if (this.stroke) {
- ctx.stroke();
- }
+ this._renderStroke(ctx);
},
/**
@@ -12166,10 +12232,22 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
ctx.closePath();
this._renderFill(ctx);
+ this._renderStroke(ctx);
+ },
- if (this.stroke) {
- ctx.stroke();
- }
+ /**
+ * @private
+ * @param ctx {CanvasRenderingContext2D} Context to render on
+ */
+ _renderDashedStroke: function(ctx) {
+ var widthBy2 = this.width / 2,
+ heightBy2 = this.height / 2;
+
+ ctx.beginPath();
+ fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray);
+ fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray);
+ fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray);
+ ctx.closePath();
},
/**
@@ -12344,11 +12422,9 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
}
ctx.transform(1, 0, 0, this.ry/this.rx, 0, 0);
ctx.arc(noTransform ? this.left : 0, noTransform ? this.top : 0, this.rx, 0, piBy2, false);
- if (this.stroke) {
- ctx.stroke();
- }
- this._removeShadow(ctx);
+
this._renderFill(ctx);
+ this._renderStroke(ctx);
ctx.restore();
},
@@ -12530,74 +12606,25 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
ctx.closePath();
this._renderFill(ctx);
- this._removeShadow(ctx);
-
- if (this.strokeDashArray) {
- this._renderDashedStroke(ctx);
- }
- else if (this.stroke) {
- ctx.stroke();
- }
+ this._renderStroke(ctx);
},
/**
* @private
+ * @param ctx {CanvasRenderingContext2D} context to render on
*/
_renderDashedStroke: function(ctx) {
+ var x = -this.width/2,
+ y = -this.height/2,
+ w = this.width,
+ h = this.height;
- if (1 & this.strokeDashArray.length /* if odd number of items */) {
- /* duplicate items */
- this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray);
- }
-
- var i = 0,
- x = -this.width/2, y = -this.height/2,
- _this = this,
- padding = this.padding,
- dashedArrayLength = this.strokeDashArray.length;
-
- ctx.save();
ctx.beginPath();
-
- /** @ignore */
- function renderSide(xMultiplier, yMultiplier) {
-
- var lineLength = 0,
- lengthDiff = 0,
- sideLength = (yMultiplier ? _this.height : _this.width) + padding * 2;
-
- while (lineLength < sideLength) {
-
- var lengthOfSubPath = _this.strokeDashArray[i++];
- lineLength += lengthOfSubPath;
-
- if (lineLength > sideLength) {
- lengthDiff = lineLength - sideLength;
- }
-
- // track coords
- if (xMultiplier) {
- x += (lengthOfSubPath * xMultiplier) - (lengthDiff * xMultiplier || 0);
- }
- else {
- y += (lengthOfSubPath * yMultiplier) - (lengthDiff * yMultiplier || 0);
- }
-
- ctx[1 & i /* odd */ ? 'moveTo' : 'lineTo'](x, y);
- if (i >= dashedArrayLength) {
- i = 0;
- }
- }
- }
-
- renderSide(1, 0);
- renderSide(0, 1);
- renderSide(-1, 0);
- renderSide(0, -1);
-
- ctx.stroke();
+ fabric.util.drawDashedLine(ctx, x, y, x+w, y, this.strokeDashArray);
+ fabric.util.drawDashedLine(ctx, x+w, y, x+w, y+h, this.strokeDashArray);
+ fabric.util.drawDashedLine(ctx, x+w, y+h, x, y+h, this.strokeDashArray);
+ fabric.util.drawDashedLine(ctx, x, y+h, x, y, this.strokeDashArray);
ctx.closePath();
- ctx.restore();
},
/**
@@ -12741,7 +12768,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* Constructor
* @param {Array} points array of points
* @param {Object} [options] Options object
- * @param {Boolean} Whether points offsetting should be skipped
+ * @param {Boolean} skipOffset Whether points offsetting should be skipped
* @return {fabric.Polyline} thisArg
*/
initialize: function(points, options, skipOffset) {
@@ -12753,6 +12780,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
/**
* @private
+ * @param {Boolean} skipOffset Whether points offsetting should be skipped
*/
_calcDimensions: function(skipOffset) {
return fabric.Polygon.prototype._calcDimensions.call(this, skipOffset);
@@ -12809,10 +12837,23 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
point = this.points[i];
ctx.lineTo(point.x, point.y);
}
+
this._renderFill(ctx);
- this._removeShadow(ctx);
- if (this.stroke) {
- ctx.stroke();
+ this._renderStroke(ctx);
+ },
+
+ /**
+ * @private
+ * @param {CanvasRenderingContext2D} ctx Context to render on
+ */
+ _renderDashedStroke: function(ctx) {
+ var p1, p2;
+
+ ctx.beginPath();
+ for (var i = 0, len = this.points.length; i < len; i++) {
+ p1 = this.points[i];
+ p2 = this.points[i+1] || p1;
+ fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray);
}
},
@@ -12995,13 +13036,28 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
ctx.lineTo(point.x, point.y);
}
this._renderFill(ctx);
- this._removeShadow(ctx);
- if (this.stroke) {
+ if (this.stroke || this.strokeDashArray) {
ctx.closePath();
- ctx.stroke();
+ this._renderStroke(ctx);
}
},
+ /**
+ * @private
+ * @param ctx {CanvasRenderingContext2D} context to render on
+ */
+ _renderDashedStroke: function(ctx) {
+ var p1, p2;
+
+ ctx.beginPath();
+ for (var i = 0, len = this.points.length; i < len; i++) {
+ p1 = this.points[i];
+ p2 = this.points[i+1] || this.points[0];
+ fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray);
+ }
+ ctx.closePath();
+ },
+
/**
* Returns complexity of an instance
* @return {Number} complexity of this instance
@@ -13618,17 +13674,14 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
this._render(ctx);
this._renderFill(ctx);
- this.clipTo && ctx.restore();
- if (this.shadow && !this.shadow.affectStroke) {
- this._removeShadow(ctx);
- }
-
if (this.stroke) {
ctx.strokeStyle = this.stroke;
ctx.lineWidth = this.strokeWidth;
ctx.lineCap = ctx.lineJoin = 'round';
- ctx.stroke();
+ this._renderStroke(ctx);
}
+ this.clipTo && ctx.restore();
+
this._removeShadow(ctx);
if (!noTransform && this.active) {
@@ -14680,12 +14733,11 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
this._setShadow(ctx);
this.clipTo && fabric.util.clipContext(this, ctx);
this._render(ctx);
- this.clipTo && ctx.restore();
- this._removeShadow(ctx);
-
- if (this.stroke) {
- this._stroke(ctx);
+ if (this.shadow && !this.shadow.affectStroke) {
+ this._removeShadow(ctx);
}
+ this._renderStroke(ctx);
+ this.clipTo && ctx.restore();
if (this.active && !noTransform) {
this.drawBorders(ctx);
@@ -14694,18 +14746,40 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
ctx.restore();
},
+ /**
+ * @private
+ * @param {CanvasRenderingContext2D} ctx Context to render on
+ */
_stroke: function(ctx) {
ctx.save();
ctx.lineWidth = this.strokeWidth;
ctx.strokeStyle = this.stroke;
- ctx.strokeRect(
- -this.width / 2,
- -this.height / 2,
- this.width,
- this.height);
+ ctx.beginPath();
+ ctx.strokeRect(-this.width / 2, -this.height / 2, this.width, this.height);
+ ctx.beginPath();
ctx.restore();
},
+ /**
+ * @private
+ * @param {CanvasRenderingContext2D} ctx Context to render on
+ */
+ _renderDashedStroke: function(ctx) {
+ var x = -this.width/2,
+ y = -this.height/2,
+ w = this.width,
+ h = this.height;
+
+ ctx.lineWidth = this.strokeWidth;
+ ctx.strokeStyle = this.stroke;
+ ctx.beginPath();
+ fabric.util.drawDashedLine(ctx, x, y, x+w, y, this.strokeDashArray);
+ fabric.util.drawDashedLine(ctx, x+w, y, x+w, y+h, this.strokeDashArray);
+ fabric.util.drawDashedLine(ctx, x+w, y+h, x, y+h, this.strokeDashArray);
+ fabric.util.drawDashedLine(ctx, x, y+h, x, y, this.strokeDashArray);
+ ctx.closePath();
+ },
+
/**
* Returns object representation of an instance
* @param {Array} propertiesToInclude
@@ -14723,16 +14797,37 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* @return {String} svg representation of an instance
*/
toSVG: function() {
- return '
-1},complexity:function(){return this.getObjects().reduce(function(e,t){return e+=t.complexity?t.complexity():0,e},0)},toGrayscale:function(){return this.forEachObject(function(e){e.toGrayscale()})}},function(){function n(e,t){var n=e.indexOf(t);return n!==-1&&e.splice(n,1),e}function r(e,t){return Math.floor(Math.random()*(t-e+1))+e}function s(e){return e*i}function o(e){return e/i}function u(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)}function a(e,t){return parseFloat(Number(e).toFixed(t))}function f(){return!1}function l(e){e||(e={});var t=+(new Date),n=e.duration||500,r=t+n,i,s=e.onChange||function(){},o=e.abort||function(){return!1},u=e.easing||function(e,t,n,r){return-n*Math.cos(e/r*(Math.PI/2))+n+t},a="startValue"in e?e.startValue:0,f="endValue"in e?e.endValue:100,l=e.byValue||f-a;e.onStart&&e.onStart(),function c(){i=+(new Date);var f=i>r?n:i-t;s(u(f,a,l,n));if(i>r||o()){e.onComplete&&e.onComplete();return}h(c)}()}function p(e,t,n){if(e){var r=fabric.util.createImage();r.onload=function(){t&&t.call(n,r),r=r.onload=null},r.src=e}else t&&t.call(n,e)}function d(e,t){function n(e){return fabric[fabric.util.string.camelize(fabric.util.string.capitalize(e))]}function r(){++s===o&&t&&t(i)}var i=[],s=0,o=e.length;e.forEach(function(e,t){if(!e.type)return;var s=n(e.type);s.async?s.fromObject(e,function(e,n){n||(i[t]=e),r()}):(i[t]=s.fromObject(e),r())})}function v(e,t,n){var r;return e.length>1?r=new fabric.PathGroup(e,t):r=e[0],typeof n!="undefined"&&r.setSourcePath(n),r}function m(e,t,n){if(n&&Object.prototype.toString.call(n)==="[object Array]")for(var r=0,i=n.length;rr)r+=u[p++%h],r>l&&(r=l),n[d?"lineTo":"moveTo"](r,0),d=!d;n.restore()}function y(e){return e||(e=fabric.document.createElement("canvas")),!e.getContext&&typeof G_vmlCanvasManager!="undefined"&&G_vmlCanvasManager.initElement(e),e}function b(){return fabric.isLikelyNode?new(require("canvas").Image):fabric.document.createElement("img")}function w(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))}}function E(e,t){t.save(),t.beginPath(),e.clipTo(t),t.clip()}function S(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]]}var e=Math.sqrt,t=Math.atan2;fabric.util={};var i=Math.PI/180,c=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(e){fabric.window.setTimeout(e,1e3/60)},h=function(){return c.apply(fabric.window,arguments)};fabric.util.removeFromArray=n,fabric.util.degreesToRadians=s,fabric.util.radiansToDegrees=o,fabric.util.rotatePoint=u,fabric.util.toFixed=a,fabric.util.getRandomInt=r,fabric.util.falseFunction=f,fabric.util.animate=l,fabric.util.requestAnimFrame=h,fabric.util.loadImage=p,fabric.util.enlivenObjects=d,fabric.util.groupSVGElements=v,fabric.util.populateWithProperties=m,fabric.util.drawDashedLine=g,fabric.util.createCanvasElement=y,fabric.util.createImage=b,fabric.util.createAccessors=w,fabric.util.clipContext=E,fabric.util.multiplyTransformMatrices=S}(),function(){function t(t,n){var r=e.call(arguments,2),i=[];for(var s=0,o=t.length;s -1},complexity:function(){return this.getObjects().reduce(function(e,t){return e+=t.complexity?t.complexity():0,e},0)},toGrayscale:function(){return this.forEachObject(function(e){e.toGrayscale()})}},function(){function n(e,t){var n=e.indexOf(t);return n!==-1&&e.splice(n,1),e}function r(e,t){return Math.floor(Math.random()*(t-e+1))+e}function s(e){return e*i}function o(e){return e/i}function u(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)}function a(e,t){return parseFloat(Number(e).toFixed(t))}function f(){return!1}function l(e){e||(e={});var t=+(new Date),n=e.duration||500,r=t+n,i,s=e.onChange||function(){},o=e.abort||function(){return!1},u=e.easing||function(e,t,n,r){return-n*Math.cos(e/r*(Math.PI/2))+n+t},a="startValue"in e?e.startValue:0,f="endValue"in e?e.endValue:100,l=e.byValue||f-a;e.onStart&&e.onStart(),function c(){i=+(new Date);var f=i>r?n:i-t;s(u(f,a,l,n));if(i>r||o()){e.onComplete&&e.onComplete();return}h(c)}()}function p(e,t,n){if(e){var r=fabric.util.createImage();r.onload=function(){t&&t.call(n,r),r=r.onload=null},r.src=e}else t&&t.call(n,e)}function d(e,t){function n(e){return fabric[fabric.util.string.camelize(fabric.util.string.capitalize(e))]}function r(){++s===o&&t&&t(i)}var i=[],s=0,o=e.length;e.forEach(function(e,t){if(!e.type)return;var s=n(e.type);s.async?s.fromObject(e,function(e,n){n||(i[t]=e),r()}):(i[t]=s.fromObject(e),r())})}function v(e,t,n){var r;return e.length>1?r=new fabric.PathGroup(e,t):r=e[0],typeof n!="undefined"&&r.setSourcePath(n),r}function m(e,t,n){if(n&&Object.prototype.toString.call(n)==="[object Array]")for(var r=0,i=n.length;rr)r+=u[p++%h],r>l&&(r=l),n[d?"lineTo":"moveTo"](r,0),d=!d;n.restore()}function y(e){return e||(e=fabric.document.createElement("canvas")),!e.getContext&&typeof G_vmlCanvasManager!="undefined"&&G_vmlCanvasManager.initElement(e),e}function b(){return fabric.isLikelyNode?new(require("canvas").Image):fabric.document.createElement("img")}function w(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))}}function E(e,t){t.save(),t.beginPath(),e.clipTo(t),t.clip()}function S(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]]}var e=Math.sqrt,t=Math.atan2;fabric.util={};var i=Math.PI/180,c=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(e){fabric.window.setTimeout(e,1e3/60)},h=function(){return c.apply(fabric.window,arguments)};fabric.util.removeFromArray=n,fabric.util.degreesToRadians=s,fabric.util.radiansToDegrees=o,fabric.util.rotatePoint=u,fabric.util.toFixed=a,fabric.util.getRandomInt=r,fabric.util.falseFunction=f,fabric.util.animate=l,fabric.util.requestAnimFrame=h,fabric.util.loadImage=p,fabric.util.enlivenObjects=d,fabric.util.groupSVGElements=v,fabric.util.populateWithProperties=m,fabric.util.drawDashedLine=g,fabric.util.createCanvasElement=y,fabric.util.createImage=b,fabric.util.createAccessors=w,fabric.util.clipContext=E,fabric.util.multiplyTransformMatrices=S}(),function(){function t(t,n){var r=e.call(arguments,2),i=[];for(var s=0,o=t.length;s>>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>>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(;n0&&(i.status="Intersection"),i},t.Intersection.intersectPolygonPolygon=function(e,t){var r=new n("No Intersection"),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("No Intersection");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])}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]),t=n.sourceFromHex(e),t||(t=n.sourceFromRgb(e)),t&&this.setSource(t)},getSource:function(){return this._source},setSource:function(e){this._source=e},toRgb:function(){var e=this.getSource();return"rgb("+e[0]+","+e[1]+","+e[2]+")"},toRgba:function(){var e=this.getSource();return"rgba("+e[0]+","+e[1]+","+e[2]+","+e[3]+")"},toHex:function(){var e=this.getSource(),t=e[0].toString(16);t=t.length===1?"0"+t:t;var n=e[1].toString(16);n=n.length===1?"0"+n:n;var r=e[2].toString(16);return r=r.length===1?"0"+r:r,t.toUpperCase()+n.toUpperCase()+r.toUpperCase()},getAlpha:function(){return this.getSource()[3]},setAlpha:function(e){var t=this.getSource();return t[3]=e,this.setSource(t),this},toGrayscale:function(){var e=this.getSource(),t=parseInt((e[0]*.3+e[1]*.59+e[2]*.11).toFixed(0),10),n=e[3];return this.setSource([t,t,t,n]),this},toBlackWhite:function(e){var t=this.getSource(),n=(t[0]*.3+t[1]*.59+t[2]*.11).toFixed(0),r=t[3];return e=e||127,n=Number(n)