From 75a71e3b51f456112306a73100f77530bc12d2bd Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sat, 10 Feb 2018 13:39:46 +0100 Subject: [PATCH] Version 2.0.1 (#4707) * removed gz and require * added changelog and changes --- .gitignore | 2 + .npmignore | 1 + CHANGELOG.md | 5 + HEADER.js | 2 +- dist/fabric.js | 18 +- dist/fabric.min.js | 2 +- dist/fabric.min.js.gz | Bin 79012 -> 0 bytes dist/fabric.require.js | 13800 --------------------------------------- package.json | 2 +- 9 files changed, 20 insertions(+), 13812 deletions(-) delete mode 100644 dist/fabric.min.js.gz delete mode 100644 dist/fabric.require.js diff --git a/.gitignore b/.gitignore index eb188e73..abb7a60c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ before_commit /coverage/ .idea/ +/dist/fabric.require.js +/dist/fabric.min.js.gz diff --git a/.npmignore b/.npmignore index ad5bfd93..c0801f4f 100644 --- a/.npmignore +++ b/.npmignore @@ -3,6 +3,7 @@ lib/ dist/all.min.js dist/all.min.js.gz dist/fabric.min.js +dist/fabric.require.js dist/fabric.min.js.gz .DS_Store HEADER.js diff --git a/CHANGELOG.md b/CHANGELOG.md index c19f30e5..ce27ffc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +**Version 2.0.1** + - fixed filter for blend image in WEBGL [#4706](https://github.com/kangax/fabric.js/pull/4706) + - fixed interactions between canvas toDataURL and multiplier + retina [#4705](https://github.com/kangax/fabric.js/pull/4705) + - fixed bug with originX and originY not invalidating the transform [#4703](https://github.com/kangax/fabric.js/pull/4703) + - fixed unwanted mutation on object enliving in fabric.Image [#4699](https://github.com/kangax/fabric.js/pull/4699) **Version 2.0.0** - final - fix dataurl and svg export on retina and rounding [#4674](https://github.com/kangax/fabric.js/pull/4674) diff --git a/HEADER.js b/HEADER.js index 3c1d978c..e5f0f414 100644 --- a/HEADER.js +++ b/HEADER.js @@ -1,6 +1,6 @@ /*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */ -var fabric = fabric || { version: '2.0.0' }; +var fabric = fabric || { version: '2.0.1' }; if (typeof exports !== 'undefined') { exports.fabric = fabric; } diff --git a/dist/fabric.js b/dist/fabric.js index 813ec700..a2b0bdab 100644 --- a/dist/fabric.js +++ b/dist/fabric.js @@ -1,7 +1,7 @@ /* build: `node build.js modules=ALL exclude=gestures,accessors minifier=uglifyjs` */ - /*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */ +/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */ -var fabric = fabric || { version: '2.0.0-rc.4' }; +var fabric = fabric || { version: '2.0.1' }; if (typeof exports !== 'undefined') { exports.fabric = fabric; } @@ -11629,7 +11629,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab var format = options.format || 'png', quality = options.quality || 1, - multiplier = options.multiplier || options.enableRetinaScaling ? 1 : 1 / this.getRetinaScaling(), + multiplier = (options.multiplier || 1) * (options.enableRetinaScaling ? 1 : 1 / this.getRetinaScaling()), cropping = { left: options.left || 0, top: options.top || 0, @@ -14246,7 +14246,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati * Returns coordinates of object's bounding rectangle (left, top, width, height) * the box is intented as aligned to axis of canvas. * @param {Boolean} [absolute] use coordinates without viewportTransform - * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords + * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords / .aCoords * @return {Object} Object with left, top, width, height properties */ getBoundingRect: function(absolute, calculate) { @@ -14433,7 +14433,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati prefix = this.group.transformMatrixKey(skipGroup) + sep; }; return prefix + this.top + sep + this.left + sep + this.scaleX + sep + this.scaleY + - sep + this.skewX + sep + this.skewY + sep + this.angle + + sep + this.skewX + sep + this.skewY + sep + this.angle + sep + this.originX + sep + this.originY + sep + this.width + sep + this.height + sep + this.strokeWidth + this.flipX + this.flipY; }, @@ -19351,7 +19351,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * @param {Object} object Object to create an instance from * @param {Function} callback Callback to invoke when an image instance is created */ - fabric.Image.fromObject = function(object, callback) { + fabric.Image.fromObject = function(_object, callback) { + var object = fabric.util.object.clone(_object); fabric.util.loadImage(object.src, function(img, error) { if (error) { callback && callback(null, error); @@ -22121,13 +22122,12 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) { alpha: 1, vertexSource: 'attribute vec2 aPosition;\n' + - 'attribute vec2 aTexCoord;\n' + 'varying vec2 vTexCoord;\n' + 'varying vec2 vTexCoord2;\n' + 'uniform mat3 uTransformMatrix;\n' + 'void main() {\n' + - 'vTexCoord = aTexCoord;\n' + - 'vTexCoord2 = (uTransformMatrix * vec3(aTexCoord, 1.0)).xy;\n' + + 'vTexCoord = aPosition;\n' + + 'vTexCoord2 = (uTransformMatrix * vec3(aPosition, 1.0)).xy;\n' + 'gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\n' + '}', diff --git a/dist/fabric.min.js b/dist/fabric.min.js index 1725de56..267e7c31 100644 --- a/dist/fabric.min.js +++ b/dist/fabric.min.js @@ -1 +1 @@ -function resizeCanvasIfNeeded(t){var e=t.targetCanvas,i=e.width,r=e.height,n=t.destinationWidth,s=t.destinationHeight;i===n&&r===s||(e.width=n,e.height=s)}function copyGLTo2DDrawImage(t,e){var i=t.canvas,r=e.targetCanvas,n=r.getContext("2d");n.translate(0,r.height),n.scale(1,-1);var s=i.height-r.height;n.drawImage(i,0,s,r.width,r.height,0,0,r.width,r.height)}function copyGLTo2DPutImageData(t,e){var i=e.targetCanvas.getContext("2d"),r=e.destinationWidth,n=e.destinationHeight,s=r*n*4,o=new Uint8Array(this.imageBuffer,0,s),a=new Uint8ClampedArray(this.imageBuffer,0,s);t.readPixels(0,0,r,n,t.RGBA,t.UNSIGNED_BYTE,o);var h=new ImageData(a,r,n);i.putImageData(h,0,0)}var fabric=fabric||{version:"2.0.0-rc.4"};"undefined"!=typeof exports&&(exports.fabric=fabric),"undefined"!=typeof document&&"undefined"!=typeof window?(fabric.document=document,fabric.window=window):(fabric.document=require("jsdom").jsdom(decodeURIComponent("%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E"),{features:{FetchExternalResources:["img"]}}),fabric.jsdomImplForWrapper=require("jsdom/lib/jsdom/living/generated/utils").implForWrapper,fabric.nodeCanvas=require("jsdom/lib/jsdom/utils").Canvas,fabric.window=fabric.document.defaultView,DOMParser=require("xmldom").DOMParser),fabric.isTouchSupported="ontouchstart"in fabric.window,fabric.isLikelyNode="undefined"!=typeof Buffer&&"undefined"==typeof window,fabric.SHARED_ATTRIBUTES=["display","transform","fill","fill-opacity","fill-rule","opacity","stroke","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","id","paint-order","instantiated_by_use"],fabric.DPI=96,fabric.reNum="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",fabric.fontPaths={},fabric.iMatrix=[1,0,0,1,0,0],fabric.canvasModule="canvas",fabric.perfLimitSizeTotal=2097152,fabric.maxCacheSideLimit=4096,fabric.minCacheSideLimit=256,fabric.charWidthsCache={},fabric.textureSize=2048,fabric.enableGLFiltering=!0,fabric.devicePixelRatio=fabric.window.devicePixelRatio||fabric.window.webkitDevicePixelRatio||fabric.window.mozDevicePixelRatio||1,fabric.browserShadowBlurConstant=1,fabric.initFilterBackend=function(){return fabric.enableGLFiltering&&fabric.isWebglSupported&&fabric.isWebglSupported(fabric.textureSize)?(console.log("max texture size: "+fabric.maxTextureSize),new fabric.WebglFilterBackend({tileSize:fabric.textureSize})):fabric.Canvas2dFilterBackend?new fabric.Canvas2dFilterBackend:void 0},"undefined"!=typeof document&&"undefined"!=typeof window&&(window.fabric=fabric),function(){function t(t,e){if(this.__eventListeners[t]){var i=this.__eventListeners[t];e?i[i.indexOf(e)]=!1:fabric.util.array.fill(i,!1)}}function e(t,e){if(this.__eventListeners||(this.__eventListeners={}),1===arguments.length)for(var i in t)this.on(i,t[i]);else this.__eventListeners[t]||(this.__eventListeners[t]=[]),this.__eventListeners[t].push(e);return this}function i(e,i){if(this.__eventListeners){if(0===arguments.length)for(e in this.__eventListeners)t.call(this,e);else if(1===arguments.length&&"object"==typeof arguments[0])for(var r in e)t.call(this,r,e[r]);else t.call(this,e,i);return this}}function r(t,e){if(this.__eventListeners){var i=this.__eventListeners[t];if(i){for(var r=0,n=i.length;r-1},complexity:function(){return this.getObjects().reduce(function(t,e){return t+=e.complexity?e.complexity():0},0)}},fabric.CommonMethods={_setOptions:function(t){for(var e in t)this.set(e,t[e])},_initGradient:function(t,e){!t||!t.colorStops||t instanceof fabric.Gradient||this.set(e,new fabric.Gradient(t))},_initPattern:function(t,e,i){!t||!t.source||t instanceof fabric.Pattern?i&&i():this.set(e,new fabric.Pattern(t,i))},_initClipping:function(t){if(t.clipTo&&"string"==typeof t.clipTo){var e=fabric.util.getFunctionBody(t.clipTo);void 0!==e&&(this.clipTo=new Function("ctx",e))}},_setObject:function(t){for(var e in t)this._set(e,t[e])},set:function(t,e){return"object"==typeof t?this._setObject(t):"function"==typeof e&&"clipTo"!==t?this._set(t,e(this.get(t))):this._set(t,e),this},_set:function(t,e){this[t]=e},toggle:function(t){var e=this.get(t);return"boolean"==typeof e&&this.set(t,!e),this},get:function(t){return this[t]}},function(t){var e=Math.sqrt,i=Math.atan2,r=Math.pow,n=Math.abs,s=Math.PI/180;fabric.util={removeFromArray:function(t,e){var i=t.indexOf(e);return-1!==i&&t.splice(i,1),t},getRandomInt:function(t,e){return Math.floor(Math.random()*(e-t+1))+t},degreesToRadians:function(t){return t*s},radiansToDegrees:function(t){return t/s},rotatePoint:function(t,e,i){t.subtractEquals(e);var r=fabric.util.rotateVector(t,i);return new fabric.Point(r.x,r.y).addEquals(e)},rotateVector:function(t,e){var i=Math.sin(e),r=Math.cos(e);return{x:t.x*r-t.y*i,y:t.x*i+t.y*r}},transformPoint:function(t,e,i){return i?new fabric.Point(e[0]*t.x+e[2]*t.y,e[1]*t.x+e[3]*t.y):new fabric.Point(e[0]*t.x+e[2]*t.y+e[4],e[1]*t.x+e[3]*t.y+e[5])},makeBoundingBoxFromPoints:function(t){var e=[t[0].x,t[1].x,t[2].x,t[3].x],i=fabric.util.array.min(e),r=fabric.util.array.max(e)-i,n=[t[0].y,t[1].y,t[2].y,t[3].y],s=fabric.util.array.min(n);return{left:i,top:s,width:r,height:fabric.util.array.max(n)-s}},invertTransform:function(t){var e=1/(t[0]*t[3]-t[1]*t[2]),i=[e*t[3],-e*t[1],-e*t[2],e*t[0]],r=fabric.util.transformPoint({x:t[4],y:t[5]},i,!0);return i[4]=-r.x,i[5]=-r.y,i},toFixed:function(t,e){return parseFloat(Number(t).toFixed(e))},parseUnit:function(t,e){var i=/\D{0,2}$/.exec(t),r=parseFloat(t);switch(e||(e=fabric.Text.DEFAULT_SVG_FONT_SIZE),i[0]){case"mm":return r*fabric.DPI/25.4;case"cm":return r*fabric.DPI/2.54;case"in":return r*fabric.DPI;case"pt":return r*fabric.DPI/72;case"pc":return r*fabric.DPI/72*12;case"em":return r*e;default:return r}},falseFunction:function(){return!1},getKlass:function(t,e){return t=fabric.util.string.camelize(t.charAt(0).toUpperCase()+t.slice(1)),fabric.util.resolveNamespace(e)[t]},getSvgAttributes:function(t){var e=["instantiated_by_use","style","id","class"];switch(t){case"linearGradient":e=e.concat(["x1","y1","x2","y2","gradientUnits","gradientTransform"]);break;case"radialGradient":e=e.concat(["gradientUnits","gradientTransform","cx","cy","r","fx","fy","fr"]);break;case"stop":e=e.concat(["offset","stop-color","stop-opacity"])}return e},resolveNamespace:function(e){if(!e)return fabric;var i,r=e.split("."),n=r.length,s=t||fabric.window;for(i=0;ir;)(r+=a[d++%f])>l&&(r=l),t[g?"lineTo":"moveTo"](r,0),g=!g;t.restore()},createCanvasElement:function(){return fabric.document.createElement("canvas")},createImage:function(){return fabric.document.createElement("img")},clipContext:function(t,e){e.save(),e.beginPath(),t.clipTo(e),e.clip()},multiplyTransformMatrices:function(t,e,i){return[t[0]*e[0]+t[2]*e[1],t[1]*e[0]+t[3]*e[1],t[0]*e[2]+t[2]*e[3],t[1]*e[2]+t[3]*e[3],i?0:t[0]*e[4]+t[2]*e[5]+t[4],i?0:t[1]*e[4]+t[3]*e[5]+t[5]]},qrDecompose:function(t){var n=i(t[1],t[0]),o=r(t[0],2)+r(t[1],2),a=e(o),h=(t[0]*t[3]-t[2]*t[1])/a,c=i(t[0]*t[2]+t[1]*t[3],o);return{angle:n/s,scaleX:a,scaleY:h,skewX:c/s,skewY:0,translateX:t[4],translateY:t[5]}},customTransformMatrix:function(t,e,i){var r=[1,0,n(Math.tan(i*s)),1],o=[n(t),0,0,n(e)];return fabric.util.multiplyTransformMatrices(o,r,!0)},resetObjectTransform:function(t){t.scaleX=1,t.scaleY=1,t.skewX=0,t.skewY=0,t.flipX=!1,t.flipY=!1,t.rotate(0)},getFunctionBody:function(t){return(String(t).match(/function[^{]*\{([\s\S]*)\}/)||{})[1]},isTransparent:function(t,e,i,r){r>0&&(e>r?e-=r:e=0,i>r?i-=r:i=0);var n,s,o=!0,a=t.getImageData(e,i,2*r||1,2*r||1),h=a.data.length;for(n=3;n0?P-=2*f:1===c&&P<0&&(P+=2*f);for(var M=Math.ceil(Math.abs(P/f*2)),F=[],I=P/M,L=8/3*Math.sin(I/4)*Math.sin(I/4)/Math.sin(I/2),R=A+I,B=0;B=n?s-n:2*Math.PI-(n-s)}function i(t,e,i,r,n,a,h,c){var l=o.call(arguments);if(s[l])return s[l];var u,f,d,g,p,v,m,b,_=Math.sqrt,y=Math.min,x=Math.max,C=Math.abs,S=[],w=[[],[]];f=6*t-12*i+6*n,u=-3*t+9*i-9*n+3*h,d=3*i-3*t;for(var T=0;T<2;++T)if(T>0&&(f=6*e-12*r+6*a,u=-3*e+9*r-9*a+3*c,d=3*r-3*e),C(u)<1e-12){if(C(f)<1e-12)continue;0<(g=-d/f)&&g<1&&S.push(g)}else(m=f*f-4*d*u)<0||(0<(p=(-f+(b=_(m)))/(2*u))&&p<1&&S.push(p),0<(v=(-f-b)/(2*u))&&v<1&&S.push(v));for(var O,k,D,j=S.length,E=j;j--;)O=(D=1-(g=S[j]))*D*D*t+3*D*D*g*i+3*D*g*g*n+g*g*g*h,w[0][j]=O,k=D*D*D*e+3*D*D*g*r+3*D*g*g*a+g*g*g*c,w[1][j]=k;w[0][E]=t,w[1][E]=e,w[0][E+1]=h,w[1][E+1]=c;var A=[{x:y.apply(null,w[0]),y:y.apply(null,w[1])},{x:x.apply(null,w[0]),y:x.apply(null,w[1])}];return s[l]=A,A}var r={},n={},s={},o=Array.prototype.join;fabric.util.drawArc=function(e,i,r,n){for(var s=n[0],o=n[1],a=n[2],h=n[3],c=n[4],l=[[],[],[],[]],u=t(n[5]-i,n[6]-r,s,o,h,c,a),f=0,d=u.length;f=e})}}}(),function(){function t(e,i,r){if(r)if(!fabric.isLikelyNode&&i instanceof Element)e=i;else if(i instanceof Array){e=[];for(var n=0,s=i.length;n/g,">")},graphemeSplit:function(t){var e,i=0,r=[];for(i=0,e;i57343)return t.charAt(e);if(55296<=i&&i<=56319){if(t.length<=e+1)throw"High surrogate without following low surrogate";var r=t.charCodeAt(e+1);if(56320>r||r>57343)throw"High surrogate without following low surrogate";return t.charAt(e)+t.charAt(e+1)}if(0===e)throw"Low surrogate without preceding high surrogate";var n=t.charCodeAt(e-1);if(55296>n||n>56319)throw"Low surrogate without preceding high surrogate";return!1}(t,i))&&r.push(e);return r}}}(),function(){function t(){}function e(t){for(var e=null,r=this;r.constructor.superclass;){var n=r.constructor.superclass.prototype[t];if(r[t]!==n){e=n;break}r=r.constructor.superclass.prototype}return e?arguments.length>1?e.apply(this,i.call(arguments,1)):e.call(this):console.log("tried to callSuper "+t+", method not found in prototype chain",this)}var i=Array.prototype.slice,r=function(){},n=function(){for(var t in{toString:1})if("toString"===t)return!1;return!0}(),s=function(t,e,i){for(var r in e)r in t.prototype&&"function"==typeof t.prototype[r]&&(e[r]+"").indexOf("callSuper")>-1?t.prototype[r]=function(t){return function(){var r=this.constructor.superclass;this.constructor.superclass=i;var n=e[t].apply(this,arguments);if(this.constructor.superclass=r,"initialize"!==t)return n}}(r):t.prototype[r]=e[r],n&&(e.toString!==Object.prototype.toString&&(t.prototype.toString=e.toString),e.valueOf!==Object.prototype.valueOf&&(t.prototype.valueOf=e.valueOf))};fabric.util.createClass=function(){function n(){this.initialize.apply(this,arguments)}var o=null,a=i.call(arguments,0);"function"==typeof a[0]&&(o=a.shift()),n.superclass=o,n.subclasses=[],o&&(t.prototype=o.prototype,n.prototype=new t,o.subclasses.push(n));for(var h=0,c=a.length;h=.9999?"":"alpha(opacity="+100*e+")",i.filter=i.filter.replace(r,e)):i.filter+=" alpha(opacity="+100*e+")",t}),fabric.util.setStyle=function(t,e){var i=t.style;if(!i)return t;if("string"==typeof e)return t.style.cssText+=";"+e,e.indexOf("opacity")>-1?n(t,e.match(/opacity:\s*(\d?\.?\d*)/)[1]):t;for(var r in e)"opacity"===r?n(t,e[r]):i["float"===r||"cssFloat"===r?void 0===i.styleFloat?"cssFloat":"styleFloat":r]=e[r];return t}}(),function(){function t(t,e){var i=fabric.document.createElement(t);for(var r in e)"class"===r?i.className=e[r]:"for"===r?i.htmlFor=e[r]:i.setAttribute(r,e[r]);return i}function e(t){for(var e=0,i=0,r=fabric.document.documentElement,n=fabric.document.body||{scrollLeft:0,scrollTop:0};t&&(t.parentNode||t.host)&&((t=t.parentNode||t.host)===fabric.document?(e=n.scrollLeft||r.scrollLeft||0,i=n.scrollTop||r.scrollTop||0):(e+=t.scrollLeft||0,i+=t.scrollTop||0),1!==t.nodeType||"fixed"!==t.style.position););return{left:e,top:i}}var i,r=Array.prototype.slice,n=function(t){return r.call(t,0)};try{i=n(fabric.document.childNodes)instanceof Array}catch(t){}i||(n=function(t){for(var e=new Array(t.length),i=t.length;i--;)e[i]=t[i];return e});var s;s=fabric.document.defaultView&&fabric.document.defaultView.getComputedStyle?function(t,e){var i=fabric.document.defaultView.getComputedStyle(t,null);return i?i[e]:void 0}:function(t,e){var i=t.style[e];return!i&&t.currentStyle&&(i=t.currentStyle[e]),i},function(){var t=fabric.document.documentElement.style,e="userSelect"in t?"userSelect":"MozUserSelect"in t?"MozUserSelect":"WebkitUserSelect"in t?"WebkitUserSelect":"KhtmlUserSelect"in t?"KhtmlUserSelect":"";fabric.util.makeElementUnselectable=function(t){return void 0!==t.onselectstart&&(t.onselectstart=fabric.util.falseFunction),e?t.style[e]="none":"string"==typeof t.unselectable&&(t.unselectable="on"),t},fabric.util.makeElementSelectable=function(t){return void 0!==t.onselectstart&&(t.onselectstart=null),e?t.style[e]="":"string"==typeof t.unselectable&&(t.unselectable=""),t}}(),function(){fabric.util.getScript=function(t,e){var i=fabric.document.getElementsByTagName("head")[0],r=fabric.document.createElement("script"),n=!0;r.onload=r.onreadystatechange=function(t){if(n){if("string"==typeof this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)return;n=!1,e(t||fabric.window.event),r=r.onload=r.onreadystatechange=null}},r.src=t,i.appendChild(r)}}(),fabric.util.getById=function(t){return"string"==typeof t?fabric.document.getElementById(t):t},fabric.util.toArray=n,fabric.util.makeElement=t,fabric.util.addClass=function(t,e){t&&-1===(" "+t.className+" ").indexOf(" "+e+" ")&&(t.className+=(t.className?" ":"")+e)},fabric.util.wrapElement=function(e,i,r){return"string"==typeof i&&(i=t(i,r)),e.parentNode&&e.parentNode.replaceChild(i,e),i.appendChild(e),i},fabric.util.getScrollLeftTop=e,fabric.util.getElementOffset=function(t){var i,r,n=t&&t.ownerDocument,o={left:0,top:0},a={left:0,top:0},h={borderLeftWidth:"left",borderTopWidth:"top",paddingLeft:"left",paddingTop:"top"};if(!n)return a;for(var c in h)a[h[c]]+=parseInt(s(t,c),10)||0;return i=n.documentElement,void 0!==t.getBoundingClientRect&&(o=t.getBoundingClientRect()),r=e(t),{left:o.left+r.left-(i.clientLeft||0)+a.left,top:o.top+r.top-(i.clientTop||0)+a.top}},fabric.util.getElementStyle=s,fabric.util.getNodeCanvas=function(t){var e=fabric.jsdomImplForWrapper(t);return e._canvas||e._image}}(),function(){function t(){}var e=function(){for(var t=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP.3.0")},function(){return new XMLHttpRequest}],e=t.length;e--;)try{if(t[e]())return t[e]}catch(t){}}();fabric.util.request=function(i,r){r||(r={});var n=r.method?r.method.toUpperCase():"GET",s=r.onComplete||function(){},o=e(),a=r.body||r.parameters;return o.onreadystatechange=function(){4===o.readyState&&(s(o),o.onreadystatechange=t)},"GET"===n&&(a=null,"string"==typeof r.parameters&&(i=function(t,e){return t+(/\?/.test(t)?"&":"?")+e}(i,r.parameters))),o.open(n,i,!0),"POST"!==n&&"PUT"!==n||o.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),o.send(a),o}}(),fabric.log=function(){},fabric.warn=function(){},"undefined"!=typeof console&&["log","warn"].forEach(function(t){void 0!==console[t]&&"function"==typeof console[t].apply&&(fabric[t]=function(){return console[t].apply(console,arguments)})}),function(){function t(){return!1}function e(){return i.apply(fabric.window,arguments)}var i=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(t){return fabric.window.setTimeout(t,1e3/60)},r=fabric.window.cancelAnimationFrame||fabric.window.clearTimeout;fabric.util.animate=function(i){e(function(r){i||(i={});var n,s=r||+new Date,o=i.duration||500,a=s+o,h=i.onChange||t,c=i.abort||t,l=i.onComplete||t,u=i.easing||function(t,e,i,r){return-i*Math.cos(t/r*(Math.PI/2))+i+e},f="startValue"in i?i.startValue:0,d="endValue"in i?i.endValue:100,g=i.byValue||d-f;i.onStart&&i.onStart(),function t(r){if(c())l(d,1,1);else{var p=(n=r||+new Date)>a?o:n-s,v=p/o,m=u(p,f,g,o),b=Math.abs((m-f)/g);h(m,b,v),n>a?i.onComplete&&i.onComplete():e(t)}}(s)})},fabric.util.requestAnimFrame=e,fabric.util.cancelAnimFrame=function(){return r.apply(fabric.window,arguments)}}(),function(){fabric.util.animateColor=function(t,e,i,r){var n=new fabric.Color(t).getSource(),s=new fabric.Color(e).getSource();r=r||{},fabric.util.animate(fabric.util.object.extend(r,{duration:i||500,startValue:n,endValue:s,byValue:s,easing:function(t,e,i,n){return function(t,e,i){var r="rgba("+parseInt(t[0]+i*(e[0]-t[0]),10)+","+parseInt(t[1]+i*(e[1]-t[1]),10)+","+parseInt(t[2]+i*(e[2]-t[2]),10);return r+=","+(t&&e?parseFloat(t[3]+i*(e[3]-t[3])):1),r+=")"}(e,i,r.colorEasing?r.colorEasing(t,n):1-Math.cos(t/n*(Math.PI/2)))}}))}}(),function(){function t(t,e,i,r){return t-1&&a>-1&&a-1&&(e="stroke")}else n=s?e.map(d):d(e,r);else e="";return!s&&isNaN(n)?e:n}function r(t){return new RegExp("^("+t.join("|")+")\\b","i")}function n(t,e){var i,r,n,s,o=[];for(n=0,s=e.length;na?a:o),1===o&&1===a&&0===h&&0===l&&0===g&&0===p)return x;if((g||p)&&(C=" translate("+d(g)+" "+d(p)+") "),r=C+" matrix("+o+" 0 0 "+a+" "+h*o+" "+l*a+") ","svg"===t.nodeName){for(n=t.ownerDocument.createElement("g");t.firstChild;)n.appendChild(t.firstChild);t.appendChild(n)}else r=(n=t).getAttribute("transform")+r;return n.setAttribute("transform",r),x}var c=t.fabric||(t.fabric={}),l=c.util.object.extend,u=c.util.object.clone,f=c.util.toFixed,d=c.util.parseUnit,g=c.util.multiplyTransformMatrices,p={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","paint-order":"paintFirst","stroke-dasharray":"strokeDashArray","stroke-linecap":"strokeLineCap","stroke-linejoin":"strokeLineJoin","stroke-miterlimit":"strokeMiterLimit","stroke-opacity":"strokeOpacity","stroke-width":"strokeWidth","text-decoration":"textDecoration","text-anchor":"textAnchor",opacity:"opacity"},v={stroke:"strokeOpacity",fill:"fillOpacity"};c.svgValidTagNamesRegEx=r(["path","circle","polygon","polyline","ellipse","rect","line","image","text","linearGradient","radialGradient","stop"]),c.svgViewBoxElementsRegEx=r(["symbol","image","marker","pattern","view","svg"]),c.svgInvalidAncestorsRegEx=r(["pattern","defs","symbol","metadata","clipPath","mask","desc"]),c.svgValidParentsRegEx=r(["symbol","g","a","svg"]),c.cssRules={},c.gradientDefs={},c.parseTransformAttribute=function(){function t(t,e,i){t[i]=Math.tan(c.util.degreesToRadians(e[0]))}var e=[1,0,0,1,0,0],i=c.reNum,r="(?:\\s+,?\\s*|,\\s*)",n="(?:"+("(?:(matrix)\\s*\\(\\s*("+i+")"+r+"("+i+")"+r+"("+i+")"+r+"("+i+")"+r+"("+i+")"+r+"("+i+")\\s*\\))")+"|"+("(?:(translate)\\s*\\(\\s*("+i+")(?:"+r+"("+i+"))?\\s*\\))")+"|"+("(?:(scale)\\s*\\(\\s*("+i+")(?:"+r+"("+i+"))?\\s*\\))")+"|"+("(?:(rotate)\\s*\\(\\s*("+i+")(?:"+r+"("+i+")"+r+"("+i+"))?\\s*\\))")+"|"+("(?:(skewX)\\s*\\(\\s*("+i+")\\s*\\))")+"|"+("(?:(skewY)\\s*\\(\\s*("+i+")\\s*\\))")+")",s="^\\s*(?:"+("(?:"+n+"(?:"+r+"*"+n+")*)")+"?)\\s*$",o=new RegExp(s),a=new RegExp(n,"g");return function(i){var r=e.concat(),s=[];if(!i||i&&!o.test(i))return r;i.replace(a,function(i){var o=new RegExp(n).exec(i).filter(function(t){return!!t}),a=o[1],h=o.slice(2).map(parseFloat);switch(a){case"translate":!function(t,e){t[4]=e[0],2===e.length&&(t[5]=e[1])}(r,h);break;case"rotate":h[0]=c.util.degreesToRadians(h[0]),function(t,e){var i=Math.cos(e[0]),r=Math.sin(e[0]),n=0,s=0;3===e.length&&(n=e[1],s=e[2]),t[0]=i,t[1]=r,t[2]=-r,t[3]=i,t[4]=n-(i*n-r*s),t[5]=s-(r*n+i*s)}(r,h);break;case"scale":!function(t,e){var i=e[0],r=2===e.length?e[1]:e[0];t[0]=i,t[3]=r}(r,h);break;case"skewX":t(r,h,2);break;case"skewY":t(r,h,1);break;case"matrix":r=h}s.push(r.concat()),r=e.concat()});for(var h=s[0];s.length>1;)s.shift(),h=c.util.multiplyTransformMatrices(h,s[0]);return h}}();var m=new RegExp("^\\s*("+c.reNum+"+)\\s*,?\\s*("+c.reNum+"+)\\s*,?\\s*("+c.reNum+"+)\\s*,?\\s*("+c.reNum+"+)\\s*$");c.parseSVGDocument=function(t,e,i,r){if(t){!function(t){for(var e=n(t,["use","svg:use"]),i=0;e.length&&i/i,""))),n&&n.documentElement||e&&e(null),c.parseSVGDocument(n.documentElement,function(t,i,r,n){e&&e(t,i,r,n)},i,r)}})},loadSVGFromString:function(t,e,i,r){t=t.trim();var n;if("undefined"!=typeof DOMParser){var s=new DOMParser;s&&s.parseFromString&&(n=s.parseFromString(t,"text/xml"))}else c.window.ActiveXObject&&((n=new ActiveXObject("Microsoft.XMLDOM")).async="false",n.loadXML(t.replace(//i,"")));c.parseSVGDocument(n.documentElement,function(t,i,r,n){e(t,i,r,n)},i,r)}})}("undefined"!=typeof exports?exports:this),fabric.ElementsParser=function(t,e,i,r,n){this.elements=t,this.callback=e,this.options=i,this.reviver=r,this.svgUid=i&&i.svgUid||0,this.parsingOptions=n},fabric.ElementsParser.prototype.parse=function(){this.instances=new Array(this.elements.length),this.numElements=this.elements.length,this.createObjects()},fabric.ElementsParser.prototype.createObjects=function(){for(var t=0,e=this.elements.length;tt.x&&this.y>t.y},gte:function(t){return this.x>=t.x&&this.y>=t.y},lerp:function(t,i){return void 0===i&&(i=.5),i=Math.max(Math.min(1,i),0),new e(this.x+(t.x-this.x)*i,this.y+(t.y-this.y)*i)},distanceFrom:function(t){var e=this.x-t.x,i=this.y-t.y;return Math.sqrt(e*e+i*i)},midPointFrom:function(t){return this.lerp(t)},min:function(t){return new e(Math.min(this.x,t.x),Math.min(this.y,t.y))},max:function(t){return new e(Math.max(this.x,t.x),Math.max(this.y,t.y))},toString:function(){return this.x+","+this.y},setXY:function(t,e){return this.x=t,this.y=e,this},setX:function(t){return this.x=t,this},setY:function(t){return this.y=t,this},setFromPoint:function(t){return this.x=t.x,this.y=t.y,this},swap:function(t){var e=this.x,i=this.y;this.x=t.x,this.y=t.y,t.x=e,t.y=i},clone:function(){return new e(this.x,this.y)}})}("undefined"!=typeof exports?exports:this),function(t){"use strict";function e(t){this.status=t,this.points=[]}var i=t.fabric||(t.fabric={});i.Intersection?i.warn("fabric.Intersection is already defined"):(i.Intersection=e,i.Intersection.prototype={constructor:e,appendPoint:function(t){return this.points.push(t),this},appendPoints:function(t){return this.points=this.points.concat(t),this}},i.Intersection.intersectLineLine=function(t,r,n,s){var o,a=(s.x-n.x)*(t.y-n.y)-(s.y-n.y)*(t.x-n.x),h=(r.x-t.x)*(t.y-n.y)-(r.y-t.y)*(t.x-n.x),c=(s.y-n.y)*(r.x-t.x)-(s.x-n.x)*(r.y-t.y);if(0!==c){var l=a/c,u=h/c;0<=l&&l<=1&&0<=u&&u<=1?(o=new e("Intersection")).appendPoint(new i.Point(t.x+l*(r.x-t.x),t.y+l*(r.y-t.y))):o=new e}else o=new e(0===a||0===h?"Coincident":"Parallel");return o},i.Intersection.intersectLinePolygon=function(t,i,r){var n,s,o,a,h=new e,c=r.length;for(a=0;a0&&(h.status="Intersection"),h},i.Intersection.intersectPolygonPolygon=function(t,i){var r,n=new e,s=t.length;for(r=0;r0&&(n.status="Intersection"),n},i.Intersection.intersectPolygonRectangle=function(t,r,n){var s=r.min(n),o=r.max(n),a=new i.Point(o.x,s.y),h=new i.Point(s.x,o.y),c=e.intersectLinePolygon(s,a,t),l=e.intersectLinePolygon(a,o,t),u=e.intersectLinePolygon(o,h,t),f=e.intersectLinePolygon(h,s,t),d=new e;return d.appendPoints(c.points),d.appendPoints(l.points),d.appendPoints(u.points),d.appendPoints(f.points),d.points.length>0&&(d.status="Intersection"),d})}("undefined"!=typeof exports?exports:this),function(t){"use strict";function e(t){t?this._tryParsingColor(t):this.setSource([0,0,0,1])}function i(t,e,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?t+6*(e-t)*i:i<.5?e:i<2/3?t+(e-t)*(2/3-i)*6:t}var r=t.fabric||(t.fabric={});r.Color?r.warn("fabric.Color is already defined."):(r.Color=e,r.Color.prototype={_tryParsingColor:function(t){var i;t in e.colorNameMap&&(t=e.colorNameMap[t]),"transparent"===t&&(i=[255,255,255,0]),i||(i=e.sourceFromHex(t)),i||(i=e.sourceFromRgb(t)),i||(i=e.sourceFromHsl(t)),i||(i=[0,0,0,1]),i&&this.setSource(i)},_rgbToHsl:function(t,e,i){t/=255,e/=255,i/=255;var n,s,o,a=r.util.array.max([t,e,i]),h=r.util.array.min([t,e,i]);if(o=(a+h)/2,a===h)n=s=0;else{var c=a-h;switch(s=o>.5?c/(2-a-h):c/(a+h),a){case t:n=(e-i)/c+(e1?1:o,s){var a=s.split(/\s*;\s*/);for(""===a[a.length-1]&&a.pop(),n=a.length;n--;){var h=a[n].split(/\s*:\s*/),c=h[0].trim(),l=h[1].trim();"stop-color"===c?e=l:"stop-opacity"===c&&(r=l)}}return e||(e=t.getAttribute("stop-color")||"rgb(0,0,0)"),r||(r=t.getAttribute("stop-opacity")),e=new fabric.Color(e),i=e.getAlpha(),r=isNaN(parseFloat(r))?1:parseFloat(r),r*=i,{offset:o,color:e.toRgb(),opacity:r}}function e(t,e,i){var r,n=0,s=1,o="";for(var a in e)"Infinity"===e[a]?e[a]=1:"-Infinity"===e[a]&&(e[a]=0),r=parseFloat(e[a],10),s="string"==typeof e[a]&&/^(\d+\.\d+)%|(\d+)%$/.test(e[a])?.01:1,"x1"===a||"x2"===a||"r2"===a?(s*="objectBoundingBox"===i?t.width:1,n="objectBoundingBox"===i?t.left||0:0):"y1"!==a&&"y2"!==a||(s*="objectBoundingBox"===i?t.height:1,n="objectBoundingBox"===i?t.top||0:0),e[a]=r*s+n;if("ellipse"===t.type&&null!==e.r2&&"objectBoundingBox"===i&&t.rx!==t.ry){var h=t.ry/t.rx;o=" scale(1, "+h+")",e.y1&&(e.y1/=h),e.y2&&(e.y2/=h)}return o}var i=fabric.util.object.clone;fabric.Gradient=fabric.util.createClass({offsetX:0,offsetY:0,initialize:function(t){t||(t={});var e={};this.id=fabric.Object.__uid++,this.type=t.type||"linear",e={x1:t.coords.x1||0,y1:t.coords.y1||0,x2:t.coords.x2||0,y2:t.coords.y2||0},"radial"===this.type&&(e.r1=t.coords.r1||0,e.r2=t.coords.r2||0),this.coords=e,this.colorStops=t.colorStops.slice(),t.gradientTransform&&(this.gradientTransform=t.gradientTransform),this.offsetX=t.offsetX||this.offsetX,this.offsetY=t.offsetY||this.offsetY},addColorStop:function(t){for(var e in t){var i=new fabric.Color(t[e]);this.colorStops.push({offset:parseFloat(e),color:i.toRgb(),opacity:i.getAlpha()})}return this},toObject:function(t){var e={type:this.type,coords:this.coords,colorStops:this.colorStops,offsetX:this.offsetX,offsetY:this.offsetY,gradientTransform:this.gradientTransform?this.gradientTransform.concat():this.gradientTransform};return fabric.util.populateWithProperties(this,e,t),e},toSVG:function(t){var e,r,n,s,o=i(this.coords,!0),a=i(this.colorStops,!0),h=o.r1>o.r2,c=t.width/2,l=t.height/2;a.sort(function(t,e){return t.offset-e.offset}),"path"===t.type&&(c-=t.pathOffset.x,l-=t.pathOffset.y);for(var u in o)"x1"===u||"x2"===u?o[u]+=this.offsetX-c:"y1"!==u&&"y2"!==u||(o[u]+=this.offsetY-l);if(s='id="SVGID_'+this.id+'" gradientUnits="userSpaceOnUse"',this.gradientTransform&&(s+=' gradientTransform="matrix('+this.gradientTransform.join(" ")+')" '),"linear"===this.type?n=["\n']:"radial"===this.type&&(n=["\n']),"radial"===this.type){if(h)for((a=a.concat()).reverse(),e=0,r=a.length;e0){var d=f/Math.max(o.r1,o.r2);for(e=0,r=a.length;e\n')}return n.push("linear"===this.type?"\n":"\n"),n.join("")},toLive:function(t){var e,i,r,n=fabric.util.object.clone(this.coords);if(this.type){for("linear"===this.type?e=t.createLinearGradient(n.x1,n.y1,n.x2,n.y2):"radial"===this.type&&(e=t.createRadialGradient(n.x1,n.y1,n.r1,n.x2,n.y2,n.r2)),i=0,r=this.colorStops.length;i\n\n\n'},setOptions:function(t){for(var e in t)this[e]=t[e]},toLive:function(t){var e="function"==typeof this.source?this.source():this.source;if(!e)return"";if(void 0!==e.src){if(!e.complete)return"";if(0===e.naturalWidth||0===e.naturalHeight)return""}return t.createPattern(e,this.repeat)}})}(),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.toFixed;e.Shadow?e.warn("fabric.Shadow is already defined."):(e.Shadow=e.util.createClass({color:"rgb(0,0,0)",blur:0,offsetX:0,offsetY:0,affectStroke:!1,includeDefaultValues:!0,initialize:function(t){"string"==typeof t&&(t=this._parseShadow(t));for(var i in t)this[i]=t[i];this.id=e.Object.__uid++},_parseShadow:function(t){var i=t.trim(),r=e.Shadow.reOffsetsAndBlur.exec(i)||[];return{color:(i.replace(e.Shadow.reOffsetsAndBlur,"")||"rgb(0,0,0)").trim(),offsetX:parseInt(r[1],10)||0,offsetY:parseInt(r[2],10)||0,blur:parseInt(r[3],10)||0}},toString:function(){return[this.offsetX,this.offsetY,this.blur,this.color].join("px ")},toSVG:function(t){var r=40,n=40,s=e.Object.NUM_FRACTION_DIGITS,o=e.util.rotateVector({x:this.offsetX,y:this.offsetY},e.util.degreesToRadians(-t.angle));return t.width&&t.height&&(r=100*i((Math.abs(o.x)+this.blur)/t.width,s)+20,n=100*i((Math.abs(o.y)+this.blur)/t.height,s)+20),t.flipX&&(o.x*=-1),t.flipY&&(o.y*=-1),'\n\t\n\t\n\t\n\t\n\t\n\t\t\n\t\t\n\t\n\n'},toObject:function(){if(this.includeDefaultValues)return{color:this.color,blur:this.blur,offsetX:this.offsetX,offsetY:this.offsetY,affectStroke:this.affectStroke};var t={},i=e.Shadow.prototype;return["color","blur","offsetX","offsetY","affectStroke"].forEach(function(e){this[e]!==i[e]&&(t[e]=this[e])},this),t}}),e.Shadow.reOffsetsAndBlur=/(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/)}("undefined"!=typeof exports?exports:this),function(){"use strict";if(fabric.StaticCanvas)fabric.warn("fabric.StaticCanvas is already defined.");else{var t=fabric.util.object.extend,e=fabric.util.getElementOffset,i=fabric.util.removeFromArray,r=fabric.util.toFixed,n=fabric.util.transformPoint,s=fabric.util.invertTransform,o=new Error("Could not initialize `canvas` element");fabric.StaticCanvas=fabric.util.createClass(fabric.CommonMethods,{initialize:function(t,e){e||(e={}),this.renderAndResetBound=this.renderAndReset.bind(this),this.requestRenderAllBound=this.requestRenderAll.bind(this),this._initStatic(t,e)},backgroundColor:"",backgroundImage:null,overlayColor:"",overlayImage:null,includeDefaultValues:!0,stateful:!1,renderOnAddRemove:!0,clipTo:null,controlsAboveOverlay:!1,allowTouchScrolling:!1,imageSmoothingEnabled:!0,viewportTransform:fabric.iMatrix.concat(),backgroundVpt:!0,overlayVpt:!0,onBeforeScaleRotate:function(){},enableRetinaScaling:!0,vptCoords:{},skipOffscreen:!0,_initStatic:function(t,e){var i=this.requestRenderAllBound;this._objects=[],this._createLowerCanvas(t),this._initOptions(e),this._setImageSmoothing(),this.interactive||this._initRetinaScaling(),e.overlayImage&&this.setOverlayImage(e.overlayImage,i),e.backgroundImage&&this.setBackgroundImage(e.backgroundImage,i),e.backgroundColor&&this.setBackgroundColor(e.backgroundColor,i),e.overlayColor&&this.setOverlayColor(e.overlayColor,i),this.calcOffset()},_isRetinaScaling:function(){return 1!==fabric.devicePixelRatio&&this.enableRetinaScaling},getRetinaScaling:function(){return this._isRetinaScaling()?fabric.devicePixelRatio:1},_initRetinaScaling:function(){this._isRetinaScaling()&&(this.lowerCanvasEl.setAttribute("width",this.width*fabric.devicePixelRatio),this.lowerCanvasEl.setAttribute("height",this.height*fabric.devicePixelRatio),this.contextContainer.scale(fabric.devicePixelRatio,fabric.devicePixelRatio))},calcOffset:function(){return this._offset=e(this.lowerCanvasEl),this},setOverlayImage:function(t,e,i){return this.__setBgOverlayImage("overlayImage",t,e,i)},setBackgroundImage:function(t,e,i){return this.__setBgOverlayImage("backgroundImage",t,e,i)},setOverlayColor:function(t,e){return this.__setBgOverlayColor("overlayColor",t,e)},setBackgroundColor:function(t,e){return this.__setBgOverlayColor("backgroundColor",t,e)},_setImageSmoothing:function(){var t=this.getContext();t.imageSmoothingEnabled=t.imageSmoothingEnabled||t.webkitImageSmoothingEnabled||t.mozImageSmoothingEnabled||t.msImageSmoothingEnabled||t.oImageSmoothingEnabled,t.imageSmoothingEnabled=this.imageSmoothingEnabled},__setBgOverlayImage:function(t,e,i,r){return"string"==typeof e?fabric.util.loadImage(e,function(e){e&&(this[t]=new fabric.Image(e,r)),i&&i(e)},this,r&&r.crossOrigin):(r&&e.setOptions(r),this[t]=e,i&&i(e)),this},__setBgOverlayColor:function(t,e,i){return this[t]=e,this._initGradient(e,t),this._initPattern(e,t,i),this},_createCanvasElement:function(){var t=fabric.util.createCanvasElement();if(!t)throw o;if(t.style||(t.style={}),void 0===t.getContext)throw o;return t},_initOptions:function(t){this._setOptions(t),this.width=this.width||parseInt(this.lowerCanvasEl.width,10)||0,this.height=this.height||parseInt(this.lowerCanvasEl.height,10)||0,this.lowerCanvasEl.style&&(this.lowerCanvasEl.width=this.width,this.lowerCanvasEl.height=this.height,this.lowerCanvasEl.style.width=this.width+"px",this.lowerCanvasEl.style.height=this.height+"px",this.viewportTransform=this.viewportTransform.slice())},_createLowerCanvas:function(t){t&&t.getContext?this.lowerCanvasEl=t:this.lowerCanvasEl=fabric.util.getById(t)||this._createCanvasElement(),fabric.util.addClass(this.lowerCanvasEl,"lower-canvas"),this.interactive&&this._applyCanvasStyle(this.lowerCanvasEl),this.contextContainer=this.lowerCanvasEl.getContext("2d")},getWidth:function(){return this.width},getHeight:function(){return this.height},setWidth:function(t,e){return this.setDimensions({width:t},e)},setHeight:function(t,e){return this.setDimensions({height:t},e)},setDimensions:function(t,e){var i;e=e||{};for(var r in t)i=t[r],e.cssOnly||(this._setBackstoreDimension(r,t[r]),i+="px"),e.backstoreOnly||this._setCssDimension(r,i);return this._isCurrentlyDrawing&&this.freeDrawingBrush&&this.freeDrawingBrush._setBrushStyles(),this._initRetinaScaling(),this._setImageSmoothing(),this.calcOffset(),e.cssOnly||this.requestRenderAll(),this},_setBackstoreDimension:function(t,e){return this.lowerCanvasEl[t]=e,this.upperCanvasEl&&(this.upperCanvasEl[t]=e),this.cacheCanvasEl&&(this.cacheCanvasEl[t]=e),this[t]=e,this},_setCssDimension:function(t,e){return this.lowerCanvasEl.style[t]=e,this.upperCanvasEl&&(this.upperCanvasEl.style[t]=e),this.wrapperEl&&(this.wrapperEl.style[t]=e),this},getZoom:function(){return this.viewportTransform[0]},setViewportTransform:function(t){var e,i,r,n=this._activeObject;for(this.viewportTransform=t,i=0,r=this._objects.length;i"),i.join("")},_setSVGPreamble:function(t,e){e.suppressPreamble||t.push('\n','\n')},_setSVGHeader:function(t,e){var i,n=e.width||this.width,s=e.height||this.height,o='viewBox="0 0 '+this.width+" "+this.height+'" ',a=fabric.Object.NUM_FRACTION_DIGITS;e.viewBox?o='viewBox="'+e.viewBox.x+" "+e.viewBox.y+" "+e.viewBox.width+" "+e.viewBox.height+'" ':this.svgViewportTransformation&&(i=this.viewportTransform,o='viewBox="'+r(-i[4]/i[0],a)+" "+r(-i[5]/i[3],a)+" "+r(this.width/i[0],a)+" "+r(this.height/i[3],a)+'" '),t.push("\n',"Created with Fabric.js ",fabric.version,"\n","\n",this.createSVGFontFacesMarkup(),this.createSVGRefElementsMarkup(),"\n")},createSVGRefElementsMarkup:function(){var t=this;return["backgroundColor","overlayColor"].map(function(e){var i=t[e];if(i&&i.toLive)return i.toSVG(t,!1)}).join("")},createSVGFontFacesMarkup:function(){var t,e,i,r,n,s,o,a,h="",c={},l=fabric.fontPaths,u=this.getObjects();for(o=0,a=u.length;o',"\n",h,"","\n"].join("")),h},_setSVGObjects:function(t,e){var i,r,n,s=this.getObjects();for(r=0,n=s.length;r\n")}else t.push('\n")},sendToBack:function(t){if(!t)return this;var e,r,n,s=this._activeObject;if(t===s&&"activeSelection"===t.type)for(e=(n=s._objects).length;e--;)r=n[e],i(this._objects,r),this._objects.unshift(r);else i(this._objects,t),this._objects.unshift(t);return this.renderOnAddRemove&&this.requestRenderAll(),this},bringToFront:function(t){if(!t)return this;var e,r,n,s=this._activeObject;if(t===s&&"activeSelection"===t.type)for(n=s._objects,e=0;e0+c&&(o=s-1,i(this._objects,n),this._objects.splice(o,0,n)),c++;else 0!==(s=this._objects.indexOf(t))&&(o=this._findNewLowerIndex(t,s,e),i(this._objects,t),this._objects.splice(o,0,t));return this.renderOnAddRemove&&this.requestRenderAll(),this},_findNewLowerIndex:function(t,e,i){var r,n;if(i)for(r=e,n=e-1;n>=0;--n){if(t.intersectsWithObject(this._objects[n])||t.isContainedWithinObject(this._objects[n])||this._objects[n].isContainedWithinObject(t)){r=n;break}}else r=e-1;return r},bringForward:function(t,e){if(!t)return this;var r,n,s,o,a,h=this._activeObject,c=0;if(t===h&&"activeSelection"===t.type)for(r=(a=h._objects).length;r--;)n=a[r],(s=this._objects.indexOf(n))"}}),t(fabric.StaticCanvas.prototype,fabric.Observable),t(fabric.StaticCanvas.prototype,fabric.Collection),t(fabric.StaticCanvas.prototype,fabric.DataURLExporter),t(fabric.StaticCanvas,{EMPTY_JSON:'{"objects": [], "background": "white"}',supports:function(t){var e=fabric.util.createCanvasElement();if(!e||!e.getContext)return null;var i=e.getContext("2d");if(!i)return null;switch(t){case"getImageData":return void 0!==i.getImageData;case"setLineDash":return void 0!==i.setLineDash;case"toDataURL":return void 0!==e.toDataURL;case"toDataURLWithQuality":try{return e.toDataURL("image/jpeg",0),!0}catch(t){}return!1;default:return null}}}),fabric.StaticCanvas.prototype.toJSON=fabric.StaticCanvas.prototype.toObject,fabric.isLikelyNode&&(fabric.StaticCanvas.prototype.createPNGStream=function(){var t=fabric.util.getNodeCanvas(this.lowerCanvasEl);return t&&t.createPNGStream()},fabric.StaticCanvas.prototype.createJPEGStream=function(t){var e=fabric.util.getNodeCanvas(this.lowerCanvasEl);return e&&e.createJPEGStream(t)})}}(),fabric.BaseBrush=fabric.util.createClass({color:"rgb(0, 0, 0)",width:1,shadow:null,strokeLineCap:"round",strokeLineJoin:"round",strokeMiterLimit:10,strokeDashArray:null,setShadow:function(t){return this.shadow=new fabric.Shadow(t),this},_setBrushStyles:function(){var t=this.canvas.contextTop;t.strokeStyle=this.color,t.lineWidth=this.width,t.lineCap=this.strokeLineCap,t.miterLimit=this.strokeMiterLimit,t.lineJoin=this.strokeLineJoin,this.strokeDashArray&&fabric.StaticCanvas.supports("setLineDash")&&t.setLineDash(this.strokeDashArray)},_saveAndTransform:function(t){var e=this.canvas.viewportTransform;t.save(),t.transform(e[0],e[1],e[2],e[3],e[4],e[5])},_setShadow:function(){if(this.shadow){var t=this.canvas.contextTop,e=this.canvas.getZoom();t.shadowColor=this.shadow.color,t.shadowBlur=this.shadow.blur*e,t.shadowOffsetX=this.shadow.offsetX*e,t.shadowOffsetY=this.shadow.offsetY*e}},_resetShadow:function(){var t=this.canvas.contextTop;t.shadowColor="",t.shadowBlur=t.shadowOffsetX=t.shadowOffsetY=0}}),fabric.PencilBrush=fabric.util.createClass(fabric.BaseBrush,{initialize:function(t){this.canvas=t,this._points=[]},onMouseDown:function(t){this._prepareForDrawing(t),this._captureDrawingPath(t),this._render()},onMouseMove:function(t){this._captureDrawingPath(t),this.canvas.clearContext(this.canvas.contextTop),this._render()},onMouseUp:function(){this._finalizeAndAddPath()},_prepareForDrawing:function(t){var e=new fabric.Point(t.x,t.y);this._reset(),this._addPoint(e),this.canvas.contextTop.moveTo(e.x,e.y)},_addPoint:function(t){this._points.length>1&&t.eq(this._points[this._points.length-1])||this._points.push(t)},_reset:function(){this._points.length=0,this._setBrushStyles(),this._setShadow()},_captureDrawingPath:function(t){var e=new fabric.Point(t.x,t.y);this._addPoint(e)},_render:function(){var t,e,i=this.canvas.contextTop,r=this._points[0],n=this._points[1];if(this._saveAndTransform(i),i.beginPath(),2===this._points.length&&r.x===n.x&&r.y===n.y){var s=this.width/1e3;r=new fabric.Point(r.x,r.y),n=new fabric.Point(n.x,n.y),r.x-=s,n.x+=s}for(i.moveTo(r.x,r.y),t=1,e=this._points.length;t2;for(c&&(a=t[2].xt[e-2].x?1:n.x===t[e-2].x?0:-1,h=n.y>t[e-2].y?1:n.y===t[e-2].y?0:-1),i.push("L ",n.x+a*r," ",n.y+h*r),i},createPath:function(t){var e=new fabric.Path(t,{fill:null,stroke:this.color,strokeWidth:this.width,strokeLineCap:this.strokeLineCap,strokeMiterLimit:this.strokeMiterLimit,strokeLineJoin:this.strokeLineJoin,strokeDashArray:this.strokeDashArray}),i=new fabric.Point(e.left+e.width/2,e.top+e.height/2);return i=e.translateToGivenOrigin(i,"center","center",e.originX,e.originY),e.top=i.y,e.left=i.x,this.shadow&&(this.shadow.affectStroke=!0,e.setShadow(this.shadow)),e},_finalizeAndAddPath:function(){this.canvas.contextTop.closePath();var t=this.convertPointsToSVGPath(this._points).join("");if("M 0 0 Q 0 0 0 0 L 0 0"!==t){var e=this.createPath(t);this.canvas.clearContext(this.canvas.contextTop),this.canvas.add(e),this.canvas.renderAll(),e.setCoords(),this._resetShadow(),this.canvas.fire("path:created",{path:e})}else this.canvas.requestRenderAll()}}),fabric.CircleBrush=fabric.util.createClass(fabric.BaseBrush,{width:10,initialize:function(t){this.canvas=t,this.points=[]},drawDot:function(t){var e=this.addPoint(t),i=this.canvas.contextTop;this._saveAndTransform(i),i.fillStyle=e.fill,i.beginPath(),i.arc(e.x,e.y,e.radius,0,2*Math.PI,!1),i.closePath(),i.fill(),i.restore()},onMouseDown:function(t){this.points.length=0,this.canvas.clearContext(this.canvas.contextTop),this._setShadow(),this.drawDot(t)},_render:function(){var t,e,i,r=this.canvas.contextTop,n=this.points;for(this._saveAndTransform(r),t=0,e=n.length;t0&&!this.preserveObjectStacking){e=[],i=[];for(var n=0,s=this._objects.length;n1&&(this._activeObject._objects=i),e.push.apply(e,i)}else e=this._objects;return e},renderAll:function(){!this.contextTopDirty||this._groupSelector||this.isDrawingMode||(this.clearContext(this.contextTop),this.contextTopDirty=!1),this.isDrawingMode&&this._isCurrentlyDrawing&&this.freeDrawingBrush&&this.freeDrawingBrush._render();var t=this.contextContainer;return this.renderCanvas(t,this._chooseObjectsToRender()),this},renderTop:function(){var t=this.contextTop;return this.clearContext(t),this.selection&&this._groupSelector&&this._drawSelection(t),this.fire("after:render"),this.contextTopDirty=!0,this},_resetCurrentTransform:function(){var t=this._currentTransform;t.target.set({scaleX:t.original.scaleX,scaleY:t.original.scaleY,skewX:t.original.skewX,skewY:t.original.skewY,left:t.original.left,top:t.original.top}),this._shouldCenterTransform(t.target)?"rotate"===t.action?this._setOriginToCenter(t.target):("center"!==t.originX&&("right"===t.originX?t.mouseXSign=-1:t.mouseXSign=1),"center"!==t.originY&&("bottom"===t.originY?t.mouseYSign=-1:t.mouseYSign=1),t.originX="center",t.originY="center"):(t.originX=t.original.originX,t.originY=t.original.originY)},containsPoint:function(t,e,i){var r,n=i||this.getPointer(t,!0);return r=e.group&&e.group===this._activeObject&&"activeSelection"===e.group.type?this._normalizePointer(e.group,n):{x:n.x,y:n.y},e.containsPoint(r)||e._findTargetCorner(n)},_normalizePointer:function(t,e){var i=t.calcTransformMatrix(),r=fabric.util.invertTransform(i),n=this.restorePointerVpt(e);return fabric.util.transformPoint(n,r)},isTargetTransparent:function(t,e,i){var r=this.contextCache,n=t.selectionBackgroundColor,s=this.viewportTransform;t.selectionBackgroundColor="",this.clearContext(r),r.save(),r.transform(s[0],s[1],s[2],s[3],s[4],s[5]),t.render(r),r.restore(),t===this._activeObject&&t._renderControls(r,{hasBorders:!1,transparentCorners:!1},{hasBorders:!1}),t.selectionBackgroundColor=n;return fabric.util.isTransparent(r,e,i,this.targetFindTolerance)},_isSelectionKeyPressed:function(t){return"[object Array]"===Object.prototype.toString.call(this.selectionKey)?!!this.selectionKey.find(function(e){return!0===t[e]}):t[this.selectionKey]},_shouldClearSelection:function(t,e){var i=this.getActiveObjects(),r=this._activeObject;return!e||e&&r&&i.length>1&&-1===i.indexOf(e)&&r!==e&&!this._isSelectionKeyPressed(t)||e&&!e.evented||e&&!e.selectable&&r&&r!==e},_shouldCenterTransform:function(t){if(t){var e,i=this._currentTransform;return"scale"===i.action||"scaleX"===i.action||"scaleY"===i.action?e=this.centeredScaling||t.centeredScaling:"rotate"===i.action&&(e=this.centeredRotation||t.centeredRotation),e?!i.altKey:i.altKey}},_getOriginFromCorner:function(t,e){var i={x:t.originX,y:t.originY};return"ml"===e||"tl"===e||"bl"===e?i.x="right":"mr"!==e&&"tr"!==e&&"br"!==e||(i.x="left"),"tl"===e||"mt"===e||"tr"===e?i.y="bottom":"bl"!==e&&"mb"!==e&&"br"!==e||(i.y="top"),i},_getActionFromCorner:function(t,e,i){if(!e)return"drag";switch(e){case"mtr":return"rotate";case"ml":case"mr":return i[this.altActionKey]?"skewY":"scaleX";case"mt":case"mb":return i[this.altActionKey]?"skewX":"scaleY";default:return"scale"}},_setupCurrentTransform:function(t,i){if(i){var r=this.getPointer(t),n=i._findTargetCorner(this.getPointer(t,!0)),s=this._getActionFromCorner(i,n,t),o=this._getOriginFromCorner(i,n);this._currentTransform={target:i,action:s,corner:n,scaleX:i.scaleX,scaleY:i.scaleY,skewX:i.skewX,skewY:i.skewY,offsetX:r.x-i.left,offsetY:r.y-i.top,originX:o.x,originY:o.y,ex:r.x,ey:r.y,lastX:r.x,lastY:r.y,left:i.left,top:i.top,theta:e(i.angle),width:i.width*i.scaleX,mouseXSign:1,mouseYSign:1,shiftKey:t.shiftKey,altKey:t[this.centeredKey]},this._currentTransform.original={left:i.left,top:i.top,scaleX:i.scaleX,scaleY:i.scaleY,skewX:i.skewX,skewY:i.skewY,originX:o.x,originY:o.y},this._resetCurrentTransform()}},_translateObject:function(t,e){var i=this._currentTransform,r=i.target,n=t-i.offsetX,s=e-i.offsetY,o=!r.get("lockMovementX")&&r.left!==n,a=!r.get("lockMovementY")&&r.top!==s;return o&&r.set("left",n),a&&r.set("top",s),o||a},_changeSkewTransformOrigin:function(t,e,i){var r="originX",n={0:"center"},s=e.target.skewX,o="left",a="right",h="mt"===e.corner||"ml"===e.corner?1:-1,c=1;t=t>0?1:-1,"y"===i&&(s=e.target.skewY,o="top",a="bottom",r="originY"),n[-1]=o,n[1]=a,e.target.flipX&&(c*=-1),e.target.flipY&&(c*=-1),0===s?(e.skewSign=-h*t*c,e[r]=n[-t]):(s=s>0?1:-1,e.skewSign=s,e[r]=n[s*h*c])},_skewObject:function(t,e,i){var r=this._currentTransform,n=r.target,s=!1,o=n.get("lockSkewingX"),a=n.get("lockSkewingY");if(o&&"x"===i||a&&"y"===i)return!1;var h,c,l=n.getCenterPoint(),u=n.toLocalPoint(new fabric.Point(t,e),"center","center")[i],f=n.toLocalPoint(new fabric.Point(r.lastX,r.lastY),"center","center")[i],d=n._getTransformedDimensions();return this._changeSkewTransformOrigin(u-f,r,i),h=n.toLocalPoint(new fabric.Point(t,e),r.originX,r.originY)[i],c=n.translateToOriginPoint(l,r.originX,r.originY),s=this._setObjectSkew(h,r,i,d),r.lastX=t,r.lastY=e,n.setPositionByOrigin(c,r.originX,r.originY),s},_setObjectSkew:function(t,e,i,r){var n,s,o,a,h,c,l,u,f,d=e.target,g=!1,p=e.skewSign;return"x"===i?(a="y",h="Y",c="X",u=0,f=d.skewY):(a="x",h="X",c="Y",u=d.skewX,f=0),o=d._getTransformedDimensions(u,f),(l=2*Math.abs(t)-o[i])<=2?n=0:(n=p*Math.atan(l/d["scale"+c]/(o[a]/d["scale"+h])),n=fabric.util.radiansToDegrees(n)),g=d["skew"+c]!==n,d.set("skew"+c,n),0!==d["skew"+h]&&(s=d._getTransformedDimensions(),n=r[a]/s[a]*d["scale"+h],d.set("scale"+h,n)),g},_scaleObject:function(t,e,i){var r=this._currentTransform,n=r.target,s=n.get("lockScalingX"),o=n.get("lockScalingY"),a=n.get("lockScalingFlip");if(s&&o)return!1;var h=n.translateToOriginPoint(n.getCenterPoint(),r.originX,r.originY),c=n.toLocalPoint(new fabric.Point(t,e),r.originX,r.originY),l=n._getTransformedDimensions(),u=!1;return this._setLocalMouse(c,r),u=this._setObjectScale(c,r,s,o,i,a,l),n.setPositionByOrigin(h,r.originX,r.originY),u},_setObjectScale:function(t,e,i,r,n,s,o){var a,h,c,l,u=e.target,f=!1,d=!1,g=!1;return c=t.x*u.scaleX/o.x,l=t.y*u.scaleY/o.y,a=u.scaleX!==c,h=u.scaleY!==l,s&&c<=0&&cs?t.x<0?t.x+=s:t.x-=s:t.x=0,n(t.y)>s?t.y<0?t.y+=s:t.y-=s:t.y=0},_rotateObject:function(t,e){var n=this._currentTransform;if(n.target.get("lockRotation"))return!1;var s=r(n.ey-n.top,n.ex-n.left),o=r(e-n.top,t-n.left),a=i(o-s+n.theta),h=!0;if(n.target.snapAngle>0){var c=n.target.snapAngle,l=n.target.snapThreshold||c,u=Math.ceil(a/c)*c,f=Math.floor(a/c)*c;Math.abs(a-f)0?0:-i),e.ey-(r>0?0:-r),o,a)),this.selectionLineWidth&&this.selectionBorderColor)if(t.lineWidth=this.selectionLineWidth,t.strokeStyle=this.selectionBorderColor,this.selectionDashArray.length>1&&!s){var h=e.ex+.5-(i>0?0:o),c=e.ey+.5-(r>0?0:a);t.beginPath(),fabric.util.drawDashedLine(t,h,c,h+o,c,this.selectionDashArray),fabric.util.drawDashedLine(t,h,c+a-1,h+o,c+a-1,this.selectionDashArray),fabric.util.drawDashedLine(t,h,c,h,c+a,this.selectionDashArray),fabric.util.drawDashedLine(t,h+o-1,c,h+o-1,c+a,this.selectionDashArray),t.closePath(),t.stroke()}else fabric.Object.prototype._setLineDash.call(this,t,this.selectionDashArray),t.strokeRect(e.ex+.5-(i>0?0:o),e.ey+.5-(r>0?0:a),o,a)},findTarget:function(t,e){if(!this.skipTargetFind){var i,r,n=this.getPointer(t,!0),s=this._activeObject,o=this.getActiveObjects();if(this.targets=[],o.length>1&&!e&&s===this._searchPossibleTargets([s],n))return s;if(1===o.length&&s._findTargetCorner(n))return s;if(1===o.length&&s===this._searchPossibleTargets([s],n)){if(!this.preserveObjectStacking)return s;i=s,r=this.targets,this.targets=[]}var a=this._searchPossibleTargets(this._objects,n);return t[this.altSelectionKey]&&a&&i&&a!==i&&(a=i,this.targets=r),a}},_checkTarget:function(t,e){if(e&&e.visible&&e.evented&&this.containsPoint(null,e,t)){if(!this.perPixelTargetFind&&!e.perPixelTargetFind||e.isEditing)return!0;if(!this.isTargetTransparent(e,t.x,t.y))return!0}},_searchPossibleTargets:function(t,e){for(var i,r,n,s=t.length;s--;)if(this._checkTarget(e,t[s])){"group"===(i=t[s]).type&&i.subTargetCheck&&(r=this._normalizePointer(i,e),(n=this._searchPossibleTargets(i._objects,r))&&this.targets.push(n));break}return i},restorePointerVpt:function(t){return fabric.util.transformPoint(t,fabric.util.invertTransform(this.viewportTransform))},getPointer:function(e,i,r){r||(r=this.upperCanvasEl);var n,s=t(e),o=r.getBoundingClientRect(),a=o.width||0,h=o.height||0;return a&&h||("top"in o&&"bottom"in o&&(h=Math.abs(o.top-o.bottom)),"right"in o&&"left"in o&&(a=Math.abs(o.right-o.left))),this.calcOffset(),s.x=s.x-this._offset.left,s.y=s.y-this._offset.top,i||(s=this.restorePointerVpt(s)),n=0===a||0===h?{width:1,height:1}:{width:r.width/a,height:r.height/h},{x:s.x*n.width,y:s.y*n.height}},_createUpperCanvas:function(){var t=this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/,"");this.upperCanvasEl?this.upperCanvasEl.className="":this.upperCanvasEl=this._createCanvasElement(),fabric.util.addClass(this.upperCanvasEl,"upper-canvas "+t),this.wrapperEl.appendChild(this.upperCanvasEl),this._copyCanvasStyle(this.lowerCanvasEl,this.upperCanvasEl),this._applyCanvasStyle(this.upperCanvasEl),this.contextTop=this.upperCanvasEl.getContext("2d")},_createCacheCanvas:function(){this.cacheCanvasEl=this._createCanvasElement(),this.cacheCanvasEl.setAttribute("width",this.width),this.cacheCanvasEl.setAttribute("height",this.height),this.contextCache=this.cacheCanvasEl.getContext("2d")},_initWrapperElement:function(){this.wrapperEl=fabric.util.wrapElement(this.lowerCanvasEl,"div",{class:this.containerClass}),fabric.util.setStyle(this.wrapperEl,{width:this.width+"px",height:this.height+"px",position:"relative"}),fabric.util.makeElementUnselectable(this.wrapperEl)},_applyCanvasStyle:function(t){var e=this.width||t.width,i=this.height||t.height;fabric.util.setStyle(t,{position:"absolute",width:e+"px",height:i+"px",left:0,top:0,"touch-action":"none"}),t.width=e,t.height=i,fabric.util.makeElementUnselectable(t)},_copyCanvasStyle:function(t,e){e.style.cssText=t.style.cssText},getSelectionContext:function(){return this.contextTop},getSelectionElement:function(){return this.upperCanvasEl},getActiveObject:function(){return this._activeObject},getActiveObjects:function(){var t=this._activeObject;return t?"activeSelection"===t.type&&t._objects?t._objects.slice(0):[t]:[]},_onObjectRemoved:function(t){t===this._activeObject&&(this.fire("before:selection:cleared",{target:t}),this._discardActiveObject(),this.fire("selection:cleared",{target:t}),t.fire("deselected")),this._hoveredTarget===t&&(this._hoveredTarget=null),this.callSuper("_onObjectRemoved",t)},_fireSelectionEvents:function(t,e){var i=!1,r=this.getActiveObjects(),n=[],s=[],o={e:e};t.forEach(function(t){-1===r.indexOf(t)&&(i=!0,t.fire("deselected",o),s.push(t))}),r.forEach(function(e){-1===t.indexOf(e)&&(i=!0,e.fire("selected",o),n.push(e))}),t.length>0&&r.length>0?(o.selected=n,o.deselected=s,o.updated=n[0]||s[0],o.target=this._activeObject,i&&this.fire("selection:updated",o)):r.length>0?(1===r.length&&(o.target=n[0],this.fire("object:selected",o)),o.selected=n,o.target=this._activeObject,this.fire("selection:created",o)):t.length>0&&(o.deselected=s,this.fire("selection:cleared",o))},setActiveObject:function(t,e){var i=this.getActiveObjects();return this._setActiveObject(t,e),this._fireSelectionEvents(i,e),this},_setActiveObject:function(t,e){return this._activeObject!==t&&(!!this._discardActiveObject(e,t)&&(!t.onSelect({e:e})&&(this._activeObject=t,!0)))},_discardActiveObject:function(t,e){var i=this._activeObject;if(i){if(i.onDeselect({e:t,object:e}))return!1;this._activeObject=null}return!0},discardActiveObject:function(t){var e=this.getActiveObjects();return e.length&&this.fire("before:selection:cleared",{target:e[0],e:t}),this._discardActiveObject(t),this._fireSelectionEvents(e,t),this},dispose:function(){var t=this.wrapperEl;return this.removeListeners(),t.removeChild(this.upperCanvasEl),t.removeChild(this.lowerCanvasEl),delete this.upperCanvasEl,t.parentNode&&t.parentNode.replaceChild(this.lowerCanvasEl,this.wrapperEl),delete this.wrapperEl,fabric.StaticCanvas.prototype.dispose.call(this),this},clear:function(){return this.discardActiveObject(),this.clearContext(this.contextTop),this.callSuper("clear")},drawControls:function(t){var e=this._activeObject;e&&e._renderControls(t)},_toObject:function(t,e,i){var r=this._realizeGroupTransformOnObject(t),n=this.callSuper("_toObject",t,e,i);return this._unwindGroupTransformOnObject(t,r),n},_realizeGroupTransformOnObject:function(t){if(t.group&&"activeSelection"===t.group.type&&this._activeObject===t.group){var e={};return["angle","flipX","flipY","left","scaleX","scaleY","skewX","skewY","top"].forEach(function(i){e[i]=t[i]}),this._activeObject.realizeTransform(t),e}return null},_unwindGroupTransformOnObject:function(t,e){e&&t.set(e)},_setSVGObject:function(t,e,i){var r=this._realizeGroupTransformOnObject(e);this.callSuper("_setSVGObject",t,e,i),this._unwindGroupTransformOnObject(e,r)}});for(var o in fabric.StaticCanvas)"prototype"!==o&&(fabric.Canvas[o]=fabric.StaticCanvas[o]);fabric.isTouchSupported&&(fabric.Canvas.prototype._setCursorFromEvent=function(){})}(),function(){function t(t,e){return"which"in t?t.which===e:t.button===e-1}var e={mt:0,tr:1,mr:2,br:3,mb:4,bl:5,ml:6,tl:7},i=fabric.util.addListener,r=fabric.util.removeListener;fabric.util.object.extend(fabric.Canvas.prototype,{cursorMap:["n-resize","ne-resize","e-resize","se-resize","s-resize","sw-resize","w-resize","nw-resize"],_initEventListeners:function(){this.removeListeners(),this._bindEvents(),i(fabric.window,"resize",this._onResize),i(this.upperCanvasEl,"mousedown",this._onMouseDown),i(this.upperCanvasEl,"dblclick",this._onDoubleClick),i(this.upperCanvasEl,"mousemove",this._onMouseMove),i(this.upperCanvasEl,"mouseout",this._onMouseOut),i(this.upperCanvasEl,"mouseenter",this._onMouseEnter),i(this.upperCanvasEl,"wheel",this._onMouseWheel),i(this.upperCanvasEl,"contextmenu",this._onContextMenu),i(this.upperCanvasEl,"touchstart",this._onMouseDown,{passive:!1}),i(this.upperCanvasEl,"touchmove",this._onMouseMove,{passive:!1}),"undefined"!=typeof eventjs&&"add"in eventjs&&(eventjs.add(this.upperCanvasEl,"gesture",this._onGesture),eventjs.add(this.upperCanvasEl,"drag",this._onDrag),eventjs.add(this.upperCanvasEl,"orientation",this._onOrientationChange),eventjs.add(this.upperCanvasEl,"shake",this._onShake),eventjs.add(this.upperCanvasEl,"longpress",this._onLongPress))},_bindEvents:function(){this.eventsBinded||(this._onMouseDown=this._onMouseDown.bind(this),this._onMouseMove=this._onMouseMove.bind(this),this._onMouseUp=this._onMouseUp.bind(this),this._onResize=this._onResize.bind(this),this._onGesture=this._onGesture.bind(this),this._onDrag=this._onDrag.bind(this),this._onShake=this._onShake.bind(this),this._onLongPress=this._onLongPress.bind(this),this._onOrientationChange=this._onOrientationChange.bind(this),this._onMouseWheel=this._onMouseWheel.bind(this),this._onMouseOut=this._onMouseOut.bind(this),this._onMouseEnter=this._onMouseEnter.bind(this),this._onContextMenu=this._onContextMenu.bind(this),this._onDoubleClick=this._onDoubleClick.bind(this),this.eventsBinded=!0)},removeListeners:function(){r(fabric.window,"resize",this._onResize),r(this.upperCanvasEl,"mousedown",this._onMouseDown),r(this.upperCanvasEl,"mousemove",this._onMouseMove),r(this.upperCanvasEl,"mouseout",this._onMouseOut),r(this.upperCanvasEl,"mouseenter",this._onMouseEnter),r(this.upperCanvasEl,"wheel",this._onMouseWheel),r(this.upperCanvasEl,"contextmenu",this._onContextMenu),r(this.upperCanvasEl,"doubleclick",this._onDoubleClick),r(this.upperCanvasEl,"touchstart",this._onMouseDown),r(this.upperCanvasEl,"touchmove",this._onMouseMove),"undefined"!=typeof eventjs&&"remove"in eventjs&&(eventjs.remove(this.upperCanvasEl,"gesture",this._onGesture),eventjs.remove(this.upperCanvasEl,"drag",this._onDrag),eventjs.remove(this.upperCanvasEl,"orientation",this._onOrientationChange),eventjs.remove(this.upperCanvasEl,"shake",this._onShake),eventjs.remove(this.upperCanvasEl,"longpress",this._onLongPress))},_onGesture:function(t,e){this.__onTransformGesture&&this.__onTransformGesture(t,e)},_onDrag:function(t,e){this.__onDrag&&this.__onDrag(t,e)},_onMouseWheel:function(t){this.__onMouseWheel(t)},_onMouseOut:function(t){var e=this._hoveredTarget;this.fire("mouse:out",{target:e,e:t}),this._hoveredTarget=null,e&&e.fire("mouseout",{e:t}),this._iTextInstances&&this._iTextInstances.forEach(function(t){t.isEditing&&t.hiddenTextarea.focus()})},_onMouseEnter:function(t){this.findTarget(t)||(this.fire("mouse:over",{target:null,e:t}),this._hoveredTarget=null)},_onOrientationChange:function(t,e){this.__onOrientationChange&&this.__onOrientationChange(t,e)},_onShake:function(t,e){this.__onShake&&this.__onShake(t,e)},_onLongPress:function(t,e){this.__onLongPress&&this.__onLongPress(t,e)},_onContextMenu:function(t){return this.stopContextMenu&&(t.stopPropagation(),t.preventDefault()),!1},_onDoubleClick:function(t){this._handleEvent(t,"dblclick")},_onMouseDown:function(t){this.__onMouseDown(t),i(fabric.document,"touchend",this._onMouseUp,{passive:!1}),i(fabric.document,"touchmove",this._onMouseMove,{passive:!1}),r(this.upperCanvasEl,"mousemove",this._onMouseMove),r(this.upperCanvasEl,"touchmove",this._onMouseMove),"touchstart"===t.type?r(this.upperCanvasEl,"mousedown",this._onMouseDown):(i(fabric.document,"mouseup",this._onMouseUp),i(fabric.document,"mousemove",this._onMouseMove))},_onMouseUp:function(t){if(this.__onMouseUp(t),r(fabric.document,"mouseup",this._onMouseUp),r(fabric.document,"touchend",this._onMouseUp),r(fabric.document,"mousemove",this._onMouseMove),r(fabric.document,"touchmove",this._onMouseMove),i(this.upperCanvasEl,"mousemove",this._onMouseMove),i(this.upperCanvasEl,"touchmove",this._onMouseMove,{passive:!1}),"touchend"===t.type){var e=this;setTimeout(function(){i(e.upperCanvasEl,"mousedown",e._onMouseDown)},400)}},_onMouseMove:function(t){!this.allowTouchScrolling&&t.preventDefault&&t.preventDefault(),this.__onMouseMove(t)},_onResize:function(){this.calcOffset()},_shouldRender:function(t,e){var i=this._activeObject;return(!i||!i.isEditing||t!==i)&&!!(t&&(t.isMoving||t!==i)||!t&&i||!t&&!i&&!this._groupSelector||e&&this._previousPointer&&this.selection&&(e.x!==this._previousPointer.x||e.y!==this._previousPointer.y))},__onMouseUp:function(e){var i,r=!0,n=this._currentTransform,s=this._groupSelector,o=!s||0===s.left&&0===s.top;if(t(e,3))this.fireRightClick&&this._handleEvent(e,"up",i,3,o);else if(t(e,2))this.fireMiddleClick&&this._handleEvent(e,"up",i,2,o);else if(this.isDrawingMode&&this._isCurrentlyDrawing)this._onMouseUpInDrawingMode(e);else{n&&(this._finalizeCurrentTransform(e),r=!n.actionPerformed),i=r?this.findTarget(e,!0):n.target;var a=this._shouldRender(i,this.getPointer(e));i||!o?this._maybeGroupObjects(e):(this._groupSelector=null,this._currentTransform=null),i&&(i.isMoving=!1),this._setCursorFromEvent(e,i),this._handleEvent(e,"up",i||null,1,o),i&&(i.__corner=0),a&&this.requestRenderAll()}},_handleEvent:function(t,e,i,r,n){var s=void 0===i?this.findTarget(t):i,o=this.targets||[],a={e:t,target:s,subTargets:o,button:r||1,isClick:n||!1};this.fire("mouse:"+e,a),s&&s.fire("mouse"+e,a);for(var h=0;h1)){var r=this._groupSelector;r?(i=this.getPointer(t,!0),r.left=i.x-r.ex,r.top=i.y-r.ey,this.renderTop()):this._currentTransform?this._transformObject(t):(e=this.findTarget(t)||null,this._setCursorFromEvent(t,e),this._fireOverOutEvents(e,t)),this._handleEvent(t,"move",this._currentTransform?null:e)}},_fireOverOutEvents:function(t,e){var i,r,n=this._hoveredTarget;n!==t&&(i={e:e,target:t,previousTarget:this._hoveredTarget},r={e:e,target:this._hoveredTarget,nextTarget:t},this._hoveredTarget=t),t?n!==t&&(n&&(this.fire("mouse:out",r),n.fire("mouseout",r)),this.fire("mouse:over",i),t.fire("mouseover",i)):n&&(this.fire("mouse:out",r),n.fire("mouseout",r))},__onMouseWheel:function(t){this._handleEvent(t,"wheel")},_transformObject:function(t){var e=this.getPointer(t),i=this._currentTransform;i.reset=!1,i.target.isMoving=!0,i.shiftKey=t.shiftKey,i.altKey=t[this.centeredKey],this._beforeScaleTransform(t,i),this._performTransformAction(t,i,e),i.actionPerformed&&this.requestRenderAll()},_performTransformAction:function(t,e,i){var r=i.x,n=i.y,s=e.target,o=e.action,a=!1;"rotate"===o?(a=this._rotateObject(r,n))&&this._fire("rotating",s,t):"scale"===o?(a=this._onScale(t,e,r,n))&&this._fire("scaling",s,t):"scaleX"===o?(a=this._scaleObject(r,n,"x"))&&this._fire("scaling",s,t):"scaleY"===o?(a=this._scaleObject(r,n,"y"))&&this._fire("scaling",s,t):"skewX"===o?(a=this._skewObject(r,n,"x"))&&this._fire("skewing",s,t):"skewY"===o?(a=this._skewObject(r,n,"y"))&&this._fire("skewing",s,t):(a=this._translateObject(r,n))&&(this._fire("moving",s,t),this.setCursor(s.moveCursor||this.moveCursor)),e.actionPerformed=e.actionPerformed||a},_fire:function(t,e,i){this.fire("object:"+t,{target:e,e:i}),e.fire(t,{e:i})},_beforeScaleTransform:function(t,e){if("scale"===e.action||"scaleX"===e.action||"scaleY"===e.action){var i=this._shouldCenterTransform(e.target);(i&&("center"!==e.originX||"center"!==e.originY)||!i&&"center"===e.originX&&"center"===e.originY)&&(this._resetCurrentTransform(),e.reset=!0)}},_onScale:function(t,e,i,r){return this._isUniscalePossible(t,e.target)?(e.currentAction="scale",this._scaleObject(i,r)):(e.reset||"scale"!==e.currentAction||this._resetCurrentTransform(),e.currentAction="scaleEqually",this._scaleObject(i,r,"equally"))},_isUniscalePossible:function(t,e){return(t[this.uniScaleKey]||this.uniScaleTransform)&&!e.get("lockUniScaling")},_setCursorFromEvent:function(t,e){if(!e)return this.setCursor(this.defaultCursor),!1;var i=e.hoverCursor||this.hoverCursor,r=this._activeObject&&"activeSelection"===this._activeObject.type?this._activeObject:null,n=(!r||!r.contains(e))&&e._findTargetCorner(this.getPointer(t,!0));n?this.setCursor(this.getCornerCursor(n,e,t)):this.setCursor(i)},getCornerCursor:function(t,i,r){return this.actionIsDisabled(t,i,r)?this.notAllowedCursor:t in e?this._getRotatedCornerCursor(t,i,r):"mtr"===t&&i.hasRotatingPoint?this.rotationCursor:this.defaultCursor},actionIsDisabled:function(t,e,i){return"mt"===t||"mb"===t?i[this.altActionKey]?e.lockSkewingX:e.lockScalingY:"ml"===t||"mr"===t?i[this.altActionKey]?e.lockSkewingY:e.lockScalingX:"mtr"===t?e.lockRotation:this._isUniscalePossible(i,e)?e.lockScalingX&&e.lockScalingY:e.lockScalingX||e.lockScalingY},_getRotatedCornerCursor:function(t,i,r){var n=Math.round(i.angle%360/45);return n<0&&(n+=8),n+=e[t],r[this.altActionKey]&&e[t]%2==0&&(n+=2),n%=8,this.cursorMap[n]}})}(),function(){var t=Math.min,e=Math.max;fabric.util.object.extend(fabric.Canvas.prototype,{_shouldGroup:function(t,e){var i=this._activeObject;return i&&this._isSelectionKeyPressed(t)&&e&&e.selectable&&this.selection&&(i!==e||"activeSelection"===i.type)},_handleGrouping:function(t,e){var i=this._activeObject;i.__corner||(e!==i||(e=this.findTarget(t,!0)))&&(i&&"activeSelection"===i.type?this._updateActiveSelection(e,t):this._createActiveSelection(e,t))},_updateActiveSelection:function(t,e){var i=this._activeObject,r=i._objects.slice(0);i.contains(t)?(i.removeWithUpdate(t),this._hoveredTarget=t,1===i.size()&&this._setActiveObject(i.item(0),e)):(i.addWithUpdate(t),this._hoveredTarget=i),this._fireSelectionEvents(r,e)},_createActiveSelection:function(t,e){var i=this.getActiveObjects(),r=this._createGroup(t);this._hoveredTarget=r,this._setActiveObject(r,e),this._fireSelectionEvents(i,e)},_createGroup:function(t){var e=this.getObjects(),i=e.indexOf(this._activeObject)1&&(e=new fabric.ActiveSelection(i.reverse(),{canvas:this}),this.setActiveObject(e,t))},_collectObjects:function(){for(var i,r=[],n=this._groupSelector.ex,s=this._groupSelector.ey,o=n+this._groupSelector.left,a=s+this._groupSelector.top,h=new fabric.Point(t(n,o),t(s,a)),c=new fabric.Point(e(n,o),e(s,a)),l=!this.selectionFullyContained,u=n===o&&s===a,f=this._objects.length;f--&&!((i=this._objects[f])&&i.selectable&&i.visible&&(l&&i.intersectsWithRect(h,c)||i.isContainedWithinRect(h,c)||l&&i.containsPoint(h)||l&&i.containsPoint(c))&&(r.push(i),u)););return r},_maybeGroupObjects:function(t){this.selection&&this._groupSelector&&this._groupSelectedObjects(t),this.setCursor(this.defaultCursor),this._groupSelector=null,this._currentTransform=null}})}(),function(){var t=fabric.StaticCanvas.supports("toDataURLWithQuality");fabric.util.object.extend(fabric.StaticCanvas.prototype,{toDataURL:function(t){t||(t={});var e=t.format||"png",i=t.quality||1,r=t.multiplier||t.enableRetinaScaling?1:1/this.getRetinaScaling(),n={left:t.left||0,top:t.top||0,width:t.width||0,height:t.height||0};return this.__toDataURLWithMultiplier(e,i,n,r)},__toDataURLWithMultiplier:function(t,e,i,r){var n=this.width,s=this.height,o=(i.width||this.width)*r,a=(i.height||this.height)*r,h=this.getZoom()*r,c=this.viewportTransform,l=[h,0,0,h,(c[4]-i.left)*r,(c[5]-i.top)*r],u=this.interactive,f=this.skipOffscreen,d=n!==o||s!==a;this.viewportTransform=l,this.skipOffscreen=!1,this.interactive=!1,d&&this.setDimensions({width:o,height:a},{backstoreOnly:!0}),this.renderAll();var g=this.__toDataURL(t,e,i);return this.interactive=u,this.skipOffscreen=f,this.viewportTransform=c,d&&this.setDimensions({width:n,height:s},{backstoreOnly:!0}),this.renderAll(),g},__toDataURL:function(e,i){var r=this.contextContainer.canvas;"jpg"===e&&(e="jpeg");return t?r.toDataURL("image/"+e,i):r.toDataURL("image/"+e)}})}(),fabric.util.object.extend(fabric.StaticCanvas.prototype,{loadFromDatalessJSON:function(t,e,i){return this.loadFromJSON(t,e,i)},loadFromJSON:function(t,e,i){if(t){var r="string"==typeof t?JSON.parse(t):fabric.util.object.clone(t),n=this,s=this.renderOnAddRemove;return this.renderOnAddRemove=!1,this._enlivenObjects(r.objects,function(t){n.clear(),n._setBgOverlay(r,function(){t.forEach(function(t,e){n.insertAt(t,e)}),n.renderOnAddRemove=s,delete r.objects,delete r.backgroundImage,delete r.overlayImage,delete r.background,delete r.overlay,n._setOptions(r),n.renderAll(),e&&e()})},i),this}},_setBgOverlay:function(t,e){var i={backgroundColor:!1,overlayColor:!1,backgroundImage:!1,overlayImage:!1};if(t.backgroundImage||t.overlayImage||t.background||t.overlay){var r=function(){i.backgroundImage&&i.overlayImage&&i.backgroundColor&&i.overlayColor&&e&&e()};this.__setBgOverlay("backgroundImage",t.backgroundImage,i,r),this.__setBgOverlay("overlayImage",t.overlayImage,i,r),this.__setBgOverlay("backgroundColor",t.background,i,r),this.__setBgOverlay("overlayColor",t.overlay,i,r)}else e&&e()},__setBgOverlay:function(t,e,i,r){var n=this;if(!e)return i[t]=!0,void(r&&r());"backgroundImage"===t||"overlayImage"===t?fabric.util.enlivenObjects([e],function(e){n[t]=e[0],i[t]=!0,r&&r()}):this["set"+fabric.util.string.capitalize(t,!0)](e,function(){i[t]=!0,r&&r()})},_enlivenObjects:function(t,e,i){t&&0!==t.length?fabric.util.enlivenObjects(t,function(t){e&&e(t)},null,i):e&&e([])},_toDataURL:function(t,e){this.clone(function(i){e(i.toDataURL(t))})},_toDataURLWithMultiplier:function(t,e,i){this.clone(function(r){i(r.toDataURLWithMultiplier(t,e))})},clone:function(t,e){var i=JSON.stringify(this.toJSON(e));this.cloneWithoutData(function(e){e.loadFromJSON(i,function(){t&&t(e)})})},cloneWithoutData:function(t){var e=fabric.document.createElement("canvas");e.width=this.width,e.height=this.height;var i=new fabric.Canvas(e);i.clipTo=this.clipTo,this.backgroundImage?(i.setBackgroundImage(this.backgroundImage.src,function(){i.renderAll(),t&&t(i)}),i.backgroundImageOpacity=this.backgroundImageOpacity,i.backgroundImageStretch=this.backgroundImageStretch):t&&t(i)}}),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend,r=e.util.object.clone,n=e.util.toFixed,s=e.util.string.capitalize,o=e.util.degreesToRadians,a=e.StaticCanvas.supports("setLineDash"),h=!e.isLikelyNode;e.Object||(e.Object=e.util.createClass(e.CommonMethods,{type:"object",originX:"left",originY:"top",top:0,left:0,width:0,height:0,scaleX:1,scaleY:1,flipX:!1,flipY:!1,opacity:1,angle:0,skewX:0,skewY:0,cornerSize:13,transparentCorners:!0,hoverCursor:null,moveCursor:null,padding:0,borderColor:"rgba(102,153,255,0.75)",borderDashArray:null,cornerColor:"rgba(102,153,255,0.5)",cornerStrokeColor:null,cornerStyle:"rect",cornerDashArray:null,centeredScaling:!1,centeredRotation:!0,fill:"rgb(0,0,0)",fillRule:"nonzero",globalCompositeOperation:"source-over",backgroundColor:"",selectionBackgroundColor:"",stroke:null,strokeWidth:1,strokeDashArray:null,strokeLineCap:"butt",strokeLineJoin:"miter",strokeMiterLimit:10,shadow:null,borderOpacityWhenMoving:.4,borderScaleFactor:1,transformMatrix:null,minScaleLimit:0,selectable:!0,evented:!0,visible:!0,hasControls:!0,hasBorders:!0,hasRotatingPoint:!0,rotatingPointOffset:40,perPixelTargetFind:!1,includeDefaultValues:!0,clipTo:null,lockMovementX:!1,lockMovementY:!1,lockRotation:!1,lockScalingX:!1,lockScalingY:!1,lockUniScaling:!1,lockSkewingX:!1,lockSkewingY:!1,lockScalingFlip:!1,excludeFromExport:!1,objectCaching:h,statefullCache:!1,noScaleCache:!0,dirty:!0,__corner:0,paintFirst:"fill",stateProperties:"top left width height scaleX scaleY flipX flipY originX originY transformMatrix stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit angle opacity fill globalCompositeOperation shadow clipTo visible backgroundColor skewX skewY fillRule paintFirst".split(" "),cacheProperties:"fill stroke strokeWidth strokeDashArray width height paintFirst strokeLineCap strokeLineJoin strokeMiterLimit backgroundColor".split(" "),initialize:function(t){t&&this.setOptions(t)},_createCacheCanvas:function(){this._cacheProperties={},this._cacheCanvas=e.document.createElement("canvas"),this._cacheContext=this._cacheCanvas.getContext("2d"),this._updateCacheCanvas()},_limitCacheSize:function(t){var i=e.perfLimitSizeTotal,r=t.width,n=t.height,s=e.maxCacheSideLimit,o=e.minCacheSideLimit;if(r<=s&&n<=s&&r*n<=i)return rl&&(t.zoomX/=r/l,t.width=l,t.capped=!0),n>u&&(t.zoomY/=n/u,t.height=u,t.capped=!0),t},_getCacheCanvasDimensions:function(){var t=this.canvas&&this.canvas.getZoom()||1,i=this.getObjectScaling(),r=this.canvas&&this.canvas._isRetinaScaling()?e.devicePixelRatio:1,n=this._getNonTransformedDimensions(),s=i.scaleX*t*r,o=i.scaleY*t*r;return{width:n.x*s+2,height:n.y*o+2,zoomX:s,zoomY:o,x:n.x,y:n.y}},_updateCacheCanvas:function(){if(this.noScaleCache&&this.canvas&&this.canvas._currentTransform){var t=this.canvas._currentTransform.target,i=this.canvas._currentTransform.action;if(this===t&&i.slice&&"scale"===i.slice(0,5))return!1}var r,n,s=this._cacheCanvas,o=this._limitCacheSize(this._getCacheCanvasDimensions()),a=e.minCacheSideLimit,h=o.width,c=o.height,l=o.zoomX,u=o.zoomY,f=h!==this.cacheWidth||c!==this.cacheHeight,d=this.zoomX!==l||this.zoomY!==u,g=f||d,p=0,v=0,m=!1;if(f){var b=this._cacheCanvas.width,_=this._cacheCanvas.height,y=h>b||c>_;m=y||(h<.9*b||c<.9*_)&&b>a&&_>a,y&&!o.capped&&(h>a||c>a)&&(p=.1*h,v=.1*c)}return!!g&&(m?(s.width=Math.ceil(h+p),s.height=Math.ceil(c+v)):(this._cacheContext.setTransform(1,0,0,1,0,0),this._cacheContext.clearRect(0,0,s.width,s.height)),r=o.x*l/2,n=o.y*u/2,this.cacheTranslationX=Math.round(s.width/2-r)+r,this.cacheTranslationY=Math.round(s.height/2-n)+n,this.cacheWidth=h,this.cacheHeight=c,this._cacheContext.translate(this.cacheTranslationX,this.cacheTranslationY),this._cacheContext.scale(l,u),this.zoomX=l,this.zoomY=u,!0)},setOptions:function(t){this._setOptions(t),this._initGradient(t.fill,"fill"),this._initGradient(t.stroke,"stroke"),this._initClipping(t),this._initPattern(t.fill,"fill"),this._initPattern(t.stroke,"stroke")},transform:function(t){var e;e=this.group&&!this.group._transformDone?this.calcTransformMatrix():this.calcOwnMatrix(),t.transform(e[0],e[1],e[2],e[3],e[4],e[5])},toObject:function(t){var i=e.Object.NUM_FRACTION_DIGITS,r={type:this.type,version:e.version,originX:this.originX,originY:this.originY,left:n(this.left,i),top:n(this.top,i),width:n(this.width,i),height:n(this.height,i),fill:this.fill&&this.fill.toObject?this.fill.toObject():this.fill,stroke:this.stroke&&this.stroke.toObject?this.stroke.toObject():this.stroke,strokeWidth:n(this.strokeWidth,i),strokeDashArray:this.strokeDashArray?this.strokeDashArray.concat():this.strokeDashArray,strokeLineCap:this.strokeLineCap,strokeLineJoin:this.strokeLineJoin,strokeMiterLimit:n(this.strokeMiterLimit,i),scaleX:n(this.scaleX,i),scaleY:n(this.scaleY,i),angle:n(this.angle,i),flipX:this.flipX,flipY:this.flipY,opacity:n(this.opacity,i),shadow:this.shadow&&this.shadow.toObject?this.shadow.toObject():this.shadow,visible:this.visible,clipTo:this.clipTo&&String(this.clipTo),backgroundColor:this.backgroundColor,fillRule:this.fillRule,paintFirst:this.paintFirst,globalCompositeOperation:this.globalCompositeOperation,transformMatrix:this.transformMatrix?this.transformMatrix.concat():null,skewX:n(this.skewX,i),skewY:n(this.skewY,i)};return e.util.populateWithProperties(this,r,t),this.includeDefaultValues||(r=this._removeDefaultValues(r)),r},toDatalessObject:function(t){return this.toObject(t)},_removeDefaultValues:function(t){var i=e.util.getKlass(t.type).prototype;return i.stateProperties.forEach(function(e){t[e]===i[e]&&delete t[e];"[object Array]"===Object.prototype.toString.call(t[e])&&"[object Array]"===Object.prototype.toString.call(i[e])&&0===t[e].length&&0===i[e].length&&delete t[e]}),t},toString:function(){return"#"},getObjectScaling:function(){var t=this.scaleX,e=this.scaleY;if(this.group){var i=this.group.getObjectScaling();t*=i.scaleX,e*=i.scaleY}return{scaleX:t,scaleY:e}},getObjectOpacity:function(){var t=this.opacity;return this.group&&(t*=this.group.getObjectOpacity()),t},_set:function(t,i){var r="scaleX"===t||"scaleY"===t,n=this[t]!==i,s=!1;return r&&(i=this._constrainScale(i)),"scaleX"===t&&i<0?(this.flipX=!this.flipX,i*=-1):"scaleY"===t&&i<0?(this.flipY=!this.flipY,i*=-1):"shadow"!==t||!i||i instanceof e.Shadow?"dirty"===t&&this.group&&this.group.set("dirty",i):i=new e.Shadow(i),this[t]=i,n&&(s=this.group&&this.group.isOnACache(),this.cacheProperties.indexOf(t)>-1?(this.dirty=!0,s&&this.group.set("dirty",!0)):s&&this.stateProperties.indexOf(t)>-1&&this.group.set("dirty",!0)),this},setOnGroup:function(){},getViewportTransform:function(){return this.canvas&&this.canvas.viewportTransform?this.canvas.viewportTransform:e.iMatrix.concat()},isNotVisible:function(){return 0===this.opacity||0===this.width&&0===this.height||!this.visible},render:function(t){this.isNotVisible()||this.canvas&&this.canvas.skipOffscreen&&!this.group&&!this.isOnScreen()||(t.save(),this._setupCompositeOperation(t),this.drawSelectionBackground(t),this.transform(t),this._setOpacity(t),this._setShadow(t,this),this.transformMatrix&&t.transform.apply(t,this.transformMatrix),this.clipTo&&e.util.clipContext(this,t),this.shouldCache()?(this._cacheCanvas||this._createCacheCanvas(),this.isCacheDirty()&&(this.statefullCache&&this.saveState({propertySet:"cacheProperties"}),this.drawObject(this._cacheContext),this.dirty=!1),this.drawCacheOnCanvas(t)):(this._removeCacheCanvas(),this.dirty=!1,this.drawObject(t),this.objectCaching&&this.statefullCache&&this.saveState({propertySet:"cacheProperties"})),this.clipTo&&t.restore(),t.restore())},_removeCacheCanvas:function(){this._cacheCanvas=null,this.cacheWidth=0,this.cacheHeight=0},needsItsOwnCache:function(){return"stroke"===this.paintFirst&&"object"==typeof this.shadow},shouldCache:function(){return this.ownCaching=this.objectCaching&&(!this.group||this.needsItsOwnCache()||!this.group.isOnACache()),this.ownCaching},willDrawShadow:function(){return!!this.shadow&&(0!==this.shadow.offsetX||0!==this.shadow.offsetY)},drawObject:function(t){this._renderBackground(t),this._setStrokeStyles(t,this),this._setFillStyles(t,this),this._render(t)},drawCacheOnCanvas:function(t){t.scale(1/this.zoomX,1/this.zoomY),t.drawImage(this._cacheCanvas,-this.cacheTranslationX,-this.cacheTranslationY)},isCacheDirty:function(t){if(this.isNotVisible())return!1;if(this._cacheCanvas&&!t&&this._updateCacheCanvas())return!0;if(this.dirty||this.statefullCache&&this.hasStateChanged("cacheProperties")){if(this._cacheCanvas&&!t){var e=this.cacheWidth/this.zoomX,i=this.cacheHeight/this.zoomY;this._cacheContext.clearRect(-e/2,-i/2,e,i)}return!0}return!1},_renderBackground:function(t){if(this.backgroundColor){var e=this._getNonTransformedDimensions();t.fillStyle=this.backgroundColor,t.fillRect(-e.x/2,-e.y/2,e.x,e.y),this._removeShadow(t)}},_setOpacity:function(t){this.group&&!this.group._transformDone?t.globalAlpha=this.getObjectOpacity():t.globalAlpha*=this.opacity},_setStrokeStyles:function(t,e){e.stroke&&(t.lineWidth=e.strokeWidth,t.lineCap=e.strokeLineCap,t.lineJoin=e.strokeLineJoin,t.miterLimit=e.strokeMiterLimit,t.strokeStyle=e.stroke.toLive?e.stroke.toLive(t,this):e.stroke)},_setFillStyles:function(t,e){e.fill&&(t.fillStyle=e.fill.toLive?e.fill.toLive(t,this):e.fill)},_setLineDash:function(t,e,i){e&&(1&e.length&&e.push.apply(e,e),a?t.setLineDash(e):i&&i(t))},_renderControls:function(t,i){var r,n,s,a=this.getViewportTransform(),h=this.calcTransformMatrix();n=void 0!==(i=i||{}).hasBorders?i.hasBorders:this.hasBorders,s=void 0!==i.hasControls?i.hasControls:this.hasControls,h=e.util.multiplyTransformMatrices(a,h),r=e.util.qrDecompose(h),t.save(),t.translate(r.translateX,r.translateY),t.lineWidth=1*this.borderScaleFactor,this.group||(t.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1),i.forActiveSelection?(t.rotate(o(r.angle)),n&&this.drawBordersInGroup(t,r,i)):(t.rotate(o(this.angle)),n&&this.drawBorders(t,i)),s&&this.drawControls(t,i),t.restore()},_setShadow:function(t){if(this.shadow){var i=this.canvas&&this.canvas.viewportTransform[0]||1,r=this.canvas&&this.canvas.viewportTransform[3]||1,n=this.getObjectScaling();this.canvas&&this.canvas._isRetinaScaling()&&(i*=e.devicePixelRatio,r*=e.devicePixelRatio),t.shadowColor=this.shadow.color,t.shadowBlur=this.shadow.blur*e.browserShadowBlurConstant*(i+r)*(n.scaleX+n.scaleY)/4,t.shadowOffsetX=this.shadow.offsetX*i*n.scaleX,t.shadowOffsetY=this.shadow.offsetY*r*n.scaleY}},_removeShadow:function(t){this.shadow&&(t.shadowColor="",t.shadowBlur=t.shadowOffsetX=t.shadowOffsetY=0)},_applyPatternGradientTransform:function(t,e){if(!e||!e.toLive)return{offsetX:0,offsetY:0};var i=e.gradientTransform||e.patternTransform,r=-this.width/2+e.offsetX||0,n=-this.height/2+e.offsetY||0;return t.translate(r,n),i&&t.transform(i[0],i[1],i[2],i[3],i[4],i[5]),{offsetX:r,offsetY:n}},_renderPaintInOrder:function(t){"stroke"===this.paintFirst?(this._renderStroke(t),this._renderFill(t)):(this._renderFill(t),this._renderStroke(t))},_renderFill:function(t){this.fill&&(t.save(),this._applyPatternGradientTransform(t,this.fill),"evenodd"===this.fillRule?t.fill("evenodd"):t.fill(),t.restore())},_renderStroke:function(t){this.stroke&&0!==this.strokeWidth&&(this.shadow&&!this.shadow.affectStroke&&this._removeShadow(t),t.save(),this._setLineDash(t,this.strokeDashArray,this._renderDashedStroke),this._applyPatternGradientTransform(t,this.stroke),t.stroke(),t.restore())},_findCenterFromElement:function(){return{x:this.left+this.width/2,y:this.top+this.height/2}},_assignTransformMatrixProps:function(){if(this.transformMatrix){var t=e.util.qrDecompose(this.transformMatrix);this.flipX=!1,this.flipY=!1,this.set("scaleX",t.scaleX),this.set("scaleY",t.scaleY),this.angle=t.angle,this.skewX=t.skewX,this.skewY=0}},_removeTransformMatrix:function(t){var i=this._findCenterFromElement();this.transformMatrix&&(this._assignTransformMatrixProps(),i=e.util.transformPoint(i,this.transformMatrix)),this.transformMatrix=null,t&&(this.scaleX*=t.scaleX,this.scaleY*=t.scaleY,this.cropX=t.cropX,this.cropY=t.cropY,i.x+=t.offsetLeft,i.y+=t.offsetTop,this.width=t.width,this.height=t.height),this.setPositionByOrigin(i,"center","center")},clone:function(t,i){var r=this.toObject(i);this.constructor.fromObject?this.constructor.fromObject(r,t):e.Object._fromObject("Object",r,t)},cloneAsImage:function(t,i){var r=this.toDataURL(i);return e.util.loadImage(r,function(i){t&&t(new e.Image(i))}),this},toDataURL:function(t){t||(t={});var i=e.util.createCanvasElement(),r=this.getBoundingRect();i.width=r.width,i.height=r.height,e.util.wrapElement(i,"div");var n=new e.StaticCanvas(i,{enableRetinaScaling:t.enableRetinaScaling,renderOnAddRemove:!1,skipOffscreen:!1});"jpg"===t.format&&(t.format="jpeg"),"jpeg"===t.format&&(n.backgroundColor="#fff");var s={left:this.left,top:this.top};this.setPositionByOrigin(new e.Point(n.width/2,n.height/2),"center","center");var o=this.canvas;n.add(this);var a=n.toDataURL(t);return this.set(s).setCoords(),this.canvas=o,n._objects=[],n.dispose(),n=null,a},isType:function(t){return this.type===t},complexity:function(){return 1},toJSON:function(t){return this.toObject(t)},setGradient:function(t,i){i||(i={});var r={colorStops:[]};return r.type=i.type||(i.r1||i.r2?"radial":"linear"),r.coords={x1:i.x1,y1:i.y1,x2:i.x2,y2:i.y2},(i.r1||i.r2)&&(r.coords.r1=i.r1,r.coords.r2=i.r2),r.gradientTransform=i.gradientTransform,e.Gradient.prototype.addColorStop.call(r,i.colorStops),this.set(t,e.Gradient.forObject(this,r))},setPatternFill:function(t){return this.set("fill",new e.Pattern(t))},setShadow:function(t){return this.set("shadow",t?new e.Shadow(t):null)},setColor:function(t){return this.set("fill",t),this},rotate:function(t){var e=("center"!==this.originX||"center"!==this.originY)&&this.centeredRotation;return e&&this._setOriginToCenter(),this.set("angle",t),e&&this._resetOrigin(),this},centerH:function(){return this.canvas&&this.canvas.centerObjectH(this),this},viewportCenterH:function(){return this.canvas&&this.canvas.viewportCenterObjectH(this),this},centerV:function(){return this.canvas&&this.canvas.centerObjectV(this),this},viewportCenterV:function(){return this.canvas&&this.canvas.viewportCenterObjectV(this),this},center:function(){return this.canvas&&this.canvas.centerObject(this),this},viewportCenter:function(){return this.canvas&&this.canvas.viewportCenterObject(this),this},getLocalPointer:function(t,i){i=i||this.canvas.getPointer(t);var r=new e.Point(i.x,i.y),n=this._getLeftTopCoords();return this.angle&&(r=e.util.rotatePoint(r,n,o(-this.angle))),{x:r.x-n.x,y:r.y-n.y}},_setupCompositeOperation:function(t){this.globalCompositeOperation&&(t.globalCompositeOperation=this.globalCompositeOperation)}}),e.util.createAccessors&&e.util.createAccessors(e.Object),i(e.Object.prototype,e.Observable),e.Object.NUM_FRACTION_DIGITS=2,e.Object._fromObject=function(t,i,n,s){var o=e[t];i=r(i,!0),e.util.enlivenPatterns([i.fill,i.stroke],function(t){void 0!==t[0]&&(i.fill=t[0]),void 0!==t[1]&&(i.stroke=t[1]);var e=s?new o(i[s],i):new o(i);n&&n(e)})},e.Object.__uid=0)}("undefined"!=typeof exports?exports:this),function(){var t=fabric.util.degreesToRadians,e={left:-.5,center:0,right:.5},i={top:-.5,center:0,bottom:.5};fabric.util.object.extend(fabric.Object.prototype,{translateToGivenOrigin:function(t,r,n,s,o){var a,h,c,l=t.x,u=t.y;return"string"==typeof r?r=e[r]:r-=.5,"string"==typeof s?s=e[s]:s-=.5,a=s-r,"string"==typeof n?n=i[n]:n-=.5,"string"==typeof o?o=i[o]:o-=.5,h=o-n,(a||h)&&(c=this._getTransformedDimensions(),l=t.x+a*c.x,u=t.y+h*c.y),new fabric.Point(l,u)},translateToCenterPoint:function(e,i,r){var n=this.translateToGivenOrigin(e,i,r,"center","center");return this.angle?fabric.util.rotatePoint(n,e,t(this.angle)):n},translateToOriginPoint:function(e,i,r){var n=this.translateToGivenOrigin(e,"center","center",i,r);return this.angle?fabric.util.rotatePoint(n,e,t(this.angle)):n},getCenterPoint:function(){var t=new fabric.Point(this.left,this.top);return this.translateToCenterPoint(t,this.originX,this.originY)},getPointByOrigin:function(t,e){var i=this.getCenterPoint();return this.translateToOriginPoint(i,t,e)},toLocalPoint:function(e,i,r){var n,s,o=this.getCenterPoint();return n=void 0!==i&&void 0!==r?this.translateToGivenOrigin(o,"center","center",i,r):new fabric.Point(this.left,this.top),s=new fabric.Point(e.x,e.y),this.angle&&(s=fabric.util.rotatePoint(s,o,-t(this.angle))),s.subtractEquals(n)},setPositionByOrigin:function(t,e,i){var r=this.translateToCenterPoint(t,e,i),n=this.translateToOriginPoint(r,this.originX,this.originY);this.set("left",n.x),this.set("top",n.y)},adjustPosition:function(i){var r,n,s=t(this.angle),o=this.getScaledWidth(),a=Math.cos(s)*o,h=Math.sin(s)*o;r="string"==typeof this.originX?e[this.originX]:this.originX-.5,n="string"==typeof i?e[i]:i-.5,this.left+=a*(n-r),this.top+=h*(n-r),this.setCoords(),this.originX=i},_setOriginToCenter:function(){this._originalOriginX=this.originX,this._originalOriginY=this.originY;var t=this.getCenterPoint();this.originX="center",this.originY="center",this.left=t.x,this.top=t.y},_resetOrigin:function(){var t=this.translateToOriginPoint(this.getCenterPoint(),this._originalOriginX,this._originalOriginY);this.originX=this._originalOriginX,this.originY=this._originalOriginY,this.left=t.x,this.top=t.y,this._originalOriginX=null,this._originalOriginY=null},_getLeftTopCoords:function(){return this.translateToOriginPoint(this.getCenterPoint(),"left","top")},onDeselect:function(){}})}(),function(){var t=fabric.util.degreesToRadians,e=fabric.util.multiplyTransformMatrices;fabric.util.object.extend(fabric.Object.prototype,{oCoords:null,aCoords:null,ownMatrixCache:null,matrixCache:null,getCoords:function(t,e){this.oCoords||this.setCoords();var i=t?this.aCoords:this.oCoords;return function(t){return[new fabric.Point(t.tl.x,t.tl.y),new fabric.Point(t.tr.x,t.tr.y),new fabric.Point(t.br.x,t.br.y),new fabric.Point(t.bl.x,t.bl.y)]}(e?this.calcCoords(t):i)},intersectsWithRect:function(t,e,i,r){var n=this.getCoords(i,r);return"Intersection"===fabric.Intersection.intersectPolygonRectangle(n,t,e).status},intersectsWithObject:function(t,e,i){return"Intersection"===fabric.Intersection.intersectPolygonPolygon(this.getCoords(e,i),t.getCoords(e,i)).status||t.isContainedWithinObject(this,e,i)||this.isContainedWithinObject(t,e,i)},isContainedWithinObject:function(t,e,i){for(var r=this.getCoords(e,i),n=0,s=t._getImageLines(i?t.calcCoords(e):e?t.aCoords:t.oCoords);n<4;n++)if(!t.containsPoint(r[n],s))return!1;return!0},isContainedWithinRect:function(t,e,i,r){var n=this.getBoundingRect(i,r);return n.left>=t.x&&n.left+n.width<=e.x&&n.top>=t.y&&n.top+n.height<=e.y},containsPoint:function(t,e,i,r){var e=e||this._getImageLines(r?this.calcCoords(i):i?this.aCoords:this.oCoords),n=this._findCrossPoints(t,e);return 0!==n&&n%2==1},isOnScreen:function(t){if(!this.canvas)return!1;for(var e,i=this.canvas.vptCoords.tl,r=this.canvas.vptCoords.br,n=this.getCoords(!0,t),s=0;s<4;s++)if((e=n[s]).x<=r.x&&e.x>=i.x&&e.y<=r.y&&e.y>=i.y)return!0;if(this.intersectsWithRect(i,r,!0))return!0;var o={x:(i.x+r.x)/2,y:(i.y+r.y)/2};return!!this.containsPoint(o,null,!0)},_getImageLines:function(t){return{topline:{o:t.tl,d:t.tr},rightline:{o:t.tr,d:t.br},bottomline:{o:t.br,d:t.bl},leftline:{o:t.bl,d:t.tl}}},_findCrossPoints:function(t,e){var i,r,n,s,o=0;for(var a in e)if(!((s=e[a]).o.y=t.y&&s.d.y>=t.y||(s.o.x===s.d.x&&s.o.x>=t.x?n=s.o.x:(i=0,r=(s.d.y-s.o.y)/(s.d.x-s.o.x),n=-(t.y-i*t.x-(s.o.y-r*s.o.x))/(i-r)),n>=t.x&&(o+=1),2!==o)))break;return o},getBoundingRect:function(t,e){var i=this.getCoords(t,e);return fabric.util.makeBoundingBoxFromPoints(i)},getScaledWidth:function(){return this._getTransformedDimensions().x},getScaledHeight:function(){return this._getTransformedDimensions().y},_constrainScale:function(t){return Math.abs(t)0?Math.atan(o/s):0,l=s/Math.cos(c)/2,u=Math.cos(c+i)*l,f=Math.sin(c+i)*l,d=this.getCenterPoint(),g=e?d:fabric.util.transformPoint(d,r),p=new fabric.Point(g.x-u,g.y-f),v=new fabric.Point(p.x+s*h,p.y+s*a),m=new fabric.Point(p.x-o*a,p.y+o*h),b=new fabric.Point(g.x+u,g.y+f);if(!e)var _=new fabric.Point((p.x+m.x)/2,(p.y+m.y)/2),y=new fabric.Point((v.x+p.x)/2,(v.y+p.y)/2),x=new fabric.Point((b.x+v.x)/2,(b.y+v.y)/2),C=new fabric.Point((b.x+m.x)/2,(b.y+m.y)/2),S=new fabric.Point(y.x+a*this.rotatingPointOffset,y.y-h*this.rotatingPointOffset);g={tl:p,tr:v,br:b,bl:m};return e||(g.ml=_,g.mt=y,g.mr=x,g.mb=C,g.mtr=S),g},setCoords:function(t,e){return this.oCoords=this.calcCoords(t),e||(this.aCoords=this.calcCoords(!0)),t||this._setCornerCoords&&this._setCornerCoords(),this},_calcRotateMatrix:function(){if(this.angle){var e=t(this.angle),i=Math.cos(e),r=Math.sin(e);return 6.123233995736766e-17!==i&&-1.8369701987210297e-16!==i||(i=0),[i,r,-r,i,0,0]}return fabric.iMatrix.concat()},transformMatrixKey:function(t){var e="";return!t&&this.group&&(e=this.group.transformMatrixKey(t)+"_"),e+this.top+"_"+this.left+"_"+this.scaleX+"_"+this.scaleY+"_"+this.skewX+"_"+this.skewY+"_"+this.angle+"_"+this.width+"_"+this.height+"_"+this.strokeWidth+this.flipX+this.flipY},calcTransformMatrix:function(t){if(t)return this.calcOwnMatrix();var i=this.transformMatrixKey(),r=this.matrixCache||(this.matrixCache={});if(r.key===i)return r.value;var n=this.calcOwnMatrix();return this.group&&(n=e(this.group.calcTransformMatrix(),n)),r.key=i,r.value=n,n},calcOwnMatrix:function(){var t=this.transformMatrixKey(!0),i=this.ownMatrixCache||(this.ownMatrixCache={});if(i.key===t)return i.value;var r,n=this.getCenterPoint(),s=[1,0,0,1,n.x,n.y],o=this._calcDimensionsTransformMatrix(this.skewX,this.skewY,!0);return this.angle&&(r=this._calcRotateMatrix(),s=e(s,r)),s=e(s,o),i.key=t,i.value=s,s},_calcDimensionsTransformMatrix:function(i,r,n){var s,o=[this.scaleX*(n&&this.flipX?-1:1),0,0,this.scaleY*(n&&this.flipY?-1:1),0,0];return i&&(s=[1,0,Math.tan(t(i)),1],o=e(o,s,!0)),r&&(s=[1,Math.tan(t(r)),0,1],o=e(o,s,!0)),o},_getNonTransformedDimensions:function(){var t=this.strokeWidth;return{x:this.width+t,y:this.height+t}},_getTransformedDimensions:function(t,e){void 0===t&&(t=this.skewX),void 0===e&&(e=this.skewY);var i,r,n=this._getNonTransformedDimensions(),s=n.x/2,o=n.y/2,a=[{x:-s,y:-o},{x:s,y:-o},{x:-s,y:o},{x:s,y:o}],h=this._calcDimensionsTransformMatrix(t,e,!1);for(i=0;i\n')}},_createBaseSVGMarkup:function(){var t=[];return this.fill&&this.fill.toLive&&t.push(this.fill.toSVG(this,!1)),this.stroke&&this.stroke.toLive&&t.push(this.stroke.toSVG(this,!1)),this.shadow&&t.push(this.shadow.toSVG(this)),t},addPaintOrder:function(){return"fill"!==this.paintFirst?' paint-order="'+this.paintFirst+'" ':""}})}(),function(){function t(t,e,r){var n={};r.forEach(function(e){n[e]=t[e]}),i(t[e],n,!0)}function e(t,i,r){if(t===i)return!0;if(Array.isArray(t)){if(t.length!==i.length)return!1;for(var n=0,s=t.length;n\n'),t?t(e.join("")):e.join("")}}),i.Line.ATTRIBUTE_NAMES=i.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" ")),i.Line.fromElement=function(t,e,n){n=n||{};var s=i.parseAttributes(t,i.Line.ATTRIBUTE_NAMES),o=[s.x1||0,s.y1||0,s.x2||0,s.y2||0];e(new i.Line(o,r(s,n)))},i.Line.fromObject=function(t,e){var r=n(t,!0);r.points=[t.x1,t.y1,t.x2,t.y2],i.Object._fromObject("Line",r,function(t){delete t.points,e&&e(t)},"points")})}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=Math.PI;e.Circle?e.warn("fabric.Circle is already defined."):(e.Circle=e.util.createClass(e.Object,{type:"circle",radius:0,startAngle:0,endAngle:2*i,cacheProperties:e.Object.prototype.cacheProperties.concat("radius"),_set:function(t,e){return this.callSuper("_set",t,e),"radius"===t&&this.setRadius(e),this},toObject:function(t){return this.callSuper("toObject",["radius","startAngle","endAngle"].concat(t))},toSVG:function(t){var e=this._createBaseSVGMarkup(),r=(this.endAngle-this.startAngle)%(2*i);if(0===r)e.push("\n");else{var n=Math.cos(this.startAngle)*this.radius,s=Math.sin(this.startAngle)*this.radius,o=Math.cos(this.endAngle)*this.radius,a=Math.sin(this.endAngle)*this.radius,h=r>i?"1":"0";e.push('\n')}return t?t(e.join("")):e.join("")},_render:function(t){t.beginPath(),t.arc(0,0,this.radius,this.startAngle,this.endAngle,!1),this._renderPaintInOrder(t)},getRadiusX:function(){return this.get("radius")*this.get("scaleX")},getRadiusY:function(){return this.get("radius")*this.get("scaleY")},setRadius:function(t){return this.radius=t,this.set("width",2*t).set("height",2*t)}}),e.Circle.ATTRIBUTE_NAMES=e.SHARED_ATTRIBUTES.concat("cx cy r".split(" ")),e.Circle.fromElement=function(t,i){var r=e.parseAttributes(t,e.Circle.ATTRIBUTE_NAMES);if(!function(t){return"radius"in t&&t.radius>=0}(r))throw new Error("value of `r` attribute is required and can not be negative");r.left=(r.left||0)-r.radius,r.top=(r.top||0)-r.radius,i(new e.Circle(r))},e.Circle.fromObject=function(t,i){return e.Object._fromObject("Circle",t,i)})}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={});e.Triangle?e.warn("fabric.Triangle is already defined"):(e.Triangle=e.util.createClass(e.Object,{type:"triangle",width:100,height:100,_render:function(t){var e=this.width/2,i=this.height/2;t.beginPath(),t.moveTo(-e,i),t.lineTo(0,-i),t.lineTo(e,i),t.closePath(),this._renderPaintInOrder(t)},_renderDashedStroke:function(t){var i=this.width/2,r=this.height/2;t.beginPath(),e.util.drawDashedLine(t,-i,r,0,-r,this.strokeDashArray),e.util.drawDashedLine(t,0,-r,i,r,this.strokeDashArray),e.util.drawDashedLine(t,i,r,-i,r,this.strokeDashArray),t.closePath()},toSVG:function(t){var e=this._createBaseSVGMarkup(),i=this.width/2,r=this.height/2,n=[-i+" "+r,"0 "+-r,i+" "+r].join(",");return e.push(""),t?t(e.join("")):e.join("")}}),e.Triangle.fromObject=function(t,i){return e.Object._fromObject("Triangle",t,i)})}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=2*Math.PI;e.Ellipse?e.warn("fabric.Ellipse is already defined."):(e.Ellipse=e.util.createClass(e.Object,{type:"ellipse",rx:0,ry:0,cacheProperties:e.Object.prototype.cacheProperties.concat("rx","ry"),initialize:function(t){this.callSuper("initialize",t),this.set("rx",t&&t.rx||0),this.set("ry",t&&t.ry||0)},_set:function(t,e){switch(this.callSuper("_set",t,e),t){case"rx":this.rx=e,this.set("width",2*e);break;case"ry":this.ry=e,this.set("height",2*e)}return this},getRx:function(){return this.get("rx")*this.get("scaleX")},getRy:function(){return this.get("ry")*this.get("scaleY")},toObject:function(t){return this.callSuper("toObject",["rx","ry"].concat(t))},toSVG:function(t){var e=this._createBaseSVGMarkup();return e.push("\n"),t?t(e.join("")):e.join("")},_render:function(t){t.beginPath(),t.save(),t.transform(1,0,0,this.ry/this.rx,0,0),t.arc(0,0,this.rx,0,i,!1),t.restore(),this._renderPaintInOrder(t)}}),e.Ellipse.ATTRIBUTE_NAMES=e.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" ")),e.Ellipse.fromElement=function(t,i){var r=e.parseAttributes(t,e.Ellipse.ATTRIBUTE_NAMES);r.left=(r.left||0)-r.rx,r.top=(r.top||0)-r.ry,i(new e.Ellipse(r))},e.Ellipse.fromObject=function(t,i){return e.Object._fromObject("Ellipse",t,i)})}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend;e.Rect?e.warn("fabric.Rect is already defined"):(e.Rect=e.util.createClass(e.Object,{stateProperties:e.Object.prototype.stateProperties.concat("rx","ry"),type:"rect",rx:0,ry:0,cacheProperties:e.Object.prototype.cacheProperties.concat("rx","ry"),initialize:function(t){this.callSuper("initialize",t),this._initRxRy()},_initRxRy:function(){this.rx&&!this.ry?this.ry=this.rx:this.ry&&!this.rx&&(this.rx=this.ry)},_render:function(t){if(1!==this.width||1!==this.height){var e=this.rx?Math.min(this.rx,this.width/2):0,i=this.ry?Math.min(this.ry,this.height/2):0,r=this.width,n=this.height,s=-this.width/2,o=-this.height/2,a=0!==e||0!==i,h=.4477152502;t.beginPath(),t.moveTo(s+e,o),t.lineTo(s+r-e,o),a&&t.bezierCurveTo(s+r-h*e,o,s+r,o+h*i,s+r,o+i),t.lineTo(s+r,o+n-i),a&&t.bezierCurveTo(s+r,o+n-h*i,s+r-h*e,o+n,s+r-e,o+n),t.lineTo(s+e,o+n),a&&t.bezierCurveTo(s+h*e,o+n,s,o+n-h*i,s,o+n-i),t.lineTo(s,o+i),a&&t.bezierCurveTo(s,o+h*i,s+h*e,o,s+e,o),t.closePath(),this._renderPaintInOrder(t)}else t.fillRect(-.5,-.5,1,1)},_renderDashedStroke:function(t){var i=-this.width/2,r=-this.height/2,n=this.width,s=this.height;t.beginPath(),e.util.drawDashedLine(t,i,r,i+n,r,this.strokeDashArray),e.util.drawDashedLine(t,i+n,r,i+n,r+s,this.strokeDashArray),e.util.drawDashedLine(t,i+n,r+s,i,r+s,this.strokeDashArray),e.util.drawDashedLine(t,i,r+s,i,r,this.strokeDashArray),t.closePath()},toObject:function(t){return this.callSuper("toObject",["rx","ry"].concat(t))},toSVG:function(t){var e=this._createBaseSVGMarkup(),i=-this.width/2,r=-this.height/2;return e.push("\n"),t?t(e.join("")):e.join("")}}),e.Rect.ATTRIBUTE_NAMES=e.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" ")),e.Rect.fromElement=function(t,r,n){if(!t)return r(null);n=n||{};var s=e.parseAttributes(t,e.Rect.ATTRIBUTE_NAMES);s.left=s.left||0,s.top=s.top||0;var o=new e.Rect(i(n?e.util.object.clone(n):{},s));o.visible=o.visible&&o.width>0&&o.height>0,r(o)},e.Rect.fromObject=function(t,i){return e.Object._fromObject("Rect",t,i)})}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend,r=e.util.array.min,n=e.util.array.max,s=e.util.toFixed;e.Polyline?e.warn("fabric.Polyline is already defined"):(e.Polyline=e.util.createClass(e.Object,{type:"polyline",points:null,cacheProperties:e.Object.prototype.cacheProperties.concat("points"),initialize:function(t,e){e=e||{},this.points=t||[],this.callSuper("initialize",e);var i=this._calcDimensions();void 0===e.left&&(this.left=i.left),void 0===e.top&&(this.top=i.top),this.width=i.width,this.height=i.height,this.pathOffset={x:i.left+this.width/2,y:i.top+this.height/2}},_calcDimensions:function(){var t=this.points,e=r(t,"x")||0,i=r(t,"y")||0;return{left:e,top:i,width:(n(t,"x")||0)-e,height:(n(t,"y")||0)-i}},toObject:function(t){return i(this.callSuper("toObject",t),{points:this.points.concat()})},toSVG:function(t){for(var i=[],r=this.pathOffset.x,n=this.pathOffset.y,o=this._createBaseSVGMarkup(),a=e.Object.NUM_FRACTION_DIGITS,h=0,c=this.points.length;h\n"),t?t(o.join("")):o.join("")},commonRender:function(t){var e,i=this.points.length,r=this.pathOffset.x,n=this.pathOffset.y;if(!i||isNaN(this.points[i-1].y))return!1;t.beginPath(),t.moveTo(this.points[0].x-r,this.points[0].y-n);for(var s=0;s"},toObject:function(t){return n(this.callSuper("toObject",t),{path:this.path.map(function(t){return t.slice()}),top:this.top,left:this.left})},toDatalessObject:function(t){var e=this.toObject(["sourcePath"].concat(t));return e.sourcePath&&delete e.path,e},toSVG:function(t){for(var e=[],i=this._createBaseSVGMarkup(),r="",n=0,s=this.path.length;n\n"),t?t(i.join("")):i.join("")},complexity:function(){return this.path.length},_parsePath:function(){for(var t,e,i,r,n,s=[],o=[],c=/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/gi,l=0,u=this.path.length;lp)for(var m=1,b=n.length;m"},addWithUpdate:function(t){return this._restoreObjectsState(),e.util.resetObjectTransform(this),t&&(this._objects.push(t),t.group=this,t._set("canvas",this.canvas)),this._calcBounds(),this._updateObjectsCoords(),this.setCoords(),this.dirty=!0,this},removeWithUpdate:function(t){return this._restoreObjectsState(),e.util.resetObjectTransform(this),this.remove(t),this._calcBounds(),this._updateObjectsCoords(),this.setCoords(),this.dirty=!0,this},_onObjectAdded:function(t){this.dirty=!0,t.group=this,t._set("canvas",this.canvas)},_onObjectRemoved:function(t){this.dirty=!0,delete t.group},_set:function(t,e){var i=this._objects.length;if(this.useSetOnGroup)for(;i--;)this._objects[i].setOnGroup(t,e);if("canvas"===t)for(i=this._objects.length;i--;)this._objects[i]._set(t,e);this.callSuper("_set",t,e)},toObject:function(t){var e=this.getObjects().map(function(e){var i=e.includeDefaultValues;e.includeDefaultValues=e.group.includeDefaultValues;var r=e.toObject(t);return e.includeDefaultValues=i,r});return i(this.callSuper("toObject",t),{objects:e})},toDatalessObject:function(t){var e,r=this.sourcePath;return e=r||this.getObjects().map(function(e){var i=e.includeDefaultValues;e.includeDefaultValues=e.group.includeDefaultValues;var r=e.toDatalessObject(t);return e.includeDefaultValues=i,r}),i(this.callSuper("toDatalessObject",t),{objects:e})},render:function(t){this._transformDone=!0,this.callSuper("render",t),this._transformDone=!1},shouldCache:function(){var t=this.objectCaching&&(!this.group||this.needsItsOwnCache()||!this.group.isOnACache());if(this.ownCaching=t,t)for(var e=0,i=this._objects.length;e\n');for(var i=0,r=this._objects.length;i\n"),t?t(e.join("")):e.join("")}}),e.Group.fromObject=function(t,i){e.util.enlivenObjects(t.objects,function(r){var n=e.util.object.clone(t,!0);delete n.objects,i&&i(new e.Group(r,n,!0))})})}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={});e.ActiveSelection||(e.ActiveSelection=e.util.createClass(e.Group,{type:"activeSelection",initialize:function(t,i){i=i||{},this._objects=t||[];for(var r=this._objects.length;r--;)this._objects[r].group=this;i.originX&&(this.originX=i.originX),i.originY&&(this.originY=i.originY),this._calcBounds(),this._updateObjectsCoords(),e.Object.prototype.initialize.call(this,i),this.setCoords()},toGroup:function(){var t=this._objects;this._objects=[];var i=this.toObject(),r=new e.Group([]);if(delete i.objects,r.set(i),r.type="group",t.forEach(function(t){t.group=r,t.canvas.remove(t)}),r._objects=t,!this.canvas)return r;var n=this.canvas;return n.add(r),n._activeObject=r,r.setCoords(),r},onDeselect:function(){return this.destroy(),!1},toString:function(){return"#"},_set:function(t,i){var r=this._objects.length;if("canvas"===t)for(;r--;)this._objects[r].set(t,i);if(this.useSetOnGroup)for(;r--;)this._objects[r].setOnGroup(t,i);e.Object.prototype._set.call(this,t,i)},shouldCache:function(){return!1},willDrawShadow:function(){if(this.shadow)return this.callSuper("willDrawShadow");for(var t=0,e=this._objects.length;t\n');var n=["\t\n'];if("fill"===this.paintFirst&&Array.prototype.push.apply(e,n),this.stroke||this.strokeDashArray){var s=this.fill;this.fill=null,e.push("\t\n'),this.fill=s}return"fill"!==this.paintFirst&&Array.prototype.push.apply(e,n),e.push("\n"),t?t(e.join("")):e.join("")},getSrc:function(t){var e=t?this._element:this._originalElement;return e?e.toDataURL?e.toDataURL():e.src:this.src||""},setSrc:function(t,e,i){return fabric.util.loadImage(t,function(t){this.setElement(t,i),e(this)},this,i&&i.crossOrigin),this},toString:function(){return'#'},applyResizeFilters:function(){var t=this.resizeFilter,e=this.canvas?this.canvas.getRetinaScaling():1,i=this.minimumScaleTrigger,r=this.scaleX*e,n=this.scaleY*e,s=this._filteredEl||this._originalElement;if(!t||r>i&&n>i)return this._element=s,this._filterScalingX=1,void(this._filterScalingY=1);fabric.filterBackend||(fabric.filterBackend=fabric.initFilterBackend());var o=fabric.util.createCanvasElement(),a=this._filteredEl?this.cacheKey:this.cacheKey+"_filtered",h=s.width,c=s.height;o.width=h,o.height=c,this._element=o,t.scaleX=r,t.scaleY=n,fabric.filterBackend.applyFilters([t],s,h,c,this._element,a),this._filterScalingX=o.width/this._originalElement.width,this._filterScalingY=o.height/this._originalElement.height},applyFilters:function(t){if(t=t||this.filters||[],0===(t=t.filter(function(t){return t})).length)return this._element=this._originalElement,this._filteredEl=null,this._filterScalingX=1,this._filterScalingY=1,this;var e=this._originalElement,i=e.naturalWidth||e.width,r=e.naturalHeight||e.height;if(this._element===this._originalElement){var n=fabric.util.createCanvasElement();n.width=i,n.height=r,this._element=n,this._filteredEl=n}else this._element.getContext("2d").clearRect(0,0,i,r);return fabric.filterBackend||(fabric.filterBackend=fabric.initFilterBackend()),fabric.filterBackend.applyFilters(t,this._originalElement,i,r,this._element,this.cacheKey),this._originalElement.width===this._element.width&&this._originalElement.height===this._element.height||(this._filterScalingX=this._element.width/this._originalElement.width,this._filterScalingY=this._element.height/this._originalElement.height),this},_render:function(t){!1===this.isMoving&&this.resizeFilter&&this._needsResize()&&(this._lastScaleX=this.scaleX,this._lastScaleY=this.scaleY,this.applyResizeFilters()),this._stroke(t),this._renderPaintInOrder(t)},_renderFill:function(t){var e=this.width,i=this.height,r=e*this._filterScalingX,n=i*this._filterScalingY,s=-e/2,o=-i/2,a=this._element;a&&t.drawImage(a,this.cropX*this._filterScalingX,this.cropY*this._filterScalingY,r,n,s,o,e,i)},_needsResize:function(){return this.scaleX!==this._lastScaleX||this.scaleY!==this._lastScaleY},_resetWidthHeight:function(){var t=this.getElement();this.set("width",t.width),this.set("height",t.height)},_initElement:function(t,e){this.setElement(fabric.util.getById(t),e),fabric.util.addClass(this.getElement(),fabric.Image.CSS_CANVAS)},_initConfig:function(t){t||(t={}),this.setOptions(t),this._setWidthHeight(t),this._element&&this.crossOrigin&&(this._element.crossOrigin=this.crossOrigin)},_initFilters:function(t,e){t&&t.length?fabric.util.enlivenObjects(t,function(t){e&&e(t)},"fabric.Image.filters"):e&&e()},_setWidthHeight:function(t){this.width="width"in t?t.width:this.getElement()?this.getElement().width||0:0,this.height="height"in t?t.height:this.getElement()?this.getElement().height||0:0},parsePreserveAspectRatioAttribute:function(){var t,e=fabric.util.parsePreserveAspectRatioAttribute(this.preserveAspectRatio||""),i=this._element.width,r=this._element.height,n=1,s=1,o=0,a=0,h=0,c=0,l=this.width,u=this.height,f={width:l,height:u};return!e||"none"===e.alignX&&"none"===e.alignY?(n=l/i,s=u/r):("meet"===e.meetOrSlice&&(t=(l-i*(n=s=fabric.util.findScaleToFit(this._element,f)))/2,"Min"===e.alignX&&(o=-t),"Max"===e.alignX&&(o=t),t=(u-r*s)/2,"Min"===e.alignY&&(a=-t),"Max"===e.alignY&&(a=t)),"slice"===e.meetOrSlice&&(t=i-l/(n=s=fabric.util.findScaleToCover(this._element,f)),"Mid"===e.alignX&&(h=t/2),"Max"===e.alignX&&(h=t),t=r-u/s,"Mid"===e.alignY&&(c=t/2),"Max"===e.alignY&&(c=t),i=l/n,r=u/s)),{width:i,height:r,scaleX:n,scaleY:s,offsetLeft:o,offsetTop:a,cropX:h,cropY:c}}}),fabric.Image.CSS_CANVAS="canvas-img",fabric.Image.prototype.getSvgSrc=fabric.Image.prototype.getSrc,fabric.Image.fromObject=function(t,e){fabric.util.loadImage(t.src,function(i,r){r?e&&e(null,r):fabric.Image.prototype._initFilters.call(t,t.filters,function(r){t.filters=r||[],fabric.Image.prototype._initFilters.call(t,[t.resizeFilter],function(r){t.resizeFilter=r[0];var n=new fabric.Image(i,t);e(n)})})},null,t.crossOrigin)},fabric.Image.fromURL=function(t,e,i){fabric.util.loadImage(t,function(t){e&&e(new fabric.Image(t,i))},null,i&&i.crossOrigin)},fabric.Image.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y width height preserveAspectRatio xlink:href crossOrigin".split(" ")),fabric.Image.fromElement=function(t,i,r){var n=fabric.parseAttributes(t,fabric.Image.ATTRIBUTE_NAMES);fabric.Image.fromURL(n["xlink:href"],i,e(r?fabric.util.object.clone(r):{},n))})}("undefined"!=typeof exports?exports:this),fabric.util.object.extend(fabric.Object.prototype,{_getAngleValueForStraighten:function(){var t=this.angle%360;return t>0?90*Math.round((t-1)/90):90*Math.round(t/90)},straighten:function(){return this.rotate(this._getAngleValueForStraighten()),this},fxStraighten:function(t){var e=function(){},i=(t=t||{}).onComplete||e,r=t.onChange||e,n=this;return fabric.util.animate({startValue:this.get("angle"),endValue:this._getAngleValueForStraighten(),duration:this.FX_DURATION,onChange:function(t){n.rotate(t),r()},onComplete:function(){n.setCoords(),i()}}),this}}),fabric.util.object.extend(fabric.StaticCanvas.prototype,{straightenObject:function(t){return t.straighten(),this.requestRenderAll(),this},fxStraightenObject:function(t){return t.fxStraighten({onChange:this.requestRenderAllBound}),this}}),function(){"use strict";function t(t,e){var i="precision "+e+" float;\nvoid main(){}",r=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(r,i),t.compileShader(r),!!t.getShaderParameter(r,t.COMPILE_STATUS)}function e(t){t&&t.tileSize&&(this.tileSize=t.tileSize),this.setupGLContext(this.tileSize,this.tileSize),this.captureGPUInfo()}fabric.isWebglSupported=function(e){if(fabric.isLikelyNode)return!1;e=e||fabric.WebglFilterBackend.prototype.tileSize;var i=document.createElement("canvas"),r=i.getContext("webgl")||i.getContext("experimental-webgl"),n=!1;if(r){fabric.maxTextureSize=r.getParameter(r.MAX_TEXTURE_SIZE),n=fabric.maxTextureSize>=e;for(var s=["highp","mediump","lowp"],o=0;o<3;o++)if(t(r,s[o])){fabric.webGlPrecision=s[o];break}}return this.isSupported=n,n},fabric.WebglFilterBackend=e,e.prototype={tileSize:2048,resources:{},setupGLContext:function(t,e){this.dispose(),this.createWebGLCanvas(t,e),this.aPosition=new Float32Array([0,0,0,1,1,0,1,1]),this.chooseFastestCopyGLTo2DMethod(t,e)},chooseFastestCopyGLTo2DMethod:function(t,e){var i,r=void 0!==window.performance;try{new ImageData(1,1),i=!0}catch(t){i=!1}var n="undefined"!=typeof ArrayBuffer,s="undefined"!=typeof Uint8ClampedArray;if(r&&i&&n&&s){var o,a,h=fabric.util.createCanvasElement(),c=new ArrayBuffer(t*e*4),l={imageBuffer:c,destinationWidth:t,destinationHeight:e,targetCanvas:h};h.width=t,h.height=e,o=window.performance.now(),copyGLTo2DDrawImage.call(l,this.gl,l),a=window.performance.now()-o,o=window.performance.now(),copyGLTo2DPutImageData.call(l,this.gl,l),a>window.performance.now()-o?(this.imageBuffer=c,this.copyGLTo2D=copyGLTo2DPutImageData):this.copyGLTo2D=copyGLTo2DDrawImage}},createWebGLCanvas:function(t,e){var i=fabric.util.createCanvasElement();i.width=t,i.height=e;var r={premultipliedAlpha:!1},n=i.getContext("webgl",r);n||(n=i.getContext("experimental-webgl",r)),n&&(n.clearColor(0,0,0,0),this.canvas=i,this.gl=n)},applyFilters:function(t,e,i,r,n,s){var o,a=this.gl;s&&(o=this.getCachedTexture(s,e));var h={originalWidth:e.width||e.originalWidth,originalHeight:e.height||e.originalHeight,sourceWidth:i,sourceHeight:r,destinationWidth:i,destinationHeight:r,context:a,sourceTexture:this.createTexture(a,i,r,!o&&e),targetTexture:this.createTexture(a,i,r),originalTexture:o||this.createTexture(a,i,r,!o&&e),passes:t.length,webgl:!0,aPosition:this.aPosition,programCache:this.programCache,pass:0,filterBackend:this,targetCanvas:n},c=a.createFramebuffer();return a.bindFramebuffer(a.FRAMEBUFFER,c),t.forEach(function(t){t&&t.applyTo(h)}),resizeCanvasIfNeeded(h),this.copyGLTo2D(a,h),a.bindTexture(a.TEXTURE_2D,null),a.deleteTexture(h.sourceTexture),a.deleteTexture(h.targetTexture),a.deleteFramebuffer(c),n.getContext("2d").setTransform(1,0,0,1,0,0),h},applyFiltersDebug:function(t,e,i,r,n,s){var o=this.gl,a=this.applyFilters(t,e,i,r,n,s),h=o.getError();if(h!==o.NO_ERROR){var c=this.glErrorToString(o,h),l=new Error("WebGL Error "+c);throw l.glErrorCode=h,l}return a},glErrorToString:function(t,e){if(!t)return"Context undefined for error code: "+e;if("number"!=typeof e)return"Error code is not a number";switch(e){case t.NO_ERROR:return"NO_ERROR";case t.INVALID_ENUM:return"INVALID_ENUM";case t.INVALID_VALUE:return"INVALID_VALUE";case t.INVALID_OPERATION:return"INVALID_OPERATION";case t.INVALID_FRAMEBUFFER_OPERATION:return"INVALID_FRAMEBUFFER_OPERATION";case t.OUT_OF_MEMORY:return"OUT_OF_MEMORY";case t.CONTEXT_LOST_WEBGL:return"CONTEXT_LOST_WEBGL";default:return"UNKNOWN_ERROR"}},dispose:function(){this.canvas&&(this.canvas=null,this.gl=null),this.clearWebGLCaches()},clearWebGLCaches:function(){this.programCache={},this.textureCache={}},createTexture:function(t,e,i,r){var n=t.createTexture();return t.bindTexture(t.TEXTURE_2D,n),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),r?t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,r):t.texImage2D(t.TEXTURE_2D,0,t.RGBA,e,i,0,t.RGBA,t.UNSIGNED_BYTE,null),n},getCachedTexture:function(t,e){if(this.textureCache[t])return this.textureCache[t];var i=this.createTexture(this.gl,e.width,e.height,e);return this.textureCache[t]=i,i},evictCachesForKey:function(t){this.textureCache[t]&&(this.gl.deleteTexture(this.textureCache[t]),delete this.textureCache[t])},copyGLTo2D:copyGLTo2DDrawImage,captureGPUInfo:function(){if(this.gpuInfo)return this.gpuInfo;var t=this.gl,e=t.getExtension("WEBGL_debug_renderer_info"),i={renderer:"",vendor:""};if(e){var r=t.getParameter(e.UNMASKED_RENDERER_WEBGL),n=t.getParameter(e.UNMASKED_VENDOR_WEBGL);r&&(i.renderer=r.toLowerCase()),n&&(i.vendor=n.toLowerCase())}return this.gpuInfo=i,i}}}(),function(){"use strict";function t(){}var e=function(){};fabric.Canvas2dFilterBackend=t,t.prototype={evictCachesForKey:e,dispose:e,clearWebGLCaches:e,resources:{},applyFilters:function(t,e,i,r,n){var s=n.getContext("2d");s.drawImage(e,0,0,i,r);var o={sourceWidth:i,sourceHeight:r,imageData:s.getImageData(0,0,i,r),originalEl:e,originalImageData:s.getImageData(0,0,i,r),canvasEl:n,ctx:s,filterBackend:this};return t.forEach(function(t){t.applyTo(o)}),o.imageData.width===i&&o.imageData.height===r||(n.width=o.imageData.width,n.height=o.imageData.height),s.putImageData(o.imageData,0,0),o}}}(),fabric.Image.filters=fabric.Image.filters||{},fabric.Image.filters.BaseFilter=fabric.util.createClass({type:"BaseFilter",vertexSource:"attribute vec2 aPosition;\nvarying vec2 vTexCoord;\nvoid main() {\nvTexCoord = aPosition;\ngl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\n}",fragmentSource:"precision highp float;\nvarying vec2 vTexCoord;\nuniform sampler2D uTexture;\nvoid main() {\ngl_FragColor = texture2D(uTexture, vTexCoord);\n}",initialize:function(t){t&&this.setOptions(t)},setOptions:function(t){for(var e in t)this[e]=t[e]},createProgram:function(t,e,i){e=e||this.fragmentSource,i=i||this.vertexSource,"highp"!==fabric.webGlPrecision&&(e=e.replace(/precision highp float/g,"precision "+fabric.webGlPrecision+" float"));var r=t.createShader(t.VERTEX_SHADER);if(t.shaderSource(r,i),t.compileShader(r),!t.getShaderParameter(r,t.COMPILE_STATUS))throw new Error("Vertex shader compile error for "+this.type+": "+t.getShaderInfoLog(r));var n=t.createShader(t.FRAGMENT_SHADER);if(t.shaderSource(n,e),t.compileShader(n),!t.getShaderParameter(n,t.COMPILE_STATUS))throw new Error("Fragment shader compile error for "+this.type+": "+t.getShaderInfoLog(n));var s=t.createProgram();if(t.attachShader(s,r),t.attachShader(s,n),t.linkProgram(s),!t.getProgramParameter(s,t.LINK_STATUS))throw new Error('Shader link error for "${this.type}" '+t.getProgramInfoLog(s));var o=this.getAttributeLocations(t,s),a=this.getUniformLocations(t,s)||{};return a.uStepW=t.getUniformLocation(s,"uStepW"),a.uStepH=t.getUniformLocation(s,"uStepH"),{program:s,attributeLocations:o,uniformLocations:a}},getAttributeLocations:function(t,e){return{aPosition:t.getAttribLocation(e,"aPosition")}},getUniformLocations:function(){return{}},sendAttributeData:function(t,e,i){var r=e.aPostion,n=t.createBuffer();t.bindBuffer(t.ARRAY_BUFFER,n),t.enableVertexAttribArray(r),t.vertexAttribPointer(r,2,t.FLOAT,!1,0,0),t.bufferData(t.ARRAY_BUFFER,i,t.STATIC_DRAW)},_setupFrameBuffer:function(t){var e,i,r=t.context;t.passes>1?(e=t.destinationWidth,i=t.destinationHeight,t.sourceWidth===e&&t.sourceHeight===i||(r.deleteTexture(t.targetTexture),t.targetTexture=t.filterBackend.createTexture(r,e,i)),r.framebufferTexture2D(r.FRAMEBUFFER,r.COLOR_ATTACHMENT0,r.TEXTURE_2D,t.targetTexture,0)):(r.bindFramebuffer(r.FRAMEBUFFER,null),r.finish())},_swapTextures:function(t){t.passes--,t.pass++;var e=t.targetTexture;t.targetTexture=t.sourceTexture,t.sourceTexture=e},isNeutralState:function(){return!1},applyTo:function(t){if(t.webgl){if(t.passes>1&&this.isNeutralState(t))return;this._setupFrameBuffer(t),this.applyToWebGL(t),this._swapTextures(t)}else this.isNeutralState()||this.applyTo2d(t)},retrieveShader:function(t){return t.programCache.hasOwnProperty(this.type)||(t.programCache[this.type]=this.createProgram(t.context)),t.programCache[this.type]},applyToWebGL:function(t){var e=t.context,i=this.retrieveShader(t);0===t.pass&&t.originalTexture?e.bindTexture(e.TEXTURE_2D,t.originalTexture):e.bindTexture(e.TEXTURE_2D,t.sourceTexture),e.useProgram(i.program),this.sendAttributeData(e,i.attributeLocations,t.aPosition),e.uniform1f(i.uniformLocations.uStepW,1/t.sourceWidth),e.uniform1f(i.uniformLocations.uStepH,1/t.sourceHeight),this.sendUniformData(e,i.uniformLocations),e.viewport(0,0,t.destinationWidth,t.destinationHeight),e.drawArrays(e.TRIANGLE_STRIP,0,4)},bindAdditionalTexture:function(t,e,i){t.activeTexture(i),t.bindTexture(t.TEXTURE_2D,e),t.activeTexture(t.TEXTURE0)},unbindAdditionalTexture:function(t,e){t.activeTexture(e),t.bindTexture(t.TEXTURE_2D,null),t.activeTexture(t.TEXTURE0)},getMainParameter:function(){return this[this.mainParameter]},setMainParameter:function(t){this[this.mainParameter]=t},sendUniformData:function(){},createHelpLayer:function(t){if(!t.helpLayer){var e=document.createElement("canvas");e.width=t.sourceWidth,e.height=t.sourceHeight,t.helpLayer=e}},toObject:function(){var t={type:this.type},e=this.mainParameter;return e&&(t[e]=this[e]),t},toJSON:function(){return this.toObject()}}),fabric.Image.filters.BaseFilter.fromObject=function(t,e){var i=new fabric.Image.filters[t.type](t);return e&&e(i),i},function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.Image.filters,r=e.util.createClass;i.ColorMatrix=r(i.BaseFilter,{type:"ColorMatrix",fragmentSource:"precision highp float;\nuniform sampler2D uTexture;\nvarying vec2 vTexCoord;\nuniform mat4 uColorMatrix;\nuniform vec4 uConstants;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\ncolor *= uColorMatrix;\ncolor += uConstants;\ngl_FragColor = color;\n}",matrix:[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0],mainParameter:"matrix",colorsOnly:!0,initialize:function(t){this.callSuper("initialize",t),this.matrix=this.matrix.slice(0)},isNeutralState:function(){for(var t=i.ColorMatrix,e=20;e--;)if(this.matrix[e]!==t.prototype.matrix[e])return!1;return!0},applyTo2d:function(t){var e,i,r,n,s,o=t.imageData.data,a=o.length,h=this.matrix,c=this.colorsOnly;for(s=0;sy||o<0||o>_||(h=4*(a*_+o),c=v[d*m+f],e+=p[h]*c,i+=p[h+1]*c,r+=p[h+2]*c,S||(n+=p[h+3]*c));C[s]=e,C[s+1]=i,C[s+2]=r,C[s+3]=S?p[s+3]:n}t.imageData=x},getUniformLocations:function(t,e){return{uMatrix:t.getUniformLocation(e,"uMatrix"),uOpaque:t.getUniformLocation(e,"uOpaque"),uHalfSize:t.getUniformLocation(e,"uHalfSize"),uSize:t.getUniformLocation(e,"uSize")}},sendUniformData:function(t,e){t.uniform1fv(e.uMatrix,this.matrix)},toObject:function(){return i(this.callSuper("toObject"),{opaque:this.opaque,matrix:this.matrix})}}),e.Image.filters.Convolute.fromObject=e.Image.filters.BaseFilter.fromObject}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.Image.filters,r=e.util.createClass;i.Grayscale=r(i.BaseFilter,{type:"Grayscale",fragmentSource:{average:"precision highp float;\nuniform sampler2D uTexture;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nfloat average = (color.r + color.b + color.g) / 3.0;\ngl_FragColor = vec4(average, average, average, color.a);\n}",lightness:"precision highp float;\nuniform sampler2D uTexture;\nuniform int uMode;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 col = texture2D(uTexture, vTexCoord);\nfloat average = (max(max(col.r, col.g),col.b) + min(min(col.r, col.g),col.b)) / 2.0;\ngl_FragColor = vec4(average, average, average, col.a);\n}",luminosity:"precision highp float;\nuniform sampler2D uTexture;\nuniform int uMode;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 col = texture2D(uTexture, vTexCoord);\nfloat average = 0.21 * col.r + 0.72 * col.g + 0.07 * col.b;\ngl_FragColor = vec4(average, average, average, col.a);\n}"},mode:"average",mainParameter:"mode",applyTo2d:function(t){var e,i,r=t.imageData.data,n=r.length,s=this.mode;for(e=0;ec[0]&&n>c[1]&&s>c[2]&&r1&&this.isNeutralState(t))return;t.passes++,this.width=t.sourceWidth,this.horizontal=!0,this.dW=Math.round(this.width*this.scaleX),this.dH=t.sourceHeight,this.tempScale=this.dW/this.width,this.taps=this.getTaps(),t.destinationWidth=this.dW,this._setupFrameBuffer(t),this.applyToWebGL(t),this._swapTextures(t),t.sourceWidth=t.destinationWidth,this.height=t.sourceHeight,this.horizontal=!1,this.dH=Math.round(this.height*this.scaleY),this.tempScale=this.dH/this.height,this.taps=this.getTaps(),t.destinationHeight=this.dH,this._setupFrameBuffer(t),this.applyToWebGL(t),this._swapTextures(t),t.sourceHeight=t.destinationHeight}else this.isNeutralState(t)||this.applyTo2d(t)},isNeutralState:function(t){var e=t.scaleX||this.scaleX,i=t.scaleY||this.scaleY;return 1===e&&1===i},lanczosCreate:function(t){return function(e){if(e>=t||e<=-t)return 0;if(e<1.1920929e-7&&e>-1.1920929e-7)return 1;var i=(e*=Math.PI)/t;return a(e)/e*a(i)/i}},applyTo2d:function(t){var e=t.imageData,i=this.scaleX,r=this.scaleY;this.rcpScaleX=1/i,this.rcpScaleY=1/r;var n,s=e.width,a=e.height,h=o(s*i),c=o(a*r);"sliceHack"===this.resizeType?n=this.sliceByTwo(t,s,a,h,c):"hermite"===this.resizeType?n=this.hermiteFastResize(t,s,a,h,c):"bilinear"===this.resizeType?n=this.bilinearFiltering(t,s,a,h,c):"lanczos"===this.resizeType&&(n=this.lanczosResize(t,s,a,h,c)),t.imageData=n},sliceByTwo:function(t,i,n,s,o){var a,h,c=t.imageData,l=!1,u=!1,f=.5*i,d=.5*n,g=e.filterBackend.resources,p=0,v=0,m=i,b=0;for(g.sliceByTwo||(g.sliceByTwo=document.createElement("canvas")),((a=g.sliceByTwo).width<1.5*i||a.height=e)){P=r(1e3*s(w-C.x)),x[P]||(x[P]={});for(var F=S.y-y;F<=S.y+y;F++)F<0||F>=o||(M=r(1e3*s(F-C.y)),x[P][M]||(x[P][M]=g(n(i(P*m,2)+i(M*b,2))/1e3)),(T=x[P][M])>0&&(k+=T,D+=T*u[O=4*(F*e+w)],j+=T*u[O+1],E+=T*u[O+2],A+=T*u[O+3]))}d[O=4*(h*a+t)]=D/k,d[O+1]=j/k,d[O+2]=E/k,d[O+3]=A/k}return++t1&&M<-1||(_=2*M*M*M-3*M*M+1)>0&&(T+=_*d[(P=4*(A+k*e))+3],x+=_,d[P+3]<255&&(_=_*d[P+3]/250),C+=_*d[P],S+=_*d[P+1],w+=_*d[P+2],y+=_)}p[b]=C/y,p[b+1]=S/y,p[b+2]=w/y,p[b+3]=T/x}return g},toObject:function(){return{type:this.type,scaleX:this.scaleX,scaleY:this.scaleY,resizeType:this.resizeType,lanczosLobes:this.lanczosLobes}}}),e.Image.filters.Resize.fromObject=e.Image.filters.BaseFilter.fromObject}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.Image.filters,r=e.util.createClass;i.Contrast=r(i.BaseFilter,{type:"Contrast",fragmentSource:"precision highp float;\nuniform sampler2D uTexture;\nuniform float uContrast;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nfloat contrastF = 1.015 * (uContrast + 1.0) / (1.0 * (1.015 - uContrast));\ncolor.rgb = contrastF * (color.rgb - 0.5) + 0.5;\ngl_FragColor = color;\n}",contrast:0,mainParameter:"contrast",applyTo2d:function(t){if(0!==this.contrast){var e,i=t.imageData.data,r=i.length,n=Math.floor(255*this.contrast),s=259*(n+255)/(255*(259-n));for(e=0;e1&&(e=1/this.aspectRatio):this.aspectRatio<1&&(e=this.aspectRatio),t=e*this.blur*.12,this.horizontal?i[0]=t:i[1]=t,i}}),i.Blur.fromObject=e.Image.filters.BaseFilter.fromObject}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.Image.filters,r=e.util.createClass;i.Gamma=r(i.BaseFilter,{type:"Gamma",fragmentSource:"precision highp float;\nuniform sampler2D uTexture;\nuniform vec3 uGamma;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nvec3 correction = (1.0 / uGamma);\ncolor.r = pow(color.r, correction.r);\ncolor.g = pow(color.g, correction.g);\ncolor.b = pow(color.b, correction.b);\ngl_FragColor = color;\ngl_FragColor.rgb *= color.a;\n}",gamma:[1,1,1],mainParameter:"gamma",applyTo2d:function(t){var e,i=t.imageData.data,r=this.gamma,n=i.length,s=1/r[0],o=1/r[1],a=1/r[2];for(this.rVals||(this.rVals=new Uint8Array(256),this.gVals=new Uint8Array(256),this.bVals=new Uint8Array(256)),e=0,n=256;e'},_getCacheCanvasDimensions:function(){var t=this.callSuper("_getCacheCanvasDimensions"),e=this.fontSize;return t.width+=e*t.zoomX,t.height+=e*t.zoomY,t},_render:function(t){this._setTextStyles(t),this._renderTextLinesBackground(t),this._renderTextDecoration(t,"underline"),this._renderText(t),this._renderTextDecoration(t,"overline"),this._renderTextDecoration(t,"linethrough")},_renderText:function(t){"stroke"===this.paintFirst?(this._renderTextStroke(t),this._renderTextFill(t)):(this._renderTextFill(t),this._renderTextStroke(t))},_setTextStyles:function(t,e,i){t.textBaseline="alphabetic",t.font=this._getFontDeclaration(e,i)},calcTextWidth:function(){for(var t=this.getLineWidth(0),e=1,i=this._textLines.length;et&&(t=r)}return t},_renderTextLine:function(t,e,i,r,n,s){this._renderChars(t,e,i,r,n,s)},_renderTextLinesBackground:function(t){if(this.textBackgroundColor||this.styleHas("textBackgroundColor")){for(var e,i,r,n,s,o,a=0,h=t.fillStyle,c=this._getLeftOffset(),l=this._getTopOffset(),u=0,f=0,d=0,g=this._textLines.length;dn)){var d=a-n;h[t]=a,h[c]+=d,n=a}return{width:n*u,kernedWidth:a*u}},getHeightOfChar:function(t,e){return this.getValueOfPropertyAt(t,e,"fontSize")},measureLine:function(t){var e=this._measureLine(t);return 0!==this.charSpacing&&(e.width-=this._getWidthOfCharSpacing()),e.width<0&&(e.width=0),e},_measureLine:function(t){var e,i,r,n,s=0,o=this._textLines[t],a=new Array(o.length);for(this.__charBounds[t]=a,e=0;e0&&!n){var u=this.__charBounds[e][i-1];l.left=u.left+u.width+a.kernedWidth-a.width}return l},getHeightOfLine:function(t){if(this.__lineHeights[t])return this.__lineHeights[t];for(var e=this._textLines[t],i=this.getHeightOfChar(t,0),r=1,n=e.length;ri&&(i=s)}return this.__lineHeights[t]=i*this.lineHeight*this._fontSizeMult,this.__lineHeights[t]},calcTextHeight:function(){for(var t,e=0,i=0,r=this._textLines.length;i0?(t.fillStyle=f,s&&f&&t.fillRect(d+r+o,g+l*(1-this._fontSizeFraction)+this.offsets[e]*this.fontSize,a,this.fontSize/15),o=h.left,a=h.width,s=c,f=u):a+=h.kernedWidth;t.fillStyle=u,c&&u&&t.fillRect(d+r+o,g+l*(1-this._fontSizeFraction)+this.offsets[e]*this.fontSize,a,this.fontSize/15),g+=i}else g+=i;this._removeShadow(t)}},_getFontDeclaration:function(t,i){var r=t||this;return[e.isLikelyNode?r.fontWeight:r.fontStyle,e.isLikelyNode?r.fontStyle:r.fontWeight,i?"200px":r.fontSize+"px",e.isLikelyNode?'"'+r.fontFamily+'"':r.fontFamily].join(" ")},render:function(t){this.visible&&(this.canvas&&this.canvas.skipOffscreen&&!this.group&&!this.isOnScreen()||(this._shouldClearDimensionCache()&&this.initDimensions(),this.callSuper("render",t)))},_splitTextIntoLines:function(t){for(var i=t.split(this._reNewline),r=new Array(i.length),n=["\n"],s=[],o=0;o-1&&(t.underline=!0),t.textDecoration.indexOf("line-through")>-1&&(t.linethrough=!0),t.textDecoration.indexOf("overline")>-1&&(t.overline=!0),delete t.textDecoration)}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,caching:!0,_reSpace:/\s|\n/,_currentCursorOpacity:0,_selectionDirection:null,_abortCursorAnimation:!1,__widthOfSpace:[],inCompositionMode:!1,initialize:function(t,e){this.callSuper("initialize",t,e),this.initBehavior()},setSelectionStart:function(t){t=Math.max(t,0),this._updateAndFire("selectionStart",t)},setSelectionEnd:function(t){t=Math.min(t,this.text.length),this._updateAndFire("selectionEnd",t)},_updateAndFire:function(t,e){this[t]!==e&&(this._fireSelectionChanged(),this[t]=e),this._updateTextarea()},_fireSelectionChanged:function(){this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})},initDimensions:function(){this.isEditing&&this.initDelayedCursor(),this.clearContextTop(),this.callSuper("initDimensions")},render:function(t){this.clearContextTop(),this.callSuper("render",t),this.cursorOffsetCache={},this.renderCursorOrSelection()},_render:function(t){this.callSuper("_render",t)},clearContextTop:function(t){if(this.isEditing&&this.canvas&&this.canvas.contextTop){var e=this.canvas.contextTop,i=this.canvas.viewportTransform;e.save(),e.transform(i[0],i[1],i[2],i[3],i[4],i[5]),this.transform(e),this.transformMatrix&&e.transform.apply(e,this.transformMatrix),this._clearTextArea(e),t||e.restore()}},renderCursorOrSelection:function(){if(this.isEditing&&this.canvas){var t,e=this._getCursorBoundaries();this.canvas&&this.canvas.contextTop?(t=this.canvas.contextTop,this.clearContextTop(!0)):(t=this.canvas.contextContainer).save(),this.selectionStart===this.selectionEnd?this.renderCursor(e,t):this.renderSelection(e,t),t.restore()}},_clearTextArea:function(t){var e=this.width+4,i=this.height+4;t.clearRect(-e/2,-i/2,e,i)},_getCursorBoundaries:function(t){void 0===t&&(t=this.selectionStart);var e=this._getLeftOffset(),i=this._getTopOffset(),r=this._getCursorBoundariesOffsets(t);return{left:e,top:i,leftOffset:r.left,topOffset:r.top}},_getCursorBoundariesOffsets:function(t){if(this.cursorOffsetCache&&"top"in this.cursorOffsetCache)return this.cursorOffsetCache;for(var e,i,r=0,n=0,s=this.get2DCursorLocation(t),o=0;o0?n:0)},this.cursorOffsetCache=i,this.cursorOffsetCache},renderCursor:function(t,e){var i=this.get2DCursorLocation(),r=i.lineIndex,n=i.charIndex>0?i.charIndex-1:0,s=this.getValueOfPropertyAt(r,n,"fontSize"),o=this.scaleX*this.canvas.getZoom(),a=this.cursorWidth/o,h=t.topOffset;h+=(1-this._fontSizeFraction)*this.getHeightOfLine(r)/this.lineHeight-s*(1-this._fontSizeFraction),this.inCompositionMode&&this.renderSelection(t,e),e.fillStyle=this.getValueOfPropertyAt(r,n,"fill"),e.globalAlpha=this.__isMousedown?1:this._currentCursorOpacity,e.fillRect(t.left+t.leftOffset-a/2,h+t.top,a,s)},renderSelection:function(t,e){for(var i=this.inCompositionMode?this.hiddenTextarea.selectionStart:this.selectionStart,r=this.inCompositionMode?this.hiddenTextarea.selectionEnd:this.selectionEnd,n=-1!==this.textAlign.indexOf("justify"),s=this.get2DCursorLocation(i),o=this.get2DCursorLocation(r),a=s.lineIndex,h=o.lineIndex,c=s.charIndex<0?0:s.charIndex,l=o.charIndex<0?0:o.charIndex,u=a;u<=h;u++){var f=this._getLineLeftOffset(u)||0,d=this.getHeightOfLine(u),g=0,p=0,v=0;u===a&&(p=this.__charBounds[a][c].left),u>=a&&u1)&&(d/=this.lineHeight),this.inCompositionMode?(e.fillStyle=this.compositionColor||"black",e.fillRect(t.left+f+p,t.top+t.topOffset+d,v-p,1)):(e.fillStyle=this.selectionColor,e.fillRect(t.left+f+p,t.top+t.topOffset,v-p,d)),t.topOffset+=g}},getCurrentCharFontSize:function(){var t=this._getCurrentCharIndex();return this.getValueOfPropertyAt(t.l,t.c,"fontSize")},getCurrentCharColor:function(){var t=this._getCurrentCharIndex();return this.getValueOfPropertyAt(t.l,t.c,"fill")},_getCurrentCharIndex:function(){var t=this.get2DCursorLocation(this.selectionStart,!0),e=t.charIndex>0?t.charIndex-1:0;return{l:t.lineIndex,c:e}}}),fabric.IText.fromObject=function(e,i){if(t(e),e.styles)for(var r in e.styles)for(var n in e.styles[r])t(e.styles[r][n]);fabric.Object._fromObject("IText",e,i,"text")}}(),function(){var t=fabric.util.object.clone;fabric.util.object.extend(fabric.IText.prototype,{initBehavior:function(){this.initAddedHandler(),this.initRemovedHandler(),this.initCursorSelectionHandlers(),this.initDoubleClickSimulation(),this.mouseMoveHandler=this.mouseMoveHandler.bind(this)},onDeselect:function(t){this.isEditing&&this.exitEditing(),this.selected=!1,fabric.Object.prototype.onDeselect.call(this,t)},initAddedHandler:function(){var t=this;this.on("added",function(){var e=t.canvas;e&&(e._hasITextHandlers||(e._hasITextHandlers=!0,t._initCanvasHandlers(e)),e._iTextInstances=e._iTextInstances||[],e._iTextInstances.push(t))})},initRemovedHandler:function(){var t=this;this.on("removed",function(){var e=t.canvas;e&&(e._iTextInstances=e._iTextInstances||[],fabric.util.removeFromArray(e._iTextInstances,t),0===e._iTextInstances.length&&(e._hasITextHandlers=!1,t._removeCanvasHandlers(e)))})},_initCanvasHandlers:function(t){t._mouseUpITextHandler=function(){t._iTextInstances&&t._iTextInstances.forEach(function(t){t.__isMousedown=!1})}.bind(this),t.on("mouse:up",t._mouseUpITextHandler)},_removeCanvasHandlers:function(t){t.off("mouse:up",t._mouseUpITextHandler)},_tick:function(){this._currentTickState=this._animateCursor(this,1,this.cursorDuration,"_onTickComplete")},_animateCursor:function(t,e,i,r){var n;return n={isAborted:!1,abort:function(){this.isAborted=!0}},t.animate("_currentCursorOpacity",e,{duration:i,onComplete:function(){n.isAborted||t[r]()},onChange:function(){t.canvas&&t.selectionStart===t.selectionEnd&&t.renderCursorOrSelection()},abort:function(){return n.isAborted}}),n},_onTickComplete:function(){var t=this;this._cursorTimeout1&&clearTimeout(this._cursorTimeout1),this._cursorTimeout1=setTimeout(function(){t._currentTickCompleteState=t._animateCursor(t,0,this.cursorDuration/2,"_tick")},100)},initDelayedCursor:function(t){var e=this,i=t?0:this.cursorDelay;this.abortCursorAnimation(),this._currentCursorOpacity=1,this._cursorTimeout2=setTimeout(function(){e._tick()},i)},abortCursorAnimation:function(){var t=this._currentTickState||this._currentTickCompleteState,e=this.canvas;this._currentTickState&&this._currentTickState.abort(),this._currentTickCompleteState&&this._currentTickCompleteState.abort(),clearTimeout(this._cursorTimeout1),clearTimeout(this._cursorTimeout2),this._currentCursorOpacity=0,t&&e&&e.clearContext(e.contextTop||e.contextContainer)},selectAll:function(){return this.selectionStart=0,this.selectionEnd=this._text.length,this._fireSelectionChanged(),this._updateTextarea(),this},getSelectedText:function(){return this._text.slice(this.selectionStart,this.selectionEnd).join("")},findWordBoundaryLeft:function(t){var e=0,i=t-1;if(this._reSpace.test(this._text[i]))for(;this._reSpace.test(this._text[i]);)e++,i--;for(;/\S/.test(this._text[i])&&i>-1;)e++,i--;return t-e},findWordBoundaryRight:function(t){var e=0,i=t;if(this._reSpace.test(this._text[i]))for(;this._reSpace.test(this._text[i]);)e++,i++;for(;/\S/.test(this._text[i])&&i-1;)e++,i--;return t-e},findLineBoundaryRight:function(t){for(var e=0,i=t;!/\n/.test(this._text[i])&&i0&&ithis.__selectionStartOnMouseDown?(this.selectionStart=this.__selectionStartOnMouseDown,this.selectionEnd=e):(this.selectionStart=e,this.selectionEnd=this.__selectionStartOnMouseDown),this.selectionStart===i&&this.selectionEnd===r||(this.restartCursorIfNeeded(),this._fireSelectionChanged(),this._updateTextarea(),this.renderCursorOrSelection()))}},_setEditingProps:function(){this.hoverCursor="text",this.canvas&&(this.canvas.defaultCursor=this.canvas.moveCursor="text"),this.borderColor=this.editingBorderColor,this.hasControls=this.selectable=!1,this.lockMovementX=this.lockMovementY=!0},fromStringToGraphemeSelection:function(t,e,i){var r=i.slice(0,t),n=fabric.util.string.graphemeSplit(r).length;if(t===e)return{selectionStart:n,selectionEnd:n};var s=i.slice(t,e);return{selectionStart:n,selectionEnd:n+fabric.util.string.graphemeSplit(s).length}},fromGraphemeToStringSelection:function(t,e,i){var r=i.slice(0,t).join("").length;if(t===e)return{selectionStart:r,selectionEnd:r};return{selectionStart:r,selectionEnd:r+i.slice(t,e).join("").length}},_updateTextarea:function(){if(this.cursorOffsetCache={},this.hiddenTextarea){if(!this.inCompositionMode){var t=this.fromGraphemeToStringSelection(this.selectionStart,this.selectionEnd,this._text);this.hiddenTextarea.selectionStart=t.selectionStart,this.hiddenTextarea.selectionEnd=t.selectionEnd}this.updateTextareaPosition()}},updateFromTextArea:function(){if(this.hiddenTextarea){this.cursorOffsetCache={},this.text=this.hiddenTextarea.value,this._shouldClearDimensionCache()&&(this.initDimensions(),this.setCoords());var t=this.fromStringToGraphemeSelection(this.hiddenTextarea.selectionStart,this.hiddenTextarea.selectionEnd,this.hiddenTextarea.value);this.selectionEnd=this.selectionStart=t.selectionEnd,this.inCompositionMode||(this.selectionStart=t.selectionStart),this.updateTextareaPosition()}},updateTextareaPosition:function(){if(this.selectionStart===this.selectionEnd){var t=this._calcTextareaPosition();this.hiddenTextarea.style.left=t.left,this.hiddenTextarea.style.top=t.top}},_calcTextareaPosition:function(){if(!this.canvas)return{x:1,y:1};var t=this.inCompositionMode?this.compositionStart:this.selectionStart,e=this._getCursorBoundaries(t),i=this.get2DCursorLocation(t),r=i.lineIndex,n=i.charIndex,s=this.getValueOfPropertyAt(r,n,"fontSize")*this.lineHeight,o=e.leftOffset,a=this.calcTransformMatrix(),h={x:e.left+o,y:e.top+e.topOffset+s},c=this.canvas.upperCanvasEl,l=c.width-s,u=c.height-s;return h=fabric.util.transformPoint(h,a),(h=fabric.util.transformPoint(h,this.canvas.viewportTransform)).x<0&&(h.x=0),h.x>l&&(h.x=l),h.y<0&&(h.y=0),h.y>u&&(h.y=u),h.x+=this.canvas._offset.left,h.y+=this.canvas._offset.top,{left:h.x+"px",top:h.y+"px",fontSize:s+"px",charHeight:s}},_saveEditingProps:function(){this._savedProps={hasControls:this.hasControls,borderColor:this.borderColor,lockMovementX:this.lockMovementX,lockMovementY:this.lockMovementY,hoverCursor:this.hoverCursor,defaultCursor:this.canvas&&this.canvas.defaultCursor,moveCursor:this.canvas&&this.canvas.moveCursor}},_restoreEditingProps:function(){this._savedProps&&(this.hoverCursor=this._savedProps.hoverCursor,this.hasControls=this._savedProps.hasControls,this.borderColor=this._savedProps.borderColor,this.lockMovementX=this._savedProps.lockMovementX,this.lockMovementY=this._savedProps.lockMovementY,this.canvas&&(this.canvas.defaultCursor=this._savedProps.defaultCursor,this.canvas.moveCursor=this._savedProps.moveCursor))},exitEditing:function(){var t=this._textBeforeEdit!==this.text;return this.selected=!1,this.isEditing=!1,this.selectable=!0,this.selectionEnd=this.selectionStart,this.hiddenTextarea&&(this.hiddenTextarea.blur&&this.hiddenTextarea.blur(),this.canvas&&this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea),this.hiddenTextarea=null),this.abortCursorAnimation(),this._restoreEditingProps(),this._currentCursorOpacity=0,this._shouldClearDimensionCache()&&(this.initDimensions(),this.setCoords()),this.fire("editing:exited"),t&&this.fire("modified"),this.canvas&&(this.canvas.off("mouse:move",this.mouseMoveHandler),this.canvas.fire("text:editing:exited",{target:this}),t&&this.canvas.fire("object:modified",{target:this})),this},_removeExtraneousStyles:function(){for(var t in this.styles)this._textLines[t]||delete this.styles[t]},removeStyleFromTo:function(t,e){var i,r,n=this.get2DCursorLocation(t,!0),s=this.get2DCursorLocation(e,!0),o=n.lineIndex,a=n.charIndex,h=s.lineIndex,c=s.charIndex;if(o!==h){if(this.styles[o])for(i=a;i=c&&(r[l-f]=r[u],delete r[u])}},shiftLineStyles:function(e,i){var r=t(this.styles);for(var n in this.styles){var s=parseInt(n,10);s>e&&(this.styles[s+i]=r[s],r[s-i]||delete this.styles[s])}},restartCursorIfNeeded:function(){this._currentTickState&&!this._currentTickState.isAborted&&this._currentTickCompleteState&&!this._currentTickCompleteState.isAborted||this.initDelayedCursor()},insertNewlineStyleObject:function(e,i,r,n){var s,o={},a=!1;r||(r=1),this.shiftLineStyles(e,r),this.styles[e]&&(s=this.styles[e][0===i?i:i-1]);for(var h in this.styles[e]){var c=parseInt(h,10);c>=i&&(a=!0,o[c-i]=this.styles[e][h],delete this.styles[e][h])}for(a?this.styles[e+r]=o:delete this.styles[e+r];r>1;)r--,n&&n[r]?this.styles[e+r]={0:t(n[r])}:s?this.styles[e+r]={0:t(s)}:delete this.styles[e+r];this._forceClearCache=!0},insertCharStyleObject:function(e,i,r,n){this.styles||(this.styles={});var s=this.styles[e],o=s?t(s):{};r||(r=1);for(var a in o){var h=parseInt(a,10);h>=i&&(s[h+r]=o[h],o[h-r]||delete s[h])}if(this._forceClearCache=!0,n)for(;r--;)Object.keys(n[r]).length&&(this.styles[e]||(this.styles[e]={}),this.styles[e][i+r]=t(n[r]));else if(s)for(var c=s[i?i-1:1];c&&r--;)this.styles[e][i+r]=t(c)},insertNewStyleBlock:function(t,e,i){for(var r=this.get2DCursorLocation(e,!0),n=[0],s=0,o=0;o0&&(this.insertCharStyleObject(r.lineIndex,r.charIndex,n[0],i),i=i&&i.slice(n[0]+1)),s&&this.insertNewlineStyleObject(r.lineIndex,r.charIndex+n[0],s);for(o=1;o0?this.insertCharStyleObject(r.lineIndex+o,0,n[o],i):i&&(this.styles[r.lineIndex+o][0]=i[0]),i=i&&i.slice(n[o]+1);n[o]>0&&this.insertCharStyleObject(r.lineIndex+o,0,n[o],i)},setSelectionStartEndWithShift:function(t,e,i){i<=t?(e===t?this._selectionDirection="left":"right"===this._selectionDirection&&(this._selectionDirection="left",this.selectionEnd=t),this.selectionStart=i):i>t&&it?this.selectionStart=t:this.selectionStart<0&&(this.selectionStart=0),this.selectionEnd>t?this.selectionEnd=t:this.selectionEnd<0&&(this.selectionEnd=0)}})}(),fabric.util.object.extend(fabric.IText.prototype,{initDoubleClickSimulation:function(){this.__lastClickTime=+new Date,this.__lastLastClickTime=+new Date,this.__lastPointer={},this.on("mousedown",this.onMouseDown.bind(this))},onMouseDown:function(t){this.__newClickTime=+new Date;var e=this.canvas.getPointer(t.e);this.isTripleClick(e,t.e)&&(this.fire("tripleclick",t),this._stopEvent(t.e)),this.__lastLastClickTime=this.__lastClickTime,this.__lastClickTime=this.__newClickTime,this.__lastPointer=e,this.__lastIsEditing=this.isEditing,this.__lastSelected=this.selected},isTripleClick:function(t){return this.__newClickTime-this.__lastClickTime<500&&this.__lastClickTime-this.__lastLastClickTime<500&&this.__lastPointer.x===t.x&&this.__lastPointer.y===t.y},_stopEvent:function(t){t.preventDefault&&t.preventDefault(),t.stopPropagation&&t.stopPropagation()},initCursorSelectionHandlers:function(){this.initMousedownHandler(),this.initMouseupHandler(),this.initClicks()},initClicks:function(){this.on("mousedblclick",function(t){this.selectWord(this.getSelectionStartFromPointer(t.e))}),this.on("tripleclick",function(t){this.selectLine(this.getSelectionStartFromPointer(t.e))})},_mouseDownHandler:function(t){if(this.canvas&&this.editable&&(!t.e.button||1===t.e.button)){var e=this.canvas.getPointer(t.e);this.__mousedownX=e.x,this.__mousedownY=e.y,this.__isMousedown=!0,this.selected&&this.setCursorByClick(t.e),this.isEditing&&(this.__selectionStartOnMouseDown=this.selectionStart,this.selectionStart===this.selectionEnd&&this.abortCursorAnimation(),this.renderCursorOrSelection())}},initMousedownHandler:function(){this.on("mousedown",this._mouseDownHandler)},_isObjectMoved:function(t){var e=this.canvas.getPointer(t);return this.__mousedownX!==e.x||this.__mousedownY!==e.y},initMouseupHandler:function(){this.on("mouseup",function(t){this.__isMousedown=!1,!this.editable||this._isObjectMoved(t.e)||t.e.button&&1!==t.e.button||(this.__lastSelected&&!this.__corner&&(this.enterEditing(t.e),this.selectionStart===this.selectionEnd?this.initDelayedCursor(!0):this.renderCursorOrSelection()),this.selected=!0)})},setCursorByClick:function(t){var e=this.getSelectionStartFromPointer(t),i=this.selectionStart,r=this.selectionEnd;t.shiftKey?this.setSelectionStartEndWithShift(i,r,e):(this.selectionStart=e,this.selectionEnd=e),this.isEditing&&(this._fireSelectionChanged(),this._updateTextarea())},getSelectionStartFromPointer:function(t){for(var e,i=this.getLocalPointer(t),r=0,n=0,s=0,o=0,a=0,h=0,c=this._textLines.length;h0&&(o+=this._textLines[h-1].length+1);n=this._getLineLeftOffset(a)*this.scaleX;for(var l=0,u=(e=this._textLines[a]).length;ls||o<0?0:1);return this.flipX&&(a=n-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.setAttribute("autocorrect","off"),this.hiddenTextarea.setAttribute("autocomplete","off"),this.hiddenTextarea.setAttribute("spellcheck","false"),this.hiddenTextarea.setAttribute("data-fabric-hiddentextarea",""),this.hiddenTextarea.setAttribute("wrap","off");var t=this._calcTextareaPosition();this.hiddenTextarea.style.cssText="position: absolute; top: "+t.top+"; left: "+t.left+"; z-index: -999; opacity: 0; width: 1px; height: 1px; font-size: 1px; line-height: 1px; paddingーtop: "+t.fontSize+";",fabric.document.body.appendChild(this.hiddenTextarea),fabric.util.addListener(this.hiddenTextarea,"keydown",this.onKeyDown.bind(this)),fabric.util.addListener(this.hiddenTextarea,"keyup",this.onKeyUp.bind(this)),fabric.util.addListener(this.hiddenTextarea,"input",this.onInput.bind(this)),fabric.util.addListener(this.hiddenTextarea,"copy",this.copy.bind(this)),fabric.util.addListener(this.hiddenTextarea,"cut",this.copy.bind(this)),fabric.util.addListener(this.hiddenTextarea,"paste",this.paste.bind(this)),fabric.util.addListener(this.hiddenTextarea,"compositionstart",this.onCompositionStart.bind(this)),fabric.util.addListener(this.hiddenTextarea,"compositionupdate",this.onCompositionUpdate.bind(this)),fabric.util.addListener(this.hiddenTextarea,"compositionend",this.onCompositionEnd.bind(this)),!this._clickHandlerInitialized&&this.canvas&&(fabric.util.addListener(this.canvas.upperCanvasEl,"click",this.onClick.bind(this)),this._clickHandlerInitialized=!0)},keysMap:{9:"exitEditing",27:"exitEditing",33:"moveCursorUp",34:"moveCursorDown",35:"moveCursorRight",36:"moveCursorLeft",37:"moveCursorLeft",38:"moveCursorUp",39:"moveCursorRight",40:"moveCursorDown"},ctrlKeysMapUp:{67:"copy",88:"cut"},ctrlKeysMapDown:{65:"selectAll"},onClick:function(){this.hiddenTextarea&&this.hiddenTextarea.focus()},onKeyDown:function(t){if(this.isEditing&&!this.inCompositionMode){if(t.keyCode in this.keysMap)this[this.keysMap[t.keyCode]](t);else{if(!(t.keyCode in this.ctrlKeysMapDown&&(t.ctrlKey||t.metaKey)))return;this[this.ctrlKeysMapDown[t.keyCode]](t)}t.stopImmediatePropagation(),t.preventDefault(),t.keyCode>=33&&t.keyCode<=40?(this.clearContextTop(),this.renderCursorOrSelection()):this.canvas&&this.canvas.requestRenderAll()}},onKeyUp:function(t){!this.isEditing||this._copyDone||this.inCompositionMode?this._copyDone=!1:t.keyCode in this.ctrlKeysMapUp&&(t.ctrlKey||t.metaKey)&&(this[this.ctrlKeysMapUp[t.keyCode]](t),t.stopImmediatePropagation(),t.preventDefault(),this.canvas&&this.canvas.requestRenderAll())},onInput:function(t){var e=this.fromPaste;if(this.fromPaste=!1,t&&t.stopPropagation(),this.isEditing){var i,r,n=this._splitTextIntoLines(this.hiddenTextarea.value).graphemeText,s=this._text.length,o=n.length,a=o-s;if(""===this.hiddenTextarea.value)return this.styles={},this.updateFromTextArea(),this.fire("changed"),void(this.canvas&&(this.canvas.fire("text:changed",{target:this}),this.canvas.requestRenderAll()));var h=this.fromStringToGraphemeSelection(this.hiddenTextarea.selectionStart,this.hiddenTextarea.selectionEnd,this.hiddenTextarea.value),c=this.selectionStart>h.selectionStart;this.selectionStart!==this.selectionEnd?(i=this._text.slice(this.selectionStart,this.selectionEnd),a+=this.selectionEnd-this.selectionStart):o0&&(r+=(i=this.__charBounds[t][e-1]).left+i.width),r},getDownCursorOffset:function(t,e){var i=this._getSelectionForOffset(t,e),r=this.get2DCursorLocation(i),n=r.lineIndex;if(n===this._textLines.length-1||t.metaKey||34===t.keyCode)return this._text.length-i;var s=r.charIndex,o=this._getWidthBeforeCursor(n,s),a=this._getIndexOnLine(n+1,o);return this._textLines[n].slice(s).length+a+2},_getSelectionForOffset:function(t,e){return t.shiftKey&&this.selectionStart!==this.selectionEnd&&e?this.selectionEnd:this.selectionStart},getUpCursorOffset:function(t,e){var i=this._getSelectionForOffset(t,e),r=this.get2DCursorLocation(i),n=r.lineIndex;if(0===n||t.metaKey||33===t.keyCode)return-i;var s=r.charIndex,o=this._getWidthBeforeCursor(n,s),a=this._getIndexOnLine(n-1,o),h=this._textLines[n].slice(0,s);return-this._textLines[n-1].length+a-h.length},_getIndexOnLine:function(t,e){for(var i,r,n=this._textLines[t],s=this._getLineLeftOffset(t),o=0,a=0,h=n.length;ae){r=!0;var c=s-i,l=s,u=Math.abs(c-e);o=Math.abs(l-e)=this._text.length&&this.selectionEnd>=this._text.length||this._moveCursorUpOrDown("Down",t)},moveCursorUp:function(t){0===this.selectionStart&&0===this.selectionEnd||this._moveCursorUpOrDown("Up",t)},_moveCursorUpOrDown:function(t,e){var i=this["get"+t+"CursorOffset"](e,"right"===this._selectionDirection);e.shiftKey?this.moveCursorWithShift(i):this.moveCursorWithoutShift(i),0!==i&&(this.setSelectionInBoundaries(),this.abortCursorAnimation(),this._currentCursorOpacity=1,this.initDelayedCursor(),this._fireSelectionChanged(),this._updateTextarea())},moveCursorWithShift:function(t){var e="left"===this._selectionDirection?this.selectionStart+t:this.selectionEnd+t;return this.setSelectionStartEndWithShift(this.selectionStart,this.selectionEnd,e),0!==t},moveCursorWithoutShift:function(t){return t<0?(this.selectionStart+=t,this.selectionEnd=this.selectionStart):(this.selectionEnd+=t,this.selectionStart=this.selectionEnd),0!==t},moveCursorLeft:function(t){0===this.selectionStart&&0===this.selectionEnd||this._moveCursorLeftOrRight("Left",t)},_move:function(t,e,i){var r;if(t.altKey)r=this["findWordBoundary"+i](this[e]);else{if(!t.metaKey&&35!==t.keyCode&&36!==t.keyCode)return this[e]+="Left"===i?-1:1,!0;r=this["findLineBoundary"+i](this[e])}if(void 0!==typeof r&&this[e]!==r)return this[e]=r,!0},_moveLeft:function(t,e){return this._move(t,e,"Left")},_moveRight:function(t,e){return this._move(t,e,"Right")},moveCursorLeftWithoutShift:function(t){var e=!0;return this._selectionDirection="left",this.selectionEnd===this.selectionStart&&0!==this.selectionStart&&(e=this._moveLeft(t,"selectionStart")),this.selectionEnd=this.selectionStart,e},moveCursorLeftWithShift:function(t){return"right"===this._selectionDirection&&this.selectionStart!==this.selectionEnd?this._moveLeft(t,"selectionEnd"):0!==this.selectionStart?(this._selectionDirection="left",this._moveLeft(t,"selectionStart")):void 0},moveCursorRight:function(t){this.selectionStart>=this._text.length&&this.selectionEnd>=this._text.length||this._moveCursorLeftOrRight("Right",t)},_moveCursorLeftOrRight:function(t,e){var i="moveCursor"+t+"With";this._currentCursorOpacity=1,e.shiftKey?i+="Shift":i+="outShift",this[i](e)&&(this.abortCursorAnimation(),this.initDelayedCursor(),this._fireSelectionChanged(),this._updateTextarea())},moveCursorRightWithShift:function(t){return"left"===this._selectionDirection&&this.selectionStart!==this.selectionEnd?this._moveRight(t,"selectionStart"):this.selectionEnd!==this._text.length?(this._selectionDirection="right",this._moveRight(t,"selectionEnd")):void 0},moveCursorRightWithoutShift:function(t){var e=!0;return this._selectionDirection="right",this.selectionStart===this.selectionEnd?(e=this._moveRight(t,"selectionStart"),this.selectionEnd=this.selectionStart):this.selectionStart=this.selectionEnd,e},removeChars:function(t,e){void 0===e&&(e=t+1),this.removeStyleFromTo(t,e),this._text.splice(t,e-t),this.text=this._text.join(""),this.set("dirty",!0),this._shouldClearDimensionCache()&&(this.initDimensions(),this.setCoords()),this._removeExtraneousStyles()},insertChars:function(t,e,i,r){void 0===r&&(r=i),r>i&&this.removeStyleFromTo(i,r);var n=fabric.util.string.graphemeSplit(t);this.insertNewStyleBlock(n,i,e),this._text=[].concat(this._text.slice(0,i),n,this._text.slice(r)),this.text=this._text.join(""),this.set("dirty",!0),this._shouldClearDimensionCache()&&(this.initDimensions(),this.setCoords()),this._removeExtraneousStyles()}}),function(){var t=fabric.util.toFixed;fabric.util.object.extend(fabric.Text.prototype,{toSVG:function(t){var e=this._createBaseSVGMarkup(),i=this._getSVGLeftTopOffsets(),r=this._getSVGTextAndBg(i.textTop,i.textLeft);return this._wrapSVGTextAndBg(e,r),t?t(e.join("")):e.join("")},_getSVGLeftTopOffsets:function(){return{textLeft:-this.width/2,textTop:-this.height/2,lineTop:this.getHeightOfLine(0)}},_wrapSVGTextAndBg:function(t,e){var i=this.getSvgFilter(),r=""===i?"":' style="'+i+'"',n=this.getSvgTextDecoration(this);t.push("\t\n",e.textBgRects.join(""),'\t\t",e.textSpans.join(""),"\n","\t\n")},_getSVGTextAndBg:function(t,e){var i,r=[],n=[],s=t;this._setSVGBg(n);for(var o=0,a=this._textLines.length;o",fabric.util.string.escapeXml(e),""].join("")},_setSVGTextLineText:function(t,e,i,r){var n,s,o,a,h,c=this.getHeightOfLine(e),l=-1!==this.textAlign.indexOf("justify"),u="",f=0,d=this._textLines[e];r+=c*(1-this._fontSizeFraction)/this.lineHeight;for(var g=0,p=d.length-1;g<=p;g++)h=g===p||this.charSpacing,u+=d[g],o=this.__charBounds[e][g],0===f?(i+=o.kernedWidth-o.width,f+=o.width):f+=o.kernedWidth,l&&!h&&this._reSpaceAndTab.test(d[g])&&(h=!0),h||(n=n||this.getCompleteStyleDeclaration(e,g),s=this.getCompleteStyleDeclaration(e,g+1),h=this._hasStyleChangedForSvg(n,s)),h&&(a=this._getStyleDeclaration(e,g)||{},t.push(this._createTextCharSpan(u,a,i,r)),u="",n=s,i+=f,f=0)},_pushTextBgRect:function(e,i,r,n,s,o){var a=fabric.Object.NUM_FRACTION_DIGITS;e.push("\t\t\n')},_setSVGTextLineBg:function(t,e,i,r){for(var n,s,o=this._textLines[e],a=this.getHeightOfLine(e)/this.lineHeight,h=0,c=0,l=this.getValueOfPropertyAt(e,0,"textBackgroundColor"),u=0,f=o.length;uthis.width&&this._set("width",this.dynamicMinWidth),-1!==this.textAlign.indexOf("justify")&&this.enlargeSpaces(),this.height=this.calcTextHeight(),this.saveState({propertySet:"_dimensionAffectingProps"}))},_generateStyleMap:function(t){for(var e=0,i=0,r=0,n={},s=0;s0?(i=0,r++,e++):this._reSpaceAndTab.test(t.graphemeText[r])&&s>0&&(i++,r++),n[s]={line:e,offset:i},r+=t.graphemeLines[s].length,i+=t.graphemeLines[s].length;return n},styleHas:function(t,i){if(this._styleMap&&!this.isWrapping){var r=this._styleMap[i];r&&(i=r.line)}return e.Text.prototype.styleHas.call(this,t,i)},_getStyleDeclaration:function(t,e){if(this._styleMap&&!this.isWrapping){var i=this._styleMap[t];if(!i)return null;t=i.line,e=i.offset+e}return this.callSuper("_getStyleDeclaration",t,e)},_setStyleDeclaration:function(t,e,i){var r=this._styleMap[t];t=r.line,e=r.offset+e,this.styles[t][e]=i},_deleteStyleDeclaration:function(t,e){var i=this._styleMap[t];t=i.line,e=i.offset+e,delete this.styles[t][e]},_getLineStyle:function(t){var e=this._styleMap[t];return this.styles[e.line]},_setLineStyle:function(t,e){var i=this._styleMap[t];this.styles[i.line]=e},_deleteLineStyle:function(t){var e=this._styleMap[t];delete this.styles[e.line]},_wrapText:function(t,e){var i,r=[];for(this.isWrapping=!0,i=0;i=r&&!d&&(s.push(o),o=[],n=l,d=!0),d||o.push(" "),o=o.concat(h),u=this._measureWord([" "],i,c),c++,d=!1,l>f&&(f=l);return p&&s.push(o),f>this.dynamicMinWidth&&(this.dynamicMinWidth=f-g),s},isEndOfWrapping:function(t){return!this._styleMap[t+1]||this._styleMap[t+1].line!==this._styleMap[t].line},_splitTextIntoLines:function(t){for(var i=e.Text.prototype._splitTextIntoLines.call(this,t),r=this._wrapText(i.lines,this.width),n=new Array(r.length),s=0;s=h.getMinWidth()?(h.set("width",l),!0):void 0},fabric.util.object.extend(fabric.Textbox.prototype,{_removeExtraneousStyles:function(){for(var t in this._styleMap)this._textLines[t]||delete this.styles[this._styleMap[t].line]}})}(); \ No newline at end of file +function resizeCanvasIfNeeded(t){var e=t.targetCanvas,i=e.width,r=e.height,n=t.destinationWidth,s=t.destinationHeight;i===n&&r===s||(e.width=n,e.height=s)}function copyGLTo2DDrawImage(t,e){var i=t.canvas,r=e.targetCanvas,n=r.getContext("2d");n.translate(0,r.height),n.scale(1,-1);var s=i.height-r.height;n.drawImage(i,0,s,r.width,r.height,0,0,r.width,r.height)}function copyGLTo2DPutImageData(t,e){var i=e.targetCanvas.getContext("2d"),r=e.destinationWidth,n=e.destinationHeight,s=r*n*4,o=new Uint8Array(this.imageBuffer,0,s),a=new Uint8ClampedArray(this.imageBuffer,0,s);t.readPixels(0,0,r,n,t.RGBA,t.UNSIGNED_BYTE,o);var h=new ImageData(a,r,n);i.putImageData(h,0,0)}var fabric=fabric||{version:"2.0.1"};"undefined"!=typeof exports&&(exports.fabric=fabric),"undefined"!=typeof document&&"undefined"!=typeof window?(fabric.document=document,fabric.window=window):(fabric.document=require("jsdom").jsdom(decodeURIComponent("%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E"),{features:{FetchExternalResources:["img"]}}),fabric.jsdomImplForWrapper=require("jsdom/lib/jsdom/living/generated/utils").implForWrapper,fabric.nodeCanvas=require("jsdom/lib/jsdom/utils").Canvas,fabric.window=fabric.document.defaultView,DOMParser=require("xmldom").DOMParser),fabric.isTouchSupported="ontouchstart"in fabric.window,fabric.isLikelyNode="undefined"!=typeof Buffer&&"undefined"==typeof window,fabric.SHARED_ATTRIBUTES=["display","transform","fill","fill-opacity","fill-rule","opacity","stroke","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","id","paint-order","instantiated_by_use"],fabric.DPI=96,fabric.reNum="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",fabric.fontPaths={},fabric.iMatrix=[1,0,0,1,0,0],fabric.canvasModule="canvas",fabric.perfLimitSizeTotal=2097152,fabric.maxCacheSideLimit=4096,fabric.minCacheSideLimit=256,fabric.charWidthsCache={},fabric.textureSize=2048,fabric.enableGLFiltering=!0,fabric.devicePixelRatio=fabric.window.devicePixelRatio||fabric.window.webkitDevicePixelRatio||fabric.window.mozDevicePixelRatio||1,fabric.browserShadowBlurConstant=1,fabric.initFilterBackend=function(){return fabric.enableGLFiltering&&fabric.isWebglSupported&&fabric.isWebglSupported(fabric.textureSize)?(console.log("max texture size: "+fabric.maxTextureSize),new fabric.WebglFilterBackend({tileSize:fabric.textureSize})):fabric.Canvas2dFilterBackend?new fabric.Canvas2dFilterBackend:void 0},"undefined"!=typeof document&&"undefined"!=typeof window&&(window.fabric=fabric),function(){function t(t,e){if(this.__eventListeners[t]){var i=this.__eventListeners[t];e?i[i.indexOf(e)]=!1:fabric.util.array.fill(i,!1)}}function e(t,e){if(this.__eventListeners||(this.__eventListeners={}),1===arguments.length)for(var i in t)this.on(i,t[i]);else this.__eventListeners[t]||(this.__eventListeners[t]=[]),this.__eventListeners[t].push(e);return this}function i(e,i){if(this.__eventListeners){if(0===arguments.length)for(e in this.__eventListeners)t.call(this,e);else if(1===arguments.length&&"object"==typeof arguments[0])for(var r in e)t.call(this,r,e[r]);else t.call(this,e,i);return this}}function r(t,e){if(this.__eventListeners){var i=this.__eventListeners[t];if(i){for(var r=0,n=i.length;r-1},complexity:function(){return this.getObjects().reduce(function(t,e){return t+=e.complexity?e.complexity():0},0)}},fabric.CommonMethods={_setOptions:function(t){for(var e in t)this.set(e,t[e])},_initGradient:function(t,e){!t||!t.colorStops||t instanceof fabric.Gradient||this.set(e,new fabric.Gradient(t))},_initPattern:function(t,e,i){!t||!t.source||t instanceof fabric.Pattern?i&&i():this.set(e,new fabric.Pattern(t,i))},_initClipping:function(t){if(t.clipTo&&"string"==typeof t.clipTo){var e=fabric.util.getFunctionBody(t.clipTo);void 0!==e&&(this.clipTo=new Function("ctx",e))}},_setObject:function(t){for(var e in t)this._set(e,t[e])},set:function(t,e){return"object"==typeof t?this._setObject(t):"function"==typeof e&&"clipTo"!==t?this._set(t,e(this.get(t))):this._set(t,e),this},_set:function(t,e){this[t]=e},toggle:function(t){var e=this.get(t);return"boolean"==typeof e&&this.set(t,!e),this},get:function(t){return this[t]}},function(t){var e=Math.sqrt,i=Math.atan2,r=Math.pow,n=Math.abs,s=Math.PI/180;fabric.util={removeFromArray:function(t,e){var i=t.indexOf(e);return-1!==i&&t.splice(i,1),t},getRandomInt:function(t,e){return Math.floor(Math.random()*(e-t+1))+t},degreesToRadians:function(t){return t*s},radiansToDegrees:function(t){return t/s},rotatePoint:function(t,e,i){t.subtractEquals(e);var r=fabric.util.rotateVector(t,i);return new fabric.Point(r.x,r.y).addEquals(e)},rotateVector:function(t,e){var i=Math.sin(e),r=Math.cos(e);return{x:t.x*r-t.y*i,y:t.x*i+t.y*r}},transformPoint:function(t,e,i){return i?new fabric.Point(e[0]*t.x+e[2]*t.y,e[1]*t.x+e[3]*t.y):new fabric.Point(e[0]*t.x+e[2]*t.y+e[4],e[1]*t.x+e[3]*t.y+e[5])},makeBoundingBoxFromPoints:function(t){var e=[t[0].x,t[1].x,t[2].x,t[3].x],i=fabric.util.array.min(e),r=fabric.util.array.max(e)-i,n=[t[0].y,t[1].y,t[2].y,t[3].y],s=fabric.util.array.min(n);return{left:i,top:s,width:r,height:fabric.util.array.max(n)-s}},invertTransform:function(t){var e=1/(t[0]*t[3]-t[1]*t[2]),i=[e*t[3],-e*t[1],-e*t[2],e*t[0]],r=fabric.util.transformPoint({x:t[4],y:t[5]},i,!0);return i[4]=-r.x,i[5]=-r.y,i},toFixed:function(t,e){return parseFloat(Number(t).toFixed(e))},parseUnit:function(t,e){var i=/\D{0,2}$/.exec(t),r=parseFloat(t);switch(e||(e=fabric.Text.DEFAULT_SVG_FONT_SIZE),i[0]){case"mm":return r*fabric.DPI/25.4;case"cm":return r*fabric.DPI/2.54;case"in":return r*fabric.DPI;case"pt":return r*fabric.DPI/72;case"pc":return r*fabric.DPI/72*12;case"em":return r*e;default:return r}},falseFunction:function(){return!1},getKlass:function(t,e){return t=fabric.util.string.camelize(t.charAt(0).toUpperCase()+t.slice(1)),fabric.util.resolveNamespace(e)[t]},getSvgAttributes:function(t){var e=["instantiated_by_use","style","id","class"];switch(t){case"linearGradient":e=e.concat(["x1","y1","x2","y2","gradientUnits","gradientTransform"]);break;case"radialGradient":e=e.concat(["gradientUnits","gradientTransform","cx","cy","r","fx","fy","fr"]);break;case"stop":e=e.concat(["offset","stop-color","stop-opacity"])}return e},resolveNamespace:function(e){if(!e)return fabric;var i,r=e.split("."),n=r.length,s=t||fabric.window;for(i=0;ir;)(r+=a[d++%f])>l&&(r=l),t[g?"lineTo":"moveTo"](r,0),g=!g;t.restore()},createCanvasElement:function(){return fabric.document.createElement("canvas")},createImage:function(){return fabric.document.createElement("img")},clipContext:function(t,e){e.save(),e.beginPath(),t.clipTo(e),e.clip()},multiplyTransformMatrices:function(t,e,i){return[t[0]*e[0]+t[2]*e[1],t[1]*e[0]+t[3]*e[1],t[0]*e[2]+t[2]*e[3],t[1]*e[2]+t[3]*e[3],i?0:t[0]*e[4]+t[2]*e[5]+t[4],i?0:t[1]*e[4]+t[3]*e[5]+t[5]]},qrDecompose:function(t){var n=i(t[1],t[0]),o=r(t[0],2)+r(t[1],2),a=e(o),h=(t[0]*t[3]-t[2]*t[1])/a,c=i(t[0]*t[2]+t[1]*t[3],o);return{angle:n/s,scaleX:a,scaleY:h,skewX:c/s,skewY:0,translateX:t[4],translateY:t[5]}},customTransformMatrix:function(t,e,i){var r=[1,0,n(Math.tan(i*s)),1],o=[n(t),0,0,n(e)];return fabric.util.multiplyTransformMatrices(o,r,!0)},resetObjectTransform:function(t){t.scaleX=1,t.scaleY=1,t.skewX=0,t.skewY=0,t.flipX=!1,t.flipY=!1,t.rotate(0)},getFunctionBody:function(t){return(String(t).match(/function[^{]*\{([\s\S]*)\}/)||{})[1]},isTransparent:function(t,e,i,r){r>0&&(e>r?e-=r:e=0,i>r?i-=r:i=0);var n,s,o=!0,a=t.getImageData(e,i,2*r||1,2*r||1),h=a.data.length;for(n=3;n0?P-=2*f:1===c&&P<0&&(P+=2*f);for(var M=Math.ceil(Math.abs(P/f*2)),F=[],I=P/M,L=8/3*Math.sin(I/4)*Math.sin(I/4)/Math.sin(I/2),R=A+I,B=0;B=n?s-n:2*Math.PI-(n-s)}function i(t,e,i,r,n,a,h,c){var l=o.call(arguments);if(s[l])return s[l];var u,f,d,g,p,v,m,b,_=Math.sqrt,y=Math.min,x=Math.max,C=Math.abs,S=[],w=[[],[]];f=6*t-12*i+6*n,u=-3*t+9*i-9*n+3*h,d=3*i-3*t;for(var T=0;T<2;++T)if(T>0&&(f=6*e-12*r+6*a,u=-3*e+9*r-9*a+3*c,d=3*r-3*e),C(u)<1e-12){if(C(f)<1e-12)continue;0<(g=-d/f)&&g<1&&S.push(g)}else(m=f*f-4*d*u)<0||(0<(p=(-f+(b=_(m)))/(2*u))&&p<1&&S.push(p),0<(v=(-f-b)/(2*u))&&v<1&&S.push(v));for(var O,k,D,j=S.length,E=j;j--;)O=(D=1-(g=S[j]))*D*D*t+3*D*D*g*i+3*D*g*g*n+g*g*g*h,w[0][j]=O,k=D*D*D*e+3*D*D*g*r+3*D*g*g*a+g*g*g*c,w[1][j]=k;w[0][E]=t,w[1][E]=e,w[0][E+1]=h,w[1][E+1]=c;var A=[{x:y.apply(null,w[0]),y:y.apply(null,w[1])},{x:x.apply(null,w[0]),y:x.apply(null,w[1])}];return s[l]=A,A}var r={},n={},s={},o=Array.prototype.join;fabric.util.drawArc=function(e,i,r,n){for(var s=n[0],o=n[1],a=n[2],h=n[3],c=n[4],l=[[],[],[],[]],u=t(n[5]-i,n[6]-r,s,o,h,c,a),f=0,d=u.length;f=e})}}}(),function(){function t(e,i,r){if(r)if(!fabric.isLikelyNode&&i instanceof Element)e=i;else if(i instanceof Array){e=[];for(var n=0,s=i.length;n/g,">")},graphemeSplit:function(t){var e,i=0,r=[];for(i=0,e;i57343)return t.charAt(e);if(55296<=i&&i<=56319){if(t.length<=e+1)throw"High surrogate without following low surrogate";var r=t.charCodeAt(e+1);if(56320>r||r>57343)throw"High surrogate without following low surrogate";return t.charAt(e)+t.charAt(e+1)}if(0===e)throw"Low surrogate without preceding high surrogate";var n=t.charCodeAt(e-1);if(55296>n||n>56319)throw"Low surrogate without preceding high surrogate";return!1}(t,i))&&r.push(e);return r}}}(),function(){function t(){}function e(t){for(var e=null,r=this;r.constructor.superclass;){var n=r.constructor.superclass.prototype[t];if(r[t]!==n){e=n;break}r=r.constructor.superclass.prototype}return e?arguments.length>1?e.apply(this,i.call(arguments,1)):e.call(this):console.log("tried to callSuper "+t+", method not found in prototype chain",this)}var i=Array.prototype.slice,r=function(){},n=function(){for(var t in{toString:1})if("toString"===t)return!1;return!0}(),s=function(t,e,i){for(var r in e)r in t.prototype&&"function"==typeof t.prototype[r]&&(e[r]+"").indexOf("callSuper")>-1?t.prototype[r]=function(t){return function(){var r=this.constructor.superclass;this.constructor.superclass=i;var n=e[t].apply(this,arguments);if(this.constructor.superclass=r,"initialize"!==t)return n}}(r):t.prototype[r]=e[r],n&&(e.toString!==Object.prototype.toString&&(t.prototype.toString=e.toString),e.valueOf!==Object.prototype.valueOf&&(t.prototype.valueOf=e.valueOf))};fabric.util.createClass=function(){function n(){this.initialize.apply(this,arguments)}var o=null,a=i.call(arguments,0);"function"==typeof a[0]&&(o=a.shift()),n.superclass=o,n.subclasses=[],o&&(t.prototype=o.prototype,n.prototype=new t,o.subclasses.push(n));for(var h=0,c=a.length;h=.9999?"":"alpha(opacity="+100*e+")",i.filter=i.filter.replace(r,e)):i.filter+=" alpha(opacity="+100*e+")",t}),fabric.util.setStyle=function(t,e){var i=t.style;if(!i)return t;if("string"==typeof e)return t.style.cssText+=";"+e,e.indexOf("opacity")>-1?n(t,e.match(/opacity:\s*(\d?\.?\d*)/)[1]):t;for(var r in e)"opacity"===r?n(t,e[r]):i["float"===r||"cssFloat"===r?void 0===i.styleFloat?"cssFloat":"styleFloat":r]=e[r];return t}}(),function(){function t(t,e){var i=fabric.document.createElement(t);for(var r in e)"class"===r?i.className=e[r]:"for"===r?i.htmlFor=e[r]:i.setAttribute(r,e[r]);return i}function e(t){for(var e=0,i=0,r=fabric.document.documentElement,n=fabric.document.body||{scrollLeft:0,scrollTop:0};t&&(t.parentNode||t.host)&&((t=t.parentNode||t.host)===fabric.document?(e=n.scrollLeft||r.scrollLeft||0,i=n.scrollTop||r.scrollTop||0):(e+=t.scrollLeft||0,i+=t.scrollTop||0),1!==t.nodeType||"fixed"!==t.style.position););return{left:e,top:i}}var i,r=Array.prototype.slice,n=function(t){return r.call(t,0)};try{i=n(fabric.document.childNodes)instanceof Array}catch(t){}i||(n=function(t){for(var e=new Array(t.length),i=t.length;i--;)e[i]=t[i];return e});var s;s=fabric.document.defaultView&&fabric.document.defaultView.getComputedStyle?function(t,e){var i=fabric.document.defaultView.getComputedStyle(t,null);return i?i[e]:void 0}:function(t,e){var i=t.style[e];return!i&&t.currentStyle&&(i=t.currentStyle[e]),i},function(){var t=fabric.document.documentElement.style,e="userSelect"in t?"userSelect":"MozUserSelect"in t?"MozUserSelect":"WebkitUserSelect"in t?"WebkitUserSelect":"KhtmlUserSelect"in t?"KhtmlUserSelect":"";fabric.util.makeElementUnselectable=function(t){return void 0!==t.onselectstart&&(t.onselectstart=fabric.util.falseFunction),e?t.style[e]="none":"string"==typeof t.unselectable&&(t.unselectable="on"),t},fabric.util.makeElementSelectable=function(t){return void 0!==t.onselectstart&&(t.onselectstart=null),e?t.style[e]="":"string"==typeof t.unselectable&&(t.unselectable=""),t}}(),function(){fabric.util.getScript=function(t,e){var i=fabric.document.getElementsByTagName("head")[0],r=fabric.document.createElement("script"),n=!0;r.onload=r.onreadystatechange=function(t){if(n){if("string"==typeof this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)return;n=!1,e(t||fabric.window.event),r=r.onload=r.onreadystatechange=null}},r.src=t,i.appendChild(r)}}(),fabric.util.getById=function(t){return"string"==typeof t?fabric.document.getElementById(t):t},fabric.util.toArray=n,fabric.util.makeElement=t,fabric.util.addClass=function(t,e){t&&-1===(" "+t.className+" ").indexOf(" "+e+" ")&&(t.className+=(t.className?" ":"")+e)},fabric.util.wrapElement=function(e,i,r){return"string"==typeof i&&(i=t(i,r)),e.parentNode&&e.parentNode.replaceChild(i,e),i.appendChild(e),i},fabric.util.getScrollLeftTop=e,fabric.util.getElementOffset=function(t){var i,r,n=t&&t.ownerDocument,o={left:0,top:0},a={left:0,top:0},h={borderLeftWidth:"left",borderTopWidth:"top",paddingLeft:"left",paddingTop:"top"};if(!n)return a;for(var c in h)a[h[c]]+=parseInt(s(t,c),10)||0;return i=n.documentElement,void 0!==t.getBoundingClientRect&&(o=t.getBoundingClientRect()),r=e(t),{left:o.left+r.left-(i.clientLeft||0)+a.left,top:o.top+r.top-(i.clientTop||0)+a.top}},fabric.util.getElementStyle=s,fabric.util.getNodeCanvas=function(t){var e=fabric.jsdomImplForWrapper(t);return e._canvas||e._image}}(),function(){function t(){}var e=function(){for(var t=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP.3.0")},function(){return new XMLHttpRequest}],e=t.length;e--;)try{if(t[e]())return t[e]}catch(t){}}();fabric.util.request=function(i,r){r||(r={});var n=r.method?r.method.toUpperCase():"GET",s=r.onComplete||function(){},o=e(),a=r.body||r.parameters;return o.onreadystatechange=function(){4===o.readyState&&(s(o),o.onreadystatechange=t)},"GET"===n&&(a=null,"string"==typeof r.parameters&&(i=function(t,e){return t+(/\?/.test(t)?"&":"?")+e}(i,r.parameters))),o.open(n,i,!0),"POST"!==n&&"PUT"!==n||o.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),o.send(a),o}}(),fabric.log=function(){},fabric.warn=function(){},"undefined"!=typeof console&&["log","warn"].forEach(function(t){void 0!==console[t]&&"function"==typeof console[t].apply&&(fabric[t]=function(){return console[t].apply(console,arguments)})}),function(){function t(){return!1}function e(){return i.apply(fabric.window,arguments)}var i=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(t){return fabric.window.setTimeout(t,1e3/60)},r=fabric.window.cancelAnimationFrame||fabric.window.clearTimeout;fabric.util.animate=function(i){e(function(r){i||(i={});var n,s=r||+new Date,o=i.duration||500,a=s+o,h=i.onChange||t,c=i.abort||t,l=i.onComplete||t,u=i.easing||function(t,e,i,r){return-i*Math.cos(t/r*(Math.PI/2))+i+e},f="startValue"in i?i.startValue:0,d="endValue"in i?i.endValue:100,g=i.byValue||d-f;i.onStart&&i.onStart(),function t(r){if(c())l(d,1,1);else{var p=(n=r||+new Date)>a?o:n-s,v=p/o,m=u(p,f,g,o),b=Math.abs((m-f)/g);h(m,b,v),n>a?i.onComplete&&i.onComplete():e(t)}}(s)})},fabric.util.requestAnimFrame=e,fabric.util.cancelAnimFrame=function(){return r.apply(fabric.window,arguments)}}(),function(){fabric.util.animateColor=function(t,e,i,r){var n=new fabric.Color(t).getSource(),s=new fabric.Color(e).getSource();r=r||{},fabric.util.animate(fabric.util.object.extend(r,{duration:i||500,startValue:n,endValue:s,byValue:s,easing:function(t,e,i,n){return function(t,e,i){var r="rgba("+parseInt(t[0]+i*(e[0]-t[0]),10)+","+parseInt(t[1]+i*(e[1]-t[1]),10)+","+parseInt(t[2]+i*(e[2]-t[2]),10);return r+=","+(t&&e?parseFloat(t[3]+i*(e[3]-t[3])):1),r+=")"}(e,i,r.colorEasing?r.colorEasing(t,n):1-Math.cos(t/n*(Math.PI/2)))}}))}}(),function(){function t(t,e,i,r){return t-1&&a>-1&&a-1&&(e="stroke")}else n=s?e.map(d):d(e,r);else e="";return!s&&isNaN(n)?e:n}function r(t){return new RegExp("^("+t.join("|")+")\\b","i")}function n(t,e){var i,r,n,s,o=[];for(n=0,s=e.length;na?a:o),1===o&&1===a&&0===h&&0===l&&0===g&&0===p)return x;if((g||p)&&(C=" translate("+d(g)+" "+d(p)+") "),r=C+" matrix("+o+" 0 0 "+a+" "+h*o+" "+l*a+") ","svg"===t.nodeName){for(n=t.ownerDocument.createElement("g");t.firstChild;)n.appendChild(t.firstChild);t.appendChild(n)}else r=(n=t).getAttribute("transform")+r;return n.setAttribute("transform",r),x}var c=t.fabric||(t.fabric={}),l=c.util.object.extend,u=c.util.object.clone,f=c.util.toFixed,d=c.util.parseUnit,g=c.util.multiplyTransformMatrices,p={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","paint-order":"paintFirst","stroke-dasharray":"strokeDashArray","stroke-linecap":"strokeLineCap","stroke-linejoin":"strokeLineJoin","stroke-miterlimit":"strokeMiterLimit","stroke-opacity":"strokeOpacity","stroke-width":"strokeWidth","text-decoration":"textDecoration","text-anchor":"textAnchor",opacity:"opacity"},v={stroke:"strokeOpacity",fill:"fillOpacity"};c.svgValidTagNamesRegEx=r(["path","circle","polygon","polyline","ellipse","rect","line","image","text","linearGradient","radialGradient","stop"]),c.svgViewBoxElementsRegEx=r(["symbol","image","marker","pattern","view","svg"]),c.svgInvalidAncestorsRegEx=r(["pattern","defs","symbol","metadata","clipPath","mask","desc"]),c.svgValidParentsRegEx=r(["symbol","g","a","svg"]),c.cssRules={},c.gradientDefs={},c.parseTransformAttribute=function(){function t(t,e,i){t[i]=Math.tan(c.util.degreesToRadians(e[0]))}var e=[1,0,0,1,0,0],i=c.reNum,r="(?:\\s+,?\\s*|,\\s*)",n="(?:"+("(?:(matrix)\\s*\\(\\s*("+i+")"+r+"("+i+")"+r+"("+i+")"+r+"("+i+")"+r+"("+i+")"+r+"("+i+")\\s*\\))")+"|"+("(?:(translate)\\s*\\(\\s*("+i+")(?:"+r+"("+i+"))?\\s*\\))")+"|"+("(?:(scale)\\s*\\(\\s*("+i+")(?:"+r+"("+i+"))?\\s*\\))")+"|"+("(?:(rotate)\\s*\\(\\s*("+i+")(?:"+r+"("+i+")"+r+"("+i+"))?\\s*\\))")+"|"+("(?:(skewX)\\s*\\(\\s*("+i+")\\s*\\))")+"|"+("(?:(skewY)\\s*\\(\\s*("+i+")\\s*\\))")+")",s="^\\s*(?:"+("(?:"+n+"(?:"+r+"*"+n+")*)")+"?)\\s*$",o=new RegExp(s),a=new RegExp(n,"g");return function(i){var r=e.concat(),s=[];if(!i||i&&!o.test(i))return r;i.replace(a,function(i){var o=new RegExp(n).exec(i).filter(function(t){return!!t}),a=o[1],h=o.slice(2).map(parseFloat);switch(a){case"translate":!function(t,e){t[4]=e[0],2===e.length&&(t[5]=e[1])}(r,h);break;case"rotate":h[0]=c.util.degreesToRadians(h[0]),function(t,e){var i=Math.cos(e[0]),r=Math.sin(e[0]),n=0,s=0;3===e.length&&(n=e[1],s=e[2]),t[0]=i,t[1]=r,t[2]=-r,t[3]=i,t[4]=n-(i*n-r*s),t[5]=s-(r*n+i*s)}(r,h);break;case"scale":!function(t,e){var i=e[0],r=2===e.length?e[1]:e[0];t[0]=i,t[3]=r}(r,h);break;case"skewX":t(r,h,2);break;case"skewY":t(r,h,1);break;case"matrix":r=h}s.push(r.concat()),r=e.concat()});for(var h=s[0];s.length>1;)s.shift(),h=c.util.multiplyTransformMatrices(h,s[0]);return h}}();var m=new RegExp("^\\s*("+c.reNum+"+)\\s*,?\\s*("+c.reNum+"+)\\s*,?\\s*("+c.reNum+"+)\\s*,?\\s*("+c.reNum+"+)\\s*$");c.parseSVGDocument=function(t,e,i,r){if(t){!function(t){for(var e=n(t,["use","svg:use"]),i=0;e.length&&i/i,""))),n&&n.documentElement||e&&e(null),c.parseSVGDocument(n.documentElement,function(t,i,r,n){e&&e(t,i,r,n)},i,r)}})},loadSVGFromString:function(t,e,i,r){t=t.trim();var n;if("undefined"!=typeof DOMParser){var s=new DOMParser;s&&s.parseFromString&&(n=s.parseFromString(t,"text/xml"))}else c.window.ActiveXObject&&((n=new ActiveXObject("Microsoft.XMLDOM")).async="false",n.loadXML(t.replace(//i,"")));c.parseSVGDocument(n.documentElement,function(t,i,r,n){e(t,i,r,n)},i,r)}})}("undefined"!=typeof exports?exports:this),fabric.ElementsParser=function(t,e,i,r,n){this.elements=t,this.callback=e,this.options=i,this.reviver=r,this.svgUid=i&&i.svgUid||0,this.parsingOptions=n},fabric.ElementsParser.prototype.parse=function(){this.instances=new Array(this.elements.length),this.numElements=this.elements.length,this.createObjects()},fabric.ElementsParser.prototype.createObjects=function(){for(var t=0,e=this.elements.length;tt.x&&this.y>t.y},gte:function(t){return this.x>=t.x&&this.y>=t.y},lerp:function(t,i){return void 0===i&&(i=.5),i=Math.max(Math.min(1,i),0),new e(this.x+(t.x-this.x)*i,this.y+(t.y-this.y)*i)},distanceFrom:function(t){var e=this.x-t.x,i=this.y-t.y;return Math.sqrt(e*e+i*i)},midPointFrom:function(t){return this.lerp(t)},min:function(t){return new e(Math.min(this.x,t.x),Math.min(this.y,t.y))},max:function(t){return new e(Math.max(this.x,t.x),Math.max(this.y,t.y))},toString:function(){return this.x+","+this.y},setXY:function(t,e){return this.x=t,this.y=e,this},setX:function(t){return this.x=t,this},setY:function(t){return this.y=t,this},setFromPoint:function(t){return this.x=t.x,this.y=t.y,this},swap:function(t){var e=this.x,i=this.y;this.x=t.x,this.y=t.y,t.x=e,t.y=i},clone:function(){return new e(this.x,this.y)}})}("undefined"!=typeof exports?exports:this),function(t){"use strict";function e(t){this.status=t,this.points=[]}var i=t.fabric||(t.fabric={});i.Intersection?i.warn("fabric.Intersection is already defined"):(i.Intersection=e,i.Intersection.prototype={constructor:e,appendPoint:function(t){return this.points.push(t),this},appendPoints:function(t){return this.points=this.points.concat(t),this}},i.Intersection.intersectLineLine=function(t,r,n,s){var o,a=(s.x-n.x)*(t.y-n.y)-(s.y-n.y)*(t.x-n.x),h=(r.x-t.x)*(t.y-n.y)-(r.y-t.y)*(t.x-n.x),c=(s.y-n.y)*(r.x-t.x)-(s.x-n.x)*(r.y-t.y);if(0!==c){var l=a/c,u=h/c;0<=l&&l<=1&&0<=u&&u<=1?(o=new e("Intersection")).appendPoint(new i.Point(t.x+l*(r.x-t.x),t.y+l*(r.y-t.y))):o=new e}else o=new e(0===a||0===h?"Coincident":"Parallel");return o},i.Intersection.intersectLinePolygon=function(t,i,r){var n,s,o,a,h=new e,c=r.length;for(a=0;a0&&(h.status="Intersection"),h},i.Intersection.intersectPolygonPolygon=function(t,i){var r,n=new e,s=t.length;for(r=0;r0&&(n.status="Intersection"),n},i.Intersection.intersectPolygonRectangle=function(t,r,n){var s=r.min(n),o=r.max(n),a=new i.Point(o.x,s.y),h=new i.Point(s.x,o.y),c=e.intersectLinePolygon(s,a,t),l=e.intersectLinePolygon(a,o,t),u=e.intersectLinePolygon(o,h,t),f=e.intersectLinePolygon(h,s,t),d=new e;return d.appendPoints(c.points),d.appendPoints(l.points),d.appendPoints(u.points),d.appendPoints(f.points),d.points.length>0&&(d.status="Intersection"),d})}("undefined"!=typeof exports?exports:this),function(t){"use strict";function e(t){t?this._tryParsingColor(t):this.setSource([0,0,0,1])}function i(t,e,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?t+6*(e-t)*i:i<.5?e:i<2/3?t+(e-t)*(2/3-i)*6:t}var r=t.fabric||(t.fabric={});r.Color?r.warn("fabric.Color is already defined."):(r.Color=e,r.Color.prototype={_tryParsingColor:function(t){var i;t in e.colorNameMap&&(t=e.colorNameMap[t]),"transparent"===t&&(i=[255,255,255,0]),i||(i=e.sourceFromHex(t)),i||(i=e.sourceFromRgb(t)),i||(i=e.sourceFromHsl(t)),i||(i=[0,0,0,1]),i&&this.setSource(i)},_rgbToHsl:function(t,e,i){t/=255,e/=255,i/=255;var n,s,o,a=r.util.array.max([t,e,i]),h=r.util.array.min([t,e,i]);if(o=(a+h)/2,a===h)n=s=0;else{var c=a-h;switch(s=o>.5?c/(2-a-h):c/(a+h),a){case t:n=(e-i)/c+(e1?1:o,s){var a=s.split(/\s*;\s*/);for(""===a[a.length-1]&&a.pop(),n=a.length;n--;){var h=a[n].split(/\s*:\s*/),c=h[0].trim(),l=h[1].trim();"stop-color"===c?e=l:"stop-opacity"===c&&(r=l)}}return e||(e=t.getAttribute("stop-color")||"rgb(0,0,0)"),r||(r=t.getAttribute("stop-opacity")),e=new fabric.Color(e),i=e.getAlpha(),r=isNaN(parseFloat(r))?1:parseFloat(r),r*=i,{offset:o,color:e.toRgb(),opacity:r}}function e(t,e,i){var r,n=0,s=1,o="";for(var a in e)"Infinity"===e[a]?e[a]=1:"-Infinity"===e[a]&&(e[a]=0),r=parseFloat(e[a],10),s="string"==typeof e[a]&&/^(\d+\.\d+)%|(\d+)%$/.test(e[a])?.01:1,"x1"===a||"x2"===a||"r2"===a?(s*="objectBoundingBox"===i?t.width:1,n="objectBoundingBox"===i?t.left||0:0):"y1"!==a&&"y2"!==a||(s*="objectBoundingBox"===i?t.height:1,n="objectBoundingBox"===i?t.top||0:0),e[a]=r*s+n;if("ellipse"===t.type&&null!==e.r2&&"objectBoundingBox"===i&&t.rx!==t.ry){var h=t.ry/t.rx;o=" scale(1, "+h+")",e.y1&&(e.y1/=h),e.y2&&(e.y2/=h)}return o}var i=fabric.util.object.clone;fabric.Gradient=fabric.util.createClass({offsetX:0,offsetY:0,initialize:function(t){t||(t={});var e={};this.id=fabric.Object.__uid++,this.type=t.type||"linear",e={x1:t.coords.x1||0,y1:t.coords.y1||0,x2:t.coords.x2||0,y2:t.coords.y2||0},"radial"===this.type&&(e.r1=t.coords.r1||0,e.r2=t.coords.r2||0),this.coords=e,this.colorStops=t.colorStops.slice(),t.gradientTransform&&(this.gradientTransform=t.gradientTransform),this.offsetX=t.offsetX||this.offsetX,this.offsetY=t.offsetY||this.offsetY},addColorStop:function(t){for(var e in t){var i=new fabric.Color(t[e]);this.colorStops.push({offset:parseFloat(e),color:i.toRgb(),opacity:i.getAlpha()})}return this},toObject:function(t){var e={type:this.type,coords:this.coords,colorStops:this.colorStops,offsetX:this.offsetX,offsetY:this.offsetY,gradientTransform:this.gradientTransform?this.gradientTransform.concat():this.gradientTransform};return fabric.util.populateWithProperties(this,e,t),e},toSVG:function(t){var e,r,n,s,o=i(this.coords,!0),a=i(this.colorStops,!0),h=o.r1>o.r2,c=t.width/2,l=t.height/2;a.sort(function(t,e){return t.offset-e.offset}),"path"===t.type&&(c-=t.pathOffset.x,l-=t.pathOffset.y);for(var u in o)"x1"===u||"x2"===u?o[u]+=this.offsetX-c:"y1"!==u&&"y2"!==u||(o[u]+=this.offsetY-l);if(s='id="SVGID_'+this.id+'" gradientUnits="userSpaceOnUse"',this.gradientTransform&&(s+=' gradientTransform="matrix('+this.gradientTransform.join(" ")+')" '),"linear"===this.type?n=["\n']:"radial"===this.type&&(n=["\n']),"radial"===this.type){if(h)for((a=a.concat()).reverse(),e=0,r=a.length;e0){var d=f/Math.max(o.r1,o.r2);for(e=0,r=a.length;e\n')}return n.push("linear"===this.type?"\n":"\n"),n.join("")},toLive:function(t){var e,i,r,n=fabric.util.object.clone(this.coords);if(this.type){for("linear"===this.type?e=t.createLinearGradient(n.x1,n.y1,n.x2,n.y2):"radial"===this.type&&(e=t.createRadialGradient(n.x1,n.y1,n.r1,n.x2,n.y2,n.r2)),i=0,r=this.colorStops.length;i\n\n\n'},setOptions:function(t){for(var e in t)this[e]=t[e]},toLive:function(t){var e="function"==typeof this.source?this.source():this.source;if(!e)return"";if(void 0!==e.src){if(!e.complete)return"";if(0===e.naturalWidth||0===e.naturalHeight)return""}return t.createPattern(e,this.repeat)}})}(),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.toFixed;e.Shadow?e.warn("fabric.Shadow is already defined."):(e.Shadow=e.util.createClass({color:"rgb(0,0,0)",blur:0,offsetX:0,offsetY:0,affectStroke:!1,includeDefaultValues:!0,initialize:function(t){"string"==typeof t&&(t=this._parseShadow(t));for(var i in t)this[i]=t[i];this.id=e.Object.__uid++},_parseShadow:function(t){var i=t.trim(),r=e.Shadow.reOffsetsAndBlur.exec(i)||[];return{color:(i.replace(e.Shadow.reOffsetsAndBlur,"")||"rgb(0,0,0)").trim(),offsetX:parseInt(r[1],10)||0,offsetY:parseInt(r[2],10)||0,blur:parseInt(r[3],10)||0}},toString:function(){return[this.offsetX,this.offsetY,this.blur,this.color].join("px ")},toSVG:function(t){var r=40,n=40,s=e.Object.NUM_FRACTION_DIGITS,o=e.util.rotateVector({x:this.offsetX,y:this.offsetY},e.util.degreesToRadians(-t.angle));return t.width&&t.height&&(r=100*i((Math.abs(o.x)+this.blur)/t.width,s)+20,n=100*i((Math.abs(o.y)+this.blur)/t.height,s)+20),t.flipX&&(o.x*=-1),t.flipY&&(o.y*=-1),'\n\t\n\t\n\t\n\t\n\t\n\t\t\n\t\t\n\t\n\n'},toObject:function(){if(this.includeDefaultValues)return{color:this.color,blur:this.blur,offsetX:this.offsetX,offsetY:this.offsetY,affectStroke:this.affectStroke};var t={},i=e.Shadow.prototype;return["color","blur","offsetX","offsetY","affectStroke"].forEach(function(e){this[e]!==i[e]&&(t[e]=this[e])},this),t}}),e.Shadow.reOffsetsAndBlur=/(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/)}("undefined"!=typeof exports?exports:this),function(){"use strict";if(fabric.StaticCanvas)fabric.warn("fabric.StaticCanvas is already defined.");else{var t=fabric.util.object.extend,e=fabric.util.getElementOffset,i=fabric.util.removeFromArray,r=fabric.util.toFixed,n=fabric.util.transformPoint,s=fabric.util.invertTransform,o=new Error("Could not initialize `canvas` element");fabric.StaticCanvas=fabric.util.createClass(fabric.CommonMethods,{initialize:function(t,e){e||(e={}),this.renderAndResetBound=this.renderAndReset.bind(this),this.requestRenderAllBound=this.requestRenderAll.bind(this),this._initStatic(t,e)},backgroundColor:"",backgroundImage:null,overlayColor:"",overlayImage:null,includeDefaultValues:!0,stateful:!1,renderOnAddRemove:!0,clipTo:null,controlsAboveOverlay:!1,allowTouchScrolling:!1,imageSmoothingEnabled:!0,viewportTransform:fabric.iMatrix.concat(),backgroundVpt:!0,overlayVpt:!0,onBeforeScaleRotate:function(){},enableRetinaScaling:!0,vptCoords:{},skipOffscreen:!0,_initStatic:function(t,e){var i=this.requestRenderAllBound;this._objects=[],this._createLowerCanvas(t),this._initOptions(e),this._setImageSmoothing(),this.interactive||this._initRetinaScaling(),e.overlayImage&&this.setOverlayImage(e.overlayImage,i),e.backgroundImage&&this.setBackgroundImage(e.backgroundImage,i),e.backgroundColor&&this.setBackgroundColor(e.backgroundColor,i),e.overlayColor&&this.setOverlayColor(e.overlayColor,i),this.calcOffset()},_isRetinaScaling:function(){return 1!==fabric.devicePixelRatio&&this.enableRetinaScaling},getRetinaScaling:function(){return this._isRetinaScaling()?fabric.devicePixelRatio:1},_initRetinaScaling:function(){this._isRetinaScaling()&&(this.lowerCanvasEl.setAttribute("width",this.width*fabric.devicePixelRatio),this.lowerCanvasEl.setAttribute("height",this.height*fabric.devicePixelRatio),this.contextContainer.scale(fabric.devicePixelRatio,fabric.devicePixelRatio))},calcOffset:function(){return this._offset=e(this.lowerCanvasEl),this},setOverlayImage:function(t,e,i){return this.__setBgOverlayImage("overlayImage",t,e,i)},setBackgroundImage:function(t,e,i){return this.__setBgOverlayImage("backgroundImage",t,e,i)},setOverlayColor:function(t,e){return this.__setBgOverlayColor("overlayColor",t,e)},setBackgroundColor:function(t,e){return this.__setBgOverlayColor("backgroundColor",t,e)},_setImageSmoothing:function(){var t=this.getContext();t.imageSmoothingEnabled=t.imageSmoothingEnabled||t.webkitImageSmoothingEnabled||t.mozImageSmoothingEnabled||t.msImageSmoothingEnabled||t.oImageSmoothingEnabled,t.imageSmoothingEnabled=this.imageSmoothingEnabled},__setBgOverlayImage:function(t,e,i,r){return"string"==typeof e?fabric.util.loadImage(e,function(e){e&&(this[t]=new fabric.Image(e,r)),i&&i(e)},this,r&&r.crossOrigin):(r&&e.setOptions(r),this[t]=e,i&&i(e)),this},__setBgOverlayColor:function(t,e,i){return this[t]=e,this._initGradient(e,t),this._initPattern(e,t,i),this},_createCanvasElement:function(){var t=fabric.util.createCanvasElement();if(!t)throw o;if(t.style||(t.style={}),void 0===t.getContext)throw o;return t},_initOptions:function(t){this._setOptions(t),this.width=this.width||parseInt(this.lowerCanvasEl.width,10)||0,this.height=this.height||parseInt(this.lowerCanvasEl.height,10)||0,this.lowerCanvasEl.style&&(this.lowerCanvasEl.width=this.width,this.lowerCanvasEl.height=this.height,this.lowerCanvasEl.style.width=this.width+"px",this.lowerCanvasEl.style.height=this.height+"px",this.viewportTransform=this.viewportTransform.slice())},_createLowerCanvas:function(t){t&&t.getContext?this.lowerCanvasEl=t:this.lowerCanvasEl=fabric.util.getById(t)||this._createCanvasElement(),fabric.util.addClass(this.lowerCanvasEl,"lower-canvas"),this.interactive&&this._applyCanvasStyle(this.lowerCanvasEl),this.contextContainer=this.lowerCanvasEl.getContext("2d")},getWidth:function(){return this.width},getHeight:function(){return this.height},setWidth:function(t,e){return this.setDimensions({width:t},e)},setHeight:function(t,e){return this.setDimensions({height:t},e)},setDimensions:function(t,e){var i;e=e||{};for(var r in t)i=t[r],e.cssOnly||(this._setBackstoreDimension(r,t[r]),i+="px"),e.backstoreOnly||this._setCssDimension(r,i);return this._isCurrentlyDrawing&&this.freeDrawingBrush&&this.freeDrawingBrush._setBrushStyles(),this._initRetinaScaling(),this._setImageSmoothing(),this.calcOffset(),e.cssOnly||this.requestRenderAll(),this},_setBackstoreDimension:function(t,e){return this.lowerCanvasEl[t]=e,this.upperCanvasEl&&(this.upperCanvasEl[t]=e),this.cacheCanvasEl&&(this.cacheCanvasEl[t]=e),this[t]=e,this},_setCssDimension:function(t,e){return this.lowerCanvasEl.style[t]=e,this.upperCanvasEl&&(this.upperCanvasEl.style[t]=e),this.wrapperEl&&(this.wrapperEl.style[t]=e),this},getZoom:function(){return this.viewportTransform[0]},setViewportTransform:function(t){var e,i,r,n=this._activeObject;for(this.viewportTransform=t,i=0,r=this._objects.length;i"),i.join("")},_setSVGPreamble:function(t,e){e.suppressPreamble||t.push('\n','\n')},_setSVGHeader:function(t,e){var i,n=e.width||this.width,s=e.height||this.height,o='viewBox="0 0 '+this.width+" "+this.height+'" ',a=fabric.Object.NUM_FRACTION_DIGITS;e.viewBox?o='viewBox="'+e.viewBox.x+" "+e.viewBox.y+" "+e.viewBox.width+" "+e.viewBox.height+'" ':this.svgViewportTransformation&&(i=this.viewportTransform,o='viewBox="'+r(-i[4]/i[0],a)+" "+r(-i[5]/i[3],a)+" "+r(this.width/i[0],a)+" "+r(this.height/i[3],a)+'" '),t.push("\n',"Created with Fabric.js ",fabric.version,"\n","\n",this.createSVGFontFacesMarkup(),this.createSVGRefElementsMarkup(),"\n")},createSVGRefElementsMarkup:function(){var t=this;return["backgroundColor","overlayColor"].map(function(e){var i=t[e];if(i&&i.toLive)return i.toSVG(t,!1)}).join("")},createSVGFontFacesMarkup:function(){var t,e,i,r,n,s,o,a,h="",c={},l=fabric.fontPaths,u=this.getObjects();for(o=0,a=u.length;o',"\n",h,"","\n"].join("")),h},_setSVGObjects:function(t,e){var i,r,n,s=this.getObjects();for(r=0,n=s.length;r\n")}else t.push('\n")},sendToBack:function(t){if(!t)return this;var e,r,n,s=this._activeObject;if(t===s&&"activeSelection"===t.type)for(e=(n=s._objects).length;e--;)r=n[e],i(this._objects,r),this._objects.unshift(r);else i(this._objects,t),this._objects.unshift(t);return this.renderOnAddRemove&&this.requestRenderAll(),this},bringToFront:function(t){if(!t)return this;var e,r,n,s=this._activeObject;if(t===s&&"activeSelection"===t.type)for(n=s._objects,e=0;e0+c&&(o=s-1,i(this._objects,n),this._objects.splice(o,0,n)),c++;else 0!==(s=this._objects.indexOf(t))&&(o=this._findNewLowerIndex(t,s,e),i(this._objects,t),this._objects.splice(o,0,t));return this.renderOnAddRemove&&this.requestRenderAll(),this},_findNewLowerIndex:function(t,e,i){var r,n;if(i)for(r=e,n=e-1;n>=0;--n){if(t.intersectsWithObject(this._objects[n])||t.isContainedWithinObject(this._objects[n])||this._objects[n].isContainedWithinObject(t)){r=n;break}}else r=e-1;return r},bringForward:function(t,e){if(!t)return this;var r,n,s,o,a,h=this._activeObject,c=0;if(t===h&&"activeSelection"===t.type)for(r=(a=h._objects).length;r--;)n=a[r],(s=this._objects.indexOf(n))"}}),t(fabric.StaticCanvas.prototype,fabric.Observable),t(fabric.StaticCanvas.prototype,fabric.Collection),t(fabric.StaticCanvas.prototype,fabric.DataURLExporter),t(fabric.StaticCanvas,{EMPTY_JSON:'{"objects": [], "background": "white"}',supports:function(t){var e=fabric.util.createCanvasElement();if(!e||!e.getContext)return null;var i=e.getContext("2d");if(!i)return null;switch(t){case"getImageData":return void 0!==i.getImageData;case"setLineDash":return void 0!==i.setLineDash;case"toDataURL":return void 0!==e.toDataURL;case"toDataURLWithQuality":try{return e.toDataURL("image/jpeg",0),!0}catch(t){}return!1;default:return null}}}),fabric.StaticCanvas.prototype.toJSON=fabric.StaticCanvas.prototype.toObject,fabric.isLikelyNode&&(fabric.StaticCanvas.prototype.createPNGStream=function(){var t=fabric.util.getNodeCanvas(this.lowerCanvasEl);return t&&t.createPNGStream()},fabric.StaticCanvas.prototype.createJPEGStream=function(t){var e=fabric.util.getNodeCanvas(this.lowerCanvasEl);return e&&e.createJPEGStream(t)})}}(),fabric.BaseBrush=fabric.util.createClass({color:"rgb(0, 0, 0)",width:1,shadow:null,strokeLineCap:"round",strokeLineJoin:"round",strokeMiterLimit:10,strokeDashArray:null,setShadow:function(t){return this.shadow=new fabric.Shadow(t),this},_setBrushStyles:function(){var t=this.canvas.contextTop;t.strokeStyle=this.color,t.lineWidth=this.width,t.lineCap=this.strokeLineCap,t.miterLimit=this.strokeMiterLimit,t.lineJoin=this.strokeLineJoin,this.strokeDashArray&&fabric.StaticCanvas.supports("setLineDash")&&t.setLineDash(this.strokeDashArray)},_saveAndTransform:function(t){var e=this.canvas.viewportTransform;t.save(),t.transform(e[0],e[1],e[2],e[3],e[4],e[5])},_setShadow:function(){if(this.shadow){var t=this.canvas.contextTop,e=this.canvas.getZoom();t.shadowColor=this.shadow.color,t.shadowBlur=this.shadow.blur*e,t.shadowOffsetX=this.shadow.offsetX*e,t.shadowOffsetY=this.shadow.offsetY*e}},_resetShadow:function(){var t=this.canvas.contextTop;t.shadowColor="",t.shadowBlur=t.shadowOffsetX=t.shadowOffsetY=0}}),fabric.PencilBrush=fabric.util.createClass(fabric.BaseBrush,{initialize:function(t){this.canvas=t,this._points=[]},onMouseDown:function(t){this._prepareForDrawing(t),this._captureDrawingPath(t),this._render()},onMouseMove:function(t){this._captureDrawingPath(t),this.canvas.clearContext(this.canvas.contextTop),this._render()},onMouseUp:function(){this._finalizeAndAddPath()},_prepareForDrawing:function(t){var e=new fabric.Point(t.x,t.y);this._reset(),this._addPoint(e),this.canvas.contextTop.moveTo(e.x,e.y)},_addPoint:function(t){this._points.length>1&&t.eq(this._points[this._points.length-1])||this._points.push(t)},_reset:function(){this._points.length=0,this._setBrushStyles(),this._setShadow()},_captureDrawingPath:function(t){var e=new fabric.Point(t.x,t.y);this._addPoint(e)},_render:function(){var t,e,i=this.canvas.contextTop,r=this._points[0],n=this._points[1];if(this._saveAndTransform(i),i.beginPath(),2===this._points.length&&r.x===n.x&&r.y===n.y){var s=this.width/1e3;r=new fabric.Point(r.x,r.y),n=new fabric.Point(n.x,n.y),r.x-=s,n.x+=s}for(i.moveTo(r.x,r.y),t=1,e=this._points.length;t2;for(c&&(a=t[2].xt[e-2].x?1:n.x===t[e-2].x?0:-1,h=n.y>t[e-2].y?1:n.y===t[e-2].y?0:-1),i.push("L ",n.x+a*r," ",n.y+h*r),i},createPath:function(t){var e=new fabric.Path(t,{fill:null,stroke:this.color,strokeWidth:this.width,strokeLineCap:this.strokeLineCap,strokeMiterLimit:this.strokeMiterLimit,strokeLineJoin:this.strokeLineJoin,strokeDashArray:this.strokeDashArray}),i=new fabric.Point(e.left+e.width/2,e.top+e.height/2);return i=e.translateToGivenOrigin(i,"center","center",e.originX,e.originY),e.top=i.y,e.left=i.x,this.shadow&&(this.shadow.affectStroke=!0,e.setShadow(this.shadow)),e},_finalizeAndAddPath:function(){this.canvas.contextTop.closePath();var t=this.convertPointsToSVGPath(this._points).join("");if("M 0 0 Q 0 0 0 0 L 0 0"!==t){var e=this.createPath(t);this.canvas.clearContext(this.canvas.contextTop),this.canvas.add(e),this.canvas.renderAll(),e.setCoords(),this._resetShadow(),this.canvas.fire("path:created",{path:e})}else this.canvas.requestRenderAll()}}),fabric.CircleBrush=fabric.util.createClass(fabric.BaseBrush,{width:10,initialize:function(t){this.canvas=t,this.points=[]},drawDot:function(t){var e=this.addPoint(t),i=this.canvas.contextTop;this._saveAndTransform(i),i.fillStyle=e.fill,i.beginPath(),i.arc(e.x,e.y,e.radius,0,2*Math.PI,!1),i.closePath(),i.fill(),i.restore()},onMouseDown:function(t){this.points.length=0,this.canvas.clearContext(this.canvas.contextTop),this._setShadow(),this.drawDot(t)},_render:function(){var t,e,i,r=this.canvas.contextTop,n=this.points;for(this._saveAndTransform(r),t=0,e=n.length;t0&&!this.preserveObjectStacking){e=[],i=[];for(var n=0,s=this._objects.length;n1&&(this._activeObject._objects=i),e.push.apply(e,i)}else e=this._objects;return e},renderAll:function(){!this.contextTopDirty||this._groupSelector||this.isDrawingMode||(this.clearContext(this.contextTop),this.contextTopDirty=!1),this.isDrawingMode&&this._isCurrentlyDrawing&&this.freeDrawingBrush&&this.freeDrawingBrush._render();var t=this.contextContainer;return this.renderCanvas(t,this._chooseObjectsToRender()),this},renderTop:function(){var t=this.contextTop;return this.clearContext(t),this.selection&&this._groupSelector&&this._drawSelection(t),this.fire("after:render"),this.contextTopDirty=!0,this},_resetCurrentTransform:function(){var t=this._currentTransform;t.target.set({scaleX:t.original.scaleX,scaleY:t.original.scaleY,skewX:t.original.skewX,skewY:t.original.skewY,left:t.original.left,top:t.original.top}),this._shouldCenterTransform(t.target)?"rotate"===t.action?this._setOriginToCenter(t.target):("center"!==t.originX&&("right"===t.originX?t.mouseXSign=-1:t.mouseXSign=1),"center"!==t.originY&&("bottom"===t.originY?t.mouseYSign=-1:t.mouseYSign=1),t.originX="center",t.originY="center"):(t.originX=t.original.originX,t.originY=t.original.originY)},containsPoint:function(t,e,i){var r,n=i||this.getPointer(t,!0);return r=e.group&&e.group===this._activeObject&&"activeSelection"===e.group.type?this._normalizePointer(e.group,n):{x:n.x,y:n.y},e.containsPoint(r)||e._findTargetCorner(n)},_normalizePointer:function(t,e){var i=t.calcTransformMatrix(),r=fabric.util.invertTransform(i),n=this.restorePointerVpt(e);return fabric.util.transformPoint(n,r)},isTargetTransparent:function(t,e,i){var r=this.contextCache,n=t.selectionBackgroundColor,s=this.viewportTransform;t.selectionBackgroundColor="",this.clearContext(r),r.save(),r.transform(s[0],s[1],s[2],s[3],s[4],s[5]),t.render(r),r.restore(),t===this._activeObject&&t._renderControls(r,{hasBorders:!1,transparentCorners:!1},{hasBorders:!1}),t.selectionBackgroundColor=n;return fabric.util.isTransparent(r,e,i,this.targetFindTolerance)},_isSelectionKeyPressed:function(t){return"[object Array]"===Object.prototype.toString.call(this.selectionKey)?!!this.selectionKey.find(function(e){return!0===t[e]}):t[this.selectionKey]},_shouldClearSelection:function(t,e){var i=this.getActiveObjects(),r=this._activeObject;return!e||e&&r&&i.length>1&&-1===i.indexOf(e)&&r!==e&&!this._isSelectionKeyPressed(t)||e&&!e.evented||e&&!e.selectable&&r&&r!==e},_shouldCenterTransform:function(t){if(t){var e,i=this._currentTransform;return"scale"===i.action||"scaleX"===i.action||"scaleY"===i.action?e=this.centeredScaling||t.centeredScaling:"rotate"===i.action&&(e=this.centeredRotation||t.centeredRotation),e?!i.altKey:i.altKey}},_getOriginFromCorner:function(t,e){var i={x:t.originX,y:t.originY};return"ml"===e||"tl"===e||"bl"===e?i.x="right":"mr"!==e&&"tr"!==e&&"br"!==e||(i.x="left"),"tl"===e||"mt"===e||"tr"===e?i.y="bottom":"bl"!==e&&"mb"!==e&&"br"!==e||(i.y="top"),i},_getActionFromCorner:function(t,e,i){if(!e)return"drag";switch(e){case"mtr":return"rotate";case"ml":case"mr":return i[this.altActionKey]?"skewY":"scaleX";case"mt":case"mb":return i[this.altActionKey]?"skewX":"scaleY";default:return"scale"}},_setupCurrentTransform:function(t,i){if(i){var r=this.getPointer(t),n=i._findTargetCorner(this.getPointer(t,!0)),s=this._getActionFromCorner(i,n,t),o=this._getOriginFromCorner(i,n);this._currentTransform={target:i,action:s,corner:n,scaleX:i.scaleX,scaleY:i.scaleY,skewX:i.skewX,skewY:i.skewY,offsetX:r.x-i.left,offsetY:r.y-i.top,originX:o.x,originY:o.y,ex:r.x,ey:r.y,lastX:r.x,lastY:r.y,left:i.left,top:i.top,theta:e(i.angle),width:i.width*i.scaleX,mouseXSign:1,mouseYSign:1,shiftKey:t.shiftKey,altKey:t[this.centeredKey]},this._currentTransform.original={left:i.left,top:i.top,scaleX:i.scaleX,scaleY:i.scaleY,skewX:i.skewX,skewY:i.skewY,originX:o.x,originY:o.y},this._resetCurrentTransform()}},_translateObject:function(t,e){var i=this._currentTransform,r=i.target,n=t-i.offsetX,s=e-i.offsetY,o=!r.get("lockMovementX")&&r.left!==n,a=!r.get("lockMovementY")&&r.top!==s;return o&&r.set("left",n),a&&r.set("top",s),o||a},_changeSkewTransformOrigin:function(t,e,i){var r="originX",n={0:"center"},s=e.target.skewX,o="left",a="right",h="mt"===e.corner||"ml"===e.corner?1:-1,c=1;t=t>0?1:-1,"y"===i&&(s=e.target.skewY,o="top",a="bottom",r="originY"),n[-1]=o,n[1]=a,e.target.flipX&&(c*=-1),e.target.flipY&&(c*=-1),0===s?(e.skewSign=-h*t*c,e[r]=n[-t]):(s=s>0?1:-1,e.skewSign=s,e[r]=n[s*h*c])},_skewObject:function(t,e,i){var r=this._currentTransform,n=r.target,s=!1,o=n.get("lockSkewingX"),a=n.get("lockSkewingY");if(o&&"x"===i||a&&"y"===i)return!1;var h,c,l=n.getCenterPoint(),u=n.toLocalPoint(new fabric.Point(t,e),"center","center")[i],f=n.toLocalPoint(new fabric.Point(r.lastX,r.lastY),"center","center")[i],d=n._getTransformedDimensions();return this._changeSkewTransformOrigin(u-f,r,i),h=n.toLocalPoint(new fabric.Point(t,e),r.originX,r.originY)[i],c=n.translateToOriginPoint(l,r.originX,r.originY),s=this._setObjectSkew(h,r,i,d),r.lastX=t,r.lastY=e,n.setPositionByOrigin(c,r.originX,r.originY),s},_setObjectSkew:function(t,e,i,r){var n,s,o,a,h,c,l,u,f,d=e.target,g=!1,p=e.skewSign;return"x"===i?(a="y",h="Y",c="X",u=0,f=d.skewY):(a="x",h="X",c="Y",u=d.skewX,f=0),o=d._getTransformedDimensions(u,f),(l=2*Math.abs(t)-o[i])<=2?n=0:(n=p*Math.atan(l/d["scale"+c]/(o[a]/d["scale"+h])),n=fabric.util.radiansToDegrees(n)),g=d["skew"+c]!==n,d.set("skew"+c,n),0!==d["skew"+h]&&(s=d._getTransformedDimensions(),n=r[a]/s[a]*d["scale"+h],d.set("scale"+h,n)),g},_scaleObject:function(t,e,i){var r=this._currentTransform,n=r.target,s=n.get("lockScalingX"),o=n.get("lockScalingY"),a=n.get("lockScalingFlip");if(s&&o)return!1;var h=n.translateToOriginPoint(n.getCenterPoint(),r.originX,r.originY),c=n.toLocalPoint(new fabric.Point(t,e),r.originX,r.originY),l=n._getTransformedDimensions(),u=!1;return this._setLocalMouse(c,r),u=this._setObjectScale(c,r,s,o,i,a,l),n.setPositionByOrigin(h,r.originX,r.originY),u},_setObjectScale:function(t,e,i,r,n,s,o){var a,h,c,l,u=e.target,f=!1,d=!1,g=!1;return c=t.x*u.scaleX/o.x,l=t.y*u.scaleY/o.y,a=u.scaleX!==c,h=u.scaleY!==l,s&&c<=0&&cs?t.x<0?t.x+=s:t.x-=s:t.x=0,n(t.y)>s?t.y<0?t.y+=s:t.y-=s:t.y=0},_rotateObject:function(t,e){var n=this._currentTransform;if(n.target.get("lockRotation"))return!1;var s=r(n.ey-n.top,n.ex-n.left),o=r(e-n.top,t-n.left),a=i(o-s+n.theta),h=!0;if(n.target.snapAngle>0){var c=n.target.snapAngle,l=n.target.snapThreshold||c,u=Math.ceil(a/c)*c,f=Math.floor(a/c)*c;Math.abs(a-f)0?0:-i),e.ey-(r>0?0:-r),o,a)),this.selectionLineWidth&&this.selectionBorderColor)if(t.lineWidth=this.selectionLineWidth,t.strokeStyle=this.selectionBorderColor,this.selectionDashArray.length>1&&!s){var h=e.ex+.5-(i>0?0:o),c=e.ey+.5-(r>0?0:a);t.beginPath(),fabric.util.drawDashedLine(t,h,c,h+o,c,this.selectionDashArray),fabric.util.drawDashedLine(t,h,c+a-1,h+o,c+a-1,this.selectionDashArray),fabric.util.drawDashedLine(t,h,c,h,c+a,this.selectionDashArray),fabric.util.drawDashedLine(t,h+o-1,c,h+o-1,c+a,this.selectionDashArray),t.closePath(),t.stroke()}else fabric.Object.prototype._setLineDash.call(this,t,this.selectionDashArray),t.strokeRect(e.ex+.5-(i>0?0:o),e.ey+.5-(r>0?0:a),o,a)},findTarget:function(t,e){if(!this.skipTargetFind){var i,r,n=this.getPointer(t,!0),s=this._activeObject,o=this.getActiveObjects();if(this.targets=[],o.length>1&&!e&&s===this._searchPossibleTargets([s],n))return s;if(1===o.length&&s._findTargetCorner(n))return s;if(1===o.length&&s===this._searchPossibleTargets([s],n)){if(!this.preserveObjectStacking)return s;i=s,r=this.targets,this.targets=[]}var a=this._searchPossibleTargets(this._objects,n);return t[this.altSelectionKey]&&a&&i&&a!==i&&(a=i,this.targets=r),a}},_checkTarget:function(t,e){if(e&&e.visible&&e.evented&&this.containsPoint(null,e,t)){if(!this.perPixelTargetFind&&!e.perPixelTargetFind||e.isEditing)return!0;if(!this.isTargetTransparent(e,t.x,t.y))return!0}},_searchPossibleTargets:function(t,e){for(var i,r,n,s=t.length;s--;)if(this._checkTarget(e,t[s])){"group"===(i=t[s]).type&&i.subTargetCheck&&(r=this._normalizePointer(i,e),(n=this._searchPossibleTargets(i._objects,r))&&this.targets.push(n));break}return i},restorePointerVpt:function(t){return fabric.util.transformPoint(t,fabric.util.invertTransform(this.viewportTransform))},getPointer:function(e,i,r){r||(r=this.upperCanvasEl);var n,s=t(e),o=r.getBoundingClientRect(),a=o.width||0,h=o.height||0;return a&&h||("top"in o&&"bottom"in o&&(h=Math.abs(o.top-o.bottom)),"right"in o&&"left"in o&&(a=Math.abs(o.right-o.left))),this.calcOffset(),s.x=s.x-this._offset.left,s.y=s.y-this._offset.top,i||(s=this.restorePointerVpt(s)),n=0===a||0===h?{width:1,height:1}:{width:r.width/a,height:r.height/h},{x:s.x*n.width,y:s.y*n.height}},_createUpperCanvas:function(){var t=this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/,"");this.upperCanvasEl?this.upperCanvasEl.className="":this.upperCanvasEl=this._createCanvasElement(),fabric.util.addClass(this.upperCanvasEl,"upper-canvas "+t),this.wrapperEl.appendChild(this.upperCanvasEl),this._copyCanvasStyle(this.lowerCanvasEl,this.upperCanvasEl),this._applyCanvasStyle(this.upperCanvasEl),this.contextTop=this.upperCanvasEl.getContext("2d")},_createCacheCanvas:function(){this.cacheCanvasEl=this._createCanvasElement(),this.cacheCanvasEl.setAttribute("width",this.width),this.cacheCanvasEl.setAttribute("height",this.height),this.contextCache=this.cacheCanvasEl.getContext("2d")},_initWrapperElement:function(){this.wrapperEl=fabric.util.wrapElement(this.lowerCanvasEl,"div",{class:this.containerClass}),fabric.util.setStyle(this.wrapperEl,{width:this.width+"px",height:this.height+"px",position:"relative"}),fabric.util.makeElementUnselectable(this.wrapperEl)},_applyCanvasStyle:function(t){var e=this.width||t.width,i=this.height||t.height;fabric.util.setStyle(t,{position:"absolute",width:e+"px",height:i+"px",left:0,top:0,"touch-action":"none"}),t.width=e,t.height=i,fabric.util.makeElementUnselectable(t)},_copyCanvasStyle:function(t,e){e.style.cssText=t.style.cssText},getSelectionContext:function(){return this.contextTop},getSelectionElement:function(){return this.upperCanvasEl},getActiveObject:function(){return this._activeObject},getActiveObjects:function(){var t=this._activeObject;return t?"activeSelection"===t.type&&t._objects?t._objects.slice(0):[t]:[]},_onObjectRemoved:function(t){t===this._activeObject&&(this.fire("before:selection:cleared",{target:t}),this._discardActiveObject(),this.fire("selection:cleared",{target:t}),t.fire("deselected")),this._hoveredTarget===t&&(this._hoveredTarget=null),this.callSuper("_onObjectRemoved",t)},_fireSelectionEvents:function(t,e){var i=!1,r=this.getActiveObjects(),n=[],s=[],o={e:e};t.forEach(function(t){-1===r.indexOf(t)&&(i=!0,t.fire("deselected",o),s.push(t))}),r.forEach(function(e){-1===t.indexOf(e)&&(i=!0,e.fire("selected",o),n.push(e))}),t.length>0&&r.length>0?(o.selected=n,o.deselected=s,o.updated=n[0]||s[0],o.target=this._activeObject,i&&this.fire("selection:updated",o)):r.length>0?(1===r.length&&(o.target=n[0],this.fire("object:selected",o)),o.selected=n,o.target=this._activeObject,this.fire("selection:created",o)):t.length>0&&(o.deselected=s,this.fire("selection:cleared",o))},setActiveObject:function(t,e){var i=this.getActiveObjects();return this._setActiveObject(t,e),this._fireSelectionEvents(i,e),this},_setActiveObject:function(t,e){return this._activeObject!==t&&(!!this._discardActiveObject(e,t)&&(!t.onSelect({e:e})&&(this._activeObject=t,!0)))},_discardActiveObject:function(t,e){var i=this._activeObject;if(i){if(i.onDeselect({e:t,object:e}))return!1;this._activeObject=null}return!0},discardActiveObject:function(t){var e=this.getActiveObjects();return e.length&&this.fire("before:selection:cleared",{target:e[0],e:t}),this._discardActiveObject(t),this._fireSelectionEvents(e,t),this},dispose:function(){var t=this.wrapperEl;return this.removeListeners(),t.removeChild(this.upperCanvasEl),t.removeChild(this.lowerCanvasEl),delete this.upperCanvasEl,t.parentNode&&t.parentNode.replaceChild(this.lowerCanvasEl,this.wrapperEl),delete this.wrapperEl,fabric.StaticCanvas.prototype.dispose.call(this),this},clear:function(){return this.discardActiveObject(),this.clearContext(this.contextTop),this.callSuper("clear")},drawControls:function(t){var e=this._activeObject;e&&e._renderControls(t)},_toObject:function(t,e,i){var r=this._realizeGroupTransformOnObject(t),n=this.callSuper("_toObject",t,e,i);return this._unwindGroupTransformOnObject(t,r),n},_realizeGroupTransformOnObject:function(t){if(t.group&&"activeSelection"===t.group.type&&this._activeObject===t.group){var e={};return["angle","flipX","flipY","left","scaleX","scaleY","skewX","skewY","top"].forEach(function(i){e[i]=t[i]}),this._activeObject.realizeTransform(t),e}return null},_unwindGroupTransformOnObject:function(t,e){e&&t.set(e)},_setSVGObject:function(t,e,i){var r=this._realizeGroupTransformOnObject(e);this.callSuper("_setSVGObject",t,e,i),this._unwindGroupTransformOnObject(e,r)}});for(var o in fabric.StaticCanvas)"prototype"!==o&&(fabric.Canvas[o]=fabric.StaticCanvas[o]);fabric.isTouchSupported&&(fabric.Canvas.prototype._setCursorFromEvent=function(){})}(),function(){function t(t,e){return"which"in t?t.which===e:t.button===e-1}var e={mt:0,tr:1,mr:2,br:3,mb:4,bl:5,ml:6,tl:7},i=fabric.util.addListener,r=fabric.util.removeListener;fabric.util.object.extend(fabric.Canvas.prototype,{cursorMap:["n-resize","ne-resize","e-resize","se-resize","s-resize","sw-resize","w-resize","nw-resize"],_initEventListeners:function(){this.removeListeners(),this._bindEvents(),i(fabric.window,"resize",this._onResize),i(this.upperCanvasEl,"mousedown",this._onMouseDown),i(this.upperCanvasEl,"dblclick",this._onDoubleClick),i(this.upperCanvasEl,"mousemove",this._onMouseMove),i(this.upperCanvasEl,"mouseout",this._onMouseOut),i(this.upperCanvasEl,"mouseenter",this._onMouseEnter),i(this.upperCanvasEl,"wheel",this._onMouseWheel),i(this.upperCanvasEl,"contextmenu",this._onContextMenu),i(this.upperCanvasEl,"touchstart",this._onMouseDown,{passive:!1}),i(this.upperCanvasEl,"touchmove",this._onMouseMove,{passive:!1}),"undefined"!=typeof eventjs&&"add"in eventjs&&(eventjs.add(this.upperCanvasEl,"gesture",this._onGesture),eventjs.add(this.upperCanvasEl,"drag",this._onDrag),eventjs.add(this.upperCanvasEl,"orientation",this._onOrientationChange),eventjs.add(this.upperCanvasEl,"shake",this._onShake),eventjs.add(this.upperCanvasEl,"longpress",this._onLongPress))},_bindEvents:function(){this.eventsBinded||(this._onMouseDown=this._onMouseDown.bind(this),this._onMouseMove=this._onMouseMove.bind(this),this._onMouseUp=this._onMouseUp.bind(this),this._onResize=this._onResize.bind(this),this._onGesture=this._onGesture.bind(this),this._onDrag=this._onDrag.bind(this),this._onShake=this._onShake.bind(this),this._onLongPress=this._onLongPress.bind(this),this._onOrientationChange=this._onOrientationChange.bind(this),this._onMouseWheel=this._onMouseWheel.bind(this),this._onMouseOut=this._onMouseOut.bind(this),this._onMouseEnter=this._onMouseEnter.bind(this),this._onContextMenu=this._onContextMenu.bind(this),this._onDoubleClick=this._onDoubleClick.bind(this),this.eventsBinded=!0)},removeListeners:function(){r(fabric.window,"resize",this._onResize),r(this.upperCanvasEl,"mousedown",this._onMouseDown),r(this.upperCanvasEl,"mousemove",this._onMouseMove),r(this.upperCanvasEl,"mouseout",this._onMouseOut),r(this.upperCanvasEl,"mouseenter",this._onMouseEnter),r(this.upperCanvasEl,"wheel",this._onMouseWheel),r(this.upperCanvasEl,"contextmenu",this._onContextMenu),r(this.upperCanvasEl,"doubleclick",this._onDoubleClick),r(this.upperCanvasEl,"touchstart",this._onMouseDown),r(this.upperCanvasEl,"touchmove",this._onMouseMove),"undefined"!=typeof eventjs&&"remove"in eventjs&&(eventjs.remove(this.upperCanvasEl,"gesture",this._onGesture),eventjs.remove(this.upperCanvasEl,"drag",this._onDrag),eventjs.remove(this.upperCanvasEl,"orientation",this._onOrientationChange),eventjs.remove(this.upperCanvasEl,"shake",this._onShake),eventjs.remove(this.upperCanvasEl,"longpress",this._onLongPress))},_onGesture:function(t,e){this.__onTransformGesture&&this.__onTransformGesture(t,e)},_onDrag:function(t,e){this.__onDrag&&this.__onDrag(t,e)},_onMouseWheel:function(t){this.__onMouseWheel(t)},_onMouseOut:function(t){var e=this._hoveredTarget;this.fire("mouse:out",{target:e,e:t}),this._hoveredTarget=null,e&&e.fire("mouseout",{e:t}),this._iTextInstances&&this._iTextInstances.forEach(function(t){t.isEditing&&t.hiddenTextarea.focus()})},_onMouseEnter:function(t){this.findTarget(t)||(this.fire("mouse:over",{target:null,e:t}),this._hoveredTarget=null)},_onOrientationChange:function(t,e){this.__onOrientationChange&&this.__onOrientationChange(t,e)},_onShake:function(t,e){this.__onShake&&this.__onShake(t,e)},_onLongPress:function(t,e){this.__onLongPress&&this.__onLongPress(t,e)},_onContextMenu:function(t){return this.stopContextMenu&&(t.stopPropagation(),t.preventDefault()),!1},_onDoubleClick:function(t){this._handleEvent(t,"dblclick")},_onMouseDown:function(t){this.__onMouseDown(t),i(fabric.document,"touchend",this._onMouseUp,{passive:!1}),i(fabric.document,"touchmove",this._onMouseMove,{passive:!1}),r(this.upperCanvasEl,"mousemove",this._onMouseMove),r(this.upperCanvasEl,"touchmove",this._onMouseMove),"touchstart"===t.type?r(this.upperCanvasEl,"mousedown",this._onMouseDown):(i(fabric.document,"mouseup",this._onMouseUp),i(fabric.document,"mousemove",this._onMouseMove))},_onMouseUp:function(t){if(this.__onMouseUp(t),r(fabric.document,"mouseup",this._onMouseUp),r(fabric.document,"touchend",this._onMouseUp),r(fabric.document,"mousemove",this._onMouseMove),r(fabric.document,"touchmove",this._onMouseMove),i(this.upperCanvasEl,"mousemove",this._onMouseMove),i(this.upperCanvasEl,"touchmove",this._onMouseMove,{passive:!1}),"touchend"===t.type){var e=this;setTimeout(function(){i(e.upperCanvasEl,"mousedown",e._onMouseDown)},400)}},_onMouseMove:function(t){!this.allowTouchScrolling&&t.preventDefault&&t.preventDefault(),this.__onMouseMove(t)},_onResize:function(){this.calcOffset()},_shouldRender:function(t,e){var i=this._activeObject;return(!i||!i.isEditing||t!==i)&&!!(t&&(t.isMoving||t!==i)||!t&&i||!t&&!i&&!this._groupSelector||e&&this._previousPointer&&this.selection&&(e.x!==this._previousPointer.x||e.y!==this._previousPointer.y))},__onMouseUp:function(e){var i,r=!0,n=this._currentTransform,s=this._groupSelector,o=!s||0===s.left&&0===s.top;if(t(e,3))this.fireRightClick&&this._handleEvent(e,"up",i,3,o);else if(t(e,2))this.fireMiddleClick&&this._handleEvent(e,"up",i,2,o);else if(this.isDrawingMode&&this._isCurrentlyDrawing)this._onMouseUpInDrawingMode(e);else{n&&(this._finalizeCurrentTransform(e),r=!n.actionPerformed),i=r?this.findTarget(e,!0):n.target;var a=this._shouldRender(i,this.getPointer(e));i||!o?this._maybeGroupObjects(e):(this._groupSelector=null,this._currentTransform=null),i&&(i.isMoving=!1),this._setCursorFromEvent(e,i),this._handleEvent(e,"up",i||null,1,o),i&&(i.__corner=0),a&&this.requestRenderAll()}},_handleEvent:function(t,e,i,r,n){var s=void 0===i?this.findTarget(t):i,o=this.targets||[],a={e:t,target:s,subTargets:o,button:r||1,isClick:n||!1};this.fire("mouse:"+e,a),s&&s.fire("mouse"+e,a);for(var h=0;h1)){var r=this._groupSelector;r?(i=this.getPointer(t,!0),r.left=i.x-r.ex,r.top=i.y-r.ey,this.renderTop()):this._currentTransform?this._transformObject(t):(e=this.findTarget(t)||null,this._setCursorFromEvent(t,e),this._fireOverOutEvents(e,t)),this._handleEvent(t,"move",this._currentTransform?null:e)}},_fireOverOutEvents:function(t,e){var i,r,n=this._hoveredTarget;n!==t&&(i={e:e,target:t,previousTarget:this._hoveredTarget},r={e:e,target:this._hoveredTarget,nextTarget:t},this._hoveredTarget=t),t?n!==t&&(n&&(this.fire("mouse:out",r),n.fire("mouseout",r)),this.fire("mouse:over",i),t.fire("mouseover",i)):n&&(this.fire("mouse:out",r),n.fire("mouseout",r))},__onMouseWheel:function(t){this._handleEvent(t,"wheel")},_transformObject:function(t){var e=this.getPointer(t),i=this._currentTransform;i.reset=!1,i.target.isMoving=!0,i.shiftKey=t.shiftKey,i.altKey=t[this.centeredKey],this._beforeScaleTransform(t,i),this._performTransformAction(t,i,e),i.actionPerformed&&this.requestRenderAll()},_performTransformAction:function(t,e,i){var r=i.x,n=i.y,s=e.target,o=e.action,a=!1;"rotate"===o?(a=this._rotateObject(r,n))&&this._fire("rotating",s,t):"scale"===o?(a=this._onScale(t,e,r,n))&&this._fire("scaling",s,t):"scaleX"===o?(a=this._scaleObject(r,n,"x"))&&this._fire("scaling",s,t):"scaleY"===o?(a=this._scaleObject(r,n,"y"))&&this._fire("scaling",s,t):"skewX"===o?(a=this._skewObject(r,n,"x"))&&this._fire("skewing",s,t):"skewY"===o?(a=this._skewObject(r,n,"y"))&&this._fire("skewing",s,t):(a=this._translateObject(r,n))&&(this._fire("moving",s,t),this.setCursor(s.moveCursor||this.moveCursor)),e.actionPerformed=e.actionPerformed||a},_fire:function(t,e,i){this.fire("object:"+t,{target:e,e:i}),e.fire(t,{e:i})},_beforeScaleTransform:function(t,e){if("scale"===e.action||"scaleX"===e.action||"scaleY"===e.action){var i=this._shouldCenterTransform(e.target);(i&&("center"!==e.originX||"center"!==e.originY)||!i&&"center"===e.originX&&"center"===e.originY)&&(this._resetCurrentTransform(),e.reset=!0)}},_onScale:function(t,e,i,r){return this._isUniscalePossible(t,e.target)?(e.currentAction="scale",this._scaleObject(i,r)):(e.reset||"scale"!==e.currentAction||this._resetCurrentTransform(),e.currentAction="scaleEqually",this._scaleObject(i,r,"equally"))},_isUniscalePossible:function(t,e){return(t[this.uniScaleKey]||this.uniScaleTransform)&&!e.get("lockUniScaling")},_setCursorFromEvent:function(t,e){if(!e)return this.setCursor(this.defaultCursor),!1;var i=e.hoverCursor||this.hoverCursor,r=this._activeObject&&"activeSelection"===this._activeObject.type?this._activeObject:null,n=(!r||!r.contains(e))&&e._findTargetCorner(this.getPointer(t,!0));n?this.setCursor(this.getCornerCursor(n,e,t)):this.setCursor(i)},getCornerCursor:function(t,i,r){return this.actionIsDisabled(t,i,r)?this.notAllowedCursor:t in e?this._getRotatedCornerCursor(t,i,r):"mtr"===t&&i.hasRotatingPoint?this.rotationCursor:this.defaultCursor},actionIsDisabled:function(t,e,i){return"mt"===t||"mb"===t?i[this.altActionKey]?e.lockSkewingX:e.lockScalingY:"ml"===t||"mr"===t?i[this.altActionKey]?e.lockSkewingY:e.lockScalingX:"mtr"===t?e.lockRotation:this._isUniscalePossible(i,e)?e.lockScalingX&&e.lockScalingY:e.lockScalingX||e.lockScalingY},_getRotatedCornerCursor:function(t,i,r){var n=Math.round(i.angle%360/45);return n<0&&(n+=8),n+=e[t],r[this.altActionKey]&&e[t]%2==0&&(n+=2),n%=8,this.cursorMap[n]}})}(),function(){var t=Math.min,e=Math.max;fabric.util.object.extend(fabric.Canvas.prototype,{_shouldGroup:function(t,e){var i=this._activeObject;return i&&this._isSelectionKeyPressed(t)&&e&&e.selectable&&this.selection&&(i!==e||"activeSelection"===i.type)},_handleGrouping:function(t,e){var i=this._activeObject;i.__corner||(e!==i||(e=this.findTarget(t,!0)))&&(i&&"activeSelection"===i.type?this._updateActiveSelection(e,t):this._createActiveSelection(e,t))},_updateActiveSelection:function(t,e){var i=this._activeObject,r=i._objects.slice(0);i.contains(t)?(i.removeWithUpdate(t),this._hoveredTarget=t,1===i.size()&&this._setActiveObject(i.item(0),e)):(i.addWithUpdate(t),this._hoveredTarget=i),this._fireSelectionEvents(r,e)},_createActiveSelection:function(t,e){var i=this.getActiveObjects(),r=this._createGroup(t);this._hoveredTarget=r,this._setActiveObject(r,e),this._fireSelectionEvents(i,e)},_createGroup:function(t){var e=this.getObjects(),i=e.indexOf(this._activeObject)1&&(e=new fabric.ActiveSelection(i.reverse(),{canvas:this}),this.setActiveObject(e,t))},_collectObjects:function(){for(var i,r=[],n=this._groupSelector.ex,s=this._groupSelector.ey,o=n+this._groupSelector.left,a=s+this._groupSelector.top,h=new fabric.Point(t(n,o),t(s,a)),c=new fabric.Point(e(n,o),e(s,a)),l=!this.selectionFullyContained,u=n===o&&s===a,f=this._objects.length;f--&&!((i=this._objects[f])&&i.selectable&&i.visible&&(l&&i.intersectsWithRect(h,c)||i.isContainedWithinRect(h,c)||l&&i.containsPoint(h)||l&&i.containsPoint(c))&&(r.push(i),u)););return r},_maybeGroupObjects:function(t){this.selection&&this._groupSelector&&this._groupSelectedObjects(t),this.setCursor(this.defaultCursor),this._groupSelector=null,this._currentTransform=null}})}(),function(){var t=fabric.StaticCanvas.supports("toDataURLWithQuality");fabric.util.object.extend(fabric.StaticCanvas.prototype,{toDataURL:function(t){t||(t={});var e=t.format||"png",i=t.quality||1,r=(t.multiplier||1)*(t.enableRetinaScaling?1:1/this.getRetinaScaling()),n={left:t.left||0,top:t.top||0,width:t.width||0,height:t.height||0};return this.__toDataURLWithMultiplier(e,i,n,r)},__toDataURLWithMultiplier:function(t,e,i,r){var n=this.width,s=this.height,o=(i.width||this.width)*r,a=(i.height||this.height)*r,h=this.getZoom()*r,c=this.viewportTransform,l=[h,0,0,h,(c[4]-i.left)*r,(c[5]-i.top)*r],u=this.interactive,f=this.skipOffscreen,d=n!==o||s!==a;this.viewportTransform=l,this.skipOffscreen=!1,this.interactive=!1,d&&this.setDimensions({width:o,height:a},{backstoreOnly:!0}),this.renderAll();var g=this.__toDataURL(t,e,i);return this.interactive=u,this.skipOffscreen=f,this.viewportTransform=c,d&&this.setDimensions({width:n,height:s},{backstoreOnly:!0}),this.renderAll(),g},__toDataURL:function(e,i){var r=this.contextContainer.canvas;"jpg"===e&&(e="jpeg");return t?r.toDataURL("image/"+e,i):r.toDataURL("image/"+e)}})}(),fabric.util.object.extend(fabric.StaticCanvas.prototype,{loadFromDatalessJSON:function(t,e,i){return this.loadFromJSON(t,e,i)},loadFromJSON:function(t,e,i){if(t){var r="string"==typeof t?JSON.parse(t):fabric.util.object.clone(t),n=this,s=this.renderOnAddRemove;return this.renderOnAddRemove=!1,this._enlivenObjects(r.objects,function(t){n.clear(),n._setBgOverlay(r,function(){t.forEach(function(t,e){n.insertAt(t,e)}),n.renderOnAddRemove=s,delete r.objects,delete r.backgroundImage,delete r.overlayImage,delete r.background,delete r.overlay,n._setOptions(r),n.renderAll(),e&&e()})},i),this}},_setBgOverlay:function(t,e){var i={backgroundColor:!1,overlayColor:!1,backgroundImage:!1,overlayImage:!1};if(t.backgroundImage||t.overlayImage||t.background||t.overlay){var r=function(){i.backgroundImage&&i.overlayImage&&i.backgroundColor&&i.overlayColor&&e&&e()};this.__setBgOverlay("backgroundImage",t.backgroundImage,i,r),this.__setBgOverlay("overlayImage",t.overlayImage,i,r),this.__setBgOverlay("backgroundColor",t.background,i,r),this.__setBgOverlay("overlayColor",t.overlay,i,r)}else e&&e()},__setBgOverlay:function(t,e,i,r){var n=this;if(!e)return i[t]=!0,void(r&&r());"backgroundImage"===t||"overlayImage"===t?fabric.util.enlivenObjects([e],function(e){n[t]=e[0],i[t]=!0,r&&r()}):this["set"+fabric.util.string.capitalize(t,!0)](e,function(){i[t]=!0,r&&r()})},_enlivenObjects:function(t,e,i){t&&0!==t.length?fabric.util.enlivenObjects(t,function(t){e&&e(t)},null,i):e&&e([])},_toDataURL:function(t,e){this.clone(function(i){e(i.toDataURL(t))})},_toDataURLWithMultiplier:function(t,e,i){this.clone(function(r){i(r.toDataURLWithMultiplier(t,e))})},clone:function(t,e){var i=JSON.stringify(this.toJSON(e));this.cloneWithoutData(function(e){e.loadFromJSON(i,function(){t&&t(e)})})},cloneWithoutData:function(t){var e=fabric.document.createElement("canvas");e.width=this.width,e.height=this.height;var i=new fabric.Canvas(e);i.clipTo=this.clipTo,this.backgroundImage?(i.setBackgroundImage(this.backgroundImage.src,function(){i.renderAll(),t&&t(i)}),i.backgroundImageOpacity=this.backgroundImageOpacity,i.backgroundImageStretch=this.backgroundImageStretch):t&&t(i)}}),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend,r=e.util.object.clone,n=e.util.toFixed,s=e.util.string.capitalize,o=e.util.degreesToRadians,a=e.StaticCanvas.supports("setLineDash"),h=!e.isLikelyNode;e.Object||(e.Object=e.util.createClass(e.CommonMethods,{type:"object",originX:"left",originY:"top",top:0,left:0,width:0,height:0,scaleX:1,scaleY:1,flipX:!1,flipY:!1,opacity:1,angle:0,skewX:0,skewY:0,cornerSize:13,transparentCorners:!0,hoverCursor:null,moveCursor:null,padding:0,borderColor:"rgba(102,153,255,0.75)",borderDashArray:null,cornerColor:"rgba(102,153,255,0.5)",cornerStrokeColor:null,cornerStyle:"rect",cornerDashArray:null,centeredScaling:!1,centeredRotation:!0,fill:"rgb(0,0,0)",fillRule:"nonzero",globalCompositeOperation:"source-over",backgroundColor:"",selectionBackgroundColor:"",stroke:null,strokeWidth:1,strokeDashArray:null,strokeLineCap:"butt",strokeLineJoin:"miter",strokeMiterLimit:10,shadow:null,borderOpacityWhenMoving:.4,borderScaleFactor:1,transformMatrix:null,minScaleLimit:0,selectable:!0,evented:!0,visible:!0,hasControls:!0,hasBorders:!0,hasRotatingPoint:!0,rotatingPointOffset:40,perPixelTargetFind:!1,includeDefaultValues:!0,clipTo:null,lockMovementX:!1,lockMovementY:!1,lockRotation:!1,lockScalingX:!1,lockScalingY:!1,lockUniScaling:!1,lockSkewingX:!1,lockSkewingY:!1,lockScalingFlip:!1,excludeFromExport:!1,objectCaching:h,statefullCache:!1,noScaleCache:!0,dirty:!0,__corner:0,paintFirst:"fill",stateProperties:"top left width height scaleX scaleY flipX flipY originX originY transformMatrix stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit angle opacity fill globalCompositeOperation shadow clipTo visible backgroundColor skewX skewY fillRule paintFirst".split(" "),cacheProperties:"fill stroke strokeWidth strokeDashArray width height paintFirst strokeLineCap strokeLineJoin strokeMiterLimit backgroundColor".split(" "),initialize:function(t){t&&this.setOptions(t)},_createCacheCanvas:function(){this._cacheProperties={},this._cacheCanvas=e.document.createElement("canvas"),this._cacheContext=this._cacheCanvas.getContext("2d"),this._updateCacheCanvas()},_limitCacheSize:function(t){var i=e.perfLimitSizeTotal,r=t.width,n=t.height,s=e.maxCacheSideLimit,o=e.minCacheSideLimit;if(r<=s&&n<=s&&r*n<=i)return rl&&(t.zoomX/=r/l,t.width=l,t.capped=!0),n>u&&(t.zoomY/=n/u,t.height=u,t.capped=!0),t},_getCacheCanvasDimensions:function(){var t=this.canvas&&this.canvas.getZoom()||1,i=this.getObjectScaling(),r=this.canvas&&this.canvas._isRetinaScaling()?e.devicePixelRatio:1,n=this._getNonTransformedDimensions(),s=i.scaleX*t*r,o=i.scaleY*t*r;return{width:n.x*s+2,height:n.y*o+2,zoomX:s,zoomY:o,x:n.x,y:n.y}},_updateCacheCanvas:function(){if(this.noScaleCache&&this.canvas&&this.canvas._currentTransform){var t=this.canvas._currentTransform.target,i=this.canvas._currentTransform.action;if(this===t&&i.slice&&"scale"===i.slice(0,5))return!1}var r,n,s=this._cacheCanvas,o=this._limitCacheSize(this._getCacheCanvasDimensions()),a=e.minCacheSideLimit,h=o.width,c=o.height,l=o.zoomX,u=o.zoomY,f=h!==this.cacheWidth||c!==this.cacheHeight,d=this.zoomX!==l||this.zoomY!==u,g=f||d,p=0,v=0,m=!1;if(f){var b=this._cacheCanvas.width,_=this._cacheCanvas.height,y=h>b||c>_;m=y||(h<.9*b||c<.9*_)&&b>a&&_>a,y&&!o.capped&&(h>a||c>a)&&(p=.1*h,v=.1*c)}return!!g&&(m?(s.width=Math.ceil(h+p),s.height=Math.ceil(c+v)):(this._cacheContext.setTransform(1,0,0,1,0,0),this._cacheContext.clearRect(0,0,s.width,s.height)),r=o.x*l/2,n=o.y*u/2,this.cacheTranslationX=Math.round(s.width/2-r)+r,this.cacheTranslationY=Math.round(s.height/2-n)+n,this.cacheWidth=h,this.cacheHeight=c,this._cacheContext.translate(this.cacheTranslationX,this.cacheTranslationY),this._cacheContext.scale(l,u),this.zoomX=l,this.zoomY=u,!0)},setOptions:function(t){this._setOptions(t),this._initGradient(t.fill,"fill"),this._initGradient(t.stroke,"stroke"),this._initClipping(t),this._initPattern(t.fill,"fill"),this._initPattern(t.stroke,"stroke")},transform:function(t){var e;e=this.group&&!this.group._transformDone?this.calcTransformMatrix():this.calcOwnMatrix(),t.transform(e[0],e[1],e[2],e[3],e[4],e[5])},toObject:function(t){var i=e.Object.NUM_FRACTION_DIGITS,r={type:this.type,version:e.version,originX:this.originX,originY:this.originY,left:n(this.left,i),top:n(this.top,i),width:n(this.width,i),height:n(this.height,i),fill:this.fill&&this.fill.toObject?this.fill.toObject():this.fill,stroke:this.stroke&&this.stroke.toObject?this.stroke.toObject():this.stroke,strokeWidth:n(this.strokeWidth,i),strokeDashArray:this.strokeDashArray?this.strokeDashArray.concat():this.strokeDashArray,strokeLineCap:this.strokeLineCap,strokeLineJoin:this.strokeLineJoin,strokeMiterLimit:n(this.strokeMiterLimit,i),scaleX:n(this.scaleX,i),scaleY:n(this.scaleY,i),angle:n(this.angle,i),flipX:this.flipX,flipY:this.flipY,opacity:n(this.opacity,i),shadow:this.shadow&&this.shadow.toObject?this.shadow.toObject():this.shadow,visible:this.visible,clipTo:this.clipTo&&String(this.clipTo),backgroundColor:this.backgroundColor,fillRule:this.fillRule,paintFirst:this.paintFirst,globalCompositeOperation:this.globalCompositeOperation,transformMatrix:this.transformMatrix?this.transformMatrix.concat():null,skewX:n(this.skewX,i),skewY:n(this.skewY,i)};return e.util.populateWithProperties(this,r,t),this.includeDefaultValues||(r=this._removeDefaultValues(r)),r},toDatalessObject:function(t){return this.toObject(t)},_removeDefaultValues:function(t){var i=e.util.getKlass(t.type).prototype;return i.stateProperties.forEach(function(e){t[e]===i[e]&&delete t[e];"[object Array]"===Object.prototype.toString.call(t[e])&&"[object Array]"===Object.prototype.toString.call(i[e])&&0===t[e].length&&0===i[e].length&&delete t[e]}),t},toString:function(){return"#"},getObjectScaling:function(){var t=this.scaleX,e=this.scaleY;if(this.group){var i=this.group.getObjectScaling();t*=i.scaleX,e*=i.scaleY}return{scaleX:t,scaleY:e}},getObjectOpacity:function(){var t=this.opacity;return this.group&&(t*=this.group.getObjectOpacity()),t},_set:function(t,i){var r="scaleX"===t||"scaleY"===t,n=this[t]!==i,s=!1;return r&&(i=this._constrainScale(i)),"scaleX"===t&&i<0?(this.flipX=!this.flipX,i*=-1):"scaleY"===t&&i<0?(this.flipY=!this.flipY,i*=-1):"shadow"!==t||!i||i instanceof e.Shadow?"dirty"===t&&this.group&&this.group.set("dirty",i):i=new e.Shadow(i),this[t]=i,n&&(s=this.group&&this.group.isOnACache(),this.cacheProperties.indexOf(t)>-1?(this.dirty=!0,s&&this.group.set("dirty",!0)):s&&this.stateProperties.indexOf(t)>-1&&this.group.set("dirty",!0)),this},setOnGroup:function(){},getViewportTransform:function(){return this.canvas&&this.canvas.viewportTransform?this.canvas.viewportTransform:e.iMatrix.concat()},isNotVisible:function(){return 0===this.opacity||0===this.width&&0===this.height||!this.visible},render:function(t){this.isNotVisible()||this.canvas&&this.canvas.skipOffscreen&&!this.group&&!this.isOnScreen()||(t.save(),this._setupCompositeOperation(t),this.drawSelectionBackground(t),this.transform(t),this._setOpacity(t),this._setShadow(t,this),this.transformMatrix&&t.transform.apply(t,this.transformMatrix),this.clipTo&&e.util.clipContext(this,t),this.shouldCache()?(this._cacheCanvas||this._createCacheCanvas(),this.isCacheDirty()&&(this.statefullCache&&this.saveState({propertySet:"cacheProperties"}),this.drawObject(this._cacheContext),this.dirty=!1),this.drawCacheOnCanvas(t)):(this._removeCacheCanvas(),this.dirty=!1,this.drawObject(t),this.objectCaching&&this.statefullCache&&this.saveState({propertySet:"cacheProperties"})),this.clipTo&&t.restore(),t.restore())},_removeCacheCanvas:function(){this._cacheCanvas=null,this.cacheWidth=0,this.cacheHeight=0},needsItsOwnCache:function(){return"stroke"===this.paintFirst&&"object"==typeof this.shadow},shouldCache:function(){return this.ownCaching=this.objectCaching&&(!this.group||this.needsItsOwnCache()||!this.group.isOnACache()),this.ownCaching},willDrawShadow:function(){return!!this.shadow&&(0!==this.shadow.offsetX||0!==this.shadow.offsetY)},drawObject:function(t){this._renderBackground(t),this._setStrokeStyles(t,this),this._setFillStyles(t,this),this._render(t)},drawCacheOnCanvas:function(t){t.scale(1/this.zoomX,1/this.zoomY),t.drawImage(this._cacheCanvas,-this.cacheTranslationX,-this.cacheTranslationY)},isCacheDirty:function(t){if(this.isNotVisible())return!1;if(this._cacheCanvas&&!t&&this._updateCacheCanvas())return!0;if(this.dirty||this.statefullCache&&this.hasStateChanged("cacheProperties")){if(this._cacheCanvas&&!t){var e=this.cacheWidth/this.zoomX,i=this.cacheHeight/this.zoomY;this._cacheContext.clearRect(-e/2,-i/2,e,i)}return!0}return!1},_renderBackground:function(t){if(this.backgroundColor){var e=this._getNonTransformedDimensions();t.fillStyle=this.backgroundColor,t.fillRect(-e.x/2,-e.y/2,e.x,e.y),this._removeShadow(t)}},_setOpacity:function(t){this.group&&!this.group._transformDone?t.globalAlpha=this.getObjectOpacity():t.globalAlpha*=this.opacity},_setStrokeStyles:function(t,e){e.stroke&&(t.lineWidth=e.strokeWidth,t.lineCap=e.strokeLineCap,t.lineJoin=e.strokeLineJoin,t.miterLimit=e.strokeMiterLimit,t.strokeStyle=e.stroke.toLive?e.stroke.toLive(t,this):e.stroke)},_setFillStyles:function(t,e){e.fill&&(t.fillStyle=e.fill.toLive?e.fill.toLive(t,this):e.fill)},_setLineDash:function(t,e,i){e&&(1&e.length&&e.push.apply(e,e),a?t.setLineDash(e):i&&i(t))},_renderControls:function(t,i){var r,n,s,a=this.getViewportTransform(),h=this.calcTransformMatrix();n=void 0!==(i=i||{}).hasBorders?i.hasBorders:this.hasBorders,s=void 0!==i.hasControls?i.hasControls:this.hasControls,h=e.util.multiplyTransformMatrices(a,h),r=e.util.qrDecompose(h),t.save(),t.translate(r.translateX,r.translateY),t.lineWidth=1*this.borderScaleFactor,this.group||(t.globalAlpha=this.isMoving?this.borderOpacityWhenMoving:1),i.forActiveSelection?(t.rotate(o(r.angle)),n&&this.drawBordersInGroup(t,r,i)):(t.rotate(o(this.angle)),n&&this.drawBorders(t,i)),s&&this.drawControls(t,i),t.restore()},_setShadow:function(t){if(this.shadow){var i=this.canvas&&this.canvas.viewportTransform[0]||1,r=this.canvas&&this.canvas.viewportTransform[3]||1,n=this.getObjectScaling();this.canvas&&this.canvas._isRetinaScaling()&&(i*=e.devicePixelRatio,r*=e.devicePixelRatio),t.shadowColor=this.shadow.color,t.shadowBlur=this.shadow.blur*e.browserShadowBlurConstant*(i+r)*(n.scaleX+n.scaleY)/4,t.shadowOffsetX=this.shadow.offsetX*i*n.scaleX,t.shadowOffsetY=this.shadow.offsetY*r*n.scaleY}},_removeShadow:function(t){this.shadow&&(t.shadowColor="",t.shadowBlur=t.shadowOffsetX=t.shadowOffsetY=0)},_applyPatternGradientTransform:function(t,e){if(!e||!e.toLive)return{offsetX:0,offsetY:0};var i=e.gradientTransform||e.patternTransform,r=-this.width/2+e.offsetX||0,n=-this.height/2+e.offsetY||0;return t.translate(r,n),i&&t.transform(i[0],i[1],i[2],i[3],i[4],i[5]),{offsetX:r,offsetY:n}},_renderPaintInOrder:function(t){"stroke"===this.paintFirst?(this._renderStroke(t),this._renderFill(t)):(this._renderFill(t),this._renderStroke(t))},_renderFill:function(t){this.fill&&(t.save(),this._applyPatternGradientTransform(t,this.fill),"evenodd"===this.fillRule?t.fill("evenodd"):t.fill(),t.restore())},_renderStroke:function(t){this.stroke&&0!==this.strokeWidth&&(this.shadow&&!this.shadow.affectStroke&&this._removeShadow(t),t.save(),this._setLineDash(t,this.strokeDashArray,this._renderDashedStroke),this._applyPatternGradientTransform(t,this.stroke),t.stroke(),t.restore())},_findCenterFromElement:function(){return{x:this.left+this.width/2,y:this.top+this.height/2}},_assignTransformMatrixProps:function(){if(this.transformMatrix){var t=e.util.qrDecompose(this.transformMatrix);this.flipX=!1,this.flipY=!1,this.set("scaleX",t.scaleX),this.set("scaleY",t.scaleY),this.angle=t.angle,this.skewX=t.skewX,this.skewY=0}},_removeTransformMatrix:function(t){var i=this._findCenterFromElement();this.transformMatrix&&(this._assignTransformMatrixProps(),i=e.util.transformPoint(i,this.transformMatrix)),this.transformMatrix=null,t&&(this.scaleX*=t.scaleX,this.scaleY*=t.scaleY,this.cropX=t.cropX,this.cropY=t.cropY,i.x+=t.offsetLeft,i.y+=t.offsetTop,this.width=t.width,this.height=t.height),this.setPositionByOrigin(i,"center","center")},clone:function(t,i){var r=this.toObject(i);this.constructor.fromObject?this.constructor.fromObject(r,t):e.Object._fromObject("Object",r,t)},cloneAsImage:function(t,i){var r=this.toDataURL(i);return e.util.loadImage(r,function(i){t&&t(new e.Image(i))}),this},toDataURL:function(t){t||(t={});var i=e.util.createCanvasElement(),r=this.getBoundingRect();i.width=r.width,i.height=r.height,e.util.wrapElement(i,"div");var n=new e.StaticCanvas(i,{enableRetinaScaling:t.enableRetinaScaling,renderOnAddRemove:!1,skipOffscreen:!1});"jpg"===t.format&&(t.format="jpeg"),"jpeg"===t.format&&(n.backgroundColor="#fff");var s={left:this.left,top:this.top};this.setPositionByOrigin(new e.Point(n.width/2,n.height/2),"center","center");var o=this.canvas;n.add(this);var a=n.toDataURL(t);return this.set(s).setCoords(),this.canvas=o,n._objects=[],n.dispose(),n=null,a},isType:function(t){return this.type===t},complexity:function(){return 1},toJSON:function(t){return this.toObject(t)},setGradient:function(t,i){i||(i={});var r={colorStops:[]};return r.type=i.type||(i.r1||i.r2?"radial":"linear"),r.coords={x1:i.x1,y1:i.y1,x2:i.x2,y2:i.y2},(i.r1||i.r2)&&(r.coords.r1=i.r1,r.coords.r2=i.r2),r.gradientTransform=i.gradientTransform,e.Gradient.prototype.addColorStop.call(r,i.colorStops),this.set(t,e.Gradient.forObject(this,r))},setPatternFill:function(t){return this.set("fill",new e.Pattern(t))},setShadow:function(t){return this.set("shadow",t?new e.Shadow(t):null)},setColor:function(t){return this.set("fill",t),this},rotate:function(t){var e=("center"!==this.originX||"center"!==this.originY)&&this.centeredRotation;return e&&this._setOriginToCenter(),this.set("angle",t),e&&this._resetOrigin(),this},centerH:function(){return this.canvas&&this.canvas.centerObjectH(this),this},viewportCenterH:function(){return this.canvas&&this.canvas.viewportCenterObjectH(this),this},centerV:function(){return this.canvas&&this.canvas.centerObjectV(this),this},viewportCenterV:function(){return this.canvas&&this.canvas.viewportCenterObjectV(this),this},center:function(){return this.canvas&&this.canvas.centerObject(this),this},viewportCenter:function(){return this.canvas&&this.canvas.viewportCenterObject(this),this},getLocalPointer:function(t,i){i=i||this.canvas.getPointer(t);var r=new e.Point(i.x,i.y),n=this._getLeftTopCoords();return this.angle&&(r=e.util.rotatePoint(r,n,o(-this.angle))),{x:r.x-n.x,y:r.y-n.y}},_setupCompositeOperation:function(t){this.globalCompositeOperation&&(t.globalCompositeOperation=this.globalCompositeOperation)}}),e.util.createAccessors&&e.util.createAccessors(e.Object),i(e.Object.prototype,e.Observable),e.Object.NUM_FRACTION_DIGITS=2,e.Object._fromObject=function(t,i,n,s){var o=e[t];i=r(i,!0),e.util.enlivenPatterns([i.fill,i.stroke],function(t){void 0!==t[0]&&(i.fill=t[0]),void 0!==t[1]&&(i.stroke=t[1]);var e=s?new o(i[s],i):new o(i);n&&n(e)})},e.Object.__uid=0)}("undefined"!=typeof exports?exports:this),function(){var t=fabric.util.degreesToRadians,e={left:-.5,center:0,right:.5},i={top:-.5,center:0,bottom:.5};fabric.util.object.extend(fabric.Object.prototype,{translateToGivenOrigin:function(t,r,n,s,o){var a,h,c,l=t.x,u=t.y;return"string"==typeof r?r=e[r]:r-=.5,"string"==typeof s?s=e[s]:s-=.5,a=s-r,"string"==typeof n?n=i[n]:n-=.5,"string"==typeof o?o=i[o]:o-=.5,h=o-n,(a||h)&&(c=this._getTransformedDimensions(),l=t.x+a*c.x,u=t.y+h*c.y),new fabric.Point(l,u)},translateToCenterPoint:function(e,i,r){var n=this.translateToGivenOrigin(e,i,r,"center","center");return this.angle?fabric.util.rotatePoint(n,e,t(this.angle)):n},translateToOriginPoint:function(e,i,r){var n=this.translateToGivenOrigin(e,"center","center",i,r);return this.angle?fabric.util.rotatePoint(n,e,t(this.angle)):n},getCenterPoint:function(){var t=new fabric.Point(this.left,this.top);return this.translateToCenterPoint(t,this.originX,this.originY)},getPointByOrigin:function(t,e){var i=this.getCenterPoint();return this.translateToOriginPoint(i,t,e)},toLocalPoint:function(e,i,r){var n,s,o=this.getCenterPoint();return n=void 0!==i&&void 0!==r?this.translateToGivenOrigin(o,"center","center",i,r):new fabric.Point(this.left,this.top),s=new fabric.Point(e.x,e.y),this.angle&&(s=fabric.util.rotatePoint(s,o,-t(this.angle))),s.subtractEquals(n)},setPositionByOrigin:function(t,e,i){var r=this.translateToCenterPoint(t,e,i),n=this.translateToOriginPoint(r,this.originX,this.originY);this.set("left",n.x),this.set("top",n.y)},adjustPosition:function(i){var r,n,s=t(this.angle),o=this.getScaledWidth(),a=Math.cos(s)*o,h=Math.sin(s)*o;r="string"==typeof this.originX?e[this.originX]:this.originX-.5,n="string"==typeof i?e[i]:i-.5,this.left+=a*(n-r),this.top+=h*(n-r),this.setCoords(),this.originX=i},_setOriginToCenter:function(){this._originalOriginX=this.originX,this._originalOriginY=this.originY;var t=this.getCenterPoint();this.originX="center",this.originY="center",this.left=t.x,this.top=t.y},_resetOrigin:function(){var t=this.translateToOriginPoint(this.getCenterPoint(),this._originalOriginX,this._originalOriginY);this.originX=this._originalOriginX,this.originY=this._originalOriginY,this.left=t.x,this.top=t.y,this._originalOriginX=null,this._originalOriginY=null},_getLeftTopCoords:function(){return this.translateToOriginPoint(this.getCenterPoint(),"left","top")},onDeselect:function(){}})}(),function(){var t=fabric.util.degreesToRadians,e=fabric.util.multiplyTransformMatrices;fabric.util.object.extend(fabric.Object.prototype,{oCoords:null,aCoords:null,ownMatrixCache:null,matrixCache:null,getCoords:function(t,e){this.oCoords||this.setCoords();var i=t?this.aCoords:this.oCoords;return function(t){return[new fabric.Point(t.tl.x,t.tl.y),new fabric.Point(t.tr.x,t.tr.y),new fabric.Point(t.br.x,t.br.y),new fabric.Point(t.bl.x,t.bl.y)]}(e?this.calcCoords(t):i)},intersectsWithRect:function(t,e,i,r){var n=this.getCoords(i,r);return"Intersection"===fabric.Intersection.intersectPolygonRectangle(n,t,e).status},intersectsWithObject:function(t,e,i){return"Intersection"===fabric.Intersection.intersectPolygonPolygon(this.getCoords(e,i),t.getCoords(e,i)).status||t.isContainedWithinObject(this,e,i)||this.isContainedWithinObject(t,e,i)},isContainedWithinObject:function(t,e,i){for(var r=this.getCoords(e,i),n=0,s=t._getImageLines(i?t.calcCoords(e):e?t.aCoords:t.oCoords);n<4;n++)if(!t.containsPoint(r[n],s))return!1;return!0},isContainedWithinRect:function(t,e,i,r){var n=this.getBoundingRect(i,r);return n.left>=t.x&&n.left+n.width<=e.x&&n.top>=t.y&&n.top+n.height<=e.y},containsPoint:function(t,e,i,r){var e=e||this._getImageLines(r?this.calcCoords(i):i?this.aCoords:this.oCoords),n=this._findCrossPoints(t,e);return 0!==n&&n%2==1},isOnScreen:function(t){if(!this.canvas)return!1;for(var e,i=this.canvas.vptCoords.tl,r=this.canvas.vptCoords.br,n=this.getCoords(!0,t),s=0;s<4;s++)if((e=n[s]).x<=r.x&&e.x>=i.x&&e.y<=r.y&&e.y>=i.y)return!0;if(this.intersectsWithRect(i,r,!0))return!0;var o={x:(i.x+r.x)/2,y:(i.y+r.y)/2};return!!this.containsPoint(o,null,!0)},_getImageLines:function(t){return{topline:{o:t.tl,d:t.tr},rightline:{o:t.tr,d:t.br},bottomline:{o:t.br,d:t.bl},leftline:{o:t.bl,d:t.tl}}},_findCrossPoints:function(t,e){var i,r,n,s,o=0;for(var a in e)if(!((s=e[a]).o.y=t.y&&s.d.y>=t.y||(s.o.x===s.d.x&&s.o.x>=t.x?n=s.o.x:(i=0,r=(s.d.y-s.o.y)/(s.d.x-s.o.x),n=-(t.y-i*t.x-(s.o.y-r*s.o.x))/(i-r)),n>=t.x&&(o+=1),2!==o)))break;return o},getBoundingRect:function(t,e){var i=this.getCoords(t,e);return fabric.util.makeBoundingBoxFromPoints(i)},getScaledWidth:function(){return this._getTransformedDimensions().x},getScaledHeight:function(){return this._getTransformedDimensions().y},_constrainScale:function(t){return Math.abs(t)0?Math.atan(o/s):0,l=s/Math.cos(c)/2,u=Math.cos(c+i)*l,f=Math.sin(c+i)*l,d=this.getCenterPoint(),g=e?d:fabric.util.transformPoint(d,r),p=new fabric.Point(g.x-u,g.y-f),v=new fabric.Point(p.x+s*h,p.y+s*a),m=new fabric.Point(p.x-o*a,p.y+o*h),b=new fabric.Point(g.x+u,g.y+f);if(!e)var _=new fabric.Point((p.x+m.x)/2,(p.y+m.y)/2),y=new fabric.Point((v.x+p.x)/2,(v.y+p.y)/2),x=new fabric.Point((b.x+v.x)/2,(b.y+v.y)/2),C=new fabric.Point((b.x+m.x)/2,(b.y+m.y)/2),S=new fabric.Point(y.x+a*this.rotatingPointOffset,y.y-h*this.rotatingPointOffset);g={tl:p,tr:v,br:b,bl:m};return e||(g.ml=_,g.mt=y,g.mr=x,g.mb=C,g.mtr=S),g},setCoords:function(t,e){return this.oCoords=this.calcCoords(t),e||(this.aCoords=this.calcCoords(!0)),t||this._setCornerCoords&&this._setCornerCoords(),this},_calcRotateMatrix:function(){if(this.angle){var e=t(this.angle),i=Math.cos(e),r=Math.sin(e);return 6.123233995736766e-17!==i&&-1.8369701987210297e-16!==i||(i=0),[i,r,-r,i,0,0]}return fabric.iMatrix.concat()},transformMatrixKey:function(t){var e="";return!t&&this.group&&(e=this.group.transformMatrixKey(t)+"_"),e+this.top+"_"+this.left+"_"+this.scaleX+"_"+this.scaleY+"_"+this.skewX+"_"+this.skewY+"_"+this.angle+"_"+this.originX+"_"+this.originY+"_"+this.width+"_"+this.height+"_"+this.strokeWidth+this.flipX+this.flipY},calcTransformMatrix:function(t){if(t)return this.calcOwnMatrix();var i=this.transformMatrixKey(),r=this.matrixCache||(this.matrixCache={});if(r.key===i)return r.value;var n=this.calcOwnMatrix();return this.group&&(n=e(this.group.calcTransformMatrix(),n)),r.key=i,r.value=n,n},calcOwnMatrix:function(){var t=this.transformMatrixKey(!0),i=this.ownMatrixCache||(this.ownMatrixCache={});if(i.key===t)return i.value;var r,n=this.getCenterPoint(),s=[1,0,0,1,n.x,n.y],o=this._calcDimensionsTransformMatrix(this.skewX,this.skewY,!0);return this.angle&&(r=this._calcRotateMatrix(),s=e(s,r)),s=e(s,o),i.key=t,i.value=s,s},_calcDimensionsTransformMatrix:function(i,r,n){var s,o=[this.scaleX*(n&&this.flipX?-1:1),0,0,this.scaleY*(n&&this.flipY?-1:1),0,0];return i&&(s=[1,0,Math.tan(t(i)),1],o=e(o,s,!0)),r&&(s=[1,Math.tan(t(r)),0,1],o=e(o,s,!0)),o},_getNonTransformedDimensions:function(){var t=this.strokeWidth;return{x:this.width+t,y:this.height+t}},_getTransformedDimensions:function(t,e){void 0===t&&(t=this.skewX),void 0===e&&(e=this.skewY);var i,r,n=this._getNonTransformedDimensions(),s=n.x/2,o=n.y/2,a=[{x:-s,y:-o},{x:s,y:-o},{x:-s,y:o},{x:s,y:o}],h=this._calcDimensionsTransformMatrix(t,e,!1);for(i=0;i\n')}},_createBaseSVGMarkup:function(){var t=[];return this.fill&&this.fill.toLive&&t.push(this.fill.toSVG(this,!1)),this.stroke&&this.stroke.toLive&&t.push(this.stroke.toSVG(this,!1)),this.shadow&&t.push(this.shadow.toSVG(this)),t},addPaintOrder:function(){return"fill"!==this.paintFirst?' paint-order="'+this.paintFirst+'" ':""}})}(),function(){function t(t,e,r){var n={};r.forEach(function(e){n[e]=t[e]}),i(t[e],n,!0)}function e(t,i,r){if(t===i)return!0;if(Array.isArray(t)){if(t.length!==i.length)return!1;for(var n=0,s=t.length;n\n'),t?t(e.join("")):e.join("")}}),i.Line.ATTRIBUTE_NAMES=i.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" ")),i.Line.fromElement=function(t,e,n){n=n||{};var s=i.parseAttributes(t,i.Line.ATTRIBUTE_NAMES),o=[s.x1||0,s.y1||0,s.x2||0,s.y2||0];e(new i.Line(o,r(s,n)))},i.Line.fromObject=function(t,e){var r=n(t,!0);r.points=[t.x1,t.y1,t.x2,t.y2],i.Object._fromObject("Line",r,function(t){delete t.points,e&&e(t)},"points")})}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=Math.PI;e.Circle?e.warn("fabric.Circle is already defined."):(e.Circle=e.util.createClass(e.Object,{type:"circle",radius:0,startAngle:0,endAngle:2*i,cacheProperties:e.Object.prototype.cacheProperties.concat("radius"),_set:function(t,e){return this.callSuper("_set",t,e),"radius"===t&&this.setRadius(e),this},toObject:function(t){return this.callSuper("toObject",["radius","startAngle","endAngle"].concat(t))},toSVG:function(t){var e=this._createBaseSVGMarkup(),r=(this.endAngle-this.startAngle)%(2*i);if(0===r)e.push("\n");else{var n=Math.cos(this.startAngle)*this.radius,s=Math.sin(this.startAngle)*this.radius,o=Math.cos(this.endAngle)*this.radius,a=Math.sin(this.endAngle)*this.radius,h=r>i?"1":"0";e.push('\n')}return t?t(e.join("")):e.join("")},_render:function(t){t.beginPath(),t.arc(0,0,this.radius,this.startAngle,this.endAngle,!1),this._renderPaintInOrder(t)},getRadiusX:function(){return this.get("radius")*this.get("scaleX")},getRadiusY:function(){return this.get("radius")*this.get("scaleY")},setRadius:function(t){return this.radius=t,this.set("width",2*t).set("height",2*t)}}),e.Circle.ATTRIBUTE_NAMES=e.SHARED_ATTRIBUTES.concat("cx cy r".split(" ")),e.Circle.fromElement=function(t,i){var r=e.parseAttributes(t,e.Circle.ATTRIBUTE_NAMES);if(!function(t){return"radius"in t&&t.radius>=0}(r))throw new Error("value of `r` attribute is required and can not be negative");r.left=(r.left||0)-r.radius,r.top=(r.top||0)-r.radius,i(new e.Circle(r))},e.Circle.fromObject=function(t,i){return e.Object._fromObject("Circle",t,i)})}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={});e.Triangle?e.warn("fabric.Triangle is already defined"):(e.Triangle=e.util.createClass(e.Object,{type:"triangle",width:100,height:100,_render:function(t){var e=this.width/2,i=this.height/2;t.beginPath(),t.moveTo(-e,i),t.lineTo(0,-i),t.lineTo(e,i),t.closePath(),this._renderPaintInOrder(t)},_renderDashedStroke:function(t){var i=this.width/2,r=this.height/2;t.beginPath(),e.util.drawDashedLine(t,-i,r,0,-r,this.strokeDashArray),e.util.drawDashedLine(t,0,-r,i,r,this.strokeDashArray),e.util.drawDashedLine(t,i,r,-i,r,this.strokeDashArray),t.closePath()},toSVG:function(t){var e=this._createBaseSVGMarkup(),i=this.width/2,r=this.height/2,n=[-i+" "+r,"0 "+-r,i+" "+r].join(",");return e.push(""),t?t(e.join("")):e.join("")}}),e.Triangle.fromObject=function(t,i){return e.Object._fromObject("Triangle",t,i)})}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=2*Math.PI;e.Ellipse?e.warn("fabric.Ellipse is already defined."):(e.Ellipse=e.util.createClass(e.Object,{type:"ellipse",rx:0,ry:0,cacheProperties:e.Object.prototype.cacheProperties.concat("rx","ry"),initialize:function(t){this.callSuper("initialize",t),this.set("rx",t&&t.rx||0),this.set("ry",t&&t.ry||0)},_set:function(t,e){switch(this.callSuper("_set",t,e),t){case"rx":this.rx=e,this.set("width",2*e);break;case"ry":this.ry=e,this.set("height",2*e)}return this},getRx:function(){return this.get("rx")*this.get("scaleX")},getRy:function(){return this.get("ry")*this.get("scaleY")},toObject:function(t){return this.callSuper("toObject",["rx","ry"].concat(t))},toSVG:function(t){var e=this._createBaseSVGMarkup();return e.push("\n"),t?t(e.join("")):e.join("")},_render:function(t){t.beginPath(),t.save(),t.transform(1,0,0,this.ry/this.rx,0,0),t.arc(0,0,this.rx,0,i,!1),t.restore(),this._renderPaintInOrder(t)}}),e.Ellipse.ATTRIBUTE_NAMES=e.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" ")),e.Ellipse.fromElement=function(t,i){var r=e.parseAttributes(t,e.Ellipse.ATTRIBUTE_NAMES);r.left=(r.left||0)-r.rx,r.top=(r.top||0)-r.ry,i(new e.Ellipse(r))},e.Ellipse.fromObject=function(t,i){return e.Object._fromObject("Ellipse",t,i)})}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend;e.Rect?e.warn("fabric.Rect is already defined"):(e.Rect=e.util.createClass(e.Object,{stateProperties:e.Object.prototype.stateProperties.concat("rx","ry"),type:"rect",rx:0,ry:0,cacheProperties:e.Object.prototype.cacheProperties.concat("rx","ry"),initialize:function(t){this.callSuper("initialize",t),this._initRxRy()},_initRxRy:function(){this.rx&&!this.ry?this.ry=this.rx:this.ry&&!this.rx&&(this.rx=this.ry)},_render:function(t){if(1!==this.width||1!==this.height){var e=this.rx?Math.min(this.rx,this.width/2):0,i=this.ry?Math.min(this.ry,this.height/2):0,r=this.width,n=this.height,s=-this.width/2,o=-this.height/2,a=0!==e||0!==i,h=.4477152502;t.beginPath(),t.moveTo(s+e,o),t.lineTo(s+r-e,o),a&&t.bezierCurveTo(s+r-h*e,o,s+r,o+h*i,s+r,o+i),t.lineTo(s+r,o+n-i),a&&t.bezierCurveTo(s+r,o+n-h*i,s+r-h*e,o+n,s+r-e,o+n),t.lineTo(s+e,o+n),a&&t.bezierCurveTo(s+h*e,o+n,s,o+n-h*i,s,o+n-i),t.lineTo(s,o+i),a&&t.bezierCurveTo(s,o+h*i,s+h*e,o,s+e,o),t.closePath(),this._renderPaintInOrder(t)}else t.fillRect(-.5,-.5,1,1)},_renderDashedStroke:function(t){var i=-this.width/2,r=-this.height/2,n=this.width,s=this.height;t.beginPath(),e.util.drawDashedLine(t,i,r,i+n,r,this.strokeDashArray),e.util.drawDashedLine(t,i+n,r,i+n,r+s,this.strokeDashArray),e.util.drawDashedLine(t,i+n,r+s,i,r+s,this.strokeDashArray),e.util.drawDashedLine(t,i,r+s,i,r,this.strokeDashArray),t.closePath()},toObject:function(t){return this.callSuper("toObject",["rx","ry"].concat(t))},toSVG:function(t){var e=this._createBaseSVGMarkup(),i=-this.width/2,r=-this.height/2;return e.push("\n"),t?t(e.join("")):e.join("")}}),e.Rect.ATTRIBUTE_NAMES=e.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" ")),e.Rect.fromElement=function(t,r,n){if(!t)return r(null);n=n||{};var s=e.parseAttributes(t,e.Rect.ATTRIBUTE_NAMES);s.left=s.left||0,s.top=s.top||0;var o=new e.Rect(i(n?e.util.object.clone(n):{},s));o.visible=o.visible&&o.width>0&&o.height>0,r(o)},e.Rect.fromObject=function(t,i){return e.Object._fromObject("Rect",t,i)})}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.object.extend,r=e.util.array.min,n=e.util.array.max,s=e.util.toFixed;e.Polyline?e.warn("fabric.Polyline is already defined"):(e.Polyline=e.util.createClass(e.Object,{type:"polyline",points:null,cacheProperties:e.Object.prototype.cacheProperties.concat("points"),initialize:function(t,e){e=e||{},this.points=t||[],this.callSuper("initialize",e);var i=this._calcDimensions();void 0===e.left&&(this.left=i.left),void 0===e.top&&(this.top=i.top),this.width=i.width,this.height=i.height,this.pathOffset={x:i.left+this.width/2,y:i.top+this.height/2}},_calcDimensions:function(){var t=this.points,e=r(t,"x")||0,i=r(t,"y")||0;return{left:e,top:i,width:(n(t,"x")||0)-e,height:(n(t,"y")||0)-i}},toObject:function(t){return i(this.callSuper("toObject",t),{points:this.points.concat()})},toSVG:function(t){for(var i=[],r=this.pathOffset.x,n=this.pathOffset.y,o=this._createBaseSVGMarkup(),a=e.Object.NUM_FRACTION_DIGITS,h=0,c=this.points.length;h\n"),t?t(o.join("")):o.join("")},commonRender:function(t){var e,i=this.points.length,r=this.pathOffset.x,n=this.pathOffset.y;if(!i||isNaN(this.points[i-1].y))return!1;t.beginPath(),t.moveTo(this.points[0].x-r,this.points[0].y-n);for(var s=0;s"},toObject:function(t){return n(this.callSuper("toObject",t),{path:this.path.map(function(t){return t.slice()}),top:this.top,left:this.left})},toDatalessObject:function(t){var e=this.toObject(["sourcePath"].concat(t));return e.sourcePath&&delete e.path,e},toSVG:function(t){for(var e=[],i=this._createBaseSVGMarkup(),r="",n=0,s=this.path.length;n\n"),t?t(i.join("")):i.join("")},complexity:function(){return this.path.length},_parsePath:function(){for(var t,e,i,r,n,s=[],o=[],c=/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/gi,l=0,u=this.path.length;lp)for(var m=1,b=n.length;m"},addWithUpdate:function(t){return this._restoreObjectsState(),e.util.resetObjectTransform(this),t&&(this._objects.push(t),t.group=this,t._set("canvas",this.canvas)),this._calcBounds(),this._updateObjectsCoords(),this.setCoords(),this.dirty=!0,this},removeWithUpdate:function(t){return this._restoreObjectsState(),e.util.resetObjectTransform(this),this.remove(t),this._calcBounds(),this._updateObjectsCoords(),this.setCoords(),this.dirty=!0,this},_onObjectAdded:function(t){this.dirty=!0,t.group=this,t._set("canvas",this.canvas)},_onObjectRemoved:function(t){this.dirty=!0,delete t.group},_set:function(t,e){var i=this._objects.length;if(this.useSetOnGroup)for(;i--;)this._objects[i].setOnGroup(t,e);if("canvas"===t)for(i=this._objects.length;i--;)this._objects[i]._set(t,e);this.callSuper("_set",t,e)},toObject:function(t){var e=this.getObjects().map(function(e){var i=e.includeDefaultValues;e.includeDefaultValues=e.group.includeDefaultValues;var r=e.toObject(t);return e.includeDefaultValues=i,r});return i(this.callSuper("toObject",t),{objects:e})},toDatalessObject:function(t){var e,r=this.sourcePath;return e=r||this.getObjects().map(function(e){var i=e.includeDefaultValues;e.includeDefaultValues=e.group.includeDefaultValues;var r=e.toDatalessObject(t);return e.includeDefaultValues=i,r}),i(this.callSuper("toDatalessObject",t),{objects:e})},render:function(t){this._transformDone=!0,this.callSuper("render",t),this._transformDone=!1},shouldCache:function(){var t=this.objectCaching&&(!this.group||this.needsItsOwnCache()||!this.group.isOnACache());if(this.ownCaching=t,t)for(var e=0,i=this._objects.length;e\n');for(var i=0,r=this._objects.length;i\n"),t?t(e.join("")):e.join("")}}),e.Group.fromObject=function(t,i){e.util.enlivenObjects(t.objects,function(r){var n=e.util.object.clone(t,!0);delete n.objects,i&&i(new e.Group(r,n,!0))})})}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={});e.ActiveSelection||(e.ActiveSelection=e.util.createClass(e.Group,{type:"activeSelection",initialize:function(t,i){i=i||{},this._objects=t||[];for(var r=this._objects.length;r--;)this._objects[r].group=this;i.originX&&(this.originX=i.originX),i.originY&&(this.originY=i.originY),this._calcBounds(),this._updateObjectsCoords(),e.Object.prototype.initialize.call(this,i),this.setCoords()},toGroup:function(){var t=this._objects;this._objects=[];var i=this.toObject(),r=new e.Group([]);if(delete i.objects,r.set(i),r.type="group",t.forEach(function(t){t.group=r,t.canvas.remove(t)}),r._objects=t,!this.canvas)return r;var n=this.canvas;return n.add(r),n._activeObject=r,r.setCoords(),r},onDeselect:function(){return this.destroy(),!1},toString:function(){return"#"},_set:function(t,i){var r=this._objects.length;if("canvas"===t)for(;r--;)this._objects[r].set(t,i);if(this.useSetOnGroup)for(;r--;)this._objects[r].setOnGroup(t,i);e.Object.prototype._set.call(this,t,i)},shouldCache:function(){return!1},willDrawShadow:function(){if(this.shadow)return this.callSuper("willDrawShadow");for(var t=0,e=this._objects.length;t\n');var n=["\t\n'];if("fill"===this.paintFirst&&Array.prototype.push.apply(e,n),this.stroke||this.strokeDashArray){var s=this.fill;this.fill=null,e.push("\t\n'),this.fill=s}return"fill"!==this.paintFirst&&Array.prototype.push.apply(e,n),e.push("\n"),t?t(e.join("")):e.join("")},getSrc:function(t){var e=t?this._element:this._originalElement;return e?e.toDataURL?e.toDataURL():e.src:this.src||""},setSrc:function(t,e,i){return fabric.util.loadImage(t,function(t){this.setElement(t,i),e(this)},this,i&&i.crossOrigin),this},toString:function(){return'#'},applyResizeFilters:function(){var t=this.resizeFilter,e=this.canvas?this.canvas.getRetinaScaling():1,i=this.minimumScaleTrigger,r=this.scaleX*e,n=this.scaleY*e,s=this._filteredEl||this._originalElement;if(!t||r>i&&n>i)return this._element=s,this._filterScalingX=1,void(this._filterScalingY=1);fabric.filterBackend||(fabric.filterBackend=fabric.initFilterBackend());var o=fabric.util.createCanvasElement(),a=this._filteredEl?this.cacheKey:this.cacheKey+"_filtered",h=s.width,c=s.height;o.width=h,o.height=c,this._element=o,t.scaleX=r,t.scaleY=n,fabric.filterBackend.applyFilters([t],s,h,c,this._element,a),this._filterScalingX=o.width/this._originalElement.width,this._filterScalingY=o.height/this._originalElement.height},applyFilters:function(t){if(t=t||this.filters||[],0===(t=t.filter(function(t){return t})).length)return this._element=this._originalElement,this._filteredEl=null,this._filterScalingX=1,this._filterScalingY=1,this;var e=this._originalElement,i=e.naturalWidth||e.width,r=e.naturalHeight||e.height;if(this._element===this._originalElement){var n=fabric.util.createCanvasElement();n.width=i,n.height=r,this._element=n,this._filteredEl=n}else this._element.getContext("2d").clearRect(0,0,i,r);return fabric.filterBackend||(fabric.filterBackend=fabric.initFilterBackend()),fabric.filterBackend.applyFilters(t,this._originalElement,i,r,this._element,this.cacheKey),this._originalElement.width===this._element.width&&this._originalElement.height===this._element.height||(this._filterScalingX=this._element.width/this._originalElement.width,this._filterScalingY=this._element.height/this._originalElement.height),this},_render:function(t){!1===this.isMoving&&this.resizeFilter&&this._needsResize()&&(this._lastScaleX=this.scaleX,this._lastScaleY=this.scaleY,this.applyResizeFilters()),this._stroke(t),this._renderPaintInOrder(t)},_renderFill:function(t){var e=this.width,i=this.height,r=e*this._filterScalingX,n=i*this._filterScalingY,s=-e/2,o=-i/2,a=this._element;a&&t.drawImage(a,this.cropX*this._filterScalingX,this.cropY*this._filterScalingY,r,n,s,o,e,i)},_needsResize:function(){return this.scaleX!==this._lastScaleX||this.scaleY!==this._lastScaleY},_resetWidthHeight:function(){var t=this.getElement();this.set("width",t.width),this.set("height",t.height)},_initElement:function(t,e){this.setElement(fabric.util.getById(t),e),fabric.util.addClass(this.getElement(),fabric.Image.CSS_CANVAS)},_initConfig:function(t){t||(t={}),this.setOptions(t),this._setWidthHeight(t),this._element&&this.crossOrigin&&(this._element.crossOrigin=this.crossOrigin)},_initFilters:function(t,e){t&&t.length?fabric.util.enlivenObjects(t,function(t){e&&e(t)},"fabric.Image.filters"):e&&e()},_setWidthHeight:function(t){this.width="width"in t?t.width:this.getElement()?this.getElement().width||0:0,this.height="height"in t?t.height:this.getElement()?this.getElement().height||0:0},parsePreserveAspectRatioAttribute:function(){var t,e=fabric.util.parsePreserveAspectRatioAttribute(this.preserveAspectRatio||""),i=this._element.width,r=this._element.height,n=1,s=1,o=0,a=0,h=0,c=0,l=this.width,u=this.height,f={width:l,height:u};return!e||"none"===e.alignX&&"none"===e.alignY?(n=l/i,s=u/r):("meet"===e.meetOrSlice&&(t=(l-i*(n=s=fabric.util.findScaleToFit(this._element,f)))/2,"Min"===e.alignX&&(o=-t),"Max"===e.alignX&&(o=t),t=(u-r*s)/2,"Min"===e.alignY&&(a=-t),"Max"===e.alignY&&(a=t)),"slice"===e.meetOrSlice&&(t=i-l/(n=s=fabric.util.findScaleToCover(this._element,f)),"Mid"===e.alignX&&(h=t/2),"Max"===e.alignX&&(h=t),t=r-u/s,"Mid"===e.alignY&&(c=t/2),"Max"===e.alignY&&(c=t),i=l/n,r=u/s)),{width:i,height:r,scaleX:n,scaleY:s,offsetLeft:o,offsetTop:a,cropX:h,cropY:c}}}),fabric.Image.CSS_CANVAS="canvas-img",fabric.Image.prototype.getSvgSrc=fabric.Image.prototype.getSrc,fabric.Image.fromObject=function(t,e){var i=fabric.util.object.clone(t);fabric.util.loadImage(i.src,function(t,r){r?e&&e(null,r):fabric.Image.prototype._initFilters.call(i,i.filters,function(r){i.filters=r||[],fabric.Image.prototype._initFilters.call(i,[i.resizeFilter],function(r){i.resizeFilter=r[0];var n=new fabric.Image(t,i);e(n)})})},null,i.crossOrigin)},fabric.Image.fromURL=function(t,e,i){fabric.util.loadImage(t,function(t){e&&e(new fabric.Image(t,i))},null,i&&i.crossOrigin)},fabric.Image.ATTRIBUTE_NAMES=fabric.SHARED_ATTRIBUTES.concat("x y width height preserveAspectRatio xlink:href crossOrigin".split(" ")),fabric.Image.fromElement=function(t,i,r){var n=fabric.parseAttributes(t,fabric.Image.ATTRIBUTE_NAMES);fabric.Image.fromURL(n["xlink:href"],i,e(r?fabric.util.object.clone(r):{},n))})}("undefined"!=typeof exports?exports:this),fabric.util.object.extend(fabric.Object.prototype,{_getAngleValueForStraighten:function(){var t=this.angle%360;return t>0?90*Math.round((t-1)/90):90*Math.round(t/90)},straighten:function(){return this.rotate(this._getAngleValueForStraighten()),this},fxStraighten:function(t){var e=function(){},i=(t=t||{}).onComplete||e,r=t.onChange||e,n=this;return fabric.util.animate({startValue:this.get("angle"),endValue:this._getAngleValueForStraighten(),duration:this.FX_DURATION,onChange:function(t){n.rotate(t),r()},onComplete:function(){n.setCoords(),i()}}),this}}),fabric.util.object.extend(fabric.StaticCanvas.prototype,{straightenObject:function(t){return t.straighten(),this.requestRenderAll(),this},fxStraightenObject:function(t){return t.fxStraighten({onChange:this.requestRenderAllBound}),this}}),function(){"use strict";function t(t,e){var i="precision "+e+" float;\nvoid main(){}",r=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(r,i),t.compileShader(r),!!t.getShaderParameter(r,t.COMPILE_STATUS)}function e(t){t&&t.tileSize&&(this.tileSize=t.tileSize),this.setupGLContext(this.tileSize,this.tileSize),this.captureGPUInfo()}fabric.isWebglSupported=function(e){if(fabric.isLikelyNode)return!1;e=e||fabric.WebglFilterBackend.prototype.tileSize;var i=document.createElement("canvas"),r=i.getContext("webgl")||i.getContext("experimental-webgl"),n=!1;if(r){fabric.maxTextureSize=r.getParameter(r.MAX_TEXTURE_SIZE),n=fabric.maxTextureSize>=e;for(var s=["highp","mediump","lowp"],o=0;o<3;o++)if(t(r,s[o])){fabric.webGlPrecision=s[o];break}}return this.isSupported=n,n},fabric.WebglFilterBackend=e,e.prototype={tileSize:2048,resources:{},setupGLContext:function(t,e){this.dispose(),this.createWebGLCanvas(t,e),this.aPosition=new Float32Array([0,0,0,1,1,0,1,1]),this.chooseFastestCopyGLTo2DMethod(t,e)},chooseFastestCopyGLTo2DMethod:function(t,e){var i,r=void 0!==window.performance;try{new ImageData(1,1),i=!0}catch(t){i=!1}var n="undefined"!=typeof ArrayBuffer,s="undefined"!=typeof Uint8ClampedArray;if(r&&i&&n&&s){var o,a,h=fabric.util.createCanvasElement(),c=new ArrayBuffer(t*e*4),l={imageBuffer:c,destinationWidth:t,destinationHeight:e,targetCanvas:h};h.width=t,h.height=e,o=window.performance.now(),copyGLTo2DDrawImage.call(l,this.gl,l),a=window.performance.now()-o,o=window.performance.now(),copyGLTo2DPutImageData.call(l,this.gl,l),a>window.performance.now()-o?(this.imageBuffer=c,this.copyGLTo2D=copyGLTo2DPutImageData):this.copyGLTo2D=copyGLTo2DDrawImage}},createWebGLCanvas:function(t,e){var i=fabric.util.createCanvasElement();i.width=t,i.height=e;var r={premultipliedAlpha:!1},n=i.getContext("webgl",r);n||(n=i.getContext("experimental-webgl",r)),n&&(n.clearColor(0,0,0,0),this.canvas=i,this.gl=n)},applyFilters:function(t,e,i,r,n,s){var o,a=this.gl;s&&(o=this.getCachedTexture(s,e));var h={originalWidth:e.width||e.originalWidth,originalHeight:e.height||e.originalHeight,sourceWidth:i,sourceHeight:r,destinationWidth:i,destinationHeight:r,context:a,sourceTexture:this.createTexture(a,i,r,!o&&e),targetTexture:this.createTexture(a,i,r),originalTexture:o||this.createTexture(a,i,r,!o&&e),passes:t.length,webgl:!0,aPosition:this.aPosition,programCache:this.programCache,pass:0,filterBackend:this,targetCanvas:n},c=a.createFramebuffer();return a.bindFramebuffer(a.FRAMEBUFFER,c),t.forEach(function(t){t&&t.applyTo(h)}),resizeCanvasIfNeeded(h),this.copyGLTo2D(a,h),a.bindTexture(a.TEXTURE_2D,null),a.deleteTexture(h.sourceTexture),a.deleteTexture(h.targetTexture),a.deleteFramebuffer(c),n.getContext("2d").setTransform(1,0,0,1,0,0),h},applyFiltersDebug:function(t,e,i,r,n,s){var o=this.gl,a=this.applyFilters(t,e,i,r,n,s),h=o.getError();if(h!==o.NO_ERROR){var c=this.glErrorToString(o,h),l=new Error("WebGL Error "+c);throw l.glErrorCode=h,l}return a},glErrorToString:function(t,e){if(!t)return"Context undefined for error code: "+e;if("number"!=typeof e)return"Error code is not a number";switch(e){case t.NO_ERROR:return"NO_ERROR";case t.INVALID_ENUM:return"INVALID_ENUM";case t.INVALID_VALUE:return"INVALID_VALUE";case t.INVALID_OPERATION:return"INVALID_OPERATION";case t.INVALID_FRAMEBUFFER_OPERATION:return"INVALID_FRAMEBUFFER_OPERATION";case t.OUT_OF_MEMORY:return"OUT_OF_MEMORY";case t.CONTEXT_LOST_WEBGL:return"CONTEXT_LOST_WEBGL";default:return"UNKNOWN_ERROR"}},dispose:function(){this.canvas&&(this.canvas=null,this.gl=null),this.clearWebGLCaches()},clearWebGLCaches:function(){this.programCache={},this.textureCache={}},createTexture:function(t,e,i,r){var n=t.createTexture();return t.bindTexture(t.TEXTURE_2D,n),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),r?t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,r):t.texImage2D(t.TEXTURE_2D,0,t.RGBA,e,i,0,t.RGBA,t.UNSIGNED_BYTE,null),n},getCachedTexture:function(t,e){if(this.textureCache[t])return this.textureCache[t];var i=this.createTexture(this.gl,e.width,e.height,e);return this.textureCache[t]=i,i},evictCachesForKey:function(t){this.textureCache[t]&&(this.gl.deleteTexture(this.textureCache[t]),delete this.textureCache[t])},copyGLTo2D:copyGLTo2DDrawImage,captureGPUInfo:function(){if(this.gpuInfo)return this.gpuInfo;var t=this.gl,e=t.getExtension("WEBGL_debug_renderer_info"),i={renderer:"",vendor:""};if(e){var r=t.getParameter(e.UNMASKED_RENDERER_WEBGL),n=t.getParameter(e.UNMASKED_VENDOR_WEBGL);r&&(i.renderer=r.toLowerCase()),n&&(i.vendor=n.toLowerCase())}return this.gpuInfo=i,i}}}(),function(){"use strict";function t(){}var e=function(){};fabric.Canvas2dFilterBackend=t,t.prototype={evictCachesForKey:e,dispose:e,clearWebGLCaches:e,resources:{},applyFilters:function(t,e,i,r,n){var s=n.getContext("2d");s.drawImage(e,0,0,i,r);var o={sourceWidth:i,sourceHeight:r,imageData:s.getImageData(0,0,i,r),originalEl:e,originalImageData:s.getImageData(0,0,i,r),canvasEl:n,ctx:s,filterBackend:this};return t.forEach(function(t){t.applyTo(o)}),o.imageData.width===i&&o.imageData.height===r||(n.width=o.imageData.width,n.height=o.imageData.height),s.putImageData(o.imageData,0,0),o}}}(),fabric.Image.filters=fabric.Image.filters||{},fabric.Image.filters.BaseFilter=fabric.util.createClass({type:"BaseFilter",vertexSource:"attribute vec2 aPosition;\nvarying vec2 vTexCoord;\nvoid main() {\nvTexCoord = aPosition;\ngl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\n}",fragmentSource:"precision highp float;\nvarying vec2 vTexCoord;\nuniform sampler2D uTexture;\nvoid main() {\ngl_FragColor = texture2D(uTexture, vTexCoord);\n}",initialize:function(t){t&&this.setOptions(t)},setOptions:function(t){for(var e in t)this[e]=t[e]},createProgram:function(t,e,i){e=e||this.fragmentSource,i=i||this.vertexSource,"highp"!==fabric.webGlPrecision&&(e=e.replace(/precision highp float/g,"precision "+fabric.webGlPrecision+" float"));var r=t.createShader(t.VERTEX_SHADER);if(t.shaderSource(r,i),t.compileShader(r),!t.getShaderParameter(r,t.COMPILE_STATUS))throw new Error("Vertex shader compile error for "+this.type+": "+t.getShaderInfoLog(r));var n=t.createShader(t.FRAGMENT_SHADER);if(t.shaderSource(n,e),t.compileShader(n),!t.getShaderParameter(n,t.COMPILE_STATUS))throw new Error("Fragment shader compile error for "+this.type+": "+t.getShaderInfoLog(n));var s=t.createProgram();if(t.attachShader(s,r),t.attachShader(s,n),t.linkProgram(s),!t.getProgramParameter(s,t.LINK_STATUS))throw new Error('Shader link error for "${this.type}" '+t.getProgramInfoLog(s));var o=this.getAttributeLocations(t,s),a=this.getUniformLocations(t,s)||{};return a.uStepW=t.getUniformLocation(s,"uStepW"),a.uStepH=t.getUniformLocation(s,"uStepH"),{program:s,attributeLocations:o,uniformLocations:a}},getAttributeLocations:function(t,e){return{aPosition:t.getAttribLocation(e,"aPosition")}},getUniformLocations:function(){return{}},sendAttributeData:function(t,e,i){var r=e.aPostion,n=t.createBuffer();t.bindBuffer(t.ARRAY_BUFFER,n),t.enableVertexAttribArray(r),t.vertexAttribPointer(r,2,t.FLOAT,!1,0,0),t.bufferData(t.ARRAY_BUFFER,i,t.STATIC_DRAW)},_setupFrameBuffer:function(t){var e,i,r=t.context;t.passes>1?(e=t.destinationWidth,i=t.destinationHeight,t.sourceWidth===e&&t.sourceHeight===i||(r.deleteTexture(t.targetTexture),t.targetTexture=t.filterBackend.createTexture(r,e,i)),r.framebufferTexture2D(r.FRAMEBUFFER,r.COLOR_ATTACHMENT0,r.TEXTURE_2D,t.targetTexture,0)):(r.bindFramebuffer(r.FRAMEBUFFER,null),r.finish())},_swapTextures:function(t){t.passes--,t.pass++;var e=t.targetTexture;t.targetTexture=t.sourceTexture,t.sourceTexture=e},isNeutralState:function(){return!1},applyTo:function(t){if(t.webgl){if(t.passes>1&&this.isNeutralState(t))return;this._setupFrameBuffer(t),this.applyToWebGL(t),this._swapTextures(t)}else this.isNeutralState()||this.applyTo2d(t)},retrieveShader:function(t){return t.programCache.hasOwnProperty(this.type)||(t.programCache[this.type]=this.createProgram(t.context)),t.programCache[this.type]},applyToWebGL:function(t){var e=t.context,i=this.retrieveShader(t);0===t.pass&&t.originalTexture?e.bindTexture(e.TEXTURE_2D,t.originalTexture):e.bindTexture(e.TEXTURE_2D,t.sourceTexture),e.useProgram(i.program),this.sendAttributeData(e,i.attributeLocations,t.aPosition),e.uniform1f(i.uniformLocations.uStepW,1/t.sourceWidth),e.uniform1f(i.uniformLocations.uStepH,1/t.sourceHeight),this.sendUniformData(e,i.uniformLocations),e.viewport(0,0,t.destinationWidth,t.destinationHeight),e.drawArrays(e.TRIANGLE_STRIP,0,4)},bindAdditionalTexture:function(t,e,i){t.activeTexture(i),t.bindTexture(t.TEXTURE_2D,e),t.activeTexture(t.TEXTURE0)},unbindAdditionalTexture:function(t,e){t.activeTexture(e),t.bindTexture(t.TEXTURE_2D,null),t.activeTexture(t.TEXTURE0)},getMainParameter:function(){return this[this.mainParameter]},setMainParameter:function(t){this[this.mainParameter]=t},sendUniformData:function(){},createHelpLayer:function(t){if(!t.helpLayer){var e=document.createElement("canvas");e.width=t.sourceWidth,e.height=t.sourceHeight,t.helpLayer=e}},toObject:function(){var t={type:this.type},e=this.mainParameter;return e&&(t[e]=this[e]),t},toJSON:function(){return this.toObject()}}),fabric.Image.filters.BaseFilter.fromObject=function(t,e){var i=new fabric.Image.filters[t.type](t);return e&&e(i),i},function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.Image.filters,r=e.util.createClass;i.ColorMatrix=r(i.BaseFilter,{type:"ColorMatrix",fragmentSource:"precision highp float;\nuniform sampler2D uTexture;\nvarying vec2 vTexCoord;\nuniform mat4 uColorMatrix;\nuniform vec4 uConstants;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\ncolor *= uColorMatrix;\ncolor += uConstants;\ngl_FragColor = color;\n}",matrix:[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0],mainParameter:"matrix",colorsOnly:!0,initialize:function(t){this.callSuper("initialize",t),this.matrix=this.matrix.slice(0)},isNeutralState:function(){for(var t=i.ColorMatrix,e=20;e--;)if(this.matrix[e]!==t.prototype.matrix[e])return!1;return!0},applyTo2d:function(t){var e,i,r,n,s,o=t.imageData.data,a=o.length,h=this.matrix,c=this.colorsOnly;for(s=0;sy||o<0||o>_||(h=4*(a*_+o),c=v[d*m+f],e+=p[h]*c,i+=p[h+1]*c,r+=p[h+2]*c,S||(n+=p[h+3]*c));C[s]=e,C[s+1]=i,C[s+2]=r,C[s+3]=S?p[s+3]:n}t.imageData=x},getUniformLocations:function(t,e){return{uMatrix:t.getUniformLocation(e,"uMatrix"),uOpaque:t.getUniformLocation(e,"uOpaque"),uHalfSize:t.getUniformLocation(e,"uHalfSize"),uSize:t.getUniformLocation(e,"uSize")}},sendUniformData:function(t,e){t.uniform1fv(e.uMatrix,this.matrix)},toObject:function(){return i(this.callSuper("toObject"),{opaque:this.opaque,matrix:this.matrix})}}),e.Image.filters.Convolute.fromObject=e.Image.filters.BaseFilter.fromObject}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.Image.filters,r=e.util.createClass;i.Grayscale=r(i.BaseFilter,{type:"Grayscale",fragmentSource:{average:"precision highp float;\nuniform sampler2D uTexture;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nfloat average = (color.r + color.b + color.g) / 3.0;\ngl_FragColor = vec4(average, average, average, color.a);\n}",lightness:"precision highp float;\nuniform sampler2D uTexture;\nuniform int uMode;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 col = texture2D(uTexture, vTexCoord);\nfloat average = (max(max(col.r, col.g),col.b) + min(min(col.r, col.g),col.b)) / 2.0;\ngl_FragColor = vec4(average, average, average, col.a);\n}",luminosity:"precision highp float;\nuniform sampler2D uTexture;\nuniform int uMode;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 col = texture2D(uTexture, vTexCoord);\nfloat average = 0.21 * col.r + 0.72 * col.g + 0.07 * col.b;\ngl_FragColor = vec4(average, average, average, col.a);\n}"},mode:"average",mainParameter:"mode",applyTo2d:function(t){var e,i,r=t.imageData.data,n=r.length,s=this.mode;for(e=0;ec[0]&&n>c[1]&&s>c[2]&&r1&&this.isNeutralState(t))return;t.passes++,this.width=t.sourceWidth,this.horizontal=!0,this.dW=Math.round(this.width*this.scaleX),this.dH=t.sourceHeight,this.tempScale=this.dW/this.width,this.taps=this.getTaps(),t.destinationWidth=this.dW,this._setupFrameBuffer(t),this.applyToWebGL(t),this._swapTextures(t),t.sourceWidth=t.destinationWidth,this.height=t.sourceHeight,this.horizontal=!1,this.dH=Math.round(this.height*this.scaleY),this.tempScale=this.dH/this.height,this.taps=this.getTaps(),t.destinationHeight=this.dH,this._setupFrameBuffer(t),this.applyToWebGL(t),this._swapTextures(t),t.sourceHeight=t.destinationHeight}else this.isNeutralState(t)||this.applyTo2d(t)},isNeutralState:function(t){var e=t.scaleX||this.scaleX,i=t.scaleY||this.scaleY;return 1===e&&1===i},lanczosCreate:function(t){return function(e){if(e>=t||e<=-t)return 0;if(e<1.1920929e-7&&e>-1.1920929e-7)return 1;var i=(e*=Math.PI)/t;return a(e)/e*a(i)/i}},applyTo2d:function(t){var e=t.imageData,i=this.scaleX,r=this.scaleY;this.rcpScaleX=1/i,this.rcpScaleY=1/r;var n,s=e.width,a=e.height,h=o(s*i),c=o(a*r);"sliceHack"===this.resizeType?n=this.sliceByTwo(t,s,a,h,c):"hermite"===this.resizeType?n=this.hermiteFastResize(t,s,a,h,c):"bilinear"===this.resizeType?n=this.bilinearFiltering(t,s,a,h,c):"lanczos"===this.resizeType&&(n=this.lanczosResize(t,s,a,h,c)),t.imageData=n},sliceByTwo:function(t,i,n,s,o){var a,h,c=t.imageData,l=!1,u=!1,f=.5*i,d=.5*n,g=e.filterBackend.resources,p=0,v=0,m=i,b=0;for(g.sliceByTwo||(g.sliceByTwo=document.createElement("canvas")),((a=g.sliceByTwo).width<1.5*i||a.height=e)){P=r(1e3*s(w-C.x)),x[P]||(x[P]={});for(var F=S.y-y;F<=S.y+y;F++)F<0||F>=o||(M=r(1e3*s(F-C.y)),x[P][M]||(x[P][M]=g(n(i(P*m,2)+i(M*b,2))/1e3)),(T=x[P][M])>0&&(k+=T,D+=T*u[O=4*(F*e+w)],j+=T*u[O+1],E+=T*u[O+2],A+=T*u[O+3]))}d[O=4*(h*a+t)]=D/k,d[O+1]=j/k,d[O+2]=E/k,d[O+3]=A/k}return++t1&&M<-1||(_=2*M*M*M-3*M*M+1)>0&&(T+=_*d[(P=4*(A+k*e))+3],x+=_,d[P+3]<255&&(_=_*d[P+3]/250),C+=_*d[P],S+=_*d[P+1],w+=_*d[P+2],y+=_)}p[b]=C/y,p[b+1]=S/y,p[b+2]=w/y,p[b+3]=T/x}return g},toObject:function(){return{type:this.type,scaleX:this.scaleX,scaleY:this.scaleY,resizeType:this.resizeType,lanczosLobes:this.lanczosLobes}}}),e.Image.filters.Resize.fromObject=e.Image.filters.BaseFilter.fromObject}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.Image.filters,r=e.util.createClass;i.Contrast=r(i.BaseFilter,{type:"Contrast",fragmentSource:"precision highp float;\nuniform sampler2D uTexture;\nuniform float uContrast;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nfloat contrastF = 1.015 * (uContrast + 1.0) / (1.0 * (1.015 - uContrast));\ncolor.rgb = contrastF * (color.rgb - 0.5) + 0.5;\ngl_FragColor = color;\n}",contrast:0,mainParameter:"contrast",applyTo2d:function(t){if(0!==this.contrast){var e,i=t.imageData.data,r=i.length,n=Math.floor(255*this.contrast),s=259*(n+255)/(255*(259-n));for(e=0;e1&&(e=1/this.aspectRatio):this.aspectRatio<1&&(e=this.aspectRatio),t=e*this.blur*.12,this.horizontal?i[0]=t:i[1]=t,i}}),i.Blur.fromObject=e.Image.filters.BaseFilter.fromObject}("undefined"!=typeof exports?exports:this),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.Image.filters,r=e.util.createClass;i.Gamma=r(i.BaseFilter,{type:"Gamma",fragmentSource:"precision highp float;\nuniform sampler2D uTexture;\nuniform vec3 uGamma;\nvarying vec2 vTexCoord;\nvoid main() {\nvec4 color = texture2D(uTexture, vTexCoord);\nvec3 correction = (1.0 / uGamma);\ncolor.r = pow(color.r, correction.r);\ncolor.g = pow(color.g, correction.g);\ncolor.b = pow(color.b, correction.b);\ngl_FragColor = color;\ngl_FragColor.rgb *= color.a;\n}",gamma:[1,1,1],mainParameter:"gamma",applyTo2d:function(t){var e,i=t.imageData.data,r=this.gamma,n=i.length,s=1/r[0],o=1/r[1],a=1/r[2];for(this.rVals||(this.rVals=new Uint8Array(256),this.gVals=new Uint8Array(256),this.bVals=new Uint8Array(256)),e=0,n=256;e'},_getCacheCanvasDimensions:function(){var t=this.callSuper("_getCacheCanvasDimensions"),e=this.fontSize;return t.width+=e*t.zoomX,t.height+=e*t.zoomY,t},_render:function(t){this._setTextStyles(t),this._renderTextLinesBackground(t),this._renderTextDecoration(t,"underline"),this._renderText(t),this._renderTextDecoration(t,"overline"),this._renderTextDecoration(t,"linethrough")},_renderText:function(t){"stroke"===this.paintFirst?(this._renderTextStroke(t),this._renderTextFill(t)):(this._renderTextFill(t),this._renderTextStroke(t))},_setTextStyles:function(t,e,i){t.textBaseline="alphabetic",t.font=this._getFontDeclaration(e,i)},calcTextWidth:function(){for(var t=this.getLineWidth(0),e=1,i=this._textLines.length;et&&(t=r)}return t},_renderTextLine:function(t,e,i,r,n,s){this._renderChars(t,e,i,r,n,s)},_renderTextLinesBackground:function(t){if(this.textBackgroundColor||this.styleHas("textBackgroundColor")){for(var e,i,r,n,s,o,a=0,h=t.fillStyle,c=this._getLeftOffset(),l=this._getTopOffset(),u=0,f=0,d=0,g=this._textLines.length;dn)){var d=a-n;h[t]=a,h[c]+=d,n=a}return{width:n*u,kernedWidth:a*u}},getHeightOfChar:function(t,e){return this.getValueOfPropertyAt(t,e,"fontSize")},measureLine:function(t){var e=this._measureLine(t);return 0!==this.charSpacing&&(e.width-=this._getWidthOfCharSpacing()),e.width<0&&(e.width=0),e},_measureLine:function(t){var e,i,r,n,s=0,o=this._textLines[t],a=new Array(o.length);for(this.__charBounds[t]=a,e=0;e0&&!n){var u=this.__charBounds[e][i-1];l.left=u.left+u.width+a.kernedWidth-a.width}return l},getHeightOfLine:function(t){if(this.__lineHeights[t])return this.__lineHeights[t];for(var e=this._textLines[t],i=this.getHeightOfChar(t,0),r=1,n=e.length;ri&&(i=s)}return this.__lineHeights[t]=i*this.lineHeight*this._fontSizeMult,this.__lineHeights[t]},calcTextHeight:function(){for(var t,e=0,i=0,r=this._textLines.length;i0?(t.fillStyle=f,s&&f&&t.fillRect(d+r+o,g+l*(1-this._fontSizeFraction)+this.offsets[e]*this.fontSize,a,this.fontSize/15),o=h.left,a=h.width,s=c,f=u):a+=h.kernedWidth;t.fillStyle=u,c&&u&&t.fillRect(d+r+o,g+l*(1-this._fontSizeFraction)+this.offsets[e]*this.fontSize,a,this.fontSize/15),g+=i}else g+=i;this._removeShadow(t)}},_getFontDeclaration:function(t,i){var r=t||this;return[e.isLikelyNode?r.fontWeight:r.fontStyle,e.isLikelyNode?r.fontStyle:r.fontWeight,i?"200px":r.fontSize+"px",e.isLikelyNode?'"'+r.fontFamily+'"':r.fontFamily].join(" ")},render:function(t){this.visible&&(this.canvas&&this.canvas.skipOffscreen&&!this.group&&!this.isOnScreen()||(this._shouldClearDimensionCache()&&this.initDimensions(),this.callSuper("render",t)))},_splitTextIntoLines:function(t){for(var i=t.split(this._reNewline),r=new Array(i.length),n=["\n"],s=[],o=0;o-1&&(t.underline=!0),t.textDecoration.indexOf("line-through")>-1&&(t.linethrough=!0),t.textDecoration.indexOf("overline")>-1&&(t.overline=!0),delete t.textDecoration)}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,caching:!0,_reSpace:/\s|\n/,_currentCursorOpacity:0,_selectionDirection:null,_abortCursorAnimation:!1,__widthOfSpace:[],inCompositionMode:!1,initialize:function(t,e){this.callSuper("initialize",t,e),this.initBehavior()},setSelectionStart:function(t){t=Math.max(t,0),this._updateAndFire("selectionStart",t)},setSelectionEnd:function(t){t=Math.min(t,this.text.length),this._updateAndFire("selectionEnd",t)},_updateAndFire:function(t,e){this[t]!==e&&(this._fireSelectionChanged(),this[t]=e),this._updateTextarea()},_fireSelectionChanged:function(){this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})},initDimensions:function(){this.isEditing&&this.initDelayedCursor(),this.clearContextTop(),this.callSuper("initDimensions")},render:function(t){this.clearContextTop(),this.callSuper("render",t),this.cursorOffsetCache={},this.renderCursorOrSelection()},_render:function(t){this.callSuper("_render",t)},clearContextTop:function(t){if(this.isEditing&&this.canvas&&this.canvas.contextTop){var e=this.canvas.contextTop,i=this.canvas.viewportTransform;e.save(),e.transform(i[0],i[1],i[2],i[3],i[4],i[5]),this.transform(e),this.transformMatrix&&e.transform.apply(e,this.transformMatrix),this._clearTextArea(e),t||e.restore()}},renderCursorOrSelection:function(){if(this.isEditing&&this.canvas){var t,e=this._getCursorBoundaries();this.canvas&&this.canvas.contextTop?(t=this.canvas.contextTop,this.clearContextTop(!0)):(t=this.canvas.contextContainer).save(),this.selectionStart===this.selectionEnd?this.renderCursor(e,t):this.renderSelection(e,t),t.restore()}},_clearTextArea:function(t){var e=this.width+4,i=this.height+4;t.clearRect(-e/2,-i/2,e,i)},_getCursorBoundaries:function(t){void 0===t&&(t=this.selectionStart);var e=this._getLeftOffset(),i=this._getTopOffset(),r=this._getCursorBoundariesOffsets(t);return{left:e,top:i,leftOffset:r.left,topOffset:r.top}},_getCursorBoundariesOffsets:function(t){if(this.cursorOffsetCache&&"top"in this.cursorOffsetCache)return this.cursorOffsetCache;for(var e,i,r=0,n=0,s=this.get2DCursorLocation(t),o=0;o0?n:0)},this.cursorOffsetCache=i,this.cursorOffsetCache},renderCursor:function(t,e){var i=this.get2DCursorLocation(),r=i.lineIndex,n=i.charIndex>0?i.charIndex-1:0,s=this.getValueOfPropertyAt(r,n,"fontSize"),o=this.scaleX*this.canvas.getZoom(),a=this.cursorWidth/o,h=t.topOffset;h+=(1-this._fontSizeFraction)*this.getHeightOfLine(r)/this.lineHeight-s*(1-this._fontSizeFraction),this.inCompositionMode&&this.renderSelection(t,e),e.fillStyle=this.getValueOfPropertyAt(r,n,"fill"),e.globalAlpha=this.__isMousedown?1:this._currentCursorOpacity,e.fillRect(t.left+t.leftOffset-a/2,h+t.top,a,s)},renderSelection:function(t,e){for(var i=this.inCompositionMode?this.hiddenTextarea.selectionStart:this.selectionStart,r=this.inCompositionMode?this.hiddenTextarea.selectionEnd:this.selectionEnd,n=-1!==this.textAlign.indexOf("justify"),s=this.get2DCursorLocation(i),o=this.get2DCursorLocation(r),a=s.lineIndex,h=o.lineIndex,c=s.charIndex<0?0:s.charIndex,l=o.charIndex<0?0:o.charIndex,u=a;u<=h;u++){var f=this._getLineLeftOffset(u)||0,d=this.getHeightOfLine(u),g=0,p=0,v=0;u===a&&(p=this.__charBounds[a][c].left),u>=a&&u1)&&(d/=this.lineHeight),this.inCompositionMode?(e.fillStyle=this.compositionColor||"black",e.fillRect(t.left+f+p,t.top+t.topOffset+d,v-p,1)):(e.fillStyle=this.selectionColor,e.fillRect(t.left+f+p,t.top+t.topOffset,v-p,d)),t.topOffset+=g}},getCurrentCharFontSize:function(){var t=this._getCurrentCharIndex();return this.getValueOfPropertyAt(t.l,t.c,"fontSize")},getCurrentCharColor:function(){var t=this._getCurrentCharIndex();return this.getValueOfPropertyAt(t.l,t.c,"fill")},_getCurrentCharIndex:function(){var t=this.get2DCursorLocation(this.selectionStart,!0),e=t.charIndex>0?t.charIndex-1:0;return{l:t.lineIndex,c:e}}}),fabric.IText.fromObject=function(e,i){if(t(e),e.styles)for(var r in e.styles)for(var n in e.styles[r])t(e.styles[r][n]);fabric.Object._fromObject("IText",e,i,"text")}}(),function(){var t=fabric.util.object.clone;fabric.util.object.extend(fabric.IText.prototype,{initBehavior:function(){this.initAddedHandler(),this.initRemovedHandler(),this.initCursorSelectionHandlers(),this.initDoubleClickSimulation(),this.mouseMoveHandler=this.mouseMoveHandler.bind(this)},onDeselect:function(t){this.isEditing&&this.exitEditing(),this.selected=!1,fabric.Object.prototype.onDeselect.call(this,t)},initAddedHandler:function(){var t=this;this.on("added",function(){var e=t.canvas;e&&(e._hasITextHandlers||(e._hasITextHandlers=!0,t._initCanvasHandlers(e)),e._iTextInstances=e._iTextInstances||[],e._iTextInstances.push(t))})},initRemovedHandler:function(){var t=this;this.on("removed",function(){var e=t.canvas;e&&(e._iTextInstances=e._iTextInstances||[],fabric.util.removeFromArray(e._iTextInstances,t),0===e._iTextInstances.length&&(e._hasITextHandlers=!1,t._removeCanvasHandlers(e)))})},_initCanvasHandlers:function(t){t._mouseUpITextHandler=function(){t._iTextInstances&&t._iTextInstances.forEach(function(t){t.__isMousedown=!1})}.bind(this),t.on("mouse:up",t._mouseUpITextHandler)},_removeCanvasHandlers:function(t){t.off("mouse:up",t._mouseUpITextHandler)},_tick:function(){this._currentTickState=this._animateCursor(this,1,this.cursorDuration,"_onTickComplete")},_animateCursor:function(t,e,i,r){var n;return n={isAborted:!1,abort:function(){this.isAborted=!0}},t.animate("_currentCursorOpacity",e,{duration:i,onComplete:function(){n.isAborted||t[r]()},onChange:function(){t.canvas&&t.selectionStart===t.selectionEnd&&t.renderCursorOrSelection()},abort:function(){return n.isAborted}}),n},_onTickComplete:function(){var t=this;this._cursorTimeout1&&clearTimeout(this._cursorTimeout1),this._cursorTimeout1=setTimeout(function(){t._currentTickCompleteState=t._animateCursor(t,0,this.cursorDuration/2,"_tick")},100)},initDelayedCursor:function(t){var e=this,i=t?0:this.cursorDelay;this.abortCursorAnimation(),this._currentCursorOpacity=1,this._cursorTimeout2=setTimeout(function(){e._tick()},i)},abortCursorAnimation:function(){var t=this._currentTickState||this._currentTickCompleteState,e=this.canvas;this._currentTickState&&this._currentTickState.abort(),this._currentTickCompleteState&&this._currentTickCompleteState.abort(),clearTimeout(this._cursorTimeout1),clearTimeout(this._cursorTimeout2),this._currentCursorOpacity=0,t&&e&&e.clearContext(e.contextTop||e.contextContainer)},selectAll:function(){return this.selectionStart=0,this.selectionEnd=this._text.length,this._fireSelectionChanged(),this._updateTextarea(),this},getSelectedText:function(){return this._text.slice(this.selectionStart,this.selectionEnd).join("")},findWordBoundaryLeft:function(t){var e=0,i=t-1;if(this._reSpace.test(this._text[i]))for(;this._reSpace.test(this._text[i]);)e++,i--;for(;/\S/.test(this._text[i])&&i>-1;)e++,i--;return t-e},findWordBoundaryRight:function(t){var e=0,i=t;if(this._reSpace.test(this._text[i]))for(;this._reSpace.test(this._text[i]);)e++,i++;for(;/\S/.test(this._text[i])&&i-1;)e++,i--;return t-e},findLineBoundaryRight:function(t){for(var e=0,i=t;!/\n/.test(this._text[i])&&i0&&ithis.__selectionStartOnMouseDown?(this.selectionStart=this.__selectionStartOnMouseDown,this.selectionEnd=e):(this.selectionStart=e,this.selectionEnd=this.__selectionStartOnMouseDown),this.selectionStart===i&&this.selectionEnd===r||(this.restartCursorIfNeeded(),this._fireSelectionChanged(),this._updateTextarea(),this.renderCursorOrSelection()))}},_setEditingProps:function(){this.hoverCursor="text",this.canvas&&(this.canvas.defaultCursor=this.canvas.moveCursor="text"),this.borderColor=this.editingBorderColor,this.hasControls=this.selectable=!1,this.lockMovementX=this.lockMovementY=!0},fromStringToGraphemeSelection:function(t,e,i){var r=i.slice(0,t),n=fabric.util.string.graphemeSplit(r).length;if(t===e)return{selectionStart:n,selectionEnd:n};var s=i.slice(t,e);return{selectionStart:n,selectionEnd:n+fabric.util.string.graphemeSplit(s).length}},fromGraphemeToStringSelection:function(t,e,i){var r=i.slice(0,t).join("").length;if(t===e)return{selectionStart:r,selectionEnd:r};return{selectionStart:r,selectionEnd:r+i.slice(t,e).join("").length}},_updateTextarea:function(){if(this.cursorOffsetCache={},this.hiddenTextarea){if(!this.inCompositionMode){var t=this.fromGraphemeToStringSelection(this.selectionStart,this.selectionEnd,this._text);this.hiddenTextarea.selectionStart=t.selectionStart,this.hiddenTextarea.selectionEnd=t.selectionEnd}this.updateTextareaPosition()}},updateFromTextArea:function(){if(this.hiddenTextarea){this.cursorOffsetCache={},this.text=this.hiddenTextarea.value,this._shouldClearDimensionCache()&&(this.initDimensions(),this.setCoords());var t=this.fromStringToGraphemeSelection(this.hiddenTextarea.selectionStart,this.hiddenTextarea.selectionEnd,this.hiddenTextarea.value);this.selectionEnd=this.selectionStart=t.selectionEnd,this.inCompositionMode||(this.selectionStart=t.selectionStart),this.updateTextareaPosition()}},updateTextareaPosition:function(){if(this.selectionStart===this.selectionEnd){var t=this._calcTextareaPosition();this.hiddenTextarea.style.left=t.left,this.hiddenTextarea.style.top=t.top}},_calcTextareaPosition:function(){if(!this.canvas)return{x:1,y:1};var t=this.inCompositionMode?this.compositionStart:this.selectionStart,e=this._getCursorBoundaries(t),i=this.get2DCursorLocation(t),r=i.lineIndex,n=i.charIndex,s=this.getValueOfPropertyAt(r,n,"fontSize")*this.lineHeight,o=e.leftOffset,a=this.calcTransformMatrix(),h={x:e.left+o,y:e.top+e.topOffset+s},c=this.canvas.upperCanvasEl,l=c.width-s,u=c.height-s;return h=fabric.util.transformPoint(h,a),(h=fabric.util.transformPoint(h,this.canvas.viewportTransform)).x<0&&(h.x=0),h.x>l&&(h.x=l),h.y<0&&(h.y=0),h.y>u&&(h.y=u),h.x+=this.canvas._offset.left,h.y+=this.canvas._offset.top,{left:h.x+"px",top:h.y+"px",fontSize:s+"px",charHeight:s}},_saveEditingProps:function(){this._savedProps={hasControls:this.hasControls,borderColor:this.borderColor,lockMovementX:this.lockMovementX,lockMovementY:this.lockMovementY,hoverCursor:this.hoverCursor,defaultCursor:this.canvas&&this.canvas.defaultCursor,moveCursor:this.canvas&&this.canvas.moveCursor}},_restoreEditingProps:function(){this._savedProps&&(this.hoverCursor=this._savedProps.hoverCursor,this.hasControls=this._savedProps.hasControls,this.borderColor=this._savedProps.borderColor,this.lockMovementX=this._savedProps.lockMovementX,this.lockMovementY=this._savedProps.lockMovementY,this.canvas&&(this.canvas.defaultCursor=this._savedProps.defaultCursor,this.canvas.moveCursor=this._savedProps.moveCursor))},exitEditing:function(){var t=this._textBeforeEdit!==this.text;return this.selected=!1,this.isEditing=!1,this.selectable=!0,this.selectionEnd=this.selectionStart,this.hiddenTextarea&&(this.hiddenTextarea.blur&&this.hiddenTextarea.blur(),this.canvas&&this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea),this.hiddenTextarea=null),this.abortCursorAnimation(),this._restoreEditingProps(),this._currentCursorOpacity=0,this._shouldClearDimensionCache()&&(this.initDimensions(),this.setCoords()),this.fire("editing:exited"),t&&this.fire("modified"),this.canvas&&(this.canvas.off("mouse:move",this.mouseMoveHandler),this.canvas.fire("text:editing:exited",{target:this}),t&&this.canvas.fire("object:modified",{target:this})),this},_removeExtraneousStyles:function(){for(var t in this.styles)this._textLines[t]||delete this.styles[t]},removeStyleFromTo:function(t,e){var i,r,n=this.get2DCursorLocation(t,!0),s=this.get2DCursorLocation(e,!0),o=n.lineIndex,a=n.charIndex,h=s.lineIndex,c=s.charIndex;if(o!==h){if(this.styles[o])for(i=a;i=c&&(r[l-f]=r[u],delete r[u])}},shiftLineStyles:function(e,i){var r=t(this.styles);for(var n in this.styles){var s=parseInt(n,10);s>e&&(this.styles[s+i]=r[s],r[s-i]||delete this.styles[s])}},restartCursorIfNeeded:function(){this._currentTickState&&!this._currentTickState.isAborted&&this._currentTickCompleteState&&!this._currentTickCompleteState.isAborted||this.initDelayedCursor()},insertNewlineStyleObject:function(e,i,r,n){var s,o={},a=!1;r||(r=1),this.shiftLineStyles(e,r),this.styles[e]&&(s=this.styles[e][0===i?i:i-1]);for(var h in this.styles[e]){var c=parseInt(h,10);c>=i&&(a=!0,o[c-i]=this.styles[e][h],delete this.styles[e][h])}for(a?this.styles[e+r]=o:delete this.styles[e+r];r>1;)r--,n&&n[r]?this.styles[e+r]={0:t(n[r])}:s?this.styles[e+r]={0:t(s)}:delete this.styles[e+r];this._forceClearCache=!0},insertCharStyleObject:function(e,i,r,n){this.styles||(this.styles={});var s=this.styles[e],o=s?t(s):{};r||(r=1);for(var a in o){var h=parseInt(a,10);h>=i&&(s[h+r]=o[h],o[h-r]||delete s[h])}if(this._forceClearCache=!0,n)for(;r--;)Object.keys(n[r]).length&&(this.styles[e]||(this.styles[e]={}),this.styles[e][i+r]=t(n[r]));else if(s)for(var c=s[i?i-1:1];c&&r--;)this.styles[e][i+r]=t(c)},insertNewStyleBlock:function(t,e,i){for(var r=this.get2DCursorLocation(e,!0),n=[0],s=0,o=0;o0&&(this.insertCharStyleObject(r.lineIndex,r.charIndex,n[0],i),i=i&&i.slice(n[0]+1)),s&&this.insertNewlineStyleObject(r.lineIndex,r.charIndex+n[0],s);for(o=1;o0?this.insertCharStyleObject(r.lineIndex+o,0,n[o],i):i&&(this.styles[r.lineIndex+o][0]=i[0]),i=i&&i.slice(n[o]+1);n[o]>0&&this.insertCharStyleObject(r.lineIndex+o,0,n[o],i)},setSelectionStartEndWithShift:function(t,e,i){i<=t?(e===t?this._selectionDirection="left":"right"===this._selectionDirection&&(this._selectionDirection="left",this.selectionEnd=t),this.selectionStart=i):i>t&&it?this.selectionStart=t:this.selectionStart<0&&(this.selectionStart=0),this.selectionEnd>t?this.selectionEnd=t:this.selectionEnd<0&&(this.selectionEnd=0)}})}(),fabric.util.object.extend(fabric.IText.prototype,{initDoubleClickSimulation:function(){this.__lastClickTime=+new Date,this.__lastLastClickTime=+new Date,this.__lastPointer={},this.on("mousedown",this.onMouseDown.bind(this))},onMouseDown:function(t){this.__newClickTime=+new Date;var e=this.canvas.getPointer(t.e);this.isTripleClick(e,t.e)&&(this.fire("tripleclick",t),this._stopEvent(t.e)),this.__lastLastClickTime=this.__lastClickTime,this.__lastClickTime=this.__newClickTime,this.__lastPointer=e,this.__lastIsEditing=this.isEditing,this.__lastSelected=this.selected},isTripleClick:function(t){return this.__newClickTime-this.__lastClickTime<500&&this.__lastClickTime-this.__lastLastClickTime<500&&this.__lastPointer.x===t.x&&this.__lastPointer.y===t.y},_stopEvent:function(t){t.preventDefault&&t.preventDefault(),t.stopPropagation&&t.stopPropagation()},initCursorSelectionHandlers:function(){this.initMousedownHandler(),this.initMouseupHandler(),this.initClicks()},initClicks:function(){this.on("mousedblclick",function(t){this.selectWord(this.getSelectionStartFromPointer(t.e))}),this.on("tripleclick",function(t){this.selectLine(this.getSelectionStartFromPointer(t.e))})},_mouseDownHandler:function(t){if(this.canvas&&this.editable&&(!t.e.button||1===t.e.button)){var e=this.canvas.getPointer(t.e);this.__mousedownX=e.x,this.__mousedownY=e.y,this.__isMousedown=!0,this.selected&&this.setCursorByClick(t.e),this.isEditing&&(this.__selectionStartOnMouseDown=this.selectionStart,this.selectionStart===this.selectionEnd&&this.abortCursorAnimation(),this.renderCursorOrSelection())}},initMousedownHandler:function(){this.on("mousedown",this._mouseDownHandler)},_isObjectMoved:function(t){var e=this.canvas.getPointer(t);return this.__mousedownX!==e.x||this.__mousedownY!==e.y},initMouseupHandler:function(){this.on("mouseup",function(t){this.__isMousedown=!1,!this.editable||this._isObjectMoved(t.e)||t.e.button&&1!==t.e.button||(this.__lastSelected&&!this.__corner&&(this.enterEditing(t.e),this.selectionStart===this.selectionEnd?this.initDelayedCursor(!0):this.renderCursorOrSelection()),this.selected=!0)})},setCursorByClick:function(t){var e=this.getSelectionStartFromPointer(t),i=this.selectionStart,r=this.selectionEnd;t.shiftKey?this.setSelectionStartEndWithShift(i,r,e):(this.selectionStart=e,this.selectionEnd=e),this.isEditing&&(this._fireSelectionChanged(),this._updateTextarea())},getSelectionStartFromPointer:function(t){for(var e,i=this.getLocalPointer(t),r=0,n=0,s=0,o=0,a=0,h=0,c=this._textLines.length;h0&&(o+=this._textLines[h-1].length+1);n=this._getLineLeftOffset(a)*this.scaleX;for(var l=0,u=(e=this._textLines[a]).length;ls||o<0?0:1);return this.flipX&&(a=n-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.setAttribute("autocorrect","off"),this.hiddenTextarea.setAttribute("autocomplete","off"),this.hiddenTextarea.setAttribute("spellcheck","false"),this.hiddenTextarea.setAttribute("data-fabric-hiddentextarea",""),this.hiddenTextarea.setAttribute("wrap","off");var t=this._calcTextareaPosition();this.hiddenTextarea.style.cssText="position: absolute; top: "+t.top+"; left: "+t.left+"; z-index: -999; opacity: 0; width: 1px; height: 1px; font-size: 1px; line-height: 1px; paddingーtop: "+t.fontSize+";",fabric.document.body.appendChild(this.hiddenTextarea),fabric.util.addListener(this.hiddenTextarea,"keydown",this.onKeyDown.bind(this)),fabric.util.addListener(this.hiddenTextarea,"keyup",this.onKeyUp.bind(this)),fabric.util.addListener(this.hiddenTextarea,"input",this.onInput.bind(this)),fabric.util.addListener(this.hiddenTextarea,"copy",this.copy.bind(this)),fabric.util.addListener(this.hiddenTextarea,"cut",this.copy.bind(this)),fabric.util.addListener(this.hiddenTextarea,"paste",this.paste.bind(this)),fabric.util.addListener(this.hiddenTextarea,"compositionstart",this.onCompositionStart.bind(this)),fabric.util.addListener(this.hiddenTextarea,"compositionupdate",this.onCompositionUpdate.bind(this)),fabric.util.addListener(this.hiddenTextarea,"compositionend",this.onCompositionEnd.bind(this)),!this._clickHandlerInitialized&&this.canvas&&(fabric.util.addListener(this.canvas.upperCanvasEl,"click",this.onClick.bind(this)),this._clickHandlerInitialized=!0)},keysMap:{9:"exitEditing",27:"exitEditing",33:"moveCursorUp",34:"moveCursorDown",35:"moveCursorRight",36:"moveCursorLeft",37:"moveCursorLeft",38:"moveCursorUp",39:"moveCursorRight",40:"moveCursorDown"},ctrlKeysMapUp:{67:"copy",88:"cut"},ctrlKeysMapDown:{65:"selectAll"},onClick:function(){this.hiddenTextarea&&this.hiddenTextarea.focus()},onKeyDown:function(t){if(this.isEditing&&!this.inCompositionMode){if(t.keyCode in this.keysMap)this[this.keysMap[t.keyCode]](t);else{if(!(t.keyCode in this.ctrlKeysMapDown&&(t.ctrlKey||t.metaKey)))return;this[this.ctrlKeysMapDown[t.keyCode]](t)}t.stopImmediatePropagation(),t.preventDefault(),t.keyCode>=33&&t.keyCode<=40?(this.clearContextTop(),this.renderCursorOrSelection()):this.canvas&&this.canvas.requestRenderAll()}},onKeyUp:function(t){!this.isEditing||this._copyDone||this.inCompositionMode?this._copyDone=!1:t.keyCode in this.ctrlKeysMapUp&&(t.ctrlKey||t.metaKey)&&(this[this.ctrlKeysMapUp[t.keyCode]](t),t.stopImmediatePropagation(),t.preventDefault(),this.canvas&&this.canvas.requestRenderAll())},onInput:function(t){var e=this.fromPaste;if(this.fromPaste=!1,t&&t.stopPropagation(),this.isEditing){var i,r,n=this._splitTextIntoLines(this.hiddenTextarea.value).graphemeText,s=this._text.length,o=n.length,a=o-s;if(""===this.hiddenTextarea.value)return this.styles={},this.updateFromTextArea(),this.fire("changed"),void(this.canvas&&(this.canvas.fire("text:changed",{target:this}),this.canvas.requestRenderAll()));var h=this.fromStringToGraphemeSelection(this.hiddenTextarea.selectionStart,this.hiddenTextarea.selectionEnd,this.hiddenTextarea.value),c=this.selectionStart>h.selectionStart;this.selectionStart!==this.selectionEnd?(i=this._text.slice(this.selectionStart,this.selectionEnd),a+=this.selectionEnd-this.selectionStart):o0&&(r+=(i=this.__charBounds[t][e-1]).left+i.width),r},getDownCursorOffset:function(t,e){var i=this._getSelectionForOffset(t,e),r=this.get2DCursorLocation(i),n=r.lineIndex;if(n===this._textLines.length-1||t.metaKey||34===t.keyCode)return this._text.length-i;var s=r.charIndex,o=this._getWidthBeforeCursor(n,s),a=this._getIndexOnLine(n+1,o);return this._textLines[n].slice(s).length+a+2},_getSelectionForOffset:function(t,e){return t.shiftKey&&this.selectionStart!==this.selectionEnd&&e?this.selectionEnd:this.selectionStart},getUpCursorOffset:function(t,e){var i=this._getSelectionForOffset(t,e),r=this.get2DCursorLocation(i),n=r.lineIndex;if(0===n||t.metaKey||33===t.keyCode)return-i;var s=r.charIndex,o=this._getWidthBeforeCursor(n,s),a=this._getIndexOnLine(n-1,o),h=this._textLines[n].slice(0,s);return-this._textLines[n-1].length+a-h.length},_getIndexOnLine:function(t,e){for(var i,r,n=this._textLines[t],s=this._getLineLeftOffset(t),o=0,a=0,h=n.length;ae){r=!0;var c=s-i,l=s,u=Math.abs(c-e);o=Math.abs(l-e)=this._text.length&&this.selectionEnd>=this._text.length||this._moveCursorUpOrDown("Down",t)},moveCursorUp:function(t){0===this.selectionStart&&0===this.selectionEnd||this._moveCursorUpOrDown("Up",t)},_moveCursorUpOrDown:function(t,e){var i=this["get"+t+"CursorOffset"](e,"right"===this._selectionDirection);e.shiftKey?this.moveCursorWithShift(i):this.moveCursorWithoutShift(i),0!==i&&(this.setSelectionInBoundaries(),this.abortCursorAnimation(),this._currentCursorOpacity=1,this.initDelayedCursor(),this._fireSelectionChanged(),this._updateTextarea())},moveCursorWithShift:function(t){var e="left"===this._selectionDirection?this.selectionStart+t:this.selectionEnd+t;return this.setSelectionStartEndWithShift(this.selectionStart,this.selectionEnd,e),0!==t},moveCursorWithoutShift:function(t){return t<0?(this.selectionStart+=t,this.selectionEnd=this.selectionStart):(this.selectionEnd+=t,this.selectionStart=this.selectionEnd),0!==t},moveCursorLeft:function(t){0===this.selectionStart&&0===this.selectionEnd||this._moveCursorLeftOrRight("Left",t)},_move:function(t,e,i){var r;if(t.altKey)r=this["findWordBoundary"+i](this[e]);else{if(!t.metaKey&&35!==t.keyCode&&36!==t.keyCode)return this[e]+="Left"===i?-1:1,!0;r=this["findLineBoundary"+i](this[e])}if(void 0!==typeof r&&this[e]!==r)return this[e]=r,!0},_moveLeft:function(t,e){return this._move(t,e,"Left")},_moveRight:function(t,e){return this._move(t,e,"Right")},moveCursorLeftWithoutShift:function(t){var e=!0;return this._selectionDirection="left",this.selectionEnd===this.selectionStart&&0!==this.selectionStart&&(e=this._moveLeft(t,"selectionStart")),this.selectionEnd=this.selectionStart,e},moveCursorLeftWithShift:function(t){return"right"===this._selectionDirection&&this.selectionStart!==this.selectionEnd?this._moveLeft(t,"selectionEnd"):0!==this.selectionStart?(this._selectionDirection="left",this._moveLeft(t,"selectionStart")):void 0},moveCursorRight:function(t){this.selectionStart>=this._text.length&&this.selectionEnd>=this._text.length||this._moveCursorLeftOrRight("Right",t)},_moveCursorLeftOrRight:function(t,e){var i="moveCursor"+t+"With";this._currentCursorOpacity=1,e.shiftKey?i+="Shift":i+="outShift",this[i](e)&&(this.abortCursorAnimation(),this.initDelayedCursor(),this._fireSelectionChanged(),this._updateTextarea())},moveCursorRightWithShift:function(t){return"left"===this._selectionDirection&&this.selectionStart!==this.selectionEnd?this._moveRight(t,"selectionStart"):this.selectionEnd!==this._text.length?(this._selectionDirection="right",this._moveRight(t,"selectionEnd")):void 0},moveCursorRightWithoutShift:function(t){var e=!0;return this._selectionDirection="right",this.selectionStart===this.selectionEnd?(e=this._moveRight(t,"selectionStart"),this.selectionEnd=this.selectionStart):this.selectionStart=this.selectionEnd,e},removeChars:function(t,e){void 0===e&&(e=t+1),this.removeStyleFromTo(t,e),this._text.splice(t,e-t),this.text=this._text.join(""),this.set("dirty",!0),this._shouldClearDimensionCache()&&(this.initDimensions(),this.setCoords()),this._removeExtraneousStyles()},insertChars:function(t,e,i,r){void 0===r&&(r=i),r>i&&this.removeStyleFromTo(i,r);var n=fabric.util.string.graphemeSplit(t);this.insertNewStyleBlock(n,i,e),this._text=[].concat(this._text.slice(0,i),n,this._text.slice(r)),this.text=this._text.join(""),this.set("dirty",!0),this._shouldClearDimensionCache()&&(this.initDimensions(),this.setCoords()),this._removeExtraneousStyles()}}),function(){var t=fabric.util.toFixed;fabric.util.object.extend(fabric.Text.prototype,{toSVG:function(t){var e=this._createBaseSVGMarkup(),i=this._getSVGLeftTopOffsets(),r=this._getSVGTextAndBg(i.textTop,i.textLeft);return this._wrapSVGTextAndBg(e,r),t?t(e.join("")):e.join("")},_getSVGLeftTopOffsets:function(){return{textLeft:-this.width/2,textTop:-this.height/2,lineTop:this.getHeightOfLine(0)}},_wrapSVGTextAndBg:function(t,e){var i=this.getSvgFilter(),r=""===i?"":' style="'+i+'"',n=this.getSvgTextDecoration(this);t.push("\t\n",e.textBgRects.join(""),'\t\t",e.textSpans.join(""),"\n","\t\n")},_getSVGTextAndBg:function(t,e){var i,r=[],n=[],s=t;this._setSVGBg(n);for(var o=0,a=this._textLines.length;o",fabric.util.string.escapeXml(e),""].join("")},_setSVGTextLineText:function(t,e,i,r){var n,s,o,a,h,c=this.getHeightOfLine(e),l=-1!==this.textAlign.indexOf("justify"),u="",f=0,d=this._textLines[e];r+=c*(1-this._fontSizeFraction)/this.lineHeight;for(var g=0,p=d.length-1;g<=p;g++)h=g===p||this.charSpacing,u+=d[g],o=this.__charBounds[e][g],0===f?(i+=o.kernedWidth-o.width,f+=o.width):f+=o.kernedWidth,l&&!h&&this._reSpaceAndTab.test(d[g])&&(h=!0),h||(n=n||this.getCompleteStyleDeclaration(e,g),s=this.getCompleteStyleDeclaration(e,g+1),h=this._hasStyleChangedForSvg(n,s)),h&&(a=this._getStyleDeclaration(e,g)||{},t.push(this._createTextCharSpan(u,a,i,r)),u="",n=s,i+=f,f=0)},_pushTextBgRect:function(e,i,r,n,s,o){var a=fabric.Object.NUM_FRACTION_DIGITS;e.push("\t\t\n')},_setSVGTextLineBg:function(t,e,i,r){for(var n,s,o=this._textLines[e],a=this.getHeightOfLine(e)/this.lineHeight,h=0,c=0,l=this.getValueOfPropertyAt(e,0,"textBackgroundColor"),u=0,f=o.length;uthis.width&&this._set("width",this.dynamicMinWidth),-1!==this.textAlign.indexOf("justify")&&this.enlargeSpaces(),this.height=this.calcTextHeight(),this.saveState({propertySet:"_dimensionAffectingProps"}))},_generateStyleMap:function(t){for(var e=0,i=0,r=0,n={},s=0;s0?(i=0,r++,e++):this._reSpaceAndTab.test(t.graphemeText[r])&&s>0&&(i++,r++),n[s]={line:e,offset:i},r+=t.graphemeLines[s].length,i+=t.graphemeLines[s].length;return n},styleHas:function(t,i){if(this._styleMap&&!this.isWrapping){var r=this._styleMap[i];r&&(i=r.line)}return e.Text.prototype.styleHas.call(this,t,i)},_getStyleDeclaration:function(t,e){if(this._styleMap&&!this.isWrapping){var i=this._styleMap[t];if(!i)return null;t=i.line,e=i.offset+e}return this.callSuper("_getStyleDeclaration",t,e)},_setStyleDeclaration:function(t,e,i){var r=this._styleMap[t];t=r.line,e=r.offset+e,this.styles[t][e]=i},_deleteStyleDeclaration:function(t,e){var i=this._styleMap[t];t=i.line,e=i.offset+e,delete this.styles[t][e]},_getLineStyle:function(t){var e=this._styleMap[t];return this.styles[e.line]},_setLineStyle:function(t,e){var i=this._styleMap[t];this.styles[i.line]=e},_deleteLineStyle:function(t){var e=this._styleMap[t];delete this.styles[e.line]},_wrapText:function(t,e){var i,r=[];for(this.isWrapping=!0,i=0;i=r&&!d&&(s.push(o),o=[],n=l,d=!0),d||o.push(" "),o=o.concat(h),u=this._measureWord([" "],i,c),c++,d=!1,l>f&&(f=l);return p&&s.push(o),f>this.dynamicMinWidth&&(this.dynamicMinWidth=f-g),s},isEndOfWrapping:function(t){return!this._styleMap[t+1]||this._styleMap[t+1].line!==this._styleMap[t].line},_splitTextIntoLines:function(t){for(var i=e.Text.prototype._splitTextIntoLines.call(this,t),r=this._wrapText(i.lines,this.width),n=new Array(r.length),s=0;s=h.getMinWidth()?(h.set("width",l),!0):void 0},fabric.util.object.extend(fabric.Textbox.prototype,{_removeExtraneousStyles:function(){for(var t in this._styleMap)this._textLines[t]||delete this.styles[this._styleMap[t].line]}})}(); \ No newline at end of file diff --git a/dist/fabric.min.js.gz b/dist/fabric.min.js.gz deleted file mode 100644 index 39fd57508740eab53b4957ff2d7359bd3a63f5a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79012 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 Cz18Ia diff --git a/dist/fabric.require.js b/dist/fabric.require.js deleted file mode 100644 index 7e6577e5..00000000 --- a/dist/fabric.require.js +++ /dev/null @@ -1,13800 +0,0 @@ -var fabric = fabric || { - version: "2.0.0-rc.4" -}; - -if (typeof exports !== "undefined") { - exports.fabric = fabric; -} - -if (typeof document !== "undefined" && typeof window !== "undefined") { - fabric.document = document; - fabric.window = window; -} else { - fabric.document = require("jsdom").jsdom(decodeURIComponent("%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E"), { - features: { - FetchExternalResources: [ "img" ] - } - }); - fabric.jsdomImplForWrapper = require("jsdom/lib/jsdom/living/generated/utils").implForWrapper; - fabric.nodeCanvas = require("jsdom/lib/jsdom/utils").Canvas; - fabric.window = fabric.document.defaultView; - DOMParser = require("xmldom").DOMParser; -} - -fabric.isTouchSupported = "ontouchstart" in fabric.window; - -fabric.isLikelyNode = typeof Buffer !== "undefined" && typeof window === "undefined"; - -fabric.SHARED_ATTRIBUTES = [ "display", "transform", "fill", "fill-opacity", "fill-rule", "opacity", "stroke", "stroke-dasharray", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "id", "paint-order", "instantiated_by_use" ]; - -fabric.DPI = 96; - -fabric.reNum = "(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)"; - -fabric.fontPaths = {}; - -fabric.iMatrix = [ 1, 0, 0, 1, 0, 0 ]; - -fabric.canvasModule = "canvas"; - -fabric.perfLimitSizeTotal = 2097152; - -fabric.maxCacheSideLimit = 4096; - -fabric.minCacheSideLimit = 256; - -fabric.charWidthsCache = {}; - -fabric.textureSize = 2048; - -fabric.enableGLFiltering = true; - -fabric.devicePixelRatio = fabric.window.devicePixelRatio || fabric.window.webkitDevicePixelRatio || fabric.window.mozDevicePixelRatio || 1; - -fabric.browserShadowBlurConstant = 1; - -fabric.initFilterBackend = function() { - if (fabric.enableGLFiltering && fabric.isWebglSupported && fabric.isWebglSupported(fabric.textureSize)) { - console.log("max texture size: " + fabric.maxTextureSize); - return new fabric.WebglFilterBackend({ - tileSize: fabric.textureSize - }); - } else if (fabric.Canvas2dFilterBackend) { - return new fabric.Canvas2dFilterBackend(); - } -}; - -if (typeof document !== "undefined" && typeof window !== "undefined") { - window.fabric = fabric; -} - -(function() { - function _removeEventListener(eventName, handler) { - if (!this.__eventListeners[eventName]) { - return; - } - var eventListener = this.__eventListeners[eventName]; - if (handler) { - eventListener[eventListener.indexOf(handler)] = false; - } else { - fabric.util.array.fill(eventListener, false); - } - } - function observe(eventName, handler) { - if (!this.__eventListeners) { - this.__eventListeners = {}; - } - if (arguments.length === 1) { - for (var prop in eventName) { - this.on(prop, eventName[prop]); - } - } else { - if (!this.__eventListeners[eventName]) { - this.__eventListeners[eventName] = []; - } - this.__eventListeners[eventName].push(handler); - } - return this; - } - function stopObserving(eventName, handler) { - if (!this.__eventListeners) { - return; - } - if (arguments.length === 0) { - for (eventName in this.__eventListeners) { - _removeEventListener.call(this, eventName); - } - } else if (arguments.length === 1 && typeof arguments[0] === "object") { - for (var prop in eventName) { - _removeEventListener.call(this, prop, eventName[prop]); - } - } else { - _removeEventListener.call(this, eventName, handler); - } - return this; - } - function fire(eventName, options) { - if (!this.__eventListeners) { - return; - } - var listenersForEvent = this.__eventListeners[eventName]; - if (!listenersForEvent) { - return; - } - for (var i = 0, len = listenersForEvent.length; i < len; i++) { - listenersForEvent[i] && listenersForEvent[i].call(this, options || {}); - } - this.__eventListeners[eventName] = listenersForEvent.filter(function(value) { - return value !== false; - }); - return this; - } - fabric.Observable = { - observe: observe, - stopObserving: stopObserving, - fire: fire, - on: observe, - off: stopObserving, - trigger: fire - }; -})(); - -fabric.Collection = { - _objects: [], - add: function() { - this._objects.push.apply(this._objects, arguments); - if (this._onObjectAdded) { - for (var i = 0, length = arguments.length; i < length; i++) { - this._onObjectAdded(arguments[i]); - } - } - this.renderOnAddRemove && this.requestRenderAll(); - return this; - }, - insertAt: function(object, index, nonSplicing) { - var objects = this.getObjects(); - if (nonSplicing) { - objects[index] = object; - } else { - objects.splice(index, 0, object); - } - this._onObjectAdded && this._onObjectAdded(object); - this.renderOnAddRemove && this.requestRenderAll(); - return this; - }, - remove: function() { - var objects = this.getObjects(), index, somethingRemoved = false; - for (var i = 0, length = arguments.length; i < length; i++) { - index = objects.indexOf(arguments[i]); - if (index !== -1) { - somethingRemoved = true; - objects.splice(index, 1); - this._onObjectRemoved && this._onObjectRemoved(arguments[i]); - } - } - this.renderOnAddRemove && somethingRemoved && this.requestRenderAll(); - return this; - }, - forEachObject: function(callback, context) { - var objects = this.getObjects(); - for (var i = 0, len = objects.length; i < len; i++) { - callback.call(context, objects[i], i, objects); - } - return this; - }, - getObjects: function(type) { - if (typeof type === "undefined") { - return this._objects; - } - return this._objects.filter(function(o) { - return o.type === type; - }); - }, - item: function(index) { - return this.getObjects()[index]; - }, - isEmpty: function() { - return this.getObjects().length === 0; - }, - size: function() { - return this.getObjects().length; - }, - contains: function(object) { - return this.getObjects().indexOf(object) > -1; - }, - complexity: function() { - return this.getObjects().reduce(function(memo, current) { - memo += current.complexity ? current.complexity() : 0; - return memo; - }, 0); - } -}; - -fabric.CommonMethods = { - _setOptions: function(options) { - for (var prop in options) { - this.set(prop, options[prop]); - } - }, - _initGradient: function(filler, property) { - if (filler && filler.colorStops && !(filler instanceof fabric.Gradient)) { - this.set(property, new fabric.Gradient(filler)); - } - }, - _initPattern: function(filler, property, callback) { - if (filler && filler.source && !(filler instanceof fabric.Pattern)) { - this.set(property, new fabric.Pattern(filler, callback)); - } else { - callback && callback(); - } - }, - _initClipping: function(options) { - if (!options.clipTo || typeof options.clipTo !== "string") { - return; - } - var functionBody = fabric.util.getFunctionBody(options.clipTo); - if (typeof functionBody !== "undefined") { - this.clipTo = new Function("ctx", functionBody); - } - }, - _setObject: function(obj) { - for (var prop in obj) { - this._set(prop, obj[prop]); - } - }, - set: function(key, value) { - if (typeof key === "object") { - this._setObject(key); - } else { - if (typeof value === "function" && key !== "clipTo") { - this._set(key, value(this.get(key))); - } else { - this._set(key, value); - } - } - return this; - }, - _set: function(key, value) { - this[key] = value; - }, - toggle: function(property) { - var value = this.get(property); - if (typeof value === "boolean") { - this.set(property, !value); - } - return this; - }, - get: function(property) { - return this[property]; - } -}; - -(function(global) { - var sqrt = Math.sqrt, atan2 = Math.atan2, pow = Math.pow, abs = Math.abs, PiBy180 = Math.PI / 180; - fabric.util = { - removeFromArray: function(array, value) { - var idx = array.indexOf(value); - if (idx !== -1) { - array.splice(idx, 1); - } - return array; - }, - getRandomInt: function(min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; - }, - degreesToRadians: function(degrees) { - return degrees * PiBy180; - }, - radiansToDegrees: function(radians) { - return radians / PiBy180; - }, - rotatePoint: function(point, origin, radians) { - point.subtractEquals(origin); - var v = fabric.util.rotateVector(point, radians); - return new fabric.Point(v.x, v.y).addEquals(origin); - }, - rotateVector: function(vector, radians) { - var sin = Math.sin(radians), cos = Math.cos(radians), rx = vector.x * cos - vector.y * sin, ry = vector.x * sin + vector.y * cos; - return { - x: rx, - y: ry - }; - }, - transformPoint: function(p, t, ignoreOffset) { - if (ignoreOffset) { - return new fabric.Point(t[0] * p.x + t[2] * p.y, t[1] * p.x + t[3] * p.y); - } - return new fabric.Point(t[0] * p.x + t[2] * p.y + t[4], t[1] * p.x + t[3] * p.y + t[5]); - }, - makeBoundingBoxFromPoints: function(points) { - var xPoints = [ points[0].x, points[1].x, points[2].x, points[3].x ], minX = fabric.util.array.min(xPoints), maxX = fabric.util.array.max(xPoints), width = maxX - minX, yPoints = [ points[0].y, points[1].y, points[2].y, points[3].y ], minY = fabric.util.array.min(yPoints), maxY = fabric.util.array.max(yPoints), height = maxY - minY; - return { - left: minX, - top: minY, - width: width, - height: height - }; - }, - invertTransform: function(t) { - var a = 1 / (t[0] * t[3] - t[1] * t[2]), r = [ a * t[3], -a * t[1], -a * t[2], a * t[0] ], o = fabric.util.transformPoint({ - x: t[4], - y: t[5] - }, r, true); - r[4] = -o.x; - r[5] = -o.y; - return r; - }, - toFixed: function(number, fractionDigits) { - return parseFloat(Number(number).toFixed(fractionDigits)); - }, - parseUnit: function(value, fontSize) { - var unit = /\D{0,2}$/.exec(value), number = parseFloat(value); - if (!fontSize) { - fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE; - } - switch (unit[0]) { - case "mm": - return number * fabric.DPI / 25.4; - - case "cm": - return number * fabric.DPI / 2.54; - - case "in": - return number * fabric.DPI; - - case "pt": - return number * fabric.DPI / 72; - - case "pc": - return number * fabric.DPI / 72 * 12; - - case "em": - return number * fontSize; - - default: - return number; - } - }, - falseFunction: function() { - return false; - }, - getKlass: function(type, namespace) { - type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1)); - return fabric.util.resolveNamespace(namespace)[type]; - }, - getSvgAttributes: function(type) { - var attributes = [ "instantiated_by_use", "style", "id", "class" ]; - switch (type) { - case "linearGradient": - attributes = attributes.concat([ "x1", "y1", "x2", "y2", "gradientUnits", "gradientTransform" ]); - break; - - case "radialGradient": - attributes = attributes.concat([ "gradientUnits", "gradientTransform", "cx", "cy", "r", "fx", "fy", "fr" ]); - break; - - case "stop": - attributes = attributes.concat([ "offset", "stop-color", "stop-opacity" ]); - break; - } - return attributes; - }, - resolveNamespace: function(namespace) { - if (!namespace) { - return fabric; - } - var parts = namespace.split("."), len = parts.length, i, obj = global || fabric.window; - for (i = 0; i < len; ++i) { - obj = obj[parts[i]]; - } - return obj; - }, - loadImage: function(url, callback, context, crossOrigin) { - if (!url) { - callback && callback.call(context, url); - return; - } - var img = fabric.util.createImage(); - var onLoadCallback = function() { - callback && callback.call(context, img); - img = img.onload = img.onerror = null; - }; - img.onload = onLoadCallback; - img.onerror = function() { - fabric.log("Error loading " + img.src); - callback && callback.call(context, null, true); - img = img.onload = img.onerror = null; - }; - if (url.indexOf("data") !== 0 && crossOrigin) { - img.crossOrigin = crossOrigin; - } - if (url.substring(0, 14) === "data:image/svg") { - img.onload = null; - fabric.util.loadImageInDom(img, onLoadCallback); - } - img.src = url; - }, - loadImageInDom: function(img, onLoadCallback) { - var div = fabric.document.createElement("div"); - div.style.width = div.style.height = "1px"; - div.style.left = div.style.top = "-100%"; - div.style.position = "absolute"; - div.appendChild(img); - fabric.document.querySelector("body").appendChild(div); - img.onload = function() { - onLoadCallback(); - div.parentNode.removeChild(div); - div = null; - }; - }, - enlivenObjects: function(objects, callback, namespace, reviver) { - objects = objects || []; - function onLoaded() { - if (++numLoadedObjects === numTotalObjects) { - callback && callback(enlivenedObjects); - } - } - var enlivenedObjects = [], numLoadedObjects = 0, numTotalObjects = objects.length; - if (!numTotalObjects) { - callback && callback(enlivenedObjects); - return; - } - objects.forEach(function(o, index) { - if (!o || !o.type) { - onLoaded(); - return; - } - var klass = fabric.util.getKlass(o.type, namespace); - klass.fromObject(o, function(obj, error) { - error || (enlivenedObjects[index] = obj); - reviver && reviver(o, obj, error); - onLoaded(); - }); - }); - }, - enlivenPatterns: function(patterns, callback) { - patterns = patterns || []; - function onLoaded() { - if (++numLoadedPatterns === numPatterns) { - callback && callback(enlivenedPatterns); - } - } - var enlivenedPatterns = [], numLoadedPatterns = 0, numPatterns = patterns.length; - if (!numPatterns) { - callback && callback(enlivenedPatterns); - return; - } - patterns.forEach(function(p, index) { - if (p && p.source) { - new fabric.Pattern(p, function(pattern) { - enlivenedPatterns[index] = pattern; - onLoaded(); - }); - } else { - enlivenedPatterns[index] = p; - onLoaded(); - } - }); - }, - groupSVGElements: function(elements, options, path) { - var object; - if (elements.length === 1) { - return elements[0]; - } - if (options) { - if (options.width && options.height) { - options.centerPoint = { - x: options.width / 2, - y: options.height / 2 - }; - } else { - delete options.width; - delete options.height; - } - } - object = new fabric.Group(elements, options); - if (typeof path !== "undefined") { - object.sourcePath = path; - } - return object; - }, - populateWithProperties: function(source, destination, properties) { - if (properties && Object.prototype.toString.call(properties) === "[object Array]") { - for (var i = 0, len = properties.length; i < len; i++) { - if (properties[i] in source) { - destination[properties[i]] = source[properties[i]]; - } - } - } - }, - drawDashedLine: function(ctx, x, y, x2, y2, da) { - var dx = x2 - x, dy = y2 - y, len = sqrt(dx * dx + dy * dy), rot = atan2(dy, dx), dc = da.length, di = 0, draw = true; - ctx.save(); - ctx.translate(x, y); - ctx.moveTo(0, 0); - ctx.rotate(rot); - x = 0; - while (len > x) { - x += da[di++ % dc]; - if (x > len) { - x = len; - } - ctx[draw ? "lineTo" : "moveTo"](x, 0); - draw = !draw; - } - ctx.restore(); - }, - createCanvasElement: function() { - return fabric.document.createElement("canvas"); - }, - createImage: function() { - return fabric.document.createElement("img"); - }, - clipContext: function(receiver, ctx) { - ctx.save(); - ctx.beginPath(); - receiver.clipTo(ctx); - ctx.clip(); - }, - multiplyTransformMatrices: function(a, b, is2x2) { - return [ a[0] * b[0] + a[2] * b[1], a[1] * b[0] + a[3] * b[1], a[0] * b[2] + a[2] * b[3], a[1] * b[2] + a[3] * b[3], is2x2 ? 0 : a[0] * b[4] + a[2] * b[5] + a[4], is2x2 ? 0 : a[1] * b[4] + a[3] * b[5] + a[5] ]; - }, - qrDecompose: function(a) { - var angle = atan2(a[1], a[0]), denom = pow(a[0], 2) + pow(a[1], 2), scaleX = sqrt(denom), scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX, skewX = atan2(a[0] * a[2] + a[1] * a[3], denom); - return { - angle: angle / PiBy180, - scaleX: scaleX, - scaleY: scaleY, - skewX: skewX / PiBy180, - skewY: 0, - translateX: a[4], - translateY: a[5] - }; - }, - customTransformMatrix: function(scaleX, scaleY, skewX) { - var skewMatrixX = [ 1, 0, abs(Math.tan(skewX * PiBy180)), 1 ], scaleMatrix = [ abs(scaleX), 0, 0, abs(scaleY) ]; - return fabric.util.multiplyTransformMatrices(scaleMatrix, skewMatrixX, true); - }, - resetObjectTransform: function(target) { - target.scaleX = 1; - target.scaleY = 1; - target.skewX = 0; - target.skewY = 0; - target.flipX = false; - target.flipY = false; - target.rotate(0); - }, - getFunctionBody: function(fn) { - return (String(fn).match(/function[^{]*\{([\s\S]*)\}/) || {})[1]; - }, - isTransparent: function(ctx, x, y, tolerance) { - if (tolerance > 0) { - if (x > tolerance) { - x -= tolerance; - } else { - x = 0; - } - if (y > tolerance) { - y -= tolerance; - } else { - y = 0; - } - } - var _isTransparent = true, i, temp, imageData = ctx.getImageData(x, y, tolerance * 2 || 1, tolerance * 2 || 1), l = imageData.data.length; - for (i = 3; i < l; i += 4) { - temp = imageData.data[i]; - _isTransparent = temp <= 0; - if (_isTransparent === false) { - break; - } - } - imageData = null; - return _isTransparent; - }, - parsePreserveAspectRatioAttribute: function(attribute) { - var meetOrSlice = "meet", alignX = "Mid", alignY = "Mid", aspectRatioAttrs = attribute.split(" "), align; - if (aspectRatioAttrs && aspectRatioAttrs.length) { - meetOrSlice = aspectRatioAttrs.pop(); - if (meetOrSlice !== "meet" && meetOrSlice !== "slice") { - align = meetOrSlice; - meetOrSlice = "meet"; - } else if (aspectRatioAttrs.length) { - align = aspectRatioAttrs.pop(); - } - } - alignX = align !== "none" ? align.slice(1, 4) : "none"; - alignY = align !== "none" ? align.slice(5, 8) : "none"; - return { - meetOrSlice: meetOrSlice, - alignX: alignX, - alignY: alignY - }; - }, - clearFabricFontCache: function(fontFamily) { - if (!fontFamily) { - fabric.charWidthsCache = {}; - } else if (fabric.charWidthsCache[fontFamily]) { - delete fabric.charWidthsCache[fontFamily]; - } - }, - limitDimsByArea: function(ar, maximumArea) { - var roughWidth = Math.sqrt(maximumArea * ar), perfLimitSizeY = Math.floor(maximumArea / roughWidth); - return { - x: Math.floor(roughWidth), - y: perfLimitSizeY - }; - }, - capValue: function(min, value, max) { - return Math.max(min, Math.min(value, max)); - }, - findScaleToFit: function(source, destination) { - return Math.min(destination.width / source.width, destination.height / source.height); - }, - findScaleToCover: function(source, destination) { - return Math.max(destination.width / source.width, destination.height / source.height); - } - }; -})(typeof exports !== "undefined" ? exports : this); - -(function() { - var arcToSegmentsCache = {}, segmentToBezierCache = {}, boundsOfCurveCache = {}, _join = Array.prototype.join; - function arcToSegments(toX, toY, rx, ry, large, sweep, rotateX) { - var argsString = _join.call(arguments); - if (arcToSegmentsCache[argsString]) { - return arcToSegmentsCache[argsString]; - } - var PI = Math.PI, th = rotateX * PI / 180, sinTh = Math.sin(th), cosTh = Math.cos(th), fromX = 0, fromY = 0; - rx = Math.abs(rx); - ry = Math.abs(ry); - var px = -cosTh * toX * .5 - sinTh * toY * .5, py = -cosTh * toY * .5 + sinTh * toX * .5, rx2 = rx * rx, ry2 = ry * ry, py2 = py * py, px2 = px * px, pl = rx2 * ry2 - rx2 * py2 - ry2 * px2, root = 0; - if (pl < 0) { - var s = Math.sqrt(1 - pl / (rx2 * ry2)); - rx *= s; - ry *= s; - } else { - root = (large === sweep ? -1 : 1) * Math.sqrt(pl / (rx2 * py2 + ry2 * px2)); - } - var cx = root * rx * py / ry, cy = -root * ry * px / rx, cx1 = cosTh * cx - sinTh * cy + toX * .5, cy1 = sinTh * cx + cosTh * cy + toY * .5, mTheta = calcVectorAngle(1, 0, (px - cx) / rx, (py - cy) / ry), dtheta = calcVectorAngle((px - cx) / rx, (py - cy) / ry, (-px - cx) / rx, (-py - cy) / ry); - if (sweep === 0 && dtheta > 0) { - dtheta -= 2 * PI; - } else if (sweep === 1 && dtheta < 0) { - dtheta += 2 * PI; - } - var segments = Math.ceil(Math.abs(dtheta / PI * 2)), result = [], mDelta = dtheta / segments, mT = 8 / 3 * Math.sin(mDelta / 4) * Math.sin(mDelta / 4) / Math.sin(mDelta / 2), th3 = mTheta + mDelta; - for (var i = 0; i < segments; i++) { - result[i] = segmentToBezier(mTheta, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY); - fromX = result[i][4]; - fromY = result[i][5]; - mTheta = th3; - th3 += mDelta; - } - arcToSegmentsCache[argsString] = result; - return result; - } - function segmentToBezier(th2, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY) { - var argsString2 = _join.call(arguments); - if (segmentToBezierCache[argsString2]) { - return segmentToBezierCache[argsString2]; - } - var costh2 = Math.cos(th2), sinth2 = Math.sin(th2), costh3 = Math.cos(th3), sinth3 = Math.sin(th3), toX = cosTh * rx * costh3 - sinTh * ry * sinth3 + cx1, toY = sinTh * rx * costh3 + cosTh * ry * sinth3 + cy1, cp1X = fromX + mT * (-cosTh * rx * sinth2 - sinTh * ry * costh2), cp1Y = fromY + mT * (-sinTh * rx * sinth2 + cosTh * ry * costh2), cp2X = toX + mT * (cosTh * rx * sinth3 + sinTh * ry * costh3), cp2Y = toY + mT * (sinTh * rx * sinth3 - cosTh * ry * costh3); - segmentToBezierCache[argsString2] = [ cp1X, cp1Y, cp2X, cp2Y, toX, toY ]; - return segmentToBezierCache[argsString2]; - } - function calcVectorAngle(ux, uy, vx, vy) { - var ta = Math.atan2(uy, ux), tb = Math.atan2(vy, vx); - if (tb >= ta) { - return tb - ta; - } else { - return 2 * Math.PI - (ta - tb); - } - } - fabric.util.drawArc = function(ctx, fx, fy, coords) { - var rx = coords[0], ry = coords[1], rot = coords[2], large = coords[3], sweep = coords[4], tx = coords[5], ty = coords[6], segs = [ [], [], [], [] ], segsNorm = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot); - for (var i = 0, len = segsNorm.length; i < len; i++) { - segs[i][0] = segsNorm[i][0] + fx; - segs[i][1] = segsNorm[i][1] + fy; - segs[i][2] = segsNorm[i][2] + fx; - segs[i][3] = segsNorm[i][3] + fy; - segs[i][4] = segsNorm[i][4] + fx; - segs[i][5] = segsNorm[i][5] + fy; - ctx.bezierCurveTo.apply(ctx, segs[i]); - } - }; - fabric.util.getBoundsOfArc = function(fx, fy, rx, ry, rot, large, sweep, tx, ty) { - var fromX = 0, fromY = 0, bound, bounds = [], segs = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot); - for (var i = 0, len = segs.length; i < len; i++) { - bound = getBoundsOfCurve(fromX, fromY, segs[i][0], segs[i][1], segs[i][2], segs[i][3], segs[i][4], segs[i][5]); - bounds.push({ - x: bound[0].x + fx, - y: bound[0].y + fy - }); - bounds.push({ - x: bound[1].x + fx, - y: bound[1].y + fy - }); - fromX = segs[i][4]; - fromY = segs[i][5]; - } - return bounds; - }; - function getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3) { - var argsString = _join.call(arguments); - if (boundsOfCurveCache[argsString]) { - return boundsOfCurveCache[argsString]; - } - var sqrt = Math.sqrt, min = Math.min, max = Math.max, abs = Math.abs, tvalues = [], bounds = [ [], [] ], a, b, c, t, t1, t2, b2ac, sqrtb2ac; - b = 6 * x0 - 12 * x1 + 6 * x2; - a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3; - c = 3 * x1 - 3 * x0; - for (var i = 0; i < 2; ++i) { - if (i > 0) { - b = 6 * y0 - 12 * y1 + 6 * y2; - a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3; - c = 3 * y1 - 3 * y0; - } - if (abs(a) < 1e-12) { - if (abs(b) < 1e-12) { - continue; - } - t = -c / b; - if (0 < t && t < 1) { - tvalues.push(t); - } - continue; - } - b2ac = b * b - 4 * c * a; - if (b2ac < 0) { - continue; - } - sqrtb2ac = sqrt(b2ac); - t1 = (-b + sqrtb2ac) / (2 * a); - if (0 < t1 && t1 < 1) { - tvalues.push(t1); - } - t2 = (-b - sqrtb2ac) / (2 * a); - if (0 < t2 && t2 < 1) { - tvalues.push(t2); - } - } - var x, y, j = tvalues.length, jlen = j, mt; - while (j--) { - t = tvalues[j]; - mt = 1 - t; - x = mt * mt * mt * x0 + 3 * mt * mt * t * x1 + 3 * mt * t * t * x2 + t * t * t * x3; - bounds[0][j] = x; - y = mt * mt * mt * y0 + 3 * mt * mt * t * y1 + 3 * mt * t * t * y2 + t * t * t * y3; - bounds[1][j] = y; - } - bounds[0][jlen] = x0; - bounds[1][jlen] = y0; - bounds[0][jlen + 1] = x3; - bounds[1][jlen + 1] = y3; - var result = [ { - x: min.apply(null, bounds[0]), - y: min.apply(null, bounds[1]) - }, { - x: max.apply(null, bounds[0]), - y: max.apply(null, bounds[1]) - } ]; - boundsOfCurveCache[argsString] = result; - return result; - } - fabric.util.getBoundsOfCurve = getBoundsOfCurve; -})(); - -(function() { - var slice = Array.prototype.slice; - function invoke(array, method) { - var args = slice.call(arguments, 2), result = []; - for (var i = 0, len = array.length; i < len; i++) { - result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]); - } - return result; - } - function max(array, byProperty) { - return find(array, byProperty, function(value1, value2) { - return value1 >= value2; - }); - } - function min(array, byProperty) { - return find(array, byProperty, function(value1, value2) { - return value1 < value2; - }); - } - function fill(array, value) { - var k = array.length; - while (k--) { - array[k] = value; - } - return array; - } - function find(array, byProperty, condition) { - if (!array || array.length === 0) { - return; - } - var i = array.length - 1, result = byProperty ? array[i][byProperty] : array[i]; - if (byProperty) { - while (i--) { - if (condition(array[i][byProperty], result)) { - result = array[i][byProperty]; - } - } - } else { - while (i--) { - if (condition(array[i], result)) { - result = array[i]; - } - } - } - return result; - } - fabric.util.array = { - fill: fill, - invoke: invoke, - min: min, - max: max - }; -})(); - -(function() { - function extend(destination, source, deep) { - if (deep) { - if (!fabric.isLikelyNode && source instanceof Element) { - destination = source; - } else if (source instanceof Array) { - destination = []; - for (var i = 0, len = source.length; i < len; i++) { - destination[i] = extend({}, source[i], deep); - } - } else if (source && typeof source === "object") { - for (var property in source) { - if (source.hasOwnProperty(property)) { - destination[property] = extend({}, source[property], deep); - } - } - } else { - destination = source; - } - } else { - for (var property in source) { - destination[property] = source[property]; - } - } - return destination; - } - function clone(object, deep) { - return extend({}, object, deep); - } - fabric.util.object = { - extend: extend, - clone: clone - }; - fabric.util.object.extend(fabric.util, fabric.Observable); -})(); - -(function() { - function camelize(string) { - return string.replace(/-+(.)?/g, function(match, character) { - return character ? character.toUpperCase() : ""; - }); - } - function capitalize(string, firstLetterOnly) { - return string.charAt(0).toUpperCase() + (firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase()); - } - function escapeXml(string) { - return string.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(//g, ">"); - } - function graphemeSplit(textstring) { - var i = 0, chr, graphemes = []; - for (i = 0, chr; i < textstring.length; i++) { - if ((chr = getWholeChar(textstring, i)) === false) { - continue; - } - graphemes.push(chr); - } - return graphemes; - } - function getWholeChar(str, i) { - var code = str.charCodeAt(i); - if (isNaN(code)) { - return ""; - } - if (code < 55296 || code > 57343) { - return str.charAt(i); - } - if (55296 <= code && code <= 56319) { - if (str.length <= i + 1) { - throw "High surrogate without following low surrogate"; - } - var next = str.charCodeAt(i + 1); - if (56320 > next || next > 57343) { - throw "High surrogate without following low surrogate"; - } - return str.charAt(i) + str.charAt(i + 1); - } - if (i === 0) { - throw "Low surrogate without preceding high surrogate"; - } - var prev = str.charCodeAt(i - 1); - if (55296 > prev || prev > 56319) { - throw "Low surrogate without preceding high surrogate"; - } - return false; - } - fabric.util.string = { - camelize: camelize, - capitalize: capitalize, - escapeXml: escapeXml, - graphemeSplit: graphemeSplit - }; -})(); - -(function() { - var slice = Array.prototype.slice, emptyFunction = function() {}, IS_DONTENUM_BUGGY = function() { - for (var p in { - toString: 1 - }) { - if (p === "toString") { - return false; - } - } - return true; - }(), addMethods = function(klass, source, parent) { - for (var property in source) { - if (property in klass.prototype && typeof klass.prototype[property] === "function" && (source[property] + "").indexOf("callSuper") > -1) { - klass.prototype[property] = function(property) { - return function() { - var superclass = this.constructor.superclass; - this.constructor.superclass = parent; - var returnValue = source[property].apply(this, arguments); - this.constructor.superclass = superclass; - if (property !== "initialize") { - return returnValue; - } - }; - }(property); - } else { - klass.prototype[property] = source[property]; - } - if (IS_DONTENUM_BUGGY) { - if (source.toString !== Object.prototype.toString) { - klass.prototype.toString = source.toString; - } - if (source.valueOf !== Object.prototype.valueOf) { - klass.prototype.valueOf = source.valueOf; - } - } - } - }; - function Subclass() {} - function callSuper(methodName) { - var parentMethod = null, _this = this; - while (_this.constructor.superclass) { - var superClassMethod = _this.constructor.superclass.prototype[methodName]; - if (_this[methodName] !== superClassMethod) { - parentMethod = superClassMethod; - break; - } - _this = _this.constructor.superclass.prototype; - } - if (!parentMethod) { - return console.log("tried to callSuper " + methodName + ", method not found in prototype chain", this); - } - return arguments.length > 1 ? parentMethod.apply(this, slice.call(arguments, 1)) : parentMethod.call(this); - } - function createClass() { - var parent = null, properties = slice.call(arguments, 0); - if (typeof properties[0] === "function") { - parent = properties.shift(); - } - function klass() { - this.initialize.apply(this, arguments); - } - klass.superclass = parent; - klass.subclasses = []; - if (parent) { - Subclass.prototype = parent.prototype; - klass.prototype = new Subclass(); - parent.subclasses.push(klass); - } - for (var i = 0, length = properties.length; i < length; i++) { - addMethods(klass, properties[i], parent); - } - if (!klass.prototype.initialize) { - klass.prototype.initialize = emptyFunction; - } - klass.prototype.constructor = klass; - klass.prototype.callSuper = callSuper; - return klass; - } - fabric.util.createClass = createClass; -})(); - -(function() { - var unknown = "unknown"; - function areHostMethods(object) { - var methodNames = Array.prototype.slice.call(arguments, 1), t, i, len = methodNames.length; - for (i = 0; i < len; i++) { - t = typeof object[methodNames[i]]; - if (!/^(?:function|object|unknown)$/.test(t)) { - return false; - } - } - return true; - } - var getElement, setElement, getUniqueId = function() { - var uid = 0; - return function(element) { - return element.__uniqueID || (element.__uniqueID = "uniqueID__" + uid++); - }; - }(); - (function() { - var elements = {}; - getElement = function(uid) { - return elements[uid]; - }; - setElement = function(uid, element) { - elements[uid] = element; - }; - })(); - function createListener(uid, handler) { - return { - handler: handler, - wrappedHandler: createWrappedHandler(uid, handler) - }; - } - function createWrappedHandler(uid, handler) { - return function(e) { - handler.call(getElement(uid), e || fabric.window.event); - }; - } - function createDispatcher(uid, eventName) { - return function(e) { - if (handlers[uid] && handlers[uid][eventName]) { - var handlersForEvent = handlers[uid][eventName]; - for (var i = 0, len = handlersForEvent.length; i < len; i++) { - handlersForEvent[i].call(this, e || fabric.window.event); - } - } - }; - } - var shouldUseAddListenerRemoveListener = areHostMethods(fabric.document.documentElement, "addEventListener", "removeEventListener") && areHostMethods(fabric.window, "addEventListener", "removeEventListener"), shouldUseAttachEventDetachEvent = areHostMethods(fabric.document.documentElement, "attachEvent", "detachEvent") && areHostMethods(fabric.window, "attachEvent", "detachEvent"), listeners = {}, handlers = {}, addListener, removeListener; - if (shouldUseAddListenerRemoveListener) { - addListener = function(element, eventName, handler, options) { - element && element.addEventListener(eventName, handler, shouldUseAttachEventDetachEvent ? false : options); - }; - removeListener = function(element, eventName, handler, options) { - element && element.removeEventListener(eventName, handler, shouldUseAttachEventDetachEvent ? false : options); - }; - } else if (shouldUseAttachEventDetachEvent) { - addListener = function(element, eventName, handler) { - if (!element) { - return; - } - var uid = getUniqueId(element); - setElement(uid, element); - if (!listeners[uid]) { - listeners[uid] = {}; - } - if (!listeners[uid][eventName]) { - listeners[uid][eventName] = []; - } - var listener = createListener(uid, handler); - listeners[uid][eventName].push(listener); - element.attachEvent("on" + eventName, listener.wrappedHandler); - }; - removeListener = function(element, eventName, handler) { - if (!element) { - return; - } - var uid = getUniqueId(element), listener; - if (listeners[uid] && listeners[uid][eventName]) { - for (var i = 0, len = listeners[uid][eventName].length; i < len; i++) { - listener = listeners[uid][eventName][i]; - if (listener && listener.handler === handler) { - element.detachEvent("on" + eventName, listener.wrappedHandler); - listeners[uid][eventName][i] = null; - } - } - } - }; - } else { - addListener = function(element, eventName, handler) { - if (!element) { - return; - } - var uid = getUniqueId(element); - if (!handlers[uid]) { - handlers[uid] = {}; - } - if (!handlers[uid][eventName]) { - handlers[uid][eventName] = []; - var existingHandler = element["on" + eventName]; - if (existingHandler) { - handlers[uid][eventName].push(existingHandler); - } - element["on" + eventName] = createDispatcher(uid, eventName); - } - handlers[uid][eventName].push(handler); - }; - removeListener = function(element, eventName, handler) { - if (!element) { - return; - } - var uid = getUniqueId(element); - if (handlers[uid] && handlers[uid][eventName]) { - var handlersForEvent = handlers[uid][eventName]; - for (var i = 0, len = handlersForEvent.length; i < len; i++) { - if (handlersForEvent[i] === handler) { - handlersForEvent.splice(i, 1); - } - } - } - }; - } - fabric.util.addListener = addListener; - fabric.util.removeListener = removeListener; - function getPointer(event) { - event || (event = fabric.window.event); - var element = event.target || (typeof event.srcElement !== unknown ? event.srcElement : null), scroll = fabric.util.getScrollLeftTop(element); - return { - x: pointerX(event) + scroll.left, - y: pointerY(event) + scroll.top - }; - } - var pointerX = function(event) { - return event.clientX; - }, pointerY = function(event) { - return event.clientY; - }; - function _getPointer(event, pageProp, clientProp) { - var touchProp = event.type === "touchend" ? "changedTouches" : "touches"; - return event[touchProp] && event[touchProp][0] ? event[touchProp][0][pageProp] - (event[touchProp][0][pageProp] - event[touchProp][0][clientProp]) || event[clientProp] : event[clientProp]; - } - if (fabric.isTouchSupported) { - pointerX = function(event) { - return _getPointer(event, "pageX", "clientX"); - }; - pointerY = function(event) { - return _getPointer(event, "pageY", "clientY"); - }; - } - fabric.util.getPointer = getPointer; -})(); - -(function() { - function setStyle(element, styles) { - var elementStyle = element.style; - if (!elementStyle) { - return element; - } - if (typeof styles === "string") { - element.style.cssText += ";" + styles; - return styles.indexOf("opacity") > -1 ? setOpacity(element, styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; - } - for (var property in styles) { - if (property === "opacity") { - setOpacity(element, styles[property]); - } else { - var normalizedProperty = property === "float" || property === "cssFloat" ? typeof elementStyle.styleFloat === "undefined" ? "cssFloat" : "styleFloat" : property; - elementStyle[normalizedProperty] = styles[property]; - } - } - return element; - } - var parseEl = fabric.document.createElement("div"), supportsOpacity = typeof parseEl.style.opacity === "string", supportsFilters = typeof parseEl.style.filter === "string", reOpacity = /alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/, setOpacity = function(element) { - return element; - }; - if (supportsOpacity) { - setOpacity = function(element, value) { - element.style.opacity = value; - return element; - }; - } else if (supportsFilters) { - setOpacity = function(element, value) { - var es = element.style; - if (element.currentStyle && !element.currentStyle.hasLayout) { - es.zoom = 1; - } - if (reOpacity.test(es.filter)) { - value = value >= .9999 ? "" : "alpha(opacity=" + value * 100 + ")"; - es.filter = es.filter.replace(reOpacity, value); - } else { - es.filter += " alpha(opacity=" + value * 100 + ")"; - } - return element; - }; - } - fabric.util.setStyle = setStyle; -})(); - -(function() { - var _slice = Array.prototype.slice; - function getById(id) { - return typeof id === "string" ? fabric.document.getElementById(id) : id; - } - var sliceCanConvertNodelists, toArray = function(arrayLike) { - return _slice.call(arrayLike, 0); - }; - try { - sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array; - } catch (err) {} - if (!sliceCanConvertNodelists) { - toArray = function(arrayLike) { - var arr = new Array(arrayLike.length), i = arrayLike.length; - while (i--) { - arr[i] = arrayLike[i]; - } - return arr; - }; - } - function makeElement(tagName, attributes) { - var el = fabric.document.createElement(tagName); - for (var prop in attributes) { - if (prop === "class") { - el.className = attributes[prop]; - } else if (prop === "for") { - el.htmlFor = attributes[prop]; - } else { - el.setAttribute(prop, attributes[prop]); - } - } - return el; - } - function addClass(element, className) { - if (element && (" " + element.className + " ").indexOf(" " + className + " ") === -1) { - element.className += (element.className ? " " : "") + className; - } - } - function wrapElement(element, wrapper, attributes) { - if (typeof wrapper === "string") { - wrapper = makeElement(wrapper, attributes); - } - if (element.parentNode) { - element.parentNode.replaceChild(wrapper, element); - } - wrapper.appendChild(element); - return wrapper; - } - function getScrollLeftTop(element) { - var left = 0, top = 0, docElement = fabric.document.documentElement, body = fabric.document.body || { - scrollLeft: 0, - scrollTop: 0 - }; - while (element && (element.parentNode || element.host)) { - element = element.parentNode || element.host; - if (element === fabric.document) { - left = body.scrollLeft || docElement.scrollLeft || 0; - top = body.scrollTop || docElement.scrollTop || 0; - } else { - left += element.scrollLeft || 0; - top += element.scrollTop || 0; - } - if (element.nodeType === 1 && element.style.position === "fixed") { - break; - } - } - return { - left: left, - top: top - }; - } - function getElementOffset(element) { - var docElem, doc = element && element.ownerDocument, box = { - left: 0, - top: 0 - }, offset = { - left: 0, - top: 0 - }, scrollLeftTop, offsetAttributes = { - borderLeftWidth: "left", - borderTopWidth: "top", - paddingLeft: "left", - paddingTop: "top" - }; - if (!doc) { - return offset; - } - for (var attr in offsetAttributes) { - offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0; - } - docElem = doc.documentElement; - if (typeof element.getBoundingClientRect !== "undefined") { - box = element.getBoundingClientRect(); - } - scrollLeftTop = getScrollLeftTop(element); - return { - left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left, - top: box.top + scrollLeftTop.top - (docElem.clientTop || 0) + offset.top - }; - } - var getElementStyle; - if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) { - getElementStyle = function(element, attr) { - var style = fabric.document.defaultView.getComputedStyle(element, null); - return style ? style[attr] : undefined; - }; - } else { - getElementStyle = function(element, attr) { - var value = element.style[attr]; - if (!value && element.currentStyle) { - value = element.currentStyle[attr]; - } - return value; - }; - } - (function() { - var style = fabric.document.documentElement.style, selectProp = "userSelect" in style ? "userSelect" : "MozUserSelect" in style ? "MozUserSelect" : "WebkitUserSelect" in style ? "WebkitUserSelect" : "KhtmlUserSelect" in style ? "KhtmlUserSelect" : ""; - function makeElementUnselectable(element) { - if (typeof element.onselectstart !== "undefined") { - element.onselectstart = fabric.util.falseFunction; - } - if (selectProp) { - element.style[selectProp] = "none"; - } else if (typeof element.unselectable === "string") { - element.unselectable = "on"; - } - return element; - } - function makeElementSelectable(element) { - if (typeof element.onselectstart !== "undefined") { - element.onselectstart = null; - } - if (selectProp) { - element.style[selectProp] = ""; - } else if (typeof element.unselectable === "string") { - element.unselectable = ""; - } - return element; - } - fabric.util.makeElementUnselectable = makeElementUnselectable; - fabric.util.makeElementSelectable = makeElementSelectable; - })(); - (function() { - function getScript(url, callback) { - var headEl = fabric.document.getElementsByTagName("head")[0], scriptEl = fabric.document.createElement("script"), loading = true; - scriptEl.onload = scriptEl.onreadystatechange = function(e) { - if (loading) { - if (typeof this.readyState === "string" && this.readyState !== "loaded" && this.readyState !== "complete") { - return; - } - loading = false; - callback(e || fabric.window.event); - scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null; - } - }; - scriptEl.src = url; - headEl.appendChild(scriptEl); - } - fabric.util.getScript = getScript; - })(); - function getNodeCanvas(element) { - var impl = fabric.jsdomImplForWrapper(element); - return impl._canvas || impl._image; - } - fabric.util.getById = getById; - fabric.util.toArray = toArray; - fabric.util.makeElement = makeElement; - fabric.util.addClass = addClass; - fabric.util.wrapElement = wrapElement; - fabric.util.getScrollLeftTop = getScrollLeftTop; - fabric.util.getElementOffset = getElementOffset; - fabric.util.getElementStyle = getElementStyle; - fabric.util.getNodeCanvas = getNodeCanvas; -})(); - -(function() { - function addParamToUrl(url, param) { - return url + (/\?/.test(url) ? "&" : "?") + param; - } - var makeXHR = function() { - var factories = [ function() { - return new ActiveXObject("Microsoft.XMLHTTP"); - }, function() { - return new ActiveXObject("Msxml2.XMLHTTP"); - }, function() { - return new ActiveXObject("Msxml2.XMLHTTP.3.0"); - }, function() { - return new XMLHttpRequest(); - } ]; - for (var i = factories.length; i--; ) { - try { - var req = factories[i](); - if (req) { - return factories[i]; - } - } catch (err) {} - } - }(); - function emptyFn() {} - function request(url, options) { - options || (options = {}); - var method = options.method ? options.method.toUpperCase() : "GET", onComplete = options.onComplete || function() {}, xhr = makeXHR(), body = options.body || options.parameters; - xhr.onreadystatechange = function() { - if (xhr.readyState === 4) { - onComplete(xhr); - xhr.onreadystatechange = emptyFn; - } - }; - if (method === "GET") { - body = null; - if (typeof options.parameters === "string") { - url = addParamToUrl(url, options.parameters); - } - } - xhr.open(method, url, true); - if (method === "POST" || method === "PUT") { - xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - } - xhr.send(body); - return xhr; - } - fabric.util.request = request; -})(); - -fabric.log = function() {}; - -fabric.warn = function() {}; - -if (typeof console !== "undefined") { - [ "log", "warn" ].forEach(function(methodName) { - if (typeof console[methodName] !== "undefined" && typeof console[methodName].apply === "function") { - fabric[methodName] = function() { - return console[methodName].apply(console, arguments); - }; - } - }); -} - -(function() { - function noop() { - return false; - } - function animate(options) { - requestAnimFrame(function(timestamp) { - options || (options = {}); - var start = timestamp || +new Date(), duration = options.duration || 500, finish = start + duration, time, onChange = options.onChange || noop, abort = options.abort || noop, onComplete = options.onComplete || noop, easing = options.easing || function(t, b, c, d) { - return -c * Math.cos(t / d * (Math.PI / 2)) + c + b; - }, startValue = "startValue" in options ? options.startValue : 0, endValue = "endValue" in options ? options.endValue : 100, byValue = options.byValue || endValue - startValue; - options.onStart && options.onStart(); - (function tick(ticktime) { - if (abort()) { - onComplete(endValue, 1, 1); - return; - } - time = ticktime || +new Date(); - var currentTime = time > finish ? duration : time - start, timePerc = currentTime / duration, current = easing(currentTime, startValue, byValue, duration), valuePerc = Math.abs((current - startValue) / byValue); - onChange(current, valuePerc, timePerc); - if (time > finish) { - options.onComplete && options.onComplete(); - return; - } - requestAnimFrame(tick); - })(start); - }); - } - var _requestAnimFrame = fabric.window.requestAnimationFrame || fabric.window.webkitRequestAnimationFrame || fabric.window.mozRequestAnimationFrame || fabric.window.oRequestAnimationFrame || fabric.window.msRequestAnimationFrame || function(callback) { - return fabric.window.setTimeout(callback, 1e3 / 60); - }; - var _cancelAnimFrame = fabric.window.cancelAnimationFrame || fabric.window.clearTimeout; - function requestAnimFrame() { - return _requestAnimFrame.apply(fabric.window, arguments); - } - function cancelAnimFrame() { - return _cancelAnimFrame.apply(fabric.window, arguments); - } - fabric.util.animate = animate; - fabric.util.requestAnimFrame = requestAnimFrame; - fabric.util.cancelAnimFrame = cancelAnimFrame; -})(); - -(function() { - function calculateColor(begin, end, pos) { - var color = "rgba(" + parseInt(begin[0] + pos * (end[0] - begin[0]), 10) + "," + parseInt(begin[1] + pos * (end[1] - begin[1]), 10) + "," + parseInt(begin[2] + pos * (end[2] - begin[2]), 10); - color += "," + (begin && end ? parseFloat(begin[3] + pos * (end[3] - begin[3])) : 1); - color += ")"; - return color; - } - function animateColor(fromColor, toColor, duration, options) { - var startColor = new fabric.Color(fromColor).getSource(), endColor = new fabric.Color(toColor).getSource(); - options = options || {}; - fabric.util.animate(fabric.util.object.extend(options, { - duration: duration || 500, - startValue: startColor, - endValue: endColor, - byValue: endColor, - easing: function(currentTime, startValue, byValue, duration) { - var posValue = options.colorEasing ? options.colorEasing(currentTime, duration) : 1 - Math.cos(currentTime / duration * (Math.PI / 2)); - return calculateColor(startValue, byValue, posValue); - } - })); - } - fabric.util.animateColor = animateColor; -})(); - -(function() { - function normalize(a, c, p, s) { - if (a < Math.abs(c)) { - a = c; - s = p / 4; - } else { - if (c === 0 && a === 0) { - s = p / (2 * Math.PI) * Math.asin(1); - } else { - s = p / (2 * Math.PI) * Math.asin(c / a); - } - } - return { - a: a, - c: c, - p: p, - s: s - }; - } - function elastic(opts, t, d) { - return opts.a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p); - } - function easeOutCubic(t, b, c, d) { - return c * ((t = t / d - 1) * t * t + 1) + b; - } - function easeInOutCubic(t, b, c, d) { - t /= d / 2; - if (t < 1) { - return c / 2 * t * t * t + b; - } - return c / 2 * ((t -= 2) * t * t + 2) + b; - } - function easeInQuart(t, b, c, d) { - return c * (t /= d) * t * t * t + b; - } - function easeOutQuart(t, b, c, d) { - return -c * ((t = t / d - 1) * t * t * t - 1) + b; - } - function easeInOutQuart(t, b, c, d) { - t /= d / 2; - if (t < 1) { - return c / 2 * t * t * t * t + b; - } - return -c / 2 * ((t -= 2) * t * t * t - 2) + b; - } - function easeInQuint(t, b, c, d) { - return c * (t /= d) * t * t * t * t + b; - } - function easeOutQuint(t, b, c, d) { - return c * ((t = t / d - 1) * t * t * t * t + 1) + b; - } - function easeInOutQuint(t, b, c, d) { - t /= d / 2; - if (t < 1) { - return c / 2 * t * t * t * t * t + b; - } - return c / 2 * ((t -= 2) * t * t * t * t + 2) + b; - } - function easeInSine(t, b, c, d) { - return -c * Math.cos(t / d * (Math.PI / 2)) + c + b; - } - function easeOutSine(t, b, c, d) { - return c * Math.sin(t / d * (Math.PI / 2)) + b; - } - function easeInOutSine(t, b, c, d) { - return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b; - } - function easeInExpo(t, b, c, d) { - return t === 0 ? b : c * Math.pow(2, 10 * (t / d - 1)) + b; - } - function easeOutExpo(t, b, c, d) { - return t === d ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b; - } - function easeInOutExpo(t, b, c, d) { - if (t === 0) { - return b; - } - if (t === d) { - return b + c; - } - t /= d / 2; - if (t < 1) { - return c / 2 * Math.pow(2, 10 * (t - 1)) + b; - } - return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b; - } - function easeInCirc(t, b, c, d) { - return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b; - } - function easeOutCirc(t, b, c, d) { - return c * Math.sqrt(1 - (t = t / d - 1) * t) + b; - } - function easeInOutCirc(t, b, c, d) { - t /= d / 2; - if (t < 1) { - return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b; - } - return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b; - } - function easeInElastic(t, b, c, d) { - var s = 1.70158, p = 0, a = c; - if (t === 0) { - return b; - } - t /= d; - if (t === 1) { - return b + c; - } - if (!p) { - p = d * .3; - } - var opts = normalize(a, c, p, s); - return -elastic(opts, t, d) + b; - } - function easeOutElastic(t, b, c, d) { - var s = 1.70158, p = 0, a = c; - if (t === 0) { - return b; - } - t /= d; - if (t === 1) { - return b + c; - } - if (!p) { - p = d * .3; - } - var opts = normalize(a, c, p, s); - return opts.a * Math.pow(2, -10 * t) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p) + opts.c + b; - } - function easeInOutElastic(t, b, c, d) { - var s = 1.70158, p = 0, a = c; - if (t === 0) { - return b; - } - t /= d / 2; - if (t === 2) { - return b + c; - } - if (!p) { - p = d * (.3 * 1.5); - } - var opts = normalize(a, c, p, s); - if (t < 1) { - return -.5 * elastic(opts, t, d) + b; - } - return opts.a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p) * .5 + opts.c + b; - } - function easeInBack(t, b, c, d, s) { - if (s === undefined) { - s = 1.70158; - } - return c * (t /= d) * t * ((s + 1) * t - s) + b; - } - function easeOutBack(t, b, c, d, s) { - if (s === undefined) { - s = 1.70158; - } - return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; - } - function easeInOutBack(t, b, c, d, s) { - if (s === undefined) { - s = 1.70158; - } - t /= d / 2; - if (t < 1) { - return c / 2 * (t * t * (((s *= 1.525) + 1) * t - s)) + b; - } - return c / 2 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2) + b; - } - function easeInBounce(t, b, c, d) { - return c - easeOutBounce(d - t, 0, c, d) + b; - } - function easeOutBounce(t, b, c, d) { - if ((t /= d) < 1 / 2.75) { - return c * (7.5625 * t * t) + b; - } else if (t < 2 / 2.75) { - return c * (7.5625 * (t -= 1.5 / 2.75) * t + .75) + b; - } else if (t < 2.5 / 2.75) { - return c * (7.5625 * (t -= 2.25 / 2.75) * t + .9375) + b; - } else { - return c * (7.5625 * (t -= 2.625 / 2.75) * t + .984375) + b; - } - } - function easeInOutBounce(t, b, c, d) { - if (t < d / 2) { - return easeInBounce(t * 2, 0, c, d) * .5 + b; - } - return easeOutBounce(t * 2 - d, 0, c, d) * .5 + c * .5 + b; - } - fabric.util.ease = { - easeInQuad: function(t, b, c, d) { - return c * (t /= d) * t + b; - }, - easeOutQuad: function(t, b, c, d) { - return -c * (t /= d) * (t - 2) + b; - }, - easeInOutQuad: function(t, b, c, d) { - t /= d / 2; - if (t < 1) { - return c / 2 * t * t + b; - } - return -c / 2 * (--t * (t - 2) - 1) + b; - }, - easeInCubic: function(t, b, c, d) { - return c * (t /= d) * t * t + b; - }, - easeOutCubic: easeOutCubic, - easeInOutCubic: easeInOutCubic, - easeInQuart: easeInQuart, - easeOutQuart: easeOutQuart, - easeInOutQuart: easeInOutQuart, - easeInQuint: easeInQuint, - easeOutQuint: easeOutQuint, - easeInOutQuint: easeInOutQuint, - easeInSine: easeInSine, - easeOutSine: easeOutSine, - easeInOutSine: easeInOutSine, - easeInExpo: easeInExpo, - easeOutExpo: easeOutExpo, - easeInOutExpo: easeInOutExpo, - easeInCirc: easeInCirc, - easeOutCirc: easeOutCirc, - easeInOutCirc: easeInOutCirc, - easeInElastic: easeInElastic, - easeOutElastic: easeOutElastic, - easeInOutElastic: easeInOutElastic, - easeInBack: easeInBack, - easeOutBack: easeOutBack, - easeInOutBack: easeInOutBack, - easeInBounce: easeInBounce, - easeOutBounce: easeOutBounce, - easeInOutBounce: easeInOutBounce - }; -})(); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, clone = fabric.util.object.clone, toFixed = fabric.util.toFixed, parseUnit = fabric.util.parseUnit, multiplyTransformMatrices = fabric.util.multiplyTransformMatrices, svgValidTagNames = [ "path", "circle", "polygon", "polyline", "ellipse", "rect", "line", "image", "text", "linearGradient", "radialGradient", "stop" ], svgViewBoxElements = [ "symbol", "image", "marker", "pattern", "view", "svg" ], svgInvalidAncestors = [ "pattern", "defs", "symbol", "metadata", "clipPath", "mask", "desc" ], svgValidParents = [ "symbol", "g", "a", "svg" ], attributesMap = { - cx: "left", - x: "left", - r: "radius", - cy: "top", - y: "top", - display: "visible", - visibility: "visible", - transform: "transformMatrix", - "fill-opacity": "fillOpacity", - "fill-rule": "fillRule", - "font-family": "fontFamily", - "font-size": "fontSize", - "font-style": "fontStyle", - "font-weight": "fontWeight", - "paint-order": "paintFirst", - "stroke-dasharray": "strokeDashArray", - "stroke-linecap": "strokeLineCap", - "stroke-linejoin": "strokeLineJoin", - "stroke-miterlimit": "strokeMiterLimit", - "stroke-opacity": "strokeOpacity", - "stroke-width": "strokeWidth", - "text-decoration": "textDecoration", - "text-anchor": "textAnchor", - opacity: "opacity" - }, colorAttributes = { - stroke: "strokeOpacity", - fill: "fillOpacity" - }; - fabric.svgValidTagNamesRegEx = getSvgRegex(svgValidTagNames); - fabric.svgViewBoxElementsRegEx = getSvgRegex(svgViewBoxElements); - fabric.svgInvalidAncestorsRegEx = getSvgRegex(svgInvalidAncestors); - fabric.svgValidParentsRegEx = getSvgRegex(svgValidParents); - fabric.cssRules = {}; - fabric.gradientDefs = {}; - function normalizeAttr(attr) { - if (attr in attributesMap) { - return attributesMap[attr]; - } - return attr; - } - function normalizeValue(attr, value, parentAttributes, fontSize) { - var isArray = Object.prototype.toString.call(value) === "[object Array]", parsed; - if ((attr === "fill" || attr === "stroke") && value === "none") { - value = ""; - } else if (attr === "strokeDashArray") { - if (value === "none") { - value = null; - } else { - value = value.replace(/,/g, " ").split(/\s+/).map(function(n) { - return parseFloat(n); - }); - } - } else if (attr === "transformMatrix") { - if (parentAttributes && parentAttributes.transformMatrix) { - value = multiplyTransformMatrices(parentAttributes.transformMatrix, fabric.parseTransformAttribute(value)); - } else { - value = fabric.parseTransformAttribute(value); - } - } else if (attr === "visible") { - value = value !== "none" && value !== "hidden"; - if (parentAttributes && parentAttributes.visible === false) { - value = false; - } - } else if (attr === "opacity") { - value = parseFloat(value); - if (parentAttributes && typeof parentAttributes.opacity !== "undefined") { - value *= parentAttributes.opacity; - } - } else if (attr === "textAnchor") { - value = value === "start" ? "left" : value === "end" ? "right" : "center"; - } else if (attr === "paintFirst") { - var fillIndex = value.indexOf("fill"); - var strokeIndex = value.indexOf("stroke"); - var value = "fill"; - if (fillIndex > -1 && strokeIndex > -1 && strokeIndex < fillIndex) { - value = "stroke"; - } else if (fillIndex === -1 && strokeIndex > -1) { - value = "stroke"; - } - } else { - parsed = isArray ? value.map(parseUnit) : parseUnit(value, fontSize); - } - return !isArray && isNaN(parsed) ? value : parsed; - } - function getSvgRegex(arr) { - return new RegExp("^(" + arr.join("|") + ")\\b", "i"); - } - function _setStrokeFillOpacity(attributes) { - for (var attr in colorAttributes) { - if (typeof attributes[colorAttributes[attr]] === "undefined" || attributes[attr] === "") { - continue; - } - if (typeof attributes[attr] === "undefined") { - if (!fabric.Object.prototype[attr]) { - continue; - } - attributes[attr] = fabric.Object.prototype[attr]; - } - if (attributes[attr].indexOf("url(") === 0) { - continue; - } - var color = new fabric.Color(attributes[attr]); - attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba(); - } - return attributes; - } - function _getMultipleNodes(doc, nodeNames) { - var nodeName, nodeArray = [], nodeList, i, len; - for (i = 0, len = nodeNames.length; i < len; i++) { - nodeName = nodeNames[i]; - nodeList = doc.getElementsByTagName(nodeName); - nodeArray = nodeArray.concat(Array.prototype.slice.call(nodeList)); - } - return nodeArray; - } - fabric.parseTransformAttribute = function() { - function rotateMatrix(matrix, args) { - var cos = Math.cos(args[0]), sin = Math.sin(args[0]), x = 0, y = 0; - if (args.length === 3) { - x = args[1]; - y = args[2]; - } - matrix[0] = cos; - matrix[1] = sin; - matrix[2] = -sin; - matrix[3] = cos; - matrix[4] = x - (cos * x - sin * y); - matrix[5] = y - (sin * x + cos * y); - } - function scaleMatrix(matrix, args) { - var multiplierX = args[0], multiplierY = args.length === 2 ? args[1] : args[0]; - matrix[0] = multiplierX; - matrix[3] = multiplierY; - } - function skewMatrix(matrix, args, pos) { - matrix[pos] = Math.tan(fabric.util.degreesToRadians(args[0])); - } - function translateMatrix(matrix, args) { - matrix[4] = args[0]; - if (args.length === 2) { - matrix[5] = args[1]; - } - } - var iMatrix = [ 1, 0, 0, 1, 0, 0 ], number = fabric.reNum, commaWsp = "(?:\\s+,?\\s*|,\\s*)", skewX = "(?:(skewX)\\s*\\(\\s*(" + number + ")\\s*\\))", skewY = "(?:(skewY)\\s*\\(\\s*(" + number + ")\\s*\\))", rotate = "(?:(rotate)\\s*\\(\\s*(" + number + ")(?:" + commaWsp + "(" + number + ")" + commaWsp + "(" + number + "))?\\s*\\))", scale = "(?:(scale)\\s*\\(\\s*(" + number + ")(?:" + commaWsp + "(" + number + "))?\\s*\\))", translate = "(?:(translate)\\s*\\(\\s*(" + number + ")(?:" + commaWsp + "(" + number + "))?\\s*\\))", matrix = "(?:(matrix)\\s*\\(\\s*" + "(" + number + ")" + commaWsp + "(" + number + ")" + commaWsp + "(" + number + ")" + commaWsp + "(" + number + ")" + commaWsp + "(" + number + ")" + commaWsp + "(" + number + ")" + "\\s*\\))", transform = "(?:" + matrix + "|" + translate + "|" + scale + "|" + rotate + "|" + skewX + "|" + skewY + ")", transforms = "(?:" + transform + "(?:" + commaWsp + "*" + transform + ")*" + ")", transformList = "^\\s*(?:" + transforms + "?)\\s*$", reTransformList = new RegExp(transformList), reTransform = new RegExp(transform, "g"); - return function(attributeValue) { - var matrix = iMatrix.concat(), matrices = []; - if (!attributeValue || attributeValue && !reTransformList.test(attributeValue)) { - return matrix; - } - attributeValue.replace(reTransform, function(match) { - var m = new RegExp(transform).exec(match).filter(function(match) { - return !!match; - }), operation = m[1], args = m.slice(2).map(parseFloat); - switch (operation) { - case "translate": - translateMatrix(matrix, args); - break; - - case "rotate": - args[0] = fabric.util.degreesToRadians(args[0]); - rotateMatrix(matrix, args); - break; - - case "scale": - scaleMatrix(matrix, args); - break; - - case "skewX": - skewMatrix(matrix, args, 2); - break; - - case "skewY": - skewMatrix(matrix, args, 1); - break; - - case "matrix": - matrix = args; - break; - } - matrices.push(matrix.concat()); - matrix = iMatrix.concat(); - }); - var combinedMatrix = matrices[0]; - while (matrices.length > 1) { - matrices.shift(); - combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]); - } - return combinedMatrix; - }; - }(); - function parseStyleString(style, oStyle) { - var attr, value; - style.replace(/;\s*$/, "").split(";").forEach(function(chunk) { - var pair = chunk.split(":"); - attr = pair[0].trim().toLowerCase(); - value = pair[1].trim(); - oStyle[attr] = value; - }); - } - function parseStyleObject(style, oStyle) { - var attr, value; - for (var prop in style) { - if (typeof style[prop] === "undefined") { - continue; - } - attr = prop.toLowerCase(); - value = style[prop]; - oStyle[attr] = value; - } - } - function getGlobalStylesForElement(element, svgUid) { - var styles = {}; - for (var rule in fabric.cssRules[svgUid]) { - if (elementMatchesRule(element, rule.split(" "))) { - for (var property in fabric.cssRules[svgUid][rule]) { - styles[property] = fabric.cssRules[svgUid][rule][property]; - } - } - } - return styles; - } - function elementMatchesRule(element, selectors) { - var firstMatching, parentMatching = true; - firstMatching = selectorMatches(element, selectors.pop()); - if (firstMatching && selectors.length) { - parentMatching = doesSomeParentMatch(element, selectors); - } - return firstMatching && parentMatching && selectors.length === 0; - } - function doesSomeParentMatch(element, selectors) { - var selector, parentMatching = true; - while (element.parentNode && element.parentNode.nodeType === 1 && selectors.length) { - if (parentMatching) { - selector = selectors.pop(); - } - element = element.parentNode; - parentMatching = selectorMatches(element, selector); - } - return selectors.length === 0; - } - function selectorMatches(element, selector) { - var nodeName = element.nodeName, classNames = element.getAttribute("class"), id = element.getAttribute("id"), matcher, i; - matcher = new RegExp("^" + nodeName, "i"); - selector = selector.replace(matcher, ""); - if (id && selector.length) { - matcher = new RegExp("#" + id + "(?![a-zA-Z\\-]+)", "i"); - selector = selector.replace(matcher, ""); - } - if (classNames && selector.length) { - classNames = classNames.split(" "); - for (i = classNames.length; i--; ) { - matcher = new RegExp("\\." + classNames[i] + "(?![a-zA-Z\\-]+)", "i"); - selector = selector.replace(matcher, ""); - } - } - return selector.length === 0; - } - function elementById(doc, id) { - var el; - doc.getElementById && (el = doc.getElementById(id)); - if (el) { - return el; - } - var node, i, len, nodelist = doc.getElementsByTagName("*"); - for (i = 0, len = nodelist.length; i < len; i++) { - node = nodelist[i]; - if (id === node.getAttribute("id")) { - return node; - } - } - } - function parseUseDirectives(doc) { - var nodelist = _getMultipleNodes(doc, [ "use", "svg:use" ]), i = 0; - while (nodelist.length && i < nodelist.length) { - var el = nodelist[i], xlink = el.getAttribute("xlink:href").substr(1), x = el.getAttribute("x") || 0, y = el.getAttribute("y") || 0, el2 = elementById(doc, xlink).cloneNode(true), currentTrans = (el2.getAttribute("transform") || "") + " translate(" + x + ", " + y + ")", parentNode, oldLength = nodelist.length, attr, j, attrs, len; - applyViewboxTransform(el2); - if (/^svg$/i.test(el2.nodeName)) { - var el3 = el2.ownerDocument.createElement("g"); - for (j = 0, attrs = el2.attributes, len = attrs.length; j < len; j++) { - attr = attrs.item(j); - el3.setAttribute(attr.nodeName, attr.nodeValue); - } - while (el2.firstChild) { - el3.appendChild(el2.firstChild); - } - el2 = el3; - } - for (j = 0, attrs = el.attributes, len = attrs.length; j < len; j++) { - attr = attrs.item(j); - if (attr.nodeName === "x" || attr.nodeName === "y" || attr.nodeName === "xlink:href") { - continue; - } - if (attr.nodeName === "transform") { - currentTrans = attr.nodeValue + " " + currentTrans; - } else { - el2.setAttribute(attr.nodeName, attr.nodeValue); - } - } - el2.setAttribute("transform", currentTrans); - el2.setAttribute("instantiated_by_use", "1"); - el2.removeAttribute("id"); - parentNode = el.parentNode; - parentNode.replaceChild(el2, el); - if (nodelist.length === oldLength) { - i++; - } - } - } - var reViewBoxAttrValue = new RegExp("^" + "\\s*(" + fabric.reNum + "+)\\s*,?" + "\\s*(" + fabric.reNum + "+)\\s*,?" + "\\s*(" + fabric.reNum + "+)\\s*,?" + "\\s*(" + fabric.reNum + "+)\\s*" + "$"); - function applyViewboxTransform(element) { - var viewBoxAttr = element.getAttribute("viewBox"), scaleX = 1, scaleY = 1, minX = 0, minY = 0, viewBoxWidth, viewBoxHeight, matrix, el, widthAttr = element.getAttribute("width"), heightAttr = element.getAttribute("height"), x = element.getAttribute("x") || 0, y = element.getAttribute("y") || 0, preserveAspectRatio = element.getAttribute("preserveAspectRatio") || "", missingViewBox = !viewBoxAttr || !fabric.svgViewBoxElementsRegEx.test(element.nodeName) || !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue)), missingDimAttr = !widthAttr || !heightAttr || widthAttr === "100%" || heightAttr === "100%", toBeParsed = missingViewBox && missingDimAttr, parsedDim = {}, translateMatrix = ""; - parsedDim.width = 0; - parsedDim.height = 0; - parsedDim.toBeParsed = toBeParsed; - if (toBeParsed) { - return parsedDim; - } - if (missingViewBox) { - parsedDim.width = parseUnit(widthAttr); - parsedDim.height = parseUnit(heightAttr); - return parsedDim; - } - minX = -parseFloat(viewBoxAttr[1]); - minY = -parseFloat(viewBoxAttr[2]); - viewBoxWidth = parseFloat(viewBoxAttr[3]); - viewBoxHeight = parseFloat(viewBoxAttr[4]); - if (!missingDimAttr) { - parsedDim.width = parseUnit(widthAttr); - parsedDim.height = parseUnit(heightAttr); - scaleX = parsedDim.width / viewBoxWidth; - scaleY = parsedDim.height / viewBoxHeight; - } else { - parsedDim.width = viewBoxWidth; - parsedDim.height = viewBoxHeight; - } - preserveAspectRatio = fabric.util.parsePreserveAspectRatioAttribute(preserveAspectRatio); - if (preserveAspectRatio.alignX !== "none") { - scaleY = scaleX = scaleX > scaleY ? scaleY : scaleX; - } - if (scaleX === 1 && scaleY === 1 && minX === 0 && minY === 0 && x === 0 && y === 0) { - return parsedDim; - } - if (x || y) { - translateMatrix = " translate(" + parseUnit(x) + " " + parseUnit(y) + ") "; - } - matrix = translateMatrix + " matrix(" + scaleX + " 0" + " 0 " + scaleY + " " + minX * scaleX + " " + minY * scaleY + ") "; - if (element.nodeName === "svg") { - el = element.ownerDocument.createElement("g"); - while (element.firstChild) { - el.appendChild(element.firstChild); - } - element.appendChild(el); - } else { - el = element; - matrix = el.getAttribute("transform") + matrix; - } - el.setAttribute("transform", matrix); - return parsedDim; - } - function hasAncestorWithNodeName(element, nodeName) { - while (element && (element = element.parentNode)) { - if (element.nodeName && nodeName.test(element.nodeName.replace("svg:", "")) && !element.getAttribute("instantiated_by_use")) { - return true; - } - } - return false; - } - fabric.parseSVGDocument = function(doc, callback, reviver, parsingOptions) { - if (!doc) { - return; - } - parseUseDirectives(doc); - var svgUid = fabric.Object.__uid++, i, len, options = applyViewboxTransform(doc), descendants = fabric.util.toArray(doc.getElementsByTagName("*")); - options.crossOrigin = parsingOptions && parsingOptions.crossOrigin; - options.svgUid = svgUid; - if (descendants.length === 0 && fabric.isLikelyNode) { - descendants = doc.selectNodes('//*[name(.)!="svg"]'); - var arr = []; - for (i = 0, len = descendants.length; i < len; i++) { - arr[i] = descendants[i]; - } - descendants = arr; - } - var elements = descendants.filter(function(el) { - applyViewboxTransform(el); - return fabric.svgValidTagNamesRegEx.test(el.nodeName.replace("svg:", "")) && !hasAncestorWithNodeName(el, fabric.svgInvalidAncestorsRegEx); - }); - if (!elements || elements && !elements.length) { - callback && callback([], {}); - return; - } - fabric.gradientDefs[svgUid] = fabric.getGradientDefs(doc); - fabric.cssRules[svgUid] = fabric.getCSSRules(doc); - fabric.parseElements(elements, function(instances, elements) { - if (callback) { - callback(instances, options, elements, descendants); - } - }, clone(options), reviver, parsingOptions); - }; - var reFontDeclaration = new RegExp("(normal|italic)?\\s*(normal|small-caps)?\\s*" + "(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\\s*(" + fabric.reNum + "(?:px|cm|mm|em|pt|pc|in)*)(?:\\/(normal|" + fabric.reNum + "))?\\s+(.*)"); - extend(fabric, { - parseFontDeclaration: function(value, oStyle) { - var match = value.match(reFontDeclaration); - if (!match) { - return; - } - var fontStyle = match[1], fontWeight = match[3], fontSize = match[4], lineHeight = match[5], fontFamily = match[6]; - if (fontStyle) { - oStyle.fontStyle = fontStyle; - } - if (fontWeight) { - oStyle.fontWeight = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight); - } - if (fontSize) { - oStyle.fontSize = parseUnit(fontSize); - } - if (fontFamily) { - oStyle.fontFamily = fontFamily; - } - if (lineHeight) { - oStyle.lineHeight = lineHeight === "normal" ? 1 : lineHeight; - } - }, - getGradientDefs: function(doc) { - var tagArray = [ "linearGradient", "radialGradient", "svg:linearGradient", "svg:radialGradient" ], elList = _getMultipleNodes(doc, tagArray), el, j = 0, id, xlink, gradientDefs = {}, idsToXlinkMap = {}; - j = elList.length; - while (j--) { - el = elList[j]; - xlink = el.getAttribute("xlink:href"); - id = el.getAttribute("id"); - if (xlink) { - idsToXlinkMap[id] = xlink.substr(1); - } - gradientDefs[id] = el; - } - for (id in idsToXlinkMap) { - var el2 = gradientDefs[idsToXlinkMap[id]].cloneNode(true); - el = gradientDefs[id]; - while (el2.firstChild) { - el.appendChild(el2.firstChild); - } - } - return gradientDefs; - }, - parseAttributes: function(element, attributes, svgUid) { - if (!element) { - return; - } - var value, parentAttributes = {}, fontSize; - if (typeof svgUid === "undefined") { - svgUid = element.getAttribute("svgUid"); - } - if (element.parentNode && fabric.svgValidParentsRegEx.test(element.parentNode.nodeName)) { - parentAttributes = fabric.parseAttributes(element.parentNode, attributes, svgUid); - } - fontSize = parentAttributes && parentAttributes.fontSize || element.getAttribute("font-size") || fabric.Text.DEFAULT_SVG_FONT_SIZE; - var ownAttributes = attributes.reduce(function(memo, attr) { - value = element.getAttribute(attr); - if (value) { - memo[attr] = value; - } - return memo; - }, {}); - ownAttributes = extend(ownAttributes, extend(getGlobalStylesForElement(element, svgUid), fabric.parseStyleAttribute(element))); - var normalizedAttr, normalizedValue, normalizedStyle = {}; - for (var attr in ownAttributes) { - normalizedAttr = normalizeAttr(attr); - normalizedValue = normalizeValue(normalizedAttr, ownAttributes[attr], parentAttributes, fontSize); - normalizedStyle[normalizedAttr] = normalizedValue; - } - if (normalizedStyle && normalizedStyle.font) { - fabric.parseFontDeclaration(normalizedStyle.font, normalizedStyle); - } - var mergedAttrs = extend(parentAttributes, normalizedStyle); - return fabric.svgValidParentsRegEx.test(element.nodeName) ? mergedAttrs : _setStrokeFillOpacity(mergedAttrs); - }, - parseElements: function(elements, callback, options, reviver, parsingOptions) { - new fabric.ElementsParser(elements, callback, options, reviver, parsingOptions).parse(); - }, - parseStyleAttribute: function(element) { - var oStyle = {}, style = element.getAttribute("style"); - if (!style) { - return oStyle; - } - if (typeof style === "string") { - parseStyleString(style, oStyle); - } else { - parseStyleObject(style, oStyle); - } - return oStyle; - }, - parsePointsAttribute: function(points) { - if (!points) { - return null; - } - points = points.replace(/,/g, " ").trim(); - points = points.split(/\s+/); - var parsedPoints = [], i, len; - for (i = 0, len = points.length; i < len; i += 2) { - parsedPoints.push({ - x: parseFloat(points[i]), - y: parseFloat(points[i + 1]) - }); - } - return parsedPoints; - }, - getCSSRules: function(doc) { - var styles = doc.getElementsByTagName("style"), i, len, allRules = {}, rules; - for (i = 0, len = styles.length; i < len; i++) { - var styleContents = styles[i].textContent || styles[i].text; - styleContents = styleContents.replace(/\/\*[\s\S]*?\*\//g, ""); - if (styleContents.trim() === "") { - continue; - } - rules = styleContents.match(/[^{]*\{[\s\S]*?\}/g); - rules = rules.map(function(rule) { - return rule.trim(); - }); - rules.forEach(function(rule) { - var match = rule.match(/([\s\S]*?)\s*\{([^}]*)\}/), ruleObj = {}, declaration = match[2].trim(), propertyValuePairs = declaration.replace(/;$/, "").split(/\s*;\s*/); - for (i = 0, len = propertyValuePairs.length; i < len; i++) { - var pair = propertyValuePairs[i].split(/\s*:\s*/), property = pair[0], value = pair[1]; - ruleObj[property] = value; - } - rule = match[1]; - rule.split(",").forEach(function(_rule) { - _rule = _rule.replace(/^svg/i, "").trim(); - if (_rule === "") { - return; - } - if (allRules[_rule]) { - fabric.util.object.extend(allRules[_rule], ruleObj); - } else { - allRules[_rule] = fabric.util.object.clone(ruleObj); - } - }); - }); - } - return allRules; - }, - loadSVGFromURL: function(url, callback, reviver, options) { - url = url.replace(/^\n\s*/, "").trim(); - new fabric.util.request(url, { - method: "get", - onComplete: onComplete - }); - function onComplete(r) { - var xml = r.responseXML; - if (xml && !xml.documentElement && fabric.window.ActiveXObject && r.responseText) { - xml = new ActiveXObject("Microsoft.XMLDOM"); - xml.async = "false"; - xml.loadXML(r.responseText.replace(//i, "")); - } - if (!xml || !xml.documentElement) { - callback && callback(null); - } - fabric.parseSVGDocument(xml.documentElement, function(results, _options, elements, allElements) { - callback && callback(results, _options, elements, allElements); - }, reviver, options); - } - }, - loadSVGFromString: function(string, callback, reviver, options) { - string = string.trim(); - var doc; - if (typeof DOMParser !== "undefined") { - var parser = new DOMParser(); - if (parser && parser.parseFromString) { - doc = parser.parseFromString(string, "text/xml"); - } - } else if (fabric.window.ActiveXObject) { - doc = new ActiveXObject("Microsoft.XMLDOM"); - doc.async = "false"; - doc.loadXML(string.replace(//i, "")); - } - fabric.parseSVGDocument(doc.documentElement, function(results, _options, elements, allElements) { - callback(results, _options, elements, allElements); - }, reviver, options); - } - }); -})(typeof exports !== "undefined" ? exports : this); - -fabric.ElementsParser = function(elements, callback, options, reviver, parsingOptions) { - this.elements = elements; - this.callback = callback; - this.options = options; - this.reviver = reviver; - this.svgUid = options && options.svgUid || 0; - this.parsingOptions = parsingOptions; -}; - -fabric.ElementsParser.prototype.parse = function() { - this.instances = new Array(this.elements.length); - this.numElements = this.elements.length; - this.createObjects(); -}; - -fabric.ElementsParser.prototype.createObjects = function() { - for (var i = 0, len = this.elements.length; i < len; i++) { - this.elements[i].setAttribute("svgUid", this.svgUid); - (function(_obj, i) { - setTimeout(function() { - _obj.createObject(_obj.elements[i], i); - }, 0); - })(this, i); - } -}; - -fabric.ElementsParser.prototype.createObject = function(el, index) { - var klass = fabric[fabric.util.string.capitalize(el.tagName.replace("svg:", ""))]; - if (klass && klass.fromElement) { - try { - this._createObject(klass, el, index); - } catch (err) { - fabric.log(err); - } - } else { - this.checkIfDone(); - } -}; - -fabric.ElementsParser.prototype._createObject = function(klass, el, index) { - klass.fromElement(el, this.createCallback(index, el), this.options); -}; - -fabric.ElementsParser.prototype.createCallback = function(index, el) { - var _this = this; - return function(obj) { - var _options; - _this.resolveGradient(obj, "fill"); - _this.resolveGradient(obj, "stroke"); - if (obj instanceof fabric.Image) { - _options = obj.parsePreserveAspectRatioAttribute(el); - } - obj._removeTransformMatrix(_options); - _this.reviver && _this.reviver(el, obj); - _this.instances[index] = obj; - _this.checkIfDone(); - }; -}; - -fabric.ElementsParser.prototype.resolveGradient = function(obj, property) { - var instanceFillValue = obj.get(property); - if (!/^url\(/.test(instanceFillValue)) { - return; - } - var gradientId = instanceFillValue.slice(5, instanceFillValue.length - 1); - if (fabric.gradientDefs[this.svgUid][gradientId]) { - obj.set(property, fabric.Gradient.fromElement(fabric.gradientDefs[this.svgUid][gradientId], obj)); - } -}; - -fabric.ElementsParser.prototype.checkIfDone = function() { - if (--this.numElements === 0) { - this.instances = this.instances.filter(function(el) { - return el != null; - }); - this.callback(this.instances, this.elements); - } -}; - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}); - if (fabric.Point) { - fabric.warn("fabric.Point is already defined"); - return; - } - fabric.Point = Point; - function Point(x, y) { - this.x = x; - this.y = y; - } - Point.prototype = { - type: "point", - constructor: Point, - add: function(that) { - return new Point(this.x + that.x, this.y + that.y); - }, - addEquals: function(that) { - this.x += that.x; - this.y += that.y; - return this; - }, - scalarAdd: function(scalar) { - return new Point(this.x + scalar, this.y + scalar); - }, - scalarAddEquals: function(scalar) { - this.x += scalar; - this.y += scalar; - return this; - }, - subtract: function(that) { - return new Point(this.x - that.x, this.y - that.y); - }, - subtractEquals: function(that) { - this.x -= that.x; - this.y -= that.y; - return this; - }, - scalarSubtract: function(scalar) { - return new Point(this.x - scalar, this.y - scalar); - }, - scalarSubtractEquals: function(scalar) { - this.x -= scalar; - this.y -= scalar; - return this; - }, - multiply: function(scalar) { - return new Point(this.x * scalar, this.y * scalar); - }, - multiplyEquals: function(scalar) { - this.x *= scalar; - this.y *= scalar; - return this; - }, - divide: function(scalar) { - return new Point(this.x / scalar, this.y / scalar); - }, - divideEquals: function(scalar) { - this.x /= scalar; - this.y /= scalar; - return this; - }, - eq: function(that) { - return this.x === that.x && this.y === that.y; - }, - lt: function(that) { - return this.x < that.x && this.y < that.y; - }, - lte: function(that) { - return this.x <= that.x && this.y <= that.y; - }, - gt: function(that) { - return this.x > that.x && this.y > that.y; - }, - gte: function(that) { - return this.x >= that.x && this.y >= that.y; - }, - lerp: function(that, t) { - if (typeof t === "undefined") { - t = .5; - } - t = Math.max(Math.min(1, t), 0); - return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t); - }, - distanceFrom: function(that) { - var dx = this.x - that.x, dy = this.y - that.y; - return Math.sqrt(dx * dx + dy * dy); - }, - midPointFrom: function(that) { - return this.lerp(that); - }, - min: function(that) { - return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y)); - }, - max: function(that) { - return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y)); - }, - toString: function() { - return this.x + "," + this.y; - }, - setXY: function(x, y) { - this.x = x; - this.y = y; - return this; - }, - setX: function(x) { - this.x = x; - return this; - }, - setY: function(y) { - this.y = y; - return this; - }, - setFromPoint: function(that) { - this.x = that.x; - this.y = that.y; - return this; - }, - swap: function(that) { - var x = this.x, y = this.y; - this.x = that.x; - this.y = that.y; - that.x = x; - that.y = y; - }, - clone: function() { - return new Point(this.x, this.y); - } - }; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}); - if (fabric.Intersection) { - fabric.warn("fabric.Intersection is already defined"); - return; - } - function Intersection(status) { - this.status = status; - this.points = []; - } - fabric.Intersection = Intersection; - fabric.Intersection.prototype = { - constructor: Intersection, - appendPoint: function(point) { - this.points.push(point); - return this; - }, - appendPoints: function(points) { - this.points = this.points.concat(points); - return this; - } - }; - fabric.Intersection.intersectLineLine = function(a1, a2, b1, b2) { - var result, uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y); - if (uB !== 0) { - var ua = uaT / uB, ub = ubT / uB; - if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { - result = new Intersection("Intersection"); - result.appendPoint(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); - } else { - result = new Intersection(); - } - } else { - if (uaT === 0 || ubT === 0) { - result = new Intersection("Coincident"); - } else { - result = new Intersection("Parallel"); - } - } - return result; - }; - fabric.Intersection.intersectLinePolygon = function(a1, a2, points) { - var result = new Intersection(), length = points.length, b1, b2, inter, i; - for (i = 0; i < length; i++) { - b1 = points[i]; - b2 = points[(i + 1) % length]; - inter = Intersection.intersectLineLine(a1, a2, b1, b2); - result.appendPoints(inter.points); - } - if (result.points.length > 0) { - result.status = "Intersection"; - } - return result; - }; - fabric.Intersection.intersectPolygonPolygon = function(points1, points2) { - var result = new Intersection(), length = points1.length, i; - for (i = 0; i < length; i++) { - var a1 = points1[i], a2 = points1[(i + 1) % length], inter = Intersection.intersectLinePolygon(a1, a2, points2); - result.appendPoints(inter.points); - } - if (result.points.length > 0) { - result.status = "Intersection"; - } - return result; - }; - fabric.Intersection.intersectPolygonRectangle = function(points, r1, r2) { - var min = r1.min(r2), max = r1.max(r2), topRight = new fabric.Point(max.x, min.y), bottomLeft = new fabric.Point(min.x, max.y), inter1 = Intersection.intersectLinePolygon(min, topRight, points), inter2 = Intersection.intersectLinePolygon(topRight, max, points), inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points), inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points), result = new Intersection(); - result.appendPoints(inter1.points); - result.appendPoints(inter2.points); - result.appendPoints(inter3.points); - result.appendPoints(inter4.points); - if (result.points.length > 0) { - result.status = "Intersection"; - } - return result; - }; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}); - if (fabric.Color) { - fabric.warn("fabric.Color is already defined."); - return; - } - function Color(color) { - if (!color) { - this.setSource([ 0, 0, 0, 1 ]); - } else { - this._tryParsingColor(color); - } - } - fabric.Color = Color; - fabric.Color.prototype = { - _tryParsingColor: function(color) { - var source; - if (color in Color.colorNameMap) { - color = Color.colorNameMap[color]; - } - if (color === "transparent") { - source = [ 255, 255, 255, 0 ]; - } - if (!source) { - source = Color.sourceFromHex(color); - } - if (!source) { - source = Color.sourceFromRgb(color); - } - if (!source) { - source = Color.sourceFromHsl(color); - } - if (!source) { - source = [ 0, 0, 0, 1 ]; - } - if (source) { - this.setSource(source); - } - }, - _rgbToHsl: function(r, g, b) { - r /= 255; - g /= 255; - b /= 255; - var h, s, l, max = fabric.util.array.max([ r, g, b ]), min = fabric.util.array.min([ r, g, b ]); - l = (max + min) / 2; - if (max === min) { - h = s = 0; - } else { - var d = max - min; - s = l > .5 ? d / (2 - max - min) : d / (max + min); - switch (max) { - case r: - h = (g - b) / d + (g < b ? 6 : 0); - break; - - case g: - h = (b - r) / d + 2; - break; - - case b: - h = (r - g) / d + 4; - break; - } - h /= 6; - } - return [ Math.round(h * 360), Math.round(s * 100), Math.round(l * 100) ]; - }, - getSource: function() { - return this._source; - }, - setSource: function(source) { - this._source = source; - }, - toRgb: function() { - var source = this.getSource(); - return "rgb(" + source[0] + "," + source[1] + "," + source[2] + ")"; - }, - toRgba: function() { - var source = this.getSource(); - return "rgba(" + source[0] + "," + source[1] + "," + source[2] + "," + source[3] + ")"; - }, - toHsl: function() { - var source = this.getSource(), hsl = this._rgbToHsl(source[0], source[1], source[2]); - return "hsl(" + hsl[0] + "," + hsl[1] + "%," + hsl[2] + "%)"; - }, - toHsla: function() { - var source = this.getSource(), hsl = this._rgbToHsl(source[0], source[1], source[2]); - return "hsla(" + hsl[0] + "," + hsl[1] + "%," + hsl[2] + "%," + source[3] + ")"; - }, - toHex: function() { - var source = this.getSource(), r, g, b; - r = source[0].toString(16); - r = r.length === 1 ? "0" + r : r; - g = source[1].toString(16); - g = g.length === 1 ? "0" + g : g; - b = source[2].toString(16); - b = b.length === 1 ? "0" + b : b; - return r.toUpperCase() + g.toUpperCase() + b.toUpperCase(); - }, - toHexa: function() { - var source = this.getSource(), a; - a = Math.round(source[3] * 255); - a = a.toString(16); - a = a.length === 1 ? "0" + a : a; - return this.toHex() + a.toUpperCase(); - }, - getAlpha: function() { - return this.getSource()[3]; - }, - setAlpha: function(alpha) { - var source = this.getSource(); - source[3] = alpha; - this.setSource(source); - return this; - }, - toGrayscale: function() { - var source = this.getSource(), average = parseInt((source[0] * .3 + source[1] * .59 + source[2] * .11).toFixed(0), 10), currentAlpha = source[3]; - this.setSource([ average, average, average, currentAlpha ]); - return this; - }, - toBlackWhite: function(threshold) { - var source = this.getSource(), average = (source[0] * .3 + source[1] * .59 + source[2] * .11).toFixed(0), currentAlpha = source[3]; - threshold = threshold || 127; - average = Number(average) < Number(threshold) ? 0 : 255; - this.setSource([ average, average, average, currentAlpha ]); - return this; - }, - overlayWith: function(otherColor) { - if (!(otherColor instanceof Color)) { - otherColor = new Color(otherColor); - } - var result = [], alpha = this.getAlpha(), otherAlpha = .5, source = this.getSource(), otherSource = otherColor.getSource(), i; - for (i = 0; i < 3; i++) { - result.push(Math.round(source[i] * (1 - otherAlpha) + otherSource[i] * otherAlpha)); - } - result[3] = alpha; - this.setSource(result); - return this; - } - }; - fabric.Color.reRGBa = /^rgba?\(\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*(?:\s*,\s*((?:\d*\.?\d+)?)\s*)?\)$/; - fabric.Color.reHSLa = /^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/; - fabric.Color.reHex = /^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i; - fabric.Color.colorNameMap = { - aliceblue: "#F0F8FF", - antiquewhite: "#FAEBD7", - aqua: "#00FFFF", - aquamarine: "#7FFFD4", - azure: "#F0FFFF", - beige: "#F5F5DC", - bisque: "#FFE4C4", - black: "#000000", - blanchedalmond: "#FFEBCD", - blue: "#0000FF", - blueviolet: "#8A2BE2", - brown: "#A52A2A", - burlywood: "#DEB887", - cadetblue: "#5F9EA0", - chartreuse: "#7FFF00", - chocolate: "#D2691E", - coral: "#FF7F50", - cornflowerblue: "#6495ED", - cornsilk: "#FFF8DC", - crimson: "#DC143C", - cyan: "#00FFFF", - darkblue: "#00008B", - darkcyan: "#008B8B", - darkgoldenrod: "#B8860B", - darkgray: "#A9A9A9", - darkgrey: "#A9A9A9", - darkgreen: "#006400", - darkkhaki: "#BDB76B", - darkmagenta: "#8B008B", - darkolivegreen: "#556B2F", - darkorange: "#FF8C00", - darkorchid: "#9932CC", - darkred: "#8B0000", - darksalmon: "#E9967A", - darkseagreen: "#8FBC8F", - darkslateblue: "#483D8B", - darkslategray: "#2F4F4F", - darkslategrey: "#2F4F4F", - darkturquoise: "#00CED1", - darkviolet: "#9400D3", - deeppink: "#FF1493", - deepskyblue: "#00BFFF", - dimgray: "#696969", - dimgrey: "#696969", - dodgerblue: "#1E90FF", - firebrick: "#B22222", - floralwhite: "#FFFAF0", - forestgreen: "#228B22", - fuchsia: "#FF00FF", - gainsboro: "#DCDCDC", - ghostwhite: "#F8F8FF", - gold: "#FFD700", - goldenrod: "#DAA520", - gray: "#808080", - grey: "#808080", - green: "#008000", - greenyellow: "#ADFF2F", - honeydew: "#F0FFF0", - hotpink: "#FF69B4", - indianred: "#CD5C5C", - indigo: "#4B0082", - ivory: "#FFFFF0", - khaki: "#F0E68C", - lavender: "#E6E6FA", - lavenderblush: "#FFF0F5", - lawngreen: "#7CFC00", - lemonchiffon: "#FFFACD", - lightblue: "#ADD8E6", - lightcoral: "#F08080", - lightcyan: "#E0FFFF", - lightgoldenrodyellow: "#FAFAD2", - lightgray: "#D3D3D3", - lightgrey: "#D3D3D3", - lightgreen: "#90EE90", - lightpink: "#FFB6C1", - lightsalmon: "#FFA07A", - lightseagreen: "#20B2AA", - lightskyblue: "#87CEFA", - lightslategray: "#778899", - lightslategrey: "#778899", - lightsteelblue: "#B0C4DE", - lightyellow: "#FFFFE0", - lime: "#00FF00", - limegreen: "#32CD32", - linen: "#FAF0E6", - magenta: "#FF00FF", - maroon: "#800000", - mediumaquamarine: "#66CDAA", - mediumblue: "#0000CD", - mediumorchid: "#BA55D3", - mediumpurple: "#9370DB", - mediumseagreen: "#3CB371", - mediumslateblue: "#7B68EE", - mediumspringgreen: "#00FA9A", - mediumturquoise: "#48D1CC", - mediumvioletred: "#C71585", - midnightblue: "#191970", - mintcream: "#F5FFFA", - mistyrose: "#FFE4E1", - moccasin: "#FFE4B5", - navajowhite: "#FFDEAD", - navy: "#000080", - oldlace: "#FDF5E6", - olive: "#808000", - olivedrab: "#6B8E23", - orange: "#FFA500", - orangered: "#FF4500", - orchid: "#DA70D6", - palegoldenrod: "#EEE8AA", - palegreen: "#98FB98", - paleturquoise: "#AFEEEE", - palevioletred: "#DB7093", - papayawhip: "#FFEFD5", - peachpuff: "#FFDAB9", - peru: "#CD853F", - pink: "#FFC0CB", - plum: "#DDA0DD", - powderblue: "#B0E0E6", - purple: "#800080", - rebeccapurple: "#663399", - red: "#FF0000", - rosybrown: "#BC8F8F", - royalblue: "#4169E1", - saddlebrown: "#8B4513", - salmon: "#FA8072", - sandybrown: "#F4A460", - seagreen: "#2E8B57", - seashell: "#FFF5EE", - sienna: "#A0522D", - silver: "#C0C0C0", - skyblue: "#87CEEB", - slateblue: "#6A5ACD", - slategray: "#708090", - slategrey: "#708090", - snow: "#FFFAFA", - springgreen: "#00FF7F", - steelblue: "#4682B4", - tan: "#D2B48C", - teal: "#008080", - thistle: "#D8BFD8", - tomato: "#FF6347", - turquoise: "#40E0D0", - violet: "#EE82EE", - wheat: "#F5DEB3", - white: "#FFFFFF", - whitesmoke: "#F5F5F5", - yellow: "#FFFF00", - yellowgreen: "#9ACD32" - }; - function hue2rgb(p, q, t) { - if (t < 0) { - t += 1; - } - if (t > 1) { - t -= 1; - } - if (t < 1 / 6) { - return p + (q - p) * 6 * t; - } - if (t < 1 / 2) { - return q; - } - if (t < 2 / 3) { - return p + (q - p) * (2 / 3 - t) * 6; - } - return p; - } - fabric.Color.fromRgb = function(color) { - return Color.fromSource(Color.sourceFromRgb(color)); - }; - fabric.Color.sourceFromRgb = function(color) { - var match = color.match(Color.reRGBa); - if (match) { - var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1), g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1), b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1); - return [ parseInt(r, 10), parseInt(g, 10), parseInt(b, 10), match[4] ? parseFloat(match[4]) : 1 ]; - } - }; - fabric.Color.fromRgba = Color.fromRgb; - fabric.Color.fromHsl = function(color) { - return Color.fromSource(Color.sourceFromHsl(color)); - }; - fabric.Color.sourceFromHsl = function(color) { - var match = color.match(Color.reHSLa); - if (!match) { - return; - } - var h = (parseFloat(match[1]) % 360 + 360) % 360 / 360, s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1), l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1), r, g, b; - if (s === 0) { - r = g = b = l; - } else { - var q = l <= .5 ? l * (s + 1) : l + s - l * s, p = l * 2 - q; - r = hue2rgb(p, q, h + 1 / 3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1 / 3); - } - return [ Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), match[4] ? parseFloat(match[4]) : 1 ]; - }; - fabric.Color.fromHsla = Color.fromHsl; - fabric.Color.fromHex = function(color) { - return Color.fromSource(Color.sourceFromHex(color)); - }; - fabric.Color.sourceFromHex = function(color) { - if (color.match(Color.reHex)) { - var value = color.slice(color.indexOf("#") + 1), isShortNotation = value.length === 3 || value.length === 4, isRGBa = value.length === 8 || value.length === 4, r = isShortNotation ? value.charAt(0) + value.charAt(0) : value.substring(0, 2), g = isShortNotation ? value.charAt(1) + value.charAt(1) : value.substring(2, 4), b = isShortNotation ? value.charAt(2) + value.charAt(2) : value.substring(4, 6), a = isRGBa ? isShortNotation ? value.charAt(3) + value.charAt(3) : value.substring(6, 8) : "FF"; - return [ parseInt(r, 16), parseInt(g, 16), parseInt(b, 16), parseFloat((parseInt(a, 16) / 255).toFixed(2)) ]; - } - }; - fabric.Color.fromSource = function(source) { - var oColor = new Color(); - oColor.setSource(source); - return oColor; - }; -})(typeof exports !== "undefined" ? exports : this); - -(function() { - function getColorStop(el) { - var style = el.getAttribute("style"), offset = el.getAttribute("offset") || 0, color, colorAlpha, opacity, i; - offset = parseFloat(offset) / (/%$/.test(offset) ? 100 : 1); - offset = offset < 0 ? 0 : offset > 1 ? 1 : offset; - if (style) { - var keyValuePairs = style.split(/\s*;\s*/); - if (keyValuePairs[keyValuePairs.length - 1] === "") { - keyValuePairs.pop(); - } - for (i = keyValuePairs.length; i--; ) { - var split = keyValuePairs[i].split(/\s*:\s*/), key = split[0].trim(), value = split[1].trim(); - if (key === "stop-color") { - color = value; - } else if (key === "stop-opacity") { - opacity = value; - } - } - } - if (!color) { - color = el.getAttribute("stop-color") || "rgb(0,0,0)"; - } - if (!opacity) { - opacity = el.getAttribute("stop-opacity"); - } - color = new fabric.Color(color); - colorAlpha = color.getAlpha(); - opacity = isNaN(parseFloat(opacity)) ? 1 : parseFloat(opacity); - opacity *= colorAlpha; - return { - offset: offset, - color: color.toRgb(), - opacity: opacity - }; - } - function getLinearCoords(el) { - return { - x1: el.getAttribute("x1") || 0, - y1: el.getAttribute("y1") || 0, - x2: el.getAttribute("x2") || "100%", - y2: el.getAttribute("y2") || 0 - }; - } - function getRadialCoords(el) { - return { - x1: el.getAttribute("fx") || el.getAttribute("cx") || "50%", - y1: el.getAttribute("fy") || el.getAttribute("cy") || "50%", - r1: 0, - x2: el.getAttribute("cx") || "50%", - y2: el.getAttribute("cy") || "50%", - r2: el.getAttribute("r") || "50%" - }; - } - var clone = fabric.util.object.clone; - fabric.Gradient = fabric.util.createClass({ - offsetX: 0, - offsetY: 0, - initialize: function(options) { - options || (options = {}); - var coords = {}; - this.id = fabric.Object.__uid++; - this.type = options.type || "linear"; - coords = { - x1: options.coords.x1 || 0, - y1: options.coords.y1 || 0, - x2: options.coords.x2 || 0, - y2: options.coords.y2 || 0 - }; - if (this.type === "radial") { - coords.r1 = options.coords.r1 || 0; - coords.r2 = options.coords.r2 || 0; - } - this.coords = coords; - this.colorStops = options.colorStops.slice(); - if (options.gradientTransform) { - this.gradientTransform = options.gradientTransform; - } - this.offsetX = options.offsetX || this.offsetX; - this.offsetY = options.offsetY || this.offsetY; - }, - addColorStop: function(colorStops) { - for (var position in colorStops) { - var color = new fabric.Color(colorStops[position]); - this.colorStops.push({ - offset: parseFloat(position), - color: color.toRgb(), - opacity: color.getAlpha() - }); - } - return this; - }, - toObject: function(propertiesToInclude) { - var object = { - type: this.type, - coords: this.coords, - colorStops: this.colorStops, - offsetX: this.offsetX, - offsetY: this.offsetY, - gradientTransform: this.gradientTransform ? this.gradientTransform.concat() : this.gradientTransform - }; - fabric.util.populateWithProperties(this, object, propertiesToInclude); - return object; - }, - toSVG: function(object) { - var coords = clone(this.coords, true), i, len, markup, commonAttributes, colorStops = clone(this.colorStops, true), needsSwap = coords.r1 > coords.r2, offsetX = object.width / 2, offsetY = object.height / 2; - colorStops.sort(function(a, b) { - return a.offset - b.offset; - }); - if (object.type === "path") { - offsetX -= object.pathOffset.x; - offsetY -= object.pathOffset.y; - } - for (var prop in coords) { - if (prop === "x1" || prop === "x2") { - coords[prop] += this.offsetX - offsetX; - } else if (prop === "y1" || prop === "y2") { - coords[prop] += this.offsetY - offsetY; - } - } - commonAttributes = 'id="SVGID_' + this.id + '" gradientUnits="userSpaceOnUse"'; - if (this.gradientTransform) { - commonAttributes += ' gradientTransform="matrix(' + this.gradientTransform.join(" ") + ')" '; - } - if (this.type === "linear") { - markup = [ "\n' ]; - } else if (this.type === "radial") { - markup = [ "\n' ]; - } - if (this.type === "radial") { - if (needsSwap) { - colorStops = colorStops.concat(); - colorStops.reverse(); - for (i = 0, len = colorStops.length; i < len; i++) { - colorStops[i].offset = 1 - colorStops[i].offset; - } - } - var minRadius = Math.min(coords.r1, coords.r2); - if (minRadius > 0) { - var maxRadius = Math.max(coords.r1, coords.r2), percentageShift = minRadius / maxRadius; - for (i = 0, len = colorStops.length; i < len; i++) { - colorStops[i].offset += percentageShift * (1 - colorStops[i].offset); - } - } - } - for (i = 0, len = colorStops.length; i < len; i++) { - var colorStop = colorStops[i]; - markup.push("\n'); - } - markup.push(this.type === "linear" ? "\n" : "\n"); - return markup.join(""); - }, - toLive: function(ctx) { - var gradient, coords = fabric.util.object.clone(this.coords), i, len; - if (!this.type) { - return; - } - if (this.type === "linear") { - gradient = ctx.createLinearGradient(coords.x1, coords.y1, coords.x2, coords.y2); - } else if (this.type === "radial") { - gradient = ctx.createRadialGradient(coords.x1, coords.y1, coords.r1, coords.x2, coords.y2, coords.r2); - } - for (i = 0, len = this.colorStops.length; i < len; i++) { - var color = this.colorStops[i].color, opacity = this.colorStops[i].opacity, offset = this.colorStops[i].offset; - if (typeof opacity !== "undefined") { - color = new fabric.Color(color).setAlpha(opacity).toRgba(); - } - gradient.addColorStop(offset, color); - } - return gradient; - } - }); - fabric.util.object.extend(fabric.Gradient, { - fromElement: function(el, instance) { - var colorStopEls = el.getElementsByTagName("stop"), type, gradientUnits = el.getAttribute("gradientUnits") || "objectBoundingBox", gradientTransform = el.getAttribute("gradientTransform"), colorStops = [], coords, ellipseMatrix, i; - if (el.nodeName === "linearGradient" || el.nodeName === "LINEARGRADIENT") { - type = "linear"; - } else { - type = "radial"; - } - if (type === "linear") { - coords = getLinearCoords(el); - } else if (type === "radial") { - coords = getRadialCoords(el); - } - for (i = colorStopEls.length; i--; ) { - colorStops.push(getColorStop(colorStopEls[i])); - } - ellipseMatrix = _convertPercentUnitsToValues(instance, coords, gradientUnits); - var gradient = new fabric.Gradient({ - type: type, - coords: coords, - colorStops: colorStops, - offsetX: -instance.left, - offsetY: -instance.top - }); - if (gradientTransform || ellipseMatrix !== "") { - gradient.gradientTransform = fabric.parseTransformAttribute((gradientTransform || "") + ellipseMatrix); - } - return gradient; - }, - forObject: function(obj, options) { - options || (options = {}); - _convertPercentUnitsToValues(obj, options.coords, "userSpaceOnUse"); - return new fabric.Gradient(options); - } - }); - function _convertPercentUnitsToValues(object, options, gradientUnits) { - var propValue, addFactor = 0, multFactor = 1, ellipseMatrix = ""; - for (var prop in options) { - if (options[prop] === "Infinity") { - options[prop] = 1; - } else if (options[prop] === "-Infinity") { - options[prop] = 0; - } - propValue = parseFloat(options[prop], 10); - if (typeof options[prop] === "string" && /^(\d+\.\d+)%|(\d+)%$/.test(options[prop])) { - multFactor = .01; - } else { - multFactor = 1; - } - if (prop === "x1" || prop === "x2" || prop === "r2") { - multFactor *= gradientUnits === "objectBoundingBox" ? object.width : 1; - addFactor = gradientUnits === "objectBoundingBox" ? object.left || 0 : 0; - } else if (prop === "y1" || prop === "y2") { - multFactor *= gradientUnits === "objectBoundingBox" ? object.height : 1; - addFactor = gradientUnits === "objectBoundingBox" ? object.top || 0 : 0; - } - options[prop] = propValue * multFactor + addFactor; - } - if (object.type === "ellipse" && options.r2 !== null && gradientUnits === "objectBoundingBox" && object.rx !== object.ry) { - var scaleFactor = object.ry / object.rx; - ellipseMatrix = " scale(1, " + scaleFactor + ")"; - if (options.y1) { - options.y1 /= scaleFactor; - } - if (options.y2) { - options.y2 /= scaleFactor; - } - } - return ellipseMatrix; - } -})(); - -(function() { - "use strict"; - var toFixed = fabric.util.toFixed; - fabric.Pattern = fabric.util.createClass({ - repeat: "repeat", - offsetX: 0, - offsetY: 0, - crossOrigin: "", - patternTransform: null, - initialize: function(options, callback) { - options || (options = {}); - this.id = fabric.Object.__uid++; - this.setOptions(options); - if (!options.source || options.source && typeof options.source !== "string") { - callback && callback(this); - return; - } - if (typeof fabric.util.getFunctionBody(options.source) !== "undefined") { - this.source = new Function(fabric.util.getFunctionBody(options.source)); - callback && callback(this); - } else { - var _this = this; - this.source = fabric.util.createImage(); - fabric.util.loadImage(options.source, function(img) { - _this.source = img; - callback && callback(_this); - }, null, this.crossOrigin); - } - }, - toObject: function(propertiesToInclude) { - var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, source, object; - if (typeof this.source === "function") { - source = String(this.source); - } else if (typeof this.source.src === "string") { - source = this.source.src; - } else if (typeof this.source === "object" && this.source.toDataURL) { - source = this.source.toDataURL(); - } - object = { - type: "pattern", - source: source, - repeat: this.repeat, - crossOrigin: this.crossOrigin, - offsetX: toFixed(this.offsetX, NUM_FRACTION_DIGITS), - offsetY: toFixed(this.offsetY, NUM_FRACTION_DIGITS), - patternTransform: this.patternTransform ? this.patternTransform.concat() : null - }; - fabric.util.populateWithProperties(this, object, propertiesToInclude); - return object; - }, - toSVG: function(object) { - var patternSource = typeof this.source === "function" ? this.source() : this.source, patternWidth = patternSource.width / object.width, patternHeight = patternSource.height / object.height, patternOffsetX = this.offsetX / object.width, patternOffsetY = this.offsetY / object.height, patternImgSrc = ""; - if (this.repeat === "repeat-x" || this.repeat === "no-repeat") { - patternHeight = 1; - } - if (this.repeat === "repeat-y" || this.repeat === "no-repeat") { - patternWidth = 1; - } - if (patternSource.src) { - patternImgSrc = patternSource.src; - } else if (patternSource.toDataURL) { - patternImgSrc = patternSource.toDataURL(); - } - return '\n' + '\n' + "\n"; - }, - setOptions: function(options) { - for (var prop in options) { - this[prop] = options[prop]; - } - }, - toLive: function(ctx) { - var source = typeof this.source === "function" ? this.source() : this.source; - if (!source) { - return ""; - } - if (typeof source.src !== "undefined") { - if (!source.complete) { - return ""; - } - if (source.naturalWidth === 0 || source.naturalHeight === 0) { - return ""; - } - } - return ctx.createPattern(source, this.repeat); - } - }); -})(); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), toFixed = fabric.util.toFixed; - if (fabric.Shadow) { - fabric.warn("fabric.Shadow is already defined."); - return; - } - fabric.Shadow = fabric.util.createClass({ - color: "rgb(0,0,0)", - blur: 0, - offsetX: 0, - offsetY: 0, - affectStroke: false, - includeDefaultValues: true, - initialize: function(options) { - if (typeof options === "string") { - options = this._parseShadow(options); - } - for (var prop in options) { - this[prop] = options[prop]; - } - this.id = fabric.Object.__uid++; - }, - _parseShadow: function(shadow) { - var shadowStr = shadow.trim(), offsetsAndBlur = fabric.Shadow.reOffsetsAndBlur.exec(shadowStr) || [], color = shadowStr.replace(fabric.Shadow.reOffsetsAndBlur, "") || "rgb(0,0,0)"; - return { - color: color.trim(), - offsetX: parseInt(offsetsAndBlur[1], 10) || 0, - offsetY: parseInt(offsetsAndBlur[2], 10) || 0, - blur: parseInt(offsetsAndBlur[3], 10) || 0 - }; - }, - toString: function() { - return [ this.offsetX, this.offsetY, this.blur, this.color ].join("px "); - }, - toSVG: function(object) { - var fBoxX = 40, fBoxY = 40, NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, offset = fabric.util.rotateVector({ - x: this.offsetX, - y: this.offsetY - }, fabric.util.degreesToRadians(-object.angle)), BLUR_BOX = 20; - if (object.width && object.height) { - fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX; - fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX; - } - if (object.flipX) { - offset.x *= -1; - } - if (object.flipY) { - offset.y *= -1; - } - return '\n" + '\t\n' + '\t\n' + '\t\n' + '\t\n' + "\t\n" + "\t\t\n" + '\t\t\n' + "\t\n" + "\n"; - }, - toObject: function() { - if (this.includeDefaultValues) { - return { - color: this.color, - blur: this.blur, - offsetX: this.offsetX, - offsetY: this.offsetY, - affectStroke: this.affectStroke - }; - } - var obj = {}, proto = fabric.Shadow.prototype; - [ "color", "blur", "offsetX", "offsetY", "affectStroke" ].forEach(function(prop) { - if (this[prop] !== proto[prop]) { - obj[prop] = this[prop]; - } - }, this); - return obj; - } - }); - fabric.Shadow.reOffsetsAndBlur = /(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/; -})(typeof exports !== "undefined" ? exports : this); - -(function() { - "use strict"; - if (fabric.StaticCanvas) { - fabric.warn("fabric.StaticCanvas is already defined."); - return; - } - var extend = fabric.util.object.extend, getElementOffset = fabric.util.getElementOffset, removeFromArray = fabric.util.removeFromArray, toFixed = fabric.util.toFixed, transformPoint = fabric.util.transformPoint, invertTransform = fabric.util.invertTransform, CANVAS_INIT_ERROR = new Error("Could not initialize `canvas` element"); - fabric.StaticCanvas = fabric.util.createClass(fabric.CommonMethods, { - initialize: function(el, options) { - options || (options = {}); - this.renderAndResetBound = this.renderAndReset.bind(this); - this.requestRenderAllBound = this.requestRenderAll.bind(this); - this._initStatic(el, options); - }, - backgroundColor: "", - backgroundImage: null, - overlayColor: "", - overlayImage: null, - includeDefaultValues: true, - stateful: false, - renderOnAddRemove: true, - clipTo: null, - controlsAboveOverlay: false, - allowTouchScrolling: false, - imageSmoothingEnabled: true, - viewportTransform: fabric.iMatrix.concat(), - backgroundVpt: true, - overlayVpt: true, - onBeforeScaleRotate: function() {}, - enableRetinaScaling: true, - vptCoords: {}, - skipOffscreen: true, - _initStatic: function(el, options) { - var cb = this.requestRenderAllBound; - this._objects = []; - this._createLowerCanvas(el); - this._initOptions(options); - this._setImageSmoothing(); - if (!this.interactive) { - this._initRetinaScaling(); - } - if (options.overlayImage) { - this.setOverlayImage(options.overlayImage, cb); - } - if (options.backgroundImage) { - this.setBackgroundImage(options.backgroundImage, cb); - } - if (options.backgroundColor) { - this.setBackgroundColor(options.backgroundColor, cb); - } - if (options.overlayColor) { - this.setOverlayColor(options.overlayColor, cb); - } - this.calcOffset(); - }, - _isRetinaScaling: function() { - return fabric.devicePixelRatio !== 1 && this.enableRetinaScaling; - }, - getRetinaScaling: function() { - return this._isRetinaScaling() ? fabric.devicePixelRatio : 1; - }, - _initRetinaScaling: function() { - if (!this._isRetinaScaling()) { - return; - } - this.lowerCanvasEl.setAttribute("width", this.width * fabric.devicePixelRatio); - this.lowerCanvasEl.setAttribute("height", this.height * fabric.devicePixelRatio); - this.contextContainer.scale(fabric.devicePixelRatio, fabric.devicePixelRatio); - }, - calcOffset: function() { - this._offset = getElementOffset(this.lowerCanvasEl); - return this; - }, - setOverlayImage: function(image, callback, options) { - return this.__setBgOverlayImage("overlayImage", image, callback, options); - }, - setBackgroundImage: function(image, callback, options) { - return this.__setBgOverlayImage("backgroundImage", image, callback, options); - }, - setOverlayColor: function(overlayColor, callback) { - return this.__setBgOverlayColor("overlayColor", overlayColor, callback); - }, - setBackgroundColor: function(backgroundColor, callback) { - return this.__setBgOverlayColor("backgroundColor", backgroundColor, callback); - }, - _setImageSmoothing: function() { - var ctx = this.getContext(); - ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled || ctx.webkitImageSmoothingEnabled || ctx.mozImageSmoothingEnabled || ctx.msImageSmoothingEnabled || ctx.oImageSmoothingEnabled; - ctx.imageSmoothingEnabled = this.imageSmoothingEnabled; - }, - __setBgOverlayImage: function(property, image, callback, options) { - if (typeof image === "string") { - fabric.util.loadImage(image, function(img) { - img && (this[property] = new fabric.Image(img, options)); - callback && callback(img); - }, this, options && options.crossOrigin); - } else { - options && image.setOptions(options); - this[property] = image; - callback && callback(image); - } - return this; - }, - __setBgOverlayColor: function(property, color, callback) { - this[property] = color; - this._initGradient(color, property); - this._initPattern(color, property, callback); - return this; - }, - _createCanvasElement: function() { - var element = fabric.util.createCanvasElement(); - if (!element) { - throw CANVAS_INIT_ERROR; - } - if (!element.style) { - element.style = {}; - } - if (typeof element.getContext === "undefined") { - throw CANVAS_INIT_ERROR; - } - return element; - }, - _initOptions: function(options) { - this._setOptions(options); - this.width = this.width || parseInt(this.lowerCanvasEl.width, 10) || 0; - this.height = this.height || parseInt(this.lowerCanvasEl.height, 10) || 0; - if (!this.lowerCanvasEl.style) { - return; - } - this.lowerCanvasEl.width = this.width; - this.lowerCanvasEl.height = this.height; - this.lowerCanvasEl.style.width = this.width + "px"; - this.lowerCanvasEl.style.height = this.height + "px"; - this.viewportTransform = this.viewportTransform.slice(); - }, - _createLowerCanvas: function(canvasEl) { - if (canvasEl && canvasEl.getContext) { - this.lowerCanvasEl = canvasEl; - } else { - this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement(); - } - fabric.util.addClass(this.lowerCanvasEl, "lower-canvas"); - if (this.interactive) { - this._applyCanvasStyle(this.lowerCanvasEl); - } - this.contextContainer = this.lowerCanvasEl.getContext("2d"); - }, - getWidth: function() { - return this.width; - }, - getHeight: function() { - return this.height; - }, - setWidth: function(value, options) { - return this.setDimensions({ - width: value - }, options); - }, - setHeight: function(value, options) { - return this.setDimensions({ - height: value - }, options); - }, - setDimensions: function(dimensions, options) { - var cssValue; - options = options || {}; - for (var prop in dimensions) { - cssValue = dimensions[prop]; - if (!options.cssOnly) { - this._setBackstoreDimension(prop, dimensions[prop]); - cssValue += "px"; - } - if (!options.backstoreOnly) { - this._setCssDimension(prop, cssValue); - } - } - if (this._isCurrentlyDrawing) { - this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles(); - } - this._initRetinaScaling(); - this._setImageSmoothing(); - this.calcOffset(); - if (!options.cssOnly) { - this.requestRenderAll(); - } - return this; - }, - _setBackstoreDimension: function(prop, value) { - this.lowerCanvasEl[prop] = value; - if (this.upperCanvasEl) { - this.upperCanvasEl[prop] = value; - } - if (this.cacheCanvasEl) { - this.cacheCanvasEl[prop] = value; - } - this[prop] = value; - return this; - }, - _setCssDimension: function(prop, value) { - this.lowerCanvasEl.style[prop] = value; - if (this.upperCanvasEl) { - this.upperCanvasEl.style[prop] = value; - } - if (this.wrapperEl) { - this.wrapperEl.style[prop] = value; - } - return this; - }, - getZoom: function() { - return this.viewportTransform[0]; - }, - setViewportTransform: function(vpt) { - var activeObject = this._activeObject, object, ignoreVpt = false, skipAbsolute = true, i, len; - this.viewportTransform = vpt; - for (i = 0, len = this._objects.length; i < len; i++) { - object = this._objects[i]; - object.group || object.setCoords(ignoreVpt, skipAbsolute); - } - if (activeObject && activeObject.type === "activeSelection") { - activeObject.setCoords(ignoreVpt, skipAbsolute); - } - this.calcViewportBoundaries(); - this.renderOnAddRemove && this.requestRenderAll(); - return this; - }, - zoomToPoint: function(point, value) { - var before = point, vpt = this.viewportTransform.slice(0); - point = transformPoint(point, invertTransform(this.viewportTransform)); - vpt[0] = value; - vpt[3] = value; - var after = transformPoint(point, vpt); - vpt[4] += before.x - after.x; - vpt[5] += before.y - after.y; - return this.setViewportTransform(vpt); - }, - setZoom: function(value) { - this.zoomToPoint(new fabric.Point(0, 0), value); - return this; - }, - absolutePan: function(point) { - var vpt = this.viewportTransform.slice(0); - vpt[4] = -point.x; - vpt[5] = -point.y; - return this.setViewportTransform(vpt); - }, - relativePan: function(point) { - return this.absolutePan(new fabric.Point(-point.x - this.viewportTransform[4], -point.y - this.viewportTransform[5])); - }, - getElement: function() { - return this.lowerCanvasEl; - }, - _onObjectAdded: function(obj) { - this.stateful && obj.setupState(); - obj._set("canvas", this); - obj.setCoords(); - this.fire("object:added", { - target: obj - }); - obj.fire("added"); - }, - _onObjectRemoved: function(obj) { - this.fire("object:removed", { - target: obj - }); - obj.fire("removed"); - delete obj.canvas; - }, - clearContext: function(ctx) { - ctx.clearRect(0, 0, this.width, this.height); - return this; - }, - getContext: function() { - return this.contextContainer; - }, - clear: function() { - this._objects.length = 0; - this.backgroundImage = null; - this.overlayImage = null; - this.backgroundColor = ""; - this.overlayColor = ""; - if (this._hasITextHandlers) { - this.off("mouse:up", this._mouseUpITextHandler); - this._iTextInstances = null; - this._hasITextHandlers = false; - } - this.clearContext(this.contextContainer); - this.fire("canvas:cleared"); - this.renderOnAddRemove && this.requestRenderAll(); - return this; - }, - renderAll: function() { - var canvasToDrawOn = this.contextContainer; - this.renderCanvas(canvasToDrawOn, this._objects); - return this; - }, - renderAndReset: function() { - this.isRendering = 0; - this.renderAll(); - }, - requestRenderAll: function() { - if (!this.isRendering) { - this.isRendering = fabric.util.requestAnimFrame(this.renderAndResetBound); - } - return this; - }, - calcViewportBoundaries: function() { - var points = {}, width = this.width, height = this.height, iVpt = invertTransform(this.viewportTransform); - points.tl = transformPoint({ - x: 0, - y: 0 - }, iVpt); - points.br = transformPoint({ - x: width, - y: height - }, iVpt); - points.tr = new fabric.Point(points.br.x, points.tl.y); - points.bl = new fabric.Point(points.tl.x, points.br.y); - this.vptCoords = points; - return points; - }, - renderCanvas: function(ctx, objects) { - var v = this.viewportTransform; - if (this.isRendering) { - fabric.util.cancelAnimFrame(this.isRendering); - this.isRendering = 0; - } - this.calcViewportBoundaries(); - this.clearContext(ctx); - this.fire("before:render"); - if (this.clipTo) { - fabric.util.clipContext(this, ctx); - } - this._renderBackground(ctx); - ctx.save(); - ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); - this._renderObjects(ctx, objects); - ctx.restore(); - if (!this.controlsAboveOverlay && this.interactive) { - this.drawControls(ctx); - } - if (this.clipTo) { - ctx.restore(); - } - this._renderOverlay(ctx); - if (this.controlsAboveOverlay && this.interactive) { - this.drawControls(ctx); - } - this.fire("after:render"); - }, - _renderObjects: function(ctx, objects) { - var i, len; - for (i = 0, len = objects.length; i < len; ++i) { - objects[i] && objects[i].render(ctx); - } - }, - _renderBackgroundOrOverlay: function(ctx, property) { - var object = this[property + "Color"], v; - if (object) { - ctx.fillStyle = object.toLive ? object.toLive(ctx, this) : object; - ctx.fillRect(object.offsetX || 0, object.offsetY || 0, this.width, this.height); - } - object = this[property + "Image"]; - if (object) { - if (this[property + "Vpt"]) { - v = this.viewportTransform; - ctx.save(); - ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); - } - object.render(ctx); - this[property + "Vpt"] && ctx.restore(); - } - }, - _renderBackground: function(ctx) { - this._renderBackgroundOrOverlay(ctx, "background"); - }, - _renderOverlay: function(ctx) { - this._renderBackgroundOrOverlay(ctx, "overlay"); - }, - getCenter: function() { - return { - top: this.height / 2, - left: this.width / 2 - }; - }, - centerObjectH: function(object) { - return this._centerObject(object, new fabric.Point(this.getCenter().left, object.getCenterPoint().y)); - }, - centerObjectV: function(object) { - return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenter().top)); - }, - centerObject: function(object) { - var center = this.getCenter(); - return this._centerObject(object, new fabric.Point(center.left, center.top)); - }, - viewportCenterObject: function(object) { - var vpCenter = this.getVpCenter(); - return this._centerObject(object, vpCenter); - }, - viewportCenterObjectH: function(object) { - var vpCenter = this.getVpCenter(); - this._centerObject(object, new fabric.Point(vpCenter.x, object.getCenterPoint().y)); - return this; - }, - viewportCenterObjectV: function(object) { - var vpCenter = this.getVpCenter(); - return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, vpCenter.y)); - }, - getVpCenter: function() { - var center = this.getCenter(), iVpt = invertTransform(this.viewportTransform); - return transformPoint({ - x: center.left, - y: center.top - }, iVpt); - }, - _centerObject: function(object, center) { - object.setPositionByOrigin(center, "center", "center"); - object.setCoords(); - this.renderOnAddRemove && this.requestRenderAll(); - return this; - }, - toDatalessJSON: function(propertiesToInclude) { - return this.toDatalessObject(propertiesToInclude); - }, - toObject: function(propertiesToInclude) { - return this._toObjectMethod("toObject", propertiesToInclude); - }, - toDatalessObject: function(propertiesToInclude) { - return this._toObjectMethod("toDatalessObject", propertiesToInclude); - }, - _toObjectMethod: function(methodName, propertiesToInclude) { - var data = { - version: fabric.version, - objects: this._toObjects(methodName, propertiesToInclude) - }; - extend(data, this.__serializeBgOverlay(methodName, propertiesToInclude)); - fabric.util.populateWithProperties(this, data, propertiesToInclude); - return data; - }, - _toObjects: function(methodName, propertiesToInclude) { - return this.getObjects().filter(function(object) { - return !object.excludeFromExport; - }).map(function(instance) { - return this._toObject(instance, methodName, propertiesToInclude); - }, this); - }, - _toObject: function(instance, methodName, propertiesToInclude) { - var originalValue; - if (!this.includeDefaultValues) { - originalValue = instance.includeDefaultValues; - instance.includeDefaultValues = false; - } - var object = instance[methodName](propertiesToInclude); - if (!this.includeDefaultValues) { - instance.includeDefaultValues = originalValue; - } - return object; - }, - __serializeBgOverlay: function(methodName, propertiesToInclude) { - var data = {}, bgImage = this.backgroundImage, overlay = this.overlayImage; - if (this.backgroundColor) { - data.background = this.backgroundColor.toObject ? this.backgroundColor.toObject(propertiesToInclude) : this.backgroundColor; - } - if (this.overlayColor) { - data.overlay = this.overlayColor.toObject ? this.overlayColor.toObject(propertiesToInclude) : this.overlayColor; - } - if (bgImage && !bgImage.excludeFromExport) { - data.backgroundImage = this._toObject(bgImage, methodName, propertiesToInclude); - } - if (overlay && !overlay.excludeFromExport) { - data.overlayImage = this._toObject(overlay, methodName, propertiesToInclude); - } - return data; - }, - svgViewportTransformation: true, - toSVG: function(options, reviver) { - options || (options = {}); - var markup = []; - this._setSVGPreamble(markup, options); - this._setSVGHeader(markup, options); - this._setSVGBgOverlayColor(markup, "backgroundColor"); - this._setSVGBgOverlayImage(markup, "backgroundImage", reviver); - this._setSVGObjects(markup, reviver); - this._setSVGBgOverlayColor(markup, "overlayColor"); - this._setSVGBgOverlayImage(markup, "overlayImage", reviver); - markup.push(""); - return markup.join(""); - }, - _setSVGPreamble: function(markup, options) { - if (options.suppressPreamble) { - return; - } - markup.push('\n', '\n'); - }, - _setSVGHeader: function(markup, options) { - var width = options.width || this.width, height = options.height || this.height, vpt, viewBox = 'viewBox="0 0 ' + this.width + " " + this.height + '" ', NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; - if (options.viewBox) { - viewBox = 'viewBox="' + options.viewBox.x + " " + options.viewBox.y + " " + options.viewBox.width + " " + options.viewBox.height + '" '; - } else { - if (this.svgViewportTransformation) { - vpt = this.viewportTransform; - viewBox = 'viewBox="' + toFixed(-vpt[4] / vpt[0], NUM_FRACTION_DIGITS) + " " + toFixed(-vpt[5] / vpt[3], NUM_FRACTION_DIGITS) + " " + toFixed(this.width / vpt[0], NUM_FRACTION_DIGITS) + " " + toFixed(this.height / vpt[3], NUM_FRACTION_DIGITS) + '" '; - } - } - markup.push("\n', "Created with Fabric.js ", fabric.version, "\n", "\n", this.createSVGFontFacesMarkup(), this.createSVGRefElementsMarkup(), "\n"); - }, - createSVGRefElementsMarkup: function() { - var _this = this, markup = [ "backgroundColor", "overlayColor" ].map(function(prop) { - var fill = _this[prop]; - if (fill && fill.toLive) { - return fill.toSVG(_this, false); - } - }); - return markup.join(""); - }, - createSVGFontFacesMarkup: function() { - var markup = "", fontList = {}, obj, fontFamily, style, row, rowIndex, _char, charIndex, i, len, fontPaths = fabric.fontPaths, objects = this.getObjects(); - for (i = 0, len = objects.length; i < len; i++) { - obj = objects[i]; - fontFamily = obj.fontFamily; - if (obj.type.indexOf("text") === -1 || fontList[fontFamily] || !fontPaths[fontFamily]) { - continue; - } - fontList[fontFamily] = true; - if (!obj.styles) { - continue; - } - style = obj.styles; - for (rowIndex in style) { - row = style[rowIndex]; - for (charIndex in row) { - _char = row[charIndex]; - fontFamily = _char.fontFamily; - if (!fontList[fontFamily] && fontPaths[fontFamily]) { - fontList[fontFamily] = true; - } - } - } - } - for (var j in fontList) { - markup += [ "\t\t@font-face {\n", "\t\t\tfont-family: '", j, "';\n", "\t\t\tsrc: url('", fontPaths[j], "');\n", "\t\t}\n" ].join(""); - } - if (markup) { - markup = [ '\t\n" ].join(""); - } - return markup; - }, - _setSVGObjects: function(markup, reviver) { - var instance, i, len, objects = this.getObjects(); - for (i = 0, len = objects.length; i < len; i++) { - instance = objects[i]; - if (instance.excludeFromExport) { - continue; - } - this._setSVGObject(markup, instance, reviver); - } - }, - _setSVGObject: function(markup, instance, reviver) { - markup.push(instance.toSVG(reviver)); - }, - _setSVGBgOverlayImage: function(markup, property, reviver) { - if (this[property] && this[property].toSVG) { - markup.push(this[property].toSVG(reviver)); - } - }, - _setSVGBgOverlayColor: function(markup, property) { - var filler = this[property]; - if (!filler) { - return; - } - if (filler.toLive) { - var repeat = filler.repeat; - markup.push('\n"); - } else { - markup.push('\n"); - } - }, - sendToBack: function(object) { - if (!object) { - return this; - } - var activeSelection = this._activeObject, i, obj, objs; - if (object === activeSelection && object.type === "activeSelection") { - objs = activeSelection._objects; - for (i = objs.length; i--; ) { - obj = objs[i]; - removeFromArray(this._objects, obj); - this._objects.unshift(obj); - } - } else { - removeFromArray(this._objects, object); - this._objects.unshift(object); - } - this.renderOnAddRemove && this.requestRenderAll(); - return this; - }, - bringToFront: function(object) { - if (!object) { - return this; - } - var activeSelection = this._activeObject, i, obj, objs; - if (object === activeSelection && object.type === "activeSelection") { - objs = activeSelection._objects; - for (i = 0; i < objs.length; i++) { - obj = objs[i]; - removeFromArray(this._objects, obj); - this._objects.push(obj); - } - } else { - removeFromArray(this._objects, object); - this._objects.push(object); - } - this.renderOnAddRemove && this.requestRenderAll(); - return this; - }, - sendBackwards: function(object, intersecting) { - if (!object) { - return this; - } - var activeSelection = this._activeObject, i, obj, idx, newIdx, objs, objsMoved = 0; - if (object === activeSelection && object.type === "activeSelection") { - objs = activeSelection._objects; - for (i = 0; i < objs.length; i++) { - obj = objs[i]; - idx = this._objects.indexOf(obj); - if (idx > 0 + objsMoved) { - newIdx = idx - 1; - removeFromArray(this._objects, obj); - this._objects.splice(newIdx, 0, obj); - } - objsMoved++; - } - } else { - idx = this._objects.indexOf(object); - if (idx !== 0) { - newIdx = this._findNewLowerIndex(object, idx, intersecting); - removeFromArray(this._objects, object); - this._objects.splice(newIdx, 0, object); - } - } - this.renderOnAddRemove && this.requestRenderAll(); - return this; - }, - _findNewLowerIndex: function(object, idx, intersecting) { - var newIdx, i; - if (intersecting) { - newIdx = idx; - for (i = idx - 1; i >= 0; --i) { - var isIntersecting = object.intersectsWithObject(this._objects[i]) || object.isContainedWithinObject(this._objects[i]) || this._objects[i].isContainedWithinObject(object); - if (isIntersecting) { - newIdx = i; - break; - } - } - } else { - newIdx = idx - 1; - } - return newIdx; - }, - bringForward: function(object, intersecting) { - if (!object) { - return this; - } - var activeSelection = this._activeObject, i, obj, idx, newIdx, objs, objsMoved = 0; - if (object === activeSelection && object.type === "activeSelection") { - objs = activeSelection._objects; - for (i = objs.length; i--; ) { - obj = objs[i]; - idx = this._objects.indexOf(obj); - if (idx < this._objects.length - 1 - objsMoved) { - newIdx = idx + 1; - removeFromArray(this._objects, obj); - this._objects.splice(newIdx, 0, obj); - } - objsMoved++; - } - } else { - idx = this._objects.indexOf(object); - if (idx !== this._objects.length - 1) { - newIdx = this._findNewUpperIndex(object, idx, intersecting); - removeFromArray(this._objects, object); - this._objects.splice(newIdx, 0, object); - } - } - this.renderOnAddRemove && this.requestRenderAll(); - return this; - }, - _findNewUpperIndex: function(object, idx, intersecting) { - var newIdx, i, len; - if (intersecting) { - newIdx = idx; - for (i = idx + 1, len = this._objects.length; i < len; ++i) { - var isIntersecting = object.intersectsWithObject(this._objects[i]) || object.isContainedWithinObject(this._objects[i]) || this._objects[i].isContainedWithinObject(object); - if (isIntersecting) { - newIdx = i; - break; - } - } - } else { - newIdx = idx + 1; - } - return newIdx; - }, - moveTo: function(object, index) { - removeFromArray(this._objects, object); - this._objects.splice(index, 0, object); - return this.renderOnAddRemove && this.requestRenderAll(); - }, - dispose: function() { - this.forEachObject(function(object) { - object.dispose && object.dispose(); - }); - this._objects = []; - this.backgroundImage = null; - this.overlayImage = null; - this._iTextInstances = null; - this.lowerCanvasEl = null; - this.cacheCanvasEl = null; - return this; - }, - toString: function() { - return "#"; - } - }); - extend(fabric.StaticCanvas.prototype, fabric.Observable); - extend(fabric.StaticCanvas.prototype, fabric.Collection); - extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter); - extend(fabric.StaticCanvas, { - EMPTY_JSON: '{"objects": [], "background": "white"}', - supports: function(methodName) { - var el = fabric.util.createCanvasElement(); - if (!el || !el.getContext) { - return null; - } - var ctx = el.getContext("2d"); - if (!ctx) { - return null; - } - switch (methodName) { - case "getImageData": - return typeof ctx.getImageData !== "undefined"; - - case "setLineDash": - return typeof ctx.setLineDash !== "undefined"; - - case "toDataURL": - return typeof el.toDataURL !== "undefined"; - - case "toDataURLWithQuality": - try { - el.toDataURL("image/jpeg", 0); - return true; - } catch (e) {} - return false; - - default: - return null; - } - } - }); - fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject; - if (fabric.isLikelyNode) { - fabric.StaticCanvas.prototype.createPNGStream = function() { - var impl = fabric.util.getNodeCanvas(this.lowerCanvasEl); - return impl && impl.createPNGStream(); - }; - fabric.StaticCanvas.prototype.createJPEGStream = function(opts) { - var impl = fabric.util.getNodeCanvas(this.lowerCanvasEl); - return impl && impl.createJPEGStream(opts); - }; - } -})(); - -fabric.BaseBrush = fabric.util.createClass({ - color: "rgb(0, 0, 0)", - width: 1, - shadow: null, - strokeLineCap: "round", - strokeLineJoin: "round", - strokeMiterLimit: 10, - strokeDashArray: null, - setShadow: function(options) { - this.shadow = new fabric.Shadow(options); - return this; - }, - _setBrushStyles: function() { - var ctx = this.canvas.contextTop; - ctx.strokeStyle = this.color; - ctx.lineWidth = this.width; - ctx.lineCap = this.strokeLineCap; - ctx.miterLimit = this.strokeMiterLimit; - ctx.lineJoin = this.strokeLineJoin; - if (this.strokeDashArray && fabric.StaticCanvas.supports("setLineDash")) { - ctx.setLineDash(this.strokeDashArray); - } - }, - _saveAndTransform: function(ctx) { - var v = this.canvas.viewportTransform; - ctx.save(); - ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); - }, - _setShadow: function() { - if (!this.shadow) { - return; - } - var ctx = this.canvas.contextTop, zoom = this.canvas.getZoom(); - ctx.shadowColor = this.shadow.color; - ctx.shadowBlur = this.shadow.blur * zoom; - ctx.shadowOffsetX = this.shadow.offsetX * zoom; - ctx.shadowOffsetY = this.shadow.offsetY * zoom; - }, - _resetShadow: function() { - var ctx = this.canvas.contextTop; - ctx.shadowColor = ""; - ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; - } -}); - -(function() { - fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush, { - initialize: function(canvas) { - this.canvas = canvas; - this._points = []; - }, - onMouseDown: function(pointer) { - this._prepareForDrawing(pointer); - this._captureDrawingPath(pointer); - this._render(); - }, - onMouseMove: function(pointer) { - this._captureDrawingPath(pointer); - this.canvas.clearContext(this.canvas.contextTop); - this._render(); - }, - onMouseUp: function() { - this._finalizeAndAddPath(); - }, - _prepareForDrawing: function(pointer) { - var p = new fabric.Point(pointer.x, pointer.y); - this._reset(); - this._addPoint(p); - this.canvas.contextTop.moveTo(p.x, p.y); - }, - _addPoint: function(point) { - if (this._points.length > 1 && point.eq(this._points[this._points.length - 1])) { - return; - } - this._points.push(point); - }, - _reset: function() { - this._points.length = 0; - this._setBrushStyles(); - this._setShadow(); - }, - _captureDrawingPath: function(pointer) { - var pointerPoint = new fabric.Point(pointer.x, pointer.y); - this._addPoint(pointerPoint); - }, - _render: function() { - var ctx = this.canvas.contextTop, i, len, p1 = this._points[0], p2 = this._points[1]; - this._saveAndTransform(ctx); - ctx.beginPath(); - if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) { - var width = this.width / 1e3; - p1 = new fabric.Point(p1.x, p1.y); - p2 = new fabric.Point(p2.x, p2.y); - p1.x -= width; - p2.x += width; - } - ctx.moveTo(p1.x, p1.y); - for (i = 1, len = this._points.length; i < len; i++) { - var midPoint = p1.midPointFrom(p2); - ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y); - p1 = this._points[i]; - p2 = this._points[i + 1]; - } - ctx.lineTo(p1.x, p1.y); - ctx.stroke(); - ctx.restore(); - }, - convertPointsToSVGPath: function(points) { - var path = [], i, width = this.width / 1e3, p1 = new fabric.Point(points[0].x, points[0].y), p2 = new fabric.Point(points[1].x, points[1].y), len = points.length, multSignX = 1, multSignY = 1, manyPoints = len > 2; - if (manyPoints) { - multSignX = points[2].x < p2.x ? -1 : points[2].x === p2.x ? 0 : 1; - multSignY = points[2].y < p2.y ? -1 : points[2].y === p2.y ? 0 : 1; - } - path.push("M ", p1.x - multSignX * width, " ", p1.y - multSignY * width, " "); - for (i = 1; i < len; i++) { - if (!p1.eq(p2)) { - var midPoint = p1.midPointFrom(p2); - path.push("Q ", p1.x, " ", p1.y, " ", midPoint.x, " ", midPoint.y, " "); - } - p1 = points[i]; - if (i + 1 < points.length) { - p2 = points[i + 1]; - } - } - if (manyPoints) { - multSignX = p1.x > points[i - 2].x ? 1 : p1.x === points[i - 2].x ? 0 : -1; - multSignY = p1.y > points[i - 2].y ? 1 : p1.y === points[i - 2].y ? 0 : -1; - } - path.push("L ", p1.x + multSignX * width, " ", p1.y + multSignY * width); - return path; - }, - createPath: function(pathData) { - var path = new fabric.Path(pathData, { - fill: null, - stroke: this.color, - strokeWidth: this.width, - strokeLineCap: this.strokeLineCap, - strokeMiterLimit: this.strokeMiterLimit, - strokeLineJoin: this.strokeLineJoin, - strokeDashArray: this.strokeDashArray - }); - var position = new fabric.Point(path.left + path.width / 2, path.top + path.height / 2); - position = path.translateToGivenOrigin(position, "center", "center", path.originX, path.originY); - path.top = position.y; - path.left = position.x; - if (this.shadow) { - this.shadow.affectStroke = true; - path.setShadow(this.shadow); - } - return path; - }, - _finalizeAndAddPath: function() { - var ctx = this.canvas.contextTop; - ctx.closePath(); - var pathData = this.convertPointsToSVGPath(this._points).join(""); - if (pathData === "M 0 0 Q 0 0 0 0 L 0 0") { - this.canvas.requestRenderAll(); - return; - } - var path = this.createPath(pathData); - this.canvas.clearContext(this.canvas.contextTop); - this.canvas.add(path); - this.canvas.renderAll(); - path.setCoords(); - this._resetShadow(); - this.canvas.fire("path:created", { - path: path - }); - } - }); -})(); - -fabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, { - width: 10, - initialize: function(canvas) { - this.canvas = canvas; - this.points = []; - }, - drawDot: function(pointer) { - var point = this.addPoint(pointer), ctx = this.canvas.contextTop; - this._saveAndTransform(ctx); - ctx.fillStyle = point.fill; - ctx.beginPath(); - ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false); - ctx.closePath(); - ctx.fill(); - ctx.restore(); - }, - onMouseDown: function(pointer) { - this.points.length = 0; - this.canvas.clearContext(this.canvas.contextTop); - this._setShadow(); - this.drawDot(pointer); - }, - _render: function() { - var ctx = this.canvas.contextTop, i, len, points = this.points, point; - this._saveAndTransform(ctx); - for (i = 0, len = points.length; i < len; i++) { - point = points[i]; - ctx.fillStyle = point.fill; - ctx.beginPath(); - ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false); - ctx.closePath(); - ctx.fill(); - } - ctx.restore(); - }, - onMouseMove: function(pointer) { - this.drawDot(pointer); - }, - onMouseUp: function() { - var originalRenderOnAddRemove = this.canvas.renderOnAddRemove, i, len; - this.canvas.renderOnAddRemove = false; - var circles = []; - for (i = 0, len = this.points.length; i < len; i++) { - var point = this.points[i], circle = new fabric.Circle({ - radius: point.radius, - left: point.x, - top: point.y, - originX: "center", - originY: "center", - fill: point.fill - }); - this.shadow && circle.setShadow(this.shadow); - circles.push(circle); - } - var group = new fabric.Group(circles, { - originX: "center", - originY: "center" - }); - group.canvas = this.canvas; - this.canvas.add(group); - this.canvas.fire("path:created", { - path: group - }); - this.canvas.clearContext(this.canvas.contextTop); - this._resetShadow(); - this.canvas.renderOnAddRemove = originalRenderOnAddRemove; - this.canvas.requestRenderAll(); - }, - addPoint: function(pointer) { - var pointerPoint = new fabric.Point(pointer.x, pointer.y), circleRadius = fabric.util.getRandomInt(Math.max(0, this.width - 20), this.width + 20) / 2, circleColor = new fabric.Color(this.color).setAlpha(fabric.util.getRandomInt(0, 100) / 100).toRgba(); - pointerPoint.radius = circleRadius; - pointerPoint.fill = circleColor; - this.points.push(pointerPoint); - return pointerPoint; - } -}); - -fabric.SprayBrush = fabric.util.createClass(fabric.BaseBrush, { - width: 10, - density: 20, - dotWidth: 1, - dotWidthVariance: 1, - randomOpacity: false, - optimizeOverlapping: true, - initialize: function(canvas) { - this.canvas = canvas; - this.sprayChunks = []; - }, - onMouseDown: function(pointer) { - this.sprayChunks.length = 0; - this.canvas.clearContext(this.canvas.contextTop); - this._setShadow(); - this.addSprayChunk(pointer); - this.render(this.sprayChunkPoints); - }, - onMouseMove: function(pointer) { - this.addSprayChunk(pointer); - this.render(this.sprayChunkPoints); - }, - onMouseUp: function() { - var originalRenderOnAddRemove = this.canvas.renderOnAddRemove; - this.canvas.renderOnAddRemove = false; - var rects = []; - for (var i = 0, ilen = this.sprayChunks.length; i < ilen; i++) { - var sprayChunk = this.sprayChunks[i]; - for (var j = 0, jlen = sprayChunk.length; j < jlen; j++) { - var rect = new fabric.Rect({ - width: sprayChunk[j].width, - height: sprayChunk[j].width, - left: sprayChunk[j].x + 1, - top: sprayChunk[j].y + 1, - originX: "center", - originY: "center", - fill: this.color - }); - rects.push(rect); - } - } - if (this.optimizeOverlapping) { - rects = this._getOptimizedRects(rects); - } - var group = new fabric.Group(rects, { - originX: "center", - originY: "center" - }); - this.shadow && group.setShadow(this.shadow); - this.canvas.add(group); - this.canvas.fire("path:created", { - path: group - }); - this.canvas.clearContext(this.canvas.contextTop); - this._resetShadow(); - this.canvas.renderOnAddRemove = originalRenderOnAddRemove; - this.canvas.requestRenderAll(); - }, - _getOptimizedRects: function(rects) { - var uniqueRects = {}, key, i, len; - for (i = 0, len = rects.length; i < len; i++) { - key = rects[i].left + "" + rects[i].top; - if (!uniqueRects[key]) { - uniqueRects[key] = rects[i]; - } - } - var uniqueRectsArray = []; - for (key in uniqueRects) { - uniqueRectsArray.push(uniqueRects[key]); - } - return uniqueRectsArray; - }, - render: function(sprayChunk) { - var ctx = this.canvas.contextTop, i, len; - ctx.fillStyle = this.color; - this._saveAndTransform(ctx); - for (i = 0, len = sprayChunk.length; i < len; i++) { - var point = sprayChunk[i]; - if (typeof point.opacity !== "undefined") { - ctx.globalAlpha = point.opacity; - } - ctx.fillRect(point.x, point.y, point.width, point.width); - } - ctx.restore(); - }, - _render: function() { - var ctx = this.canvas.contextTop, i, ilen; - ctx.fillStyle = this.color; - this._saveAndTransform(ctx); - for (i = 0, ilen = this.sprayChunks.length; i < ilen; i++) { - this.render(this.sprayChunks[i]); - } - ctx.restore(); - }, - addSprayChunk: function(pointer) { - this.sprayChunkPoints = []; - var x, y, width, radius = this.width / 2, i; - for (i = 0; i < this.density; i++) { - x = fabric.util.getRandomInt(pointer.x - radius, pointer.x + radius); - y = fabric.util.getRandomInt(pointer.y - radius, pointer.y + radius); - if (this.dotWidthVariance) { - width = fabric.util.getRandomInt(Math.max(1, this.dotWidth - this.dotWidthVariance), this.dotWidth + this.dotWidthVariance); - } else { - width = this.dotWidth; - } - var point = new fabric.Point(x, y); - point.width = width; - if (this.randomOpacity) { - point.opacity = fabric.util.getRandomInt(0, 100) / 100; - } - this.sprayChunkPoints.push(point); - } - this.sprayChunks.push(this.sprayChunkPoints); - } -}); - -fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, { - getPatternSrc: function() { - var dotWidth = 20, dotDistance = 5, patternCanvas = fabric.document.createElement("canvas"), patternCtx = patternCanvas.getContext("2d"); - patternCanvas.width = patternCanvas.height = dotWidth + dotDistance; - patternCtx.fillStyle = this.color; - patternCtx.beginPath(); - patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false); - patternCtx.closePath(); - patternCtx.fill(); - return patternCanvas; - }, - getPatternSrcFunction: function() { - return String(this.getPatternSrc).replace("this.color", '"' + this.color + '"'); - }, - getPattern: function() { - return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), "repeat"); - }, - _setBrushStyles: function() { - this.callSuper("_setBrushStyles"); - this.canvas.contextTop.strokeStyle = this.getPattern(); - }, - createPath: function(pathData) { - var path = this.callSuper("createPath", pathData), topLeft = path._getLeftTopCoords().scalarAdd(path.strokeWidth / 2); - path.stroke = new fabric.Pattern({ - source: this.source || this.getPatternSrcFunction(), - offsetX: -topLeft.x, - offsetY: -topLeft.y - }); - return path; - } -}); - -(function() { - var getPointer = fabric.util.getPointer, degreesToRadians = fabric.util.degreesToRadians, radiansToDegrees = fabric.util.radiansToDegrees, atan2 = Math.atan2, abs = Math.abs, supportLineDash = fabric.StaticCanvas.supports("setLineDash"), STROKE_OFFSET = .5; - fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, { - initialize: function(el, options) { - options || (options = {}); - this.renderAndResetBound = this.renderAndReset.bind(this); - this._initStatic(el, options); - this._initInteractive(); - this._createCacheCanvas(); - }, - uniScaleTransform: false, - uniScaleKey: "shiftKey", - centeredScaling: false, - centeredRotation: false, - centeredKey: "altKey", - altActionKey: "shiftKey", - interactive: true, - selection: true, - selectionKey: "shiftKey", - altSelectionKey: null, - selectionColor: "rgba(100, 100, 255, 0.3)", - selectionDashArray: [], - selectionBorderColor: "rgba(255, 255, 255, 0.3)", - selectionLineWidth: 1, - selectionFullyContained: false, - hoverCursor: "move", - moveCursor: "move", - defaultCursor: "default", - freeDrawingCursor: "crosshair", - rotationCursor: "crosshair", - notAllowedCursor: "not-allowed", - containerClass: "canvas-container", - perPixelTargetFind: false, - targetFindTolerance: 0, - skipTargetFind: false, - isDrawingMode: false, - preserveObjectStacking: false, - snapAngle: 0, - snapThreshold: null, - stopContextMenu: false, - fireRightClick: false, - fireMiddleClick: false, - _initInteractive: function() { - this._currentTransform = null; - this._groupSelector = null; - this._initWrapperElement(); - this._createUpperCanvas(); - this._initEventListeners(); - this._initRetinaScaling(); - this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this); - this.calcOffset(); - }, - _chooseObjectsToRender: function() { - var activeObjects = this.getActiveObjects(), object, objsToRender, activeGroupObjects; - if (activeObjects.length > 0 && !this.preserveObjectStacking) { - objsToRender = []; - activeGroupObjects = []; - for (var i = 0, length = this._objects.length; i < length; i++) { - object = this._objects[i]; - if (activeObjects.indexOf(object) === -1) { - objsToRender.push(object); - } else { - activeGroupObjects.push(object); - } - } - if (activeObjects.length > 1) { - this._activeObject._objects = activeGroupObjects; - } - objsToRender.push.apply(objsToRender, activeGroupObjects); - } else { - objsToRender = this._objects; - } - return objsToRender; - }, - renderAll: function() { - if (this.contextTopDirty && !this._groupSelector && !this.isDrawingMode) { - this.clearContext(this.contextTop); - this.contextTopDirty = false; - } - if (this.isDrawingMode && this._isCurrentlyDrawing) { - this.freeDrawingBrush && this.freeDrawingBrush._render(); - } - var canvasToDrawOn = this.contextContainer; - this.renderCanvas(canvasToDrawOn, this._chooseObjectsToRender()); - return this; - }, - renderTop: function() { - var ctx = this.contextTop; - this.clearContext(ctx); - if (this.selection && this._groupSelector) { - this._drawSelection(ctx); - } - this.fire("after:render"); - this.contextTopDirty = true; - return this; - }, - _resetCurrentTransform: function() { - var t = this._currentTransform; - t.target.set({ - scaleX: t.original.scaleX, - scaleY: t.original.scaleY, - skewX: t.original.skewX, - skewY: t.original.skewY, - left: t.original.left, - top: t.original.top - }); - if (this._shouldCenterTransform(t.target)) { - if (t.action === "rotate") { - this._setOriginToCenter(t.target); - } else { - if (t.originX !== "center") { - if (t.originX === "right") { - t.mouseXSign = -1; - } else { - t.mouseXSign = 1; - } - } - if (t.originY !== "center") { - if (t.originY === "bottom") { - t.mouseYSign = -1; - } else { - t.mouseYSign = 1; - } - } - t.originX = "center"; - t.originY = "center"; - } - } else { - t.originX = t.original.originX; - t.originY = t.original.originY; - } - }, - containsPoint: function(e, target, point) { - var ignoreZoom = true, pointer = point || this.getPointer(e, ignoreZoom), xy; - if (target.group && target.group === this._activeObject && target.group.type === "activeSelection") { - xy = this._normalizePointer(target.group, pointer); - } else { - xy = { - x: pointer.x, - y: pointer.y - }; - } - return target.containsPoint(xy) || target._findTargetCorner(pointer); - }, - _normalizePointer: function(object, pointer) { - var m = object.calcTransformMatrix(), invertedM = fabric.util.invertTransform(m), vptPointer = this.restorePointerVpt(pointer); - return fabric.util.transformPoint(vptPointer, invertedM); - }, - isTargetTransparent: function(target, x, y) { - var ctx = this.contextCache, originalColor = target.selectionBackgroundColor, v = this.viewportTransform; - target.selectionBackgroundColor = ""; - this.clearContext(ctx); - ctx.save(); - ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); - target.render(ctx); - ctx.restore(); - target === this._activeObject && target._renderControls(ctx, { - hasBorders: false, - transparentCorners: false - }, { - hasBorders: false - }); - target.selectionBackgroundColor = originalColor; - var isTransparent = fabric.util.isTransparent(ctx, x, y, this.targetFindTolerance); - return isTransparent; - }, - _isSelectionKeyPressed: function(e) { - var selectionKeyPressed = false; - if (Object.prototype.toString.call(this.selectionKey) === "[object Array]") { - selectionKeyPressed = !!this.selectionKey.find(function(key) { - return e[key] === true; - }); - } else { - selectionKeyPressed = e[this.selectionKey]; - } - return selectionKeyPressed; - }, - _shouldClearSelection: function(e, target) { - var activeObjects = this.getActiveObjects(), activeObject = this._activeObject; - return !target || target && activeObject && activeObjects.length > 1 && activeObjects.indexOf(target) === -1 && activeObject !== target && !this._isSelectionKeyPressed(e) || target && !target.evented || target && !target.selectable && activeObject && activeObject !== target; - }, - _shouldCenterTransform: function(target) { - if (!target) { - return; - } - var t = this._currentTransform, centerTransform; - if (t.action === "scale" || t.action === "scaleX" || t.action === "scaleY") { - centerTransform = this.centeredScaling || target.centeredScaling; - } else if (t.action === "rotate") { - centerTransform = this.centeredRotation || target.centeredRotation; - } - return centerTransform ? !t.altKey : t.altKey; - }, - _getOriginFromCorner: function(target, corner) { - var origin = { - x: target.originX, - y: target.originY - }; - if (corner === "ml" || corner === "tl" || corner === "bl") { - origin.x = "right"; - } else if (corner === "mr" || corner === "tr" || corner === "br") { - origin.x = "left"; - } - if (corner === "tl" || corner === "mt" || corner === "tr") { - origin.y = "bottom"; - } else if (corner === "bl" || corner === "mb" || corner === "br") { - origin.y = "top"; - } - return origin; - }, - _getActionFromCorner: function(target, corner, e) { - if (!corner) { - return "drag"; - } - switch (corner) { - case "mtr": - return "rotate"; - - case "ml": - case "mr": - return e[this.altActionKey] ? "skewY" : "scaleX"; - - case "mt": - case "mb": - return e[this.altActionKey] ? "skewX" : "scaleY"; - - default: - return "scale"; - } - }, - _setupCurrentTransform: function(e, target) { - if (!target) { - return; - } - var pointer = this.getPointer(e), corner = target._findTargetCorner(this.getPointer(e, true)), action = this._getActionFromCorner(target, corner, e), origin = this._getOriginFromCorner(target, corner); - this._currentTransform = { - target: target, - action: action, - corner: corner, - scaleX: target.scaleX, - scaleY: target.scaleY, - skewX: target.skewX, - skewY: target.skewY, - offsetX: pointer.x - target.left, - offsetY: pointer.y - target.top, - originX: origin.x, - originY: origin.y, - ex: pointer.x, - ey: pointer.y, - lastX: pointer.x, - lastY: pointer.y, - left: target.left, - top: target.top, - theta: degreesToRadians(target.angle), - width: target.width * target.scaleX, - mouseXSign: 1, - mouseYSign: 1, - shiftKey: e.shiftKey, - altKey: e[this.centeredKey] - }; - this._currentTransform.original = { - left: target.left, - top: target.top, - scaleX: target.scaleX, - scaleY: target.scaleY, - skewX: target.skewX, - skewY: target.skewY, - originX: origin.x, - originY: origin.y - }; - this._resetCurrentTransform(); - }, - _translateObject: function(x, y) { - var transform = this._currentTransform, target = transform.target, newLeft = x - transform.offsetX, newTop = y - transform.offsetY, moveX = !target.get("lockMovementX") && target.left !== newLeft, moveY = !target.get("lockMovementY") && target.top !== newTop; - moveX && target.set("left", newLeft); - moveY && target.set("top", newTop); - return moveX || moveY; - }, - _changeSkewTransformOrigin: function(mouseMove, t, by) { - var property = "originX", origins = { - 0: "center" - }, skew = t.target.skewX, originA = "left", originB = "right", corner = t.corner === "mt" || t.corner === "ml" ? 1 : -1, flipSign = 1; - mouseMove = mouseMove > 0 ? 1 : -1; - if (by === "y") { - skew = t.target.skewY; - originA = "top"; - originB = "bottom"; - property = "originY"; - } - origins[-1] = originA; - origins[1] = originB; - t.target.flipX && (flipSign *= -1); - t.target.flipY && (flipSign *= -1); - if (skew === 0) { - t.skewSign = -corner * mouseMove * flipSign; - t[property] = origins[-mouseMove]; - } else { - skew = skew > 0 ? 1 : -1; - t.skewSign = skew; - t[property] = origins[skew * corner * flipSign]; - } - }, - _skewObject: function(x, y, by) { - var t = this._currentTransform, target = t.target, skewed = false, lockSkewingX = target.get("lockSkewingX"), lockSkewingY = target.get("lockSkewingY"); - if (lockSkewingX && by === "x" || lockSkewingY && by === "y") { - return false; - } - var center = target.getCenterPoint(), actualMouseByCenter = target.toLocalPoint(new fabric.Point(x, y), "center", "center")[by], lastMouseByCenter = target.toLocalPoint(new fabric.Point(t.lastX, t.lastY), "center", "center")[by], actualMouseByOrigin, constraintPosition, dim = target._getTransformedDimensions(); - this._changeSkewTransformOrigin(actualMouseByCenter - lastMouseByCenter, t, by); - actualMouseByOrigin = target.toLocalPoint(new fabric.Point(x, y), t.originX, t.originY)[by]; - constraintPosition = target.translateToOriginPoint(center, t.originX, t.originY); - skewed = this._setObjectSkew(actualMouseByOrigin, t, by, dim); - t.lastX = x; - t.lastY = y; - target.setPositionByOrigin(constraintPosition, t.originX, t.originY); - return skewed; - }, - _setObjectSkew: function(localMouse, transform, by, _dim) { - var target = transform.target, newValue, skewed = false, skewSign = transform.skewSign, newDim, dimNoSkew, otherBy, _otherBy, _by, newDimMouse, skewX, skewY; - if (by === "x") { - otherBy = "y"; - _otherBy = "Y"; - _by = "X"; - skewX = 0; - skewY = target.skewY; - } else { - otherBy = "x"; - _otherBy = "X"; - _by = "Y"; - skewX = target.skewX; - skewY = 0; - } - dimNoSkew = target._getTransformedDimensions(skewX, skewY); - newDimMouse = 2 * Math.abs(localMouse) - dimNoSkew[by]; - if (newDimMouse <= 2) { - newValue = 0; - } else { - newValue = skewSign * Math.atan(newDimMouse / target["scale" + _by] / (dimNoSkew[otherBy] / target["scale" + _otherBy])); - newValue = fabric.util.radiansToDegrees(newValue); - } - skewed = target["skew" + _by] !== newValue; - target.set("skew" + _by, newValue); - if (target["skew" + _otherBy] !== 0) { - newDim = target._getTransformedDimensions(); - newValue = _dim[otherBy] / newDim[otherBy] * target["scale" + _otherBy]; - target.set("scale" + _otherBy, newValue); - } - return skewed; - }, - _scaleObject: function(x, y, by) { - var t = this._currentTransform, target = t.target, lockScalingX = target.get("lockScalingX"), lockScalingY = target.get("lockScalingY"), lockScalingFlip = target.get("lockScalingFlip"); - if (lockScalingX && lockScalingY) { - return false; - } - var constraintPosition = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY), localMouse = target.toLocalPoint(new fabric.Point(x, y), t.originX, t.originY), dim = target._getTransformedDimensions(), scaled = false; - this._setLocalMouse(localMouse, t); - scaled = this._setObjectScale(localMouse, t, lockScalingX, lockScalingY, by, lockScalingFlip, dim); - target.setPositionByOrigin(constraintPosition, t.originX, t.originY); - return scaled; - }, - _setObjectScale: function(localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip, _dim) { - var target = transform.target, forbidScalingX = false, forbidScalingY = false, scaled = false, changeX, changeY, scaleX, scaleY; - scaleX = localMouse.x * target.scaleX / _dim.x; - scaleY = localMouse.y * target.scaleY / _dim.y; - changeX = target.scaleX !== scaleX; - changeY = target.scaleY !== scaleY; - if (lockScalingFlip && scaleX <= 0 && scaleX < target.scaleX) { - forbidScalingX = true; - localMouse.x = 0; - } - if (lockScalingFlip && scaleY <= 0 && scaleY < target.scaleY) { - forbidScalingY = true; - localMouse.y = 0; - } - if (by === "equally" && !lockScalingX && !lockScalingY) { - scaled = this._scaleObjectEqually(localMouse, target, transform, _dim); - } else if (!by) { - forbidScalingX || lockScalingX || target.set("scaleX", scaleX) && (scaled = scaled || changeX); - forbidScalingY || lockScalingY || target.set("scaleY", scaleY) && (scaled = scaled || changeY); - } else if (by === "x" && !target.get("lockUniScaling")) { - forbidScalingX || lockScalingX || target.set("scaleX", scaleX) && (scaled = scaled || changeX); - } else if (by === "y" && !target.get("lockUniScaling")) { - forbidScalingY || lockScalingY || target.set("scaleY", scaleY) && (scaled = scaled || changeY); - } - transform.newScaleX = scaleX; - transform.newScaleY = scaleY; - forbidScalingX || forbidScalingY || this._flipObject(transform, by); - return scaled; - }, - _scaleObjectEqually: function(localMouse, target, transform, _dim) { - var dist = localMouse.y + localMouse.x, lastDist = _dim.y * transform.original.scaleY / target.scaleY + _dim.x * transform.original.scaleX / target.scaleX, scaled, signX = localMouse.x < 0 ? -1 : 1, signY = localMouse.y < 0 ? -1 : 1; - transform.newScaleX = signX * Math.abs(transform.original.scaleX * dist / lastDist); - transform.newScaleY = signY * Math.abs(transform.original.scaleY * dist / lastDist); - scaled = transform.newScaleX !== target.scaleX || transform.newScaleY !== target.scaleY; - target.set("scaleX", transform.newScaleX); - target.set("scaleY", transform.newScaleY); - return scaled; - }, - _flipObject: function(transform, by) { - if (transform.newScaleX < 0 && by !== "y") { - if (transform.originX === "left") { - transform.originX = "right"; - } else if (transform.originX === "right") { - transform.originX = "left"; - } - } - if (transform.newScaleY < 0 && by !== "x") { - if (transform.originY === "top") { - transform.originY = "bottom"; - } else if (transform.originY === "bottom") { - transform.originY = "top"; - } - } - }, - _setLocalMouse: function(localMouse, t) { - var target = t.target, zoom = this.getZoom(), padding = target.padding / zoom; - if (t.originX === "right") { - localMouse.x *= -1; - } else if (t.originX === "center") { - localMouse.x *= t.mouseXSign * 2; - if (localMouse.x < 0) { - t.mouseXSign = -t.mouseXSign; - } - } - if (t.originY === "bottom") { - localMouse.y *= -1; - } else if (t.originY === "center") { - localMouse.y *= t.mouseYSign * 2; - if (localMouse.y < 0) { - t.mouseYSign = -t.mouseYSign; - } - } - if (abs(localMouse.x) > padding) { - if (localMouse.x < 0) { - localMouse.x += padding; - } else { - localMouse.x -= padding; - } - } else { - localMouse.x = 0; - } - if (abs(localMouse.y) > padding) { - if (localMouse.y < 0) { - localMouse.y += padding; - } else { - localMouse.y -= padding; - } - } else { - localMouse.y = 0; - } - }, - _rotateObject: function(x, y) { - var t = this._currentTransform; - if (t.target.get("lockRotation")) { - return false; - } - var lastAngle = atan2(t.ey - t.top, t.ex - t.left), curAngle = atan2(y - t.top, x - t.left), angle = radiansToDegrees(curAngle - lastAngle + t.theta), hasRotated = true; - if (t.target.snapAngle > 0) { - var snapAngle = t.target.snapAngle, snapThreshold = t.target.snapThreshold || snapAngle, rightAngleLocked = Math.ceil(angle / snapAngle) * snapAngle, leftAngleLocked = Math.floor(angle / snapAngle) * snapAngle; - if (Math.abs(angle - leftAngleLocked) < snapThreshold) { - angle = leftAngleLocked; - } else if (Math.abs(angle - rightAngleLocked) < snapThreshold) { - angle = rightAngleLocked; - } - } - if (angle < 0) { - angle = 360 + angle; - } - angle %= 360; - if (t.target.angle === angle) { - hasRotated = false; - } else { - t.target.angle = angle; - } - return hasRotated; - }, - setCursor: function(value) { - this.upperCanvasEl.style.cursor = value; - }, - _resetObjectTransform: function(target) { - target.scaleX = 1; - target.scaleY = 1; - target.skewX = 0; - target.skewY = 0; - target.rotate(0); - }, - _drawSelection: function(ctx) { - var groupSelector = this._groupSelector, left = groupSelector.left, top = groupSelector.top, aleft = abs(left), atop = abs(top); - if (this.selectionColor) { - ctx.fillStyle = this.selectionColor; - ctx.fillRect(groupSelector.ex - (left > 0 ? 0 : -left), groupSelector.ey - (top > 0 ? 0 : -top), aleft, atop); - } - if (!this.selectionLineWidth || !this.selectionBorderColor) { - return; - } - ctx.lineWidth = this.selectionLineWidth; - ctx.strokeStyle = this.selectionBorderColor; - if (this.selectionDashArray.length > 1 && !supportLineDash) { - var px = groupSelector.ex + STROKE_OFFSET - (left > 0 ? 0 : aleft), py = groupSelector.ey + STROKE_OFFSET - (top > 0 ? 0 : atop); - ctx.beginPath(); - fabric.util.drawDashedLine(ctx, px, py, px + aleft, py, this.selectionDashArray); - fabric.util.drawDashedLine(ctx, px, py + atop - 1, px + aleft, py + atop - 1, this.selectionDashArray); - fabric.util.drawDashedLine(ctx, px, py, px, py + atop, this.selectionDashArray); - fabric.util.drawDashedLine(ctx, px + aleft - 1, py, px + aleft - 1, py + atop, this.selectionDashArray); - ctx.closePath(); - ctx.stroke(); - } else { - fabric.Object.prototype._setLineDash.call(this, ctx, this.selectionDashArray); - ctx.strokeRect(groupSelector.ex + STROKE_OFFSET - (left > 0 ? 0 : aleft), groupSelector.ey + STROKE_OFFSET - (top > 0 ? 0 : atop), aleft, atop); - } - }, - findTarget: function(e, skipGroup) { - if (this.skipTargetFind) { - return; - } - var ignoreZoom = true, pointer = this.getPointer(e, ignoreZoom), activeObject = this._activeObject, aObjects = this.getActiveObjects(), activeTarget, activeTargetSubs; - this.targets = []; - if (aObjects.length > 1 && !skipGroup && activeObject === this._searchPossibleTargets([ activeObject ], pointer)) { - return activeObject; - } - if (aObjects.length === 1 && activeObject._findTargetCorner(pointer)) { - return activeObject; - } - if (aObjects.length === 1 && activeObject === this._searchPossibleTargets([ activeObject ], pointer)) { - if (!this.preserveObjectStacking) { - return activeObject; - } else { - activeTarget = activeObject; - activeTargetSubs = this.targets; - this.targets = []; - } - } - var target = this._searchPossibleTargets(this._objects, pointer); - if (e[this.altSelectionKey] && target && activeTarget && target !== activeTarget) { - target = activeTarget; - this.targets = activeTargetSubs; - } - return target; - }, - _checkTarget: function(pointer, obj) { - if (obj && obj.visible && obj.evented && this.containsPoint(null, obj, pointer)) { - if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) { - var isTransparent = this.isTargetTransparent(obj, pointer.x, pointer.y); - if (!isTransparent) { - return true; - } - } else { - return true; - } - } - }, - _searchPossibleTargets: function(objects, pointer) { - var target, i = objects.length, normalizedPointer, subTarget; - while (i--) { - if (this._checkTarget(pointer, objects[i])) { - target = objects[i]; - if (target.type === "group" && target.subTargetCheck) { - normalizedPointer = this._normalizePointer(target, pointer); - subTarget = this._searchPossibleTargets(target._objects, normalizedPointer); - subTarget && this.targets.push(subTarget); - } - break; - } - } - return target; - }, - restorePointerVpt: function(pointer) { - return fabric.util.transformPoint(pointer, fabric.util.invertTransform(this.viewportTransform)); - }, - getPointer: function(e, ignoreZoom, upperCanvasEl) { - if (!upperCanvasEl) { - upperCanvasEl = this.upperCanvasEl; - } - var pointer = getPointer(e), bounds = upperCanvasEl.getBoundingClientRect(), boundsWidth = bounds.width || 0, boundsHeight = bounds.height || 0, cssScale; - if (!boundsWidth || !boundsHeight) { - if ("top" in bounds && "bottom" in bounds) { - boundsHeight = Math.abs(bounds.top - bounds.bottom); - } - if ("right" in bounds && "left" in bounds) { - boundsWidth = Math.abs(bounds.right - bounds.left); - } - } - this.calcOffset(); - pointer.x = pointer.x - this._offset.left; - pointer.y = pointer.y - this._offset.top; - if (!ignoreZoom) { - pointer = this.restorePointerVpt(pointer); - } - if (boundsWidth === 0 || boundsHeight === 0) { - cssScale = { - width: 1, - height: 1 - }; - } else { - cssScale = { - width: upperCanvasEl.width / boundsWidth, - height: upperCanvasEl.height / boundsHeight - }; - } - return { - x: pointer.x * cssScale.width, - y: pointer.y * cssScale.height - }; - }, - _createUpperCanvas: function() { - var lowerCanvasClass = this.lowerCanvasEl.className.replace(/\s*lower-canvas\s*/, ""); - if (this.upperCanvasEl) { - this.upperCanvasEl.className = ""; - } else { - this.upperCanvasEl = this._createCanvasElement(); - } - fabric.util.addClass(this.upperCanvasEl, "upper-canvas " + lowerCanvasClass); - this.wrapperEl.appendChild(this.upperCanvasEl); - this._copyCanvasStyle(this.lowerCanvasEl, this.upperCanvasEl); - this._applyCanvasStyle(this.upperCanvasEl); - this.contextTop = this.upperCanvasEl.getContext("2d"); - }, - _createCacheCanvas: function() { - this.cacheCanvasEl = this._createCanvasElement(); - this.cacheCanvasEl.setAttribute("width", this.width); - this.cacheCanvasEl.setAttribute("height", this.height); - this.contextCache = this.cacheCanvasEl.getContext("2d"); - }, - _initWrapperElement: function() { - this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, "div", { - class: this.containerClass - }); - fabric.util.setStyle(this.wrapperEl, { - width: this.width + "px", - height: this.height + "px", - position: "relative" - }); - fabric.util.makeElementUnselectable(this.wrapperEl); - }, - _applyCanvasStyle: function(element) { - var width = this.width || element.width, height = this.height || element.height; - fabric.util.setStyle(element, { - position: "absolute", - width: width + "px", - height: height + "px", - left: 0, - top: 0, - "touch-action": "none" - }); - element.width = width; - element.height = height; - fabric.util.makeElementUnselectable(element); - }, - _copyCanvasStyle: function(fromEl, toEl) { - toEl.style.cssText = fromEl.style.cssText; - }, - getSelectionContext: function() { - return this.contextTop; - }, - getSelectionElement: function() { - return this.upperCanvasEl; - }, - getActiveObject: function() { - return this._activeObject; - }, - getActiveObjects: function() { - var active = this._activeObject; - if (active) { - if (active.type === "activeSelection" && active._objects) { - return active._objects.slice(0); - } else { - return [ active ]; - } - } - return []; - }, - _onObjectRemoved: function(obj) { - if (obj === this._activeObject) { - this.fire("before:selection:cleared", { - target: obj - }); - this._discardActiveObject(); - this.fire("selection:cleared", { - target: obj - }); - obj.fire("deselected"); - } - if (this._hoveredTarget === obj) { - this._hoveredTarget = null; - } - this.callSuper("_onObjectRemoved", obj); - }, - _fireSelectionEvents: function(oldObjects, e) { - var somethingChanged = false, objects = this.getActiveObjects(), added = [], removed = [], opt = { - e: e - }; - oldObjects.forEach(function(oldObject) { - if (objects.indexOf(oldObject) === -1) { - somethingChanged = true; - oldObject.fire("deselected", opt); - removed.push(oldObject); - } - }); - objects.forEach(function(object) { - if (oldObjects.indexOf(object) === -1) { - somethingChanged = true; - object.fire("selected", opt); - added.push(object); - } - }); - if (oldObjects.length > 0 && objects.length > 0) { - opt.selected = added; - opt.deselected = removed; - opt.updated = added[0] || removed[0]; - opt.target = this._activeObject; - somethingChanged && this.fire("selection:updated", opt); - } else if (objects.length > 0) { - if (objects.length === 1) { - opt.target = added[0]; - this.fire("object:selected", opt); - } - opt.selected = added; - opt.target = this._activeObject; - this.fire("selection:created", opt); - } else if (oldObjects.length > 0) { - opt.deselected = removed; - this.fire("selection:cleared", opt); - } - }, - setActiveObject: function(object, e) { - var currentActives = this.getActiveObjects(); - this._setActiveObject(object, e); - this._fireSelectionEvents(currentActives, e); - return this; - }, - _setActiveObject: function(object, e) { - if (this._activeObject === object) { - return false; - } - if (!this._discardActiveObject(e, object)) { - return false; - } - if (object.onSelect({ - e: e - })) { - return false; - } - this._activeObject = object; - return true; - }, - _discardActiveObject: function(e, object) { - var obj = this._activeObject; - if (obj) { - if (obj.onDeselect({ - e: e, - object: object - })) { - return false; - } - this._activeObject = null; - } - return true; - }, - discardActiveObject: function(e) { - var currentActives = this.getActiveObjects(); - if (currentActives.length) { - this.fire("before:selection:cleared", { - target: currentActives[0], - e: e - }); - } - this._discardActiveObject(e); - this._fireSelectionEvents(currentActives, e); - return this; - }, - dispose: function() { - var wrapper = this.wrapperEl; - this.removeListeners(); - wrapper.removeChild(this.upperCanvasEl); - wrapper.removeChild(this.lowerCanvasEl); - delete this.upperCanvasEl; - if (wrapper.parentNode) { - wrapper.parentNode.replaceChild(this.lowerCanvasEl, this.wrapperEl); - } - delete this.wrapperEl; - fabric.StaticCanvas.prototype.dispose.call(this); - return this; - }, - clear: function() { - this.discardActiveObject(); - this.clearContext(this.contextTop); - return this.callSuper("clear"); - }, - drawControls: function(ctx) { - var activeObject = this._activeObject; - if (activeObject) { - activeObject._renderControls(ctx); - } - }, - _toObject: function(instance, methodName, propertiesToInclude) { - var originalProperties = this._realizeGroupTransformOnObject(instance), object = this.callSuper("_toObject", instance, methodName, propertiesToInclude); - this._unwindGroupTransformOnObject(instance, originalProperties); - return object; - }, - _realizeGroupTransformOnObject: function(instance) { - if (instance.group && instance.group.type === "activeSelection" && this._activeObject === instance.group) { - var layoutProps = [ "angle", "flipX", "flipY", "left", "scaleX", "scaleY", "skewX", "skewY", "top" ]; - var originalValues = {}; - layoutProps.forEach(function(prop) { - originalValues[prop] = instance[prop]; - }); - this._activeObject.realizeTransform(instance); - return originalValues; - } else { - return null; - } - }, - _unwindGroupTransformOnObject: function(instance, originalValues) { - if (originalValues) { - instance.set(originalValues); - } - }, - _setSVGObject: function(markup, instance, reviver) { - var originalProperties = this._realizeGroupTransformOnObject(instance); - this.callSuper("_setSVGObject", markup, instance, reviver); - this._unwindGroupTransformOnObject(instance, originalProperties); - } - }); - for (var prop in fabric.StaticCanvas) { - if (prop !== "prototype") { - fabric.Canvas[prop] = fabric.StaticCanvas[prop]; - } - } - if (fabric.isTouchSupported) { - fabric.Canvas.prototype._setCursorFromEvent = function() {}; - } -})(); - -(function() { - var cursorOffset = { - mt: 0, - tr: 1, - mr: 2, - br: 3, - mb: 4, - bl: 5, - ml: 6, - tl: 7 - }, addListener = fabric.util.addListener, removeListener = fabric.util.removeListener, RIGHT_CLICK = 3, MIDDLE_CLICK = 2, LEFT_CLICK = 1; - function checkClick(e, value) { - return "which" in e ? e.which === value : e.button === value - 1; - } - fabric.util.object.extend(fabric.Canvas.prototype, { - cursorMap: [ "n-resize", "ne-resize", "e-resize", "se-resize", "s-resize", "sw-resize", "w-resize", "nw-resize" ], - _initEventListeners: function() { - this.removeListeners(); - this._bindEvents(); - addListener(fabric.window, "resize", this._onResize); - addListener(this.upperCanvasEl, "mousedown", this._onMouseDown); - addListener(this.upperCanvasEl, "dblclick", this._onDoubleClick); - addListener(this.upperCanvasEl, "mousemove", this._onMouseMove); - addListener(this.upperCanvasEl, "mouseout", this._onMouseOut); - addListener(this.upperCanvasEl, "mouseenter", this._onMouseEnter); - addListener(this.upperCanvasEl, "wheel", this._onMouseWheel); - addListener(this.upperCanvasEl, "contextmenu", this._onContextMenu); - addListener(this.upperCanvasEl, "touchstart", this._onMouseDown, { - passive: false - }); - addListener(this.upperCanvasEl, "touchmove", this._onMouseMove, { - passive: false - }); - if (typeof eventjs !== "undefined" && "add" in eventjs) { - eventjs.add(this.upperCanvasEl, "gesture", this._onGesture); - eventjs.add(this.upperCanvasEl, "drag", this._onDrag); - eventjs.add(this.upperCanvasEl, "orientation", this._onOrientationChange); - eventjs.add(this.upperCanvasEl, "shake", this._onShake); - eventjs.add(this.upperCanvasEl, "longpress", this._onLongPress); - } - }, - _bindEvents: function() { - if (this.eventsBinded) { - return; - } - this._onMouseDown = this._onMouseDown.bind(this); - this._onMouseMove = this._onMouseMove.bind(this); - this._onMouseUp = this._onMouseUp.bind(this); - this._onResize = this._onResize.bind(this); - this._onGesture = this._onGesture.bind(this); - this._onDrag = this._onDrag.bind(this); - this._onShake = this._onShake.bind(this); - this._onLongPress = this._onLongPress.bind(this); - this._onOrientationChange = this._onOrientationChange.bind(this); - this._onMouseWheel = this._onMouseWheel.bind(this); - this._onMouseOut = this._onMouseOut.bind(this); - this._onMouseEnter = this._onMouseEnter.bind(this); - this._onContextMenu = this._onContextMenu.bind(this); - this._onDoubleClick = this._onDoubleClick.bind(this); - this.eventsBinded = true; - }, - removeListeners: function() { - removeListener(fabric.window, "resize", this._onResize); - removeListener(this.upperCanvasEl, "mousedown", this._onMouseDown); - removeListener(this.upperCanvasEl, "mousemove", this._onMouseMove); - removeListener(this.upperCanvasEl, "mouseout", this._onMouseOut); - removeListener(this.upperCanvasEl, "mouseenter", this._onMouseEnter); - removeListener(this.upperCanvasEl, "wheel", this._onMouseWheel); - removeListener(this.upperCanvasEl, "contextmenu", this._onContextMenu); - removeListener(this.upperCanvasEl, "doubleclick", this._onDoubleClick); - removeListener(this.upperCanvasEl, "touchstart", this._onMouseDown); - removeListener(this.upperCanvasEl, "touchmove", this._onMouseMove); - if (typeof eventjs !== "undefined" && "remove" in eventjs) { - eventjs.remove(this.upperCanvasEl, "gesture", this._onGesture); - eventjs.remove(this.upperCanvasEl, "drag", this._onDrag); - eventjs.remove(this.upperCanvasEl, "orientation", this._onOrientationChange); - eventjs.remove(this.upperCanvasEl, "shake", this._onShake); - eventjs.remove(this.upperCanvasEl, "longpress", this._onLongPress); - } - }, - _onGesture: function(e, self) { - this.__onTransformGesture && this.__onTransformGesture(e, self); - }, - _onDrag: function(e, self) { - this.__onDrag && this.__onDrag(e, self); - }, - _onMouseWheel: function(e) { - this.__onMouseWheel(e); - }, - _onMouseOut: function(e) { - var target = this._hoveredTarget; - this.fire("mouse:out", { - target: target, - e: e - }); - this._hoveredTarget = null; - target && target.fire("mouseout", { - e: e - }); - if (this._iTextInstances) { - this._iTextInstances.forEach(function(obj) { - if (obj.isEditing) { - obj.hiddenTextarea.focus(); - } - }); - } - }, - _onMouseEnter: function(e) { - if (!this.findTarget(e)) { - this.fire("mouse:over", { - target: null, - e: e - }); - this._hoveredTarget = null; - } - }, - _onOrientationChange: function(e, self) { - this.__onOrientationChange && this.__onOrientationChange(e, self); - }, - _onShake: function(e, self) { - this.__onShake && this.__onShake(e, self); - }, - _onLongPress: function(e, self) { - this.__onLongPress && this.__onLongPress(e, self); - }, - _onContextMenu: function(e) { - if (this.stopContextMenu) { - e.stopPropagation(); - e.preventDefault(); - } - return false; - }, - _onDoubleClick: function(e) { - this._handleEvent(e, "dblclick"); - }, - _onMouseDown: function(e) { - this.__onMouseDown(e); - addListener(fabric.document, "touchend", this._onMouseUp, { - passive: false - }); - addListener(fabric.document, "touchmove", this._onMouseMove, { - passive: false - }); - removeListener(this.upperCanvasEl, "mousemove", this._onMouseMove); - removeListener(this.upperCanvasEl, "touchmove", this._onMouseMove); - if (e.type === "touchstart") { - removeListener(this.upperCanvasEl, "mousedown", this._onMouseDown); - } else { - addListener(fabric.document, "mouseup", this._onMouseUp); - addListener(fabric.document, "mousemove", this._onMouseMove); - } - }, - _onMouseUp: function(e) { - this.__onMouseUp(e); - removeListener(fabric.document, "mouseup", this._onMouseUp); - removeListener(fabric.document, "touchend", this._onMouseUp); - removeListener(fabric.document, "mousemove", this._onMouseMove); - removeListener(fabric.document, "touchmove", this._onMouseMove); - addListener(this.upperCanvasEl, "mousemove", this._onMouseMove); - addListener(this.upperCanvasEl, "touchmove", this._onMouseMove, { - passive: false - }); - if (e.type === "touchend") { - var _this = this; - setTimeout(function() { - addListener(_this.upperCanvasEl, "mousedown", _this._onMouseDown); - }, 400); - } - }, - _onMouseMove: function(e) { - !this.allowTouchScrolling && e.preventDefault && e.preventDefault(); - this.__onMouseMove(e); - }, - _onResize: function() { - this.calcOffset(); - }, - _shouldRender: function(target, pointer) { - var activeObject = this._activeObject; - if (activeObject && activeObject.isEditing && target === activeObject) { - return false; - } - return !!(target && (target.isMoving || target !== activeObject) || !target && !!activeObject || !target && !activeObject && !this._groupSelector || pointer && this._previousPointer && this.selection && (pointer.x !== this._previousPointer.x || pointer.y !== this._previousPointer.y)); - }, - __onMouseUp: function(e) { - var target, searchTarget = true, transform = this._currentTransform, groupSelector = this._groupSelector, isClick = !groupSelector || groupSelector.left === 0 && groupSelector.top === 0; - if (checkClick(e, RIGHT_CLICK)) { - if (this.fireRightClick) { - this._handleEvent(e, "up", target, RIGHT_CLICK, isClick); - } - return; - } - if (checkClick(e, MIDDLE_CLICK)) { - if (this.fireMiddleClick) { - this._handleEvent(e, "up", target, MIDDLE_CLICK, isClick); - } - return; - } - if (this.isDrawingMode && this._isCurrentlyDrawing) { - this._onMouseUpInDrawingMode(e); - return; - } - if (transform) { - this._finalizeCurrentTransform(e); - searchTarget = !transform.actionPerformed; - } - target = searchTarget ? this.findTarget(e, true) : transform.target; - var shouldRender = this._shouldRender(target, this.getPointer(e)); - if (target || !isClick) { - this._maybeGroupObjects(e); - } else { - this._groupSelector = null; - this._currentTransform = null; - } - if (target) { - target.isMoving = false; - } - this._setCursorFromEvent(e, target); - this._handleEvent(e, "up", target ? target : null, LEFT_CLICK, isClick); - target && (target.__corner = 0); - shouldRender && this.requestRenderAll(); - }, - _handleEvent: function(e, eventType, targetObj, button, isClick) { - var target = typeof targetObj === "undefined" ? this.findTarget(e) : targetObj, targets = this.targets || [], options = { - e: e, - target: target, - subTargets: targets, - button: button || LEFT_CLICK, - isClick: isClick || false - }; - this.fire("mouse:" + eventType, options); - target && target.fire("mouse" + eventType, options); - for (var i = 0; i < targets.length; i++) { - targets[i].fire("mouse" + eventType, options); - } - }, - _finalizeCurrentTransform: function(e) { - var transform = this._currentTransform, target = transform.target; - if (target._scaling) { - target._scaling = false; - } - target.setCoords(); - this._restoreOriginXY(target); - if (transform.actionPerformed || this.stateful && target.hasStateChanged()) { - this.fire("object:modified", { - target: target, - e: e - }); - target.fire("modified", { - e: e - }); - } - }, - _restoreOriginXY: function(target) { - if (this._previousOriginX && this._previousOriginY) { - var originPoint = target.translateToOriginPoint(target.getCenterPoint(), this._previousOriginX, this._previousOriginY); - target.originX = this._previousOriginX; - target.originY = this._previousOriginY; - target.left = originPoint.x; - target.top = originPoint.y; - this._previousOriginX = null; - this._previousOriginY = null; - } - }, - _onMouseDownInDrawingMode: function(e) { - this._isCurrentlyDrawing = true; - if (this.getActiveObject()) { - this.discardActiveObject(e).requestRenderAll(); - } - if (this.clipTo) { - fabric.util.clipContext(this, this.contextTop); - } - var pointer = this.getPointer(e); - this.freeDrawingBrush.onMouseDown(pointer); - this._handleEvent(e, "down"); - }, - _onMouseMoveInDrawingMode: function(e) { - if (this._isCurrentlyDrawing) { - var pointer = this.getPointer(e); - this.freeDrawingBrush.onMouseMove(pointer); - } - this.setCursor(this.freeDrawingCursor); - this._handleEvent(e, "move"); - }, - _onMouseUpInDrawingMode: function(e) { - this._isCurrentlyDrawing = false; - if (this.clipTo) { - this.contextTop.restore(); - } - this.freeDrawingBrush.onMouseUp(); - this._handleEvent(e, "up"); - }, - __onMouseDown: function(e) { - var target = this.findTarget(e) || null; - if (checkClick(e, RIGHT_CLICK)) { - if (this.fireRightClick) { - this._handleEvent(e, "down", target, RIGHT_CLICK); - } - return; - } - if (checkClick(e, MIDDLE_CLICK)) { - if (this.fireMiddleClick) { - this._handleEvent(e, "down", target, MIDDLE_CLICK); - } - return; - } - if (this.isDrawingMode) { - this._onMouseDownInDrawingMode(e); - return; - } - if (this._currentTransform) { - return; - } - var pointer = this.getPointer(e, true); - this._previousPointer = pointer; - var shouldRender = this._shouldRender(target, pointer), shouldGroup = this._shouldGroup(e, target); - if (this._shouldClearSelection(e, target)) { - this.discardActiveObject(e); - } else if (shouldGroup) { - this._handleGrouping(e, target); - target = this._activeObject; - } - if (this.selection && (!target || !target.selectable && !target.isEditing && target !== this._activeObject)) { - this._groupSelector = { - ex: pointer.x, - ey: pointer.y, - top: 0, - left: 0 - }; - } - if (target) { - if (target.selectable) { - this.setActiveObject(target, e); - } - if (target === this._activeObject && (target.__corner || !shouldGroup)) { - this._beforeTransform(e, target); - this._setupCurrentTransform(e, target); - } - } - this._handleEvent(e, "down", target); - shouldRender && this.requestRenderAll(); - }, - _beforeTransform: function(e, target) { - this.stateful && target.saveState(); - if (target._findTargetCorner(this.getPointer(e))) { - this.onBeforeScaleRotate(target); - } - }, - _setOriginToCenter: function(target) { - this._previousOriginX = this._currentTransform.target.originX; - this._previousOriginY = this._currentTransform.target.originY; - var center = target.getCenterPoint(); - target.originX = "center"; - target.originY = "center"; - target.left = center.x; - target.top = center.y; - this._currentTransform.left = target.left; - this._currentTransform.top = target.top; - }, - _setCenterToOrigin: function(target) { - var originPoint = target.translateToOriginPoint(target.getCenterPoint(), this._previousOriginX, this._previousOriginY); - target.originX = this._previousOriginX; - target.originY = this._previousOriginY; - target.left = originPoint.x; - target.top = originPoint.y; - this._previousOriginX = null; - this._previousOriginY = null; - }, - __onMouseMove: function(e) { - var target, pointer; - if (this.isDrawingMode) { - this._onMouseMoveInDrawingMode(e); - return; - } - if (typeof e.touches !== "undefined" && e.touches.length > 1) { - return; - } - var groupSelector = this._groupSelector; - if (groupSelector) { - pointer = this.getPointer(e, true); - groupSelector.left = pointer.x - groupSelector.ex; - groupSelector.top = pointer.y - groupSelector.ey; - this.renderTop(); - } else if (!this._currentTransform) { - target = this.findTarget(e) || null; - this._setCursorFromEvent(e, target); - this._fireOverOutEvents(target, e); - } else { - this._transformObject(e); - } - this._handleEvent(e, "move", this._currentTransform ? null : target); - }, - _fireOverOutEvents: function(target, e) { - var overOpt, outOpt, hoveredTarget = this._hoveredTarget; - if (hoveredTarget !== target) { - overOpt = { - e: e, - target: target, - previousTarget: this._hoveredTarget - }; - outOpt = { - e: e, - target: this._hoveredTarget, - nextTarget: target - }; - this._hoveredTarget = target; - } - if (target) { - if (hoveredTarget !== target) { - if (hoveredTarget) { - this.fire("mouse:out", outOpt); - hoveredTarget.fire("mouseout", outOpt); - } - this.fire("mouse:over", overOpt); - target.fire("mouseover", overOpt); - } - } else if (hoveredTarget) { - this.fire("mouse:out", outOpt); - hoveredTarget.fire("mouseout", outOpt); - } - }, - __onMouseWheel: function(e) { - this._handleEvent(e, "wheel"); - }, - _transformObject: function(e) { - var pointer = this.getPointer(e), transform = this._currentTransform; - transform.reset = false; - transform.target.isMoving = true; - transform.shiftKey = e.shiftKey; - transform.altKey = e[this.centeredKey]; - this._beforeScaleTransform(e, transform); - this._performTransformAction(e, transform, pointer); - transform.actionPerformed && this.requestRenderAll(); - }, - _performTransformAction: function(e, transform, pointer) { - var x = pointer.x, y = pointer.y, target = transform.target, action = transform.action, actionPerformed = false; - if (action === "rotate") { - (actionPerformed = this._rotateObject(x, y)) && this._fire("rotating", target, e); - } else if (action === "scale") { - (actionPerformed = this._onScale(e, transform, x, y)) && this._fire("scaling", target, e); - } else if (action === "scaleX") { - (actionPerformed = this._scaleObject(x, y, "x")) && this._fire("scaling", target, e); - } else if (action === "scaleY") { - (actionPerformed = this._scaleObject(x, y, "y")) && this._fire("scaling", target, e); - } else if (action === "skewX") { - (actionPerformed = this._skewObject(x, y, "x")) && this._fire("skewing", target, e); - } else if (action === "skewY") { - (actionPerformed = this._skewObject(x, y, "y")) && this._fire("skewing", target, e); - } else { - actionPerformed = this._translateObject(x, y); - if (actionPerformed) { - this._fire("moving", target, e); - this.setCursor(target.moveCursor || this.moveCursor); - } - } - transform.actionPerformed = transform.actionPerformed || actionPerformed; - }, - _fire: function(eventName, target, e) { - this.fire("object:" + eventName, { - target: target, - e: e - }); - target.fire(eventName, { - e: e - }); - }, - _beforeScaleTransform: function(e, transform) { - if (transform.action === "scale" || transform.action === "scaleX" || transform.action === "scaleY") { - var centerTransform = this._shouldCenterTransform(transform.target); - if (centerTransform && (transform.originX !== "center" || transform.originY !== "center") || !centerTransform && transform.originX === "center" && transform.originY === "center") { - this._resetCurrentTransform(); - transform.reset = true; - } - } - }, - _onScale: function(e, transform, x, y) { - if (this._isUniscalePossible(e, transform.target)) { - transform.currentAction = "scale"; - return this._scaleObject(x, y); - } else { - if (!transform.reset && transform.currentAction === "scale") { - this._resetCurrentTransform(); - } - transform.currentAction = "scaleEqually"; - return this._scaleObject(x, y, "equally"); - } - }, - _isUniscalePossible: function(e, target) { - return (e[this.uniScaleKey] || this.uniScaleTransform) && !target.get("lockUniScaling"); - }, - _setCursorFromEvent: function(e, target) { - if (!target) { - this.setCursor(this.defaultCursor); - return false; - } - var hoverCursor = target.hoverCursor || this.hoverCursor, activeSelection = this._activeObject && this._activeObject.type === "activeSelection" ? this._activeObject : null, corner = (!activeSelection || !activeSelection.contains(target)) && target._findTargetCorner(this.getPointer(e, true)); - if (!corner) { - this.setCursor(hoverCursor); - } else { - this.setCursor(this.getCornerCursor(corner, target, e)); - } - }, - getCornerCursor: function(corner, target, e) { - if (this.actionIsDisabled(corner, target, e)) { - return this.notAllowedCursor; - } else if (corner in cursorOffset) { - return this._getRotatedCornerCursor(corner, target, e); - } else if (corner === "mtr" && target.hasRotatingPoint) { - return this.rotationCursor; - } else { - return this.defaultCursor; - } - }, - actionIsDisabled: function(corner, target, e) { - if (corner === "mt" || corner === "mb") { - return e[this.altActionKey] ? target.lockSkewingX : target.lockScalingY; - } else if (corner === "ml" || corner === "mr") { - return e[this.altActionKey] ? target.lockSkewingY : target.lockScalingX; - } else if (corner === "mtr") { - return target.lockRotation; - } else { - return this._isUniscalePossible(e, target) ? target.lockScalingX && target.lockScalingY : target.lockScalingX || target.lockScalingY; - } - }, - _getRotatedCornerCursor: function(corner, target, e) { - var n = Math.round(target.angle % 360 / 45); - if (n < 0) { - n += 8; - } - n += cursorOffset[corner]; - if (e[this.altActionKey] && cursorOffset[corner] % 2 === 0) { - n += 2; - } - n %= 8; - return this.cursorMap[n]; - } - }); -})(); - -(function() { - var min = Math.min, max = Math.max; - fabric.util.object.extend(fabric.Canvas.prototype, { - _shouldGroup: function(e, target) { - var activeObject = this._activeObject; - return activeObject && this._isSelectionKeyPressed(e) && target && target.selectable && this.selection && (activeObject !== target || activeObject.type === "activeSelection"); - }, - _handleGrouping: function(e, target) { - var activeObject = this._activeObject; - if (activeObject.__corner) { - return; - } - if (target === activeObject) { - target = this.findTarget(e, true); - if (!target) { - return; - } - } - if (activeObject && activeObject.type === "activeSelection") { - this._updateActiveSelection(target, e); - } else { - this._createActiveSelection(target, e); - } - }, - _updateActiveSelection: function(target, e) { - var activeSelection = this._activeObject, currentActiveObjects = activeSelection._objects.slice(0); - if (activeSelection.contains(target)) { - activeSelection.removeWithUpdate(target); - this._hoveredTarget = target; - if (activeSelection.size() === 1) { - this._setActiveObject(activeSelection.item(0), e); - } - } else { - activeSelection.addWithUpdate(target); - this._hoveredTarget = activeSelection; - } - this._fireSelectionEvents(currentActiveObjects, e); - }, - _createActiveSelection: function(target, e) { - var currentActives = this.getActiveObjects(), group = this._createGroup(target); - this._hoveredTarget = group; - this._setActiveObject(group, e); - this._fireSelectionEvents(currentActives, e); - }, - _createGroup: function(target) { - var objects = this.getObjects(), isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target), groupObjects = isActiveLower ? [ this._activeObject, target ] : [ target, this._activeObject ]; - this._activeObject.isEditing && this._activeObject.exitEditing(); - return new fabric.ActiveSelection(groupObjects, { - canvas: this - }); - }, - _groupSelectedObjects: function(e) { - var group = this._collectObjects(), aGroup; - if (group.length === 1) { - this.setActiveObject(group[0], e); - } else if (group.length > 1) { - aGroup = new fabric.ActiveSelection(group.reverse(), { - canvas: this - }); - this.setActiveObject(aGroup, e); - } - }, - _collectObjects: function() { - var group = [], currentObject, x1 = this._groupSelector.ex, y1 = this._groupSelector.ey, x2 = x1 + this._groupSelector.left, y2 = y1 + this._groupSelector.top, selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)), selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)), allowIntersect = !this.selectionFullyContained, isClick = x1 === x2 && y1 === y2; - for (var i = this._objects.length; i--; ) { - currentObject = this._objects[i]; - if (!currentObject || !currentObject.selectable || !currentObject.visible) { - continue; - } - if (allowIntersect && currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2) || currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) || allowIntersect && currentObject.containsPoint(selectionX1Y1) || allowIntersect && currentObject.containsPoint(selectionX2Y2)) { - group.push(currentObject); - if (isClick) { - break; - } - } - } - return group; - }, - _maybeGroupObjects: function(e) { - if (this.selection && this._groupSelector) { - this._groupSelectedObjects(e); - } - this.setCursor(this.defaultCursor); - this._groupSelector = null; - this._currentTransform = null; - } - }); -})(); - -(function() { - var supportQuality = fabric.StaticCanvas.supports("toDataURLWithQuality"); - fabric.util.object.extend(fabric.StaticCanvas.prototype, { - toDataURL: function(options) { - options || (options = {}); - var format = options.format || "png", quality = options.quality || 1, multiplier = options.multiplier || options.enableRetinaScaling ? 1 : 1 / this.getRetinaScaling(), cropping = { - left: options.left || 0, - top: options.top || 0, - width: options.width || 0, - height: options.height || 0 - }; - return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier); - }, - __toDataURLWithMultiplier: function(format, quality, cropping, multiplier) { - var origWidth = this.width, origHeight = this.height, scaledWidth = (cropping.width || this.width) * multiplier, scaledHeight = (cropping.height || this.height) * multiplier, zoom = this.getZoom(), newZoom = zoom * multiplier, vp = this.viewportTransform, translateX = (vp[4] - cropping.left) * multiplier, translateY = (vp[5] - cropping.top) * multiplier, newVp = [ newZoom, 0, 0, newZoom, translateX, translateY ], originalInteractive = this.interactive, originalSkipOffScreen = this.skipOffscreen, needsResize = origWidth !== scaledWidth || origHeight !== scaledHeight; - this.viewportTransform = newVp; - this.skipOffscreen = false; - this.interactive = false; - if (needsResize) { - this.setDimensions({ - width: scaledWidth, - height: scaledHeight - }, { - backstoreOnly: true - }); - } - this.renderAll(); - var data = this.__toDataURL(format, quality, cropping); - this.interactive = originalInteractive; - this.skipOffscreen = originalSkipOffScreen; - this.viewportTransform = vp; - if (needsResize) { - this.setDimensions({ - width: origWidth, - height: origHeight - }, { - backstoreOnly: true - }); - } - this.renderAll(); - return data; - }, - __toDataURL: function(format, quality) { - var canvasEl = this.contextContainer.canvas; - if (format === "jpg") { - format = "jpeg"; - } - var data = supportQuality ? canvasEl.toDataURL("image/" + format, quality) : canvasEl.toDataURL("image/" + format); - return data; - } - }); -})(); - -fabric.util.object.extend(fabric.StaticCanvas.prototype, { - loadFromDatalessJSON: function(json, callback, reviver) { - return this.loadFromJSON(json, callback, reviver); - }, - loadFromJSON: function(json, callback, reviver) { - if (!json) { - return; - } - var serialized = typeof json === "string" ? JSON.parse(json) : fabric.util.object.clone(json); - var _this = this, renderOnAddRemove = this.renderOnAddRemove; - this.renderOnAddRemove = false; - this._enlivenObjects(serialized.objects, function(enlivenedObjects) { - _this.clear(); - _this._setBgOverlay(serialized, function() { - enlivenedObjects.forEach(function(obj, index) { - _this.insertAt(obj, index); - }); - _this.renderOnAddRemove = renderOnAddRemove; - delete serialized.objects; - delete serialized.backgroundImage; - delete serialized.overlayImage; - delete serialized.background; - delete serialized.overlay; - _this._setOptions(serialized); - _this.renderAll(); - callback && callback(); - }); - }, reviver); - return this; - }, - _setBgOverlay: function(serialized, callback) { - var loaded = { - backgroundColor: false, - overlayColor: false, - backgroundImage: false, - overlayImage: false - }; - if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background && !serialized.overlay) { - callback && callback(); - return; - } - var cbIfLoaded = function() { - if (loaded.backgroundImage && loaded.overlayImage && loaded.backgroundColor && loaded.overlayColor) { - callback && callback(); - } - }; - this.__setBgOverlay("backgroundImage", serialized.backgroundImage, loaded, cbIfLoaded); - this.__setBgOverlay("overlayImage", serialized.overlayImage, loaded, cbIfLoaded); - this.__setBgOverlay("backgroundColor", serialized.background, loaded, cbIfLoaded); - this.__setBgOverlay("overlayColor", serialized.overlay, loaded, cbIfLoaded); - }, - __setBgOverlay: function(property, value, loaded, callback) { - var _this = this; - if (!value) { - loaded[property] = true; - callback && callback(); - return; - } - if (property === "backgroundImage" || property === "overlayImage") { - fabric.util.enlivenObjects([ value ], function(enlivedObject) { - _this[property] = enlivedObject[0]; - loaded[property] = true; - callback && callback(); - }); - } else { - this["set" + fabric.util.string.capitalize(property, true)](value, function() { - loaded[property] = true; - callback && callback(); - }); - } - }, - _enlivenObjects: function(objects, callback, reviver) { - if (!objects || objects.length === 0) { - callback && callback([]); - return; - } - fabric.util.enlivenObjects(objects, function(enlivenedObjects) { - callback && callback(enlivenedObjects); - }, null, reviver); - }, - _toDataURL: function(format, callback) { - this.clone(function(clone) { - callback(clone.toDataURL(format)); - }); - }, - _toDataURLWithMultiplier: function(format, multiplier, callback) { - this.clone(function(clone) { - callback(clone.toDataURLWithMultiplier(format, multiplier)); - }); - }, - clone: function(callback, properties) { - var data = JSON.stringify(this.toJSON(properties)); - this.cloneWithoutData(function(clone) { - clone.loadFromJSON(data, function() { - callback && callback(clone); - }); - }); - }, - cloneWithoutData: function(callback) { - var el = fabric.document.createElement("canvas"); - el.width = this.width; - el.height = this.height; - var clone = new fabric.Canvas(el); - clone.clipTo = this.clipTo; - if (this.backgroundImage) { - clone.setBackgroundImage(this.backgroundImage.src, function() { - clone.renderAll(); - callback && callback(clone); - }); - clone.backgroundImageOpacity = this.backgroundImageOpacity; - clone.backgroundImageStretch = this.backgroundImageStretch; - } else { - callback && callback(clone); - } - } -}); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, clone = fabric.util.object.clone, toFixed = fabric.util.toFixed, capitalize = fabric.util.string.capitalize, degreesToRadians = fabric.util.degreesToRadians, supportsLineDash = fabric.StaticCanvas.supports("setLineDash"), objectCaching = !fabric.isLikelyNode, ALIASING_LIMIT = 2; - if (fabric.Object) { - return; - } - fabric.Object = fabric.util.createClass(fabric.CommonMethods, { - type: "object", - originX: "left", - originY: "top", - top: 0, - left: 0, - width: 0, - height: 0, - scaleX: 1, - scaleY: 1, - flipX: false, - flipY: false, - opacity: 1, - angle: 0, - skewX: 0, - skewY: 0, - cornerSize: 13, - transparentCorners: true, - hoverCursor: null, - moveCursor: null, - padding: 0, - borderColor: "rgba(102,153,255,0.75)", - borderDashArray: null, - cornerColor: "rgba(102,153,255,0.5)", - cornerStrokeColor: null, - cornerStyle: "rect", - cornerDashArray: null, - centeredScaling: false, - centeredRotation: true, - fill: "rgb(0,0,0)", - fillRule: "nonzero", - globalCompositeOperation: "source-over", - backgroundColor: "", - selectionBackgroundColor: "", - stroke: null, - strokeWidth: 1, - strokeDashArray: null, - strokeLineCap: "butt", - strokeLineJoin: "miter", - strokeMiterLimit: 10, - shadow: null, - borderOpacityWhenMoving: .4, - borderScaleFactor: 1, - transformMatrix: null, - minScaleLimit: 0, - selectable: true, - evented: true, - visible: true, - hasControls: true, - hasBorders: true, - hasRotatingPoint: true, - rotatingPointOffset: 40, - perPixelTargetFind: false, - includeDefaultValues: true, - clipTo: null, - lockMovementX: false, - lockMovementY: false, - lockRotation: false, - lockScalingX: false, - lockScalingY: false, - lockUniScaling: false, - lockSkewingX: false, - lockSkewingY: false, - lockScalingFlip: false, - excludeFromExport: false, - objectCaching: objectCaching, - statefullCache: false, - noScaleCache: true, - dirty: true, - __corner: 0, - paintFirst: "fill", - stateProperties: ("top left width height scaleX scaleY flipX flipY originX originY transformMatrix " + "stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit " + "angle opacity fill globalCompositeOperation shadow clipTo visible backgroundColor " + "skewX skewY fillRule paintFirst").split(" "), - cacheProperties: ("fill stroke strokeWidth strokeDashArray width height paintFirst" + " strokeLineCap strokeLineJoin strokeMiterLimit backgroundColor").split(" "), - initialize: function(options) { - if (options) { - this.setOptions(options); - } - }, - _createCacheCanvas: function() { - this._cacheProperties = {}; - this._cacheCanvas = fabric.document.createElement("canvas"); - this._cacheContext = this._cacheCanvas.getContext("2d"); - this._updateCacheCanvas(); - }, - _limitCacheSize: function(dims) { - var perfLimitSizeTotal = fabric.perfLimitSizeTotal, width = dims.width, height = dims.height, max = fabric.maxCacheSideLimit, min = fabric.minCacheSideLimit; - if (width <= max && height <= max && width * height <= perfLimitSizeTotal) { - if (width < min) { - dims.width = min; - } - if (height < min) { - dims.height = min; - } - return dims; - } - var ar = width / height, limitedDims = fabric.util.limitDimsByArea(ar, perfLimitSizeTotal), capValue = fabric.util.capValue, x = capValue(min, limitedDims.x, max), y = capValue(min, limitedDims.y, max); - if (width > x) { - dims.zoomX /= width / x; - dims.width = x; - dims.capped = true; - } - if (height > y) { - dims.zoomY /= height / y; - dims.height = y; - dims.capped = true; - } - return dims; - }, - _getCacheCanvasDimensions: function() { - var zoom = this.canvas && this.canvas.getZoom() || 1, objectScale = this.getObjectScaling(), retina = this.canvas && this.canvas._isRetinaScaling() ? fabric.devicePixelRatio : 1, dim = this._getNonTransformedDimensions(), zoomX = objectScale.scaleX * zoom * retina, zoomY = objectScale.scaleY * zoom * retina, width = dim.x * zoomX, height = dim.y * zoomY; - return { - width: width + ALIASING_LIMIT, - height: height + ALIASING_LIMIT, - zoomX: zoomX, - zoomY: zoomY, - x: dim.x, - y: dim.y - }; - }, - _updateCacheCanvas: function() { - if (this.noScaleCache && this.canvas && this.canvas._currentTransform) { - var target = this.canvas._currentTransform.target, action = this.canvas._currentTransform.action; - if (this === target && action.slice && action.slice(0, 5) === "scale") { - return false; - } - } - var canvas = this._cacheCanvas, dims = this._limitCacheSize(this._getCacheCanvasDimensions()), minCacheSize = fabric.minCacheSideLimit, width = dims.width, height = dims.height, drawingWidth, drawingHeight, zoomX = dims.zoomX, zoomY = dims.zoomY, dimensionsChanged = width !== this.cacheWidth || height !== this.cacheHeight, zoomChanged = this.zoomX !== zoomX || this.zoomY !== zoomY, shouldRedraw = dimensionsChanged || zoomChanged, additionalWidth = 0, additionalHeight = 0, shouldResizeCanvas = false; - if (dimensionsChanged) { - var canvasWidth = this._cacheCanvas.width, canvasHeight = this._cacheCanvas.height, sizeGrowing = width > canvasWidth || height > canvasHeight, sizeShrinking = (width < canvasWidth * .9 || height < canvasHeight * .9) && canvasWidth > minCacheSize && canvasHeight > minCacheSize; - shouldResizeCanvas = sizeGrowing || sizeShrinking; - if (sizeGrowing && !dims.capped && (width > minCacheSize || height > minCacheSize)) { - additionalWidth = width * .1; - additionalHeight = height * .1; - } - } - if (shouldRedraw) { - if (shouldResizeCanvas) { - canvas.width = Math.ceil(width + additionalWidth); - canvas.height = Math.ceil(height + additionalHeight); - } else { - this._cacheContext.setTransform(1, 0, 0, 1, 0, 0); - this._cacheContext.clearRect(0, 0, canvas.width, canvas.height); - } - drawingWidth = dims.x * zoomX / 2; - drawingHeight = dims.y * zoomY / 2; - this.cacheTranslationX = Math.round(canvas.width / 2 - drawingWidth) + drawingWidth; - this.cacheTranslationY = Math.round(canvas.height / 2 - drawingHeight) + drawingHeight; - this.cacheWidth = width; - this.cacheHeight = height; - this._cacheContext.translate(this.cacheTranslationX, this.cacheTranslationY); - this._cacheContext.scale(zoomX, zoomY); - this.zoomX = zoomX; - this.zoomY = zoomY; - return true; - } - return false; - }, - setOptions: function(options) { - this._setOptions(options); - this._initGradient(options.fill, "fill"); - this._initGradient(options.stroke, "stroke"); - this._initClipping(options); - this._initPattern(options.fill, "fill"); - this._initPattern(options.stroke, "stroke"); - }, - transform: function(ctx) { - var m; - if (this.group && !this.group._transformDone) { - m = this.calcTransformMatrix(); - } else { - m = this.calcOwnMatrix(); - } - ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]); - }, - toObject: function(propertiesToInclude) { - var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, object = { - type: this.type, - version: fabric.version, - originX: this.originX, - originY: this.originY, - left: toFixed(this.left, NUM_FRACTION_DIGITS), - top: toFixed(this.top, NUM_FRACTION_DIGITS), - width: toFixed(this.width, NUM_FRACTION_DIGITS), - height: toFixed(this.height, NUM_FRACTION_DIGITS), - fill: this.fill && this.fill.toObject ? this.fill.toObject() : this.fill, - stroke: this.stroke && this.stroke.toObject ? this.stroke.toObject() : this.stroke, - strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS), - strokeDashArray: this.strokeDashArray ? this.strokeDashArray.concat() : this.strokeDashArray, - strokeLineCap: this.strokeLineCap, - strokeLineJoin: this.strokeLineJoin, - strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS), - scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS), - scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS), - angle: toFixed(this.angle, NUM_FRACTION_DIGITS), - flipX: this.flipX, - flipY: this.flipY, - opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS), - shadow: this.shadow && this.shadow.toObject ? this.shadow.toObject() : this.shadow, - visible: this.visible, - clipTo: this.clipTo && String(this.clipTo), - backgroundColor: this.backgroundColor, - fillRule: this.fillRule, - paintFirst: this.paintFirst, - globalCompositeOperation: this.globalCompositeOperation, - transformMatrix: this.transformMatrix ? this.transformMatrix.concat() : null, - skewX: toFixed(this.skewX, NUM_FRACTION_DIGITS), - skewY: toFixed(this.skewY, NUM_FRACTION_DIGITS) - }; - fabric.util.populateWithProperties(this, object, propertiesToInclude); - if (!this.includeDefaultValues) { - object = this._removeDefaultValues(object); - } - return object; - }, - toDatalessObject: function(propertiesToInclude) { - return this.toObject(propertiesToInclude); - }, - _removeDefaultValues: function(object) { - var prototype = fabric.util.getKlass(object.type).prototype, stateProperties = prototype.stateProperties; - stateProperties.forEach(function(prop) { - if (object[prop] === prototype[prop]) { - delete object[prop]; - } - var isArray = Object.prototype.toString.call(object[prop]) === "[object Array]" && Object.prototype.toString.call(prototype[prop]) === "[object Array]"; - if (isArray && object[prop].length === 0 && prototype[prop].length === 0) { - delete object[prop]; - } - }); - return object; - }, - toString: function() { - return "#"; - }, - getObjectScaling: function() { - var scaleX = this.scaleX, scaleY = this.scaleY; - if (this.group) { - var scaling = this.group.getObjectScaling(); - scaleX *= scaling.scaleX; - scaleY *= scaling.scaleY; - } - return { - scaleX: scaleX, - scaleY: scaleY - }; - }, - getObjectOpacity: function() { - var opacity = this.opacity; - if (this.group) { - opacity *= this.group.getObjectOpacity(); - } - return opacity; - }, - _set: function(key, value) { - var shouldConstrainValue = key === "scaleX" || key === "scaleY", isChanged = this[key] !== value, groupNeedsUpdate = false; - if (shouldConstrainValue) { - value = this._constrainScale(value); - } - if (key === "scaleX" && value < 0) { - this.flipX = !this.flipX; - value *= -1; - } else if (key === "scaleY" && value < 0) { - this.flipY = !this.flipY; - value *= -1; - } else if (key === "shadow" && value && !(value instanceof fabric.Shadow)) { - value = new fabric.Shadow(value); - } else if (key === "dirty" && this.group) { - this.group.set("dirty", value); - } - this[key] = value; - if (isChanged) { - groupNeedsUpdate = this.group && this.group.isOnACache(); - if (this.cacheProperties.indexOf(key) > -1) { - this.dirty = true; - groupNeedsUpdate && this.group.set("dirty", true); - } else if (groupNeedsUpdate && this.stateProperties.indexOf(key) > -1) { - this.group.set("dirty", true); - } - } - return this; - }, - setOnGroup: function() {}, - getViewportTransform: function() { - if (this.canvas && this.canvas.viewportTransform) { - return this.canvas.viewportTransform; - } - return fabric.iMatrix.concat(); - }, - isNotVisible: function() { - return this.opacity === 0 || this.width === 0 && this.height === 0 || !this.visible; - }, - render: function(ctx) { - if (this.isNotVisible()) { - return; - } - if (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) { - return; - } - ctx.save(); - this._setupCompositeOperation(ctx); - this.drawSelectionBackground(ctx); - this.transform(ctx); - this._setOpacity(ctx); - this._setShadow(ctx, this); - if (this.transformMatrix) { - ctx.transform.apply(ctx, this.transformMatrix); - } - this.clipTo && fabric.util.clipContext(this, ctx); - if (this.shouldCache()) { - if (!this._cacheCanvas) { - this._createCacheCanvas(); - } - if (this.isCacheDirty()) { - this.statefullCache && this.saveState({ - propertySet: "cacheProperties" - }); - this.drawObject(this._cacheContext); - this.dirty = false; - } - this.drawCacheOnCanvas(ctx); - } else { - this._removeCacheCanvas(); - this.dirty = false; - this.drawObject(ctx); - if (this.objectCaching && this.statefullCache) { - this.saveState({ - propertySet: "cacheProperties" - }); - } - } - this.clipTo && ctx.restore(); - ctx.restore(); - }, - _removeCacheCanvas: function() { - this._cacheCanvas = null; - this.cacheWidth = 0; - this.cacheHeight = 0; - }, - needsItsOwnCache: function() { - if (this.paintFirst === "stroke" && typeof this.shadow === "object") { - return true; - } - return false; - }, - shouldCache: function() { - this.ownCaching = this.objectCaching && (!this.group || this.needsItsOwnCache() || !this.group.isOnACache()); - return this.ownCaching; - }, - willDrawShadow: function() { - return !!this.shadow && (this.shadow.offsetX !== 0 || this.shadow.offsetY !== 0); - }, - drawObject: function(ctx) { - this._renderBackground(ctx); - this._setStrokeStyles(ctx, this); - this._setFillStyles(ctx, this); - this._render(ctx); - }, - drawCacheOnCanvas: function(ctx) { - ctx.scale(1 / this.zoomX, 1 / this.zoomY); - ctx.drawImage(this._cacheCanvas, -this.cacheTranslationX, -this.cacheTranslationY); - }, - isCacheDirty: function(skipCanvas) { - if (this.isNotVisible()) { - return false; - } - if (this._cacheCanvas && !skipCanvas && this._updateCacheCanvas()) { - return true; - } else { - if (this.dirty || this.statefullCache && this.hasStateChanged("cacheProperties")) { - if (this._cacheCanvas && !skipCanvas) { - var width = this.cacheWidth / this.zoomX; - var height = this.cacheHeight / this.zoomY; - this._cacheContext.clearRect(-width / 2, -height / 2, width, height); - } - return true; - } - } - return false; - }, - _renderBackground: function(ctx) { - if (!this.backgroundColor) { - return; - } - var dim = this._getNonTransformedDimensions(); - ctx.fillStyle = this.backgroundColor; - ctx.fillRect(-dim.x / 2, -dim.y / 2, dim.x, dim.y); - this._removeShadow(ctx); - }, - _setOpacity: function(ctx) { - if (this.group && !this.group._transformDone) { - ctx.globalAlpha = this.getObjectOpacity(); - } else { - ctx.globalAlpha *= this.opacity; - } - }, - _setStrokeStyles: function(ctx, decl) { - if (decl.stroke) { - ctx.lineWidth = decl.strokeWidth; - ctx.lineCap = decl.strokeLineCap; - ctx.lineJoin = decl.strokeLineJoin; - ctx.miterLimit = decl.strokeMiterLimit; - ctx.strokeStyle = decl.stroke.toLive ? decl.stroke.toLive(ctx, this) : decl.stroke; - } - }, - _setFillStyles: function(ctx, decl) { - if (decl.fill) { - ctx.fillStyle = decl.fill.toLive ? decl.fill.toLive(ctx, this) : decl.fill; - } - }, - _setLineDash: function(ctx, dashArray, alternative) { - if (!dashArray) { - return; - } - if (1 & dashArray.length) { - dashArray.push.apply(dashArray, dashArray); - } - if (supportsLineDash) { - ctx.setLineDash(dashArray); - } else { - alternative && alternative(ctx); - } - }, - _renderControls: function(ctx, styleOverride) { - var vpt = this.getViewportTransform(), matrix = this.calcTransformMatrix(), options, drawBorders, drawControls; - styleOverride = styleOverride || {}; - drawBorders = typeof styleOverride.hasBorders !== "undefined" ? styleOverride.hasBorders : this.hasBorders; - drawControls = typeof styleOverride.hasControls !== "undefined" ? styleOverride.hasControls : this.hasControls; - matrix = fabric.util.multiplyTransformMatrices(vpt, matrix); - options = fabric.util.qrDecompose(matrix); - ctx.save(); - ctx.translate(options.translateX, options.translateY); - ctx.lineWidth = 1 * this.borderScaleFactor; - if (!this.group) { - ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; - } - if (styleOverride.forActiveSelection) { - ctx.rotate(degreesToRadians(options.angle)); - drawBorders && this.drawBordersInGroup(ctx, options, styleOverride); - } else { - ctx.rotate(degreesToRadians(this.angle)); - drawBorders && this.drawBorders(ctx, styleOverride); - } - drawControls && this.drawControls(ctx, styleOverride); - ctx.restore(); - }, - _setShadow: function(ctx) { - if (!this.shadow) { - return; - } - var multX = this.canvas && this.canvas.viewportTransform[0] || 1, multY = this.canvas && this.canvas.viewportTransform[3] || 1, scaling = this.getObjectScaling(); - if (this.canvas && this.canvas._isRetinaScaling()) { - multX *= fabric.devicePixelRatio; - multY *= fabric.devicePixelRatio; - } - ctx.shadowColor = this.shadow.color; - ctx.shadowBlur = this.shadow.blur * fabric.browserShadowBlurConstant * (multX + multY) * (scaling.scaleX + scaling.scaleY) / 4; - ctx.shadowOffsetX = this.shadow.offsetX * multX * scaling.scaleX; - ctx.shadowOffsetY = this.shadow.offsetY * multY * scaling.scaleY; - }, - _removeShadow: function(ctx) { - if (!this.shadow) { - return; - } - ctx.shadowColor = ""; - ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0; - }, - _applyPatternGradientTransform: function(ctx, filler) { - if (!filler || !filler.toLive) { - return { - offsetX: 0, - offsetY: 0 - }; - } - var t = filler.gradientTransform || filler.patternTransform; - var offsetX = -this.width / 2 + filler.offsetX || 0, offsetY = -this.height / 2 + filler.offsetY || 0; - ctx.translate(offsetX, offsetY); - if (t) { - ctx.transform(t[0], t[1], t[2], t[3], t[4], t[5]); - } - return { - offsetX: offsetX, - offsetY: offsetY - }; - }, - _renderPaintInOrder: function(ctx) { - if (this.paintFirst === "stroke") { - this._renderStroke(ctx); - this._renderFill(ctx); - } else { - this._renderFill(ctx); - this._renderStroke(ctx); - } - }, - _renderFill: function(ctx) { - if (!this.fill) { - return; - } - ctx.save(); - this._applyPatternGradientTransform(ctx, this.fill); - if (this.fillRule === "evenodd") { - ctx.fill("evenodd"); - } else { - ctx.fill(); - } - ctx.restore(); - }, - _renderStroke: function(ctx) { - if (!this.stroke || this.strokeWidth === 0) { - return; - } - if (this.shadow && !this.shadow.affectStroke) { - this._removeShadow(ctx); - } - ctx.save(); - this._setLineDash(ctx, this.strokeDashArray, this._renderDashedStroke); - this._applyPatternGradientTransform(ctx, this.stroke); - ctx.stroke(); - ctx.restore(); - }, - _findCenterFromElement: function() { - return { - x: this.left + this.width / 2, - y: this.top + this.height / 2 - }; - }, - _assignTransformMatrixProps: function() { - if (this.transformMatrix) { - var options = fabric.util.qrDecompose(this.transformMatrix); - this.flipX = false; - this.flipY = false; - this.set("scaleX", options.scaleX); - this.set("scaleY", options.scaleY); - this.angle = options.angle; - this.skewX = options.skewX; - this.skewY = 0; - } - }, - _removeTransformMatrix: function(preserveAspectRatioOptions) { - var center = this._findCenterFromElement(); - if (this.transformMatrix) { - this._assignTransformMatrixProps(); - center = fabric.util.transformPoint(center, this.transformMatrix); - } - this.transformMatrix = null; - if (preserveAspectRatioOptions) { - this.scaleX *= preserveAspectRatioOptions.scaleX; - this.scaleY *= preserveAspectRatioOptions.scaleY; - this.cropX = preserveAspectRatioOptions.cropX; - this.cropY = preserveAspectRatioOptions.cropY; - center.x += preserveAspectRatioOptions.offsetLeft; - center.y += preserveAspectRatioOptions.offsetTop; - this.width = preserveAspectRatioOptions.width; - this.height = preserveAspectRatioOptions.height; - } - this.setPositionByOrigin(center, "center", "center"); - }, - clone: function(callback, propertiesToInclude) { - var objectForm = this.toObject(propertiesToInclude); - if (this.constructor.fromObject) { - this.constructor.fromObject(objectForm, callback); - } else { - fabric.Object._fromObject("Object", objectForm, callback); - } - }, - cloneAsImage: function(callback, options) { - var dataUrl = this.toDataURL(options); - fabric.util.loadImage(dataUrl, function(img) { - if (callback) { - callback(new fabric.Image(img)); - } - }); - return this; - }, - toDataURL: function(options) { - options || (options = {}); - var el = fabric.util.createCanvasElement(), boundingRect = this.getBoundingRect(); - el.width = boundingRect.width; - el.height = boundingRect.height; - fabric.util.wrapElement(el, "div"); - var canvas = new fabric.StaticCanvas(el, { - enableRetinaScaling: options.enableRetinaScaling, - renderOnAddRemove: false, - skipOffscreen: false - }); - if (options.format === "jpg") { - options.format = "jpeg"; - } - if (options.format === "jpeg") { - canvas.backgroundColor = "#fff"; - } - var origParams = { - left: this.left, - top: this.top - }; - this.setPositionByOrigin(new fabric.Point(canvas.width / 2, canvas.height / 2), "center", "center"); - var originalCanvas = this.canvas; - canvas.add(this); - var data = canvas.toDataURL(options); - this.set(origParams).setCoords(); - this.canvas = originalCanvas; - canvas._objects = []; - canvas.dispose(); - canvas = null; - return data; - }, - isType: function(type) { - return this.type === type; - }, - complexity: function() { - return 1; - }, - toJSON: function(propertiesToInclude) { - return this.toObject(propertiesToInclude); - }, - setGradient: function(property, options) { - options || (options = {}); - var gradient = { - colorStops: [] - }; - gradient.type = options.type || (options.r1 || options.r2 ? "radial" : "linear"); - gradient.coords = { - x1: options.x1, - y1: options.y1, - x2: options.x2, - y2: options.y2 - }; - if (options.r1 || options.r2) { - gradient.coords.r1 = options.r1; - gradient.coords.r2 = options.r2; - } - gradient.gradientTransform = options.gradientTransform; - fabric.Gradient.prototype.addColorStop.call(gradient, options.colorStops); - return this.set(property, fabric.Gradient.forObject(this, gradient)); - }, - setPatternFill: function(options) { - return this.set("fill", new fabric.Pattern(options)); - }, - setShadow: function(options) { - return this.set("shadow", options ? new fabric.Shadow(options) : null); - }, - setColor: function(color) { - this.set("fill", color); - return this; - }, - rotate: function(angle) { - var shouldCenterOrigin = (this.originX !== "center" || this.originY !== "center") && this.centeredRotation; - if (shouldCenterOrigin) { - this._setOriginToCenter(); - } - this.set("angle", angle); - if (shouldCenterOrigin) { - this._resetOrigin(); - } - return this; - }, - centerH: function() { - this.canvas && this.canvas.centerObjectH(this); - return this; - }, - viewportCenterH: function() { - this.canvas && this.canvas.viewportCenterObjectH(this); - return this; - }, - centerV: function() { - this.canvas && this.canvas.centerObjectV(this); - return this; - }, - viewportCenterV: function() { - this.canvas && this.canvas.viewportCenterObjectV(this); - return this; - }, - center: function() { - this.canvas && this.canvas.centerObject(this); - return this; - }, - viewportCenter: function() { - this.canvas && this.canvas.viewportCenterObject(this); - return this; - }, - getLocalPointer: function(e, pointer) { - pointer = pointer || this.canvas.getPointer(e); - var pClicked = new fabric.Point(pointer.x, pointer.y), objectLeftTop = this._getLeftTopCoords(); - if (this.angle) { - pClicked = fabric.util.rotatePoint(pClicked, objectLeftTop, degreesToRadians(-this.angle)); - } - return { - x: pClicked.x - objectLeftTop.x, - y: pClicked.y - objectLeftTop.y - }; - }, - _setupCompositeOperation: function(ctx) { - if (this.globalCompositeOperation) { - ctx.globalCompositeOperation = this.globalCompositeOperation; - } - } - }); - fabric.util.createAccessors && fabric.util.createAccessors(fabric.Object); - extend(fabric.Object.prototype, fabric.Observable); - fabric.Object.NUM_FRACTION_DIGITS = 2; - fabric.Object._fromObject = function(className, object, callback, extraParam) { - var klass = fabric[className]; - object = clone(object, true); - fabric.util.enlivenPatterns([ object.fill, object.stroke ], function(patterns) { - if (typeof patterns[0] !== "undefined") { - object.fill = patterns[0]; - } - if (typeof patterns[1] !== "undefined") { - object.stroke = patterns[1]; - } - var instance = extraParam ? new klass(object[extraParam], object) : new klass(object); - callback && callback(instance); - }); - }; - fabric.Object.__uid = 0; -})(typeof exports !== "undefined" ? exports : this); - -(function() { - var degreesToRadians = fabric.util.degreesToRadians, originXOffset = { - left: -.5, - center: 0, - right: .5 - }, originYOffset = { - top: -.5, - center: 0, - bottom: .5 - }; - fabric.util.object.extend(fabric.Object.prototype, { - translateToGivenOrigin: function(point, fromOriginX, fromOriginY, toOriginX, toOriginY) { - var x = point.x, y = point.y, offsetX, offsetY, dim; - if (typeof fromOriginX === "string") { - fromOriginX = originXOffset[fromOriginX]; - } else { - fromOriginX -= .5; - } - if (typeof toOriginX === "string") { - toOriginX = originXOffset[toOriginX]; - } else { - toOriginX -= .5; - } - offsetX = toOriginX - fromOriginX; - if (typeof fromOriginY === "string") { - fromOriginY = originYOffset[fromOriginY]; - } else { - fromOriginY -= .5; - } - if (typeof toOriginY === "string") { - toOriginY = originYOffset[toOriginY]; - } else { - toOriginY -= .5; - } - offsetY = toOriginY - fromOriginY; - if (offsetX || offsetY) { - dim = this._getTransformedDimensions(); - x = point.x + offsetX * dim.x; - y = point.y + offsetY * dim.y; - } - return new fabric.Point(x, y); - }, - translateToCenterPoint: function(point, originX, originY) { - var p = this.translateToGivenOrigin(point, originX, originY, "center", "center"); - if (this.angle) { - return fabric.util.rotatePoint(p, point, degreesToRadians(this.angle)); - } - return p; - }, - translateToOriginPoint: function(center, originX, originY) { - var p = this.translateToGivenOrigin(center, "center", "center", originX, originY); - if (this.angle) { - return fabric.util.rotatePoint(p, center, degreesToRadians(this.angle)); - } - return p; - }, - getCenterPoint: function() { - var leftTop = new fabric.Point(this.left, this.top); - return this.translateToCenterPoint(leftTop, this.originX, this.originY); - }, - getPointByOrigin: function(originX, originY) { - var center = this.getCenterPoint(); - return this.translateToOriginPoint(center, originX, originY); - }, - toLocalPoint: function(point, originX, originY) { - var center = this.getCenterPoint(), p, p2; - if (typeof originX !== "undefined" && typeof originY !== "undefined") { - p = this.translateToGivenOrigin(center, "center", "center", originX, originY); - } else { - p = new fabric.Point(this.left, this.top); - } - p2 = new fabric.Point(point.x, point.y); - if (this.angle) { - p2 = fabric.util.rotatePoint(p2, center, -degreesToRadians(this.angle)); - } - return p2.subtractEquals(p); - }, - setPositionByOrigin: function(pos, originX, originY) { - var center = this.translateToCenterPoint(pos, originX, originY), position = this.translateToOriginPoint(center, this.originX, this.originY); - this.set("left", position.x); - this.set("top", position.y); - }, - adjustPosition: function(to) { - var angle = degreesToRadians(this.angle), hypotFull = this.getScaledWidth(), xFull = Math.cos(angle) * hypotFull, yFull = Math.sin(angle) * hypotFull, offsetFrom, offsetTo; - if (typeof this.originX === "string") { - offsetFrom = originXOffset[this.originX]; - } else { - offsetFrom = this.originX - .5; - } - if (typeof to === "string") { - offsetTo = originXOffset[to]; - } else { - offsetTo = to - .5; - } - this.left += xFull * (offsetTo - offsetFrom); - this.top += yFull * (offsetTo - offsetFrom); - this.setCoords(); - this.originX = to; - }, - _setOriginToCenter: function() { - this._originalOriginX = this.originX; - this._originalOriginY = this.originY; - var center = this.getCenterPoint(); - this.originX = "center"; - this.originY = "center"; - this.left = center.x; - this.top = center.y; - }, - _resetOrigin: function() { - var originPoint = this.translateToOriginPoint(this.getCenterPoint(), this._originalOriginX, this._originalOriginY); - this.originX = this._originalOriginX; - this.originY = this._originalOriginY; - this.left = originPoint.x; - this.top = originPoint.y; - this._originalOriginX = null; - this._originalOriginY = null; - }, - _getLeftTopCoords: function() { - return this.translateToOriginPoint(this.getCenterPoint(), "left", "top"); - }, - onDeselect: function() {} - }); -})(); - -(function() { - function getCoords(coords) { - return [ new fabric.Point(coords.tl.x, coords.tl.y), new fabric.Point(coords.tr.x, coords.tr.y), new fabric.Point(coords.br.x, coords.br.y), new fabric.Point(coords.bl.x, coords.bl.y) ]; - } - var degreesToRadians = fabric.util.degreesToRadians, multiplyMatrices = fabric.util.multiplyTransformMatrices; - fabric.util.object.extend(fabric.Object.prototype, { - oCoords: null, - aCoords: null, - ownMatrixCache: null, - matrixCache: null, - getCoords: function(absolute, calculate) { - if (!this.oCoords) { - this.setCoords(); - } - var coords = absolute ? this.aCoords : this.oCoords; - return getCoords(calculate ? this.calcCoords(absolute) : coords); - }, - intersectsWithRect: function(pointTL, pointBR, absolute, calculate) { - var coords = this.getCoords(absolute, calculate), intersection = fabric.Intersection.intersectPolygonRectangle(coords, pointTL, pointBR); - return intersection.status === "Intersection"; - }, - intersectsWithObject: function(other, absolute, calculate) { - var intersection = fabric.Intersection.intersectPolygonPolygon(this.getCoords(absolute, calculate), other.getCoords(absolute, calculate)); - return intersection.status === "Intersection" || other.isContainedWithinObject(this, absolute, calculate) || this.isContainedWithinObject(other, absolute, calculate); - }, - isContainedWithinObject: function(other, absolute, calculate) { - var points = this.getCoords(absolute, calculate), i = 0, lines = other._getImageLines(calculate ? other.calcCoords(absolute) : absolute ? other.aCoords : other.oCoords); - for (;i < 4; i++) { - if (!other.containsPoint(points[i], lines)) { - return false; - } - } - return true; - }, - isContainedWithinRect: function(pointTL, pointBR, absolute, calculate) { - var boundingRect = this.getBoundingRect(absolute, calculate); - return boundingRect.left >= pointTL.x && boundingRect.left + boundingRect.width <= pointBR.x && boundingRect.top >= pointTL.y && boundingRect.top + boundingRect.height <= pointBR.y; - }, - containsPoint: function(point, lines, absolute, calculate) { - var lines = lines || this._getImageLines(calculate ? this.calcCoords(absolute) : absolute ? this.aCoords : this.oCoords), xPoints = this._findCrossPoints(point, lines); - return xPoints !== 0 && xPoints % 2 === 1; - }, - isOnScreen: function(calculate) { - if (!this.canvas) { - return false; - } - var pointTL = this.canvas.vptCoords.tl, pointBR = this.canvas.vptCoords.br; - var points = this.getCoords(true, calculate), point; - for (var i = 0; i < 4; i++) { - point = points[i]; - if (point.x <= pointBR.x && point.x >= pointTL.x && point.y <= pointBR.y && point.y >= pointTL.y) { - return true; - } - } - if (this.intersectsWithRect(pointTL, pointBR, true)) { - return true; - } - var centerPoint = { - x: (pointTL.x + pointBR.x) / 2, - y: (pointTL.y + pointBR.y) / 2 - }; - if (this.containsPoint(centerPoint, null, true)) { - return true; - } - return false; - }, - _getImageLines: function(oCoords) { - return { - topline: { - o: oCoords.tl, - d: oCoords.tr - }, - rightline: { - o: oCoords.tr, - d: oCoords.br - }, - bottomline: { - o: oCoords.br, - d: oCoords.bl - }, - leftline: { - o: oCoords.bl, - d: oCoords.tl - } - }; - }, - _findCrossPoints: function(point, lines) { - var b1, b2, a1, a2, xi, xcount = 0, iLine; - for (var lineKey in lines) { - iLine = lines[lineKey]; - if (iLine.o.y < point.y && iLine.d.y < point.y) { - continue; - } - if (iLine.o.y >= point.y && iLine.d.y >= point.y) { - continue; - } - if (iLine.o.x === iLine.d.x && iLine.o.x >= point.x) { - xi = iLine.o.x; - } else { - b1 = 0; - b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x); - a1 = point.y - b1 * point.x; - a2 = iLine.o.y - b2 * iLine.o.x; - xi = -(a1 - a2) / (b1 - b2); - } - if (xi >= point.x) { - xcount += 1; - } - if (xcount === 2) { - break; - } - } - return xcount; - }, - getBoundingRect: function(absolute, calculate) { - var coords = this.getCoords(absolute, calculate); - return fabric.util.makeBoundingBoxFromPoints(coords); - }, - getScaledWidth: function() { - return this._getTransformedDimensions().x; - }, - getScaledHeight: function() { - return this._getTransformedDimensions().y; - }, - _constrainScale: function(value) { - if (Math.abs(value) < this.minScaleLimit) { - if (value < 0) { - return -this.minScaleLimit; - } else { - return this.minScaleLimit; - } - } else if (value === 0) { - return 1e-4; - } - return value; - }, - scale: function(value) { - this._set("scaleX", value); - this._set("scaleY", value); - return this.setCoords(); - }, - scaleToWidth: function(value, absolute) { - var boundingRectFactor = this.getBoundingRect(absolute).width / this.getScaledWidth(); - return this.scale(value / this.width / boundingRectFactor); - }, - scaleToHeight: function(value, absolute) { - var boundingRectFactor = this.getBoundingRect(absolute).height / this.getScaledHeight(); - return this.scale(value / this.height / boundingRectFactor); - }, - calcCoords: function(absolute) { - var theta = degreesToRadians(this.angle), vpt = this.getViewportTransform(), dim = absolute ? this._getTransformedDimensions() : this._calculateCurrentDimensions(), currentWidth = dim.x, currentHeight = dim.y, sinTh = theta ? Math.sin(theta) : 0, cosTh = theta ? Math.cos(theta) : 1, _angle = currentWidth > 0 ? Math.atan(currentHeight / currentWidth) : 0, _hypotenuse = currentWidth / Math.cos(_angle) / 2, offsetX = Math.cos(_angle + theta) * _hypotenuse, offsetY = Math.sin(_angle + theta) * _hypotenuse, center = this.getCenterPoint(), coords = absolute ? center : fabric.util.transformPoint(center, vpt), tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY), tr = new fabric.Point(tl.x + currentWidth * cosTh, tl.y + currentWidth * sinTh), bl = new fabric.Point(tl.x - currentHeight * sinTh, tl.y + currentHeight * cosTh), br = new fabric.Point(coords.x + offsetX, coords.y + offsetY); - if (!absolute) { - var 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); - } - var coords = { - tl: tl, - tr: tr, - br: br, - bl: bl - }; - if (!absolute) { - coords.ml = ml; - coords.mt = mt; - coords.mr = mr; - coords.mb = mb; - coords.mtr = mtr; - } - return coords; - }, - setCoords: function(ignoreZoom, skipAbsolute) { - this.oCoords = this.calcCoords(ignoreZoom); - if (!skipAbsolute) { - this.aCoords = this.calcCoords(true); - } - ignoreZoom || this._setCornerCoords && this._setCornerCoords(); - return this; - }, - _calcRotateMatrix: function() { - if (this.angle) { - var theta = degreesToRadians(this.angle), cos = Math.cos(theta), sin = Math.sin(theta); - if (cos === 6.123233995736766e-17 || cos === -1.8369701987210297e-16) { - cos = 0; - } - return [ cos, sin, -sin, cos, 0, 0 ]; - } - return fabric.iMatrix.concat(); - }, - transformMatrixKey: function(skipGroup) { - var sep = "_", prefix = ""; - if (!skipGroup && this.group) { - prefix = this.group.transformMatrixKey(skipGroup) + sep; - } - return prefix + this.top + sep + this.left + sep + this.scaleX + sep + this.scaleY + sep + this.skewX + sep + this.skewY + sep + this.angle + sep + this.width + sep + this.height + sep + this.strokeWidth + this.flipX + this.flipY; - }, - calcTransformMatrix: function(skipGroup) { - if (skipGroup) { - return this.calcOwnMatrix(); - } - var key = this.transformMatrixKey(), cache = this.matrixCache || (this.matrixCache = {}); - if (cache.key === key) { - return cache.value; - } - var matrix = this.calcOwnMatrix(); - if (this.group) { - matrix = multiplyMatrices(this.group.calcTransformMatrix(), matrix); - } - cache.key = key; - cache.value = matrix; - return matrix; - }, - calcOwnMatrix: function() { - var key = this.transformMatrixKey(true), cache = this.ownMatrixCache || (this.ownMatrixCache = {}); - if (cache.key === key) { - return cache.value; - } - var center = this.getCenterPoint(), matrix = [ 1, 0, 0, 1, center.x, center.y ], rotateMatrix, dimensionMatrix = this._calcDimensionsTransformMatrix(this.skewX, this.skewY, true); - if (this.angle) { - rotateMatrix = this._calcRotateMatrix(); - matrix = multiplyMatrices(matrix, rotateMatrix); - } - matrix = multiplyMatrices(matrix, dimensionMatrix); - cache.key = key; - cache.value = matrix; - return matrix; - }, - _calcDimensionsTransformMatrix: function(skewX, skewY, flipping) { - var skewMatrix, scaleX = this.scaleX * (flipping && this.flipX ? -1 : 1), scaleY = this.scaleY * (flipping && this.flipY ? -1 : 1), scaleMatrix = [ scaleX, 0, 0, scaleY, 0, 0 ]; - if (skewX) { - skewMatrix = [ 1, 0, Math.tan(degreesToRadians(skewX)), 1 ]; - scaleMatrix = multiplyMatrices(scaleMatrix, skewMatrix, true); - } - if (skewY) { - skewMatrix = [ 1, Math.tan(degreesToRadians(skewY)), 0, 1 ]; - scaleMatrix = multiplyMatrices(scaleMatrix, skewMatrix, true); - } - return scaleMatrix; - }, - _getNonTransformedDimensions: function() { - var strokeWidth = this.strokeWidth, w = this.width + strokeWidth, h = this.height + strokeWidth; - return { - x: w, - y: h - }; - }, - _getTransformedDimensions: function(skewX, skewY) { - if (typeof skewX === "undefined") { - skewX = this.skewX; - } - if (typeof skewY === "undefined") { - skewY = this.skewY; - } - var dimensions = this._getNonTransformedDimensions(), dimX = dimensions.x / 2, dimY = dimensions.y / 2, points = [ { - x: -dimX, - y: -dimY - }, { - x: dimX, - y: -dimY - }, { - x: -dimX, - y: dimY - }, { - x: dimX, - y: dimY - } ], i, transformMatrix = this._calcDimensionsTransformMatrix(skewX, skewY, false), bbox; - for (i = 0; i < points.length; i++) { - points[i] = fabric.util.transformPoint(points[i], transformMatrix); - } - bbox = fabric.util.makeBoundingBoxFromPoints(points); - return { - x: bbox.width, - y: bbox.height - }; - }, - _calculateCurrentDimensions: function() { - var vpt = this.getViewportTransform(), dim = this._getTransformedDimensions(), p = fabric.util.transformPoint(dim, vpt, true); - return p.scalarAdd(2 * this.padding); - } - }); -})(); - -fabric.util.object.extend(fabric.Object.prototype, { - sendToBack: function() { - if (this.group) { - fabric.StaticCanvas.prototype.sendToBack.call(this.group, this); - } else { - this.canvas.sendToBack(this); - } - return this; - }, - bringToFront: function() { - if (this.group) { - fabric.StaticCanvas.prototype.bringToFront.call(this.group, this); - } else { - this.canvas.bringToFront(this); - } - return this; - }, - sendBackwards: function(intersecting) { - if (this.group) { - fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting); - } else { - this.canvas.sendBackwards(this, intersecting); - } - return this; - }, - bringForward: function(intersecting) { - if (this.group) { - fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting); - } else { - this.canvas.bringForward(this, intersecting); - } - return this; - }, - moveTo: function(index) { - if (this.group && this.group.type !== "activeSelection") { - fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index); - } else { - this.canvas.moveTo(this, index); - } - return this; - } -}); - -(function() { - function getSvgColorString(prop, value) { - if (!value) { - return prop + ": none; "; - } else if (value.toLive) { - return prop + ": url(#SVGID_" + value.id + "); "; - } else { - var color = new fabric.Color(value), str = prop + ": " + color.toRgb() + "; ", opacity = color.getAlpha(); - if (opacity !== 1) { - str += prop + "-opacity: " + opacity.toString() + "; "; - } - return str; - } - } - var toFixed = fabric.util.toFixed; - fabric.util.object.extend(fabric.Object.prototype, { - getSvgStyles: function(skipShadow) { - var fillRule = this.fillRule, strokeWidth = this.strokeWidth ? this.strokeWidth : "0", strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(" ") : "none", strokeLineCap = this.strokeLineCap ? this.strokeLineCap : "butt", strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : "miter", strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : "4", opacity = typeof this.opacity !== "undefined" ? this.opacity : "1", visibility = this.visible ? "" : " visibility: hidden;", filter = skipShadow ? "" : this.getSvgFilter(), fill = getSvgColorString("fill", this.fill), stroke = getSvgColorString("stroke", this.stroke); - return [ stroke, "stroke-width: ", strokeWidth, "; ", "stroke-dasharray: ", strokeDashArray, "; ", "stroke-linecap: ", strokeLineCap, "; ", "stroke-linejoin: ", strokeLineJoin, "; ", "stroke-miterlimit: ", strokeMiterLimit, "; ", fill, "fill-rule: ", fillRule, "; ", "opacity: ", opacity, ";", filter, visibility ].join(""); - }, - getSvgSpanStyles: function(style, useWhiteSpace) { - var term = "; ", strokeWidth = style.strokeWidth ? "stroke-width: " + style.strokeWidth + term : "", fontFamily = style.fontFamily ? "font-family: " + style.fontFamily.replace(/"/g, "'") + term : "", fontSize = style.fontSize ? "font-size: " + style.fontSize + "px" + term : "", fontStyle = style.fontStyle ? "font-style: " + style.fontStyle + term : "", fontWeight = style.fontWeight ? "font-weight: " + style.fontWeight + term : "", fill = style.fill ? getSvgColorString("fill", style.fill) : "", stroke = style.stroke ? getSvgColorString("stroke", style.stroke) : "", textDecoration = this.getSvgTextDecoration(style); - if (textDecoration) { - textDecoration = "text-decoration: " + textDecoration + term; - } - return [ stroke, strokeWidth, fontFamily, fontSize, fontStyle, fontWeight, textDecoration, fill, useWhiteSpace ? "white-space: pre; " : "" ].join(""); - }, - getSvgTextDecoration: function(style) { - if ("overline" in style || "underline" in style || "linethrough" in style) { - return (style.overline ? "overline " : "") + (style.underline ? "underline " : "") + (style.linethrough ? "line-through " : ""); - } - return ""; - }, - getSvgFilter: function() { - return this.shadow ? "filter: url(#SVGID_" + this.shadow.id + ");" : ""; - }, - getSvgId: function() { - return this.id ? 'id="' + this.id + '" ' : ""; - }, - getSvgTransform: function() { - var angle = this.angle, skewX = this.skewX % 360, skewY = this.skewY % 360, center = this.getCenterPoint(), NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, translatePart = "translate(" + toFixed(center.x, NUM_FRACTION_DIGITS) + " " + toFixed(center.y, NUM_FRACTION_DIGITS) + ")", anglePart = angle !== 0 ? " rotate(" + toFixed(angle, NUM_FRACTION_DIGITS) + ")" : "", scalePart = this.scaleX === 1 && this.scaleY === 1 ? "" : " scale(" + toFixed(this.scaleX, NUM_FRACTION_DIGITS) + " " + toFixed(this.scaleY, NUM_FRACTION_DIGITS) + ")", skewXPart = skewX !== 0 ? " skewX(" + toFixed(skewX, NUM_FRACTION_DIGITS) + ")" : "", skewYPart = skewY !== 0 ? " skewY(" + toFixed(skewY, NUM_FRACTION_DIGITS) + ")" : "", flipXPart = this.flipX ? " matrix(-1 0 0 1 0 0) " : "", flipYPart = this.flipY ? " matrix(1 0 0 -1 0 0)" : ""; - return [ translatePart, anglePart, scalePart, flipXPart, flipYPart, skewXPart, skewYPart ].join(""); - }, - getSvgTransformMatrix: function() { - return this.transformMatrix ? " matrix(" + this.transformMatrix.join(" ") + ") " : ""; - }, - _setSVGBg: function(textBgRects) { - if (this.backgroundColor) { - var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; - textBgRects.push("\t\t\n'); - } - }, - _createBaseSVGMarkup: function() { - var markup = []; - if (this.fill && this.fill.toLive) { - markup.push(this.fill.toSVG(this, false)); - } - if (this.stroke && this.stroke.toLive) { - markup.push(this.stroke.toSVG(this, false)); - } - if (this.shadow) { - markup.push(this.shadow.toSVG(this)); - } - return markup; - }, - addPaintOrder: function() { - return this.paintFirst !== "fill" ? ' paint-order="' + this.paintFirst + '" ' : ""; - } - }); -})(); - -(function() { - var extend = fabric.util.object.extend, originalSet = "stateProperties"; - function saveProps(origin, destination, props) { - var tmpObj = {}, deep = true; - props.forEach(function(prop) { - tmpObj[prop] = origin[prop]; - }); - extend(origin[destination], tmpObj, deep); - } - function _isEqual(origValue, currentValue, firstPass) { - if (origValue === currentValue) { - return true; - } else if (Array.isArray(origValue)) { - if (origValue.length !== currentValue.length) { - return false; - } - for (var i = 0, len = origValue.length; i < len; i++) { - if (!_isEqual(origValue[i], currentValue[i])) { - return false; - } - } - return true; - } else if (origValue && typeof origValue === "object") { - var keys = Object.keys(origValue), key; - if (!firstPass && keys.length !== Object.keys(currentValue).length) { - return false; - } - for (var i = 0, len = keys.length; i < len; i++) { - key = keys[i]; - if (!_isEqual(origValue[key], currentValue[key])) { - return false; - } - } - return true; - } - } - fabric.util.object.extend(fabric.Object.prototype, { - hasStateChanged: function(propertySet) { - propertySet = propertySet || originalSet; - var dashedPropertySet = "_" + propertySet; - if (Object.keys(this[dashedPropertySet]).length < this[propertySet].length) { - return true; - } - return !_isEqual(this[dashedPropertySet], this, true); - }, - saveState: function(options) { - var propertySet = options && options.propertySet || originalSet, destination = "_" + propertySet; - if (!this[destination]) { - return this.setupState(options); - } - saveProps(this, destination, this[propertySet]); - if (options && options.stateProperties) { - saveProps(this, destination, options.stateProperties); - } - return this; - }, - setupState: function(options) { - options = options || {}; - var propertySet = options.propertySet || originalSet; - options.propertySet = propertySet; - this["_" + propertySet] = {}; - this.saveState(options); - return this; - } - }); -})(); - -(function() { - var degreesToRadians = fabric.util.degreesToRadians; - fabric.util.object.extend(fabric.Object.prototype, { - _controlsVisibility: null, - _findTargetCorner: function(pointer) { - if (!this.hasControls || this.group || (!this.canvas || this.canvas._activeObject !== this)) { - return false; - } - var ex = pointer.x, ey = pointer.y, xPoints, lines; - this.__corner = 0; - for (var i in this.oCoords) { - if (!this.isControlVisible(i)) { - continue; - } - if (i === "mtr" && !this.hasRotatingPoint) { - continue; - } - if (this.get("lockUniScaling") && (i === "mt" || i === "mr" || i === "mb" || i === "ml")) { - continue; - } - lines = this._getImageLines(this.oCoords[i].corner); - xPoints = this._findCrossPoints({ - x: ex, - y: ey - }, lines); - if (xPoints !== 0 && xPoints % 2 === 1) { - this.__corner = i; - return i; - } - } - return false; - }, - _setCornerCoords: function() { - var coords = this.oCoords, newTheta = degreesToRadians(45 - this.angle), cornerHypotenuse = this.cornerSize * .707106, cosHalfOffset = cornerHypotenuse * Math.cos(newTheta), sinHalfOffset = cornerHypotenuse * Math.sin(newTheta), x, y; - for (var point in coords) { - x = coords[point].x; - y = coords[point].y; - coords[point].corner = { - tl: { - x: x - sinHalfOffset, - y: y - cosHalfOffset - }, - tr: { - x: x + cosHalfOffset, - y: y - sinHalfOffset - }, - bl: { - x: x - cosHalfOffset, - y: y + sinHalfOffset - }, - br: { - x: x + sinHalfOffset, - y: y + cosHalfOffset - } - }; - } - }, - drawSelectionBackground: function(ctx) { - if (!this.selectionBackgroundColor || this.canvas && !this.canvas.interactive || this.canvas && this.canvas._activeObject !== this) { - return this; - } - ctx.save(); - var center = this.getCenterPoint(), wh = this._calculateCurrentDimensions(), vpt = this.canvas.viewportTransform; - ctx.translate(center.x, center.y); - ctx.scale(1 / vpt[0], 1 / vpt[3]); - ctx.rotate(degreesToRadians(this.angle)); - ctx.fillStyle = this.selectionBackgroundColor; - ctx.fillRect(-wh.x / 2, -wh.y / 2, wh.x, wh.y); - ctx.restore(); - return this; - }, - drawBorders: function(ctx, styleOverride) { - styleOverride = styleOverride || {}; - var wh = this._calculateCurrentDimensions(), strokeWidth = 1 / this.borderScaleFactor, width = wh.x + strokeWidth, height = wh.y + strokeWidth, drawRotatingPoint = typeof styleOverride.hasRotatingPoint !== "undefined" ? styleOverride.hasRotatingPoint : this.hasRotatingPoint, hasControls = typeof styleOverride.hasControls !== "undefined" ? styleOverride.hasControls : this.hasControls, rotatingPointOffset = typeof styleOverride.rotatingPointOffset !== "undefined" ? styleOverride.rotatingPointOffset : this.rotatingPointOffset; - ctx.save(); - ctx.strokeStyle = styleOverride.borderColor || this.borderColor; - this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray, null); - ctx.strokeRect(-width / 2, -height / 2, width, height); - if (drawRotatingPoint && this.isControlVisible("mtr") && hasControls) { - var rotateHeight = -height / 2; - ctx.beginPath(); - ctx.moveTo(0, rotateHeight); - ctx.lineTo(0, rotateHeight - rotatingPointOffset); - ctx.stroke(); - } - ctx.restore(); - return this; - }, - drawBordersInGroup: function(ctx, options, styleOverride) { - styleOverride = styleOverride || {}; - var p = this._getNonTransformedDimensions(), matrix = fabric.util.customTransformMatrix(options.scaleX, options.scaleY, options.skewX), wh = fabric.util.transformPoint(p, matrix), strokeWidth = 1 / this.borderScaleFactor, width = wh.x + strokeWidth, height = wh.y + strokeWidth; - ctx.save(); - this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray, null); - ctx.strokeStyle = styleOverride.borderColor || this.borderColor; - ctx.strokeRect(-width / 2, -height / 2, width, height); - ctx.restore(); - return this; - }, - drawControls: function(ctx, styleOverride) { - styleOverride = styleOverride || {}; - var wh = this._calculateCurrentDimensions(), width = wh.x, height = wh.y, scaleOffset = styleOverride.cornerSize || this.cornerSize, left = -(width + scaleOffset) / 2, top = -(height + scaleOffset) / 2, transparentCorners = typeof styleOverride.transparentCorners !== "undefined" ? styleOverride.transparentCorners : this.transparentCorners, hasRotatingPoint = typeof styleOverride.hasRotatingPoint !== "undefined" ? styleOverride.hasRotatingPoint : this.hasRotatingPoint, methodName = transparentCorners ? "stroke" : "fill"; - ctx.save(); - ctx.strokeStyle = ctx.fillStyle = styleOverride.cornerColor || this.cornerColor; - if (!this.transparentCorners) { - ctx.strokeStyle = styleOverride.cornerStrokeColor || this.cornerStrokeColor; - } - this._setLineDash(ctx, styleOverride.cornerDashArray || this.cornerDashArray, null); - this._drawControl("tl", ctx, methodName, left, top, styleOverride); - this._drawControl("tr", ctx, methodName, left + width, top, styleOverride); - this._drawControl("bl", ctx, methodName, left, top + height, styleOverride); - this._drawControl("br", ctx, methodName, left + width, top + height, styleOverride); - if (!this.get("lockUniScaling")) { - this._drawControl("mt", ctx, methodName, left + width / 2, top, styleOverride); - this._drawControl("mb", ctx, methodName, left + width / 2, top + height, styleOverride); - this._drawControl("mr", ctx, methodName, left + width, top + height / 2, styleOverride); - this._drawControl("ml", ctx, methodName, left, top + height / 2, styleOverride); - } - if (hasRotatingPoint) { - this._drawControl("mtr", ctx, methodName, left + width / 2, top - this.rotatingPointOffset, styleOverride); - } - ctx.restore(); - return this; - }, - _drawControl: function(control, ctx, methodName, left, top, styleOverride) { - styleOverride = styleOverride || {}; - if (!this.isControlVisible(control)) { - return; - } - var size = this.cornerSize, stroke = !this.transparentCorners && this.cornerStrokeColor; - switch (styleOverride.cornerStyle || this.cornerStyle) { - case "circle": - ctx.beginPath(); - ctx.arc(left + size / 2, top + size / 2, size / 2, 0, 2 * Math.PI, false); - ctx[methodName](); - if (stroke) { - ctx.stroke(); - } - break; - - default: - this.transparentCorners || ctx.clearRect(left, top, size, size); - ctx[methodName + "Rect"](left, top, size, size); - if (stroke) { - ctx.strokeRect(left, top, size, size); - } - } - }, - isControlVisible: function(controlName) { - return this._getControlsVisibility()[controlName]; - }, - setControlVisible: function(controlName, visible) { - this._getControlsVisibility()[controlName] = visible; - return this; - }, - setControlsVisibility: function(options) { - options || (options = {}); - for (var p in options) { - this.setControlVisible(p, options[p]); - } - return this; - }, - _getControlsVisibility: function() { - if (!this._controlsVisibility) { - this._controlsVisibility = { - tl: true, - tr: true, - br: true, - bl: true, - ml: true, - mt: true, - mr: true, - mb: true, - mtr: true - }; - } - return this._controlsVisibility; - }, - onDeselect: function() {}, - onSelect: function() {} - }); -})(); - -fabric.util.object.extend(fabric.StaticCanvas.prototype, { - FX_DURATION: 500, - fxCenterObjectH: function(object, callbacks) { - callbacks = callbacks || {}; - var empty = function() {}, onComplete = callbacks.onComplete || empty, onChange = callbacks.onChange || empty, _this = this; - fabric.util.animate({ - startValue: object.left, - endValue: this.getCenter().left, - duration: this.FX_DURATION, - onChange: function(value) { - object.set("left", value); - _this.requestRenderAll(); - onChange(); - }, - onComplete: function() { - object.setCoords(); - onComplete(); - } - }); - return this; - }, - fxCenterObjectV: function(object, callbacks) { - callbacks = callbacks || {}; - var empty = function() {}, onComplete = callbacks.onComplete || empty, onChange = callbacks.onChange || empty, _this = this; - fabric.util.animate({ - startValue: object.top, - endValue: this.getCenter().top, - duration: this.FX_DURATION, - onChange: function(value) { - object.set("top", value); - _this.requestRenderAll(); - onChange(); - }, - onComplete: function() { - object.setCoords(); - onComplete(); - } - }); - return this; - }, - fxRemove: function(object, callbacks) { - callbacks = callbacks || {}; - var empty = function() {}, onComplete = callbacks.onComplete || empty, onChange = callbacks.onChange || empty, _this = this; - fabric.util.animate({ - startValue: object.opacity, - endValue: 0, - duration: this.FX_DURATION, - onChange: function(value) { - object.set("opacity", value); - _this.requestRenderAll(); - onChange(); - }, - onComplete: function() { - _this.remove(object); - onComplete(); - } - }); - return this; - } -}); - -fabric.util.object.extend(fabric.Object.prototype, { - animate: function() { - if (arguments[0] && typeof arguments[0] === "object") { - var propsToAnimate = [], prop, skipCallbacks; - for (prop in arguments[0]) { - propsToAnimate.push(prop); - } - for (var i = 0, len = propsToAnimate.length; i < len; i++) { - prop = propsToAnimate[i]; - skipCallbacks = i !== len - 1; - this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks); - } - } else { - this._animate.apply(this, arguments); - } - return this; - }, - _animate: function(property, to, options, skipCallbacks) { - var _this = this, propPair; - to = to.toString(); - if (!options) { - options = {}; - } else { - options = fabric.util.object.clone(options); - } - if (~property.indexOf(".")) { - propPair = property.split("."); - } - var currentValue = propPair ? this.get(propPair[0])[propPair[1]] : this.get(property); - if (!("from" in options)) { - options.from = currentValue; - } - if (~to.indexOf("=")) { - to = currentValue + parseFloat(to.replace("=", "")); - } else { - to = parseFloat(to); - } - fabric.util.animate({ - startValue: options.from, - endValue: to, - byValue: options.by, - easing: options.easing, - duration: options.duration, - abort: options.abort && function() { - return options.abort.call(_this); - }, - onChange: function(value, valueProgress, timeProgress) { - if (propPair) { - _this[propPair[0]][propPair[1]] = value; - } else { - _this.set(property, value); - } - if (skipCallbacks) { - return; - } - options.onChange && options.onChange(value, valueProgress, timeProgress); - }, - onComplete: function(value, valueProgress, timeProgress) { - if (skipCallbacks) { - return; - } - _this.setCoords(); - options.onComplete && options.onComplete(value, valueProgress, timeProgress); - } - }); - } -}); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, clone = fabric.util.object.clone, coordProps = { - x1: 1, - x2: 1, - y1: 1, - y2: 1 - }, supportsLineDash = fabric.StaticCanvas.supports("setLineDash"); - if (fabric.Line) { - fabric.warn("fabric.Line is already defined"); - return; - } - fabric.Line = fabric.util.createClass(fabric.Object, { - type: "line", - x1: 0, - y1: 0, - x2: 0, - y2: 0, - cacheProperties: fabric.Object.prototype.cacheProperties.concat("x1", "x2", "y1", "y2"), - initialize: function(points, options) { - if (!points) { - points = [ 0, 0, 0, 0 ]; - } - this.callSuper("initialize", options); - this.set("x1", points[0]); - this.set("y1", points[1]); - this.set("x2", points[2]); - this.set("y2", points[3]); - this._setWidthHeight(options); - }, - _setWidthHeight: function(options) { - options || (options = {}); - this.width = Math.abs(this.x2 - this.x1); - this.height = Math.abs(this.y2 - this.y1); - this.left = "left" in options ? options.left : this._getLeftToOriginX(); - this.top = "top" in options ? options.top : this._getTopToOriginY(); - }, - _set: function(key, value) { - this.callSuper("_set", key, value); - if (typeof coordProps[key] !== "undefined") { - this._setWidthHeight(); - } - return this; - }, - _getLeftToOriginX: makeEdgeToOriginGetter({ - origin: "originX", - axis1: "x1", - axis2: "x2", - dimension: "width" - }, { - nearest: "left", - center: "center", - farthest: "right" - }), - _getTopToOriginY: makeEdgeToOriginGetter({ - origin: "originY", - axis1: "y1", - axis2: "y2", - dimension: "height" - }, { - nearest: "top", - center: "center", - farthest: "bottom" - }), - _render: function(ctx) { - ctx.beginPath(); - if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) { - var p = this.calcLinePoints(); - ctx.moveTo(p.x1, p.y1); - ctx.lineTo(p.x2, p.y2); - } - ctx.lineWidth = this.strokeWidth; - var origStrokeStyle = ctx.strokeStyle; - ctx.strokeStyle = this.stroke || ctx.fillStyle; - this.stroke && this._renderStroke(ctx); - ctx.strokeStyle = origStrokeStyle; - }, - _renderDashedStroke: function(ctx) { - var p = this.calcLinePoints(); - ctx.beginPath(); - fabric.util.drawDashedLine(ctx, p.x1, p.y1, p.x2, p.y2, this.strokeDashArray); - ctx.closePath(); - }, - _findCenterFromElement: function() { - return { - x: (this.x1 + this.x2) / 2, - y: (this.y1 + this.y2) / 2 - }; - }, - toObject: function(propertiesToInclude) { - return extend(this.callSuper("toObject", propertiesToInclude), this.calcLinePoints()); - }, - _getNonTransformedDimensions: function() { - var dim = this.callSuper("_getNonTransformedDimensions"); - if (this.strokeLineCap === "butt") { - if (this.width === 0) { - dim.y -= this.strokeWidth; - } - if (this.height === 0) { - dim.x -= this.strokeWidth; - } - } - return dim; - }, - calcLinePoints: function() { - var xMult = this.x1 <= this.x2 ? -1 : 1, yMult = this.y1 <= this.y2 ? -1 : 1, x1 = xMult * this.width * .5, y1 = yMult * this.height * .5, x2 = xMult * this.width * -.5, y2 = yMult * this.height * -.5; - return { - x1: x1, - x2: x2, - y1: y1, - y2: y2 - }; - }, - toSVG: function(reviver) { - var markup = this._createBaseSVGMarkup(), p = this.calcLinePoints(); - markup.push("\n'); - return reviver ? reviver(markup.join("")) : markup.join(""); - } - }); - fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat("x1 y1 x2 y2".split(" ")); - fabric.Line.fromElement = function(element, callback, options) { - options = options || {}; - var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES), points = [ parsedAttributes.x1 || 0, parsedAttributes.y1 || 0, parsedAttributes.x2 || 0, parsedAttributes.y2 || 0 ]; - callback(new fabric.Line(points, extend(parsedAttributes, options))); - }; - fabric.Line.fromObject = function(object, callback) { - function _callback(instance) { - delete instance.points; - callback && callback(instance); - } - var options = clone(object, true); - options.points = [ object.x1, object.y1, object.x2, object.y2 ]; - fabric.Object._fromObject("Line", options, _callback, "points"); - }; - function makeEdgeToOriginGetter(propertyNames, originValues) { - var origin = propertyNames.origin, axis1 = propertyNames.axis1, axis2 = propertyNames.axis2, dimension = propertyNames.dimension, nearest = originValues.nearest, center = originValues.center, farthest = originValues.farthest; - return function() { - switch (this.get(origin)) { - case nearest: - return Math.min(this.get(axis1), this.get(axis2)); - - case center: - return Math.min(this.get(axis1), this.get(axis2)) + .5 * this.get(dimension); - - case farthest: - return Math.max(this.get(axis1), this.get(axis2)); - } - }; - } -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), pi = Math.PI; - if (fabric.Circle) { - fabric.warn("fabric.Circle is already defined."); - return; - } - fabric.Circle = fabric.util.createClass(fabric.Object, { - type: "circle", - radius: 0, - startAngle: 0, - endAngle: pi * 2, - cacheProperties: fabric.Object.prototype.cacheProperties.concat("radius"), - _set: function(key, value) { - this.callSuper("_set", key, value); - if (key === "radius") { - this.setRadius(value); - } - return this; - }, - toObject: function(propertiesToInclude) { - return this.callSuper("toObject", [ "radius", "startAngle", "endAngle" ].concat(propertiesToInclude)); - }, - toSVG: function(reviver) { - var markup = this._createBaseSVGMarkup(), x = 0, y = 0, angle = (this.endAngle - this.startAngle) % (2 * pi); - if (angle === 0) { - markup.push("\n"); - } else { - var startX = Math.cos(this.startAngle) * this.radius, startY = Math.sin(this.startAngle) * this.radius, endX = Math.cos(this.endAngle) * this.radius, endY = Math.sin(this.endAngle) * this.radius, largeFlag = angle > pi ? "1" : "0"; - markup.push('\n'); - } - return reviver ? reviver(markup.join("")) : markup.join(""); - }, - _render: function(ctx) { - ctx.beginPath(); - ctx.arc(0, 0, this.radius, this.startAngle, this.endAngle, false); - this._renderPaintInOrder(ctx); - }, - getRadiusX: function() { - return this.get("radius") * this.get("scaleX"); - }, - getRadiusY: function() { - return this.get("radius") * this.get("scaleY"); - }, - setRadius: function(value) { - this.radius = value; - return this.set("width", value * 2).set("height", value * 2); - } - }); - fabric.Circle.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat("cx cy r".split(" ")); - fabric.Circle.fromElement = function(element, callback) { - var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES); - if (!isValidRadius(parsedAttributes)) { - throw new Error("value of `r` attribute is required and can not be negative"); - } - parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.radius; - parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.radius; - callback(new fabric.Circle(parsedAttributes)); - }; - function isValidRadius(attributes) { - return "radius" in attributes && attributes.radius >= 0; - } - fabric.Circle.fromObject = function(object, callback) { - return fabric.Object._fromObject("Circle", object, callback); - }; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}); - if (fabric.Triangle) { - fabric.warn("fabric.Triangle is already defined"); - return; - } - fabric.Triangle = fabric.util.createClass(fabric.Object, { - type: "triangle", - width: 100, - height: 100, - _render: function(ctx) { - var widthBy2 = this.width / 2, heightBy2 = this.height / 2; - ctx.beginPath(); - ctx.moveTo(-widthBy2, heightBy2); - ctx.lineTo(0, -heightBy2); - ctx.lineTo(widthBy2, heightBy2); - ctx.closePath(); - this._renderPaintInOrder(ctx); - }, - _renderDashedStroke: function(ctx) { - var widthBy2 = this.width / 2, heightBy2 = this.height / 2; - ctx.beginPath(); - fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray); - fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray); - fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray); - ctx.closePath(); - }, - toSVG: function(reviver) { - var markup = this._createBaseSVGMarkup(), widthBy2 = this.width / 2, heightBy2 = this.height / 2, points = [ -widthBy2 + " " + heightBy2, "0 " + -heightBy2, widthBy2 + " " + heightBy2 ].join(","); - markup.push(""); - return reviver ? reviver(markup.join("")) : markup.join(""); - } - }); - fabric.Triangle.fromObject = function(object, callback) { - return fabric.Object._fromObject("Triangle", object, callback); - }; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), piBy2 = Math.PI * 2; - if (fabric.Ellipse) { - fabric.warn("fabric.Ellipse is already defined."); - return; - } - fabric.Ellipse = fabric.util.createClass(fabric.Object, { - type: "ellipse", - rx: 0, - ry: 0, - cacheProperties: fabric.Object.prototype.cacheProperties.concat("rx", "ry"), - initialize: function(options) { - this.callSuper("initialize", options); - this.set("rx", options && options.rx || 0); - this.set("ry", options && options.ry || 0); - }, - _set: function(key, value) { - this.callSuper("_set", key, value); - switch (key) { - case "rx": - this.rx = value; - this.set("width", value * 2); - break; - - case "ry": - this.ry = value; - this.set("height", value * 2); - break; - } - return this; - }, - getRx: function() { - return this.get("rx") * this.get("scaleX"); - }, - getRy: function() { - return this.get("ry") * this.get("scaleY"); - }, - toObject: function(propertiesToInclude) { - return this.callSuper("toObject", [ "rx", "ry" ].concat(propertiesToInclude)); - }, - toSVG: function(reviver) { - var markup = this._createBaseSVGMarkup(); - markup.push("\n"); - return reviver ? reviver(markup.join("")) : markup.join(""); - }, - _render: function(ctx) { - ctx.beginPath(); - ctx.save(); - ctx.transform(1, 0, 0, this.ry / this.rx, 0, 0); - ctx.arc(0, 0, this.rx, 0, piBy2, false); - ctx.restore(); - this._renderPaintInOrder(ctx); - } - }); - fabric.Ellipse.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat("cx cy rx ry".split(" ")); - fabric.Ellipse.fromElement = function(element, callback) { - var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES); - parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.rx; - parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.ry; - callback(new fabric.Ellipse(parsedAttributes)); - }; - fabric.Ellipse.fromObject = function(object, callback) { - return fabric.Object._fromObject("Ellipse", object, callback); - }; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend; - if (fabric.Rect) { - fabric.warn("fabric.Rect is already defined"); - return; - } - fabric.Rect = fabric.util.createClass(fabric.Object, { - stateProperties: fabric.Object.prototype.stateProperties.concat("rx", "ry"), - type: "rect", - rx: 0, - ry: 0, - cacheProperties: fabric.Object.prototype.cacheProperties.concat("rx", "ry"), - initialize: function(options) { - this.callSuper("initialize", options); - this._initRxRy(); - }, - _initRxRy: function() { - if (this.rx && !this.ry) { - this.ry = this.rx; - } else if (this.ry && !this.rx) { - this.rx = this.ry; - } - }, - _render: function(ctx) { - if (this.width === 1 && this.height === 1) { - ctx.fillRect(-.5, -.5, 1, 1); - return; - } - var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0, ry = this.ry ? Math.min(this.ry, this.height / 2) : 0, w = this.width, h = this.height, x = -this.width / 2, y = -this.height / 2, isRounded = rx !== 0 || ry !== 0, k = 1 - .5522847498; - ctx.beginPath(); - ctx.moveTo(x + rx, y); - ctx.lineTo(x + w - rx, y); - isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry); - ctx.lineTo(x + w, y + h - ry); - isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h); - ctx.lineTo(x + rx, y + h); - isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry); - ctx.lineTo(x, y + ry); - isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y); - ctx.closePath(); - this._renderPaintInOrder(ctx); - }, - _renderDashedStroke: function(ctx) { - var x = -this.width / 2, y = -this.height / 2, w = this.width, h = this.height; - ctx.beginPath(); - fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray); - fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray); - fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray); - fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray); - ctx.closePath(); - }, - toObject: function(propertiesToInclude) { - return this.callSuper("toObject", [ "rx", "ry" ].concat(propertiesToInclude)); - }, - toSVG: function(reviver) { - var markup = this._createBaseSVGMarkup(), x = -this.width / 2, y = -this.height / 2; - markup.push("\n"); - return reviver ? reviver(markup.join("")) : markup.join(""); - } - }); - fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat("x y rx ry width height".split(" ")); - fabric.Rect.fromElement = function(element, callback, options) { - if (!element) { - return callback(null); - } - options = options || {}; - var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES); - parsedAttributes.left = parsedAttributes.left || 0; - parsedAttributes.top = parsedAttributes.top || 0; - var rect = new fabric.Rect(extend(options ? fabric.util.object.clone(options) : {}, parsedAttributes)); - rect.visible = rect.visible && rect.width > 0 && rect.height > 0; - callback(rect); - }; - fabric.Rect.fromObject = function(object, callback) { - return fabric.Object._fromObject("Rect", object, callback); - }; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, min = fabric.util.array.min, max = fabric.util.array.max, toFixed = fabric.util.toFixed; - if (fabric.Polyline) { - fabric.warn("fabric.Polyline is already defined"); - return; - } - fabric.Polyline = fabric.util.createClass(fabric.Object, { - type: "polyline", - points: null, - cacheProperties: fabric.Object.prototype.cacheProperties.concat("points"), - initialize: function(points, options) { - options = options || {}; - this.points = points || []; - this.callSuper("initialize", options); - var calcDim = this._calcDimensions(); - if (typeof options.left === "undefined") { - this.left = calcDim.left; - } - if (typeof options.top === "undefined") { - this.top = calcDim.top; - } - this.width = calcDim.width; - this.height = calcDim.height; - this.pathOffset = { - x: calcDim.left + this.width / 2, - y: calcDim.top + this.height / 2 - }; - }, - _calcDimensions: function() { - var points = this.points, minX = min(points, "x") || 0, minY = min(points, "y") || 0, maxX = max(points, "x") || 0, maxY = max(points, "y") || 0, width = maxX - minX, height = maxY - minY; - return { - left: minX, - top: minY, - width: width, - height: height - }; - }, - toObject: function(propertiesToInclude) { - return extend(this.callSuper("toObject", propertiesToInclude), { - points: this.points.concat() - }); - }, - toSVG: function(reviver) { - var points = [], diffX = this.pathOffset.x, diffY = this.pathOffset.y, markup = this._createBaseSVGMarkup(), NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; - for (var i = 0, len = this.points.length; i < len; i++) { - points.push(toFixed(this.points[i].x - diffX, NUM_FRACTION_DIGITS), ",", toFixed(this.points[i].y - diffY, NUM_FRACTION_DIGITS), " "); - } - markup.push("<", this.type, " ", this.getSvgId(), 'points="', points.join(""), '" style="', this.getSvgStyles(), '" transform="', this.getSvgTransform(), " ", this.getSvgTransformMatrix(), '"', this.addPaintOrder(), "/>\n"); - return reviver ? reviver(markup.join("")) : markup.join(""); - }, - commonRender: function(ctx) { - var point, len = this.points.length, x = this.pathOffset.x, y = this.pathOffset.y; - if (!len || isNaN(this.points[len - 1].y)) { - return false; - } - ctx.beginPath(); - ctx.moveTo(this.points[0].x - x, this.points[0].y - y); - for (var i = 0; i < len; i++) { - point = this.points[i]; - ctx.lineTo(point.x - x, point.y - y); - } - return true; - }, - _render: function(ctx) { - if (!this.commonRender(ctx)) { - return; - } - this._renderPaintInOrder(ctx); - }, - _renderDashedStroke: function(ctx) { - var p1, p2; - ctx.beginPath(); - for (var i = 0, len = this.points.length; i < len; i++) { - p1 = this.points[i]; - p2 = this.points[i + 1] || p1; - fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray); - } - }, - complexity: function() { - return this.get("points").length; - } - }); - fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); - fabric.Polyline.fromElement = function(element, callback, options) { - if (!element) { - return callback(null); - } - options || (options = {}); - var points = fabric.parsePointsAttribute(element.getAttribute("points")), parsedAttributes = fabric.parseAttributes(element, fabric.Polyline.ATTRIBUTE_NAMES); - callback(new fabric.Polyline(points, fabric.util.object.extend(parsedAttributes, options))); - }; - fabric.Polyline.fromObject = function(object, callback) { - return fabric.Object._fromObject("Polyline", object, callback, "points"); - }; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend; - if (fabric.Polygon) { - fabric.warn("fabric.Polygon is already defined"); - return; - } - fabric.Polygon = fabric.util.createClass(fabric.Polyline, { - type: "polygon", - _render: function(ctx) { - if (!this.commonRender(ctx)) { - return; - } - ctx.closePath(); - this._renderPaintInOrder(ctx); - }, - _renderDashedStroke: function(ctx) { - this.callSuper("_renderDashedStroke", ctx); - ctx.closePath(); - } - }); - fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); - fabric.Polygon.fromElement = function(element, callback, options) { - if (!element) { - return callback(null); - } - options || (options = {}); - var points = fabric.parsePointsAttribute(element.getAttribute("points")), parsedAttributes = fabric.parseAttributes(element, fabric.Polygon.ATTRIBUTE_NAMES); - callback(new fabric.Polygon(points, extend(parsedAttributes, options))); - }; - fabric.Polygon.fromObject = function(object, callback) { - return fabric.Object._fromObject("Polygon", object, callback, "points"); - }; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), min = fabric.util.array.min, max = fabric.util.array.max, extend = fabric.util.object.extend, _toString = Object.prototype.toString, drawArc = fabric.util.drawArc, commandLengths = { - m: 2, - l: 2, - h: 1, - v: 1, - c: 6, - s: 4, - q: 4, - t: 2, - a: 7 - }, repeatedCommands = { - m: "l", - M: "L" - }; - if (fabric.Path) { - fabric.warn("fabric.Path is already defined"); - return; - } - fabric.Path = fabric.util.createClass(fabric.Object, { - type: "path", - path: null, - cacheProperties: fabric.Object.prototype.cacheProperties.concat("path", "fillRule"), - stateProperties: fabric.Object.prototype.stateProperties.concat("path"), - initialize: function(path, options) { - options = options || {}; - this.callSuper("initialize", options); - if (!path) { - path = []; - } - var fromArray = _toString.call(path) === "[object Array]"; - this.path = fromArray ? path : path.match && path.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi); - if (!this.path) { - return; - } - if (!fromArray) { - this.path = this._parsePath(); - } - this._setPositionDimensions(options); - }, - _setPositionDimensions: function(options) { - var calcDim = this._parseDimensions(); - this.width = calcDim.width; - this.height = calcDim.height; - if (typeof options.left === "undefined") { - this.left = calcDim.left; - } - if (typeof options.top === "undefined") { - this.top = calcDim.top; - } - this.pathOffset = this.pathOffset || { - x: calcDim.left + this.width / 2, - y: calcDim.top + this.height / 2 - }; - }, - _renderPathCommands: function(ctx) { - var current, previous = null, subpathStartX = 0, subpathStartY = 0, x = 0, y = 0, controlX = 0, controlY = 0, tempX, tempY, l = -this.pathOffset.x, t = -this.pathOffset.y; - ctx.beginPath(); - for (var i = 0, len = this.path.length; i < len; ++i) { - current = this.path[i]; - switch (current[0]) { - case "l": - x += current[1]; - y += current[2]; - ctx.lineTo(x + l, y + t); - break; - - case "L": - x = current[1]; - y = current[2]; - ctx.lineTo(x + l, y + t); - break; - - case "h": - x += current[1]; - ctx.lineTo(x + l, y + t); - break; - - case "H": - x = current[1]; - ctx.lineTo(x + l, y + t); - break; - - case "v": - y += current[1]; - ctx.lineTo(x + l, y + t); - break; - - case "V": - y = current[1]; - ctx.lineTo(x + l, y + t); - break; - - case "m": - x += current[1]; - y += current[2]; - subpathStartX = x; - subpathStartY = y; - ctx.moveTo(x + l, y + t); - break; - - case "M": - x = current[1]; - y = current[2]; - subpathStartX = x; - subpathStartY = y; - ctx.moveTo(x + l, y + t); - break; - - case "c": - tempX = x + current[5]; - tempY = y + current[6]; - controlX = x + current[3]; - controlY = y + current[4]; - ctx.bezierCurveTo(x + current[1] + l, y + current[2] + t, controlX + l, controlY + t, tempX + l, tempY + t); - x = tempX; - y = tempY; - break; - - case "C": - x = current[5]; - y = current[6]; - controlX = current[3]; - controlY = current[4]; - ctx.bezierCurveTo(current[1] + l, current[2] + t, controlX + l, controlY + t, x + l, y + t); - break; - - case "s": - tempX = x + current[3]; - tempY = y + current[4]; - if (previous[0].match(/[CcSs]/) === null) { - controlX = x; - controlY = y; - } else { - controlX = 2 * x - controlX; - controlY = 2 * y - controlY; - } - ctx.bezierCurveTo(controlX + l, controlY + t, x + current[1] + l, y + current[2] + t, tempX + l, tempY + t); - controlX = x + current[1]; - controlY = y + current[2]; - x = tempX; - y = tempY; - break; - - case "S": - tempX = current[3]; - tempY = current[4]; - if (previous[0].match(/[CcSs]/) === null) { - controlX = x; - controlY = y; - } else { - controlX = 2 * x - controlX; - controlY = 2 * y - controlY; - } - ctx.bezierCurveTo(controlX + l, controlY + t, current[1] + l, current[2] + t, tempX + l, tempY + t); - x = tempX; - y = tempY; - controlX = current[1]; - controlY = current[2]; - break; - - case "q": - tempX = x + current[3]; - tempY = y + current[4]; - controlX = x + current[1]; - controlY = y + current[2]; - ctx.quadraticCurveTo(controlX + l, controlY + t, tempX + l, tempY + t); - x = tempX; - y = tempY; - break; - - case "Q": - tempX = current[3]; - tempY = current[4]; - ctx.quadraticCurveTo(current[1] + l, current[2] + t, tempX + l, tempY + t); - x = tempX; - y = tempY; - controlX = current[1]; - controlY = current[2]; - break; - - case "t": - tempX = x + current[1]; - tempY = y + current[2]; - if (previous[0].match(/[QqTt]/) === null) { - controlX = x; - controlY = y; - } else { - controlX = 2 * x - controlX; - controlY = 2 * y - controlY; - } - ctx.quadraticCurveTo(controlX + l, controlY + t, tempX + l, tempY + t); - x = tempX; - y = tempY; - break; - - case "T": - tempX = current[1]; - tempY = current[2]; - if (previous[0].match(/[QqTt]/) === null) { - controlX = x; - controlY = y; - } else { - controlX = 2 * x - controlX; - controlY = 2 * y - controlY; - } - ctx.quadraticCurveTo(controlX + l, controlY + t, tempX + l, tempY + t); - x = tempX; - y = tempY; - break; - - case "a": - drawArc(ctx, x + l, y + t, [ current[1], current[2], current[3], current[4], current[5], current[6] + x + l, current[7] + y + t ]); - x += current[6]; - y += current[7]; - break; - - case "A": - drawArc(ctx, x + l, y + t, [ current[1], current[2], current[3], current[4], current[5], current[6] + l, current[7] + t ]); - x = current[6]; - y = current[7]; - break; - - case "z": - case "Z": - x = subpathStartX; - y = subpathStartY; - ctx.closePath(); - break; - } - previous = current; - } - }, - _render: function(ctx) { - this._renderPathCommands(ctx); - this._renderPaintInOrder(ctx); - }, - toString: function() { - return "#"; - }, - toObject: function(propertiesToInclude) { - var o = extend(this.callSuper("toObject", propertiesToInclude), { - path: this.path.map(function(item) { - return item.slice(); - }), - top: this.top, - left: this.left - }); - return o; - }, - toDatalessObject: function(propertiesToInclude) { - var o = this.toObject([ "sourcePath" ].concat(propertiesToInclude)); - if (o.sourcePath) { - delete o.path; - } - return o; - }, - toSVG: function(reviver) { - var chunks = [], markup = this._createBaseSVGMarkup(), addTransform = ""; - for (var i = 0, len = this.path.length; i < len; i++) { - chunks.push(this.path[i].join(" ")); - } - var path = chunks.join(" "); - addTransform = " translate(" + -this.pathOffset.x + ", " + -this.pathOffset.y + ") "; - markup.push("\n"); - return reviver ? reviver(markup.join("")) : markup.join(""); - }, - complexity: function() { - return this.path.length; - }, - _parsePath: function() { - var result = [], coords = [], currentPath, parsed, re = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/gi, match, coordsStr; - for (var i = 0, coordsParsed, len = this.path.length; i < len; i++) { - currentPath = this.path[i]; - coordsStr = currentPath.slice(1).trim(); - coords.length = 0; - while (match = re.exec(coordsStr)) { - coords.push(match[0]); - } - coordsParsed = [ currentPath.charAt(0) ]; - for (var j = 0, jlen = coords.length; j < jlen; j++) { - parsed = parseFloat(coords[j]); - if (!isNaN(parsed)) { - coordsParsed.push(parsed); - } - } - var command = coordsParsed[0], commandLength = commandLengths[command.toLowerCase()], repeatedCommand = repeatedCommands[command] || command; - if (coordsParsed.length - 1 > commandLength) { - for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) { - result.push([ command ].concat(coordsParsed.slice(k, k + commandLength))); - command = repeatedCommand; - } - } else { - result.push(coordsParsed); - } - } - return result; - }, - _parseDimensions: function() { - var aX = [], aY = [], current, previous = null, subpathStartX = 0, subpathStartY = 0, x = 0, y = 0, controlX = 0, controlY = 0, tempX, tempY, bounds; - for (var i = 0, len = this.path.length; i < len; ++i) { - current = this.path[i]; - switch (current[0]) { - case "l": - x += current[1]; - y += current[2]; - bounds = []; - break; - - case "L": - x = current[1]; - y = current[2]; - bounds = []; - break; - - case "h": - x += current[1]; - bounds = []; - break; - - case "H": - x = current[1]; - bounds = []; - break; - - case "v": - y += current[1]; - bounds = []; - break; - - case "V": - y = current[1]; - bounds = []; - break; - - case "m": - x += current[1]; - y += current[2]; - subpathStartX = x; - subpathStartY = y; - bounds = []; - break; - - case "M": - x = current[1]; - y = current[2]; - subpathStartX = x; - subpathStartY = y; - bounds = []; - break; - - case "c": - tempX = x + current[5]; - tempY = y + current[6]; - controlX = x + current[3]; - controlY = y + current[4]; - bounds = fabric.util.getBoundsOfCurve(x, y, x + current[1], y + current[2], controlX, controlY, tempX, tempY); - x = tempX; - y = tempY; - break; - - case "C": - controlX = current[3]; - controlY = current[4]; - bounds = fabric.util.getBoundsOfCurve(x, y, current[1], current[2], controlX, controlY, current[5], current[6]); - x = current[5]; - y = current[6]; - break; - - case "s": - tempX = x + current[3]; - tempY = y + current[4]; - if (previous[0].match(/[CcSs]/) === null) { - controlX = x; - controlY = y; - } else { - controlX = 2 * x - controlX; - controlY = 2 * y - controlY; - } - bounds = fabric.util.getBoundsOfCurve(x, y, controlX, controlY, x + current[1], y + current[2], tempX, tempY); - controlX = x + current[1]; - controlY = y + current[2]; - x = tempX; - y = tempY; - break; - - case "S": - tempX = current[3]; - tempY = current[4]; - if (previous[0].match(/[CcSs]/) === null) { - controlX = x; - controlY = y; - } else { - controlX = 2 * x - controlX; - controlY = 2 * y - controlY; - } - bounds = fabric.util.getBoundsOfCurve(x, y, controlX, controlY, current[1], current[2], tempX, tempY); - x = tempX; - y = tempY; - controlX = current[1]; - controlY = current[2]; - break; - - case "q": - tempX = x + current[3]; - tempY = y + current[4]; - controlX = x + current[1]; - controlY = y + current[2]; - bounds = fabric.util.getBoundsOfCurve(x, y, controlX, controlY, controlX, controlY, tempX, tempY); - x = tempX; - y = tempY; - break; - - case "Q": - controlX = current[1]; - controlY = current[2]; - bounds = fabric.util.getBoundsOfCurve(x, y, controlX, controlY, controlX, controlY, current[3], current[4]); - x = current[3]; - y = current[4]; - break; - - case "t": - tempX = x + current[1]; - tempY = y + current[2]; - if (previous[0].match(/[QqTt]/) === null) { - controlX = x; - controlY = y; - } else { - controlX = 2 * x - controlX; - controlY = 2 * y - controlY; - } - bounds = fabric.util.getBoundsOfCurve(x, y, controlX, controlY, controlX, controlY, tempX, tempY); - x = tempX; - y = tempY; - break; - - case "T": - tempX = current[1]; - tempY = current[2]; - if (previous[0].match(/[QqTt]/) === null) { - controlX = x; - controlY = y; - } else { - controlX = 2 * x - controlX; - controlY = 2 * y - controlY; - } - bounds = fabric.util.getBoundsOfCurve(x, y, controlX, controlY, controlX, controlY, tempX, tempY); - x = tempX; - y = tempY; - break; - - case "a": - bounds = fabric.util.getBoundsOfArc(x, y, current[1], current[2], current[3], current[4], current[5], current[6] + x, current[7] + y); - x += current[6]; - y += current[7]; - break; - - case "A": - bounds = fabric.util.getBoundsOfArc(x, y, current[1], current[2], current[3], current[4], current[5], current[6], current[7]); - x = current[6]; - y = current[7]; - break; - - case "z": - case "Z": - x = subpathStartX; - y = subpathStartY; - break; - } - previous = current; - bounds.forEach(function(point) { - aX.push(point.x); - aY.push(point.y); - }); - aX.push(x); - aY.push(y); - } - var minX = min(aX) || 0, minY = min(aY) || 0, maxX = max(aX) || 0, maxY = max(aY) || 0, deltaX = maxX - minX, deltaY = maxY - minY, o = { - left: minX, - top: minY, - width: deltaX, - height: deltaY - }; - return o; - } - }); - fabric.Path.fromObject = function(object, callback) { - if (typeof object.sourcePath === "string") { - var pathUrl = object.sourcePath; - fabric.loadSVGFromURL(pathUrl, function(elements) { - var path = elements[0]; - path.setOptions(object); - callback && callback(path); - }); - } else { - fabric.Object._fromObject("Path", object, callback, "path"); - } - }; - fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat([ "d" ]); - fabric.Path.fromElement = function(element, callback, options) { - var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES); - callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options))); - }; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, min = fabric.util.array.min, max = fabric.util.array.max; - if (fabric.Group) { - return; - } - fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection, { - type: "group", - strokeWidth: 0, - subTargetCheck: false, - cacheProperties: [], - useSetOnGroup: false, - initialize: function(objects, options, isAlreadyGrouped) { - options = options || {}; - this._objects = []; - isAlreadyGrouped && this.callSuper("initialize", options); - this._objects = objects || []; - for (var i = this._objects.length; i--; ) { - this._objects[i].group = this; - } - if (options.originX) { - this.originX = options.originX; - } - if (options.originY) { - this.originY = options.originY; - } - if (!isAlreadyGrouped) { - var center = options && options.centerPoint; - center || this._calcBounds(); - this._updateObjectsCoords(center); - delete options.centerPoint; - this.callSuper("initialize", options); - } else { - this._updateObjectsACoords(); - } - this.setCoords(); - }, - _updateObjectsACoords: function() { - var ignoreZoom = true, skipAbsolute = true; - for (var i = this._objects.length; i--; ) { - this._objects[i].setCoords(ignoreZoom, skipAbsolute); - } - }, - _updateObjectsCoords: function(center) { - var center = center || this.getCenterPoint(); - for (var i = this._objects.length; i--; ) { - this._updateObjectCoords(this._objects[i], center); - } - }, - _updateObjectCoords: function(object, center) { - var objectLeft = object.left, objectTop = object.top, ignoreZoom = true, skipAbsolute = true; - object.set({ - left: objectLeft - center.x, - top: objectTop - center.y - }); - object.group = this; - object.setCoords(ignoreZoom, skipAbsolute); - }, - toString: function() { - return "#"; - }, - addWithUpdate: function(object) { - this._restoreObjectsState(); - fabric.util.resetObjectTransform(this); - if (object) { - this._objects.push(object); - object.group = this; - object._set("canvas", this.canvas); - } - this._calcBounds(); - this._updateObjectsCoords(); - this.setCoords(); - this.dirty = true; - return this; - }, - removeWithUpdate: function(object) { - this._restoreObjectsState(); - fabric.util.resetObjectTransform(this); - this.remove(object); - this._calcBounds(); - this._updateObjectsCoords(); - this.setCoords(); - this.dirty = true; - return this; - }, - _onObjectAdded: function(object) { - this.dirty = true; - object.group = this; - object._set("canvas", this.canvas); - }, - _onObjectRemoved: function(object) { - this.dirty = true; - delete object.group; - }, - _set: function(key, value) { - var i = this._objects.length; - if (this.useSetOnGroup) { - while (i--) { - this._objects[i].setOnGroup(key, value); - } - } - if (key === "canvas") { - i = this._objects.length; - while (i--) { - this._objects[i]._set(key, value); - } - } - this.callSuper("_set", key, value); - }, - toObject: function(propertiesToInclude) { - var objsToObject = this.getObjects().map(function(obj) { - var originalDefaults = obj.includeDefaultValues; - obj.includeDefaultValues = obj.group.includeDefaultValues; - var _obj = obj.toObject(propertiesToInclude); - obj.includeDefaultValues = originalDefaults; - return _obj; - }); - return extend(this.callSuper("toObject", propertiesToInclude), { - objects: objsToObject - }); - }, - toDatalessObject: function(propertiesToInclude) { - var objsToObject, sourcePath = this.sourcePath; - if (sourcePath) { - objsToObject = sourcePath; - } else { - objsToObject = this.getObjects().map(function(obj) { - var originalDefaults = obj.includeDefaultValues; - obj.includeDefaultValues = obj.group.includeDefaultValues; - var _obj = obj.toDatalessObject(propertiesToInclude); - obj.includeDefaultValues = originalDefaults; - return _obj; - }); - } - return extend(this.callSuper("toDatalessObject", propertiesToInclude), { - objects: objsToObject - }); - }, - render: function(ctx) { - this._transformDone = true; - this.callSuper("render", ctx); - this._transformDone = false; - }, - shouldCache: function() { - var ownCache = this.objectCaching && (!this.group || this.needsItsOwnCache() || !this.group.isOnACache()); - this.ownCaching = ownCache; - if (ownCache) { - for (var i = 0, len = this._objects.length; i < len; i++) { - if (this._objects[i].willDrawShadow()) { - this.ownCaching = false; - return false; - } - } - } - return ownCache; - }, - willDrawShadow: function() { - if (this.shadow) { - return this.callSuper("willDrawShadow"); - } - for (var i = 0, len = this._objects.length; i < len; i++) { - if (this._objects[i].willDrawShadow()) { - return true; - } - } - return false; - }, - isOnACache: function() { - return this.ownCaching || this.group && this.group.isOnACache(); - }, - drawObject: function(ctx) { - for (var i = 0, len = this._objects.length; i < len; i++) { - this._objects[i].render(ctx); - } - }, - isCacheDirty: function() { - if (this.callSuper("isCacheDirty")) { - return true; - } - if (!this.statefullCache) { - return false; - } - for (var i = 0, len = this._objects.length; i < len; i++) { - if (this._objects[i].isCacheDirty(true)) { - if (this._cacheCanvas) { - var x = this.cacheWidth / this.zoomX, y = this.cacheHeight / this.zoomY; - this._cacheContext.clearRect(-x / 2, -y / 2, x, y); - } - return true; - } - } - return false; - }, - _restoreObjectsState: function() { - this._objects.forEach(this._restoreObjectState, this); - return this; - }, - realizeTransform: function(object) { - var matrix = object.calcTransformMatrix(), options = fabric.util.qrDecompose(matrix), center = new fabric.Point(options.translateX, options.translateY); - object.flipX = false; - object.flipY = false; - object.set("scaleX", options.scaleX); - object.set("scaleY", options.scaleY); - object.skewX = options.skewX; - object.skewY = options.skewY; - object.angle = options.angle; - object.setPositionByOrigin(center, "center", "center"); - return object; - }, - _restoreObjectState: function(object) { - this.realizeTransform(object); - object.setCoords(); - delete object.group; - return this; - }, - destroy: function() { - this._objects.forEach(function(object) { - object.set("dirty", true); - }); - return this._restoreObjectsState(); - }, - toActiveSelection: function() { - if (!this.canvas) { - return; - } - var objects = this._objects, canvas = this.canvas; - this._objects = []; - var options = this.toObject(); - delete options.objects; - var activeSelection = new fabric.ActiveSelection([]); - activeSelection.set(options); - activeSelection.type = "activeSelection"; - canvas.remove(this); - objects.forEach(function(object) { - object.group = activeSelection; - object.dirty = true; - canvas.add(object); - }); - activeSelection.canvas = canvas; - activeSelection._objects = objects; - canvas._activeObject = activeSelection; - activeSelection.setCoords(); - return activeSelection; - }, - ungroupOnCanvas: function() { - return this._restoreObjectsState(); - }, - setObjectsCoords: function() { - var ignoreZoom = true, skipAbsolute = true; - this.forEachObject(function(object) { - object.setCoords(ignoreZoom, skipAbsolute); - }); - return this; - }, - _calcBounds: function(onlyWidthHeight) { - var aX = [], aY = [], o, prop, props = [ "tr", "br", "bl", "tl" ], i = 0, iLen = this._objects.length, j, jLen = props.length, ignoreZoom = true; - for (;i < iLen; ++i) { - o = this._objects[i]; - o.setCoords(ignoreZoom); - for (j = 0; j < jLen; j++) { - prop = props[j]; - aX.push(o.oCoords[prop].x); - aY.push(o.oCoords[prop].y); - } - } - this.set(this._getBounds(aX, aY, onlyWidthHeight)); - }, - _getBounds: function(aX, aY, onlyWidthHeight) { - var minXY = new fabric.Point(min(aX), min(aY)), maxXY = new fabric.Point(max(aX), max(aY)), obj = { - width: maxXY.x - minXY.x || 0, - height: maxXY.y - minXY.y || 0 - }; - if (!onlyWidthHeight) { - obj.left = minXY.x || 0; - obj.top = minXY.y || 0; - if (this.originX === "center") { - obj.left += obj.width / 2; - } - if (this.originX === "right") { - obj.left += obj.width; - } - if (this.originY === "center") { - obj.top += obj.height / 2; - } - if (this.originY === "bottom") { - obj.top += obj.height; - } - } - return obj; - }, - toSVG: function(reviver) { - var markup = this._createBaseSVGMarkup(); - markup.push("\n'); - for (var i = 0, len = this._objects.length; i < len; i++) { - markup.push("\t", this._objects[i].toSVG(reviver)); - } - markup.push("\n"); - return reviver ? reviver(markup.join("")) : markup.join(""); - } - }); - fabric.Group.fromObject = function(object, callback) { - fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) { - var options = fabric.util.object.clone(object, true); - delete options.objects; - callback && callback(new fabric.Group(enlivenedObjects, options, true)); - }); - }; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}); - if (fabric.ActiveSelection) { - return; - } - fabric.ActiveSelection = fabric.util.createClass(fabric.Group, { - type: "activeSelection", - initialize: function(objects, options) { - options = options || {}; - this._objects = objects || []; - for (var i = this._objects.length; i--; ) { - this._objects[i].group = this; - } - if (options.originX) { - this.originX = options.originX; - } - if (options.originY) { - this.originY = options.originY; - } - this._calcBounds(); - this._updateObjectsCoords(); - fabric.Object.prototype.initialize.call(this, options); - this.setCoords(); - }, - toGroup: function() { - var objects = this._objects; - this._objects = []; - var options = this.toObject(); - var newGroup = new fabric.Group([]); - delete options.objects; - newGroup.set(options); - newGroup.type = "group"; - objects.forEach(function(object) { - object.group = newGroup; - object.canvas.remove(object); - }); - newGroup._objects = objects; - if (!this.canvas) { - return newGroup; - } - var canvas = this.canvas; - canvas.add(newGroup); - canvas._activeObject = newGroup; - newGroup.setCoords(); - return newGroup; - }, - onDeselect: function() { - this.destroy(); - return false; - }, - toString: function() { - return "#"; - }, - _set: function(key, value) { - var i = this._objects.length; - if (key === "canvas") { - while (i--) { - this._objects[i].set(key, value); - } - } - if (this.useSetOnGroup) { - while (i--) { - this._objects[i].setOnGroup(key, value); - } - } - fabric.Object.prototype._set.call(this, key, value); - }, - shouldCache: function() { - return false; - }, - willDrawShadow: function() { - if (this.shadow) { - return this.callSuper("willDrawShadow"); - } - for (var i = 0, len = this._objects.length; i < len; i++) { - if (this._objects[i].willDrawShadow()) { - return true; - } - } - return false; - }, - isOnACache: function() { - return false; - }, - _renderControls: function(ctx, styleOverride, childrenOverride) { - ctx.save(); - ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1; - this.callSuper("_renderControls", ctx, styleOverride); - childrenOverride = childrenOverride || {}; - if (typeof childrenOverride.hasControls === "undefined") { - childrenOverride.hasControls = false; - } - if (typeof childrenOverride.hasRotatingPoint === "undefined") { - childrenOverride.hasRotatingPoint = false; - } - childrenOverride.forActiveSelection = true; - for (var i = 0, len = this._objects.length; i < len; i++) { - this._objects[i]._renderControls(ctx, childrenOverride); - } - ctx.restore(); - } - }); - fabric.ActiveSelection.fromObject = function(object, callback) { - fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) { - delete object.objects; - callback && callback(new fabric.ActiveSelection(enlivenedObjects, object, true)); - }); - }; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var extend = fabric.util.object.extend; - if (!global.fabric) { - global.fabric = {}; - } - if (global.fabric.Image) { - fabric.warn("fabric.Image is already defined."); - return; - } - fabric.Image = fabric.util.createClass(fabric.Object, { - type: "image", - crossOrigin: "", - strokeWidth: 0, - _lastScaleX: 1, - _lastScaleY: 1, - _filterScalingX: 1, - _filterScalingY: 1, - minimumScaleTrigger: .5, - stateProperties: fabric.Object.prototype.stateProperties.concat("cropX", "cropY"), - objectCaching: false, - cacheKey: "", - cropX: 0, - cropY: 0, - initialize: function(element, options) { - options || (options = {}); - this.filters = []; - this.cacheKey = "texture" + fabric.Object.__uid++; - this.callSuper("initialize", options); - this._initElement(element, options); - }, - getElement: function() { - return this._element; - }, - setElement: function(element, options) { - var backend = fabric.filterBackend; - if (backend && backend.evictCachesForKey) { - backend.evictCachesForKey(this.cacheKey); - backend.evictCachesForKey(this.cacheKey + "_filtered"); - } - this._element = element; - this._originalElement = element; - this._initConfig(options); - if (this.resizeFilter) { - this.applyResizeFilters(); - } - if (this.filters.length !== 0) { - this.applyFilters(); - } - return this; - }, - dispose: function() { - var backend = fabric.filterBackend; - if (backend && backend.evictCachesForKey) { - backend.evictCachesForKey(this.cacheKey); - backend.evictCachesForKey(this.cacheKey + "_filtered"); - } - this._originalElement = undefined; - this._element = undefined; - this._filteredEl = undefined; - }, - setCrossOrigin: function(value) { - this.crossOrigin = value; - this._element.crossOrigin = value; - return this; - }, - getOriginalSize: function() { - var element = this.getElement(); - return { - width: element.width, - height: element.height - }; - }, - _stroke: function(ctx) { - if (!this.stroke || this.strokeWidth === 0) { - return; - } - var w = this.width / 2, h = this.height / 2; - ctx.beginPath(); - ctx.moveTo(-w, -h); - ctx.lineTo(w, -h); - ctx.lineTo(w, h); - ctx.lineTo(-w, h); - ctx.lineTo(-w, -h); - ctx.closePath(); - }, - _renderDashedStroke: function(ctx) { - var x = -this.width / 2, y = -this.height / 2, w = this.width, h = this.height; - ctx.save(); - this._setStrokeStyles(ctx, this); - ctx.beginPath(); - fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray); - fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray); - fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray); - fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray); - ctx.closePath(); - ctx.restore(); - }, - toObject: function(propertiesToInclude) { - var filters = []; - this.filters.forEach(function(filterObj) { - if (filterObj) { - filters.push(filterObj.toObject()); - } - }); - var object = extend(this.callSuper("toObject", [ "crossOrigin", "cropX", "cropY" ].concat(propertiesToInclude)), { - src: this.getSrc(), - filters: filters - }); - if (this.resizeFilter) { - object.resizeFilter = this.resizeFilter.toObject(); - } - return object; - }, - toSVG: function(reviver) { - var markup = this._createBaseSVGMarkup(), x = -this.width / 2, y = -this.height / 2; - markup.push('\n'); - var imageMarkup = [ "\t\n' ]; - if (this.paintFirst === "fill") { - Array.prototype.push.apply(markup, imageMarkup); - } - if (this.stroke || this.strokeDashArray) { - var origFill = this.fill; - this.fill = null; - markup.push("\t\n'); - this.fill = origFill; - } - if (this.paintFirst !== "fill") { - Array.prototype.push.apply(markup, imageMarkup); - } - markup.push("\n"); - return reviver ? reviver(markup.join("")) : markup.join(""); - }, - getSrc: function(filtered) { - var element = filtered ? this._element : this._originalElement; - if (element) { - if (element.toDataURL) { - return element.toDataURL(); - } - return element.src; - } else { - return this.src || ""; - } - }, - setSrc: function(src, callback, options) { - fabric.util.loadImage(src, function(img) { - this.setElement(img, options); - callback(this); - }, this, options && options.crossOrigin); - return this; - }, - toString: function() { - return '#'; - }, - applyResizeFilters: function() { - var filter = this.resizeFilter, retinaScaling = this.canvas ? this.canvas.getRetinaScaling() : 1, minimumScale = this.minimumScaleTrigger, scaleX = this.scaleX * retinaScaling, scaleY = this.scaleY * retinaScaling, elementToFilter = this._filteredEl || this._originalElement; - if (!filter || scaleX > minimumScale && scaleY > minimumScale) { - this._element = elementToFilter; - this._filterScalingX = 1; - this._filterScalingY = 1; - return; - } - if (!fabric.filterBackend) { - fabric.filterBackend = fabric.initFilterBackend(); - } - var canvasEl = fabric.util.createCanvasElement(), cacheKey = this._filteredEl ? this.cacheKey : this.cacheKey + "_filtered", sourceWidth = elementToFilter.width, sourceHeight = elementToFilter.height; - canvasEl.width = sourceWidth; - canvasEl.height = sourceHeight; - this._element = canvasEl; - filter.scaleX = scaleX; - filter.scaleY = scaleY; - fabric.filterBackend.applyFilters([ filter ], elementToFilter, sourceWidth, sourceHeight, this._element, cacheKey); - this._filterScalingX = canvasEl.width / this._originalElement.width; - this._filterScalingY = canvasEl.height / this._originalElement.height; - }, - applyFilters: function(filters) { - filters = filters || this.filters || []; - filters = filters.filter(function(filter) { - return filter; - }); - if (filters.length === 0) { - this._element = this._originalElement; - this._filteredEl = null; - this._filterScalingX = 1; - this._filterScalingY = 1; - return this; - } - var imgElement = this._originalElement, sourceWidth = imgElement.naturalWidth || imgElement.width, sourceHeight = imgElement.naturalHeight || imgElement.height; - if (this._element === this._originalElement) { - var canvasEl = fabric.util.createCanvasElement(); - canvasEl.width = sourceWidth; - canvasEl.height = sourceHeight; - this._element = canvasEl; - this._filteredEl = canvasEl; - } else { - this._element.getContext("2d").clearRect(0, 0, sourceWidth, sourceHeight); - } - if (!fabric.filterBackend) { - fabric.filterBackend = fabric.initFilterBackend(); - } - fabric.filterBackend.applyFilters(filters, this._originalElement, sourceWidth, sourceHeight, this._element, this.cacheKey); - if (this._originalElement.width !== this._element.width || this._originalElement.height !== this._element.height) { - this._filterScalingX = this._element.width / this._originalElement.width; - this._filterScalingY = this._element.height / this._originalElement.height; - } - return this; - }, - _render: function(ctx) { - if (this.isMoving === false && this.resizeFilter && this._needsResize()) { - this._lastScaleX = this.scaleX; - this._lastScaleY = this.scaleY; - this.applyResizeFilters(); - } - this._stroke(ctx); - this._renderPaintInOrder(ctx); - }, - _renderFill: function(ctx) { - var w = this.width, h = this.height, sW = w * this._filterScalingX, sH = h * this._filterScalingY, x = -w / 2, y = -h / 2, elementToDraw = this._element; - elementToDraw && ctx.drawImage(elementToDraw, this.cropX * this._filterScalingX, this.cropY * this._filterScalingY, sW, sH, x, y, w, h); - }, - _needsResize: function() { - return this.scaleX !== this._lastScaleX || this.scaleY !== this._lastScaleY; - }, - _resetWidthHeight: function() { - var element = this.getElement(); - this.set("width", element.width); - this.set("height", element.height); - }, - _initElement: function(element, options) { - this.setElement(fabric.util.getById(element), options); - fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS); - }, - _initConfig: function(options) { - options || (options = {}); - this.setOptions(options); - this._setWidthHeight(options); - if (this._element && this.crossOrigin) { - this._element.crossOrigin = this.crossOrigin; - } - }, - _initFilters: function(filters, callback) { - if (filters && filters.length) { - fabric.util.enlivenObjects(filters, function(enlivenedObjects) { - callback && callback(enlivenedObjects); - }, "fabric.Image.filters"); - } else { - callback && callback(); - } - }, - _setWidthHeight: function(options) { - this.width = "width" in options ? options.width : this.getElement() ? this.getElement().width || 0 : 0; - this.height = "height" in options ? options.height : this.getElement() ? this.getElement().height || 0 : 0; - }, - parsePreserveAspectRatioAttribute: function() { - var pAR = fabric.util.parsePreserveAspectRatioAttribute(this.preserveAspectRatio || ""), rWidth = this._element.width, rHeight = this._element.height, scaleX = 1, scaleY = 1, offsetLeft = 0, offsetTop = 0, cropX = 0, cropY = 0, offset, pWidth = this.width, pHeight = this.height, parsedAttributes = { - width: pWidth, - height: pHeight - }; - if (pAR && (pAR.alignX !== "none" || pAR.alignY !== "none")) { - if (pAR.meetOrSlice === "meet") { - scaleX = scaleY = fabric.util.findScaleToFit(this._element, parsedAttributes); - offset = (pWidth - rWidth * scaleX) / 2; - if (pAR.alignX === "Min") { - offsetLeft = -offset; - } - if (pAR.alignX === "Max") { - offsetLeft = offset; - } - offset = (pHeight - rHeight * scaleY) / 2; - if (pAR.alignY === "Min") { - offsetTop = -offset; - } - if (pAR.alignY === "Max") { - offsetTop = offset; - } - } - if (pAR.meetOrSlice === "slice") { - scaleX = scaleY = fabric.util.findScaleToCover(this._element, parsedAttributes); - offset = rWidth - pWidth / scaleX; - if (pAR.alignX === "Mid") { - cropX = offset / 2; - } - if (pAR.alignX === "Max") { - cropX = offset; - } - offset = rHeight - pHeight / scaleY; - if (pAR.alignY === "Mid") { - cropY = offset / 2; - } - if (pAR.alignY === "Max") { - cropY = offset; - } - rWidth = pWidth / scaleX; - rHeight = pHeight / scaleY; - } - } else { - scaleX = pWidth / rWidth; - scaleY = pHeight / rHeight; - } - return { - width: rWidth, - height: rHeight, - scaleX: scaleX, - scaleY: scaleY, - offsetLeft: offsetLeft, - offsetTop: offsetTop, - cropX: cropX, - cropY: cropY - }; - } - }); - fabric.Image.CSS_CANVAS = "canvas-img"; - fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc; - fabric.Image.fromObject = function(object, callback) { - fabric.util.loadImage(object.src, function(img, error) { - if (error) { - callback && callback(null, error); - return; - } - fabric.Image.prototype._initFilters.call(object, object.filters, function(filters) { - object.filters = filters || []; - fabric.Image.prototype._initFilters.call(object, [ object.resizeFilter ], function(resizeFilters) { - object.resizeFilter = resizeFilters[0]; - var image = new fabric.Image(img, object); - callback(image); - }); - }); - }, null, object.crossOrigin); - }; - fabric.Image.fromURL = function(url, callback, imgOptions) { - fabric.util.loadImage(url, function(img) { - callback && callback(new fabric.Image(img, imgOptions)); - }, null, imgOptions && imgOptions.crossOrigin); - }; - fabric.Image.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat("x y width height preserveAspectRatio xlink:href crossOrigin".split(" ")); - fabric.Image.fromElement = function(element, callback, options) { - var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES); - fabric.Image.fromURL(parsedAttributes["xlink:href"], callback, extend(options ? fabric.util.object.clone(options) : {}, parsedAttributes)); - }; -})(typeof exports !== "undefined" ? exports : this); - -fabric.util.object.extend(fabric.Object.prototype, { - _getAngleValueForStraighten: function() { - var angle = this.angle % 360; - if (angle > 0) { - return Math.round((angle - 1) / 90) * 90; - } - return Math.round(angle / 90) * 90; - }, - straighten: function() { - this.rotate(this._getAngleValueForStraighten()); - return this; - }, - fxStraighten: function(callbacks) { - callbacks = callbacks || {}; - var empty = function() {}, onComplete = callbacks.onComplete || empty, onChange = callbacks.onChange || empty, _this = this; - fabric.util.animate({ - startValue: this.get("angle"), - endValue: this._getAngleValueForStraighten(), - duration: this.FX_DURATION, - onChange: function(value) { - _this.rotate(value); - onChange(); - }, - onComplete: function() { - _this.setCoords(); - onComplete(); - } - }); - return this; - } -}); - -fabric.util.object.extend(fabric.StaticCanvas.prototype, { - straightenObject: function(object) { - object.straighten(); - this.requestRenderAll(); - return this; - }, - fxStraightenObject: function(object) { - object.fxStraighten({ - onChange: this.requestRenderAllBound - }); - return this; - } -}); - -(function() { - "use strict"; - function testPrecision(gl, precision) { - var fragmentSource = "precision " + precision + " float;\nvoid main(){}"; - var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); - gl.shaderSource(fragmentShader, fragmentSource); - gl.compileShader(fragmentShader); - if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { - return false; - } - return true; - } - fabric.isWebglSupported = function(tileSize) { - if (fabric.isLikelyNode) { - return false; - } - tileSize = tileSize || fabric.WebglFilterBackend.prototype.tileSize; - var canvas = document.createElement("canvas"); - var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); - var isSupported = false; - if (gl) { - fabric.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE); - isSupported = fabric.maxTextureSize >= tileSize; - var precisions = [ "highp", "mediump", "lowp" ]; - for (var i = 0; i < 3; i++) { - if (testPrecision(gl, precisions[i])) { - fabric.webGlPrecision = precisions[i]; - break; - } - } - } - this.isSupported = isSupported; - return isSupported; - }; - fabric.WebglFilterBackend = WebglFilterBackend; - function WebglFilterBackend(options) { - if (options && options.tileSize) { - this.tileSize = options.tileSize; - } - this.setupGLContext(this.tileSize, this.tileSize); - this.captureGPUInfo(); - } - WebglFilterBackend.prototype = { - tileSize: 2048, - resources: {}, - setupGLContext: function(width, height) { - this.dispose(); - this.createWebGLCanvas(width, height); - this.aPosition = new Float32Array([ 0, 0, 0, 1, 1, 0, 1, 1 ]); - this.chooseFastestCopyGLTo2DMethod(width, height); - }, - chooseFastestCopyGLTo2DMethod: function(width, height) { - var canMeasurePerf = typeof window.performance !== "undefined"; - var canUseImageData; - try { - new ImageData(1, 1); - canUseImageData = true; - } catch (e) { - canUseImageData = false; - } - var canUseArrayBuffer = typeof ArrayBuffer !== "undefined"; - var canUseUint8Clamped = typeof Uint8ClampedArray !== "undefined"; - if (!(canMeasurePerf && canUseImageData && canUseArrayBuffer && canUseUint8Clamped)) { - return; - } - var targetCanvas = fabric.util.createCanvasElement(); - var imageBuffer = new ArrayBuffer(width * height * 4); - var testContext = { - imageBuffer: imageBuffer, - destinationWidth: width, - destinationHeight: height, - targetCanvas: targetCanvas - }; - var startTime, drawImageTime, putImageDataTime; - targetCanvas.width = width; - targetCanvas.height = height; - startTime = window.performance.now(); - copyGLTo2DDrawImage.call(testContext, this.gl, testContext); - drawImageTime = window.performance.now() - startTime; - startTime = window.performance.now(); - copyGLTo2DPutImageData.call(testContext, this.gl, testContext); - putImageDataTime = window.performance.now() - startTime; - if (drawImageTime > putImageDataTime) { - this.imageBuffer = imageBuffer; - this.copyGLTo2D = copyGLTo2DPutImageData; - } else { - this.copyGLTo2D = copyGLTo2DDrawImage; - } - }, - createWebGLCanvas: function(width, height) { - var canvas = fabric.util.createCanvasElement(); - canvas.width = width; - canvas.height = height; - var glOptions = { - premultipliedAlpha: false - }, gl = canvas.getContext("webgl", glOptions); - if (!gl) { - gl = canvas.getContext("experimental-webgl", glOptions); - } - if (!gl) { - return; - } - gl.clearColor(0, 0, 0, 0); - this.canvas = canvas; - this.gl = gl; - }, - applyFilters: function(filters, source, width, height, targetCanvas, cacheKey) { - var gl = this.gl; - var cachedTexture; - if (cacheKey) { - cachedTexture = this.getCachedTexture(cacheKey, source); - } - var pipelineState = { - originalWidth: source.width || source.originalWidth, - originalHeight: source.height || source.originalHeight, - sourceWidth: width, - sourceHeight: height, - destinationWidth: width, - destinationHeight: height, - context: gl, - sourceTexture: this.createTexture(gl, width, height, !cachedTexture && source), - targetTexture: this.createTexture(gl, width, height), - originalTexture: cachedTexture || this.createTexture(gl, width, height, !cachedTexture && source), - passes: filters.length, - webgl: true, - aPosition: this.aPosition, - programCache: this.programCache, - pass: 0, - filterBackend: this, - targetCanvas: targetCanvas - }; - var tempFbo = gl.createFramebuffer(); - gl.bindFramebuffer(gl.FRAMEBUFFER, tempFbo); - filters.forEach(function(filter) { - filter && filter.applyTo(pipelineState); - }); - resizeCanvasIfNeeded(pipelineState); - this.copyGLTo2D(gl, pipelineState); - gl.bindTexture(gl.TEXTURE_2D, null); - gl.deleteTexture(pipelineState.sourceTexture); - gl.deleteTexture(pipelineState.targetTexture); - gl.deleteFramebuffer(tempFbo); - targetCanvas.getContext("2d").setTransform(1, 0, 0, 1, 0, 0); - return pipelineState; - }, - applyFiltersDebug: function(filters, source, width, height, targetCanvas, cacheKey) { - var gl = this.gl; - var ret = this.applyFilters(filters, source, width, height, targetCanvas, cacheKey); - var glError = gl.getError(); - if (glError !== gl.NO_ERROR) { - var errorString = this.glErrorToString(gl, glError); - var error = new Error("WebGL Error " + errorString); - error.glErrorCode = glError; - throw error; - } - return ret; - }, - glErrorToString: function(context, errorCode) { - if (!context) { - return "Context undefined for error code: " + errorCode; - } else if (typeof errorCode !== "number") { - return "Error code is not a number"; - } - switch (errorCode) { - case context.NO_ERROR: - return "NO_ERROR"; - - case context.INVALID_ENUM: - return "INVALID_ENUM"; - - case context.INVALID_VALUE: - return "INVALID_VALUE"; - - case context.INVALID_OPERATION: - return "INVALID_OPERATION"; - - case context.INVALID_FRAMEBUFFER_OPERATION: - return "INVALID_FRAMEBUFFER_OPERATION"; - - case context.OUT_OF_MEMORY: - return "OUT_OF_MEMORY"; - - case context.CONTEXT_LOST_WEBGL: - return "CONTEXT_LOST_WEBGL"; - - default: - return "UNKNOWN_ERROR"; - } - }, - dispose: function() { - if (this.canvas) { - this.canvas = null; - this.gl = null; - } - this.clearWebGLCaches(); - }, - clearWebGLCaches: function() { - this.programCache = {}; - this.textureCache = {}; - }, - createTexture: function(gl, width, height, textureImageSource) { - var texture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - if (textureImageSource) { - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureImageSource); - } else { - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - } - return texture; - }, - getCachedTexture: function(uniqueId, textureImageSource) { - if (this.textureCache[uniqueId]) { - return this.textureCache[uniqueId]; - } else { - var texture = this.createTexture(this.gl, textureImageSource.width, textureImageSource.height, textureImageSource); - this.textureCache[uniqueId] = texture; - return texture; - } - }, - evictCachesForKey: function(cacheKey) { - if (this.textureCache[cacheKey]) { - this.gl.deleteTexture(this.textureCache[cacheKey]); - delete this.textureCache[cacheKey]; - } - }, - copyGLTo2D: copyGLTo2DDrawImage, - captureGPUInfo: function() { - if (this.gpuInfo) { - return this.gpuInfo; - } - var gl = this.gl; - var ext = gl.getExtension("WEBGL_debug_renderer_info"); - var gpuInfo = { - renderer: "", - vendor: "" - }; - if (ext) { - var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL); - var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL); - if (renderer) { - gpuInfo.renderer = renderer.toLowerCase(); - } - if (vendor) { - gpuInfo.vendor = vendor.toLowerCase(); - } - } - this.gpuInfo = gpuInfo; - return gpuInfo; - } - }; -})(); - -function resizeCanvasIfNeeded(pipelineState) { - var targetCanvas = pipelineState.targetCanvas, width = targetCanvas.width, height = targetCanvas.height, dWidth = pipelineState.destinationWidth, dHeight = pipelineState.destinationHeight; - if (width !== dWidth || height !== dHeight) { - targetCanvas.width = dWidth; - targetCanvas.height = dHeight; - } -} - -function copyGLTo2DDrawImage(gl, pipelineState) { - var glCanvas = gl.canvas, targetCanvas = pipelineState.targetCanvas, ctx = targetCanvas.getContext("2d"); - ctx.translate(0, targetCanvas.height); - ctx.scale(1, -1); - var sourceY = glCanvas.height - targetCanvas.height; - ctx.drawImage(glCanvas, 0, sourceY, targetCanvas.width, targetCanvas.height, 0, 0, targetCanvas.width, targetCanvas.height); -} - -function copyGLTo2DPutImageData(gl, pipelineState) { - var targetCanvas = pipelineState.targetCanvas, ctx = targetCanvas.getContext("2d"), dWidth = pipelineState.destinationWidth, dHeight = pipelineState.destinationHeight, numBytes = dWidth * dHeight * 4; - var u8 = new Uint8Array(this.imageBuffer, 0, numBytes); - var u8Clamped = new Uint8ClampedArray(this.imageBuffer, 0, numBytes); - gl.readPixels(0, 0, dWidth, dHeight, gl.RGBA, gl.UNSIGNED_BYTE, u8); - var imgData = new ImageData(u8Clamped, dWidth, dHeight); - ctx.putImageData(imgData, 0, 0); -} - -(function() { - "use strict"; - var noop = function() {}; - fabric.Canvas2dFilterBackend = Canvas2dFilterBackend; - function Canvas2dFilterBackend() {} - Canvas2dFilterBackend.prototype = { - evictCachesForKey: noop, - dispose: noop, - clearWebGLCaches: noop, - resources: {}, - applyFilters: function(filters, sourceElement, sourceWidth, sourceHeight, targetCanvas) { - var ctx = targetCanvas.getContext("2d"); - ctx.drawImage(sourceElement, 0, 0, sourceWidth, sourceHeight); - var imageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight); - var originalImageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight); - var pipelineState = { - sourceWidth: sourceWidth, - sourceHeight: sourceHeight, - imageData: imageData, - originalEl: sourceElement, - originalImageData: originalImageData, - canvasEl: targetCanvas, - ctx: ctx, - filterBackend: this - }; - filters.forEach(function(filter) { - filter.applyTo(pipelineState); - }); - if (pipelineState.imageData.width !== sourceWidth || pipelineState.imageData.height !== sourceHeight) { - targetCanvas.width = pipelineState.imageData.width; - targetCanvas.height = pipelineState.imageData.height; - } - ctx.putImageData(pipelineState.imageData, 0, 0); - return pipelineState; - } - }; -})(); - -fabric.Image.filters = fabric.Image.filters || {}; - -fabric.Image.filters.BaseFilter = fabric.util.createClass({ - type: "BaseFilter", - vertexSource: "attribute vec2 aPosition;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vTexCoord = aPosition;\n" + "gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\n" + "}", - fragmentSource: "precision highp float;\n" + "varying vec2 vTexCoord;\n" + "uniform sampler2D uTexture;\n" + "void main() {\n" + "gl_FragColor = texture2D(uTexture, vTexCoord);\n" + "}", - initialize: function(options) { - if (options) { - this.setOptions(options); - } - }, - setOptions: function(options) { - for (var prop in options) { - this[prop] = options[prop]; - } - }, - createProgram: function(gl, fragmentSource, vertexSource) { - fragmentSource = fragmentSource || this.fragmentSource; - vertexSource = vertexSource || this.vertexSource; - if (fabric.webGlPrecision !== "highp") { - fragmentSource = fragmentSource.replace(/precision highp float/g, "precision " + fabric.webGlPrecision + " float"); - } - var vertexShader = gl.createShader(gl.VERTEX_SHADER); - gl.shaderSource(vertexShader, vertexSource); - gl.compileShader(vertexShader); - if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { - throw new Error("Vertex shader compile error for " + this.type + ": " + gl.getShaderInfoLog(vertexShader)); - } - var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); - gl.shaderSource(fragmentShader, fragmentSource); - gl.compileShader(fragmentShader); - if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { - throw new Error("Fragment shader compile error for " + this.type + ": " + gl.getShaderInfoLog(fragmentShader)); - } - var program = gl.createProgram(); - gl.attachShader(program, vertexShader); - gl.attachShader(program, fragmentShader); - gl.linkProgram(program); - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { - throw new Error('Shader link error for "${this.type}" ' + gl.getProgramInfoLog(program)); - } - var attributeLocations = this.getAttributeLocations(gl, program); - var uniformLocations = this.getUniformLocations(gl, program) || {}; - uniformLocations.uStepW = gl.getUniformLocation(program, "uStepW"); - uniformLocations.uStepH = gl.getUniformLocation(program, "uStepH"); - return { - program: program, - attributeLocations: attributeLocations, - uniformLocations: uniformLocations - }; - }, - getAttributeLocations: function(gl, program) { - return { - aPosition: gl.getAttribLocation(program, "aPosition") - }; - }, - getUniformLocations: function() { - return {}; - }, - sendAttributeData: function(gl, attributeLocations, aPositionData) { - var attributeLocation = attributeLocations.aPostion; - var buffer = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.enableVertexAttribArray(attributeLocation); - gl.vertexAttribPointer(attributeLocation, 2, gl.FLOAT, false, 0, 0); - gl.bufferData(gl.ARRAY_BUFFER, aPositionData, gl.STATIC_DRAW); - }, - _setupFrameBuffer: function(options) { - var gl = options.context, width, height; - if (options.passes > 1) { - width = options.destinationWidth; - height = options.destinationHeight; - if (options.sourceWidth !== width || options.sourceHeight !== height) { - gl.deleteTexture(options.targetTexture); - options.targetTexture = options.filterBackend.createTexture(gl, width, height); - } - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, options.targetTexture, 0); - } else { - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - gl.finish(); - } - }, - _swapTextures: function(options) { - options.passes--; - options.pass++; - var temp = options.targetTexture; - options.targetTexture = options.sourceTexture; - options.sourceTexture = temp; - }, - isNeutralState: function() { - return false; - }, - applyTo: function(options) { - if (options.webgl) { - if (options.passes > 1 && this.isNeutralState(options)) { - return; - } - this._setupFrameBuffer(options); - this.applyToWebGL(options); - this._swapTextures(options); - } else if (!this.isNeutralState()) { - this.applyTo2d(options); - } - }, - retrieveShader: function(options) { - if (!options.programCache.hasOwnProperty(this.type)) { - options.programCache[this.type] = this.createProgram(options.context); - } - return options.programCache[this.type]; - }, - applyToWebGL: function(options) { - var gl = options.context; - var shader = this.retrieveShader(options); - if (options.pass === 0 && options.originalTexture) { - gl.bindTexture(gl.TEXTURE_2D, options.originalTexture); - } else { - gl.bindTexture(gl.TEXTURE_2D, options.sourceTexture); - } - gl.useProgram(shader.program); - this.sendAttributeData(gl, shader.attributeLocations, options.aPosition); - gl.uniform1f(shader.uniformLocations.uStepW, 1 / options.sourceWidth); - gl.uniform1f(shader.uniformLocations.uStepH, 1 / options.sourceHeight); - this.sendUniformData(gl, shader.uniformLocations); - gl.viewport(0, 0, options.destinationWidth, options.destinationHeight); - gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); - }, - bindAdditionalTexture: function(gl, texture, textureUnit) { - gl.activeTexture(textureUnit); - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.activeTexture(gl.TEXTURE0); - }, - unbindAdditionalTexture: function(gl, textureUnit) { - gl.activeTexture(textureUnit); - gl.bindTexture(gl.TEXTURE_2D, null); - gl.activeTexture(gl.TEXTURE0); - }, - getMainParameter: function() { - return this[this.mainParameter]; - }, - setMainParameter: function(value) { - this[this.mainParameter] = value; - }, - sendUniformData: function() {}, - createHelpLayer: function(options) { - if (!options.helpLayer) { - var helpLayer = document.createElement("canvas"); - helpLayer.width = options.sourceWidth; - helpLayer.height = options.sourceHeight; - options.helpLayer = helpLayer; - } - }, - toObject: function() { - var object = { - type: this.type - }, mainP = this.mainParameter; - if (mainP) { - object[mainP] = this[mainP]; - } - return object; - }, - toJSON: function() { - return this.toObject(); - } -}); - -fabric.Image.filters.BaseFilter.fromObject = function(object, callback) { - var filter = new fabric.Image.filters[object.type](object); - callback && callback(filter); - return filter; -}; - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.ColorMatrix = createClass(filters.BaseFilter, { - type: "ColorMatrix", - fragmentSource: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "varying vec2 vTexCoord;\n" + "uniform mat4 uColorMatrix;\n" + "uniform vec4 uConstants;\n" + "void main() {\n" + "vec4 color = texture2D(uTexture, vTexCoord);\n" + "color *= uColorMatrix;\n" + "color += uConstants;\n" + "gl_FragColor = color;\n" + "}", - matrix: [ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0 ], - mainParameter: "matrix", - colorsOnly: true, - initialize: function(options) { - this.callSuper("initialize", options); - this.matrix = this.matrix.slice(0); - }, - isNeutralState: function() { - var _class = filters.ColorMatrix; - for (var i = 20; i--; ) { - if (this.matrix[i] !== _class.prototype.matrix[i]) { - return false; - } - } - return true; - }, - applyTo2d: function(options) { - var imageData = options.imageData, data = imageData.data, iLen = data.length, m = this.matrix, r, g, b, a, i, colorsOnly = this.colorsOnly; - for (i = 0; i < iLen; i += 4) { - r = data[i]; - g = data[i + 1]; - b = data[i + 2]; - if (colorsOnly) { - data[i] = r * m[0] + g * m[1] + b * m[2] + m[4] * 255; - data[i + 1] = r * m[5] + g * m[6] + b * m[7] + m[9] * 255; - data[i + 2] = r * m[10] + g * m[11] + b * m[12] + m[14] * 255; - } else { - a = data[i + 3]; - data[i] = r * m[0] + g * m[1] + b * m[2] + a * m[3] + m[4] * 255; - data[i + 1] = r * m[5] + g * m[6] + b * m[7] + a * m[8] + m[9] * 255; - data[i + 2] = r * m[10] + g * m[11] + b * m[12] + a * m[13] + m[14] * 255; - data[i + 3] = r * m[15] + g * m[16] + b * m[17] + a * m[18] + m[19] * 255; - } - } - }, - getUniformLocations: function(gl, program) { - return { - uColorMatrix: gl.getUniformLocation(program, "uColorMatrix"), - uConstants: gl.getUniformLocation(program, "uConstants") - }; - }, - sendUniformData: function(gl, uniformLocations) { - var m = this.matrix, matrix = [ m[0], m[1], m[2], m[3], m[5], m[6], m[7], m[8], m[10], m[11], m[12], m[13], m[15], m[16], m[17], m[18] ], constants = [ m[4], m[9], m[14], m[19] ]; - gl.uniformMatrix4fv(uniformLocations.uColorMatrix, false, matrix); - gl.uniform4fv(uniformLocations.uConstants, constants); - } - }); - fabric.Image.filters.ColorMatrix.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.Brightness = createClass(filters.BaseFilter, { - type: "Brightness", - fragmentSource: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uBrightness;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = texture2D(uTexture, vTexCoord);\n" + "color.rgb += uBrightness;\n" + "gl_FragColor = color;\n" + "}", - brightness: 0, - mainParameter: "brightness", - applyTo2d: function(options) { - if (this.brightness === 0) { - return; - } - var imageData = options.imageData, data = imageData.data, i, len = data.length, brightness = Math.round(this.brightness * 255); - for (i = 0; i < len; i += 4) { - data[i] = data[i] + brightness; - data[i + 1] = data[i + 1] + brightness; - data[i + 2] = data[i + 2] + brightness; - } - }, - getUniformLocations: function(gl, program) { - return { - uBrightness: gl.getUniformLocation(program, "uBrightness") - }; - }, - sendUniformData: function(gl, uniformLocations) { - gl.uniform1f(uniformLocations.uBrightness, this.brightness); - } - }); - fabric.Image.filters.Brightness.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.Convolute = createClass(filters.BaseFilter, { - type: "Convolute", - opaque: false, - matrix: [ 0, 0, 0, 0, 1, 0, 0, 0, 0 ], - fragmentSource: { - Convolute_3_1: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uMatrix[9];\n" + "uniform float uStepW;\n" + "uniform float uStepH;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = vec4(0, 0, 0, 0);\n" + "for (float h = 0.0; h < 3.0; h+=1.0) {\n" + "for (float w = 0.0; w < 3.0; w+=1.0) {\n" + "vec2 matrixPos = vec2(uStepW * (w - 1), uStepH * (h - 1));\n" + "color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 3.0 + w)];\n" + "}\n" + "}\n" + "gl_FragColor = color;\n" + "}", - Convolute_3_0: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uMatrix[9];\n" + "uniform float uStepW;\n" + "uniform float uStepH;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = vec4(0, 0, 0, 1);\n" + "for (float h = 0.0; h < 3.0; h+=1.0) {\n" + "for (float w = 0.0; w < 3.0; w+=1.0) {\n" + "vec2 matrixPos = vec2(uStepW * (w - 1.0), uStepH * (h - 1.0));\n" + "color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 3.0 + w)];\n" + "}\n" + "}\n" + "float alpha = texture2D(uTexture, vTexCoord).a;\n" + "gl_FragColor = color;\n" + "gl_FragColor.a = alpha;\n" + "}", - Convolute_5_1: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uMatrix[25];\n" + "uniform float uStepW;\n" + "uniform float uStepH;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = vec4(0, 0, 0, 0);\n" + "for (float h = 0.0; h < 5.0; h+=1.0) {\n" + "for (float w = 0.0; w < 5.0; w+=1.0) {\n" + "vec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\n" + "color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 5.0 + w)];\n" + "}\n" + "}\n" + "gl_FragColor = color;\n" + "}", - Convolute_5_0: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uMatrix[25];\n" + "uniform float uStepW;\n" + "uniform float uStepH;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = vec4(0, 0, 0, 1);\n" + "for (float h = 0.0; h < 5.0; h+=1.0) {\n" + "for (float w = 0.0; w < 5.0; w+=1.0) {\n" + "vec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\n" + "color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 5.0 + w)];\n" + "}\n" + "}\n" + "float alpha = texture2D(uTexture, vTexCoord).a;\n" + "gl_FragColor = color;\n" + "gl_FragColor.a = alpha;\n" + "}", - Convolute_7_1: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uMatrix[49];\n" + "uniform float uStepW;\n" + "uniform float uStepH;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = vec4(0, 0, 0, 0);\n" + "for (float h = 0.0; h < 7.0; h+=1.0) {\n" + "for (float w = 0.0; w < 7.0; w+=1.0) {\n" + "vec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\n" + "color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 7.0 + w)];\n" + "}\n" + "}\n" + "gl_FragColor = color;\n" + "}", - Convolute_7_0: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uMatrix[49];\n" + "uniform float uStepW;\n" + "uniform float uStepH;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = vec4(0, 0, 0, 1);\n" + "for (float h = 0.0; h < 7.0; h+=1.0) {\n" + "for (float w = 0.0; w < 7.0; w+=1.0) {\n" + "vec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\n" + "color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 7.0 + w)];\n" + "}\n" + "}\n" + "float alpha = texture2D(uTexture, vTexCoord).a;\n" + "gl_FragColor = color;\n" + "gl_FragColor.a = alpha;\n" + "}", - Convolute_9_1: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uMatrix[81];\n" + "uniform float uStepW;\n" + "uniform float uStepH;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = vec4(0, 0, 0, 0);\n" + "for (float h = 0.0; h < 9.0; h+=1.0) {\n" + "for (float w = 0.0; w < 9.0; w+=1.0) {\n" + "vec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\n" + "color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 9.0 + w)];\n" + "}\n" + "}\n" + "gl_FragColor = color;\n" + "}", - Convolute_9_0: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uMatrix[81];\n" + "uniform float uStepW;\n" + "uniform float uStepH;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = vec4(0, 0, 0, 1);\n" + "for (float h = 0.0; h < 9.0; h+=1.0) {\n" + "for (float w = 0.0; w < 9.0; w+=1.0) {\n" + "vec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\n" + "color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 9.0 + w)];\n" + "}\n" + "}\n" + "float alpha = texture2D(uTexture, vTexCoord).a;\n" + "gl_FragColor = color;\n" + "gl_FragColor.a = alpha;\n" + "}" - }, - retrieveShader: function(options) { - var size = Math.sqrt(this.matrix.length); - var cacheKey = this.type + "_" + size + "_" + (this.opaque ? 1 : 0); - var shaderSource = this.fragmentSource[cacheKey]; - if (!options.programCache.hasOwnProperty(cacheKey)) { - options.programCache[cacheKey] = this.createProgram(options.context, shaderSource); - } - return options.programCache[cacheKey]; - }, - applyTo2d: function(options) { - var imageData = options.imageData, data = imageData.data, weights = this.matrix, side = Math.round(Math.sqrt(weights.length)), halfSide = Math.floor(side / 2), sw = imageData.width, sh = imageData.height, output = options.ctx.createImageData(sw, sh), dst = output.data, alphaFac = this.opaque ? 1 : 0, r, g, b, a, dstOff, scx, scy, srcOff, wt, x, y, cx, cy; - for (y = 0; y < sh; y++) { - for (x = 0; x < sw; x++) { - dstOff = (y * sw + x) * 4; - r = 0; - g = 0; - b = 0; - a = 0; - for (cy = 0; cy < side; cy++) { - for (cx = 0; cx < side; cx++) { - scy = y + cy - halfSide; - scx = x + cx - halfSide; - if (scy < 0 || scy > sh || scx < 0 || scx > sw) { - continue; - } - srcOff = (scy * sw + scx) * 4; - wt = weights[cy * side + cx]; - r += data[srcOff] * wt; - g += data[srcOff + 1] * wt; - b += data[srcOff + 2] * wt; - if (!alphaFac) { - a += data[srcOff + 3] * wt; - } - } - } - dst[dstOff] = r; - dst[dstOff + 1] = g; - dst[dstOff + 2] = b; - if (!alphaFac) { - dst[dstOff + 3] = a; - } else { - dst[dstOff + 3] = data[dstOff + 3]; - } - } - } - options.imageData = output; - }, - getUniformLocations: function(gl, program) { - return { - uMatrix: gl.getUniformLocation(program, "uMatrix"), - uOpaque: gl.getUniformLocation(program, "uOpaque"), - uHalfSize: gl.getUniformLocation(program, "uHalfSize"), - uSize: gl.getUniformLocation(program, "uSize") - }; - }, - sendUniformData: function(gl, uniformLocations) { - gl.uniform1fv(uniformLocations.uMatrix, this.matrix); - }, - toObject: function() { - return extend(this.callSuper("toObject"), { - opaque: this.opaque, - matrix: this.matrix - }); - } - }); - fabric.Image.filters.Convolute.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.Grayscale = createClass(filters.BaseFilter, { - type: "Grayscale", - fragmentSource: { - average: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = texture2D(uTexture, vTexCoord);\n" + "float average = (color.r + color.b + color.g) / 3.0;\n" + "gl_FragColor = vec4(average, average, average, color.a);\n" + "}", - lightness: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform int uMode;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 col = texture2D(uTexture, vTexCoord);\n" + "float average = (max(max(col.r, col.g),col.b) + min(min(col.r, col.g),col.b)) / 2.0;\n" + "gl_FragColor = vec4(average, average, average, col.a);\n" + "}", - luminosity: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform int uMode;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 col = texture2D(uTexture, vTexCoord);\n" + "float average = 0.21 * col.r + 0.72 * col.g + 0.07 * col.b;\n" + "gl_FragColor = vec4(average, average, average, col.a);\n" + "}" - }, - mode: "average", - mainParameter: "mode", - applyTo2d: function(options) { - var imageData = options.imageData, data = imageData.data, i, len = data.length, value, mode = this.mode; - for (i = 0; i < len; i += 4) { - if (mode === "average") { - value = (data[i] + data[i + 1] + data[i + 2]) / 3; - } else if (mode === "lightness") { - value = (Math.min(data[i], data[i + 1], data[i + 2]) + Math.max(data[i], data[i + 1], data[i + 2])) / 2; - } else if (mode === "luminosity") { - value = .21 * data[i] + .72 * data[i + 1] + .07 * data[i + 2]; - } - data[i] = value; - data[i + 1] = value; - data[i + 2] = value; - } - }, - retrieveShader: function(options) { - var cacheKey = this.type + "_" + this.mode; - if (!options.programCache.hasOwnProperty(cacheKey)) { - var shaderSource = this.fragmentSource[this.mode]; - options.programCache[cacheKey] = this.createProgram(options.context, shaderSource); - } - return options.programCache[cacheKey]; - }, - getUniformLocations: function(gl, program) { - return { - uMode: gl.getUniformLocation(program, "uMode") - }; - }, - sendUniformData: function(gl, uniformLocations) { - var mode = 1; - gl.uniform1i(uniformLocations.uMode, mode); - } - }); - fabric.Image.filters.Grayscale.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.Invert = createClass(filters.BaseFilter, { - type: "Invert", - fragmentSource: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform int uInvert;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = texture2D(uTexture, vTexCoord);\n" + "if (uInvert == 1) {\n" + "gl_FragColor = vec4(1.0 - color.r,1.0 -color.g,1.0 -color.b,color.a);\n" + "} else {\n" + "gl_FragColor = color;\n" + "}\n" + "}", - invert: true, - mainParameter: "invert", - applyTo2d: function(options) { - if (!this.invert) { - return; - } - var imageData = options.imageData, data = imageData.data, i, len = data.length; - for (i = 0; i < len; i += 4) { - data[i] = 255 - data[i]; - data[i + 1] = 255 - data[i + 1]; - data[i + 2] = 255 - data[i + 2]; - } - }, - getUniformLocations: function(gl, program) { - return { - uInvert: gl.getUniformLocation(program, "uInvert") - }; - }, - sendUniformData: function(gl, uniformLocations) { - gl.uniform1i(uniformLocations.uInvert, this.invert); - } - }); - fabric.Image.filters.Invert.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.Noise = createClass(filters.BaseFilter, { - type: "Noise", - fragmentSource: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uStepH;\n" + "uniform float uNoise;\n" + "uniform float uSeed;\n" + "varying vec2 vTexCoord;\n" + "float rand(vec2 co, float seed, float vScale) {\n" + "return fract(sin(dot(co.xy * vScale ,vec2(12.9898 , 78.233))) * 43758.5453 * (seed + 0.01) / 2.0);\n" + "}\n" + "void main() {\n" + "vec4 color = texture2D(uTexture, vTexCoord);\n" + "color.rgb += (0.5 - rand(vTexCoord, uSeed, 0.1 / uStepH)) * uNoise;\n" + "gl_FragColor = color;\n" + "}", - mainParameter: "noise", - noise: 0, - applyTo2d: function(options) { - if (this.noise === 0) { - return; - } - var imageData = options.imageData, data = imageData.data, i, len = data.length, noise = this.noise, rand; - for (i = 0, len = data.length; i < len; i += 4) { - rand = (.5 - Math.random()) * noise; - data[i] += rand; - data[i + 1] += rand; - data[i + 2] += rand; - } - }, - getUniformLocations: function(gl, program) { - return { - uNoise: gl.getUniformLocation(program, "uNoise"), - uSeed: gl.getUniformLocation(program, "uSeed") - }; - }, - sendUniformData: function(gl, uniformLocations) { - gl.uniform1f(uniformLocations.uNoise, this.noise / 255); - gl.uniform1f(uniformLocations.uSeed, Math.random()); - }, - toObject: function() { - return extend(this.callSuper("toObject"), { - noise: this.noise - }); - } - }); - fabric.Image.filters.Noise.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.Pixelate = createClass(filters.BaseFilter, { - type: "Pixelate", - blocksize: 4, - mainParameter: "blocksize", - fragmentSource: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uBlocksize;\n" + "uniform float uStepW;\n" + "uniform float uStepH;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "float blockW = uBlocksize * uStepW;\n" + "float blockH = uBlocksize * uStepW;\n" + "int posX = int(vTexCoord.x / blockW);\n" + "int posY = int(vTexCoord.y / blockH);\n" + "float fposX = float(posX);\n" + "float fposY = float(posY);\n" + "vec2 squareCoords = vec2(fposX * blockW, fposY * blockH);\n" + "vec4 color = texture2D(uTexture, squareCoords);\n" + "gl_FragColor = color;\n" + "}", - applyTo2d: function(options) { - if (this.blocksize === 1) { - return; - } - var imageData = options.imageData, data = imageData.data, iLen = imageData.height, jLen = imageData.width, index, i, j, r, g, b, a, _i, _j, _iLen, _jLen; - for (i = 0; i < iLen; i += this.blocksize) { - for (j = 0; j < jLen; j += this.blocksize) { - index = i * 4 * jLen + j * 4; - r = data[index]; - g = data[index + 1]; - b = data[index + 2]; - a = data[index + 3]; - _iLen = Math.min(i + this.blocksize, iLen); - _jLen = Math.min(j + this.blocksize, jLen); - for (_i = i; _i < _iLen; _i++) { - for (_j = j; _j < _jLen; _j++) { - index = _i * 4 * jLen + _j * 4; - data[index] = r; - data[index + 1] = g; - data[index + 2] = b; - data[index + 3] = a; - } - } - } - } - }, - isNeutralState: function() { - return this.blocksize === 1; - }, - getUniformLocations: function(gl, program) { - return { - uBlocksize: gl.getUniformLocation(program, "uBlocksize"), - uStepW: gl.getUniformLocation(program, "uStepW"), - uStepH: gl.getUniformLocation(program, "uStepH") - }; - }, - sendUniformData: function(gl, uniformLocations) { - gl.uniform1f(uniformLocations.uBlocksize, this.blocksize); - } - }); - fabric.Image.filters.Pixelate.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.RemoveColor = createClass(filters.BaseFilter, { - type: "RemoveColor", - color: "#FFFFFF", - fragmentSource: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec4 uLow;\n" + "uniform vec4 uHigh;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "gl_FragColor = texture2D(uTexture, vTexCoord);\n" + "if(all(greaterThan(gl_FragColor.rgb,uLow.rgb)) && all(greaterThan(uHigh.rgb,gl_FragColor.rgb))) {\n" + "gl_FragColor.a = 0.0;\n" + "}\n" + "}", - distance: .02, - useAlpha: false, - applyTo2d: function(options) { - var imageData = options.imageData, data = imageData.data, i, distance = this.distance * 255, r, g, b, source = new fabric.Color(this.color).getSource(), lowC = [ source[0] - distance, source[1] - distance, source[2] - distance ], highC = [ source[0] + distance, source[1] + distance, source[2] + distance ]; - for (i = 0; i < data.length; i += 4) { - r = data[i]; - g = data[i + 1]; - b = data[i + 2]; - if (r > lowC[0] && g > lowC[1] && b > lowC[2] && r < highC[0] && g < highC[1] && b < highC[2]) { - data[i + 3] = 0; - } - } - }, - getUniformLocations: function(gl, program) { - return { - uLow: gl.getUniformLocation(program, "uLow"), - uHigh: gl.getUniformLocation(program, "uHigh") - }; - }, - sendUniformData: function(gl, uniformLocations) { - var source = new fabric.Color(this.color).getSource(), distance = parseFloat(this.distance), lowC = [ 0 + source[0] / 255 - distance, 0 + source[1] / 255 - distance, 0 + source[2] / 255 - distance, 1 ], highC = [ source[0] / 255 + distance, source[1] / 255 + distance, source[2] / 255 + distance, 1 ]; - gl.uniform4fv(uniformLocations.uLow, lowC); - gl.uniform4fv(uniformLocations.uHigh, highC); - }, - toObject: function() { - return extend(this.callSuper("toObject"), { - color: this.color, - distance: this.distance - }); - } - }); - fabric.Image.filters.RemoveColor.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass; - var matrices = { - Brownie: [ .5997, .34553, -.27082, 0, .186, -.0377, .86095, .15059, 0, -.1449, .24113, -.07441, .44972, 0, -.02965, 0, 0, 0, 1, 0 ], - Vintage: [ .62793, .32021, -.03965, 0, .03784, .02578, .64411, .03259, 0, .02926, .0466, -.08512, .52416, 0, .02023, 0, 0, 0, 1, 0 ], - Kodachrome: [ 1.12855, -.39673, -.03992, 0, .24991, -.16404, 1.08352, -.05498, 0, .09698, -.16786, -.56034, 1.60148, 0, .13972, 0, 0, 0, 1, 0 ], - Technicolor: [ 1.91252, -.85453, -.09155, 0, .04624, -.30878, 1.76589, -.10601, 0, -.27589, -.2311, -.75018, 1.84759, 0, .12137, 0, 0, 0, 1, 0 ], - Polaroid: [ 1.438, -.062, -.062, 0, 0, -.122, 1.378, -.122, 0, 0, -.016, -.016, 1.483, 0, 0, 0, 0, 0, 1, 0 ], - Sepia: [ .393, .769, .189, 0, 0, .349, .686, .168, 0, 0, .272, .534, .131, 0, 0, 0, 0, 0, 1, 0 ], - BlackWhite: [ 1.5, 1.5, 1.5, 0, -1, 1.5, 1.5, 1.5, 0, -1, 1.5, 1.5, 1.5, 0, -1, 0, 0, 0, 1, 0 ] - }; - for (var key in matrices) { - filters[key] = createClass(filters.ColorMatrix, { - type: key, - matrix: matrices[key], - mainParameter: false, - colorsOnly: true - }); - fabric.Image.filters[key].fromObject = fabric.Image.filters.BaseFilter.fromObject; - } -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric, filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.BlendColor = createClass(filters.BaseFilter, { - type: "BlendColor", - color: "#F95C63", - mode: "multiply", - alpha: 1, - fragmentSource: { - multiply: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec4 uColor;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = texture2D(uTexture, vTexCoord);\n" + "color.rgb *= uColor.rgb;\n" + "gl_FragColor = color;\n" + "}", - screen: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec4 uColor;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = texture2D(uTexture, vTexCoord);\n" + "color.rgb = 1.0 - (1.0 - color.rgb) * (1.0 - uColor.rgb);\n" + "gl_FragColor = color;\n" + "}", - add: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec4 uColor;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "gl_FragColor = texture2D(uTexture, vTexCoord);\n" + "gl_FragColor.rgb += uColor.rgb;\n" + "}", - diff: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec4 uColor;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "gl_FragColor = texture2D(uTexture, vTexCoord);\n" + "gl_FragColor.rgb = abs(gl_FragColor.rgb - uColor.rgb);\n" + "}", - subtract: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec4 uColor;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "gl_FragColor = texture2D(uTexture, vTexCoord);\n" + "gl_FragColor.rgb -= uColor.rgb;\n" + "}", - lighten: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec4 uColor;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "gl_FragColor = texture2D(uTexture, vTexCoord);\n" + "gl_FragColor.rgb = max(gl_FragColor.rgb, uColor.rgb);\n" + "}", - darken: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec4 uColor;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "gl_FragColor = texture2D(uTexture, vTexCoord);\n" + "gl_FragColor.rgb = min(gl_FragColor.rgb, uColor.rgb);\n" + "}", - exclusion: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec4 uColor;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "gl_FragColor = texture2D(uTexture, vTexCoord);\n" + "gl_FragColor.rgb += uColor.rgb - 2.0 * (uColor.rgb * gl_FragColor.rgb);\n" + "}", - overlay: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec4 uColor;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "gl_FragColor = texture2D(uTexture, vTexCoord);\n" + "if (uColor.r < 0.5) {\n" + "gl_FragColor.r *= 2.0 * uColor.r;\n" + "} else {\n" + "gl_FragColor.r = 1.0 - 2.0 * (1.0 - gl_FragColor.r) * (1.0 - uColor.r);\n" + "}\n" + "if (uColor.g < 0.5) {\n" + "gl_FragColor.g *= 2.0 * uColor.g;\n" + "} else {\n" + "gl_FragColor.g = 1.0 - 2.0 * (1.0 - gl_FragColor.g) * (1.0 - uColor.g);\n" + "}\n" + "if (uColor.b < 0.5) {\n" + "gl_FragColor.b *= 2.0 * uColor.b;\n" + "} else {\n" + "gl_FragColor.b = 1.0 - 2.0 * (1.0 - gl_FragColor.b) * (1.0 - uColor.b);\n" + "}\n" + "}", - tint: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec4 uColor;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "gl_FragColor = texture2D(uTexture, vTexCoord);\n" + "gl_FragColor.rgb *= (1.0 - uColor.a);\n" + "gl_FragColor.rgb += uColor.rgb;\n" + "}" - }, - retrieveShader: function(options) { - var cacheKey = this.type + "_" + this.mode; - var shaderSource = this.fragmentSource[this.mode]; - if (!options.programCache.hasOwnProperty(cacheKey)) { - options.programCache[cacheKey] = this.createProgram(options.context, shaderSource); - } - return options.programCache[cacheKey]; - }, - applyTo2d: function(options) { - var imageData = options.imageData, data = imageData.data, iLen = data.length, tr, tg, tb, r, g, b, source, alpha1 = 1 - this.alpha; - source = new fabric.Color(this.color).getSource(); - tr = source[0] * this.alpha; - tg = source[1] * this.alpha; - tb = source[2] * this.alpha; - for (var i = 0; i < iLen; i += 4) { - r = data[i]; - g = data[i + 1]; - b = data[i + 2]; - switch (this.mode) { - case "multiply": - data[i] = r * tr / 255; - data[i + 1] = g * tg / 255; - data[i + 2] = b * tb / 255; - break; - - case "screen": - data[i] = 255 - (255 - r) * (255 - tr) / 255; - data[i + 1] = 255 - (255 - g) * (255 - tg) / 255; - data[i + 2] = 255 - (255 - b) * (255 - tb) / 255; - break; - - case "add": - data[i] = r + tr; - data[i + 1] = g + tg; - data[i + 2] = b + tb; - break; - - case "diff": - case "difference": - data[i] = Math.abs(r - tr); - data[i + 1] = Math.abs(g - tg); - data[i + 2] = Math.abs(b - tb); - break; - - case "subtract": - data[i] = r - tr; - data[i + 1] = g - tg; - data[i + 2] = b - tb; - break; - - case "darken": - data[i] = Math.min(r, tr); - data[i + 1] = Math.min(g, tg); - data[i + 2] = Math.min(b, tb); - break; - - case "lighten": - data[i] = Math.max(r, tr); - data[i + 1] = Math.max(g, tg); - data[i + 2] = Math.max(b, tb); - break; - - case "overlay": - data[i] = tr < 128 ? 2 * r * tr / 255 : 255 - 2 * (255 - r) * (255 - tr) / 255; - data[i + 1] = tg < 128 ? 2 * g * tg / 255 : 255 - 2 * (255 - g) * (255 - tg) / 255; - data[i + 2] = tb < 128 ? 2 * b * tb / 255 : 255 - 2 * (255 - b) * (255 - tb) / 255; - break; - - case "exclusion": - data[i] = tr + r - 2 * tr * r / 255; - data[i + 1] = tg + g - 2 * tg * g / 255; - data[i + 2] = tb + b - 2 * tb * b / 255; - break; - - case "tint": - data[i] = tr + r * alpha1; - data[i + 1] = tg + g * alpha1; - data[i + 2] = tb + b * alpha1; - } - } - }, - getUniformLocations: function(gl, program) { - return { - uColor: gl.getUniformLocation(program, "uColor") - }; - }, - sendUniformData: function(gl, uniformLocations) { - var source = new fabric.Color(this.color).getSource(); - source[0] = this.alpha * source[0] / 255; - source[1] = this.alpha * source[1] / 255; - source[2] = this.alpha * source[2] / 255; - source[3] = this.alpha; - gl.uniform4fv(uniformLocations.uColor, source); - }, - toObject: function() { - return { - type: this.type, - color: this.color, - mode: this.mode, - alpha: this.alpha - }; - } - }); - fabric.Image.filters.BlendColor.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric, filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.BlendImage = createClass(filters.BaseFilter, { - type: "BlendImage", - image: null, - mode: "multiply", - alpha: 1, - vertexSource: "attribute vec2 aPosition;\n" + "attribute vec2 aTexCoord;\n" + "varying vec2 vTexCoord;\n" + "varying vec2 vTexCoord2;\n" + "uniform mat3 uTransformMatrix;\n" + "void main() {\n" + "vTexCoord = aTexCoord;\n" + "vTexCoord2 = (uTransformMatrix * vec3(aTexCoord, 1.0)).xy;\n" + "gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\n" + "}", - fragmentSource: { - multiply: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform sampler2D uImage;\n" + "uniform vec4 uColor;\n" + "varying vec2 vTexCoord;\n" + "varying vec2 vTexCoord2;\n" + "void main() {\n" + "vec4 color = texture2D(uTexture, vTexCoord);\n" + "vec4 color2 = texture2D(uImage, vTexCoord2);\n" + "color.rgba *= color2.rgba;\n" + "gl_FragColor = color;\n" + "}", - mask: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform sampler2D uImage;\n" + "uniform vec4 uColor;\n" + "varying vec2 vTexCoord;\n" + "varying vec2 vTexCoord2;\n" + "void main() {\n" + "vec4 color = texture2D(uTexture, vTexCoord);\n" + "vec4 color2 = texture2D(uImage, vTexCoord2);\n" + "color.a = color2.a;\n" + "gl_FragColor = color;\n" + "}" - }, - retrieveShader: function(options) { - var cacheKey = this.type + "_" + this.mode; - var shaderSource = this.fragmentSource[this.mode]; - if (!options.programCache.hasOwnProperty(cacheKey)) { - options.programCache[cacheKey] = this.createProgram(options.context, shaderSource); - } - return options.programCache[cacheKey]; - }, - applyToWebGL: function(options) { - var gl = options.context, texture = this.createTexture(options.filterBackend, this.image); - this.bindAdditionalTexture(gl, texture, gl.TEXTURE1); - this.callSuper("applyToWebGL", options); - this.unbindAdditionalTexture(gl, gl.TEXTURE1); - }, - createTexture: function(backend, image) { - return backend.getCachedTexture(image.cacheKey, image._element); - }, - calculateMatrix: function() { - var image = this.image, width = image._element.width, height = image._element.height; - return [ 1 / image.scaleX, 0, 0, 0, 1 / image.scaleY, 0, -image.left / width, -image.top / height, 1 ]; - }, - applyTo2d: function(options) { - var imageData = options.imageData, resources = options.filterBackend.resources, data = imageData.data, iLen = data.length, width = options.imageData.width, height = options.imageData.height, tr, tg, tb, ta, r, g, b, a, canvas1, context, image = this.image, blendData; - if (!resources.blendImage) { - resources.blendImage = document.createElement("canvas"); - } - canvas1 = resources.blendImage; - if (canvas1.width !== width || canvas1.height !== height) { - canvas1.width = width; - canvas1.height = height; - } - context = canvas1.getContext("2d"); - context.setTransform(image.scaleX, 0, 0, image.scaleY, image.left, image.top); - context.drawImage(image._element, 0, 0, width, height); - blendData = context.getImageData(0, 0, width, height).data; - for (var i = 0; i < iLen; i += 4) { - r = data[i]; - g = data[i + 1]; - b = data[i + 2]; - a = data[i + 3]; - tr = blendData[i]; - tg = blendData[i + 1]; - tb = blendData[i + 2]; - ta = blendData[i + 3]; - switch (this.mode) { - case "multiply": - data[i] = r * tr / 255; - data[i + 1] = g * tg / 255; - data[i + 2] = b * tb / 255; - data[i + 3] = a * ta / 255; - break; - - case "mask": - data[i + 3] = ta; - break; - } - } - }, - getUniformLocations: function(gl, program) { - return { - uTransformMatrix: gl.getUniformLocation(program, "uTransformMatrix"), - uImage: gl.getUniformLocation(program, "uImage") - }; - }, - sendUniformData: function(gl, uniformLocations) { - var matrix = this.calculateMatrix(); - gl.uniform1i(uniformLocations.uImage, 1); - gl.uniformMatrix3fv(uniformLocations.uTransformMatrix, false, matrix); - }, - toObject: function() { - return { - type: this.type, - image: this.image && this.image.toObject(), - mode: this.mode, - alpha: this.alpha - }; - } - }); - fabric.Image.filters.BlendImage.fromObject = function(object, callback) { - fabric.Image.fromObject(object.image, function(image) { - var options = fabric.util.object.clone(object); - options.image = image; - callback(new fabric.Image.filters.BlendImage(options)); - }); - }; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), pow = Math.pow, floor = Math.floor, sqrt = Math.sqrt, abs = Math.abs, round = Math.round, sin = Math.sin, ceil = Math.ceil, filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.Resize = createClass(filters.BaseFilter, { - type: "Resize", - resizeType: "hermite", - scaleX: 0, - scaleY: 0, - lanczosLobes: 3, - getUniformLocations: function(gl, program) { - return { - uDelta: gl.getUniformLocation(program, "uDelta"), - uTaps: gl.getUniformLocation(program, "uTaps") - }; - }, - sendUniformData: function(gl, uniformLocations) { - gl.uniform2fv(uniformLocations.uDelta, this.horizontal ? [ 1 / this.width, 0 ] : [ 0, 1 / this.height ]); - gl.uniform1fv(uniformLocations.uTaps, this.taps); - }, - retrieveShader: function(options) { - var filterWindow = this.getFilterWindow(), cacheKey = this.type + "_" + filterWindow; - if (!options.programCache.hasOwnProperty(cacheKey)) { - var fragmentShader = this.generateShader(filterWindow); - options.programCache[cacheKey] = this.createProgram(options.context, fragmentShader); - } - return options.programCache[cacheKey]; - }, - getFilterWindow: function() { - var scale = this.tempScale; - return Math.ceil(this.lanczosLobes / scale); - }, - getTaps: function() { - var lobeFunction = this.lanczosCreate(this.lanczosLobes), scale = this.tempScale, filterWindow = this.getFilterWindow(), taps = new Array(filterWindow); - for (var i = 1; i <= filterWindow; i++) { - taps[i - 1] = lobeFunction(i * scale); - } - return taps; - }, - generateShader: function(filterWindow) { - var offsets = new Array(filterWindow), fragmentShader = this.fragmentSourceTOP, filterWindow; - for (var i = 1; i <= filterWindow; i++) { - offsets[i - 1] = i + ".0 * uDelta"; - } - fragmentShader += "uniform float uTaps[" + filterWindow + "];\n"; - fragmentShader += "void main() {\n"; - fragmentShader += " vec4 color = texture2D(uTexture, vTexCoord);\n"; - fragmentShader += " float sum = 1.0;\n"; - offsets.forEach(function(offset, i) { - fragmentShader += " color += texture2D(uTexture, vTexCoord + " + offset + ") * uTaps[" + i + "];\n"; - fragmentShader += " color += texture2D(uTexture, vTexCoord - " + offset + ") * uTaps[" + i + "];\n"; - fragmentShader += " sum += 2.0 * uTaps[" + i + "];\n"; - }); - fragmentShader += " gl_FragColor = color / sum;\n"; - fragmentShader += "}"; - return fragmentShader; - }, - fragmentSourceTOP: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec2 uDelta;\n" + "varying vec2 vTexCoord;\n", - applyTo: function(options) { - if (options.webgl) { - if (options.passes > 1 && this.isNeutralState(options)) { - return; - } - options.passes++; - this.width = options.sourceWidth; - this.horizontal = true; - this.dW = Math.round(this.width * this.scaleX); - this.dH = options.sourceHeight; - this.tempScale = this.dW / this.width; - this.taps = this.getTaps(); - options.destinationWidth = this.dW; - this._setupFrameBuffer(options); - this.applyToWebGL(options); - this._swapTextures(options); - options.sourceWidth = options.destinationWidth; - this.height = options.sourceHeight; - this.horizontal = false; - this.dH = Math.round(this.height * this.scaleY); - this.tempScale = this.dH / this.height; - this.taps = this.getTaps(); - options.destinationHeight = this.dH; - this._setupFrameBuffer(options); - this.applyToWebGL(options); - this._swapTextures(options); - options.sourceHeight = options.destinationHeight; - } else if (!this.isNeutralState(options)) { - this.applyTo2d(options); - } - }, - isNeutralState: function(options) { - var scaleX = options.scaleX || this.scaleX, scaleY = options.scaleY || this.scaleY; - return scaleX === 1 && scaleY === 1; - }, - lanczosCreate: function(lobes) { - return function(x) { - if (x >= lobes || x <= -lobes) { - return 0; - } - if (x < 1.1920929e-7 && x > -1.1920929e-7) { - return 1; - } - x *= Math.PI; - var xx = x / lobes; - return sin(x) / x * sin(xx) / xx; - }; - }, - applyTo2d: function(options) { - var imageData = options.imageData, scaleX = this.scaleX, scaleY = this.scaleY; - this.rcpScaleX = 1 / scaleX; - this.rcpScaleY = 1 / scaleY; - var oW = imageData.width, oH = imageData.height, dW = round(oW * scaleX), dH = round(oH * scaleY), newData; - if (this.resizeType === "sliceHack") { - newData = this.sliceByTwo(options, oW, oH, dW, dH); - } else if (this.resizeType === "hermite") { - newData = this.hermiteFastResize(options, oW, oH, dW, dH); - } else if (this.resizeType === "bilinear") { - newData = this.bilinearFiltering(options, oW, oH, dW, dH); - } else if (this.resizeType === "lanczos") { - newData = this.lanczosResize(options, oW, oH, dW, dH); - } - options.imageData = newData; - }, - sliceByTwo: function(options, oW, oH, dW, dH) { - var imageData = options.imageData, mult = .5, doneW = false, doneH = false, stepW = oW * mult, stepH = oH * mult, resources = fabric.filterBackend.resources, tmpCanvas, ctx, sX = 0, sY = 0, dX = oW, dY = 0; - if (!resources.sliceByTwo) { - resources.sliceByTwo = document.createElement("canvas"); - } - tmpCanvas = resources.sliceByTwo; - if (tmpCanvas.width < oW * 1.5 || tmpCanvas.height < oH) { - tmpCanvas.width = oW * 1.5; - tmpCanvas.height = oH; - } - ctx = tmpCanvas.getContext("2d"); - ctx.clearRect(0, 0, oW * 1.5, oH); - ctx.putImageData(imageData, 0, 0); - dW = floor(dW); - dH = floor(dH); - while (!doneW || !doneH) { - oW = stepW; - oH = stepH; - if (dW < floor(stepW * mult)) { - stepW = floor(stepW * mult); - } else { - stepW = dW; - doneW = true; - } - if (dH < floor(stepH * mult)) { - stepH = floor(stepH * mult); - } else { - stepH = dH; - doneH = true; - } - ctx.drawImage(tmpCanvas, sX, sY, oW, oH, dX, dY, stepW, stepH); - sX = dX; - sY = dY; - dY += stepH; - } - return ctx.getImageData(sX, sY, dW, dH); - }, - lanczosResize: function(options, oW, oH, dW, dH) { - function process(u) { - var v, i, weight, idx, a, red, green, blue, alpha, fX, fY; - center.x = (u + .5) * ratioX; - icenter.x = floor(center.x); - for (v = 0; v < dH; v++) { - center.y = (v + .5) * ratioY; - icenter.y = floor(center.y); - a = 0; - red = 0; - green = 0; - blue = 0; - alpha = 0; - for (i = icenter.x - range2X; i <= icenter.x + range2X; i++) { - if (i < 0 || i >= oW) { - continue; - } - fX = floor(1e3 * abs(i - center.x)); - if (!cacheLanc[fX]) { - cacheLanc[fX] = {}; - } - for (var j = icenter.y - range2Y; j <= icenter.y + range2Y; j++) { - if (j < 0 || j >= oH) { - continue; - } - fY = floor(1e3 * abs(j - center.y)); - if (!cacheLanc[fX][fY]) { - cacheLanc[fX][fY] = lanczos(sqrt(pow(fX * rcpRatioX, 2) + pow(fY * rcpRatioY, 2)) / 1e3); - } - weight = cacheLanc[fX][fY]; - if (weight > 0) { - idx = (j * oW + i) * 4; - a += weight; - red += weight * srcData[idx]; - green += weight * srcData[idx + 1]; - blue += weight * srcData[idx + 2]; - alpha += weight * srcData[idx + 3]; - } - } - } - idx = (v * dW + u) * 4; - destData[idx] = red / a; - destData[idx + 1] = green / a; - destData[idx + 2] = blue / a; - destData[idx + 3] = alpha / a; - } - if (++u < dW) { - return process(u); - } else { - return destImg; - } - } - var srcData = options.imageData.data, destImg = options.ctx.createImageData(dW, dH), destData = destImg.data, lanczos = this.lanczosCreate(this.lanczosLobes), ratioX = this.rcpScaleX, ratioY = this.rcpScaleY, rcpRatioX = 2 / this.rcpScaleX, rcpRatioY = 2 / this.rcpScaleY, range2X = ceil(ratioX * this.lanczosLobes / 2), range2Y = ceil(ratioY * this.lanczosLobes / 2), cacheLanc = {}, center = {}, icenter = {}; - return process(0); - }, - bilinearFiltering: function(options, oW, oH, dW, dH) { - var a, b, c, d, x, y, i, j, xDiff, yDiff, chnl, color, offset = 0, origPix, ratioX = this.rcpScaleX, ratioY = this.rcpScaleY, w4 = 4 * (oW - 1), img = options.imageData, pixels = img.data, destImage = options.ctx.createImageData(dW, dH), destPixels = destImage.data; - for (i = 0; i < dH; i++) { - for (j = 0; j < dW; j++) { - x = floor(ratioX * j); - y = floor(ratioY * i); - xDiff = ratioX * j - x; - yDiff = ratioY * i - y; - origPix = 4 * (y * oW + x); - for (chnl = 0; chnl < 4; chnl++) { - a = pixels[origPix + chnl]; - b = pixels[origPix + 4 + chnl]; - c = pixels[origPix + w4 + chnl]; - d = pixels[origPix + w4 + 4 + chnl]; - color = a * (1 - xDiff) * (1 - yDiff) + b * xDiff * (1 - yDiff) + c * yDiff * (1 - xDiff) + d * xDiff * yDiff; - destPixels[offset++] = color; - } - } - } - return destImage; - }, - hermiteFastResize: function(options, oW, oH, dW, dH) { - var ratioW = this.rcpScaleX, ratioH = this.rcpScaleY, ratioWHalf = ceil(ratioW / 2), ratioHHalf = ceil(ratioH / 2), img = options.imageData, data = img.data, img2 = options.ctx.createImageData(dW, dH), data2 = img2.data; - for (var j = 0; j < dH; j++) { - for (var i = 0; i < dW; i++) { - var x2 = (i + j * dW) * 4, weight = 0, weights = 0, weightsAlpha = 0, gxR = 0, gxG = 0, gxB = 0, gxA = 0, centerY = (j + .5) * ratioH; - for (var yy = floor(j * ratioH); yy < (j + 1) * ratioH; yy++) { - var dy = abs(centerY - (yy + .5)) / ratioHHalf, centerX = (i + .5) * ratioW, w0 = dy * dy; - for (var xx = floor(i * ratioW); xx < (i + 1) * ratioW; xx++) { - var dx = abs(centerX - (xx + .5)) / ratioWHalf, w = sqrt(w0 + dx * dx); - if (w > 1 && w < -1) { - continue; - } - weight = 2 * w * w * w - 3 * w * w + 1; - if (weight > 0) { - dx = 4 * (xx + yy * oW); - gxA += weight * data[dx + 3]; - weightsAlpha += weight; - if (data[dx + 3] < 255) { - weight = weight * data[dx + 3] / 250; - } - gxR += weight * data[dx]; - gxG += weight * data[dx + 1]; - gxB += weight * data[dx + 2]; - weights += weight; - } - } - } - data2[x2] = gxR / weights; - data2[x2 + 1] = gxG / weights; - data2[x2 + 2] = gxB / weights; - data2[x2 + 3] = gxA / weightsAlpha; - } - } - return img2; - }, - toObject: function() { - return { - type: this.type, - scaleX: this.scaleX, - scaleY: this.scaleY, - resizeType: this.resizeType, - lanczosLobes: this.lanczosLobes - }; - } - }); - fabric.Image.filters.Resize.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.Contrast = createClass(filters.BaseFilter, { - type: "Contrast", - fragmentSource: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uContrast;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = texture2D(uTexture, vTexCoord);\n" + "float contrastF = 1.015 * (uContrast + 1.0) / (1.0 * (1.015 - uContrast));\n" + "color.rgb = contrastF * (color.rgb - 0.5) + 0.5;\n" + "gl_FragColor = color;\n" + "}", - contrast: 0, - mainParameter: "contrast", - applyTo2d: function(options) { - if (this.contrast === 0) { - return; - } - var imageData = options.imageData, i, len, data = imageData.data, len = data.length, contrast = Math.floor(this.contrast * 255), contrastF = 259 * (contrast + 255) / (255 * (259 - contrast)); - for (i = 0; i < len; i += 4) { - data[i] = contrastF * (data[i] - 128) + 128; - data[i + 1] = contrastF * (data[i + 1] - 128) + 128; - data[i + 2] = contrastF * (data[i + 2] - 128) + 128; - } - }, - getUniformLocations: function(gl, program) { - return { - uContrast: gl.getUniformLocation(program, "uContrast") - }; - }, - sendUniformData: function(gl, uniformLocations) { - gl.uniform1f(uniformLocations.uContrast, this.contrast); - } - }); - fabric.Image.filters.Contrast.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.Saturation = createClass(filters.BaseFilter, { - type: "Saturation", - fragmentSource: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uSaturation;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = texture2D(uTexture, vTexCoord);\n" + "float rgMax = max(color.r, color.g);\n" + "float rgbMax = max(rgMax, color.b);\n" + "color.r += rgbMax != color.r ? (rgbMax - color.r) * uSaturation : 0.00;\n" + "color.g += rgbMax != color.g ? (rgbMax - color.g) * uSaturation : 0.00;\n" + "color.b += rgbMax != color.b ? (rgbMax - color.b) * uSaturation : 0.00;\n" + "gl_FragColor = color;\n" + "}", - saturation: 0, - mainParameter: "saturation", - applyTo2d: function(options) { - if (this.saturation === 0) { - return; - } - var imageData = options.imageData, data = imageData.data, len = data.length, adjust = -this.saturation, i, max; - for (i = 0; i < len; i += 4) { - max = Math.max(data[i], data[i + 1], data[i + 2]); - data[i] += max !== data[i] ? (max - data[i]) * adjust : 0; - data[i + 1] += max !== data[i + 1] ? (max - data[i + 1]) * adjust : 0; - data[i + 2] += max !== data[i + 2] ? (max - data[i + 2]) * adjust : 0; - } - }, - getUniformLocations: function(gl, program) { - return { - uSaturation: gl.getUniformLocation(program, "uSaturation") - }; - }, - sendUniformData: function(gl, uniformLocations) { - gl.uniform1f(uniformLocations.uSaturation, -this.saturation); - } - }); - fabric.Image.filters.Saturation.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.Blur = createClass(filters.BaseFilter, { - type: "Blur", - fragmentSource: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec2 uDelta;\n" + "varying vec2 vTexCoord;\n" + "const float nSamples = 15.0;\n" + "vec3 v3offset = vec3(12.9898, 78.233, 151.7182);\n" + "float random(vec3 scale) {\n" + "return fract(sin(dot(gl_FragCoord.xyz, scale)) * 43758.5453);\n" + "}\n" + "void main() {\n" + "vec4 color = vec4(0.0);\n" + "float total = 0.0;\n" + "float offset = random(v3offset);\n" + "for (float t = -nSamples; t <= nSamples; t++) {\n" + "float percent = (t + offset - 0.5) / nSamples;\n" + "float weight = 1.0 - abs(percent);\n" + "color += texture2D(uTexture, vTexCoord + uDelta * percent) * weight;\n" + "total += weight;\n" + "}\n" + "gl_FragColor = color / total;\n" + "}", - blur: 0, - mainParameter: "blur", - applyTo: function(options) { - if (options.webgl) { - this.aspectRatio = options.sourceWidth / options.sourceHeight; - options.passes++; - this._setupFrameBuffer(options); - this.horizontal = true; - this.applyToWebGL(options); - this._swapTextures(options); - this._setupFrameBuffer(options); - this.horizontal = false; - this.applyToWebGL(options); - this._swapTextures(options); - } else { - this.applyTo2d(options); - } - }, - applyTo2d: function(options) { - options.imageData = this.simpleBlur(options); - }, - simpleBlur: function(options) { - var resources = options.filterBackend.resources, canvas1, canvas2, width = options.imageData.width, height = options.imageData.height; - if (!resources.blurLayer1) { - resources.blurLayer1 = document.createElement("canvas"); - resources.blurLayer2 = document.createElement("canvas"); - } - canvas1 = resources.blurLayer1; - canvas2 = resources.blurLayer2; - if (canvas1.width !== width || canvas1.height !== height) { - canvas2.width = canvas1.width = width; - canvas2.height = canvas1.height = height; - } - var ctx1 = canvas1.getContext("2d"), ctx2 = canvas2.getContext("2d"), nSamples = 15, random, percent, j, i, blur = this.blur * .06 * .5; - ctx1.putImageData(options.imageData, 0, 0); - ctx2.clearRect(0, 0, width, height); - for (i = -nSamples; i <= nSamples; i++) { - random = (Math.random() - .5) / 4; - percent = i / nSamples; - j = blur * percent * width + random; - ctx2.globalAlpha = 1 - Math.abs(percent); - ctx2.drawImage(canvas1, j, random); - ctx1.drawImage(canvas2, 0, 0); - ctx2.globalAlpha = 1; - ctx2.clearRect(0, 0, canvas2.width, canvas2.height); - } - for (i = -nSamples; i <= nSamples; i++) { - random = (Math.random() - .5) / 4; - percent = i / nSamples; - j = blur * percent * height + random; - ctx2.globalAlpha = 1 - Math.abs(percent); - ctx2.drawImage(canvas1, random, j); - ctx1.drawImage(canvas2, 0, 0); - ctx2.globalAlpha = 1; - ctx2.clearRect(0, 0, canvas2.width, canvas2.height); - } - options.ctx.drawImage(canvas1, 0, 0); - var newImageData = options.ctx.getImageData(0, 0, canvas1.width, canvas1.height); - ctx1.globalAlpha = 1; - ctx1.clearRect(0, 0, canvas1.width, canvas1.height); - return newImageData; - }, - getUniformLocations: function(gl, program) { - return { - delta: gl.getUniformLocation(program, "uDelta") - }; - }, - sendUniformData: function(gl, uniformLocations) { - var delta = this.chooseRightDelta(); - gl.uniform2fv(uniformLocations.delta, delta); - }, - chooseRightDelta: function() { - var blurScale = 1, delta = [ 0, 0 ], blur; - if (this.horizontal) { - if (this.aspectRatio > 1) { - blurScale = 1 / this.aspectRatio; - } - } else { - if (this.aspectRatio < 1) { - blurScale = this.aspectRatio; - } - } - blur = blurScale * this.blur * .12; - if (this.horizontal) { - delta[0] = blur; - } else { - delta[1] = blur; - } - return delta; - } - }); - filters.Blur.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.Gamma = createClass(filters.BaseFilter, { - type: "Gamma", - fragmentSource: "precision highp float;\n" + "uniform sampler2D uTexture;\n" + "uniform vec3 uGamma;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + "vec4 color = texture2D(uTexture, vTexCoord);\n" + "vec3 correction = (1.0 / uGamma);\n" + "color.r = pow(color.r, correction.r);\n" + "color.g = pow(color.g, correction.g);\n" + "color.b = pow(color.b, correction.b);\n" + "gl_FragColor = color;\n" + "gl_FragColor.rgb *= color.a;\n" + "}", - gamma: [ 1, 1, 1 ], - mainParameter: "gamma", - applyTo2d: function(options) { - var imageData = options.imageData, data = imageData.data, gamma = this.gamma, len = data.length, rInv = 1 / gamma[0], gInv = 1 / gamma[1], bInv = 1 / gamma[2], i; - if (!this.rVals) { - this.rVals = new Uint8Array(256); - this.gVals = new Uint8Array(256); - this.bVals = new Uint8Array(256); - } - for (i = 0, len = 256; i < len; i++) { - this.rVals[i] = Math.pow(i / 255, rInv) * 255; - this.gVals[i] = Math.pow(i / 255, gInv) * 255; - this.bVals[i] = Math.pow(i / 255, bInv) * 255; - } - for (i = 0, len = data.length; i < len; i += 4) { - data[i] = this.rVals[data[i]]; - data[i + 1] = this.gVals[data[i + 1]]; - data[i + 2] = this.bVals[data[i + 2]]; - } - }, - getUniformLocations: function(gl, program) { - return { - uGamma: gl.getUniformLocation(program, "uGamma") - }; - }, - sendUniformData: function(gl, uniformLocations) { - gl.uniform3fv(uniformLocations.uGamma, this.gamma); - } - }); - fabric.Image.filters.Gamma.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.Composed = createClass(filters.BaseFilter, { - type: "Composed", - subFilters: [], - initialize: function(options) { - this.callSuper("initialize", options); - this.subFilters = this.subFilters.slice(0); - }, - applyTo: function(options) { - options.passes += this.subFilters.length - 1; - this.subFilters.forEach(function(filter) { - filter.applyTo(options); - }); - }, - toObject: function() { - return fabric.util.object.extend(this.callSuper("toObject"), { - subFilters: this.subFilters.map(function(filter) { - return filter.toObject(); - }) - }); - } - }); - fabric.Image.filters.Composed.fromObject = function(object, callback) { - var filters = object.subFilters || [], subFilters = filters.map(function(filter) { - return new fabric.Image.filters[filter.type](filter); - }), instance = new fabric.Image.filters.Composed({ - subFilters: subFilters - }); - callback && callback(instance); - return instance; - }; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass; - filters.HueRotation = createClass(filters.ColorMatrix, { - type: "HueRotation", - rotation: 0, - mainParameter: "rotation", - calculateMatrix: function() { - var rad = this.rotation * Math.PI, cos = Math.cos(rad), sin = Math.sin(rad), aThird = 1 / 3, aThirdSqtSin = Math.sqrt(aThird) * sin, OneMinusCos = 1 - cos; - this.matrix = [ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0 ]; - this.matrix[0] = cos + OneMinusCos / 3; - this.matrix[1] = aThird * OneMinusCos - aThirdSqtSin; - this.matrix[2] = aThird * OneMinusCos + aThirdSqtSin; - this.matrix[5] = aThird * OneMinusCos + aThirdSqtSin; - this.matrix[6] = cos + aThird * OneMinusCos; - this.matrix[7] = aThird * OneMinusCos - aThirdSqtSin; - this.matrix[10] = aThird * OneMinusCos - aThirdSqtSin; - this.matrix[11] = aThird * OneMinusCos + aThirdSqtSin; - this.matrix[12] = cos + aThird * OneMinusCos; - }, - applyTo: function(options) { - this.calculateMatrix(); - fabric.Image.filters.BaseFilter.prototype.applyTo.call(this, options); - } - }); - fabric.Image.filters.HueRotation.fromObject = fabric.Image.filters.BaseFilter.fromObject; -})(typeof exports !== "undefined" ? exports : this); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}), clone = fabric.util.object.clone, MIN_TEXT_WIDTH = 2, CACHE_FONT_SIZE = 200; - if (fabric.Text) { - fabric.warn("fabric.Text is already defined"); - return; - } - fabric.Text = fabric.util.createClass(fabric.Object, { - _dimensionAffectingProps: [ "fontSize", "fontWeight", "fontFamily", "fontStyle", "lineHeight", "text", "charSpacing", "textAlign", "styles" ], - _reNewline: /\r?\n/, - _reSpacesAndTabs: /[ \t\r]/g, - _reSpaceAndTab: /[ \t\r]/, - _reWords: /\S+/g, - type: "text", - fontSize: 40, - fontWeight: "normal", - fontFamily: "Times New Roman", - underline: false, - overline: false, - linethrough: false, - textAlign: "left", - fontStyle: "normal", - lineHeight: 1.16, - textBackgroundColor: "", - stateProperties: fabric.Object.prototype.stateProperties.concat("fontFamily", "fontWeight", "fontSize", "text", "underline", "overline", "linethrough", "textAlign", "fontStyle", "lineHeight", "textBackgroundColor", "charSpacing", "styles"), - cacheProperties: fabric.Object.prototype.cacheProperties.concat("fontFamily", "fontWeight", "fontSize", "text", "underline", "overline", "linethrough", "textAlign", "fontStyle", "lineHeight", "textBackgroundColor", "charSpacing", "styles"), - stroke: null, - shadow: null, - _fontSizeFraction: .222, - offsets: { - underline: .1, - linethrough: -.315, - overline: -.88 - }, - _fontSizeMult: 1.13, - charSpacing: 0, - styles: null, - _measuringContext: null, - _styleProperties: [ "stroke", "strokeWidth", "fill", "fontFamily", "fontSize", "fontWeight", "fontStyle", "underline", "overline", "linethrough", "textBackgroundColor" ], - __charBounds: [], - initialize: function(text, options) { - this.styles = options ? options.styles || {} : {}; - this.text = text; - this.__skipDimension = true; - this.callSuper("initialize", options); - this.__skipDimension = false; - this.initDimensions(); - this.setCoords(); - this.setupState({ - propertySet: "_dimensionAffectingProps" - }); - }, - getMeasuringContext: function() { - if (!fabric._measuringContext) { - fabric._measuringContext = this.canvas && this.canvas.contextCache || fabric.util.createCanvasElement().getContext("2d"); - } - return fabric._measuringContext; - }, - _splitText: function() { - var newLines = this._splitTextIntoLines(this.text); - this.textLines = newLines.lines; - this._textLines = newLines.graphemeLines; - this._unwrappedTextLines = newLines._unwrappedLines; - this._text = newLines.graphemeText; - return newLines; - }, - initDimensions: function() { - if (this.__skipDimension) { - return; - } - this._splitText(); - this._clearCache(); - this.width = this.calcTextWidth() || this.cursorWidth || MIN_TEXT_WIDTH; - if (this.textAlign.indexOf("justify") !== -1) { - this.enlargeSpaces(); - } - this.height = this.calcTextHeight(); - this.saveState({ - propertySet: "_dimensionAffectingProps" - }); - }, - enlargeSpaces: function() { - var diffSpace, currentLineWidth, numberOfSpaces, accumulatedSpace, line, charBound, spaces; - for (var i = 0, len = this._textLines.length; i < len; i++) { - if (this.textAlign !== "justify" && (i === len - 1 || this.isEndOfWrapping(i))) { - continue; - } - accumulatedSpace = 0; - line = this._textLines[i]; - currentLineWidth = this.getLineWidth(i); - if (currentLineWidth < this.width && (spaces = this.textLines[i].match(this._reSpacesAndTabs))) { - numberOfSpaces = spaces.length; - diffSpace = (this.width - currentLineWidth) / numberOfSpaces; - for (var j = 0, jlen = line.length; j <= jlen; j++) { - charBound = this.__charBounds[i][j]; - if (this._reSpaceAndTab.test(line[j])) { - charBound.width += diffSpace; - charBound.kernedWidth += diffSpace; - charBound.left += accumulatedSpace; - accumulatedSpace += diffSpace; - } else { - charBound.left += accumulatedSpace; - } - } - } - } - }, - isEndOfWrapping: function(lineIndex) { - return lineIndex === this._textLines.length - 1; - }, - toString: function() { - return "#'; - }, - _getCacheCanvasDimensions: function() { - var dims = this.callSuper("_getCacheCanvasDimensions"); - var fontSize = this.fontSize; - dims.width += fontSize * dims.zoomX; - dims.height += fontSize * dims.zoomY; - return dims; - }, - _render: function(ctx) { - this._setTextStyles(ctx); - this._renderTextLinesBackground(ctx); - this._renderTextDecoration(ctx, "underline"); - this._renderText(ctx); - this._renderTextDecoration(ctx, "overline"); - this._renderTextDecoration(ctx, "linethrough"); - }, - _renderText: function(ctx) { - if (this.paintFirst === "stroke") { - this._renderTextStroke(ctx); - this._renderTextFill(ctx); - } else { - this._renderTextFill(ctx); - this._renderTextStroke(ctx); - } - }, - _setTextStyles: function(ctx, charStyle, forMeasuring) { - ctx.textBaseline = "alphabetic"; - ctx.font = this._getFontDeclaration(charStyle, forMeasuring); - }, - calcTextWidth: function() { - var maxWidth = this.getLineWidth(0); - for (var i = 1, len = this._textLines.length; i < len; i++) { - var currentLineWidth = this.getLineWidth(i); - if (currentLineWidth > maxWidth) { - maxWidth = currentLineWidth; - } - } - return maxWidth; - }, - _renderTextLine: function(method, ctx, line, left, top, lineIndex) { - this._renderChars(method, ctx, line, left, top, lineIndex); - }, - _renderTextLinesBackground: function(ctx) { - if (!this.textBackgroundColor && !this.styleHas("textBackgroundColor")) { - return; - } - var lineTopOffset = 0, heightOfLine, lineLeftOffset, originalFill = ctx.fillStyle, line, lastColor, leftOffset = this._getLeftOffset(), topOffset = this._getTopOffset(), boxStart = 0, boxWidth = 0, charBox, currentColor; - for (var i = 0, len = this._textLines.length; i < len; i++) { - heightOfLine = this.getHeightOfLine(i); - if (!this.textBackgroundColor && !this.styleHas("textBackgroundColor", i)) { - lineTopOffset += heightOfLine; - continue; - } - line = this._textLines[i]; - lineLeftOffset = this._getLineLeftOffset(i); - boxWidth = 0; - boxStart = 0; - lastColor = this.getValueOfPropertyAt(i, 0, "textBackgroundColor"); - for (var j = 0, jlen = line.length; j < jlen; j++) { - charBox = this.__charBounds[i][j]; - currentColor = this.getValueOfPropertyAt(i, j, "textBackgroundColor"); - if (currentColor !== lastColor) { - ctx.fillStyle = lastColor; - lastColor && ctx.fillRect(leftOffset + lineLeftOffset + boxStart, topOffset + lineTopOffset, boxWidth, heightOfLine / this.lineHeight); - boxStart = charBox.left; - boxWidth = charBox.width; - lastColor = currentColor; - } else { - boxWidth += charBox.kernedWidth; - } - } - if (currentColor) { - ctx.fillStyle = currentColor; - ctx.fillRect(leftOffset + lineLeftOffset + boxStart, topOffset + lineTopOffset, boxWidth, heightOfLine / this.lineHeight); - } - lineTopOffset += heightOfLine; - } - ctx.fillStyle = originalFill; - this._removeShadow(ctx); - }, - getFontCache: function(decl) { - var fontFamily = decl.fontFamily.toLowerCase(); - if (!fabric.charWidthsCache[fontFamily]) { - fabric.charWidthsCache[fontFamily] = {}; - } - var cache = fabric.charWidthsCache[fontFamily], cacheProp = decl.fontStyle.toLowerCase() + "_" + (decl.fontWeight + "").toLowerCase(); - if (!cache[cacheProp]) { - cache[cacheProp] = {}; - } - return cache[cacheProp]; - }, - _applyCharStyles: function(method, ctx, lineIndex, charIndex, styleDeclaration) { - this._setFillStyles(ctx, styleDeclaration); - this._setStrokeStyles(ctx, styleDeclaration); - ctx.font = this._getFontDeclaration(styleDeclaration); - }, - _measureChar: function(_char, charStyle, previousChar, prevCharStyle) { - var fontCache = this.getFontCache(charStyle), fontDeclaration = this._getFontDeclaration(charStyle), previousFontDeclaration = this._getFontDeclaration(prevCharStyle), couple = previousChar + _char, stylesAreEqual = fontDeclaration === previousFontDeclaration, width, coupleWidth, previousWidth, fontMultiplier = charStyle.fontSize / CACHE_FONT_SIZE, kernedWidth; - if (previousChar && fontCache[previousChar]) { - previousWidth = fontCache[previousChar]; - } - if (fontCache[_char]) { - kernedWidth = width = fontCache[_char]; - } - if (stylesAreEqual && fontCache[couple]) { - coupleWidth = fontCache[couple]; - kernedWidth = coupleWidth - previousWidth; - } - if (!width || !previousWidth || !coupleWidth) { - var ctx = this.getMeasuringContext(); - this._setTextStyles(ctx, charStyle, true); - } - if (!width) { - kernedWidth = width = ctx.measureText(_char).width; - fontCache[_char] = width; - } - if (!previousWidth && stylesAreEqual && previousChar) { - previousWidth = ctx.measureText(previousChar).width; - fontCache[previousChar] = previousWidth; - } - if (stylesAreEqual && !coupleWidth) { - coupleWidth = ctx.measureText(couple).width; - fontCache[couple] = coupleWidth; - kernedWidth = coupleWidth - previousWidth; - if (kernedWidth > width) { - var diff = kernedWidth - width; - fontCache[_char] = kernedWidth; - fontCache[couple] += diff; - width = kernedWidth; - } - } - return { - width: width * fontMultiplier, - kernedWidth: kernedWidth * fontMultiplier - }; - }, - getHeightOfChar: function(l, c) { - return this.getValueOfPropertyAt(l, c, "fontSize"); - }, - measureLine: function(lineIndex) { - var lineInfo = this._measureLine(lineIndex); - if (this.charSpacing !== 0) { - lineInfo.width -= this._getWidthOfCharSpacing(); - } - if (lineInfo.width < 0) { - lineInfo.width = 0; - } - return lineInfo; - }, - _measureLine: function(lineIndex) { - var width = 0, i, grapheme, line = this._textLines[lineIndex], prevGrapheme, graphemeInfo, numOfSpaces = 0, lineBounds = new Array(line.length); - this.__charBounds[lineIndex] = lineBounds; - for (i = 0; i < line.length; i++) { - grapheme = line[i]; - graphemeInfo = this._getGraphemeBox(grapheme, lineIndex, i, prevGrapheme); - lineBounds[i] = graphemeInfo; - width += graphemeInfo.kernedWidth; - prevGrapheme = grapheme; - } - lineBounds[i] = { - left: graphemeInfo ? graphemeInfo.left + graphemeInfo.width : 0, - width: 0, - kernedWidth: 0, - height: this.fontSize - }; - return { - width: width, - numOfSpaces: numOfSpaces - }; - }, - _getGraphemeBox: function(grapheme, lineIndex, charIndex, previousGrapheme, skipLeft) { - var charStyle = this.getCompleteStyleDeclaration(lineIndex, charIndex), prevCharStyle = previousGrapheme ? this.getCompleteStyleDeclaration(lineIndex, charIndex - 1) : {}, info = this._measureChar(grapheme, charStyle, previousGrapheme, prevCharStyle), kernedWidth = info.kernedWidth, width = info.width; - if (this.charSpacing !== 0) { - width += this._getWidthOfCharSpacing(); - kernedWidth += this._getWidthOfCharSpacing(); - } - var box = { - width: width, - left: 0, - height: charStyle.fontSize, - kernedWidth: kernedWidth - }; - if (charIndex > 0 && !skipLeft) { - var previousBox = this.__charBounds[lineIndex][charIndex - 1]; - box.left = previousBox.left + previousBox.width + info.kernedWidth - info.width; - } - return box; - }, - getHeightOfLine: function(lineIndex) { - if (this.__lineHeights[lineIndex]) { - return this.__lineHeights[lineIndex]; - } - var line = this._textLines[lineIndex], maxHeight = this.getHeightOfChar(lineIndex, 0); - for (var i = 1, len = line.length; i < len; i++) { - var currentCharHeight = this.getHeightOfChar(lineIndex, i); - if (currentCharHeight > maxHeight) { - maxHeight = currentCharHeight; - } - } - this.__lineHeights[lineIndex] = maxHeight * this.lineHeight * this._fontSizeMult; - return this.__lineHeights[lineIndex]; - }, - calcTextHeight: function() { - var lineHeight, height = 0; - for (var i = 0, len = this._textLines.length; i < len; i++) { - lineHeight = this.getHeightOfLine(i); - height += i === len - 1 ? lineHeight / this.lineHeight : lineHeight; - } - return height; - }, - _getLeftOffset: function() { - return -this.width / 2; - }, - _getTopOffset: function() { - return -this.height / 2; - }, - _renderTextCommon: function(ctx, method) { - ctx.save(); - var lineHeights = 0, left = this._getLeftOffset(), top = this._getTopOffset(), offsets = this._applyPatternGradientTransform(ctx, method === "fillText" ? this.fill : this.stroke); - for (var i = 0, len = this._textLines.length; i < len; i++) { - var heightOfLine = this.getHeightOfLine(i), maxHeight = heightOfLine / this.lineHeight, leftOffset = this._getLineLeftOffset(i); - this._renderTextLine(method, ctx, this._textLines[i], left + leftOffset - offsets.offsetX, top + lineHeights + maxHeight - offsets.offsetY, i); - lineHeights += heightOfLine; - } - ctx.restore(); - }, - _renderTextFill: function(ctx) { - if (!this.fill && !this.styleHas("fill")) { - return; - } - this._renderTextCommon(ctx, "fillText"); - }, - _renderTextStroke: function(ctx) { - if ((!this.stroke || this.strokeWidth === 0) && this.isEmptyStyles()) { - return; - } - if (this.shadow && !this.shadow.affectStroke) { - this._removeShadow(ctx); - } - ctx.save(); - this._setLineDash(ctx, this.strokeDashArray); - ctx.beginPath(); - this._renderTextCommon(ctx, "strokeText"); - ctx.closePath(); - ctx.restore(); - }, - _renderChars: function(method, ctx, line, left, top, lineIndex) { - var lineHeight = this.getHeightOfLine(lineIndex), isJustify = this.textAlign.indexOf("justify") !== -1, actualStyle, nextStyle, charsToRender = "", charBox, boxWidth = 0, timeToRender, shortCut = !isJustify && this.charSpacing === 0 && this.isEmptyStyles(lineIndex); - ctx.save(); - top -= lineHeight * this._fontSizeFraction / this.lineHeight; - if (shortCut) { - this._renderChar(method, ctx, lineIndex, 0, this.textLines[lineIndex], left, top, lineHeight); - ctx.restore(); - return; - } - for (var i = 0, len = line.length - 1; i <= len; i++) { - timeToRender = i === len || this.charSpacing; - charsToRender += line[i]; - charBox = this.__charBounds[lineIndex][i]; - if (boxWidth === 0) { - left += charBox.kernedWidth - charBox.width; - boxWidth += charBox.width; - } else { - boxWidth += charBox.kernedWidth; - } - if (isJustify && !timeToRender) { - if (this._reSpaceAndTab.test(line[i])) { - timeToRender = true; - } - } - if (!timeToRender) { - actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i); - nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1); - timeToRender = this._hasStyleChanged(actualStyle, nextStyle); - } - if (timeToRender) { - this._renderChar(method, ctx, lineIndex, i, charsToRender, left, top, lineHeight); - charsToRender = ""; - actualStyle = nextStyle; - left += boxWidth; - boxWidth = 0; - } - } - ctx.restore(); - }, - _renderChar: function(method, ctx, lineIndex, charIndex, _char, left, top) { - var decl = this._getStyleDeclaration(lineIndex, charIndex), fullDecl = this.getCompleteStyleDeclaration(lineIndex, charIndex), shouldFill = method === "fillText" && fullDecl.fill, shouldStroke = method === "strokeText" && fullDecl.stroke && fullDecl.strokeWidth; - if (!shouldStroke && !shouldFill) { - return; - } - decl && ctx.save(); - this._applyCharStyles(method, ctx, lineIndex, charIndex, fullDecl); - if (decl && decl.textBackgroundColor) { - this._removeShadow(ctx); - } - shouldFill && ctx.fillText(_char, left, top); - shouldStroke && ctx.strokeText(_char, left, top); - decl && ctx.restore(); - }, - _hasStyleChanged: function(prevStyle, thisStyle) { - return prevStyle.fill !== thisStyle.fill || prevStyle.stroke !== thisStyle.stroke || prevStyle.strokeWidth !== thisStyle.strokeWidth || prevStyle.fontSize !== thisStyle.fontSize || prevStyle.fontFamily !== thisStyle.fontFamily || prevStyle.fontWeight !== thisStyle.fontWeight || prevStyle.fontStyle !== thisStyle.fontStyle; - }, - _hasStyleChangedForSvg: function(prevStyle, thisStyle) { - return this._hasStyleChanged(prevStyle, thisStyle) || prevStyle.overline !== thisStyle.overline || prevStyle.underline !== thisStyle.underline || prevStyle.linethrough !== thisStyle.linethrough; - }, - _getLineLeftOffset: function(lineIndex) { - var lineWidth = this.getLineWidth(lineIndex); - if (this.textAlign === "center") { - return (this.width - lineWidth) / 2; - } - if (this.textAlign === "right") { - return this.width - lineWidth; - } - if (this.textAlign === "justify-center" && this.isEndOfWrapping(lineIndex)) { - return (this.width - lineWidth) / 2; - } - if (this.textAlign === "justify-right" && this.isEndOfWrapping(lineIndex)) { - return this.width - lineWidth; - } - return 0; - }, - _clearCache: function() { - this.__lineWidths = []; - this.__lineHeights = []; - this.__charBounds = []; - }, - _shouldClearDimensionCache: function() { - var shouldClear = this._forceClearCache; - shouldClear || (shouldClear = this.hasStateChanged("_dimensionAffectingProps")); - if (shouldClear) { - this.dirty = true; - this._forceClearCache = false; - } - return shouldClear; - }, - getLineWidth: function(lineIndex) { - if (this.__lineWidths[lineIndex]) { - return this.__lineWidths[lineIndex]; - } - var width, line = this._textLines[lineIndex], lineInfo; - if (line === "") { - width = 0; - } else { - lineInfo = this.measureLine(lineIndex); - width = lineInfo.width; - } - this.__lineWidths[lineIndex] = width; - return width; - }, - _getWidthOfCharSpacing: function() { - if (this.charSpacing !== 0) { - return this.fontSize * this.charSpacing / 1e3; - } - return 0; - }, - getValueOfPropertyAt: function(lineIndex, charIndex, property) { - var charStyle = this._getStyleDeclaration(lineIndex, charIndex), styleDecoration = charStyle && typeof charStyle[property] !== "undefined"; - return styleDecoration ? charStyle[property] : this[property]; - }, - _renderTextDecoration: function(ctx, type) { - if (!this[type] && !this.styleHas(type)) { - return; - } - var heightOfLine, lineLeftOffset, line, lastDecoration, leftOffset = this._getLeftOffset(), topOffset = this._getTopOffset(), boxStart, boxWidth, charBox, currentDecoration, maxHeight, currentFill, lastFill; - for (var i = 0, len = this._textLines.length; i < len; i++) { - heightOfLine = this.getHeightOfLine(i); - if (!this[type] && !this.styleHas(type, i)) { - topOffset += heightOfLine; - continue; - } - line = this._textLines[i]; - maxHeight = heightOfLine / this.lineHeight; - lineLeftOffset = this._getLineLeftOffset(i); - boxStart = 0; - boxWidth = 0; - lastDecoration = this.getValueOfPropertyAt(i, 0, type); - lastFill = this.getValueOfPropertyAt(i, 0, "fill"); - for (var j = 0, jlen = line.length; j < jlen; j++) { - charBox = this.__charBounds[i][j]; - currentDecoration = this.getValueOfPropertyAt(i, j, type); - currentFill = this.getValueOfPropertyAt(i, j, "fill"); - if ((currentDecoration !== lastDecoration || currentFill !== lastFill) && boxWidth > 0) { - ctx.fillStyle = lastFill; - lastDecoration && lastFill && ctx.fillRect(leftOffset + lineLeftOffset + boxStart, topOffset + maxHeight * (1 - this._fontSizeFraction) + this.offsets[type] * this.fontSize, boxWidth, this.fontSize / 15); - boxStart = charBox.left; - boxWidth = charBox.width; - lastDecoration = currentDecoration; - lastFill = currentFill; - } else { - boxWidth += charBox.kernedWidth; - } - } - ctx.fillStyle = currentFill; - currentDecoration && currentFill && ctx.fillRect(leftOffset + lineLeftOffset + boxStart, topOffset + maxHeight * (1 - this._fontSizeFraction) + this.offsets[type] * this.fontSize, boxWidth, this.fontSize / 15); - topOffset += heightOfLine; - } - this._removeShadow(ctx); - }, - _getFontDeclaration: function(styleObject, forMeasuring) { - var style = styleObject || this; - return [ fabric.isLikelyNode ? style.fontWeight : style.fontStyle, fabric.isLikelyNode ? style.fontStyle : style.fontWeight, forMeasuring ? CACHE_FONT_SIZE + "px" : style.fontSize + "px", fabric.isLikelyNode ? '"' + style.fontFamily + '"' : style.fontFamily ].join(" "); - }, - render: function(ctx) { - if (!this.visible) { - return; - } - if (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) { - return; - } - if (this._shouldClearDimensionCache()) { - this.initDimensions(); - } - this.callSuper("render", ctx); - }, - _splitTextIntoLines: function(text) { - var lines = text.split(this._reNewline), newLines = new Array(lines.length), newLine = [ "\n" ], newText = []; - for (var i = 0; i < lines.length; i++) { - newLines[i] = fabric.util.string.graphemeSplit(lines[i]); - newText = newText.concat(newLines[i], newLine); - } - newText.pop(); - return { - _unwrappedLines: newLines, - lines: lines, - graphemeText: newText, - graphemeLines: newLines - }; - }, - toObject: function(propertiesToInclude) { - var additionalProperties = [ "text", "fontSize", "fontWeight", "fontFamily", "fontStyle", "lineHeight", "underline", "overline", "linethrough", "textAlign", "textBackgroundColor", "charSpacing" ].concat(propertiesToInclude); - var obj = this.callSuper("toObject", additionalProperties); - obj.styles = clone(this.styles, true); - return obj; - }, - set: function(key, value) { - this.callSuper("set", key, value); - var needsDims = false; - if (typeof key === "object") { - for (var _key in key) { - needsDims = needsDims || this._dimensionAffectingProps.indexOf(_key) !== -1; - } - } else { - needsDims = this._dimensionAffectingProps.indexOf(key) !== -1; - } - if (needsDims) { - this.initDimensions(); - this.setCoords(); - } - return this; - }, - complexity: function() { - return 1; - } - }); - fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat("x y dx dy font-family font-style font-weight font-size text-decoration text-anchor".split(" ")); - fabric.Text.DEFAULT_SVG_FONT_SIZE = 16; - fabric.Text.fromElement = function(element, callback, options) { - if (!element) { - return callback(null); - } - var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES), parsedAnchor = parsedAttributes.textAnchor || "left"; - options = fabric.util.object.extend(options ? clone(options) : {}, parsedAttributes); - options.top = options.top || 0; - options.left = options.left || 0; - if (parsedAttributes.textDecoration) { - var textDecoration = parsedAttributes.textDecoration; - if (textDecoration.indexOf("underline") !== -1) { - options.underline = true; - } - if (textDecoration.indexOf("overline") !== -1) { - options.overline = true; - } - if (textDecoration.indexOf("line-through") !== -1) { - options.linethrough = true; - } - delete options.textDecoration; - } - if ("dx" in parsedAttributes) { - options.left += parsedAttributes.dx; - } - if ("dy" in parsedAttributes) { - options.top += parsedAttributes.dy; - } - if (!("fontSize" in options)) { - options.fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE; - } - var textContent = ""; - if (!("textContent" in element)) { - if ("firstChild" in element && element.firstChild !== null) { - if ("data" in element.firstChild && element.firstChild.data !== null) { - textContent = element.firstChild.data; - } - } - } else { - textContent = element.textContent; - } - textContent = textContent.replace(/^\s+|\s+$|\n+/g, "").replace(/\s+/g, " "); - var text = new fabric.Text(textContent, options), textHeightScaleFactor = text.getScaledHeight() / text.height, lineHeightDiff = (text.height + text.strokeWidth) * text.lineHeight - text.height, scaledDiff = lineHeightDiff * textHeightScaleFactor, textHeight = text.getScaledHeight() + scaledDiff, offX = 0; - if (parsedAnchor === "center") { - offX = text.getScaledWidth() / 2; - } - if (parsedAnchor === "right") { - offX = text.getScaledWidth(); - } - text.set({ - left: text.left - offX, - top: text.top - (textHeight - text.fontSize * (.18 + text._fontSizeFraction)) / text.lineHeight - }); - callback(text); - }; - fabric.Text.fromObject = function(object, callback) { - return fabric.Object._fromObject("Text", object, callback, "text"); - }; - fabric.util.createAccessors && fabric.util.createAccessors(fabric.Text); -})(typeof exports !== "undefined" ? exports : this); - -(function() { - fabric.util.object.extend(fabric.Text.prototype, { - isEmptyStyles: function(lineIndex) { - if (!this.styles) { - return true; - } - if (typeof lineIndex !== "undefined" && !this.styles[lineIndex]) { - return true; - } - var obj = typeof lineIndex === "undefined" ? this.styles : { - line: this.styles[lineIndex] - }; - for (var p1 in obj) { - for (var p2 in obj[p1]) { - for (var p3 in obj[p1][p2]) { - return false; - } - } - } - return true; - }, - styleHas: function(property, lineIndex) { - if (!this.styles || !property || property === "") { - return false; - } - if (typeof lineIndex !== "undefined" && !this.styles[lineIndex]) { - return false; - } - var obj = typeof lineIndex === "undefined" ? this.styles : { - line: this.styles[lineIndex] - }; - for (var p1 in obj) { - for (var p2 in obj[p1]) { - if (typeof obj[p1][p2][property] !== "undefined") { - return true; - } - } - } - return false; - }, - cleanStyle: function(property) { - if (!this.styles || !property || property === "") { - return false; - } - var obj = this.styles, stylesCount = 0, letterCount, foundStyle = false, style, canBeSwapped = true, graphemeCount = 0; - for (var p1 in obj) { - letterCount = 0; - for (var p2 in obj[p1]) { - stylesCount++; - if (!foundStyle) { - style = obj[p1][p2][property]; - foundStyle = true; - } else if (obj[p1][p2][property] !== style) { - canBeSwapped = false; - } - if (obj[p1][p2][property] === this[property]) { - delete obj[p1][p2][property]; - } - if (Object.keys(obj[p1][p2]).length !== 0) { - letterCount++; - } else { - delete obj[p1][p2]; - } - } - if (letterCount === 0) { - delete obj[p1]; - } - } - for (var i = 0; i < this._textLines.length; i++) { - graphemeCount += this._textLines[i].length; - } - if (canBeSwapped && stylesCount === graphemeCount) { - this[property] = style; - this.removeStyle(property); - } - }, - removeStyle: function(property) { - if (!this.styles || !property || property === "") { - return; - } - var obj = this.styles, line, lineNum, charNum; - for (lineNum in obj) { - line = obj[lineNum]; - for (charNum in line) { - delete line[charNum][property]; - if (Object.keys(line[charNum]).length === 0) { - delete line[charNum]; - } - } - if (Object.keys(line).length === 0) { - delete obj[lineNum]; - } - } - }, - _extendStyles: function(index, styles) { - var loc = this.get2DCursorLocation(index); - if (!this._getLineStyle(loc.lineIndex)) { - this._setLineStyle(loc.lineIndex, {}); - } - if (!this._getStyleDeclaration(loc.lineIndex, loc.charIndex)) { - this._setStyleDeclaration(loc.lineIndex, loc.charIndex, {}); - } - fabric.util.object.extend(this._getStyleDeclaration(loc.lineIndex, loc.charIndex), styles); - }, - get2DCursorLocation: function(selectionStart, skipWrapping) { - if (typeof selectionStart === "undefined") { - selectionStart = this.selectionStart; - } - var lines = skipWrapping ? this._unwrappedTextLines : this._textLines; - var len = lines.length; - for (var i = 0; i < len; i++) { - if (selectionStart <= lines[i].length) { - return { - lineIndex: i, - charIndex: selectionStart - }; - } - selectionStart -= lines[i].length + 1; - } - return { - lineIndex: i - 1, - charIndex: lines[i - 1].length < selectionStart ? lines[i - 1].length : selectionStart - }; - }, - getSelectionStyles: function(startIndex, endIndex, complete) { - if (typeof startIndex === "undefined") { - startIndex = this.selectionStart || 0; - } - if (typeof endIndex === "undefined") { - endIndex = this.selectionEnd || startIndex; - } - var styles = []; - for (var i = startIndex; i < endIndex; i++) { - styles.push(this.getStyleAtPosition(i, complete)); - } - return styles; - }, - getStyleAtPosition: function(position, complete) { - var loc = this.get2DCursorLocation(position), style = complete ? this.getCompleteStyleDeclaration(loc.lineIndex, loc.charIndex) : this._getStyleDeclaration(loc.lineIndex, loc.charIndex); - return style || {}; - }, - setSelectionStyles: function(styles, startIndex, endIndex) { - if (typeof startIndex === "undefined") { - startIndex = this.selectionStart || 0; - } - if (typeof endIndex === "undefined") { - endIndex = this.selectionEnd || startIndex; - } - for (var i = startIndex; i < endIndex; i++) { - this._extendStyles(i, styles); - } - this._forceClearCache = true; - return this; - }, - _getStyleDeclaration: function(lineIndex, charIndex) { - var lineStyle = this.styles && this.styles[lineIndex]; - if (!lineStyle) { - return null; - } - return lineStyle[charIndex]; - }, - getCompleteStyleDeclaration: function(lineIndex, charIndex) { - var style = this._getStyleDeclaration(lineIndex, charIndex) || {}, styleObject = {}, prop; - for (var i = 0; i < this._styleProperties.length; i++) { - prop = this._styleProperties[i]; - styleObject[prop] = typeof style[prop] === "undefined" ? this[prop] : style[prop]; - } - return styleObject; - }, - _setStyleDeclaration: function(lineIndex, charIndex, style) { - this.styles[lineIndex][charIndex] = style; - }, - _deleteStyleDeclaration: function(lineIndex, charIndex) { - delete this.styles[lineIndex][charIndex]; - }, - _getLineStyle: function(lineIndex) { - return this.styles[lineIndex]; - }, - _setLineStyle: function(lineIndex, style) { - this.styles[lineIndex] = style; - }, - _deleteLineStyle: function(lineIndex) { - delete this.styles[lineIndex]; - } - }); -})(); - -(function() { - function parseDecoration(object) { - if (object.textDecoration) { - object.textDecoration.indexOf("underline") > -1 && (object.underline = true); - object.textDecoration.indexOf("line-through") > -1 && (object.linethrough = true); - object.textDecoration.indexOf("overline") > -1 && (object.overline = true); - delete object.textDecoration; - } - } - fabric.IText = fabric.util.createClass(fabric.Text, fabric.Observable, { - type: "i-text", - selectionStart: 0, - selectionEnd: 0, - selectionColor: "rgba(17,119,255,0.3)", - isEditing: false, - editable: true, - editingBorderColor: "rgba(102,153,255,0.25)", - cursorWidth: 2, - cursorColor: "#333", - cursorDelay: 1e3, - cursorDuration: 600, - caching: true, - _reSpace: /\s|\n/, - _currentCursorOpacity: 0, - _selectionDirection: null, - _abortCursorAnimation: false, - __widthOfSpace: [], - inCompositionMode: false, - initialize: function(text, options) { - this.callSuper("initialize", text, options); - this.initBehavior(); - }, - setSelectionStart: function(index) { - index = Math.max(index, 0); - this._updateAndFire("selectionStart", index); - }, - setSelectionEnd: function(index) { - index = Math.min(index, this.text.length); - this._updateAndFire("selectionEnd", index); - }, - _updateAndFire: function(property, index) { - if (this[property] !== index) { - this._fireSelectionChanged(); - this[property] = index; - } - this._updateTextarea(); - }, - _fireSelectionChanged: function() { - this.fire("selection:changed"); - this.canvas && this.canvas.fire("text:selection:changed", { - target: this - }); - }, - initDimensions: function() { - this.isEditing && this.initDelayedCursor(); - this.clearContextTop(); - this.callSuper("initDimensions"); - }, - render: function(ctx) { - this.clearContextTop(); - this.callSuper("render", ctx); - this.cursorOffsetCache = {}; - this.renderCursorOrSelection(); - }, - _render: function(ctx) { - this.callSuper("_render", ctx); - }, - clearContextTop: function(skipRestore) { - if (!this.isEditing) { - return; - } - if (this.canvas && this.canvas.contextTop) { - var ctx = this.canvas.contextTop, v = this.canvas.viewportTransform; - ctx.save(); - ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); - this.transform(ctx); - this.transformMatrix && ctx.transform.apply(ctx, this.transformMatrix); - this._clearTextArea(ctx); - skipRestore || ctx.restore(); - } - }, - renderCursorOrSelection: function() { - if (!this.isEditing || !this.canvas) { - return; - } - var boundaries = this._getCursorBoundaries(), ctx; - if (this.canvas && this.canvas.contextTop) { - ctx = this.canvas.contextTop; - this.clearContextTop(true); - } else { - ctx = this.canvas.contextContainer; - ctx.save(); - } - if (this.selectionStart === this.selectionEnd) { - this.renderCursor(boundaries, ctx); - } else { - this.renderSelection(boundaries, ctx); - } - ctx.restore(); - }, - _clearTextArea: function(ctx) { - var width = this.width + 4, height = this.height + 4; - ctx.clearRect(-width / 2, -height / 2, width, height); - }, - _getCursorBoundaries: function(position) { - if (typeof position === "undefined") { - position = this.selectionStart; - } - var left = this._getLeftOffset(), top = this._getTopOffset(), offsets = this._getCursorBoundariesOffsets(position); - return { - left: left, - top: top, - leftOffset: offsets.left, - topOffset: offsets.top - }; - }, - _getCursorBoundariesOffsets: function(position) { - if (this.cursorOffsetCache && "top" in this.cursorOffsetCache) { - return this.cursorOffsetCache; - } - var lineLeftOffset, lineIndex = 0, charIndex = 0, topOffset = 0, leftOffset = 0, boundaries, cursorPosition = this.get2DCursorLocation(position); - for (var i = 0; i < cursorPosition.lineIndex; i++) { - topOffset += this.getHeightOfLine(i); - } - lineLeftOffset = this._getLineLeftOffset(cursorPosition.lineIndex); - var bound = this.__charBounds[cursorPosition.lineIndex][cursorPosition.charIndex]; - bound && (leftOffset = bound.left); - if (this.charSpacing !== 0 && charIndex === this._textLines[lineIndex].length) { - leftOffset -= this._getWidthOfCharSpacing(); - } - boundaries = { - top: topOffset, - left: lineLeftOffset + (leftOffset > 0 ? leftOffset : 0) - }; - this.cursorOffsetCache = boundaries; - return this.cursorOffsetCache; - }, - renderCursor: function(boundaries, ctx) { - var cursorLocation = this.get2DCursorLocation(), lineIndex = cursorLocation.lineIndex, charIndex = cursorLocation.charIndex > 0 ? cursorLocation.charIndex - 1 : 0, charHeight = this.getValueOfPropertyAt(lineIndex, charIndex, "fontSize"), multiplier = this.scaleX * this.canvas.getZoom(), cursorWidth = this.cursorWidth / multiplier, topOffset = boundaries.topOffset; - topOffset += (1 - this._fontSizeFraction) * this.getHeightOfLine(lineIndex) / this.lineHeight - charHeight * (1 - this._fontSizeFraction); - if (this.inCompositionMode) { - this.renderSelection(boundaries, ctx); - } - ctx.fillStyle = this.getValueOfPropertyAt(lineIndex, charIndex, "fill"); - ctx.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity; - ctx.fillRect(boundaries.left + boundaries.leftOffset - cursorWidth / 2, topOffset + boundaries.top, cursorWidth, charHeight); - }, - renderSelection: function(boundaries, ctx) { - var selectionStart = this.inCompositionMode ? this.hiddenTextarea.selectionStart : this.selectionStart, selectionEnd = this.inCompositionMode ? this.hiddenTextarea.selectionEnd : this.selectionEnd, isJustify = this.textAlign.indexOf("justify") !== -1, start = this.get2DCursorLocation(selectionStart), end = this.get2DCursorLocation(selectionEnd), startLine = start.lineIndex, endLine = end.lineIndex, startChar = start.charIndex < 0 ? 0 : start.charIndex, endChar = end.charIndex < 0 ? 0 : end.charIndex; - for (var i = startLine; i <= endLine; i++) { - var lineOffset = this._getLineLeftOffset(i) || 0, lineHeight = this.getHeightOfLine(i), realLineHeight = 0, boxStart = 0, boxEnd = 0; - if (i === startLine) { - boxStart = this.__charBounds[startLine][startChar].left; - } - if (i >= startLine && i < endLine) { - boxEnd = isJustify && !this.isEndOfWrapping(i) ? this.width : this.getLineWidth(i) || 5; - } else if (i === endLine) { - if (endChar === 0) { - boxEnd = this.__charBounds[endLine][endChar].left; - } else { - boxEnd = this.__charBounds[endLine][endChar - 1].left + this.__charBounds[endLine][endChar - 1].width; - } - } - realLineHeight = lineHeight; - if (this.lineHeight < 1 || i === endLine && this.lineHeight > 1) { - lineHeight /= this.lineHeight; - } - if (this.inCompositionMode) { - ctx.fillStyle = this.compositionColor || "black"; - ctx.fillRect(boundaries.left + lineOffset + boxStart, boundaries.top + boundaries.topOffset + lineHeight, boxEnd - boxStart, 1); - } else { - ctx.fillStyle = this.selectionColor; - ctx.fillRect(boundaries.left + lineOffset + boxStart, boundaries.top + boundaries.topOffset, boxEnd - boxStart, lineHeight); - } - boundaries.topOffset += realLineHeight; - } - }, - getCurrentCharFontSize: function() { - var cp = this._getCurrentCharIndex(); - return this.getValueOfPropertyAt(cp.l, cp.c, "fontSize"); - }, - getCurrentCharColor: function() { - var cp = this._getCurrentCharIndex(); - return this.getValueOfPropertyAt(cp.l, cp.c, "fill"); - }, - _getCurrentCharIndex: function() { - var cursorPosition = this.get2DCursorLocation(this.selectionStart, true), charIndex = cursorPosition.charIndex > 0 ? cursorPosition.charIndex - 1 : 0; - return { - l: cursorPosition.lineIndex, - c: charIndex - }; - } - }); - fabric.IText.fromObject = function(object, callback) { - parseDecoration(object); - if (object.styles) { - for (var i in object.styles) { - for (var j in object.styles[i]) { - parseDecoration(object.styles[i][j]); - } - } - } - fabric.Object._fromObject("IText", object, callback, "text"); - }; -})(); - -(function() { - var clone = fabric.util.object.clone; - fabric.util.object.extend(fabric.IText.prototype, { - initBehavior: function() { - this.initAddedHandler(); - this.initRemovedHandler(); - this.initCursorSelectionHandlers(); - this.initDoubleClickSimulation(); - this.mouseMoveHandler = this.mouseMoveHandler.bind(this); - }, - onDeselect: function(options) { - this.isEditing && this.exitEditing(); - this.selected = false; - fabric.Object.prototype.onDeselect.call(this, options); - }, - initAddedHandler: function() { - var _this = this; - this.on("added", function() { - var canvas = _this.canvas; - if (canvas) { - if (!canvas._hasITextHandlers) { - canvas._hasITextHandlers = true; - _this._initCanvasHandlers(canvas); - } - canvas._iTextInstances = canvas._iTextInstances || []; - canvas._iTextInstances.push(_this); - } - }); - }, - initRemovedHandler: function() { - var _this = this; - this.on("removed", function() { - var canvas = _this.canvas; - if (canvas) { - canvas._iTextInstances = canvas._iTextInstances || []; - fabric.util.removeFromArray(canvas._iTextInstances, _this); - if (canvas._iTextInstances.length === 0) { - canvas._hasITextHandlers = false; - _this._removeCanvasHandlers(canvas); - } - } - }); - }, - _initCanvasHandlers: function(canvas) { - canvas._mouseUpITextHandler = function() { - if (canvas._iTextInstances) { - canvas._iTextInstances.forEach(function(obj) { - obj.__isMousedown = false; - }); - } - }.bind(this); - canvas.on("mouse:up", canvas._mouseUpITextHandler); - }, - _removeCanvasHandlers: function(canvas) { - canvas.off("mouse:up", canvas._mouseUpITextHandler); - }, - _tick: function() { - this._currentTickState = this._animateCursor(this, 1, this.cursorDuration, "_onTickComplete"); - }, - _animateCursor: function(obj, targetOpacity, duration, completeMethod) { - var tickState; - tickState = { - isAborted: false, - abort: function() { - this.isAborted = true; - } - }; - obj.animate("_currentCursorOpacity", targetOpacity, { - duration: duration, - onComplete: function() { - if (!tickState.isAborted) { - obj[completeMethod](); - } - }, - onChange: function() { - if (obj.canvas && obj.selectionStart === obj.selectionEnd) { - obj.renderCursorOrSelection(); - } - }, - abort: function() { - return tickState.isAborted; - } - }); - return tickState; - }, - _onTickComplete: function() { - var _this = this; - if (this._cursorTimeout1) { - clearTimeout(this._cursorTimeout1); - } - this._cursorTimeout1 = setTimeout(function() { - _this._currentTickCompleteState = _this._animateCursor(_this, 0, this.cursorDuration / 2, "_tick"); - }, 100); - }, - initDelayedCursor: function(restart) { - var _this = this, delay = restart ? 0 : this.cursorDelay; - this.abortCursorAnimation(); - this._currentCursorOpacity = 1; - this._cursorTimeout2 = setTimeout(function() { - _this._tick(); - }, delay); - }, - abortCursorAnimation: function() { - var shouldClear = this._currentTickState || this._currentTickCompleteState, canvas = this.canvas; - this._currentTickState && this._currentTickState.abort(); - this._currentTickCompleteState && this._currentTickCompleteState.abort(); - clearTimeout(this._cursorTimeout1); - clearTimeout(this._cursorTimeout2); - this._currentCursorOpacity = 0; - if (shouldClear && canvas) { - canvas.clearContext(canvas.contextTop || canvas.contextContainer); - } - }, - selectAll: function() { - this.selectionStart = 0; - this.selectionEnd = this._text.length; - this._fireSelectionChanged(); - this._updateTextarea(); - return this; - }, - getSelectedText: function() { - return this._text.slice(this.selectionStart, this.selectionEnd).join(""); - }, - findWordBoundaryLeft: function(startFrom) { - var offset = 0, index = startFrom - 1; - if (this._reSpace.test(this._text[index])) { - while (this._reSpace.test(this._text[index])) { - offset++; - index--; - } - } - while (/\S/.test(this._text[index]) && index > -1) { - offset++; - index--; - } - return startFrom - offset; - }, - findWordBoundaryRight: function(startFrom) { - var offset = 0, index = startFrom; - if (this._reSpace.test(this._text[index])) { - while (this._reSpace.test(this._text[index])) { - offset++; - index++; - } - } - while (/\S/.test(this._text[index]) && index < this.text.length) { - offset++; - index++; - } - return startFrom + offset; - }, - findLineBoundaryLeft: function(startFrom) { - var offset = 0, index = startFrom - 1; - while (!/\n/.test(this._text[index]) && index > -1) { - offset++; - index--; - } - return startFrom - offset; - }, - findLineBoundaryRight: function(startFrom) { - var offset = 0, index = startFrom; - while (!/\n/.test(this._text[index]) && index < this.text.length) { - offset++; - index++; - } - return startFrom + offset; - }, - searchWordBoundary: function(selectionStart, direction) { - var index = this._reSpace.test(this.text.charAt(selectionStart)) ? selectionStart - 1 : selectionStart, _char = this.text.charAt(index), reNonWord = /[ \n\.,;!\?\-]/; - while (!reNonWord.test(_char) && index > 0 && index < this.text.length) { - index += direction; - _char = this.text.charAt(index); - } - if (reNonWord.test(_char) && _char !== "\n") { - index += direction === 1 ? 0 : 1; - } - return index; - }, - selectWord: function(selectionStart) { - selectionStart = selectionStart || this.selectionStart; - var newSelectionStart = this.searchWordBoundary(selectionStart, -1), newSelectionEnd = this.searchWordBoundary(selectionStart, 1); - this.selectionStart = newSelectionStart; - this.selectionEnd = newSelectionEnd; - this._fireSelectionChanged(); - this._updateTextarea(); - this.renderCursorOrSelection(); - }, - selectLine: function(selectionStart) { - selectionStart = selectionStart || this.selectionStart; - var newSelectionStart = this.findLineBoundaryLeft(selectionStart), newSelectionEnd = this.findLineBoundaryRight(selectionStart); - this.selectionStart = newSelectionStart; - this.selectionEnd = newSelectionEnd; - this._fireSelectionChanged(); - this._updateTextarea(); - return this; - }, - enterEditing: function(e) { - if (this.isEditing || !this.editable) { - return; - } - if (this.canvas) { - this.canvas.calcOffset(); - this.exitEditingOnOthers(this.canvas); - } - this.isEditing = true; - this.initHiddenTextarea(e); - this.hiddenTextarea.focus(); - this.hiddenTextarea.value = this.text; - this._updateTextarea(); - this._saveEditingProps(); - this._setEditingProps(); - this._textBeforeEdit = this.text; - this._tick(); - this.fire("editing:entered"); - this._fireSelectionChanged(); - if (!this.canvas) { - return this; - } - this.canvas.fire("text:editing:entered", { - target: this - }); - this.initMouseMoveHandler(); - this.canvas.requestRenderAll(); - return this; - }, - exitEditingOnOthers: function(canvas) { - if (canvas._iTextInstances) { - canvas._iTextInstances.forEach(function(obj) { - obj.selected = false; - if (obj.isEditing) { - obj.exitEditing(); - } - }); - } - }, - initMouseMoveHandler: function() { - this.canvas.on("mouse:move", this.mouseMoveHandler); - }, - mouseMoveHandler: function(options) { - if (!this.__isMousedown || !this.isEditing) { - return; - } - var newSelectionStart = this.getSelectionStartFromPointer(options.e), currentStart = this.selectionStart, currentEnd = this.selectionEnd; - if ((newSelectionStart !== this.__selectionStartOnMouseDown || currentStart === currentEnd) && (currentStart === newSelectionStart || currentEnd === newSelectionStart)) { - return; - } - if (newSelectionStart > this.__selectionStartOnMouseDown) { - this.selectionStart = this.__selectionStartOnMouseDown; - this.selectionEnd = newSelectionStart; - } else { - this.selectionStart = newSelectionStart; - this.selectionEnd = this.__selectionStartOnMouseDown; - } - if (this.selectionStart !== currentStart || this.selectionEnd !== currentEnd) { - this.restartCursorIfNeeded(); - this._fireSelectionChanged(); - this._updateTextarea(); - this.renderCursorOrSelection(); - } - }, - _setEditingProps: function() { - this.hoverCursor = "text"; - if (this.canvas) { - this.canvas.defaultCursor = this.canvas.moveCursor = "text"; - } - this.borderColor = this.editingBorderColor; - this.hasControls = this.selectable = false; - this.lockMovementX = this.lockMovementY = true; - }, - fromStringToGraphemeSelection: function(start, end, text) { - var smallerTextStart = text.slice(0, start), graphemeStart = fabric.util.string.graphemeSplit(smallerTextStart).length; - if (start === end) { - return { - selectionStart: graphemeStart, - selectionEnd: graphemeStart - }; - } - var smallerTextEnd = text.slice(start, end), graphemeEnd = fabric.util.string.graphemeSplit(smallerTextEnd).length; - return { - selectionStart: graphemeStart, - selectionEnd: graphemeStart + graphemeEnd - }; - }, - fromGraphemeToStringSelection: function(start, end, _text) { - var smallerTextStart = _text.slice(0, start), graphemeStart = smallerTextStart.join("").length; - if (start === end) { - return { - selectionStart: graphemeStart, - selectionEnd: graphemeStart - }; - } - var smallerTextEnd = _text.slice(start, end), graphemeEnd = smallerTextEnd.join("").length; - return { - selectionStart: graphemeStart, - selectionEnd: graphemeStart + graphemeEnd - }; - }, - _updateTextarea: function() { - this.cursorOffsetCache = {}; - if (!this.hiddenTextarea) { - return; - } - if (!this.inCompositionMode) { - var newSelection = this.fromGraphemeToStringSelection(this.selectionStart, this.selectionEnd, this._text); - this.hiddenTextarea.selectionStart = newSelection.selectionStart; - this.hiddenTextarea.selectionEnd = newSelection.selectionEnd; - } - this.updateTextareaPosition(); - }, - updateFromTextArea: function() { - if (!this.hiddenTextarea) { - return; - } - this.cursorOffsetCache = {}; - this.text = this.hiddenTextarea.value; - if (this._shouldClearDimensionCache()) { - this.initDimensions(); - this.setCoords(); - } - var newSelection = this.fromStringToGraphemeSelection(this.hiddenTextarea.selectionStart, this.hiddenTextarea.selectionEnd, this.hiddenTextarea.value); - this.selectionEnd = this.selectionStart = newSelection.selectionEnd; - if (!this.inCompositionMode) { - this.selectionStart = newSelection.selectionStart; - } - this.updateTextareaPosition(); - }, - updateTextareaPosition: function() { - if (this.selectionStart === this.selectionEnd) { - var style = this._calcTextareaPosition(); - this.hiddenTextarea.style.left = style.left; - this.hiddenTextarea.style.top = style.top; - } - }, - _calcTextareaPosition: function() { - if (!this.canvas) { - return { - x: 1, - y: 1 - }; - } - var desiredPostion = this.inCompositionMode ? this.compositionStart : this.selectionStart, boundaries = this._getCursorBoundaries(desiredPostion), cursorLocation = this.get2DCursorLocation(desiredPostion), lineIndex = cursorLocation.lineIndex, charIndex = cursorLocation.charIndex, charHeight = this.getValueOfPropertyAt(lineIndex, charIndex, "fontSize") * this.lineHeight, leftOffset = boundaries.leftOffset, m = this.calcTransformMatrix(), p = { - x: boundaries.left + leftOffset, - y: boundaries.top + boundaries.topOffset + charHeight - }, upperCanvas = this.canvas.upperCanvasEl, maxWidth = upperCanvas.width - charHeight, maxHeight = upperCanvas.height - charHeight; - p = fabric.util.transformPoint(p, m); - p = fabric.util.transformPoint(p, this.canvas.viewportTransform); - if (p.x < 0) { - p.x = 0; - } - if (p.x > maxWidth) { - p.x = maxWidth; - } - if (p.y < 0) { - p.y = 0; - } - if (p.y > maxHeight) { - p.y = maxHeight; - } - p.x += this.canvas._offset.left; - p.y += this.canvas._offset.top; - return { - left: p.x + "px", - top: p.y + "px", - fontSize: charHeight + "px", - charHeight: charHeight - }; - }, - _saveEditingProps: function() { - this._savedProps = { - hasControls: this.hasControls, - borderColor: this.borderColor, - lockMovementX: this.lockMovementX, - lockMovementY: this.lockMovementY, - hoverCursor: this.hoverCursor, - defaultCursor: this.canvas && this.canvas.defaultCursor, - moveCursor: this.canvas && this.canvas.moveCursor - }; - }, - _restoreEditingProps: function() { - if (!this._savedProps) { - return; - } - this.hoverCursor = this._savedProps.hoverCursor; - this.hasControls = this._savedProps.hasControls; - this.borderColor = this._savedProps.borderColor; - this.lockMovementX = this._savedProps.lockMovementX; - this.lockMovementY = this._savedProps.lockMovementY; - if (this.canvas) { - this.canvas.defaultCursor = this._savedProps.defaultCursor; - this.canvas.moveCursor = this._savedProps.moveCursor; - } - }, - exitEditing: function() { - var isTextChanged = this._textBeforeEdit !== this.text; - this.selected = false; - this.isEditing = false; - this.selectable = true; - this.selectionEnd = this.selectionStart; - if (this.hiddenTextarea) { - this.hiddenTextarea.blur && this.hiddenTextarea.blur(); - this.canvas && this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea); - this.hiddenTextarea = null; - } - this.abortCursorAnimation(); - this._restoreEditingProps(); - this._currentCursorOpacity = 0; - if (this._shouldClearDimensionCache()) { - this.initDimensions(); - this.setCoords(); - } - this.fire("editing:exited"); - isTextChanged && this.fire("modified"); - if (this.canvas) { - this.canvas.off("mouse:move", this.mouseMoveHandler); - this.canvas.fire("text:editing:exited", { - target: this - }); - isTextChanged && this.canvas.fire("object:modified", { - target: this - }); - } - return this; - }, - _removeExtraneousStyles: function() { - for (var prop in this.styles) { - if (!this._textLines[prop]) { - delete this.styles[prop]; - } - } - }, - removeStyleFromTo: function(start, end) { - var cursorStart = this.get2DCursorLocation(start, true), cursorEnd = this.get2DCursorLocation(end, true), lineStart = cursorStart.lineIndex, charStart = cursorStart.charIndex, lineEnd = cursorEnd.lineIndex, charEnd = cursorEnd.charIndex, i, styleObj; - if (lineStart !== lineEnd) { - if (this.styles[lineStart]) { - for (i = charStart; i < this._unwrappedTextLines[lineStart].length; i++) { - delete this.styles[lineStart][i]; - } - } - if (this.styles[lineEnd]) { - for (i = charEnd; i < this._unwrappedTextLines[lineEnd].length; i++) { - styleObj = this.styles[lineEnd][i]; - if (styleObj) { - this.styles[lineStart] || (this.styles[lineStart] = {}); - this.styles[lineStart][charStart + i - charEnd] = styleObj; - } - } - } - for (i = lineStart + 1; i <= lineEnd; i++) { - delete this.styles[i]; - } - this.shiftLineStyles(lineEnd, lineStart - lineEnd); - } else { - if (this.styles[lineStart]) { - styleObj = this.styles[lineStart]; - var diff = charEnd - charStart, numericChar, _char; - for (i = charStart; i < charEnd; i++) { - delete styleObj[i]; - } - for (_char in this.styles[lineStart]) { - numericChar = parseInt(_char, 10); - if (numericChar >= charEnd) { - styleObj[numericChar - diff] = styleObj[_char]; - delete styleObj[_char]; - } - } - } - } - }, - shiftLineStyles: function(lineIndex, offset) { - var clonedStyles = clone(this.styles); - for (var line in this.styles) { - var numericLine = parseInt(line, 10); - if (numericLine > lineIndex) { - this.styles[numericLine + offset] = clonedStyles[numericLine]; - if (!clonedStyles[numericLine - offset]) { - delete this.styles[numericLine]; - } - } - } - }, - restartCursorIfNeeded: function() { - if (!this._currentTickState || this._currentTickState.isAborted || !this._currentTickCompleteState || this._currentTickCompleteState.isAborted) { - this.initDelayedCursor(); - } - }, - insertNewlineStyleObject: function(lineIndex, charIndex, qty, copiedStyle) { - var currentCharStyle, newLineStyles = {}, somethingAdded = false; - qty || (qty = 1); - this.shiftLineStyles(lineIndex, qty); - if (this.styles[lineIndex]) { - currentCharStyle = this.styles[lineIndex][charIndex === 0 ? charIndex : charIndex - 1]; - } - for (var index in this.styles[lineIndex]) { - var numIndex = parseInt(index, 10); - if (numIndex >= charIndex) { - somethingAdded = true; - newLineStyles[numIndex - charIndex] = this.styles[lineIndex][index]; - delete this.styles[lineIndex][index]; - } - } - if (somethingAdded) { - this.styles[lineIndex + qty] = newLineStyles; - } else { - delete this.styles[lineIndex + qty]; - } - while (qty > 1) { - qty--; - if (copiedStyle && copiedStyle[qty]) { - this.styles[lineIndex + qty] = { - 0: clone(copiedStyle[qty]) - }; - } else if (currentCharStyle) { - this.styles[lineIndex + qty] = { - 0: clone(currentCharStyle) - }; - } else { - delete this.styles[lineIndex + qty]; - } - } - this._forceClearCache = true; - }, - insertCharStyleObject: function(lineIndex, charIndex, quantity, copiedStyle) { - if (!this.styles) { - this.styles = {}; - } - var currentLineStyles = this.styles[lineIndex], currentLineStylesCloned = currentLineStyles ? clone(currentLineStyles) : {}; - quantity || (quantity = 1); - for (var index in currentLineStylesCloned) { - var numericIndex = parseInt(index, 10); - if (numericIndex >= charIndex) { - currentLineStyles[numericIndex + quantity] = currentLineStylesCloned[numericIndex]; - if (!currentLineStylesCloned[numericIndex - quantity]) { - delete currentLineStyles[numericIndex]; - } - } - } - this._forceClearCache = true; - if (copiedStyle) { - while (quantity--) { - if (!Object.keys(copiedStyle[quantity]).length) { - continue; - } - if (!this.styles[lineIndex]) { - this.styles[lineIndex] = {}; - } - this.styles[lineIndex][charIndex + quantity] = clone(copiedStyle[quantity]); - } - return; - } - if (!currentLineStyles) { - return; - } - var newStyle = currentLineStyles[charIndex ? charIndex - 1 : 1]; - while (newStyle && quantity--) { - this.styles[lineIndex][charIndex + quantity] = clone(newStyle); - } - }, - insertNewStyleBlock: function(insertedText, start, copiedStyle) { - var cursorLoc = this.get2DCursorLocation(start, true), addedLines = [ 0 ], linesLenght = 0; - for (var i = 0; i < insertedText.length; i++) { - if (insertedText[i] === "\n") { - linesLenght++; - addedLines[linesLenght] = 0; - } else { - addedLines[linesLenght]++; - } - } - if (addedLines[0] > 0) { - this.insertCharStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addedLines[0], copiedStyle); - copiedStyle = copiedStyle && copiedStyle.slice(addedLines[0] + 1); - } - linesLenght && this.insertNewlineStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex + addedLines[0], linesLenght); - for (var i = 1; i < linesLenght; i++) { - if (addedLines[i] > 0) { - this.insertCharStyleObject(cursorLoc.lineIndex + i, 0, addedLines[i], copiedStyle); - } else if (copiedStyle) { - this.styles[cursorLoc.lineIndex + i][0] = copiedStyle[0]; - } - copiedStyle = copiedStyle && copiedStyle.slice(addedLines[i] + 1); - } - if (addedLines[i] > 0) { - this.insertCharStyleObject(cursorLoc.lineIndex + i, 0, addedLines[i], copiedStyle); - } - }, - setSelectionStartEndWithShift: function(start, end, newSelection) { - if (newSelection <= start) { - if (end === start) { - this._selectionDirection = "left"; - } else if (this._selectionDirection === "right") { - this._selectionDirection = "left"; - this.selectionEnd = start; - } - this.selectionStart = newSelection; - } else if (newSelection > start && newSelection < end) { - if (this._selectionDirection === "right") { - this.selectionEnd = newSelection; - } else { - this.selectionStart = newSelection; - } - } else { - if (end === start) { - this._selectionDirection = "right"; - } else if (this._selectionDirection === "left") { - this._selectionDirection = "right"; - this.selectionStart = end; - } - this.selectionEnd = newSelection; - } - }, - setSelectionInBoundaries: function() { - var length = this.text.length; - if (this.selectionStart > length) { - this.selectionStart = length; - } else if (this.selectionStart < 0) { - this.selectionStart = 0; - } - if (this.selectionEnd > length) { - this.selectionEnd = length; - } else if (this.selectionEnd < 0) { - this.selectionEnd = 0; - } - } - }); -})(); - -fabric.util.object.extend(fabric.IText.prototype, { - initDoubleClickSimulation: function() { - this.__lastClickTime = +new Date(); - this.__lastLastClickTime = +new Date(); - this.__lastPointer = {}; - this.on("mousedown", this.onMouseDown.bind(this)); - }, - onMouseDown: function(options) { - this.__newClickTime = +new Date(); - var newPointer = this.canvas.getPointer(options.e); - if (this.isTripleClick(newPointer, options.e)) { - this.fire("tripleclick", options); - this._stopEvent(options.e); - } - this.__lastLastClickTime = this.__lastClickTime; - this.__lastClickTime = this.__newClickTime; - this.__lastPointer = newPointer; - this.__lastIsEditing = this.isEditing; - this.__lastSelected = this.selected; - }, - isTripleClick: function(newPointer) { - return this.__newClickTime - this.__lastClickTime < 500 && this.__lastClickTime - this.__lastLastClickTime < 500 && this.__lastPointer.x === newPointer.x && this.__lastPointer.y === newPointer.y; - }, - _stopEvent: function(e) { - e.preventDefault && e.preventDefault(); - e.stopPropagation && e.stopPropagation(); - }, - initCursorSelectionHandlers: function() { - this.initMousedownHandler(); - this.initMouseupHandler(); - this.initClicks(); - }, - initClicks: function() { - this.on("mousedblclick", function(options) { - this.selectWord(this.getSelectionStartFromPointer(options.e)); - }); - this.on("tripleclick", function(options) { - this.selectLine(this.getSelectionStartFromPointer(options.e)); - }); - }, - _mouseDownHandler: function(options) { - if (!this.canvas || !this.editable || options.e.button && options.e.button !== 1) { - return; - } - var pointer = this.canvas.getPointer(options.e); - this.__mousedownX = pointer.x; - this.__mousedownY = pointer.y; - this.__isMousedown = true; - if (this.selected) { - this.setCursorByClick(options.e); - } - if (this.isEditing) { - this.__selectionStartOnMouseDown = this.selectionStart; - if (this.selectionStart === this.selectionEnd) { - this.abortCursorAnimation(); - } - this.renderCursorOrSelection(); - } - }, - initMousedownHandler: function() { - this.on("mousedown", this._mouseDownHandler); - }, - _isObjectMoved: function(e) { - var pointer = this.canvas.getPointer(e); - return this.__mousedownX !== pointer.x || this.__mousedownY !== pointer.y; - }, - initMouseupHandler: function() { - this.on("mouseup", function(options) { - this.__isMousedown = false; - if (!this.editable || this._isObjectMoved(options.e) || options.e.button && options.e.button !== 1) { - return; - } - if (this.__lastSelected && !this.__corner) { - this.enterEditing(options.e); - if (this.selectionStart === this.selectionEnd) { - this.initDelayedCursor(true); - } else { - this.renderCursorOrSelection(); - } - } - this.selected = true; - }); - }, - setCursorByClick: function(e) { - var newSelection = this.getSelectionStartFromPointer(e), start = this.selectionStart, end = this.selectionEnd; - if (e.shiftKey) { - this.setSelectionStartEndWithShift(start, end, newSelection); - } else { - this.selectionStart = newSelection; - this.selectionEnd = newSelection; - } - if (this.isEditing) { - this._fireSelectionChanged(); - this._updateTextarea(); - } - }, - getSelectionStartFromPointer: function(e) { - var mouseOffset = this.getLocalPointer(e), prevWidth = 0, width = 0, height = 0, charIndex = 0, lineIndex = 0, lineLeftOffset, line; - for (var i = 0, len = this._textLines.length; i < len; i++) { - if (height <= mouseOffset.y) { - height += this.getHeightOfLine(i) * this.scaleY; - lineIndex = i; - if (i > 0) { - charIndex += this._textLines[i - 1].length + 1; - } - } else { - break; - } - } - lineLeftOffset = this._getLineLeftOffset(lineIndex); - width = lineLeftOffset * this.scaleX; - line = this._textLines[lineIndex]; - for (var j = 0, jlen = line.length; j < jlen; j++) { - prevWidth = width; - width += this.__charBounds[lineIndex][j].kernedWidth * this.scaleX; - if (width <= mouseOffset.x) { - charIndex++; - } else { - break; - } - } - return this._getNewSelectionStartFromOffset(mouseOffset, prevWidth, width, charIndex, jlen); - }, - _getNewSelectionStartFromOffset: function(mouseOffset, prevWidth, width, index, jlen) { - var distanceBtwLastCharAndCursor = mouseOffset.x - prevWidth, distanceBtwNextCharAndCursor = width - mouseOffset.x, offset = distanceBtwNextCharAndCursor > distanceBtwLastCharAndCursor || distanceBtwNextCharAndCursor < 0 ? 0 : 1, newSelectionStart = index + offset; - if (this.flipX) { - newSelectionStart = jlen - newSelectionStart; - } - if (newSelectionStart > this._text.length) { - newSelectionStart = this._text.length; - } - return newSelectionStart; - } -}); - -fabric.util.object.extend(fabric.IText.prototype, { - initHiddenTextarea: function() { - this.hiddenTextarea = fabric.document.createElement("textarea"); - this.hiddenTextarea.setAttribute("autocapitalize", "off"); - this.hiddenTextarea.setAttribute("autocorrect", "off"); - this.hiddenTextarea.setAttribute("autocomplete", "off"); - this.hiddenTextarea.setAttribute("spellcheck", "false"); - this.hiddenTextarea.setAttribute("data-fabric-hiddentextarea", ""); - this.hiddenTextarea.setAttribute("wrap", "off"); - var style = this._calcTextareaPosition(); - this.hiddenTextarea.style.cssText = "position: absolute; top: " + style.top + "; left: " + style.left + "; z-index: -999; opacity: 0; width: 1px; height: 1px; font-size: 1px;" + " line-height: 1px; paddingーtop: " + style.fontSize + ";"; - fabric.document.body.appendChild(this.hiddenTextarea); - fabric.util.addListener(this.hiddenTextarea, "keydown", this.onKeyDown.bind(this)); - fabric.util.addListener(this.hiddenTextarea, "keyup", this.onKeyUp.bind(this)); - fabric.util.addListener(this.hiddenTextarea, "input", this.onInput.bind(this)); - fabric.util.addListener(this.hiddenTextarea, "copy", this.copy.bind(this)); - fabric.util.addListener(this.hiddenTextarea, "cut", this.copy.bind(this)); - fabric.util.addListener(this.hiddenTextarea, "paste", this.paste.bind(this)); - fabric.util.addListener(this.hiddenTextarea, "compositionstart", this.onCompositionStart.bind(this)); - fabric.util.addListener(this.hiddenTextarea, "compositionupdate", this.onCompositionUpdate.bind(this)); - fabric.util.addListener(this.hiddenTextarea, "compositionend", this.onCompositionEnd.bind(this)); - if (!this._clickHandlerInitialized && this.canvas) { - fabric.util.addListener(this.canvas.upperCanvasEl, "click", this.onClick.bind(this)); - this._clickHandlerInitialized = true; - } - }, - keysMap: { - 9: "exitEditing", - 27: "exitEditing", - 33: "moveCursorUp", - 34: "moveCursorDown", - 35: "moveCursorRight", - 36: "moveCursorLeft", - 37: "moveCursorLeft", - 38: "moveCursorUp", - 39: "moveCursorRight", - 40: "moveCursorDown" - }, - ctrlKeysMapUp: { - 67: "copy", - 88: "cut" - }, - ctrlKeysMapDown: { - 65: "selectAll" - }, - onClick: function() { - this.hiddenTextarea && this.hiddenTextarea.focus(); - }, - onKeyDown: function(e) { - if (!this.isEditing || this.inCompositionMode) { - return; - } - if (e.keyCode in this.keysMap) { - this[this.keysMap[e.keyCode]](e); - } else if (e.keyCode in this.ctrlKeysMapDown && (e.ctrlKey || e.metaKey)) { - this[this.ctrlKeysMapDown[e.keyCode]](e); - } else { - return; - } - e.stopImmediatePropagation(); - e.preventDefault(); - if (e.keyCode >= 33 && e.keyCode <= 40) { - this.clearContextTop(); - this.renderCursorOrSelection(); - } else { - this.canvas && this.canvas.requestRenderAll(); - } - }, - onKeyUp: function(e) { - if (!this.isEditing || this._copyDone || this.inCompositionMode) { - this._copyDone = false; - return; - } - if (e.keyCode in this.ctrlKeysMapUp && (e.ctrlKey || e.metaKey)) { - this[this.ctrlKeysMapUp[e.keyCode]](e); - } else { - return; - } - e.stopImmediatePropagation(); - e.preventDefault(); - this.canvas && this.canvas.requestRenderAll(); - }, - onInput: function(e) { - var fromPaste = this.fromPaste; - this.fromPaste = false; - e && e.stopPropagation(); - if (!this.isEditing) { - return; - } - var nextText = this._splitTextIntoLines(this.hiddenTextarea.value).graphemeText, charCount = this._text.length, nextCharCount = nextText.length, removedText, insertedText, charDiff = nextCharCount - charCount; - if (this.hiddenTextarea.value === "") { - this.styles = {}; - this.updateFromTextArea(); - this.fire("changed"); - if (this.canvas) { - this.canvas.fire("text:changed", { - target: this - }); - this.canvas.requestRenderAll(); - } - return; - } - var textareaSelection = this.fromStringToGraphemeSelection(this.hiddenTextarea.selectionStart, this.hiddenTextarea.selectionEnd, this.hiddenTextarea.value); - var backDelete = this.selectionStart > textareaSelection.selectionStart; - if (this.selectionStart !== this.selectionEnd) { - removedText = this._text.slice(this.selectionStart, this.selectionEnd); - charDiff += this.selectionEnd - this.selectionStart; - } else if (nextCharCount < charCount) { - if (backDelete) { - removedText = this._text.slice(this.selectionEnd + charDiff, this.selectionEnd); - } else { - removedText = this._text.slice(this.selectionStart, this.selectionStart - charDiff); - } - } - insertedText = nextText.slice(textareaSelection.selectionEnd - charDiff, textareaSelection.selectionEnd); - if (removedText && removedText.length) { - if (this.selectionStart !== this.selectionEnd) { - this.removeStyleFromTo(this.selectionStart, this.selectionEnd); - } else if (backDelete) { - this.removeStyleFromTo(this.selectionEnd - removedText.length, this.selectionEnd); - } else { - this.removeStyleFromTo(this.selectionEnd, this.selectionEnd + removedText.length); - } - } - if (insertedText.length) { - if (fromPaste && insertedText.join("") === fabric.copiedText) { - this.insertNewStyleBlock(insertedText, this.selectionStart, fabric.copiedTextStyle); - } else { - this.insertNewStyleBlock(insertedText, this.selectionStart); - } - } - this.updateFromTextArea(); - this.fire("changed"); - if (this.canvas) { - this.canvas.fire("text:changed", { - target: this - }); - this.canvas.requestRenderAll(); - } - }, - onCompositionStart: function() { - this.inCompositionMode = true; - }, - onCompositionEnd: function() { - this.inCompositionMode = false; - }, - onCompositionUpdate: function(e) { - this.compositionStart = e.target.selectionStart; - this.compositionEnd = e.target.selectionEnd; - this.updateTextareaPosition(); - }, - copy: function() { - if (this.selectionStart === this.selectionEnd) { - return; - } - fabric.copiedText = this.getSelectedText(); - fabric.copiedTextStyle = this.getSelectionStyles(this.selectionStart, this.selectionEnd, true); - this._copyDone = true; - }, - paste: function() { - this.fromPaste = true; - }, - _getClipboardData: function(e) { - return e && e.clipboardData || fabric.window.clipboardData; - }, - _getWidthBeforeCursor: function(lineIndex, charIndex) { - var widthBeforeCursor = this._getLineLeftOffset(lineIndex), bound; - if (charIndex > 0) { - bound = this.__charBounds[lineIndex][charIndex - 1]; - widthBeforeCursor += bound.left + bound.width; - } - return widthBeforeCursor; - }, - getDownCursorOffset: function(e, isRight) { - var selectionProp = this._getSelectionForOffset(e, isRight), cursorLocation = this.get2DCursorLocation(selectionProp), lineIndex = cursorLocation.lineIndex; - if (lineIndex === this._textLines.length - 1 || e.metaKey || e.keyCode === 34) { - return this._text.length - selectionProp; - } - var charIndex = cursorLocation.charIndex, widthBeforeCursor = this._getWidthBeforeCursor(lineIndex, charIndex), indexOnOtherLine = this._getIndexOnLine(lineIndex + 1, widthBeforeCursor), textAfterCursor = this._textLines[lineIndex].slice(charIndex); - return textAfterCursor.length + indexOnOtherLine + 2; - }, - _getSelectionForOffset: function(e, isRight) { - if (e.shiftKey && this.selectionStart !== this.selectionEnd && isRight) { - return this.selectionEnd; - } else { - return this.selectionStart; - } - }, - getUpCursorOffset: function(e, isRight) { - var selectionProp = this._getSelectionForOffset(e, isRight), cursorLocation = this.get2DCursorLocation(selectionProp), lineIndex = cursorLocation.lineIndex; - if (lineIndex === 0 || e.metaKey || e.keyCode === 33) { - return -selectionProp; - } - var charIndex = cursorLocation.charIndex, widthBeforeCursor = this._getWidthBeforeCursor(lineIndex, charIndex), indexOnOtherLine = this._getIndexOnLine(lineIndex - 1, widthBeforeCursor), textBeforeCursor = this._textLines[lineIndex].slice(0, charIndex); - return -this._textLines[lineIndex - 1].length + indexOnOtherLine - textBeforeCursor.length; - }, - _getIndexOnLine: function(lineIndex, width) { - var line = this._textLines[lineIndex], lineLeftOffset = this._getLineLeftOffset(lineIndex), widthOfCharsOnLine = lineLeftOffset, indexOnLine = 0, charWidth, foundMatch; - for (var j = 0, jlen = line.length; j < jlen; j++) { - charWidth = this.__charBounds[lineIndex][j].width; - widthOfCharsOnLine += charWidth; - if (widthOfCharsOnLine > width) { - foundMatch = true; - var leftEdge = widthOfCharsOnLine - charWidth, rightEdge = widthOfCharsOnLine, offsetFromLeftEdge = Math.abs(leftEdge - width), offsetFromRightEdge = Math.abs(rightEdge - width); - indexOnLine = offsetFromRightEdge < offsetFromLeftEdge ? j : j - 1; - break; - } - } - if (!foundMatch) { - indexOnLine = line.length - 1; - } - return indexOnLine; - }, - moveCursorDown: function(e) { - if (this.selectionStart >= this._text.length && this.selectionEnd >= this._text.length) { - return; - } - this._moveCursorUpOrDown("Down", e); - }, - moveCursorUp: function(e) { - if (this.selectionStart === 0 && this.selectionEnd === 0) { - return; - } - this._moveCursorUpOrDown("Up", e); - }, - _moveCursorUpOrDown: function(direction, e) { - var action = "get" + direction + "CursorOffset", offset = this[action](e, this._selectionDirection === "right"); - if (e.shiftKey) { - this.moveCursorWithShift(offset); - } else { - this.moveCursorWithoutShift(offset); - } - if (offset !== 0) { - this.setSelectionInBoundaries(); - this.abortCursorAnimation(); - this._currentCursorOpacity = 1; - this.initDelayedCursor(); - this._fireSelectionChanged(); - this._updateTextarea(); - } - }, - moveCursorWithShift: function(offset) { - var newSelection = this._selectionDirection === "left" ? this.selectionStart + offset : this.selectionEnd + offset; - this.setSelectionStartEndWithShift(this.selectionStart, this.selectionEnd, newSelection); - return offset !== 0; - }, - moveCursorWithoutShift: function(offset) { - if (offset < 0) { - this.selectionStart += offset; - this.selectionEnd = this.selectionStart; - } else { - this.selectionEnd += offset; - this.selectionStart = this.selectionEnd; - } - return offset !== 0; - }, - moveCursorLeft: function(e) { - if (this.selectionStart === 0 && this.selectionEnd === 0) { - return; - } - this._moveCursorLeftOrRight("Left", e); - }, - _move: function(e, prop, direction) { - var newValue; - if (e.altKey) { - newValue = this["findWordBoundary" + direction](this[prop]); - } else if (e.metaKey || e.keyCode === 35 || e.keyCode === 36) { - newValue = this["findLineBoundary" + direction](this[prop]); - } else { - this[prop] += direction === "Left" ? -1 : 1; - return true; - } - if (typeof newValue !== undefined && this[prop] !== newValue) { - this[prop] = newValue; - return true; - } - }, - _moveLeft: function(e, prop) { - return this._move(e, prop, "Left"); - }, - _moveRight: function(e, prop) { - return this._move(e, prop, "Right"); - }, - moveCursorLeftWithoutShift: function(e) { - var change = true; - this._selectionDirection = "left"; - if (this.selectionEnd === this.selectionStart && this.selectionStart !== 0) { - change = this._moveLeft(e, "selectionStart"); - } - this.selectionEnd = this.selectionStart; - return change; - }, - moveCursorLeftWithShift: function(e) { - if (this._selectionDirection === "right" && this.selectionStart !== this.selectionEnd) { - return this._moveLeft(e, "selectionEnd"); - } else if (this.selectionStart !== 0) { - this._selectionDirection = "left"; - return this._moveLeft(e, "selectionStart"); - } - }, - moveCursorRight: function(e) { - if (this.selectionStart >= this._text.length && this.selectionEnd >= this._text.length) { - return; - } - this._moveCursorLeftOrRight("Right", e); - }, - _moveCursorLeftOrRight: function(direction, e) { - var actionName = "moveCursor" + direction + "With"; - this._currentCursorOpacity = 1; - if (e.shiftKey) { - actionName += "Shift"; - } else { - actionName += "outShift"; - } - if (this[actionName](e)) { - this.abortCursorAnimation(); - this.initDelayedCursor(); - this._fireSelectionChanged(); - this._updateTextarea(); - } - }, - moveCursorRightWithShift: function(e) { - if (this._selectionDirection === "left" && this.selectionStart !== this.selectionEnd) { - return this._moveRight(e, "selectionStart"); - } else if (this.selectionEnd !== this._text.length) { - this._selectionDirection = "right"; - return this._moveRight(e, "selectionEnd"); - } - }, - moveCursorRightWithoutShift: function(e) { - var changed = true; - this._selectionDirection = "right"; - if (this.selectionStart === this.selectionEnd) { - changed = this._moveRight(e, "selectionStart"); - this.selectionEnd = this.selectionStart; - } else { - this.selectionStart = this.selectionEnd; - } - return changed; - }, - removeChars: function(start, end) { - if (typeof end === "undefined") { - end = start + 1; - } - this.removeStyleFromTo(start, end); - this._text.splice(start, end - start); - this.text = this._text.join(""); - this.set("dirty", true); - if (this._shouldClearDimensionCache()) { - this.initDimensions(); - this.setCoords(); - } - this._removeExtraneousStyles(); - }, - insertChars: function(text, style, start, end) { - if (typeof end === "undefined") { - end = start; - } - if (end > start) { - this.removeStyleFromTo(start, end); - } - var graphemes = fabric.util.string.graphemeSplit(text); - this.insertNewStyleBlock(graphemes, start, style); - this._text = [].concat(this._text.slice(0, start), graphemes, this._text.slice(end)); - this.text = this._text.join(""); - this.set("dirty", true); - if (this._shouldClearDimensionCache()) { - this.initDimensions(); - this.setCoords(); - } - this._removeExtraneousStyles(); - } -}); - -(function() { - var toFixed = fabric.util.toFixed; - fabric.util.object.extend(fabric.Text.prototype, { - toSVG: function(reviver) { - var markup = this._createBaseSVGMarkup(), offsets = this._getSVGLeftTopOffsets(), textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft); - this._wrapSVGTextAndBg(markup, textAndBg); - return reviver ? reviver(markup.join("")) : markup.join(""); - }, - _getSVGLeftTopOffsets: function() { - return { - textLeft: -this.width / 2, - textTop: -this.height / 2, - lineTop: this.getHeightOfLine(0) - }; - }, - _wrapSVGTextAndBg: function(markup, textAndBg) { - var noShadow = true, filter = this.getSvgFilter(), style = filter === "" ? "" : ' style="' + filter + '"', textDecoration = this.getSvgTextDecoration(this); - markup.push("\t\n", textAndBg.textBgRects.join(""), '\t\t", textAndBg.textSpans.join(""), "\n", "\t\n"); - }, - _getSVGTextAndBg: function(textTopOffset, textLeftOffset) { - var textSpans = [], textBgRects = [], height = textTopOffset, lineOffset; - this._setSVGBg(textBgRects); - for (var i = 0, len = this._textLines.length; i < len; i++) { - lineOffset = this._getLineLeftOffset(i); - if (this.textBackgroundColor || this.styleHas("textBackgroundColor", i)) { - this._setSVGTextLineBg(textBgRects, i, textLeftOffset + lineOffset, height); - } - this._setSVGTextLineText(textSpans, i, textLeftOffset + lineOffset, height); - height += this.getHeightOfLine(i); - } - return { - textSpans: textSpans, - textBgRects: textBgRects - }; - }, - _createTextCharSpan: function(_char, styleDecl, left, top) { - var styleProps = this.getSvgSpanStyles(styleDecl, _char !== _char.trim()), fillStyles = styleProps ? 'style="' + styleProps + '"' : "", NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; - return [ '", fabric.util.string.escapeXml(_char), "" ].join(""); - }, - _setSVGTextLineText: function(textSpans, lineIndex, textLeftOffset, textTopOffset) { - var lineHeight = this.getHeightOfLine(lineIndex), isJustify = this.textAlign.indexOf("justify") !== -1, actualStyle, nextStyle, charsToRender = "", charBox, style, boxWidth = 0, line = this._textLines[lineIndex], timeToRender; - textTopOffset += lineHeight * (1 - this._fontSizeFraction) / this.lineHeight; - for (var i = 0, len = line.length - 1; i <= len; i++) { - timeToRender = i === len || this.charSpacing; - charsToRender += line[i]; - charBox = this.__charBounds[lineIndex][i]; - if (boxWidth === 0) { - textLeftOffset += charBox.kernedWidth - charBox.width; - boxWidth += charBox.width; - } else { - boxWidth += charBox.kernedWidth; - } - if (isJustify && !timeToRender) { - if (this._reSpaceAndTab.test(line[i])) { - timeToRender = true; - } - } - if (!timeToRender) { - actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i); - nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1); - timeToRender = this._hasStyleChangedForSvg(actualStyle, nextStyle); - } - if (timeToRender) { - style = this._getStyleDeclaration(lineIndex, i) || {}; - textSpans.push(this._createTextCharSpan(charsToRender, style, textLeftOffset, textTopOffset)); - charsToRender = ""; - actualStyle = nextStyle; - textLeftOffset += boxWidth; - boxWidth = 0; - } - } - }, - _pushTextBgRect: function(textBgRects, color, left, top, width, height) { - var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; - textBgRects.push("\t\t\n'); - }, - _setSVGTextLineBg: function(textBgRects, i, leftOffset, textTopOffset) { - var line = this._textLines[i], heightOfLine = this.getHeightOfLine(i) / this.lineHeight, boxWidth = 0, boxStart = 0, charBox, currentColor, lastColor = this.getValueOfPropertyAt(i, 0, "textBackgroundColor"); - for (var j = 0, jlen = line.length; j < jlen; j++) { - charBox = this.__charBounds[i][j]; - currentColor = this.getValueOfPropertyAt(i, j, "textBackgroundColor"); - if (currentColor !== lastColor) { - lastColor && this._pushTextBgRect(textBgRects, lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine); - boxStart = charBox.left; - boxWidth = charBox.width; - lastColor = currentColor; - } else { - boxWidth += charBox.kernedWidth; - } - } - currentColor && this._pushTextBgRect(textBgRects, currentColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine); - }, - _getFillAttributes: function(value) { - var fillColor = value && typeof value === "string" ? new fabric.Color(value) : ""; - if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) { - return 'fill="' + value + '"'; - } - return 'opacity="' + fillColor.getAlpha() + '" fill="' + fillColor.setAlpha(1).toRgb() + '"'; - }, - _getSVGLineTopOffset: function(lineIndex) { - var lineTopOffset = 0, lastHeight = 0; - for (var j = 0; j < lineIndex; j++) { - lineTopOffset += this.getHeightOfLine(j); - } - lastHeight = this.getHeightOfLine(j); - return { - lineTop: lineTopOffset, - offset: (this._fontSizeMult - this._fontSizeFraction) * lastHeight / (this.lineHeight * this._fontSizeMult) - }; - }, - getSvgStyles: function(skipShadow) { - var svgStyle = fabric.Object.prototype.getSvgStyles.call(this, skipShadow); - return svgStyle + " white-space: pre;"; - } - }); -})(); - -(function(global) { - "use strict"; - var fabric = global.fabric || (global.fabric = {}); - fabric.Textbox = fabric.util.createClass(fabric.IText, fabric.Observable, { - type: "textbox", - minWidth: 20, - dynamicMinWidth: 2, - __cachedLines: null, - lockScalingFlip: true, - noScaleCache: false, - _dimensionAffectingProps: fabric.Text.prototype._dimensionAffectingProps.concat("width"), - initialize: function(text, options) { - this.callSuper("initialize", text, options); - }, - initDimensions: function() { - if (this.__skipDimension) { - return; - } - this.isEditing && this.initDelayedCursor(); - this.clearContextTop(); - this._clearCache(); - this.dynamicMinWidth = 0; - this._styleMap = this._generateStyleMap(this._splitText()); - if (this.dynamicMinWidth > this.width) { - this._set("width", this.dynamicMinWidth); - } - if (this.textAlign.indexOf("justify") !== -1) { - this.enlargeSpaces(); - } - this.height = this.calcTextHeight(); - this.saveState({ - propertySet: "_dimensionAffectingProps" - }); - }, - _generateStyleMap: function(textInfo) { - var realLineCount = 0, realLineCharCount = 0, charCount = 0, map = {}; - for (var i = 0; i < textInfo.graphemeLines.length; i++) { - if (textInfo.graphemeText[charCount] === "\n" && i > 0) { - realLineCharCount = 0; - charCount++; - realLineCount++; - } else if (this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) && i > 0) { - realLineCharCount++; - charCount++; - } - map[i] = { - line: realLineCount, - offset: realLineCharCount - }; - charCount += textInfo.graphemeLines[i].length; - realLineCharCount += textInfo.graphemeLines[i].length; - } - return map; - }, - styleHas: function(property, lineIndex) { - if (this._styleMap && !this.isWrapping) { - var map = this._styleMap[lineIndex]; - if (map) { - lineIndex = map.line; - } - } - return fabric.Text.prototype.styleHas.call(this, property, lineIndex); - }, - _getStyleDeclaration: function(lineIndex, charIndex) { - if (this._styleMap && !this.isWrapping) { - var map = this._styleMap[lineIndex]; - if (!map) { - return null; - } - lineIndex = map.line; - charIndex = map.offset + charIndex; - } - return this.callSuper("_getStyleDeclaration", lineIndex, charIndex); - }, - _setStyleDeclaration: function(lineIndex, charIndex, style) { - var map = this._styleMap[lineIndex]; - lineIndex = map.line; - charIndex = map.offset + charIndex; - this.styles[lineIndex][charIndex] = style; - }, - _deleteStyleDeclaration: function(lineIndex, charIndex) { - var map = this._styleMap[lineIndex]; - lineIndex = map.line; - charIndex = map.offset + charIndex; - delete this.styles[lineIndex][charIndex]; - }, - _getLineStyle: function(lineIndex) { - var map = this._styleMap[lineIndex]; - return this.styles[map.line]; - }, - _setLineStyle: function(lineIndex, style) { - var map = this._styleMap[lineIndex]; - this.styles[map.line] = style; - }, - _deleteLineStyle: function(lineIndex) { - var map = this._styleMap[lineIndex]; - delete this.styles[map.line]; - }, - _wrapText: function(lines, desiredWidth) { - var wrapped = [], i; - this.isWrapping = true; - for (i = 0; i < lines.length; i++) { - wrapped = wrapped.concat(this._wrapLine(lines[i], i, desiredWidth)); - } - this.isWrapping = false; - return wrapped; - }, - _measureWord: function(word, lineIndex, charOffset) { - var width = 0, prevGrapheme, skipLeft = true; - charOffset = charOffset || 0; - for (var i = 0, len = word.length; i < len; i++) { - var box = this._getGraphemeBox(word[i], lineIndex, i + charOffset, prevGrapheme, skipLeft); - width += box.kernedWidth; - prevGrapheme = word[i]; - } - return width; - }, - _wrapLine: function(_line, lineIndex, desiredWidth) { - var lineWidth = 0, graphemeLines = [], line = [], words = _line.split(this._reSpaceAndTab), word = "", offset = 0, infix = " ", wordWidth = 0, infixWidth = 0, largestWordWidth = 0, lineJustStarted = true, additionalSpace = this._getWidthOfCharSpacing(); - for (var i = 0; i < words.length; i++) { - word = fabric.util.string.graphemeSplit(words[i]); - wordWidth = this._measureWord(word, lineIndex, offset); - offset += word.length; - lineWidth += infixWidth + wordWidth - additionalSpace; - if (lineWidth >= desiredWidth && !lineJustStarted) { - graphemeLines.push(line); - line = []; - lineWidth = wordWidth; - lineJustStarted = true; - } - if (!lineJustStarted) { - line.push(infix); - } - line = line.concat(word); - infixWidth = this._measureWord([ infix ], lineIndex, offset); - offset++; - lineJustStarted = false; - if (wordWidth > largestWordWidth) { - largestWordWidth = wordWidth; - } - } - i && graphemeLines.push(line); - if (largestWordWidth > this.dynamicMinWidth) { - this.dynamicMinWidth = largestWordWidth - additionalSpace; - } - return graphemeLines; - }, - isEndOfWrapping: function(lineIndex) { - if (!this._styleMap[lineIndex + 1]) { - return true; - } - if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) { - return true; - } - return false; - }, - _splitTextIntoLines: function(text) { - var newText = fabric.Text.prototype._splitTextIntoLines.call(this, text), graphemeLines = this._wrapText(newText.lines, this.width), lines = new Array(graphemeLines.length); - for (var i = 0; i < graphemeLines.length; i++) { - lines[i] = graphemeLines[i].join(""); - } - newText.lines = lines; - newText.graphemeLines = graphemeLines; - return newText; - }, - getMinWidth: function() { - return Math.max(this.minWidth, this.dynamicMinWidth); - }, - toObject: function(propertiesToInclude) { - return this.callSuper("toObject", [ "minWidth" ].concat(propertiesToInclude)); - } - }); - fabric.Textbox.fromObject = function(object, callback) { - return fabric.Object._fromObject("Textbox", object, callback, "text"); - }; -})(typeof exports !== "undefined" ? exports : this); - -(function() { - var setObjectScaleOverridden = fabric.Canvas.prototype._setObjectScale; - fabric.Canvas.prototype._setObjectScale = function(localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip, _dim) { - var t = transform.target; - if (by === "x" && t instanceof fabric.Textbox) { - var tw = t._getTransformedDimensions().x; - var w = t.width * (localMouse.x / tw); - if (w >= t.getMinWidth()) { - t.set("width", w); - return true; - } - } else { - return setObjectScaleOverridden.call(fabric.Canvas.prototype, localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip, _dim); - } - }; - fabric.util.object.extend(fabric.Textbox.prototype, { - _removeExtraneousStyles: function() { - for (var prop in this._styleMap) { - if (!this._textLines[prop]) { - delete this.styles[this._styleMap[prop].line]; - } - } - } - }); -})(); - -window.fabric = fabric; - -if (typeof define === "function" && define.amd) { - define([], function() { - return fabric; - }); -} \ No newline at end of file diff --git a/package.json b/package.json index af764e61..da39e187 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "fabric", "description": "Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.", "homepage": "http://fabricjs.com/", - "version": "2.0.0", + "version": "2.0.1", "author": "Juriy Zaytsev ", "contributors": [ {