{"version":3,"sources":["webpack:///./src/assets/images/ZizbeyJobsLogo.svg","webpack:///./src/View/endUsers/requestJobInfo.vue","webpack:///./src/View/endUsers/component/imageCroper.vue","webpack:///src/View/endUsers/component/imageCroper.vue","webpack:///./src/View/endUsers/component/imageCroper.vue?b24e","webpack:///./src/View/endUsers/component/imageCroper.vue?d008","webpack:///./src/View/endUsers/component/imageEditor.vue","webpack:///src/View/endUsers/component/imageEditor.vue","webpack:///./src/View/endUsers/component/imageEditor.vue?70de","webpack:///./src/View/endUsers/component/imageEditor.vue?7b60","webpack:///src/View/endUsers/requestJobInfo.vue","webpack:///./src/View/endUsers/requestJobInfo.vue?3c85","webpack:///./src/View/endUsers/requestJobInfo.vue?4e8a","webpack:///./src/View/endUsers/component/imageEditor.vue?9180","webpack:///./node_modules/fabric/dist/fabric.js","webpack:///./src/View/endUsers/requestJobInfo.vue?d233","webpack:///./src/View/endUsers/component/imageCroper.vue?b189"],"names":["module","exports","render","_vm","this","_c","_self","staticClass","_m","ShowErr","_e","style","cardHeight","class","movileView","_v","_s","jrtitle","isFromName","_f","jrDate","staticStyle","attrs","images","length","on","$event","saveButton","isDragging","preventDefault","handleDrop","apply","arguments","handleDragOver","handleDragLeave","triggerFileInput","ref","handleFiles","_l","image","index","key","removeImage","type2","editImage","url","name","displayTitle","isExpire","apiData","showEditFunc","closeBtn","cropStart","cropStart2","selectedImage","imageDivHeight2","showLogoCropper","showLogoEditor","$store","getters","showLoader","loaderMessage","showAlert","alertMessage","alertColor","staticRenderFns","require","title","undefined","entityName","emitData","uploadImage","showClipper","innerWidth","bgColor","ratio","imageToCrop","rotateDegree","areaVal","slot","directives","rawName","value","expression","domProps","target","composing","zoomIn","zoomOut","innerwidth","components","clipperFixed","clipperPreview","Button","data","resultURL","zoomScale","showSelectionButton","props","mounted","watch","handler","created","methods","getResult","dataURItoBlob","byteString","ia","resolve","type","isUpdated","file","imageToCropUpload","component","startAddingText","isDrawingMode","enableDrawingMode","highLighterOn","enableHighlighterMode","addShape","deleteSelected","clearAll","selectedColor","updateColor","isAddingText","selectedITEM","canvas","currentTool","innerHeight","selectedObject","imageObject","window","beforeDestroy","handleKeydown","handleResize","initializeCanvas","loadImageFromURL","fabric","width","height","img","left","top","selectable","evented","handleCanvasClick","fontSize","fill","stroke","strokeWidth","shape","radius","createArrow","hexToRgba","g","b","r","handleObjectSelected","clearSelectedObject","activeObjects","uint8Array","moment","imageCroper","imageEditor","snakBar","Loader","tenpFIles","sessionToken","dubArray","doneOnce","chanesIndex","changesArray","backupUrl","destroyed","getDublicateDataSet","getTokenExp","status","message","MyJobApp","response","err","color","element","error","setTimeout","resizeWindowHandler","event","reloadagain","processFiles","files","reader","size","lastModified","alert","version","document","HTMLDocument","Document","implementation","createHTMLDocument","jsdom","virtualWindow","JSDOM","decodeURIComponent","features","FetchExternalResources","resources","jsdomImplForWrapper","implForWrapper","nodeCanvas","Canvas","DOMParser","resizeCanvasIfNeeded","pipelineState","targetCanvas","dWidth","destinationWidth","dHeight","destinationHeight","copyGLTo2DDrawImage","gl","glCanvas","ctx","getContext","translate","scale","sourceY","drawImage","copyGLTo2DPutImageData","numBytes","u8","Uint8Array","imageBuffer","u8Clamped","Uint8ClampedArray","readPixels","RGBA","UNSIGNED_BYTE","imgData","ImageData","putImageData","isTouchSupported","navigator","maxTouchPoints","isLikelyNode","Buffer","SHARED_ATTRIBUTES","DPI","reNum","commaWsp","rePathCommand","reNonWord","fontPaths","iMatrix","svgNS","perfLimitSizeTotal","maxCacheSideLimit","minCacheSideLimit","charWidthsCache","textureSize","disableStyleCopyPaste","enableGLFiltering","devicePixelRatio","webkitDevicePixelRatio","mozDevicePixelRatio","browserShadowBlurConstant","arcToSegmentsCache","boundsOfCurveCache","cachesBoundsOfCurve","forceGLPutImageData","initFilterBackend","isWebglSupported","console","log","maxTextureSize","WebglFilterBackend","tileSize","Canvas2dFilterBackend","_removeEventListener","eventName","__eventListeners","eventListener","indexOf","util","array","prop","push","_once","_handler","off","bind","once","call","fire","options","listenersForEvent","i","len","filter","Observable","Collection","_objects","add","_onObjectAdded","renderOnAddRemove","requestRenderAll","insertAt","object","nonSplicing","objects","splice","remove","somethingRemoved","_onObjectRemoved","forEachObject","callback","context","getObjects","concat","o","item","isEmpty","contains","deep","some","obj","complexity","reduce","memo","current","CommonMethods","_setOptions","set","_initGradient","filler","property","colorStops","Gradient","_initPattern","source","Pattern","_setObject","_set","toggle","get","global","sqrt","Math","atan2","pow","PiBy180","PI","PiBy2","cos","angle","angleSlice","sin","sign","removeFromArray","idx","getRandomInt","min","max","floor","random","degreesToRadians","degrees","radiansToDegrees","radians","rotatePoint","point","origin","newPoint","Point","x","y","v","rotateVector","addEquals","vector","rx","ry","createVector","from","to","calcAngleBetweenVectors","a","acos","hypot","getHatVector","multiply","getBisector","A","B","C","AB","AC","alpha","ro","phi","projectStrokeOnPoints","points","openPath","coords","s","strokeUniformScalar","strokeUniform","scaleX","scaleY","getStrokeHatVector","scalar","forEach","p","miterVector","bisector","bisectorVector","strokeLineJoin","strokeMiterLimit","subtract","SQRT2","transformPoint","t","ignoreOffset","makeBoundingBoxFromPoints","transform","xPoints","minX","maxX","yPoints","minY","maxY","invertTransform","toFixed","number","fractionDigits","parseFloat","Number","parseUnit","unit","exec","Text","DEFAULT_SVG_FONT_SIZE","falseFunction","getKlass","namespace","string","camelize","charAt","toUpperCase","slice","resolveNamespace","getSvgAttributes","attributes","parts","split","loadImage","crossOrigin","createImage","onLoadCallback","onload","onerror","src","substring","loadImageInDom","div","createElement","position","appendChild","querySelector","parentNode","removeChild","enlivenObjects","reviver","enlivenedObjects","numLoadedObjects","numTotalObjects","onLoaded","klass","fromObject","enlivenObjectEnlivables","enlivenProps","Object","ENLIVEN_PROPS","map","enlivedProps","enlivenPatterns","patterns","numLoadedPatterns","numPatterns","enlivenedPatterns","pattern","groupSVGElements","elements","path","sourcePath","centerPoint","Group","populateWithProperties","destination","properties","Array","isArray","createCanvasElement","copyCanvasElement","newCanvas","toDataURL","canvasEl","format","quality","multiplyTransformMatrices","is2x2","qrDecompose","denom","skewX","skewY","translateX","translateY","calcRotateMatrix","theta","calcDimensionsMatrix","scaleMatrix","flipX","flipY","tan","composeMatrix","matrix","resetObjectTransform","rotate","saveObjectTransform","isTransparent","tolerance","temp","_isTransparent","imageData","getImageData","l","parsePreserveAspectRatioAttribute","attribute","align","meetOrSlice","alignX","alignY","aspectRatioAttrs","pop","clearFabricFontCache","fontFamily","toLowerCase","limitDimsByArea","ar","maximumArea","roughWidth","perfLimitSizeY","capValue","findScaleToFit","findScaleToCover","matrixToSVG","NUM_FRACTION_DIGITS","join","removeTransformFromObject","inverted","finalTransform","calcOwnMatrix","applyTransformToObject","addTransformToObject","center","setPositionByOrigin","sizeAfterTransform","dimX","dimY","transformMatrix","bbox","mergeClipPaths","c1","c2","calcTransformMatrix","clipPath","hasStyleChanged","prevStyle","thisStyle","forTextSpans","fontWeight","fontStyle","textBackgroundColor","deltaY","overline","underline","linethrough","stylesToArray","styles","text","clone","textLines","charIndex","stylesArray","c","keys","styleChanged","start","end","stylesFromArray","styleIndex","stylesObject","assign","_join","prototype","commandLengths","m","h","q","repeatedCommands","M","segmentToBezier","th2","th3","cosTh","sinTh","cx1","cy1","mT","fromX","fromY","costh2","sinth2","costh3","sinth3","toX","toY","cp1X","cp1Y","cp2X","cp2Y","arcToSegments","large","sweep","rotateX","th","abs","px","py","rx2","ry2","py2","px2","pl","root","cx","cy","mTheta","calcVectorAngle","dtheta","segments","ceil","result","mDelta","ux","uy","vx","vy","ta","tb","getBoundsOfCurve","x0","y0","x1","y1","x2","y2","x3","y3","argsString","t1","t2","b2ac","sqrtb2ac","tvalues","bounds","mt","j","jlen","fromArcToBeziers","fx","fy","rot","tx","ty","segsNorm","makePathSimpler","converted","previous","controlX","controlY","destinationPath","calcLineLength","CB1","CB2","CB3","CB4","getPointOnCubicBezierIterator","p1x","p1y","p2x","p2y","p3x","p3y","p4x","p4y","pct","c3","c4","getTangentCubicIterator","invT","tangentX","tangentY","QB1","QB2","QB3","getPointOnQuadraticBezierIterator","getTangentQuadraticIterator","pathIterator","iterator","perc","tempP","tmpLen","findPercentageForDistance","segInfo","distance","nextLen","lastPerc","nextStep","angleFinder","getPathSegmentsInfo","tempInfo","totalLength","info","command","destX","destY","getPointOnPath","infos","segPercent","segment","lerp","parsePath","pathString","currentPath","parsed","match","coordsStr","re","rNumber","rNumberCommaWsp","rFlagCommaWsp","rArcSeq","regArcArgumentSequence","RegExp","coordsParsed","trim","args","isNaN","commandLength","repeatedCommand","k","klen","getSmoothPathFromPoints","correction","p1","p2","multSignX","multSignY","manyPoints","eq","midPoint","midPointFrom","transformPath","pathOffset","pathSegment","newSegment","joinPath","pathData","invoke","method","byProperty","find","value1","value2","condition","extend","Element","hasOwnProperty","replace","character","capitalize","firstLetterOnly","escapeXml","graphemeSplit","textstring","chr","graphemes","getWholeChar","str","code","charCodeAt","next","prev","emptyFunction","IS_DONTENUM_BUGGY","toString","addMethods","parent","superclass","constructor","returnValue","valueOf","Subclass","callSuper","methodName","parentMethod","_this","superClassMethod","createClass","initialize","shift","subclasses","couldUseAttachEvent","attachEvent","touchEvents","getTouchInfo","touchProp","changedTouches","addListener","addEventListener","removeListener","removeEventListener","getPointer","scroll","getScrollLeftTop","_evt","clientX","clientY","isTouchEvent","pointerType","setStyle","elementStyle","cssText","setOpacity","normalizedProperty","styleFloat","setProperty","parseEl","supportsOpacity","opacity","supportsFilters","reOpacity","es","currentStyle","hasLayout","zoom","test","_slice","getById","id","getElementById","sliceCanConvertNodelists","getElementStyle","toArray","arrayLike","childNodes","makeElement","tagName","el","className","htmlFor","setAttribute","addClass","wrapElement","wrapper","replaceChild","docElement","documentElement","body","scrollLeft","scrollTop","host","nodeType","getElementOffset","docElem","scrollLeftTop","doc","ownerDocument","box","offset","offsetAttributes","borderLeftWidth","borderTopWidth","paddingLeft","paddingTop","attr","parseInt","getBoundingClientRect","clientLeft","clientTop","getNodeCanvas","impl","_canvas","_image","cleanUpJsdomNode","_currentSrc","_attributes","_classList","setImageSmoothing","imageSmoothingEnabled","webkitImageSmoothingEnabled","mozImageSmoothingEnabled","msImageSmoothingEnabled","oImageSmoothingEnabled","arr","defaultView","getComputedStyle","selectProp","makeElementUnselectable","onselectstart","unselectable","makeElementSelectable","addParamToUrl","param","emptyFn","request","onComplete","xhr","XMLHttpRequest","parameters","onreadystatechange","readyState","open","setRequestHeader","send","warn","RUNNING_ANIMATIONS","noop","defaultEasing","d","animate","cancel","removeFromRegistry","runningAnimations","currentValue","startValue","completionRate","durationRate","requestAnimFrame","timestamp","time","Date","duration","finish","onChange","abort","easing","isMany","endValue","byValue","onStart","tick","ticktime","currentTime","timePerc","_value","valuePerc","cancelAll","animations","animation","cancelByCanvas","cancelled","cancelByTarget","findAnimationsByTarget","findAnimationIndex","cancelFunc","findAnimation","_requestAnimFrame","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","_cancelAnimFrame","cancelAnimationFrame","clearTimeout","cancelAnimFrame","calculateColor","begin","pos","animateColor","fromColor","toColor","startColor","Color","getSource","endColor","originalOnComplete","originalOnChange","posValue","colorEasing","normalize","asin","elastic","opts","easeOutCubic","easeInOutCubic","easeInQuart","easeOutQuart","easeInOutQuart","easeInQuint","easeOutQuint","easeInOutQuint","easeInSine","easeOutSine","easeInOutSine","easeInExpo","easeOutExpo","easeInOutExpo","easeInCirc","easeOutCirc","easeInOutCirc","easeInElastic","easeOutElastic","easeInOutElastic","easeInBack","easeOutBack","easeInOutBack","easeInBounce","easeOutBounce","easeInOutBounce","ease","easeInQuad","easeOutQuad","easeInOutQuad","easeInCubic","svgValidTagNames","svgViewBoxElements","svgInvalidAncestors","svgValidParents","attributesMap","display","visibility","colorAttributes","fSize","cPath","normalizeAttr","normalizeValue","parentAttributes","parseTransformAttribute","visible","fillIndex","strokeIndex","getSvgRegex","_setStrokeFillOpacity","setAlpha","getAlpha","toRgba","_getMultipleNodes","nodeNames","nodeName","nodeList","nodeArray","getElementsByTagName","parseStyleString","oStyle","chunk","pair","parseStyleObject","getGlobalStylesForElement","svgUid","rule","cssRules","elementMatchesRule","selectors","firstMatching","parentMatching","selectorMatches","doesSomeParentMatch","selector","matcher","classNames","getAttribute","elementById","node","nodelist","parseUseDirectives","xlinkAttribute","xlink","el2","cloneNode","currentTrans","oldLength","applyViewboxTransform","el3","createElementNS","setAttributeNS","nodeValue","firstChild","removeAttribute","svgValidTagNamesRegEx","svgViewBoxElementsRegEx","svgInvalidAncestorsRegEx","svgValidParentsRegEx","gradientDefs","clipPaths","rotateMatrix","multiplierX","multiplierY","skewMatrix","translateMatrix","transforms","transformList","reTransformList","reTransform","attributeValue","matrices","operation","combinedMatrix","reViewBoxAttrValue","viewBoxWidth","viewBoxHeight","viewBoxAttr","widthAttr","heightAttr","preserveAspectRatio","missingViewBox","missingDimAttr","toBeParsed","parsedDim","widthDiff","heightDiff","hasAncestorWithNodeName","recursivelyParseGradientsXlink","gradient","gradientsAttrs","xlinkAttr","xLink","referencedGradient","hasAttribute","children","referenceClone","parseSVGDocument","parsingOptions","__uid","descendants","selectNodes","getGradientDefs","getCSSRules","parseElements","instances","reFontDeclaration","parseFontDeclaration","lineHeight","tagArray","elList","parseAttributes","parentFontSize","ownAttributes","cssAttrs","parseStyleAttribute","normalizedAttr","normalizedValue","normalizedStyle","font","mergedAttrs","ElementsParser","parse","parsePointsAttribute","parsedPoints","rules","allRules","styleContents","textContent","ruleObj","declaration","propertyValuePairs","_rule","loadSVGFromURL","xml","responseXML","results","_options","allElements","loadSVGFromString","parser","parseFromString","regexUrl","proto","numElements","createObjects","createObject","findTag","fromElement","createCallback","checkIfDone","resolveGradient","Image","_originalElement","_removeTransformMatrix","resolveClipPath","extractPropertyDefinition","storage","regex","lastIndex","gradientDef","opacityAttr","createClipPathCallback","container","_newObj","fillRule","clipRule","usingElement","objTransformInv","gTransform","clipPathTag","clipPathOwner","that","scalarAdd","scalarAddEquals","subtractEquals","scalarSubtract","scalarSubtractEquals","multiplyEquals","divide","divideEquals","lt","lte","gt","gte","distanceFrom","dx","dy","setXY","setX","setY","setFromPoint","swap","Intersection","appendPoint","appendPoints","intersectLineLine","a1","a2","b1","b2","uaT","ubT","uB","ua","ub","intersectLinePolygon","inter","intersectPolygonPolygon","points1","points2","intersectPolygonRectangle","r1","r2","topRight","bottomLeft","inter1","inter2","inter3","inter4","_tryParsingColor","setSource","hue2rgb","colorNameMap","sourceFromHex","sourceFromRgb","sourceFromHsl","_rgbToHsl","round","_source","toRgb","toHsl","hsl","toHsla","toHex","toHexa","toGrayscale","average","currentAlpha","toBlackWhite","threshold","overlayWith","otherColor","otherAlpha","otherSource","reRGBa","reHSLa","reHex","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgrey","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgrey","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen","fromRgb","fromSource","fromRgba","fromHsl","fromHsla","fromHex","isShortNotation","isRGBa","oColor","scaleMap","skewMap","controls","LEFT","TOP","RIGHT","BOTTOM","CENTER","opposite","bottom","right","findCornerQuadrant","fabricObject","control","cornerAngle","fireEvent","canvasOptions","scaleIsProportional","eventData","uniScaleKey","uniformIsToggled","uniformScaling","isTransformCentered","originX","originY","scalingIsForbidden","by","scaleProportionally","lockX","lockScalingX","lockY","lockScalingY","scaleCursorStyleHandler","notAllowed","n","skewCursorStyleHandler","lockSkewingY","lockSkewingX","scaleSkewCursorStyleHandler","altActionKey","scaleOrSkewActionName","isAlternative","rotationStyleHandler","lockRotation","cursorStyle","commonEventInfo","e","pointer","wrapWithFixedAnchor","actionHandler","getCenterPoint","constraint","translateToOriginPoint","actionPerformed","wrapWithFireEvent","getLocalPoint","corner","getZoom","padding","localPoint","toLocalPoint","offsetX","offsetY","targetHasOneFlip","compensateScaleForSkew","oppositeSkew","scaleToCompensate","axis","reference","newDim","_getTransformedDimensions","newValue","skewObjectX","newSkew","dimNoSkew","totalSkewSize","currentSkew","hasSkewed","dimBeforeSkewing","skewObjectY","skewHandlerX","localPointFromCenter","finalHandler","skewHandlerY","rotationWithSnapping","pivotPoint","lastAngle","ey","ex","curAngle","hasRotated","snapAngle","snapThreshold","rightAngleLocked","leftAngleLocked","scaleObject","dim","signX","signY","forbidScaling","gestureScale","lockScalingFlip","original","originalDistance","oldScaleX","oldScaleY","scaleObjectFromCorner","scaleObjectX","scaleObjectY","scalingYOrSkewingX","scalingY","scalingXOrSkewingY","scalingX","changeWidth","strokePadding","multiplier","oldWidth","newWidth","dragHandler","newLeft","newTop","moveX","moveY","scalingEqually","controlsUtils","renderCircleControl","styleOverride","xSize","sizeX","cornerSize","ySize","sizeY","transparentCorners","cornerStrokeColor","myLeft","myTop","save","fillStyle","cornerColor","strokeStyle","lineWidth","beginPath","arc","restore","renderSquareControl","xSizeBy2","ySizeBy2","strokeRect","Control","actionName","touchSizeX","touchSizeY","withConnection","mouseDownHandler","mouseUpHandler","getActionHandler","getMouseDownHandler","getMouseUpHandler","cursorStyleHandler","getActionName","getVisibility","controlKey","objectVisibility","_controlsVisibility","setVisibility","positionHandler","finalMatrix","calcCornerCoords","objectAngle","objectCornerSize","centerX","centerY","isTouch","cosHalfOffset","sinHalfOffset","cosHalfOffsetComp","sinHalfOffsetComp","controlTriangleAngle","cornerHypotenuse","newTheta","newThetaComp","tl","tr","bl","br","cornerStyle","getColorStop","colorAlpha","keyValuePairs","getLinearCoords","getRadialCoords","__convertPercentUnitsToValues","instance","svgOptions","gradientUnits","propValue","finalValue","gradientTransform","option","addColorStop","toObject","propertiesToInclude","toSVG","markup","commonAttributes","needsSwap","withViewport","additionalTransform","sort","reverse","minRadius","maxRadius","percentageShift","colorStop","toLive","createLinearGradient","createRadialGradient","colorStopEls","repeat","patternTransform","setOptions","isError","patternSource","patternWidth","patternHeight","patternOffsetX","patternOffsetY","patternImgSrc","complete","naturalWidth","naturalHeight","createPattern","Shadow","blur","affectStroke","includeDefaultValues","nonScaling","_parseShadow","shadow","shadowStr","offsetsAndBlur","reOffsetsAndBlur","fBoxX","fBoxY","BLUR_BOX","StaticCanvas","CANVAS_INIT_ERROR","Error","renderAndResetBound","renderAndReset","requestRenderAllBound","_initStatic","backgroundColor","backgroundImage","overlayColor","overlayImage","stateful","controlsAboveOverlay","allowTouchScrolling","viewportTransform","backgroundVpt","overlayVpt","enableRetinaScaling","vptCoords","skipOffscreen","cb","_createLowerCanvas","_initOptions","interactive","_initRetinaScaling","setOverlayImage","setBackgroundImage","setBackgroundColor","setOverlayColor","calcOffset","_isRetinaScaling","getRetinaScaling","scaleRatio","__initRetinaScaling","lowerCanvasEl","contextContainer","upperCanvasEl","contextTop","_offset","__setBgOverlayImage","__setBgOverlayColor","_createCanvasElement","_originalCanvasStyle","_applyCanvasStyle","getWidth","getHeight","setWidth","setDimensions","setHeight","dimensions","cssValue","cssOnly","_setBackstoreDimension","hasLostContext","backstoreOnly","_setCssDimension","_isCurrentlyDrawing","freeDrawingBrush","_setBrushStyles","cacheCanvasEl","wrapperEl","setViewportTransform","vpt","activeObject","_activeObject","backgroundObject","overlayObject","group","setCoords","calcViewportBoundaries","zoomToPoint","before","after","setZoom","absolutePan","relativePan","getElement","setupState","clearContext","clearRect","clear","_hasITextHandlers","_mouseUpITextHandler","_iTextInstances","renderAll","canvasToDrawOn","renderCanvas","isRendering","iVpt","cancelRequestedRender","_renderBackground","_renderObjects","drawControls","shouldCache","_transformDone","renderCache","forClipping","drawClipPathOnCanvas","_renderOverlay","globalCompositeOperation","zoomX","zoomY","_cacheCanvas","cacheTranslationX","cacheTranslationY","_renderBackgroundOrOverlay","needsVpt","moveTo","lineTo","closePath","getCenter","centerObjectH","_centerObject","centerObjectV","centerObject","viewportCenterObject","vpCenter","getVpCenter","viewportCenterObjectH","viewportCenterObjectV","toDatalessJSON","toDatalessObject","_toObjectMethod","_toObjects","excludeFromExport","_toObject","__serializeBgOverlay","originalValue","bgImage","background","overlay","svgViewportTransformation","_setSVGPreamble","_setSVGHeader","clipPathId","_setSVGBgOverlayColor","_setSVGBgOverlayImage","_setSVGObjects","suppressPreamble","encoding","viewBox","createSVGFontFacesMarkup","createSVGRefElementsMarkup","createSVGClipPathMarkup","toClipPathSVG","shouldTransform","row","rowIndex","_char","fontList","_setSVGObject","finalWidth","finalHeight","shouldInvert","sendToBack","objs","activeSelection","unshift","bringToFront","sendBackwards","intersecting","newIdx","objsMoved","_findNewLowerIndex","isIntersecting","intersectsWithObject","isContainedWithinObject","bringForward","_findNewUpperIndex","dispose","classList","DataURLExporter","EMPTY_JSON","supports","setLineDash","toJSON","createPNGStream","createJPEGStream","BaseBrush","strokeLineCap","strokeDashArray","limitedToCanvasSize","lineCap","miterLimit","lineJoin","_saveAndTransform","_setShadow","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY","needsFullRender","_resetShadow","_isOutSideCanvas","PencilBrush","decimate","drawStraightLine","straightLineKey","_points","_hasStraightLine","_drawSegment","quadraticCurveTo","onMouseDown","_isMainEvent","_prepareForDrawing","_captureDrawingPath","_render","onMouseMove","oldEnd","onMouseUp","_finalizeAndAddPath","_reset","_addPoint","pointerPoint","convertPointsToSVGPath","_isEmptySVGPath","createPath","Path","decimatePoints","cDistance","adjustedDistance","lastPoint","newPoints","CircleBrush","drawDot","addPoint","dot","originalRenderOnAddRemove","circles","circle","Circle","circleRadius","circleColor","SprayBrush","density","dotWidth","dotWidthVariance","randomOpacity","optimizeOverlapping","sprayChunks","addSprayChunk","sprayChunkPoints","rects","ilen","sprayChunk","rect","Rect","_getOptimizedRects","uniqueRects","uniqueRectsArray","globalAlpha","fillRect","PatternBrush","getPatternSrc","dotDistance","patternCanvas","patternCtx","getPatternSrcFunction","String","getPattern","topLeft","_getLeftTopCoords","_initInteractive","_createCacheCanvas","centeredScaling","centeredRotation","centeredKey","selection","selectionKey","altSelectionKey","selectionColor","selectionDashArray","selectionBorderColor","selectionLineWidth","selectionFullyContained","hoverCursor","moveCursor","defaultCursor","freeDrawingCursor","notAllowedCursor","containerClass","perPixelTargetFind","targetFindTolerance","skipTargetFind","preserveObjectStacking","stopContextMenu","fireRightClick","fireMiddleClick","targets","enablePointerEvents","_hoveredTarget","_hoveredTargets","_currentTransform","_groupSelector","_initWrapperElement","_createUpperCanvas","_initEventListeners","_chooseObjectsToRender","objsToRender","activeGroupObjects","getActiveObjects","contextTopDirty","renderTopLayer","_drawSelection","renderTop","_normalizePointer","invertedM","vptPointer","restorePointerVpt","isTargetTransparent","normalizedPointer","targetRelativeX","targetRelativeY","_cacheContext","contextCache","originalColor","selectionBackgroundColor","_isSelectionKeyPressed","selectionKeyPressed","_shouldClearSelection","_shouldCenterTransform","action","altKey","centerTransform","_getOriginFromCorner","_getActionFromCorner","alreadySelected","_setupCurrentTransform","__corner","lastX","lastY","shiftKey","_beforeTransform","setCursor","cursor","viewportStart","viewportExtent","extent","strokeOffset","_setLineDash","findTarget","skipGroup","activeTarget","activeTargetSubs","ignoreZoom","aObjects","shouldLookForActive","_findTargetCorner","_searchPossibleTargets","_checkTarget","globalPointer","containsPoint","isEditing","subTarget","objToCheck","pointerToUse","subTargetCheck","_absolutePointer","_pointer","cssScale","boundsWidth","boundsHeight","retinaScaling","lowerCanvasClass","_copyCanvasStyle","getTopContext","fromEl","toEl","getSelectionContext","getSelectionElement","getActiveObject","active","_discardActiveObject","_fireSelectionEvents","oldObjects","somethingChanged","added","removed","oldObject","selected","deselected","setActiveObject","currentActives","_setActiveObject","onSelect","onDeselect","discardActiveObject","removeListeners","_renderControls","originalProperties","_realizeGroupTransformOnObject","_unwindGroupTransformOnObject","layoutProps","originalValues","clearContextTop","RIGHT_CLICK","MIDDLE_CLICK","LEFT_CLICK","addEventOptions","passive","checkClick","button","mainTouchId","_bindEvents","addOrRemove","_getEventPrefix","functor","eventjsFunctor","canvasElement","eventTypePrefix","_onResize","_onMouseDown","_onMouseMove","_onMouseOut","_onMouseEnter","_onMouseWheel","_onContextMenu","_onDoubleClick","_onDragOver","_onDragEnter","_onDragLeave","_onDrop","_onTouchStart","eventjs","_onGesture","_onDrag","_onOrientationChange","_onShake","_onLongPress","_onMouseUp","_onTouchEnd","eventsBound","_simpleEventHandler","self","__onTransformGesture","__onDrag","__onMouseWheel","_target","__onOrientationChange","__onShake","__onLongPress","_fireEnterLeaveEvents","stopPropagation","_cacheTransformEventData","_handleEvent","_resetTransformEventData","getPointerId","evt","identifier","pointerId","isPrimary","touches","__onMouseDown","__onMouseUp","_willAddMouseDown","__onMouseMove","_shouldRender","groupSelector","shouldRender","isClick","_onMouseUpInDrawingMode","_finalizeCurrentTransform","targetWasActive","_maybeGroupObjects","activeOn","isMoving","originalControl","originalMouseUpHandler","_setCursorFromEvent","eventType","subTargets","absolutePointer","currentTarget","currentSubTargets","_scaling","hasStateChanged","_fire","_onMouseDownInDrawingMode","_onMouseMoveInDrawingMode","_previousPointer","shouldGroup","_shouldGroup","_handleGrouping","saveState","_transformObject","_fireOverOutEvents","fireSyntheticInOutEvents","oldTarget","evtOut","canvasEvtOut","evtIn","canvasEvtIn","_draggedoverTarget","config","inOpt","outOpt","outFires","inFires","targetChanged","previousTarget","nextTarget","reset","_performTransformAction","getCornerCursor","_updateActiveSelection","_createActiveSelection","currentActiveObjects","removeWithUpdate","addWithUpdate","_createGroup","isActiveLower","groupObjects","exitEditing","ActiveSelection","_groupSelectedObjects","aGroup","_collectObjects","currentObject","selectionX1Y1","selectionX2Y2","allowIntersect","intersectsWithRect","isContainedWithinRect","toCanvasElement","cropping","scaledWidth","scaledHeight","originalWidth","originalHeight","newZoom","vp","originalInteractive","newVp","originalRetina","originalContextTop","loadFromJSON","json","serialized","JSON","_enlivenObjects","_setBgOverlay","enlivenedCanvasClip","__setupCanvas","loaded","cbIfLoaded","__setBgOverlay","enlivedObject","_toDataURL","_toDataURLWithMultiplier","toDataURLWithMultiplier","stringify","cloneWithoutData","backgroundImageOpacity","backgroundImageStretch","objectCaching","ALIASING_LIMIT","touchCornerSize","borderColor","borderDashArray","cornerDashArray","strokeDashOffset","borderOpacityWhenMoving","borderScaleFactor","minScaleLimit","hasControls","hasBorders","lockMovementX","lockMovementY","statefullCache","noScaleCache","dirty","paintFirst","stateProperties","cacheProperties","colorProperties","absolutePositioned","_cacheProperties","_updateCacheCanvas","_limitCacheSize","dims","limitedDims","capped","_getCacheCanvasDimensions","objectScale","getTotalObjectScaling","neededX","neededY","drawingWidth","drawingHeight","minCacheSize","dimensionsChanged","cacheWidth","cacheHeight","zoomChanged","shouldRedraw","additionalWidth","additionalHeight","shouldResizeCanvas","canvasWidth","canvasHeight","sizeGrowing","sizeShrinking","getHeightOfLine","setTransform","needFullTransform","_removeDefaultValues","getObjectScaling","retina","getObjectOpacity","shouldConstrainValue","isChanged","groupNeedsUpdate","_constrainScale","isOnACache","setOnGroup","getViewportTransform","isNotVisible","isOnScreen","_setupCompositeOperation","drawSelectionBackground","_setOpacity","drawCacheOnCanvas","_removeCacheCanvas","drawObject","propertySet","isCacheDirty","hasStroke","hasFill","needsItsOwnCache","ownCaching","willDrawShadow","drawClipPathOnCache","originalFill","originalStroke","_setClippingProperties","_drawClipPath","skipCanvas","_getNonTransformedDimensions","_removeShadow","_setStrokeStyles","decl","lineDashOffset","_applyPatternForTransformedGradient","_applyPatternGradientTransform","_setFillStyles","dashArray","drawBorders","forActiveSelection","drawBordersInGroup","scaling","multX","multY","_renderPaintInOrder","_renderStroke","_renderFill","pCtx","pCanvas","_findCenterFromElement","_assignTransformMatrixProps","preserveAspectRatioOptions","cropX","cropY","offsetLeft","offsetTop","objectForm","_fromObject","cloneAsImage","utils","origParams","originalGroup","originalShadow","withoutTransform","withoutShadow","boundingRect","getBoundingRect","shadowOffset","originalCanvas","isType","includes","shouldCenterOrigin","_setOriginToCenter","_resetOrigin","centerH","viewportCenterH","centerV","viewportCenterV","viewportCenter","getLocalPointer","pClicked","objectLeftTop","createAccessors","extraParam","originXOffset","originYOffset","translateToGivenOrigin","fromOriginX","fromOriginY","toOriginX","toOriginY","translateToCenterPoint","leftTop","getPointByOrigin","adjustPosition","offsetFrom","offsetTo","hypotFull","getScaledWidth","xFull","yFull","_originalOriginX","_originalOriginY","originPoint","arrayFromCoords","multiplyMatrices","oCoords","aCoords","lineCoords","ownMatrixCache","matrixCache","_getCoords","absolute","calculate","calcACoords","calcLineCoords","getCoords","pointTL","pointBR","intersection","other","otherCoords","lines","_getImageLines","_findCrossPoints","_containsCenterOfCanvas","isPartiallyOnScreen","allPointsAreOutside","every","topline","rightline","bottomline","leftline","xi","iLine","xcount","lineKey","getScaledHeight","scaleToWidth","boundingRectFactor","scaleToHeight","cosP","sinP","cosPSinP","cosPMinusSinP","calcOCoords","_calcRotateMatrix","_calcTranslateMatrix","startMatrix","_calculateCurrentDimensions","forEachControl","w","skipCorners","_setCornerCoords","transformMatrixKey","sep","prefix","cache","tMatrix","noSkew","_finalizeDimensions","getSvgColorString","getSvgStyles","skipShadow","getSvgFilter","getSvgSpanStyles","useWhiteSpace","term","textDecoration","getSvgTextDecoration","decoration","getSvgCommons","getSvgTransform","full","svgTransform","_setSVGBg","textBgRects","_getFillAttributes","_createBaseSVGMarkup","_toSVG","_createBaseClipPathSVGMarkup","objectMarkup","commonPieces","clipPathMarkup","noStyle","styleInfo","shadowInfo","withShadow","vectorEffect","absoluteClipPath","addPaintOrder","originalSet","saveProps","tmpObj","_isEqual","origValue","firstPass","dashedPropertySet","forTouch","isControlVisible","touchCorner","fn","controlObject","wh","shouldStroke","setControlVisible","setControlsVisibility","FX_DURATION","fxCenterObjectH","callbacks","empty","fxCenterObjectV","fxRemove","skipCallbacks","propsToAnimate","out","_animate","propPair","propIsColor","valueProgress","timeProgress","coordProps","makeEdgeToOriginGetter","propertyNames","originValues","axis1","axis2","dimension","nearest","farthest","Line","_setWidthHeight","_getLeftToOriginX","_getTopToOriginY","calcLinePoints","origStrokeStyle","xMult","yMult","ATTRIBUTE_NAMES","parsedAttributes","_callback","isValidRadius","startAngle","endAngle","setRadius","svgString","startX","startY","endX","endY","largeFlag","getRadiusX","getRadiusY","Triangle","widthBy2","heightBy2","piBy2","Ellipse","getRx","getRy","_initRxRy","isRounded","bezierCurveTo","Polyline","exactBoundingBox","_setPositionDimensions","_projectStrokeOnPoints","correctLeftTop","calcDim","_calcDimensions","correctSize","fromSVG","diffX","diffY","commonRender","fromElementGenerator","_class","Polygon","_setPath","_renderPathCommands","subpathStartX","subpathStartY","_getOffsetTransform","digits","aX","aY","deltaX","pathUrl","elivenedObjects","useSetOnGroup","isAlreadyGrouped","_updateObjectsACoords","_calcBounds","_updateObjectsCoords","skipControls","_updateObjectCoords","objectLeft","objectTop","nested","_restoreObjectsState","_includeDefaultValues","objsToObject","originalDefaults","_obj","ownCache","groupMatrix","destroy","toActiveSelection","ungroupOnCanvas","setObjectsCoords","onlyWidthHeight","iLen","jLen","_getBounds","minXY","maxXY","toGroup","newGroup","childrenOverride","srcFromAttribute","_lastScaleX","_lastScaleY","_filterScalingX","_filterScalingY","minimumScaleTrigger","cacheKey","imageSmoothing","filters","_initElement","_element","setElement","removeTexture","_initConfig","applyFilters","resizeFilter","applyResizeFilters","backend","filterBackend","evictCachesForKey","getCrossOrigin","getOriginalSize","_stroke","filterObj","getSrc","hasCrop","strokeSvg","imageMarkup","imageRendering","getSvgSrc","origFill","filtered","setSrc","minimumScale","elementToFilter","_filteredEl","sourceWidth","sourceHeight","isNeutralState","imgElement","_needsResize","elementToDraw","elWidth","elHeight","sX","sY","sW","sH","maxDestW","maxDestH","_resetWidthHeight","CSS_CANVAS","_initFilters","pAR","rWidth","rHeight","pWidth","pHeight","_object","resizeFilters","fromURL","imgOptions","_getAngleValueForStraighten","straighten","fxStraighten","straightenObject","fxStraightenObject","testPrecision","precision","fragmentSource","fragmentShader","createShader","FRAGMENT_SHADER","shaderSource","compileShader","getShaderParameter","COMPILE_STATUS","setupGLContext","captureGPUInfo","isSupported","getParameter","MAX_TEXTURE_SIZE","precisions","webGlPrecision","createWebGLCanvas","aPosition","Float32Array","chooseFastestCopyGLTo2DMethod","canUseImageData","canMeasurePerf","performance","canUseArrayBuffer","ArrayBuffer","canUseUint8Clamped","copyGLTo2D","startTime","drawImageTime","putImageDataTime","testContext","now","glOptions","premultipliedAlpha","depth","stencil","antialias","clearColor","cachedTexture","getCachedTexture","sourceTexture","createTexture","targetTexture","originalTexture","passes","webgl","programCache","pass","tempFbo","createFramebuffer","bindFramebuffer","FRAMEBUFFER","applyTo","bindTexture","TEXTURE_2D","deleteTexture","deleteFramebuffer","clearWebGLCaches","textureCache","textureImageSource","filterType","texture","texParameteri","TEXTURE_MAG_FILTER","NEAREST","TEXTURE_MIN_FILTER","TEXTURE_WRAP_S","CLAMP_TO_EDGE","TEXTURE_WRAP_T","texImage2D","uniqueId","gpuInfo","renderer","vendor","ext","getExtension","UNMASKED_RENDERER_WEBGL","UNMASKED_VENDOR_WEBGL","sourceElement","originalImageData","originalEl","BaseFilter","vertexSource","createProgram","vertexShader","VERTEX_SHADER","getShaderInfoLog","program","attachShader","linkProgram","getProgramParameter","LINK_STATUS","getProgramInfoLog","attributeLocations","getAttributeLocations","uniformLocations","getUniformLocations","uStepW","getUniformLocation","uStepH","getAttribLocation","sendAttributeData","aPositionData","attributeLocation","buffer","createBuffer","bindBuffer","ARRAY_BUFFER","enableVertexAttribArray","vertexAttribPointer","FLOAT","bufferData","STATIC_DRAW","_setupFrameBuffer","framebufferTexture2D","COLOR_ATTACHMENT0","_swapTextures","main","mainParameter","applyToWebGL","applyTo2d","retrieveShader","shader","useProgram","uniform1f","sendUniformData","viewport","drawArrays","TRIANGLE_STRIP","bindAdditionalTexture","textureUnit","activeTexture","TEXTURE0","unbindAdditionalTexture","getMainParameter","setMainParameter","createHelpLayer","helpLayer","mainP","ColorMatrix","colorsOnly","uColorMatrix","uConstants","constants","uniformMatrix4fv","uniform4fv","Brightness","brightness","uBrightness","Convolute","opaque","Convolute_3_1","Convolute_3_0","Convolute_5_1","Convolute_5_0","Convolute_7_1","Convolute_7_0","Convolute_9_1","Convolute_9_0","dstOff","scx","scy","srcOff","wt","weights","side","halfSide","sw","sh","output","createImageData","dst","alphaFac","uMatrix","uOpaque","uHalfSize","uSize","uniform1fv","Grayscale","lightness","luminosity","mode","uMode","uniform1i","Invert","invert","uInvert","Noise","noise","rand","uNoise","uSeed","Pixelate","blocksize","_i","_j","_iLen","_jLen","uBlocksize","RemoveColor","useAlpha","lowC","highC","uLow","uHigh","Brownie","Vintage","Kodachrome","Technicolor","Polaroid","Sepia","BlackWhite","BlendColor","screen","diff","lighten","darken","exclusion","tint","buildSource","tg","alpha1","uColor","BlendImage","mask","TEXTURE1","calculateMatrix","canvas1","blendData","blendImage","uTransformMatrix","uImage","uniformMatrix3fv","Resize","resizeType","lanczosLobes","uDelta","uTaps","uniform2fv","horizontal","taps","filterWindow","getFilterWindow","generateShader","tempScale","getTaps","lobeFunction","lanczosCreate","offsets","fragmentSourceTOP","dW","dH","lobes","xx","rcpScaleX","rcpScaleY","newData","oW","oH","sliceByTwo","hermiteFastResize","bilinearFiltering","lanczosResize","tmpCanvas","mult","doneW","doneH","stepW","stepH","dX","dY","process","u","weight","fX","fY","ratioX","icenter","ratioY","range2X","cacheLanc","range2Y","lanczos","rcpRatioX","rcpRatioY","srcData","destData","destImg","xDiff","yDiff","chnl","origPix","w4","pixels","destImage","destPixels","ratioW","ratioH","ratioWHalf","ratioHHalf","img2","data2","weightsAlpha","gxR","gxG","gxB","gxA","yy","w0","Contrast","contrast","contrastF","uContrast","Saturation","saturation","adjust","uSaturation","Vibrance","vibrance","avg","amt","uVibrance","Blur","aspectRatio","simpleBlur","canvas2","blurLayer1","blurLayer2","percent","ctx1","ctx2","nSamples","newImageData","delta","chooseRightDelta","blurScale","Gamma","gamma","rInv","gInv","bInv","rVals","gVals","bVals","uGamma","uniform3fv","Composed","subFilters","HueRotation","rotation","rad","aThird","aThirdSqtSin","OneMinusCos","additionalProps","_dimensionAffectingProps","_reNewline","_reSpacesAndTabs","_reSpaceAndTab","_reWords","textAlign","superscript","baseline","subscript","pathStartOffset","pathSide","pathAlign","_fontSizeFraction","_fontSizeMult","charSpacing","_measuringContext","direction","_styleProperties","__charBounds","CACHE_FONT_SIZE","MIN_TEXT_WIDTH","__skipDimension","setPathInfo","initDimensions","segmentsInfo","getMeasuringContext","_splitText","newLines","_splitTextIntoLines","_textLines","graphemeLines","_unwrappedTextLines","_unwrappedLines","_text","graphemeText","_clearCache","calcTextWidth","cursorWidth","calcTextHeight","enlargeSpaces","diffSpace","currentLineWidth","numberOfSpaces","accumulatedSpace","line","charBound","spaces","isEndOfWrapping","getLineWidth","kernedWidth","lineIndex","missingNewlineOffset","_setTextStyles","_renderTextLinesBackground","_renderTextDecoration","_renderText","_renderTextStroke","_renderTextFill","charStyle","forMeasuring","textBaseline","_getFontDeclaration","maxWidth","_renderTextLine","_renderChars","styleHas","heightOfLine","lineLeftOffset","lastColor","charBox","currentColor","drawStart","leftOffset","_getLeftOffset","lineTopOffset","_getTopOffset","boxStart","boxWidth","_getLineLeftOffset","getValueOfPropertyAt","renderLeft","getFontCache","cacheProp","_measureChar","previousChar","prevCharStyle","coupleWidth","previousWidth","fontCache","fontDeclaration","previousFontDeclaration","couple","stylesAreEqual","fontMultiplier","measureText","getHeightOfChar","measureLine","lineInfo","_measureLine","_getWidthOfCharSpacing","grapheme","prevGrapheme","graphemeInfo","startingPoint","totalPathLength","numOfSpaces","lineBounds","positionInPath","_getGraphemeBox","_setGraphemeOnPath","centerPosition","skipLeft","getCompleteStyleDeclaration","previousBox","__lineHeights","maxHeight","_renderTextCommon","lineHeights","isEmptyStyles","actualStyle","nextStyle","timeToRender","drawingLeft","isJustify","charsToRender","shortCut","isLtr","currentDirection","_renderChar","_applyPatternGradientTransformText","handleFiller","fillOffsets","strokeOffsets","_getStyleDeclaration","fullDecl","shouldFill","fillText","strokeText","setSuperscript","_setScript","setSubscript","schema","loc","get2DCursorLocation","setSelectionStyles","lineDiff","__lineWidths","_shouldClearDimensionCache","shouldClear","_forceClearCache","_size","_dy","lastDecoration","currentDecoration","currentFill","lastFill","topOffset","styleObject","family","fontIsGeneric","genericFonts","newLine","newText","allProperties","needsDims","isAddingPath","_key","parsedAnchor","textAnchor","originalStrokeWidth","textHeightScaleFactor","lineHeightDiff","scaledDiff","textHeight","offX","objectCopy","textInstance","pathInstance","p3","0","cleanStyle","letterCount","stylePropertyValue","stylesCount","allStyleObjectPropertiesMatch","graphemeCount","stylePropertyHasBeenSet","removeStyle","lineNum","charNum","_extendStyles","_getLineStyle","_setLineStyle","_setStyleDeclaration","selectionStart","skipWrapping","getSelectionStyles","startIndex","endIndex","selectionEnd","getStyleAtPosition","lineStyle","_deleteStyleDeclaration","_deleteLineStyle","parseDecoration","IText","editable","editingBorderColor","cursorColor","cursorDelay","cursorDuration","caching","hiddenTextareaContainer","_reSpace","_currentCursorOpacity","_selectionDirection","_abortCursorAnimation","__widthOfSpace","inCompositionMode","initBehavior","setSelectionStart","_updateAndFire","setSelectionEnd","_fireSelectionChanged","_updateTextarea","initDelayedCursor","cursorOffsetCache","renderCursorOrSelection","skipRestore","_clearTextArea","boundaries","_getCursorBoundaries","renderCursor","renderSelection","_getCursorBoundariesOffsets","cursorPosition","bound","cursorLocation","charHeight","__isMousedown","hiddenTextarea","startLine","endLine","startChar","endChar","lineOffset","realLineHeight","boxEnd","drawWidth","drawHeight","extraTop","compositionColor","getCurrentCharFontSize","cp","_getCurrentCharIndex","getCurrentCharColor","objCopy","initAddedHandler","initRemovedHandler","initCursorSelectionHandlers","initDoubleClickSimulation","mouseMoveHandler","_initCanvasHandlers","_removeCanvasHandlers","_tick","_currentTickState","_animateCursor","targetOpacity","completeMethod","tickState","isAborted","_onTickComplete","_cursorTimeout1","_currentTickCompleteState","restart","delay","abortCursorAnimation","_cursorTimeout2","selectAll","getSelectedText","findWordBoundaryLeft","startFrom","findWordBoundaryRight","findLineBoundaryLeft","findLineBoundaryRight","searchWordBoundary","selectWord","newSelectionStart","newSelectionEnd","selectLine","enterEditing","exitEditingOnOthers","initHiddenTextarea","focus","_saveEditingProps","_setEditingProps","_textBeforeEdit","initMouseMoveHandler","activeElement","getSelectionStartFromPointer","currentStart","currentEnd","__selectionStartOnMouseDown","restartCursorIfNeeded","fromStringToGraphemeSelection","smallerTextStart","graphemeStart","smallerTextEnd","graphemeEnd","fromGraphemeToStringSelection","newSelection","updateTextareaPosition","updateFromTextArea","_calcTextareaPosition","desiredPosition","compositionStart","upperCanvas","upperCanvasWidth","upperCanvasHeight","clientWidth","clientHeight","_savedProps","_restoreEditingProps","isTextChanged","_removeExtraneousStyles","removeStyleFromTo","styleObj","cursorStart","cursorEnd","lineStart","charStart","lineEnd","charEnd","shiftLineStyles","numericChar","clonedStyles","numericLine","insertNewlineStyleObject","qty","copiedStyle","currentCharStyle","newLineStyles","someStyleIsCarryingOver","originalLineLength","isEndOfLine","numIndex","styleCarriedOver","insertCharStyleObject","quantity","currentLineStyles","currentLineStylesCloned","numericIndex","newStyle","insertNewStyleBlock","insertedText","cursorLoc","addedLines","linesLength","setSelectionStartEndWithShift","setSelectionInBoundaries","__lastClickTime","__lastLastClickTime","__lastPointer","__newClickTime","newPointer","isTripleClick","_stopEvent","__lastIsEditing","__lastSelected","initMousedownHandler","initMouseupHandler","initClicks","doubleClickHandler","tripleClickHandler","_mouseDownHandler","setCursorByClick","_mouseDownHandlerBefore","currentActive","mouseOffset","prevWidth","_getNewSelectionStartFromOffset","distanceBtwLastCharAndCursor","distanceBtwNextCharAndCursor","onKeyDown","onKeyUp","onInput","copy","paste","onCompositionStart","onCompositionUpdate","onCompositionEnd","_clickHandlerInitialized","onClick","keysMap","9","27","33","34","35","36","37","38","39","40","keysMapRtl","ctrlKeysMapUp","67","88","ctrlKeysMapDown","65","keyMap","keyCode","ctrlKey","metaKey","stopImmediatePropagation","_copyDone","fromPaste","removedText","removeFrom","removeTo","nextText","charCount","nextCharCount","charDiff","textareaSelection","backDelete","copiedText","copiedTextStyle","compositionEnd","_getClipboardData","clipboardData","_getWidthBeforeCursor","widthBeforeCursor","getDownCursorOffset","isRight","selectionProp","_getSelectionForOffset","indexOnOtherLine","_getIndexOnLine","textAfterCursor","getUpCursorOffset","textBeforeCursor","charWidth","foundMatch","widthOfCharsOnLine","indexOnLine","leftEdge","rightEdge","offsetFromLeftEdge","offsetFromRightEdge","moveCursorDown","_moveCursorUpOrDown","moveCursorUp","moveCursorWithShift","moveCursorWithoutShift","moveCursorLeft","_moveCursorLeftOrRight","_move","_moveLeft","_moveRight","moveCursorLeftWithoutShift","change","moveCursorLeftWithShift","moveCursorRight","moveCursorRightWithShift","moveCursorRightWithoutShift","changed","removeChars","insertChars","multipleSpacesRegex","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","lineTop","noShadow","textSpans","textTopOffset","textLeftOffset","_setSVGTextLineBg","_setSVGTextLineText","_createTextCharSpan","styleDecl","shouldUseWhitespace","styleProps","fillStyles","dySpan","_pushTextBgRect","fillColor","_getSVGLineTopOffset","lastHeight","svgStyle","Textbox","minWidth","dynamicMinWidth","__cachedLines","_wordJoiners","splitByGrapheme","_styleMap","_generateStyleMap","textInfo","realLineCount","realLineCharCount","isWrapping","nextOffset","nextLineIndex","shouldLimit","mapNextLine","_wrapText","desiredWidth","wrapped","_wrapLine","_measureWord","word","charOffset","_line","reservedSpace","words","infix","wordWidth","infixWidth","largestWordWidth","lineJustStarted","additionalSpace","getMinWidth","linesToKeep","scaleSkewStyleHandler","scaleStyleHandler","objectControls","ml","mr","mb","mtr","textBoxControls"],"mappings":"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AG,IAAI,CAACE,YAAY,uBAAuB,CAACJ,EAAIY,GAAG,qBAClI,WAAY,IAAIZ,EAAIC,KAAKC,EAAGF,EAAIG,MAAMD,GAAG,OAAOA,EAAG,MAAM,CAACiB,MAAM,CAAC,GAAK,QAAQ,CAACjB,EAAG,SAAS,CAACiB,MAAM,CAAC,GAAK,SAAS,OAAS,a,YC6F7G,GACfoE,YACAG,eAEAC,OACA,OACAuB,iBACAF,iBACAU,kBACA/G,cACAiF,aACA+B,YACAC,iBACAH,gBACAnD,gCACAuD,mCACAC,oBACAC,iBACAR,0BAGAxB,4DACAI,UACA6B,qDAEAhC,UACA,oBACA,6CACA,sCACA,wCACA,kBACA,wCAEA,oDACAgC,sDACA,4DACA,8DAEAC,gBACA,qDACA,6DACA,8DACAD,yDACAA,wDAEA5B,SACAkB,WACA,mBAEA,qCACA,sBACA,wBAGA,yBAEA,qBACA,sBACA,sBACA,uBACA,0BAEAY,iBACA,kBACA,uBAGAC,eACA,qCACA,wCACA,sBACA,mBAEA,mBAEA,yBAEAC,mBACA,cACA,sCACA,0CAGAC,oBACAC,gCACA,oBACA,YAAAC,SAAAC,GAAA,EACA,uCACA,MACA,IACAC,oCAEAA,kCAEAA,OACAC,8CACAC,+CACAC,cACAC,aAEA,mBACA,0BACA,sBAGA9B,kBACA,sBACA,sBACA,6BACA,qBACA,yBAaA+B,qBAIA,GAHA,uBAEA,2BACA,8CACA,8BACA,MACA,oCACA,0BACAJ,SACAC,QACAI,YACAC,wBACAJ,gBAEA,mBAEA,uBAGAzB,wBACA,sBAEA,oBAEA,6BACA,yEACA,sCACA,mDACA,qDAEA,8BAGAF,oBACA,sBACA,oBACA,6BACA,sDACA,qCACA,mDACA,qDAEA,8BAUAG,YACA,sBACA,sBACA,6BACA,mBACA,6BAEA,SACAsB,SACAC,QACAM,0BACAC,cACAN,eAGA,MAEA,UACA,WACAO,2BACA,EACAH,mBACAT,UACAC,aAEA,MAEA,YACAW,qBACA,MAEA,aACAA,6BACA,EACAH,mBACAI,YAEA,MAEA,WACAD,6CACA,IAEA,MAIA,IACA,mBACA,+BACA,0BAGAE,cACA,sEACAL,mBACAC,0BACAC,cACAR,SACAC,QACAC,cACAC,cAGAS,eACA,QAAAC,IAAAC,IAaA,OAXA,cACAC,yBACAF,yBACAC,0BAGA,eACAC,yBACAF,yBACAC,0BAEA,gCAEAhC,cAIA,GAHA,qBACA,uDAEA,oBACA,8CACA,qCAEA,sBACA,kCACA,mDACA,oEACA,qDAEA,yBAIA,2BACA,gCACA,iDACA,kEACA,mDAEA,0BAGAkC,wBAEA,8BAEAC,sBACA,0BAEAtC,iBACA,uCAEA,aACAuC,cACA,wBAEA,kCACA,0BAGAzF,cACA,qBACA,8CACAwC,YACAjE,MACAwB,2BACA0C,UAGAxC,cACA,8CACA,qDACA,+BACA,uBAGAkC,iBACA,uBACA,8BACA,8CACA,4BACA,oBACA,2BACAuD,qBAEA,sBAAAnD,SACAD,UCvamX,ICQ/W,G,UAAY,eACd,EACA,EACA,GACA,EACA,KACA,WACA,OAIa,I,4CCiIXqD,EAAS,EAAQ,QAON,GACfvE,YACAwE,cACAC,cACAtE,cACAuE,eACAC,eAEAvE,OACA,OACA1E,UACAH,WACA8B,gBACAuH,aACA7G,kBACAD,mBACAP,WACAD,YACAuH,gBACAhH,uCACAD,mBACAJ,gBACAzC,WACAG,aACAE,cACAS,UACAiJ,YACA5I,cACA6I,YACAvJ,cACAwJ,cACAC,kBACAC,eAGAtE,UACA6B,4DAEA0C,YACA1C,+DAEAhC,UACA,2BAEA,yBACA,0BAEA,sBAEA,4CACA,mBACA,wCAEA,gBACA,2BACA,iBACA,oEAEA,QAIA,iBACA,iCACA,8BAEA,6BACA,6BAEA,0BAIA,+CAEA,gBACA,2BACA,iBACA,oEAEA,QAIA,iBACA,iCACA,8BAEA,6BACA,4BAEA,0BAKAiC,gBACA,sCACA,8CAEA7B,SACAuE,sBAGA,uCACA,kDACA,mBACA,qCAIAC,cACA,kCAAAC,UAAAC,uBACAC,yBACA,kBACA,gBACAC,IACA,gBACA,oBACA,kBACA,sBACA,cACA,iBAEA,sBAGA,gBACA,oCAEA,kBACA,iBACA,kCAAAH,UAAAC,cAEAG,IACA,iCAAAtH,aAAAmH,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","file":"js/chunk-e1e54948.97f8ed95.js","sourcesContent":["module.exports = __webpack_public_path__ + \"img/ZizbeyJobsLogo.6dbee2ac.svg\";","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',[_c('div',{staticClass:\"h-screen px-2 overflow-hidden\"},[_vm._m(0),(!_vm.ShowErr)?_c('div',{staticClass:\"py-2 overflow-auto\",style:(`max-height:` + _vm.cardHeight + `px;overflow: auto; !important`)},[_c('div',{staticClass:\"card bg-white rounded-xl p-4 my-2\"},[_c('div',{staticClass:\"mb-2\",class:!_vm.movileView ? '' : 'flex items-center justify-between'},[_c('div',{},[_c('div',{staticClass:\"text-primary heading-5 font-semibold\"},[_vm._v(_vm._s(_vm.jrtitle)),_c('span',{staticClass:\"pl-1 text-gray4 heading-7\"},[_vm._v(\"(\"+_vm._s(_vm.isFromName === 'job' ? 'Job' : 'Request')+\")\")])]),_c('div',{staticClass:\"text-text2 heading-7 font-semibold\"},[_c('i',{staticClass:\"fas fa-calendar pr-1\"}),_vm._v(_vm._s(_vm._f(\"dateTimeFilter\")(_vm.jrDate)))])]),_c('Button',{class:!_vm.movileView ? 'pt-2 text-right justify-end' : '',staticStyle:{\"letter-spacing\":\"1.4px\"},attrs:{\"isSqure\":true,\"disabled\":_vm.images.length === 0,\"btnSize\":'small',\"textColor\":'white',\"btnColor\":'primary',\"btnText\":'Send Attachment'},on:{\"buttonAction\":function($event){return _vm.saveButton()}}})],1),_c('div',{staticClass:\"text-text2 heading-5 font-semibold\"},[_vm._v(\"Provide Related Details: Upload Images:\")]),_c('div',{staticClass:\"py-4 pt-4\"},[_c('p',{staticClass:\"label_css\"},[_vm._v(\"Attachments:\")]),_c('div',{staticClass:\"cursor-pointer\",class:['dropzone', { 'dragging': _vm.isDragging }],on:{\"drop\":function($event){$event.preventDefault();return _vm.handleDrop.apply(null, arguments)},\"dragover\":function($event){$event.preventDefault();return _vm.handleDragOver.apply(null, arguments)},\"dragleave\":_vm.handleDragLeave,\"click\":_vm.triggerFileInput}},[_c('input',{ref:\"fileInput\",staticClass:\"hidden\",attrs:{\"type\":\"file\",\"accept\":\"image/*, video/*\",\"multiple\":\"\"},on:{\"change\":_vm.handleFiles}}),_vm._v(\" Drag & Drop images here or click to select \")])]),_c('div',{staticClass:\"pt-4\"},[(_vm.images.length > 0)?_c('p',{staticClass:\"label_css\"},[_vm._v(\"Preview: (\"+_vm._s(_vm.images.length)+\")\")]):_vm._e(),_c('div',{staticClass:\"flex flex-wrap gap-6 pt-2\"},_vm._l((_vm.images),function(image,index){return _c('div',{key:index,staticClass:\"image-card card border border-gray2 rounded-md p-1 w-52 h-52 flex flex-col items-center relative\"},[_c('div',{staticClass:\"text-white heading-5 cursor-pointer bg-error px-3 py-1 opacity-90 rounded-full absolute right-1 top-1\",on:{\"click\":function($event){return _vm.removeImage(index)}}},[_c('i',{staticClass:\"fa-solid fa-times\"})]),(image.type2 === 'image')?_c('div',{staticClass:\"text-white heading-5 cursor-pointer bg-primary px-3 py-1 opacity-90 rounded-full absolute right-10 top-1\",on:{\"click\":function($event){return _vm.editImage(index)}}},[_c('i',{staticClass:\"fa-solid fa-pen-to-square\"})]):_vm._e(),_c('div',{staticClass:\"w-full h-full\"},[(image.type2 === 'image')?_c('img',{staticClass:\"w-full h-full object-cover\",staticStyle:{\"object-fit\":\"contain\",\"height\":\"150px\"},attrs:{\"src\":image.url,\"alt\":\"image preview\"}}):_vm._e(),(image.type2 === 'video')?_c('div',{staticClass:\"flex items-center justify-center w-full h-full bg-gray-200\"},[_c('i',{staticClass:\"fas fa-play text-4xl text-white\"})]):_vm._e()]),_c('div',{staticClass:\"text-center text-sm text-text2 mt-2\",staticStyle:{\"line-break\":\"anywhere\"}},[_vm._v(_vm._s(image.name))])])}),0)])])]):_vm._e(),(_vm.ShowErr)?_c('div',[_c('div',{staticClass:\"bg-gray-200 w-full px-2 md:px-0 h-screen flex items-center justify-center\"},[_c('div',{staticClass:\"bg-white border border-gray-200 flex flex-col items-center justify-center px-20 py-8 rounded-lg shadow-2xl\"},[(_vm.displayTitle === 'Detail Submitted.')?_c('p',{staticClass:\"text-6xl md:text-7xl lg:text-6xl font-bold tracking-wider text-gray-300\"},[_c('i',{staticClass:\"fa-solid fa-check fa-fade\"})]):_vm._e(),(_vm.displayTitle !== 'Detail Submitted.')?_c('p',{staticClass:\"text-6xl md:text-7xl lg:text-6xl font-bold tracking-wider text-red-400\"},[_c('i',{staticClass:\"fa-solid fa-times fa-fade\"})]):_vm._e(),_c('p',{staticClass:\"text-gray-500 mt-3 py-2 border-y-2 text-center\"},[_vm._v(_vm._s(_vm.displayTitle))])])])]):_vm._e(),(_vm.isExpire)?_c('div',{staticClass:\"popup_overlay\"},[_c('div',{staticClass:\"bg-gray-200 w-full px-2 md:px-0 h-screen flex items-center justify-center\"},[_c('div',{staticClass:\"bg-white border border-gray-200 flex flex-col items-center justify-center px-20 py-8 rounded-lg shadow-2xl\"},[_vm._m(1),_c('p',{staticClass:\"text-gray-500 mt-3 py-2 border-y-2 text-center\"},[_vm._v(\"Link has Expired at \"+_vm._s(_vm._f(\"formatTime\")(_vm.apiData)))])])])]):_vm._e()]),(_vm.showEditFunc)?_c('div',{staticClass:\"bg-screen_bg card popup_overlay\"},[_c('div',{staticClass:\"custom_dialog\",style:(`width: 100%; overflow: auto; height:100vh;`)},[_vm._m(2),_c('div',{staticClass:\"card bg-white rounded-xl p-4 m-4 pt-0 mt-2 mb-2\"},[_c('div',{},[_c('div',{staticClass:\"mb-2\",class:!_vm.movileView ? '' : 'flex items-center justify-between'},[_c('div',{staticClass:\"text-text2 font-semibold heading-4\"},[_vm._v(\"Image Modifier\")]),_c('div',{staticClass:\"flex items-center\",class:!_vm.movileView ? 'pt-1 text-right justify-end' : ''},[_c('Button',{attrs:{\"btnSize\":'medium',\"textColor\":'text1',\"btnColor\":'gray1',\"btnText\":'Reset & Close'},on:{\"buttonAction\":function($event){return _vm.closeBtn(0)}}}),_c('Button',{staticClass:\"pl-2\",attrs:{\"btnSize\":'medium',\"textColor\":'white',\"btnColor\":'primary',\"btnText\":'Save & Close'},on:{\"buttonAction\":function($event){return _vm.closeBtn(1)}}})],1)]),_c('div',{staticClass:\"flex items-center pt-2\"},[_c('Button',{staticStyle:{\"letter-spacing\":\"1.4px\"},attrs:{\"iconClass\":'fas fa-crop',\"isSqure\":true,\"btnSize\":'small',\"textColor\":'white',\"btnColor\":'primary',\"btnText\":'Crop Image'},on:{\"buttonAction\":function($event){return _vm.cropStart()}}}),_c('Button',{staticClass:\"pl-2\",staticStyle:{\"letter-spacing\":\"1.4px\"},attrs:{\"iconClass\":'fas fa-pencil',\"isSqure\":true,\"btnSize\":'small',\"textColor\":'white',\"btnColor\":'primary',\"btnText\":'Edit Image'},on:{\"buttonAction\":function($event){return _vm.cropStart2()}}})],1)])]),(_vm.selectedImage.type2 === 'image')?_c('div',{staticClass:\"card bg-white rounded-xl p-4 m-4 mt-0 flex justify-center\"},[(_vm.selectedImage)?_c('img',{style:(!_vm.movileView ? '`width: auto`' : `width: auto;max-height: 100%;height:` + _vm.imageDivHeight2 + `px;`),attrs:{\"src\":_vm.selectedImage.url,\"alt\":\"Selected image\"}}):_vm._e()]):_vm._e(),(_vm.selectedImage.type2 === 'video')?_c('div',{staticClass:\"card bg-white rounded-xl p-4 m-4 mt-0 flex justify-center\"},[(_vm.selectedImage)?_c('video',{staticClass:\"mt-1\",style:(`width: 100%;height:` + _vm.imageDivHeight2 + `px;`),attrs:{\"id\":\"myVideo\",\"autoplay\":\"\",\"controls\":\"\"}},[_c('source',{staticClass:\"ma-0\",attrs:{\"type\":\"video/mp4\",\"align\":\"center\",\"justify\":\"center\",\"src\":_vm.selectedImage.url}})]):_vm._e()]):_vm._e()]),(_vm.showLogoCropper)?_c('div',{attrs:{\"fullscreen\":\"\"}},[(_vm.showLogoCropper)?_c('imageCroper',{attrs:{\"entityName\":_vm.selectedImage.name,\"imageToCrop\":_vm.selectedImage.url,\"title\":'Image Crop',\"ratio\":4/4}}):_vm._e()],1):_vm._e(),(_vm.showLogoEditor)?_c('div',{attrs:{\"fullscreen\":\"\"}},[(_vm.showLogoEditor)?_c('imageEditor',{attrs:{\"entityName\":_vm.selectedImage.name,\"imageToCrop\":_vm.selectedImage.url,\"title\":'Image Editor',\"ratio\":4/4}}):_vm._e()],1):_vm._e()]):_vm._e(),(_vm.$store.getters.showLoader)?_c('loader',{attrs:{\"data\":_vm.$store.getters.loaderMessage}}):_vm._e(),(_vm.$store.getters.showAlert)?_c('snak-bar',{attrs:{\"status\":_vm.$store.getters.showAlert,\"message\":_vm.$store.getters.alertMessage,\"color\":_vm.$store.getters.alertColor}}):_vm._e()],1)\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"card top_primary_card font-bold text-gray1 p-3 rounded-xl w-full\"},[_c('div',{staticClass:\"flex items-start justify-start pl-4\"},[_c('img',{attrs:{\"src\":require(\"@/assets/images/ZizbeyJobsLogo.svg\")}}),_c('div',{staticClass:\"heading-2 text-primary font-semibold pl-1\"},[_vm._v(\"ZizbeyJobs\")])])])\n},function (){var _vm=this,_c=_vm._self._c;return _c('p',{staticClass:\"text-6xl md:text-7xl lg:text-6xl font-bold tracking-wider text-red-400\"},[_c('i',{staticClass:\"fa-solid fa-triangle-exclamation fa-fade\"})])\n},function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"card top_primary_card font-bold text-gray1 p-1 m-4 rounded-xl\"},[_c('div',{staticClass:\"flex items-start justify-start pl-4\"},[_c('img',{attrs:{\"src\":require(\"@/assets/images/ZizbeyJobsLogo.svg\")}}),_c('div',{staticClass:\"heading-2 text-primary font-semibold pl-1\"},[_vm._v(\"ZizbeyJobs\")])])])\n}]\n\nexport { render, staticRenderFns }","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"bg-white shadow-xl border-l-2 cust_card border-gray-100\",staticStyle:{\"position\":\"fixed\",\"height\":\"100%\",\"width\":\"100%\",\"min-width\":\"80px\",\"z-index\":\"100\",\"top\":\"0\",\"overflow-x\":\"hidden\",\"overflow-y\":\"auto\",\"transition\":\"0.5s\",\"border-radius\":\"0px !important\",\"right\":\"0\"}},[_c('div',{staticClass:\"px-5 py-2 bg-primary text-white heading-2 font-bold flex flex-wrap items-center justify-between\"},[_c('div',[_c('p',{staticClass:\"mb-2 flex flex-wrap\"},[_vm._v(_vm._s(_vm.title)+\": \"),(_vm.entityName !== undefined && _vm.entityName !== '')?_c('span',{staticClass:\"whitespace-nowrap ml-1\"},[_vm._v(_vm._s(_vm.entityName))]):_vm._e()])]),_c('div',{staticClass:\"flex gap-4 mb-2\"},[_c('Button',{attrs:{\"btnSize\":'medium',\"textColor\":'text1',\"btnColor\":'gray1',\"btnText\":'Discard'},on:{\"buttonAction\":function($event){return _vm.emitData(false)}}}),_c('Button',{attrs:{\"btnSize\":'medium',\"textColor\":'white',\"btnColor\":'success',\"btnText\":'Save'},on:{\"buttonAction\":_vm.uploadImage}})],1)]),_c('div',{attrs:{\"wrap\":\"\"}},[(_vm.showClipper)?_c('div',{staticClass:\"flex flex-wrap md:flex-nowrap p-4 gap-4\",style:(_vm.innerWidth > 800 ? `display: flex` : '')},[_c('div',{staticClass:\"imageDiv\",style:(`width:${_vm.innerWidth > 500 ? _vm.innerWidth > 800 ? 800 : _vm.innerWidth : _vm.innerWidth}px`)},[_vm._m(0),_c('div',{staticClass:\"divider\"}),_c('clipperFixed',{ref:\"clipper\",staticClass:\"my-clipper\",staticStyle:{\"height\":\"400px\"},attrs:{\"bg-color\":_vm.bgColor,\"ratio\":_vm.ratio,\"crossorigin\":'anonymous',\"src\":_vm.imageToCrop,\"rotate\":_vm.rotateDegree,\"area\":_vm.areaVal,\"preview\":\"my-preview\"}},[_c('div',{staticClass:\"placeholder\",attrs:{\"slot\":\"placeholder\"},slot:\"placeholder\"},[_vm._v(\"No image\")])]),_c('div',{staticClass:\"py-3\",attrs:{\"flat\":\"\"}},[_c('div',{staticClass:\"flex items-center justify-between\",attrs:{\"wrap\":\"\"}},[_c('div',{staticClass:\"pa-2 displayFlex\",attrs:{\"xl8\":\"\",\"md8\":\"\",\"sm6\":\"\",\"xs6\":\"\",\"lg8\":\"\"}},[_c('div',{staticClass:\"cursor-pointer\",on:{\"click\":function($event){_vm.rotateDegree -= 10}}},[_c('i',{staticClass:\"mx-2 fas fa-undo\"})]),_c('div',{staticStyle:{\"width\":\"50px\"}},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.rotateDegree),expression:\"rotateDegree\"}],staticClass:\"outline-none border border-gray-500 text-gray-900 text-sm rounded focus:border-gray-800 block w-full pl-2 p-2.5 h-12 heading-4\",attrs:{\"autocomplete\":\"new-password\",\"type\":\"\",\"maxlength\":\"100\",\"placeholder\":\"Login Password\"},domProps:{\"value\":(_vm.rotateDegree)},on:{\"input\":function($event){if($event.target.composing)return;_vm.rotateDegree=$event.target.value}}})]),_c('div',{staticClass:\"cursor-pointer\",on:{\"click\":function($event){_vm.rotateDegree += 10}}},[_c('i',{staticClass:\"mx-2 fas fa-redo\"})])]),_c('div'),_c('div',{staticClass:\"text-right displayFlex pr-2\",staticStyle:{\"justify-content\":\"flex-end\",\"align-items\":\"stretch\"},attrs:{\"xl4\":\"\",\"lg4\":\"\",\"md4\":\"\",\"sm6\":\"\",\"xs6\":\"\"}},[_c('div',{staticClass:\"p-2 pb-0\"},[_c('div',{staticClass:\"colorDiv\",staticStyle:{\"background-color\":\"black\"},on:{\"click\":function($event){_vm.bgColor = '#000000'}}}),(_vm.bgColor === '#000000')?_c('span',[_c('i',{staticClass:\"mx-1 h-5 w-5 fas fa-check text-primary\",attrs:{\"small\":\"\",\"color\":\"\"}})]):_vm._e()]),_c('div',{staticClass:\"p-2 pb-0\"},[_c('div',{staticClass:\"colorDiv\",staticStyle:{\"background-color\":\"white\"},on:{\"click\":function($event){_vm.bgColor = '#ffffff'}}}),(_vm.bgColor === '#ffffff')?_c('span',[_c('i',{staticClass:\"mx-1 h-5 w-5 fas fa-check text-primary\",attrs:{\"small\":\"\",\"color\":\"\"}})]):_vm._e()]),_c('div',{staticClass:\"ml-3\",staticStyle:{\"align-self\":\"center\"}},[_c('span',{on:{\"click\":_vm.zoomIn}},[_c('i',{staticClass:\"mx-1 fas fa-search-plus text-text2 h-5 w-5\",attrs:{\"small\":\"\"}})]),_vm._v(\" / \"),_c('span',{on:{\"click\":_vm.zoomOut}},[_c('i',{staticClass:\"mx-1 fas fa-search-minus text-text2 h-5 w-5\",attrs:{\"small\":\"\"}})])])])])])],1),_c('div',{staticClass:\"previewDiv\",style:(`width:${_vm.innerWidth > 800 ? 350 : _vm.innerwidth < 400 ? _vm.innerWidth : 300}px`)},[_vm._m(1),_c('div',{staticClass:\"divider\"}),_c('clipperPreview',{staticClass:\"my-clipper\",attrs:{\"name\":\"my-preview\",\"crossorigin\":'anonymous'}},[_c('div',{staticClass:\"placeholder\",attrs:{\"slot\":\"placeholder\"},slot:\"placeholder\"},[_vm._v(\"preview area\")])])],1)]):_vm._e()])])\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"p-2 flex justify-between\",attrs:{\"wrap\":\"\"}},[_c('div',{staticClass:\"heading-2\"},[_vm._v(\" Image \")])])\n},function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"p-2\"},[_c('h3',{staticClass:\"heading-2\"},[_vm._v(\"Preview\")])])\n}]\n\nexport { render, staticRenderFns }","\n\n","import mod from \"-!../../../../node_modules/cache-loader/dist/cjs.js??ref--13-0!../../../../node_modules/thread-loader/dist/cjs.js!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./imageCroper.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../node_modules/cache-loader/dist/cjs.js??ref--13-0!../../../../node_modules/thread-loader/dist/cjs.js!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./imageCroper.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./imageCroper.vue?vue&type=template&id=5594bef0&scoped=true&\"\nimport script from \"./imageCroper.vue?vue&type=script&lang=js&\"\nexport * from \"./imageCroper.vue?vue&type=script&lang=js&\"\nimport style0 from \"./imageCroper.vue?vue&type=style&index=0&id=5594bef0&prod&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"5594bef0\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"bg-white shadow-xl border-l-2 cust_card border-rgray-100\",staticStyle:{\"position\":\"fixed\",\"height\":\"100%\",\"width\":\"100%\",\"min-width\":\"80px\",\"z-index\":\"100\",\"top\":\"0\",\"overflow-x\":\"hidden\",\"overflow-y\":\"auto\",\"transition\":\"0.5s\",\"border-radius\":\"0px !important\",\"right\":\"0\"}},[_c('div',{staticClass:\"px-5 py-2 bg-primary text-white heading-2 font-bold flex flex-wrap items-center justify-between\"},[_vm._m(0),_c('div',{staticClass:\"flex gap-4 mb-2\"},[_c('Button',{attrs:{\"btnSize\":'medium',\"textColor\":'text1',\"btnColor\":'gray1',\"btnText\":'Discard'},on:{\"buttonAction\":function($event){return _vm.emitData(false, null)}}}),_c('Button',{attrs:{\"btnSize\":'medium',\"textColor\":'white',\"btnColor\":'success',\"btnText\":'Save'},on:{\"buttonAction\":_vm.uploadImage}})],1)]),_c('div',{attrs:{\"wrap\":\"\"}},[_c('div',{staticClass:\"p-4\"},[_c('div',{staticClass:\"imageDiv\"},[_c('div',{staticClass:\"p-2 flex justify-between\",attrs:{\"wrap\":\"\"}},[_c('div',{staticClass:\"flex items-center\"},[_c('div',{staticClass:\"d_icon_child\"},[_c('span',{staticClass:\"text-white cursor-pointer bg-primary rounded-xl\",class:!_vm.movileView ? 'px-3 py-2 heading-4' : 'heading-6 py-2 px-2',on:{\"click\":function($event){return _vm.startAddingText()}}},[_c('i',{staticClass:\"fa-solid fa-font\"})]),_c('span',{staticClass:\"tooltiptext heading-4 bg-transparent whitespace-nowrap rounded w-32\"},[_vm._v(\"Add Text\")])]),_c('div',{staticClass:\"d_icon_child\"},[_c('span',{staticClass:\"text-white cursor-pointer ml-2 rounded-xl\",class:`${!_vm.movileView ? 'px-3 py-2 heading-4' : 'heading-6 py-2 px-2'} ${_vm.isDrawingMode ? 'bg-secondary' : 'bg-primary'}`,on:{\"click\":function($event){_vm.isDrawingMode = !_vm.isDrawingMode;_vm.enableDrawingMode()}}},[_c('i',{staticClass:\"fas fa-pencil\"})]),_c('span',{staticClass:\"tooltiptext heading-4 bg-transparent whitespace-nowrap rounded w-32\"},[_vm._v(\"Free Draw\")])]),_c('div',{staticClass:\"d_icon_child\"},[_c('span',{staticClass:\"text-white cursor-pointer ml-2 rounded-xl\",class:`${!_vm.movileView ? 'px-3 py-2 heading-4' : 'heading-6 py-2 px-2'} ${_vm.highLighterOn ? 'bg-secondary' : 'bg-primary'}`,on:{\"click\":function($event){_vm.highLighterOn = !_vm.highLighterOn;_vm.enableHighlighterMode()}}},[_c('i',{staticClass:\"fas fa-highlighter\"})]),_c('span',{staticClass:\"tooltiptext heading-4 bg-transparent whitespace-nowrap rounded w-32\"},[_vm._v(\"Highlighter\")])]),_c('div',{staticClass:\"d_icon_child\"},[_c('span',{staticClass:\"text-white cursor-pointer bg-primary ml-2 rounded-xl\",class:!_vm.movileView ? 'px-3 py-2 heading-4' : 'heading-6 py-2 px-2',on:{\"click\":function($event){return _vm.addShape('rect')}}},[_c('i',{staticClass:\"fa-regular fa-square-full\"})]),_c('span',{staticClass:\"tooltiptext heading-4 bg-transparent whitespace-nowrap rounded w-32\"},[_vm._v(\"Add Square\")])]),_c('div',{staticClass:\"d_icon_child\"},[_c('span',{staticClass:\"text-white cursor-pointer bg-primary ml-2 rounded-xl\",class:!_vm.movileView ? 'px-3 py-2 heading-4' : 'heading-6 py-2 px-2',on:{\"click\":function($event){return _vm.addShape('circle')}}},[_c('i',{staticClass:\"fa-regular fa-circle\"})]),_c('span',{staticClass:\"tooltiptext heading-4 bg-transparent whitespace-nowrap rounded w-32\"},[_vm._v(\"Add Circle\")])]),_c('div',{staticClass:\"d_icon_child\"},[_c('span',{staticClass:\"text-white cursor-pointer bg-primary ml-2 rounded-xl\",class:!_vm.movileView ? 'px-3 py-2 heading-4' : 'heading-6 py-2 px-2',on:{\"click\":function($event){return _vm.addShape('line')}}},[_c('i',{staticClass:\"fa-solid fa-minus\"})]),_c('span',{staticClass:\"tooltiptext heading-4 bg-transparent whitespace-nowrap rounded w-32\"},[_vm._v(\"Add Line\")])]),_c('div',{staticClass:\"d_icon_child\"},[_c('span',{staticClass:\"text-white cursor-pointer bg-primary ml-2 rounded-xl\",class:!_vm.movileView ? 'px-3 py-2 heading-4' : 'heading-6 py-2 px-2',on:{\"click\":function($event){return _vm.addShape('arrow')}}},[_c('i',{staticClass:\"fa-solid fa-arrow-right-long\"})]),_c('span',{staticClass:\"tooltiptext heading-4 bg-transparent whitespace-nowrap rounded w-32\"},[_vm._v(\"Add Arrow\")])]),_c('div',{staticClass:\"d_icon_child\"},[_c('span',{staticClass:\"text-white cursor-pointer bg-error ml-2 rounded-xl\",class:!_vm.movileView ? 'px-3 py-2 heading-4' : 'heading-6 py-2 px-2',on:{\"click\":_vm.deleteSelected}},[_c('i',{staticClass:\"fa-solid fa-trash-alt\"})]),_c('span',{staticClass:\"tooltiptext heading-4 bg-transparent whitespace-nowrap rounded w-40\"},[_vm._v(\"Remove Selection\")])]),_c('div',{staticClass:\"d_icon_child\"},[_c('span',{staticClass:\"text-white cursor-pointer bg-error ml-2 rounded-xl\",class:!_vm.movileView ? 'px-3 py-2 heading-4' : 'heading-6 py-2 px-2',on:{\"click\":_vm.clearAll}},[_c('i',{staticClass:\"fas fa-eraser\"})]),_c('span',{staticClass:\"tooltiptext heading-4 bg-transparent whitespace-nowrap rounded w-32\"},[_vm._v(\"Clear All\")])]),_c('div',{staticClass:\"pl-2\"},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.selectedColor),expression:\"selectedColor\"}],staticClass:\"cursor-pointer\",attrs:{\"type\":\"color\"},domProps:{\"value\":(_vm.selectedColor)},on:{\"input\":[function($event){if($event.target.composing)return;_vm.selectedColor=$event.target.value},_vm.updateColor]}})])])]),(_vm.isAddingText)?_c('div',{staticClass:\"pl-2 -mt-1.5 heading-6 text-error font-semibold\"},[_vm._v(\"*Click where you want to put text on the image.\")]):_vm._e(),_c('div',{staticClass:\"divider\"}),_vm._m(1)])])])])\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',[_c('p',{staticClass:\"mb-2 flex flex-wrap\"},[_vm._v(\"Image Editor\")])])\n},function (){var _vm=this,_c=_vm._self._c;return _c('div',{attrs:{\"id\":\"app\"}},[_c('canvas',{attrs:{\"id\":\"canvas\",\"height\":\"400\"}})])\n}]\n\nexport { render, staticRenderFns }","\n\n\n\n\n","import mod from \"-!../../../../node_modules/cache-loader/dist/cjs.js??ref--13-0!../../../../node_modules/thread-loader/dist/cjs.js!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./imageEditor.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../node_modules/cache-loader/dist/cjs.js??ref--13-0!../../../../node_modules/thread-loader/dist/cjs.js!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./imageEditor.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./imageEditor.vue?vue&type=template&id=59879977&scoped=true&\"\nimport script from \"./imageEditor.vue?vue&type=script&lang=js&\"\nexport * from \"./imageEditor.vue?vue&type=script&lang=js&\"\nimport style0 from \"./imageEditor.vue?vue&type=style&index=0&id=59879977&prod&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"59879977\",\n null\n \n)\n\nexport default component.exports","\n\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--13-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./requestJobInfo.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--13-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./requestJobInfo.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./requestJobInfo.vue?vue&type=template&id=7b21d213&scoped=true&\"\nimport script from \"./requestJobInfo.vue?vue&type=script&lang=js&\"\nexport * from \"./requestJobInfo.vue?vue&type=script&lang=js&\"\nimport style0 from \"./requestJobInfo.vue?vue&type=style&index=0&id=7b21d213&prod&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"7b21d213\",\n null\n \n)\n\nexport default component.exports","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--7-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--7-oneOf-1-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--7-oneOf-1-2!../../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./imageEditor.vue?vue&type=style&index=0&id=59879977&prod&scoped=true&lang=css&\"","/* build: `node build.js modules=ALL exclude=gestures,accessors,erasing requirejs minifier=uglifyjs` */\n/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */\n\nvar fabric = fabric || { version: '5.4.0' };\nif (typeof exports !== 'undefined') {\n exports.fabric = fabric;\n}\n/* _AMD_START_ */\nelse if (typeof define === 'function' && define.amd) {\n define([], function() { return fabric; });\n}\n/* _AMD_END_ */\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\n if (document instanceof (typeof HTMLDocument !== 'undefined' ? HTMLDocument : Document)) {\n fabric.document = document;\n }\n else {\n fabric.document = document.implementation.createHTMLDocument('');\n }\n fabric.window = window;\n}\nelse {\n // assume we're running under node.js when document/window are not present\n var jsdom = require('jsdom');\n var virtualWindow = new jsdom.JSDOM(\n decodeURIComponent('%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E'),\n {\n features: {\n FetchExternalResources: ['img']\n },\n resources: 'usable'\n }).window;\n fabric.document = virtualWindow.document;\n fabric.jsdomImplForWrapper = require('jsdom/lib/jsdom/living/generated/utils').implForWrapper;\n fabric.nodeCanvas = require('jsdom/lib/jsdom/utils').Canvas;\n fabric.window = virtualWindow;\n DOMParser = fabric.window.DOMParser;\n}\n\n/**\n * True when in environment that supports touch events\n * @type boolean\n */\nfabric.isTouchSupported = 'ontouchstart' in fabric.window || 'ontouchstart' in fabric.document ||\n (fabric.window && fabric.window.navigator && fabric.window.navigator.maxTouchPoints > 0);\n\n/**\n * True when in environment that's probably Node.js\n * @type boolean\n */\nfabric.isLikelyNode = typeof Buffer !== 'undefined' &&\n typeof window === 'undefined';\n\n/* _FROM_SVG_START_ */\n/**\n * Attributes parsed from all SVG elements\n * @type array\n */\nfabric.SHARED_ATTRIBUTES = [\n 'display',\n 'transform',\n 'fill', 'fill-opacity', 'fill-rule',\n 'opacity',\n 'stroke', 'stroke-dasharray', 'stroke-linecap', 'stroke-dashoffset',\n 'stroke-linejoin', 'stroke-miterlimit',\n 'stroke-opacity', 'stroke-width',\n 'id', 'paint-order', 'vector-effect',\n 'instantiated_by_use', 'clip-path',\n];\n/* _FROM_SVG_END_ */\n\n/**\n * Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion.\n */\nfabric.DPI = 96;\nfabric.reNum = '(?:[-+]?(?:\\\\d+|\\\\d*\\\\.\\\\d+)(?:[eE][-+]?\\\\d+)?)';\nfabric.commaWsp = '(?:\\\\s+,?\\\\s*|,\\\\s*)';\nfabric.rePathCommand = /([-+]?((\\d+\\.\\d+)|((\\d+)|(\\.\\d+)))(?:[eE][-+]?\\d+)?)/ig;\nfabric.reNonWord = /[ \\n\\.,;!\\?\\-]/;\nfabric.fontPaths = { };\nfabric.iMatrix = [1, 0, 0, 1, 0, 0];\nfabric.svgNS = 'http://www.w3.org/2000/svg';\n\n/**\n * Pixel limit for cache canvases. 1Mpx , 4Mpx should be fine.\n * @since 1.7.14\n * @type Number\n * @default\n */\nfabric.perfLimitSizeTotal = 2097152;\n\n/**\n * Pixel limit for cache canvases width or height. IE fixes the maximum at 5000\n * @since 1.7.14\n * @type Number\n * @default\n */\nfabric.maxCacheSideLimit = 4096;\n\n/**\n * Lowest pixel limit for cache canvases, set at 256PX\n * @since 1.7.14\n * @type Number\n * @default\n */\nfabric.minCacheSideLimit = 256;\n\n/**\n * Cache Object for widths of chars in text rendering.\n */\nfabric.charWidthsCache = { };\n\n/**\n * if webgl is enabled and available, textureSize will determine the size\n * of the canvas backend\n * @since 2.0.0\n * @type Number\n * @default\n */\nfabric.textureSize = 2048;\n\n/**\n * When 'true', style information is not retained when copy/pasting text, making\n * pasted text use destination style.\n * Defaults to 'false'.\n * @type Boolean\n * @default\n */\nfabric.disableStyleCopyPaste = false;\n\n/**\n * Enable webgl for filtering picture is available\n * A filtering backend will be initialized, this will both take memory and\n * time since a default 2048x2048 canvas will be created for the gl context\n * @since 2.0.0\n * @type Boolean\n * @default\n */\nfabric.enableGLFiltering = true;\n\n/**\n * Device Pixel Ratio\n * @see https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/SettingUptheCanvas.html\n */\nfabric.devicePixelRatio = fabric.window.devicePixelRatio ||\n fabric.window.webkitDevicePixelRatio ||\n fabric.window.mozDevicePixelRatio ||\n 1;\n/**\n * Browser-specific constant to adjust CanvasRenderingContext2D.shadowBlur value,\n * which is unitless and not rendered equally across browsers.\n *\n * Values that work quite well (as of October 2017) are:\n * - Chrome: 1.5\n * - Edge: 1.75\n * - Firefox: 0.9\n * - Safari: 0.95\n *\n * @since 2.0.0\n * @type Number\n * @default 1\n */\nfabric.browserShadowBlurConstant = 1;\n\n/**\n * This object contains the result of arc to bezier conversion for faster retrieving if the same arc needs to be converted again.\n * It was an internal variable, is accessible since version 2.3.4\n */\nfabric.arcToSegmentsCache = { };\n\n/**\n * This object keeps the results of the boundsOfCurve calculation mapped by the joined arguments necessary to calculate it.\n * It does speed up calculation, if you parse and add always the same paths, but in case of heavy usage of freedrawing\n * you do not get any speed benefit and you get a big object in memory.\n * The object was a private variable before, while now is appended to the lib so that you have access to it and you\n * can eventually clear it.\n * It was an internal variable, is accessible since version 2.3.4\n */\nfabric.boundsOfCurveCache = { };\n\n/**\n * If disabled boundsOfCurveCache is not used. For apps that make heavy usage of pencil drawing probably disabling it is better\n * @default true\n */\nfabric.cachesBoundsOfCurve = true;\n\n/**\n * Skip performance testing of setupGLContext and force the use of putImageData that seems to be the one that works best on\n * Chrome + old hardware. if your users are experiencing empty images after filtering you may try to force this to true\n * this has to be set before instantiating the filtering backend ( before filtering the first image )\n * @type Boolean\n * @default false\n */\nfabric.forceGLPutImageData = false;\n\nfabric.initFilterBackend = function() {\n if (fabric.enableGLFiltering && fabric.isWebglSupported && fabric.isWebglSupported(fabric.textureSize)) {\n console.log('max texture size: ' + fabric.maxTextureSize);\n return (new fabric.WebglFilterBackend({ tileSize: fabric.textureSize }));\n }\n else if (fabric.Canvas2dFilterBackend) {\n return (new fabric.Canvas2dFilterBackend());\n }\n};\n\n\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\n // ensure globality even if entire library were function wrapped (as in Meteor.js packaging system)\n window.fabric = fabric;\n}\n\n\n(function() {\n\n /**\n * @private\n * @param {String} eventName\n * @param {Function} handler\n */\n function _removeEventListener(eventName, handler) {\n if (!this.__eventListeners[eventName]) {\n return;\n }\n var eventListener = this.__eventListeners[eventName];\n if (handler) {\n eventListener[eventListener.indexOf(handler)] = false;\n }\n else {\n fabric.util.array.fill(eventListener, false);\n }\n }\n\n /**\n * Observes specified event\n * @memberOf fabric.Observable\n * @alias on\n * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n * @param {Function} handler Function that receives a notification when an event of the specified type occurs\n * @return {Self} thisArg\n * @chainable\n */\n function on(eventName, handler) {\n if (!this.__eventListeners) {\n this.__eventListeners = { };\n }\n // one object with key/value pairs was passed\n if (arguments.length === 1) {\n for (var prop in eventName) {\n this.on(prop, eventName[prop]);\n }\n }\n else {\n if (!this.__eventListeners[eventName]) {\n this.__eventListeners[eventName] = [];\n }\n this.__eventListeners[eventName].push(handler);\n }\n return this;\n }\n\n function _once(eventName, handler) {\n var _handler = function () {\n handler.apply(this, arguments);\n this.off(eventName, _handler);\n }.bind(this);\n this.on(eventName, _handler);\n }\n\n function once(eventName, handler) {\n // one object with key/value pairs was passed\n if (arguments.length === 1) {\n for (var prop in eventName) {\n _once.call(this, prop, eventName[prop]);\n }\n }\n else {\n _once.call(this, eventName, handler);\n }\n return this;\n }\n\n /**\n * Stops event observing for a particular event handler. Calling this method\n * without arguments removes all handlers for all events\n * @memberOf fabric.Observable\n * @alias off\n * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n * @param {Function} handler Function to be deleted from EventListeners\n * @return {Self} thisArg\n * @chainable\n */\n function off(eventName, handler) {\n if (!this.__eventListeners) {\n return this;\n }\n\n // remove all key/value pairs (event name -> event handler)\n if (arguments.length === 0) {\n for (eventName in this.__eventListeners) {\n _removeEventListener.call(this, eventName);\n }\n }\n // one object with key/value pairs was passed\n else if (arguments.length === 1 && typeof arguments[0] === 'object') {\n for (var prop in eventName) {\n _removeEventListener.call(this, prop, eventName[prop]);\n }\n }\n else {\n _removeEventListener.call(this, eventName, handler);\n }\n return this;\n }\n\n /**\n * Fires event with an optional options object\n * @memberOf fabric.Observable\n * @param {String} eventName Event name to fire\n * @param {Object} [options] Options object\n * @return {Self} thisArg\n * @chainable\n */\n function fire(eventName, options) {\n if (!this.__eventListeners) {\n return this;\n }\n\n var listenersForEvent = this.__eventListeners[eventName];\n if (!listenersForEvent) {\n return this;\n }\n\n for (var i = 0, len = listenersForEvent.length; i < len; i++) {\n listenersForEvent[i] && listenersForEvent[i].call(this, options || { });\n }\n this.__eventListeners[eventName] = listenersForEvent.filter(function(value) {\n return value !== false;\n });\n return this;\n }\n\n /**\n * @namespace fabric.Observable\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#events}\n * @see {@link http://fabricjs.com/events|Events demo}\n */\n fabric.Observable = {\n fire: fire,\n on: on,\n once: once,\n off: off,\n };\n})();\n\n\n/**\n * @namespace fabric.Collection\n */\nfabric.Collection = {\n\n _objects: [],\n\n /**\n * Adds objects to collection, Canvas or Group, then renders canvas\n * (if `renderOnAddRemove` is not `false`).\n * in case of Group no changes to bounding box are made.\n * Objects should be instances of (or inherit from) fabric.Object\n * Use of this function is highly discouraged for groups.\n * you can add a bunch of objects with the add method but then you NEED\n * to run a addWithUpdate call for the Group class or position/bbox will be wrong.\n * @param {...fabric.Object} object Zero or more fabric instances\n * @return {Self} thisArg\n * @chainable\n */\n add: function () {\n this._objects.push.apply(this._objects, arguments);\n if (this._onObjectAdded) {\n for (var i = 0, length = arguments.length; i < length; i++) {\n this._onObjectAdded(arguments[i]);\n }\n }\n this.renderOnAddRemove && this.requestRenderAll();\n return this;\n },\n\n /**\n * Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`)\n * An object should be an instance of (or inherit from) fabric.Object\n * Use of this function is highly discouraged for groups.\n * you can add a bunch of objects with the insertAt method but then you NEED\n * to run a addWithUpdate call for the Group class or position/bbox will be wrong.\n * @param {Object} object Object to insert\n * @param {Number} index Index to insert object at\n * @param {Boolean} nonSplicing When `true`, no splicing (shifting) of objects occurs\n * @return {Self} thisArg\n * @chainable\n */\n insertAt: function (object, index, nonSplicing) {\n var objects = this._objects;\n if (nonSplicing) {\n objects[index] = object;\n }\n else {\n objects.splice(index, 0, object);\n }\n this._onObjectAdded && this._onObjectAdded(object);\n this.renderOnAddRemove && this.requestRenderAll();\n return this;\n },\n\n /**\n * Removes objects from a collection, then renders canvas (if `renderOnAddRemove` is not `false`)\n * @param {...fabric.Object} object Zero or more fabric instances\n * @return {Self} thisArg\n * @chainable\n */\n remove: function() {\n var objects = this._objects,\n index, somethingRemoved = false;\n\n for (var i = 0, length = arguments.length; i < length; i++) {\n index = objects.indexOf(arguments[i]);\n\n // only call onObjectRemoved if an object was actually removed\n if (index !== -1) {\n somethingRemoved = true;\n objects.splice(index, 1);\n this._onObjectRemoved && this._onObjectRemoved(arguments[i]);\n }\n }\n\n this.renderOnAddRemove && somethingRemoved && this.requestRenderAll();\n return this;\n },\n\n /**\n * Executes given function for each object in this group\n * @param {Function} callback\n * Callback invoked with current object as first argument,\n * index - as second and an array of all objects - as third.\n * Callback is invoked in a context of Global Object (e.g. `window`)\n * when no `context` argument is given\n *\n * @param {Object} context Context (aka thisObject)\n * @return {Self} thisArg\n * @chainable\n */\n forEachObject: function(callback, context) {\n var objects = this.getObjects();\n for (var i = 0, len = objects.length; i < len; i++) {\n callback.call(context, objects[i], i, objects);\n }\n return this;\n },\n\n /**\n * Returns an array of children objects of this instance\n * Type parameter introduced in 1.3.10\n * since 2.3.5 this method return always a COPY of the array;\n * @param {String} [type] When specified, only objects of this type are returned\n * @return {Array}\n */\n getObjects: function(type) {\n if (typeof type === 'undefined') {\n return this._objects.concat();\n }\n return this._objects.filter(function(o) {\n return o.type === type;\n });\n },\n\n /**\n * Returns object at specified index\n * @param {Number} index\n * @return {Self} thisArg\n */\n item: function (index) {\n return this._objects[index];\n },\n\n /**\n * Returns true if collection contains no objects\n * @return {Boolean} true if collection is empty\n */\n isEmpty: function () {\n return this._objects.length === 0;\n },\n\n /**\n * Returns a size of a collection (i.e: length of an array containing its objects)\n * @return {Number} Collection size\n */\n size: function() {\n return this._objects.length;\n },\n\n /**\n * Returns true if collection contains an object\n * @param {Object} object Object to check against\n * @param {Boolean} [deep=false] `true` to check all descendants, `false` to check only `_objects`\n * @return {Boolean} `true` if collection contains an object\n */\n contains: function (object, deep) {\n if (this._objects.indexOf(object) > -1) {\n return true;\n }\n else if (deep) {\n return this._objects.some(function (obj) {\n return typeof obj.contains === 'function' && obj.contains(object, true);\n });\n }\n return false;\n },\n\n /**\n * Returns number representation of a collection complexity\n * @return {Number} complexity\n */\n complexity: function () {\n return this._objects.reduce(function (memo, current) {\n memo += current.complexity ? current.complexity() : 0;\n return memo;\n }, 0);\n }\n};\n\n\n/**\n * @namespace fabric.CommonMethods\n */\nfabric.CommonMethods = {\n\n /**\n * Sets object's properties from options\n * @param {Object} [options] Options object\n */\n _setOptions: function(options) {\n for (var prop in options) {\n this.set(prop, options[prop]);\n }\n },\n\n /**\n * @private\n * @param {Object} [filler] Options object\n * @param {String} [property] property to set the Gradient to\n */\n _initGradient: function(filler, property) {\n if (filler && filler.colorStops && !(filler instanceof fabric.Gradient)) {\n this.set(property, new fabric.Gradient(filler));\n }\n },\n\n /**\n * @private\n * @param {Object} [filler] Options object\n * @param {String} [property] property to set the Pattern to\n * @param {Function} [callback] callback to invoke after pattern load\n */\n _initPattern: function(filler, property, callback) {\n if (filler && filler.source && !(filler instanceof fabric.Pattern)) {\n this.set(property, new fabric.Pattern(filler, callback));\n }\n else {\n callback && callback();\n }\n },\n\n /**\n * @private\n */\n _setObject: function(obj) {\n for (var prop in obj) {\n this._set(prop, obj[prop]);\n }\n },\n\n /**\n * Sets property to a given value. When changing position/dimension -related properties (left, top, scale, angle, etc.) `set` does not update position of object's borders/controls. If you need to update those, call `setCoords()`.\n * @param {String|Object} key Property name or object (if object, iterate over the object properties)\n * @param {Object|Function} value Property value (if function, the value is passed into it and its return value is used as a new one)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n set: function(key, value) {\n if (typeof key === 'object') {\n this._setObject(key);\n }\n else {\n this._set(key, value);\n }\n return this;\n },\n\n _set: function(key, value) {\n this[key] = value;\n },\n\n /**\n * Toggles specified property from `true` to `false` or from `false` to `true`\n * @param {String} property Property to toggle\n * @return {fabric.Object} thisArg\n * @chainable\n */\n toggle: function(property) {\n var value = this.get(property);\n if (typeof value === 'boolean') {\n this.set(property, !value);\n }\n return this;\n },\n\n /**\n * Basic getter\n * @param {String} property Property name\n * @return {*} value of a property\n */\n get: function(property) {\n return this[property];\n }\n};\n\n\n(function(global) {\n\n var sqrt = Math.sqrt,\n atan2 = Math.atan2,\n pow = Math.pow,\n PiBy180 = Math.PI / 180,\n PiBy2 = Math.PI / 2;\n\n /**\n * @namespace fabric.util\n */\n fabric.util = {\n\n /**\n * Calculate the cos of an angle, avoiding returning floats for known results\n * @static\n * @memberOf fabric.util\n * @param {Number} angle the angle in radians or in degree\n * @return {Number}\n */\n cos: function(angle) {\n if (angle === 0) { return 1; }\n if (angle < 0) {\n // cos(a) = cos(-a)\n angle = -angle;\n }\n var angleSlice = angle / PiBy2;\n switch (angleSlice) {\n case 1: case 3: return 0;\n case 2: return -1;\n }\n return Math.cos(angle);\n },\n\n /**\n * Calculate the sin of an angle, avoiding returning floats for known results\n * @static\n * @memberOf fabric.util\n * @param {Number} angle the angle in radians or in degree\n * @return {Number}\n */\n sin: function(angle) {\n if (angle === 0) { return 0; }\n var angleSlice = angle / PiBy2, sign = 1;\n if (angle < 0) {\n // sin(-a) = -sin(a)\n sign = -1;\n }\n switch (angleSlice) {\n case 1: return sign;\n case 2: return 0;\n case 3: return -sign;\n }\n return Math.sin(angle);\n },\n\n /**\n * Removes value from an array.\n * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf`\n * @static\n * @memberOf fabric.util\n * @param {Array} array\n * @param {*} value\n * @return {Array} original array\n */\n removeFromArray: function(array, value) {\n var idx = array.indexOf(value);\n if (idx !== -1) {\n array.splice(idx, 1);\n }\n return array;\n },\n\n /**\n * Returns random number between 2 specified ones.\n * @static\n * @memberOf fabric.util\n * @param {Number} min lower limit\n * @param {Number} max upper limit\n * @return {Number} random value (between min and max)\n */\n getRandomInt: function(min, max) {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n },\n\n /**\n * Transforms degrees to radians.\n * @static\n * @memberOf fabric.util\n * @param {Number} degrees value in degrees\n * @return {Number} value in radians\n */\n degreesToRadians: function(degrees) {\n return degrees * PiBy180;\n },\n\n /**\n * Transforms radians to degrees.\n * @static\n * @memberOf fabric.util\n * @param {Number} radians value in radians\n * @return {Number} value in degrees\n */\n radiansToDegrees: function(radians) {\n return radians / PiBy180;\n },\n\n /**\n * Rotates `point` around `origin` with `radians`\n * @static\n * @memberOf fabric.util\n * @param {fabric.Point} point The point to rotate\n * @param {fabric.Point} origin The origin of the rotation\n * @param {Number} radians The radians of the angle for the rotation\n * @return {fabric.Point} The new rotated point\n */\n rotatePoint: function(point, origin, radians) {\n var newPoint = new fabric.Point(point.x - origin.x, point.y - origin.y),\n v = fabric.util.rotateVector(newPoint, radians);\n return new fabric.Point(v.x, v.y).addEquals(origin);\n },\n\n /**\n * Rotates `vector` with `radians`\n * @static\n * @memberOf fabric.util\n * @param {Object} vector The vector to rotate (x and y)\n * @param {Number} radians The radians of the angle for the rotation\n * @return {Object} The new rotated point\n */\n rotateVector: function(vector, radians) {\n var sin = fabric.util.sin(radians),\n cos = fabric.util.cos(radians),\n rx = vector.x * cos - vector.y * sin,\n ry = vector.x * sin + vector.y * cos;\n return {\n x: rx,\n y: ry\n };\n },\n\n /**\n * Creates a vetor from points represented as a point\n * @static\n * @memberOf fabric.util\n *\n * @typedef {Object} Point\n * @property {number} x\n * @property {number} y\n *\n * @param {Point} from\n * @param {Point} to\n * @returns {Point} vector\n */\n createVector: function (from, to) {\n return new fabric.Point(to.x - from.x, to.y - from.y);\n },\n\n /**\n * Calculates angle between 2 vectors using dot product\n * @static\n * @memberOf fabric.util\n * @param {Point} a\n * @param {Point} b\n * @returns the angle in radian between the vectors\n */\n calcAngleBetweenVectors: function (a, b) {\n return Math.acos((a.x * b.x + a.y * b.y) / (Math.hypot(a.x, a.y) * Math.hypot(b.x, b.y)));\n },\n\n /**\n * @static\n * @memberOf fabric.util\n * @param {Point} v\n * @returns {Point} vector representing the unit vector of pointing to the direction of `v`\n */\n getHatVector: function (v) {\n return new fabric.Point(v.x, v.y).multiply(1 / Math.hypot(v.x, v.y));\n },\n\n /**\n * @static\n * @memberOf fabric.util\n * @param {Point} A\n * @param {Point} B\n * @param {Point} C\n * @returns {{ vector: Point, angle: number }} vector representing the bisector of A and A's angle\n */\n getBisector: function (A, B, C) {\n var AB = fabric.util.createVector(A, B), AC = fabric.util.createVector(A, C);\n var alpha = fabric.util.calcAngleBetweenVectors(AB, AC);\n // check if alpha is relative to AB->BC\n var ro = fabric.util.calcAngleBetweenVectors(fabric.util.rotateVector(AB, alpha), AC);\n var phi = alpha * (ro === 0 ? 1 : -1) / 2;\n return {\n vector: fabric.util.getHatVector(fabric.util.rotateVector(AB, phi)),\n angle: alpha\n };\n },\n\n /**\n * Project stroke width on points returning 2 projections for each point as follows:\n * - `miter`: 2 points corresponding to the outer boundary and the inner boundary of stroke.\n * - `bevel`: 2 points corresponding to the bevel boundaries, tangent to the bisector.\n * - `round`: same as `bevel`\n * Used to calculate object's bounding box\n * @static\n * @memberOf fabric.util\n * @param {Point[]} points\n * @param {Object} options\n * @param {number} options.strokeWidth\n * @param {'miter'|'bevel'|'round'} options.strokeLineJoin\n * @param {number} options.strokeMiterLimit https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit\n * @param {boolean} options.strokeUniform\n * @param {number} options.scaleX\n * @param {number} options.scaleY\n * @param {boolean} [openPath] whether the shape is open or not, affects the calculations of the first and last points\n * @returns {fabric.Point[]} array of size 2n/4n of all suspected points\n */\n projectStrokeOnPoints: function (points, options, openPath) {\n var coords = [], s = options.strokeWidth / 2,\n strokeUniformScalar = options.strokeUniform ?\n new fabric.Point(1 / options.scaleX, 1 / options.scaleY) : new fabric.Point(1, 1),\n getStrokeHatVector = function (v) {\n var scalar = s / (Math.hypot(v.x, v.y));\n return new fabric.Point(v.x * scalar * strokeUniformScalar.x, v.y * scalar * strokeUniformScalar.y);\n };\n if (points.length <= 1) {return coords;}\n points.forEach(function (p, index) {\n var A = new fabric.Point(p.x, p.y), B, C;\n if (index === 0) {\n C = points[index + 1];\n B = openPath ? getStrokeHatVector(fabric.util.createVector(C, A)).addEquals(A) : points[points.length - 1];\n }\n else if (index === points.length - 1) {\n B = points[index - 1];\n C = openPath ? getStrokeHatVector(fabric.util.createVector(B, A)).addEquals(A) : points[0];\n }\n else {\n B = points[index - 1];\n C = points[index + 1];\n }\n var bisector = fabric.util.getBisector(A, B, C),\n bisectorVector = bisector.vector,\n alpha = bisector.angle,\n scalar,\n miterVector;\n if (options.strokeLineJoin === 'miter') {\n scalar = -s / Math.sin(alpha / 2);\n miterVector = new fabric.Point(\n bisectorVector.x * scalar * strokeUniformScalar.x,\n bisectorVector.y * scalar * strokeUniformScalar.y\n );\n if (Math.hypot(miterVector.x, miterVector.y) / s <= options.strokeMiterLimit) {\n coords.push(A.add(miterVector));\n coords.push(A.subtract(miterVector));\n return;\n }\n }\n scalar = -s * Math.SQRT2;\n miterVector = new fabric.Point(\n bisectorVector.x * scalar * strokeUniformScalar.x,\n bisectorVector.y * scalar * strokeUniformScalar.y\n );\n coords.push(A.add(miterVector));\n coords.push(A.subtract(miterVector));\n });\n return coords;\n },\n\n /**\n * Apply transform t to point p\n * @static\n * @memberOf fabric.util\n * @param {fabric.Point} p The point to transform\n * @param {Array} t The transform\n * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied\n * @return {fabric.Point} The transformed point\n */\n transformPoint: function(p, t, ignoreOffset) {\n if (ignoreOffset) {\n return new fabric.Point(\n t[0] * p.x + t[2] * p.y,\n t[1] * p.x + t[3] * p.y\n );\n }\n return new fabric.Point(\n t[0] * p.x + t[2] * p.y + t[4],\n t[1] * p.x + t[3] * p.y + t[5]\n );\n },\n\n /**\n * Returns coordinates of points's bounding rectangle (left, top, width, height)\n * @param {Array} points 4 points array\n * @param {Array} [transform] an array of 6 numbers representing a 2x3 transform matrix\n * @return {Object} Object with left, top, width, height properties\n */\n makeBoundingBoxFromPoints: function(points, transform) {\n if (transform) {\n for (var i = 0; i < points.length; i++) {\n points[i] = fabric.util.transformPoint(points[i], transform);\n }\n }\n var xPoints = [points[0].x, points[1].x, points[2].x, points[3].x],\n minX = fabric.util.array.min(xPoints),\n maxX = fabric.util.array.max(xPoints),\n width = maxX - minX,\n yPoints = [points[0].y, points[1].y, points[2].y, points[3].y],\n minY = fabric.util.array.min(yPoints),\n maxY = fabric.util.array.max(yPoints),\n height = maxY - minY;\n\n return {\n left: minX,\n top: minY,\n width: width,\n height: height\n };\n },\n\n /**\n * Invert transformation t\n * @static\n * @memberOf fabric.util\n * @param {Array} t The transform\n * @return {Array} The inverted transform\n */\n invertTransform: function(t) {\n var a = 1 / (t[0] * t[3] - t[1] * t[2]),\n r = [a * t[3], -a * t[1], -a * t[2], a * t[0]],\n o = fabric.util.transformPoint({ x: t[4], y: t[5] }, r, true);\n r[4] = -o.x;\n r[5] = -o.y;\n return r;\n },\n\n /**\n * A wrapper around Number#toFixed, which contrary to native method returns number, not string.\n * @static\n * @memberOf fabric.util\n * @param {Number|String} number number to operate on\n * @param {Number} fractionDigits number of fraction digits to \"leave\"\n * @return {Number}\n */\n toFixed: function(number, fractionDigits) {\n return parseFloat(Number(number).toFixed(fractionDigits));\n },\n\n /**\n * Converts from attribute value to pixel value if applicable.\n * Returns converted pixels or original value not converted.\n * @param {Number|String} value number to operate on\n * @param {Number} fontSize\n * @return {Number|String}\n */\n parseUnit: function(value, fontSize) {\n var unit = /\\D{0,2}$/.exec(value),\n number = parseFloat(value);\n if (!fontSize) {\n fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;\n }\n switch (unit[0]) {\n case 'mm':\n return number * fabric.DPI / 25.4;\n\n case 'cm':\n return number * fabric.DPI / 2.54;\n\n case 'in':\n return number * fabric.DPI;\n\n case 'pt':\n return number * fabric.DPI / 72; // or * 4 / 3\n\n case 'pc':\n return number * fabric.DPI / 72 * 12; // or * 16\n\n case 'em':\n return number * fontSize;\n\n default:\n return number;\n }\n },\n\n /**\n * Function which always returns `false`.\n * @static\n * @memberOf fabric.util\n * @return {Boolean}\n */\n falseFunction: function() {\n return false;\n },\n\n /**\n * Returns klass \"Class\" object of given namespace\n * @memberOf fabric.util\n * @param {String} type Type of object (eg. 'circle')\n * @param {String} namespace Namespace to get klass \"Class\" object from\n * @return {Object} klass \"Class\"\n */\n getKlass: function(type, namespace) {\n // capitalize first letter only\n type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1));\n return fabric.util.resolveNamespace(namespace)[type];\n },\n\n /**\n * Returns array of attributes for given svg that fabric parses\n * @memberOf fabric.util\n * @param {String} type Type of svg element (eg. 'circle')\n * @return {Array} string names of supported attributes\n */\n getSvgAttributes: function(type) {\n var attributes = [\n 'instantiated_by_use',\n 'style',\n 'id',\n 'class'\n ];\n switch (type) {\n case 'linearGradient':\n attributes = attributes.concat(['x1', 'y1', 'x2', 'y2', 'gradientUnits', 'gradientTransform']);\n break;\n case 'radialGradient':\n attributes = attributes.concat(['gradientUnits', 'gradientTransform', 'cx', 'cy', 'r', 'fx', 'fy', 'fr']);\n break;\n case 'stop':\n attributes = attributes.concat(['offset', 'stop-color', 'stop-opacity']);\n break;\n }\n return attributes;\n },\n\n /**\n * Returns object of given namespace\n * @memberOf fabric.util\n * @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric'\n * @return {Object} Object for given namespace (default fabric)\n */\n resolveNamespace: function(namespace) {\n if (!namespace) {\n return fabric;\n }\n\n var parts = namespace.split('.'),\n len = parts.length, i,\n obj = global || fabric.window;\n\n for (i = 0; i < len; ++i) {\n obj = obj[parts[i]];\n }\n\n return obj;\n },\n\n /**\n * Loads image element from given url and passes it to a callback\n * @memberOf fabric.util\n * @param {String} url URL representing an image\n * @param {Function} callback Callback; invoked with loaded image\n * @param {*} [context] Context to invoke callback in\n * @param {Object} [crossOrigin] crossOrigin value to set image element to\n */\n loadImage: function(url, callback, context, crossOrigin) {\n if (!url) {\n callback && callback.call(context, url);\n return;\n }\n\n var img = fabric.util.createImage();\n\n /** @ignore */\n var onLoadCallback = function () {\n callback && callback.call(context, img, false);\n img = img.onload = img.onerror = null;\n };\n\n img.onload = onLoadCallback;\n /** @ignore */\n img.onerror = function() {\n fabric.log('Error loading ' + img.src);\n callback && callback.call(context, null, true);\n img = img.onload = img.onerror = null;\n };\n\n // data-urls appear to be buggy with crossOrigin\n // https://github.com/kangax/fabric.js/commit/d0abb90f1cd5c5ef9d2a94d3fb21a22330da3e0a#commitcomment-4513767\n // see https://code.google.com/p/chromium/issues/detail?id=315152\n // https://bugzilla.mozilla.org/show_bug.cgi?id=935069\n // crossOrigin null is the same as not set.\n if (url.indexOf('data') !== 0 &&\n crossOrigin !== undefined &&\n crossOrigin !== null) {\n img.crossOrigin = crossOrigin;\n }\n\n // IE10 / IE11-Fix: SVG contents from data: URI\n // will only be available if the IMG is present\n // in the DOM (and visible)\n if (url.substring(0,14) === 'data:image/svg') {\n img.onload = null;\n fabric.util.loadImageInDom(img, onLoadCallback);\n }\n\n img.src = url;\n },\n\n /**\n * Attaches SVG image with data: URL to the dom\n * @memberOf fabric.util\n * @param {Object} img Image object with data:image/svg src\n * @param {Function} callback Callback; invoked with loaded image\n * @return {Object} DOM element (div containing the SVG image)\n */\n loadImageInDom: function(img, onLoadCallback) {\n var div = fabric.document.createElement('div');\n div.style.width = div.style.height = '1px';\n div.style.left = div.style.top = '-100%';\n div.style.position = 'absolute';\n div.appendChild(img);\n fabric.document.querySelector('body').appendChild(div);\n /**\n * Wrap in function to:\n * 1. Call existing callback\n * 2. Cleanup DOM\n */\n img.onload = function () {\n onLoadCallback();\n div.parentNode.removeChild(div);\n div = null;\n };\n },\n\n /**\n * Creates corresponding fabric instances from their object representations\n * @static\n * @memberOf fabric.util\n * @param {Array} objects Objects to enliven\n * @param {Function} callback Callback to invoke when all objects are created\n * @param {String} namespace Namespace to get klass \"Class\" object from\n * @param {Function} reviver Method for further parsing of object elements,\n * called after each fabric object created.\n */\n enlivenObjects: function(objects, callback, namespace, reviver) {\n objects = objects || [];\n\n var enlivenedObjects = [],\n numLoadedObjects = 0,\n numTotalObjects = objects.length;\n\n function onLoaded() {\n if (++numLoadedObjects === numTotalObjects) {\n callback && callback(enlivenedObjects.filter(function(obj) {\n // filter out undefined objects (objects that gave error)\n return obj;\n }));\n }\n }\n\n if (!numTotalObjects) {\n callback && callback(enlivenedObjects);\n return;\n }\n\n objects.forEach(function (o, index) {\n // if sparse array\n if (!o || !o.type) {\n onLoaded();\n return;\n }\n var klass = fabric.util.getKlass(o.type, namespace);\n klass.fromObject(o, function (obj, error) {\n error || (enlivenedObjects[index] = obj);\n reviver && reviver(o, obj, error);\n onLoaded();\n });\n });\n },\n\n /**\n * Creates corresponding fabric instances residing in an object, e.g. `clipPath`\n * @see {@link fabric.Object.ENLIVEN_PROPS}\n * @param {Object} object\n * @param {Object} [context] assign enlived props to this object (pass null to skip this)\n * @param {(objects:fabric.Object[]) => void} callback\n */\n enlivenObjectEnlivables: function (object, context, callback) {\n var enlivenProps = fabric.Object.ENLIVEN_PROPS.filter(function (key) { return !!object[key]; });\n fabric.util.enlivenObjects(enlivenProps.map(function (key) { return object[key]; }), function (enlivedProps) {\n var objects = {};\n enlivenProps.forEach(function (key, index) {\n objects[key] = enlivedProps[index];\n context && (context[key] = enlivedProps[index]);\n });\n callback && callback(objects);\n });\n },\n\n /**\n * Create and wait for loading of patterns\n * @static\n * @memberOf fabric.util\n * @param {Array} patterns Objects to enliven\n * @param {Function} callback Callback to invoke when all objects are created\n * called after each fabric object created.\n */\n enlivenPatterns: function(patterns, callback) {\n patterns = patterns || [];\n\n function onLoaded() {\n if (++numLoadedPatterns === numPatterns) {\n callback && callback(enlivenedPatterns);\n }\n }\n\n var enlivenedPatterns = [],\n numLoadedPatterns = 0,\n numPatterns = patterns.length;\n\n if (!numPatterns) {\n callback && callback(enlivenedPatterns);\n return;\n }\n\n patterns.forEach(function (p, index) {\n if (p && p.source) {\n new fabric.Pattern(p, function(pattern) {\n enlivenedPatterns[index] = pattern;\n onLoaded();\n });\n }\n else {\n enlivenedPatterns[index] = p;\n onLoaded();\n }\n });\n },\n\n /**\n * Groups SVG elements (usually those retrieved from SVG document)\n * @static\n * @memberOf fabric.util\n * @param {Array} elements SVG elements to group\n * @param {Object} [options] Options object\n * @param {String} path Value to set sourcePath to\n * @return {fabric.Object|fabric.Group}\n */\n groupSVGElements: function(elements, options, path) {\n var object;\n if (elements && elements.length === 1) {\n if (typeof path !== 'undefined') {\n elements[0].sourcePath = path;\n }\n return elements[0];\n }\n if (options) {\n if (options.width && options.height) {\n options.centerPoint = {\n x: options.width / 2,\n y: options.height / 2\n };\n }\n else {\n delete options.width;\n delete options.height;\n }\n }\n object = new fabric.Group(elements, options);\n if (typeof path !== 'undefined') {\n object.sourcePath = path;\n }\n return object;\n },\n\n /**\n * Populates an object with properties of another object\n * @static\n * @memberOf fabric.util\n * @param {Object} source Source object\n * @param {Object} destination Destination object\n * @return {Array} properties Properties names to include\n */\n populateWithProperties: function(source, destination, properties) {\n if (properties && Array.isArray(properties)) {\n for (var i = 0, len = properties.length; i < len; i++) {\n if (properties[i] in source) {\n destination[properties[i]] = source[properties[i]];\n }\n }\n }\n },\n\n /**\n * Creates canvas element\n * @static\n * @memberOf fabric.util\n * @return {CanvasElement} initialized canvas element\n */\n createCanvasElement: function() {\n return fabric.document.createElement('canvas');\n },\n\n /**\n * Creates a canvas element that is a copy of another and is also painted\n * @param {CanvasElement} canvas to copy size and content of\n * @static\n * @memberOf fabric.util\n * @return {CanvasElement} initialized canvas element\n */\n copyCanvasElement: function(canvas) {\n var newCanvas = fabric.util.createCanvasElement();\n newCanvas.width = canvas.width;\n newCanvas.height = canvas.height;\n newCanvas.getContext('2d').drawImage(canvas, 0, 0);\n return newCanvas;\n },\n\n /**\n * since 2.6.0 moved from canvas instance to utility.\n * @param {CanvasElement} canvasEl to copy size and content of\n * @param {String} format 'jpeg' or 'png', in some browsers 'webp' is ok too\n * @param {Number} quality <= 1 and > 0\n * @static\n * @memberOf fabric.util\n * @return {String} data url\n */\n toDataURL: function(canvasEl, format, quality) {\n return canvasEl.toDataURL('image/' + format, quality);\n },\n\n /**\n * Creates image element (works on client and node)\n * @static\n * @memberOf fabric.util\n * @return {HTMLImageElement} HTML image element\n */\n createImage: function() {\n return fabric.document.createElement('img');\n },\n\n /**\n * Multiply matrix A by matrix B to nest transformations\n * @static\n * @memberOf fabric.util\n * @param {Array} a First transformMatrix\n * @param {Array} b Second transformMatrix\n * @param {Boolean} is2x2 flag to multiply matrices as 2x2 matrices\n * @return {Array} The product of the two transform matrices\n */\n multiplyTransformMatrices: function(a, b, is2x2) {\n // Matrix multiply a * b\n return [\n a[0] * b[0] + a[2] * b[1],\n a[1] * b[0] + a[3] * b[1],\n a[0] * b[2] + a[2] * b[3],\n a[1] * b[2] + a[3] * b[3],\n is2x2 ? 0 : a[0] * b[4] + a[2] * b[5] + a[4],\n is2x2 ? 0 : a[1] * b[4] + a[3] * b[5] + a[5]\n ];\n },\n\n /**\n * Decomposes standard 2x3 matrix into transform components\n * @static\n * @memberOf fabric.util\n * @param {Array} a transformMatrix\n * @return {Object} Components of transform\n */\n qrDecompose: function(a) {\n var angle = atan2(a[1], a[0]),\n denom = pow(a[0], 2) + pow(a[1], 2),\n scaleX = sqrt(denom),\n scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX,\n skewX = atan2(a[0] * a[2] + a[1] * a [3], denom);\n return {\n angle: angle / PiBy180,\n scaleX: scaleX,\n scaleY: scaleY,\n skewX: skewX / PiBy180,\n skewY: 0,\n translateX: a[4],\n translateY: a[5]\n };\n },\n\n /**\n * Returns a transform matrix starting from an object of the same kind of\n * the one returned from qrDecompose, useful also if you want to calculate some\n * transformations from an object that is not enlived yet\n * @static\n * @memberOf fabric.util\n * @param {Object} options\n * @param {Number} [options.angle] angle in degrees\n * @return {Number[]} transform matrix\n */\n calcRotateMatrix: function(options) {\n if (!options.angle) {\n return fabric.iMatrix.concat();\n }\n var theta = fabric.util.degreesToRadians(options.angle),\n cos = fabric.util.cos(theta),\n sin = fabric.util.sin(theta);\n return [cos, sin, -sin, cos, 0, 0];\n },\n\n /**\n * Returns a transform matrix starting from an object of the same kind of\n * the one returned from qrDecompose, useful also if you want to calculate some\n * transformations from an object that is not enlived yet.\n * is called DimensionsTransformMatrix because those properties are the one that influence\n * the size of the resulting box of the object.\n * @static\n * @memberOf fabric.util\n * @param {Object} options\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Boolean} [options.flipX]\n * @param {Boolean} [options.flipY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewY]\n * @return {Number[]} transform matrix\n */\n calcDimensionsMatrix: function(options) {\n var scaleX = typeof options.scaleX === 'undefined' ? 1 : options.scaleX,\n scaleY = typeof options.scaleY === 'undefined' ? 1 : options.scaleY,\n scaleMatrix = [\n options.flipX ? -scaleX : scaleX,\n 0,\n 0,\n options.flipY ? -scaleY : scaleY,\n 0,\n 0],\n multiply = fabric.util.multiplyTransformMatrices,\n degreesToRadians = fabric.util.degreesToRadians;\n if (options.skewX) {\n scaleMatrix = multiply(\n scaleMatrix,\n [1, 0, Math.tan(degreesToRadians(options.skewX)), 1],\n true);\n }\n if (options.skewY) {\n scaleMatrix = multiply(\n scaleMatrix,\n [1, Math.tan(degreesToRadians(options.skewY)), 0, 1],\n true);\n }\n return scaleMatrix;\n },\n\n /**\n * Returns a transform matrix starting from an object of the same kind of\n * the one returned from qrDecompose, useful also if you want to calculate some\n * transformations from an object that is not enlived yet\n * @static\n * @memberOf fabric.util\n * @param {Object} options\n * @param {Number} [options.angle]\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Boolean} [options.flipX]\n * @param {Boolean} [options.flipY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewX]\n * @param {Number} [options.translateX]\n * @param {Number} [options.translateY]\n * @return {Number[]} transform matrix\n */\n composeMatrix: function(options) {\n var matrix = [1, 0, 0, 1, options.translateX || 0, options.translateY || 0],\n multiply = fabric.util.multiplyTransformMatrices;\n if (options.angle) {\n matrix = multiply(matrix, fabric.util.calcRotateMatrix(options));\n }\n if (options.scaleX !== 1 || options.scaleY !== 1 ||\n options.skewX || options.skewY || options.flipX || options.flipY) {\n matrix = multiply(matrix, fabric.util.calcDimensionsMatrix(options));\n }\n return matrix;\n },\n\n /**\n * reset an object transform state to neutral. Top and left are not accounted for\n * @static\n * @memberOf fabric.util\n * @param {fabric.Object} target object to transform\n */\n resetObjectTransform: function (target) {\n target.scaleX = 1;\n target.scaleY = 1;\n target.skewX = 0;\n target.skewY = 0;\n target.flipX = false;\n target.flipY = false;\n target.rotate(0);\n },\n\n /**\n * Extract Object transform values\n * @static\n * @memberOf fabric.util\n * @param {fabric.Object} target object to read from\n * @return {Object} Components of transform\n */\n saveObjectTransform: function (target) {\n return {\n scaleX: target.scaleX,\n scaleY: target.scaleY,\n skewX: target.skewX,\n skewY: target.skewY,\n angle: target.angle,\n left: target.left,\n flipX: target.flipX,\n flipY: target.flipY,\n top: target.top\n };\n },\n\n /**\n * Returns true if context has transparent pixel\n * at specified location (taking tolerance into account)\n * @param {CanvasRenderingContext2D} ctx context\n * @param {Number} x x coordinate\n * @param {Number} y y coordinate\n * @param {Number} tolerance Tolerance\n */\n isTransparent: function(ctx, x, y, tolerance) {\n\n // If tolerance is > 0 adjust start coords to take into account.\n // If moves off Canvas fix to 0\n if (tolerance > 0) {\n if (x > tolerance) {\n x -= tolerance;\n }\n else {\n x = 0;\n }\n if (y > tolerance) {\n y -= tolerance;\n }\n else {\n y = 0;\n }\n }\n\n var _isTransparent = true, i, temp,\n imageData = ctx.getImageData(x, y, (tolerance * 2) || 1, (tolerance * 2) || 1),\n l = imageData.data.length;\n\n // Split image data - for tolerance > 1, pixelDataSize = 4;\n for (i = 3; i < l; i += 4) {\n temp = imageData.data[i];\n _isTransparent = temp <= 0;\n if (_isTransparent === false) {\n break; // Stop if colour found\n }\n }\n\n imageData = null;\n\n return _isTransparent;\n },\n\n /**\n * Parse preserveAspectRatio attribute from element\n * @param {string} attribute to be parsed\n * @return {Object} an object containing align and meetOrSlice attribute\n */\n parsePreserveAspectRatioAttribute: function(attribute) {\n var meetOrSlice = 'meet', alignX = 'Mid', alignY = 'Mid',\n aspectRatioAttrs = attribute.split(' '), align;\n\n if (aspectRatioAttrs && aspectRatioAttrs.length) {\n meetOrSlice = aspectRatioAttrs.pop();\n if (meetOrSlice !== 'meet' && meetOrSlice !== 'slice') {\n align = meetOrSlice;\n meetOrSlice = 'meet';\n }\n else if (aspectRatioAttrs.length) {\n align = aspectRatioAttrs.pop();\n }\n }\n //divide align in alignX and alignY\n alignX = align !== 'none' ? align.slice(1, 4) : 'none';\n alignY = align !== 'none' ? align.slice(5, 8) : 'none';\n return {\n meetOrSlice: meetOrSlice,\n alignX: alignX,\n alignY: alignY\n };\n },\n\n /**\n * Clear char widths cache for the given font family or all the cache if no\n * fontFamily is specified.\n * Use it if you know you are loading fonts in a lazy way and you are not waiting\n * for custom fonts to load properly when adding text objects to the canvas.\n * If a text object is added when its own font is not loaded yet, you will get wrong\n * measurement and so wrong bounding boxes.\n * After the font cache is cleared, either change the textObject text content or call\n * initDimensions() to trigger a recalculation\n * @memberOf fabric.util\n * @param {String} [fontFamily] font family to clear\n */\n clearFabricFontCache: function(fontFamily) {\n fontFamily = (fontFamily || '').toLowerCase();\n if (!fontFamily) {\n fabric.charWidthsCache = { };\n }\n else if (fabric.charWidthsCache[fontFamily]) {\n delete fabric.charWidthsCache[fontFamily];\n }\n },\n\n /**\n * Given current aspect ratio, determines the max width and height that can\n * respect the total allowed area for the cache.\n * @memberOf fabric.util\n * @param {Number} ar aspect ratio\n * @param {Number} maximumArea Maximum area you want to achieve\n * @return {Object.x} Limited dimensions by X\n * @return {Object.y} Limited dimensions by Y\n */\n limitDimsByArea: function(ar, maximumArea) {\n var roughWidth = Math.sqrt(maximumArea * ar),\n perfLimitSizeY = Math.floor(maximumArea / roughWidth);\n return { x: Math.floor(roughWidth), y: perfLimitSizeY };\n },\n\n capValue: function(min, value, max) {\n return Math.max(min, Math.min(value, max));\n },\n\n /**\n * Finds the scale for the object source to fit inside the object destination,\n * keeping aspect ratio intact.\n * respect the total allowed area for the cache.\n * @memberOf fabric.util\n * @param {Object | fabric.Object} source\n * @param {Number} source.height natural unscaled height of the object\n * @param {Number} source.width natural unscaled width of the object\n * @param {Object | fabric.Object} destination\n * @param {Number} destination.height natural unscaled height of the object\n * @param {Number} destination.width natural unscaled width of the object\n * @return {Number} scale factor to apply to source to fit into destination\n */\n findScaleToFit: function(source, destination) {\n return Math.min(destination.width / source.width, destination.height / source.height);\n },\n\n /**\n * Finds the scale for the object source to cover entirely the object destination,\n * keeping aspect ratio intact.\n * respect the total allowed area for the cache.\n * @memberOf fabric.util\n * @param {Object | fabric.Object} source\n * @param {Number} source.height natural unscaled height of the object\n * @param {Number} source.width natural unscaled width of the object\n * @param {Object | fabric.Object} destination\n * @param {Number} destination.height natural unscaled height of the object\n * @param {Number} destination.width natural unscaled width of the object\n * @return {Number} scale factor to apply to source to cover destination\n */\n findScaleToCover: function(source, destination) {\n return Math.max(destination.width / source.width, destination.height / source.height);\n },\n\n /**\n * given an array of 6 number returns something like `\"matrix(...numbers)\"`\n * @memberOf fabric.util\n * @param {Array} transform an array with 6 numbers\n * @return {String} transform matrix for svg\n * @return {Object.y} Limited dimensions by Y\n */\n matrixToSVG: function(transform) {\n return 'matrix(' + transform.map(function(value) {\n return fabric.util.toFixed(value, fabric.Object.NUM_FRACTION_DIGITS);\n }).join(' ') + ')';\n },\n\n /**\n * given an object and a transform, apply the inverse transform to the object,\n * this is equivalent to remove from that object that transformation, so that\n * added in a space with the removed transform, the object will be the same as before.\n * Removing from an object a transform that scale by 2 is like scaling it by 1/2.\n * Removing from an object a transfrom that rotate by 30deg is like rotating by 30deg\n * in the opposite direction.\n * This util is used to add objects inside transformed groups or nested groups.\n * @memberOf fabric.util\n * @param {fabric.Object} object the object you want to transform\n * @param {Array} transform the destination transform\n */\n removeTransformFromObject: function(object, transform) {\n var inverted = fabric.util.invertTransform(transform),\n finalTransform = fabric.util.multiplyTransformMatrices(inverted, object.calcOwnMatrix());\n fabric.util.applyTransformToObject(object, finalTransform);\n },\n\n /**\n * given an object and a transform, apply the transform to the object.\n * this is equivalent to change the space where the object is drawn.\n * Adding to an object a transform that scale by 2 is like scaling it by 2.\n * This is used when removing an object from an active selection for example.\n * @memberOf fabric.util\n * @param {fabric.Object} object the object you want to transform\n * @param {Array} transform the destination transform\n */\n addTransformToObject: function(object, transform) {\n fabric.util.applyTransformToObject(\n object,\n fabric.util.multiplyTransformMatrices(transform, object.calcOwnMatrix())\n );\n },\n\n /**\n * discard an object transform state and apply the one from the matrix.\n * @memberOf fabric.util\n * @param {fabric.Object} object the object you want to transform\n * @param {Array} transform the destination transform\n */\n applyTransformToObject: function(object, transform) {\n var options = fabric.util.qrDecompose(transform),\n center = new fabric.Point(options.translateX, options.translateY);\n object.flipX = false;\n object.flipY = false;\n object.set('scaleX', options.scaleX);\n object.set('scaleY', options.scaleY);\n object.skewX = options.skewX;\n object.skewY = options.skewY;\n object.angle = options.angle;\n object.setPositionByOrigin(center, 'center', 'center');\n },\n\n /**\n * given a width and height, return the size of the bounding box\n * that can contains the box with width/height with applied transform\n * described in options.\n * Use to calculate the boxes around objects for controls.\n * @memberOf fabric.util\n * @param {Number} width\n * @param {Number} height\n * @param {Object} options\n * @param {Number} options.scaleX\n * @param {Number} options.scaleY\n * @param {Number} options.skewX\n * @param {Number} options.skewY\n * @return {Object.x} width of containing\n * @return {Object.y} height of containing\n */\n sizeAfterTransform: function(width, height, options) {\n var dimX = width / 2, dimY = height / 2,\n points = [\n {\n x: -dimX,\n y: -dimY\n },\n {\n x: dimX,\n y: -dimY\n },\n {\n x: -dimX,\n y: dimY\n },\n {\n x: dimX,\n y: dimY\n }],\n transformMatrix = fabric.util.calcDimensionsMatrix(options),\n bbox = fabric.util.makeBoundingBoxFromPoints(points, transformMatrix);\n return {\n x: bbox.width,\n y: bbox.height,\n };\n },\n\n /**\n * Merges 2 clip paths into one visually equal clip path\n *\n * **IMPORTANT**:\\\n * Does **NOT** clone the arguments, clone them proir if necessary.\n *\n * Creates a wrapper (group) that contains one clip path and is clipped by the other so content is kept where both overlap.\n * Use this method if both the clip paths may have nested clip paths of their own, so assigning one to the other's clip path property is not possible.\n *\n * In order to handle the `inverted` property we follow logic described in the following cases:\\\n * **(1)** both clip paths are inverted - the clip paths pass the inverted prop to the wrapper and loose it themselves.\\\n * **(2)** one is inverted and the other isn't - the wrapper shouldn't become inverted and the inverted clip path must clip the non inverted one to produce an identical visual effect.\\\n * **(3)** both clip paths are not inverted - wrapper and clip paths remain unchanged.\n *\n * @memberOf fabric.util\n * @param {fabric.Object} c1\n * @param {fabric.Object} c2\n * @returns {fabric.Object} merged clip path\n */\n mergeClipPaths: function (c1, c2) {\n var a = c1, b = c2;\n if (a.inverted && !b.inverted) {\n // case (2)\n a = c2;\n b = c1;\n }\n // `b` becomes `a`'s clip path so we transform `b` to `a` coordinate plane\n fabric.util.applyTransformToObject(\n b,\n fabric.util.multiplyTransformMatrices(\n fabric.util.invertTransform(a.calcTransformMatrix()),\n b.calcTransformMatrix()\n )\n );\n // assign the `inverted` prop to the wrapping group\n var inverted = a.inverted && b.inverted;\n if (inverted) {\n // case (1)\n a.inverted = b.inverted = false;\n }\n return new fabric.Group([a], { clipPath: b, inverted: inverted });\n },\n\n /**\n * @memberOf fabric.util\n * @param {Object} prevStyle first style to compare\n * @param {Object} thisStyle second style to compare\n * @param {boolean} forTextSpans whether to check overline, underline, and line-through properties\n * @return {boolean} true if the style changed\n */\n hasStyleChanged: function(prevStyle, thisStyle, forTextSpans) {\n forTextSpans = forTextSpans || false;\n return (prevStyle.fill !== thisStyle.fill ||\n prevStyle.stroke !== thisStyle.stroke ||\n prevStyle.strokeWidth !== thisStyle.strokeWidth ||\n prevStyle.fontSize !== thisStyle.fontSize ||\n prevStyle.fontFamily !== thisStyle.fontFamily ||\n prevStyle.fontWeight !== thisStyle.fontWeight ||\n prevStyle.fontStyle !== thisStyle.fontStyle ||\n prevStyle.textBackgroundColor !== thisStyle.textBackgroundColor ||\n prevStyle.deltaY !== thisStyle.deltaY) ||\n (forTextSpans &&\n (prevStyle.overline !== thisStyle.overline ||\n prevStyle.underline !== thisStyle.underline ||\n prevStyle.linethrough !== thisStyle.linethrough));\n },\n\n /**\n * Returns the array form of a text object's inline styles property with styles grouped in ranges\n * rather than per character. This format is less verbose, and is better suited for storage\n * so it is used in serialization (not during runtime).\n * @memberOf fabric.util\n * @param {object} styles per character styles for a text object\n * @param {String} text the text string that the styles are applied to\n * @return {{start: number, end: number, style: object}[]}\n */\n stylesToArray: function(styles, text) {\n // clone style structure to prevent mutation\n var styles = fabric.util.object.clone(styles, true),\n textLines = text.split('\\n'),\n charIndex = -1, prevStyle = {}, stylesArray = [];\n //loop through each textLine\n for (var i = 0; i < textLines.length; i++) {\n if (!styles[i]) {\n //no styles exist for this line, so add the line's length to the charIndex total\n charIndex += textLines[i].length;\n continue;\n }\n //loop through each character of the current line\n for (var c = 0; c < textLines[i].length; c++) {\n charIndex++;\n var thisStyle = styles[i][c];\n //check if style exists for this character\n if (thisStyle && Object.keys(thisStyle).length > 0) {\n var styleChanged = fabric.util.hasStyleChanged(prevStyle, thisStyle, true);\n if (styleChanged) {\n stylesArray.push({\n start: charIndex,\n end: charIndex + 1,\n style: thisStyle\n });\n }\n else {\n //if style is the same as previous character, increase end index\n stylesArray[stylesArray.length - 1].end++;\n }\n }\n prevStyle = thisStyle || {};\n }\n }\n return stylesArray;\n },\n\n /**\n * Returns the object form of the styles property with styles that are assigned per\n * character rather than grouped by range. This format is more verbose, and is\n * only used during runtime (not for serialization/storage)\n * @memberOf fabric.util\n * @param {Array} styles the serialized form of a text object's styles\n * @param {String} text the text string that the styles are applied to\n * @return {Object}\n */\n stylesFromArray: function(styles, text) {\n if (!Array.isArray(styles)) {\n return styles;\n }\n var textLines = text.split('\\n'),\n charIndex = -1, styleIndex = 0, stylesObject = {};\n //loop through each textLine\n for (var i = 0; i < textLines.length; i++) {\n //loop through each character of the current line\n for (var c = 0; c < textLines[i].length; c++) {\n charIndex++;\n //check if there's a style collection that includes the current character\n if (styles[styleIndex]\n && styles[styleIndex].start <= charIndex\n && charIndex < styles[styleIndex].end) {\n //create object for line index if it doesn't exist\n stylesObject[i] = stylesObject[i] || {};\n //assign a style at this character's index\n stylesObject[i][c] = Object.assign({}, styles[styleIndex].style);\n //if character is at the end of the current style collection, move to the next\n if (charIndex === styles[styleIndex].end - 1) {\n styleIndex++;\n }\n }\n }\n }\n return stylesObject;\n }\n };\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n var _join = Array.prototype.join,\n commandLengths = {\n m: 2,\n l: 2,\n h: 1,\n v: 1,\n c: 6,\n s: 4,\n q: 4,\n t: 2,\n a: 7\n },\n repeatedCommands = {\n m: 'l',\n M: 'L'\n };\n function segmentToBezier(th2, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY) {\n var costh2 = fabric.util.cos(th2),\n sinth2 = fabric.util.sin(th2),\n costh3 = fabric.util.cos(th3),\n sinth3 = fabric.util.sin(th3),\n toX = cosTh * rx * costh3 - sinTh * ry * sinth3 + cx1,\n toY = sinTh * rx * costh3 + cosTh * ry * sinth3 + cy1,\n cp1X = fromX + mT * ( -cosTh * rx * sinth2 - sinTh * ry * costh2),\n cp1Y = fromY + mT * ( -sinTh * rx * sinth2 + cosTh * ry * costh2),\n cp2X = toX + mT * ( cosTh * rx * sinth3 + sinTh * ry * costh3),\n cp2Y = toY + mT * ( sinTh * rx * sinth3 - cosTh * ry * costh3);\n\n return ['C',\n cp1X, cp1Y,\n cp2X, cp2Y,\n toX, toY\n ];\n }\n\n /* Adapted from http://dxr.mozilla.org/mozilla-central/source/content/svg/content/src/nsSVGPathDataParser.cpp\n * by Andrea Bogazzi code is under MPL. if you don't have a copy of the license you can take it here\n * http://mozilla.org/MPL/2.0/\n */\n function arcToSegments(toX, toY, rx, ry, large, sweep, rotateX) {\n var PI = Math.PI, th = rotateX * PI / 180,\n sinTh = fabric.util.sin(th),\n cosTh = fabric.util.cos(th),\n fromX = 0, fromY = 0;\n\n rx = Math.abs(rx);\n ry = Math.abs(ry);\n\n var px = -cosTh * toX * 0.5 - sinTh * toY * 0.5,\n py = -cosTh * toY * 0.5 + sinTh * toX * 0.5,\n rx2 = rx * rx, ry2 = ry * ry, py2 = py * py, px2 = px * px,\n pl = rx2 * ry2 - rx2 * py2 - ry2 * px2,\n root = 0;\n\n if (pl < 0) {\n var s = Math.sqrt(1 - pl / (rx2 * ry2));\n rx *= s;\n ry *= s;\n }\n else {\n root = (large === sweep ? -1.0 : 1.0) *\n Math.sqrt( pl / (rx2 * py2 + ry2 * px2));\n }\n\n var cx = root * rx * py / ry,\n cy = -root * ry * px / rx,\n cx1 = cosTh * cx - sinTh * cy + toX * 0.5,\n cy1 = sinTh * cx + cosTh * cy + toY * 0.5,\n mTheta = calcVectorAngle(1, 0, (px - cx) / rx, (py - cy) / ry),\n dtheta = calcVectorAngle((px - cx) / rx, (py - cy) / ry, (-px - cx) / rx, (-py - cy) / ry);\n\n if (sweep === 0 && dtheta > 0) {\n dtheta -= 2 * PI;\n }\n else if (sweep === 1 && dtheta < 0) {\n dtheta += 2 * PI;\n }\n\n // Convert into cubic bezier segments <= 90deg\n var segments = Math.ceil(Math.abs(dtheta / PI * 2)),\n result = [], mDelta = dtheta / segments,\n mT = 8 / 3 * Math.sin(mDelta / 4) * Math.sin(mDelta / 4) / Math.sin(mDelta / 2),\n th3 = mTheta + mDelta;\n\n for (var i = 0; i < segments; i++) {\n result[i] = segmentToBezier(mTheta, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY);\n fromX = result[i][5];\n fromY = result[i][6];\n mTheta = th3;\n th3 += mDelta;\n }\n return result;\n }\n\n /*\n * Private\n */\n function calcVectorAngle(ux, uy, vx, vy) {\n var ta = Math.atan2(uy, ux),\n tb = Math.atan2(vy, vx);\n if (tb >= ta) {\n return tb - ta;\n }\n else {\n return 2 * Math.PI - (ta - tb);\n }\n }\n\n /**\n * Calculate bounding box of a beziercurve\n * @param {Number} x0 starting point\n * @param {Number} y0\n * @param {Number} x1 first control point\n * @param {Number} y1\n * @param {Number} x2 secondo control point\n * @param {Number} y2\n * @param {Number} x3 end of bezier\n * @param {Number} y3\n */\n // taken from http://jsbin.com/ivomiq/56/edit no credits available for that.\n // TODO: can we normalize this with the starting points set at 0 and then translated the bbox?\n function getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3) {\n var argsString;\n if (fabric.cachesBoundsOfCurve) {\n argsString = _join.call(arguments);\n if (fabric.boundsOfCurveCache[argsString]) {\n return fabric.boundsOfCurveCache[argsString];\n }\n }\n\n var sqrt = Math.sqrt,\n min = Math.min, max = Math.max,\n abs = Math.abs, tvalues = [],\n bounds = [[], []],\n a, b, c, t, t1, t2, b2ac, sqrtb2ac;\n\n b = 6 * x0 - 12 * x1 + 6 * x2;\n a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;\n c = 3 * x1 - 3 * x0;\n\n for (var i = 0; i < 2; ++i) {\n if (i > 0) {\n b = 6 * y0 - 12 * y1 + 6 * y2;\n a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;\n c = 3 * y1 - 3 * y0;\n }\n\n if (abs(a) < 1e-12) {\n if (abs(b) < 1e-12) {\n continue;\n }\n t = -c / b;\n if (0 < t && t < 1) {\n tvalues.push(t);\n }\n continue;\n }\n b2ac = b * b - 4 * c * a;\n if (b2ac < 0) {\n continue;\n }\n sqrtb2ac = sqrt(b2ac);\n t1 = (-b + sqrtb2ac) / (2 * a);\n if (0 < t1 && t1 < 1) {\n tvalues.push(t1);\n }\n t2 = (-b - sqrtb2ac) / (2 * a);\n if (0 < t2 && t2 < 1) {\n tvalues.push(t2);\n }\n }\n\n var x, y, j = tvalues.length, jlen = j, mt;\n while (j--) {\n t = tvalues[j];\n mt = 1 - t;\n x = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3);\n bounds[0][j] = x;\n\n y = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3);\n bounds[1][j] = y;\n }\n\n bounds[0][jlen] = x0;\n bounds[1][jlen] = y0;\n bounds[0][jlen + 1] = x3;\n bounds[1][jlen + 1] = y3;\n var result = [\n {\n x: min.apply(null, bounds[0]),\n y: min.apply(null, bounds[1])\n },\n {\n x: max.apply(null, bounds[0]),\n y: max.apply(null, bounds[1])\n }\n ];\n if (fabric.cachesBoundsOfCurve) {\n fabric.boundsOfCurveCache[argsString] = result;\n }\n return result;\n }\n\n /**\n * Converts arc to a bunch of bezier curves\n * @param {Number} fx starting point x\n * @param {Number} fy starting point y\n * @param {Array} coords Arc command\n */\n function fromArcToBeziers(fx, fy, coords) {\n var rx = coords[1],\n ry = coords[2],\n rot = coords[3],\n large = coords[4],\n sweep = coords[5],\n tx = coords[6],\n ty = coords[7],\n segsNorm = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);\n\n for (var i = 0, len = segsNorm.length; i < len; i++) {\n segsNorm[i][1] += fx;\n segsNorm[i][2] += fy;\n segsNorm[i][3] += fx;\n segsNorm[i][4] += fy;\n segsNorm[i][5] += fx;\n segsNorm[i][6] += fy;\n }\n return segsNorm;\n };\n\n /**\n * This function take a parsed SVG path and make it simpler for fabricJS logic.\n * simplification consist of: only UPPERCASE absolute commands ( relative converted to absolute )\n * S converted in C, T converted in Q, A converted in C.\n * @param {Array} path the array of commands of a parsed svg path for fabric.Path\n * @return {Array} the simplified array of commands of a parsed svg path for fabric.Path\n */\n function makePathSimpler(path) {\n // x and y represent the last point of the path. the previous command point.\n // we add them to each relative command to make it an absolute comment.\n // we also swap the v V h H with L, because are easier to transform.\n var x = 0, y = 0, len = path.length,\n // x1 and y1 represent the last point of the subpath. the subpath is started with\n // m or M command. When a z or Z command is drawn, x and y need to be resetted to\n // the last x1 and y1.\n x1 = 0, y1 = 0, current, i, converted,\n // previous will host the letter of the previous command, to handle S and T.\n // controlX and controlY will host the previous reflected control point\n destinationPath = [], previous, controlX, controlY;\n for (i = 0; i < len; ++i) {\n converted = false;\n current = path[i].slice(0);\n switch (current[0]) { // first letter\n case 'l': // lineto, relative\n current[0] = 'L';\n current[1] += x;\n current[2] += y;\n // falls through\n case 'L':\n x = current[1];\n y = current[2];\n break;\n case 'h': // horizontal lineto, relative\n current[1] += x;\n // falls through\n case 'H':\n current[0] = 'L';\n current[2] = y;\n x = current[1];\n break;\n case 'v': // vertical lineto, relative\n current[1] += y;\n // falls through\n case 'V':\n current[0] = 'L';\n y = current[1];\n current[1] = x;\n current[2] = y;\n break;\n case 'm': // moveTo, relative\n current[0] = 'M';\n current[1] += x;\n current[2] += y;\n // falls through\n case 'M':\n x = current[1];\n y = current[2];\n x1 = current[1];\n y1 = current[2];\n break;\n case 'c': // bezierCurveTo, relative\n current[0] = 'C';\n current[1] += x;\n current[2] += y;\n current[3] += x;\n current[4] += y;\n current[5] += x;\n current[6] += y;\n // falls through\n case 'C':\n controlX = current[3];\n controlY = current[4];\n x = current[5];\n y = current[6];\n break;\n case 's': // shorthand cubic bezierCurveTo, relative\n current[0] = 'S';\n current[1] += x;\n current[2] += y;\n current[3] += x;\n current[4] += y;\n // falls through\n case 'S':\n // would be sScC but since we are swapping sSc for C, we check just that.\n if (previous === 'C') {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n else {\n // If there is no previous command or if the previous command was not a C, c, S, or s,\n // the control point is coincident with the current point\n controlX = x;\n controlY = y;\n }\n x = current[3];\n y = current[4];\n current[0] = 'C';\n current[5] = current[3];\n current[6] = current[4];\n current[3] = current[1];\n current[4] = current[2];\n current[1] = controlX;\n current[2] = controlY;\n // current[3] and current[4] are NOW the second control point.\n // we keep it for the next reflection.\n controlX = current[3];\n controlY = current[4];\n break;\n case 'q': // quadraticCurveTo, relative\n current[0] = 'Q';\n current[1] += x;\n current[2] += y;\n current[3] += x;\n current[4] += y;\n // falls through\n case 'Q':\n controlX = current[1];\n controlY = current[2];\n x = current[3];\n y = current[4];\n break;\n case 't': // shorthand quadraticCurveTo, relative\n current[0] = 'T';\n current[1] += x;\n current[2] += y;\n // falls through\n case 'T':\n if (previous === 'Q') {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n else {\n // If there is no previous command or if the previous command was not a Q, q, T or t,\n // assume the control point is coincident with the current point\n controlX = x;\n controlY = y;\n }\n current[0] = 'Q';\n x = current[1];\n y = current[2];\n current[1] = controlX;\n current[2] = controlY;\n current[3] = x;\n current[4] = y;\n break;\n case 'a':\n current[0] = 'A';\n current[6] += x;\n current[7] += y;\n // falls through\n case 'A':\n converted = true;\n destinationPath = destinationPath.concat(fromArcToBeziers(x, y, current));\n x = current[6];\n y = current[7];\n break;\n case 'z':\n case 'Z':\n x = x1;\n y = y1;\n break;\n default:\n }\n if (!converted) {\n destinationPath.push(current);\n }\n previous = current[0];\n }\n return destinationPath;\n };\n\n /**\n * Calc length from point x1,y1 to x2,y2\n * @param {Number} x1 starting point x\n * @param {Number} y1 starting point y\n * @param {Number} x2 starting point x\n * @param {Number} y2 starting point y\n * @return {Number} length of segment\n */\n function calcLineLength(x1, y1, x2, y2) {\n return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));\n }\n\n // functions for the Cubic beizer\n // taken from: https://github.com/konvajs/konva/blob/7.0.5/src/shapes/Path.ts#L350\n function CB1(t) {\n return t * t * t;\n }\n function CB2(t) {\n return 3 * t * t * (1 - t);\n }\n function CB3(t) {\n return 3 * t * (1 - t) * (1 - t);\n }\n function CB4(t) {\n return (1 - t) * (1 - t) * (1 - t);\n }\n\n function getPointOnCubicBezierIterator(p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y) {\n return function(pct) {\n var c1 = CB1(pct), c2 = CB2(pct), c3 = CB3(pct), c4 = CB4(pct);\n return {\n x: p4x * c1 + p3x * c2 + p2x * c3 + p1x * c4,\n y: p4y * c1 + p3y * c2 + p2y * c3 + p1y * c4\n };\n };\n }\n\n function getTangentCubicIterator(p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y) {\n return function (pct) {\n var invT = 1 - pct,\n tangentX = (3 * invT * invT * (p2x - p1x)) + (6 * invT * pct * (p3x - p2x)) +\n (3 * pct * pct * (p4x - p3x)),\n tangentY = (3 * invT * invT * (p2y - p1y)) + (6 * invT * pct * (p3y - p2y)) +\n (3 * pct * pct * (p4y - p3y));\n return Math.atan2(tangentY, tangentX);\n };\n }\n\n function QB1(t) {\n return t * t;\n }\n\n function QB2(t) {\n return 2 * t * (1 - t);\n }\n\n function QB3(t) {\n return (1 - t) * (1 - t);\n }\n\n function getPointOnQuadraticBezierIterator(p1x, p1y, p2x, p2y, p3x, p3y) {\n return function(pct) {\n var c1 = QB1(pct), c2 = QB2(pct), c3 = QB3(pct);\n return {\n x: p3x * c1 + p2x * c2 + p1x * c3,\n y: p3y * c1 + p2y * c2 + p1y * c3\n };\n };\n }\n\n function getTangentQuadraticIterator(p1x, p1y, p2x, p2y, p3x, p3y) {\n return function (pct) {\n var invT = 1 - pct,\n tangentX = (2 * invT * (p2x - p1x)) + (2 * pct * (p3x - p2x)),\n tangentY = (2 * invT * (p2y - p1y)) + (2 * pct * (p3y - p2y));\n return Math.atan2(tangentY, tangentX);\n };\n }\n\n\n // this will run over a path segment ( a cubic or quadratic segment) and approximate it\n // with 100 segemnts. This will good enough to calculate the length of the curve\n function pathIterator(iterator, x1, y1) {\n var tempP = { x: x1, y: y1 }, p, tmpLen = 0, perc;\n for (perc = 1; perc <= 100; perc += 1) {\n p = iterator(perc / 100);\n tmpLen += calcLineLength(tempP.x, tempP.y, p.x, p.y);\n tempP = p;\n }\n return tmpLen;\n }\n\n /**\n * Given a pathInfo, and a distance in pixels, find the percentage from 0 to 1\n * that correspond to that pixels run over the path.\n * The percentage will be then used to find the correct point on the canvas for the path.\n * @param {Array} segInfo fabricJS collection of information on a parsed path\n * @param {Number} distance from starting point, in pixels.\n * @return {Object} info object with x and y ( the point on canvas ) and angle, the tangent on that point;\n */\n function findPercentageForDistance(segInfo, distance) {\n var perc = 0, tmpLen = 0, iterator = segInfo.iterator, tempP = { x: segInfo.x, y: segInfo.y },\n p, nextLen, nextStep = 0.01, angleFinder = segInfo.angleFinder, lastPerc;\n // nextStep > 0.0001 covers 0.00015625 that 1/64th of 1/100\n // the path\n while (tmpLen < distance && nextStep > 0.0001) {\n p = iterator(perc);\n lastPerc = perc;\n nextLen = calcLineLength(tempP.x, tempP.y, p.x, p.y);\n // compare tmpLen each cycle with distance, decide next perc to test.\n if ((nextLen + tmpLen) > distance) {\n // we discard this step and we make smaller steps.\n perc -= nextStep;\n nextStep /= 2;\n }\n else {\n tempP = p;\n perc += nextStep;\n tmpLen += nextLen;\n }\n }\n p.angle = angleFinder(lastPerc);\n return p;\n }\n\n /**\n * Run over a parsed and simplifed path and extrac some informations.\n * informations are length of each command and starting point\n * @param {Array} path fabricJS parsed path commands\n * @return {Array} path commands informations\n */\n function getPathSegmentsInfo(path) {\n var totalLength = 0, len = path.length, current,\n //x2 and y2 are the coords of segment start\n //x1 and y1 are the coords of the current point\n x1 = 0, y1 = 0, x2 = 0, y2 = 0, info = [], iterator, tempInfo, angleFinder;\n for (var i = 0; i < len; i++) {\n current = path[i];\n tempInfo = {\n x: x1,\n y: y1,\n command: current[0],\n };\n switch (current[0]) { //first letter\n case 'M':\n tempInfo.length = 0;\n x2 = x1 = current[1];\n y2 = y1 = current[2];\n break;\n case 'L':\n tempInfo.length = calcLineLength(x1, y1, current[1], current[2]);\n x1 = current[1];\n y1 = current[2];\n break;\n case 'C':\n iterator = getPointOnCubicBezierIterator(\n x1,\n y1,\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6]\n );\n angleFinder = getTangentCubicIterator(\n x1,\n y1,\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6]\n );\n tempInfo.iterator = iterator;\n tempInfo.angleFinder = angleFinder;\n tempInfo.length = pathIterator(iterator, x1, y1);\n x1 = current[5];\n y1 = current[6];\n break;\n case 'Q':\n iterator = getPointOnQuadraticBezierIterator(\n x1,\n y1,\n current[1],\n current[2],\n current[3],\n current[4]\n );\n angleFinder = getTangentQuadraticIterator(\n x1,\n y1,\n current[1],\n current[2],\n current[3],\n current[4]\n );\n tempInfo.iterator = iterator;\n tempInfo.angleFinder = angleFinder;\n tempInfo.length = pathIterator(iterator, x1, y1);\n x1 = current[3];\n y1 = current[4];\n break;\n case 'Z':\n case 'z':\n // we add those in order to ease calculations later\n tempInfo.destX = x2;\n tempInfo.destY = y2;\n tempInfo.length = calcLineLength(x1, y1, x2, y2);\n x1 = x2;\n y1 = y2;\n break;\n }\n totalLength += tempInfo.length;\n info.push(tempInfo);\n }\n info.push({ length: totalLength, x: x1, y: y1 });\n return info;\n }\n\n function getPointOnPath(path, distance, infos) {\n if (!infos) {\n infos = getPathSegmentsInfo(path);\n }\n var i = 0;\n while ((distance - infos[i].length > 0) && i < (infos.length - 2)) {\n distance -= infos[i].length;\n i++;\n }\n // var distance = infos[infos.length - 1] * perc;\n var segInfo = infos[i], segPercent = distance / segInfo.length,\n command = segInfo.command, segment = path[i], info;\n\n switch (command) {\n case 'M':\n return { x: segInfo.x, y: segInfo.y, angle: 0 };\n case 'Z':\n case 'z':\n info = new fabric.Point(segInfo.x, segInfo.y).lerp(\n new fabric.Point(segInfo.destX, segInfo.destY),\n segPercent\n );\n info.angle = Math.atan2(segInfo.destY - segInfo.y, segInfo.destX - segInfo.x);\n return info;\n case 'L':\n info = new fabric.Point(segInfo.x, segInfo.y).lerp(\n new fabric.Point(segment[1], segment[2]),\n segPercent\n );\n info.angle = Math.atan2(segment[2] - segInfo.y, segment[1] - segInfo.x);\n return info;\n case 'C':\n return findPercentageForDistance(segInfo, distance);\n case 'Q':\n return findPercentageForDistance(segInfo, distance);\n }\n }\n\n /**\n *\n * @param {string} pathString\n * @return {(string|number)[][]} An array of SVG path commands\n * @example Usage\n * parsePath('M 3 4 Q 3 5 2 1 4 0 Q 9 12 2 1 4 0') === [\n * ['M', 3, 4],\n * ['Q', 3, 5, 2, 1, 4, 0],\n * ['Q', 9, 12, 2, 1, 4, 0],\n * ];\n *\n */\n function parsePath(pathString) {\n var result = [],\n coords = [],\n currentPath,\n parsed,\n re = fabric.rePathCommand,\n rNumber = '[-+]?(?:\\\\d*\\\\.\\\\d+|\\\\d+\\\\.?)(?:[eE][-+]?\\\\d+)?\\\\s*',\n rNumberCommaWsp = '(' + rNumber + ')' + fabric.commaWsp,\n rFlagCommaWsp = '([01])' + fabric.commaWsp + '?',\n rArcSeq = rNumberCommaWsp + '?' + rNumberCommaWsp + '?' + rNumberCommaWsp + rFlagCommaWsp + rFlagCommaWsp +\n rNumberCommaWsp + '?(' + rNumber + ')',\n regArcArgumentSequence = new RegExp(rArcSeq, 'g'),\n match,\n coordsStr,\n // one of commands (m,M,l,L,q,Q,c,C,etc.) followed by non-command characters (i.e. command values)\n path;\n if (!pathString || !pathString.match) {\n return result;\n }\n path = pathString.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi);\n\n for (var i = 0, coordsParsed, len = path.length; i < len; i++) {\n currentPath = path[i];\n\n coordsStr = currentPath.slice(1).trim();\n coords.length = 0;\n\n var command = currentPath.charAt(0);\n coordsParsed = [command];\n\n if (command.toLowerCase() === 'a') {\n // arcs have special flags that apparently don't require spaces so handle special\n for (var args; (args = regArcArgumentSequence.exec(coordsStr));) {\n for (var j = 1; j < args.length; j++) {\n coords.push(args[j]);\n }\n }\n }\n else {\n while ((match = re.exec(coordsStr))) {\n coords.push(match[0]);\n }\n }\n\n for (var j = 0, jlen = coords.length; j < jlen; j++) {\n parsed = parseFloat(coords[j]);\n if (!isNaN(parsed)) {\n coordsParsed.push(parsed);\n }\n }\n\n var commandLength = commandLengths[command.toLowerCase()],\n repeatedCommand = repeatedCommands[command] || command;\n\n if (coordsParsed.length - 1 > commandLength) {\n for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) {\n result.push([command].concat(coordsParsed.slice(k, k + commandLength)));\n command = repeatedCommand;\n }\n }\n else {\n result.push(coordsParsed);\n }\n }\n\n return result;\n };\n\n /**\n *\n * Converts points to a smooth SVG path\n * @param {{ x: number,y: number }[]} points Array of points\n * @param {number} [correction] Apply a correction to the path (usually we use `width / 1000`). If value is undefined 0 is used as the correction value.\n * @return {(string|number)[][]} An array of SVG path commands\n */\n function getSmoothPathFromPoints(points, correction) {\n var path = [], i,\n p1 = new fabric.Point(points[0].x, points[0].y),\n p2 = new fabric.Point(points[1].x, points[1].y),\n len = points.length, multSignX = 1, multSignY = 0, manyPoints = len > 2;\n correction = correction || 0;\n\n if (manyPoints) {\n multSignX = points[2].x < p2.x ? -1 : points[2].x === p2.x ? 0 : 1;\n multSignY = points[2].y < p2.y ? -1 : points[2].y === p2.y ? 0 : 1;\n }\n path.push(['M', p1.x - multSignX * correction, p1.y - multSignY * correction]);\n for (i = 1; i < len; i++) {\n if (!p1.eq(p2)) {\n var midPoint = p1.midPointFrom(p2);\n // p1 is our bezier control point\n // midpoint is our endpoint\n // start point is p(i-1) value.\n path.push(['Q', p1.x, p1.y, midPoint.x, midPoint.y]);\n }\n p1 = points[i];\n if ((i + 1) < points.length) {\n p2 = points[i + 1];\n }\n }\n if (manyPoints) {\n multSignX = p1.x > points[i - 2].x ? 1 : p1.x === points[i - 2].x ? 0 : -1;\n multSignY = p1.y > points[i - 2].y ? 1 : p1.y === points[i - 2].y ? 0 : -1;\n }\n path.push(['L', p1.x + multSignX * correction, p1.y + multSignY * correction]);\n return path;\n }\n /**\n * Transform a path by transforming each segment.\n * it has to be a simplified path or it won't work.\n * WARNING: this depends from pathOffset for correct operation\n * @param {Array} path fabricJS parsed and simplified path commands\n * @param {Array} transform matrix that represent the transformation\n * @param {Object} [pathOffset] the fabric.Path pathOffset\n * @param {Number} pathOffset.x\n * @param {Number} pathOffset.y\n * @returns {Array} the transformed path\n */\n function transformPath(path, transform, pathOffset) {\n if (pathOffset) {\n transform = fabric.util.multiplyTransformMatrices(\n transform,\n [1, 0, 0, 1, -pathOffset.x, -pathOffset.y]\n );\n }\n return path.map(function(pathSegment) {\n var newSegment = pathSegment.slice(0), point = {};\n for (var i = 1; i < pathSegment.length - 1; i += 2) {\n point.x = pathSegment[i];\n point.y = pathSegment[i + 1];\n point = fabric.util.transformPoint(point, transform);\n newSegment[i] = point.x;\n newSegment[i + 1] = point.y;\n }\n return newSegment;\n });\n }\n\n /**\n * Join path commands to go back to svg format\n * @param {Array} pathData fabricJS parsed path commands\n * @return {String} joined path 'M 0 0 L 20 30'\n */\n fabric.util.joinPath = function(pathData) {\n return pathData.map(function (segment) { return segment.join(' '); }).join(' ');\n };\n fabric.util.parsePath = parsePath;\n fabric.util.makePathSimpler = makePathSimpler;\n fabric.util.getSmoothPathFromPoints = getSmoothPathFromPoints;\n fabric.util.getPathSegmentsInfo = getPathSegmentsInfo;\n fabric.util.getBoundsOfCurve = getBoundsOfCurve;\n fabric.util.getPointOnPath = getPointOnPath;\n fabric.util.transformPath = transformPath;\n})();\n\n\n(function() {\n\n var slice = Array.prototype.slice;\n\n /**\n * Invokes method on all items in a given array\n * @memberOf fabric.util.array\n * @param {Array} array Array to iterate over\n * @param {String} method Name of a method to invoke\n * @return {Array}\n */\n function invoke(array, method) {\n var args = slice.call(arguments, 2), result = [];\n for (var i = 0, len = array.length; i < len; i++) {\n result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]);\n }\n return result;\n }\n\n /**\n * Finds maximum value in array (not necessarily \"first\" one)\n * @memberOf fabric.util.array\n * @param {Array} array Array to iterate over\n * @param {String} byProperty\n * @return {*}\n */\n function max(array, byProperty) {\n return find(array, byProperty, function(value1, value2) {\n return value1 >= value2;\n });\n }\n\n /**\n * Finds minimum value in array (not necessarily \"first\" one)\n * @memberOf fabric.util.array\n * @param {Array} array Array to iterate over\n * @param {String} byProperty\n * @return {*}\n */\n function min(array, byProperty) {\n return find(array, byProperty, function(value1, value2) {\n return value1 < value2;\n });\n }\n\n /**\n * @private\n */\n function fill(array, value) {\n var k = array.length;\n while (k--) {\n array[k] = value;\n }\n return array;\n }\n\n /**\n * @private\n */\n function find(array, byProperty, condition) {\n if (!array || array.length === 0) {\n return;\n }\n\n var i = array.length - 1,\n result = byProperty ? array[i][byProperty] : array[i];\n if (byProperty) {\n while (i--) {\n if (condition(array[i][byProperty], result)) {\n result = array[i][byProperty];\n }\n }\n }\n else {\n while (i--) {\n if (condition(array[i], result)) {\n result = array[i];\n }\n }\n }\n return result;\n }\n\n /**\n * @namespace fabric.util.array\n */\n fabric.util.array = {\n fill: fill,\n invoke: invoke,\n min: min,\n max: max\n };\n\n})();\n\n\n(function() {\n /**\n * Copies all enumerable properties of one js object to another\n * this does not and cannot compete with generic utils.\n * Does not clone or extend fabric.Object subclasses.\n * This is mostly for internal use and has extra handling for fabricJS objects\n * it skips the canvas and group properties in deep cloning.\n * @memberOf fabric.util.object\n * @param {Object} destination Where to copy to\n * @param {Object} source Where to copy from\n * @param {Boolean} [deep] Whether to extend nested objects\n * @return {Object}\n */\n\n function extend(destination, source, deep) {\n // JScript DontEnum bug is not taken care of\n // the deep clone is for internal use, is not meant to avoid\n // javascript traps or cloning html element or self referenced objects.\n if (deep) {\n if (!fabric.isLikelyNode && source instanceof Element) {\n // avoid cloning deep images, canvases,\n destination = source;\n }\n else if (source instanceof Array) {\n destination = [];\n for (var i = 0, len = source.length; i < len; i++) {\n destination[i] = extend({ }, source[i], deep);\n }\n }\n else if (source && typeof source === 'object') {\n for (var property in source) {\n if (property === 'canvas' || property === 'group') {\n // we do not want to clone this props at all.\n // we want to keep the keys in the copy\n destination[property] = null;\n }\n else if (source.hasOwnProperty(property)) {\n destination[property] = extend({ }, source[property], deep);\n }\n }\n }\n else {\n // this sounds odd for an extend but is ok for recursive use\n destination = source;\n }\n }\n else {\n for (var property in source) {\n destination[property] = source[property];\n }\n }\n return destination;\n }\n\n /**\n * Creates an empty object and copies all enumerable properties of another object to it\n * This method is mostly for internal use, and not intended for duplicating shapes in canvas. \n * @memberOf fabric.util.object\n * @param {Object} object Object to clone\n * @param {Boolean} [deep] Whether to clone nested objects\n * @return {Object}\n */\n\n //TODO: this function return an empty object if you try to clone null\n function clone(object, deep) {\n return extend({ }, object, deep);\n }\n\n /** @namespace fabric.util.object */\n fabric.util.object = {\n extend: extend,\n clone: clone\n };\n fabric.util.object.extend(fabric.util, fabric.Observable);\n})();\n\n\n(function() {\n\n /**\n * Camelizes a string\n * @memberOf fabric.util.string\n * @param {String} string String to camelize\n * @return {String} Camelized version of a string\n */\n function camelize(string) {\n return string.replace(/-+(.)?/g, function(match, character) {\n return character ? character.toUpperCase() : '';\n });\n }\n\n /**\n * Capitalizes a string\n * @memberOf fabric.util.string\n * @param {String} string String to capitalize\n * @param {Boolean} [firstLetterOnly] If true only first letter is capitalized\n * and other letters stay untouched, if false first letter is capitalized\n * and other letters are converted to lowercase.\n * @return {String} Capitalized version of a string\n */\n function capitalize(string, firstLetterOnly) {\n return string.charAt(0).toUpperCase() +\n (firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase());\n }\n\n /**\n * Escapes XML in a string\n * @memberOf fabric.util.string\n * @param {String} string String to escape\n * @return {String} Escaped version of a string\n */\n function escapeXml(string) {\n return string.replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .replace(//g, '>');\n }\n\n /**\n * Divide a string in the user perceived single units\n * @memberOf fabric.util.string\n * @param {String} textstring String to escape\n * @return {Array} array containing the graphemes\n */\n function graphemeSplit(textstring) {\n var i = 0, chr, graphemes = [];\n for (i = 0, chr; i < textstring.length; i++) {\n if ((chr = getWholeChar(textstring, i)) === false) {\n continue;\n }\n graphemes.push(chr);\n }\n return graphemes;\n }\n\n // taken from mdn in the charAt doc page.\n function getWholeChar(str, i) {\n var code = str.charCodeAt(i);\n\n if (isNaN(code)) {\n return ''; // Position not found\n }\n if (code < 0xD800 || code > 0xDFFF) {\n return str.charAt(i);\n }\n\n // High surrogate (could change last hex to 0xDB7F to treat high private\n // surrogates as single characters)\n if (0xD800 <= code && code <= 0xDBFF) {\n if (str.length <= (i + 1)) {\n throw 'High surrogate without following low surrogate';\n }\n var next = str.charCodeAt(i + 1);\n if (0xDC00 > next || next > 0xDFFF) {\n throw 'High surrogate without following low surrogate';\n }\n return str.charAt(i) + str.charAt(i + 1);\n }\n // Low surrogate (0xDC00 <= code && code <= 0xDFFF)\n if (i === 0) {\n throw 'Low surrogate without preceding high surrogate';\n }\n var prev = str.charCodeAt(i - 1);\n\n // (could change last hex to 0xDB7F to treat high private\n // surrogates as single characters)\n if (0xD800 > prev || prev > 0xDBFF) {\n throw 'Low surrogate without preceding high surrogate';\n }\n // We can pass over low surrogates now as the second component\n // in a pair which we have already processed\n return false;\n }\n\n\n /**\n * String utilities\n * @namespace fabric.util.string\n */\n fabric.util.string = {\n camelize: camelize,\n capitalize: capitalize,\n escapeXml: escapeXml,\n graphemeSplit: graphemeSplit\n };\n})();\n\n\n(function() {\n\n var slice = Array.prototype.slice, emptyFunction = function() { },\n\n IS_DONTENUM_BUGGY = (function() {\n for (var p in { toString: 1 }) {\n if (p === 'toString') {\n return false;\n }\n }\n return true;\n })(),\n\n /** @ignore */\n addMethods = function(klass, source, parent) {\n for (var property in source) {\n\n if (property in klass.prototype &&\n typeof klass.prototype[property] === 'function' &&\n (source[property] + '').indexOf('callSuper') > -1) {\n\n klass.prototype[property] = (function(property) {\n return function() {\n\n var superclass = this.constructor.superclass;\n this.constructor.superclass = parent;\n var returnValue = source[property].apply(this, arguments);\n this.constructor.superclass = superclass;\n\n if (property !== 'initialize') {\n return returnValue;\n }\n };\n })(property);\n }\n else {\n klass.prototype[property] = source[property];\n }\n\n if (IS_DONTENUM_BUGGY) {\n if (source.toString !== Object.prototype.toString) {\n klass.prototype.toString = source.toString;\n }\n if (source.valueOf !== Object.prototype.valueOf) {\n klass.prototype.valueOf = source.valueOf;\n }\n }\n }\n };\n\n function Subclass() { }\n\n function callSuper(methodName) {\n var parentMethod = null,\n _this = this;\n\n // climb prototype chain to find method not equal to callee's method\n while (_this.constructor.superclass) {\n var superClassMethod = _this.constructor.superclass.prototype[methodName];\n if (_this[methodName] !== superClassMethod) {\n parentMethod = superClassMethod;\n break;\n }\n // eslint-disable-next-line\n _this = _this.constructor.superclass.prototype;\n }\n\n if (!parentMethod) {\n return console.log('tried to callSuper ' + methodName + ', method not found in prototype chain', this);\n }\n\n return (arguments.length > 1)\n ? parentMethod.apply(this, slice.call(arguments, 1))\n : parentMethod.call(this);\n }\n\n /**\n * Helper for creation of \"classes\".\n * @memberOf fabric.util\n * @param {Function} [parent] optional \"Class\" to inherit from\n * @param {Object} [properties] Properties shared by all instances of this class\n * (be careful modifying objects defined here as this would affect all instances)\n */\n function createClass() {\n var parent = null,\n properties = slice.call(arguments, 0);\n\n if (typeof properties[0] === 'function') {\n parent = properties.shift();\n }\n function klass() {\n this.initialize.apply(this, arguments);\n }\n\n klass.superclass = parent;\n klass.subclasses = [];\n\n if (parent) {\n Subclass.prototype = parent.prototype;\n klass.prototype = new Subclass();\n parent.subclasses.push(klass);\n }\n for (var i = 0, length = properties.length; i < length; i++) {\n addMethods(klass, properties[i], parent);\n }\n if (!klass.prototype.initialize) {\n klass.prototype.initialize = emptyFunction;\n }\n klass.prototype.constructor = klass;\n klass.prototype.callSuper = callSuper;\n return klass;\n }\n\n fabric.util.createClass = createClass;\n})();\n\n\n(function () {\n // since ie11 can use addEventListener but they do not support options, i need to check\n var couldUseAttachEvent = !!fabric.document.createElement('div').attachEvent,\n touchEvents = ['touchstart', 'touchmove', 'touchend'];\n /**\n * Adds an event listener to an element\n * @function\n * @memberOf fabric.util\n * @param {HTMLElement} element\n * @param {String} eventName\n * @param {Function} handler\n */\n fabric.util.addListener = function(element, eventName, handler, options) {\n element && element.addEventListener(eventName, handler, couldUseAttachEvent ? false : options);\n };\n\n /**\n * Removes an event listener from an element\n * @function\n * @memberOf fabric.util\n * @param {HTMLElement} element\n * @param {String} eventName\n * @param {Function} handler\n */\n fabric.util.removeListener = function(element, eventName, handler, options) {\n element && element.removeEventListener(eventName, handler, couldUseAttachEvent ? false : options);\n };\n\n function getTouchInfo(event) {\n var touchProp = event.changedTouches;\n if (touchProp && touchProp[0]) {\n return touchProp[0];\n }\n return event;\n }\n\n fabric.util.getPointer = function(event) {\n var element = event.target,\n scroll = fabric.util.getScrollLeftTop(element),\n _evt = getTouchInfo(event);\n return {\n x: _evt.clientX + scroll.left,\n y: _evt.clientY + scroll.top\n };\n };\n\n fabric.util.isTouchEvent = function(event) {\n return touchEvents.indexOf(event.type) > -1 || event.pointerType === 'touch';\n };\n})();\n\n\n(function () {\n\n /**\n * Cross-browser wrapper for setting element's style\n * @memberOf fabric.util\n * @param {HTMLElement} element\n * @param {Object} styles\n * @return {HTMLElement} Element that was passed as a first argument\n */\n function setStyle(element, styles) {\n var elementStyle = element.style;\n if (!elementStyle) {\n return element;\n }\n if (typeof styles === 'string') {\n element.style.cssText += ';' + styles;\n return styles.indexOf('opacity') > -1\n ? setOpacity(element, styles.match(/opacity:\\s*(\\d?\\.?\\d*)/)[1])\n : element;\n }\n for (var property in styles) {\n if (property === 'opacity') {\n setOpacity(element, styles[property]);\n }\n else {\n var normalizedProperty = (property === 'float' || property === 'cssFloat')\n ? (typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat')\n : property;\n elementStyle.setProperty(normalizedProperty, styles[property]);\n }\n }\n return element;\n }\n\n var parseEl = fabric.document.createElement('div'),\n supportsOpacity = typeof parseEl.style.opacity === 'string',\n supportsFilters = typeof parseEl.style.filter === 'string',\n reOpacity = /alpha\\s*\\(\\s*opacity\\s*=\\s*([^\\)]+)\\)/,\n\n /** @ignore */\n setOpacity = function (element) { return element; };\n\n if (supportsOpacity) {\n /** @ignore */\n setOpacity = function(element, value) {\n element.style.opacity = value;\n return element;\n };\n }\n else if (supportsFilters) {\n /** @ignore */\n setOpacity = function(element, value) {\n var es = element.style;\n if (element.currentStyle && !element.currentStyle.hasLayout) {\n es.zoom = 1;\n }\n if (reOpacity.test(es.filter)) {\n value = value >= 0.9999 ? '' : ('alpha(opacity=' + (value * 100) + ')');\n es.filter = es.filter.replace(reOpacity, value);\n }\n else {\n es.filter += ' alpha(opacity=' + (value * 100) + ')';\n }\n return element;\n };\n }\n\n fabric.util.setStyle = setStyle;\n\n})();\n\n\n(function() {\n\n var _slice = Array.prototype.slice;\n\n /**\n * Takes id and returns an element with that id (if one exists in a document)\n * @memberOf fabric.util\n * @param {String|HTMLElement} id\n * @return {HTMLElement|null}\n */\n function getById(id) {\n return typeof id === 'string' ? fabric.document.getElementById(id) : id;\n }\n\n var sliceCanConvertNodelists,\n /**\n * Converts an array-like object (e.g. arguments or NodeList) to an array\n * @memberOf fabric.util\n * @param {Object} arrayLike\n * @return {Array}\n */\n toArray = function(arrayLike) {\n return _slice.call(arrayLike, 0);\n };\n\n try {\n sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array;\n }\n catch (err) { }\n\n if (!sliceCanConvertNodelists) {\n toArray = function(arrayLike) {\n var arr = new Array(arrayLike.length), i = arrayLike.length;\n while (i--) {\n arr[i] = arrayLike[i];\n }\n return arr;\n };\n }\n\n /**\n * Creates specified element with specified attributes\n * @memberOf fabric.util\n * @param {String} tagName Type of an element to create\n * @param {Object} [attributes] Attributes to set on an element\n * @return {HTMLElement} Newly created element\n */\n function makeElement(tagName, attributes) {\n var el = fabric.document.createElement(tagName);\n for (var prop in attributes) {\n if (prop === 'class') {\n el.className = attributes[prop];\n }\n else if (prop === 'for') {\n el.htmlFor = attributes[prop];\n }\n else {\n el.setAttribute(prop, attributes[prop]);\n }\n }\n return el;\n }\n\n /**\n * Adds class to an element\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to add class to\n * @param {String} className Class to add to an element\n */\n function addClass(element, className) {\n if (element && (' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) {\n element.className += (element.className ? ' ' : '') + className;\n }\n }\n\n /**\n * Wraps element with another element\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to wrap\n * @param {HTMLElement|String} wrapper Element to wrap with\n * @param {Object} [attributes] Attributes to set on a wrapper\n * @return {HTMLElement} wrapper\n */\n function wrapElement(element, wrapper, attributes) {\n if (typeof wrapper === 'string') {\n wrapper = makeElement(wrapper, attributes);\n }\n if (element.parentNode) {\n element.parentNode.replaceChild(wrapper, element);\n }\n wrapper.appendChild(element);\n return wrapper;\n }\n\n /**\n * Returns element scroll offsets\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to operate on\n * @return {Object} Object with left/top values\n */\n function getScrollLeftTop(element) {\n\n var left = 0,\n top = 0,\n docElement = fabric.document.documentElement,\n body = fabric.document.body || {\n scrollLeft: 0, scrollTop: 0\n };\n\n // While loop checks (and then sets element to) .parentNode OR .host\n // to account for ShadowDOM. We still want to traverse up out of ShadowDOM,\n // but the .parentNode of a root ShadowDOM node will always be null, instead\n // it should be accessed through .host. See http://stackoverflow.com/a/24765528/4383938\n while (element && (element.parentNode || element.host)) {\n\n // Set element to element parent, or 'host' in case of ShadowDOM\n element = element.parentNode || element.host;\n\n if (element === fabric.document) {\n left = body.scrollLeft || docElement.scrollLeft || 0;\n top = body.scrollTop || docElement.scrollTop || 0;\n }\n else {\n left += element.scrollLeft || 0;\n top += element.scrollTop || 0;\n }\n\n if (element.nodeType === 1 && element.style.position === 'fixed') {\n break;\n }\n }\n\n return { left: left, top: top };\n }\n\n /**\n * Returns offset for a given element\n * @function\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to get offset for\n * @return {Object} Object with \"left\" and \"top\" properties\n */\n function getElementOffset(element) {\n var docElem,\n doc = element && element.ownerDocument,\n box = { left: 0, top: 0 },\n offset = { left: 0, top: 0 },\n scrollLeftTop,\n offsetAttributes = {\n borderLeftWidth: 'left',\n borderTopWidth: 'top',\n paddingLeft: 'left',\n paddingTop: 'top'\n };\n\n if (!doc) {\n return offset;\n }\n\n for (var attr in offsetAttributes) {\n offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0;\n }\n\n docElem = doc.documentElement;\n if ( typeof element.getBoundingClientRect !== 'undefined' ) {\n box = element.getBoundingClientRect();\n }\n\n scrollLeftTop = getScrollLeftTop(element);\n\n return {\n left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left,\n top: box.top + scrollLeftTop.top - (docElem.clientTop || 0) + offset.top\n };\n }\n\n /**\n * Returns style attribute value of a given element\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to get style attribute for\n * @param {String} attr Style attribute to get for element\n * @return {String} Style attribute value of the given element.\n */\n var getElementStyle;\n if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) {\n getElementStyle = function(element, attr) {\n var style = fabric.document.defaultView.getComputedStyle(element, null);\n return style ? style[attr] : undefined;\n };\n }\n else {\n getElementStyle = function(element, attr) {\n var value = element.style[attr];\n if (!value && element.currentStyle) {\n value = element.currentStyle[attr];\n }\n return value;\n };\n }\n\n (function () {\n var style = fabric.document.documentElement.style,\n selectProp = 'userSelect' in style\n ? 'userSelect'\n : 'MozUserSelect' in style\n ? 'MozUserSelect'\n : 'WebkitUserSelect' in style\n ? 'WebkitUserSelect'\n : 'KhtmlUserSelect' in style\n ? 'KhtmlUserSelect'\n : '';\n\n /**\n * Makes element unselectable\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to make unselectable\n * @return {HTMLElement} Element that was passed in\n */\n function makeElementUnselectable(element) {\n if (typeof element.onselectstart !== 'undefined') {\n element.onselectstart = fabric.util.falseFunction;\n }\n if (selectProp) {\n element.style[selectProp] = 'none';\n }\n else if (typeof element.unselectable === 'string') {\n element.unselectable = 'on';\n }\n return element;\n }\n\n /**\n * Makes element selectable\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to make selectable\n * @return {HTMLElement} Element that was passed in\n */\n function makeElementSelectable(element) {\n if (typeof element.onselectstart !== 'undefined') {\n element.onselectstart = null;\n }\n if (selectProp) {\n element.style[selectProp] = '';\n }\n else if (typeof element.unselectable === 'string') {\n element.unselectable = '';\n }\n return element;\n }\n\n fabric.util.makeElementUnselectable = makeElementUnselectable;\n fabric.util.makeElementSelectable = makeElementSelectable;\n })();\n\n function getNodeCanvas(element) {\n var impl = fabric.jsdomImplForWrapper(element);\n return impl._canvas || impl._image;\n };\n\n function cleanUpJsdomNode(element) {\n if (!fabric.isLikelyNode) {\n return;\n }\n var impl = fabric.jsdomImplForWrapper(element);\n if (impl) {\n impl._image = null;\n impl._canvas = null;\n // unsure if necessary\n impl._currentSrc = null;\n impl._attributes = null;\n impl._classList = null;\n }\n }\n\n function setImageSmoothing(ctx, value) {\n ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled || ctx.webkitImageSmoothingEnabled\n || ctx.mozImageSmoothingEnabled || ctx.msImageSmoothingEnabled || ctx.oImageSmoothingEnabled;\n ctx.imageSmoothingEnabled = value;\n }\n\n /**\n * setImageSmoothing sets the context imageSmoothingEnabled property.\n * Used by canvas and by ImageObject.\n * @memberOf fabric.util\n * @since 4.0.0\n * @param {HTMLRenderingContext2D} ctx to set on\n * @param {Boolean} value true or false\n */\n fabric.util.setImageSmoothing = setImageSmoothing;\n fabric.util.getById = getById;\n fabric.util.toArray = toArray;\n fabric.util.addClass = addClass;\n fabric.util.makeElement = makeElement;\n fabric.util.wrapElement = wrapElement;\n fabric.util.getScrollLeftTop = getScrollLeftTop;\n fabric.util.getElementOffset = getElementOffset;\n fabric.util.getNodeCanvas = getNodeCanvas;\n fabric.util.cleanUpJsdomNode = cleanUpJsdomNode;\n\n})();\n\n\n(function() {\n\n function addParamToUrl(url, param) {\n return url + (/\\?/.test(url) ? '&' : '?') + param;\n }\n\n function emptyFn() { }\n\n /**\n * Cross-browser abstraction for sending XMLHttpRequest\n * @memberOf fabric.util\n * @param {String} url URL to send XMLHttpRequest to\n * @param {Object} [options] Options object\n * @param {String} [options.method=\"GET\"]\n * @param {String} [options.parameters] parameters to append to url in GET or in body\n * @param {String} [options.body] body to send with POST or PUT request\n * @param {Function} options.onComplete Callback to invoke when request is completed\n * @return {XMLHttpRequest} request\n */\n function request(url, options) {\n options || (options = { });\n\n var method = options.method ? options.method.toUpperCase() : 'GET',\n onComplete = options.onComplete || function() { },\n xhr = new fabric.window.XMLHttpRequest(),\n body = options.body || options.parameters;\n\n /** @ignore */\n xhr.onreadystatechange = function() {\n if (xhr.readyState === 4) {\n onComplete(xhr);\n xhr.onreadystatechange = emptyFn;\n }\n };\n\n if (method === 'GET') {\n body = null;\n if (typeof options.parameters === 'string') {\n url = addParamToUrl(url, options.parameters);\n }\n }\n\n xhr.open(method, url, true);\n\n if (method === 'POST' || method === 'PUT') {\n xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\n }\n\n xhr.send(body);\n return xhr;\n }\n\n fabric.util.request = request;\n})();\n\n\n/**\n * Wrapper around `console.log` (when available)\n * @param {*} [values] Values to log\n */\nfabric.log = console.log;\n\n/**\n * Wrapper around `console.warn` (when available)\n * @param {*} [values] Values to log as a warning\n */\nfabric.warn = console.warn;\n\n\n(function () {\n\n var extend = fabric.util.object.extend,\n clone = fabric.util.object.clone;\n\n /**\n * @typedef {Object} AnimationOptions\n * Animation of a value or list of values.\n * When using lists, think of something like this:\n * fabric.util.animate({\n * startValue: [1, 2, 3],\n * endValue: [2, 4, 6],\n * onChange: function([a, b, c]) {\n * canvas.zoomToPoint({x: b, y: c}, a)\n * canvas.renderAll()\n * }\n * });\n * @example\n * @property {Function} [onChange] Callback; invoked on every value change\n * @property {Function} [onComplete] Callback; invoked when value change is completed\n * @example\n * // Note: startValue, endValue, and byValue must match the type\n * var animationOptions = { startValue: 0, endValue: 1, byValue: 0.25 }\n * var animationOptions = { startValue: [0, 1], endValue: [1, 2], byValue: [0.25, 0.25] }\n * @property {number | number[]} [startValue=0] Starting value\n * @property {number | number[]} [endValue=100] Ending value\n * @property {number | number[]} [byValue=100] Value to modify the property by\n * @property {Function} [easing] Easing function\n * @property {Number} [duration=500] Duration of change (in ms)\n * @property {Function} [abort] Additional function with logic. If returns true, animation aborts.\n *\n * @typedef {() => void} CancelFunction\n *\n * @typedef {Object} AnimationCurrentState\n * @property {number | number[]} currentValue value in range [`startValue`, `endValue`]\n * @property {number} completionRate value in range [0, 1]\n * @property {number} durationRate value in range [0, 1]\n *\n * @typedef {(AnimationOptions & AnimationCurrentState & { cancel: CancelFunction }} AnimationContext\n */\n\n /**\n * Array holding all running animations\n * @memberof fabric\n * @type {AnimationContext[]}\n */\n var RUNNING_ANIMATIONS = [];\n fabric.util.object.extend(RUNNING_ANIMATIONS, {\n\n /**\n * cancel all running animations at the next requestAnimFrame\n * @returns {AnimationContext[]}\n */\n cancelAll: function () {\n var animations = this.splice(0);\n animations.forEach(function (animation) {\n animation.cancel();\n });\n return animations;\n },\n\n /**\n * cancel all running animations attached to canvas at the next requestAnimFrame\n * @param {fabric.Canvas} canvas\n * @returns {AnimationContext[]}\n */\n cancelByCanvas: function (canvas) {\n if (!canvas) {\n return [];\n }\n var cancelled = this.filter(function (animation) {\n return typeof animation.target === 'object' && animation.target.canvas === canvas;\n });\n cancelled.forEach(function (animation) {\n animation.cancel();\n });\n return cancelled;\n },\n\n /**\n * cancel all running animations for target at the next requestAnimFrame\n * @param {*} target\n * @returns {AnimationContext[]}\n */\n cancelByTarget: function (target) {\n var cancelled = this.findAnimationsByTarget(target);\n cancelled.forEach(function (animation) {\n animation.cancel();\n });\n return cancelled;\n },\n\n /**\n *\n * @param {CancelFunction} cancelFunc the function returned by animate\n * @returns {number}\n */\n findAnimationIndex: function (cancelFunc) {\n return this.indexOf(this.findAnimation(cancelFunc));\n },\n\n /**\n *\n * @param {CancelFunction} cancelFunc the function returned by animate\n * @returns {AnimationContext | undefined} animation's options object\n */\n findAnimation: function (cancelFunc) {\n return this.find(function (animation) {\n return animation.cancel === cancelFunc;\n });\n },\n\n /**\n *\n * @param {*} target the object that is assigned to the target property of the animation context\n * @returns {AnimationContext[]} array of animation options object associated with target\n */\n findAnimationsByTarget: function (target) {\n if (!target) {\n return [];\n }\n return this.filter(function (animation) {\n return animation.target === target;\n });\n }\n });\n\n function noop() {\n return false;\n }\n\n function defaultEasing(t, b, c, d) {\n return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;\n }\n\n /**\n * Changes value from one to another within certain period of time, invoking callbacks as value is being changed.\n * @memberOf fabric.util\n * @param {AnimationOptions} [options] Animation options\n * @example\n * // Note: startValue, endValue, and byValue must match the type\n * fabric.util.animate({ startValue: 0, endValue: 1, byValue: 0.25 })\n * fabric.util.animate({ startValue: [0, 1], endValue: [1, 2], byValue: [0.25, 0.25] })\n * @returns {CancelFunction} cancel function\n */\n function animate(options) {\n options || (options = {});\n var cancel = false,\n context,\n removeFromRegistry = function () {\n var index = fabric.runningAnimations.indexOf(context);\n return index > -1 && fabric.runningAnimations.splice(index, 1)[0];\n };\n\n context = extend(clone(options), {\n cancel: function () {\n cancel = true;\n return removeFromRegistry();\n },\n currentValue: 'startValue' in options ? options.startValue : 0,\n completionRate: 0,\n durationRate: 0\n });\n fabric.runningAnimations.push(context);\n\n requestAnimFrame(function(timestamp) {\n var start = timestamp || +new Date(),\n duration = options.duration || 500,\n finish = start + duration, time,\n onChange = options.onChange || noop,\n abort = options.abort || noop,\n onComplete = options.onComplete || noop,\n easing = options.easing || defaultEasing,\n isMany = 'startValue' in options ? options.startValue.length > 0 : false,\n startValue = 'startValue' in options ? options.startValue : 0,\n endValue = 'endValue' in options ? options.endValue : 100,\n byValue = options.byValue || (isMany ? startValue.map(function(value, i) {\n return endValue[i] - startValue[i];\n }) : endValue - startValue);\n\n options.onStart && options.onStart();\n\n (function tick(ticktime) {\n time = ticktime || +new Date();\n var currentTime = time > finish ? duration : (time - start),\n timePerc = currentTime / duration,\n current = isMany ? startValue.map(function(_value, i) {\n return easing(currentTime, startValue[i], byValue[i], duration);\n }) : easing(currentTime, startValue, byValue, duration),\n valuePerc = isMany ? Math.abs((current[0] - startValue[0]) / byValue[0])\n : Math.abs((current - startValue) / byValue);\n // update context\n context.currentValue = isMany ? current.slice() : current;\n context.completionRate = valuePerc;\n context.durationRate = timePerc;\n if (cancel) {\n return;\n }\n if (abort(current, valuePerc, timePerc)) {\n removeFromRegistry();\n return;\n }\n if (time > finish) {\n // update context\n context.currentValue = isMany ? endValue.slice() : endValue;\n context.completionRate = 1;\n context.durationRate = 1;\n // execute callbacks\n onChange(isMany ? endValue.slice() : endValue, 1, 1);\n onComplete(endValue, 1, 1);\n removeFromRegistry();\n return;\n }\n else {\n onChange(current, valuePerc, timePerc);\n requestAnimFrame(tick);\n }\n })(start);\n });\n\n return context.cancel;\n }\n\n var _requestAnimFrame = fabric.window.requestAnimationFrame ||\n fabric.window.webkitRequestAnimationFrame ||\n fabric.window.mozRequestAnimationFrame ||\n fabric.window.oRequestAnimationFrame ||\n fabric.window.msRequestAnimationFrame ||\n function(callback) {\n return fabric.window.setTimeout(callback, 1000 / 60);\n };\n\n var _cancelAnimFrame = fabric.window.cancelAnimationFrame || fabric.window.clearTimeout;\n\n /**\n * requestAnimationFrame polyfill based on http://paulirish.com/2011/requestanimationframe-for-smart-animating/\n * In order to get a precise start time, `requestAnimFrame` should be called as an entry into the method\n * @memberOf fabric.util\n * @param {Function} callback Callback to invoke\n * @param {DOMElement} element optional Element to associate with animation\n */\n function requestAnimFrame() {\n return _requestAnimFrame.apply(fabric.window, arguments);\n }\n\n function cancelAnimFrame() {\n return _cancelAnimFrame.apply(fabric.window, arguments);\n }\n\n fabric.util.animate = animate;\n fabric.util.requestAnimFrame = requestAnimFrame;\n fabric.util.cancelAnimFrame = cancelAnimFrame;\n fabric.runningAnimations = RUNNING_ANIMATIONS;\n})();\n\n\n(function() {\n // Calculate an in-between color. Returns a \"rgba()\" string.\n // Credit: Edwin Martin \n // http://www.bitstorm.org/jquery/color-animation/jquery.animate-colors.js\n function calculateColor(begin, end, pos) {\n var color = 'rgba('\n + parseInt((begin[0] + pos * (end[0] - begin[0])), 10) + ','\n + parseInt((begin[1] + pos * (end[1] - begin[1])), 10) + ','\n + parseInt((begin[2] + pos * (end[2] - begin[2])), 10);\n\n color += ',' + (begin && end ? parseFloat(begin[3] + pos * (end[3] - begin[3])) : 1);\n color += ')';\n return color;\n }\n\n /**\n * Changes the color from one to another within certain period of time, invoking callbacks as value is being changed.\n * @memberOf fabric.util\n * @param {String} fromColor The starting color in hex or rgb(a) format.\n * @param {String} toColor The starting color in hex or rgb(a) format.\n * @param {Number} [duration] Duration of change (in ms).\n * @param {Object} [options] Animation options\n * @param {Function} [options.onChange] Callback; invoked on every value change\n * @param {Function} [options.onComplete] Callback; invoked when value change is completed\n * @param {Function} [options.colorEasing] Easing function. Note that this function only take two arguments (currentTime, duration). Thus the regular animation easing functions cannot be used.\n * @param {Function} [options.abort] Additional function with logic. If returns true, onComplete is called.\n * @returns {Function} abort function\n */\n function animateColor(fromColor, toColor, duration, options) {\n var startColor = new fabric.Color(fromColor).getSource(),\n endColor = new fabric.Color(toColor).getSource(),\n originalOnComplete = options.onComplete,\n originalOnChange = options.onChange;\n options = options || {};\n\n return fabric.util.animate(fabric.util.object.extend(options, {\n duration: duration || 500,\n startValue: startColor,\n endValue: endColor,\n byValue: endColor,\n easing: function (currentTime, startValue, byValue, duration) {\n var posValue = options.colorEasing\n ? options.colorEasing(currentTime, duration)\n : 1 - Math.cos(currentTime / duration * (Math.PI / 2));\n return calculateColor(startValue, byValue, posValue);\n },\n // has to take in account for color restoring;\n onComplete: function(current, valuePerc, timePerc) {\n if (originalOnComplete) {\n return originalOnComplete(\n calculateColor(endColor, endColor, 0),\n valuePerc,\n timePerc\n );\n }\n },\n onChange: function(current, valuePerc, timePerc) {\n if (originalOnChange) {\n if (Array.isArray(current)) {\n return originalOnChange(\n calculateColor(current, current, 0),\n valuePerc,\n timePerc\n );\n }\n originalOnChange(current, valuePerc, timePerc);\n }\n }\n }));\n }\n\n fabric.util.animateColor = animateColor;\n\n})();\n\n\n(function() {\n\n function normalize(a, c, p, s) {\n if (a < Math.abs(c)) {\n a = c;\n s = p / 4;\n }\n else {\n //handle the 0/0 case:\n if (c === 0 && a === 0) {\n s = p / (2 * Math.PI) * Math.asin(1);\n }\n else {\n s = p / (2 * Math.PI) * Math.asin(c / a);\n }\n }\n return { a: a, c: c, p: p, s: s };\n }\n\n function elastic(opts, t, d) {\n return opts.a *\n Math.pow(2, 10 * (t -= 1)) *\n Math.sin( (t * d - opts.s) * (2 * Math.PI) / opts.p );\n }\n\n /**\n * Cubic easing out\n * @memberOf fabric.util.ease\n */\n function easeOutCubic(t, b, c, d) {\n return c * ((t = t / d - 1) * t * t + 1) + b;\n }\n\n /**\n * Cubic easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutCubic(t, b, c, d) {\n t /= d / 2;\n if (t < 1) {\n return c / 2 * t * t * t + b;\n }\n return c / 2 * ((t -= 2) * t * t + 2) + b;\n }\n\n /**\n * Quartic easing in\n * @memberOf fabric.util.ease\n */\n function easeInQuart(t, b, c, d) {\n return c * (t /= d) * t * t * t + b;\n }\n\n /**\n * Quartic easing out\n * @memberOf fabric.util.ease\n */\n function easeOutQuart(t, b, c, d) {\n return -c * ((t = t / d - 1) * t * t * t - 1) + b;\n }\n\n /**\n * Quartic easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutQuart(t, b, c, d) {\n t /= d / 2;\n if (t < 1) {\n return c / 2 * t * t * t * t + b;\n }\n return -c / 2 * ((t -= 2) * t * t * t - 2) + b;\n }\n\n /**\n * Quintic easing in\n * @memberOf fabric.util.ease\n */\n function easeInQuint(t, b, c, d) {\n return c * (t /= d) * t * t * t * t + b;\n }\n\n /**\n * Quintic easing out\n * @memberOf fabric.util.ease\n */\n function easeOutQuint(t, b, c, d) {\n return c * ((t = t / d - 1) * t * t * t * t + 1) + b;\n }\n\n /**\n * Quintic easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutQuint(t, b, c, d) {\n t /= d / 2;\n if (t < 1) {\n return c / 2 * t * t * t * t * t + b;\n }\n return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;\n }\n\n /**\n * Sinusoidal easing in\n * @memberOf fabric.util.ease\n */\n function easeInSine(t, b, c, d) {\n return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;\n }\n\n /**\n * Sinusoidal easing out\n * @memberOf fabric.util.ease\n */\n function easeOutSine(t, b, c, d) {\n return c * Math.sin(t / d * (Math.PI / 2)) + b;\n }\n\n /**\n * Sinusoidal easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutSine(t, b, c, d) {\n return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;\n }\n\n /**\n * Exponential easing in\n * @memberOf fabric.util.ease\n */\n function easeInExpo(t, b, c, d) {\n return (t === 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;\n }\n\n /**\n * Exponential easing out\n * @memberOf fabric.util.ease\n */\n function easeOutExpo(t, b, c, d) {\n return (t === d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;\n }\n\n /**\n * Exponential easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutExpo(t, b, c, d) {\n if (t === 0) {\n return b;\n }\n if (t === d) {\n return b + c;\n }\n t /= d / 2;\n if (t < 1) {\n return c / 2 * Math.pow(2, 10 * (t - 1)) + b;\n }\n return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;\n }\n\n /**\n * Circular easing in\n * @memberOf fabric.util.ease\n */\n function easeInCirc(t, b, c, d) {\n return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;\n }\n\n /**\n * Circular easing out\n * @memberOf fabric.util.ease\n */\n function easeOutCirc(t, b, c, d) {\n return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;\n }\n\n /**\n * Circular easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutCirc(t, b, c, d) {\n t /= d / 2;\n if (t < 1) {\n return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;\n }\n return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;\n }\n\n /**\n * Elastic easing in\n * @memberOf fabric.util.ease\n */\n function easeInElastic(t, b, c, d) {\n var s = 1.70158, p = 0, a = c;\n if (t === 0) {\n return b;\n }\n t /= d;\n if (t === 1) {\n return b + c;\n }\n if (!p) {\n p = d * 0.3;\n }\n var opts = normalize(a, c, p, s);\n return -elastic(opts, t, d) + b;\n }\n\n /**\n * Elastic easing out\n * @memberOf fabric.util.ease\n */\n function easeOutElastic(t, b, c, d) {\n var s = 1.70158, p = 0, a = c;\n if (t === 0) {\n return b;\n }\n t /= d;\n if (t === 1) {\n return b + c;\n }\n if (!p) {\n p = d * 0.3;\n }\n var opts = normalize(a, c, p, s);\n return opts.a * Math.pow(2, -10 * t) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) + opts.c + b;\n }\n\n /**\n * Elastic easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutElastic(t, b, c, d) {\n var s = 1.70158, p = 0, a = c;\n if (t === 0) {\n return b;\n }\n t /= d / 2;\n if (t === 2) {\n return b + c;\n }\n if (!p) {\n p = d * (0.3 * 1.5);\n }\n var opts = normalize(a, c, p, s);\n if (t < 1) {\n return -0.5 * elastic(opts, t, d) + b;\n }\n return opts.a * Math.pow(2, -10 * (t -= 1)) *\n Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) * 0.5 + opts.c + b;\n }\n\n /**\n * Backwards easing in\n * @memberOf fabric.util.ease\n */\n function easeInBack(t, b, c, d, s) {\n if (s === undefined) {\n s = 1.70158;\n }\n return c * (t /= d) * t * ((s + 1) * t - s) + b;\n }\n\n /**\n * Backwards easing out\n * @memberOf fabric.util.ease\n */\n function easeOutBack(t, b, c, d, s) {\n if (s === undefined) {\n s = 1.70158;\n }\n return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;\n }\n\n /**\n * Backwards easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutBack(t, b, c, d, s) {\n if (s === undefined) {\n s = 1.70158;\n }\n t /= d / 2;\n if (t < 1) {\n return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;\n }\n return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;\n }\n\n /**\n * Bouncing easing in\n * @memberOf fabric.util.ease\n */\n function easeInBounce(t, b, c, d) {\n return c - easeOutBounce (d - t, 0, c, d) + b;\n }\n\n /**\n * Bouncing easing out\n * @memberOf fabric.util.ease\n */\n function easeOutBounce(t, b, c, d) {\n if ((t /= d) < (1 / 2.75)) {\n return c * (7.5625 * t * t) + b;\n }\n else if (t < (2 / 2.75)) {\n return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;\n }\n else if (t < (2.5 / 2.75)) {\n return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;\n }\n else {\n return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;\n }\n }\n\n /**\n * Bouncing easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutBounce(t, b, c, d) {\n if (t < d / 2) {\n return easeInBounce (t * 2, 0, c, d) * 0.5 + b;\n }\n return easeOutBounce(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;\n }\n\n /**\n * Easing functions\n * See Easing Equations by Robert Penner\n * @namespace fabric.util.ease\n */\n fabric.util.ease = {\n\n /**\n * Quadratic easing in\n * @memberOf fabric.util.ease\n */\n easeInQuad: function(t, b, c, d) {\n return c * (t /= d) * t + b;\n },\n\n /**\n * Quadratic easing out\n * @memberOf fabric.util.ease\n */\n easeOutQuad: function(t, b, c, d) {\n return -c * (t /= d) * (t - 2) + b;\n },\n\n /**\n * Quadratic easing in and out\n * @memberOf fabric.util.ease\n */\n easeInOutQuad: function(t, b, c, d) {\n t /= (d / 2);\n if (t < 1) {\n return c / 2 * t * t + b;\n }\n return -c / 2 * ((--t) * (t - 2) - 1) + b;\n },\n\n /**\n * Cubic easing in\n * @memberOf fabric.util.ease\n */\n easeInCubic: function(t, b, c, d) {\n return c * (t /= d) * t * t + b;\n },\n\n easeOutCubic: easeOutCubic,\n easeInOutCubic: easeInOutCubic,\n easeInQuart: easeInQuart,\n easeOutQuart: easeOutQuart,\n easeInOutQuart: easeInOutQuart,\n easeInQuint: easeInQuint,\n easeOutQuint: easeOutQuint,\n easeInOutQuint: easeInOutQuint,\n easeInSine: easeInSine,\n easeOutSine: easeOutSine,\n easeInOutSine: easeInOutSine,\n easeInExpo: easeInExpo,\n easeOutExpo: easeOutExpo,\n easeInOutExpo: easeInOutExpo,\n easeInCirc: easeInCirc,\n easeOutCirc: easeOutCirc,\n easeInOutCirc: easeInOutCirc,\n easeInElastic: easeInElastic,\n easeOutElastic: easeOutElastic,\n easeInOutElastic: easeInOutElastic,\n easeInBack: easeInBack,\n easeOutBack: easeOutBack,\n easeInOutBack: easeInOutBack,\n easeInBounce: easeInBounce,\n easeOutBounce: easeOutBounce,\n easeInOutBounce: easeInOutBounce\n };\n\n})();\n\n\n(function(global) {\n\n 'use strict';\n\n /**\n * @name fabric\n * @namespace\n */\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n clone = fabric.util.object.clone,\n toFixed = fabric.util.toFixed,\n parseUnit = fabric.util.parseUnit,\n multiplyTransformMatrices = fabric.util.multiplyTransformMatrices,\n\n svgValidTagNames = ['path', 'circle', 'polygon', 'polyline', 'ellipse', 'rect', 'line',\n 'image', 'text'],\n svgViewBoxElements = ['symbol', 'image', 'marker', 'pattern', 'view', 'svg'],\n svgInvalidAncestors = ['pattern', 'defs', 'symbol', 'metadata', 'clipPath', 'mask', 'desc'],\n svgValidParents = ['symbol', 'g', 'a', 'svg', 'clipPath', 'defs'],\n\n attributesMap = {\n cx: 'left',\n x: 'left',\n r: 'radius',\n cy: 'top',\n y: 'top',\n display: 'visible',\n visibility: 'visible',\n transform: 'transformMatrix',\n 'fill-opacity': 'fillOpacity',\n 'fill-rule': 'fillRule',\n 'font-family': 'fontFamily',\n 'font-size': 'fontSize',\n 'font-style': 'fontStyle',\n 'font-weight': 'fontWeight',\n 'letter-spacing': 'charSpacing',\n 'paint-order': 'paintFirst',\n 'stroke-dasharray': 'strokeDashArray',\n 'stroke-dashoffset': 'strokeDashOffset',\n 'stroke-linecap': 'strokeLineCap',\n 'stroke-linejoin': 'strokeLineJoin',\n 'stroke-miterlimit': 'strokeMiterLimit',\n 'stroke-opacity': 'strokeOpacity',\n 'stroke-width': 'strokeWidth',\n 'text-decoration': 'textDecoration',\n 'text-anchor': 'textAnchor',\n opacity: 'opacity',\n 'clip-path': 'clipPath',\n 'clip-rule': 'clipRule',\n 'vector-effect': 'strokeUniform',\n 'image-rendering': 'imageSmoothing',\n },\n\n colorAttributes = {\n stroke: 'strokeOpacity',\n fill: 'fillOpacity'\n },\n\n fSize = 'font-size', cPath = 'clip-path';\n\n fabric.svgValidTagNamesRegEx = getSvgRegex(svgValidTagNames);\n fabric.svgViewBoxElementsRegEx = getSvgRegex(svgViewBoxElements);\n fabric.svgInvalidAncestorsRegEx = getSvgRegex(svgInvalidAncestors);\n fabric.svgValidParentsRegEx = getSvgRegex(svgValidParents);\n\n fabric.cssRules = { };\n fabric.gradientDefs = { };\n fabric.clipPaths = { };\n\n function normalizeAttr(attr) {\n // transform attribute names\n if (attr in attributesMap) {\n return attributesMap[attr];\n }\n return attr;\n }\n\n function normalizeValue(attr, value, parentAttributes, fontSize) {\n var isArray = Array.isArray(value), parsed;\n\n if ((attr === 'fill' || attr === 'stroke') && value === 'none') {\n value = '';\n }\n else if (attr === 'strokeUniform') {\n return (value === 'non-scaling-stroke');\n }\n else if (attr === 'strokeDashArray') {\n if (value === 'none') {\n value = null;\n }\n else {\n value = value.replace(/,/g, ' ').split(/\\s+/).map(parseFloat);\n }\n }\n else if (attr === 'transformMatrix') {\n if (parentAttributes && parentAttributes.transformMatrix) {\n value = multiplyTransformMatrices(\n parentAttributes.transformMatrix, fabric.parseTransformAttribute(value));\n }\n else {\n value = fabric.parseTransformAttribute(value);\n }\n }\n else if (attr === 'visible') {\n value = value !== 'none' && value !== 'hidden';\n // display=none on parent element always takes precedence over child element\n if (parentAttributes && parentAttributes.visible === false) {\n value = false;\n }\n }\n else if (attr === 'opacity') {\n value = parseFloat(value);\n if (parentAttributes && typeof parentAttributes.opacity !== 'undefined') {\n value *= parentAttributes.opacity;\n }\n }\n else if (attr === 'textAnchor' /* text-anchor */) {\n value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center';\n }\n else if (attr === 'charSpacing') {\n // parseUnit returns px and we convert it to em\n parsed = parseUnit(value, fontSize) / fontSize * 1000;\n }\n else if (attr === 'paintFirst') {\n var fillIndex = value.indexOf('fill');\n var strokeIndex = value.indexOf('stroke');\n var value = 'fill';\n if (fillIndex > -1 && strokeIndex > -1 && strokeIndex < fillIndex) {\n value = 'stroke';\n }\n else if (fillIndex === -1 && strokeIndex > -1) {\n value = 'stroke';\n }\n }\n else if (attr === 'href' || attr === 'xlink:href' || attr === 'font') {\n return value;\n }\n else if (attr === 'imageSmoothing') {\n return (value === 'optimizeQuality');\n }\n else {\n parsed = isArray ? value.map(parseUnit) : parseUnit(value, fontSize);\n }\n\n return (!isArray && isNaN(parsed) ? value : parsed);\n }\n\n /**\n * @private\n */\n function getSvgRegex(arr) {\n return new RegExp('^(' + arr.join('|') + ')\\\\b', 'i');\n }\n\n /**\n * @private\n * @param {Object} attributes Array of attributes to parse\n */\n function _setStrokeFillOpacity(attributes) {\n for (var attr in colorAttributes) {\n\n if (typeof attributes[colorAttributes[attr]] === 'undefined' || attributes[attr] === '') {\n continue;\n }\n\n if (typeof attributes[attr] === 'undefined') {\n if (!fabric.Object.prototype[attr]) {\n continue;\n }\n attributes[attr] = fabric.Object.prototype[attr];\n }\n\n if (attributes[attr].indexOf('url(') === 0) {\n continue;\n }\n\n var color = new fabric.Color(attributes[attr]);\n attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba();\n }\n return attributes;\n }\n\n /**\n * @private\n */\n function _getMultipleNodes(doc, nodeNames) {\n var nodeName, nodeArray = [], nodeList, i, len;\n for (i = 0, len = nodeNames.length; i < len; i++) {\n nodeName = nodeNames[i];\n nodeList = doc.getElementsByTagName(nodeName);\n nodeArray = nodeArray.concat(Array.prototype.slice.call(nodeList));\n }\n return nodeArray;\n }\n\n /**\n * Parses \"transform\" attribute, returning an array of values\n * @static\n * @function\n * @memberOf fabric\n * @param {String} attributeValue String containing attribute value\n * @return {Array} Array of 6 elements representing transformation matrix\n */\n fabric.parseTransformAttribute = (function() {\n function rotateMatrix(matrix, args) {\n var cos = fabric.util.cos(args[0]), sin = fabric.util.sin(args[0]),\n x = 0, y = 0;\n if (args.length === 3) {\n x = args[1];\n y = args[2];\n }\n\n matrix[0] = cos;\n matrix[1] = sin;\n matrix[2] = -sin;\n matrix[3] = cos;\n matrix[4] = x - (cos * x - sin * y);\n matrix[5] = y - (sin * x + cos * y);\n }\n\n function scaleMatrix(matrix, args) {\n var multiplierX = args[0],\n multiplierY = (args.length === 2) ? args[1] : args[0];\n\n matrix[0] = multiplierX;\n matrix[3] = multiplierY;\n }\n\n function skewMatrix(matrix, args, pos) {\n matrix[pos] = Math.tan(fabric.util.degreesToRadians(args[0]));\n }\n\n function translateMatrix(matrix, args) {\n matrix[4] = args[0];\n if (args.length === 2) {\n matrix[5] = args[1];\n }\n }\n\n // identity matrix\n var iMatrix = fabric.iMatrix,\n\n // == begin transform regexp\n number = fabric.reNum,\n\n commaWsp = fabric.commaWsp,\n\n skewX = '(?:(skewX)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*\\\\))',\n\n skewY = '(?:(skewY)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*\\\\))',\n\n rotate = '(?:(rotate)\\\\s*\\\\(\\\\s*(' + number + ')(?:' +\n commaWsp + '(' + number + ')' +\n commaWsp + '(' + number + '))?\\\\s*\\\\))',\n\n scale = '(?:(scale)\\\\s*\\\\(\\\\s*(' + number + ')(?:' +\n commaWsp + '(' + number + '))?\\\\s*\\\\))',\n\n translate = '(?:(translate)\\\\s*\\\\(\\\\s*(' + number + ')(?:' +\n commaWsp + '(' + number + '))?\\\\s*\\\\))',\n\n matrix = '(?:(matrix)\\\\s*\\\\(\\\\s*' +\n '(' + number + ')' + commaWsp +\n '(' + number + ')' + commaWsp +\n '(' + number + ')' + commaWsp +\n '(' + number + ')' + commaWsp +\n '(' + number + ')' + commaWsp +\n '(' + number + ')' +\n '\\\\s*\\\\))',\n\n transform = '(?:' +\n matrix + '|' +\n translate + '|' +\n scale + '|' +\n rotate + '|' +\n skewX + '|' +\n skewY +\n ')',\n\n transforms = '(?:' + transform + '(?:' + commaWsp + '*' + transform + ')*' + ')',\n\n transformList = '^\\\\s*(?:' + transforms + '?)\\\\s*$',\n\n // http://www.w3.org/TR/SVG/coords.html#TransformAttribute\n reTransformList = new RegExp(transformList),\n // == end transform regexp\n\n reTransform = new RegExp(transform, 'g');\n\n return function(attributeValue) {\n\n // start with identity matrix\n var matrix = iMatrix.concat(),\n matrices = [];\n\n // return if no argument was given or\n // an argument does not match transform attribute regexp\n if (!attributeValue || (attributeValue && !reTransformList.test(attributeValue))) {\n return matrix;\n }\n\n attributeValue.replace(reTransform, function(match) {\n\n var m = new RegExp(transform).exec(match).filter(function (match) {\n // match !== '' && match != null\n return (!!match);\n }),\n operation = m[1],\n args = m.slice(2).map(parseFloat);\n\n switch (operation) {\n case 'translate':\n translateMatrix(matrix, args);\n break;\n case 'rotate':\n args[0] = fabric.util.degreesToRadians(args[0]);\n rotateMatrix(matrix, args);\n break;\n case 'scale':\n scaleMatrix(matrix, args);\n break;\n case 'skewX':\n skewMatrix(matrix, args, 2);\n break;\n case 'skewY':\n skewMatrix(matrix, args, 1);\n break;\n case 'matrix':\n matrix = args;\n break;\n }\n\n // snapshot current matrix into matrices array\n matrices.push(matrix.concat());\n // reset\n matrix = iMatrix.concat();\n });\n\n var combinedMatrix = matrices[0];\n while (matrices.length > 1) {\n matrices.shift();\n combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]);\n }\n return combinedMatrix;\n };\n })();\n\n /**\n * @private\n */\n function parseStyleString(style, oStyle) {\n var attr, value;\n style.replace(/;\\s*$/, '').split(';').forEach(function (chunk) {\n var pair = chunk.split(':');\n\n attr = pair[0].trim().toLowerCase();\n value = pair[1].trim();\n\n oStyle[attr] = value;\n });\n }\n\n /**\n * @private\n */\n function parseStyleObject(style, oStyle) {\n var attr, value;\n for (var prop in style) {\n if (typeof style[prop] === 'undefined') {\n continue;\n }\n\n attr = prop.toLowerCase();\n value = style[prop];\n\n oStyle[attr] = value;\n }\n }\n\n /**\n * @private\n */\n function getGlobalStylesForElement(element, svgUid) {\n var styles = { };\n for (var rule in fabric.cssRules[svgUid]) {\n if (elementMatchesRule(element, rule.split(' '))) {\n for (var property in fabric.cssRules[svgUid][rule]) {\n styles[property] = fabric.cssRules[svgUid][rule][property];\n }\n }\n }\n return styles;\n }\n\n /**\n * @private\n */\n function elementMatchesRule(element, selectors) {\n var firstMatching, parentMatching = true;\n //start from rightmost selector.\n firstMatching = selectorMatches(element, selectors.pop());\n if (firstMatching && selectors.length) {\n parentMatching = doesSomeParentMatch(element, selectors);\n }\n return firstMatching && parentMatching && (selectors.length === 0);\n }\n\n function doesSomeParentMatch(element, selectors) {\n var selector, parentMatching = true;\n while (element.parentNode && element.parentNode.nodeType === 1 && selectors.length) {\n if (parentMatching) {\n selector = selectors.pop();\n }\n element = element.parentNode;\n parentMatching = selectorMatches(element, selector);\n }\n return selectors.length === 0;\n }\n\n /**\n * @private\n */\n function selectorMatches(element, selector) {\n var nodeName = element.nodeName,\n classNames = element.getAttribute('class'),\n id = element.getAttribute('id'), matcher, i;\n // i check if a selector matches slicing away part from it.\n // if i get empty string i should match\n matcher = new RegExp('^' + nodeName, 'i');\n selector = selector.replace(matcher, '');\n if (id && selector.length) {\n matcher = new RegExp('#' + id + '(?![a-zA-Z\\\\-]+)', 'i');\n selector = selector.replace(matcher, '');\n }\n if (classNames && selector.length) {\n classNames = classNames.split(' ');\n for (i = classNames.length; i--;) {\n matcher = new RegExp('\\\\.' + classNames[i] + '(?![a-zA-Z\\\\-]+)', 'i');\n selector = selector.replace(matcher, '');\n }\n }\n return selector.length === 0;\n }\n\n /**\n * @private\n * to support IE8 missing getElementById on SVGdocument and on node xmlDOM\n */\n function elementById(doc, id) {\n var el;\n doc.getElementById && (el = doc.getElementById(id));\n if (el) {\n return el;\n }\n var node, i, len, nodelist = doc.getElementsByTagName('*');\n for (i = 0, len = nodelist.length; i < len; i++) {\n node = nodelist[i];\n if (id === node.getAttribute('id')) {\n return node;\n }\n }\n }\n\n /**\n * @private\n */\n function parseUseDirectives(doc) {\n var nodelist = _getMultipleNodes(doc, ['use', 'svg:use']), i = 0;\n while (nodelist.length && i < nodelist.length) {\n var el = nodelist[i],\n xlinkAttribute = el.getAttribute('xlink:href') || el.getAttribute('href');\n\n if (xlinkAttribute === null) {\n return;\n }\n\n var xlink = xlinkAttribute.slice(1),\n x = el.getAttribute('x') || 0,\n y = el.getAttribute('y') || 0,\n el2 = elementById(doc, xlink).cloneNode(true),\n currentTrans = (el2.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')',\n parentNode,\n oldLength = nodelist.length, attr,\n j,\n attrs,\n len,\n namespace = fabric.svgNS;\n\n applyViewboxTransform(el2);\n if (/^svg$/i.test(el2.nodeName)) {\n var el3 = el2.ownerDocument.createElementNS(namespace, 'g');\n for (j = 0, attrs = el2.attributes, len = attrs.length; j < len; j++) {\n attr = attrs.item(j);\n el3.setAttributeNS(namespace, attr.nodeName, attr.nodeValue);\n }\n // el2.firstChild != null\n while (el2.firstChild) {\n el3.appendChild(el2.firstChild);\n }\n el2 = el3;\n }\n\n for (j = 0, attrs = el.attributes, len = attrs.length; j < len; j++) {\n attr = attrs.item(j);\n if (attr.nodeName === 'x' || attr.nodeName === 'y' ||\n attr.nodeName === 'xlink:href' || attr.nodeName === 'href') {\n continue;\n }\n\n if (attr.nodeName === 'transform') {\n currentTrans = attr.nodeValue + ' ' + currentTrans;\n }\n else {\n el2.setAttribute(attr.nodeName, attr.nodeValue);\n }\n }\n\n el2.setAttribute('transform', currentTrans);\n el2.setAttribute('instantiated_by_use', '1');\n el2.removeAttribute('id');\n parentNode = el.parentNode;\n parentNode.replaceChild(el2, el);\n // some browsers do not shorten nodelist after replaceChild (IE8)\n if (nodelist.length === oldLength) {\n i++;\n }\n }\n }\n\n // http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute\n // matches, e.g.: +14.56e-12, etc.\n var reViewBoxAttrValue = new RegExp(\n '^' +\n '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' +\n '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' +\n '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' +\n '\\\\s*(' + fabric.reNum + '+)\\\\s*' +\n '$'\n );\n\n /**\n * Add a element that envelop all child elements and makes the viewbox transformMatrix descend on all elements\n */\n function applyViewboxTransform(element) {\n if (!fabric.svgViewBoxElementsRegEx.test(element.nodeName)) {\n return {};\n }\n var viewBoxAttr = element.getAttribute('viewBox'),\n scaleX = 1,\n scaleY = 1,\n minX = 0,\n minY = 0,\n viewBoxWidth, viewBoxHeight, matrix, el,\n widthAttr = element.getAttribute('width'),\n heightAttr = element.getAttribute('height'),\n x = element.getAttribute('x') || 0,\n y = element.getAttribute('y') || 0,\n preserveAspectRatio = element.getAttribute('preserveAspectRatio') || '',\n missingViewBox = (!viewBoxAttr || !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))),\n missingDimAttr = (!widthAttr || !heightAttr || widthAttr === '100%' || heightAttr === '100%'),\n toBeParsed = missingViewBox && missingDimAttr,\n parsedDim = { }, translateMatrix = '', widthDiff = 0, heightDiff = 0;\n\n parsedDim.width = 0;\n parsedDim.height = 0;\n parsedDim.toBeParsed = toBeParsed;\n\n if (missingViewBox) {\n if (((x || y) && element.parentNode && element.parentNode.nodeName !== '#document')) {\n translateMatrix = ' translate(' + parseUnit(x) + ' ' + parseUnit(y) + ') ';\n matrix = (element.getAttribute('transform') || '') + translateMatrix;\n element.setAttribute('transform', matrix);\n element.removeAttribute('x');\n element.removeAttribute('y');\n }\n }\n\n if (toBeParsed) {\n return parsedDim;\n }\n\n if (missingViewBox) {\n parsedDim.width = parseUnit(widthAttr);\n parsedDim.height = parseUnit(heightAttr);\n // set a transform for elements that have x y and are inner(only) SVGs\n return parsedDim;\n }\n minX = -parseFloat(viewBoxAttr[1]);\n minY = -parseFloat(viewBoxAttr[2]);\n viewBoxWidth = parseFloat(viewBoxAttr[3]);\n viewBoxHeight = parseFloat(viewBoxAttr[4]);\n parsedDim.minX = minX;\n parsedDim.minY = minY;\n parsedDim.viewBoxWidth = viewBoxWidth;\n parsedDim.viewBoxHeight = viewBoxHeight;\n if (!missingDimAttr) {\n parsedDim.width = parseUnit(widthAttr);\n parsedDim.height = parseUnit(heightAttr);\n scaleX = parsedDim.width / viewBoxWidth;\n scaleY = parsedDim.height / viewBoxHeight;\n }\n else {\n parsedDim.width = viewBoxWidth;\n parsedDim.height = viewBoxHeight;\n }\n\n // default is to preserve aspect ratio\n preserveAspectRatio = fabric.util.parsePreserveAspectRatioAttribute(preserveAspectRatio);\n if (preserveAspectRatio.alignX !== 'none') {\n //translate all container for the effect of Mid, Min, Max\n if (preserveAspectRatio.meetOrSlice === 'meet') {\n scaleY = scaleX = (scaleX > scaleY ? scaleY : scaleX);\n // calculate additional translation to move the viewbox\n }\n if (preserveAspectRatio.meetOrSlice === 'slice') {\n scaleY = scaleX = (scaleX > scaleY ? scaleX : scaleY);\n // calculate additional translation to move the viewbox\n }\n widthDiff = parsedDim.width - viewBoxWidth * scaleX;\n heightDiff = parsedDim.height - viewBoxHeight * scaleX;\n if (preserveAspectRatio.alignX === 'Mid') {\n widthDiff /= 2;\n }\n if (preserveAspectRatio.alignY === 'Mid') {\n heightDiff /= 2;\n }\n if (preserveAspectRatio.alignX === 'Min') {\n widthDiff = 0;\n }\n if (preserveAspectRatio.alignY === 'Min') {\n heightDiff = 0;\n }\n }\n\n if (scaleX === 1 && scaleY === 1 && minX === 0 && minY === 0 && x === 0 && y === 0) {\n return parsedDim;\n }\n if ((x || y) && element.parentNode.nodeName !== '#document') {\n translateMatrix = ' translate(' + parseUnit(x) + ' ' + parseUnit(y) + ') ';\n }\n\n matrix = translateMatrix + ' matrix(' + scaleX +\n ' 0' +\n ' 0 ' +\n scaleY + ' ' +\n (minX * scaleX + widthDiff) + ' ' +\n (minY * scaleY + heightDiff) + ') ';\n // seems unused.\n // parsedDim.viewboxTransform = fabric.parseTransformAttribute(matrix);\n if (element.nodeName === 'svg') {\n el = element.ownerDocument.createElementNS(fabric.svgNS, 'g');\n // element.firstChild != null\n while (element.firstChild) {\n el.appendChild(element.firstChild);\n }\n element.appendChild(el);\n }\n else {\n el = element;\n el.removeAttribute('x');\n el.removeAttribute('y');\n matrix = el.getAttribute('transform') + matrix;\n }\n el.setAttribute('transform', matrix);\n return parsedDim;\n }\n\n function hasAncestorWithNodeName(element, nodeName) {\n while (element && (element = element.parentNode)) {\n if (element.nodeName && nodeName.test(element.nodeName.replace('svg:', ''))\n && !element.getAttribute('instantiated_by_use')) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Parses an SVG document, converts it to an array of corresponding fabric.* instances and passes them to a callback\n * @static\n * @function\n * @memberOf fabric\n * @param {SVGDocument} doc SVG document to parse\n * @param {Function} callback Callback to call when parsing is finished;\n * It's being passed an array of elements (parsed from a document).\n * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n * @param {Object} [parsingOptions] options for parsing document\n * @param {String} [parsingOptions.crossOrigin] crossOrigin settings\n */\n fabric.parseSVGDocument = function(doc, callback, reviver, parsingOptions) {\n if (!doc) {\n return;\n }\n\n parseUseDirectives(doc);\n\n var svgUid = fabric.Object.__uid++, i, len,\n options = applyViewboxTransform(doc),\n descendants = fabric.util.toArray(doc.getElementsByTagName('*'));\n options.crossOrigin = parsingOptions && parsingOptions.crossOrigin;\n options.svgUid = svgUid;\n\n if (descendants.length === 0 && fabric.isLikelyNode) {\n // we're likely in node, where \"o3-xml\" library fails to gEBTN(\"*\")\n // https://github.com/ajaxorg/node-o3-xml/issues/21\n descendants = doc.selectNodes('//*[name(.)!=\"svg\"]');\n var arr = [];\n for (i = 0, len = descendants.length; i < len; i++) {\n arr[i] = descendants[i];\n }\n descendants = arr;\n }\n\n var elements = descendants.filter(function(el) {\n applyViewboxTransform(el);\n return fabric.svgValidTagNamesRegEx.test(el.nodeName.replace('svg:', '')) &&\n !hasAncestorWithNodeName(el, fabric.svgInvalidAncestorsRegEx); // http://www.w3.org/TR/SVG/struct.html#DefsElement\n });\n if (!elements || (elements && !elements.length)) {\n callback && callback([], {});\n return;\n }\n var clipPaths = { };\n descendants.filter(function(el) {\n return el.nodeName.replace('svg:', '') === 'clipPath';\n }).forEach(function(el) {\n var id = el.getAttribute('id');\n clipPaths[id] = fabric.util.toArray(el.getElementsByTagName('*')).filter(function(el) {\n return fabric.svgValidTagNamesRegEx.test(el.nodeName.replace('svg:', ''));\n });\n });\n fabric.gradientDefs[svgUid] = fabric.getGradientDefs(doc);\n fabric.cssRules[svgUid] = fabric.getCSSRules(doc);\n fabric.clipPaths[svgUid] = clipPaths;\n // Precedence of rules: style > class > attribute\n fabric.parseElements(elements, function(instances, elements) {\n if (callback) {\n callback(instances, options, elements, descendants);\n delete fabric.gradientDefs[svgUid];\n delete fabric.cssRules[svgUid];\n delete fabric.clipPaths[svgUid];\n }\n }, clone(options), reviver, parsingOptions);\n };\n\n function recursivelyParseGradientsXlink(doc, gradient) {\n var gradientsAttrs = ['gradientTransform', 'x1', 'x2', 'y1', 'y2', 'gradientUnits', 'cx', 'cy', 'r', 'fx', 'fy'],\n xlinkAttr = 'xlink:href',\n xLink = gradient.getAttribute(xlinkAttr).slice(1),\n referencedGradient = elementById(doc, xLink);\n if (referencedGradient && referencedGradient.getAttribute(xlinkAttr)) {\n recursivelyParseGradientsXlink(doc, referencedGradient);\n }\n gradientsAttrs.forEach(function(attr) {\n if (referencedGradient && !gradient.hasAttribute(attr) && referencedGradient.hasAttribute(attr)) {\n gradient.setAttribute(attr, referencedGradient.getAttribute(attr));\n }\n });\n if (!gradient.children.length) {\n var referenceClone = referencedGradient.cloneNode(true);\n while (referenceClone.firstChild) {\n gradient.appendChild(referenceClone.firstChild);\n }\n }\n gradient.removeAttribute(xlinkAttr);\n }\n\n var reFontDeclaration = new RegExp(\n '(normal|italic)?\\\\s*(normal|small-caps)?\\\\s*' +\n '(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\\\\s*(' +\n fabric.reNum +\n '(?:px|cm|mm|em|pt|pc|in)*)(?:\\\\/(normal|' + fabric.reNum + '))?\\\\s+(.*)');\n\n extend(fabric, {\n /**\n * Parses a short font declaration, building adding its properties to a style object\n * @static\n * @function\n * @memberOf fabric\n * @param {String} value font declaration\n * @param {Object} oStyle definition\n */\n parseFontDeclaration: function(value, oStyle) {\n var match = value.match(reFontDeclaration);\n\n if (!match) {\n return;\n }\n var fontStyle = match[1],\n // font variant is not used\n // fontVariant = match[2],\n fontWeight = match[3],\n fontSize = match[4],\n lineHeight = match[5],\n fontFamily = match[6];\n\n if (fontStyle) {\n oStyle.fontStyle = fontStyle;\n }\n if (fontWeight) {\n oStyle.fontWeight = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight);\n }\n if (fontSize) {\n oStyle.fontSize = parseUnit(fontSize);\n }\n if (fontFamily) {\n oStyle.fontFamily = fontFamily;\n }\n if (lineHeight) {\n oStyle.lineHeight = lineHeight === 'normal' ? 1 : lineHeight;\n }\n },\n\n /**\n * Parses an SVG document, returning all of the gradient declarations found in it\n * @static\n * @function\n * @memberOf fabric\n * @param {SVGDocument} doc SVG document to parse\n * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element\n */\n getGradientDefs: function(doc) {\n var tagArray = [\n 'linearGradient',\n 'radialGradient',\n 'svg:linearGradient',\n 'svg:radialGradient'],\n elList = _getMultipleNodes(doc, tagArray),\n el, j = 0, gradientDefs = { };\n j = elList.length;\n while (j--) {\n el = elList[j];\n if (el.getAttribute('xlink:href')) {\n recursivelyParseGradientsXlink(doc, el);\n }\n gradientDefs[el.getAttribute('id')] = el;\n }\n return gradientDefs;\n },\n\n /**\n * Returns an object of attributes' name/value, given element and an array of attribute names;\n * Parses parent \"g\" nodes recursively upwards.\n * @static\n * @memberOf fabric\n * @param {DOMElement} element Element to parse\n * @param {Array} attributes Array of attributes to parse\n * @return {Object} object containing parsed attributes' names/values\n */\n parseAttributes: function(element, attributes, svgUid) {\n\n if (!element) {\n return;\n }\n\n var value,\n parentAttributes = { },\n fontSize, parentFontSize;\n\n if (typeof svgUid === 'undefined') {\n svgUid = element.getAttribute('svgUid');\n }\n // if there's a parent container (`g` or `a` or `symbol` node), parse its attributes recursively upwards\n if (element.parentNode && fabric.svgValidParentsRegEx.test(element.parentNode.nodeName)) {\n parentAttributes = fabric.parseAttributes(element.parentNode, attributes, svgUid);\n }\n\n var ownAttributes = attributes.reduce(function(memo, attr) {\n value = element.getAttribute(attr);\n if (value) { // eslint-disable-line\n memo[attr] = value;\n }\n return memo;\n }, { });\n // add values parsed from style, which take precedence over attributes\n // (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes)\n var cssAttrs = extend(\n getGlobalStylesForElement(element, svgUid),\n fabric.parseStyleAttribute(element)\n );\n ownAttributes = extend(\n ownAttributes,\n cssAttrs\n );\n if (cssAttrs[cPath]) {\n element.setAttribute(cPath, cssAttrs[cPath]);\n }\n fontSize = parentFontSize = parentAttributes.fontSize || fabric.Text.DEFAULT_SVG_FONT_SIZE;\n if (ownAttributes[fSize]) {\n // looks like the minimum should be 9px when dealing with ems. this is what looks like in browsers.\n ownAttributes[fSize] = fontSize = parseUnit(ownAttributes[fSize], parentFontSize);\n }\n\n var normalizedAttr, normalizedValue, normalizedStyle = {};\n for (var attr in ownAttributes) {\n normalizedAttr = normalizeAttr(attr);\n normalizedValue = normalizeValue(normalizedAttr, ownAttributes[attr], parentAttributes, fontSize);\n normalizedStyle[normalizedAttr] = normalizedValue;\n }\n if (normalizedStyle && normalizedStyle.font) {\n fabric.parseFontDeclaration(normalizedStyle.font, normalizedStyle);\n }\n var mergedAttrs = extend(parentAttributes, normalizedStyle);\n return fabric.svgValidParentsRegEx.test(element.nodeName) ? mergedAttrs : _setStrokeFillOpacity(mergedAttrs);\n },\n\n /**\n * Transforms an array of svg elements to corresponding fabric.* instances\n * @static\n * @memberOf fabric\n * @param {Array} elements Array of elements to parse\n * @param {Function} callback Being passed an array of fabric instances (transformed from SVG elements)\n * @param {Object} [options] Options object\n * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n */\n parseElements: function(elements, callback, options, reviver, parsingOptions) {\n new fabric.ElementsParser(elements, callback, options, reviver, parsingOptions).parse();\n },\n\n /**\n * Parses \"style\" attribute, retuning an object with values\n * @static\n * @memberOf fabric\n * @param {SVGElement} element Element to parse\n * @return {Object} Objects with values parsed from style attribute of an element\n */\n parseStyleAttribute: function(element) {\n var oStyle = { },\n style = element.getAttribute('style');\n\n if (!style) {\n return oStyle;\n }\n\n if (typeof style === 'string') {\n parseStyleString(style, oStyle);\n }\n else {\n parseStyleObject(style, oStyle);\n }\n\n return oStyle;\n },\n\n /**\n * Parses \"points\" attribute, returning an array of values\n * @static\n * @memberOf fabric\n * @param {String} points points attribute string\n * @return {Array} array of points\n */\n parsePointsAttribute: function(points) {\n\n // points attribute is required and must not be empty\n if (!points) {\n return null;\n }\n\n // replace commas with whitespace and remove bookending whitespace\n points = points.replace(/,/g, ' ').trim();\n\n points = points.split(/\\s+/);\n var parsedPoints = [], i, len;\n\n for (i = 0, len = points.length; i < len; i += 2) {\n parsedPoints.push({\n x: parseFloat(points[i]),\n y: parseFloat(points[i + 1])\n });\n }\n\n // odd number of points is an error\n // if (parsedPoints.length % 2 !== 0) {\n // return null;\n // }\n\n return parsedPoints;\n },\n\n /**\n * Returns CSS rules for a given SVG document\n * @static\n * @function\n * @memberOf fabric\n * @param {SVGDocument} doc SVG document to parse\n * @return {Object} CSS rules of this document\n */\n getCSSRules: function(doc) {\n var styles = doc.getElementsByTagName('style'), i, len,\n allRules = { }, rules;\n\n // very crude parsing of style contents\n for (i = 0, len = styles.length; i < len; i++) {\n var styleContents = styles[i].textContent;\n\n // remove comments\n styleContents = styleContents.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n if (styleContents.trim() === '') {\n continue;\n }\n // recovers all the rule in this form `body { style code... }`\n // rules = styleContents.match(/[^{]*\\{[\\s\\S]*?\\}/g);\n rules = styleContents.split('}');\n // remove empty rules.\n rules = rules.filter(function(rule) { return rule.trim(); });\n // at this point we have hopefully an array of rules `body { style code... `\n // eslint-disable-next-line no-loop-func\n rules.forEach(function(rule) {\n\n var match = rule.split('{'),\n ruleObj = { }, declaration = match[1].trim(),\n propertyValuePairs = declaration.split(';').filter(function(pair) { return pair.trim(); });\n\n for (i = 0, len = propertyValuePairs.length; i < len; i++) {\n var pair = propertyValuePairs[i].split(':'),\n property = pair[0].trim(),\n value = pair[1].trim();\n ruleObj[property] = value;\n }\n rule = match[0].trim();\n rule.split(',').forEach(function(_rule) {\n _rule = _rule.replace(/^svg/i, '').trim();\n if (_rule === '') {\n return;\n }\n if (allRules[_rule]) {\n fabric.util.object.extend(allRules[_rule], ruleObj);\n }\n else {\n allRules[_rule] = fabric.util.object.clone(ruleObj);\n }\n });\n });\n }\n return allRules;\n },\n\n /**\n * Takes url corresponding to an SVG document, and parses it into a set of fabric objects.\n * Note that SVG is fetched via XMLHttpRequest, so it needs to conform to SOP (Same Origin Policy)\n * @memberOf fabric\n * @param {String} url\n * @param {Function} callback\n * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n * @param {Object} [options] Object containing options for parsing\n * @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources\n */\n loadSVGFromURL: function(url, callback, reviver, options) {\n\n url = url.replace(/^\\n\\s*/, '').trim();\n new fabric.util.request(url, {\n method: 'get',\n onComplete: onComplete\n });\n\n function onComplete(r) {\n\n var xml = r.responseXML;\n if (!xml || !xml.documentElement) {\n callback && callback(null);\n return false;\n }\n\n fabric.parseSVGDocument(xml.documentElement, function (results, _options, elements, allElements) {\n callback && callback(results, _options, elements, allElements);\n }, reviver, options);\n }\n },\n\n /**\n * Takes string corresponding to an SVG document, and parses it into a set of fabric objects\n * @memberOf fabric\n * @param {String} string\n * @param {Function} callback\n * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n * @param {Object} [options] Object containing options for parsing\n * @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources\n */\n loadSVGFromString: function(string, callback, reviver, options) {\n var parser = new fabric.window.DOMParser(),\n doc = parser.parseFromString(string.trim(), 'text/xml');\n fabric.parseSVGDocument(doc.documentElement, function (results, _options, elements, allElements) {\n callback(results, _options, elements, allElements);\n }, reviver, options);\n }\n });\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\nfabric.ElementsParser = function(elements, callback, options, reviver, parsingOptions, doc) {\n this.elements = elements;\n this.callback = callback;\n this.options = options;\n this.reviver = reviver;\n this.svgUid = (options && options.svgUid) || 0;\n this.parsingOptions = parsingOptions;\n this.regexUrl = /^url\\(['\"]?#([^'\"]+)['\"]?\\)/g;\n this.doc = doc;\n};\n\n(function(proto) {\n proto.parse = function() {\n this.instances = new Array(this.elements.length);\n this.numElements = this.elements.length;\n this.createObjects();\n };\n\n proto.createObjects = function() {\n var _this = this;\n this.elements.forEach(function(element, i) {\n element.setAttribute('svgUid', _this.svgUid);\n _this.createObject(element, i);\n });\n };\n\n proto.findTag = function(el) {\n return fabric[fabric.util.string.capitalize(el.tagName.replace('svg:', ''))];\n };\n\n proto.createObject = function(el, index) {\n var klass = this.findTag(el);\n if (klass && klass.fromElement) {\n try {\n klass.fromElement(el, this.createCallback(index, el), this.options);\n }\n catch (err) {\n fabric.log(err);\n }\n }\n else {\n this.checkIfDone();\n }\n };\n\n proto.createCallback = function(index, el) {\n var _this = this;\n return function(obj) {\n var _options;\n _this.resolveGradient(obj, el, 'fill');\n _this.resolveGradient(obj, el, 'stroke');\n if (obj instanceof fabric.Image && obj._originalElement) {\n _options = obj.parsePreserveAspectRatioAttribute(el);\n }\n obj._removeTransformMatrix(_options);\n _this.resolveClipPath(obj, el);\n _this.reviver && _this.reviver(el, obj);\n _this.instances[index] = obj;\n _this.checkIfDone();\n };\n };\n\n proto.extractPropertyDefinition = function(obj, property, storage) {\n var value = obj[property], regex = this.regexUrl;\n if (!regex.test(value)) {\n return;\n }\n regex.lastIndex = 0;\n var id = regex.exec(value)[1];\n regex.lastIndex = 0;\n return fabric[storage][this.svgUid][id];\n };\n\n proto.resolveGradient = function(obj, el, property) {\n var gradientDef = this.extractPropertyDefinition(obj, property, 'gradientDefs');\n if (gradientDef) {\n var opacityAttr = el.getAttribute(property + '-opacity');\n var gradient = fabric.Gradient.fromElement(gradientDef, obj, opacityAttr, this.options);\n obj.set(property, gradient);\n }\n };\n\n proto.createClipPathCallback = function(obj, container) {\n return function(_newObj) {\n _newObj._removeTransformMatrix();\n _newObj.fillRule = _newObj.clipRule;\n container.push(_newObj);\n };\n };\n\n proto.resolveClipPath = function(obj, usingElement) {\n var clipPath = this.extractPropertyDefinition(obj, 'clipPath', 'clipPaths'),\n element, klass, objTransformInv, container, gTransform, options;\n if (clipPath) {\n container = [];\n objTransformInv = fabric.util.invertTransform(obj.calcTransformMatrix());\n // move the clipPath tag as sibling to the real element that is using it\n var clipPathTag = clipPath[0].parentNode;\n var clipPathOwner = usingElement;\n while (clipPathOwner.parentNode && clipPathOwner.getAttribute('clip-path') !== obj.clipPath) {\n clipPathOwner = clipPathOwner.parentNode;\n }\n clipPathOwner.parentNode.appendChild(clipPathTag);\n for (var i = 0; i < clipPath.length; i++) {\n element = clipPath[i];\n klass = this.findTag(element);\n klass.fromElement(\n element,\n this.createClipPathCallback(obj, container),\n this.options\n );\n }\n if (container.length === 1) {\n clipPath = container[0];\n }\n else {\n clipPath = new fabric.Group(container);\n }\n gTransform = fabric.util.multiplyTransformMatrices(\n objTransformInv,\n clipPath.calcTransformMatrix()\n );\n if (clipPath.clipPath) {\n this.resolveClipPath(clipPath, clipPathOwner);\n }\n var options = fabric.util.qrDecompose(gTransform);\n clipPath.flipX = false;\n clipPath.flipY = false;\n clipPath.set('scaleX', options.scaleX);\n clipPath.set('scaleY', options.scaleY);\n clipPath.angle = options.angle;\n clipPath.skewX = options.skewX;\n clipPath.skewY = 0;\n clipPath.setPositionByOrigin({ x: options.translateX, y: options.translateY }, 'center', 'center');\n obj.clipPath = clipPath;\n }\n else {\n // if clip-path does not resolve to any element, delete the property.\n delete obj.clipPath;\n }\n };\n\n proto.checkIfDone = function() {\n if (--this.numElements === 0) {\n this.instances = this.instances.filter(function(el) {\n // eslint-disable-next-line no-eq-null, eqeqeq\n return el != null;\n });\n this.callback(this.instances, this.elements);\n }\n };\n})(fabric.ElementsParser.prototype);\n\n\n(function(global) {\n\n 'use strict';\n\n /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */\n\n var fabric = global.fabric || (global.fabric = { });\n\n if (fabric.Point) {\n fabric.warn('fabric.Point is already defined');\n return;\n }\n\n fabric.Point = Point;\n\n /**\n * Point class\n * @class fabric.Point\n * @memberOf fabric\n * @constructor\n * @param {Number} x\n * @param {Number} y\n * @return {fabric.Point} thisArg\n */\n function Point(x, y) {\n this.x = x;\n this.y = y;\n }\n\n Point.prototype = /** @lends fabric.Point.prototype */ {\n\n type: 'point',\n\n constructor: Point,\n\n /**\n * Adds another point to this one and returns another one\n * @param {fabric.Point} that\n * @return {fabric.Point} new Point instance with added values\n */\n add: function (that) {\n return new Point(this.x + that.x, this.y + that.y);\n },\n\n /**\n * Adds another point to this one\n * @param {fabric.Point} that\n * @return {fabric.Point} thisArg\n * @chainable\n */\n addEquals: function (that) {\n this.x += that.x;\n this.y += that.y;\n return this;\n },\n\n /**\n * Adds value to this point and returns a new one\n * @param {Number} scalar\n * @return {fabric.Point} new Point with added value\n */\n scalarAdd: function (scalar) {\n return new Point(this.x + scalar, this.y + scalar);\n },\n\n /**\n * Adds value to this point\n * @param {Number} scalar\n * @return {fabric.Point} thisArg\n * @chainable\n */\n scalarAddEquals: function (scalar) {\n this.x += scalar;\n this.y += scalar;\n return this;\n },\n\n /**\n * Subtracts another point from this point and returns a new one\n * @param {fabric.Point} that\n * @return {fabric.Point} new Point object with subtracted values\n */\n subtract: function (that) {\n return new Point(this.x - that.x, this.y - that.y);\n },\n\n /**\n * Subtracts another point from this point\n * @param {fabric.Point} that\n * @return {fabric.Point} thisArg\n * @chainable\n */\n subtractEquals: function (that) {\n this.x -= that.x;\n this.y -= that.y;\n return this;\n },\n\n /**\n * Subtracts value from this point and returns a new one\n * @param {Number} scalar\n * @return {fabric.Point}\n */\n scalarSubtract: function (scalar) {\n return new Point(this.x - scalar, this.y - scalar);\n },\n\n /**\n * Subtracts value from this point\n * @param {Number} scalar\n * @return {fabric.Point} thisArg\n * @chainable\n */\n scalarSubtractEquals: function (scalar) {\n this.x -= scalar;\n this.y -= scalar;\n return this;\n },\n\n /**\n * Multiplies this point by a value and returns a new one\n * TODO: rename in scalarMultiply in 2.0\n * @param {Number} scalar\n * @return {fabric.Point}\n */\n multiply: function (scalar) {\n return new Point(this.x * scalar, this.y * scalar);\n },\n\n /**\n * Multiplies this point by a value\n * TODO: rename in scalarMultiplyEquals in 2.0\n * @param {Number} scalar\n * @return {fabric.Point} thisArg\n * @chainable\n */\n multiplyEquals: function (scalar) {\n this.x *= scalar;\n this.y *= scalar;\n return this;\n },\n\n /**\n * Divides this point by a value and returns a new one\n * TODO: rename in scalarDivide in 2.0\n * @param {Number} scalar\n * @return {fabric.Point}\n */\n divide: function (scalar) {\n return new Point(this.x / scalar, this.y / scalar);\n },\n\n /**\n * Divides this point by a value\n * TODO: rename in scalarDivideEquals in 2.0\n * @param {Number} scalar\n * @return {fabric.Point} thisArg\n * @chainable\n */\n divideEquals: function (scalar) {\n this.x /= scalar;\n this.y /= scalar;\n return this;\n },\n\n /**\n * Returns true if this point is equal to another one\n * @param {fabric.Point} that\n * @return {Boolean}\n */\n eq: function (that) {\n return (this.x === that.x && this.y === that.y);\n },\n\n /**\n * Returns true if this point is less than another one\n * @param {fabric.Point} that\n * @return {Boolean}\n */\n lt: function (that) {\n return (this.x < that.x && this.y < that.y);\n },\n\n /**\n * Returns true if this point is less than or equal to another one\n * @param {fabric.Point} that\n * @return {Boolean}\n */\n lte: function (that) {\n return (this.x <= that.x && this.y <= that.y);\n },\n\n /**\n\n * Returns true if this point is greater another one\n * @param {fabric.Point} that\n * @return {Boolean}\n */\n gt: function (that) {\n return (this.x > that.x && this.y > that.y);\n },\n\n /**\n * Returns true if this point is greater than or equal to another one\n * @param {fabric.Point} that\n * @return {Boolean}\n */\n gte: function (that) {\n return (this.x >= that.x && this.y >= that.y);\n },\n\n /**\n * Returns new point which is the result of linear interpolation with this one and another one\n * @param {fabric.Point} that\n * @param {Number} t , position of interpolation, between 0 and 1 default 0.5\n * @return {fabric.Point}\n */\n lerp: function (that, t) {\n if (typeof t === 'undefined') {\n t = 0.5;\n }\n t = Math.max(Math.min(1, t), 0);\n return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t);\n },\n\n /**\n * Returns distance from this point and another one\n * @param {fabric.Point} that\n * @return {Number}\n */\n distanceFrom: function (that) {\n var dx = this.x - that.x,\n dy = this.y - that.y;\n return Math.sqrt(dx * dx + dy * dy);\n },\n\n /**\n * Returns the point between this point and another one\n * @param {fabric.Point} that\n * @return {fabric.Point}\n */\n midPointFrom: function (that) {\n return this.lerp(that);\n },\n\n /**\n * Returns a new point which is the min of this and another one\n * @param {fabric.Point} that\n * @return {fabric.Point}\n */\n min: function (that) {\n return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y));\n },\n\n /**\n * Returns a new point which is the max of this and another one\n * @param {fabric.Point} that\n * @return {fabric.Point}\n */\n max: function (that) {\n return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y));\n },\n\n /**\n * Returns string representation of this point\n * @return {String}\n */\n toString: function () {\n return this.x + ',' + this.y;\n },\n\n /**\n * Sets x/y of this point\n * @param {Number} x\n * @param {Number} y\n * @chainable\n */\n setXY: function (x, y) {\n this.x = x;\n this.y = y;\n return this;\n },\n\n /**\n * Sets x of this point\n * @param {Number} x\n * @chainable\n */\n setX: function (x) {\n this.x = x;\n return this;\n },\n\n /**\n * Sets y of this point\n * @param {Number} y\n * @chainable\n */\n setY: function (y) {\n this.y = y;\n return this;\n },\n\n /**\n * Sets x/y of this point from another point\n * @param {fabric.Point} that\n * @chainable\n */\n setFromPoint: function (that) {\n this.x = that.x;\n this.y = that.y;\n return this;\n },\n\n /**\n * Swaps x/y of this point and another point\n * @param {fabric.Point} that\n */\n swap: function (that) {\n var x = this.x,\n y = this.y;\n this.x = that.x;\n this.y = that.y;\n that.x = x;\n that.y = y;\n },\n\n /**\n * return a cloned instance of the point\n * @return {fabric.Point}\n */\n clone: function () {\n return new Point(this.x, this.y);\n }\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */\n var fabric = global.fabric || (global.fabric = { });\n\n if (fabric.Intersection) {\n fabric.warn('fabric.Intersection is already defined');\n return;\n }\n\n /**\n * Intersection class\n * @class fabric.Intersection\n * @memberOf fabric\n * @constructor\n */\n function Intersection(status) {\n this.status = status;\n this.points = [];\n }\n\n fabric.Intersection = Intersection;\n\n fabric.Intersection.prototype = /** @lends fabric.Intersection.prototype */ {\n\n constructor: Intersection,\n\n /**\n * Appends a point to intersection\n * @param {fabric.Point} point\n * @return {fabric.Intersection} thisArg\n * @chainable\n */\n appendPoint: function (point) {\n this.points.push(point);\n return this;\n },\n\n /**\n * Appends points to intersection\n * @param {Array} points\n * @return {fabric.Intersection} thisArg\n * @chainable\n */\n appendPoints: function (points) {\n this.points = this.points.concat(points);\n return this;\n }\n };\n\n /**\n * Checks if one line intersects another\n * TODO: rename in intersectSegmentSegment\n * @static\n * @param {fabric.Point} a1\n * @param {fabric.Point} a2\n * @param {fabric.Point} b1\n * @param {fabric.Point} b2\n * @return {fabric.Intersection}\n */\n fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) {\n var result,\n uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x),\n ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x),\n uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);\n if (uB !== 0) {\n var ua = uaT / uB,\n ub = ubT / uB;\n if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {\n result = new Intersection('Intersection');\n result.appendPoint(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y)));\n }\n else {\n result = new Intersection();\n }\n }\n else {\n if (uaT === 0 || ubT === 0) {\n result = new Intersection('Coincident');\n }\n else {\n result = new Intersection('Parallel');\n }\n }\n return result;\n };\n\n /**\n * Checks if line intersects polygon\n * TODO: rename in intersectSegmentPolygon\n * fix detection of coincident\n * @static\n * @param {fabric.Point} a1\n * @param {fabric.Point} a2\n * @param {Array} points\n * @return {fabric.Intersection}\n */\n fabric.Intersection.intersectLinePolygon = function(a1, a2, points) {\n var result = new Intersection(),\n length = points.length,\n b1, b2, inter, i;\n\n for (i = 0; i < length; i++) {\n b1 = points[i];\n b2 = points[(i + 1) % length];\n inter = Intersection.intersectLineLine(a1, a2, b1, b2);\n\n result.appendPoints(inter.points);\n }\n if (result.points.length > 0) {\n result.status = 'Intersection';\n }\n return result;\n };\n\n /**\n * Checks if polygon intersects another polygon\n * @static\n * @param {Array} points1\n * @param {Array} points2\n * @return {fabric.Intersection}\n */\n fabric.Intersection.intersectPolygonPolygon = function (points1, points2) {\n var result = new Intersection(),\n length = points1.length, i;\n\n for (i = 0; i < length; i++) {\n var a1 = points1[i],\n a2 = points1[(i + 1) % length],\n inter = Intersection.intersectLinePolygon(a1, a2, points2);\n\n result.appendPoints(inter.points);\n }\n if (result.points.length > 0) {\n result.status = 'Intersection';\n }\n return result;\n };\n\n /**\n * Checks if polygon intersects rectangle\n * @static\n * @param {Array} points\n * @param {fabric.Point} r1\n * @param {fabric.Point} r2\n * @return {fabric.Intersection}\n */\n fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) {\n var min = r1.min(r2),\n max = r1.max(r2),\n topRight = new fabric.Point(max.x, min.y),\n bottomLeft = new fabric.Point(min.x, max.y),\n inter1 = Intersection.intersectLinePolygon(min, topRight, points),\n inter2 = Intersection.intersectLinePolygon(topRight, max, points),\n inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points),\n inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points),\n result = new Intersection();\n\n result.appendPoints(inter1.points);\n result.appendPoints(inter2.points);\n result.appendPoints(inter3.points);\n result.appendPoints(inter4.points);\n\n if (result.points.length > 0) {\n result.status = 'Intersection';\n }\n return result;\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { });\n\n if (fabric.Color) {\n fabric.warn('fabric.Color is already defined.');\n return;\n }\n\n /**\n * Color class\n * The purpose of {@link fabric.Color} is to abstract and encapsulate common color operations;\n * {@link fabric.Color} is a constructor and creates instances of {@link fabric.Color} objects.\n *\n * @class fabric.Color\n * @param {String} color optional in hex or rgb(a) or hsl format or from known color list\n * @return {fabric.Color} thisArg\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#colors}\n */\n function Color(color) {\n if (!color) {\n this.setSource([0, 0, 0, 1]);\n }\n else {\n this._tryParsingColor(color);\n }\n }\n\n fabric.Color = Color;\n\n fabric.Color.prototype = /** @lends fabric.Color.prototype */ {\n\n /**\n * @private\n * @param {String|Array} color Color value to parse\n */\n _tryParsingColor: function(color) {\n var source;\n\n if (color in Color.colorNameMap) {\n color = Color.colorNameMap[color];\n }\n\n if (color === 'transparent') {\n source = [255, 255, 255, 0];\n }\n\n if (!source) {\n source = Color.sourceFromHex(color);\n }\n if (!source) {\n source = Color.sourceFromRgb(color);\n }\n if (!source) {\n source = Color.sourceFromHsl(color);\n }\n if (!source) {\n //if color is not recognize let's make black as canvas does\n source = [0, 0, 0, 1];\n }\n if (source) {\n this.setSource(source);\n }\n },\n\n /**\n * Adapted from https://github.com/mjijackson\n * @private\n * @param {Number} r Red color value\n * @param {Number} g Green color value\n * @param {Number} b Blue color value\n * @return {Array} Hsl color\n */\n _rgbToHsl: function(r, g, b) {\n r /= 255; g /= 255; b /= 255;\n\n var h, s, l,\n max = fabric.util.array.max([r, g, b]),\n min = fabric.util.array.min([r, g, b]);\n\n l = (max + min) / 2;\n\n if (max === min) {\n h = s = 0; // achromatic\n }\n else {\n var d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r:\n h = (g - b) / d + (g < b ? 6 : 0);\n break;\n case g:\n h = (b - r) / d + 2;\n break;\n case b:\n h = (r - g) / d + 4;\n break;\n }\n h /= 6;\n }\n\n return [\n Math.round(h * 360),\n Math.round(s * 100),\n Math.round(l * 100)\n ];\n },\n\n /**\n * Returns source of this color (where source is an array representation; ex: [200, 200, 100, 1])\n * @return {Array}\n */\n getSource: function() {\n return this._source;\n },\n\n /**\n * Sets source of this color (where source is an array representation; ex: [200, 200, 100, 1])\n * @param {Array} source\n */\n setSource: function(source) {\n this._source = source;\n },\n\n /**\n * Returns color representation in RGB format\n * @return {String} ex: rgb(0-255,0-255,0-255)\n */\n toRgb: function() {\n var source = this.getSource();\n return 'rgb(' + source[0] + ',' + source[1] + ',' + source[2] + ')';\n },\n\n /**\n * Returns color representation in RGBA format\n * @return {String} ex: rgba(0-255,0-255,0-255,0-1)\n */\n toRgba: function() {\n var source = this.getSource();\n return 'rgba(' + source[0] + ',' + source[1] + ',' + source[2] + ',' + source[3] + ')';\n },\n\n /**\n * Returns color representation in HSL format\n * @return {String} ex: hsl(0-360,0%-100%,0%-100%)\n */\n toHsl: function() {\n var source = this.getSource(),\n hsl = this._rgbToHsl(source[0], source[1], source[2]);\n\n return 'hsl(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%)';\n },\n\n /**\n * Returns color representation in HSLA format\n * @return {String} ex: hsla(0-360,0%-100%,0%-100%,0-1)\n */\n toHsla: function() {\n var source = this.getSource(),\n hsl = this._rgbToHsl(source[0], source[1], source[2]);\n\n return 'hsla(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%,' + source[3] + ')';\n },\n\n /**\n * Returns color representation in HEX format\n * @return {String} ex: FF5555\n */\n toHex: function() {\n var source = this.getSource(), r, g, b;\n\n r = source[0].toString(16);\n r = (r.length === 1) ? ('0' + r) : r;\n\n g = source[1].toString(16);\n g = (g.length === 1) ? ('0' + g) : g;\n\n b = source[2].toString(16);\n b = (b.length === 1) ? ('0' + b) : b;\n\n return r.toUpperCase() + g.toUpperCase() + b.toUpperCase();\n },\n\n /**\n * Returns color representation in HEXA format\n * @return {String} ex: FF5555CC\n */\n toHexa: function() {\n var source = this.getSource(), a;\n\n a = Math.round(source[3] * 255);\n a = a.toString(16);\n a = (a.length === 1) ? ('0' + a) : a;\n\n return this.toHex() + a.toUpperCase();\n },\n\n /**\n * Gets value of alpha channel for this color\n * @return {Number} 0-1\n */\n getAlpha: function() {\n return this.getSource()[3];\n },\n\n /**\n * Sets value of alpha channel for this color\n * @param {Number} alpha Alpha value 0-1\n * @return {fabric.Color} thisArg\n */\n setAlpha: function(alpha) {\n var source = this.getSource();\n source[3] = alpha;\n this.setSource(source);\n return this;\n },\n\n /**\n * Transforms color to its grayscale representation\n * @return {fabric.Color} thisArg\n */\n toGrayscale: function() {\n var source = this.getSource(),\n average = parseInt((source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), 10),\n currentAlpha = source[3];\n this.setSource([average, average, average, currentAlpha]);\n return this;\n },\n\n /**\n * Transforms color to its black and white representation\n * @param {Number} threshold\n * @return {fabric.Color} thisArg\n */\n toBlackWhite: function(threshold) {\n var source = this.getSource(),\n average = (source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0),\n currentAlpha = source[3];\n\n threshold = threshold || 127;\n\n average = (Number(average) < Number(threshold)) ? 0 : 255;\n this.setSource([average, average, average, currentAlpha]);\n return this;\n },\n\n /**\n * Overlays color with another color\n * @param {String|fabric.Color} otherColor\n * @return {fabric.Color} thisArg\n */\n overlayWith: function(otherColor) {\n if (!(otherColor instanceof Color)) {\n otherColor = new Color(otherColor);\n }\n\n var result = [],\n alpha = this.getAlpha(),\n otherAlpha = 0.5,\n source = this.getSource(),\n otherSource = otherColor.getSource(), i;\n\n for (i = 0; i < 3; i++) {\n result.push(Math.round((source[i] * (1 - otherAlpha)) + (otherSource[i] * otherAlpha)));\n }\n\n result[3] = alpha;\n this.setSource(result);\n return this;\n }\n };\n\n /**\n * Regex matching color in RGB or RGBA formats (ex: rgb(0, 0, 0), rgba(255, 100, 10, 0.5), rgba( 255 , 100 , 10 , 0.5 ), rgb(1,1,1), rgba(100%, 60%, 10%, 0.5))\n * @static\n * @field\n * @memberOf fabric.Color\n */\n // eslint-disable-next-line max-len\n 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*)?\\)$/i;\n\n /**\n * Regex matching color in HSL or HSLA formats (ex: hsl(200, 80%, 10%), hsla(300, 50%, 80%, 0.5), hsla( 300 , 50% , 80% , 0.5 ))\n * @static\n * @field\n * @memberOf fabric.Color\n */\n fabric.Color.reHSLa = /^hsla?\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3}\\%)\\s*,\\s*(\\d{1,3}\\%)\\s*(?:\\s*,\\s*(\\d+(?:\\.\\d+)?)\\s*)?\\)$/i;\n\n /**\n * Regex matching color in HEX format (ex: #FF5544CC, #FF5555, 010155, aff)\n * @static\n * @field\n * @memberOf fabric.Color\n */\n fabric.Color.reHex = /^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i;\n\n /**\n * Map of the 148 color names with HEX code\n * @static\n * @field\n * @memberOf fabric.Color\n * @see: https://www.w3.org/TR/css3-color/#svg-color\n */\n fabric.Color.colorNameMap = {\n aliceblue: '#F0F8FF',\n antiquewhite: '#FAEBD7',\n aqua: '#00FFFF',\n aquamarine: '#7FFFD4',\n azure: '#F0FFFF',\n beige: '#F5F5DC',\n bisque: '#FFE4C4',\n black: '#000000',\n blanchedalmond: '#FFEBCD',\n blue: '#0000FF',\n blueviolet: '#8A2BE2',\n brown: '#A52A2A',\n burlywood: '#DEB887',\n cadetblue: '#5F9EA0',\n chartreuse: '#7FFF00',\n chocolate: '#D2691E',\n coral: '#FF7F50',\n cornflowerblue: '#6495ED',\n cornsilk: '#FFF8DC',\n crimson: '#DC143C',\n cyan: '#00FFFF',\n darkblue: '#00008B',\n darkcyan: '#008B8B',\n darkgoldenrod: '#B8860B',\n darkgray: '#A9A9A9',\n darkgrey: '#A9A9A9',\n darkgreen: '#006400',\n darkkhaki: '#BDB76B',\n darkmagenta: '#8B008B',\n darkolivegreen: '#556B2F',\n darkorange: '#FF8C00',\n darkorchid: '#9932CC',\n darkred: '#8B0000',\n darksalmon: '#E9967A',\n darkseagreen: '#8FBC8F',\n darkslateblue: '#483D8B',\n darkslategray: '#2F4F4F',\n darkslategrey: '#2F4F4F',\n darkturquoise: '#00CED1',\n darkviolet: '#9400D3',\n deeppink: '#FF1493',\n deepskyblue: '#00BFFF',\n dimgray: '#696969',\n dimgrey: '#696969',\n dodgerblue: '#1E90FF',\n firebrick: '#B22222',\n floralwhite: '#FFFAF0',\n forestgreen: '#228B22',\n fuchsia: '#FF00FF',\n gainsboro: '#DCDCDC',\n ghostwhite: '#F8F8FF',\n gold: '#FFD700',\n goldenrod: '#DAA520',\n gray: '#808080',\n grey: '#808080',\n green: '#008000',\n greenyellow: '#ADFF2F',\n honeydew: '#F0FFF0',\n hotpink: '#FF69B4',\n indianred: '#CD5C5C',\n indigo: '#4B0082',\n ivory: '#FFFFF0',\n khaki: '#F0E68C',\n lavender: '#E6E6FA',\n lavenderblush: '#FFF0F5',\n lawngreen: '#7CFC00',\n lemonchiffon: '#FFFACD',\n lightblue: '#ADD8E6',\n lightcoral: '#F08080',\n lightcyan: '#E0FFFF',\n lightgoldenrodyellow: '#FAFAD2',\n lightgray: '#D3D3D3',\n lightgrey: '#D3D3D3',\n lightgreen: '#90EE90',\n lightpink: '#FFB6C1',\n lightsalmon: '#FFA07A',\n lightseagreen: '#20B2AA',\n lightskyblue: '#87CEFA',\n lightslategray: '#778899',\n lightslategrey: '#778899',\n lightsteelblue: '#B0C4DE',\n lightyellow: '#FFFFE0',\n lime: '#00FF00',\n limegreen: '#32CD32',\n linen: '#FAF0E6',\n magenta: '#FF00FF',\n maroon: '#800000',\n mediumaquamarine: '#66CDAA',\n mediumblue: '#0000CD',\n mediumorchid: '#BA55D3',\n mediumpurple: '#9370DB',\n mediumseagreen: '#3CB371',\n mediumslateblue: '#7B68EE',\n mediumspringgreen: '#00FA9A',\n mediumturquoise: '#48D1CC',\n mediumvioletred: '#C71585',\n midnightblue: '#191970',\n mintcream: '#F5FFFA',\n mistyrose: '#FFE4E1',\n moccasin: '#FFE4B5',\n navajowhite: '#FFDEAD',\n navy: '#000080',\n oldlace: '#FDF5E6',\n olive: '#808000',\n olivedrab: '#6B8E23',\n orange: '#FFA500',\n orangered: '#FF4500',\n orchid: '#DA70D6',\n palegoldenrod: '#EEE8AA',\n palegreen: '#98FB98',\n paleturquoise: '#AFEEEE',\n palevioletred: '#DB7093',\n papayawhip: '#FFEFD5',\n peachpuff: '#FFDAB9',\n peru: '#CD853F',\n pink: '#FFC0CB',\n plum: '#DDA0DD',\n powderblue: '#B0E0E6',\n purple: '#800080',\n rebeccapurple: '#663399',\n red: '#FF0000',\n rosybrown: '#BC8F8F',\n royalblue: '#4169E1',\n saddlebrown: '#8B4513',\n salmon: '#FA8072',\n sandybrown: '#F4A460',\n seagreen: '#2E8B57',\n seashell: '#FFF5EE',\n sienna: '#A0522D',\n silver: '#C0C0C0',\n skyblue: '#87CEEB',\n slateblue: '#6A5ACD',\n slategray: '#708090',\n slategrey: '#708090',\n snow: '#FFFAFA',\n springgreen: '#00FF7F',\n steelblue: '#4682B4',\n tan: '#D2B48C',\n teal: '#008080',\n thistle: '#D8BFD8',\n tomato: '#FF6347',\n turquoise: '#40E0D0',\n violet: '#EE82EE',\n wheat: '#F5DEB3',\n white: '#FFFFFF',\n whitesmoke: '#F5F5F5',\n yellow: '#FFFF00',\n yellowgreen: '#9ACD32'\n };\n\n /**\n * @private\n * @param {Number} p\n * @param {Number} q\n * @param {Number} t\n * @return {Number}\n */\n function hue2rgb(p, q, t) {\n if (t < 0) {\n t += 1;\n }\n if (t > 1) {\n t -= 1;\n }\n if (t < 1 / 6) {\n return p + (q - p) * 6 * t;\n }\n if (t < 1 / 2) {\n return q;\n }\n if (t < 2 / 3) {\n return p + (q - p) * (2 / 3 - t) * 6;\n }\n return p;\n }\n\n /**\n * Returns new color object, when given a color in RGB format\n * @memberOf fabric.Color\n * @param {String} color Color value ex: rgb(0-255,0-255,0-255)\n * @return {fabric.Color}\n */\n fabric.Color.fromRgb = function(color) {\n return Color.fromSource(Color.sourceFromRgb(color));\n };\n\n /**\n * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format\n * @memberOf fabric.Color\n * @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%)\n * @return {Array} source\n */\n fabric.Color.sourceFromRgb = function(color) {\n var match = color.match(Color.reRGBa);\n if (match) {\n var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1),\n g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1),\n b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1);\n\n return [\n parseInt(r, 10),\n parseInt(g, 10),\n parseInt(b, 10),\n match[4] ? parseFloat(match[4]) : 1\n ];\n }\n };\n\n /**\n * Returns new color object, when given a color in RGBA format\n * @static\n * @function\n * @memberOf fabric.Color\n * @param {String} color\n * @return {fabric.Color}\n */\n fabric.Color.fromRgba = Color.fromRgb;\n\n /**\n * Returns new color object, when given a color in HSL format\n * @param {String} color Color value ex: hsl(0-260,0%-100%,0%-100%)\n * @memberOf fabric.Color\n * @return {fabric.Color}\n */\n fabric.Color.fromHsl = function(color) {\n return Color.fromSource(Color.sourceFromHsl(color));\n };\n\n /**\n * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format.\n * Adapted from https://github.com/mjijackson\n * @memberOf fabric.Color\n * @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1)\n * @return {Array} source\n * @see http://http://www.w3.org/TR/css3-color/#hsl-color\n */\n fabric.Color.sourceFromHsl = function(color) {\n var match = color.match(Color.reHSLa);\n if (!match) {\n return;\n }\n\n var h = (((parseFloat(match[1]) % 360) + 360) % 360) / 360,\n s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1),\n l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1),\n r, g, b;\n\n if (s === 0) {\n r = g = b = l;\n }\n else {\n var q = l <= 0.5 ? l * (s + 1) : l + s - l * s,\n p = l * 2 - q;\n\n r = hue2rgb(p, q, h + 1 / 3);\n g = hue2rgb(p, q, h);\n b = hue2rgb(p, q, h - 1 / 3);\n }\n\n return [\n Math.round(r * 255),\n Math.round(g * 255),\n Math.round(b * 255),\n match[4] ? parseFloat(match[4]) : 1\n ];\n };\n\n /**\n * Returns new color object, when given a color in HSLA format\n * @static\n * @function\n * @memberOf fabric.Color\n * @param {String} color\n * @return {fabric.Color}\n */\n fabric.Color.fromHsla = Color.fromHsl;\n\n /**\n * Returns new color object, when given a color in HEX format\n * @static\n * @memberOf fabric.Color\n * @param {String} color Color value ex: FF5555\n * @return {fabric.Color}\n */\n fabric.Color.fromHex = function(color) {\n return Color.fromSource(Color.sourceFromHex(color));\n };\n\n /**\n * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HEX format\n * @static\n * @memberOf fabric.Color\n * @param {String} color ex: FF5555 or FF5544CC (RGBa)\n * @return {Array} source\n */\n fabric.Color.sourceFromHex = function(color) {\n if (color.match(Color.reHex)) {\n var value = color.slice(color.indexOf('#') + 1),\n isShortNotation = (value.length === 3 || value.length === 4),\n isRGBa = (value.length === 8 || value.length === 4),\n r = isShortNotation ? (value.charAt(0) + value.charAt(0)) : value.substring(0, 2),\n g = isShortNotation ? (value.charAt(1) + value.charAt(1)) : value.substring(2, 4),\n b = isShortNotation ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6),\n a = isRGBa ? (isShortNotation ? (value.charAt(3) + value.charAt(3)) : value.substring(6, 8)) : 'FF';\n\n return [\n parseInt(r, 16),\n parseInt(g, 16),\n parseInt(b, 16),\n parseFloat((parseInt(a, 16) / 255).toFixed(2))\n ];\n }\n };\n\n /**\n * Returns new color object, when given color in array representation (ex: [200, 100, 100, 0.5])\n * @static\n * @memberOf fabric.Color\n * @param {Array} source\n * @return {fabric.Color}\n */\n fabric.Color.fromSource = function(source) {\n var oColor = new Color();\n oColor.setSource(source);\n return oColor;\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n scaleMap = ['e', 'se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e'],\n skewMap = ['ns', 'nesw', 'ew', 'nwse'],\n controls = {},\n LEFT = 'left', TOP = 'top', RIGHT = 'right', BOTTOM = 'bottom', CENTER = 'center',\n opposite = {\n top: BOTTOM,\n bottom: TOP,\n left: RIGHT,\n right: LEFT,\n center: CENTER,\n }, radiansToDegrees = fabric.util.radiansToDegrees,\n sign = (Math.sign || function(x) { return ((x > 0) - (x < 0)) || +x; });\n\n /**\n * Combine control position and object angle to find the control direction compared\n * to the object center.\n * @param {fabric.Object} fabricObject the fabric object for which we are rendering controls\n * @param {fabric.Control} control the control class\n * @return {Number} 0 - 7 a quadrant number\n */\n function findCornerQuadrant(fabricObject, control) {\n var cornerAngle = fabricObject.angle + radiansToDegrees(Math.atan2(control.y, control.x)) + 360;\n return Math.round((cornerAngle % 360) / 45);\n }\n\n function fireEvent(eventName, options) {\n var target = options.transform.target,\n canvas = target.canvas,\n canvasOptions = fabric.util.object.clone(options);\n canvasOptions.target = target;\n canvas && canvas.fire('object:' + eventName, canvasOptions);\n target.fire(eventName, options);\n }\n\n /**\n * Inspect event and fabricObject properties to understand if the scaling action\n * @param {Event} eventData from the user action\n * @param {fabric.Object} fabricObject the fabric object about to scale\n * @return {Boolean} true if scale is proportional\n */\n function scaleIsProportional(eventData, fabricObject) {\n var canvas = fabricObject.canvas, uniScaleKey = canvas.uniScaleKey,\n uniformIsToggled = eventData[uniScaleKey];\n return (canvas.uniformScaling && !uniformIsToggled) ||\n (!canvas.uniformScaling && uniformIsToggled);\n }\n\n /**\n * Checks if transform is centered\n * @param {Object} transform transform data\n * @return {Boolean} true if transform is centered\n */\n function isTransformCentered(transform) {\n return transform.originX === CENTER && transform.originY === CENTER;\n }\n\n /**\n * Inspect fabricObject to understand if the current scaling action is allowed\n * @param {fabric.Object} fabricObject the fabric object about to scale\n * @param {String} by 'x' or 'y' or ''\n * @param {Boolean} scaleProportionally true if we are trying to scale proportionally\n * @return {Boolean} true if scaling is not allowed at current conditions\n */\n function scalingIsForbidden(fabricObject, by, scaleProportionally) {\n var lockX = fabricObject.lockScalingX, lockY = fabricObject.lockScalingY;\n if (lockX && lockY) {\n return true;\n }\n if (!by && (lockX || lockY) && scaleProportionally) {\n return true;\n }\n if (lockX && by === 'x') {\n return true;\n }\n if (lockY && by === 'y') {\n return true;\n }\n return false;\n }\n\n /**\n * return the correct cursor style for the scale action\n * @param {Event} eventData the javascript event that is causing the scale\n * @param {fabric.Control} control the control that is interested in the action\n * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n * @return {String} a valid css string for the cursor\n */\n function scaleCursorStyleHandler(eventData, control, fabricObject) {\n var notAllowed = 'not-allowed',\n scaleProportionally = scaleIsProportional(eventData, fabricObject),\n by = '';\n if (control.x !== 0 && control.y === 0) {\n by = 'x';\n }\n else if (control.x === 0 && control.y !== 0) {\n by = 'y';\n }\n if (scalingIsForbidden(fabricObject, by, scaleProportionally)) {\n return notAllowed;\n }\n var n = findCornerQuadrant(fabricObject, control);\n return scaleMap[n] + '-resize';\n }\n\n /**\n * return the correct cursor style for the skew action\n * @param {Event} eventData the javascript event that is causing the scale\n * @param {fabric.Control} control the control that is interested in the action\n * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n * @return {String} a valid css string for the cursor\n */\n function skewCursorStyleHandler(eventData, control, fabricObject) {\n var notAllowed = 'not-allowed';\n if (control.x !== 0 && fabricObject.lockSkewingY) {\n return notAllowed;\n }\n if (control.y !== 0 && fabricObject.lockSkewingX) {\n return notAllowed;\n }\n var n = findCornerQuadrant(fabricObject, control) % 4;\n return skewMap[n] + '-resize';\n }\n\n /**\n * Combine skew and scale style handlers to cover fabric standard use case\n * @param {Event} eventData the javascript event that is causing the scale\n * @param {fabric.Control} control the control that is interested in the action\n * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n * @return {String} a valid css string for the cursor\n */\n function scaleSkewCursorStyleHandler(eventData, control, fabricObject) {\n if (eventData[fabricObject.canvas.altActionKey]) {\n return controls.skewCursorStyleHandler(eventData, control, fabricObject);\n }\n return controls.scaleCursorStyleHandler(eventData, control, fabricObject);\n }\n\n /**\n * Inspect event, control and fabricObject to return the correct action name\n * @param {Event} eventData the javascript event that is causing the scale\n * @param {fabric.Control} control the control that is interested in the action\n * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n * @return {String} an action name\n */\n function scaleOrSkewActionName(eventData, control, fabricObject) {\n var isAlternative = eventData[fabricObject.canvas.altActionKey];\n if (control.x === 0) {\n // then is scaleY or skewX\n return isAlternative ? 'skewX' : 'scaleY';\n }\n if (control.y === 0) {\n // then is scaleY or skewX\n return isAlternative ? 'skewY' : 'scaleX';\n }\n }\n\n /**\n * Find the correct style for the control that is used for rotation.\n * this function is very simple and it just take care of not-allowed or standard cursor\n * @param {Event} eventData the javascript event that is causing the scale\n * @param {fabric.Control} control the control that is interested in the action\n * @param {fabric.Object} fabricObject the fabric object that is interested in the action\n * @return {String} a valid css string for the cursor\n */\n function rotationStyleHandler(eventData, control, fabricObject) {\n if (fabricObject.lockRotation) {\n return 'not-allowed';\n }\n return control.cursorStyle;\n }\n\n function commonEventInfo(eventData, transform, x, y) {\n return {\n e: eventData,\n transform: transform,\n pointer: {\n x: x,\n y: y,\n }\n };\n }\n\n /**\n * Wrap an action handler with saving/restoring object position on the transform.\n * this is the code that permits to objects to keep their position while transforming.\n * @param {Function} actionHandler the function to wrap\n * @return {Function} a function with an action handler signature\n */\n function wrapWithFixedAnchor(actionHandler) {\n return function(eventData, transform, x, y) {\n var target = transform.target, centerPoint = target.getCenterPoint(),\n constraint = target.translateToOriginPoint(centerPoint, transform.originX, transform.originY),\n actionPerformed = actionHandler(eventData, transform, x, y);\n target.setPositionByOrigin(constraint, transform.originX, transform.originY);\n return actionPerformed;\n };\n }\n\n /**\n * Wrap an action handler with firing an event if the action is performed\n * @param {Function} actionHandler the function to wrap\n * @return {Function} a function with an action handler signature\n */\n function wrapWithFireEvent(eventName, actionHandler) {\n return function(eventData, transform, x, y) {\n var actionPerformed = actionHandler(eventData, transform, x, y);\n if (actionPerformed) {\n fireEvent(eventName, commonEventInfo(eventData, transform, x, y));\n }\n return actionPerformed;\n };\n }\n\n /**\n * Transforms a point described by x and y in a distance from the top left corner of the object\n * bounding box.\n * @param {Object} transform\n * @param {String} originX\n * @param {String} originY\n * @param {number} x\n * @param {number} y\n * @return {Fabric.Point} the normalized point\n */\n function getLocalPoint(transform, originX, originY, x, y) {\n var target = transform.target,\n control = target.controls[transform.corner],\n zoom = target.canvas.getZoom(),\n padding = target.padding / zoom,\n localPoint = target.toLocalPoint(new fabric.Point(x, y), originX, originY);\n if (localPoint.x >= padding) {\n localPoint.x -= padding;\n }\n if (localPoint.x <= -padding) {\n localPoint.x += padding;\n }\n if (localPoint.y >= padding) {\n localPoint.y -= padding;\n }\n if (localPoint.y <= padding) {\n localPoint.y += padding;\n }\n localPoint.x -= control.offsetX;\n localPoint.y -= control.offsetY;\n return localPoint;\n }\n\n /**\n * Detect if the fabric object is flipped on one side.\n * @param {fabric.Object} target\n * @return {Boolean} true if one flip, but not two.\n */\n function targetHasOneFlip(target) {\n return target.flipX !== target.flipY;\n }\n\n /**\n * Utility function to compensate the scale factor when skew is applied on both axes\n * @private\n */\n function compensateScaleForSkew(target, oppositeSkew, scaleToCompensate, axis, reference) {\n if (target[oppositeSkew] !== 0) {\n var newDim = target._getTransformedDimensions()[axis];\n var newValue = reference / newDim * target[scaleToCompensate];\n target.set(scaleToCompensate, newValue);\n }\n }\n\n /**\n * Action handler for skewing on the X axis\n * @private\n */\n function skewObjectX(eventData, transform, x, y) {\n var target = transform.target,\n // find how big the object would be, if there was no skewX. takes in account scaling\n dimNoSkew = target._getTransformedDimensions(0, target.skewY),\n localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y),\n // the mouse is in the center of the object, and we want it to stay there.\n // so the object will grow twice as much as the mouse.\n // this makes the skew growth to localPoint * 2 - dimNoSkew.\n totalSkewSize = Math.abs(localPoint.x * 2) - dimNoSkew.x,\n currentSkew = target.skewX, newSkew;\n if (totalSkewSize < 2) {\n // let's make it easy to go back to position 0.\n newSkew = 0;\n }\n else {\n newSkew = radiansToDegrees(\n Math.atan2((totalSkewSize / target.scaleX), (dimNoSkew.y / target.scaleY))\n );\n // now we have to find the sign of the skew.\n // it mostly depend on the origin of transformation.\n if (transform.originX === LEFT && transform.originY === BOTTOM) {\n newSkew = -newSkew;\n }\n if (transform.originX === RIGHT && transform.originY === TOP) {\n newSkew = -newSkew;\n }\n if (targetHasOneFlip(target)) {\n newSkew = -newSkew;\n }\n }\n var hasSkewed = currentSkew !== newSkew;\n if (hasSkewed) {\n var dimBeforeSkewing = target._getTransformedDimensions().y;\n target.set('skewX', newSkew);\n compensateScaleForSkew(target, 'skewY', 'scaleY', 'y', dimBeforeSkewing);\n }\n return hasSkewed;\n }\n\n /**\n * Action handler for skewing on the Y axis\n * @private\n */\n function skewObjectY(eventData, transform, x, y) {\n var target = transform.target,\n // find how big the object would be, if there was no skewX. takes in account scaling\n dimNoSkew = target._getTransformedDimensions(target.skewX, 0),\n localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y),\n // the mouse is in the center of the object, and we want it to stay there.\n // so the object will grow twice as much as the mouse.\n // this makes the skew growth to localPoint * 2 - dimNoSkew.\n totalSkewSize = Math.abs(localPoint.y * 2) - dimNoSkew.y,\n currentSkew = target.skewY, newSkew;\n if (totalSkewSize < 2) {\n // let's make it easy to go back to position 0.\n newSkew = 0;\n }\n else {\n newSkew = radiansToDegrees(\n Math.atan2((totalSkewSize / target.scaleY), (dimNoSkew.x / target.scaleX))\n );\n // now we have to find the sign of the skew.\n // it mostly depend on the origin of transformation.\n if (transform.originX === LEFT && transform.originY === BOTTOM) {\n newSkew = -newSkew;\n }\n if (transform.originX === RIGHT && transform.originY === TOP) {\n newSkew = -newSkew;\n }\n if (targetHasOneFlip(target)) {\n newSkew = -newSkew;\n }\n }\n var hasSkewed = currentSkew !== newSkew;\n if (hasSkewed) {\n var dimBeforeSkewing = target._getTransformedDimensions().x;\n target.set('skewY', newSkew);\n compensateScaleForSkew(target, 'skewX', 'scaleX', 'x', dimBeforeSkewing);\n }\n return hasSkewed;\n }\n\n /**\n * Wrapped Action handler for skewing on the Y axis, takes care of the\n * skew direction and determine the correct transform origin for the anchor point\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\n function skewHandlerX(eventData, transform, x, y) {\n // step1 figure out and change transform origin.\n // if skewX > 0 and originY bottom we anchor on right\n // if skewX > 0 and originY top we anchor on left\n // if skewX < 0 and originY bottom we anchor on left\n // if skewX < 0 and originY top we anchor on right\n // if skewX is 0, we look for mouse position to understand where are we going.\n var target = transform.target, currentSkew = target.skewX, originX, originY = transform.originY;\n if (target.lockSkewingX) {\n return false;\n }\n if (currentSkew === 0) {\n var localPointFromCenter = getLocalPoint(transform, CENTER, CENTER, x, y);\n if (localPointFromCenter.x > 0) {\n // we are pulling right, anchor left;\n originX = LEFT;\n }\n else {\n // we are pulling right, anchor right\n originX = RIGHT;\n }\n }\n else {\n if (currentSkew > 0) {\n originX = originY === TOP ? LEFT : RIGHT;\n }\n if (currentSkew < 0) {\n originX = originY === TOP ? RIGHT : LEFT;\n }\n // is the object flipped on one side only? swap the origin.\n if (targetHasOneFlip(target)) {\n originX = originX === LEFT ? RIGHT : LEFT;\n }\n }\n\n // once we have the origin, we find the anchor point\n transform.originX = originX;\n var finalHandler = wrapWithFireEvent('skewing', wrapWithFixedAnchor(skewObjectX));\n return finalHandler(eventData, transform, x, y);\n }\n\n /**\n * Wrapped Action handler for skewing on the Y axis, takes care of the\n * skew direction and determine the correct transform origin for the anchor point\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\n function skewHandlerY(eventData, transform, x, y) {\n // step1 figure out and change transform origin.\n // if skewY > 0 and originX left we anchor on top\n // if skewY > 0 and originX right we anchor on bottom\n // if skewY < 0 and originX left we anchor on bottom\n // if skewY < 0 and originX right we anchor on top\n // if skewY is 0, we look for mouse position to understand where are we going.\n var target = transform.target, currentSkew = target.skewY, originY, originX = transform.originX;\n if (target.lockSkewingY) {\n return false;\n }\n if (currentSkew === 0) {\n var localPointFromCenter = getLocalPoint(transform, CENTER, CENTER, x, y);\n if (localPointFromCenter.y > 0) {\n // we are pulling down, anchor up;\n originY = TOP;\n }\n else {\n // we are pulling up, anchor down\n originY = BOTTOM;\n }\n }\n else {\n if (currentSkew > 0) {\n originY = originX === LEFT ? TOP : BOTTOM;\n }\n if (currentSkew < 0) {\n originY = originX === LEFT ? BOTTOM : TOP;\n }\n // is the object flipped on one side only? swap the origin.\n if (targetHasOneFlip(target)) {\n originY = originY === TOP ? BOTTOM : TOP;\n }\n }\n\n // once we have the origin, we find the anchor point\n transform.originY = originY;\n var finalHandler = wrapWithFireEvent('skewing', wrapWithFixedAnchor(skewObjectY));\n return finalHandler(eventData, transform, x, y);\n }\n\n /**\n * Action handler for rotation and snapping, without anchor point.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n * @private\n */\n function rotationWithSnapping(eventData, transform, x, y) {\n var t = transform,\n target = t.target,\n pivotPoint = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY);\n\n if (target.lockRotation) {\n return false;\n }\n\n var lastAngle = Math.atan2(t.ey - pivotPoint.y, t.ex - pivotPoint.x),\n curAngle = Math.atan2(y - pivotPoint.y, x - pivotPoint.x),\n angle = radiansToDegrees(curAngle - lastAngle + t.theta),\n hasRotated = true;\n\n if (target.snapAngle > 0) {\n var snapAngle = target.snapAngle,\n snapThreshold = target.snapThreshold || snapAngle,\n rightAngleLocked = Math.ceil(angle / snapAngle) * snapAngle,\n leftAngleLocked = Math.floor(angle / snapAngle) * snapAngle;\n\n if (Math.abs(angle - leftAngleLocked) < snapThreshold) {\n angle = leftAngleLocked;\n }\n else if (Math.abs(angle - rightAngleLocked) < snapThreshold) {\n angle = rightAngleLocked;\n }\n }\n\n // normalize angle to positive value\n if (angle < 0) {\n angle = 360 + angle;\n }\n angle %= 360;\n\n hasRotated = target.angle !== angle;\n target.angle = angle;\n return hasRotated;\n }\n\n /**\n * Basic scaling logic, reused with different constrain for scaling X,Y, freely or equally.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @param {Object} options additional information for scaling\n * @param {String} options.by 'x', 'y', 'equally' or '' to indicate type of scaling\n * @return {Boolean} true if some change happened\n * @private\n */\n function scaleObject(eventData, transform, x, y, options) {\n options = options || {};\n var target = transform.target,\n lockScalingX = target.lockScalingX, lockScalingY = target.lockScalingY,\n by = options.by, newPoint, scaleX, scaleY, dim,\n scaleProportionally = scaleIsProportional(eventData, target),\n forbidScaling = scalingIsForbidden(target, by, scaleProportionally),\n signX, signY, gestureScale = transform.gestureScale;\n\n if (forbidScaling) {\n return false;\n }\n if (gestureScale) {\n scaleX = transform.scaleX * gestureScale;\n scaleY = transform.scaleY * gestureScale;\n }\n else {\n newPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y);\n // use of sign: We use sign to detect change of direction of an action. sign usually change when\n // we cross the origin point with the mouse. So a scale flip for example. There is an issue when scaling\n // by center and scaling using one middle control ( default: mr, mt, ml, mb), the mouse movement can easily\n // cross many time the origin point and flip the object. so we need a way to filter out the noise.\n // This ternary here should be ok to filter out X scaling when we want Y only and vice versa.\n signX = by !== 'y' ? sign(newPoint.x) : 1;\n signY = by !== 'x' ? sign(newPoint.y) : 1;\n if (!transform.signX) {\n transform.signX = signX;\n }\n if (!transform.signY) {\n transform.signY = signY;\n }\n\n if (target.lockScalingFlip &&\n (transform.signX !== signX || transform.signY !== signY)\n ) {\n return false;\n }\n\n dim = target._getTransformedDimensions();\n // missing detection of flip and logic to switch the origin\n if (scaleProportionally && !by) {\n // uniform scaling\n var distance = Math.abs(newPoint.x) + Math.abs(newPoint.y),\n original = transform.original,\n originalDistance = Math.abs(dim.x * original.scaleX / target.scaleX) +\n Math.abs(dim.y * original.scaleY / target.scaleY),\n scale = distance / originalDistance;\n scaleX = original.scaleX * scale;\n scaleY = original.scaleY * scale;\n }\n else {\n scaleX = Math.abs(newPoint.x * target.scaleX / dim.x);\n scaleY = Math.abs(newPoint.y * target.scaleY / dim.y);\n }\n // if we are scaling by center, we need to double the scale\n if (isTransformCentered(transform)) {\n scaleX *= 2;\n scaleY *= 2;\n }\n if (transform.signX !== signX && by !== 'y') {\n transform.originX = opposite[transform.originX];\n scaleX *= -1;\n transform.signX = signX;\n }\n if (transform.signY !== signY && by !== 'x') {\n transform.originY = opposite[transform.originY];\n scaleY *= -1;\n transform.signY = signY;\n }\n }\n // minScale is taken are in the setter.\n var oldScaleX = target.scaleX, oldScaleY = target.scaleY;\n if (!by) {\n !lockScalingX && target.set('scaleX', scaleX);\n !lockScalingY && target.set('scaleY', scaleY);\n }\n else {\n // forbidden cases already handled on top here.\n by === 'x' && target.set('scaleX', scaleX);\n by === 'y' && target.set('scaleY', scaleY);\n }\n return oldScaleX !== target.scaleX || oldScaleY !== target.scaleY;\n }\n\n /**\n * Generic scaling logic, to scale from corners either equally or freely.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\n function scaleObjectFromCorner(eventData, transform, x, y) {\n return scaleObject(eventData, transform, x, y);\n }\n\n /**\n * Scaling logic for the X axis.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\n function scaleObjectX(eventData, transform, x, y) {\n return scaleObject(eventData, transform, x, y , { by: 'x' });\n }\n\n /**\n * Scaling logic for the Y axis.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\n function scaleObjectY(eventData, transform, x, y) {\n return scaleObject(eventData, transform, x, y , { by: 'y' });\n }\n\n /**\n * Composed action handler to either scale Y or skew X\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\n function scalingYOrSkewingX(eventData, transform, x, y) {\n // ok some safety needed here.\n if (eventData[transform.target.canvas.altActionKey]) {\n return controls.skewHandlerX(eventData, transform, x, y);\n }\n return controls.scalingY(eventData, transform, x, y);\n }\n\n /**\n * Composed action handler to either scale X or skew Y\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\n function scalingXOrSkewingY(eventData, transform, x, y) {\n // ok some safety needed here.\n if (eventData[transform.target.canvas.altActionKey]) {\n return controls.skewHandlerY(eventData, transform, x, y);\n }\n return controls.scalingX(eventData, transform, x, y);\n }\n\n /**\n * Action handler to change textbox width\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\n function changeWidth(eventData, transform, x, y) {\n var target = transform.target, localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y),\n strokePadding = target.strokeWidth / (target.strokeUniform ? target.scaleX : 1),\n multiplier = isTransformCentered(transform) ? 2 : 1,\n oldWidth = target.width,\n newWidth = Math.abs(localPoint.x * multiplier / target.scaleX) - strokePadding;\n target.set('width', Math.max(newWidth, 0));\n return oldWidth !== newWidth;\n }\n\n /**\n * Action handler\n * @private\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if the translation occurred\n */\n function dragHandler(eventData, transform, x, y) {\n var target = transform.target,\n newLeft = x - transform.offsetX,\n newTop = y - transform.offsetY,\n moveX = !target.get('lockMovementX') && target.left !== newLeft,\n moveY = !target.get('lockMovementY') && target.top !== newTop;\n moveX && target.set('left', newLeft);\n moveY && target.set('top', newTop);\n if (moveX || moveY) {\n fireEvent('moving', commonEventInfo(eventData, transform, x, y));\n }\n return moveX || moveY;\n }\n\n controls.scaleCursorStyleHandler = scaleCursorStyleHandler;\n controls.skewCursorStyleHandler = skewCursorStyleHandler;\n controls.scaleSkewCursorStyleHandler = scaleSkewCursorStyleHandler;\n controls.rotationWithSnapping = wrapWithFireEvent('rotating', wrapWithFixedAnchor(rotationWithSnapping));\n controls.scalingEqually = wrapWithFireEvent('scaling', wrapWithFixedAnchor( scaleObjectFromCorner));\n controls.scalingX = wrapWithFireEvent('scaling', wrapWithFixedAnchor(scaleObjectX));\n controls.scalingY = wrapWithFireEvent('scaling', wrapWithFixedAnchor(scaleObjectY));\n controls.scalingYOrSkewingX = scalingYOrSkewingX;\n controls.scalingXOrSkewingY = scalingXOrSkewingY;\n controls.changeWidth = wrapWithFireEvent('resizing', wrapWithFixedAnchor(changeWidth));\n controls.skewHandlerX = skewHandlerX;\n controls.skewHandlerY = skewHandlerY;\n controls.dragHandler = dragHandler;\n controls.scaleOrSkewActionName = scaleOrSkewActionName;\n controls.rotationStyleHandler = rotationStyleHandler;\n controls.fireEvent = fireEvent;\n controls.wrapWithFixedAnchor = wrapWithFixedAnchor;\n controls.wrapWithFireEvent = wrapWithFireEvent;\n controls.getLocalPoint = getLocalPoint;\n fabric.controlsUtils = controls;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n degreesToRadians = fabric.util.degreesToRadians,\n controls = fabric.controlsUtils;\n\n /**\n * Render a round control, as per fabric features.\n * This function is written to respect object properties like transparentCorners, cornerSize\n * cornerColor, cornerStrokeColor\n * plus the addition of offsetY and offsetX.\n * @param {CanvasRenderingContext2D} ctx context to render on\n * @param {Number} left x coordinate where the control center should be\n * @param {Number} top y coordinate where the control center should be\n * @param {Object} styleOverride override for fabric.Object controls style\n * @param {fabric.Object} fabricObject the fabric object for which we are rendering controls\n */\n function renderCircleControl (ctx, left, top, styleOverride, fabricObject) {\n styleOverride = styleOverride || {};\n var xSize = this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize,\n ySize = this.sizeY || styleOverride.cornerSize || fabricObject.cornerSize,\n transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ?\n styleOverride.transparentCorners : fabricObject.transparentCorners,\n methodName = transparentCorners ? 'stroke' : 'fill',\n stroke = !transparentCorners && (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor),\n myLeft = left,\n myTop = top, size;\n ctx.save();\n ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor;\n ctx.strokeStyle = styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor;\n // as soon as fabric react v5, remove ie11, use proper ellipse code.\n if (xSize > ySize) {\n size = xSize;\n ctx.scale(1.0, ySize / xSize);\n myTop = top * xSize / ySize;\n }\n else if (ySize > xSize) {\n size = ySize;\n ctx.scale(xSize / ySize, 1.0);\n myLeft = left * ySize / xSize;\n }\n else {\n size = xSize;\n }\n // this is still wrong\n ctx.lineWidth = 1;\n ctx.beginPath();\n ctx.arc(myLeft, myTop, size / 2, 0, 2 * Math.PI, false);\n ctx[methodName]();\n if (stroke) {\n ctx.stroke();\n }\n ctx.restore();\n }\n\n /**\n * Render a square control, as per fabric features.\n * This function is written to respect object properties like transparentCorners, cornerSize\n * cornerColor, cornerStrokeColor\n * plus the addition of offsetY and offsetX.\n * @param {CanvasRenderingContext2D} ctx context to render on\n * @param {Number} left x coordinate where the control center should be\n * @param {Number} top y coordinate where the control center should be\n * @param {Object} styleOverride override for fabric.Object controls style\n * @param {fabric.Object} fabricObject the fabric object for which we are rendering controls\n */\n function renderSquareControl(ctx, left, top, styleOverride, fabricObject) {\n styleOverride = styleOverride || {};\n var xSize = this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize,\n ySize = this.sizeY || styleOverride.cornerSize || fabricObject.cornerSize,\n transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ?\n styleOverride.transparentCorners : fabricObject.transparentCorners,\n methodName = transparentCorners ? 'stroke' : 'fill',\n stroke = !transparentCorners && (\n styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor\n ), xSizeBy2 = xSize / 2, ySizeBy2 = ySize / 2;\n ctx.save();\n ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor;\n ctx.strokeStyle = styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor;\n // this is still wrong\n ctx.lineWidth = 1;\n ctx.translate(left, top);\n ctx.rotate(degreesToRadians(fabricObject.angle));\n // this does not work, and fixed with ( && ) does not make sense.\n // to have real transparent corners we need the controls on upperCanvas\n // transparentCorners || ctx.clearRect(-xSizeBy2, -ySizeBy2, xSize, ySize);\n ctx[methodName + 'Rect'](-xSizeBy2, -ySizeBy2, xSize, ySize);\n if (stroke) {\n ctx.strokeRect(-xSizeBy2, -ySizeBy2, xSize, ySize);\n }\n ctx.restore();\n }\n\n controls.renderCircleControl = renderCircleControl;\n controls.renderSquareControl = renderSquareControl;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { });\n\n function Control(options) {\n for (var i in options) {\n this[i] = options[i];\n }\n }\n\n fabric.Control = Control;\n\n fabric.Control.prototype = /** @lends fabric.Control.prototype */ {\n\n /**\n * keep track of control visibility.\n * mainly for backward compatibility.\n * if you do not want to see a control, you can remove it\n * from the controlset.\n * @type {Boolean}\n * @default true\n */\n visible: true,\n\n /**\n * Name of the action that the control will likely execute.\n * This is optional. FabricJS uses to identify what the user is doing for some\n * extra optimizations. If you are writing a custom control and you want to know\n * somewhere else in the code what is going on, you can use this string here.\n * you can also provide a custom getActionName if your control run multiple actions\n * depending on some external state.\n * default to scale since is the most common, used on 4 corners by default\n * @type {String}\n * @default 'scale'\n */\n actionName: 'scale',\n\n /**\n * Drawing angle of the control.\n * NOT used for now, but name marked as needed for internal logic\n * example: to reuse the same drawing function for different rotated controls\n * @type {Number}\n * @default 0\n */\n angle: 0,\n\n /**\n * Relative position of the control. X\n * 0,0 is the center of the Object, while -0.5 (left) or 0.5 (right) are the extremities\n * of the bounding box.\n * @type {Number}\n * @default 0\n */\n x: 0,\n\n /**\n * Relative position of the control. Y\n * 0,0 is the center of the Object, while -0.5 (top) or 0.5 (bottom) are the extremities\n * of the bounding box.\n * @type {Number}\n * @default 0\n */\n y: 0,\n\n /**\n * Horizontal offset of the control from the defined position. In pixels\n * Positive offset moves the control to the right, negative to the left.\n * It used when you want to have position of control that does not scale with\n * the bounding box. Example: rotation control is placed at x:0, y: 0.5 on\n * the boundindbox, with an offset of 30 pixels vertically. Those 30 pixels will\n * stay 30 pixels no matter how the object is big. Another example is having 2\n * controls in the corner, that stay in the same position when the object scale.\n * of the bounding box.\n * @type {Number}\n * @default 0\n */\n offsetX: 0,\n\n /**\n * Vertical offset of the control from the defined position. In pixels\n * Positive offset moves the control to the bottom, negative to the top.\n * @type {Number}\n * @default 0\n */\n offsetY: 0,\n\n /**\n * Sets the length of the control. If null, defaults to object's cornerSize.\n * Expects both sizeX and sizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n sizeX: null,\n\n /**\n * Sets the height of the control. If null, defaults to object's cornerSize.\n * Expects both sizeX and sizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n sizeY: null,\n\n /**\n * Sets the length of the touch area of the control. If null, defaults to object's touchCornerSize.\n * Expects both touchSizeX and touchSizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n touchSizeX: null,\n\n /**\n * Sets the height of the touch area of the control. If null, defaults to object's touchCornerSize.\n * Expects both touchSizeX and touchSizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n touchSizeY: null,\n\n /**\n * Css cursor style to display when the control is hovered.\n * if the method `cursorStyleHandler` is provided, this property is ignored.\n * @type {String}\n * @default 'crosshair'\n */\n cursorStyle: 'crosshair',\n\n /**\n * If controls has an offsetY or offsetX, draw a line that connects\n * the control to the bounding box\n * @type {Boolean}\n * @default false\n */\n withConnection: false,\n\n /**\n * The control actionHandler, provide one to handle action ( control being moved )\n * @param {Event} eventData the native mouse event\n * @param {Object} transformData properties of the current transform\n * @param {Number} x x position of the cursor\n * @param {Number} y y position of the cursor\n * @return {Boolean} true if the action/event modified the object\n */\n actionHandler: function(/* eventData, transformData, x, y */) { },\n\n /**\n * The control handler for mouse down, provide one to handle mouse down on control\n * @param {Event} eventData the native mouse event\n * @param {Object} transformData properties of the current transform\n * @param {Number} x x position of the cursor\n * @param {Number} y y position of the cursor\n * @return {Boolean} true if the action/event modified the object\n */\n mouseDownHandler: function(/* eventData, transformData, x, y */) { },\n\n /**\n * The control mouseUpHandler, provide one to handle an effect on mouse up.\n * @param {Event} eventData the native mouse event\n * @param {Object} transformData properties of the current transform\n * @param {Number} x x position of the cursor\n * @param {Number} y y position of the cursor\n * @return {Boolean} true if the action/event modified the object\n */\n mouseUpHandler: function(/* eventData, transformData, x, y */) { },\n\n /**\n * Returns control actionHandler\n * @param {Event} eventData the native mouse event\n * @param {fabric.Object} fabricObject on which the control is displayed\n * @param {fabric.Control} control control for which the action handler is being asked\n * @return {Function} the action handler\n */\n getActionHandler: function(/* eventData, fabricObject, control */) {\n return this.actionHandler;\n },\n\n /**\n * Returns control mouseDown handler\n * @param {Event} eventData the native mouse event\n * @param {fabric.Object} fabricObject on which the control is displayed\n * @param {fabric.Control} control control for which the action handler is being asked\n * @return {Function} the action handler\n */\n getMouseDownHandler: function(/* eventData, fabricObject, control */) {\n return this.mouseDownHandler;\n },\n\n /**\n * Returns control mouseUp handler\n * @param {Event} eventData the native mouse event\n * @param {fabric.Object} fabricObject on which the control is displayed\n * @param {fabric.Control} control control for which the action handler is being asked\n * @return {Function} the action handler\n */\n getMouseUpHandler: function(/* eventData, fabricObject, control */) {\n return this.mouseUpHandler;\n },\n\n /**\n * Returns control cursorStyle for css using cursorStyle. If you need a more elaborate\n * function you can pass one in the constructor\n * the cursorStyle property\n * @param {Event} eventData the native mouse event\n * @param {fabric.Control} control the current control ( likely this)\n * @param {fabric.Object} object on which the control is displayed\n * @return {String}\n */\n cursorStyleHandler: function(eventData, control /* fabricObject */) {\n return control.cursorStyle;\n },\n\n /**\n * Returns the action name. The basic implementation just return the actionName property.\n * @param {Event} eventData the native mouse event\n * @param {fabric.Control} control the current control ( likely this)\n * @param {fabric.Object} object on which the control is displayed\n * @return {String}\n */\n getActionName: function(eventData, control /* fabricObject */) {\n return control.actionName;\n },\n\n /**\n * Returns controls visibility\n * @param {fabric.Object} object on which the control is displayed\n * @param {String} controlKey key where the control is memorized on the\n * @return {Boolean}\n */\n getVisibility: function(fabricObject, controlKey) {\n var objectVisibility = fabricObject._controlsVisibility;\n if (objectVisibility && typeof objectVisibility[controlKey] !== 'undefined') {\n return objectVisibility[controlKey];\n }\n return this.visible;\n },\n\n /**\n * Sets controls visibility\n * @param {Boolean} visibility for the object\n * @return {Void}\n */\n setVisibility: function(visibility /* name, fabricObject */) {\n this.visible = visibility;\n },\n\n\n positionHandler: function(dim, finalMatrix /*, fabricObject, currentControl */) {\n var point = fabric.util.transformPoint({\n x: this.x * dim.x + this.offsetX,\n y: this.y * dim.y + this.offsetY }, finalMatrix);\n return point;\n },\n\n /**\n * Returns the coords for this control based on object values.\n * @param {Number} objectAngle angle from the fabric object holding the control\n * @param {Number} objectCornerSize cornerSize from the fabric object holding the control (or touchCornerSize if\n * isTouch is true)\n * @param {Number} centerX x coordinate where the control center should be\n * @param {Number} centerY y coordinate where the control center should be\n * @param {boolean} isTouch true if touch corner, false if normal corner\n */\n calcCornerCoords: function(objectAngle, objectCornerSize, centerX, centerY, isTouch) {\n var cosHalfOffset,\n sinHalfOffset,\n cosHalfOffsetComp,\n sinHalfOffsetComp,\n xSize = (isTouch) ? this.touchSizeX : this.sizeX,\n ySize = (isTouch) ? this.touchSizeY : this.sizeY;\n if (xSize && ySize && xSize !== ySize) {\n // handle rectangular corners\n var controlTriangleAngle = Math.atan2(ySize, xSize);\n var cornerHypotenuse = Math.sqrt(xSize * xSize + ySize * ySize) / 2;\n var newTheta = controlTriangleAngle - fabric.util.degreesToRadians(objectAngle);\n var newThetaComp = Math.PI / 2 - controlTriangleAngle - fabric.util.degreesToRadians(objectAngle);\n cosHalfOffset = cornerHypotenuse * fabric.util.cos(newTheta);\n sinHalfOffset = cornerHypotenuse * fabric.util.sin(newTheta);\n // use complementary angle for two corners\n cosHalfOffsetComp = cornerHypotenuse * fabric.util.cos(newThetaComp);\n sinHalfOffsetComp = cornerHypotenuse * fabric.util.sin(newThetaComp);\n }\n else {\n // handle square corners\n // use default object corner size unless size is defined\n var cornerSize = (xSize && ySize) ? xSize : objectCornerSize;\n /* 0.7071067812 stands for sqrt(2)/2 */\n cornerHypotenuse = cornerSize * 0.7071067812;\n // complementary angles are equal since they're both 45 degrees\n var newTheta = fabric.util.degreesToRadians(45 - objectAngle);\n cosHalfOffset = cosHalfOffsetComp = cornerHypotenuse * fabric.util.cos(newTheta);\n sinHalfOffset = sinHalfOffsetComp = cornerHypotenuse * fabric.util.sin(newTheta);\n }\n\n return {\n tl: {\n x: centerX - sinHalfOffsetComp,\n y: centerY - cosHalfOffsetComp,\n },\n tr: {\n x: centerX + cosHalfOffset,\n y: centerY - sinHalfOffset,\n },\n bl: {\n x: centerX - cosHalfOffset,\n y: centerY + sinHalfOffset,\n },\n br: {\n x: centerX + sinHalfOffsetComp,\n y: centerY + cosHalfOffsetComp,\n },\n };\n },\n\n /**\n * Render function for the control.\n * When this function runs the context is unscaled. unrotate. Just retina scaled.\n * all the functions will have to translate to the point left,top before starting Drawing\n * if they want to draw a control where the position is detected.\n * left and top are the result of the positionHandler function\n * @param {RenderingContext2D} ctx the context where the control will be drawn\n * @param {Number} left position of the canvas where we are about to render the control.\n * @param {Number} top position of the canvas where we are about to render the control.\n * @param {Object} styleOverride\n * @param {fabric.Object} fabricObject the object where the control is about to be rendered\n */\n render: function(ctx, left, top, styleOverride, fabricObject) {\n styleOverride = styleOverride || {};\n switch (styleOverride.cornerStyle || fabricObject.cornerStyle) {\n case 'circle':\n fabric.controlsUtils.renderCircleControl.call(this, ctx, left, top, styleOverride, fabricObject);\n break;\n default:\n fabric.controlsUtils.renderSquareControl.call(this, ctx, left, top, styleOverride, fabricObject);\n }\n },\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n /* _FROM_SVG_START_ */\n function getColorStop(el, multiplier) {\n var style = el.getAttribute('style'),\n offset = el.getAttribute('offset') || 0,\n color, colorAlpha, opacity, i;\n\n // convert percents to absolute values\n offset = parseFloat(offset) / (/%$/.test(offset) ? 100 : 1);\n offset = offset < 0 ? 0 : offset > 1 ? 1 : offset;\n if (style) {\n var keyValuePairs = style.split(/\\s*;\\s*/);\n\n if (keyValuePairs[keyValuePairs.length - 1] === '') {\n keyValuePairs.pop();\n }\n\n for (i = keyValuePairs.length; i--; ) {\n\n var split = keyValuePairs[i].split(/\\s*:\\s*/),\n key = split[0].trim(),\n value = split[1].trim();\n\n if (key === 'stop-color') {\n color = value;\n }\n else if (key === 'stop-opacity') {\n opacity = value;\n }\n }\n }\n\n if (!color) {\n color = el.getAttribute('stop-color') || 'rgb(0,0,0)';\n }\n if (!opacity) {\n opacity = el.getAttribute('stop-opacity');\n }\n\n color = new fabric.Color(color);\n colorAlpha = color.getAlpha();\n opacity = isNaN(parseFloat(opacity)) ? 1 : parseFloat(opacity);\n opacity *= colorAlpha * multiplier;\n\n return {\n offset: offset,\n color: color.toRgb(),\n opacity: opacity\n };\n }\n\n function getLinearCoords(el) {\n return {\n x1: el.getAttribute('x1') || 0,\n y1: el.getAttribute('y1') || 0,\n x2: el.getAttribute('x2') || '100%',\n y2: el.getAttribute('y2') || 0\n };\n }\n\n function getRadialCoords(el) {\n return {\n x1: el.getAttribute('fx') || el.getAttribute('cx') || '50%',\n y1: el.getAttribute('fy') || el.getAttribute('cy') || '50%',\n r1: 0,\n x2: el.getAttribute('cx') || '50%',\n y2: el.getAttribute('cy') || '50%',\n r2: el.getAttribute('r') || '50%'\n };\n }\n /* _FROM_SVG_END_ */\n\n var clone = fabric.util.object.clone;\n\n /**\n * Gradient class\n * @class fabric.Gradient\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#gradients}\n * @see {@link fabric.Gradient#initialize} for constructor definition\n */\n fabric.Gradient = fabric.util.createClass(/** @lends fabric.Gradient.prototype */ {\n\n /**\n * Horizontal offset for aligning gradients coming from SVG when outside pathgroups\n * @type Number\n * @default 0\n */\n offsetX: 0,\n\n /**\n * Vertical offset for aligning gradients coming from SVG when outside pathgroups\n * @type Number\n * @default 0\n */\n offsetY: 0,\n\n /**\n * A transform matrix to apply to the gradient before painting.\n * Imported from svg gradients, is not applied with the current transform in the center.\n * Before this transform is applied, the origin point is at the top left corner of the object\n * plus the addition of offsetY and offsetX.\n * @type Number[]\n * @default null\n */\n gradientTransform: null,\n\n /**\n * coordinates units for coords.\n * If `pixels`, the number of coords are in the same unit of width / height.\n * If set as `percentage` the coords are still a number, but 1 means 100% of width\n * for the X and 100% of the height for the y. It can be bigger than 1 and negative.\n * allowed values pixels or percentage.\n * @type String\n * @default 'pixels'\n */\n gradientUnits: 'pixels',\n\n /**\n * Gradient type linear or radial\n * @type String\n * @default 'pixels'\n */\n type: 'linear',\n\n /**\n * Constructor\n * @param {Object} options Options object with type, coords, gradientUnits and colorStops\n * @param {Object} [options.type] gradient type linear or radial\n * @param {Object} [options.gradientUnits] gradient units\n * @param {Object} [options.offsetX] SVG import compatibility\n * @param {Object} [options.offsetY] SVG import compatibility\n * @param {Object[]} options.colorStops contains the colorstops.\n * @param {Object} options.coords contains the coords of the gradient\n * @param {Number} [options.coords.x1] X coordiante of the first point for linear or of the focal point for radial\n * @param {Number} [options.coords.y1] Y coordiante of the first point for linear or of the focal point for radial\n * @param {Number} [options.coords.x2] X coordiante of the second point for linear or of the center point for radial\n * @param {Number} [options.coords.y2] Y coordiante of the second point for linear or of the center point for radial\n * @param {Number} [options.coords.r1] only for radial gradient, radius of the inner circle\n * @param {Number} [options.coords.r2] only for radial gradient, radius of the external circle\n * @return {fabric.Gradient} thisArg\n */\n initialize: function(options) {\n options || (options = { });\n options.coords || (options.coords = { });\n\n var coords, _this = this;\n\n // sets everything, then coords and colorstops get sets again\n Object.keys(options).forEach(function(option) {\n _this[option] = options[option];\n });\n\n if (this.id) {\n this.id += '_' + fabric.Object.__uid++;\n }\n else {\n this.id = fabric.Object.__uid++;\n }\n\n coords = {\n x1: options.coords.x1 || 0,\n y1: options.coords.y1 || 0,\n x2: options.coords.x2 || 0,\n y2: options.coords.y2 || 0\n };\n\n if (this.type === 'radial') {\n coords.r1 = options.coords.r1 || 0;\n coords.r2 = options.coords.r2 || 0;\n }\n\n this.coords = coords;\n this.colorStops = options.colorStops.slice();\n },\n\n /**\n * Adds another colorStop\n * @param {Object} colorStop Object with offset and color\n * @return {fabric.Gradient} thisArg\n */\n addColorStop: function(colorStops) {\n for (var position in colorStops) {\n var color = new fabric.Color(colorStops[position]);\n this.colorStops.push({\n offset: parseFloat(position),\n color: color.toRgb(),\n opacity: color.getAlpha()\n });\n }\n return this;\n },\n\n /**\n * Returns object representation of a gradient\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object}\n */\n toObject: function(propertiesToInclude) {\n var object = {\n type: this.type,\n coords: this.coords,\n colorStops: this.colorStops,\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n gradientUnits: this.gradientUnits,\n gradientTransform: this.gradientTransform ? this.gradientTransform.concat() : this.gradientTransform\n };\n fabric.util.populateWithProperties(this, object, propertiesToInclude);\n\n return object;\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of an gradient\n * @param {Object} object Object to create a gradient for\n * @return {String} SVG representation of an gradient (linear/radial)\n */\n toSVG: function(object, options) {\n var coords = clone(this.coords, true), i, len, options = options || {},\n markup, commonAttributes, colorStops = clone(this.colorStops, true),\n needsSwap = coords.r1 > coords.r2,\n transform = this.gradientTransform ? this.gradientTransform.concat() : fabric.iMatrix.concat(),\n offsetX = -this.offsetX, offsetY = -this.offsetY,\n withViewport = !!options.additionalTransform,\n gradientUnits = this.gradientUnits === 'pixels' ? 'userSpaceOnUse' : 'objectBoundingBox';\n // colorStops must be sorted ascending\n colorStops.sort(function(a, b) {\n return a.offset - b.offset;\n });\n\n if (gradientUnits === 'objectBoundingBox') {\n offsetX /= object.width;\n offsetY /= object.height;\n }\n else {\n offsetX += object.width / 2;\n offsetY += object.height / 2;\n }\n if (object.type === 'path' && this.gradientUnits !== 'percentage') {\n offsetX -= object.pathOffset.x;\n offsetY -= object.pathOffset.y;\n }\n\n\n transform[4] -= offsetX;\n transform[5] -= offsetY;\n\n commonAttributes = 'id=\"SVGID_' + this.id +\n '\" gradientUnits=\"' + gradientUnits + '\"';\n commonAttributes += ' gradientTransform=\"' + (withViewport ?\n options.additionalTransform + ' ' : '') + fabric.util.matrixToSVG(transform) + '\" ';\n\n if (this.type === 'linear') {\n markup = [\n '\\n'\n ];\n }\n else if (this.type === 'radial') {\n // svg radial gradient has just 1 radius. the biggest.\n markup = [\n '\\n'\n ];\n }\n\n if (this.type === 'radial') {\n if (needsSwap) {\n // svg goes from internal to external radius. if radius are inverted, swap color stops.\n colorStops = colorStops.concat();\n colorStops.reverse();\n for (i = 0, len = colorStops.length; i < len; i++) {\n colorStops[i].offset = 1 - colorStops[i].offset;\n }\n }\n var minRadius = Math.min(coords.r1, coords.r2);\n if (minRadius > 0) {\n // i have to shift all colorStops and add new one in 0.\n var maxRadius = Math.max(coords.r1, coords.r2),\n percentageShift = minRadius / maxRadius;\n for (i = 0, len = colorStops.length; i < len; i++) {\n colorStops[i].offset += percentageShift * (1 - colorStops[i].offset);\n }\n }\n }\n\n for (i = 0, len = colorStops.length; i < len; i++) {\n var colorStop = colorStops[i];\n markup.push(\n '\\n'\n );\n }\n\n markup.push((this.type === 'linear' ? '\\n' : '\\n'));\n\n return markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns an instance of CanvasGradient\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @return {CanvasGradient}\n */\n toLive: function(ctx) {\n var gradient, coords = fabric.util.object.clone(this.coords), i, len;\n\n if (!this.type) {\n return;\n }\n\n if (this.type === 'linear') {\n gradient = ctx.createLinearGradient(\n coords.x1, coords.y1, coords.x2, coords.y2);\n }\n else if (this.type === 'radial') {\n gradient = ctx.createRadialGradient(\n coords.x1, coords.y1, coords.r1, coords.x2, coords.y2, coords.r2);\n }\n\n for (i = 0, len = this.colorStops.length; i < len; i++) {\n var color = this.colorStops[i].color,\n opacity = this.colorStops[i].opacity,\n offset = this.colorStops[i].offset;\n\n if (typeof opacity !== 'undefined') {\n color = new fabric.Color(color).setAlpha(opacity).toRgba();\n }\n gradient.addColorStop(offset, color);\n }\n\n return gradient;\n }\n });\n\n fabric.util.object.extend(fabric.Gradient, {\n\n /* _FROM_SVG_START_ */\n /**\n * Returns {@link fabric.Gradient} instance from an SVG element\n * @static\n * @memberOf fabric.Gradient\n * @param {SVGGradientElement} el SVG gradient element\n * @param {fabric.Object} instance\n * @param {String} opacityAttr A fill-opacity or stroke-opacity attribute to multiply to each stop's opacity.\n * @param {Object} svgOptions an object containing the size of the SVG in order to parse correctly gradients\n * that uses gradientUnits as 'userSpaceOnUse' and percentages.\n * @param {Object.number} viewBoxWidth width part of the viewBox attribute on svg\n * @param {Object.number} viewBoxHeight height part of the viewBox attribute on svg\n * @param {Object.number} width width part of the svg tag if viewBox is not specified\n * @param {Object.number} height height part of the svg tag if viewBox is not specified\n * @return {fabric.Gradient} Gradient instance\n * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement\n * @see http://www.w3.org/TR/SVG/pservers.html#RadialGradientElement\n */\n fromElement: function(el, instance, opacityAttr, svgOptions) {\n /**\n * @example:\n *\n * \n * \n * \n * \n *\n * OR\n *\n * \n * \n * \n * \n *\n * OR\n *\n * \n * \n * \n * \n * \n *\n * OR\n *\n * \n * \n * \n * \n * \n *\n */\n\n var multiplier = parseFloat(opacityAttr) / (/%$/.test(opacityAttr) ? 100 : 1);\n multiplier = multiplier < 0 ? 0 : multiplier > 1 ? 1 : multiplier;\n if (isNaN(multiplier)) {\n multiplier = 1;\n }\n\n var colorStopEls = el.getElementsByTagName('stop'),\n type,\n gradientUnits = el.getAttribute('gradientUnits') === 'userSpaceOnUse' ?\n 'pixels' : 'percentage',\n gradientTransform = el.getAttribute('gradientTransform') || '',\n colorStops = [],\n coords, i, offsetX = 0, offsetY = 0,\n transformMatrix;\n if (el.nodeName === 'linearGradient' || el.nodeName === 'LINEARGRADIENT') {\n type = 'linear';\n coords = getLinearCoords(el);\n }\n else {\n type = 'radial';\n coords = getRadialCoords(el);\n }\n\n for (i = colorStopEls.length; i--; ) {\n colorStops.push(getColorStop(colorStopEls[i], multiplier));\n }\n\n transformMatrix = fabric.parseTransformAttribute(gradientTransform);\n\n __convertPercentUnitsToValues(instance, coords, svgOptions, gradientUnits);\n\n if (gradientUnits === 'pixels') {\n offsetX = -instance.left;\n offsetY = -instance.top;\n }\n\n var gradient = new fabric.Gradient({\n id: el.getAttribute('id'),\n type: type,\n coords: coords,\n colorStops: colorStops,\n gradientUnits: gradientUnits,\n gradientTransform: transformMatrix,\n offsetX: offsetX,\n offsetY: offsetY,\n });\n\n return gradient;\n }\n /* _FROM_SVG_END_ */\n });\n\n /**\n * @private\n */\n function __convertPercentUnitsToValues(instance, options, svgOptions, gradientUnits) {\n var propValue, finalValue;\n Object.keys(options).forEach(function(prop) {\n propValue = options[prop];\n if (propValue === 'Infinity') {\n finalValue = 1;\n }\n else if (propValue === '-Infinity') {\n finalValue = 0;\n }\n else {\n finalValue = parseFloat(options[prop], 10);\n if (typeof propValue === 'string' && /^(\\d+\\.\\d+)%|(\\d+)%$/.test(propValue)) {\n finalValue *= 0.01;\n if (gradientUnits === 'pixels') {\n // then we need to fix those percentages here in svg parsing\n if (prop === 'x1' || prop === 'x2' || prop === 'r2') {\n finalValue *= svgOptions.viewBoxWidth || svgOptions.width;\n }\n if (prop === 'y1' || prop === 'y2') {\n finalValue *= svgOptions.viewBoxHeight || svgOptions.height;\n }\n }\n }\n }\n options[prop] = finalValue;\n });\n }\n})();\n\n\n(function() {\n\n 'use strict';\n\n var toFixed = fabric.util.toFixed;\n\n /**\n * Pattern class\n * @class fabric.Pattern\n * @see {@link http://fabricjs.com/patterns|Pattern demo}\n * @see {@link http://fabricjs.com/dynamic-patterns|DynamicPattern demo}\n * @see {@link fabric.Pattern#initialize} for constructor definition\n */\n\n\n fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ {\n\n /**\n * Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat)\n * @type String\n * @default\n */\n repeat: 'repeat',\n\n /**\n * Pattern horizontal offset from object's left/top corner\n * @type Number\n * @default\n */\n offsetX: 0,\n\n /**\n * Pattern vertical offset from object's left/top corner\n * @type Number\n * @default\n */\n offsetY: 0,\n\n /**\n * crossOrigin value (one of \"\", \"anonymous\", \"use-credentials\")\n * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes\n * @type String\n * @default\n */\n crossOrigin: '',\n\n /**\n * transform matrix to change the pattern, imported from svgs.\n * @type Array\n * @default\n */\n patternTransform: null,\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n * @param {Function} [callback] function to invoke after callback init.\n * @return {fabric.Pattern} thisArg\n */\n initialize: function(options, callback) {\n options || (options = { });\n\n this.id = fabric.Object.__uid++;\n this.setOptions(options);\n if (!options.source || (options.source && typeof options.source !== 'string')) {\n callback && callback(this);\n return;\n }\n else {\n // img src string\n var _this = this;\n this.source = fabric.util.createImage();\n fabric.util.loadImage(options.source, function(img, isError) {\n _this.source = img;\n callback && callback(_this, isError);\n }, null, this.crossOrigin);\n }\n },\n\n /**\n * Returns object representation of a pattern\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of a pattern instance\n */\n toObject: function(propertiesToInclude) {\n var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n source, object;\n\n // element\n if (typeof this.source.src === 'string') {\n source = this.source.src;\n }\n // element\n else if (typeof this.source === 'object' && this.source.toDataURL) {\n source = this.source.toDataURL();\n }\n\n object = {\n type: 'pattern',\n source: source,\n repeat: this.repeat,\n crossOrigin: this.crossOrigin,\n offsetX: toFixed(this.offsetX, NUM_FRACTION_DIGITS),\n offsetY: toFixed(this.offsetY, NUM_FRACTION_DIGITS),\n patternTransform: this.patternTransform ? this.patternTransform.concat() : null\n };\n fabric.util.populateWithProperties(this, object, propertiesToInclude);\n\n return object;\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of a pattern\n * @param {fabric.Object} object\n * @return {String} SVG representation of a pattern\n */\n toSVG: function(object) {\n var patternSource = typeof this.source === 'function' ? this.source() : this.source,\n patternWidth = patternSource.width / object.width,\n patternHeight = patternSource.height / object.height,\n patternOffsetX = this.offsetX / object.width,\n patternOffsetY = this.offsetY / object.height,\n patternImgSrc = '';\n if (this.repeat === 'repeat-x' || this.repeat === 'no-repeat') {\n patternHeight = 1;\n if (patternOffsetY) {\n patternHeight += Math.abs(patternOffsetY);\n }\n }\n if (this.repeat === 'repeat-y' || this.repeat === 'no-repeat') {\n patternWidth = 1;\n if (patternOffsetX) {\n patternWidth += Math.abs(patternOffsetX);\n }\n\n }\n if (patternSource.src) {\n patternImgSrc = patternSource.src;\n }\n else if (patternSource.toDataURL) {\n patternImgSrc = patternSource.toDataURL();\n }\n\n return '\\n' +\n '\\n' +\n '\\n';\n },\n /* _TO_SVG_END_ */\n\n setOptions: function(options) {\n for (var prop in options) {\n this[prop] = options[prop];\n }\n },\n\n /**\n * Returns an instance of CanvasPattern\n * @param {CanvasRenderingContext2D} ctx Context to create pattern\n * @return {CanvasPattern}\n */\n toLive: function(ctx) {\n var source = this.source;\n // if the image failed to load, return, and allow rest to continue loading\n if (!source) {\n return '';\n }\n\n // if an image\n if (typeof source.src !== 'undefined') {\n if (!source.complete) {\n return '';\n }\n if (source.naturalWidth === 0 || source.naturalHeight === 0) {\n return '';\n }\n }\n return ctx.createPattern(source, this.repeat);\n }\n });\n})();\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n toFixed = fabric.util.toFixed;\n\n if (fabric.Shadow) {\n fabric.warn('fabric.Shadow is already defined.');\n return;\n }\n\n /**\n * Shadow class\n * @class fabric.Shadow\n * @see {@link http://fabricjs.com/shadows|Shadow demo}\n * @see {@link fabric.Shadow#initialize} for constructor definition\n */\n fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ {\n\n /**\n * Shadow color\n * @type String\n * @default\n */\n color: 'rgb(0,0,0)',\n\n /**\n * Shadow blur\n * @type Number\n */\n blur: 0,\n\n /**\n * Shadow horizontal offset\n * @type Number\n * @default\n */\n offsetX: 0,\n\n /**\n * Shadow vertical offset\n * @type Number\n * @default\n */\n offsetY: 0,\n\n /**\n * Whether the shadow should affect stroke operations\n * @type Boolean\n * @default\n */\n affectStroke: false,\n\n /**\n * Indicates whether toObject should include default values\n * @type Boolean\n * @default\n */\n includeDefaultValues: true,\n\n /**\n * When `false`, the shadow will scale with the object.\n * When `true`, the shadow's offsetX, offsetY, and blur will not be affected by the object's scale.\n * default to false\n * @type Boolean\n * @default\n */\n nonScaling: false,\n\n /**\n * Constructor\n * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetY properties or string (e.g. \"rgba(0,0,0,0.2) 2px 2px 10px\")\n * @return {fabric.Shadow} thisArg\n */\n initialize: function(options) {\n\n if (typeof options === 'string') {\n options = this._parseShadow(options);\n }\n\n for (var prop in options) {\n this[prop] = options[prop];\n }\n\n this.id = fabric.Object.__uid++;\n },\n\n /**\n * @private\n * @param {String} shadow Shadow value to parse\n * @return {Object} Shadow object with color, offsetX, offsetY and blur\n */\n _parseShadow: function(shadow) {\n var shadowStr = shadow.trim(),\n offsetsAndBlur = fabric.Shadow.reOffsetsAndBlur.exec(shadowStr) || [],\n color = shadowStr.replace(fabric.Shadow.reOffsetsAndBlur, '') || 'rgb(0,0,0)';\n\n return {\n color: color.trim(),\n offsetX: parseFloat(offsetsAndBlur[1], 10) || 0,\n offsetY: parseFloat(offsetsAndBlur[2], 10) || 0,\n blur: parseFloat(offsetsAndBlur[3], 10) || 0\n };\n },\n\n /**\n * Returns a string representation of an instance\n * @see http://www.w3.org/TR/css-text-decor-3/#text-shadow\n * @return {String} Returns CSS3 text-shadow declaration\n */\n toString: function() {\n return [this.offsetX, this.offsetY, this.blur, this.color].join('px ');\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of a shadow\n * @param {fabric.Object} object\n * @return {String} SVG representation of a shadow\n */\n toSVG: function(object) {\n var fBoxX = 40, fBoxY = 40, NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n offset = fabric.util.rotateVector(\n { x: this.offsetX, y: this.offsetY },\n fabric.util.degreesToRadians(-object.angle)),\n BLUR_BOX = 20, color = new fabric.Color(this.color);\n\n if (object.width && object.height) {\n //http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion\n // we add some extra space to filter box to contain the blur ( 20 )\n fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;\n fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;\n }\n if (object.flipX) {\n offset.x *= -1;\n }\n if (object.flipY) {\n offset.y *= -1;\n }\n\n return (\n '\\n' +\n '\\t\\n' +\n '\\t\\n' +\n '\\t\\n' +\n '\\t\\n' +\n '\\t\\n' +\n '\\t\\t\\n' +\n '\\t\\t\\n' +\n '\\t\\n' +\n '\\n');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns object representation of a shadow\n * @return {Object} Object representation of a shadow instance\n */\n toObject: function() {\n if (this.includeDefaultValues) {\n return {\n color: this.color,\n blur: this.blur,\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n affectStroke: this.affectStroke,\n nonScaling: this.nonScaling\n };\n }\n var obj = { }, proto = fabric.Shadow.prototype;\n\n ['color', 'blur', 'offsetX', 'offsetY', 'affectStroke', 'nonScaling'].forEach(function(prop) {\n if (this[prop] !== proto[prop]) {\n obj[prop] = this[prop];\n }\n }, this);\n\n return obj;\n }\n });\n\n /**\n * Regex matching shadow offsetX, offsetY and blur (ex: \"2px 2px 10px rgba(0,0,0,0.2)\", \"rgb(0,255,0) 2px 2px\")\n * @static\n * @field\n * @memberOf fabric.Shadow\n */\n // eslint-disable-next-line max-len\n fabric.Shadow.reOffsetsAndBlur = /(?:\\s|^)(-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?(-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?(\\d+(?:\\.\\d*)?(?:px)?)?(?:\\s?|$)(?:$|\\s)/;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function () {\n\n 'use strict';\n\n if (fabric.StaticCanvas) {\n fabric.warn('fabric.StaticCanvas is already defined.');\n return;\n }\n\n // aliases for faster resolution\n var extend = fabric.util.object.extend,\n getElementOffset = fabric.util.getElementOffset,\n removeFromArray = fabric.util.removeFromArray,\n toFixed = fabric.util.toFixed,\n transformPoint = fabric.util.transformPoint,\n invertTransform = fabric.util.invertTransform,\n getNodeCanvas = fabric.util.getNodeCanvas,\n createCanvasElement = fabric.util.createCanvasElement,\n\n CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element');\n\n /**\n * Static canvas class\n * @class fabric.StaticCanvas\n * @mixes fabric.Collection\n * @mixes fabric.Observable\n * @see {@link http://fabricjs.com/static_canvas|StaticCanvas demo}\n * @see {@link fabric.StaticCanvas#initialize} for constructor definition\n * @fires before:render\n * @fires after:render\n * @fires canvas:cleared\n * @fires object:added\n * @fires object:removed\n */\n fabric.StaticCanvas = fabric.util.createClass(fabric.CommonMethods, /** @lends fabric.StaticCanvas.prototype */ {\n\n /**\n * Constructor\n * @param {HTMLElement | String} el <canvas> element to initialize instance on\n * @param {Object} [options] Options object\n * @return {Object} thisArg\n */\n initialize: function(el, options) {\n options || (options = { });\n this.renderAndResetBound = this.renderAndReset.bind(this);\n this.requestRenderAllBound = this.requestRenderAll.bind(this);\n this._initStatic(el, options);\n },\n\n /**\n * Background color of canvas instance.\n * Should be set via {@link fabric.StaticCanvas#setBackgroundColor}.\n * @type {(String|fabric.Pattern)}\n * @default\n */\n backgroundColor: '',\n\n /**\n * Background image of canvas instance.\n * since 2.4.0 image caching is active, please when putting an image as background, add to the\n * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom\n * vale. As an alternative you can disable image objectCaching\n * @type fabric.Image\n * @default\n */\n backgroundImage: null,\n\n /**\n * Overlay color of canvas instance.\n * Should be set via {@link fabric.StaticCanvas#setOverlayColor}\n * @since 1.3.9\n * @type {(String|fabric.Pattern)}\n * @default\n */\n overlayColor: '',\n\n /**\n * Overlay image of canvas instance.\n * since 2.4.0 image caching is active, please when putting an image as overlay, add to the\n * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom\n * vale. As an alternative you can disable image objectCaching\n * @type fabric.Image\n * @default\n */\n overlayImage: null,\n\n /**\n * Indicates whether toObject/toDatalessObject should include default values\n * if set to false, takes precedence over the object value.\n * @type Boolean\n * @default\n */\n includeDefaultValues: true,\n\n /**\n * Indicates whether objects' state should be saved\n * @type Boolean\n * @default\n */\n stateful: false,\n\n /**\n * Indicates whether {@link fabric.Collection.add}, {@link fabric.Collection.insertAt} and {@link fabric.Collection.remove},\n * {@link fabric.StaticCanvas.moveTo}, {@link fabric.StaticCanvas.clear} and many more, should also re-render canvas.\n * Disabling this option will not give a performance boost when adding/removing a lot of objects to/from canvas at once\n * since the renders are quequed and executed one per frame.\n * Disabling is suggested anyway and managing the renders of the app manually is not a big effort ( canvas.requestRenderAll() )\n * Left default to true to do not break documentation and old app, fiddles.\n * @type Boolean\n * @default\n */\n renderOnAddRemove: true,\n\n /**\n * Indicates whether object controls (borders/controls) are rendered above overlay image\n * @type Boolean\n * @default\n */\n controlsAboveOverlay: false,\n\n /**\n * Indicates whether the browser can be scrolled when using a touchscreen and dragging on the canvas\n * @type Boolean\n * @default\n */\n allowTouchScrolling: false,\n\n /**\n * Indicates whether this canvas will use image smoothing, this is on by default in browsers\n * @type Boolean\n * @default\n */\n imageSmoothingEnabled: true,\n\n /**\n * The transformation (a Canvas 2D API transform matrix) which focuses the viewport\n * @type Array\n * @example Default transform\n * canvas.viewportTransform = [1, 0, 0, 1, 0, 0];\n * @example Scale by 70% and translate toward bottom-right by 50, without skewing\n * canvas.viewportTransform = [0.7, 0, 0, 0.7, 50, 50];\n * @default\n */\n viewportTransform: fabric.iMatrix.concat(),\n\n /**\n * if set to false background image is not affected by viewport transform\n * @since 1.6.3\n * @type Boolean\n * @default\n */\n backgroundVpt: true,\n\n /**\n * if set to false overlya image is not affected by viewport transform\n * @since 1.6.3\n * @type Boolean\n * @default\n */\n overlayVpt: true,\n\n /**\n * When true, canvas is scaled by devicePixelRatio for better rendering on retina screens\n * @type Boolean\n * @default\n */\n enableRetinaScaling: true,\n\n /**\n * Describe canvas element extension over design\n * properties are tl,tr,bl,br.\n * if canvas is not zoomed/panned those points are the four corner of canvas\n * if canvas is viewportTransformed you those points indicate the extension\n * of canvas element in plain untrasformed coordinates\n * The coordinates get updated with @method calcViewportBoundaries.\n * @memberOf fabric.StaticCanvas.prototype\n */\n vptCoords: { },\n\n /**\n * Based on vptCoords and object.aCoords, skip rendering of objects that\n * are not included in current viewport.\n * May greatly help in applications with crowded canvas and use of zoom/pan\n * If One of the corner of the bounding box of the object is on the canvas\n * the objects get rendered.\n * @memberOf fabric.StaticCanvas.prototype\n * @type Boolean\n * @default\n */\n skipOffscreen: true,\n\n /**\n * a fabricObject that, without stroke define a clipping area with their shape. filled in black\n * the clipPath object gets used when the canvas has rendered, and the context is placed in the\n * top left corner of the canvas.\n * clipPath will clip away controls, if you do not want this to happen use controlsAboveOverlay = true\n * @type fabric.Object\n */\n clipPath: undefined,\n\n /**\n * @private\n * @param {HTMLElement | String} el <canvas> element to initialize instance on\n * @param {Object} [options] Options object\n */\n _initStatic: function(el, options) {\n var cb = this.requestRenderAllBound;\n this._objects = [];\n this._createLowerCanvas(el);\n this._initOptions(options);\n // only initialize retina scaling once\n if (!this.interactive) {\n this._initRetinaScaling();\n }\n\n if (options.overlayImage) {\n this.setOverlayImage(options.overlayImage, cb);\n }\n if (options.backgroundImage) {\n this.setBackgroundImage(options.backgroundImage, cb);\n }\n if (options.backgroundColor) {\n this.setBackgroundColor(options.backgroundColor, cb);\n }\n if (options.overlayColor) {\n this.setOverlayColor(options.overlayColor, cb);\n }\n this.calcOffset();\n },\n\n /**\n * @private\n */\n _isRetinaScaling: function() {\n return (fabric.devicePixelRatio > 1 && this.enableRetinaScaling);\n },\n\n /**\n * @private\n * @return {Number} retinaScaling if applied, otherwise 1;\n */\n getRetinaScaling: function() {\n return this._isRetinaScaling() ? Math.max(1, fabric.devicePixelRatio) : 1;\n },\n\n /**\n * @private\n */\n _initRetinaScaling: function() {\n if (!this._isRetinaScaling()) {\n return;\n }\n var scaleRatio = fabric.devicePixelRatio;\n this.__initRetinaScaling(scaleRatio, this.lowerCanvasEl, this.contextContainer);\n if (this.upperCanvasEl) {\n this.__initRetinaScaling(scaleRatio, this.upperCanvasEl, this.contextTop);\n }\n },\n\n __initRetinaScaling: function(scaleRatio, canvas, context) {\n canvas.setAttribute('width', this.width * scaleRatio);\n canvas.setAttribute('height', this.height * scaleRatio);\n context.scale(scaleRatio, scaleRatio);\n },\n\n\n /**\n * Calculates canvas element offset relative to the document\n * This method is also attached as \"resize\" event handler of window\n * @return {fabric.Canvas} instance\n * @chainable\n */\n calcOffset: function () {\n this._offset = getElementOffset(this.lowerCanvasEl);\n return this;\n },\n\n /**\n * Sets {@link fabric.StaticCanvas#overlayImage|overlay image} for this canvas\n * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set overlay to\n * @param {Function} callback callback to invoke when image is loaded and set as an overlay\n * @param {Object} [options] Optional options to set for the {@link fabric.Image|overlay image}.\n * @return {fabric.Canvas} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/MnzHT/|jsFiddle demo}\n * @example Normal overlayImage with left/top = 0\n * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n * // Needed to position overlayImage at 0/0\n * originX: 'left',\n * originY: 'top'\n * });\n * @example overlayImage with different properties\n * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n * opacity: 0.5,\n * angle: 45,\n * left: 400,\n * top: 400,\n * originX: 'left',\n * originY: 'top'\n * });\n * @example Stretched overlayImage #1 - width/height correspond to canvas width/height\n * fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img, isError) {\n * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'});\n * canvas.setOverlayImage(img, canvas.renderAll.bind(canvas));\n * });\n * @example Stretched overlayImage #2 - width/height correspond to canvas width/height\n * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n * width: canvas.width,\n * height: canvas.height,\n * // Needed to position overlayImage at 0/0\n * originX: 'left',\n * originY: 'top'\n * });\n * @example overlayImage loaded from cross-origin\n * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n * opacity: 0.5,\n * angle: 45,\n * left: 400,\n * top: 400,\n * originX: 'left',\n * originY: 'top',\n * crossOrigin: 'anonymous'\n * });\n */\n setOverlayImage: function (image, callback, options) {\n return this.__setBgOverlayImage('overlayImage', image, callback, options);\n },\n\n /**\n * Sets {@link fabric.StaticCanvas#backgroundImage|background image} for this canvas\n * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set background to\n * @param {Function} callback Callback to invoke when image is loaded and set as background\n * @param {Object} [options] Optional options to set for the {@link fabric.Image|background image}.\n * @return {fabric.Canvas} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/djnr8o7a/28/|jsFiddle demo}\n * @example Normal backgroundImage with left/top = 0\n * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n * // Needed to position backgroundImage at 0/0\n * originX: 'left',\n * originY: 'top'\n * });\n * @example backgroundImage with different properties\n * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n * opacity: 0.5,\n * angle: 45,\n * left: 400,\n * top: 400,\n * originX: 'left',\n * originY: 'top'\n * });\n * @example Stretched backgroundImage #1 - width/height correspond to canvas width/height\n * fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img, isError) {\n * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'});\n * canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas));\n * });\n * @example Stretched backgroundImage #2 - width/height correspond to canvas width/height\n * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n * width: canvas.width,\n * height: canvas.height,\n * // Needed to position backgroundImage at 0/0\n * originX: 'left',\n * originY: 'top'\n * });\n * @example backgroundImage loaded from cross-origin\n * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n * opacity: 0.5,\n * angle: 45,\n * left: 400,\n * top: 400,\n * originX: 'left',\n * originY: 'top',\n * crossOrigin: 'anonymous'\n * });\n */\n // TODO: fix stretched examples\n setBackgroundImage: function (image, callback, options) {\n return this.__setBgOverlayImage('backgroundImage', image, callback, options);\n },\n\n /**\n * Sets {@link fabric.StaticCanvas#overlayColor|foreground color} for this canvas\n * @param {(String|fabric.Pattern)} overlayColor Color or pattern to set foreground color to\n * @param {Function} callback Callback to invoke when foreground color is set\n * @return {fabric.Canvas} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/pB55h/|jsFiddle demo}\n * @example Normal overlayColor - color value\n * canvas.setOverlayColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));\n * @example fabric.Pattern used as overlayColor\n * canvas.setOverlayColor({\n * source: 'http://fabricjs.com/assets/escheresque_ste.png'\n * }, canvas.renderAll.bind(canvas));\n * @example fabric.Pattern used as overlayColor with repeat and offset\n * canvas.setOverlayColor({\n * source: 'http://fabricjs.com/assets/escheresque_ste.png',\n * repeat: 'repeat',\n * offsetX: 200,\n * offsetY: 100\n * }, canvas.renderAll.bind(canvas));\n */\n setOverlayColor: function(overlayColor, callback) {\n return this.__setBgOverlayColor('overlayColor', overlayColor, callback);\n },\n\n /**\n * Sets {@link fabric.StaticCanvas#backgroundColor|background color} for this canvas\n * @param {(String|fabric.Pattern)} backgroundColor Color or pattern to set background color to\n * @param {Function} callback Callback to invoke when background color is set\n * @return {fabric.Canvas} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/hXzvk/|jsFiddle demo}\n * @example Normal backgroundColor - color value\n * canvas.setBackgroundColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));\n * @example fabric.Pattern used as backgroundColor\n * canvas.setBackgroundColor({\n * source: 'http://fabricjs.com/assets/escheresque_ste.png'\n * }, canvas.renderAll.bind(canvas));\n * @example fabric.Pattern used as backgroundColor with repeat and offset\n * canvas.setBackgroundColor({\n * source: 'http://fabricjs.com/assets/escheresque_ste.png',\n * repeat: 'repeat',\n * offsetX: 200,\n * offsetY: 100\n * }, canvas.renderAll.bind(canvas));\n */\n setBackgroundColor: function(backgroundColor, callback) {\n return this.__setBgOverlayColor('backgroundColor', backgroundColor, callback);\n },\n\n /**\n * @private\n * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundImage|backgroundImage}\n * or {@link fabric.StaticCanvas#overlayImage|overlayImage})\n * @param {(fabric.Image|String|null)} image fabric.Image instance, URL of an image or null to set background or overlay to\n * @param {Function} callback Callback to invoke when image is loaded and set as background or overlay. The first argument is the created image, the second argument is a flag indicating whether an error occurred or not.\n * @param {Object} [options] Optional options to set for the {@link fabric.Image|image}.\n */\n __setBgOverlayImage: function(property, image, callback, options) {\n if (typeof image === 'string') {\n fabric.util.loadImage(image, function(img, isError) {\n if (img) {\n var instance = new fabric.Image(img, options);\n this[property] = instance;\n instance.canvas = this;\n }\n callback && callback(img, isError);\n }, this, options && options.crossOrigin);\n }\n else {\n options && image.setOptions(options);\n this[property] = image;\n image && (image.canvas = this);\n callback && callback(image, false);\n }\n\n return this;\n },\n\n /**\n * @private\n * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundColor|backgroundColor}\n * or {@link fabric.StaticCanvas#overlayColor|overlayColor})\n * @param {(Object|String|null)} color Object with pattern information, color value or null\n * @param {Function} [callback] Callback is invoked when color is set\n */\n __setBgOverlayColor: function(property, color, callback) {\n this[property] = color;\n this._initGradient(color, property);\n this._initPattern(color, property, callback);\n return this;\n },\n\n /**\n * @private\n */\n _createCanvasElement: function() {\n var element = createCanvasElement();\n if (!element) {\n throw CANVAS_INIT_ERROR;\n }\n if (!element.style) {\n element.style = { };\n }\n if (typeof element.getContext === 'undefined') {\n throw CANVAS_INIT_ERROR;\n }\n return element;\n },\n\n /**\n * @private\n * @param {Object} [options] Options object\n */\n _initOptions: function (options) {\n var lowerCanvasEl = this.lowerCanvasEl;\n this._setOptions(options);\n\n this.width = this.width || parseInt(lowerCanvasEl.width, 10) || 0;\n this.height = this.height || parseInt(lowerCanvasEl.height, 10) || 0;\n\n if (!this.lowerCanvasEl.style) {\n return;\n }\n\n lowerCanvasEl.width = this.width;\n lowerCanvasEl.height = this.height;\n\n lowerCanvasEl.style.width = this.width + 'px';\n lowerCanvasEl.style.height = this.height + 'px';\n\n this.viewportTransform = this.viewportTransform.slice();\n },\n\n /**\n * Creates a bottom canvas\n * @private\n * @param {HTMLElement} [canvasEl]\n */\n _createLowerCanvas: function (canvasEl) {\n // canvasEl === 'HTMLCanvasElement' does not work on jsdom/node\n if (canvasEl && canvasEl.getContext) {\n this.lowerCanvasEl = canvasEl;\n }\n else {\n this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement();\n }\n\n fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas');\n this._originalCanvasStyle = this.lowerCanvasEl.style;\n if (this.interactive) {\n this._applyCanvasStyle(this.lowerCanvasEl);\n }\n\n this.contextContainer = this.lowerCanvasEl.getContext('2d');\n },\n\n /**\n * Returns canvas width (in px)\n * @return {Number}\n */\n getWidth: function () {\n return this.width;\n },\n\n /**\n * Returns canvas height (in px)\n * @return {Number}\n */\n getHeight: function () {\n return this.height;\n },\n\n /**\n * Sets width of this canvas instance\n * @param {Number|String} value Value to set width to\n * @param {Object} [options] Options object\n * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n setWidth: function (value, options) {\n return this.setDimensions({ width: value }, options);\n },\n\n /**\n * Sets height of this canvas instance\n * @param {Number|String} value Value to set height to\n * @param {Object} [options] Options object\n * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n setHeight: function (value, options) {\n return this.setDimensions({ height: value }, options);\n },\n\n /**\n * Sets dimensions (width, height) of this canvas instance. when options.cssOnly flag active you should also supply the unit of measure (px/%/em)\n * @param {Object} dimensions Object with width/height properties\n * @param {Number|String} [dimensions.width] Width of canvas element\n * @param {Number|String} [dimensions.height] Height of canvas element\n * @param {Object} [options] Options object\n * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n setDimensions: function (dimensions, options) {\n var cssValue;\n\n options = options || {};\n\n for (var prop in dimensions) {\n cssValue = dimensions[prop];\n\n if (!options.cssOnly) {\n this._setBackstoreDimension(prop, dimensions[prop]);\n cssValue += 'px';\n this.hasLostContext = true;\n }\n\n if (!options.backstoreOnly) {\n this._setCssDimension(prop, cssValue);\n }\n }\n if (this._isCurrentlyDrawing) {\n this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles(this.contextTop);\n }\n this._initRetinaScaling();\n this.calcOffset();\n\n if (!options.cssOnly) {\n this.requestRenderAll();\n }\n\n return this;\n },\n\n /**\n * Helper for setting width/height\n * @private\n * @param {String} prop property (width|height)\n * @param {Number} value value to set property to\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n _setBackstoreDimension: function (prop, value) {\n this.lowerCanvasEl[prop] = value;\n\n if (this.upperCanvasEl) {\n this.upperCanvasEl[prop] = value;\n }\n\n if (this.cacheCanvasEl) {\n this.cacheCanvasEl[prop] = value;\n }\n\n this[prop] = value;\n\n return this;\n },\n\n /**\n * Helper for setting css width/height\n * @private\n * @param {String} prop property (width|height)\n * @param {String} value value to set property to\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n _setCssDimension: function (prop, value) {\n this.lowerCanvasEl.style[prop] = value;\n\n if (this.upperCanvasEl) {\n this.upperCanvasEl.style[prop] = value;\n }\n\n if (this.wrapperEl) {\n this.wrapperEl.style[prop] = value;\n }\n\n return this;\n },\n\n /**\n * Returns canvas zoom level\n * @return {Number}\n */\n getZoom: function () {\n return this.viewportTransform[0];\n },\n\n /**\n * Sets viewport transformation of this canvas instance\n * @param {Array} vpt a Canvas 2D API transform matrix\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n setViewportTransform: function (vpt) {\n var activeObject = this._activeObject,\n backgroundObject = this.backgroundImage,\n overlayObject = this.overlayImage,\n object, i, len;\n this.viewportTransform = vpt;\n for (i = 0, len = this._objects.length; i < len; i++) {\n object = this._objects[i];\n object.group || object.setCoords(true);\n }\n if (activeObject) {\n activeObject.setCoords();\n }\n if (backgroundObject) {\n backgroundObject.setCoords(true);\n }\n if (overlayObject) {\n overlayObject.setCoords(true);\n }\n this.calcViewportBoundaries();\n this.renderOnAddRemove && this.requestRenderAll();\n return this;\n },\n\n /**\n * Sets zoom level of this canvas instance, the zoom centered around point\n * meaning that following zoom to point with the same point will have the visual\n * effect of the zoom originating from that point. The point won't move.\n * It has nothing to do with canvas center or visual center of the viewport.\n * @param {fabric.Point} point to zoom with respect to\n * @param {Number} value to set zoom to, less than 1 zooms out\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n zoomToPoint: function (point, value) {\n // TODO: just change the scale, preserve other transformations\n var before = point, vpt = this.viewportTransform.slice(0);\n point = transformPoint(point, invertTransform(this.viewportTransform));\n vpt[0] = value;\n vpt[3] = value;\n var after = transformPoint(point, vpt);\n vpt[4] += before.x - after.x;\n vpt[5] += before.y - after.y;\n return this.setViewportTransform(vpt);\n },\n\n /**\n * Sets zoom level of this canvas instance\n * @param {Number} value to set zoom to, less than 1 zooms out\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n setZoom: function (value) {\n this.zoomToPoint(new fabric.Point(0, 0), value);\n return this;\n },\n\n /**\n * Pan viewport so as to place point at top left corner of canvas\n * @param {fabric.Point} point to move to\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n absolutePan: function (point) {\n var vpt = this.viewportTransform.slice(0);\n vpt[4] = -point.x;\n vpt[5] = -point.y;\n return this.setViewportTransform(vpt);\n },\n\n /**\n * Pans viewpoint relatively\n * @param {fabric.Point} point (position vector) to move by\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n relativePan: function (point) {\n return this.absolutePan(new fabric.Point(\n -point.x - this.viewportTransform[4],\n -point.y - this.viewportTransform[5]\n ));\n },\n\n /**\n * Returns <canvas> element corresponding to this instance\n * @return {HTMLCanvasElement}\n */\n getElement: function () {\n return this.lowerCanvasEl;\n },\n\n /**\n * @private\n * @param {fabric.Object} obj Object that was added\n */\n _onObjectAdded: function(obj) {\n this.stateful && obj.setupState();\n obj._set('canvas', this);\n obj.setCoords();\n this.fire('object:added', { target: obj });\n obj.fire('added');\n },\n\n /**\n * @private\n * @param {fabric.Object} obj Object that was removed\n */\n _onObjectRemoved: function(obj) {\n this.fire('object:removed', { target: obj });\n obj.fire('removed');\n delete obj.canvas;\n },\n\n /**\n * Clears specified context of canvas element\n * @param {CanvasRenderingContext2D} ctx Context to clear\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n clearContext: function(ctx) {\n ctx.clearRect(0, 0, this.width, this.height);\n return this;\n },\n\n /**\n * Returns context of canvas where objects are drawn\n * @return {CanvasRenderingContext2D}\n */\n getContext: function () {\n return this.contextContainer;\n },\n\n /**\n * Clears all contexts (background, main, top) of an instance\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n clear: function () {\n this.remove.apply(this, this.getObjects());\n this.backgroundImage = null;\n this.overlayImage = null;\n this.backgroundColor = '';\n this.overlayColor = '';\n if (this._hasITextHandlers) {\n this.off('mouse:up', this._mouseUpITextHandler);\n this._iTextInstances = null;\n this._hasITextHandlers = false;\n }\n this.clearContext(this.contextContainer);\n this.fire('canvas:cleared');\n this.renderOnAddRemove && this.requestRenderAll();\n return this;\n },\n\n /**\n * Renders the canvas\n * @return {fabric.Canvas} instance\n * @chainable\n */\n renderAll: function () {\n var canvasToDrawOn = this.contextContainer;\n this.renderCanvas(canvasToDrawOn, this._objects);\n return this;\n },\n\n /**\n * Function created to be instance bound at initialization\n * used in requestAnimationFrame rendering\n * Let the fabricJS call it. If you call it manually you could have more\n * animationFrame stacking on to of each other\n * for an imperative rendering, use canvas.renderAll\n * @private\n * @return {fabric.Canvas} instance\n * @chainable\n */\n renderAndReset: function() {\n this.isRendering = 0;\n this.renderAll();\n },\n\n /**\n * Append a renderAll request to next animation frame.\n * unless one is already in progress, in that case nothing is done\n * a boolean flag will avoid appending more.\n * @return {fabric.Canvas} instance\n * @chainable\n */\n requestRenderAll: function () {\n if (!this.isRendering) {\n this.isRendering = fabric.util.requestAnimFrame(this.renderAndResetBound);\n }\n return this;\n },\n\n /**\n * Calculate the position of the 4 corner of canvas with current viewportTransform.\n * helps to determinate when an object is in the current rendering viewport using\n * object absolute coordinates ( aCoords )\n * @return {Object} points.tl\n * @chainable\n */\n calcViewportBoundaries: function() {\n var points = { }, width = this.width, height = this.height,\n iVpt = invertTransform(this.viewportTransform);\n points.tl = transformPoint({ x: 0, y: 0 }, iVpt);\n points.br = transformPoint({ x: width, y: height }, iVpt);\n points.tr = new fabric.Point(points.br.x, points.tl.y);\n points.bl = new fabric.Point(points.tl.x, points.br.y);\n this.vptCoords = points;\n return points;\n },\n\n cancelRequestedRender: function() {\n if (this.isRendering) {\n fabric.util.cancelAnimFrame(this.isRendering);\n this.isRendering = 0;\n }\n },\n\n /**\n * Renders background, objects, overlay and controls.\n * @param {CanvasRenderingContext2D} ctx\n * @param {Array} objects to render\n * @return {fabric.Canvas} instance\n * @chainable\n */\n renderCanvas: function(ctx, objects) {\n var v = this.viewportTransform, path = this.clipPath;\n this.cancelRequestedRender();\n this.calcViewportBoundaries();\n this.clearContext(ctx);\n fabric.util.setImageSmoothing(ctx, this.imageSmoothingEnabled);\n this.fire('before:render', { ctx: ctx, });\n this._renderBackground(ctx);\n\n ctx.save();\n //apply viewport transform once for all rendering process\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n this._renderObjects(ctx, objects);\n ctx.restore();\n if (!this.controlsAboveOverlay && this.interactive) {\n this.drawControls(ctx);\n }\n if (path) {\n path.canvas = this;\n // needed to setup a couple of variables\n path.shouldCache();\n path._transformDone = true;\n path.renderCache({ forClipping: true });\n this.drawClipPathOnCanvas(ctx);\n }\n this._renderOverlay(ctx);\n if (this.controlsAboveOverlay && this.interactive) {\n this.drawControls(ctx);\n }\n this.fire('after:render', { ctx: ctx, });\n },\n\n /**\n * Paint the cached clipPath on the lowerCanvasEl\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n drawClipPathOnCanvas: function(ctx) {\n var v = this.viewportTransform, path = this.clipPath;\n ctx.save();\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n // DEBUG: uncomment this line, comment the following\n // ctx.globalAlpha = 0.4;\n ctx.globalCompositeOperation = 'destination-in';\n path.transform(ctx);\n ctx.scale(1 / path.zoomX, 1 / path.zoomY);\n ctx.drawImage(path._cacheCanvas, -path.cacheTranslationX, -path.cacheTranslationY);\n ctx.restore();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Array} objects to render\n */\n _renderObjects: function(ctx, objects) {\n var i, len;\n for (i = 0, len = objects.length; i < len; ++i) {\n objects[i] && objects[i].render(ctx);\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {string} property 'background' or 'overlay'\n */\n _renderBackgroundOrOverlay: function(ctx, property) {\n var fill = this[property + 'Color'], object = this[property + 'Image'],\n v = this.viewportTransform, needsVpt = this[property + 'Vpt'];\n if (!fill && !object) {\n return;\n }\n if (fill) {\n ctx.save();\n ctx.beginPath();\n ctx.moveTo(0, 0);\n ctx.lineTo(this.width, 0);\n ctx.lineTo(this.width, this.height);\n ctx.lineTo(0, this.height);\n ctx.closePath();\n ctx.fillStyle = fill.toLive\n ? fill.toLive(ctx, this)\n : fill;\n if (needsVpt) {\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n }\n ctx.transform(1, 0, 0, 1, fill.offsetX || 0, fill.offsetY || 0);\n var m = fill.gradientTransform || fill.patternTransform;\n m && ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\n ctx.fill();\n ctx.restore();\n }\n if (object) {\n ctx.save();\n var skipOffscreen = this.skipOffscreen;\n // if the object doesn't move with the viewport,\n // the offscreen concept does not apply;\n this.skipOffscreen = needsVpt;\n if (needsVpt) {\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n }\n object.render(ctx);\n this.skipOffscreen = skipOffscreen;\n ctx.restore();\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderBackground: function(ctx) {\n this._renderBackgroundOrOverlay(ctx, 'background');\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderOverlay: function(ctx) {\n this._renderBackgroundOrOverlay(ctx, 'overlay');\n },\n\n /**\n * Returns coordinates of a center of canvas.\n * Returned value is an object with top and left properties\n * @return {Object} object with \"top\" and \"left\" number values\n * @deprecated migrate to `getCenterPoint`\n */\n getCenter: function () {\n return {\n top: this.height / 2,\n left: this.width / 2\n };\n },\n\n /**\n * Returns coordinates of a center of canvas.\n * @return {fabric.Point} \n */\n getCenterPoint: function () {\n return new fabric.Point(this.width / 2, this.height / 2);\n },\n\n /**\n * Centers object horizontally in the canvas\n * @param {fabric.Object} object Object to center horizontally\n * @return {fabric.Canvas} thisArg\n */\n centerObjectH: function (object) {\n return this._centerObject(object, new fabric.Point(this.getCenterPoint().x, object.getCenterPoint().y));\n },\n\n /**\n * Centers object vertically in the canvas\n * @param {fabric.Object} object Object to center vertically\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n centerObjectV: function (object) {\n return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenterPoint().y));\n },\n\n /**\n * Centers object vertically and horizontally in the canvas\n * @param {fabric.Object} object Object to center vertically and horizontally\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n centerObject: function(object) {\n var center = this.getCenterPoint();\n return this._centerObject(object, center);\n },\n\n /**\n * Centers object vertically and horizontally in the viewport\n * @param {fabric.Object} object Object to center vertically and horizontally\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n viewportCenterObject: function(object) {\n var vpCenter = this.getVpCenter();\n return this._centerObject(object, vpCenter);\n },\n\n /**\n * Centers object horizontally in the viewport, object.top is unchanged\n * @param {fabric.Object} object Object to center vertically and horizontally\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n viewportCenterObjectH: function(object) {\n var vpCenter = this.getVpCenter();\n this._centerObject(object, new fabric.Point(vpCenter.x, object.getCenterPoint().y));\n return this;\n },\n\n /**\n * Centers object Vertically in the viewport, object.top is unchanged\n * @param {fabric.Object} object Object to center vertically and horizontally\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n viewportCenterObjectV: function(object) {\n var vpCenter = this.getVpCenter();\n\n return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, vpCenter.y));\n },\n\n /**\n * Calculate the point in canvas that correspond to the center of actual viewport.\n * @return {fabric.Point} vpCenter, viewport center\n * @chainable\n */\n getVpCenter: function() {\n var center = this.getCenterPoint(),\n iVpt = invertTransform(this.viewportTransform);\n return transformPoint(center, iVpt);\n },\n\n /**\n * @private\n * @param {fabric.Object} object Object to center\n * @param {fabric.Point} center Center point\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n _centerObject: function(object, center) {\n object.setPositionByOrigin(center, 'center', 'center');\n object.setCoords();\n this.renderOnAddRemove && this.requestRenderAll();\n return this;\n },\n\n /**\n * Returns dataless JSON representation of canvas\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {String} json string\n */\n toDatalessJSON: function (propertiesToInclude) {\n return this.toDatalessObject(propertiesToInclude);\n },\n\n /**\n * Returns object representation of canvas\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function (propertiesToInclude) {\n return this._toObjectMethod('toObject', propertiesToInclude);\n },\n\n /**\n * Returns dataless object representation of canvas\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toDatalessObject: function (propertiesToInclude) {\n return this._toObjectMethod('toDatalessObject', propertiesToInclude);\n },\n\n /**\n * @private\n */\n _toObjectMethod: function (methodName, propertiesToInclude) {\n\n var clipPath = this.clipPath, data = {\n version: fabric.version,\n objects: this._toObjects(methodName, propertiesToInclude),\n };\n if (clipPath && !clipPath.excludeFromExport) {\n data.clipPath = this._toObject(this.clipPath, methodName, propertiesToInclude);\n }\n extend(data, this.__serializeBgOverlay(methodName, propertiesToInclude));\n\n fabric.util.populateWithProperties(this, data, propertiesToInclude);\n\n return data;\n },\n\n /**\n * @private\n */\n _toObjects: function(methodName, propertiesToInclude) {\n return this._objects.filter(function(object) {\n return !object.excludeFromExport;\n }).map(function(instance) {\n return this._toObject(instance, methodName, propertiesToInclude);\n }, this);\n },\n\n /**\n * @private\n */\n _toObject: function(instance, methodName, propertiesToInclude) {\n var originalValue;\n\n if (!this.includeDefaultValues) {\n originalValue = instance.includeDefaultValues;\n instance.includeDefaultValues = false;\n }\n\n var object = instance[methodName](propertiesToInclude);\n if (!this.includeDefaultValues) {\n instance.includeDefaultValues = originalValue;\n }\n return object;\n },\n\n /**\n * @private\n */\n __serializeBgOverlay: function(methodName, propertiesToInclude) {\n var data = {}, bgImage = this.backgroundImage, overlayImage = this.overlayImage,\n bgColor = this.backgroundColor, overlayColor = this.overlayColor;\n\n if (bgColor && bgColor.toObject) {\n if (!bgColor.excludeFromExport) {\n data.background = bgColor.toObject(propertiesToInclude);\n }\n }\n else if (bgColor) {\n data.background = bgColor;\n }\n\n if (overlayColor && overlayColor.toObject) {\n if (!overlayColor.excludeFromExport) {\n data.overlay = overlayColor.toObject(propertiesToInclude);\n }\n }\n else if (overlayColor) {\n data.overlay = overlayColor;\n }\n\n if (bgImage && !bgImage.excludeFromExport) {\n data.backgroundImage = this._toObject(bgImage, methodName, propertiesToInclude);\n }\n if (overlayImage && !overlayImage.excludeFromExport) {\n data.overlayImage = this._toObject(overlayImage, methodName, propertiesToInclude);\n }\n\n return data;\n },\n\n /* _TO_SVG_START_ */\n /**\n * When true, getSvgTransform() will apply the StaticCanvas.viewportTransform to the SVG transformation. When true,\n * a zoomed canvas will then produce zoomed SVG output.\n * @type Boolean\n * @default\n */\n svgViewportTransformation: true,\n\n /**\n * Returns SVG representation of canvas\n * @function\n * @param {Object} [options] Options object for SVG output\n * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included\n * @param {Object} [options.viewBox] SVG viewbox object\n * @param {Number} [options.viewBox.x] x-coordinate of viewbox\n * @param {Number} [options.viewBox.y] y-coordinate of viewbox\n * @param {Number} [options.viewBox.width] Width of viewbox\n * @param {Number} [options.viewBox.height] Height of viewbox\n * @param {String} [options.encoding=UTF-8] Encoding of SVG output\n * @param {String} [options.width] desired width of svg with or without units\n * @param {String} [options.height] desired height of svg with or without units\n * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation.\n * @return {String} SVG string\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}\n * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo}\n * @example Normal SVG output\n * var svg = canvas.toSVG();\n * @example SVG output without preamble (without <?xml ../>)\n * var svg = canvas.toSVG({suppressPreamble: true});\n * @example SVG output with viewBox attribute\n * var svg = canvas.toSVG({\n * viewBox: {\n * x: 100,\n * y: 100,\n * width: 200,\n * height: 300\n * }\n * });\n * @example SVG output with different encoding (default: UTF-8)\n * var svg = canvas.toSVG({encoding: 'ISO-8859-1'});\n * @example Modify SVG output with reviver function\n * var svg = canvas.toSVG(null, function(svg) {\n * return svg.replace('stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; ', '');\n * });\n */\n toSVG: function(options, reviver) {\n options || (options = { });\n options.reviver = reviver;\n var markup = [];\n\n this._setSVGPreamble(markup, options);\n this._setSVGHeader(markup, options);\n if (this.clipPath) {\n markup.push('\\n');\n }\n this._setSVGBgOverlayColor(markup, 'background');\n this._setSVGBgOverlayImage(markup, 'backgroundImage', reviver);\n this._setSVGObjects(markup, reviver);\n if (this.clipPath) {\n markup.push('\\n');\n }\n this._setSVGBgOverlayColor(markup, 'overlay');\n this._setSVGBgOverlayImage(markup, 'overlayImage', reviver);\n\n markup.push('');\n\n return markup.join('');\n },\n\n /**\n * @private\n */\n _setSVGPreamble: function(markup, options) {\n if (options.suppressPreamble) {\n return;\n }\n markup.push(\n '\\n',\n '\\n'\n );\n },\n\n /**\n * @private\n */\n _setSVGHeader: function(markup, options) {\n var width = options.width || this.width,\n height = options.height || this.height,\n vpt, viewBox = 'viewBox=\"0 0 ' + this.width + ' ' + this.height + '\" ',\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n\n if (options.viewBox) {\n viewBox = 'viewBox=\"' +\n options.viewBox.x + ' ' +\n options.viewBox.y + ' ' +\n options.viewBox.width + ' ' +\n options.viewBox.height + '\" ';\n }\n else {\n if (this.svgViewportTransformation) {\n vpt = this.viewportTransform;\n viewBox = 'viewBox=\"' +\n toFixed(-vpt[4] / vpt[0], NUM_FRACTION_DIGITS) + ' ' +\n toFixed(-vpt[5] / vpt[3], NUM_FRACTION_DIGITS) + ' ' +\n toFixed(this.width / vpt[0], NUM_FRACTION_DIGITS) + ' ' +\n toFixed(this.height / vpt[3], NUM_FRACTION_DIGITS) + '\" ';\n }\n }\n\n markup.push(\n '\\n',\n 'Created with Fabric.js ', fabric.version, '\\n',\n '\\n',\n this.createSVGFontFacesMarkup(),\n this.createSVGRefElementsMarkup(),\n this.createSVGClipPathMarkup(options),\n '\\n'\n );\n },\n\n createSVGClipPathMarkup: function(options) {\n var clipPath = this.clipPath;\n if (clipPath) {\n clipPath.clipPathId = 'CLIPPATH_' + fabric.Object.__uid++;\n return '\\n' +\n this.clipPath.toClipPathSVG(options.reviver) +\n '\\n';\n }\n return '';\n },\n\n /**\n * Creates markup containing SVG referenced elements like patterns, gradients etc.\n * @return {String}\n */\n createSVGRefElementsMarkup: function() {\n var _this = this,\n markup = ['background', 'overlay'].map(function(prop) {\n var fill = _this[prop + 'Color'];\n if (fill && fill.toLive) {\n var shouldTransform = _this[prop + 'Vpt'], vpt = _this.viewportTransform,\n object = {\n width: _this.width / (shouldTransform ? vpt[0] : 1),\n height: _this.height / (shouldTransform ? vpt[3] : 1)\n };\n return fill.toSVG(\n object,\n { additionalTransform: shouldTransform ? fabric.util.matrixToSVG(vpt) : '' }\n );\n }\n });\n return markup.join('');\n },\n\n /**\n * Creates markup containing SVG font faces,\n * font URLs for font faces must be collected by developers\n * and are not extracted from the DOM by fabricjs\n * @param {Array} objects Array of fabric objects\n * @return {String}\n */\n createSVGFontFacesMarkup: function() {\n var markup = '', fontList = { }, obj, fontFamily,\n style, row, rowIndex, _char, charIndex, i, len,\n fontPaths = fabric.fontPaths, objects = [];\n\n this._objects.forEach(function add(object) {\n objects.push(object);\n if (object._objects) {\n object._objects.forEach(add);\n }\n });\n\n for (i = 0, len = objects.length; i < len; i++) {\n obj = objects[i];\n fontFamily = obj.fontFamily;\n if (obj.type.indexOf('text') === -1 || fontList[fontFamily] || !fontPaths[fontFamily]) {\n continue;\n }\n fontList[fontFamily] = true;\n if (!obj.styles) {\n continue;\n }\n style = obj.styles;\n for (rowIndex in style) {\n row = style[rowIndex];\n for (charIndex in row) {\n _char = row[charIndex];\n fontFamily = _char.fontFamily;\n if (!fontList[fontFamily] && fontPaths[fontFamily]) {\n fontList[fontFamily] = true;\n }\n }\n }\n }\n\n for (var j in fontList) {\n markup += [\n '\\t\\t@font-face {\\n',\n '\\t\\t\\tfont-family: \\'', j, '\\';\\n',\n '\\t\\t\\tsrc: url(\\'', fontPaths[j], '\\');\\n',\n '\\t\\t}\\n'\n ].join('');\n }\n\n if (markup) {\n markup = [\n '\\t\\n'\n ].join('');\n }\n\n return markup;\n },\n\n /**\n * @private\n */\n _setSVGObjects: function(markup, reviver) {\n var instance, i, len, objects = this._objects;\n for (i = 0, len = objects.length; i < len; i++) {\n instance = objects[i];\n if (instance.excludeFromExport) {\n continue;\n }\n this._setSVGObject(markup, instance, reviver);\n }\n },\n\n /**\n * @private\n */\n _setSVGObject: function(markup, instance, reviver) {\n markup.push(instance.toSVG(reviver));\n },\n\n /**\n * @private\n */\n _setSVGBgOverlayImage: function(markup, property, reviver) {\n if (this[property] && !this[property].excludeFromExport && this[property].toSVG) {\n markup.push(this[property].toSVG(reviver));\n }\n },\n\n /**\n * @private\n */\n _setSVGBgOverlayColor: function(markup, property) {\n var filler = this[property + 'Color'], vpt = this.viewportTransform, finalWidth = this.width,\n finalHeight = this.height;\n if (!filler) {\n return;\n }\n if (filler.toLive) {\n var repeat = filler.repeat, iVpt = fabric.util.invertTransform(vpt), shouldInvert = this[property + 'Vpt'],\n additionalTransform = shouldInvert ? fabric.util.matrixToSVG(iVpt) : '';\n markup.push(\n '\\n'\n );\n }\n else {\n markup.push(\n '\\n'\n );\n }\n },\n /* _TO_SVG_END_ */\n\n /**\n * Moves an object or the objects of a multiple selection\n * to the bottom of the stack of drawn objects\n * @param {fabric.Object} object Object to send to back\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n sendToBack: function (object) {\n if (!object) {\n return this;\n }\n var activeSelection = this._activeObject,\n i, obj, objs;\n if (object === activeSelection && object.type === 'activeSelection') {\n objs = activeSelection._objects;\n for (i = objs.length; i--;) {\n obj = objs[i];\n removeFromArray(this._objects, obj);\n this._objects.unshift(obj);\n }\n }\n else {\n removeFromArray(this._objects, object);\n this._objects.unshift(object);\n }\n this.renderOnAddRemove && this.requestRenderAll();\n return this;\n },\n\n /**\n * Moves an object or the objects of a multiple selection\n * to the top of the stack of drawn objects\n * @param {fabric.Object} object Object to send\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n bringToFront: function (object) {\n if (!object) {\n return this;\n }\n var activeSelection = this._activeObject,\n i, obj, objs;\n if (object === activeSelection && object.type === 'activeSelection') {\n objs = activeSelection._objects;\n for (i = 0; i < objs.length; i++) {\n obj = objs[i];\n removeFromArray(this._objects, obj);\n this._objects.push(obj);\n }\n }\n else {\n removeFromArray(this._objects, object);\n this._objects.push(object);\n }\n this.renderOnAddRemove && this.requestRenderAll();\n return this;\n },\n\n /**\n * Moves an object or a selection down in stack of drawn objects\n * An optional parameter, intersecting allows to move the object in behind\n * the first intersecting object. Where intersection is calculated with\n * bounding box. If no intersection is found, there will not be change in the\n * stack.\n * @param {fabric.Object} object Object to send\n * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n sendBackwards: function (object, intersecting) {\n if (!object) {\n return this;\n }\n var activeSelection = this._activeObject,\n i, obj, idx, newIdx, objs, objsMoved = 0;\n\n if (object === activeSelection && object.type === 'activeSelection') {\n objs = activeSelection._objects;\n for (i = 0; i < objs.length; i++) {\n obj = objs[i];\n idx = this._objects.indexOf(obj);\n if (idx > 0 + objsMoved) {\n newIdx = idx - 1;\n removeFromArray(this._objects, obj);\n this._objects.splice(newIdx, 0, obj);\n }\n objsMoved++;\n }\n }\n else {\n idx = this._objects.indexOf(object);\n if (idx !== 0) {\n // if object is not on the bottom of stack\n newIdx = this._findNewLowerIndex(object, idx, intersecting);\n removeFromArray(this._objects, object);\n this._objects.splice(newIdx, 0, object);\n }\n }\n this.renderOnAddRemove && this.requestRenderAll();\n return this;\n },\n\n /**\n * @private\n */\n _findNewLowerIndex: function(object, idx, intersecting) {\n var newIdx, i;\n\n if (intersecting) {\n newIdx = idx;\n\n // traverse down the stack looking for the nearest intersecting object\n for (i = idx - 1; i >= 0; --i) {\n\n var isIntersecting = object.intersectsWithObject(this._objects[i]) ||\n object.isContainedWithinObject(this._objects[i]) ||\n this._objects[i].isContainedWithinObject(object);\n\n if (isIntersecting) {\n newIdx = i;\n break;\n }\n }\n }\n else {\n newIdx = idx - 1;\n }\n\n return newIdx;\n },\n\n /**\n * Moves an object or a selection up in stack of drawn objects\n * An optional parameter, intersecting allows to move the object in front\n * of the first intersecting object. Where intersection is calculated with\n * bounding box. If no intersection is found, there will not be change in the\n * stack.\n * @param {fabric.Object} object Object to send\n * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n bringForward: function (object, intersecting) {\n if (!object) {\n return this;\n }\n var activeSelection = this._activeObject,\n i, obj, idx, newIdx, objs, objsMoved = 0;\n\n if (object === activeSelection && object.type === 'activeSelection') {\n objs = activeSelection._objects;\n for (i = objs.length; i--;) {\n obj = objs[i];\n idx = this._objects.indexOf(obj);\n if (idx < this._objects.length - 1 - objsMoved) {\n newIdx = idx + 1;\n removeFromArray(this._objects, obj);\n this._objects.splice(newIdx, 0, obj);\n }\n objsMoved++;\n }\n }\n else {\n idx = this._objects.indexOf(object);\n if (idx !== this._objects.length - 1) {\n // if object is not on top of stack (last item in an array)\n newIdx = this._findNewUpperIndex(object, idx, intersecting);\n removeFromArray(this._objects, object);\n this._objects.splice(newIdx, 0, object);\n }\n }\n this.renderOnAddRemove && this.requestRenderAll();\n return this;\n },\n\n /**\n * @private\n */\n _findNewUpperIndex: function(object, idx, intersecting) {\n var newIdx, i, len;\n\n if (intersecting) {\n newIdx = idx;\n\n // traverse up the stack looking for the nearest intersecting object\n for (i = idx + 1, len = this._objects.length; i < len; ++i) {\n\n var isIntersecting = object.intersectsWithObject(this._objects[i]) ||\n object.isContainedWithinObject(this._objects[i]) ||\n this._objects[i].isContainedWithinObject(object);\n\n if (isIntersecting) {\n newIdx = i;\n break;\n }\n }\n }\n else {\n newIdx = idx + 1;\n }\n\n return newIdx;\n },\n\n /**\n * Moves an object to specified level in stack of drawn objects\n * @param {fabric.Object} object Object to send\n * @param {Number} index Position to move to\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n moveTo: function (object, index) {\n removeFromArray(this._objects, object);\n this._objects.splice(index, 0, object);\n return this.renderOnAddRemove && this.requestRenderAll();\n },\n\n /**\n * Clears a canvas element and dispose objects\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n dispose: function () {\n // cancel eventually ongoing renders\n if (this.isRendering) {\n fabric.util.cancelAnimFrame(this.isRendering);\n this.isRendering = 0;\n }\n this.forEachObject(function(object) {\n object.dispose && object.dispose();\n });\n this._objects = [];\n if (this.backgroundImage && this.backgroundImage.dispose) {\n this.backgroundImage.dispose();\n }\n this.backgroundImage = null;\n if (this.overlayImage && this.overlayImage.dispose) {\n this.overlayImage.dispose();\n }\n this.overlayImage = null;\n this._iTextInstances = null;\n this.contextContainer = null;\n // restore canvas style\n this.lowerCanvasEl.classList.remove('lower-canvas');\n fabric.util.setStyle(this.lowerCanvasEl, this._originalCanvasStyle);\n delete this._originalCanvasStyle;\n // restore canvas size to original size in case retina scaling was applied\n this.lowerCanvasEl.setAttribute('width', this.width);\n this.lowerCanvasEl.setAttribute('height', this.height);\n fabric.util.cleanUpJsdomNode(this.lowerCanvasEl);\n this.lowerCanvasEl = undefined;\n return this;\n },\n\n /**\n * Returns a string representation of an instance\n * @return {String} string representation of an instance\n */\n toString: function () {\n return '#';\n }\n });\n\n extend(fabric.StaticCanvas.prototype, fabric.Observable);\n extend(fabric.StaticCanvas.prototype, fabric.Collection);\n extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter);\n\n extend(fabric.StaticCanvas, /** @lends fabric.StaticCanvas */ {\n\n /**\n * @static\n * @type String\n * @default\n */\n EMPTY_JSON: '{\"objects\": [], \"background\": \"white\"}',\n\n /**\n * Provides a way to check support of some of the canvas methods\n * (either those of HTMLCanvasElement itself, or rendering context)\n *\n * @param {String} methodName Method to check support for;\n * Could be one of \"setLineDash\"\n * @return {Boolean | null} `true` if method is supported (or at least exists),\n * `null` if canvas element or context can not be initialized\n */\n supports: function (methodName) {\n var el = createCanvasElement();\n\n if (!el || !el.getContext) {\n return null;\n }\n\n var ctx = el.getContext('2d');\n if (!ctx) {\n return null;\n }\n\n switch (methodName) {\n\n case 'setLineDash':\n return typeof ctx.setLineDash !== 'undefined';\n\n default:\n return null;\n }\n }\n });\n\n /**\n * Returns Object representation of canvas\n * this alias is provided because if you call JSON.stringify on an instance,\n * the toJSON object will be invoked if it exists.\n * Having a toJSON method means you can do JSON.stringify(myCanvas)\n * @function\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} JSON compatible object\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}\n * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo}\n * @example JSON without additional properties\n * var json = canvas.toJSON();\n * @example JSON with additional properties included\n * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY']);\n * @example JSON without default values\n * canvas.includeDefaultValues = false;\n * var json = canvas.toJSON();\n */\n fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject;\n\n if (fabric.isLikelyNode) {\n fabric.StaticCanvas.prototype.createPNGStream = function() {\n var impl = getNodeCanvas(this.lowerCanvasEl);\n return impl && impl.createPNGStream();\n };\n fabric.StaticCanvas.prototype.createJPEGStream = function(opts) {\n var impl = getNodeCanvas(this.lowerCanvasEl);\n return impl && impl.createJPEGStream(opts);\n };\n }\n})();\n\n\n/**\n * BaseBrush class\n * @class fabric.BaseBrush\n * @see {@link http://fabricjs.com/freedrawing|Freedrawing demo}\n */\nfabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype */ {\n\n /**\n * Color of a brush\n * @type String\n * @default\n */\n color: 'rgb(0, 0, 0)',\n\n /**\n * Width of a brush, has to be a Number, no string literals\n * @type Number\n * @default\n */\n width: 1,\n\n /**\n * Shadow object representing shadow of this shape.\n * Backwards incompatibility note: This property replaces \"shadowColor\" (String), \"shadowOffsetX\" (Number),\n * \"shadowOffsetY\" (Number) and \"shadowBlur\" (Number) since v1.2.12\n * @type fabric.Shadow\n * @default\n */\n shadow: null,\n\n /**\n * Line endings style of a brush (one of \"butt\", \"round\", \"square\")\n * @type String\n * @default\n */\n strokeLineCap: 'round',\n\n /**\n * Corner style of a brush (one of \"bevel\", \"round\", \"miter\")\n * @type String\n * @default\n */\n strokeLineJoin: 'round',\n\n /**\n * Maximum miter length (used for strokeLineJoin = \"miter\") of a brush's\n * @type Number\n * @default\n */\n strokeMiterLimit: 10,\n\n /**\n * Stroke Dash Array.\n * @type Array\n * @default\n */\n strokeDashArray: null,\n\n /**\n * When `true`, the free drawing is limited to the whiteboard size. Default to false.\n * @type Boolean\n * @default false\n */\n\n limitedToCanvasSize: false,\n\n\n /**\n * Sets brush styles\n * @private\n * @param {CanvasRenderingContext2D} ctx\n */\n _setBrushStyles: function (ctx) {\n ctx.strokeStyle = this.color;\n ctx.lineWidth = this.width;\n ctx.lineCap = this.strokeLineCap;\n ctx.miterLimit = this.strokeMiterLimit;\n ctx.lineJoin = this.strokeLineJoin;\n ctx.setLineDash(this.strokeDashArray || []);\n },\n\n /**\n * Sets the transformation on given context\n * @param {RenderingContext2d} ctx context to render on\n * @private\n */\n _saveAndTransform: function(ctx) {\n var v = this.canvas.viewportTransform;\n ctx.save();\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n },\n\n /**\n * Sets brush shadow styles\n * @private\n */\n _setShadow: function() {\n if (!this.shadow) {\n return;\n }\n\n var canvas = this.canvas,\n shadow = this.shadow,\n ctx = canvas.contextTop,\n zoom = canvas.getZoom();\n if (canvas && canvas._isRetinaScaling()) {\n zoom *= fabric.devicePixelRatio;\n }\n\n ctx.shadowColor = shadow.color;\n ctx.shadowBlur = shadow.blur * zoom;\n ctx.shadowOffsetX = shadow.offsetX * zoom;\n ctx.shadowOffsetY = shadow.offsetY * zoom;\n },\n\n needsFullRender: function() {\n var color = new fabric.Color(this.color);\n return color.getAlpha() < 1 || !!this.shadow;\n },\n\n /**\n * Removes brush shadow styles\n * @private\n */\n _resetShadow: function() {\n var ctx = this.canvas.contextTop;\n\n ctx.shadowColor = '';\n ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;\n },\n\n /**\n * Check is pointer is outside canvas boundaries\n * @param {Object} pointer\n * @private\n */\n _isOutSideCanvas: function(pointer) {\n return pointer.x < 0 || pointer.x > this.canvas.getWidth() || pointer.y < 0 || pointer.y > this.canvas.getHeight();\n }\n});\n\n\n(function() {\n /**\n * PencilBrush class\n * @class fabric.PencilBrush\n * @extends fabric.BaseBrush\n */\n fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.PencilBrush.prototype */ {\n\n /**\n * Discard points that are less than `decimate` pixel distant from each other\n * @type Number\n * @default 0.4\n */\n decimate: 0.4,\n\n /**\n * Draws a straight line between last recorded point to current pointer\n * Used for `shift` functionality\n *\n * @type boolean\n * @default false\n */\n drawStraightLine: false,\n\n /**\n * The event modifier key that makes the brush draw a straight line.\n * If `null` or 'none' or any other string that is not a modifier key the feature is disabled.\n * @type {'altKey' | 'shiftKey' | 'ctrlKey' | 'none' | undefined | null}\n */\n straightLineKey: 'shiftKey',\n\n /**\n * Constructor\n * @param {fabric.Canvas} canvas\n * @return {fabric.PencilBrush} Instance of a pencil brush\n */\n initialize: function(canvas) {\n this.canvas = canvas;\n this._points = [];\n },\n\n needsFullRender: function () {\n return this.callSuper('needsFullRender') || this._hasStraightLine;\n },\n\n /**\n * Invoked inside on mouse down and mouse move\n * @param {Object} pointer\n */\n _drawSegment: function (ctx, p1, p2) {\n var midPoint = p1.midPointFrom(p2);\n ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);\n return midPoint;\n },\n\n /**\n * Invoked on mouse down\n * @param {Object} pointer\n */\n onMouseDown: function(pointer, options) {\n if (!this.canvas._isMainEvent(options.e)) {\n return;\n }\n this.drawStraightLine = options.e[this.straightLineKey];\n this._prepareForDrawing(pointer);\n // capture coordinates immediately\n // this allows to draw dots (when movement never occurs)\n this._captureDrawingPath(pointer);\n this._render();\n },\n\n /**\n * Invoked on mouse move\n * @param {Object} pointer\n */\n onMouseMove: function(pointer, options) {\n if (!this.canvas._isMainEvent(options.e)) {\n return;\n }\n this.drawStraightLine = options.e[this.straightLineKey];\n if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\n return;\n }\n if (this._captureDrawingPath(pointer) && this._points.length > 1) {\n if (this.needsFullRender()) {\n // redraw curve\n // clear top canvas\n this.canvas.clearContext(this.canvas.contextTop);\n this._render();\n }\n else {\n var points = this._points, length = points.length, ctx = this.canvas.contextTop;\n // draw the curve update\n this._saveAndTransform(ctx);\n if (this.oldEnd) {\n ctx.beginPath();\n ctx.moveTo(this.oldEnd.x, this.oldEnd.y);\n }\n this.oldEnd = this._drawSegment(ctx, points[length - 2], points[length - 1], true);\n ctx.stroke();\n ctx.restore();\n }\n }\n },\n\n /**\n * Invoked on mouse up\n */\n onMouseUp: function(options) {\n if (!this.canvas._isMainEvent(options.e)) {\n return true;\n }\n this.drawStraightLine = false;\n this.oldEnd = undefined;\n this._finalizeAndAddPath();\n return false;\n },\n\n /**\n * @private\n * @param {Object} pointer Actual mouse position related to the canvas.\n */\n _prepareForDrawing: function(pointer) {\n\n var p = new fabric.Point(pointer.x, pointer.y);\n\n this._reset();\n this._addPoint(p);\n this.canvas.contextTop.moveTo(p.x, p.y);\n },\n\n /**\n * @private\n * @param {fabric.Point} point Point to be added to points array\n */\n _addPoint: function(point) {\n if (this._points.length > 1 && point.eq(this._points[this._points.length - 1])) {\n return false;\n }\n if (this.drawStraightLine && this._points.length > 1) {\n this._hasStraightLine = true;\n this._points.pop();\n }\n this._points.push(point);\n return true;\n },\n\n /**\n * Clear points array and set contextTop canvas style.\n * @private\n */\n _reset: function() {\n this._points = [];\n this._setBrushStyles(this.canvas.contextTop);\n this._setShadow();\n this._hasStraightLine = false;\n },\n\n /**\n * @private\n * @param {Object} pointer Actual mouse position related to the canvas.\n */\n _captureDrawingPath: function(pointer) {\n var pointerPoint = new fabric.Point(pointer.x, pointer.y);\n return this._addPoint(pointerPoint);\n },\n\n /**\n * Draw a smooth path on the topCanvas using quadraticCurveTo\n * @private\n * @param {CanvasRenderingContext2D} [ctx]\n */\n _render: function(ctx) {\n var i, len,\n p1 = this._points[0],\n p2 = this._points[1];\n ctx = ctx || this.canvas.contextTop;\n this._saveAndTransform(ctx);\n ctx.beginPath();\n //if we only have 2 points in the path and they are the same\n //it means that the user only clicked the canvas without moving the mouse\n //then we should be drawing a dot. A path isn't drawn between two identical dots\n //that's why we set them apart a bit\n if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) {\n var width = this.width / 1000;\n p1 = new fabric.Point(p1.x, p1.y);\n p2 = new fabric.Point(p2.x, p2.y);\n p1.x -= width;\n p2.x += width;\n }\n ctx.moveTo(p1.x, p1.y);\n\n for (i = 1, len = this._points.length; i < len; i++) {\n // we pick the point between pi + 1 & pi + 2 as the\n // end point and p1 as our control point.\n this._drawSegment(ctx, p1, p2);\n p1 = this._points[i];\n p2 = this._points[i + 1];\n }\n // Draw last line as a straight line while\n // we wait for the next point to be able to calculate\n // the bezier control point\n ctx.lineTo(p1.x, p1.y);\n ctx.stroke();\n ctx.restore();\n },\n\n /**\n * Converts points to SVG path\n * @param {Array} points Array of points\n * @return {(string|number)[][]} SVG path commands\n */\n convertPointsToSVGPath: function (points) {\n var correction = this.width / 1000;\n return fabric.util.getSmoothPathFromPoints(points, correction);\n },\n\n /**\n * @private\n * @param {(string|number)[][]} pathData SVG path commands\n * @returns {boolean}\n */\n _isEmptySVGPath: function (pathData) {\n var pathString = fabric.util.joinPath(pathData);\n return pathString === 'M 0 0 Q 0 0 0 0 L 0 0';\n },\n\n /**\n * Creates fabric.Path object to add on canvas\n * @param {(string|number)[][]} pathData Path data\n * @return {fabric.Path} Path to add on canvas\n */\n createPath: function(pathData) {\n var path = new fabric.Path(pathData, {\n fill: null,\n stroke: this.color,\n strokeWidth: this.width,\n strokeLineCap: this.strokeLineCap,\n strokeMiterLimit: this.strokeMiterLimit,\n strokeLineJoin: this.strokeLineJoin,\n strokeDashArray: this.strokeDashArray,\n });\n if (this.shadow) {\n this.shadow.affectStroke = true;\n path.shadow = new fabric.Shadow(this.shadow);\n }\n\n return path;\n },\n\n /**\n * Decimate points array with the decimate value\n */\n decimatePoints: function(points, distance) {\n if (points.length <= 2) {\n return points;\n }\n var zoom = this.canvas.getZoom(), adjustedDistance = Math.pow(distance / zoom, 2),\n i, l = points.length - 1, lastPoint = points[0], newPoints = [lastPoint],\n cDistance;\n for (i = 1; i < l - 1; i++) {\n cDistance = Math.pow(lastPoint.x - points[i].x, 2) + Math.pow(lastPoint.y - points[i].y, 2);\n if (cDistance >= adjustedDistance) {\n lastPoint = points[i];\n newPoints.push(lastPoint);\n }\n }\n /**\n * Add the last point from the original line to the end of the array.\n * This ensures decimate doesn't delete the last point on the line, and ensures the line is > 1 point.\n */\n newPoints.push(points[l]);\n return newPoints;\n },\n\n /**\n * On mouseup after drawing the path on contextTop canvas\n * we use the points captured to create an new fabric path object\n * and add it to the fabric canvas.\n */\n _finalizeAndAddPath: function() {\n var ctx = this.canvas.contextTop;\n ctx.closePath();\n if (this.decimate) {\n this._points = this.decimatePoints(this._points, this.decimate);\n }\n var pathData = this.convertPointsToSVGPath(this._points);\n if (this._isEmptySVGPath(pathData)) {\n // do not create 0 width/height paths, as they are\n // rendered inconsistently across browsers\n // Firefox 4, for example, renders a dot,\n // whereas Chrome 10 renders nothing\n this.canvas.requestRenderAll();\n return;\n }\n\n var path = this.createPath(pathData);\n this.canvas.clearContext(this.canvas.contextTop);\n this.canvas.fire('before:path:created', { path: path });\n this.canvas.add(path);\n this.canvas.requestRenderAll();\n path.setCoords();\n this._resetShadow();\n\n\n // fire event 'path' created\n this.canvas.fire('path:created', { path: path });\n }\n });\n})();\n\n\n/**\n * CircleBrush class\n * @class fabric.CircleBrush\n */\nfabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.CircleBrush.prototype */ {\n\n /**\n * Width of a brush\n * @type Number\n * @default\n */\n width: 10,\n\n /**\n * Constructor\n * @param {fabric.Canvas} canvas\n * @return {fabric.CircleBrush} Instance of a circle brush\n */\n initialize: function(canvas) {\n this.canvas = canvas;\n this.points = [];\n },\n\n /**\n * Invoked inside on mouse down and mouse move\n * @param {Object} pointer\n */\n drawDot: function(pointer) {\n var point = this.addPoint(pointer),\n ctx = this.canvas.contextTop;\n this._saveAndTransform(ctx);\n this.dot(ctx, point);\n ctx.restore();\n },\n\n dot: function(ctx, point) {\n ctx.fillStyle = point.fill;\n ctx.beginPath();\n ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false);\n ctx.closePath();\n ctx.fill();\n },\n\n /**\n * Invoked on mouse down\n */\n onMouseDown: function(pointer) {\n this.points.length = 0;\n this.canvas.clearContext(this.canvas.contextTop);\n this._setShadow();\n this.drawDot(pointer);\n },\n\n /**\n * Render the full state of the brush\n * @private\n */\n _render: function() {\n var ctx = this.canvas.contextTop, i, len,\n points = this.points;\n this._saveAndTransform(ctx);\n for (i = 0, len = points.length; i < len; i++) {\n this.dot(ctx, points[i]);\n }\n ctx.restore();\n },\n\n /**\n * Invoked on mouse move\n * @param {Object} pointer\n */\n onMouseMove: function(pointer) {\n if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\n return;\n }\n if (this.needsFullRender()) {\n this.canvas.clearContext(this.canvas.contextTop);\n this.addPoint(pointer);\n this._render();\n }\n else {\n this.drawDot(pointer);\n }\n },\n\n /**\n * Invoked on mouse up\n */\n onMouseUp: function() {\n var originalRenderOnAddRemove = this.canvas.renderOnAddRemove, i, len;\n this.canvas.renderOnAddRemove = false;\n\n var circles = [];\n\n for (i = 0, len = this.points.length; i < len; i++) {\n var point = this.points[i],\n circle = new fabric.Circle({\n radius: point.radius,\n left: point.x,\n top: point.y,\n originX: 'center',\n originY: 'center',\n fill: point.fill\n });\n\n this.shadow && (circle.shadow = new fabric.Shadow(this.shadow));\n\n circles.push(circle);\n }\n var group = new fabric.Group(circles);\n group.canvas = this.canvas;\n\n this.canvas.fire('before:path:created', { path: group });\n this.canvas.add(group);\n this.canvas.fire('path:created', { path: group });\n\n this.canvas.clearContext(this.canvas.contextTop);\n this._resetShadow();\n this.canvas.renderOnAddRemove = originalRenderOnAddRemove;\n this.canvas.requestRenderAll();\n },\n\n /**\n * @param {Object} pointer\n * @return {fabric.Point} Just added pointer point\n */\n addPoint: function(pointer) {\n var pointerPoint = new fabric.Point(pointer.x, pointer.y),\n\n circleRadius = fabric.util.getRandomInt(\n Math.max(0, this.width - 20), this.width + 20) / 2,\n\n circleColor = new fabric.Color(this.color)\n .setAlpha(fabric.util.getRandomInt(0, 100) / 100)\n .toRgba();\n\n pointerPoint.radius = circleRadius;\n pointerPoint.fill = circleColor;\n\n this.points.push(pointerPoint);\n\n return pointerPoint;\n }\n});\n\n\n/**\n * SprayBrush class\n * @class fabric.SprayBrush\n */\nfabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric.SprayBrush.prototype */ {\n\n /**\n * Width of a spray\n * @type Number\n * @default\n */\n width: 10,\n\n /**\n * Density of a spray (number of dots per chunk)\n * @type Number\n * @default\n */\n density: 20,\n\n /**\n * Width of spray dots\n * @type Number\n * @default\n */\n dotWidth: 1,\n\n /**\n * Width variance of spray dots\n * @type Number\n * @default\n */\n dotWidthVariance: 1,\n\n /**\n * Whether opacity of a dot should be random\n * @type Boolean\n * @default\n */\n randomOpacity: false,\n\n /**\n * Whether overlapping dots (rectangles) should be removed (for performance reasons)\n * @type Boolean\n * @default\n */\n optimizeOverlapping: true,\n\n /**\n * Constructor\n * @param {fabric.Canvas} canvas\n * @return {fabric.SprayBrush} Instance of a spray brush\n */\n initialize: function(canvas) {\n this.canvas = canvas;\n this.sprayChunks = [];\n },\n\n /**\n * Invoked on mouse down\n * @param {Object} pointer\n */\n onMouseDown: function(pointer) {\n this.sprayChunks.length = 0;\n this.canvas.clearContext(this.canvas.contextTop);\n this._setShadow();\n\n this.addSprayChunk(pointer);\n this.render(this.sprayChunkPoints);\n },\n\n /**\n * Invoked on mouse move\n * @param {Object} pointer\n */\n onMouseMove: function(pointer) {\n if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\n return;\n }\n this.addSprayChunk(pointer);\n this.render(this.sprayChunkPoints);\n },\n\n /**\n * Invoked on mouse up\n */\n onMouseUp: function() {\n var originalRenderOnAddRemove = this.canvas.renderOnAddRemove;\n this.canvas.renderOnAddRemove = false;\n\n var rects = [];\n\n for (var i = 0, ilen = this.sprayChunks.length; i < ilen; i++) {\n var sprayChunk = this.sprayChunks[i];\n\n for (var j = 0, jlen = sprayChunk.length; j < jlen; j++) {\n\n var rect = new fabric.Rect({\n width: sprayChunk[j].width,\n height: sprayChunk[j].width,\n left: sprayChunk[j].x + 1,\n top: sprayChunk[j].y + 1,\n originX: 'center',\n originY: 'center',\n fill: this.color\n });\n rects.push(rect);\n }\n }\n\n if (this.optimizeOverlapping) {\n rects = this._getOptimizedRects(rects);\n }\n\n var group = new fabric.Group(rects);\n this.shadow && group.set('shadow', new fabric.Shadow(this.shadow));\n this.canvas.fire('before:path:created', { path: group });\n this.canvas.add(group);\n this.canvas.fire('path:created', { path: group });\n\n this.canvas.clearContext(this.canvas.contextTop);\n this._resetShadow();\n this.canvas.renderOnAddRemove = originalRenderOnAddRemove;\n this.canvas.requestRenderAll();\n },\n\n /**\n * @private\n * @param {Array} rects\n */\n _getOptimizedRects: function(rects) {\n\n // avoid creating duplicate rects at the same coordinates\n var uniqueRects = { }, key, i, len;\n\n for (i = 0, len = rects.length; i < len; i++) {\n key = rects[i].left + '' + rects[i].top;\n if (!uniqueRects[key]) {\n uniqueRects[key] = rects[i];\n }\n }\n var uniqueRectsArray = [];\n for (key in uniqueRects) {\n uniqueRectsArray.push(uniqueRects[key]);\n }\n\n return uniqueRectsArray;\n },\n\n /**\n * Render new chunk of spray brush\n */\n render: function(sprayChunk) {\n var ctx = this.canvas.contextTop, i, len;\n ctx.fillStyle = this.color;\n\n this._saveAndTransform(ctx);\n\n for (i = 0, len = sprayChunk.length; i < len; i++) {\n var point = sprayChunk[i];\n if (typeof point.opacity !== 'undefined') {\n ctx.globalAlpha = point.opacity;\n }\n ctx.fillRect(point.x, point.y, point.width, point.width);\n }\n ctx.restore();\n },\n\n /**\n * Render all spray chunks\n */\n _render: function() {\n var ctx = this.canvas.contextTop, i, ilen;\n ctx.fillStyle = this.color;\n\n this._saveAndTransform(ctx);\n\n for (i = 0, ilen = this.sprayChunks.length; i < ilen; i++) {\n this.render(this.sprayChunks[i]);\n }\n ctx.restore();\n },\n\n /**\n * @param {Object} pointer\n */\n addSprayChunk: function(pointer) {\n this.sprayChunkPoints = [];\n\n var x, y, width, radius = this.width / 2, i;\n\n for (i = 0; i < this.density; i++) {\n\n x = fabric.util.getRandomInt(pointer.x - radius, pointer.x + radius);\n y = fabric.util.getRandomInt(pointer.y - radius, pointer.y + radius);\n\n if (this.dotWidthVariance) {\n width = fabric.util.getRandomInt(\n // bottom clamp width to 1\n Math.max(1, this.dotWidth - this.dotWidthVariance),\n this.dotWidth + this.dotWidthVariance);\n }\n else {\n width = this.dotWidth;\n }\n\n var point = new fabric.Point(x, y);\n point.width = width;\n\n if (this.randomOpacity) {\n point.opacity = fabric.util.getRandomInt(0, 100) / 100;\n }\n\n this.sprayChunkPoints.push(point);\n }\n\n this.sprayChunks.push(this.sprayChunkPoints);\n }\n});\n\n\n/**\n * PatternBrush class\n * @class fabric.PatternBrush\n * @extends fabric.BaseBrush\n */\nfabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fabric.PatternBrush.prototype */ {\n\n getPatternSrc: function() {\n\n var dotWidth = 20,\n dotDistance = 5,\n patternCanvas = fabric.util.createCanvasElement(),\n patternCtx = patternCanvas.getContext('2d');\n\n patternCanvas.width = patternCanvas.height = dotWidth + dotDistance;\n\n patternCtx.fillStyle = this.color;\n patternCtx.beginPath();\n patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false);\n patternCtx.closePath();\n patternCtx.fill();\n\n return patternCanvas;\n },\n\n getPatternSrcFunction: function() {\n return String(this.getPatternSrc).replace('this.color', '\"' + this.color + '\"');\n },\n\n /**\n * Creates \"pattern\" instance property\n * @param {CanvasRenderingContext2D} ctx\n */\n getPattern: function(ctx) {\n return ctx.createPattern(this.source || this.getPatternSrc(), 'repeat');\n },\n\n /**\n * Sets brush styles\n * @param {CanvasRenderingContext2D} ctx\n */\n _setBrushStyles: function(ctx) {\n this.callSuper('_setBrushStyles', ctx);\n ctx.strokeStyle = this.getPattern(ctx);\n },\n\n /**\n * Creates path\n */\n createPath: function(pathData) {\n var path = this.callSuper('createPath', pathData),\n topLeft = path._getLeftTopCoords().scalarAdd(path.strokeWidth / 2);\n\n path.stroke = new fabric.Pattern({\n source: this.source || this.getPatternSrcFunction(),\n offsetX: -topLeft.x,\n offsetY: -topLeft.y\n });\n return path;\n }\n});\n\n\n(function() {\n\n var getPointer = fabric.util.getPointer,\n degreesToRadians = fabric.util.degreesToRadians,\n isTouchEvent = fabric.util.isTouchEvent;\n\n /**\n * Canvas class\n * @class fabric.Canvas\n * @extends fabric.StaticCanvas\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#canvas}\n * @see {@link fabric.Canvas#initialize} for constructor definition\n *\n * @fires object:modified at the end of a transform or any change when statefull is true\n * @fires object:rotating while an object is being rotated from the control\n * @fires object:scaling while an object is being scaled by controls\n * @fires object:moving while an object is being dragged\n * @fires object:skewing while an object is being skewed from the controls\n *\n * @fires before:transform before a transform is is started\n * @fires before:selection:cleared\n * @fires selection:cleared\n * @fires selection:updated\n * @fires selection:created\n *\n * @fires path:created after a drawing operation ends and the path is added\n * @fires mouse:down\n * @fires mouse:move\n * @fires mouse:up\n * @fires mouse:down:before on mouse down, before the inner fabric logic runs\n * @fires mouse:move:before on mouse move, before the inner fabric logic runs\n * @fires mouse:up:before on mouse up, before the inner fabric logic runs\n * @fires mouse:over\n * @fires mouse:out\n * @fires mouse:dblclick whenever a native dbl click event fires on the canvas.\n *\n * @fires dragover\n * @fires dragenter\n * @fires dragleave\n * @fires drop:before before drop event. same native event. This is added to handle edge cases\n * @fires drop\n * @fires after:render at the end of the render process, receives the context in the callback\n * @fires before:render at start the render process, receives the context in the callback\n *\n */\n fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ {\n\n /**\n * Constructor\n * @param {HTMLElement | String} el <canvas> element to initialize instance on\n * @param {Object} [options] Options object\n * @return {Object} thisArg\n */\n initialize: function(el, options) {\n options || (options = { });\n this.renderAndResetBound = this.renderAndReset.bind(this);\n this.requestRenderAllBound = this.requestRenderAll.bind(this);\n this._initStatic(el, options);\n this._initInteractive();\n this._createCacheCanvas();\n },\n\n /**\n * When true, objects can be transformed by one side (unproportionally)\n * when dragged on the corners that normally would not do that.\n * @type Boolean\n * @default\n * @since fabric 4.0 // changed name and default value\n */\n uniformScaling: true,\n\n /**\n * Indicates which key switches uniform scaling.\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * If `null` or 'none' or any other string that is not a modifier key\n * feature is disabled.\n * totally wrong named. this sounds like `uniform scaling`\n * if Canvas.uniformScaling is true, pressing this will set it to false\n * and viceversa.\n * @since 1.6.2\n * @type String\n * @default\n */\n uniScaleKey: 'shiftKey',\n\n /**\n * When true, objects use center point as the origin of scale transformation.\n * Backwards incompatibility note: This property replaces \"centerTransform\" (Boolean).\n * @since 1.3.4\n * @type Boolean\n * @default\n */\n centeredScaling: false,\n\n /**\n * When true, objects use center point as the origin of rotate transformation.\n * Backwards incompatibility note: This property replaces \"centerTransform\" (Boolean).\n * @since 1.3.4\n * @type Boolean\n * @default\n */\n centeredRotation: false,\n\n /**\n * Indicates which key enable centered Transform\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * If `null` or 'none' or any other string that is not a modifier key\n * feature is disabled feature disabled.\n * @since 1.6.2\n * @type String\n * @default\n */\n centeredKey: 'altKey',\n\n /**\n * Indicates which key enable alternate action on corner\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * If `null` or 'none' or any other string that is not a modifier key\n * feature is disabled feature disabled.\n * @since 1.6.2\n * @type String\n * @default\n */\n altActionKey: 'shiftKey',\n\n /**\n * Indicates that canvas is interactive. This property should not be changed.\n * @type Boolean\n * @default\n */\n interactive: true,\n\n /**\n * Indicates whether group selection should be enabled\n * @type Boolean\n * @default\n */\n selection: true,\n\n /**\n * Indicates which key or keys enable multiple click selection\n * Pass value as a string or array of strings\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * If `null` or empty or containing any other string that is not a modifier key\n * feature is disabled.\n * @since 1.6.2\n * @type String|Array\n * @default\n */\n selectionKey: 'shiftKey',\n\n /**\n * Indicates which key enable alternative selection\n * in case of target overlapping with active object\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * For a series of reason that come from the general expectations on how\n * things should work, this feature works only for preserveObjectStacking true.\n * If `null` or 'none' or any other string that is not a modifier key\n * feature is disabled.\n * @since 1.6.5\n * @type null|String\n * @default\n */\n altSelectionKey: null,\n\n /**\n * Color of selection\n * @type String\n * @default\n */\n selectionColor: 'rgba(100, 100, 255, 0.3)', // blue\n\n /**\n * Default dash array pattern\n * If not empty the selection border is dashed\n * @type Array\n */\n selectionDashArray: [],\n\n /**\n * Color of the border of selection (usually slightly darker than color of selection itself)\n * @type String\n * @default\n */\n selectionBorderColor: 'rgba(255, 255, 255, 0.3)',\n\n /**\n * Width of a line used in object/group selection\n * @type Number\n * @default\n */\n selectionLineWidth: 1,\n\n /**\n * Select only shapes that are fully contained in the dragged selection rectangle.\n * @type Boolean\n * @default\n */\n selectionFullyContained: false,\n\n /**\n * Default cursor value used when hovering over an object on canvas\n * @type String\n * @default\n */\n hoverCursor: 'move',\n\n /**\n * Default cursor value used when moving an object on canvas\n * @type String\n * @default\n */\n moveCursor: 'move',\n\n /**\n * Default cursor value used for the entire canvas\n * @type String\n * @default\n */\n defaultCursor: 'default',\n\n /**\n * Cursor value used during free drawing\n * @type String\n * @default\n */\n freeDrawingCursor: 'crosshair',\n\n /**\n * Cursor value used for disabled elements ( corners with disabled action )\n * @type String\n * @since 2.0.0\n * @default\n */\n notAllowedCursor: 'not-allowed',\n\n /**\n * Default element class that's given to wrapper (div) element of canvas\n * @type String\n * @default\n */\n containerClass: 'canvas-container',\n\n /**\n * When true, object detection happens on per-pixel basis rather than on per-bounding-box\n * @type Boolean\n * @default\n */\n perPixelTargetFind: false,\n\n /**\n * Number of pixels around target pixel to tolerate (consider active) during object detection\n * @type Number\n * @default\n */\n targetFindTolerance: 0,\n\n /**\n * When true, target detection is skipped. Target detection will return always undefined.\n * click selection won't work anymore, events will fire with no targets.\n * if something is selected before setting it to true, it will be deselected at the first click.\n * area selection will still work. check the `selection` property too.\n * if you deactivate both, you should look into staticCanvas.\n * @type Boolean\n * @default\n */\n skipTargetFind: false,\n\n /**\n * When true, mouse events on canvas (mousedown/mousemove/mouseup) result in free drawing.\n * After mousedown, mousemove creates a shape,\n * and then mouseup finalizes it and adds an instance of `fabric.Path` onto canvas.\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-4#free_drawing}\n * @type Boolean\n * @default\n */\n isDrawingMode: false,\n\n /**\n * Indicates whether objects should remain in current stack position when selected.\n * When false objects are brought to top and rendered as part of the selection group\n * @type Boolean\n * @default\n */\n preserveObjectStacking: false,\n\n /**\n * Indicates the angle that an object will lock to while rotating.\n * @type Number\n * @since 1.6.7\n * @default\n */\n snapAngle: 0,\n\n /**\n * Indicates the distance from the snapAngle the rotation will lock to the snapAngle.\n * When `null`, the snapThreshold will default to the snapAngle.\n * @type null|Number\n * @since 1.6.7\n * @default\n */\n snapThreshold: null,\n\n /**\n * Indicates if the right click on canvas can output the context menu or not\n * @type Boolean\n * @since 1.6.5\n * @default\n */\n stopContextMenu: false,\n\n /**\n * Indicates if the canvas can fire right click events\n * @type Boolean\n * @since 1.6.5\n * @default\n */\n fireRightClick: false,\n\n /**\n * Indicates if the canvas can fire middle click events\n * @type Boolean\n * @since 1.7.8\n * @default\n */\n fireMiddleClick: false,\n\n /**\n * Keep track of the subTargets for Mouse Events\n * @type fabric.Object[]\n */\n targets: [],\n\n /**\n * When the option is enabled, PointerEvent is used instead of MouseEvent.\n * @type Boolean\n * @default\n */\n enablePointerEvents: false,\n\n /**\n * Keep track of the hovered target\n * @type fabric.Object\n * @private\n */\n _hoveredTarget: null,\n\n /**\n * hold the list of nested targets hovered\n * @type fabric.Object[]\n * @private\n */\n _hoveredTargets: [],\n\n /**\n * @private\n */\n _initInteractive: function() {\n this._currentTransform = null;\n this._groupSelector = null;\n this._initWrapperElement();\n this._createUpperCanvas();\n this._initEventListeners();\n\n this._initRetinaScaling();\n\n this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this);\n\n this.calcOffset();\n },\n\n /**\n * Divides objects in two groups, one to render immediately\n * and one to render as activeGroup.\n * @return {Array} objects to render immediately and pushes the other in the activeGroup.\n */\n _chooseObjectsToRender: function() {\n var activeObjects = this.getActiveObjects(),\n object, objsToRender, activeGroupObjects;\n\n if (activeObjects.length > 0 && !this.preserveObjectStacking) {\n objsToRender = [];\n activeGroupObjects = [];\n for (var i = 0, length = this._objects.length; i < length; i++) {\n object = this._objects[i];\n if (activeObjects.indexOf(object) === -1 ) {\n objsToRender.push(object);\n }\n else {\n activeGroupObjects.push(object);\n }\n }\n if (activeObjects.length > 1) {\n this._activeObject._objects = activeGroupObjects;\n }\n objsToRender.push.apply(objsToRender, activeGroupObjects);\n }\n else {\n objsToRender = this._objects;\n }\n return objsToRender;\n },\n\n /**\n * Renders both the top canvas and the secondary container canvas.\n * @return {fabric.Canvas} instance\n * @chainable\n */\n renderAll: function () {\n if (this.contextTopDirty && !this._groupSelector && !this.isDrawingMode) {\n this.clearContext(this.contextTop);\n this.contextTopDirty = false;\n }\n if (this.hasLostContext) {\n this.renderTopLayer(this.contextTop);\n this.hasLostContext = false;\n }\n var canvasToDrawOn = this.contextContainer;\n this.renderCanvas(canvasToDrawOn, this._chooseObjectsToRender());\n return this;\n },\n\n renderTopLayer: function(ctx) {\n ctx.save();\n if (this.isDrawingMode && this._isCurrentlyDrawing) {\n this.freeDrawingBrush && this.freeDrawingBrush._render();\n this.contextTopDirty = true;\n }\n // we render the top context - last object\n if (this.selection && this._groupSelector) {\n this._drawSelection(ctx);\n this.contextTopDirty = true;\n }\n ctx.restore();\n },\n\n /**\n * Method to render only the top canvas.\n * Also used to render the group selection box.\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n renderTop: function () {\n var ctx = this.contextTop;\n this.clearContext(ctx);\n this.renderTopLayer(ctx);\n this.fire('after:render');\n return this;\n },\n\n /**\n * @private\n */\n _normalizePointer: function (object, pointer) {\n var m = object.calcTransformMatrix(),\n invertedM = fabric.util.invertTransform(m),\n vptPointer = this.restorePointerVpt(pointer);\n return fabric.util.transformPoint(vptPointer, invertedM);\n },\n\n /**\n * Returns true if object is transparent at a certain location\n * @param {fabric.Object} target Object to check\n * @param {Number} x Left coordinate\n * @param {Number} y Top coordinate\n * @return {Boolean}\n */\n isTargetTransparent: function (target, x, y) {\n // in case the target is the activeObject, we cannot execute this optimization\n // because we need to draw controls too.\n if (target.shouldCache() && target._cacheCanvas && target !== this._activeObject) {\n var normalizedPointer = this._normalizePointer(target, {x: x, y: y}),\n targetRelativeX = Math.max(target.cacheTranslationX + (normalizedPointer.x * target.zoomX), 0),\n targetRelativeY = Math.max(target.cacheTranslationY + (normalizedPointer.y * target.zoomY), 0);\n\n var isTransparent = fabric.util.isTransparent(\n target._cacheContext, Math.round(targetRelativeX), Math.round(targetRelativeY), this.targetFindTolerance);\n\n return isTransparent;\n }\n\n var ctx = this.contextCache,\n originalColor = target.selectionBackgroundColor, v = this.viewportTransform;\n\n target.selectionBackgroundColor = '';\n\n this.clearContext(ctx);\n\n ctx.save();\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n target.render(ctx);\n ctx.restore();\n\n target.selectionBackgroundColor = originalColor;\n\n var isTransparent = fabric.util.isTransparent(\n ctx, x, y, this.targetFindTolerance);\n\n return isTransparent;\n },\n\n /**\n * takes an event and determines if selection key has been pressed\n * @private\n * @param {Event} e Event object\n */\n _isSelectionKeyPressed: function(e) {\n var selectionKeyPressed = false;\n\n if (Array.isArray(this.selectionKey)) {\n selectionKeyPressed = !!this.selectionKey.find(function(key) { return e[key] === true; });\n }\n else {\n selectionKeyPressed = e[this.selectionKey];\n }\n\n return selectionKeyPressed;\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n */\n _shouldClearSelection: function (e, target) {\n var activeObjects = this.getActiveObjects(),\n activeObject = this._activeObject;\n\n return (\n !target\n ||\n (target &&\n activeObject &&\n activeObjects.length > 1 &&\n activeObjects.indexOf(target) === -1 &&\n activeObject !== target &&\n !this._isSelectionKeyPressed(e))\n ||\n (target && !target.evented)\n ||\n (target &&\n !target.selectable &&\n activeObject &&\n activeObject !== target)\n );\n },\n\n /**\n * centeredScaling from object can't override centeredScaling from canvas.\n * this should be fixed, since object setting should take precedence over canvas.\n * also this should be something that will be migrated in the control properties.\n * as ability to define the origin of the transformation that the control provide.\n * @private\n * @param {fabric.Object} target\n * @param {String} action\n * @param {Boolean} altKey\n */\n _shouldCenterTransform: function (target, action, altKey) {\n if (!target) {\n return;\n }\n\n var centerTransform;\n\n if (action === 'scale' || action === 'scaleX' || action === 'scaleY' || action === 'resizing') {\n centerTransform = this.centeredScaling || target.centeredScaling;\n }\n else if (action === 'rotate') {\n centerTransform = this.centeredRotation || target.centeredRotation;\n }\n\n return centerTransform ? !altKey : altKey;\n },\n\n /**\n * should disappear before release 4.0\n * @private\n */\n _getOriginFromCorner: function(target, corner) {\n var origin = {\n x: target.originX,\n y: target.originY\n };\n\n if (corner === 'ml' || corner === 'tl' || corner === 'bl') {\n origin.x = 'right';\n }\n else if (corner === 'mr' || corner === 'tr' || corner === 'br') {\n origin.x = 'left';\n }\n\n if (corner === 'tl' || corner === 'mt' || corner === 'tr') {\n origin.y = 'bottom';\n }\n else if (corner === 'bl' || corner === 'mb' || corner === 'br') {\n origin.y = 'top';\n }\n return origin;\n },\n\n /**\n * @private\n * @param {Boolean} alreadySelected true if target is already selected\n * @param {String} corner a string representing the corner ml, mr, tl ...\n * @param {Event} e Event object\n * @param {fabric.Object} [target] inserted back to help overriding. Unused\n */\n _getActionFromCorner: function(alreadySelected, corner, e, target) {\n if (!corner || !alreadySelected) {\n return 'drag';\n }\n var control = target.controls[corner];\n return control.getActionName(e, control, target);\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n */\n _setupCurrentTransform: function (e, target, alreadySelected) {\n if (!target) {\n return;\n }\n\n var pointer = this.getPointer(e), corner = target.__corner,\n control = target.controls[corner],\n actionHandler = (alreadySelected && corner) ?\n control.getActionHandler(e, target, control) : fabric.controlsUtils.dragHandler,\n action = this._getActionFromCorner(alreadySelected, corner, e, target),\n origin = this._getOriginFromCorner(target, corner),\n altKey = e[this.centeredKey],\n transform = {\n target: target,\n action: action,\n actionHandler: actionHandler,\n corner: corner,\n scaleX: target.scaleX,\n scaleY: target.scaleY,\n skewX: target.skewX,\n skewY: target.skewY,\n // used by transation\n offsetX: pointer.x - target.left,\n offsetY: pointer.y - target.top,\n originX: origin.x,\n originY: origin.y,\n ex: pointer.x,\n ey: pointer.y,\n lastX: pointer.x,\n lastY: pointer.y,\n // unsure they are useful anymore.\n // left: target.left,\n // top: target.top,\n theta: degreesToRadians(target.angle),\n // end of unsure\n width: target.width * target.scaleX,\n shiftKey: e.shiftKey,\n altKey: altKey,\n original: fabric.util.saveObjectTransform(target),\n };\n\n if (this._shouldCenterTransform(target, action, altKey)) {\n transform.originX = 'center';\n transform.originY = 'center';\n }\n transform.original.originX = origin.x;\n transform.original.originY = origin.y;\n this._currentTransform = transform;\n this._beforeTransform(e);\n },\n\n /**\n * Set the cursor type of the canvas element\n * @param {String} value Cursor type of the canvas element.\n * @see http://www.w3.org/TR/css3-ui/#cursor\n */\n setCursor: function (value) {\n this.upperCanvasEl.style.cursor = value;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx to draw the selection on\n */\n _drawSelection: function (ctx) {\n var selector = this._groupSelector,\n viewportStart = new fabric.Point(selector.ex, selector.ey),\n start = fabric.util.transformPoint(viewportStart, this.viewportTransform),\n viewportExtent = new fabric.Point(selector.ex + selector.left, selector.ey + selector.top),\n extent = fabric.util.transformPoint(viewportExtent, this.viewportTransform),\n minX = Math.min(start.x, extent.x),\n minY = Math.min(start.y, extent.y),\n maxX = Math.max(start.x, extent.x),\n maxY = Math.max(start.y, extent.y),\n strokeOffset = this.selectionLineWidth / 2;\n\n if (this.selectionColor) {\n ctx.fillStyle = this.selectionColor;\n ctx.fillRect(minX, minY, maxX - minX, maxY - minY);\n }\n\n if (!this.selectionLineWidth || !this.selectionBorderColor) {\n return;\n }\n ctx.lineWidth = this.selectionLineWidth;\n ctx.strokeStyle = this.selectionBorderColor;\n\n minX += strokeOffset;\n minY += strokeOffset;\n maxX -= strokeOffset;\n maxY -= strokeOffset;\n // selection border\n fabric.Object.prototype._setLineDash.call(this, ctx, this.selectionDashArray);\n ctx.strokeRect(minX, minY, maxX - minX, maxY - minY);\n },\n\n /**\n * Method that determines what object we are clicking on\n * the skipGroup parameter is for internal use, is needed for shift+click action\n * 11/09/2018 TODO: would be cool if findTarget could discern between being a full target\n * or the outside part of the corner.\n * @param {Event} e mouse event\n * @param {Boolean} skipGroup when true, activeGroup is skipped and only objects are traversed through\n * @return {fabric.Object} the target found\n */\n findTarget: function (e, skipGroup) {\n if (this.skipTargetFind) {\n return;\n }\n\n var ignoreZoom = true,\n pointer = this.getPointer(e, ignoreZoom),\n activeObject = this._activeObject,\n aObjects = this.getActiveObjects(),\n activeTarget, activeTargetSubs,\n isTouch = isTouchEvent(e),\n shouldLookForActive = (aObjects.length > 1 && !skipGroup) || aObjects.length === 1;\n\n // first check current group (if one exists)\n // active group does not check sub targets like normal groups.\n // if active group just exits.\n this.targets = [];\n\n // if we hit the corner of an activeObject, let's return that.\n if (shouldLookForActive && activeObject._findTargetCorner(pointer, isTouch)) {\n return activeObject;\n }\n if (aObjects.length > 1 && !skipGroup && activeObject === this._searchPossibleTargets([activeObject], pointer)) {\n return activeObject;\n }\n if (aObjects.length === 1 &&\n activeObject === this._searchPossibleTargets([activeObject], pointer)) {\n if (!this.preserveObjectStacking) {\n return activeObject;\n }\n else {\n activeTarget = activeObject;\n activeTargetSubs = this.targets;\n this.targets = [];\n }\n }\n var target = this._searchPossibleTargets(this._objects, pointer);\n if (e[this.altSelectionKey] && target && activeTarget && target !== activeTarget) {\n target = activeTarget;\n this.targets = activeTargetSubs;\n }\n return target;\n },\n\n /**\n * Checks point is inside the object.\n * @param {Object} [pointer] x,y object of point coordinates we want to check.\n * @param {fabric.Object} obj Object to test against\n * @param {Object} [globalPointer] x,y object of point coordinates relative to canvas used to search per pixel target.\n * @return {Boolean} true if point is contained within an area of given object\n * @private\n */\n _checkTarget: function(pointer, obj, globalPointer) {\n if (obj &&\n obj.visible &&\n obj.evented &&\n // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html\n // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html\n obj.containsPoint(pointer)\n ) {\n if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) {\n var isTransparent = this.isTargetTransparent(obj, globalPointer.x, globalPointer.y);\n if (!isTransparent) {\n return true;\n }\n }\n else {\n return true;\n }\n }\n },\n\n /**\n * Function used to search inside objects an object that contains pointer in bounding box or that contains pointerOnCanvas when painted\n * @param {Array} [objects] objects array to look into\n * @param {Object} [pointer] x,y object of point coordinates we want to check.\n * @return {fabric.Object} object that contains pointer\n * @private\n */\n _searchPossibleTargets: function(objects, pointer) {\n // Cache all targets where their bounding box contains point.\n var target, i = objects.length, subTarget;\n // Do not check for currently grouped objects, since we check the parent group itself.\n // until we call this function specifically to search inside the activeGroup\n while (i--) {\n var objToCheck = objects[i];\n var pointerToUse = objToCheck.group ?\n this._normalizePointer(objToCheck.group, pointer) : pointer;\n if (this._checkTarget(pointerToUse, objToCheck, pointer)) {\n target = objects[i];\n if (target.subTargetCheck && target instanceof fabric.Group) {\n subTarget = this._searchPossibleTargets(target._objects, pointer);\n subTarget && this.targets.push(subTarget);\n }\n break;\n }\n }\n return target;\n },\n\n /**\n * Returns pointer coordinates without the effect of the viewport\n * @param {Object} pointer with \"x\" and \"y\" number values\n * @return {Object} object with \"x\" and \"y\" number values\n */\n restorePointerVpt: function(pointer) {\n return fabric.util.transformPoint(\n pointer,\n fabric.util.invertTransform(this.viewportTransform)\n );\n },\n\n /**\n * Returns pointer coordinates relative to canvas.\n * Can return coordinates with or without viewportTransform.\n * ignoreZoom false gives back coordinates that represent\n * the point clicked on canvas element.\n * ignoreZoom true gives back coordinates after being processed\n * by the viewportTransform ( sort of coordinates of what is displayed\n * on the canvas where you are clicking.\n * ignoreZoom true = HTMLElement coordinates relative to top,left\n * ignoreZoom false, default = fabric space coordinates, the same used for shape position\n * To interact with your shapes top and left you want to use ignoreZoom true\n * most of the time, while ignoreZoom false will give you coordinates\n * compatible with the object.oCoords system.\n * of the time.\n * @param {Event} e\n * @param {Boolean} ignoreZoom\n * @return {Object} object with \"x\" and \"y\" number values\n */\n getPointer: function (e, ignoreZoom) {\n // return cached values if we are in the event processing chain\n if (this._absolutePointer && !ignoreZoom) {\n return this._absolutePointer;\n }\n if (this._pointer && ignoreZoom) {\n return this._pointer;\n }\n\n var pointer = getPointer(e),\n upperCanvasEl = this.upperCanvasEl,\n bounds = upperCanvasEl.getBoundingClientRect(),\n boundsWidth = bounds.width || 0,\n boundsHeight = bounds.height || 0,\n cssScale;\n\n if (!boundsWidth || !boundsHeight ) {\n if ('top' in bounds && 'bottom' in bounds) {\n boundsHeight = Math.abs( bounds.top - bounds.bottom );\n }\n if ('right' in bounds && 'left' in bounds) {\n boundsWidth = Math.abs( bounds.right - bounds.left );\n }\n }\n\n this.calcOffset();\n pointer.x = pointer.x - this._offset.left;\n pointer.y = pointer.y - this._offset.top;\n if (!ignoreZoom) {\n pointer = this.restorePointerVpt(pointer);\n }\n\n var retinaScaling = this.getRetinaScaling();\n if (retinaScaling !== 1) {\n pointer.x /= retinaScaling;\n pointer.y /= retinaScaling;\n }\n\n if (boundsWidth === 0 || boundsHeight === 0) {\n // If bounds are not available (i.e. not visible), do not apply scale.\n cssScale = { width: 1, height: 1 };\n }\n else {\n cssScale = {\n width: upperCanvasEl.width / boundsWidth,\n height: upperCanvasEl.height / boundsHeight\n };\n }\n\n return {\n x: pointer.x * cssScale.width,\n y: pointer.y * cssScale.height\n };\n },\n\n /**\n * @private\n * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized\n */\n _createUpperCanvas: function () {\n var lowerCanvasClass = this.lowerCanvasEl.className.replace(/\\s*lower-canvas\\s*/, ''),\n lowerCanvasEl = this.lowerCanvasEl, upperCanvasEl = this.upperCanvasEl;\n\n // there is no need to create a new upperCanvas element if we have already one.\n if (upperCanvasEl) {\n upperCanvasEl.className = '';\n }\n else {\n upperCanvasEl = this._createCanvasElement();\n this.upperCanvasEl = upperCanvasEl;\n }\n fabric.util.addClass(upperCanvasEl, 'upper-canvas ' + lowerCanvasClass);\n\n this.wrapperEl.appendChild(upperCanvasEl);\n\n this._copyCanvasStyle(lowerCanvasEl, upperCanvasEl);\n this._applyCanvasStyle(upperCanvasEl);\n this.contextTop = upperCanvasEl.getContext('2d');\n },\n\n /**\n * Returns context of top canvas where interactions are drawn\n * @returns {CanvasRenderingContext2D}\n */\n getTopContext: function () {\n return this.contextTop;\n },\n\n /**\n * @private\n */\n _createCacheCanvas: function () {\n this.cacheCanvasEl = this._createCanvasElement();\n this.cacheCanvasEl.setAttribute('width', this.width);\n this.cacheCanvasEl.setAttribute('height', this.height);\n this.contextCache = this.cacheCanvasEl.getContext('2d');\n },\n\n /**\n * @private\n */\n _initWrapperElement: function () {\n this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', {\n 'class': this.containerClass\n });\n fabric.util.setStyle(this.wrapperEl, {\n width: this.width + 'px',\n height: this.height + 'px',\n position: 'relative'\n });\n fabric.util.makeElementUnselectable(this.wrapperEl);\n },\n\n /**\n * @private\n * @param {HTMLElement} element canvas element to apply styles on\n */\n _applyCanvasStyle: function (element) {\n var width = this.width || element.width,\n height = this.height || element.height;\n\n fabric.util.setStyle(element, {\n position: 'absolute',\n width: width + 'px',\n height: height + 'px',\n left: 0,\n top: 0,\n 'touch-action': this.allowTouchScrolling ? 'manipulation' : 'none',\n '-ms-touch-action': this.allowTouchScrolling ? 'manipulation' : 'none'\n });\n element.width = width;\n element.height = height;\n fabric.util.makeElementUnselectable(element);\n },\n\n /**\n * Copy the entire inline style from one element (fromEl) to another (toEl)\n * @private\n * @param {Element} fromEl Element style is copied from\n * @param {Element} toEl Element copied style is applied to\n */\n _copyCanvasStyle: function (fromEl, toEl) {\n toEl.style.cssText = fromEl.style.cssText;\n },\n\n /**\n * Returns context of canvas where object selection is drawn\n * @return {CanvasRenderingContext2D}\n */\n getSelectionContext: function() {\n return this.contextTop;\n },\n\n /**\n * Returns <canvas> element on which object selection is drawn\n * @return {HTMLCanvasElement}\n */\n getSelectionElement: function () {\n return this.upperCanvasEl;\n },\n\n /**\n * Returns currently active object\n * @return {fabric.Object} active object\n */\n getActiveObject: function () {\n return this._activeObject;\n },\n\n /**\n * Returns an array with the current selected objects\n * @return {fabric.Object} active object\n */\n getActiveObjects: function () {\n var active = this._activeObject;\n if (active) {\n if (active.type === 'activeSelection' && active._objects) {\n return active._objects.slice(0);\n }\n else {\n return [active];\n }\n }\n return [];\n },\n\n /**\n * @private\n * @param {fabric.Object} obj Object that was removed\n */\n _onObjectRemoved: function(obj) {\n // removing active object should fire \"selection:cleared\" events\n if (obj === this._activeObject) {\n this.fire('before:selection:cleared', { target: obj });\n this._discardActiveObject();\n this.fire('selection:cleared', { target: obj });\n obj.fire('deselected');\n }\n if (obj === this._hoveredTarget){\n this._hoveredTarget = null;\n this._hoveredTargets = [];\n }\n this.callSuper('_onObjectRemoved', obj);\n },\n\n /**\n * @private\n * Compares the old activeObject with the current one and fires correct events\n * @param {fabric.Object} obj old activeObject\n */\n _fireSelectionEvents: function(oldObjects, e) {\n var somethingChanged = false, objects = this.getActiveObjects(),\n added = [], removed = [];\n oldObjects.forEach(function(oldObject) {\n if (objects.indexOf(oldObject) === -1) {\n somethingChanged = true;\n oldObject.fire('deselected', {\n e: e,\n target: oldObject\n });\n removed.push(oldObject);\n }\n });\n objects.forEach(function(object) {\n if (oldObjects.indexOf(object) === -1) {\n somethingChanged = true;\n object.fire('selected', {\n e: e,\n target: object\n });\n added.push(object);\n }\n });\n if (oldObjects.length > 0 && objects.length > 0) {\n somethingChanged && this.fire('selection:updated', {\n e: e,\n selected: added,\n deselected: removed,\n });\n }\n else if (objects.length > 0) {\n this.fire('selection:created', {\n e: e,\n selected: added,\n });\n }\n else if (oldObjects.length > 0) {\n this.fire('selection:cleared', {\n e: e,\n deselected: removed,\n });\n }\n },\n\n /**\n * Sets given object as the only active object on canvas\n * @param {fabric.Object} object Object to set as an active one\n * @param {Event} [e] Event (passed along when firing \"object:selected\")\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n setActiveObject: function (object, e) {\n var currentActives = this.getActiveObjects();\n this._setActiveObject(object, e);\n this._fireSelectionEvents(currentActives, e);\n return this;\n },\n\n /**\n * This is a private method for now.\n * This is supposed to be equivalent to setActiveObject but without firing\n * any event. There is commitment to have this stay this way.\n * This is the functional part of setActiveObject.\n * @private\n * @param {Object} object to set as active\n * @param {Event} [e] Event (passed along when firing \"object:selected\")\n * @return {Boolean} true if the selection happened\n */\n _setActiveObject: function(object, e) {\n if (this._activeObject === object) {\n return false;\n }\n if (!this._discardActiveObject(e, object)) {\n return false;\n }\n if (object.onSelect({ e: e })) {\n return false;\n }\n this._activeObject = object;\n return true;\n },\n\n /**\n * This is a private method for now.\n * This is supposed to be equivalent to discardActiveObject but without firing\n * any events. There is commitment to have this stay this way.\n * This is the functional part of discardActiveObject.\n * @param {Event} [e] Event (passed along when firing \"object:deselected\")\n * @param {Object} object to set as active\n * @return {Boolean} true if the selection happened\n * @private\n */\n _discardActiveObject: function(e, object) {\n var obj = this._activeObject;\n if (obj) {\n // onDeselect return TRUE to cancel selection;\n if (obj.onDeselect({ e: e, object: object })) {\n return false;\n }\n this._activeObject = null;\n }\n return true;\n },\n\n /**\n * Discards currently active object and fire events. If the function is called by fabric\n * as a consequence of a mouse event, the event is passed as a parameter and\n * sent to the fire function for the custom events. When used as a method the\n * e param does not have any application.\n * @param {event} e\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n discardActiveObject: function (e) {\n var currentActives = this.getActiveObjects(), activeObject = this.getActiveObject();\n if (currentActives.length) {\n this.fire('before:selection:cleared', { target: activeObject, e: e });\n }\n this._discardActiveObject(e);\n this._fireSelectionEvents(currentActives, e);\n return this;\n },\n\n /**\n * Clears a canvas element and removes all event listeners\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n dispose: function () {\n var wrapper = this.wrapperEl;\n this.removeListeners();\n wrapper.removeChild(this.upperCanvasEl);\n wrapper.removeChild(this.lowerCanvasEl);\n this.contextCache = null;\n this.contextTop = null;\n ['upperCanvasEl', 'cacheCanvasEl'].forEach((function(element) {\n fabric.util.cleanUpJsdomNode(this[element]);\n this[element] = undefined;\n }).bind(this));\n if (wrapper.parentNode) {\n wrapper.parentNode.replaceChild(this.lowerCanvasEl, this.wrapperEl);\n }\n delete this.wrapperEl;\n fabric.StaticCanvas.prototype.dispose.call(this);\n return this;\n },\n\n /**\n * Clears all contexts (background, main, top) of an instance\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n clear: function () {\n // this.discardActiveGroup();\n this.discardActiveObject();\n this.clearContext(this.contextTop);\n return this.callSuper('clear');\n },\n\n /**\n * Draws objects' controls (borders/controls)\n * @param {CanvasRenderingContext2D} ctx Context to render controls on\n */\n drawControls: function(ctx) {\n var activeObject = this._activeObject;\n\n if (activeObject) {\n activeObject._renderControls(ctx);\n }\n },\n\n /**\n * @private\n */\n _toObject: function(instance, methodName, propertiesToInclude) {\n //If the object is part of the current selection group, it should\n //be transformed appropriately\n //i.e. it should be serialised as it would appear if the selection group\n //were to be destroyed.\n var originalProperties = this._realizeGroupTransformOnObject(instance),\n object = this.callSuper('_toObject', instance, methodName, propertiesToInclude);\n //Undo the damage we did by changing all of its properties\n this._unwindGroupTransformOnObject(instance, originalProperties);\n return object;\n },\n\n /**\n * Realises an object's group transformation on it\n * @private\n * @param {fabric.Object} [instance] the object to transform (gets mutated)\n * @returns the original values of instance which were changed\n */\n _realizeGroupTransformOnObject: function(instance) {\n if (instance.group && instance.group.type === 'activeSelection' && this._activeObject === instance.group) {\n var layoutProps = ['angle', 'flipX', 'flipY', 'left', 'scaleX', 'scaleY', 'skewX', 'skewY', 'top'];\n //Copy all the positionally relevant properties across now\n var originalValues = {};\n layoutProps.forEach(function(prop) {\n originalValues[prop] = instance[prop];\n });\n fabric.util.addTransformToObject(instance, this._activeObject.calcOwnMatrix());\n return originalValues;\n }\n else {\n return null;\n }\n },\n\n /**\n * Restores the changed properties of instance\n * @private\n * @param {fabric.Object} [instance] the object to un-transform (gets mutated)\n * @param {Object} [originalValues] the original values of instance, as returned by _realizeGroupTransformOnObject\n */\n _unwindGroupTransformOnObject: function(instance, originalValues) {\n if (originalValues) {\n instance.set(originalValues);\n }\n },\n\n /**\n * @private\n */\n _setSVGObject: function(markup, instance, reviver) {\n //If the object is in a selection group, simulate what would happen to that\n //object when the group is deselected\n var originalProperties = this._realizeGroupTransformOnObject(instance);\n this.callSuper('_setSVGObject', markup, instance, reviver);\n this._unwindGroupTransformOnObject(instance, originalProperties);\n },\n\n setViewportTransform: function (vpt) {\n if (this.renderOnAddRemove && this._activeObject && this._activeObject.isEditing) {\n this._activeObject.clearContextTop();\n }\n fabric.StaticCanvas.prototype.setViewportTransform.call(this, vpt);\n }\n });\n\n // copying static properties manually to work around Opera's bug,\n // where \"prototype\" property is enumerable and overrides existing prototype\n for (var prop in fabric.StaticCanvas) {\n if (prop !== 'prototype') {\n fabric.Canvas[prop] = fabric.StaticCanvas[prop];\n }\n }\n})();\n\n\n(function() {\n\n var addListener = fabric.util.addListener,\n removeListener = fabric.util.removeListener,\n RIGHT_CLICK = 3, MIDDLE_CLICK = 2, LEFT_CLICK = 1,\n addEventOptions = { passive: false };\n\n function checkClick(e, value) {\n return e.button && (e.button === value - 1);\n }\n\n fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ {\n\n /**\n * Contains the id of the touch event that owns the fabric transform\n * @type Number\n * @private\n */\n mainTouchId: null,\n\n /**\n * Adds mouse listeners to canvas\n * @private\n */\n _initEventListeners: function () {\n // in case we initialized the class twice. This should not happen normally\n // but in some kind of applications where the canvas element may be changed\n // this is a workaround to having double listeners.\n this.removeListeners();\n this._bindEvents();\n this.addOrRemove(addListener, 'add');\n },\n\n /**\n * return an event prefix pointer or mouse.\n * @private\n */\n _getEventPrefix: function () {\n return this.enablePointerEvents ? 'pointer' : 'mouse';\n },\n\n addOrRemove: function(functor, eventjsFunctor) {\n var canvasElement = this.upperCanvasEl,\n eventTypePrefix = this._getEventPrefix();\n functor(fabric.window, 'resize', this._onResize);\n functor(canvasElement, eventTypePrefix + 'down', this._onMouseDown);\n functor(canvasElement, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n functor(canvasElement, eventTypePrefix + 'out', this._onMouseOut);\n functor(canvasElement, eventTypePrefix + 'enter', this._onMouseEnter);\n functor(canvasElement, 'wheel', this._onMouseWheel);\n functor(canvasElement, 'contextmenu', this._onContextMenu);\n functor(canvasElement, 'dblclick', this._onDoubleClick);\n functor(canvasElement, 'dragover', this._onDragOver);\n functor(canvasElement, 'dragenter', this._onDragEnter);\n functor(canvasElement, 'dragleave', this._onDragLeave);\n functor(canvasElement, 'drop', this._onDrop);\n if (!this.enablePointerEvents) {\n functor(canvasElement, 'touchstart', this._onTouchStart, addEventOptions);\n }\n if (typeof eventjs !== 'undefined' && eventjsFunctor in eventjs) {\n eventjs[eventjsFunctor](canvasElement, 'gesture', this._onGesture);\n eventjs[eventjsFunctor](canvasElement, 'drag', this._onDrag);\n eventjs[eventjsFunctor](canvasElement, 'orientation', this._onOrientationChange);\n eventjs[eventjsFunctor](canvasElement, 'shake', this._onShake);\n eventjs[eventjsFunctor](canvasElement, 'longpress', this._onLongPress);\n }\n },\n\n /**\n * Removes all event listeners\n */\n removeListeners: function() {\n this.addOrRemove(removeListener, 'remove');\n // if you dispose on a mouseDown, before mouse up, you need to clean document to...\n var eventTypePrefix = this._getEventPrefix();\n removeListener(fabric.document, eventTypePrefix + 'up', this._onMouseUp);\n removeListener(fabric.document, 'touchend', this._onTouchEnd, addEventOptions);\n removeListener(fabric.document, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n removeListener(fabric.document, 'touchmove', this._onMouseMove, addEventOptions);\n },\n\n /**\n * @private\n */\n _bindEvents: function() {\n if (this.eventsBound) {\n // for any reason we pass here twice we do not want to bind events twice.\n return;\n }\n this._onMouseDown = this._onMouseDown.bind(this);\n this._onTouchStart = this._onTouchStart.bind(this);\n this._onMouseMove = this._onMouseMove.bind(this);\n this._onMouseUp = this._onMouseUp.bind(this);\n this._onTouchEnd = this._onTouchEnd.bind(this);\n this._onResize = this._onResize.bind(this);\n this._onGesture = this._onGesture.bind(this);\n this._onDrag = this._onDrag.bind(this);\n this._onShake = this._onShake.bind(this);\n this._onLongPress = this._onLongPress.bind(this);\n this._onOrientationChange = this._onOrientationChange.bind(this);\n this._onMouseWheel = this._onMouseWheel.bind(this);\n this._onMouseOut = this._onMouseOut.bind(this);\n this._onMouseEnter = this._onMouseEnter.bind(this);\n this._onContextMenu = this._onContextMenu.bind(this);\n this._onDoubleClick = this._onDoubleClick.bind(this);\n this._onDragOver = this._onDragOver.bind(this);\n this._onDragEnter = this._simpleEventHandler.bind(this, 'dragenter');\n this._onDragLeave = this._simpleEventHandler.bind(this, 'dragleave');\n this._onDrop = this._onDrop.bind(this);\n this.eventsBound = true;\n },\n\n /**\n * @private\n * @param {Event} [e] Event object fired on Event.js gesture\n * @param {Event} [self] Inner Event object\n */\n _onGesture: function(e, self) {\n this.__onTransformGesture && this.__onTransformGesture(e, self);\n },\n\n /**\n * @private\n * @param {Event} [e] Event object fired on Event.js drag\n * @param {Event} [self] Inner Event object\n */\n _onDrag: function(e, self) {\n this.__onDrag && this.__onDrag(e, self);\n },\n\n /**\n * @private\n * @param {Event} [e] Event object fired on wheel event\n */\n _onMouseWheel: function(e) {\n this.__onMouseWheel(e);\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onMouseOut: function(e) {\n var target = this._hoveredTarget;\n this.fire('mouse:out', { target: target, e: e });\n this._hoveredTarget = null;\n target && target.fire('mouseout', { e: e });\n\n var _this = this;\n this._hoveredTargets.forEach(function(_target){\n _this.fire('mouse:out', { target: _target, e: e });\n _target && _target.fire('mouseout', { e: e });\n });\n this._hoveredTargets = [];\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mouseenter\n */\n _onMouseEnter: function(e) {\n // This find target and consequent 'mouse:over' is used to\n // clear old instances on hovered target.\n // calling findTarget has the side effect of killing target.__corner.\n // as a short term fix we are not firing this if we are currently transforming.\n // as a long term fix we need to separate the action of finding a target with the\n // side effects we added to it.\n if (!this._currentTransform && !this.findTarget(e)) {\n this.fire('mouse:over', { target: null, e: e });\n this._hoveredTarget = null;\n this._hoveredTargets = [];\n }\n },\n\n /**\n * @private\n * @param {Event} [e] Event object fired on Event.js orientation change\n * @param {Event} [self] Inner Event object\n */\n _onOrientationChange: function(e, self) {\n this.__onOrientationChange && this.__onOrientationChange(e, self);\n },\n\n /**\n * @private\n * @param {Event} [e] Event object fired on Event.js shake\n * @param {Event} [self] Inner Event object\n */\n _onShake: function(e, self) {\n this.__onShake && this.__onShake(e, self);\n },\n\n /**\n * @private\n * @param {Event} [e] Event object fired on Event.js shake\n * @param {Event} [self] Inner Event object\n */\n _onLongPress: function(e, self) {\n this.__onLongPress && this.__onLongPress(e, self);\n },\n\n /**\n * prevent default to allow drop event to be fired\n * @private\n * @param {Event} [e] Event object fired on Event.js shake\n */\n _onDragOver: function(e) {\n e.preventDefault();\n var target = this._simpleEventHandler('dragover', e);\n this._fireEnterLeaveEvents(target, e);\n },\n\n /**\n * `drop:before` is a an event that allow you to schedule logic\n * before the `drop` event. Prefer `drop` event always, but if you need\n * to run some drop-disabling logic on an event, since there is no way\n * to handle event handlers ordering, use `drop:before`\n * @param {Event} e\n */\n _onDrop: function (e) {\n this._simpleEventHandler('drop:before', e);\n return this._simpleEventHandler('drop', e);\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onContextMenu: function (e) {\n if (this.stopContextMenu) {\n e.stopPropagation();\n e.preventDefault();\n }\n return false;\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onDoubleClick: function (e) {\n this._cacheTransformEventData(e);\n this._handleEvent(e, 'dblclick');\n this._resetTransformEventData(e);\n },\n\n /**\n * Return a the id of an event.\n * returns either the pointerId or the identifier or 0 for the mouse event\n * @private\n * @param {Event} evt Event object\n */\n getPointerId: function(evt) {\n var changedTouches = evt.changedTouches;\n\n if (changedTouches) {\n return changedTouches[0] && changedTouches[0].identifier;\n }\n\n if (this.enablePointerEvents) {\n return evt.pointerId;\n }\n\n return -1;\n },\n\n /**\n * Determines if an event has the id of the event that is considered main\n * @private\n * @param {evt} event Event object\n */\n _isMainEvent: function(evt) {\n if (evt.isPrimary === true) {\n return true;\n }\n if (evt.isPrimary === false) {\n return false;\n }\n if (evt.type === 'touchend' && evt.touches.length === 0) {\n return true;\n }\n if (evt.changedTouches) {\n return evt.changedTouches[0].identifier === this.mainTouchId;\n }\n return true;\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onTouchStart: function(e) {\n e.preventDefault();\n if (this.mainTouchId === null) {\n this.mainTouchId = this.getPointerId(e);\n }\n this.__onMouseDown(e);\n this._resetTransformEventData();\n var canvasElement = this.upperCanvasEl,\n eventTypePrefix = this._getEventPrefix();\n addListener(fabric.document, 'touchend', this._onTouchEnd, addEventOptions);\n addListener(fabric.document, 'touchmove', this._onMouseMove, addEventOptions);\n // Unbind mousedown to prevent double triggers from touch devices\n removeListener(canvasElement, eventTypePrefix + 'down', this._onMouseDown);\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onMouseDown: function (e) {\n this.__onMouseDown(e);\n this._resetTransformEventData();\n var canvasElement = this.upperCanvasEl,\n eventTypePrefix = this._getEventPrefix();\n removeListener(canvasElement, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n addListener(fabric.document, eventTypePrefix + 'up', this._onMouseUp);\n addListener(fabric.document, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onTouchEnd: function(e) {\n if (e.touches.length > 0) {\n // if there are still touches stop here\n return;\n }\n this.__onMouseUp(e);\n this._resetTransformEventData();\n this.mainTouchId = null;\n var eventTypePrefix = this._getEventPrefix();\n removeListener(fabric.document, 'touchend', this._onTouchEnd, addEventOptions);\n removeListener(fabric.document, 'touchmove', this._onMouseMove, addEventOptions);\n var _this = this;\n if (this._willAddMouseDown) {\n clearTimeout(this._willAddMouseDown);\n }\n this._willAddMouseDown = setTimeout(function() {\n // Wait 400ms before rebinding mousedown to prevent double triggers\n // from touch devices\n addListener(_this.upperCanvasEl, eventTypePrefix + 'down', _this._onMouseDown);\n _this._willAddMouseDown = 0;\n }, 400);\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mouseup\n */\n _onMouseUp: function (e) {\n this.__onMouseUp(e);\n this._resetTransformEventData();\n var canvasElement = this.upperCanvasEl,\n eventTypePrefix = this._getEventPrefix();\n if (this._isMainEvent(e)) {\n removeListener(fabric.document, eventTypePrefix + 'up', this._onMouseUp);\n removeListener(fabric.document, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n addListener(canvasElement, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousemove\n */\n _onMouseMove: function (e) {\n !this.allowTouchScrolling && e.preventDefault && e.preventDefault();\n this.__onMouseMove(e);\n },\n\n /**\n * @private\n */\n _onResize: function () {\n this.calcOffset();\n },\n\n /**\n * Decides whether the canvas should be redrawn in mouseup and mousedown events.\n * @private\n * @param {Object} target\n */\n _shouldRender: function(target) {\n var activeObject = this._activeObject;\n\n if (\n !!activeObject !== !!target ||\n (activeObject && target && (activeObject !== target))\n ) {\n // this covers: switch of target, from target to no target, selection of target\n // multiSelection with key and mouse\n return true;\n }\n else if (activeObject && activeObject.isEditing) {\n // if we mouse up/down over a editing textbox a cursor change,\n // there is no need to re render\n return false;\n }\n return false;\n },\n\n /**\n * Method that defines the actions when mouse is released on canvas.\n * The method resets the currentTransform parameters, store the image corner\n * position in the image object and render the canvas on top.\n * @private\n * @param {Event} e Event object fired on mouseup\n */\n __onMouseUp: function (e) {\n var target, transform = this._currentTransform,\n groupSelector = this._groupSelector, shouldRender = false,\n isClick = (!groupSelector || (groupSelector.left === 0 && groupSelector.top === 0));\n this._cacheTransformEventData(e);\n target = this._target;\n this._handleEvent(e, 'up:before');\n // if right/middle click just fire events and return\n // target undefined will make the _handleEvent search the target\n if (checkClick(e, RIGHT_CLICK)) {\n if (this.fireRightClick) {\n this._handleEvent(e, 'up', RIGHT_CLICK, isClick);\n }\n return;\n }\n\n if (checkClick(e, MIDDLE_CLICK)) {\n if (this.fireMiddleClick) {\n this._handleEvent(e, 'up', MIDDLE_CLICK, isClick);\n }\n this._resetTransformEventData();\n return;\n }\n\n if (this.isDrawingMode && this._isCurrentlyDrawing) {\n this._onMouseUpInDrawingMode(e);\n return;\n }\n\n if (!this._isMainEvent(e)) {\n return;\n }\n if (transform) {\n this._finalizeCurrentTransform(e);\n shouldRender = transform.actionPerformed;\n }\n if (!isClick) {\n var targetWasActive = target === this._activeObject;\n this._maybeGroupObjects(e);\n if (!shouldRender) {\n shouldRender = (\n this._shouldRender(target) ||\n (!targetWasActive && target === this._activeObject)\n );\n }\n }\n var corner, pointer;\n if (target) {\n corner = target._findTargetCorner(\n this.getPointer(e, true),\n fabric.util.isTouchEvent(e)\n );\n if (target.selectable && target !== this._activeObject && target.activeOn === 'up') {\n this.setActiveObject(target, e);\n shouldRender = true;\n }\n else {\n var control = target.controls[corner],\n mouseUpHandler = control && control.getMouseUpHandler(e, target, control);\n if (mouseUpHandler) {\n pointer = this.getPointer(e);\n mouseUpHandler(e, transform, pointer.x, pointer.y);\n }\n }\n target.isMoving = false;\n }\n // if we are ending up a transform on a different control or a new object\n // fire the original mouse up from the corner that started the transform\n if (transform && (transform.target !== target || transform.corner !== corner)) {\n var originalControl = transform.target && transform.target.controls[transform.corner],\n originalMouseUpHandler = originalControl && originalControl.getMouseUpHandler(e, target, control);\n pointer = pointer || this.getPointer(e);\n originalMouseUpHandler && originalMouseUpHandler(e, transform, pointer.x, pointer.y);\n }\n this._setCursorFromEvent(e, target);\n this._handleEvent(e, 'up', LEFT_CLICK, isClick);\n this._groupSelector = null;\n this._currentTransform = null;\n // reset the target information about which corner is selected\n target && (target.__corner = 0);\n if (shouldRender) {\n this.requestRenderAll();\n }\n else if (!isClick) {\n this.renderTop();\n }\n },\n\n /**\n * @private\n * Handle event firing for target and subtargets\n * @param {Event} e event from mouse\n * @param {String} eventType event to fire (up, down or move)\n * @return {Fabric.Object} target return the the target found, for internal reasons.\n */\n _simpleEventHandler: function(eventType, e) {\n var target = this.findTarget(e),\n targets = this.targets,\n options = {\n e: e,\n target: target,\n subTargets: targets,\n };\n this.fire(eventType, options);\n target && target.fire(eventType, options);\n if (!targets) {\n return target;\n }\n for (var i = 0; i < targets.length; i++) {\n targets[i].fire(eventType, options);\n }\n return target;\n },\n\n /**\n * @private\n * Handle event firing for target and subtargets\n * @param {Event} e event from mouse\n * @param {String} eventType event to fire (up, down or move)\n * @param {fabric.Object} targetObj receiving event\n * @param {Number} [button] button used in the event 1 = left, 2 = middle, 3 = right\n * @param {Boolean} isClick for left button only, indicates that the mouse up happened without move.\n */\n _handleEvent: function(e, eventType, button, isClick) {\n var target = this._target,\n targets = this.targets || [],\n options = {\n e: e,\n target: target,\n subTargets: targets,\n button: button || LEFT_CLICK,\n isClick: isClick || false,\n pointer: this._pointer,\n absolutePointer: this._absolutePointer,\n transform: this._currentTransform\n };\n if (eventType === 'up') {\n options.currentTarget = this.findTarget(e);\n options.currentSubTargets = this.targets;\n }\n this.fire('mouse:' + eventType, options);\n target && target.fire('mouse' + eventType, options);\n for (var i = 0; i < targets.length; i++) {\n targets[i].fire('mouse' + eventType, options);\n }\n },\n\n /**\n * @private\n * @param {Event} e send the mouse event that generate the finalize down, so it can be used in the event\n */\n _finalizeCurrentTransform: function(e) {\n\n var transform = this._currentTransform,\n target = transform.target,\n options = {\n e: e,\n target: target,\n transform: transform,\n action: transform.action,\n };\n\n if (target._scaling) {\n target._scaling = false;\n }\n\n target.setCoords();\n\n if (transform.actionPerformed || (this.stateful && target.hasStateChanged())) {\n this._fire('modified', options);\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onMouseDownInDrawingMode: function(e) {\n this._isCurrentlyDrawing = true;\n if (this.getActiveObject()) {\n this.discardActiveObject(e).requestRenderAll();\n }\n var pointer = this.getPointer(e);\n this.freeDrawingBrush.onMouseDown(pointer, { e: e, pointer: pointer });\n this._handleEvent(e, 'down');\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousemove\n */\n _onMouseMoveInDrawingMode: function(e) {\n if (this._isCurrentlyDrawing) {\n var pointer = this.getPointer(e);\n this.freeDrawingBrush.onMouseMove(pointer, { e: e, pointer: pointer });\n }\n this.setCursor(this.freeDrawingCursor);\n this._handleEvent(e, 'move');\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mouseup\n */\n _onMouseUpInDrawingMode: function(e) {\n var pointer = this.getPointer(e);\n this._isCurrentlyDrawing = this.freeDrawingBrush.onMouseUp({ e: e, pointer: pointer });\n this._handleEvent(e, 'up');\n },\n\n /**\n * Method that defines the actions when mouse is clicked on canvas.\n * The method inits the currentTransform parameters and renders all the\n * canvas so the current image can be placed on the top canvas and the rest\n * in on the container one.\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n __onMouseDown: function (e) {\n this._cacheTransformEventData(e);\n this._handleEvent(e, 'down:before');\n var target = this._target;\n // if right click just fire events\n if (checkClick(e, RIGHT_CLICK)) {\n if (this.fireRightClick) {\n this._handleEvent(e, 'down', RIGHT_CLICK);\n }\n return;\n }\n\n if (checkClick(e, MIDDLE_CLICK)) {\n if (this.fireMiddleClick) {\n this._handleEvent(e, 'down', MIDDLE_CLICK);\n }\n return;\n }\n\n if (this.isDrawingMode) {\n this._onMouseDownInDrawingMode(e);\n return;\n }\n\n if (!this._isMainEvent(e)) {\n return;\n }\n\n // ignore if some object is being transformed at this moment\n if (this._currentTransform) {\n return;\n }\n\n var pointer = this._pointer;\n // save pointer for check in __onMouseUp event\n this._previousPointer = pointer;\n var shouldRender = this._shouldRender(target),\n shouldGroup = this._shouldGroup(e, target);\n if (this._shouldClearSelection(e, target)) {\n this.discardActiveObject(e);\n }\n else if (shouldGroup) {\n this._handleGrouping(e, target);\n target = this._activeObject;\n }\n\n if (this.selection && (!target ||\n (!target.selectable && !target.isEditing && target !== this._activeObject))) {\n this._groupSelector = {\n ex: this._absolutePointer.x,\n ey: this._absolutePointer.y,\n top: 0,\n left: 0\n };\n }\n\n if (target) {\n var alreadySelected = target === this._activeObject;\n if (target.selectable && target.activeOn === 'down') {\n this.setActiveObject(target, e);\n }\n var corner = target._findTargetCorner(\n this.getPointer(e, true),\n fabric.util.isTouchEvent(e)\n );\n target.__corner = corner;\n if (target === this._activeObject && (corner || !shouldGroup)) {\n this._setupCurrentTransform(e, target, alreadySelected);\n var control = target.controls[corner],\n pointer = this.getPointer(e),\n mouseDownHandler = control && control.getMouseDownHandler(e, target, control);\n if (mouseDownHandler) {\n mouseDownHandler(e, this._currentTransform, pointer.x, pointer.y);\n }\n }\n }\n this._handleEvent(e, 'down');\n // we must renderAll so that we update the visuals\n (shouldRender || shouldGroup) && this.requestRenderAll();\n },\n\n /**\n * reset cache form common information needed during event processing\n * @private\n */\n _resetTransformEventData: function() {\n this._target = null;\n this._pointer = null;\n this._absolutePointer = null;\n },\n\n /**\n * Cache common information needed during event processing\n * @private\n * @param {Event} e Event object fired on event\n */\n _cacheTransformEventData: function(e) {\n // reset in order to avoid stale caching\n this._resetTransformEventData();\n this._pointer = this.getPointer(e, true);\n this._absolutePointer = this.restorePointerVpt(this._pointer);\n this._target = this._currentTransform ? this._currentTransform.target : this.findTarget(e) || null;\n },\n\n /**\n * @private\n */\n _beforeTransform: function(e) {\n var t = this._currentTransform;\n this.stateful && t.target.saveState();\n this.fire('before:transform', {\n e: e,\n transform: t,\n });\n },\n\n /**\n * Method that defines the actions when mouse is hovering the canvas.\n * The currentTransform parameter will define whether the user is rotating/scaling/translating\n * an image or neither of them (only hovering). A group selection is also possible and would cancel\n * all any other type of action.\n * In case of an image transformation only the top canvas will be rendered.\n * @private\n * @param {Event} e Event object fired on mousemove\n */\n __onMouseMove: function (e) {\n this._handleEvent(e, 'move:before');\n this._cacheTransformEventData(e);\n var target, pointer;\n\n if (this.isDrawingMode) {\n this._onMouseMoveInDrawingMode(e);\n return;\n }\n\n if (!this._isMainEvent(e)) {\n return;\n }\n\n var groupSelector = this._groupSelector;\n\n // We initially clicked in an empty area, so we draw a box for multiple selection\n if (groupSelector) {\n pointer = this._absolutePointer;\n\n groupSelector.left = pointer.x - groupSelector.ex;\n groupSelector.top = pointer.y - groupSelector.ey;\n\n this.renderTop();\n }\n else if (!this._currentTransform) {\n target = this.findTarget(e) || null;\n this._setCursorFromEvent(e, target);\n this._fireOverOutEvents(target, e);\n }\n else {\n this._transformObject(e);\n }\n this._handleEvent(e, 'move');\n this._resetTransformEventData();\n },\n\n /**\n * Manage the mouseout, mouseover events for the fabric object on the canvas\n * @param {Fabric.Object} target the target where the target from the mousemove event\n * @param {Event} e Event object fired on mousemove\n * @private\n */\n _fireOverOutEvents: function(target, e) {\n var _hoveredTarget = this._hoveredTarget,\n _hoveredTargets = this._hoveredTargets, targets = this.targets,\n length = Math.max(_hoveredTargets.length, targets.length);\n\n this.fireSyntheticInOutEvents(target, e, {\n oldTarget: _hoveredTarget,\n evtOut: 'mouseout',\n canvasEvtOut: 'mouse:out',\n evtIn: 'mouseover',\n canvasEvtIn: 'mouse:over',\n });\n for (var i = 0; i < length; i++){\n this.fireSyntheticInOutEvents(targets[i], e, {\n oldTarget: _hoveredTargets[i],\n evtOut: 'mouseout',\n evtIn: 'mouseover',\n });\n }\n this._hoveredTarget = target;\n this._hoveredTargets = this.targets.concat();\n },\n\n /**\n * Manage the dragEnter, dragLeave events for the fabric objects on the canvas\n * @param {Fabric.Object} target the target where the target from the onDrag event\n * @param {Event} e Event object fired on ondrag\n * @private\n */\n _fireEnterLeaveEvents: function(target, e) {\n var _draggedoverTarget = this._draggedoverTarget,\n _hoveredTargets = this._hoveredTargets, targets = this.targets,\n length = Math.max(_hoveredTargets.length, targets.length);\n\n this.fireSyntheticInOutEvents(target, e, {\n oldTarget: _draggedoverTarget,\n evtOut: 'dragleave',\n evtIn: 'dragenter',\n });\n for (var i = 0; i < length; i++) {\n this.fireSyntheticInOutEvents(targets[i], e, {\n oldTarget: _hoveredTargets[i],\n evtOut: 'dragleave',\n evtIn: 'dragenter',\n });\n }\n this._draggedoverTarget = target;\n },\n\n /**\n * Manage the synthetic in/out events for the fabric objects on the canvas\n * @param {Fabric.Object} target the target where the target from the supported events\n * @param {Event} e Event object fired\n * @param {Object} config configuration for the function to work\n * @param {String} config.targetName property on the canvas where the old target is stored\n * @param {String} [config.canvasEvtOut] name of the event to fire at canvas level for out\n * @param {String} config.evtOut name of the event to fire for out\n * @param {String} [config.canvasEvtIn] name of the event to fire at canvas level for in\n * @param {String} config.evtIn name of the event to fire for in\n * @private\n */\n fireSyntheticInOutEvents: function(target, e, config) {\n var inOpt, outOpt, oldTarget = config.oldTarget, outFires, inFires,\n targetChanged = oldTarget !== target, canvasEvtIn = config.canvasEvtIn, canvasEvtOut = config.canvasEvtOut;\n if (targetChanged) {\n inOpt = { e: e, target: target, previousTarget: oldTarget };\n outOpt = { e: e, target: oldTarget, nextTarget: target };\n }\n inFires = target && targetChanged;\n outFires = oldTarget && targetChanged;\n if (outFires) {\n canvasEvtOut && this.fire(canvasEvtOut, outOpt);\n oldTarget.fire(config.evtOut, outOpt);\n }\n if (inFires) {\n canvasEvtIn && this.fire(canvasEvtIn, inOpt);\n target.fire(config.evtIn, inOpt);\n }\n },\n\n /**\n * Method that defines actions when an Event Mouse Wheel\n * @param {Event} e Event object fired on mouseup\n */\n __onMouseWheel: function(e) {\n this._cacheTransformEventData(e);\n this._handleEvent(e, 'wheel');\n this._resetTransformEventData();\n },\n\n /**\n * @private\n * @param {Event} e Event fired on mousemove\n */\n _transformObject: function(e) {\n var pointer = this.getPointer(e),\n transform = this._currentTransform;\n\n transform.reset = false;\n transform.shiftKey = e.shiftKey;\n transform.altKey = e[this.centeredKey];\n\n this._performTransformAction(e, transform, pointer);\n transform.actionPerformed && this.requestRenderAll();\n },\n\n /**\n * @private\n */\n _performTransformAction: function(e, transform, pointer) {\n var x = pointer.x,\n y = pointer.y,\n action = transform.action,\n actionPerformed = false,\n actionHandler = transform.actionHandler;\n // this object could be created from the function in the control handlers\n\n\n if (actionHandler) {\n actionPerformed = actionHandler(e, transform, x, y);\n }\n if (action === 'drag' && actionPerformed) {\n transform.target.isMoving = true;\n this.setCursor(transform.target.moveCursor || this.moveCursor);\n }\n transform.actionPerformed = transform.actionPerformed || actionPerformed;\n },\n\n /**\n * @private\n */\n _fire: fabric.controlsUtils.fireEvent,\n\n /**\n * Sets the cursor depending on where the canvas is being hovered.\n * Note: very buggy in Opera\n * @param {Event} e Event object\n * @param {Object} target Object that the mouse is hovering, if so.\n */\n _setCursorFromEvent: function (e, target) {\n if (!target) {\n this.setCursor(this.defaultCursor);\n return false;\n }\n var hoverCursor = target.hoverCursor || this.hoverCursor,\n activeSelection = this._activeObject && this._activeObject.type === 'activeSelection' ?\n this._activeObject : null,\n // only show proper corner when group selection is not active\n corner = (!activeSelection || !activeSelection.contains(target))\n // here we call findTargetCorner always with undefined for the touch parameter.\n // we assume that if you are using a cursor you do not need to interact with\n // the bigger touch area.\n && target._findTargetCorner(this.getPointer(e, true));\n\n if (!corner) {\n if (target.subTargetCheck){\n // hoverCursor should come from top-most subTarget,\n // so we walk the array backwards\n this.targets.concat().reverse().map(function(_target){\n hoverCursor = _target.hoverCursor || hoverCursor;\n });\n }\n this.setCursor(hoverCursor);\n }\n else {\n this.setCursor(this.getCornerCursor(corner, target, e));\n }\n },\n\n /**\n * @private\n */\n getCornerCursor: function(corner, target, e) {\n var control = target.controls[corner];\n return control.cursorStyleHandler(e, control, target);\n }\n });\n})();\n\n\n(function() {\n\n var min = Math.min,\n max = Math.max;\n\n fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ {\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n * @return {Boolean}\n */\n _shouldGroup: function(e, target) {\n var activeObject = this._activeObject;\n return activeObject && this._isSelectionKeyPressed(e) && target && target.selectable && this.selection &&\n (activeObject !== target || activeObject.type === 'activeSelection') && !target.onSelect({ e: e });\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n */\n _handleGrouping: function (e, target) {\n var activeObject = this._activeObject;\n // avoid multi select when shift click on a corner\n if (activeObject.__corner) {\n return;\n }\n if (target === activeObject) {\n // if it's a group, find target again, using activeGroup objects\n target = this.findTarget(e, true);\n // if even object is not found or we are on activeObjectCorner, bail out\n if (!target || !target.selectable) {\n return;\n }\n }\n if (activeObject && activeObject.type === 'activeSelection') {\n this._updateActiveSelection(target, e);\n }\n else {\n this._createActiveSelection(target, e);\n }\n },\n\n /**\n * @private\n */\n _updateActiveSelection: function(target, e) {\n var activeSelection = this._activeObject,\n currentActiveObjects = activeSelection._objects.slice(0);\n if (activeSelection.contains(target)) {\n activeSelection.removeWithUpdate(target);\n this._hoveredTarget = target;\n this._hoveredTargets = this.targets.concat();\n if (activeSelection.size() === 1) {\n // activate last remaining object\n this._setActiveObject(activeSelection.item(0), e);\n }\n }\n else {\n activeSelection.addWithUpdate(target);\n this._hoveredTarget = activeSelection;\n this._hoveredTargets = this.targets.concat();\n }\n this._fireSelectionEvents(currentActiveObjects, e);\n },\n\n /**\n * @private\n */\n _createActiveSelection: function(target, e) {\n var currentActives = this.getActiveObjects(), group = this._createGroup(target);\n this._hoveredTarget = group;\n // ISSUE 4115: should we consider subTargets here?\n // this._hoveredTargets = [];\n // this._hoveredTargets = this.targets.concat();\n this._setActiveObject(group, e);\n this._fireSelectionEvents(currentActives, e);\n },\n\n /**\n * @private\n * @param {Object} target\n */\n _createGroup: function(target) {\n var objects = this._objects,\n isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target),\n groupObjects = isActiveLower\n ? [this._activeObject, target]\n : [target, this._activeObject];\n this._activeObject.isEditing && this._activeObject.exitEditing();\n return new fabric.ActiveSelection(groupObjects, {\n canvas: this\n });\n },\n\n /**\n * @private\n * @param {Event} e mouse event\n */\n _groupSelectedObjects: function (e) {\n\n var group = this._collectObjects(e),\n aGroup;\n\n // do not create group for 1 element only\n if (group.length === 1) {\n this.setActiveObject(group[0], e);\n }\n else if (group.length > 1) {\n aGroup = new fabric.ActiveSelection(group.reverse(), {\n canvas: this\n });\n this.setActiveObject(aGroup, e);\n }\n },\n\n /**\n * @private\n */\n _collectObjects: function(e) {\n var group = [],\n currentObject,\n x1 = this._groupSelector.ex,\n y1 = this._groupSelector.ey,\n x2 = x1 + this._groupSelector.left,\n y2 = y1 + this._groupSelector.top,\n selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)),\n selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)),\n allowIntersect = !this.selectionFullyContained,\n isClick = x1 === x2 && y1 === y2;\n // we iterate reverse order to collect top first in case of click.\n for (var i = this._objects.length; i--; ) {\n currentObject = this._objects[i];\n\n if (!currentObject || !currentObject.selectable || !currentObject.visible) {\n continue;\n }\n\n if ((allowIntersect && currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2, true)) ||\n currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2, true) ||\n (allowIntersect && currentObject.containsPoint(selectionX1Y1, null, true)) ||\n (allowIntersect && currentObject.containsPoint(selectionX2Y2, null, true))\n ) {\n group.push(currentObject);\n // only add one object if it's a click\n if (isClick) {\n break;\n }\n }\n }\n\n if (group.length > 1) {\n group = group.filter(function(object) {\n return !object.onSelect({ e: e });\n });\n }\n\n return group;\n },\n\n /**\n * @private\n */\n _maybeGroupObjects: function(e) {\n if (this.selection && this._groupSelector) {\n this._groupSelectedObjects(e);\n }\n this.setCursor(this.defaultCursor);\n // clear selection and current transformation\n this._groupSelector = null;\n }\n });\n\n})();\n\n\n(function () {\n fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n /**\n * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately\n * @param {Object} [options] Options object\n * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\n * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\n * @param {Number} [options.multiplier=1] Multiplier to scale by, to have consistent\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 2.0.0\n * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format\n * @see {@link http://jsfiddle.net/fabricjs/NfZVb/|jsFiddle demo}\n * @example Generate jpeg dataURL with lower quality\n * var dataURL = canvas.toDataURL({\n * format: 'jpeg',\n * quality: 0.8\n * });\n * @example Generate cropped png dataURL (clipping of canvas)\n * var dataURL = canvas.toDataURL({\n * format: 'png',\n * left: 100,\n * top: 100,\n * width: 200,\n * height: 200\n * });\n * @example Generate double scaled png dataURL\n * var dataURL = canvas.toDataURL({\n * format: 'png',\n * multiplier: 2\n * });\n */\n toDataURL: function (options) {\n options || (options = { });\n\n var format = options.format || 'png',\n quality = options.quality || 1,\n multiplier = (options.multiplier || 1) * (options.enableRetinaScaling ? this.getRetinaScaling() : 1),\n canvasEl = this.toCanvasElement(multiplier, options);\n return fabric.util.toDataURL(canvasEl, format, quality);\n },\n\n /**\n * Create a new HTMLCanvas element painted with the current canvas content.\n * No need to resize the actual one or repaint it.\n * Will transfer object ownership to a new canvas, paint it, and set everything back.\n * This is an intermediary step used to get to a dataUrl but also it is useful to\n * create quick image copies of a canvas without passing for the dataUrl string\n * @param {Number} [multiplier] a zoom factor.\n * @param {Object} [cropping] Cropping informations\n * @param {Number} [cropping.left] Cropping left offset.\n * @param {Number} [cropping.top] Cropping top offset.\n * @param {Number} [cropping.width] Cropping width.\n * @param {Number} [cropping.height] Cropping height.\n */\n toCanvasElement: function(multiplier, cropping) {\n multiplier = multiplier || 1;\n cropping = cropping || { };\n var scaledWidth = (cropping.width || this.width) * multiplier,\n scaledHeight = (cropping.height || this.height) * multiplier,\n zoom = this.getZoom(),\n originalWidth = this.width,\n originalHeight = this.height,\n newZoom = zoom * multiplier,\n vp = this.viewportTransform,\n translateX = (vp[4] - (cropping.left || 0)) * multiplier,\n translateY = (vp[5] - (cropping.top || 0)) * multiplier,\n originalInteractive = this.interactive,\n newVp = [newZoom, 0, 0, newZoom, translateX, translateY],\n originalRetina = this.enableRetinaScaling,\n canvasEl = fabric.util.createCanvasElement(),\n originalContextTop = this.contextTop;\n canvasEl.width = scaledWidth;\n canvasEl.height = scaledHeight;\n this.contextTop = null;\n this.enableRetinaScaling = false;\n this.interactive = false;\n this.viewportTransform = newVp;\n this.width = scaledWidth;\n this.height = scaledHeight;\n this.calcViewportBoundaries();\n this.renderCanvas(canvasEl.getContext('2d'), this._objects);\n this.viewportTransform = vp;\n this.width = originalWidth;\n this.height = originalHeight;\n this.calcViewportBoundaries();\n this.interactive = originalInteractive;\n this.enableRetinaScaling = originalRetina;\n this.contextTop = originalContextTop;\n return canvasEl;\n },\n });\n\n})();\n\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n /**\n * Populates canvas with data from the specified JSON.\n * JSON format must conform to the one of {@link fabric.Canvas#toJSON}\n * @param {String|Object} json JSON string or object\n * @param {Function} callback Callback, invoked when json is parsed\n * and corresponding objects (e.g: {@link fabric.Image})\n * are initialized\n * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created.\n * @return {fabric.Canvas} instance\n * @chainable\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#deserialization}\n * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo}\n * @example loadFromJSON\n * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));\n * @example loadFromJSON with reviver\n * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas), function(o, object) {\n * // `o` = json object\n * // `object` = fabric.Object instance\n * // ... do some stuff ...\n * });\n */\n loadFromJSON: function (json, callback, reviver) {\n if (!json) {\n return;\n }\n\n // serialize if it wasn't already\n var serialized = (typeof json === 'string')\n ? JSON.parse(json)\n : fabric.util.object.clone(json);\n\n var _this = this,\n clipPath = serialized.clipPath,\n renderOnAddRemove = this.renderOnAddRemove;\n\n this.renderOnAddRemove = false;\n\n delete serialized.clipPath;\n\n this._enlivenObjects(serialized.objects, function (enlivenedObjects) {\n _this.clear();\n _this._setBgOverlay(serialized, function () {\n if (clipPath) {\n _this._enlivenObjects([clipPath], function (enlivenedCanvasClip) {\n _this.clipPath = enlivenedCanvasClip[0];\n _this.__setupCanvas.call(_this, serialized, enlivenedObjects, renderOnAddRemove, callback);\n });\n }\n else {\n _this.__setupCanvas.call(_this, serialized, enlivenedObjects, renderOnAddRemove, callback);\n }\n });\n }, reviver);\n return this;\n },\n\n /**\n * @private\n * @param {Object} serialized Object with background and overlay information\n * @param {Array} restored canvas objects\n * @param {Function} cached renderOnAddRemove callback\n * @param {Function} callback Invoked after all background and overlay images/patterns loaded\n */\n __setupCanvas: function(serialized, enlivenedObjects, renderOnAddRemove, callback) {\n var _this = this;\n enlivenedObjects.forEach(function(obj, index) {\n // we splice the array just in case some custom classes restored from JSON\n // will add more object to canvas at canvas init.\n _this.insertAt(obj, index);\n });\n this.renderOnAddRemove = renderOnAddRemove;\n // remove parts i cannot set as options\n delete serialized.objects;\n delete serialized.backgroundImage;\n delete serialized.overlayImage;\n delete serialized.background;\n delete serialized.overlay;\n // this._initOptions does too many things to just\n // call it. Normally loading an Object from JSON\n // create the Object instance. Here the Canvas is\n // already an instance and we are just loading things over it\n this._setOptions(serialized);\n this.renderAll();\n callback && callback();\n },\n\n /**\n * @private\n * @param {Object} serialized Object with background and overlay information\n * @param {Function} callback Invoked after all background and overlay images/patterns loaded\n */\n _setBgOverlay: function(serialized, callback) {\n var loaded = {\n backgroundColor: false,\n overlayColor: false,\n backgroundImage: false,\n overlayImage: false\n };\n\n if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background && !serialized.overlay) {\n callback && callback();\n return;\n }\n\n var cbIfLoaded = function () {\n if (loaded.backgroundImage && loaded.overlayImage && loaded.backgroundColor && loaded.overlayColor) {\n callback && callback();\n }\n };\n\n this.__setBgOverlay('backgroundImage', serialized.backgroundImage, loaded, cbIfLoaded);\n this.__setBgOverlay('overlayImage', serialized.overlayImage, loaded, cbIfLoaded);\n this.__setBgOverlay('backgroundColor', serialized.background, loaded, cbIfLoaded);\n this.__setBgOverlay('overlayColor', serialized.overlay, loaded, cbIfLoaded);\n },\n\n /**\n * @private\n * @param {String} property Property to set (backgroundImage, overlayImage, backgroundColor, overlayColor)\n * @param {(Object|String)} value Value to set\n * @param {Object} loaded Set loaded property to true if property is set\n * @param {Object} callback Callback function to invoke after property is set\n */\n __setBgOverlay: function(property, value, loaded, callback) {\n var _this = this;\n\n if (!value) {\n loaded[property] = true;\n callback && callback();\n return;\n }\n\n if (property === 'backgroundImage' || property === 'overlayImage') {\n fabric.util.enlivenObjects([value], function(enlivedObject){\n _this[property] = enlivedObject[0];\n loaded[property] = true;\n callback && callback();\n });\n }\n else {\n this['set' + fabric.util.string.capitalize(property, true)](value, function() {\n loaded[property] = true;\n callback && callback();\n });\n }\n },\n\n /**\n * @private\n * @param {Array} objects\n * @param {Function} callback\n * @param {Function} [reviver]\n */\n _enlivenObjects: function (objects, callback, reviver) {\n if (!objects || objects.length === 0) {\n callback && callback([]);\n return;\n }\n\n fabric.util.enlivenObjects(objects, function(enlivenedObjects) {\n callback && callback(enlivenedObjects);\n }, null, reviver);\n },\n\n /**\n * @private\n * @param {String} format\n * @param {Function} callback\n */\n _toDataURL: function (format, callback) {\n this.clone(function (clone) {\n callback(clone.toDataURL(format));\n });\n },\n\n /**\n * @private\n * @param {String} format\n * @param {Number} multiplier\n * @param {Function} callback\n */\n _toDataURLWithMultiplier: function (format, multiplier, callback) {\n this.clone(function (clone) {\n callback(clone.toDataURLWithMultiplier(format, multiplier));\n });\n },\n\n /**\n * Clones canvas instance\n * @param {Object} [callback] Receives cloned instance as a first argument\n * @param {Array} [properties] Array of properties to include in the cloned canvas and children\n */\n clone: function (callback, properties) {\n var data = JSON.stringify(this.toJSON(properties));\n this.cloneWithoutData(function(clone) {\n clone.loadFromJSON(data, function() {\n callback && callback(clone);\n });\n });\n },\n\n /**\n * Clones canvas instance without cloning existing data.\n * This essentially copies canvas dimensions, clipping properties, etc.\n * but leaves data empty (so that you can populate it with your own)\n * @param {Object} [callback] Receives cloned instance as a first argument\n */\n cloneWithoutData: function(callback) {\n var el = fabric.util.createCanvasElement();\n\n el.width = this.width;\n el.height = this.height;\n\n var clone = new fabric.Canvas(el);\n if (this.backgroundImage) {\n clone.setBackgroundImage(this.backgroundImage.src, function() {\n clone.renderAll();\n callback && callback(clone);\n });\n clone.backgroundImageOpacity = this.backgroundImageOpacity;\n clone.backgroundImageStretch = this.backgroundImageStretch;\n }\n else {\n callback && callback(clone);\n }\n }\n});\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n clone = fabric.util.object.clone,\n toFixed = fabric.util.toFixed,\n capitalize = fabric.util.string.capitalize,\n degreesToRadians = fabric.util.degreesToRadians,\n objectCaching = !fabric.isLikelyNode,\n ALIASING_LIMIT = 2;\n\n if (fabric.Object) {\n return;\n }\n\n /**\n * Root object class from which all 2d shape classes inherit from\n * @class fabric.Object\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#objects}\n * @see {@link fabric.Object#initialize} for constructor definition\n *\n * @fires added\n * @fires removed\n *\n * @fires selected\n * @fires deselected\n * @fires modified\n * @fires modified\n * @fires moved\n * @fires scaled\n * @fires rotated\n * @fires skewed\n *\n * @fires rotating\n * @fires scaling\n * @fires moving\n * @fires skewing\n *\n * @fires mousedown\n * @fires mouseup\n * @fires mouseover\n * @fires mouseout\n * @fires mousewheel\n * @fires mousedblclick\n *\n * @fires dragover\n * @fires dragenter\n * @fires dragleave\n * @fires drop\n */\n fabric.Object = fabric.util.createClass(fabric.CommonMethods, /** @lends fabric.Object.prototype */ {\n\n /**\n * Type of an object (rect, circle, path, etc.).\n * Note that this property is meant to be read-only and not meant to be modified.\n * If you modify, certain parts of Fabric (such as JSON loading) won't work correctly.\n * @type String\n * @default\n */\n type: 'object',\n\n /**\n * Horizontal origin of transformation of an object (one of \"left\", \"right\", \"center\")\n * See http://jsfiddle.net/1ow02gea/244/ on how originX/originY affect objects in groups\n * @type String\n * @default\n */\n originX: 'left',\n\n /**\n * Vertical origin of transformation of an object (one of \"top\", \"bottom\", \"center\")\n * See http://jsfiddle.net/1ow02gea/244/ on how originX/originY affect objects in groups\n * @type String\n * @default\n */\n originY: 'top',\n\n /**\n * Top position of an object. Note that by default it's relative to object top. You can change this by setting originY={top/center/bottom}\n * @type Number\n * @default\n */\n top: 0,\n\n /**\n * Left position of an object. Note that by default it's relative to object left. You can change this by setting originX={left/center/right}\n * @type Number\n * @default\n */\n left: 0,\n\n /**\n * Object width\n * @type Number\n * @default\n */\n width: 0,\n\n /**\n * Object height\n * @type Number\n * @default\n */\n height: 0,\n\n /**\n * Object scale factor (horizontal)\n * @type Number\n * @default\n */\n scaleX: 1,\n\n /**\n * Object scale factor (vertical)\n * @type Number\n * @default\n */\n scaleY: 1,\n\n /**\n * When true, an object is rendered as flipped horizontally\n * @type Boolean\n * @default\n */\n flipX: false,\n\n /**\n * When true, an object is rendered as flipped vertically\n * @type Boolean\n * @default\n */\n flipY: false,\n\n /**\n * Opacity of an object\n * @type Number\n * @default\n */\n opacity: 1,\n\n /**\n * Angle of rotation of an object (in degrees)\n * @type Number\n * @default\n */\n angle: 0,\n\n /**\n * Angle of skew on x axes of an object (in degrees)\n * @type Number\n * @default\n */\n skewX: 0,\n\n /**\n * Angle of skew on y axes of an object (in degrees)\n * @type Number\n * @default\n */\n skewY: 0,\n\n /**\n * Size of object's controlling corners (in pixels)\n * @type Number\n * @default\n */\n cornerSize: 13,\n\n /**\n * Size of object's controlling corners when touch interaction is detected\n * @type Number\n * @default\n */\n touchCornerSize: 24,\n\n /**\n * When true, object's controlling corners are rendered as transparent inside (i.e. stroke instead of fill)\n * @type Boolean\n * @default\n */\n transparentCorners: true,\n\n /**\n * Default cursor value used when hovering over this object on canvas\n * @type String\n * @default\n */\n hoverCursor: null,\n\n /**\n * Default cursor value used when moving this object on canvas\n * @type String\n * @default\n */\n moveCursor: null,\n\n /**\n * Padding between object and its controlling borders (in pixels)\n * @type Number\n * @default\n */\n padding: 0,\n\n /**\n * Color of controlling borders of an object (when it's active)\n * @type String\n * @default\n */\n borderColor: 'rgb(178,204,255)',\n\n /**\n * Array specifying dash pattern of an object's borders (hasBorder must be true)\n * @since 1.6.2\n * @type Array\n */\n borderDashArray: null,\n\n /**\n * Color of controlling corners of an object (when it's active)\n * @type String\n * @default\n */\n cornerColor: 'rgb(178,204,255)',\n\n /**\n * Color of controlling corners of an object (when it's active and transparentCorners false)\n * @since 1.6.2\n * @type String\n * @default\n */\n cornerStrokeColor: null,\n\n /**\n * Specify style of control, 'rect' or 'circle'\n * @since 1.6.2\n * @type String\n */\n cornerStyle: 'rect',\n\n /**\n * Array specifying dash pattern of an object's control (hasBorder must be true)\n * @since 1.6.2\n * @type Array\n */\n cornerDashArray: null,\n\n /**\n * When true, this object will use center point as the origin of transformation\n * when being scaled via the controls.\n * Backwards incompatibility note: This property replaces \"centerTransform\" (Boolean).\n * @since 1.3.4\n * @type Boolean\n * @default\n */\n centeredScaling: false,\n\n /**\n * When true, this object will use center point as the origin of transformation\n * when being rotated via the controls.\n * Backwards incompatibility note: This property replaces \"centerTransform\" (Boolean).\n * @since 1.3.4\n * @type Boolean\n * @default\n */\n centeredRotation: true,\n\n /**\n * Color of object's fill\n * takes css colors https://www.w3.org/TR/css-color-3/\n * @type String\n * @default\n */\n fill: 'rgb(0,0,0)',\n\n /**\n * Fill rule used to fill an object\n * accepted values are nonzero, evenodd\n * Backwards incompatibility note: This property was used for setting globalCompositeOperation until v1.4.12 (use `fabric.Object#globalCompositeOperation` instead)\n * @type String\n * @default\n */\n fillRule: 'nonzero',\n\n /**\n * Composite rule used for canvas globalCompositeOperation\n * @type String\n * @default\n */\n globalCompositeOperation: 'source-over',\n\n /**\n * Background color of an object.\n * takes css colors https://www.w3.org/TR/css-color-3/\n * @type String\n * @default\n */\n backgroundColor: '',\n\n /**\n * Selection Background color of an object. colored layer behind the object when it is active.\n * does not mix good with globalCompositeOperation methods.\n * @type String\n * @default\n */\n selectionBackgroundColor: '',\n\n /**\n * When defined, an object is rendered via stroke and this property specifies its color\n * takes css colors https://www.w3.org/TR/css-color-3/\n * @type String\n * @default\n */\n stroke: null,\n\n /**\n * Width of a stroke used to render this object\n * @type Number\n * @default\n */\n strokeWidth: 1,\n\n /**\n * Array specifying dash pattern of an object's stroke (stroke must be defined)\n * @type Array\n */\n strokeDashArray: null,\n\n /**\n * Line offset of an object's stroke\n * @type Number\n * @default\n */\n strokeDashOffset: 0,\n\n /**\n * Line endings style of an object's stroke (one of \"butt\", \"round\", \"square\")\n * @type String\n * @default\n */\n strokeLineCap: 'butt',\n\n /**\n * Corner style of an object's stroke (one of \"bevel\", \"round\", \"miter\")\n * @type String\n * @default\n */\n strokeLineJoin: 'miter',\n\n /**\n * Maximum miter length (used for strokeLineJoin = \"miter\") of an object's stroke\n * @type Number\n * @default\n */\n strokeMiterLimit: 4,\n\n /**\n * Shadow object representing shadow of this shape\n * @type fabric.Shadow\n * @default\n */\n shadow: null,\n\n /**\n * Opacity of object's controlling borders when object is active and moving\n * @type Number\n * @default\n */\n borderOpacityWhenMoving: 0.4,\n\n /**\n * Scale factor of object's controlling borders\n * bigger number will make a thicker border\n * border is 1, so this is basically a border thickness\n * since there is no way to change the border itself.\n * @type Number\n * @default\n */\n borderScaleFactor: 1,\n\n /**\n * Minimum allowed scale value of an object\n * @type Number\n * @default\n */\n minScaleLimit: 0,\n\n /**\n * When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection).\n * But events still fire on it.\n * @type Boolean\n * @default\n */\n selectable: true,\n\n /**\n * When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4\n * @type Boolean\n * @default\n */\n evented: true,\n\n /**\n * When set to `false`, an object is not rendered on canvas\n * @type Boolean\n * @default\n */\n visible: true,\n\n /**\n * When set to `false`, object's controls are not displayed and can not be used to manipulate object\n * @type Boolean\n * @default\n */\n hasControls: true,\n\n /**\n * When set to `false`, object's controlling borders are not rendered\n * @type Boolean\n * @default\n */\n hasBorders: true,\n\n /**\n * When set to `true`, objects are \"found\" on canvas on per-pixel basis rather than according to bounding box\n * @type Boolean\n * @default\n */\n perPixelTargetFind: false,\n\n /**\n * When `false`, default object's values are not included in its serialization\n * @type Boolean\n * @default\n */\n includeDefaultValues: true,\n\n /**\n * When `true`, object horizontal movement is locked\n * @type Boolean\n * @default\n */\n lockMovementX: false,\n\n /**\n * When `true`, object vertical movement is locked\n * @type Boolean\n * @default\n */\n lockMovementY: false,\n\n /**\n * When `true`, object rotation is locked\n * @type Boolean\n * @default\n */\n lockRotation: false,\n\n /**\n * When `true`, object horizontal scaling is locked\n * @type Boolean\n * @default\n */\n lockScalingX: false,\n\n /**\n * When `true`, object vertical scaling is locked\n * @type Boolean\n * @default\n */\n lockScalingY: false,\n\n /**\n * When `true`, object horizontal skewing is locked\n * @type Boolean\n * @default\n */\n lockSkewingX: false,\n\n /**\n * When `true`, object vertical skewing is locked\n * @type Boolean\n * @default\n */\n lockSkewingY: false,\n\n /**\n * When `true`, object cannot be flipped by scaling into negative values\n * @type Boolean\n * @default\n */\n lockScalingFlip: false,\n\n /**\n * When `true`, object is not exported in OBJECT/JSON\n * @since 1.6.3\n * @type Boolean\n * @default\n */\n excludeFromExport: false,\n\n /**\n * When `true`, object is cached on an additional canvas.\n * When `false`, object is not cached unless necessary ( clipPath )\n * default to true\n * @since 1.7.0\n * @type Boolean\n * @default true\n */\n objectCaching: objectCaching,\n\n /**\n * When `true`, object properties are checked for cache invalidation. In some particular\n * situation you may want this to be disabled ( spray brush, very big, groups)\n * or if your application does not allow you to modify properties for groups child you want\n * to disable it for groups.\n * default to false\n * since 1.7.0\n * @type Boolean\n * @default false\n */\n statefullCache: false,\n\n /**\n * When `true`, cache does not get updated during scaling. The picture will get blocky if scaled\n * too much and will be redrawn with correct details at the end of scaling.\n * this setting is performance and application dependant.\n * default to true\n * since 1.7.0\n * @type Boolean\n * @default true\n */\n noScaleCache: true,\n\n /**\n * When `false`, the stoke width will scale with the object.\n * When `true`, the stroke will always match the exact pixel size entered for stroke width.\n * this Property does not work on Text classes or drawing call that uses strokeText,fillText methods\n * default to false\n * @since 2.6.0\n * @type Boolean\n * @default false\n * @type Boolean\n * @default false\n */\n strokeUniform: false,\n\n /**\n * When set to `true`, object's cache will be rerendered next render call.\n * since 1.7.0\n * @type Boolean\n * @default true\n */\n dirty: true,\n\n /**\n * keeps the value of the last hovered corner during mouse move.\n * 0 is no corner, or 'mt', 'ml', 'mtr' etc..\n * It should be private, but there is no harm in using it as\n * a read-only property.\n * @type number|string|any\n * @default 0\n */\n __corner: 0,\n\n /**\n * Determines if the fill or the stroke is drawn first (one of \"fill\" or \"stroke\")\n * @type String\n * @default\n */\n paintFirst: 'fill',\n\n /**\n * When 'down', object is set to active on mousedown/touchstart\n * When 'up', object is set to active on mouseup/touchend\n * Experimental. Let's see if this breaks anything before supporting officially\n * @private\n * since 4.4.0\n * @type String\n * @default 'down'\n */\n activeOn: 'down',\n\n /**\n * List of properties to consider when checking if state\n * of an object is changed (fabric.Object#hasStateChanged)\n * as well as for history (undo/redo) purposes\n * @type Array\n */\n stateProperties: (\n 'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' +\n 'stroke strokeWidth strokeDashArray strokeLineCap strokeDashOffset strokeLineJoin strokeMiterLimit ' +\n 'angle opacity fill globalCompositeOperation shadow visible backgroundColor ' +\n 'skewX skewY fillRule paintFirst clipPath strokeUniform'\n ).split(' '),\n\n /**\n * List of properties to consider when checking if cache needs refresh\n * Those properties are checked by statefullCache ON ( or lazy mode if we want ) or from single\n * calls to Object.set(key, value). If the key is in this list, the object is marked as dirty\n * and refreshed at the next render\n * @type Array\n */\n cacheProperties: (\n 'fill stroke strokeWidth strokeDashArray width height paintFirst strokeUniform' +\n ' strokeLineCap strokeDashOffset strokeLineJoin strokeMiterLimit backgroundColor clipPath'\n ).split(' '),\n\n /**\n * List of properties to consider for animating colors.\n * @type Array\n */\n colorProperties: (\n 'fill stroke backgroundColor'\n ).split(' '),\n\n /**\n * a fabricObject that, without stroke define a clipping area with their shape. filled in black\n * the clipPath object gets used when the object has rendered, and the context is placed in the center\n * of the object cacheCanvas.\n * If you want 0,0 of a clipPath to align with an object center, use clipPath.originX/Y to 'center'\n * @type fabric.Object\n */\n clipPath: undefined,\n\n /**\n * Meaningful ONLY when the object is used as clipPath.\n * if true, the clipPath will make the object clip to the outside of the clipPath\n * since 2.4.0\n * @type boolean\n * @default false\n */\n inverted: false,\n\n /**\n * Meaningful ONLY when the object is used as clipPath.\n * if true, the clipPath will have its top and left relative to canvas, and will\n * not be influenced by the object transform. This will make the clipPath relative\n * to the canvas, but clipping just a particular object.\n * WARNING this is beta, this feature may change or be renamed.\n * since 2.4.0\n * @type boolean\n * @default false\n */\n absolutePositioned: false,\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n initialize: function(options) {\n if (options) {\n this.setOptions(options);\n }\n },\n\n /**\n * Create a the canvas used to keep the cached copy of the object\n * @private\n */\n _createCacheCanvas: function() {\n this._cacheProperties = {};\n this._cacheCanvas = fabric.util.createCanvasElement();\n this._cacheContext = this._cacheCanvas.getContext('2d');\n this._updateCacheCanvas();\n // if canvas gets created, is empty, so dirty.\n this.dirty = true;\n },\n\n /**\n * Limit the cache dimensions so that X * Y do not cross fabric.perfLimitSizeTotal\n * and each side do not cross fabric.cacheSideLimit\n * those numbers are configurable so that you can get as much detail as you want\n * making bargain with performances.\n * @param {Object} dims\n * @param {Object} dims.width width of canvas\n * @param {Object} dims.height height of canvas\n * @param {Object} dims.zoomX zoomX zoom value to unscale the canvas before drawing cache\n * @param {Object} dims.zoomY zoomY zoom value to unscale the canvas before drawing cache\n * @return {Object}.width width of canvas\n * @return {Object}.height height of canvas\n * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\n * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\n */\n _limitCacheSize: function(dims) {\n var perfLimitSizeTotal = fabric.perfLimitSizeTotal,\n width = dims.width, height = dims.height,\n max = fabric.maxCacheSideLimit, min = fabric.minCacheSideLimit;\n if (width <= max && height <= max && width * height <= perfLimitSizeTotal) {\n if (width < min) {\n dims.width = min;\n }\n if (height < min) {\n dims.height = min;\n }\n return dims;\n }\n var ar = width / height, limitedDims = fabric.util.limitDimsByArea(ar, perfLimitSizeTotal),\n capValue = fabric.util.capValue,\n x = capValue(min, limitedDims.x, max),\n y = capValue(min, limitedDims.y, max);\n if (width > x) {\n dims.zoomX /= width / x;\n dims.width = x;\n dims.capped = true;\n }\n if (height > y) {\n dims.zoomY /= height / y;\n dims.height = y;\n dims.capped = true;\n }\n return dims;\n },\n\n /**\n * Return the dimension and the zoom level needed to create a cache canvas\n * big enough to host the object to be cached.\n * @private\n * @return {Object}.x width of object to be cached\n * @return {Object}.y height of object to be cached\n * @return {Object}.width width of canvas\n * @return {Object}.height height of canvas\n * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\n * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\n */\n _getCacheCanvasDimensions: function() {\n var objectScale = this.getTotalObjectScaling(),\n // caculate dimensions without skewing\n dim = this._getTransformedDimensions(0, 0),\n neededX = dim.x * objectScale.scaleX / this.scaleX,\n neededY = dim.y * objectScale.scaleY / this.scaleY;\n return {\n // for sure this ALIASING_LIMIT is slightly creating problem\n // in situation in which the cache canvas gets an upper limit\n // also objectScale contains already scaleX and scaleY\n width: neededX + ALIASING_LIMIT,\n height: neededY + ALIASING_LIMIT,\n zoomX: objectScale.scaleX,\n zoomY: objectScale.scaleY,\n x: neededX,\n y: neededY\n };\n },\n\n /**\n * Update width and height of the canvas for cache\n * returns true or false if canvas needed resize.\n * @private\n * @return {Boolean} true if the canvas has been resized\n */\n _updateCacheCanvas: function() {\n var targetCanvas = this.canvas;\n if (this.noScaleCache && targetCanvas && targetCanvas._currentTransform) {\n var target = targetCanvas._currentTransform.target,\n action = targetCanvas._currentTransform.action;\n if (this === target && action.slice && action.slice(0, 5) === 'scale') {\n return false;\n }\n }\n var canvas = this._cacheCanvas,\n dims = this._limitCacheSize(this._getCacheCanvasDimensions()),\n minCacheSize = fabric.minCacheSideLimit,\n width = dims.width, height = dims.height, drawingWidth, drawingHeight,\n zoomX = dims.zoomX, zoomY = dims.zoomY,\n dimensionsChanged = width !== this.cacheWidth || height !== this.cacheHeight,\n zoomChanged = this.zoomX !== zoomX || this.zoomY !== zoomY,\n shouldRedraw = dimensionsChanged || zoomChanged,\n additionalWidth = 0, additionalHeight = 0, shouldResizeCanvas = false;\n if (dimensionsChanged) {\n var canvasWidth = this._cacheCanvas.width,\n canvasHeight = this._cacheCanvas.height,\n sizeGrowing = width > canvasWidth || height > canvasHeight,\n sizeShrinking = (width < canvasWidth * 0.9 || height < canvasHeight * 0.9) &&\n canvasWidth > minCacheSize && canvasHeight > minCacheSize;\n shouldResizeCanvas = sizeGrowing || sizeShrinking;\n if (sizeGrowing && !dims.capped && (width > minCacheSize || height > minCacheSize)) {\n additionalWidth = width * 0.1;\n additionalHeight = height * 0.1;\n }\n }\n if (this instanceof fabric.Text && this.path) {\n shouldRedraw = true;\n shouldResizeCanvas = true;\n additionalWidth += this.getHeightOfLine(0) * this.zoomX;\n additionalHeight += this.getHeightOfLine(0) * this.zoomY;\n }\n if (shouldRedraw) {\n if (shouldResizeCanvas) {\n canvas.width = Math.ceil(width + additionalWidth);\n canvas.height = Math.ceil(height + additionalHeight);\n }\n else {\n this._cacheContext.setTransform(1, 0, 0, 1, 0, 0);\n this._cacheContext.clearRect(0, 0, canvas.width, canvas.height);\n }\n drawingWidth = dims.x / 2;\n drawingHeight = dims.y / 2;\n this.cacheTranslationX = Math.round(canvas.width / 2 - drawingWidth) + drawingWidth;\n this.cacheTranslationY = Math.round(canvas.height / 2 - drawingHeight) + drawingHeight;\n this.cacheWidth = width;\n this.cacheHeight = height;\n this._cacheContext.translate(this.cacheTranslationX, this.cacheTranslationY);\n this._cacheContext.scale(zoomX, zoomY);\n this.zoomX = zoomX;\n this.zoomY = zoomY;\n return true;\n }\n return false;\n },\n\n /**\n * Sets object's properties from options\n * @param {Object} [options] Options object\n */\n setOptions: function(options) {\n this._setOptions(options);\n this._initGradient(options.fill, 'fill');\n this._initGradient(options.stroke, 'stroke');\n this._initPattern(options.fill, 'fill');\n this._initPattern(options.stroke, 'stroke');\n },\n\n /**\n * Transforms context when rendering an object\n * @param {CanvasRenderingContext2D} ctx Context\n */\n transform: function(ctx) {\n var needFullTransform = (this.group && !this.group._transformDone) ||\n (this.group && this.canvas && ctx === this.canvas.contextTop);\n var m = this.calcTransformMatrix(!needFullTransform);\n ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\n },\n\n /**\n * Returns an object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n\n object = {\n type: this.type,\n version: fabric.version,\n originX: this.originX,\n originY: this.originY,\n left: toFixed(this.left, NUM_FRACTION_DIGITS),\n top: toFixed(this.top, NUM_FRACTION_DIGITS),\n width: toFixed(this.width, NUM_FRACTION_DIGITS),\n height: toFixed(this.height, NUM_FRACTION_DIGITS),\n fill: (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill,\n stroke: (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke,\n strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS),\n strokeDashArray: this.strokeDashArray ? this.strokeDashArray.concat() : this.strokeDashArray,\n strokeLineCap: this.strokeLineCap,\n strokeDashOffset: this.strokeDashOffset,\n strokeLineJoin: this.strokeLineJoin,\n strokeUniform: this.strokeUniform,\n strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS),\n scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS),\n scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS),\n angle: toFixed(this.angle, NUM_FRACTION_DIGITS),\n flipX: this.flipX,\n flipY: this.flipY,\n opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS),\n shadow: (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow,\n visible: this.visible,\n backgroundColor: this.backgroundColor,\n fillRule: this.fillRule,\n paintFirst: this.paintFirst,\n globalCompositeOperation: this.globalCompositeOperation,\n skewX: toFixed(this.skewX, NUM_FRACTION_DIGITS),\n skewY: toFixed(this.skewY, NUM_FRACTION_DIGITS),\n };\n\n if (this.clipPath && !this.clipPath.excludeFromExport) {\n object.clipPath = this.clipPath.toObject(propertiesToInclude);\n object.clipPath.inverted = this.clipPath.inverted;\n object.clipPath.absolutePositioned = this.clipPath.absolutePositioned;\n }\n\n fabric.util.populateWithProperties(this, object, propertiesToInclude);\n if (!this.includeDefaultValues) {\n object = this._removeDefaultValues(object);\n }\n\n return object;\n },\n\n /**\n * Returns (dataless) object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toDatalessObject: function(propertiesToInclude) {\n // will be overwritten by subclasses\n return this.toObject(propertiesToInclude);\n },\n\n /**\n * @private\n * @param {Object} object\n */\n _removeDefaultValues: function(object) {\n var prototype = fabric.util.getKlass(object.type).prototype,\n stateProperties = prototype.stateProperties;\n stateProperties.forEach(function(prop) {\n if (prop === 'left' || prop === 'top') {\n return;\n }\n if (object[prop] === prototype[prop]) {\n delete object[prop];\n }\n // basically a check for [] === []\n if (Array.isArray(object[prop]) && Array.isArray(prototype[prop])\n && object[prop].length === 0 && prototype[prop].length === 0) {\n delete object[prop];\n }\n });\n\n return object;\n },\n\n /**\n * Returns a string representation of an instance\n * @return {String}\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Return the object scale factor counting also the group scaling\n * @return {Object} object with scaleX and scaleY properties\n */\n getObjectScaling: function() {\n // if the object is a top level one, on the canvas, we go for simple aritmetic\n // otherwise the complex method with angles will return approximations and decimals\n // and will likely kill the cache when not needed\n // https://github.com/fabricjs/fabric.js/issues/7157\n if (!this.group) {\n return {\n scaleX: this.scaleX,\n scaleY: this.scaleY,\n };\n }\n // if we are inside a group total zoom calculation is complex, we defer to generic matrices\n var options = fabric.util.qrDecompose(this.calcTransformMatrix());\n return { scaleX: Math.abs(options.scaleX), scaleY: Math.abs(options.scaleY) };\n },\n\n /**\n * Return the object scale factor counting also the group scaling, zoom and retina\n * @return {Object} object with scaleX and scaleY properties\n */\n getTotalObjectScaling: function() {\n var scale = this.getObjectScaling(), scaleX = scale.scaleX, scaleY = scale.scaleY;\n if (this.canvas) {\n var zoom = this.canvas.getZoom();\n var retina = this.canvas.getRetinaScaling();\n scaleX *= zoom * retina;\n scaleY *= zoom * retina;\n }\n return { scaleX: scaleX, scaleY: scaleY };\n },\n\n /**\n * Return the object opacity counting also the group property\n * @return {Number}\n */\n getObjectOpacity: function() {\n var opacity = this.opacity;\n if (this.group) {\n opacity *= this.group.getObjectOpacity();\n }\n return opacity;\n },\n\n /**\n * @private\n * @param {String} key\n * @param {*} value\n * @return {fabric.Object} thisArg\n */\n _set: function(key, value) {\n var shouldConstrainValue = (key === 'scaleX' || key === 'scaleY'),\n isChanged = this[key] !== value, groupNeedsUpdate = false;\n\n if (shouldConstrainValue) {\n value = this._constrainScale(value);\n }\n if (key === 'scaleX' && value < 0) {\n this.flipX = !this.flipX;\n value *= -1;\n }\n else if (key === 'scaleY' && value < 0) {\n this.flipY = !this.flipY;\n value *= -1;\n }\n else if (key === 'shadow' && value && !(value instanceof fabric.Shadow)) {\n value = new fabric.Shadow(value);\n }\n else if (key === 'dirty' && this.group) {\n this.group.set('dirty', value);\n }\n\n this[key] = value;\n\n if (isChanged) {\n groupNeedsUpdate = this.group && this.group.isOnACache();\n if (this.cacheProperties.indexOf(key) > -1) {\n this.dirty = true;\n groupNeedsUpdate && this.group.set('dirty', true);\n }\n else if (groupNeedsUpdate && this.stateProperties.indexOf(key) > -1) {\n this.group.set('dirty', true);\n }\n }\n return this;\n },\n\n /**\n * This callback function is called by the parent group of an object every\n * time a non-delegated property changes on the group. It is passed the key\n * and value as parameters. Not adding in this function's signature to avoid\n * Travis build error about unused variables.\n */\n setOnGroup: function() {\n // implemented by sub-classes, as needed.\n },\n\n /**\n * Retrieves viewportTransform from Object's canvas if possible\n * @method getViewportTransform\n * @memberOf fabric.Object.prototype\n * @return {Array}\n */\n getViewportTransform: function() {\n if (this.canvas && this.canvas.viewportTransform) {\n return this.canvas.viewportTransform;\n }\n return fabric.iMatrix.concat();\n },\n\n /*\n * @private\n * return if the object would be visible in rendering\n * @memberOf fabric.Object.prototype\n * @return {Boolean}\n */\n isNotVisible: function() {\n return this.opacity === 0 ||\n (!this.width && !this.height && this.strokeWidth === 0) ||\n !this.visible;\n },\n\n /**\n * Renders an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n render: function(ctx) {\n // do not render if width/height are zeros or object is not visible\n if (this.isNotVisible()) {\n return;\n }\n if (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) {\n return;\n }\n ctx.save();\n this._setupCompositeOperation(ctx);\n this.drawSelectionBackground(ctx);\n this.transform(ctx);\n this._setOpacity(ctx);\n this._setShadow(ctx, this);\n if (this.shouldCache()) {\n this.renderCache();\n this.drawCacheOnCanvas(ctx);\n }\n else {\n this._removeCacheCanvas();\n this.dirty = false;\n this.drawObject(ctx);\n if (this.objectCaching && this.statefullCache) {\n this.saveState({ propertySet: 'cacheProperties' });\n }\n }\n ctx.restore();\n },\n\n renderCache: function(options) {\n options = options || {};\n if (!this._cacheCanvas || !this._cacheContext) {\n this._createCacheCanvas();\n }\n if (this.isCacheDirty()) {\n this.statefullCache && this.saveState({ propertySet: 'cacheProperties' });\n this.drawObject(this._cacheContext, options.forClipping);\n this.dirty = false;\n }\n },\n\n /**\n * Remove cacheCanvas and its dimensions from the objects\n */\n _removeCacheCanvas: function() {\n this._cacheCanvas = null;\n this._cacheContext = null;\n this.cacheWidth = 0;\n this.cacheHeight = 0;\n },\n\n /**\n * return true if the object will draw a stroke\n * Does not consider text styles. This is just a shortcut used at rendering time\n * We want it to be an approximation and be fast.\n * wrote to avoid extra caching, it has to return true when stroke happens,\n * can guess when it will not happen at 100% chance, does not matter if it misses\n * some use case where the stroke is invisible.\n * @since 3.0.0\n * @returns Boolean\n */\n hasStroke: function() {\n return this.stroke && this.stroke !== 'transparent' && this.strokeWidth !== 0;\n },\n\n /**\n * return true if the object will draw a fill\n * Does not consider text styles. This is just a shortcut used at rendering time\n * We want it to be an approximation and be fast.\n * wrote to avoid extra caching, it has to return true when fill happens,\n * can guess when it will not happen at 100% chance, does not matter if it misses\n * some use case where the fill is invisible.\n * @since 3.0.0\n * @returns Boolean\n */\n hasFill: function() {\n return this.fill && this.fill !== 'transparent';\n },\n\n /**\n * When set to `true`, force the object to have its own cache, even if it is inside a group\n * it may be needed when your object behave in a particular way on the cache and always needs\n * its own isolated canvas to render correctly.\n * Created to be overridden\n * since 1.7.12\n * @returns Boolean\n */\n needsItsOwnCache: function() {\n if (this.paintFirst === 'stroke' &&\n this.hasFill() && this.hasStroke() && typeof this.shadow === 'object') {\n return true;\n }\n if (this.clipPath) {\n return true;\n }\n return false;\n },\n\n /**\n * Decide if the object should cache or not. Create its own cache level\n * objectCaching is a global flag, wins over everything\n * needsItsOwnCache should be used when the object drawing method requires\n * a cache step. None of the fabric classes requires it.\n * Generally you do not cache objects in groups because the group outside is cached.\n * Read as: cache if is needed, or if the feature is enabled but we are not already caching.\n * @return {Boolean}\n */\n shouldCache: function() {\n this.ownCaching = this.needsItsOwnCache() || (\n this.objectCaching &&\n (!this.group || !this.group.isOnACache())\n );\n return this.ownCaching;\n },\n\n /**\n * Check if this object or a child object will cast a shadow\n * used by Group.shouldCache to know if child has a shadow recursively\n * @return {Boolean}\n */\n willDrawShadow: function() {\n return !!this.shadow && (this.shadow.offsetX !== 0 || this.shadow.offsetY !== 0);\n },\n\n /**\n * Execute the drawing operation for an object clipPath\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {fabric.Object} clipPath\n */\n drawClipPathOnCache: function(ctx, clipPath) {\n ctx.save();\n // DEBUG: uncomment this line, comment the following\n // ctx.globalAlpha = 0.4\n if (clipPath.inverted) {\n ctx.globalCompositeOperation = 'destination-out';\n }\n else {\n ctx.globalCompositeOperation = 'destination-in';\n }\n //ctx.scale(1 / 2, 1 / 2);\n if (clipPath.absolutePositioned) {\n var m = fabric.util.invertTransform(this.calcTransformMatrix());\n ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\n }\n clipPath.transform(ctx);\n ctx.scale(1 / clipPath.zoomX, 1 / clipPath.zoomY);\n ctx.drawImage(clipPath._cacheCanvas, -clipPath.cacheTranslationX, -clipPath.cacheTranslationY);\n ctx.restore();\n },\n\n /**\n * Execute the drawing operation for an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n drawObject: function(ctx, forClipping) {\n var originalFill = this.fill, originalStroke = this.stroke;\n if (forClipping) {\n this.fill = 'black';\n this.stroke = '';\n this._setClippingProperties(ctx);\n }\n else {\n this._renderBackground(ctx);\n }\n this._render(ctx);\n this._drawClipPath(ctx, this.clipPath);\n this.fill = originalFill;\n this.stroke = originalStroke;\n },\n\n /**\n * Prepare clipPath state and cache and draw it on instance's cache\n * @param {CanvasRenderingContext2D} ctx\n * @param {fabric.Object} clipPath\n */\n _drawClipPath: function (ctx, clipPath) {\n if (!clipPath) { return; }\n // needed to setup a couple of variables\n // path canvas gets overridden with this one.\n // TODO find a better solution?\n clipPath.canvas = this.canvas;\n clipPath.shouldCache();\n clipPath._transformDone = true;\n clipPath.renderCache({ forClipping: true });\n this.drawClipPathOnCache(ctx, clipPath);\n },\n\n /**\n * Paint the cached copy of the object on the target context.\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n drawCacheOnCanvas: function(ctx) {\n ctx.scale(1 / this.zoomX, 1 / this.zoomY);\n ctx.drawImage(this._cacheCanvas, -this.cacheTranslationX, -this.cacheTranslationY);\n },\n\n /**\n * Check if cache is dirty\n * @param {Boolean} skipCanvas skip canvas checks because this object is painted\n * on parent canvas.\n */\n isCacheDirty: function(skipCanvas) {\n if (this.isNotVisible()) {\n return false;\n }\n if (this._cacheCanvas && this._cacheContext && !skipCanvas && this._updateCacheCanvas()) {\n // in this case the context is already cleared.\n return true;\n }\n else {\n if (this.dirty ||\n (this.clipPath && this.clipPath.absolutePositioned) ||\n (this.statefullCache && this.hasStateChanged('cacheProperties'))\n ) {\n if (this._cacheCanvas && this._cacheContext && !skipCanvas) {\n var width = this.cacheWidth / this.zoomX;\n var height = this.cacheHeight / this.zoomY;\n this._cacheContext.clearRect(-width / 2, -height / 2, width, height);\n }\n return true;\n }\n }\n return false;\n },\n\n /**\n * Draws a background for the object big as its untransformed dimensions\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderBackground: function(ctx) {\n if (!this.backgroundColor) {\n return;\n }\n var dim = this._getNonTransformedDimensions();\n ctx.fillStyle = this.backgroundColor;\n\n ctx.fillRect(\n -dim.x / 2,\n -dim.y / 2,\n dim.x,\n dim.y\n );\n // if there is background color no other shadows\n // should be casted\n this._removeShadow(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _setOpacity: function(ctx) {\n if (this.group && !this.group._transformDone) {\n ctx.globalAlpha = this.getObjectOpacity();\n }\n else {\n ctx.globalAlpha *= this.opacity;\n }\n },\n\n _setStrokeStyles: function(ctx, decl) {\n var stroke = decl.stroke;\n if (stroke) {\n ctx.lineWidth = decl.strokeWidth;\n ctx.lineCap = decl.strokeLineCap;\n ctx.lineDashOffset = decl.strokeDashOffset;\n ctx.lineJoin = decl.strokeLineJoin;\n ctx.miterLimit = decl.strokeMiterLimit;\n if (stroke.toLive) {\n if (stroke.gradientUnits === 'percentage' || stroke.gradientTransform || stroke.patternTransform) {\n // need to transform gradient in a pattern.\n // this is a slow process. If you are hitting this codepath, and the object\n // is not using caching, you should consider switching it on.\n // we need a canvas as big as the current object caching canvas.\n this._applyPatternForTransformedGradient(ctx, stroke);\n }\n else {\n // is a simple gradient or pattern\n ctx.strokeStyle = stroke.toLive(ctx, this);\n this._applyPatternGradientTransform(ctx, stroke);\n }\n }\n else {\n // is a color\n ctx.strokeStyle = decl.stroke;\n }\n }\n },\n\n _setFillStyles: function(ctx, decl) {\n var fill = decl.fill;\n if (fill) {\n if (fill.toLive) {\n ctx.fillStyle = fill.toLive(ctx, this);\n this._applyPatternGradientTransform(ctx, decl.fill);\n }\n else {\n ctx.fillStyle = fill;\n }\n }\n },\n\n _setClippingProperties: function(ctx) {\n ctx.globalAlpha = 1;\n ctx.strokeStyle = 'transparent';\n ctx.fillStyle = '#000000';\n },\n\n /**\n * @private\n * Sets line dash\n * @param {CanvasRenderingContext2D} ctx Context to set the dash line on\n * @param {Array} dashArray array representing dashes\n */\n _setLineDash: function(ctx, dashArray) {\n if (!dashArray || dashArray.length === 0) {\n return;\n }\n // Spec requires the concatenation of two copies the dash list when the number of elements is odd\n if (1 & dashArray.length) {\n dashArray.push.apply(dashArray, dashArray);\n }\n ctx.setLineDash(dashArray);\n },\n\n /**\n * Renders controls and borders for the object\n * the context here is not transformed\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Object} [styleOverride] properties to override the object style\n */\n _renderControls: function(ctx, styleOverride) {\n var vpt = this.getViewportTransform(),\n matrix = this.calcTransformMatrix(),\n options, drawBorders, drawControls;\n styleOverride = styleOverride || { };\n drawBorders = typeof styleOverride.hasBorders !== 'undefined' ? styleOverride.hasBorders : this.hasBorders;\n drawControls = typeof styleOverride.hasControls !== 'undefined' ? styleOverride.hasControls : this.hasControls;\n matrix = fabric.util.multiplyTransformMatrices(vpt, matrix);\n options = fabric.util.qrDecompose(matrix);\n ctx.save();\n ctx.translate(options.translateX, options.translateY);\n ctx.lineWidth = 1 * this.borderScaleFactor;\n if (!this.group) {\n ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n }\n if (this.flipX) {\n options.angle -= 180;\n }\n ctx.rotate(degreesToRadians(this.group ? options.angle : this.angle));\n if (styleOverride.forActiveSelection || this.group) {\n drawBorders && this.drawBordersInGroup(ctx, options, styleOverride);\n }\n else {\n drawBorders && this.drawBorders(ctx, styleOverride);\n }\n drawControls && this.drawControls(ctx, styleOverride);\n ctx.restore();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _setShadow: function(ctx) {\n if (!this.shadow) {\n return;\n }\n\n var shadow = this.shadow, canvas = this.canvas, scaling,\n multX = (canvas && canvas.viewportTransform[0]) || 1,\n multY = (canvas && canvas.viewportTransform[3]) || 1;\n if (shadow.nonScaling) {\n scaling = { scaleX: 1, scaleY: 1 };\n }\n else {\n scaling = this.getObjectScaling();\n }\n if (canvas && canvas._isRetinaScaling()) {\n multX *= fabric.devicePixelRatio;\n multY *= fabric.devicePixelRatio;\n }\n ctx.shadowColor = shadow.color;\n ctx.shadowBlur = shadow.blur * fabric.browserShadowBlurConstant *\n (multX + multY) * (scaling.scaleX + scaling.scaleY) / 4;\n ctx.shadowOffsetX = shadow.offsetX * multX * scaling.scaleX;\n ctx.shadowOffsetY = shadow.offsetY * multY * scaling.scaleY;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _removeShadow: function(ctx) {\n if (!this.shadow) {\n return;\n }\n\n ctx.shadowColor = '';\n ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Object} filler fabric.Pattern or fabric.Gradient\n * @return {Object} offset.offsetX offset for text rendering\n * @return {Object} offset.offsetY offset for text rendering\n */\n _applyPatternGradientTransform: function(ctx, filler) {\n if (!filler || !filler.toLive) {\n return { offsetX: 0, offsetY: 0 };\n }\n var t = filler.gradientTransform || filler.patternTransform;\n var offsetX = -this.width / 2 + filler.offsetX || 0,\n offsetY = -this.height / 2 + filler.offsetY || 0;\n\n if (filler.gradientUnits === 'percentage') {\n ctx.transform(this.width, 0, 0, this.height, offsetX, offsetY);\n }\n else {\n ctx.transform(1, 0, 0, 1, offsetX, offsetY);\n }\n if (t) {\n ctx.transform(t[0], t[1], t[2], t[3], t[4], t[5]);\n }\n return { offsetX: offsetX, offsetY: offsetY };\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderPaintInOrder: function(ctx) {\n if (this.paintFirst === 'stroke') {\n this._renderStroke(ctx);\n this._renderFill(ctx);\n }\n else {\n this._renderFill(ctx);\n this._renderStroke(ctx);\n }\n },\n\n /**\n * @private\n * function that actually render something on the context.\n * empty here to allow Obects to work on tests to benchmark fabric functionalites\n * not related to rendering\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(/* ctx */) {\n\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderFill: function(ctx) {\n if (!this.fill) {\n return;\n }\n\n ctx.save();\n this._setFillStyles(ctx, this);\n if (this.fillRule === 'evenodd') {\n ctx.fill('evenodd');\n }\n else {\n ctx.fill();\n }\n ctx.restore();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderStroke: function(ctx) {\n if (!this.stroke || this.strokeWidth === 0) {\n return;\n }\n\n if (this.shadow && !this.shadow.affectStroke) {\n this._removeShadow(ctx);\n }\n\n ctx.save();\n if (this.strokeUniform && this.group) {\n var scaling = this.getObjectScaling();\n ctx.scale(1 / scaling.scaleX, 1 / scaling.scaleY);\n }\n else if (this.strokeUniform) {\n ctx.scale(1 / this.scaleX, 1 / this.scaleY);\n }\n this._setLineDash(ctx, this.strokeDashArray);\n this._setStrokeStyles(ctx, this);\n ctx.stroke();\n ctx.restore();\n },\n\n /**\n * This function try to patch the missing gradientTransform on canvas gradients.\n * transforming a context to transform the gradient, is going to transform the stroke too.\n * we want to transform the gradient but not the stroke operation, so we create\n * a transformed gradient on a pattern and then we use the pattern instead of the gradient.\n * this method has drwabacks: is slow, is in low resolution, needs a patch for when the size\n * is limited.\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {fabric.Gradient} filler a fabric gradient instance\n */\n _applyPatternForTransformedGradient: function(ctx, filler) {\n var dims = this._limitCacheSize(this._getCacheCanvasDimensions()),\n pCanvas = fabric.util.createCanvasElement(), pCtx, retinaScaling = this.canvas.getRetinaScaling(),\n width = dims.x / this.scaleX / retinaScaling, height = dims.y / this.scaleY / retinaScaling;\n pCanvas.width = Math.ceil(width);\n pCanvas.height = Math.ceil(height);\n pCtx = pCanvas.getContext('2d');\n pCtx.beginPath(); pCtx.moveTo(0, 0); pCtx.lineTo(width, 0); pCtx.lineTo(width, height);\n pCtx.lineTo(0, height); pCtx.closePath();\n pCtx.translate(width / 2, height / 2);\n pCtx.scale(\n dims.zoomX / this.scaleX / retinaScaling,\n dims.zoomY / this.scaleY / retinaScaling\n );\n this._applyPatternGradientTransform(pCtx, filler);\n pCtx.fillStyle = filler.toLive(ctx);\n pCtx.fill();\n ctx.translate(-this.width / 2 - this.strokeWidth / 2, -this.height / 2 - this.strokeWidth / 2);\n ctx.scale(\n retinaScaling * this.scaleX / dims.zoomX,\n retinaScaling * this.scaleY / dims.zoomY\n );\n ctx.strokeStyle = pCtx.createPattern(pCanvas, 'no-repeat');\n },\n\n /**\n * This function is an helper for svg import. it returns the center of the object in the svg\n * untransformed coordinates\n * @private\n * @return {Object} center point from element coordinates\n */\n _findCenterFromElement: function() {\n return { x: this.left + this.width / 2, y: this.top + this.height / 2 };\n },\n\n /**\n * This function is an helper for svg import. it decompose the transformMatrix\n * and assign properties to object.\n * untransformed coordinates\n * @private\n * @chainable\n */\n _assignTransformMatrixProps: function() {\n if (this.transformMatrix) {\n var options = fabric.util.qrDecompose(this.transformMatrix);\n this.flipX = false;\n this.flipY = false;\n this.set('scaleX', options.scaleX);\n this.set('scaleY', options.scaleY);\n this.angle = options.angle;\n this.skewX = options.skewX;\n this.skewY = 0;\n }\n },\n\n /**\n * This function is an helper for svg import. it removes the transform matrix\n * and set to object properties that fabricjs can handle\n * @private\n * @param {Object} preserveAspectRatioOptions\n * @return {thisArg}\n */\n _removeTransformMatrix: function(preserveAspectRatioOptions) {\n var center = this._findCenterFromElement();\n if (this.transformMatrix) {\n this._assignTransformMatrixProps();\n center = fabric.util.transformPoint(center, this.transformMatrix);\n }\n this.transformMatrix = null;\n if (preserveAspectRatioOptions) {\n this.scaleX *= preserveAspectRatioOptions.scaleX;\n this.scaleY *= preserveAspectRatioOptions.scaleY;\n this.cropX = preserveAspectRatioOptions.cropX;\n this.cropY = preserveAspectRatioOptions.cropY;\n center.x += preserveAspectRatioOptions.offsetLeft;\n center.y += preserveAspectRatioOptions.offsetTop;\n this.width = preserveAspectRatioOptions.width;\n this.height = preserveAspectRatioOptions.height;\n }\n this.setPositionByOrigin(center, 'center', 'center');\n },\n\n /**\n * Clones an instance, using a callback method will work for every object.\n * @param {Function} callback Callback is invoked with a clone as a first argument\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n */\n clone: function(callback, propertiesToInclude) {\n var objectForm = this.toObject(propertiesToInclude);\n if (this.constructor.fromObject) {\n this.constructor.fromObject(objectForm, callback);\n }\n else {\n fabric.Object._fromObject('Object', objectForm, callback);\n }\n },\n\n /**\n * Creates an instance of fabric.Image out of an object\n * makes use of toCanvasElement.\n * Once this method was based on toDataUrl and loadImage, so it also had a quality\n * and format option. toCanvasElement is faster and produce no loss of quality.\n * If you need to get a real Jpeg or Png from an object, using toDataURL is the right way to do it.\n * toCanvasElement and then toBlob from the obtained canvas is also a good option.\n * This method is sync now, but still support the callback because we did not want to break.\n * When fabricJS 5.0 will be planned, this will probably be changed to not have a callback.\n * @param {Function} callback callback, invoked with an instance as a first argument\n * @param {Object} [options] for clone as image, passed to toDataURL\n * @param {Number} [options.multiplier=1] Multiplier to scale by\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\n * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\n * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\n * @return {fabric.Object} thisArg\n */\n cloneAsImage: function(callback, options) {\n var canvasEl = this.toCanvasElement(options);\n if (callback) {\n callback(new fabric.Image(canvasEl));\n }\n return this;\n },\n\n /**\n * Converts an object into a HTMLCanvas element\n * @param {Object} options Options object\n * @param {Number} [options.multiplier=1] Multiplier to scale by\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\n * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\n * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\n * @return {HTMLCanvasElement} Returns DOM element with the fabric.Object\n */\n toCanvasElement: function(options) {\n options || (options = { });\n\n var utils = fabric.util, origParams = utils.saveObjectTransform(this),\n originalGroup = this.group,\n originalShadow = this.shadow, abs = Math.abs,\n multiplier = (options.multiplier || 1) * (options.enableRetinaScaling ? fabric.devicePixelRatio : 1);\n delete this.group;\n if (options.withoutTransform) {\n utils.resetObjectTransform(this);\n }\n if (options.withoutShadow) {\n this.shadow = null;\n }\n\n var el = fabric.util.createCanvasElement(),\n // skip canvas zoom and calculate with setCoords now.\n boundingRect = this.getBoundingRect(true, true),\n shadow = this.shadow, scaling,\n shadowOffset = { x: 0, y: 0 }, shadowBlur,\n width, height;\n\n if (shadow) {\n shadowBlur = shadow.blur;\n if (shadow.nonScaling) {\n scaling = { scaleX: 1, scaleY: 1 };\n }\n else {\n scaling = this.getObjectScaling();\n }\n // consider non scaling shadow.\n shadowOffset.x = 2 * Math.round(abs(shadow.offsetX) + shadowBlur) * (abs(scaling.scaleX));\n shadowOffset.y = 2 * Math.round(abs(shadow.offsetY) + shadowBlur) * (abs(scaling.scaleY));\n }\n width = boundingRect.width + shadowOffset.x;\n height = boundingRect.height + shadowOffset.y;\n // if the current width/height is not an integer\n // we need to make it so.\n el.width = Math.ceil(width);\n el.height = Math.ceil(height);\n var canvas = new fabric.StaticCanvas(el, {\n enableRetinaScaling: false,\n renderOnAddRemove: false,\n skipOffscreen: false,\n });\n if (options.format === 'jpeg') {\n canvas.backgroundColor = '#fff';\n }\n this.setPositionByOrigin(new fabric.Point(canvas.width / 2, canvas.height / 2), 'center', 'center');\n\n var originalCanvas = this.canvas;\n canvas.add(this);\n var canvasEl = canvas.toCanvasElement(multiplier || 1, options);\n this.shadow = originalShadow;\n this.set('canvas', originalCanvas);\n if (originalGroup) {\n this.group = originalGroup;\n }\n this.set(origParams).setCoords();\n // canvas.dispose will call image.dispose that will nullify the elements\n // since this canvas is a simple element for the process, we remove references\n // to objects in this way in order to avoid object trashing.\n canvas._objects = [];\n canvas.dispose();\n canvas = null;\n\n return canvasEl;\n },\n\n /**\n * Converts an object into a data-url-like string\n * @param {Object} options Options object\n * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\n * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\n * @param {Number} [options.multiplier=1] Multiplier to scale by\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\n * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\n * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\n * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format\n */\n toDataURL: function(options) {\n options || (options = { });\n return fabric.util.toDataURL(this.toCanvasElement(options), options.format || 'png', options.quality || 1);\n },\n\n /**\n * Returns true if specified type is identical to the type of an instance\n * @param {String} type Type to check against\n * @return {Boolean}\n */\n isType: function(type) {\n return arguments.length > 1 ? Array.from(arguments).includes(this.type) : this.type === type;\n },\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity of this instance (is 1 unless subclassed)\n */\n complexity: function() {\n return 1;\n },\n\n /**\n * Returns a JSON representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} JSON\n */\n toJSON: function(propertiesToInclude) {\n // delegate, not alias\n return this.toObject(propertiesToInclude);\n },\n\n /**\n * Sets \"angle\" of an instance with centered rotation\n * @param {Number} angle Angle value (in degrees)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n rotate: function(angle) {\n var shouldCenterOrigin = (this.originX !== 'center' || this.originY !== 'center') && this.centeredRotation;\n\n if (shouldCenterOrigin) {\n this._setOriginToCenter();\n }\n\n this.set('angle', angle);\n\n if (shouldCenterOrigin) {\n this._resetOrigin();\n }\n\n return this;\n },\n\n /**\n * Centers object horizontally on canvas to which it was added last.\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @return {fabric.Object} thisArg\n * @chainable\n */\n centerH: function () {\n this.canvas && this.canvas.centerObjectH(this);\n return this;\n },\n\n /**\n * Centers object horizontally on current viewport of canvas to which it was added last.\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @return {fabric.Object} thisArg\n * @chainable\n */\n viewportCenterH: function () {\n this.canvas && this.canvas.viewportCenterObjectH(this);\n return this;\n },\n\n /**\n * Centers object vertically on canvas to which it was added last.\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @return {fabric.Object} thisArg\n * @chainable\n */\n centerV: function () {\n this.canvas && this.canvas.centerObjectV(this);\n return this;\n },\n\n /**\n * Centers object vertically on current viewport of canvas to which it was added last.\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @return {fabric.Object} thisArg\n * @chainable\n */\n viewportCenterV: function () {\n this.canvas && this.canvas.viewportCenterObjectV(this);\n return this;\n },\n\n /**\n * Centers object vertically and horizontally on canvas to which is was added last\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @return {fabric.Object} thisArg\n * @chainable\n */\n center: function () {\n this.canvas && this.canvas.centerObject(this);\n return this;\n },\n\n /**\n * Centers object on current viewport of canvas to which it was added last.\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @return {fabric.Object} thisArg\n * @chainable\n */\n viewportCenter: function () {\n this.canvas && this.canvas.viewportCenterObject(this);\n return this;\n },\n\n /**\n * Returns coordinates of a pointer relative to an object\n * @param {Event} e Event to operate upon\n * @param {Object} [pointer] Pointer to operate upon (instead of event)\n * @return {Object} Coordinates of a pointer (x, y)\n */\n getLocalPointer: function(e, pointer) {\n pointer = pointer || this.canvas.getPointer(e);\n var pClicked = new fabric.Point(pointer.x, pointer.y),\n objectLeftTop = this._getLeftTopCoords();\n if (this.angle) {\n pClicked = fabric.util.rotatePoint(\n pClicked, objectLeftTop, degreesToRadians(-this.angle));\n }\n return {\n x: pClicked.x - objectLeftTop.x,\n y: pClicked.y - objectLeftTop.y\n };\n },\n\n /**\n * Sets canvas globalCompositeOperation for specific object\n * custom composition operation for the particular object can be specified using globalCompositeOperation property\n * @param {CanvasRenderingContext2D} ctx Rendering canvas context\n */\n _setupCompositeOperation: function (ctx) {\n if (this.globalCompositeOperation) {\n ctx.globalCompositeOperation = this.globalCompositeOperation;\n }\n },\n\n /**\n * cancel instance's running animations\n * override if necessary to dispose artifacts such as `clipPath`\n */\n dispose: function () {\n if (fabric.runningAnimations) {\n fabric.runningAnimations.cancelByTarget(this);\n }\n }\n });\n\n fabric.util.createAccessors && fabric.util.createAccessors(fabric.Object);\n\n extend(fabric.Object.prototype, fabric.Observable);\n\n /**\n * Defines the number of fraction digits to use when serializing object values.\n * You can use it to increase/decrease precision of such values like left, top, scaleX, scaleY, etc.\n * @static\n * @memberOf fabric.Object\n * @constant\n * @type Number\n */\n fabric.Object.NUM_FRACTION_DIGITS = 2;\n\n /**\n * Defines which properties should be enlivened from the object passed to {@link fabric.Object._fromObject}\n * @static\n * @memberOf fabric.Object\n * @constant\n * @type string[]\n */\n fabric.Object.ENLIVEN_PROPS = ['clipPath'];\n\n fabric.Object._fromObject = function(className, object, callback, extraParam) {\n var klass = fabric[className];\n object = clone(object, true);\n fabric.util.enlivenPatterns([object.fill, object.stroke], function(patterns) {\n if (typeof patterns[0] !== 'undefined') {\n object.fill = patterns[0];\n }\n if (typeof patterns[1] !== 'undefined') {\n object.stroke = patterns[1];\n }\n fabric.util.enlivenObjectEnlivables(object, object, function () {\n var instance = extraParam ? new klass(object[extraParam], object) : new klass(object);\n callback && callback(instance);\n });\n });\n };\n\n /**\n * Unique id used internally when creating SVG elements\n * @static\n * @memberOf fabric.Object\n * @type Number\n */\n fabric.Object.__uid = 0;\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n var degreesToRadians = fabric.util.degreesToRadians,\n originXOffset = {\n left: -0.5,\n center: 0,\n right: 0.5\n },\n originYOffset = {\n top: -0.5,\n center: 0,\n bottom: 0.5\n };\n\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * Translates the coordinates from a set of origin to another (based on the object's dimensions)\n * @param {fabric.Point} point The point which corresponds to the originX and originY params\n * @param {String} fromOriginX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} fromOriginY Vertical origin: 'top', 'center' or 'bottom'\n * @param {String} toOriginX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} toOriginY Vertical origin: 'top', 'center' or 'bottom'\n * @return {fabric.Point}\n */\n translateToGivenOrigin: function(point, fromOriginX, fromOriginY, toOriginX, toOriginY) {\n var x = point.x,\n y = point.y,\n offsetX, offsetY, dim;\n\n if (typeof fromOriginX === 'string') {\n fromOriginX = originXOffset[fromOriginX];\n }\n else {\n fromOriginX -= 0.5;\n }\n\n if (typeof toOriginX === 'string') {\n toOriginX = originXOffset[toOriginX];\n }\n else {\n toOriginX -= 0.5;\n }\n\n offsetX = toOriginX - fromOriginX;\n\n if (typeof fromOriginY === 'string') {\n fromOriginY = originYOffset[fromOriginY];\n }\n else {\n fromOriginY -= 0.5;\n }\n\n if (typeof toOriginY === 'string') {\n toOriginY = originYOffset[toOriginY];\n }\n else {\n toOriginY -= 0.5;\n }\n\n offsetY = toOriginY - fromOriginY;\n\n if (offsetX || offsetY) {\n dim = this._getTransformedDimensions();\n x = point.x + offsetX * dim.x;\n y = point.y + offsetY * dim.y;\n }\n\n return new fabric.Point(x, y);\n },\n\n /**\n * Translates the coordinates from origin to center coordinates (based on the object's dimensions)\n * @param {fabric.Point} point The point which corresponds to the originX and originY params\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {fabric.Point}\n */\n translateToCenterPoint: function(point, originX, originY) {\n var p = this.translateToGivenOrigin(point, originX, originY, 'center', 'center');\n if (this.angle) {\n return fabric.util.rotatePoint(p, point, degreesToRadians(this.angle));\n }\n return p;\n },\n\n /**\n * Translates the coordinates from center to origin coordinates (based on the object's dimensions)\n * @param {fabric.Point} center The point which corresponds to center of the object\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {fabric.Point}\n */\n translateToOriginPoint: function(center, originX, originY) {\n var p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY);\n if (this.angle) {\n return fabric.util.rotatePoint(p, center, degreesToRadians(this.angle));\n }\n return p;\n },\n\n /**\n * Returns the real center coordinates of the object\n * @return {fabric.Point}\n */\n getCenterPoint: function() {\n var leftTop = new fabric.Point(this.left, this.top);\n return this.translateToCenterPoint(leftTop, this.originX, this.originY);\n },\n\n /**\n * Returns the coordinates of the object based on center coordinates\n * @param {fabric.Point} point The point which corresponds to the originX and originY params\n * @return {fabric.Point}\n */\n // getOriginPoint: function(center) {\n // return this.translateToOriginPoint(center, this.originX, this.originY);\n // },\n\n /**\n * Returns the coordinates of the object as if it has a different origin\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {fabric.Point}\n */\n getPointByOrigin: function(originX, originY) {\n var center = this.getCenterPoint();\n return this.translateToOriginPoint(center, originX, originY);\n },\n\n /**\n * Returns the point in local coordinates\n * @param {fabric.Point} point The point relative to the global coordinate system\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {fabric.Point}\n */\n toLocalPoint: function(point, originX, originY) {\n var center = this.getCenterPoint(),\n p, p2;\n\n if (typeof originX !== 'undefined' && typeof originY !== 'undefined' ) {\n p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY);\n }\n else {\n p = new fabric.Point(this.left, this.top);\n }\n\n p2 = new fabric.Point(point.x, point.y);\n if (this.angle) {\n p2 = fabric.util.rotatePoint(p2, center, -degreesToRadians(this.angle));\n }\n return p2.subtractEquals(p);\n },\n\n /**\n * Returns the point in global coordinates\n * @param {fabric.Point} The point relative to the local coordinate system\n * @return {fabric.Point}\n */\n // toGlobalPoint: function(point) {\n // return fabric.util.rotatePoint(point, this.getCenterPoint(), degreesToRadians(this.angle)).addEquals(new fabric.Point(this.left, this.top));\n // },\n\n /**\n * Sets the position of the object taking into consideration the object's origin\n * @param {fabric.Point} pos The new position of the object\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {void}\n */\n setPositionByOrigin: function(pos, originX, originY) {\n var center = this.translateToCenterPoint(pos, originX, originY),\n position = this.translateToOriginPoint(center, this.originX, this.originY);\n this.set('left', position.x);\n this.set('top', position.y);\n },\n\n /**\n * @param {String} to One of 'left', 'center', 'right'\n */\n adjustPosition: function(to) {\n var angle = degreesToRadians(this.angle),\n hypotFull = this.getScaledWidth(),\n xFull = fabric.util.cos(angle) * hypotFull,\n yFull = fabric.util.sin(angle) * hypotFull,\n offsetFrom, offsetTo;\n\n //TODO: this function does not consider mixed situation like top, center.\n if (typeof this.originX === 'string') {\n offsetFrom = originXOffset[this.originX];\n }\n else {\n offsetFrom = this.originX - 0.5;\n }\n if (typeof to === 'string') {\n offsetTo = originXOffset[to];\n }\n else {\n offsetTo = to - 0.5;\n }\n this.left += xFull * (offsetTo - offsetFrom);\n this.top += yFull * (offsetTo - offsetFrom);\n this.setCoords();\n this.originX = to;\n },\n\n /**\n * Sets the origin/position of the object to it's center point\n * @private\n * @return {void}\n */\n _setOriginToCenter: function() {\n this._originalOriginX = this.originX;\n this._originalOriginY = this.originY;\n\n var center = this.getCenterPoint();\n\n this.originX = 'center';\n this.originY = 'center';\n\n this.left = center.x;\n this.top = center.y;\n },\n\n /**\n * Resets the origin/position of the object to it's original origin\n * @private\n * @return {void}\n */\n _resetOrigin: function() {\n var originPoint = this.translateToOriginPoint(\n this.getCenterPoint(),\n this._originalOriginX,\n this._originalOriginY);\n\n this.originX = this._originalOriginX;\n this.originY = this._originalOriginY;\n\n this.left = originPoint.x;\n this.top = originPoint.y;\n\n this._originalOriginX = null;\n this._originalOriginY = null;\n },\n\n /**\n * @private\n */\n _getLeftTopCoords: function() {\n return this.translateToOriginPoint(this.getCenterPoint(), 'left', 'top');\n },\n });\n\n})();\n\n\n(function() {\n\n function arrayFromCoords(coords) {\n return [\n new fabric.Point(coords.tl.x, coords.tl.y),\n new fabric.Point(coords.tr.x, coords.tr.y),\n new fabric.Point(coords.br.x, coords.br.y),\n new fabric.Point(coords.bl.x, coords.bl.y)\n ];\n }\n\n var util = fabric.util,\n degreesToRadians = util.degreesToRadians,\n multiplyMatrices = util.multiplyTransformMatrices,\n transformPoint = util.transformPoint;\n\n util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * Describe object's corner position in canvas element coordinates.\n * properties are depending on control keys and padding the main controls.\n * each property is an object with x, y and corner.\n * The `corner` property contains in a similar manner the 4 points of the\n * interactive area of the corner.\n * The coordinates depends from the controls positionHandler and are used\n * to draw and locate controls\n * @memberOf fabric.Object.prototype\n */\n oCoords: null,\n\n /**\n * Describe object's corner position in canvas object absolute coordinates\n * properties are tl,tr,bl,br and describe the four main corner.\n * each property is an object with x, y, instance of Fabric.Point.\n * The coordinates depends from this properties: width, height, scaleX, scaleY\n * skewX, skewY, angle, strokeWidth, top, left.\n * Those coordinates are useful to understand where an object is. They get updated\n * with oCoords but they do not need to be updated when zoom or panning change.\n * The coordinates get updated with @method setCoords.\n * You can calculate them without updating with @method calcACoords();\n * @memberOf fabric.Object.prototype\n */\n aCoords: null,\n\n /**\n * Describe object's corner position in canvas element coordinates.\n * includes padding. Used of object detection.\n * set and refreshed with setCoords.\n * @memberOf fabric.Object.prototype\n */\n lineCoords: null,\n\n /**\n * storage for object transform matrix\n */\n ownMatrixCache: null,\n\n /**\n * storage for object full transform matrix\n */\n matrixCache: null,\n\n /**\n * custom controls interface\n * controls are added by default_controls.js\n */\n controls: { },\n\n /**\n * return correct set of coordinates for intersection\n * this will return either aCoords or lineCoords.\n * @param {Boolean} absolute will return aCoords if true or lineCoords\n * @return {Object} {tl, tr, br, bl} points\n */\n _getCoords: function(absolute, calculate) {\n if (calculate) {\n return (absolute ? this.calcACoords() : this.calcLineCoords());\n }\n if (!this.aCoords || !this.lineCoords) {\n this.setCoords(true);\n }\n return (absolute ? this.aCoords : this.lineCoords);\n },\n\n /**\n * return correct set of coordinates for intersection\n * this will return either aCoords or lineCoords.\n * The coords are returned in an array.\n * @return {Array} [tl, tr, br, bl] of points\n */\n getCoords: function(absolute, calculate) {\n return arrayFromCoords(this._getCoords(absolute, calculate));\n },\n\n /**\n * Checks if object intersects with an area formed by 2 points\n * @param {Object} pointTL top-left point of area\n * @param {Object} pointBR bottom-right point of area\n * @param {Boolean} [absolute] use coordinates without viewportTransform\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Boolean} true if object intersects with an area formed by 2 points\n */\n intersectsWithRect: function(pointTL, pointBR, absolute, calculate) {\n var coords = this.getCoords(absolute, calculate),\n intersection = fabric.Intersection.intersectPolygonRectangle(\n coords,\n pointTL,\n pointBR\n );\n return intersection.status === 'Intersection';\n },\n\n /**\n * Checks if object intersects with another object\n * @param {Object} other Object to test\n * @param {Boolean} [absolute] use coordinates without viewportTransform\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Boolean} true if object intersects with another object\n */\n intersectsWithObject: function(other, absolute, calculate) {\n var intersection = fabric.Intersection.intersectPolygonPolygon(\n this.getCoords(absolute, calculate),\n other.getCoords(absolute, calculate)\n );\n\n return intersection.status === 'Intersection'\n || other.isContainedWithinObject(this, absolute, calculate)\n || this.isContainedWithinObject(other, absolute, calculate);\n },\n\n /**\n * Checks if object is fully contained within area of another object\n * @param {Object} other Object to test\n * @param {Boolean} [absolute] use coordinates without viewportTransform\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Boolean} true if object is fully contained within area of another object\n */\n isContainedWithinObject: function(other, absolute, calculate) {\n var points = this.getCoords(absolute, calculate),\n otherCoords = absolute ? other.aCoords : other.lineCoords,\n i = 0, lines = other._getImageLines(otherCoords);\n for (; i < 4; i++) {\n if (!other.containsPoint(points[i], lines)) {\n return false;\n }\n }\n return true;\n },\n\n /**\n * Checks if object is fully contained within area formed by 2 points\n * @param {Object} pointTL top-left point of area\n * @param {Object} pointBR bottom-right point of area\n * @param {Boolean} [absolute] use coordinates without viewportTransform\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Boolean} true if object is fully contained within area formed by 2 points\n */\n isContainedWithinRect: function(pointTL, pointBR, absolute, calculate) {\n var boundingRect = this.getBoundingRect(absolute, calculate);\n\n return (\n boundingRect.left >= pointTL.x &&\n boundingRect.left + boundingRect.width <= pointBR.x &&\n boundingRect.top >= pointTL.y &&\n boundingRect.top + boundingRect.height <= pointBR.y\n );\n },\n\n /**\n * Checks if point is inside the object\n * @param {fabric.Point} point Point to check against\n * @param {Object} [lines] object returned from @method _getImageLines\n * @param {Boolean} [absolute] use coordinates without viewportTransform\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Boolean} true if point is inside the object\n */\n containsPoint: function(point, lines, absolute, calculate) {\n var coords = this._getCoords(absolute, calculate),\n lines = lines || this._getImageLines(coords),\n xPoints = this._findCrossPoints(point, lines);\n // if xPoints is odd then point is inside the object\n return (xPoints !== 0 && xPoints % 2 === 1);\n },\n\n /**\n * Checks if object is contained within the canvas with current viewportTransform\n * the check is done stopping at first point that appears on screen\n * @param {Boolean} [calculate] use coordinates of current position instead of .aCoords\n * @return {Boolean} true if object is fully or partially contained within canvas\n */\n isOnScreen: function(calculate) {\n if (!this.canvas) {\n return false;\n }\n var pointTL = this.canvas.vptCoords.tl, pointBR = this.canvas.vptCoords.br;\n var points = this.getCoords(true, calculate);\n // if some point is on screen, the object is on screen.\n if (points.some(function(point) {\n return point.x <= pointBR.x && point.x >= pointTL.x &&\n point.y <= pointBR.y && point.y >= pointTL.y;\n })) {\n return true;\n }\n // no points on screen, check intersection with absolute coordinates\n if (this.intersectsWithRect(pointTL, pointBR, true, calculate)) {\n return true;\n }\n return this._containsCenterOfCanvas(pointTL, pointBR, calculate);\n },\n\n /**\n * Checks if the object contains the midpoint between canvas extremities\n * Does not make sense outside the context of isOnScreen and isPartiallyOnScreen\n * @private\n * @param {Fabric.Point} pointTL Top Left point\n * @param {Fabric.Point} pointBR Top Right point\n * @param {Boolean} calculate use coordinates of current position instead of .oCoords\n * @return {Boolean} true if the object contains the point\n */\n _containsCenterOfCanvas: function(pointTL, pointBR, calculate) {\n // worst case scenario the object is so big that contains the screen\n var centerPoint = { x: (pointTL.x + pointBR.x) / 2, y: (pointTL.y + pointBR.y) / 2 };\n if (this.containsPoint(centerPoint, null, true, calculate)) {\n return true;\n }\n return false;\n },\n\n /**\n * Checks if object is partially contained within the canvas with current viewportTransform\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Boolean} true if object is partially contained within canvas\n */\n isPartiallyOnScreen: function(calculate) {\n if (!this.canvas) {\n return false;\n }\n var pointTL = this.canvas.vptCoords.tl, pointBR = this.canvas.vptCoords.br;\n if (this.intersectsWithRect(pointTL, pointBR, true, calculate)) {\n return true;\n }\n var allPointsAreOutside = this.getCoords(true, calculate).every(function(point) {\n return (point.x >= pointBR.x || point.x <= pointTL.x) &&\n (point.y >= pointBR.y || point.y <= pointTL.y);\n });\n return allPointsAreOutside && this._containsCenterOfCanvas(pointTL, pointBR, calculate);\n },\n\n /**\n * Method that returns an object with the object edges in it, given the coordinates of the corners\n * @private\n * @param {Object} oCoords Coordinates of the object corners\n */\n _getImageLines: function(oCoords) {\n\n var lines = {\n topline: {\n o: oCoords.tl,\n d: oCoords.tr\n },\n rightline: {\n o: oCoords.tr,\n d: oCoords.br\n },\n bottomline: {\n o: oCoords.br,\n d: oCoords.bl\n },\n leftline: {\n o: oCoords.bl,\n d: oCoords.tl\n }\n };\n\n // // debugging\n // if (this.canvas.contextTop) {\n // this.canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);\n // this.canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);\n //\n // this.canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);\n // this.canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);\n //\n // this.canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);\n // this.canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);\n //\n // this.canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);\n // this.canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);\n // }\n\n return lines;\n },\n\n /**\n * Helper method to determine how many cross points are between the 4 object edges\n * and the horizontal line determined by a point on canvas\n * @private\n * @param {fabric.Point} point Point to check\n * @param {Object} lines Coordinates of the object being evaluated\n */\n // remove yi, not used but left code here just in case.\n _findCrossPoints: function(point, lines) {\n var b1, b2, a1, a2, xi, // yi,\n xcount = 0,\n iLine;\n\n for (var lineKey in lines) {\n iLine = lines[lineKey];\n // optimisation 1: line below point. no cross\n if ((iLine.o.y < point.y) && (iLine.d.y < point.y)) {\n continue;\n }\n // optimisation 2: line above point. no cross\n if ((iLine.o.y >= point.y) && (iLine.d.y >= point.y)) {\n continue;\n }\n // optimisation 3: vertical line case\n if ((iLine.o.x === iLine.d.x) && (iLine.o.x >= point.x)) {\n xi = iLine.o.x;\n // yi = point.y;\n }\n // calculate the intersection point\n else {\n b1 = 0;\n b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x);\n a1 = point.y - b1 * point.x;\n a2 = iLine.o.y - b2 * iLine.o.x;\n\n xi = -(a1 - a2) / (b1 - b2);\n // yi = a1 + b1 * xi;\n }\n // dont count xi < point.x cases\n if (xi >= point.x) {\n xcount += 1;\n }\n // optimisation 4: specific for square images\n if (xcount === 2) {\n break;\n }\n }\n return xcount;\n },\n\n /**\n * Returns coordinates of object's bounding rectangle (left, top, width, height)\n * the box is intended as aligned to axis of canvas.\n * @param {Boolean} [absolute] use coordinates without viewportTransform\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords / .aCoords\n * @return {Object} Object with left, top, width, height properties\n */\n getBoundingRect: function(absolute, calculate) {\n var coords = this.getCoords(absolute, calculate);\n return util.makeBoundingBoxFromPoints(coords);\n },\n\n /**\n * Returns width of an object's bounding box counting transformations\n * before 2.0 it was named getWidth();\n * @return {Number} width value\n */\n getScaledWidth: function() {\n return this._getTransformedDimensions().x;\n },\n\n /**\n * Returns height of an object bounding box counting transformations\n * before 2.0 it was named getHeight();\n * @return {Number} height value\n */\n getScaledHeight: function() {\n return this._getTransformedDimensions().y;\n },\n\n /**\n * Makes sure the scale is valid and modifies it if necessary\n * @private\n * @param {Number} value\n * @return {Number}\n */\n _constrainScale: function(value) {\n if (Math.abs(value) < this.minScaleLimit) {\n if (value < 0) {\n return -this.minScaleLimit;\n }\n else {\n return this.minScaleLimit;\n }\n }\n else if (value === 0) {\n return 0.0001;\n }\n return value;\n },\n\n /**\n * Scales an object (equally by x and y)\n * @param {Number} value Scale factor\n * @return {fabric.Object} thisArg\n * @chainable\n */\n scale: function(value) {\n this._set('scaleX', value);\n this._set('scaleY', value);\n return this.setCoords();\n },\n\n /**\n * Scales an object to a given width, with respect to bounding box (scaling by x/y equally)\n * @param {Number} value New width value\n * @param {Boolean} absolute ignore viewport\n * @return {fabric.Object} thisArg\n * @chainable\n */\n scaleToWidth: function(value, absolute) {\n // adjust to bounding rect factor so that rotated shapes would fit as well\n var boundingRectFactor = this.getBoundingRect(absolute).width / this.getScaledWidth();\n return this.scale(value / this.width / boundingRectFactor);\n },\n\n /**\n * Scales an object to a given height, with respect to bounding box (scaling by x/y equally)\n * @param {Number} value New height value\n * @param {Boolean} absolute ignore viewport\n * @return {fabric.Object} thisArg\n * @chainable\n */\n scaleToHeight: function(value, absolute) {\n // adjust to bounding rect factor so that rotated shapes would fit as well\n var boundingRectFactor = this.getBoundingRect(absolute).height / this.getScaledHeight();\n return this.scale(value / this.height / boundingRectFactor);\n },\n\n calcLineCoords: function() {\n var vpt = this.getViewportTransform(),\n padding = this.padding, angle = degreesToRadians(this.angle),\n cos = util.cos(angle), sin = util.sin(angle),\n cosP = cos * padding, sinP = sin * padding, cosPSinP = cosP + sinP,\n cosPMinusSinP = cosP - sinP, aCoords = this.calcACoords();\n\n var lineCoords = {\n tl: transformPoint(aCoords.tl, vpt),\n tr: transformPoint(aCoords.tr, vpt),\n bl: transformPoint(aCoords.bl, vpt),\n br: transformPoint(aCoords.br, vpt),\n };\n\n if (padding) {\n lineCoords.tl.x -= cosPMinusSinP;\n lineCoords.tl.y -= cosPSinP;\n lineCoords.tr.x += cosPSinP;\n lineCoords.tr.y -= cosPMinusSinP;\n lineCoords.bl.x -= cosPSinP;\n lineCoords.bl.y += cosPMinusSinP;\n lineCoords.br.x += cosPMinusSinP;\n lineCoords.br.y += cosPSinP;\n }\n\n return lineCoords;\n },\n\n calcOCoords: function() {\n var rotateMatrix = this._calcRotateMatrix(),\n translateMatrix = this._calcTranslateMatrix(),\n vpt = this.getViewportTransform(),\n startMatrix = multiplyMatrices(vpt, translateMatrix),\n finalMatrix = multiplyMatrices(startMatrix, rotateMatrix),\n finalMatrix = multiplyMatrices(finalMatrix, [1 / vpt[0], 0, 0, 1 / vpt[3], 0, 0]),\n dim = this._calculateCurrentDimensions(),\n coords = {};\n this.forEachControl(function(control, key, fabricObject) {\n coords[key] = control.positionHandler(dim, finalMatrix, fabricObject);\n });\n\n // debug code\n // var canvas = this.canvas;\n // setTimeout(function() {\n // canvas.contextTop.clearRect(0, 0, 700, 700);\n // canvas.contextTop.fillStyle = 'green';\n // Object.keys(coords).forEach(function(key) {\n // var control = coords[key];\n // canvas.contextTop.fillRect(control.x, control.y, 3, 3);\n // });\n // }, 50);\n return coords;\n },\n\n calcACoords: function() {\n var rotateMatrix = this._calcRotateMatrix(),\n translateMatrix = this._calcTranslateMatrix(),\n finalMatrix = multiplyMatrices(translateMatrix, rotateMatrix),\n dim = this._getTransformedDimensions(),\n w = dim.x / 2, h = dim.y / 2;\n return {\n // corners\n tl: transformPoint({ x: -w, y: -h }, finalMatrix),\n tr: transformPoint({ x: w, y: -h }, finalMatrix),\n bl: transformPoint({ x: -w, y: h }, finalMatrix),\n br: transformPoint({ x: w, y: h }, finalMatrix)\n };\n },\n\n /**\n * Sets corner and controls position coordinates based on current angle, width and height, left and top.\n * oCoords are used to find the corners\n * aCoords are used to quickly find an object on the canvas\n * lineCoords are used to quickly find object during pointer events.\n * See {@link https://github.com/fabricjs/fabric.js/wiki/When-to-call-setCoords} and {@link http://fabricjs.com/fabric-gotchas}\n *\n * @param {Boolean} [skipCorners] skip calculation of oCoords.\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setCoords: function(skipCorners) {\n this.aCoords = this.calcACoords();\n // in case we are in a group, for how the inner group target check works,\n // lineCoords are exactly aCoords. Since the vpt gets absorbed by the normalized pointer.\n this.lineCoords = this.group ? this.aCoords : this.calcLineCoords();\n if (skipCorners) {\n return this;\n }\n // set coordinates of the draggable boxes in the corners used to scale/rotate the image\n this.oCoords = this.calcOCoords();\n this._setCornerCoords && this._setCornerCoords();\n return this;\n },\n\n /**\n * calculate rotation matrix of an object\n * @return {Array} rotation matrix for the object\n */\n _calcRotateMatrix: function() {\n return util.calcRotateMatrix(this);\n },\n\n /**\n * calculate the translation matrix for an object transform\n * @return {Array} rotation matrix for the object\n */\n _calcTranslateMatrix: function() {\n var center = this.getCenterPoint();\n return [1, 0, 0, 1, center.x, center.y];\n },\n\n transformMatrixKey: function(skipGroup) {\n var sep = '_', prefix = '';\n if (!skipGroup && this.group) {\n prefix = this.group.transformMatrixKey(skipGroup) + sep;\n };\n return prefix + this.top + sep + this.left + sep + this.scaleX + sep + this.scaleY +\n sep + this.skewX + sep + this.skewY + sep + this.angle + sep + this.originX + sep + this.originY +\n sep + this.width + sep + this.height + sep + this.strokeWidth + this.flipX + this.flipY;\n },\n\n /**\n * calculate transform matrix that represents the current transformations from the\n * object's properties.\n * @param {Boolean} [skipGroup] return transform matrix for object not counting parent transformations\n * There are some situation in which this is useful to avoid the fake rotation.\n * @return {Array} transform matrix for the object\n */\n calcTransformMatrix: function(skipGroup) {\n var matrix = this.calcOwnMatrix();\n if (skipGroup || !this.group) {\n return matrix;\n }\n var key = this.transformMatrixKey(skipGroup), cache = this.matrixCache || (this.matrixCache = {});\n if (cache.key === key) {\n return cache.value;\n }\n if (this.group) {\n matrix = multiplyMatrices(this.group.calcTransformMatrix(false), matrix);\n }\n cache.key = key;\n cache.value = matrix;\n return matrix;\n },\n\n /**\n * calculate transform matrix that represents the current transformations from the\n * object's properties, this matrix does not include the group transformation\n * @return {Array} transform matrix for the object\n */\n calcOwnMatrix: function() {\n var key = this.transformMatrixKey(true), cache = this.ownMatrixCache || (this.ownMatrixCache = {});\n if (cache.key === key) {\n return cache.value;\n }\n var tMatrix = this._calcTranslateMatrix(),\n options = {\n angle: this.angle,\n translateX: tMatrix[4],\n translateY: tMatrix[5],\n scaleX: this.scaleX,\n scaleY: this.scaleY,\n skewX: this.skewX,\n skewY: this.skewY,\n flipX: this.flipX,\n flipY: this.flipY,\n };\n cache.key = key;\n cache.value = util.composeMatrix(options);\n return cache.value;\n },\n\n /*\n * Calculate object dimensions from its properties\n * @private\n * @return {Object} .x width dimension\n * @return {Object} .y height dimension\n */\n _getNonTransformedDimensions: function() {\n var strokeWidth = this.strokeWidth,\n w = this.width + strokeWidth,\n h = this.height + strokeWidth;\n return { x: w, y: h };\n },\n\n /*\n * Calculate object bounding box dimensions from its properties scale, skew.\n * @param {Number} skewX, a value to override current skewX\n * @param {Number} skewY, a value to override current skewY\n * @private\n * @return {Object} .x width dimension\n * @return {Object} .y height dimension\n */\n _getTransformedDimensions: function(skewX, skewY) {\n if (typeof skewX === 'undefined') {\n skewX = this.skewX;\n }\n if (typeof skewY === 'undefined') {\n skewY = this.skewY;\n }\n var dimensions, dimX, dimY,\n noSkew = skewX === 0 && skewY === 0;\n\n if (this.strokeUniform) {\n dimX = this.width;\n dimY = this.height;\n }\n else {\n dimensions = this._getNonTransformedDimensions();\n dimX = dimensions.x;\n dimY = dimensions.y;\n }\n if (noSkew) {\n return this._finalizeDimensions(dimX * this.scaleX, dimY * this.scaleY);\n }\n var bbox = util.sizeAfterTransform(dimX, dimY, {\n scaleX: this.scaleX,\n scaleY: this.scaleY,\n skewX: skewX,\n skewY: skewY,\n });\n return this._finalizeDimensions(bbox.x, bbox.y);\n },\n\n /*\n * Calculate object bounding box dimensions from its properties scale, skew.\n * @param Number width width of the bbox\n * @param Number height height of the bbox\n * @private\n * @return {Object} .x finalized width dimension\n * @return {Object} .y finalized height dimension\n */\n _finalizeDimensions: function(width, height) {\n return this.strokeUniform ?\n { x: width + this.strokeWidth, y: height + this.strokeWidth }\n :\n { x: width, y: height };\n },\n\n /*\n * Calculate object dimensions for controls box, including padding and canvas zoom.\n * and active selection\n * private\n */\n _calculateCurrentDimensions: function() {\n var vpt = this.getViewportTransform(),\n dim = this._getTransformedDimensions(),\n p = transformPoint(dim, vpt, true);\n return p.scalarAdd(2 * this.padding);\n },\n });\n})();\n\n\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * Moves an object to the bottom of the stack of drawn objects\n * @return {fabric.Object} thisArg\n * @chainable\n */\n sendToBack: function() {\n if (this.group) {\n fabric.StaticCanvas.prototype.sendToBack.call(this.group, this);\n }\n else if (this.canvas) {\n this.canvas.sendToBack(this);\n }\n return this;\n },\n\n /**\n * Moves an object to the top of the stack of drawn objects\n * @return {fabric.Object} thisArg\n * @chainable\n */\n bringToFront: function() {\n if (this.group) {\n fabric.StaticCanvas.prototype.bringToFront.call(this.group, this);\n }\n else if (this.canvas) {\n this.canvas.bringToFront(this);\n }\n return this;\n },\n\n /**\n * Moves an object down in stack of drawn objects\n * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object\n * @return {fabric.Object} thisArg\n * @chainable\n */\n sendBackwards: function(intersecting) {\n if (this.group) {\n fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting);\n }\n else if (this.canvas) {\n this.canvas.sendBackwards(this, intersecting);\n }\n return this;\n },\n\n /**\n * Moves an object up in stack of drawn objects\n * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object\n * @return {fabric.Object} thisArg\n * @chainable\n */\n bringForward: function(intersecting) {\n if (this.group) {\n fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting);\n }\n else if (this.canvas) {\n this.canvas.bringForward(this, intersecting);\n }\n return this;\n },\n\n /**\n * Moves an object to specified level in stack of drawn objects\n * @param {Number} index New position of object\n * @return {fabric.Object} thisArg\n * @chainable\n */\n moveTo: function(index) {\n if (this.group && this.group.type !== 'activeSelection') {\n fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index);\n }\n else if (this.canvas) {\n this.canvas.moveTo(this, index);\n }\n return this;\n }\n});\n\n\n/* _TO_SVG_START_ */\n(function() {\n function getSvgColorString(prop, value) {\n if (!value) {\n return prop + ': none; ';\n }\n else if (value.toLive) {\n return prop + ': url(#SVGID_' + value.id + '); ';\n }\n else {\n var color = new fabric.Color(value),\n str = prop + ': ' + color.toRgb() + '; ',\n opacity = color.getAlpha();\n if (opacity !== 1) {\n //change the color in rgb + opacity\n str += prop + '-opacity: ' + opacity.toString() + '; ';\n }\n return str;\n }\n }\n\n var toFixed = fabric.util.toFixed;\n\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n /**\n * Returns styles-string for svg-export\n * @param {Boolean} skipShadow a boolean to skip shadow filter output\n * @return {String}\n */\n getSvgStyles: function(skipShadow) {\n\n var fillRule = this.fillRule ? this.fillRule : 'nonzero',\n strokeWidth = this.strokeWidth ? this.strokeWidth : '0',\n strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : 'none',\n strokeDashOffset = this.strokeDashOffset ? this.strokeDashOffset : '0',\n strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt',\n strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter',\n strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4',\n opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1',\n visibility = this.visible ? '' : ' visibility: hidden;',\n filter = skipShadow ? '' : this.getSvgFilter(),\n fill = getSvgColorString('fill', this.fill),\n stroke = getSvgColorString('stroke', this.stroke);\n\n return [\n stroke,\n 'stroke-width: ', strokeWidth, '; ',\n 'stroke-dasharray: ', strokeDashArray, '; ',\n 'stroke-linecap: ', strokeLineCap, '; ',\n 'stroke-dashoffset: ', strokeDashOffset, '; ',\n 'stroke-linejoin: ', strokeLineJoin, '; ',\n 'stroke-miterlimit: ', strokeMiterLimit, '; ',\n fill,\n 'fill-rule: ', fillRule, '; ',\n 'opacity: ', opacity, ';',\n filter,\n visibility\n ].join('');\n },\n\n /**\n * Returns styles-string for svg-export\n * @param {Object} style the object from which to retrieve style properties\n * @param {Boolean} useWhiteSpace a boolean to include an additional attribute in the style.\n * @return {String}\n */\n getSvgSpanStyles: function(style, useWhiteSpace) {\n var term = '; ';\n var fontFamily = style.fontFamily ?\n 'font-family: ' + (((style.fontFamily.indexOf('\\'') === -1 && style.fontFamily.indexOf('\"') === -1) ?\n '\\'' + style.fontFamily + '\\'' : style.fontFamily)) + term : '';\n var strokeWidth = style.strokeWidth ? 'stroke-width: ' + style.strokeWidth + term : '',\n fontFamily = fontFamily,\n fontSize = style.fontSize ? 'font-size: ' + style.fontSize + 'px' + term : '',\n fontStyle = style.fontStyle ? 'font-style: ' + style.fontStyle + term : '',\n fontWeight = style.fontWeight ? 'font-weight: ' + style.fontWeight + term : '',\n fill = style.fill ? getSvgColorString('fill', style.fill) : '',\n stroke = style.stroke ? getSvgColorString('stroke', style.stroke) : '',\n textDecoration = this.getSvgTextDecoration(style),\n deltaY = style.deltaY ? 'baseline-shift: ' + (-style.deltaY) + '; ' : '';\n if (textDecoration) {\n textDecoration = 'text-decoration: ' + textDecoration + term;\n }\n\n return [\n stroke,\n strokeWidth,\n fontFamily,\n fontSize,\n fontStyle,\n fontWeight,\n textDecoration,\n fill,\n deltaY,\n useWhiteSpace ? 'white-space: pre; ' : ''\n ].join('');\n },\n\n /**\n * Returns text-decoration property for svg-export\n * @param {Object} style the object from which to retrieve style properties\n * @return {String}\n */\n getSvgTextDecoration: function(style) {\n return ['overline', 'underline', 'line-through'].filter(function(decoration) {\n return style[decoration.replace('-', '')];\n }).join(' ');\n },\n\n /**\n * Returns filter for svg shadow\n * @return {String}\n */\n getSvgFilter: function() {\n return this.shadow ? 'filter: url(#SVGID_' + this.shadow.id + ');' : '';\n },\n\n /**\n * Returns id attribute for svg output\n * @return {String}\n */\n getSvgCommons: function() {\n return [\n this.id ? 'id=\"' + this.id + '\" ' : '',\n this.clipPath ? 'clip-path=\"url(#' + this.clipPath.clipPathId + ')\" ' : '',\n ].join('');\n },\n\n /**\n * Returns transform-string for svg-export\n * @param {Boolean} use the full transform or the single object one.\n * @return {String}\n */\n getSvgTransform: function(full, additionalTransform) {\n var transform = full ? this.calcTransformMatrix() : this.calcOwnMatrix(),\n svgTransform = 'transform=\"' + fabric.util.matrixToSVG(transform);\n return svgTransform +\n (additionalTransform || '') + '\" ';\n },\n\n _setSVGBg: function(textBgRects) {\n if (this.backgroundColor) {\n var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n textBgRects.push(\n '\\t\\t\\n');\n }\n },\n\n /**\n * Returns svg representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n return this._createBaseSVGMarkup(this._toSVG(reviver), { reviver: reviver });\n },\n\n /**\n * Returns svg clipPath representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toClipPathSVG: function(reviver) {\n return '\\t' + this._createBaseClipPathSVGMarkup(this._toSVG(reviver), { reviver: reviver });\n },\n\n /**\n * @private\n */\n _createBaseClipPathSVGMarkup: function(objectMarkup, options) {\n options = options || {};\n var reviver = options.reviver,\n additionalTransform = options.additionalTransform || '',\n commonPieces = [\n this.getSvgTransform(true, additionalTransform),\n this.getSvgCommons(),\n ].join(''),\n // insert commons in the markup, style and svgCommons\n index = objectMarkup.indexOf('COMMON_PARTS');\n objectMarkup[index] = commonPieces;\n return reviver ? reviver(objectMarkup.join('')) : objectMarkup.join('');\n },\n\n /**\n * @private\n */\n _createBaseSVGMarkup: function(objectMarkup, options) {\n options = options || {};\n var noStyle = options.noStyle,\n reviver = options.reviver,\n styleInfo = noStyle ? '' : 'style=\"' + this.getSvgStyles() + '\" ',\n shadowInfo = options.withShadow ? 'style=\"' + this.getSvgFilter() + '\" ' : '',\n clipPath = this.clipPath,\n vectorEffect = this.strokeUniform ? 'vector-effect=\"non-scaling-stroke\" ' : '',\n absoluteClipPath = clipPath && clipPath.absolutePositioned,\n stroke = this.stroke, fill = this.fill, shadow = this.shadow,\n commonPieces, markup = [], clipPathMarkup,\n // insert commons in the markup, style and svgCommons\n index = objectMarkup.indexOf('COMMON_PARTS'),\n additionalTransform = options.additionalTransform;\n if (clipPath) {\n clipPath.clipPathId = 'CLIPPATH_' + fabric.Object.__uid++;\n clipPathMarkup = '\\n' +\n clipPath.toClipPathSVG(reviver) +\n '\\n';\n }\n if (absoluteClipPath) {\n markup.push(\n '\\n'\n );\n }\n markup.push(\n '\\n'\n );\n commonPieces = [\n styleInfo,\n vectorEffect,\n noStyle ? '' : this.addPaintOrder(), ' ',\n additionalTransform ? 'transform=\"' + additionalTransform + '\" ' : '',\n ].join('');\n objectMarkup[index] = commonPieces;\n if (fill && fill.toLive) {\n markup.push(fill.toSVG(this));\n }\n if (stroke && stroke.toLive) {\n markup.push(stroke.toSVG(this));\n }\n if (shadow) {\n markup.push(shadow.toSVG(this));\n }\n if (clipPath) {\n markup.push(clipPathMarkup);\n }\n markup.push(objectMarkup.join(''));\n markup.push('\\n');\n absoluteClipPath && markup.push('\\n');\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n\n addPaintOrder: function() {\n return this.paintFirst !== 'fill' ? ' paint-order=\"' + this.paintFirst + '\" ' : '';\n }\n });\n})();\n/* _TO_SVG_END_ */\n\n\n(function() {\n\n var extend = fabric.util.object.extend,\n originalSet = 'stateProperties';\n\n /*\n Depends on `stateProperties`\n */\n function saveProps(origin, destination, props) {\n var tmpObj = { }, deep = true;\n props.forEach(function(prop) {\n tmpObj[prop] = origin[prop];\n });\n\n extend(origin[destination], tmpObj, deep);\n }\n\n function _isEqual(origValue, currentValue, firstPass) {\n if (origValue === currentValue) {\n // if the objects are identical, return\n return true;\n }\n else if (Array.isArray(origValue)) {\n if (!Array.isArray(currentValue) || origValue.length !== currentValue.length) {\n return false;\n }\n for (var i = 0, len = origValue.length; i < len; i++) {\n if (!_isEqual(origValue[i], currentValue[i])) {\n return false;\n }\n }\n return true;\n }\n else if (origValue && typeof origValue === 'object') {\n var keys = Object.keys(origValue), key;\n if (!currentValue ||\n typeof currentValue !== 'object' ||\n (!firstPass && keys.length !== Object.keys(currentValue).length)\n ) {\n return false;\n }\n for (var i = 0, len = keys.length; i < len; i++) {\n key = keys[i];\n // since clipPath is in the statefull cache list and the clipPath objects\n // would be iterated as an object, this would lead to possible infinite recursion\n // we do not want to compare those.\n if (key === 'canvas' || key === 'group') {\n continue;\n }\n if (!_isEqual(origValue[key], currentValue[key])) {\n return false;\n }\n }\n return true;\n }\n }\n\n\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * Returns true if object state (one of its state properties) was changed\n * @param {String} [propertySet] optional name for the set of property we want to save\n * @return {Boolean} true if instance' state has changed since `{@link fabric.Object#saveState}` was called\n */\n hasStateChanged: function(propertySet) {\n propertySet = propertySet || originalSet;\n var dashedPropertySet = '_' + propertySet;\n if (Object.keys(this[dashedPropertySet]).length < this[propertySet].length) {\n return true;\n }\n return !_isEqual(this[dashedPropertySet], this, true);\n },\n\n /**\n * Saves state of an object\n * @param {Object} [options] Object with additional `stateProperties` array to include when saving state\n * @return {fabric.Object} thisArg\n */\n saveState: function(options) {\n var propertySet = options && options.propertySet || originalSet,\n destination = '_' + propertySet;\n if (!this[destination]) {\n return this.setupState(options);\n }\n saveProps(this, destination, this[propertySet]);\n if (options && options.stateProperties) {\n saveProps(this, destination, options.stateProperties);\n }\n return this;\n },\n\n /**\n * Setups state of an object\n * @param {Object} [options] Object with additional `stateProperties` array to include when saving state\n * @return {fabric.Object} thisArg\n */\n setupState: function(options) {\n options = options || { };\n var propertySet = options.propertySet || originalSet;\n options.propertySet = propertySet;\n this['_' + propertySet] = { };\n this.saveState(options);\n return this;\n }\n });\n})();\n\n\n(function() {\n\n var degreesToRadians = fabric.util.degreesToRadians;\n\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n /**\n * Determines which corner has been clicked\n * @private\n * @param {Object} pointer The pointer indicating the mouse position\n * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or false if nothing is found\n */\n _findTargetCorner: function(pointer, forTouch) {\n // objects in group, anykind, are not self modificable,\n // must not return an hovered corner.\n if (!this.hasControls || this.group || (!this.canvas || this.canvas._activeObject !== this)) {\n return false;\n }\n\n var ex = pointer.x,\n ey = pointer.y,\n xPoints,\n lines, keys = Object.keys(this.oCoords),\n j = keys.length - 1, i;\n this.__corner = 0;\n\n // cycle in reverse order so we pick first the one on top\n for (; j >= 0; j--) {\n i = keys[j];\n if (!this.isControlVisible(i)) {\n continue;\n }\n\n lines = this._getImageLines(forTouch ? this.oCoords[i].touchCorner : this.oCoords[i].corner);\n // // debugging\n //\n // this.canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);\n // this.canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);\n //\n // this.canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);\n // this.canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);\n //\n // this.canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);\n // this.canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);\n //\n // this.canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);\n // this.canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);\n\n xPoints = this._findCrossPoints({ x: ex, y: ey }, lines);\n if (xPoints !== 0 && xPoints % 2 === 1) {\n this.__corner = i;\n return i;\n }\n }\n return false;\n },\n\n /**\n * Calls a function for each control. The function gets called,\n * with the control, the object that is calling the iterator and the control's key\n * @param {Function} fn function to iterate over the controls over\n */\n forEachControl: function(fn) {\n for (var i in this.controls) {\n fn(this.controls[i], i, this);\n };\n },\n\n /**\n * Sets the coordinates of the draggable boxes in the corners of\n * the image used to scale/rotate it.\n * note: if we would switch to ROUND corner area, all of this would disappear.\n * everything would resolve to a single point and a pythagorean theorem for the distance\n * @private\n */\n _setCornerCoords: function() {\n var coords = this.oCoords;\n\n for (var control in coords) {\n var controlObject = this.controls[control];\n coords[control].corner = controlObject.calcCornerCoords(\n this.angle, this.cornerSize, coords[control].x, coords[control].y, false);\n coords[control].touchCorner = controlObject.calcCornerCoords(\n this.angle, this.touchCornerSize, coords[control].x, coords[control].y, true);\n }\n },\n\n /**\n * Draws a colored layer behind the object, inside its selection borders.\n * Requires public options: padding, selectionBackgroundColor\n * this function is called when the context is transformed\n * has checks to be skipped when the object is on a staticCanvas\n * @param {CanvasRenderingContext2D} ctx Context to draw on\n * @return {fabric.Object} thisArg\n * @chainable\n */\n drawSelectionBackground: function(ctx) {\n if (!this.selectionBackgroundColor ||\n (this.canvas && !this.canvas.interactive) ||\n (this.canvas && this.canvas._activeObject !== this)\n ) {\n return this;\n }\n ctx.save();\n var center = this.getCenterPoint(), wh = this._calculateCurrentDimensions(),\n vpt = this.canvas.viewportTransform;\n ctx.translate(center.x, center.y);\n ctx.scale(1 / vpt[0], 1 / vpt[3]);\n ctx.rotate(degreesToRadians(this.angle));\n ctx.fillStyle = this.selectionBackgroundColor;\n ctx.fillRect(-wh.x / 2, -wh.y / 2, wh.x, wh.y);\n ctx.restore();\n return this;\n },\n\n /**\n * Draws borders of an object's bounding box.\n * Requires public properties: width, height\n * Requires public options: padding, borderColor\n * @param {CanvasRenderingContext2D} ctx Context to draw on\n * @param {Object} styleOverride object to override the object style\n * @return {fabric.Object} thisArg\n * @chainable\n */\n drawBorders: function(ctx, styleOverride) {\n styleOverride = styleOverride || {};\n var wh = this._calculateCurrentDimensions(),\n strokeWidth = this.borderScaleFactor,\n width = wh.x + strokeWidth,\n height = wh.y + strokeWidth,\n hasControls = typeof styleOverride.hasControls !== 'undefined' ?\n styleOverride.hasControls : this.hasControls,\n shouldStroke = false;\n\n ctx.save();\n ctx.strokeStyle = styleOverride.borderColor || this.borderColor;\n this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray);\n\n ctx.strokeRect(\n -width / 2,\n -height / 2,\n width,\n height\n );\n\n if (hasControls) {\n ctx.beginPath();\n this.forEachControl(function(control, key, fabricObject) {\n // in this moment, the ctx is centered on the object.\n // width and height of the above function are the size of the bbox.\n if (control.withConnection && control.getVisibility(fabricObject, key)) {\n // reset movement for each control\n shouldStroke = true;\n ctx.moveTo(control.x * width, control.y * height);\n ctx.lineTo(\n control.x * width + control.offsetX,\n control.y * height + control.offsetY\n );\n }\n });\n if (shouldStroke) {\n ctx.stroke();\n }\n }\n ctx.restore();\n return this;\n },\n\n /**\n * Draws borders of an object's bounding box when it is inside a group.\n * Requires public properties: width, height\n * Requires public options: padding, borderColor\n * @param {CanvasRenderingContext2D} ctx Context to draw on\n * @param {object} options object representing current object parameters\n * @param {Object} styleOverride object to override the object style\n * @return {fabric.Object} thisArg\n * @chainable\n */\n drawBordersInGroup: function(ctx, options, styleOverride) {\n styleOverride = styleOverride || {};\n var bbox = fabric.util.sizeAfterTransform(this.width, this.height, options),\n strokeWidth = this.strokeWidth,\n strokeUniform = this.strokeUniform,\n borderScaleFactor = this.borderScaleFactor,\n width =\n bbox.x + strokeWidth * (strokeUniform ? this.canvas.getZoom() : options.scaleX) + borderScaleFactor,\n height =\n bbox.y + strokeWidth * (strokeUniform ? this.canvas.getZoom() : options.scaleY) + borderScaleFactor;\n ctx.save();\n this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray);\n ctx.strokeStyle = styleOverride.borderColor || this.borderColor;\n ctx.strokeRect(\n -width / 2,\n -height / 2,\n width,\n height\n );\n\n ctx.restore();\n return this;\n },\n\n /**\n * Draws corners of an object's bounding box.\n * Requires public properties: width, height\n * Requires public options: cornerSize, padding\n * @param {CanvasRenderingContext2D} ctx Context to draw on\n * @param {Object} styleOverride object to override the object style\n * @return {fabric.Object} thisArg\n * @chainable\n */\n drawControls: function(ctx, styleOverride) {\n styleOverride = styleOverride || {};\n ctx.save();\n var retinaScaling = 1, matrix, p;\n if (this.canvas) {\n retinaScaling = this.canvas.getRetinaScaling();\n }\n ctx.setTransform(retinaScaling, 0, 0, retinaScaling, 0, 0);\n ctx.strokeStyle = ctx.fillStyle = styleOverride.cornerColor || this.cornerColor;\n if (!this.transparentCorners) {\n ctx.strokeStyle = styleOverride.cornerStrokeColor || this.cornerStrokeColor;\n }\n this._setLineDash(ctx, styleOverride.cornerDashArray || this.cornerDashArray);\n this.setCoords();\n if (this.group) {\n // fabricJS does not really support drawing controls inside groups,\n // this piece of code here helps having at least the control in places.\n // If an application needs to show some objects as selected because of some UI state\n // can still call Object._renderControls() on any object they desire, independently of groups.\n // using no padding, circular controls and hiding the rotating cursor is higly suggested,\n matrix = this.group.calcTransformMatrix();\n }\n this.forEachControl(function(control, key, fabricObject) {\n p = fabricObject.oCoords[key];\n if (control.getVisibility(fabricObject, key)) {\n if (matrix) {\n p = fabric.util.transformPoint(p, matrix);\n }\n control.render(ctx, p.x, p.y, styleOverride, fabricObject);\n }\n });\n ctx.restore();\n\n return this;\n },\n\n /**\n * Returns true if the specified control is visible, false otherwise.\n * @param {String} controlKey The key of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'.\n * @returns {Boolean} true if the specified control is visible, false otherwise\n */\n isControlVisible: function(controlKey) {\n return this.controls[controlKey] && this.controls[controlKey].getVisibility(this, controlKey);\n },\n\n /**\n * Sets the visibility of the specified control.\n * @param {String} controlKey The key of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'.\n * @param {Boolean} visible true to set the specified control visible, false otherwise\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setControlVisible: function(controlKey, visible) {\n if (!this._controlsVisibility) {\n this._controlsVisibility = {};\n }\n this._controlsVisibility[controlKey] = visible;\n return this;\n },\n\n /**\n * Sets the visibility state of object controls.\n * @param {Object} [options] Options object\n * @param {Boolean} [options.bl] true to enable the bottom-left control, false to disable it\n * @param {Boolean} [options.br] true to enable the bottom-right control, false to disable it\n * @param {Boolean} [options.mb] true to enable the middle-bottom control, false to disable it\n * @param {Boolean} [options.ml] true to enable the middle-left control, false to disable it\n * @param {Boolean} [options.mr] true to enable the middle-right control, false to disable it\n * @param {Boolean} [options.mt] true to enable the middle-top control, false to disable it\n * @param {Boolean} [options.tl] true to enable the top-left control, false to disable it\n * @param {Boolean} [options.tr] true to enable the top-right control, false to disable it\n * @param {Boolean} [options.mtr] true to enable the middle-top-rotate control, false to disable it\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setControlsVisibility: function(options) {\n options || (options = { });\n\n for (var p in options) {\n this.setControlVisible(p, options[p]);\n }\n return this;\n },\n\n\n /**\n * This callback function is called every time _discardActiveObject or _setActiveObject\n * try to to deselect this object. If the function returns true, the process is cancelled\n * @param {Object} [options] options sent from the upper functions\n * @param {Event} [options.e] event if the process is generated by an event\n */\n onDeselect: function() {\n // implemented by sub-classes, as needed.\n },\n\n\n /**\n * This callback function is called every time _discardActiveObject or _setActiveObject\n * try to to select this object. If the function returns true, the process is cancelled\n * @param {Object} [options] options sent from the upper functions\n * @param {Event} [options.e] event if the process is generated by an event\n */\n onSelect: function() {\n // implemented by sub-classes, as needed.\n }\n });\n})();\n\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n /**\n * Animation duration (in ms) for fx* methods\n * @type Number\n * @default\n */\n FX_DURATION: 500,\n\n /**\n * Centers object horizontally with animation.\n * @param {fabric.Object} object Object to center\n * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n * @param {Function} [callbacks.onComplete] Invoked on completion\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\n * @return {fabric.AnimationContext} context\n */\n fxCenterObjectH: function (object, callbacks) {\n callbacks = callbacks || { };\n\n var empty = function() { },\n onComplete = callbacks.onComplete || empty,\n onChange = callbacks.onChange || empty,\n _this = this;\n\n return fabric.util.animate({\n target: this,\n startValue: object.left,\n endValue: this.getCenterPoint().x,\n duration: this.FX_DURATION,\n onChange: function(value) {\n object.set('left', value);\n _this.requestRenderAll();\n onChange();\n },\n onComplete: function() {\n object.setCoords();\n onComplete();\n }\n });\n },\n\n /**\n * Centers object vertically with animation.\n * @param {fabric.Object} object Object to center\n * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n * @param {Function} [callbacks.onComplete] Invoked on completion\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\n * @return {fabric.AnimationContext} context\n */\n fxCenterObjectV: function (object, callbacks) {\n callbacks = callbacks || { };\n\n var empty = function() { },\n onComplete = callbacks.onComplete || empty,\n onChange = callbacks.onChange || empty,\n _this = this;\n\n return fabric.util.animate({\n target: this,\n startValue: object.top,\n endValue: this.getCenterPoint().y,\n duration: this.FX_DURATION,\n onChange: function(value) {\n object.set('top', value);\n _this.requestRenderAll();\n onChange();\n },\n onComplete: function() {\n object.setCoords();\n onComplete();\n }\n });\n },\n\n /**\n * Same as `fabric.Canvas#remove` but animated\n * @param {fabric.Object} object Object to remove\n * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n * @param {Function} [callbacks.onComplete] Invoked on completion\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\n * @return {fabric.AnimationContext} context\n */\n fxRemove: function (object, callbacks) {\n callbacks = callbacks || { };\n\n var empty = function() { },\n onComplete = callbacks.onComplete || empty,\n onChange = callbacks.onChange || empty,\n _this = this;\n\n return fabric.util.animate({\n target: this,\n startValue: object.opacity,\n endValue: 0,\n duration: this.FX_DURATION,\n onChange: function(value) {\n object.set('opacity', value);\n _this.requestRenderAll();\n onChange();\n },\n onComplete: function () {\n _this.remove(object);\n onComplete();\n }\n });\n }\n});\n\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n /**\n * Animates object's properties\n * @param {String|Object} property Property to animate (if string) or properties to animate (if object)\n * @param {Number|Object} value Value to animate property to (if string was given first) or options object\n * @return {fabric.Object} thisArg\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#animation}\n * @return {fabric.AnimationContext | fabric.AnimationContext[]} animation context (or an array if passed multiple properties)\n *\n * As object — multiple properties\n *\n * object.animate({ left: ..., top: ... });\n * object.animate({ left: ..., top: ... }, { duration: ... });\n *\n * As string — one property\n *\n * object.animate('left', ...);\n * object.animate('left', { duration: ... });\n *\n */\n animate: function () {\n if (arguments[0] && typeof arguments[0] === 'object') {\n var propsToAnimate = [], prop, skipCallbacks, out = [];\n for (prop in arguments[0]) {\n propsToAnimate.push(prop);\n }\n for (var i = 0, len = propsToAnimate.length; i < len; i++) {\n prop = propsToAnimate[i];\n skipCallbacks = i !== len - 1;\n out.push(this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks));\n }\n return out;\n }\n else {\n return this._animate.apply(this, arguments);\n }\n },\n\n /**\n * @private\n * @param {String} property Property to animate\n * @param {String} to Value to animate to\n * @param {Object} [options] Options object\n * @param {Boolean} [skipCallbacks] When true, callbacks like onchange and oncomplete are not invoked\n */\n _animate: function(property, to, options, skipCallbacks) {\n var _this = this, propPair;\n\n to = to.toString();\n\n if (!options) {\n options = { };\n }\n else {\n options = fabric.util.object.clone(options);\n }\n\n if (~property.indexOf('.')) {\n propPair = property.split('.');\n }\n\n var propIsColor =\n _this.colorProperties.indexOf(property) > -1 ||\n (propPair && _this.colorProperties.indexOf(propPair[1]) > -1);\n\n var currentValue = propPair\n ? this.get(propPair[0])[propPair[1]]\n : this.get(property);\n\n if (!('from' in options)) {\n options.from = currentValue;\n }\n\n if (!propIsColor) {\n if (~to.indexOf('=')) {\n to = currentValue + parseFloat(to.replace('=', ''));\n }\n else {\n to = parseFloat(to);\n }\n }\n\n var _options = {\n target: this,\n startValue: options.from,\n endValue: to,\n byValue: options.by,\n easing: options.easing,\n duration: options.duration,\n abort: options.abort && function(value, valueProgress, timeProgress) {\n return options.abort.call(_this, value, valueProgress, timeProgress);\n },\n onChange: function (value, valueProgress, timeProgress) {\n if (propPair) {\n _this[propPair[0]][propPair[1]] = value;\n }\n else {\n _this.set(property, value);\n }\n if (skipCallbacks) {\n return;\n }\n options.onChange && options.onChange(value, valueProgress, timeProgress);\n },\n onComplete: function (value, valueProgress, timeProgress) {\n if (skipCallbacks) {\n return;\n }\n\n _this.setCoords();\n options.onComplete && options.onComplete(value, valueProgress, timeProgress);\n }\n };\n\n if (propIsColor) {\n return fabric.util.animateColor(_options.startValue, _options.endValue, _options.duration, _options);\n }\n else {\n return fabric.util.animate(_options);\n }\n }\n});\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n clone = fabric.util.object.clone,\n coordProps = { x1: 1, x2: 1, y1: 1, y2: 1 };\n\n if (fabric.Line) {\n fabric.warn('fabric.Line is already defined');\n return;\n }\n\n /**\n * Line class\n * @class fabric.Line\n * @extends fabric.Object\n * @see {@link fabric.Line#initialize} for constructor definition\n */\n fabric.Line = fabric.util.createClass(fabric.Object, /** @lends fabric.Line.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'line',\n\n /**\n * x value or first line edge\n * @type Number\n * @default\n */\n x1: 0,\n\n /**\n * y value or first line edge\n * @type Number\n * @default\n */\n y1: 0,\n\n /**\n * x value or second line edge\n * @type Number\n * @default\n */\n x2: 0,\n\n /**\n * y value or second line edge\n * @type Number\n * @default\n */\n y2: 0,\n\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('x1', 'x2', 'y1', 'y2'),\n\n /**\n * Constructor\n * @param {Array} [points] Array of points\n * @param {Object} [options] Options object\n * @return {fabric.Line} thisArg\n */\n initialize: function(points, options) {\n if (!points) {\n points = [0, 0, 0, 0];\n }\n\n this.callSuper('initialize', options);\n\n this.set('x1', points[0]);\n this.set('y1', points[1]);\n this.set('x2', points[2]);\n this.set('y2', points[3]);\n\n this._setWidthHeight(options);\n },\n\n /**\n * @private\n * @param {Object} [options] Options\n */\n _setWidthHeight: function(options) {\n options || (options = { });\n\n this.width = Math.abs(this.x2 - this.x1);\n this.height = Math.abs(this.y2 - this.y1);\n\n this.left = 'left' in options\n ? options.left\n : this._getLeftToOriginX();\n\n this.top = 'top' in options\n ? options.top\n : this._getTopToOriginY();\n },\n\n /**\n * @private\n * @param {String} key\n * @param {*} value\n */\n _set: function(key, value) {\n this.callSuper('_set', key, value);\n if (typeof coordProps[key] !== 'undefined') {\n this._setWidthHeight();\n }\n return this;\n },\n\n /**\n * @private\n * @return {Number} leftToOriginX Distance from left edge of canvas to originX of Line.\n */\n _getLeftToOriginX: makeEdgeToOriginGetter(\n { // property names\n origin: 'originX',\n axis1: 'x1',\n axis2: 'x2',\n dimension: 'width'\n },\n { // possible values of origin\n nearest: 'left',\n center: 'center',\n farthest: 'right'\n }\n ),\n\n /**\n * @private\n * @return {Number} topToOriginY Distance from top edge of canvas to originY of Line.\n */\n _getTopToOriginY: makeEdgeToOriginGetter(\n { // property names\n origin: 'originY',\n axis1: 'y1',\n axis2: 'y2',\n dimension: 'height'\n },\n { // possible values of origin\n nearest: 'top',\n center: 'center',\n farthest: 'bottom'\n }\n ),\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n ctx.beginPath();\n\n\n var p = this.calcLinePoints();\n ctx.moveTo(p.x1, p.y1);\n ctx.lineTo(p.x2, p.y2);\n\n ctx.lineWidth = this.strokeWidth;\n\n // TODO: test this\n // make sure setting \"fill\" changes color of a line\n // (by copying fillStyle to strokeStyle, since line is stroked, not filled)\n var origStrokeStyle = ctx.strokeStyle;\n ctx.strokeStyle = this.stroke || ctx.fillStyle;\n this.stroke && this._renderStroke(ctx);\n ctx.strokeStyle = origStrokeStyle;\n },\n\n /**\n * This function is an helper for svg import. it returns the center of the object in the svg\n * untransformed coordinates\n * @private\n * @return {Object} center point from element coordinates\n */\n _findCenterFromElement: function() {\n return {\n x: (this.x1 + this.x2) / 2,\n y: (this.y1 + this.y2) / 2,\n };\n },\n\n /**\n * Returns object representation of an instance\n * @method toObject\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return extend(this.callSuper('toObject', propertiesToInclude), this.calcLinePoints());\n },\n\n /*\n * Calculate object dimensions from its properties\n * @private\n */\n _getNonTransformedDimensions: function() {\n var dim = this.callSuper('_getNonTransformedDimensions');\n if (this.strokeLineCap === 'butt') {\n if (this.width === 0) {\n dim.y -= this.strokeWidth;\n }\n if (this.height === 0) {\n dim.x -= this.strokeWidth;\n }\n }\n return dim;\n },\n\n /**\n * Recalculates line points given width and height\n * @private\n */\n calcLinePoints: function() {\n var xMult = this.x1 <= this.x2 ? -1 : 1,\n yMult = this.y1 <= this.y2 ? -1 : 1,\n x1 = (xMult * this.width * 0.5),\n y1 = (yMult * this.height * 0.5),\n x2 = (xMult * this.width * -0.5),\n y2 = (yMult * this.height * -0.5);\n\n return {\n x1: x1,\n x2: x2,\n y1: y1,\n y2: y2\n };\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG: function() {\n var p = this.calcLinePoints();\n return [\n '\\n'\n ];\n },\n /* _TO_SVG_END_ */\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement})\n * @static\n * @memberOf fabric.Line\n * @see http://www.w3.org/TR/SVG/shapes.html#LineElement\n */\n fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' '));\n\n /**\n * Returns fabric.Line instance from an SVG element\n * @static\n * @memberOf fabric.Line\n * @param {SVGElement} element Element to parse\n * @param {Object} [options] Options object\n * @param {Function} [callback] callback function invoked after parsing\n */\n fabric.Line.fromElement = function(element, callback, options) {\n options = options || { };\n var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES),\n points = [\n parsedAttributes.x1 || 0,\n parsedAttributes.y1 || 0,\n parsedAttributes.x2 || 0,\n parsedAttributes.y2 || 0\n ];\n callback(new fabric.Line(points, extend(parsedAttributes, options)));\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Returns fabric.Line instance from an object representation\n * @static\n * @memberOf fabric.Line\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] invoked with new instance as first argument\n */\n fabric.Line.fromObject = function(object, callback) {\n function _callback(instance) {\n delete instance.points;\n callback && callback(instance);\n };\n var options = clone(object, true);\n options.points = [object.x1, object.y1, object.x2, object.y2];\n fabric.Object._fromObject('Line', options, _callback, 'points');\n };\n\n /**\n * Produces a function that calculates distance from canvas edge to Line origin.\n */\n function makeEdgeToOriginGetter(propertyNames, originValues) {\n var origin = propertyNames.origin,\n axis1 = propertyNames.axis1,\n axis2 = propertyNames.axis2,\n dimension = propertyNames.dimension,\n nearest = originValues.nearest,\n center = originValues.center,\n farthest = originValues.farthest;\n\n return function() {\n switch (this.get(origin)) {\n case nearest:\n return Math.min(this.get(axis1), this.get(axis2));\n case center:\n return Math.min(this.get(axis1), this.get(axis2)) + (0.5 * this.get(dimension));\n case farthest:\n return Math.max(this.get(axis1), this.get(axis2));\n }\n };\n\n }\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n degreesToRadians = fabric.util.degreesToRadians;\n\n if (fabric.Circle) {\n fabric.warn('fabric.Circle is already defined.');\n return;\n }\n\n /**\n * Circle class\n * @class fabric.Circle\n * @extends fabric.Object\n * @see {@link fabric.Circle#initialize} for constructor definition\n */\n fabric.Circle = fabric.util.createClass(fabric.Object, /** @lends fabric.Circle.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'circle',\n\n /**\n * Radius of this circle\n * @type Number\n * @default\n */\n radius: 0,\n\n /**\n * degrees of start of the circle.\n * probably will change to degrees in next major version\n * @type Number 0 - 359\n * @default 0\n */\n startAngle: 0,\n\n /**\n * End angle of the circle\n * probably will change to degrees in next major version\n * @type Number 1 - 360\n * @default 360\n */\n endAngle: 360,\n\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('radius', 'startAngle', 'endAngle'),\n\n /**\n * @private\n * @param {String} key\n * @param {*} value\n * @return {fabric.Circle} thisArg\n */\n _set: function(key, value) {\n this.callSuper('_set', key, value);\n\n if (key === 'radius') {\n this.setRadius(value);\n }\n\n return this;\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return this.callSuper('toObject', ['radius', 'startAngle', 'endAngle'].concat(propertiesToInclude));\n },\n\n /* _TO_SVG_START_ */\n\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG: function() {\n var svgString, x = 0, y = 0,\n angle = (this.endAngle - this.startAngle) % 360;\n\n if (angle === 0) {\n svgString = [\n '\\n'\n ];\n }\n else {\n var start = degreesToRadians(this.startAngle),\n end = degreesToRadians(this.endAngle),\n radius = this.radius,\n startX = fabric.util.cos(start) * radius,\n startY = fabric.util.sin(start) * radius,\n endX = fabric.util.cos(end) * radius,\n endY = fabric.util.sin(end) * radius,\n largeFlag = angle > 180 ? '1' : '0';\n svgString = [\n '\\n'\n ];\n }\n return svgString;\n },\n /* _TO_SVG_END_ */\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render on\n */\n _render: function(ctx) {\n ctx.beginPath();\n ctx.arc(\n 0,\n 0,\n this.radius,\n degreesToRadians(this.startAngle),\n degreesToRadians(this.endAngle),\n false\n );\n this._renderPaintInOrder(ctx);\n },\n\n /**\n * Returns horizontal radius of an object (according to how an object is scaled)\n * @return {Number}\n */\n getRadiusX: function() {\n return this.get('radius') * this.get('scaleX');\n },\n\n /**\n * Returns vertical radius of an object (according to how an object is scaled)\n * @return {Number}\n */\n getRadiusY: function() {\n return this.get('radius') * this.get('scaleY');\n },\n\n /**\n * Sets radius of an object (and updates width accordingly)\n * @return {fabric.Circle} thisArg\n */\n setRadius: function(value) {\n this.radius = value;\n return this.set('width', value * 2).set('height', value * 2);\n },\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Circle.fromElement})\n * @static\n * @memberOf fabric.Circle\n * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement\n */\n fabric.Circle.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy r'.split(' '));\n\n /**\n * Returns {@link fabric.Circle} instance from an SVG element\n * @static\n * @memberOf fabric.Circle\n * @param {SVGElement} element Element to parse\n * @param {Function} [callback] Options callback invoked after parsing is finished\n * @param {Object} [options] Options object\n * @throws {Error} If value of `r` attribute is missing or invalid\n */\n fabric.Circle.fromElement = function(element, callback) {\n var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES);\n\n if (!isValidRadius(parsedAttributes)) {\n throw new Error('value of `r` attribute is required and can not be negative');\n }\n\n parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.radius;\n parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.radius;\n callback(new fabric.Circle(parsedAttributes));\n };\n\n /**\n * @private\n */\n function isValidRadius(attributes) {\n return (('radius' in attributes) && (attributes.radius >= 0));\n }\n /* _FROM_SVG_END_ */\n\n /**\n * Returns {@link fabric.Circle} instance from an object representation\n * @static\n * @memberOf fabric.Circle\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] invoked with new instance as first argument\n * @return {void}\n */\n fabric.Circle.fromObject = function(object, callback) {\n fabric.Object._fromObject('Circle', object, callback);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { });\n\n if (fabric.Triangle) {\n fabric.warn('fabric.Triangle is already defined');\n return;\n }\n\n /**\n * Triangle class\n * @class fabric.Triangle\n * @extends fabric.Object\n * @return {fabric.Triangle} thisArg\n * @see {@link fabric.Triangle#initialize} for constructor definition\n */\n fabric.Triangle = fabric.util.createClass(fabric.Object, /** @lends fabric.Triangle.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'triangle',\n\n /**\n * Width is set to 100 to compensate the old initialize code that was setting it to 100\n * @type Number\n * @default\n */\n width: 100,\n\n /**\n * Height is set to 100 to compensate the old initialize code that was setting it to 100\n * @type Number\n * @default\n */\n height: 100,\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n var widthBy2 = this.width / 2,\n heightBy2 = this.height / 2;\n\n ctx.beginPath();\n ctx.moveTo(-widthBy2, heightBy2);\n ctx.lineTo(0, -heightBy2);\n ctx.lineTo(widthBy2, heightBy2);\n ctx.closePath();\n\n this._renderPaintInOrder(ctx);\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG: function() {\n var widthBy2 = this.width / 2,\n heightBy2 = this.height / 2,\n points = [\n -widthBy2 + ' ' + heightBy2,\n '0 ' + -heightBy2,\n widthBy2 + ' ' + heightBy2\n ].join(',');\n return [\n ''\n ];\n },\n /* _TO_SVG_END_ */\n });\n\n /**\n * Returns {@link fabric.Triangle} instance from an object representation\n * @static\n * @memberOf fabric.Triangle\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] invoked with new instance as first argument\n */\n fabric.Triangle.fromObject = function(object, callback) {\n return fabric.Object._fromObject('Triangle', object, callback);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n piBy2 = Math.PI * 2;\n\n if (fabric.Ellipse) {\n fabric.warn('fabric.Ellipse is already defined.');\n return;\n }\n\n /**\n * Ellipse class\n * @class fabric.Ellipse\n * @extends fabric.Object\n * @return {fabric.Ellipse} thisArg\n * @see {@link fabric.Ellipse#initialize} for constructor definition\n */\n fabric.Ellipse = fabric.util.createClass(fabric.Object, /** @lends fabric.Ellipse.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'ellipse',\n\n /**\n * Horizontal radius\n * @type Number\n * @default\n */\n rx: 0,\n\n /**\n * Vertical radius\n * @type Number\n * @default\n */\n ry: 0,\n\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('rx', 'ry'),\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n * @return {fabric.Ellipse} thisArg\n */\n initialize: function(options) {\n this.callSuper('initialize', options);\n this.set('rx', options && options.rx || 0);\n this.set('ry', options && options.ry || 0);\n },\n\n /**\n * @private\n * @param {String} key\n * @param {*} value\n * @return {fabric.Ellipse} thisArg\n */\n _set: function(key, value) {\n this.callSuper('_set', key, value);\n switch (key) {\n\n case 'rx':\n this.rx = value;\n this.set('width', value * 2);\n break;\n\n case 'ry':\n this.ry = value;\n this.set('height', value * 2);\n break;\n\n }\n return this;\n },\n\n /**\n * Returns horizontal radius of an object (according to how an object is scaled)\n * @return {Number}\n */\n getRx: function() {\n return this.get('rx') * this.get('scaleX');\n },\n\n /**\n * Returns Vertical radius of an object (according to how an object is scaled)\n * @return {Number}\n */\n getRy: function() {\n return this.get('ry') * this.get('scaleY');\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return this.callSuper('toObject', ['rx', 'ry'].concat(propertiesToInclude));\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG: function() {\n return [\n '\\n'\n ];\n },\n /* _TO_SVG_END_ */\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render on\n */\n _render: function(ctx) {\n ctx.beginPath();\n ctx.save();\n ctx.transform(1, 0, 0, this.ry / this.rx, 0, 0);\n ctx.arc(\n 0,\n 0,\n this.rx,\n 0,\n piBy2,\n false);\n ctx.restore();\n this._renderPaintInOrder(ctx);\n },\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Ellipse.fromElement})\n * @static\n * @memberOf fabric.Ellipse\n * @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement\n */\n fabric.Ellipse.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy rx ry'.split(' '));\n\n /**\n * Returns {@link fabric.Ellipse} instance from an SVG element\n * @static\n * @memberOf fabric.Ellipse\n * @param {SVGElement} element Element to parse\n * @param {Function} [callback] Options callback invoked after parsing is finished\n * @return {fabric.Ellipse}\n */\n fabric.Ellipse.fromElement = function(element, callback) {\n\n var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES);\n\n parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.rx;\n parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.ry;\n callback(new fabric.Ellipse(parsedAttributes));\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Returns {@link fabric.Ellipse} instance from an object representation\n * @static\n * @memberOf fabric.Ellipse\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] invoked with new instance as first argument\n * @return {void}\n */\n fabric.Ellipse.fromObject = function(object, callback) {\n fabric.Object._fromObject('Ellipse', object, callback);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend;\n\n if (fabric.Rect) {\n fabric.warn('fabric.Rect is already defined');\n return;\n }\n\n /**\n * Rectangle class\n * @class fabric.Rect\n * @extends fabric.Object\n * @return {fabric.Rect} thisArg\n * @see {@link fabric.Rect#initialize} for constructor definition\n */\n fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ {\n\n /**\n * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})\n * as well as for history (undo/redo) purposes\n * @type Array\n */\n stateProperties: fabric.Object.prototype.stateProperties.concat('rx', 'ry'),\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'rect',\n\n /**\n * Horizontal border radius\n * @type Number\n * @default\n */\n rx: 0,\n\n /**\n * Vertical border radius\n * @type Number\n * @default\n */\n ry: 0,\n\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('rx', 'ry'),\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n * @return {Object} thisArg\n */\n initialize: function(options) {\n this.callSuper('initialize', options);\n this._initRxRy();\n },\n\n /**\n * Initializes rx/ry attributes\n * @private\n */\n _initRxRy: function() {\n if (this.rx && !this.ry) {\n this.ry = this.rx;\n }\n else if (this.ry && !this.rx) {\n this.rx = this.ry;\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n\n // 1x1 case (used in spray brush) optimization was removed because\n // with caching and higher zoom level this makes more damage than help\n\n var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0,\n ry = this.ry ? Math.min(this.ry, this.height / 2) : 0,\n w = this.width,\n h = this.height,\n x = -this.width / 2,\n y = -this.height / 2,\n isRounded = rx !== 0 || ry !== 0,\n /* \"magic number\" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */\n k = 1 - 0.5522847498;\n ctx.beginPath();\n\n ctx.moveTo(x + rx, y);\n\n ctx.lineTo(x + w - rx, y);\n isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry);\n\n ctx.lineTo(x + w, y + h - ry);\n isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h);\n\n ctx.lineTo(x + rx, y + h);\n isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry);\n\n ctx.lineTo(x, y + ry);\n isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y);\n\n ctx.closePath();\n\n this._renderPaintInOrder(ctx);\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return this.callSuper('toObject', ['rx', 'ry'].concat(propertiesToInclude));\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG: function() {\n var x = -this.width / 2, y = -this.height / 2;\n return [\n '\\n'\n ];\n },\n /* _TO_SVG_END_ */\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`)\n * @static\n * @memberOf fabric.Rect\n * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement\n */\n fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' '));\n\n /**\n * Returns {@link fabric.Rect} instance from an SVG element\n * @static\n * @memberOf fabric.Rect\n * @param {SVGElement} element Element to parse\n * @param {Function} callback callback function invoked after parsing\n * @param {Object} [options] Options object\n */\n fabric.Rect.fromElement = function(element, callback, options) {\n if (!element) {\n return callback(null);\n }\n options = options || { };\n\n var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);\n parsedAttributes.left = parsedAttributes.left || 0;\n parsedAttributes.top = parsedAttributes.top || 0;\n parsedAttributes.height = parsedAttributes.height || 0;\n parsedAttributes.width = parsedAttributes.width || 0;\n var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));\n rect.visible = rect.visible && rect.width > 0 && rect.height > 0;\n callback(rect);\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Returns {@link fabric.Rect} instance from an object representation\n * @static\n * @memberOf fabric.Rect\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] Callback to invoke when an fabric.Rect instance is created\n */\n fabric.Rect.fromObject = function(object, callback) {\n return fabric.Object._fromObject('Rect', object, callback);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n min = fabric.util.array.min,\n max = fabric.util.array.max,\n toFixed = fabric.util.toFixed,\n projectStrokeOnPoints = fabric.util.projectStrokeOnPoints;\n\n if (fabric.Polyline) {\n fabric.warn('fabric.Polyline is already defined');\n return;\n }\n\n /**\n * Polyline class\n * @class fabric.Polyline\n * @extends fabric.Object\n * @see {@link fabric.Polyline#initialize} for constructor definition\n */\n fabric.Polyline = fabric.util.createClass(fabric.Object, /** @lends fabric.Polyline.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'polyline',\n\n /**\n * Points array\n * @type Array\n * @default\n */\n points: null,\n\n /**\n * WARNING: Feature in progress\n * Calculate the exact bounding box taking in account strokeWidth on acute angles\n * this will be turned to true by default on fabric 6.0\n * maybe will be left in as an optimization since calculations may be slow\n * @deprecated\n * @type Boolean\n * @default false\n */\n exactBoundingBox: false,\n\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('points'),\n\n /**\n * Constructor\n * @param {Array} points Array of points (where each point is an object with x and y)\n * @param {Object} [options] Options object\n * @return {fabric.Polyline} thisArg\n * @example\n * var poly = new fabric.Polyline([\n * { x: 10, y: 10 },\n * { x: 50, y: 30 },\n * { x: 40, y: 70 },\n * { x: 60, y: 50 },\n * { x: 100, y: 150 },\n * { x: 40, y: 100 }\n * ], {\n * stroke: 'red',\n * left: 100,\n * top: 100\n * });\n */\n initialize: function(points, options) {\n options = options || {};\n this.points = points || [];\n this.callSuper('initialize', options);\n this._setPositionDimensions(options);\n },\n\n /**\n * @private\n */\n _projectStrokeOnPoints: function () {\n return projectStrokeOnPoints(this.points, this, true);\n },\n\n _setPositionDimensions: function(options) {\n var calcDim = this._calcDimensions(options), correctLeftTop,\n correctSize = this.exactBoundingBox ? this.strokeWidth : 0;\n this.width = calcDim.width - correctSize;\n this.height = calcDim.height - correctSize;\n if (!options.fromSVG) {\n correctLeftTop = this.translateToGivenOrigin(\n {\n // this looks bad, but is one way to keep it optional for now.\n x: calcDim.left - this.strokeWidth / 2 + correctSize / 2,\n y: calcDim.top - this.strokeWidth / 2 + correctSize / 2\n },\n 'left',\n 'top',\n this.originX,\n this.originY\n );\n }\n if (typeof options.left === 'undefined') {\n this.left = options.fromSVG ? calcDim.left : correctLeftTop.x;\n }\n if (typeof options.top === 'undefined') {\n this.top = options.fromSVG ? calcDim.top : correctLeftTop.y;\n }\n this.pathOffset = {\n x: calcDim.left + this.width / 2 + correctSize / 2,\n y: calcDim.top + this.height / 2 + correctSize / 2\n };\n },\n\n /**\n * Calculate the polygon min and max point from points array,\n * returning an object with left, top, width, height to measure the\n * polygon size\n * @return {Object} object.left X coordinate of the polygon leftmost point\n * @return {Object} object.top Y coordinate of the polygon topmost point\n * @return {Object} object.width distance between X coordinates of the polygon leftmost and rightmost point\n * @return {Object} object.height distance between Y coordinates of the polygon topmost and bottommost point\n * @private\n */\n _calcDimensions: function() {\n\n var points = this.exactBoundingBox ? this._projectStrokeOnPoints() : this.points,\n minX = min(points, 'x') || 0,\n minY = min(points, 'y') || 0,\n maxX = max(points, 'x') || 0,\n maxY = max(points, 'y') || 0,\n width = (maxX - minX),\n height = (maxY - minY);\n\n return {\n left: minX,\n top: minY,\n width: width,\n height: height,\n };\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return extend(this.callSuper('toObject', propertiesToInclude), {\n points: this.points.concat()\n });\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG: function() {\n var points = [], diffX = this.pathOffset.x, diffY = this.pathOffset.y,\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n\n for (var i = 0, len = this.points.length; i < len; i++) {\n points.push(\n toFixed(this.points[i].x - diffX, NUM_FRACTION_DIGITS), ',',\n toFixed(this.points[i].y - diffY, NUM_FRACTION_DIGITS), ' '\n );\n }\n return [\n '<' + this.type + ' ', 'COMMON_PARTS',\n 'points=\"', points.join(''),\n '\" />\\n'\n ];\n },\n /* _TO_SVG_END_ */\n\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n commonRender: function(ctx) {\n var point, len = this.points.length,\n x = this.pathOffset.x,\n y = this.pathOffset.y;\n\n if (!len || isNaN(this.points[len - 1].y)) {\n // do not draw if no points or odd points\n // NaN comes from parseFloat of a empty string in parser\n return false;\n }\n ctx.beginPath();\n ctx.moveTo(this.points[0].x - x, this.points[0].y - y);\n for (var i = 0; i < len; i++) {\n point = this.points[i];\n ctx.lineTo(point.x - x, point.y - y);\n }\n return true;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n if (!this.commonRender(ctx)) {\n return;\n }\n this._renderPaintInOrder(ctx);\n },\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity of this instance\n */\n complexity: function() {\n return this.get('points').length;\n }\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Polyline.fromElement})\n * @static\n * @memberOf fabric.Polyline\n * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement\n */\n fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat();\n\n /**\n * Returns fabric.Polyline instance from an SVG element\n * @static\n * @memberOf fabric.Polyline\n * @param {SVGElement} element Element to parser\n * @param {Function} callback callback function invoked after parsing\n * @param {Object} [options] Options object\n */\n fabric.Polyline.fromElementGenerator = function(_class) {\n return function(element, callback, options) {\n if (!element) {\n return callback(null);\n }\n options || (options = { });\n\n var points = fabric.parsePointsAttribute(element.getAttribute('points')),\n parsedAttributes = fabric.parseAttributes(element, fabric[_class].ATTRIBUTE_NAMES);\n parsedAttributes.fromSVG = true;\n callback(new fabric[_class](points, extend(parsedAttributes, options)));\n };\n };\n\n fabric.Polyline.fromElement = fabric.Polyline.fromElementGenerator('Polyline');\n\n /* _FROM_SVG_END_ */\n\n /**\n * Returns fabric.Polyline instance from an object representation\n * @static\n * @memberOf fabric.Polyline\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\n */\n fabric.Polyline.fromObject = function(object, callback) {\n return fabric.Object._fromObject('Polyline', object, callback, 'points');\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = {}),\n projectStrokeOnPoints = fabric.util.projectStrokeOnPoints;\n\n if (fabric.Polygon) {\n fabric.warn('fabric.Polygon is already defined');\n return;\n }\n\n /**\n * Polygon class\n * @class fabric.Polygon\n * @extends fabric.Polyline\n * @see {@link fabric.Polygon#initialize} for constructor definition\n */\n fabric.Polygon = fabric.util.createClass(fabric.Polyline, /** @lends fabric.Polygon.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'polygon',\n\n /**\n * @private\n */\n _projectStrokeOnPoints: function () {\n return projectStrokeOnPoints(this.points, this);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n if (!this.commonRender(ctx)) {\n return;\n }\n ctx.closePath();\n this._renderPaintInOrder(ctx);\n },\n\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by `fabric.Polygon.fromElement`)\n * @static\n * @memberOf fabric.Polygon\n * @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement\n */\n fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat();\n\n /**\n * Returns {@link fabric.Polygon} instance from an SVG element\n * @static\n * @memberOf fabric.Polygon\n * @param {SVGElement} element Element to parse\n * @param {Function} callback callback function invoked after parsing\n * @param {Object} [options] Options object\n */\n fabric.Polygon.fromElement = fabric.Polyline.fromElementGenerator('Polygon');\n /* _FROM_SVG_END_ */\n\n /**\n * Returns fabric.Polygon instance from an object representation\n * @static\n * @memberOf fabric.Polygon\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\n * @return {void}\n */\n fabric.Polygon.fromObject = function(object, callback) {\n fabric.Object._fromObject('Polygon', object, callback, 'points');\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n min = fabric.util.array.min,\n max = fabric.util.array.max,\n extend = fabric.util.object.extend,\n clone = fabric.util.object.clone,\n toFixed = fabric.util.toFixed;\n\n if (fabric.Path) {\n fabric.warn('fabric.Path is already defined');\n return;\n }\n\n /**\n * Path class\n * @class fabric.Path\n * @extends fabric.Object\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#path_and_pathgroup}\n * @see {@link fabric.Path#initialize} for constructor definition\n */\n fabric.Path = fabric.util.createClass(fabric.Object, /** @lends fabric.Path.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'path',\n\n /**\n * Array of path points\n * @type Array\n * @default\n */\n path: null,\n\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('path', 'fillRule'),\n\n stateProperties: fabric.Object.prototype.stateProperties.concat('path'),\n\n /**\n * Constructor\n * @param {Array|String} path Path data (sequence of coordinates and corresponding \"command\" tokens)\n * @param {Object} [options] Options object\n * @return {fabric.Path} thisArg\n */\n initialize: function (path, options) {\n options = clone(options || {});\n delete options.path;\n this.callSuper('initialize', options);\n this._setPath(path || [], options);\n },\n\n /**\n * @private\n * @param {Array|String} path Path data (sequence of coordinates and corresponding \"command\" tokens)\n * @param {Object} [options] Options object\n */\n _setPath: function (path, options) {\n this.path = fabric.util.makePathSimpler(\n Array.isArray(path) ? path : fabric.util.parsePath(path)\n );\n\n fabric.Polyline.prototype._setPositionDimensions.call(this, options || {});\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render path on\n */\n _renderPathCommands: function(ctx) {\n var current, // current instruction\n subpathStartX = 0,\n subpathStartY = 0,\n x = 0, // current x\n y = 0, // current y\n controlX = 0, // current control point x\n controlY = 0, // current control point y\n l = -this.pathOffset.x,\n t = -this.pathOffset.y;\n\n ctx.beginPath();\n\n for (var i = 0, len = this.path.length; i < len; ++i) {\n\n current = this.path[i];\n\n switch (current[0]) { // first letter\n\n case 'L': // lineto, absolute\n x = current[1];\n y = current[2];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'M': // moveTo, absolute\n x = current[1];\n y = current[2];\n subpathStartX = x;\n subpathStartY = y;\n ctx.moveTo(x + l, y + t);\n break;\n\n case 'C': // bezierCurveTo, absolute\n x = current[5];\n y = current[6];\n controlX = current[3];\n controlY = current[4];\n ctx.bezierCurveTo(\n current[1] + l,\n current[2] + t,\n controlX + l,\n controlY + t,\n x + l,\n y + t\n );\n break;\n\n case 'Q': // quadraticCurveTo, absolute\n ctx.quadraticCurveTo(\n current[1] + l,\n current[2] + t,\n current[3] + l,\n current[4] + t\n );\n x = current[3];\n y = current[4];\n controlX = current[1];\n controlY = current[2];\n break;\n\n case 'z':\n case 'Z':\n x = subpathStartX;\n y = subpathStartY;\n ctx.closePath();\n break;\n }\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render path on\n */\n _render: function(ctx) {\n this._renderPathCommands(ctx);\n this._renderPaintInOrder(ctx);\n },\n\n /**\n * Returns string representation of an instance\n * @return {String} string representation of an instance\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return extend(this.callSuper('toObject', propertiesToInclude), {\n path: this.path.map(function(item) { return item.slice(); }),\n });\n },\n\n /**\n * Returns dataless object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toDatalessObject: function(propertiesToInclude) {\n var o = this.toObject(['sourcePath'].concat(propertiesToInclude));\n if (o.sourcePath) {\n delete o.path;\n }\n return o;\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG: function() {\n var path = fabric.util.joinPath(this.path);\n return [\n '\\n'\n ];\n },\n\n _getOffsetTransform: function() {\n var digits = fabric.Object.NUM_FRACTION_DIGITS;\n return ' translate(' + toFixed(-this.pathOffset.x, digits) + ', ' +\n toFixed(-this.pathOffset.y, digits) + ')';\n },\n\n /**\n * Returns svg clipPath representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toClipPathSVG: function(reviver) {\n var additionalTransform = this._getOffsetTransform();\n return '\\t' + this._createBaseClipPathSVGMarkup(\n this._toSVG(), { reviver: reviver, additionalTransform: additionalTransform }\n );\n },\n\n /**\n * Returns svg representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n var additionalTransform = this._getOffsetTransform();\n return this._createBaseSVGMarkup(this._toSVG(), { reviver: reviver, additionalTransform: additionalTransform });\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns number representation of an instance complexity\n * @return {Number} complexity of this instance\n */\n complexity: function() {\n return this.path.length;\n },\n\n /**\n * @private\n */\n _calcDimensions: function() {\n\n var aX = [],\n aY = [],\n current, // current instruction\n subpathStartX = 0,\n subpathStartY = 0,\n x = 0, // current x\n y = 0, // current y\n bounds;\n\n for (var i = 0, len = this.path.length; i < len; ++i) {\n\n current = this.path[i];\n\n switch (current[0]) { // first letter\n\n case 'L': // lineto, absolute\n x = current[1];\n y = current[2];\n bounds = [];\n break;\n\n case 'M': // moveTo, absolute\n x = current[1];\n y = current[2];\n subpathStartX = x;\n subpathStartY = y;\n bounds = [];\n break;\n\n case 'C': // bezierCurveTo, absolute\n bounds = fabric.util.getBoundsOfCurve(x, y,\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6]\n );\n x = current[5];\n y = current[6];\n break;\n\n case 'Q': // quadraticCurveTo, absolute\n bounds = fabric.util.getBoundsOfCurve(x, y,\n current[1],\n current[2],\n current[1],\n current[2],\n current[3],\n current[4]\n );\n x = current[3];\n y = current[4];\n break;\n\n case 'z':\n case 'Z':\n x = subpathStartX;\n y = subpathStartY;\n break;\n }\n bounds.forEach(function (point) {\n aX.push(point.x);\n aY.push(point.y);\n });\n aX.push(x);\n aY.push(y);\n }\n\n var minX = min(aX) || 0,\n minY = min(aY) || 0,\n maxX = max(aX) || 0,\n maxY = max(aY) || 0,\n deltaX = maxX - minX,\n deltaY = maxY - minY;\n\n return {\n left: minX,\n top: minY,\n width: deltaX,\n height: deltaY\n };\n }\n });\n\n /**\n * Creates an instance of fabric.Path from an object\n * @static\n * @memberOf fabric.Path\n * @param {Object} object\n * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\n */\n fabric.Path.fromObject = function(object, callback) {\n if (typeof object.sourcePath === 'string') {\n var pathUrl = object.sourcePath;\n fabric.loadSVGFromURL(pathUrl, function (elements) {\n var path = elements[0];\n path.setOptions(object);\n if (object.clipPath) {\n fabric.util.enlivenObjects([object.clipPath], function(elivenedObjects) {\n path.clipPath = elivenedObjects[0];\n callback && callback(path);\n });\n }\n else {\n callback && callback(path);\n }\n });\n }\n else {\n fabric.Object._fromObject('Path', object, callback, 'path');\n }\n };\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by `fabric.Path.fromElement`)\n * @static\n * @memberOf fabric.Path\n * @see http://www.w3.org/TR/SVG/paths.html#PathElement\n */\n fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(['d']);\n\n /**\n * Creates an instance of fabric.Path from an SVG element\n * @static\n * @memberOf fabric.Path\n * @param {SVGElement} element to parse\n * @param {Function} callback Callback to invoke when an fabric.Path instance is created\n * @param {Object} [options] Options object\n * @param {Function} [callback] Options callback invoked after parsing is finished\n */\n fabric.Path.fromElement = function(element, callback, options) {\n var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES);\n parsedAttributes.fromSVG = true;\n callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options)));\n };\n /* _FROM_SVG_END_ */\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n min = fabric.util.array.min,\n max = fabric.util.array.max;\n\n if (fabric.Group) {\n return;\n }\n\n /**\n * Group class\n * @class fabric.Group\n * @extends fabric.Object\n * @mixes fabric.Collection\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#groups}\n * @see {@link fabric.Group#initialize} for constructor definition\n */\n fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection, /** @lends fabric.Group.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'group',\n\n /**\n * Width of stroke\n * @type Number\n * @default\n */\n strokeWidth: 0,\n\n /**\n * Indicates if click, mouseover, mouseout events & hoverCursor should also check for subtargets\n * @type Boolean\n * @default\n */\n subTargetCheck: false,\n\n /**\n * Groups are container, do not render anything on theyr own, ence no cache properties\n * @type Array\n * @default\n */\n cacheProperties: [],\n\n /**\n * setOnGroup is a method used for TextBox that is no more used since 2.0.0 The behavior is still\n * available setting this boolean to true.\n * @type Boolean\n * @since 2.0.0\n * @default\n */\n useSetOnGroup: false,\n\n /**\n * Constructor\n * @param {Object} objects Group objects\n * @param {Object} [options] Options object\n * @param {Boolean} [isAlreadyGrouped] if true, objects have been grouped already.\n * @return {Object} thisArg\n */\n initialize: function(objects, options, isAlreadyGrouped) {\n options = options || {};\n this._objects = [];\n // if objects enclosed in a group have been grouped already,\n // we cannot change properties of objects.\n // Thus we need to set options to group without objects,\n isAlreadyGrouped && this.callSuper('initialize', options);\n this._objects = objects || [];\n for (var i = this._objects.length; i--; ) {\n this._objects[i].group = this;\n }\n\n if (!isAlreadyGrouped) {\n var center = options && options.centerPoint;\n // we want to set origins before calculating the bounding box.\n // so that the topleft can be set with that in mind.\n // if specific top and left are passed, are overwritten later\n // with the callSuper('initialize', options)\n if (options.originX !== undefined) {\n this.originX = options.originX;\n }\n if (options.originY !== undefined) {\n this.originY = options.originY;\n }\n // if coming from svg i do not want to calc bounds.\n // i assume width and height are passed along options\n center || this._calcBounds();\n this._updateObjectsCoords(center);\n delete options.centerPoint;\n this.callSuper('initialize', options);\n }\n else {\n this._updateObjectsACoords();\n }\n\n this.setCoords();\n },\n\n /**\n * @private\n */\n _updateObjectsACoords: function() {\n var skipControls = true;\n for (var i = this._objects.length; i--; ){\n this._objects[i].setCoords(skipControls);\n }\n },\n\n /**\n * @private\n * @param {Boolean} [skipCoordsChange] if true, coordinates of objects enclosed in a group do not change\n */\n _updateObjectsCoords: function(center) {\n var center = center || this.getCenterPoint();\n for (var i = this._objects.length; i--; ){\n this._updateObjectCoords(this._objects[i], center);\n }\n },\n\n /**\n * @private\n * @param {Object} object\n * @param {fabric.Point} center, current center of group.\n */\n _updateObjectCoords: function(object, center) {\n var objectLeft = object.left,\n objectTop = object.top,\n skipControls = true;\n\n object.set({\n left: objectLeft - center.x,\n top: objectTop - center.y\n });\n object.group = this;\n object.setCoords(skipControls);\n },\n\n /**\n * Returns string represenation of a group\n * @return {String}\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Adds an object to a group; Then recalculates group's dimension, position.\n * @param {Object} object\n * @return {fabric.Group} thisArg\n * @chainable\n */\n addWithUpdate: function(object) {\n var nested = !!this.group;\n this._restoreObjectsState();\n fabric.util.resetObjectTransform(this);\n if (object) {\n if (nested) {\n // if this group is inside another group, we need to pre transform the object\n fabric.util.removeTransformFromObject(object, this.group.calcTransformMatrix());\n }\n this._objects.push(object);\n object.group = this;\n object._set('canvas', this.canvas);\n }\n this._calcBounds();\n this._updateObjectsCoords();\n this.dirty = true;\n if (nested) {\n this.group.addWithUpdate();\n }\n else {\n this.setCoords();\n }\n return this;\n },\n\n /**\n * Removes an object from a group; Then recalculates group's dimension, position.\n * @param {Object} object\n * @return {fabric.Group} thisArg\n * @chainable\n */\n removeWithUpdate: function(object) {\n this._restoreObjectsState();\n fabric.util.resetObjectTransform(this);\n\n this.remove(object);\n this._calcBounds();\n this._updateObjectsCoords();\n this.setCoords();\n this.dirty = true;\n return this;\n },\n\n /**\n * @private\n */\n _onObjectAdded: function(object) {\n this.dirty = true;\n object.group = this;\n object._set('canvas', this.canvas);\n },\n\n /**\n * @private\n */\n _onObjectRemoved: function(object) {\n this.dirty = true;\n delete object.group;\n },\n\n /**\n * @private\n */\n _set: function(key, value) {\n var i = this._objects.length;\n if (this.useSetOnGroup) {\n while (i--) {\n this._objects[i].setOnGroup(key, value);\n }\n }\n if (key === 'canvas') {\n while (i--) {\n this._objects[i]._set(key, value);\n }\n }\n fabric.Object.prototype._set.call(this, key, value);\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n var _includeDefaultValues = this.includeDefaultValues;\n var objsToObject = this._objects\n .filter(function (obj) {\n return !obj.excludeFromExport;\n })\n .map(function (obj) {\n var originalDefaults = obj.includeDefaultValues;\n obj.includeDefaultValues = _includeDefaultValues;\n var _obj = obj.toObject(propertiesToInclude);\n obj.includeDefaultValues = originalDefaults;\n return _obj;\n });\n var obj = fabric.Object.prototype.toObject.call(this, propertiesToInclude);\n obj.objects = objsToObject;\n return obj;\n },\n\n /**\n * Returns object representation of an instance, in dataless mode.\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toDatalessObject: function(propertiesToInclude) {\n var objsToObject, sourcePath = this.sourcePath;\n if (sourcePath) {\n objsToObject = sourcePath;\n }\n else {\n var _includeDefaultValues = this.includeDefaultValues;\n objsToObject = this._objects.map(function(obj) {\n var originalDefaults = obj.includeDefaultValues;\n obj.includeDefaultValues = _includeDefaultValues;\n var _obj = obj.toDatalessObject(propertiesToInclude);\n obj.includeDefaultValues = originalDefaults;\n return _obj;\n });\n }\n var obj = fabric.Object.prototype.toDatalessObject.call(this, propertiesToInclude);\n obj.objects = objsToObject;\n return obj;\n },\n\n /**\n * Renders instance on a given context\n * @param {CanvasRenderingContext2D} ctx context to render instance on\n */\n render: function(ctx) {\n this._transformDone = true;\n this.callSuper('render', ctx);\n this._transformDone = false;\n },\n\n /**\n * Decide if the object should cache or not. Create its own cache level\n * needsItsOwnCache should be used when the object drawing method requires\n * a cache step. None of the fabric classes requires it.\n * Generally you do not cache objects in groups because the group is already cached.\n * @return {Boolean}\n */\n shouldCache: function() {\n var ownCache = fabric.Object.prototype.shouldCache.call(this);\n if (ownCache) {\n for (var i = 0, len = this._objects.length; i < len; i++) {\n if (this._objects[i].willDrawShadow()) {\n this.ownCaching = false;\n return false;\n }\n }\n }\n return ownCache;\n },\n\n /**\n * Check if this object or a child object will cast a shadow\n * @return {Boolean}\n */\n willDrawShadow: function() {\n if (fabric.Object.prototype.willDrawShadow.call(this)) {\n return true;\n }\n for (var i = 0, len = this._objects.length; i < len; i++) {\n if (this._objects[i].willDrawShadow()) {\n return true;\n }\n }\n return false;\n },\n\n /**\n * Check if this group or its parent group are caching, recursively up\n * @return {Boolean}\n */\n isOnACache: function() {\n return this.ownCaching || (this.group && this.group.isOnACache());\n },\n\n /**\n * Execute the drawing operation for an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n drawObject: function(ctx) {\n for (var i = 0, len = this._objects.length; i < len; i++) {\n this._objects[i].render(ctx);\n }\n this._drawClipPath(ctx, this.clipPath);\n },\n\n /**\n * Check if cache is dirty\n */\n isCacheDirty: function(skipCanvas) {\n if (this.callSuper('isCacheDirty', skipCanvas)) {\n return true;\n }\n if (!this.statefullCache) {\n return false;\n }\n for (var i = 0, len = this._objects.length; i < len; i++) {\n if (this._objects[i].isCacheDirty(true)) {\n if (this._cacheCanvas) {\n // if this group has not a cache canvas there is nothing to clean\n var x = this.cacheWidth / this.zoomX, y = this.cacheHeight / this.zoomY;\n this._cacheContext.clearRect(-x / 2, -y / 2, x, y);\n }\n return true;\n }\n }\n return false;\n },\n\n /**\n * Restores original state of each of group objects (original state is that which was before group was created).\n * if the nested boolean is true, the original state will be restored just for the\n * first group and not for all the group chain\n * @private\n * @param {Boolean} nested tell the function to restore object state up to the parent group and not more\n * @return {fabric.Group} thisArg\n * @chainable\n */\n _restoreObjectsState: function() {\n var groupMatrix = this.calcOwnMatrix();\n this._objects.forEach(function(object) {\n // instead of using _this = this;\n fabric.util.addTransformToObject(object, groupMatrix);\n delete object.group;\n object.setCoords();\n });\n return this;\n },\n\n /**\n * Destroys a group (restoring state of its objects)\n * @return {fabric.Group} thisArg\n * @chainable\n */\n destroy: function() {\n // when group is destroyed objects needs to get a repaint to be eventually\n // displayed on canvas.\n this._objects.forEach(function(object) {\n object.set('dirty', true);\n });\n return this._restoreObjectsState();\n },\n\n dispose: function () {\n this.callSuper('dispose');\n this.forEachObject(function (object) {\n object.dispose && object.dispose();\n });\n this._objects = [];\n },\n\n /**\n * make a group an active selection, remove the group from canvas\n * the group has to be on canvas for this to work.\n * @return {fabric.ActiveSelection} thisArg\n * @chainable\n */\n toActiveSelection: function() {\n if (!this.canvas) {\n return;\n }\n var objects = this._objects, canvas = this.canvas;\n this._objects = [];\n var options = this.toObject();\n delete options.objects;\n var activeSelection = new fabric.ActiveSelection([]);\n activeSelection.set(options);\n activeSelection.type = 'activeSelection';\n canvas.remove(this);\n objects.forEach(function(object) {\n object.group = activeSelection;\n object.dirty = true;\n canvas.add(object);\n });\n activeSelection.canvas = canvas;\n activeSelection._objects = objects;\n canvas._activeObject = activeSelection;\n activeSelection.setCoords();\n return activeSelection;\n },\n\n /**\n * Destroys a group (restoring state of its objects)\n * @return {fabric.Group} thisArg\n * @chainable\n */\n ungroupOnCanvas: function() {\n return this._restoreObjectsState();\n },\n\n /**\n * Sets coordinates of all objects inside group\n * @return {fabric.Group} thisArg\n * @chainable\n */\n setObjectsCoords: function() {\n var skipControls = true;\n this.forEachObject(function(object) {\n object.setCoords(skipControls);\n });\n return this;\n },\n\n /**\n * @private\n */\n _calcBounds: function(onlyWidthHeight) {\n var aX = [],\n aY = [],\n o, prop, coords,\n props = ['tr', 'br', 'bl', 'tl'],\n i = 0, iLen = this._objects.length,\n j, jLen = props.length;\n\n for ( ; i < iLen; ++i) {\n o = this._objects[i];\n coords = o.calcACoords();\n for (j = 0; j < jLen; j++) {\n prop = props[j];\n aX.push(coords[prop].x);\n aY.push(coords[prop].y);\n }\n o.aCoords = coords;\n }\n\n this._getBounds(aX, aY, onlyWidthHeight);\n },\n\n /**\n * @private\n */\n _getBounds: function(aX, aY, onlyWidthHeight) {\n var minXY = new fabric.Point(min(aX), min(aY)),\n maxXY = new fabric.Point(max(aX), max(aY)),\n top = minXY.y || 0, left = minXY.x || 0,\n width = (maxXY.x - minXY.x) || 0,\n height = (maxXY.y - minXY.y) || 0;\n this.width = width;\n this.height = height;\n if (!onlyWidthHeight) {\n // the bounding box always finds the topleft most corner.\n // whatever is the group origin, we set up here the left/top position.\n this.setPositionByOrigin({ x: left, y: top }, 'left', 'top');\n }\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n _toSVG: function(reviver) {\n var svgString = ['\\n'];\n\n for (var i = 0, len = this._objects.length; i < len; i++) {\n svgString.push('\\t\\t', this._objects[i].toSVG(reviver));\n }\n svgString.push('\\n');\n return svgString;\n },\n\n /**\n * Returns styles-string for svg-export, specific version for group\n * @return {String}\n */\n getSvgStyles: function() {\n var opacity = typeof this.opacity !== 'undefined' && this.opacity !== 1 ?\n 'opacity: ' + this.opacity + ';' : '',\n visibility = this.visible ? '' : ' visibility: hidden;';\n return [\n opacity,\n this.getSvgFilter(),\n visibility\n ].join('');\n },\n\n /**\n * Returns svg clipPath representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toClipPathSVG: function(reviver) {\n var svgString = [];\n\n for (var i = 0, len = this._objects.length; i < len; i++) {\n svgString.push('\\t', this._objects[i].toClipPathSVG(reviver));\n }\n\n return this._createBaseClipPathSVGMarkup(svgString, { reviver: reviver });\n },\n /* _TO_SVG_END_ */\n });\n\n /**\n * Returns {@link fabric.Group} instance from an object representation\n * @static\n * @memberOf fabric.Group\n * @param {Object} object Object to create a group from\n * @param {Function} [callback] Callback to invoke when an group instance is created\n */\n fabric.Group.fromObject = function(object, callback) {\n var objects = object.objects,\n options = fabric.util.object.clone(object, true);\n delete options.objects;\n if (typeof objects === 'string') {\n // it has to be an url or something went wrong.\n fabric.loadSVGFromURL(objects, function (elements) {\n var group = fabric.util.groupSVGElements(elements, object, objects);\n var clipPath = options.clipPath;\n delete options.clipPath;\n group.set(options);\n if (clipPath) {\n fabric.util.enlivenObjects([clipPath], function(elivenedObjects) {\n group.clipPath = elivenedObjects[0];\n callback && callback(group);\n });\n }\n else {\n callback && callback(group);\n }\n });\n return;\n }\n fabric.util.enlivenObjects(objects, function (enlivenedObjects) {\n fabric.util.enlivenObjectEnlivables(object, options, function () {\n callback && callback(new fabric.Group(enlivenedObjects, options, true));\n });\n });\n };\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { });\n\n if (fabric.ActiveSelection) {\n return;\n }\n\n /**\n * Group class\n * @class fabric.ActiveSelection\n * @extends fabric.Group\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#groups}\n * @see {@link fabric.ActiveSelection#initialize} for constructor definition\n */\n fabric.ActiveSelection = fabric.util.createClass(fabric.Group, /** @lends fabric.ActiveSelection.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'activeSelection',\n\n /**\n * Constructor\n * @param {Object} objects ActiveSelection objects\n * @param {Object} [options] Options object\n * @return {Object} thisArg\n */\n initialize: function(objects, options) {\n options = options || {};\n this._objects = objects || [];\n for (var i = this._objects.length; i--; ) {\n this._objects[i].group = this;\n }\n\n if (options.originX) {\n this.originX = options.originX;\n }\n if (options.originY) {\n this.originY = options.originY;\n }\n this._calcBounds();\n this._updateObjectsCoords();\n fabric.Object.prototype.initialize.call(this, options);\n this.setCoords();\n },\n\n /**\n * Change te activeSelection to a normal group,\n * High level function that automatically adds it to canvas as\n * active object. no events fired.\n * @since 2.0.0\n * @return {fabric.Group}\n */\n toGroup: function() {\n var objects = this._objects.concat();\n this._objects = [];\n var options = fabric.Object.prototype.toObject.call(this);\n var newGroup = new fabric.Group([]);\n delete options.type;\n newGroup.set(options);\n objects.forEach(function(object) {\n object.canvas.remove(object);\n object.group = newGroup;\n });\n newGroup._objects = objects;\n if (!this.canvas) {\n return newGroup;\n }\n var canvas = this.canvas;\n canvas.add(newGroup);\n canvas._activeObject = newGroup;\n newGroup.setCoords();\n return newGroup;\n },\n\n /**\n * If returns true, deselection is cancelled.\n * @since 2.0.0\n * @return {Boolean} [cancel]\n */\n onDeselect: function() {\n this.destroy();\n return false;\n },\n\n /**\n * Returns string representation of a group\n * @return {String}\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Decide if the object should cache or not. Create its own cache level\n * objectCaching is a global flag, wins over everything\n * needsItsOwnCache should be used when the object drawing method requires\n * a cache step. None of the fabric classes requires it.\n * Generally you do not cache objects in groups because the group outside is cached.\n * @return {Boolean}\n */\n shouldCache: function() {\n return false;\n },\n\n /**\n * Check if this group or its parent group are caching, recursively up\n * @return {Boolean}\n */\n isOnACache: function() {\n return false;\n },\n\n /**\n * Renders controls and borders for the object\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Object} [styleOverride] properties to override the object style\n * @param {Object} [childrenOverride] properties to override the children overrides\n */\n _renderControls: function(ctx, styleOverride, childrenOverride) {\n ctx.save();\n ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n childrenOverride = childrenOverride || { };\n if (typeof childrenOverride.hasControls === 'undefined') {\n childrenOverride.hasControls = false;\n }\n childrenOverride.forActiveSelection = true;\n for (var i = 0, len = this._objects.length; i < len; i++) {\n this._objects[i]._renderControls(ctx, childrenOverride);\n }\n this.callSuper('_renderControls', ctx, styleOverride);\n ctx.restore();\n },\n });\n\n /**\n * Returns {@link fabric.ActiveSelection} instance from an object representation\n * @static\n * @memberOf fabric.ActiveSelection\n * @param {Object} object Object to create a group from\n * @param {Function} [callback] Callback to invoke when an ActiveSelection instance is created\n */\n fabric.ActiveSelection.fromObject = function(object, callback) {\n fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) {\n delete object.objects;\n callback && callback(new fabric.ActiveSelection(enlivenedObjects, object, true));\n });\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var extend = fabric.util.object.extend;\n\n if (!global.fabric) {\n global.fabric = { };\n }\n\n if (global.fabric.Image) {\n fabric.warn('fabric.Image is already defined.');\n return;\n }\n\n /**\n * Image class\n * @class fabric.Image\n * @extends fabric.Object\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#images}\n * @see {@link fabric.Image#initialize} for constructor definition\n */\n fabric.Image = fabric.util.createClass(fabric.Object, /** @lends fabric.Image.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'image',\n\n /**\n * Width of a stroke.\n * For image quality a stroke multiple of 2 gives better results.\n * @type Number\n * @default\n */\n strokeWidth: 0,\n\n /**\n * When calling {@link fabric.Image.getSrc}, return value from element src with `element.getAttribute('src')`.\n * This allows for relative urls as image src.\n * @since 2.7.0\n * @type Boolean\n * @default\n */\n srcFromAttribute: false,\n\n /**\n * private\n * contains last value of scaleX to detect\n * if the Image got resized after the last Render\n * @type Number\n */\n _lastScaleX: 1,\n\n /**\n * private\n * contains last value of scaleY to detect\n * if the Image got resized after the last Render\n * @type Number\n */\n _lastScaleY: 1,\n\n /**\n * private\n * contains last value of scaling applied by the apply filter chain\n * @type Number\n */\n _filterScalingX: 1,\n\n /**\n * private\n * contains last value of scaling applied by the apply filter chain\n * @type Number\n */\n _filterScalingY: 1,\n\n /**\n * minimum scale factor under which any resizeFilter is triggered to resize the image\n * 0 will disable the automatic resize. 1 will trigger automatically always.\n * number bigger than 1 are not implemented yet.\n * @type Number\n */\n minimumScaleTrigger: 0.5,\n\n /**\n * List of properties to consider when checking if\n * state of an object is changed ({@link fabric.Object#hasStateChanged})\n * as well as for history (undo/redo) purposes\n * @type Array\n */\n stateProperties: fabric.Object.prototype.stateProperties.concat('cropX', 'cropY'),\n\n /**\n * List of properties to consider when checking if cache needs refresh\n * Those properties are checked by statefullCache ON ( or lazy mode if we want ) or from single\n * calls to Object.set(key, value). If the key is in this list, the object is marked as dirty\n * and refreshed at the next render\n * @type Array\n */\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('cropX', 'cropY'),\n\n /**\n * key used to retrieve the texture representing this image\n * @since 2.0.0\n * @type String\n * @default\n */\n cacheKey: '',\n\n /**\n * Image crop in pixels from original image size.\n * @since 2.0.0\n * @type Number\n * @default\n */\n cropX: 0,\n\n /**\n * Image crop in pixels from original image size.\n * @since 2.0.0\n * @type Number\n * @default\n */\n cropY: 0,\n\n /**\n * Indicates whether this canvas will use image smoothing when painting this image.\n * Also influence if the cacheCanvas for this image uses imageSmoothing\n * @since 4.0.0-beta.11\n * @type Boolean\n * @default\n */\n imageSmoothing: true,\n\n /**\n * Constructor\n * Image can be initialized with any canvas drawable or a string.\n * The string should be a url and will be loaded as an image.\n * Canvas and Image element work out of the box, while videos require extra code to work.\n * Please check video element events for seeking.\n * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | String} element Image element\n * @param {Object} [options] Options object\n * @param {function} [callback] callback function to call after eventual filters applied.\n * @return {fabric.Image} thisArg\n */\n initialize: function(element, options) {\n options || (options = { });\n this.filters = [];\n this.cacheKey = 'texture' + fabric.Object.__uid++;\n this.callSuper('initialize', options);\n this._initElement(element, options);\n },\n\n /**\n * Returns image element which this instance if based on\n * @return {HTMLImageElement} Image element\n */\n getElement: function() {\n return this._element || {};\n },\n\n /**\n * Sets image element for this instance to a specified one.\n * If filters defined they are applied to new image.\n * You might need to call `canvas.renderAll` and `object.setCoords` after replacing, to render new image and update controls area.\n * @param {HTMLImageElement} element\n * @param {Object} [options] Options object\n * @return {fabric.Image} thisArg\n * @chainable\n */\n setElement: function(element, options) {\n this.removeTexture(this.cacheKey);\n this.removeTexture(this.cacheKey + '_filtered');\n this._element = element;\n this._originalElement = element;\n this._initConfig(options);\n if (this.filters.length !== 0) {\n this.applyFilters();\n }\n // resizeFilters work on the already filtered copy.\n // we need to apply resizeFilters AFTER normal filters.\n // applyResizeFilters is run more often than normal filters\n // and is triggered by user interactions rather than dev code\n if (this.resizeFilter) {\n this.applyResizeFilters();\n }\n return this;\n },\n\n /**\n * Delete a single texture if in webgl mode\n */\n removeTexture: function(key) {\n var backend = fabric.filterBackend;\n if (backend && backend.evictCachesForKey) {\n backend.evictCachesForKey(key);\n }\n },\n\n /**\n * Delete textures, reference to elements and eventually JSDOM cleanup\n */\n dispose: function () {\n this.callSuper('dispose');\n this.removeTexture(this.cacheKey);\n this.removeTexture(this.cacheKey + '_filtered');\n this._cacheContext = undefined;\n ['_originalElement', '_element', '_filteredEl', '_cacheCanvas'].forEach((function(element) {\n fabric.util.cleanUpJsdomNode(this[element]);\n this[element] = undefined;\n }).bind(this));\n },\n\n /**\n * Get the crossOrigin value (of the corresponding image element)\n */\n getCrossOrigin: function() {\n return this._originalElement && (this._originalElement.crossOrigin || null);\n },\n\n /**\n * Returns original size of an image\n * @return {Object} Object with \"width\" and \"height\" properties\n */\n getOriginalSize: function() {\n var element = this.getElement();\n return {\n width: element.naturalWidth || element.width,\n height: element.naturalHeight || element.height\n };\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _stroke: function(ctx) {\n if (!this.stroke || this.strokeWidth === 0) {\n return;\n }\n var w = this.width / 2, h = this.height / 2;\n ctx.beginPath();\n ctx.moveTo(-w, -h);\n ctx.lineTo(w, -h);\n ctx.lineTo(w, h);\n ctx.lineTo(-w, h);\n ctx.lineTo(-w, -h);\n ctx.closePath();\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n var filters = [];\n\n this.filters.forEach(function(filterObj) {\n if (filterObj) {\n filters.push(filterObj.toObject());\n }\n });\n var object = extend(\n this.callSuper(\n 'toObject',\n ['cropX', 'cropY'].concat(propertiesToInclude)\n ), {\n src: this.getSrc(),\n crossOrigin: this.getCrossOrigin(),\n filters: filters,\n });\n if (this.resizeFilter) {\n object.resizeFilter = this.resizeFilter.toObject();\n }\n return object;\n },\n\n /**\n * Returns true if an image has crop applied, inspecting values of cropX,cropY,width,height.\n * @return {Boolean}\n */\n hasCrop: function() {\n return this.cropX || this.cropY || this.width < this._element.width || this.height < this._element.height;\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG: function() {\n var svgString = [], imageMarkup = [], strokeSvg, element = this._element,\n x = -this.width / 2, y = -this.height / 2, clipPath = '', imageRendering = '';\n if (!element) {\n return [];\n }\n if (this.hasCrop()) {\n var clipPathId = fabric.Object.__uid++;\n svgString.push(\n '\\n',\n '\\t\\n',\n '\\n'\n );\n clipPath = ' clip-path=\"url(#imageCrop_' + clipPathId + ')\" ';\n }\n if (!this.imageSmoothing) {\n imageRendering = '\" image-rendering=\"optimizeSpeed';\n }\n imageMarkup.push('\\t element with actual transformation, then offsetting object to the top/left\n // so that object's center aligns with container's left/top\n '\" width=\"', element.width || element.naturalWidth,\n '\" height=\"', element.height || element.height,\n imageRendering,\n '\"', clipPath,\n '>\\n');\n\n if (this.stroke || this.strokeDashArray) {\n var origFill = this.fill;\n this.fill = null;\n strokeSvg = [\n '\\t\\n'\n ];\n this.fill = origFill;\n }\n if (this.paintFirst !== 'fill') {\n svgString = svgString.concat(strokeSvg, imageMarkup);\n }\n else {\n svgString = svgString.concat(imageMarkup, strokeSvg);\n }\n return svgString;\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns source of an image\n * @param {Boolean} filtered indicates if the src is needed for svg\n * @return {String} Source of an image\n */\n getSrc: function(filtered) {\n var element = filtered ? this._element : this._originalElement;\n if (element) {\n if (element.toDataURL) {\n return element.toDataURL();\n }\n\n if (this.srcFromAttribute) {\n return element.getAttribute('src');\n }\n else {\n return element.src;\n }\n }\n else {\n return this.src || '';\n }\n },\n\n /**\n * Sets source of an image\n * @param {String} src Source string (URL)\n * @param {Function} [callback] Callback is invoked when image has been loaded (and all filters have been applied)\n * @param {Object} [options] Options object\n * @param {String} [options.crossOrigin] crossOrigin value (one of \"\", \"anonymous\", \"use-credentials\")\n * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes\n * @return {fabric.Image} thisArg\n * @chainable\n */\n setSrc: function(src, callback, options) {\n fabric.util.loadImage(src, function(img, isError) {\n this.setElement(img, options);\n this._setWidthHeight();\n callback && callback(this, isError);\n }, this, options && options.crossOrigin);\n return this;\n },\n\n /**\n * Returns string representation of an instance\n * @return {String} String representation of an instance\n */\n toString: function() {\n return '#';\n },\n\n applyResizeFilters: function() {\n var filter = this.resizeFilter,\n minimumScale = this.minimumScaleTrigger,\n objectScale = this.getTotalObjectScaling(),\n scaleX = objectScale.scaleX,\n scaleY = objectScale.scaleY,\n elementToFilter = this._filteredEl || this._originalElement;\n if (this.group) {\n this.set('dirty', true);\n }\n if (!filter || (scaleX > minimumScale && scaleY > minimumScale)) {\n this._element = elementToFilter;\n this._filterScalingX = 1;\n this._filterScalingY = 1;\n this._lastScaleX = scaleX;\n this._lastScaleY = scaleY;\n return;\n }\n if (!fabric.filterBackend) {\n fabric.filterBackend = fabric.initFilterBackend();\n }\n var canvasEl = fabric.util.createCanvasElement(),\n cacheKey = this._filteredEl ? (this.cacheKey + '_filtered') : this.cacheKey,\n sourceWidth = elementToFilter.width, sourceHeight = elementToFilter.height;\n canvasEl.width = sourceWidth;\n canvasEl.height = sourceHeight;\n this._element = canvasEl;\n this._lastScaleX = filter.scaleX = scaleX;\n this._lastScaleY = filter.scaleY = scaleY;\n fabric.filterBackend.applyFilters(\n [filter], elementToFilter, sourceWidth, sourceHeight, this._element, cacheKey);\n this._filterScalingX = canvasEl.width / this._originalElement.width;\n this._filterScalingY = canvasEl.height / this._originalElement.height;\n },\n\n /**\n * Applies filters assigned to this image (from \"filters\" array) or from filter param\n * @method applyFilters\n * @param {Array} filters to be applied\n * @param {Boolean} forResizing specify if the filter operation is a resize operation\n * @return {thisArg} return the fabric.Image object\n * @chainable\n */\n applyFilters: function(filters) {\n\n filters = filters || this.filters || [];\n filters = filters.filter(function(filter) { return filter && !filter.isNeutralState(); });\n this.set('dirty', true);\n\n // needs to clear out or WEBGL will not resize correctly\n this.removeTexture(this.cacheKey + '_filtered');\n\n if (filters.length === 0) {\n this._element = this._originalElement;\n this._filteredEl = null;\n this._filterScalingX = 1;\n this._filterScalingY = 1;\n return this;\n }\n\n var imgElement = this._originalElement,\n sourceWidth = imgElement.naturalWidth || imgElement.width,\n sourceHeight = imgElement.naturalHeight || imgElement.height;\n\n if (this._element === this._originalElement) {\n // if the element is the same we need to create a new element\n var canvasEl = fabric.util.createCanvasElement();\n canvasEl.width = sourceWidth;\n canvasEl.height = sourceHeight;\n this._element = canvasEl;\n this._filteredEl = canvasEl;\n }\n else {\n // clear the existing element to get new filter data\n // also dereference the eventual resized _element\n this._element = this._filteredEl;\n this._filteredEl.getContext('2d').clearRect(0, 0, sourceWidth, sourceHeight);\n // we also need to resize again at next renderAll, so remove saved _lastScaleX/Y\n this._lastScaleX = 1;\n this._lastScaleY = 1;\n }\n if (!fabric.filterBackend) {\n fabric.filterBackend = fabric.initFilterBackend();\n }\n fabric.filterBackend.applyFilters(\n filters, this._originalElement, sourceWidth, sourceHeight, this._element, this.cacheKey);\n if (this._originalElement.width !== this._element.width ||\n this._originalElement.height !== this._element.height) {\n this._filterScalingX = this._element.width / this._originalElement.width;\n this._filterScalingY = this._element.height / this._originalElement.height;\n }\n return this;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n fabric.util.setImageSmoothing(ctx, this.imageSmoothing);\n if (this.isMoving !== true && this.resizeFilter && this._needsResize()) {\n this.applyResizeFilters();\n }\n this._stroke(ctx);\n this._renderPaintInOrder(ctx);\n },\n\n /**\n * Paint the cached copy of the object on the target context.\n * it will set the imageSmoothing for the draw operation\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n drawCacheOnCanvas: function(ctx) {\n fabric.util.setImageSmoothing(ctx, this.imageSmoothing);\n fabric.Object.prototype.drawCacheOnCanvas.call(this, ctx);\n },\n\n /**\n * Decide if the object should cache or not. Create its own cache level\n * needsItsOwnCache should be used when the object drawing method requires\n * a cache step. None of the fabric classes requires it.\n * Generally you do not cache objects in groups because the group outside is cached.\n * This is the special image version where we would like to avoid caching where possible.\n * Essentially images do not benefit from caching. They may require caching, and in that\n * case we do it. Also caching an image usually ends in a loss of details.\n * A full performance audit should be done.\n * @return {Boolean}\n */\n shouldCache: function() {\n return this.needsItsOwnCache();\n },\n\n _renderFill: function(ctx) {\n var elementToDraw = this._element;\n if (!elementToDraw) {\n return;\n }\n var scaleX = this._filterScalingX, scaleY = this._filterScalingY,\n w = this.width, h = this.height, min = Math.min, max = Math.max,\n // crop values cannot be lesser than 0.\n cropX = max(this.cropX, 0), cropY = max(this.cropY, 0),\n elWidth = elementToDraw.naturalWidth || elementToDraw.width,\n elHeight = elementToDraw.naturalHeight || elementToDraw.height,\n sX = cropX * scaleX,\n sY = cropY * scaleY,\n // the width height cannot exceed element width/height, starting from the crop offset.\n sW = min(w * scaleX, elWidth - sX),\n sH = min(h * scaleY, elHeight - sY),\n x = -w / 2, y = -h / 2,\n maxDestW = min(w, elWidth / scaleX - cropX),\n maxDestH = min(h, elHeight / scaleY - cropY);\n\n elementToDraw && ctx.drawImage(elementToDraw, sX, sY, sW, sH, x, y, maxDestW, maxDestH);\n },\n\n /**\n * needed to check if image needs resize\n * @private\n */\n _needsResize: function() {\n var scale = this.getTotalObjectScaling();\n return (scale.scaleX !== this._lastScaleX || scale.scaleY !== this._lastScaleY);\n },\n\n /**\n * @private\n */\n _resetWidthHeight: function() {\n this.set(this.getOriginalSize());\n },\n\n /**\n * The Image class's initialization method. This method is automatically\n * called by the constructor.\n * @private\n * @param {HTMLImageElement|String} element The element representing the image\n * @param {Object} [options] Options object\n */\n _initElement: function(element, options) {\n this.setElement(fabric.util.getById(element), options);\n fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS);\n },\n\n /**\n * @private\n * @param {Object} [options] Options object\n */\n _initConfig: function(options) {\n options || (options = { });\n this.setOptions(options);\n this._setWidthHeight(options);\n },\n\n /**\n * @private\n * @param {Array} filters to be initialized\n * @param {Function} callback Callback to invoke when all fabric.Image.filters instances are created\n */\n _initFilters: function(filters, callback) {\n if (filters && filters.length) {\n fabric.util.enlivenObjects(filters, function(enlivenedObjects) {\n callback && callback(enlivenedObjects);\n }, 'fabric.Image.filters');\n }\n else {\n callback && callback();\n }\n },\n\n /**\n * @private\n * Set the width and the height of the image object, using the element or the\n * options.\n * @param {Object} [options] Object with width/height properties\n */\n _setWidthHeight: function(options) {\n options || (options = { });\n var el = this.getElement();\n this.width = options.width || el.naturalWidth || el.width || 0;\n this.height = options.height || el.naturalHeight || el.height || 0;\n },\n\n /**\n * Calculate offset for center and scale factor for the image in order to respect\n * the preserveAspectRatio attribute\n * @private\n * @return {Object}\n */\n parsePreserveAspectRatioAttribute: function() {\n var pAR = fabric.util.parsePreserveAspectRatioAttribute(this.preserveAspectRatio || ''),\n rWidth = this._element.width, rHeight = this._element.height,\n scaleX = 1, scaleY = 1, offsetLeft = 0, offsetTop = 0, cropX = 0, cropY = 0,\n offset, pWidth = this.width, pHeight = this.height, parsedAttributes = { width: pWidth, height: pHeight };\n if (pAR && (pAR.alignX !== 'none' || pAR.alignY !== 'none')) {\n if (pAR.meetOrSlice === 'meet') {\n scaleX = scaleY = fabric.util.findScaleToFit(this._element, parsedAttributes);\n offset = (pWidth - rWidth * scaleX) / 2;\n if (pAR.alignX === 'Min') {\n offsetLeft = -offset;\n }\n if (pAR.alignX === 'Max') {\n offsetLeft = offset;\n }\n offset = (pHeight - rHeight * scaleY) / 2;\n if (pAR.alignY === 'Min') {\n offsetTop = -offset;\n }\n if (pAR.alignY === 'Max') {\n offsetTop = offset;\n }\n }\n if (pAR.meetOrSlice === 'slice') {\n scaleX = scaleY = fabric.util.findScaleToCover(this._element, parsedAttributes);\n offset = rWidth - pWidth / scaleX;\n if (pAR.alignX === 'Mid') {\n cropX = offset / 2;\n }\n if (pAR.alignX === 'Max') {\n cropX = offset;\n }\n offset = rHeight - pHeight / scaleY;\n if (pAR.alignY === 'Mid') {\n cropY = offset / 2;\n }\n if (pAR.alignY === 'Max') {\n cropY = offset;\n }\n rWidth = pWidth / scaleX;\n rHeight = pHeight / scaleY;\n }\n }\n else {\n scaleX = pWidth / rWidth;\n scaleY = pHeight / rHeight;\n }\n return {\n width: rWidth,\n height: rHeight,\n scaleX: scaleX,\n scaleY: scaleY,\n offsetLeft: offsetLeft,\n offsetTop: offsetTop,\n cropX: cropX,\n cropY: cropY\n };\n }\n });\n\n /**\n * Default CSS class name for canvas\n * @static\n * @type String\n * @default\n */\n fabric.Image.CSS_CANVAS = 'canvas-img';\n\n /**\n * Alias for getSrc\n * @static\n */\n fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc;\n\n /**\n * Creates an instance of fabric.Image from its object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} callback Callback to invoke when an image instance is created\n */\n fabric.Image.fromObject = function(_object, callback) {\n var object = fabric.util.object.clone(_object);\n fabric.util.loadImage(object.src, function(img, isError) {\n if (isError) {\n callback && callback(null, true);\n return;\n }\n fabric.Image.prototype._initFilters.call(object, object.filters, function(filters) {\n object.filters = filters || [];\n fabric.Image.prototype._initFilters.call(object, [object.resizeFilter], function(resizeFilters) {\n object.resizeFilter = resizeFilters[0];\n fabric.util.enlivenObjectEnlivables(object, object, function () {\n var image = new fabric.Image(img, object);\n callback(image, false);\n });\n });\n });\n }, null, object.crossOrigin);\n };\n\n /**\n * Creates an instance of fabric.Image from an URL string\n * @static\n * @param {String} url URL to create an image from\n * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument). Second argument is a boolean indicating if an error occurred or not.\n * @param {Object} [imgOptions] Options object\n */\n fabric.Image.fromURL = function(url, callback, imgOptions) {\n fabric.util.loadImage(url, function(img, isError) {\n callback && callback(new fabric.Image(img, imgOptions), isError);\n }, null, imgOptions && imgOptions.crossOrigin);\n };\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Image.fromElement})\n * @static\n * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement}\n */\n fabric.Image.ATTRIBUTE_NAMES =\n fabric.SHARED_ATTRIBUTES.concat(\n 'x y width height preserveAspectRatio xlink:href crossOrigin image-rendering'.split(' ')\n );\n\n /**\n * Returns {@link fabric.Image} instance from an SVG element\n * @static\n * @param {SVGElement} element Element to parse\n * @param {Object} [options] Options object\n * @param {Function} callback Callback to execute when fabric.Image object is created\n * @return {fabric.Image} Instance of fabric.Image\n */\n fabric.Image.fromElement = function(element, callback, options) {\n var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES);\n fabric.Image.fromURL(parsedAttributes['xlink:href'], callback,\n extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));\n };\n /* _FROM_SVG_END_ */\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * @private\n * @return {Number} angle value\n */\n _getAngleValueForStraighten: function() {\n var angle = this.angle % 360;\n if (angle > 0) {\n return Math.round((angle - 1) / 90) * 90;\n }\n return Math.round(angle / 90) * 90;\n },\n\n /**\n * Straightens an object (rotating it from current angle to one of 0, 90, 180, 270, etc. depending on which is closer)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n straighten: function() {\n return this.rotate(this._getAngleValueForStraighten());\n },\n\n /**\n * Same as {@link fabric.Object.prototype.straighten} but with animation\n * @param {Object} callbacks Object with callback functions\n * @param {Function} [callbacks.onComplete] Invoked on completion\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\n * @return {fabric.Object} thisArg\n */\n fxStraighten: function(callbacks) {\n callbacks = callbacks || { };\n\n var empty = function() { },\n onComplete = callbacks.onComplete || empty,\n onChange = callbacks.onChange || empty,\n _this = this;\n\n return fabric.util.animate({\n target: this,\n startValue: this.get('angle'),\n endValue: this._getAngleValueForStraighten(),\n duration: this.FX_DURATION,\n onChange: function(value) {\n _this.rotate(value);\n onChange();\n },\n onComplete: function() {\n _this.setCoords();\n onComplete();\n },\n });\n }\n});\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n /**\n * Straightens object, then rerenders canvas\n * @param {fabric.Object} object Object to straighten\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n straightenObject: function (object) {\n object.straighten();\n this.requestRenderAll();\n return this;\n },\n\n /**\n * Same as {@link fabric.Canvas.prototype.straightenObject}, but animated\n * @param {fabric.Object} object Object to straighten\n * @return {fabric.Canvas} thisArg\n */\n fxStraightenObject: function (object) {\n return object.fxStraighten({\n onChange: this.requestRenderAllBound\n });\n }\n});\n\n\n(function() {\n\n 'use strict';\n\n /**\n * Tests if webgl supports certain precision\n * @param {WebGL} Canvas WebGL context to test on\n * @param {String} Precision to test can be any of following: 'lowp', 'mediump', 'highp'\n * @returns {Boolean} Whether the user's browser WebGL supports given precision.\n */\n function testPrecision(gl, precision){\n var fragmentSource = 'precision ' + precision + ' float;\\nvoid main(){}';\n var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n gl.shaderSource(fragmentShader, fragmentSource);\n gl.compileShader(fragmentShader);\n if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\n return false;\n }\n return true;\n }\n\n /**\n * Indicate whether this filtering backend is supported by the user's browser.\n * @param {Number} tileSize check if the tileSize is supported\n * @returns {Boolean} Whether the user's browser supports WebGL.\n */\n fabric.isWebglSupported = function(tileSize) {\n if (fabric.isLikelyNode) {\n return false;\n }\n tileSize = tileSize || fabric.WebglFilterBackend.prototype.tileSize;\n var canvas = document.createElement('canvas');\n var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n var isSupported = false;\n // eslint-disable-next-line\n if (gl) {\n fabric.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);\n isSupported = fabric.maxTextureSize >= tileSize;\n var precisions = ['highp', 'mediump', 'lowp'];\n for (var i = 0; i < 3; i++){\n if (testPrecision(gl, precisions[i])){\n fabric.webGlPrecision = precisions[i];\n break;\n };\n }\n }\n this.isSupported = isSupported;\n return isSupported;\n };\n\n fabric.WebglFilterBackend = WebglFilterBackend;\n\n /**\n * WebGL filter backend.\n */\n function WebglFilterBackend(options) {\n if (options && options.tileSize) {\n this.tileSize = options.tileSize;\n }\n this.setupGLContext(this.tileSize, this.tileSize);\n this.captureGPUInfo();\n };\n\n WebglFilterBackend.prototype = /** @lends fabric.WebglFilterBackend.prototype */ {\n\n tileSize: 2048,\n\n /**\n * Experimental. This object is a sort of repository of help layers used to avoid\n * of recreating them during frequent filtering. If you are previewing a filter with\n * a slider you probably do not want to create help layers every filter step.\n * in this object there will be appended some canvases, created once, resized sometimes\n * cleared never. Clearing is left to the developer.\n **/\n resources: {\n\n },\n\n /**\n * Setup a WebGL context suitable for filtering, and bind any needed event handlers.\n */\n setupGLContext: function(width, height) {\n this.dispose();\n this.createWebGLCanvas(width, height);\n // eslint-disable-next-line\n this.aPosition = new Float32Array([0, 0, 0, 1, 1, 0, 1, 1]);\n this.chooseFastestCopyGLTo2DMethod(width, height);\n },\n\n /**\n * Pick a method to copy data from GL context to 2d canvas. In some browsers using\n * putImageData is faster than drawImage for that specific operation.\n */\n chooseFastestCopyGLTo2DMethod: function(width, height) {\n var canMeasurePerf = typeof window.performance !== 'undefined', canUseImageData;\n try {\n new ImageData(1, 1);\n canUseImageData = true;\n }\n catch (e) {\n canUseImageData = false;\n }\n // eslint-disable-next-line no-undef\n var canUseArrayBuffer = typeof ArrayBuffer !== 'undefined';\n // eslint-disable-next-line no-undef\n var canUseUint8Clamped = typeof Uint8ClampedArray !== 'undefined';\n\n if (!(canMeasurePerf && canUseImageData && canUseArrayBuffer && canUseUint8Clamped)) {\n return;\n }\n\n var targetCanvas = fabric.util.createCanvasElement();\n // eslint-disable-next-line no-undef\n var imageBuffer = new ArrayBuffer(width * height * 4);\n if (fabric.forceGLPutImageData) {\n this.imageBuffer = imageBuffer;\n this.copyGLTo2D = copyGLTo2DPutImageData;\n return;\n }\n var testContext = {\n imageBuffer: imageBuffer,\n destinationWidth: width,\n destinationHeight: height,\n targetCanvas: targetCanvas\n };\n var startTime, drawImageTime, putImageDataTime;\n targetCanvas.width = width;\n targetCanvas.height = height;\n\n startTime = window.performance.now();\n copyGLTo2DDrawImage.call(testContext, this.gl, testContext);\n drawImageTime = window.performance.now() - startTime;\n\n startTime = window.performance.now();\n copyGLTo2DPutImageData.call(testContext, this.gl, testContext);\n putImageDataTime = window.performance.now() - startTime;\n\n if (drawImageTime > putImageDataTime) {\n this.imageBuffer = imageBuffer;\n this.copyGLTo2D = copyGLTo2DPutImageData;\n }\n else {\n this.copyGLTo2D = copyGLTo2DDrawImage;\n }\n },\n\n /**\n * Create a canvas element and associated WebGL context and attaches them as\n * class properties to the GLFilterBackend class.\n */\n createWebGLCanvas: function(width, height) {\n var canvas = fabric.util.createCanvasElement();\n canvas.width = width;\n canvas.height = height;\n var glOptions = {\n alpha: true,\n premultipliedAlpha: false,\n depth: false,\n stencil: false,\n antialias: false\n },\n gl = canvas.getContext('webgl', glOptions);\n if (!gl) {\n gl = canvas.getContext('experimental-webgl', glOptions);\n }\n if (!gl) {\n return;\n }\n gl.clearColor(0, 0, 0, 0);\n // this canvas can fire webglcontextlost and webglcontextrestored\n this.canvas = canvas;\n this.gl = gl;\n },\n\n /**\n * Attempts to apply the requested filters to the source provided, drawing the filtered output\n * to the provided target canvas.\n *\n * @param {Array} filters The filters to apply.\n * @param {HTMLImageElement|HTMLCanvasElement} source The source to be filtered.\n * @param {Number} width The width of the source input.\n * @param {Number} height The height of the source input.\n * @param {HTMLCanvasElement} targetCanvas The destination for filtered output to be drawn.\n * @param {String|undefined} cacheKey A key used to cache resources related to the source. If\n * omitted, caching will be skipped.\n */\n applyFilters: function(filters, source, width, height, targetCanvas, cacheKey) {\n var gl = this.gl;\n var cachedTexture;\n if (cacheKey) {\n cachedTexture = this.getCachedTexture(cacheKey, source);\n }\n var pipelineState = {\n originalWidth: source.width || source.originalWidth,\n originalHeight: source.height || source.originalHeight,\n sourceWidth: width,\n sourceHeight: height,\n destinationWidth: width,\n destinationHeight: height,\n context: gl,\n sourceTexture: this.createTexture(gl, width, height, !cachedTexture && source),\n targetTexture: this.createTexture(gl, width, height),\n originalTexture: cachedTexture ||\n this.createTexture(gl, width, height, !cachedTexture && source),\n passes: filters.length,\n webgl: true,\n aPosition: this.aPosition,\n programCache: this.programCache,\n pass: 0,\n filterBackend: this,\n targetCanvas: targetCanvas\n };\n var tempFbo = gl.createFramebuffer();\n gl.bindFramebuffer(gl.FRAMEBUFFER, tempFbo);\n filters.forEach(function(filter) { filter && filter.applyTo(pipelineState); });\n resizeCanvasIfNeeded(pipelineState);\n this.copyGLTo2D(gl, pipelineState);\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.deleteTexture(pipelineState.sourceTexture);\n gl.deleteTexture(pipelineState.targetTexture);\n gl.deleteFramebuffer(tempFbo);\n targetCanvas.getContext('2d').setTransform(1, 0, 0, 1, 0, 0);\n return pipelineState;\n },\n\n /**\n * Detach event listeners, remove references, and clean up caches.\n */\n dispose: function() {\n if (this.canvas) {\n this.canvas = null;\n this.gl = null;\n }\n this.clearWebGLCaches();\n },\n\n /**\n * Wipe out WebGL-related caches.\n */\n clearWebGLCaches: function() {\n this.programCache = {};\n this.textureCache = {};\n },\n\n /**\n * Create a WebGL texture object.\n *\n * Accepts specific dimensions to initialize the texture to or a source image.\n *\n * @param {WebGLRenderingContext} gl The GL context to use for creating the texture.\n * @param {Number} width The width to initialize the texture at.\n * @param {Number} height The height to initialize the texture.\n * @param {HTMLImageElement|HTMLCanvasElement} textureImageSource A source for the texture data.\n * @param {Number} filterType gl.NEAREST or gl.LINEAR usually, webgl numeri constants\n * @returns {WebGLTexture}\n */\n createTexture: function(gl, width, height, textureImageSource, filterType) {\n var texture = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filterType || gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filterType || gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n if (textureImageSource) {\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureImageSource);\n }\n else {\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n }\n return texture;\n },\n\n /**\n * Can be optionally used to get a texture from the cache array\n *\n * If an existing texture is not found, a new texture is created and cached.\n *\n * @param {String} uniqueId A cache key to use to find an existing texture.\n * @param {HTMLImageElement|HTMLCanvasElement} textureImageSource A source to use to create the\n * texture cache entry if one does not already exist.\n */\n getCachedTexture: function(uniqueId, textureImageSource) {\n if (this.textureCache[uniqueId]) {\n return this.textureCache[uniqueId];\n }\n else {\n var texture = this.createTexture(\n this.gl, textureImageSource.width, textureImageSource.height, textureImageSource);\n this.textureCache[uniqueId] = texture;\n return texture;\n }\n },\n\n /**\n * Clear out cached resources related to a source image that has been\n * filtered previously.\n *\n * @param {String} cacheKey The cache key provided when the source image was filtered.\n */\n evictCachesForKey: function(cacheKey) {\n if (this.textureCache[cacheKey]) {\n this.gl.deleteTexture(this.textureCache[cacheKey]);\n delete this.textureCache[cacheKey];\n }\n },\n\n copyGLTo2D: copyGLTo2DDrawImage,\n\n /**\n * Attempt to extract GPU information strings from a WebGL context.\n *\n * Useful information when debugging or blacklisting specific GPUs.\n *\n * @returns {Object} A GPU info object with renderer and vendor strings.\n */\n captureGPUInfo: function() {\n if (this.gpuInfo) {\n return this.gpuInfo;\n }\n var gl = this.gl, gpuInfo = { renderer: '', vendor: '' };\n if (!gl) {\n return gpuInfo;\n }\n var ext = gl.getExtension('WEBGL_debug_renderer_info');\n if (ext) {\n var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);\n var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);\n if (renderer) {\n gpuInfo.renderer = renderer.toLowerCase();\n }\n if (vendor) {\n gpuInfo.vendor = vendor.toLowerCase();\n }\n }\n this.gpuInfo = gpuInfo;\n return gpuInfo;\n },\n };\n})();\n\nfunction resizeCanvasIfNeeded(pipelineState) {\n var targetCanvas = pipelineState.targetCanvas,\n width = targetCanvas.width, height = targetCanvas.height,\n dWidth = pipelineState.destinationWidth,\n dHeight = pipelineState.destinationHeight;\n\n if (width !== dWidth || height !== dHeight) {\n targetCanvas.width = dWidth;\n targetCanvas.height = dHeight;\n }\n}\n\n/**\n * Copy an input WebGL canvas on to an output 2D canvas.\n *\n * The WebGL canvas is assumed to be upside down, with the top-left pixel of the\n * desired output image appearing in the bottom-left corner of the WebGL canvas.\n *\n * @param {WebGLRenderingContext} sourceContext The WebGL context to copy from.\n * @param {HTMLCanvasElement} targetCanvas The 2D target canvas to copy on to.\n * @param {Object} pipelineState The 2D target canvas to copy on to.\n */\nfunction copyGLTo2DDrawImage(gl, pipelineState) {\n var glCanvas = gl.canvas, targetCanvas = pipelineState.targetCanvas,\n ctx = targetCanvas.getContext('2d');\n ctx.translate(0, targetCanvas.height); // move it down again\n ctx.scale(1, -1); // vertical flip\n // where is my image on the big glcanvas?\n var sourceY = glCanvas.height - targetCanvas.height;\n ctx.drawImage(glCanvas, 0, sourceY, targetCanvas.width, targetCanvas.height, 0, 0,\n targetCanvas.width, targetCanvas.height);\n}\n\n/**\n * Copy an input WebGL canvas on to an output 2D canvas using 2d canvas' putImageData\n * API. Measurably faster than using ctx.drawImage in Firefox (version 54 on OSX Sierra).\n *\n * @param {WebGLRenderingContext} sourceContext The WebGL context to copy from.\n * @param {HTMLCanvasElement} targetCanvas The 2D target canvas to copy on to.\n * @param {Object} pipelineState The 2D target canvas to copy on to.\n */\nfunction copyGLTo2DPutImageData(gl, pipelineState) {\n var targetCanvas = pipelineState.targetCanvas, ctx = targetCanvas.getContext('2d'),\n dWidth = pipelineState.destinationWidth,\n dHeight = pipelineState.destinationHeight,\n numBytes = dWidth * dHeight * 4;\n\n // eslint-disable-next-line no-undef\n var u8 = new Uint8Array(this.imageBuffer, 0, numBytes);\n // eslint-disable-next-line no-undef\n var u8Clamped = new Uint8ClampedArray(this.imageBuffer, 0, numBytes);\n\n gl.readPixels(0, 0, dWidth, dHeight, gl.RGBA, gl.UNSIGNED_BYTE, u8);\n var imgData = new ImageData(u8Clamped, dWidth, dHeight);\n ctx.putImageData(imgData, 0, 0);\n}\n\n\n(function() {\n\n 'use strict';\n\n var noop = function() {};\n\n fabric.Canvas2dFilterBackend = Canvas2dFilterBackend;\n\n /**\n * Canvas 2D filter backend.\n */\n function Canvas2dFilterBackend() {};\n\n Canvas2dFilterBackend.prototype = /** @lends fabric.Canvas2dFilterBackend.prototype */ {\n evictCachesForKey: noop,\n dispose: noop,\n clearWebGLCaches: noop,\n\n /**\n * Experimental. This object is a sort of repository of help layers used to avoid\n * of recreating them during frequent filtering. If you are previewing a filter with\n * a slider you probably do not want to create help layers every filter step.\n * in this object there will be appended some canvases, created once, resized sometimes\n * cleared never. Clearing is left to the developer.\n **/\n resources: {\n\n },\n\n /**\n * Apply a set of filters against a source image and draw the filtered output\n * to the provided destination canvas.\n *\n * @param {EnhancedFilter} filters The filter to apply.\n * @param {HTMLImageElement|HTMLCanvasElement} sourceElement The source to be filtered.\n * @param {Number} sourceWidth The width of the source input.\n * @param {Number} sourceHeight The height of the source input.\n * @param {HTMLCanvasElement} targetCanvas The destination for filtered output to be drawn.\n */\n applyFilters: function(filters, sourceElement, sourceWidth, sourceHeight, targetCanvas) {\n var ctx = targetCanvas.getContext('2d');\n ctx.drawImage(sourceElement, 0, 0, sourceWidth, sourceHeight);\n var imageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight);\n var originalImageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight);\n var pipelineState = {\n sourceWidth: sourceWidth,\n sourceHeight: sourceHeight,\n imageData: imageData,\n originalEl: sourceElement,\n originalImageData: originalImageData,\n canvasEl: targetCanvas,\n ctx: ctx,\n filterBackend: this,\n };\n filters.forEach(function(filter) { filter.applyTo(pipelineState); });\n if (pipelineState.imageData.width !== sourceWidth || pipelineState.imageData.height !== sourceHeight) {\n targetCanvas.width = pipelineState.imageData.width;\n targetCanvas.height = pipelineState.imageData.height;\n }\n ctx.putImageData(pipelineState.imageData, 0, 0);\n return pipelineState;\n },\n\n };\n})();\n\n\n/**\n * @namespace fabric.Image.filters\n * @memberOf fabric.Image\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#image_filters}\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n */\nfabric.Image = fabric.Image || { };\nfabric.Image.filters = fabric.Image.filters || { };\n\n/**\n * Root filter class from which all filter classes inherit from\n * @class fabric.Image.filters.BaseFilter\n * @memberOf fabric.Image.filters\n */\nfabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Image.filters.BaseFilter.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'BaseFilter',\n\n /**\n * Array of attributes to send with buffers. do not modify\n * @private\n */\n\n vertexSource: 'attribute vec2 aPosition;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vTexCoord = aPosition;\\n' +\n 'gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\\n' +\n '}',\n\n fragmentSource: 'precision highp float;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'void main() {\\n' +\n 'gl_FragColor = texture2D(uTexture, vTexCoord);\\n' +\n '}',\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n initialize: function(options) {\n if (options) {\n this.setOptions(options);\n }\n },\n\n /**\n * Sets filter's properties from options\n * @param {Object} [options] Options object\n */\n setOptions: function(options) {\n for (var prop in options) {\n this[prop] = options[prop];\n }\n },\n\n /**\n * Compile this filter's shader program.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context to use for shader compilation.\n * @param {String} fragmentSource fragmentShader source for compilation\n * @param {String} vertexSource vertexShader source for compilation\n */\n createProgram: function(gl, fragmentSource, vertexSource) {\n fragmentSource = fragmentSource || this.fragmentSource;\n vertexSource = vertexSource || this.vertexSource;\n if (fabric.webGlPrecision !== 'highp'){\n fragmentSource = fragmentSource.replace(\n /precision highp float/g,\n 'precision ' + fabric.webGlPrecision + ' float'\n );\n }\n var vertexShader = gl.createShader(gl.VERTEX_SHADER);\n gl.shaderSource(vertexShader, vertexSource);\n gl.compileShader(vertexShader);\n if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {\n throw new Error(\n // eslint-disable-next-line prefer-template\n 'Vertex shader compile error for ' + this.type + ': ' +\n gl.getShaderInfoLog(vertexShader)\n );\n }\n\n var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n gl.shaderSource(fragmentShader, fragmentSource);\n gl.compileShader(fragmentShader);\n if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\n throw new Error(\n // eslint-disable-next-line prefer-template\n 'Fragment shader compile error for ' + this.type + ': ' +\n gl.getShaderInfoLog(fragmentShader)\n );\n }\n\n var program = gl.createProgram();\n gl.attachShader(program, vertexShader);\n gl.attachShader(program, fragmentShader);\n gl.linkProgram(program);\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n throw new Error(\n // eslint-disable-next-line prefer-template\n 'Shader link error for \"${this.type}\" ' +\n gl.getProgramInfoLog(program)\n );\n }\n\n var attributeLocations = this.getAttributeLocations(gl, program);\n var uniformLocations = this.getUniformLocations(gl, program) || { };\n uniformLocations.uStepW = gl.getUniformLocation(program, 'uStepW');\n uniformLocations.uStepH = gl.getUniformLocation(program, 'uStepH');\n return {\n program: program,\n attributeLocations: attributeLocations,\n uniformLocations: uniformLocations\n };\n },\n\n /**\n * Return a map of attribute names to WebGLAttributeLocation objects.\n *\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n * @param {WebGLShaderProgram} program The shader program from which to take attribute locations.\n * @returns {Object} A map of attribute names to attribute locations.\n */\n getAttributeLocations: function(gl, program) {\n return {\n aPosition: gl.getAttribLocation(program, 'aPosition'),\n };\n },\n\n /**\n * Return a map of uniform names to WebGLUniformLocation objects.\n *\n * Intended to be overridden by subclasses.\n *\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n * @param {WebGLShaderProgram} program The shader program from which to take uniform locations.\n * @returns {Object} A map of uniform names to uniform locations.\n */\n getUniformLocations: function (/* gl, program */) {\n // in case i do not need any special uniform i need to return an empty object\n return { };\n },\n\n /**\n * Send attribute data from this filter to its shader program on the GPU.\n *\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n * @param {Object} attributeLocations A map of shader attribute names to their locations.\n */\n sendAttributeData: function(gl, attributeLocations, aPositionData) {\n var attributeLocation = attributeLocations.aPosition;\n var buffer = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n gl.enableVertexAttribArray(attributeLocation);\n gl.vertexAttribPointer(attributeLocation, 2, gl.FLOAT, false, 0, 0);\n gl.bufferData(gl.ARRAY_BUFFER, aPositionData, gl.STATIC_DRAW);\n },\n\n _setupFrameBuffer: function(options) {\n var gl = options.context, width, height;\n if (options.passes > 1) {\n width = options.destinationWidth;\n height = options.destinationHeight;\n if (options.sourceWidth !== width || options.sourceHeight !== height) {\n gl.deleteTexture(options.targetTexture);\n options.targetTexture = options.filterBackend.createTexture(gl, width, height);\n }\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D,\n options.targetTexture, 0);\n }\n else {\n // draw last filter on canvas and not to framebuffer.\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.finish();\n }\n },\n\n _swapTextures: function(options) {\n options.passes--;\n options.pass++;\n var temp = options.targetTexture;\n options.targetTexture = options.sourceTexture;\n options.sourceTexture = temp;\n },\n\n /**\n * Generic isNeutral implementation for one parameter based filters.\n * Used only in image applyFilters to discard filters that will not have an effect\n * on the image\n * Other filters may need their own version ( ColorMatrix, HueRotation, gamma, ComposedFilter )\n * @param {Object} options\n **/\n isNeutralState: function(/* options */) {\n var main = this.mainParameter,\n _class = fabric.Image.filters[this.type].prototype;\n if (main) {\n if (Array.isArray(_class[main])) {\n for (var i = _class[main].length; i--;) {\n if (this[main][i] !== _class[main][i]) {\n return false;\n }\n }\n return true;\n }\n else {\n return _class[main] === this[main];\n }\n }\n else {\n return false;\n }\n },\n\n /**\n * Apply this filter to the input image data provided.\n *\n * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\n *\n * @param {Object} options\n * @param {Number} options.passes The number of filters remaining to be executed\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n applyTo: function(options) {\n if (options.webgl) {\n this._setupFrameBuffer(options);\n this.applyToWebGL(options);\n this._swapTextures(options);\n }\n else {\n this.applyTo2d(options);\n }\n },\n\n /**\n * Retrieves the cached shader.\n * @param {Object} options\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n retrieveShader: function(options) {\n if (!options.programCache.hasOwnProperty(this.type)) {\n options.programCache[this.type] = this.createProgram(options.context);\n }\n return options.programCache[this.type];\n },\n\n /**\n * Apply this filter using webgl.\n *\n * @param {Object} options\n * @param {Number} options.passes The number of filters remaining to be executed\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n * @param {WebGLTexture} options.originalTexture The texture of the original input image.\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n applyToWebGL: function(options) {\n var gl = options.context;\n var shader = this.retrieveShader(options);\n if (options.pass === 0 && options.originalTexture) {\n gl.bindTexture(gl.TEXTURE_2D, options.originalTexture);\n }\n else {\n gl.bindTexture(gl.TEXTURE_2D, options.sourceTexture);\n }\n gl.useProgram(shader.program);\n this.sendAttributeData(gl, shader.attributeLocations, options.aPosition);\n\n gl.uniform1f(shader.uniformLocations.uStepW, 1 / options.sourceWidth);\n gl.uniform1f(shader.uniformLocations.uStepH, 1 / options.sourceHeight);\n\n this.sendUniformData(gl, shader.uniformLocations);\n gl.viewport(0, 0, options.destinationWidth, options.destinationHeight);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n },\n\n bindAdditionalTexture: function(gl, texture, textureUnit) {\n gl.activeTexture(textureUnit);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n // reset active texture to 0 as usual\n gl.activeTexture(gl.TEXTURE0);\n },\n\n unbindAdditionalTexture: function(gl, textureUnit) {\n gl.activeTexture(textureUnit);\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.activeTexture(gl.TEXTURE0);\n },\n\n getMainParameter: function() {\n return this[this.mainParameter];\n },\n\n setMainParameter: function(value) {\n this[this.mainParameter] = value;\n },\n\n /**\n * Send uniform data from this filter to its shader program on the GPU.\n *\n * Intended to be overridden by subclasses.\n *\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n * @param {Object} uniformLocations A map of shader uniform names to their locations.\n */\n sendUniformData: function(/* gl, uniformLocations */) {\n // Intentionally left blank. Override me in subclasses.\n },\n\n /**\n * If needed by a 2d filter, this functions can create an helper canvas to be used\n * remember that options.targetCanvas is available for use till end of chain.\n */\n createHelpLayer: function(options) {\n if (!options.helpLayer) {\n var helpLayer = document.createElement('canvas');\n helpLayer.width = options.sourceWidth;\n helpLayer.height = options.sourceHeight;\n options.helpLayer = helpLayer;\n }\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n var object = { type: this.type }, mainP = this.mainParameter;\n if (mainP) {\n object[mainP] = this[mainP];\n }\n return object;\n },\n\n /**\n * Returns a JSON representation of an instance\n * @return {Object} JSON\n */\n toJSON: function() {\n // delegate, not alias\n return this.toObject();\n }\n});\n\nfabric.Image.filters.BaseFilter.fromObject = function(object, callback) {\n var filter = new fabric.Image.filters[object.type](object);\n callback && callback(filter);\n return filter;\n};\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Color Matrix filter class\n * @class fabric.Image.filters.ColorMatrix\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.ColorMatrix#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @see {@Link http://www.webwasp.co.uk/tutorials/219/Color_Matrix_Filter.php}\n * @see {@Link http://phoboslab.org/log/2013/11/fast-image-filters-with-webgl}\n * @example Kodachrome filter\n * var filter = new fabric.Image.filters.ColorMatrix({\n * matrix: [\n 1.1285582396593525, -0.3967382283601348, -0.03992559172921793, 0, 63.72958762196502,\n -0.16404339962244616, 1.0835251566291304, -0.05498805115633132, 0, 24.732407896706203,\n -0.16786010706155763, -0.5603416277695248, 1.6014850761964943, 0, 35.62982807460946,\n 0, 0, 0, 1, 0\n ]\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\n filters.ColorMatrix = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.ColorMatrix.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'ColorMatrix',\n\n fragmentSource: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'uniform mat4 uColorMatrix;\\n' +\n 'uniform vec4 uConstants;\\n' +\n 'void main() {\\n' +\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n 'color *= uColorMatrix;\\n' +\n 'color += uConstants;\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n\n /**\n * Colormatrix for pixels.\n * array of 20 floats. Numbers in positions 4, 9, 14, 19 loose meaning\n * outside the -1, 1 range.\n * 0.0039215686 is the part of 1 that get translated to 1 in 2d\n * @param {Array} matrix array of 20 numbers.\n * @default\n */\n matrix: [\n 1, 0, 0, 0, 0,\n 0, 1, 0, 0, 0,\n 0, 0, 1, 0, 0,\n 0, 0, 0, 1, 0\n ],\n\n mainParameter: 'matrix',\n\n /**\n * Lock the colormatrix on the color part, skipping alpha, mainly for non webgl scenario\n * to save some calculation\n * @type Boolean\n * @default true\n */\n colorsOnly: true,\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n initialize: function(options) {\n this.callSuper('initialize', options);\n // create a new array instead mutating the prototype with push\n this.matrix = this.matrix.slice(0);\n },\n\n /**\n * Apply the ColorMatrix operation to a Uint8Array representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\n */\n applyTo2d: function(options) {\n var imageData = options.imageData,\n data = imageData.data,\n iLen = data.length,\n m = this.matrix,\n r, g, b, a, i, colorsOnly = this.colorsOnly;\n\n for (i = 0; i < iLen; i += 4) {\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n if (colorsOnly) {\n data[i] = r * m[0] + g * m[1] + b * m[2] + m[4] * 255;\n data[i + 1] = r * m[5] + g * m[6] + b * m[7] + m[9] * 255;\n data[i + 2] = r * m[10] + g * m[11] + b * m[12] + m[14] * 255;\n }\n else {\n a = data[i + 3];\n data[i] = r * m[0] + g * m[1] + b * m[2] + a * m[3] + m[4] * 255;\n data[i + 1] = r * m[5] + g * m[6] + b * m[7] + a * m[8] + m[9] * 255;\n data[i + 2] = r * m[10] + g * m[11] + b * m[12] + a * m[13] + m[14] * 255;\n data[i + 3] = r * m[15] + g * m[16] + b * m[17] + a * m[18] + m[19] * 255;\n }\n }\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uColorMatrix: gl.getUniformLocation(program, 'uColorMatrix'),\n uConstants: gl.getUniformLocation(program, 'uConstants'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n var m = this.matrix,\n matrix = [\n m[0], m[1], m[2], m[3],\n m[5], m[6], m[7], m[8],\n m[10], m[11], m[12], m[13],\n m[15], m[16], m[17], m[18]\n ],\n constants = [m[4], m[9], m[14], m[19]];\n gl.uniformMatrix4fv(uniformLocations.uColorMatrix, false, matrix);\n gl.uniform4fv(uniformLocations.uConstants, constants);\n },\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] function to invoke after filter creation\n * @return {fabric.Image.filters.ColorMatrix} Instance of fabric.Image.filters.ColorMatrix\n */\n fabric.Image.filters.ColorMatrix.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Brightness filter class\n * @class fabric.Image.filters.Brightness\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Brightness#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Brightness({\n * brightness: 0.05\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\n filters.Brightness = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Brightness.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Brightness',\n\n /**\n * Fragment source for the brightness program\n */\n fragmentSource: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uBrightness;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n 'color.rgb += uBrightness;\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n\n /**\n * Brightness value, from -1 to 1.\n * translated to -255 to 255 for 2d\n * 0.0039215686 is the part of 1 that get translated to 1 in 2d\n * @param {Number} brightness\n * @default\n */\n brightness: 0,\n\n /**\n * Describe the property that is the filter parameter\n * @param {String} m\n * @default\n */\n mainParameter: 'brightness',\n\n /**\n * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d: function(options) {\n if (this.brightness === 0) {\n return;\n }\n var imageData = options.imageData,\n data = imageData.data, i, len = data.length,\n brightness = Math.round(this.brightness * 255);\n for (i = 0; i < len; i += 4) {\n data[i] = data[i] + brightness;\n data[i + 1] = data[i + 1] + brightness;\n data[i + 2] = data[i + 2] + brightness;\n }\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uBrightness: gl.getUniformLocation(program, 'uBrightness'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n gl.uniform1f(uniformLocations.uBrightness, this.brightness);\n },\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Brightness} Instance of fabric.Image.filters.Brightness\n */\n fabric.Image.filters.Brightness.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Adapted from html5rocks article\n * @class fabric.Image.filters.Convolute\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Convolute#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example Sharpen filter\n * var filter = new fabric.Image.filters.Convolute({\n * matrix: [ 0, -1, 0,\n * -1, 5, -1,\n * 0, -1, 0 ]\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n * @example Blur filter\n * var filter = new fabric.Image.filters.Convolute({\n * matrix: [ 1/9, 1/9, 1/9,\n * 1/9, 1/9, 1/9,\n * 1/9, 1/9, 1/9 ]\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n * @example Emboss filter\n * var filter = new fabric.Image.filters.Convolute({\n * matrix: [ 1, 1, 1,\n * 1, 0.7, -1,\n * -1, -1, -1 ]\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n * @example Emboss filter with opaqueness\n * var filter = new fabric.Image.filters.Convolute({\n * opaque: true,\n * matrix: [ 1, 1, 1,\n * 1, 0.7, -1,\n * -1, -1, -1 ]\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\n filters.Convolute = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Convolute.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Convolute',\n\n /*\n * Opaque value (true/false)\n */\n opaque: false,\n\n /*\n * matrix for the filter, max 9x9\n */\n matrix: [0, 0, 0, 0, 1, 0, 0, 0, 0],\n\n /**\n * Fragment source for the brightness program\n */\n fragmentSource: {\n Convolute_3_1: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uMatrix[9];\\n' +\n 'uniform float uStepW;\\n' +\n 'uniform float uStepH;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = vec4(0, 0, 0, 0);\\n' +\n 'for (float h = 0.0; h < 3.0; h+=1.0) {\\n' +\n 'for (float w = 0.0; w < 3.0; w+=1.0) {\\n' +\n 'vec2 matrixPos = vec2(uStepW * (w - 1), uStepH * (h - 1));\\n' +\n 'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 3.0 + w)];\\n' +\n '}\\n' +\n '}\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n Convolute_3_0: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uMatrix[9];\\n' +\n 'uniform float uStepW;\\n' +\n 'uniform float uStepH;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = vec4(0, 0, 0, 1);\\n' +\n 'for (float h = 0.0; h < 3.0; h+=1.0) {\\n' +\n 'for (float w = 0.0; w < 3.0; w+=1.0) {\\n' +\n 'vec2 matrixPos = vec2(uStepW * (w - 1.0), uStepH * (h - 1.0));\\n' +\n 'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 3.0 + w)];\\n' +\n '}\\n' +\n '}\\n' +\n 'float alpha = texture2D(uTexture, vTexCoord).a;\\n' +\n 'gl_FragColor = color;\\n' +\n 'gl_FragColor.a = alpha;\\n' +\n '}',\n Convolute_5_1: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uMatrix[25];\\n' +\n 'uniform float uStepW;\\n' +\n 'uniform float uStepH;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = vec4(0, 0, 0, 0);\\n' +\n 'for (float h = 0.0; h < 5.0; h+=1.0) {\\n' +\n 'for (float w = 0.0; w < 5.0; w+=1.0) {\\n' +\n 'vec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\\n' +\n 'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 5.0 + w)];\\n' +\n '}\\n' +\n '}\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n Convolute_5_0: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uMatrix[25];\\n' +\n 'uniform float uStepW;\\n' +\n 'uniform float uStepH;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = vec4(0, 0, 0, 1);\\n' +\n 'for (float h = 0.0; h < 5.0; h+=1.0) {\\n' +\n 'for (float w = 0.0; w < 5.0; w+=1.0) {\\n' +\n 'vec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\\n' +\n 'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 5.0 + w)];\\n' +\n '}\\n' +\n '}\\n' +\n 'float alpha = texture2D(uTexture, vTexCoord).a;\\n' +\n 'gl_FragColor = color;\\n' +\n 'gl_FragColor.a = alpha;\\n' +\n '}',\n Convolute_7_1: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uMatrix[49];\\n' +\n 'uniform float uStepW;\\n' +\n 'uniform float uStepH;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = vec4(0, 0, 0, 0);\\n' +\n 'for (float h = 0.0; h < 7.0; h+=1.0) {\\n' +\n 'for (float w = 0.0; w < 7.0; w+=1.0) {\\n' +\n 'vec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\\n' +\n 'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 7.0 + w)];\\n' +\n '}\\n' +\n '}\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n Convolute_7_0: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uMatrix[49];\\n' +\n 'uniform float uStepW;\\n' +\n 'uniform float uStepH;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = vec4(0, 0, 0, 1);\\n' +\n 'for (float h = 0.0; h < 7.0; h+=1.0) {\\n' +\n 'for (float w = 0.0; w < 7.0; w+=1.0) {\\n' +\n 'vec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\\n' +\n 'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 7.0 + w)];\\n' +\n '}\\n' +\n '}\\n' +\n 'float alpha = texture2D(uTexture, vTexCoord).a;\\n' +\n 'gl_FragColor = color;\\n' +\n 'gl_FragColor.a = alpha;\\n' +\n '}',\n Convolute_9_1: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uMatrix[81];\\n' +\n 'uniform float uStepW;\\n' +\n 'uniform float uStepH;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = vec4(0, 0, 0, 0);\\n' +\n 'for (float h = 0.0; h < 9.0; h+=1.0) {\\n' +\n 'for (float w = 0.0; w < 9.0; w+=1.0) {\\n' +\n 'vec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\\n' +\n 'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 9.0 + w)];\\n' +\n '}\\n' +\n '}\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n Convolute_9_0: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uMatrix[81];\\n' +\n 'uniform float uStepW;\\n' +\n 'uniform float uStepH;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = vec4(0, 0, 0, 1);\\n' +\n 'for (float h = 0.0; h < 9.0; h+=1.0) {\\n' +\n 'for (float w = 0.0; w < 9.0; w+=1.0) {\\n' +\n 'vec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\\n' +\n 'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 9.0 + w)];\\n' +\n '}\\n' +\n '}\\n' +\n 'float alpha = texture2D(uTexture, vTexCoord).a;\\n' +\n 'gl_FragColor = color;\\n' +\n 'gl_FragColor.a = alpha;\\n' +\n '}',\n },\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Convolute.prototype\n * @param {Object} [options] Options object\n * @param {Boolean} [options.opaque=false] Opaque value (true/false)\n * @param {Array} [options.matrix] Filter matrix\n */\n\n\n /**\n * Retrieves the cached shader.\n * @param {Object} options\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n retrieveShader: function(options) {\n var size = Math.sqrt(this.matrix.length);\n var cacheKey = this.type + '_' + size + '_' + (this.opaque ? 1 : 0);\n var shaderSource = this.fragmentSource[cacheKey];\n if (!options.programCache.hasOwnProperty(cacheKey)) {\n options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\n }\n return options.programCache[cacheKey];\n },\n\n /**\n * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d: function(options) {\n var imageData = options.imageData,\n data = imageData.data,\n weights = this.matrix,\n side = Math.round(Math.sqrt(weights.length)),\n halfSide = Math.floor(side / 2),\n sw = imageData.width,\n sh = imageData.height,\n output = options.ctx.createImageData(sw, sh),\n dst = output.data,\n // go through the destination image pixels\n alphaFac = this.opaque ? 1 : 0,\n r, g, b, a, dstOff,\n scx, scy, srcOff, wt,\n x, y, cx, cy;\n\n for (y = 0; y < sh; y++) {\n for (x = 0; x < sw; x++) {\n dstOff = (y * sw + x) * 4;\n // calculate the weighed sum of the source image pixels that\n // fall under the convolution matrix\n r = 0; g = 0; b = 0; a = 0;\n\n for (cy = 0; cy < side; cy++) {\n for (cx = 0; cx < side; cx++) {\n scy = y + cy - halfSide;\n scx = x + cx - halfSide;\n\n // eslint-disable-next-line max-depth\n if (scy < 0 || scy >= sh || scx < 0 || scx >= sw) {\n continue;\n }\n\n srcOff = (scy * sw + scx) * 4;\n wt = weights[cy * side + cx];\n\n r += data[srcOff] * wt;\n g += data[srcOff + 1] * wt;\n b += data[srcOff + 2] * wt;\n // eslint-disable-next-line max-depth\n if (!alphaFac) {\n a += data[srcOff + 3] * wt;\n }\n }\n }\n dst[dstOff] = r;\n dst[dstOff + 1] = g;\n dst[dstOff + 2] = b;\n if (!alphaFac) {\n dst[dstOff + 3] = a;\n }\n else {\n dst[dstOff + 3] = data[dstOff + 3];\n }\n }\n }\n options.imageData = output;\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uMatrix: gl.getUniformLocation(program, 'uMatrix'),\n uOpaque: gl.getUniformLocation(program, 'uOpaque'),\n uHalfSize: gl.getUniformLocation(program, 'uHalfSize'),\n uSize: gl.getUniformLocation(program, 'uSize'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n gl.uniform1fv(uniformLocations.uMatrix, this.matrix);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n opaque: this.opaque,\n matrix: this.matrix\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Convolute} Instance of fabric.Image.filters.Convolute\n */\n fabric.Image.filters.Convolute.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Grayscale image filter class\n * @class fabric.Image.filters.Grayscale\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Grayscale();\n * object.filters.push(filter);\n * object.applyFilters();\n */\n filters.Grayscale = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Grayscale.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Grayscale',\n\n fragmentSource: {\n average: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n 'float average = (color.r + color.b + color.g) / 3.0;\\n' +\n 'gl_FragColor = vec4(average, average, average, color.a);\\n' +\n '}',\n lightness: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform int uMode;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 col = texture2D(uTexture, vTexCoord);\\n' +\n 'float average = (max(max(col.r, col.g),col.b) + min(min(col.r, col.g),col.b)) / 2.0;\\n' +\n 'gl_FragColor = vec4(average, average, average, col.a);\\n' +\n '}',\n luminosity: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform int uMode;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 col = texture2D(uTexture, vTexCoord);\\n' +\n 'float average = 0.21 * col.r + 0.72 * col.g + 0.07 * col.b;\\n' +\n 'gl_FragColor = vec4(average, average, average, col.a);\\n' +\n '}',\n },\n\n\n /**\n * Grayscale mode, between 'average', 'lightness', 'luminosity'\n * @param {String} type\n * @default\n */\n mode: 'average',\n\n mainParameter: 'mode',\n\n /**\n * Apply the Grayscale operation to a Uint8Array representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\n */\n applyTo2d: function(options) {\n var imageData = options.imageData,\n data = imageData.data, i,\n len = data.length, value,\n mode = this.mode;\n for (i = 0; i < len; i += 4) {\n if (mode === 'average') {\n value = (data[i] + data[i + 1] + data[i + 2]) / 3;\n }\n else if (mode === 'lightness') {\n value = (Math.min(data[i], data[i + 1], data[i + 2]) +\n Math.max(data[i], data[i + 1], data[i + 2])) / 2;\n }\n else if (mode === 'luminosity') {\n value = 0.21 * data[i] + 0.72 * data[i + 1] + 0.07 * data[i + 2];\n }\n data[i] = value;\n data[i + 1] = value;\n data[i + 2] = value;\n }\n },\n\n /**\n * Retrieves the cached shader.\n * @param {Object} options\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n retrieveShader: function(options) {\n var cacheKey = this.type + '_' + this.mode;\n if (!options.programCache.hasOwnProperty(cacheKey)) {\n var shaderSource = this.fragmentSource[this.mode];\n options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\n }\n return options.programCache[cacheKey];\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uMode: gl.getUniformLocation(program, 'uMode'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n // default average mode.\n var mode = 1;\n gl.uniform1i(uniformLocations.uMode, mode);\n },\n\n /**\n * Grayscale filter isNeutralState implementation\n * The filter is never neutral\n * on the image\n **/\n isNeutralState: function() {\n return false;\n },\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Grayscale} Instance of fabric.Image.filters.Grayscale\n */\n fabric.Image.filters.Grayscale.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Invert filter class\n * @class fabric.Image.filters.Invert\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Invert();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Invert = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Invert.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Invert',\n\n fragmentSource: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform int uInvert;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n 'if (uInvert == 1) {\\n' +\n 'gl_FragColor = vec4(1.0 - color.r,1.0 -color.g,1.0 -color.b,color.a);\\n' +\n '} else {\\n' +\n 'gl_FragColor = color;\\n' +\n '}\\n' +\n '}',\n\n /**\n * Filter invert. if false, does nothing\n * @param {Boolean} invert\n * @default\n */\n invert: true,\n\n mainParameter: 'invert',\n\n /**\n * Apply the Invert operation to a Uint8Array representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\n */\n applyTo2d: function(options) {\n var imageData = options.imageData,\n data = imageData.data, i,\n len = data.length;\n for (i = 0; i < len; i += 4) {\n data[i] = 255 - data[i];\n data[i + 1] = 255 - data[i + 1];\n data[i + 2] = 255 - data[i + 2];\n }\n },\n\n /**\n * Invert filter isNeutralState implementation\n * Used only in image applyFilters to discard filters that will not have an effect\n * on the image\n * @param {Object} options\n **/\n isNeutralState: function() {\n return !this.invert;\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uInvert: gl.getUniformLocation(program, 'uInvert'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n gl.uniform1i(uniformLocations.uInvert, this.invert);\n },\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Invert} Instance of fabric.Image.filters.Invert\n */\n fabric.Image.filters.Invert.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Noise filter class\n * @class fabric.Image.filters.Noise\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Noise#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Noise({\n * noise: 700\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\n filters.Noise = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Noise.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Noise',\n\n /**\n * Fragment source for the noise program\n */\n fragmentSource: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uStepH;\\n' +\n 'uniform float uNoise;\\n' +\n 'uniform float uSeed;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'float rand(vec2 co, float seed, float vScale) {\\n' +\n 'return fract(sin(dot(co.xy * vScale ,vec2(12.9898 , 78.233))) * 43758.5453 * (seed + 0.01) / 2.0);\\n' +\n '}\\n' +\n 'void main() {\\n' +\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n 'color.rgb += (0.5 - rand(vTexCoord, uSeed, 0.1 / uStepH)) * uNoise;\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n\n /**\n * Describe the property that is the filter parameter\n * @param {String} m\n * @default\n */\n mainParameter: 'noise',\n\n /**\n * Noise value, from\n * @param {Number} noise\n * @default\n */\n noise: 0,\n\n /**\n * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d: function(options) {\n if (this.noise === 0) {\n return;\n }\n var imageData = options.imageData,\n data = imageData.data, i, len = data.length,\n noise = this.noise, rand;\n\n for (i = 0, len = data.length; i < len; i += 4) {\n\n rand = (0.5 - Math.random()) * noise;\n\n data[i] += rand;\n data[i + 1] += rand;\n data[i + 2] += rand;\n }\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uNoise: gl.getUniformLocation(program, 'uNoise'),\n uSeed: gl.getUniformLocation(program, 'uSeed'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n gl.uniform1f(uniformLocations.uNoise, this.noise / 255);\n gl.uniform1f(uniformLocations.uSeed, Math.random());\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n noise: this.noise\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Noise} Instance of fabric.Image.filters.Noise\n */\n fabric.Image.filters.Noise.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Pixelate filter class\n * @class fabric.Image.filters.Pixelate\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Pixelate#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Pixelate({\n * blocksize: 8\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\n filters.Pixelate = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Pixelate.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Pixelate',\n\n blocksize: 4,\n\n mainParameter: 'blocksize',\n\n /**\n * Fragment source for the Pixelate program\n */\n fragmentSource: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uBlocksize;\\n' +\n 'uniform float uStepW;\\n' +\n 'uniform float uStepH;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'float blockW = uBlocksize * uStepW;\\n' +\n 'float blockH = uBlocksize * uStepW;\\n' +\n 'int posX = int(vTexCoord.x / blockW);\\n' +\n 'int posY = int(vTexCoord.y / blockH);\\n' +\n 'float fposX = float(posX);\\n' +\n 'float fposY = float(posY);\\n' +\n 'vec2 squareCoords = vec2(fposX * blockW, fposY * blockH);\\n' +\n 'vec4 color = texture2D(uTexture, squareCoords);\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n\n /**\n * Apply the Pixelate operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d: function(options) {\n var imageData = options.imageData,\n data = imageData.data,\n iLen = imageData.height,\n jLen = imageData.width,\n index, i, j, r, g, b, a,\n _i, _j, _iLen, _jLen;\n\n for (i = 0; i < iLen; i += this.blocksize) {\n for (j = 0; j < jLen; j += this.blocksize) {\n\n index = (i * 4) * jLen + (j * 4);\n\n r = data[index];\n g = data[index + 1];\n b = data[index + 2];\n a = data[index + 3];\n\n _iLen = Math.min(i + this.blocksize, iLen);\n _jLen = Math.min(j + this.blocksize, jLen);\n for (_i = i; _i < _iLen; _i++) {\n for (_j = j; _j < _jLen; _j++) {\n index = (_i * 4) * jLen + (_j * 4);\n data[index] = r;\n data[index + 1] = g;\n data[index + 2] = b;\n data[index + 3] = a;\n }\n }\n }\n }\n },\n\n /**\n * Indicate when the filter is not gonna apply changes to the image\n **/\n isNeutralState: function() {\n return this.blocksize === 1;\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uBlocksize: gl.getUniformLocation(program, 'uBlocksize'),\n uStepW: gl.getUniformLocation(program, 'uStepW'),\n uStepH: gl.getUniformLocation(program, 'uStepH'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n gl.uniform1f(uniformLocations.uBlocksize, this.blocksize);\n },\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Pixelate} Instance of fabric.Image.filters.Pixelate\n */\n fabric.Image.filters.Pixelate.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Remove white filter class\n * @class fabric.Image.filters.RemoveColor\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.RemoveColor#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.RemoveColor({\n * threshold: 0.2,\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\n filters.RemoveColor = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.RemoveColor.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'RemoveColor',\n\n /**\n * Color to remove, in any format understood by fabric.Color.\n * @param {String} type\n * @default\n */\n color: '#FFFFFF',\n\n /**\n * Fragment source for the brightness program\n */\n fragmentSource: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform vec4 uLow;\\n' +\n 'uniform vec4 uHigh;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'gl_FragColor = texture2D(uTexture, vTexCoord);\\n' +\n 'if(all(greaterThan(gl_FragColor.rgb,uLow.rgb)) && all(greaterThan(uHigh.rgb,gl_FragColor.rgb))) {\\n' +\n 'gl_FragColor.a = 0.0;\\n' +\n '}\\n' +\n '}',\n\n /**\n * distance to actual color, as value up or down from each r,g,b\n * between 0 and 1\n **/\n distance: 0.02,\n\n /**\n * For color to remove inside distance, use alpha channel for a smoother deletion\n * NOT IMPLEMENTED YET\n **/\n useAlpha: false,\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.RemoveWhite.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.color=#RRGGBB] Threshold value\n * @param {Number} [options.distance=10] Distance value\n */\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo2d: function(options) {\n var imageData = options.imageData,\n data = imageData.data, i,\n distance = this.distance * 255,\n r, g, b,\n source = new fabric.Color(this.color).getSource(),\n lowC = [\n source[0] - distance,\n source[1] - distance,\n source[2] - distance,\n ],\n highC = [\n source[0] + distance,\n source[1] + distance,\n source[2] + distance,\n ];\n\n\n for (i = 0; i < data.length; i += 4) {\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n if (r > lowC[0] &&\n g > lowC[1] &&\n b > lowC[2] &&\n r < highC[0] &&\n g < highC[1] &&\n b < highC[2]) {\n data[i + 3] = 0;\n }\n }\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uLow: gl.getUniformLocation(program, 'uLow'),\n uHigh: gl.getUniformLocation(program, 'uHigh'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n var source = new fabric.Color(this.color).getSource(),\n distance = parseFloat(this.distance),\n lowC = [\n 0 + source[0] / 255 - distance,\n 0 + source[1] / 255 - distance,\n 0 + source[2] / 255 - distance,\n 1\n ],\n highC = [\n source[0] / 255 + distance,\n source[1] / 255 + distance,\n source[2] / 255 + distance,\n 1\n ];\n gl.uniform4fv(uniformLocations.uLow, lowC);\n gl.uniform4fv(uniformLocations.uHigh, highC);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n color: this.color,\n distance: this.distance\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.RemoveColor} Instance of fabric.Image.filters.RemoveWhite\n */\n fabric.Image.filters.RemoveColor.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n var matrices = {\n Brownie: [\n 0.59970,0.34553,-0.27082,0,0.186,\n -0.03770,0.86095,0.15059,0,-0.1449,\n 0.24113,-0.07441,0.44972,0,-0.02965,\n 0,0,0,1,0\n ],\n Vintage: [\n 0.62793,0.32021,-0.03965,0,0.03784,\n 0.02578,0.64411,0.03259,0,0.02926,\n 0.04660,-0.08512,0.52416,0,0.02023,\n 0,0,0,1,0\n ],\n Kodachrome: [\n 1.12855,-0.39673,-0.03992,0,0.24991,\n -0.16404,1.08352,-0.05498,0,0.09698,\n -0.16786,-0.56034,1.60148,0,0.13972,\n 0,0,0,1,0\n ],\n Technicolor: [\n 1.91252,-0.85453,-0.09155,0,0.04624,\n -0.30878,1.76589,-0.10601,0,-0.27589,\n -0.23110,-0.75018,1.84759,0,0.12137,\n 0,0,0,1,0\n ],\n Polaroid: [\n 1.438,-0.062,-0.062,0,0,\n -0.122,1.378,-0.122,0,0,\n -0.016,-0.016,1.483,0,0,\n 0,0,0,1,0\n ],\n Sepia: [\n 0.393, 0.769, 0.189, 0, 0,\n 0.349, 0.686, 0.168, 0, 0,\n 0.272, 0.534, 0.131, 0, 0,\n 0, 0, 0, 1, 0\n ],\n BlackWhite: [\n 1.5, 1.5, 1.5, 0, -1,\n 1.5, 1.5, 1.5, 0, -1,\n 1.5, 1.5, 1.5, 0, -1,\n 0, 0, 0, 1, 0,\n ]\n };\n\n for (var key in matrices) {\n filters[key] = createClass(filters.ColorMatrix, /** @lends fabric.Image.filters.Sepia.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: key,\n\n /**\n * Colormatrix for the effect\n * array of 20 floats. Numbers in positions 4, 9, 14, 19 loose meaning\n * outside the -1, 1 range.\n * @param {Array} matrix array of 20 numbers.\n * @default\n */\n matrix: matrices[key],\n\n /**\n * Lock the matrix export for this kind of static, parameter less filters.\n */\n mainParameter: false,\n /**\n * Lock the colormatrix on the color part, skipping alpha\n */\n colorsOnly: true,\n\n });\n fabric.Image.filters[key].fromObject = fabric.Image.filters.BaseFilter.fromObject;\n }\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n 'use strict';\n\n var fabric = global.fabric,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Color Blend filter class\n * @class fabric.Image.filter.BlendColor\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @example\n * var filter = new fabric.Image.filters.BlendColor({\n * color: '#000',\n * mode: 'multiply'\n * });\n *\n * var filter = new fabric.Image.filters.BlendImage({\n * image: fabricImageObject,\n * mode: 'multiply',\n * alpha: 0.5\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\n\n filters.BlendColor = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Blend.prototype */ {\n type: 'BlendColor',\n\n /**\n * Color to make the blend operation with. default to a reddish color since black or white\n * gives always strong result.\n * @type String\n * @default\n **/\n color: '#F95C63',\n\n /**\n * Blend mode for the filter: one of multiply, add, diff, screen, subtract,\n * darken, lighten, overlay, exclusion, tint.\n * @type String\n * @default\n **/\n mode: 'multiply',\n\n /**\n * alpha value. represent the strength of the blend color operation.\n * @type Number\n * @default\n **/\n alpha: 1,\n\n /**\n * Fragment source for the Multiply program\n */\n fragmentSource: {\n multiply: 'gl_FragColor.rgb *= uColor.rgb;\\n',\n screen: 'gl_FragColor.rgb = 1.0 - (1.0 - gl_FragColor.rgb) * (1.0 - uColor.rgb);\\n',\n add: 'gl_FragColor.rgb += uColor.rgb;\\n',\n diff: 'gl_FragColor.rgb = abs(gl_FragColor.rgb - uColor.rgb);\\n',\n subtract: 'gl_FragColor.rgb -= uColor.rgb;\\n',\n lighten: 'gl_FragColor.rgb = max(gl_FragColor.rgb, uColor.rgb);\\n',\n darken: 'gl_FragColor.rgb = min(gl_FragColor.rgb, uColor.rgb);\\n',\n exclusion: 'gl_FragColor.rgb += uColor.rgb - 2.0 * (uColor.rgb * gl_FragColor.rgb);\\n',\n overlay: 'if (uColor.r < 0.5) {\\n' +\n 'gl_FragColor.r *= 2.0 * uColor.r;\\n' +\n '} else {\\n' +\n 'gl_FragColor.r = 1.0 - 2.0 * (1.0 - gl_FragColor.r) * (1.0 - uColor.r);\\n' +\n '}\\n' +\n 'if (uColor.g < 0.5) {\\n' +\n 'gl_FragColor.g *= 2.0 * uColor.g;\\n' +\n '} else {\\n' +\n 'gl_FragColor.g = 1.0 - 2.0 * (1.0 - gl_FragColor.g) * (1.0 - uColor.g);\\n' +\n '}\\n' +\n 'if (uColor.b < 0.5) {\\n' +\n 'gl_FragColor.b *= 2.0 * uColor.b;\\n' +\n '} else {\\n' +\n 'gl_FragColor.b = 1.0 - 2.0 * (1.0 - gl_FragColor.b) * (1.0 - uColor.b);\\n' +\n '}\\n',\n tint: 'gl_FragColor.rgb *= (1.0 - uColor.a);\\n' +\n 'gl_FragColor.rgb += uColor.rgb;\\n',\n },\n\n /**\n * build the fragment source for the filters, joining the common part with\n * the specific one.\n * @param {String} mode the mode of the filter, a key of this.fragmentSource\n * @return {String} the source to be compiled\n * @private\n */\n buildSource: function(mode) {\n return 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform vec4 uColor;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n 'gl_FragColor = color;\\n' +\n 'if (color.a > 0.0) {\\n' +\n this.fragmentSource[mode] +\n '}\\n' +\n '}';\n },\n\n /**\n * Retrieves the cached shader.\n * @param {Object} options\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n retrieveShader: function(options) {\n var cacheKey = this.type + '_' + this.mode, shaderSource;\n if (!options.programCache.hasOwnProperty(cacheKey)) {\n shaderSource = this.buildSource(this.mode);\n options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\n }\n return options.programCache[cacheKey];\n },\n\n /**\n * Apply the Blend operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d: function(options) {\n var imageData = options.imageData,\n data = imageData.data, iLen = data.length,\n tr, tg, tb,\n r, g, b,\n source, alpha1 = 1 - this.alpha;\n\n source = new fabric.Color(this.color).getSource();\n tr = source[0] * this.alpha;\n tg = source[1] * this.alpha;\n tb = source[2] * this.alpha;\n\n for (var i = 0; i < iLen; i += 4) {\n\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n switch (this.mode) {\n case 'multiply':\n data[i] = r * tr / 255;\n data[i + 1] = g * tg / 255;\n data[i + 2] = b * tb / 255;\n break;\n case 'screen':\n data[i] = 255 - (255 - r) * (255 - tr) / 255;\n data[i + 1] = 255 - (255 - g) * (255 - tg) / 255;\n data[i + 2] = 255 - (255 - b) * (255 - tb) / 255;\n break;\n case 'add':\n data[i] = r + tr;\n data[i + 1] = g + tg;\n data[i + 2] = b + tb;\n break;\n case 'diff':\n case 'difference':\n data[i] = Math.abs(r - tr);\n data[i + 1] = Math.abs(g - tg);\n data[i + 2] = Math.abs(b - tb);\n break;\n case 'subtract':\n data[i] = r - tr;\n data[i + 1] = g - tg;\n data[i + 2] = b - tb;\n break;\n case 'darken':\n data[i] = Math.min(r, tr);\n data[i + 1] = Math.min(g, tg);\n data[i + 2] = Math.min(b, tb);\n break;\n case 'lighten':\n data[i] = Math.max(r, tr);\n data[i + 1] = Math.max(g, tg);\n data[i + 2] = Math.max(b, tb);\n break;\n case 'overlay':\n data[i] = tr < 128 ? (2 * r * tr / 255) : (255 - 2 * (255 - r) * (255 - tr) / 255);\n data[i + 1] = tg < 128 ? (2 * g * tg / 255) : (255 - 2 * (255 - g) * (255 - tg) / 255);\n data[i + 2] = tb < 128 ? (2 * b * tb / 255) : (255 - 2 * (255 - b) * (255 - tb) / 255);\n break;\n case 'exclusion':\n data[i] = tr + r - ((2 * tr * r) / 255);\n data[i + 1] = tg + g - ((2 * tg * g) / 255);\n data[i + 2] = tb + b - ((2 * tb * b) / 255);\n break;\n case 'tint':\n data[i] = tr + r * alpha1;\n data[i + 1] = tg + g * alpha1;\n data[i + 2] = tb + b * alpha1;\n }\n }\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uColor: gl.getUniformLocation(program, 'uColor'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n var source = new fabric.Color(this.color).getSource();\n source[0] = this.alpha * source[0] / 255;\n source[1] = this.alpha * source[1] / 255;\n source[2] = this.alpha * source[2] / 255;\n source[3] = this.alpha;\n gl.uniform4fv(uniformLocations.uColor, source);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return {\n type: this.type,\n color: this.color,\n mode: this.mode,\n alpha: this.alpha\n };\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.BlendColor} Instance of fabric.Image.filters.BlendColor\n */\n fabric.Image.filters.BlendColor.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n 'use strict';\n\n var fabric = global.fabric,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Image Blend filter class\n * @class fabric.Image.filter.BlendImage\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @example\n * var filter = new fabric.Image.filters.BlendColor({\n * color: '#000',\n * mode: 'multiply'\n * });\n *\n * var filter = new fabric.Image.filters.BlendImage({\n * image: fabricImageObject,\n * mode: 'multiply',\n * alpha: 0.5\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\n\n filters.BlendImage = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.BlendImage.prototype */ {\n type: 'BlendImage',\n\n /**\n * Color to make the blend operation with. default to a reddish color since black or white\n * gives always strong result.\n **/\n image: null,\n\n /**\n * Blend mode for the filter (one of \"multiply\", \"mask\")\n * @type String\n * @default\n **/\n mode: 'multiply',\n\n /**\n * alpha value. represent the strength of the blend image operation.\n * not implemented.\n **/\n alpha: 1,\n\n vertexSource: 'attribute vec2 aPosition;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'varying vec2 vTexCoord2;\\n' +\n 'uniform mat3 uTransformMatrix;\\n' +\n 'void main() {\\n' +\n 'vTexCoord = aPosition;\\n' +\n 'vTexCoord2 = (uTransformMatrix * vec3(aPosition, 1.0)).xy;\\n' +\n 'gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\\n' +\n '}',\n\n /**\n * Fragment source for the Multiply program\n */\n fragmentSource: {\n multiply: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform sampler2D uImage;\\n' +\n 'uniform vec4 uColor;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'varying vec2 vTexCoord2;\\n' +\n 'void main() {\\n' +\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n 'vec4 color2 = texture2D(uImage, vTexCoord2);\\n' +\n 'color.rgba *= color2.rgba;\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n mask: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform sampler2D uImage;\\n' +\n 'uniform vec4 uColor;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'varying vec2 vTexCoord2;\\n' +\n 'void main() {\\n' +\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n 'vec4 color2 = texture2D(uImage, vTexCoord2);\\n' +\n 'color.a = color2.a;\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n },\n\n /**\n * Retrieves the cached shader.\n * @param {Object} options\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n retrieveShader: function(options) {\n var cacheKey = this.type + '_' + this.mode;\n var shaderSource = this.fragmentSource[this.mode];\n if (!options.programCache.hasOwnProperty(cacheKey)) {\n options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\n }\n return options.programCache[cacheKey];\n },\n\n applyToWebGL: function(options) {\n // load texture to blend.\n var gl = options.context,\n texture = this.createTexture(options.filterBackend, this.image);\n this.bindAdditionalTexture(gl, texture, gl.TEXTURE1);\n this.callSuper('applyToWebGL', options);\n this.unbindAdditionalTexture(gl, gl.TEXTURE1);\n },\n\n createTexture: function(backend, image) {\n return backend.getCachedTexture(image.cacheKey, image._element);\n },\n\n /**\n * Calculate a transformMatrix to adapt the image to blend over\n * @param {Object} options\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n calculateMatrix: function() {\n var image = this.image,\n width = image._element.width,\n height = image._element.height;\n return [\n 1 / image.scaleX, 0, 0,\n 0, 1 / image.scaleY, 0,\n -image.left / width, -image.top / height, 1\n ];\n },\n\n /**\n * Apply the Blend operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d: function(options) {\n var imageData = options.imageData,\n resources = options.filterBackend.resources,\n data = imageData.data, iLen = data.length,\n width = imageData.width,\n height = imageData.height,\n tr, tg, tb, ta,\n r, g, b, a,\n canvas1, context, image = this.image, blendData;\n\n if (!resources.blendImage) {\n resources.blendImage = fabric.util.createCanvasElement();\n }\n canvas1 = resources.blendImage;\n context = canvas1.getContext('2d');\n if (canvas1.width !== width || canvas1.height !== height) {\n canvas1.width = width;\n canvas1.height = height;\n }\n else {\n context.clearRect(0, 0, width, height);\n }\n context.setTransform(image.scaleX, 0, 0, image.scaleY, image.left, image.top);\n context.drawImage(image._element, 0, 0, width, height);\n blendData = context.getImageData(0, 0, width, height).data;\n for (var i = 0; i < iLen; i += 4) {\n\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n a = data[i + 3];\n\n tr = blendData[i];\n tg = blendData[i + 1];\n tb = blendData[i + 2];\n ta = blendData[i + 3];\n\n switch (this.mode) {\n case 'multiply':\n data[i] = r * tr / 255;\n data[i + 1] = g * tg / 255;\n data[i + 2] = b * tb / 255;\n data[i + 3] = a * ta / 255;\n break;\n case 'mask':\n data[i + 3] = ta;\n break;\n }\n }\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uTransformMatrix: gl.getUniformLocation(program, 'uTransformMatrix'),\n uImage: gl.getUniformLocation(program, 'uImage'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n var matrix = this.calculateMatrix();\n gl.uniform1i(uniformLocations.uImage, 1); // texture unit 1.\n gl.uniformMatrix3fv(uniformLocations.uTransformMatrix, false, matrix);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return {\n type: this.type,\n image: this.image && this.image.toObject(),\n mode: this.mode,\n alpha: this.alpha\n };\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} callback to be invoked after filter creation\n * @return {fabric.Image.filters.BlendImage} Instance of fabric.Image.filters.BlendImage\n */\n fabric.Image.filters.BlendImage.fromObject = function(object, callback) {\n fabric.Image.fromObject(object.image, function(image) {\n var options = fabric.util.object.clone(object);\n options.image = image;\n callback(new fabric.Image.filters.BlendImage(options));\n });\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }), pow = Math.pow, floor = Math.floor,\n sqrt = Math.sqrt, abs = Math.abs, round = Math.round, sin = Math.sin,\n ceil = Math.ceil,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Resize image filter class\n * @class fabric.Image.filters.Resize\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Resize();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Resize = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Resize.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Resize',\n\n /**\n * Resize type\n * for webgl resizeType is just lanczos, for canvas2d can be:\n * bilinear, hermite, sliceHack, lanczos.\n * @param {String} resizeType\n * @default\n */\n resizeType: 'hermite',\n\n /**\n * Scale factor for resizing, x axis\n * @param {Number} scaleX\n * @default\n */\n scaleX: 1,\n\n /**\n * Scale factor for resizing, y axis\n * @param {Number} scaleY\n * @default\n */\n scaleY: 1,\n\n /**\n * LanczosLobes parameter for lanczos filter, valid for resizeType lanczos\n * @param {Number} lanczosLobes\n * @default\n */\n lanczosLobes: 3,\n\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uDelta: gl.getUniformLocation(program, 'uDelta'),\n uTaps: gl.getUniformLocation(program, 'uTaps'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n gl.uniform2fv(uniformLocations.uDelta, this.horizontal ? [1 / this.width, 0] : [0, 1 / this.height]);\n gl.uniform1fv(uniformLocations.uTaps, this.taps);\n },\n\n /**\n * Retrieves the cached shader.\n * @param {Object} options\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n retrieveShader: function(options) {\n var filterWindow = this.getFilterWindow(), cacheKey = this.type + '_' + filterWindow;\n if (!options.programCache.hasOwnProperty(cacheKey)) {\n var fragmentShader = this.generateShader(filterWindow);\n options.programCache[cacheKey] = this.createProgram(options.context, fragmentShader);\n }\n return options.programCache[cacheKey];\n },\n\n getFilterWindow: function() {\n var scale = this.tempScale;\n return Math.ceil(this.lanczosLobes / scale);\n },\n\n getTaps: function() {\n var lobeFunction = this.lanczosCreate(this.lanczosLobes), scale = this.tempScale,\n filterWindow = this.getFilterWindow(), taps = new Array(filterWindow);\n for (var i = 1; i <= filterWindow; i++) {\n taps[i - 1] = lobeFunction(i * scale);\n }\n return taps;\n },\n\n /**\n * Generate vertex and shader sources from the necessary steps numbers\n * @param {Number} filterWindow\n */\n generateShader: function(filterWindow) {\n var offsets = new Array(filterWindow),\n fragmentShader = this.fragmentSourceTOP, filterWindow;\n\n for (var i = 1; i <= filterWindow; i++) {\n offsets[i - 1] = i + '.0 * uDelta';\n }\n\n fragmentShader += 'uniform float uTaps[' + filterWindow + '];\\n';\n fragmentShader += 'void main() {\\n';\n fragmentShader += ' vec4 color = texture2D(uTexture, vTexCoord);\\n';\n fragmentShader += ' float sum = 1.0;\\n';\n\n offsets.forEach(function(offset, i) {\n fragmentShader += ' color += texture2D(uTexture, vTexCoord + ' + offset + ') * uTaps[' + i + '];\\n';\n fragmentShader += ' color += texture2D(uTexture, vTexCoord - ' + offset + ') * uTaps[' + i + '];\\n';\n fragmentShader += ' sum += 2.0 * uTaps[' + i + '];\\n';\n });\n fragmentShader += ' gl_FragColor = color / sum;\\n';\n fragmentShader += '}';\n return fragmentShader;\n },\n\n fragmentSourceTOP: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform vec2 uDelta;\\n' +\n 'varying vec2 vTexCoord;\\n',\n\n /**\n * Apply the resize filter to the image\n * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\n *\n * @param {Object} options\n * @param {Number} options.passes The number of filters remaining to be executed\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n applyTo: function(options) {\n if (options.webgl) {\n options.passes++;\n this.width = options.sourceWidth;\n this.horizontal = true;\n this.dW = Math.round(this.width * this.scaleX);\n this.dH = options.sourceHeight;\n this.tempScale = this.dW / this.width;\n this.taps = this.getTaps();\n options.destinationWidth = this.dW;\n this._setupFrameBuffer(options);\n this.applyToWebGL(options);\n this._swapTextures(options);\n options.sourceWidth = options.destinationWidth;\n\n this.height = options.sourceHeight;\n this.horizontal = false;\n this.dH = Math.round(this.height * this.scaleY);\n this.tempScale = this.dH / this.height;\n this.taps = this.getTaps();\n options.destinationHeight = this.dH;\n this._setupFrameBuffer(options);\n this.applyToWebGL(options);\n this._swapTextures(options);\n options.sourceHeight = options.destinationHeight;\n }\n else {\n this.applyTo2d(options);\n }\n },\n\n isNeutralState: function() {\n return this.scaleX === 1 && this.scaleY === 1;\n },\n\n lanczosCreate: function(lobes) {\n return function(x) {\n if (x >= lobes || x <= -lobes) {\n return 0.0;\n }\n if (x < 1.19209290E-07 && x > -1.19209290E-07) {\n return 1.0;\n }\n x *= Math.PI;\n var xx = x / lobes;\n return (sin(x) / x) * sin(xx) / xx;\n };\n },\n\n /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Resize.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} scaleX\n * @param {Number} scaleY\n */\n applyTo2d: function(options) {\n var imageData = options.imageData,\n scaleX = this.scaleX,\n scaleY = this.scaleY;\n\n this.rcpScaleX = 1 / scaleX;\n this.rcpScaleY = 1 / scaleY;\n\n var oW = imageData.width, oH = imageData.height,\n dW = round(oW * scaleX), dH = round(oH * scaleY),\n newData;\n\n if (this.resizeType === 'sliceHack') {\n newData = this.sliceByTwo(options, oW, oH, dW, dH);\n }\n else if (this.resizeType === 'hermite') {\n newData = this.hermiteFastResize(options, oW, oH, dW, dH);\n }\n else if (this.resizeType === 'bilinear') {\n newData = this.bilinearFiltering(options, oW, oH, dW, dH);\n }\n else if (this.resizeType === 'lanczos') {\n newData = this.lanczosResize(options, oW, oH, dW, dH);\n }\n options.imageData = newData;\n },\n\n /**\n * Filter sliceByTwo\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n sliceByTwo: function(options, oW, oH, dW, dH) {\n var imageData = options.imageData,\n mult = 0.5, doneW = false, doneH = false, stepW = oW * mult,\n stepH = oH * mult, resources = fabric.filterBackend.resources,\n tmpCanvas, ctx, sX = 0, sY = 0, dX = oW, dY = 0;\n if (!resources.sliceByTwo) {\n resources.sliceByTwo = document.createElement('canvas');\n }\n tmpCanvas = resources.sliceByTwo;\n if (tmpCanvas.width < oW * 1.5 || tmpCanvas.height < oH) {\n tmpCanvas.width = oW * 1.5;\n tmpCanvas.height = oH;\n }\n ctx = tmpCanvas.getContext('2d');\n ctx.clearRect(0, 0, oW * 1.5, oH);\n ctx.putImageData(imageData, 0, 0);\n\n dW = floor(dW);\n dH = floor(dH);\n\n while (!doneW || !doneH) {\n oW = stepW;\n oH = stepH;\n if (dW < floor(stepW * mult)) {\n stepW = floor(stepW * mult);\n }\n else {\n stepW = dW;\n doneW = true;\n }\n if (dH < floor(stepH * mult)) {\n stepH = floor(stepH * mult);\n }\n else {\n stepH = dH;\n doneH = true;\n }\n ctx.drawImage(tmpCanvas, sX, sY, oW, oH, dX, dY, stepW, stepH);\n sX = dX;\n sY = dY;\n dY += stepH;\n }\n return ctx.getImageData(sX, sY, dW, dH);\n },\n\n /**\n * Filter lanczosResize\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n lanczosResize: function(options, oW, oH, dW, dH) {\n\n function process(u) {\n var v, i, weight, idx, a, red, green,\n blue, alpha, fX, fY;\n center.x = (u + 0.5) * ratioX;\n icenter.x = floor(center.x);\n for (v = 0; v < dH; v++) {\n center.y = (v + 0.5) * ratioY;\n icenter.y = floor(center.y);\n a = 0; red = 0; green = 0; blue = 0; alpha = 0;\n for (i = icenter.x - range2X; i <= icenter.x + range2X; i++) {\n if (i < 0 || i >= oW) {\n continue;\n }\n fX = floor(1000 * abs(i - center.x));\n if (!cacheLanc[fX]) {\n cacheLanc[fX] = { };\n }\n for (var j = icenter.y - range2Y; j <= icenter.y + range2Y; j++) {\n if (j < 0 || j >= oH) {\n continue;\n }\n fY = floor(1000 * abs(j - center.y));\n if (!cacheLanc[fX][fY]) {\n cacheLanc[fX][fY] = lanczos(sqrt(pow(fX * rcpRatioX, 2) + pow(fY * rcpRatioY, 2)) / 1000);\n }\n weight = cacheLanc[fX][fY];\n if (weight > 0) {\n idx = (j * oW + i) * 4;\n a += weight;\n red += weight * srcData[idx];\n green += weight * srcData[idx + 1];\n blue += weight * srcData[idx + 2];\n alpha += weight * srcData[idx + 3];\n }\n }\n }\n idx = (v * dW + u) * 4;\n destData[idx] = red / a;\n destData[idx + 1] = green / a;\n destData[idx + 2] = blue / a;\n destData[idx + 3] = alpha / a;\n }\n\n if (++u < dW) {\n return process(u);\n }\n else {\n return destImg;\n }\n }\n\n var srcData = options.imageData.data,\n destImg = options.ctx.createImageData(dW, dH),\n destData = destImg.data,\n lanczos = this.lanczosCreate(this.lanczosLobes),\n ratioX = this.rcpScaleX, ratioY = this.rcpScaleY,\n rcpRatioX = 2 / this.rcpScaleX, rcpRatioY = 2 / this.rcpScaleY,\n range2X = ceil(ratioX * this.lanczosLobes / 2),\n range2Y = ceil(ratioY * this.lanczosLobes / 2),\n cacheLanc = { }, center = { }, icenter = { };\n\n return process(0);\n },\n\n /**\n * bilinearFiltering\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n bilinearFiltering: function(options, oW, oH, dW, dH) {\n var a, b, c, d, x, y, i, j, xDiff, yDiff, chnl,\n color, offset = 0, origPix, ratioX = this.rcpScaleX,\n ratioY = this.rcpScaleY,\n w4 = 4 * (oW - 1), img = options.imageData,\n pixels = img.data, destImage = options.ctx.createImageData(dW, dH),\n destPixels = destImage.data;\n for (i = 0; i < dH; i++) {\n for (j = 0; j < dW; j++) {\n x = floor(ratioX * j);\n y = floor(ratioY * i);\n xDiff = ratioX * j - x;\n yDiff = ratioY * i - y;\n origPix = 4 * (y * oW + x);\n\n for (chnl = 0; chnl < 4; chnl++) {\n a = pixels[origPix + chnl];\n b = pixels[origPix + 4 + chnl];\n c = pixels[origPix + w4 + chnl];\n d = pixels[origPix + w4 + 4 + chnl];\n color = a * (1 - xDiff) * (1 - yDiff) + b * xDiff * (1 - yDiff) +\n c * yDiff * (1 - xDiff) + d * xDiff * yDiff;\n destPixels[offset++] = color;\n }\n }\n }\n return destImage;\n },\n\n /**\n * hermiteFastResize\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n hermiteFastResize: function(options, oW, oH, dW, dH) {\n var ratioW = this.rcpScaleX, ratioH = this.rcpScaleY,\n ratioWHalf = ceil(ratioW / 2),\n ratioHHalf = ceil(ratioH / 2),\n img = options.imageData, data = img.data,\n img2 = options.ctx.createImageData(dW, dH), data2 = img2.data;\n for (var j = 0; j < dH; j++) {\n for (var i = 0; i < dW; i++) {\n var x2 = (i + j * dW) * 4, weight = 0, weights = 0, weightsAlpha = 0,\n gxR = 0, gxG = 0, gxB = 0, gxA = 0, centerY = (j + 0.5) * ratioH;\n for (var yy = floor(j * ratioH); yy < (j + 1) * ratioH; yy++) {\n var dy = abs(centerY - (yy + 0.5)) / ratioHHalf,\n centerX = (i + 0.5) * ratioW, w0 = dy * dy;\n for (var xx = floor(i * ratioW); xx < (i + 1) * ratioW; xx++) {\n var dx = abs(centerX - (xx + 0.5)) / ratioWHalf,\n w = sqrt(w0 + dx * dx);\n /* eslint-disable max-depth */\n if (w > 1 && w < -1) {\n continue;\n }\n //hermite filter\n weight = 2 * w * w * w - 3 * w * w + 1;\n if (weight > 0) {\n dx = 4 * (xx + yy * oW);\n //alpha\n gxA += weight * data[dx + 3];\n weightsAlpha += weight;\n //colors\n if (data[dx + 3] < 255) {\n weight = weight * data[dx + 3] / 250;\n }\n gxR += weight * data[dx];\n gxG += weight * data[dx + 1];\n gxB += weight * data[dx + 2];\n weights += weight;\n }\n /* eslint-enable max-depth */\n }\n }\n data2[x2] = gxR / weights;\n data2[x2 + 1] = gxG / weights;\n data2[x2 + 2] = gxB / weights;\n data2[x2 + 3] = gxA / weightsAlpha;\n }\n }\n return img2;\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return {\n type: this.type,\n scaleX: this.scaleX,\n scaleY: this.scaleY,\n resizeType: this.resizeType,\n lanczosLobes: this.lanczosLobes\n };\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Resize} Instance of fabric.Image.filters.Resize\n */\n fabric.Image.filters.Resize.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Contrast filter class\n * @class fabric.Image.filters.Contrast\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Contrast#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Contrast({\n * contrast: 0.25\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\n filters.Contrast = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Contrast.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Contrast',\n\n fragmentSource: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uContrast;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n 'float contrastF = 1.015 * (uContrast + 1.0) / (1.0 * (1.015 - uContrast));\\n' +\n 'color.rgb = contrastF * (color.rgb - 0.5) + 0.5;\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n\n /**\n * contrast value, range from -1 to 1.\n * @param {Number} contrast\n * @default 0\n */\n contrast: 0,\n\n mainParameter: 'contrast',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Contrast.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.contrast=0] Value to contrast the image up (-1...1)\n */\n\n /**\n * Apply the Contrast operation to a Uint8Array representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\n */\n applyTo2d: function(options) {\n if (this.contrast === 0) {\n return;\n }\n var imageData = options.imageData, i, len,\n data = imageData.data, len = data.length,\n contrast = Math.floor(this.contrast * 255),\n contrastF = 259 * (contrast + 255) / (255 * (259 - contrast));\n\n for (i = 0; i < len; i += 4) {\n data[i] = contrastF * (data[i] - 128) + 128;\n data[i + 1] = contrastF * (data[i + 1] - 128) + 128;\n data[i + 2] = contrastF * (data[i + 2] - 128) + 128;\n }\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uContrast: gl.getUniformLocation(program, 'uContrast'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n gl.uniform1f(uniformLocations.uContrast, this.contrast);\n },\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Contrast} Instance of fabric.Image.filters.Contrast\n */\n fabric.Image.filters.Contrast.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Saturate filter class\n * @class fabric.Image.filters.Saturation\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Saturation#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Saturation({\n * saturation: 1\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\n filters.Saturation = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Saturation.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Saturation',\n\n fragmentSource: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uSaturation;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n 'float rgMax = max(color.r, color.g);\\n' +\n 'float rgbMax = max(rgMax, color.b);\\n' +\n 'color.r += rgbMax != color.r ? (rgbMax - color.r) * uSaturation : 0.00;\\n' +\n 'color.g += rgbMax != color.g ? (rgbMax - color.g) * uSaturation : 0.00;\\n' +\n 'color.b += rgbMax != color.b ? (rgbMax - color.b) * uSaturation : 0.00;\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n\n /**\n * Saturation value, from -1 to 1.\n * Increases/decreases the color saturation.\n * A value of 0 has no effect.\n * \n * @param {Number} saturation\n * @default\n */\n saturation: 0,\n\n mainParameter: 'saturation',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Saturate.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.saturate=0] Value to saturate the image (-1...1)\n */\n\n /**\n * Apply the Saturation operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d: function(options) {\n if (this.saturation === 0) {\n return;\n }\n var imageData = options.imageData,\n data = imageData.data, len = data.length,\n adjust = -this.saturation, i, max;\n\n for (i = 0; i < len; i += 4) {\n max = Math.max(data[i], data[i + 1], data[i + 2]);\n data[i] += max !== data[i] ? (max - data[i]) * adjust : 0;\n data[i + 1] += max !== data[i + 1] ? (max - data[i + 1]) * adjust : 0;\n data[i + 2] += max !== data[i + 2] ? (max - data[i + 2]) * adjust : 0;\n }\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uSaturation: gl.getUniformLocation(program, 'uSaturation'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n gl.uniform1f(uniformLocations.uSaturation, -this.saturation);\n },\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Saturation} Instance of fabric.Image.filters.Saturate\n */\n fabric.Image.filters.Saturation.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Vibrance filter class\n * @class fabric.Image.filters.Vibrance\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Vibrance#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Vibrance({\n * vibrance: 1\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\n filters.Vibrance = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Vibrance.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Vibrance',\n\n fragmentSource: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform float uVibrance;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n 'float max = max(color.r, max(color.g, color.b));\\n' +\n 'float avg = (color.r + color.g + color.b) / 3.0;\\n' +\n 'float amt = (abs(max - avg) * 2.0) * uVibrance;\\n' +\n 'color.r += max != color.r ? (max - color.r) * amt : 0.00;\\n' +\n 'color.g += max != color.g ? (max - color.g) * amt : 0.00;\\n' +\n 'color.b += max != color.b ? (max - color.b) * amt : 0.00;\\n' +\n 'gl_FragColor = color;\\n' +\n '}',\n\n /**\n * Vibrance value, from -1 to 1.\n * Increases/decreases the saturation of more muted colors with less effect on saturated colors.\n * A value of 0 has no effect.\n * \n * @param {Number} vibrance\n * @default\n */\n vibrance: 0,\n\n mainParameter: 'vibrance',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Vibrance.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.vibrance=0] Vibrance value for the image (between -1 and 1)\n */\n\n /**\n * Apply the Vibrance operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d: function(options) {\n if (this.vibrance === 0) {\n return;\n }\n var imageData = options.imageData,\n data = imageData.data, len = data.length,\n adjust = -this.vibrance, i, max, avg, amt;\n\n for (i = 0; i < len; i += 4) {\n max = Math.max(data[i], data[i + 1], data[i + 2]);\n avg = (data[i] + data[i + 1] + data[i + 2]) / 3;\n amt = ((Math.abs(max - avg) * 2 / 255) * adjust);\n data[i] += max !== data[i] ? (max - data[i]) * amt : 0;\n data[i + 1] += max !== data[i + 1] ? (max - data[i + 1]) * amt : 0;\n data[i + 2] += max !== data[i + 2] ? (max - data[i + 2]) * amt : 0;\n }\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uVibrance: gl.getUniformLocation(program, 'uVibrance'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n gl.uniform1f(uniformLocations.uVibrance, -this.vibrance);\n },\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Vibrance} Instance of fabric.Image.filters.Vibrance\n */\n fabric.Image.filters.Vibrance.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Blur filter class\n * @class fabric.Image.filters.Blur\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Blur#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Blur({\n * blur: 0.5\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\n filters.Blur = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Blur.prototype */ {\n\n type: 'Blur',\n\n /*\n'gl_FragColor = vec4(0.0);',\n'gl_FragColor += texture2D(texture, vTexCoord + -7 * uDelta)*0.0044299121055113265;',\n'gl_FragColor += texture2D(texture, vTexCoord + -6 * uDelta)*0.00895781211794;',\n'gl_FragColor += texture2D(texture, vTexCoord + -5 * uDelta)*0.0215963866053;',\n'gl_FragColor += texture2D(texture, vTexCoord + -4 * uDelta)*0.0443683338718;',\n'gl_FragColor += texture2D(texture, vTexCoord + -3 * uDelta)*0.0776744219933;',\n'gl_FragColor += texture2D(texture, vTexCoord + -2 * uDelta)*0.115876621105;',\n'gl_FragColor += texture2D(texture, vTexCoord + -1 * uDelta)*0.147308056121;',\n'gl_FragColor += texture2D(texture, vTexCoord )*0.159576912161;',\n'gl_FragColor += texture2D(texture, vTexCoord + 1 * uDelta)*0.147308056121;',\n'gl_FragColor += texture2D(texture, vTexCoord + 2 * uDelta)*0.115876621105;',\n'gl_FragColor += texture2D(texture, vTexCoord + 3 * uDelta)*0.0776744219933;',\n'gl_FragColor += texture2D(texture, vTexCoord + 4 * uDelta)*0.0443683338718;',\n'gl_FragColor += texture2D(texture, vTexCoord + 5 * uDelta)*0.0215963866053;',\n'gl_FragColor += texture2D(texture, vTexCoord + 6 * uDelta)*0.00895781211794;',\n'gl_FragColor += texture2D(texture, vTexCoord + 7 * uDelta)*0.0044299121055113265;',\n*/\n\n /* eslint-disable max-len */\n fragmentSource: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform vec2 uDelta;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'const float nSamples = 15.0;\\n' +\n 'vec3 v3offset = vec3(12.9898, 78.233, 151.7182);\\n' +\n 'float random(vec3 scale) {\\n' +\n /* use the fragment position for a different seed per-pixel */\n 'return fract(sin(dot(gl_FragCoord.xyz, scale)) * 43758.5453);\\n' +\n '}\\n' +\n 'void main() {\\n' +\n 'vec4 color = vec4(0.0);\\n' +\n 'float total = 0.0;\\n' +\n 'float offset = random(v3offset);\\n' +\n 'for (float t = -nSamples; t <= nSamples; t++) {\\n' +\n 'float percent = (t + offset - 0.5) / nSamples;\\n' +\n 'float weight = 1.0 - abs(percent);\\n' +\n 'color += texture2D(uTexture, vTexCoord + uDelta * percent) * weight;\\n' +\n 'total += weight;\\n' +\n '}\\n' +\n 'gl_FragColor = color / total;\\n' +\n '}',\n /* eslint-enable max-len */\n\n /**\n * blur value, in percentage of image dimensions.\n * specific to keep the image blur constant at different resolutions\n * range between 0 and 1.\n * @type Number\n * @default\n */\n blur: 0,\n\n mainParameter: 'blur',\n\n applyTo: function(options) {\n if (options.webgl) {\n // this aspectRatio is used to give the same blur to vertical and horizontal\n this.aspectRatio = options.sourceWidth / options.sourceHeight;\n options.passes++;\n this._setupFrameBuffer(options);\n this.horizontal = true;\n this.applyToWebGL(options);\n this._swapTextures(options);\n this._setupFrameBuffer(options);\n this.horizontal = false;\n this.applyToWebGL(options);\n this._swapTextures(options);\n }\n else {\n this.applyTo2d(options);\n }\n },\n\n applyTo2d: function(options) {\n // paint canvasEl with current image data.\n //options.ctx.putImageData(options.imageData, 0, 0);\n options.imageData = this.simpleBlur(options);\n },\n\n simpleBlur: function(options) {\n var resources = options.filterBackend.resources, canvas1, canvas2,\n width = options.imageData.width,\n height = options.imageData.height;\n\n if (!resources.blurLayer1) {\n resources.blurLayer1 = fabric.util.createCanvasElement();\n resources.blurLayer2 = fabric.util.createCanvasElement();\n }\n canvas1 = resources.blurLayer1;\n canvas2 = resources.blurLayer2;\n if (canvas1.width !== width || canvas1.height !== height) {\n canvas2.width = canvas1.width = width;\n canvas2.height = canvas1.height = height;\n }\n var ctx1 = canvas1.getContext('2d'),\n ctx2 = canvas2.getContext('2d'),\n nSamples = 15,\n random, percent, j, i,\n blur = this.blur * 0.06 * 0.5;\n\n // load first canvas\n ctx1.putImageData(options.imageData, 0, 0);\n ctx2.clearRect(0, 0, width, height);\n\n for (i = -nSamples; i <= nSamples; i++) {\n random = (Math.random() - 0.5) / 4;\n percent = i / nSamples;\n j = blur * percent * width + random;\n ctx2.globalAlpha = 1 - Math.abs(percent);\n ctx2.drawImage(canvas1, j, random);\n ctx1.drawImage(canvas2, 0, 0);\n ctx2.globalAlpha = 1;\n ctx2.clearRect(0, 0, canvas2.width, canvas2.height);\n }\n for (i = -nSamples; i <= nSamples; i++) {\n random = (Math.random() - 0.5) / 4;\n percent = i / nSamples;\n j = blur * percent * height + random;\n ctx2.globalAlpha = 1 - Math.abs(percent);\n ctx2.drawImage(canvas1, random, j);\n ctx1.drawImage(canvas2, 0, 0);\n ctx2.globalAlpha = 1;\n ctx2.clearRect(0, 0, canvas2.width, canvas2.height);\n }\n options.ctx.drawImage(canvas1, 0, 0);\n var newImageData = options.ctx.getImageData(0, 0, canvas1.width, canvas1.height);\n ctx1.globalAlpha = 1;\n ctx1.clearRect(0, 0, canvas1.width, canvas1.height);\n return newImageData;\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n delta: gl.getUniformLocation(program, 'uDelta'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n var delta = this.chooseRightDelta();\n gl.uniform2fv(uniformLocations.delta, delta);\n },\n\n /**\n * choose right value of image percentage to blur with\n * @returns {Array} a numeric array with delta values\n */\n chooseRightDelta: function() {\n var blurScale = 1, delta = [0, 0], blur;\n if (this.horizontal) {\n if (this.aspectRatio > 1) {\n // image is wide, i want to shrink radius horizontal\n blurScale = 1 / this.aspectRatio;\n }\n }\n else {\n if (this.aspectRatio < 1) {\n // image is tall, i want to shrink radius vertical\n blurScale = this.aspectRatio;\n }\n }\n blur = blurScale * this.blur * 0.12;\n if (this.horizontal) {\n delta[0] = blur;\n }\n else {\n delta[1] = blur;\n }\n return delta;\n },\n });\n\n /**\n * Deserialize a JSON definition of a BlurFilter into a concrete instance.\n */\n filters.Blur.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Gamma filter class\n * @class fabric.Image.filters.Gamma\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Gamma#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Gamma({\n * gamma: [1, 0.5, 2.1]\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\n filters.Gamma = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Gamma.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Gamma',\n\n fragmentSource: 'precision highp float;\\n' +\n 'uniform sampler2D uTexture;\\n' +\n 'uniform vec3 uGamma;\\n' +\n 'varying vec2 vTexCoord;\\n' +\n 'void main() {\\n' +\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\n 'vec3 correction = (1.0 / uGamma);\\n' +\n 'color.r = pow(color.r, correction.r);\\n' +\n 'color.g = pow(color.g, correction.g);\\n' +\n 'color.b = pow(color.b, correction.b);\\n' +\n 'gl_FragColor = color;\\n' +\n 'gl_FragColor.rgb *= color.a;\\n' +\n '}',\n\n /**\n * Gamma array value, from 0.01 to 2.2.\n * @param {Array} gamma\n * @default\n */\n gamma: [1, 1, 1],\n\n /**\n * Describe the property that is the filter parameter\n * @param {String} m\n * @default\n */\n mainParameter: 'gamma',\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n initialize: function(options) {\n this.gamma = [1, 1, 1];\n filters.BaseFilter.prototype.initialize.call(this, options);\n },\n\n /**\n * Apply the Gamma operation to a Uint8Array representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\n */\n applyTo2d: function(options) {\n var imageData = options.imageData, data = imageData.data,\n gamma = this.gamma, len = data.length,\n rInv = 1 / gamma[0], gInv = 1 / gamma[1],\n bInv = 1 / gamma[2], i;\n\n if (!this.rVals) {\n // eslint-disable-next-line\n this.rVals = new Uint8Array(256);\n // eslint-disable-next-line\n this.gVals = new Uint8Array(256);\n // eslint-disable-next-line\n this.bVals = new Uint8Array(256);\n }\n\n // This is an optimization - pre-compute a look-up table for each color channel\n // instead of performing these pow calls for each pixel in the image.\n for (i = 0, len = 256; i < len; i++) {\n this.rVals[i] = Math.pow(i / 255, rInv) * 255;\n this.gVals[i] = Math.pow(i / 255, gInv) * 255;\n this.bVals[i] = Math.pow(i / 255, bInv) * 255;\n }\n for (i = 0, len = data.length; i < len; i += 4) {\n data[i] = this.rVals[data[i]];\n data[i + 1] = this.gVals[data[i + 1]];\n data[i + 2] = this.bVals[data[i + 2]];\n }\n },\n\n /**\n * Return WebGL uniform locations for this filter's shader.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\n */\n getUniformLocations: function(gl, program) {\n return {\n uGamma: gl.getUniformLocation(program, 'uGamma'),\n };\n },\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData: function(gl, uniformLocations) {\n gl.uniform3fv(uniformLocations.uGamma, this.gamma);\n },\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Gamma} Instance of fabric.Image.filters.Gamma\n */\n fabric.Image.filters.Gamma.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * A container class that knows how to apply a sequence of filters to an input image.\n */\n filters.Composed = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Composed.prototype */ {\n\n type: 'Composed',\n\n /**\n * A non sparse array of filters to apply\n */\n subFilters: [],\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n initialize: function(options) {\n this.callSuper('initialize', options);\n // create a new array instead mutating the prototype with push\n this.subFilters = this.subFilters.slice(0);\n },\n\n /**\n * Apply this container's filters to the input image provided.\n *\n * @param {Object} options\n * @param {Number} options.passes The number of filters remaining to be applied.\n */\n applyTo: function(options) {\n options.passes += this.subFilters.length - 1;\n this.subFilters.forEach(function(filter) {\n filter.applyTo(options);\n });\n },\n\n /**\n * Serialize this filter into JSON.\n *\n * @returns {Object} A JSON representation of this filter.\n */\n toObject: function() {\n return fabric.util.object.extend(this.callSuper('toObject'), {\n subFilters: this.subFilters.map(function(filter) { return filter.toObject(); }),\n });\n },\n\n isNeutralState: function() {\n return !this.subFilters.some(function(filter) { return !filter.isNeutralState(); });\n }\n });\n\n /**\n * Deserialize a JSON definition of a ComposedFilter into a concrete instance.\n */\n fabric.Image.filters.Composed.fromObject = function(object, callback) {\n var filters = object.subFilters || [],\n subFilters = filters.map(function(filter) {\n return new fabric.Image.filters[filter.type](filter);\n }),\n instance = new fabric.Image.filters.Composed({ subFilters: subFilters });\n callback && callback(instance);\n return instance;\n };\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * HueRotation filter class\n * @class fabric.Image.filters.HueRotation\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.HueRotation#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.HueRotation({\n * rotation: -0.5\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\n filters.HueRotation = createClass(filters.ColorMatrix, /** @lends fabric.Image.filters.HueRotation.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'HueRotation',\n\n /**\n * HueRotation value, from -1 to 1.\n * the unit is radians\n * @param {Number} myParameter\n * @default\n */\n rotation: 0,\n\n /**\n * Describe the property that is the filter parameter\n * @param {String} m\n * @default\n */\n mainParameter: 'rotation',\n\n calculateMatrix: function() {\n var rad = this.rotation * Math.PI, cos = fabric.util.cos(rad), sin = fabric.util.sin(rad),\n aThird = 1 / 3, aThirdSqtSin = Math.sqrt(aThird) * sin, OneMinusCos = 1 - cos;\n this.matrix = [\n 1, 0, 0, 0, 0,\n 0, 1, 0, 0, 0,\n 0, 0, 1, 0, 0,\n 0, 0, 0, 1, 0\n ];\n this.matrix[0] = cos + OneMinusCos / 3;\n this.matrix[1] = aThird * OneMinusCos - aThirdSqtSin;\n this.matrix[2] = aThird * OneMinusCos + aThirdSqtSin;\n this.matrix[5] = aThird * OneMinusCos + aThirdSqtSin;\n this.matrix[6] = cos + aThird * OneMinusCos;\n this.matrix[7] = aThird * OneMinusCos - aThirdSqtSin;\n this.matrix[10] = aThird * OneMinusCos - aThirdSqtSin;\n this.matrix[11] = aThird * OneMinusCos + aThirdSqtSin;\n this.matrix[12] = cos + aThird * OneMinusCos;\n },\n\n /**\n * HueRotation isNeutralState implementation\n * Used only in image applyFilters to discard filters that will not have an effect\n * on the image\n * @param {Object} options\n **/\n isNeutralState: function(options) {\n this.calculateMatrix();\n return filters.BaseFilter.prototype.isNeutralState.call(this, options);\n },\n\n /**\n * Apply this filter to the input image data provided.\n *\n * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\n *\n * @param {Object} options\n * @param {Number} options.passes The number of filters remaining to be executed\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n applyTo: function(options) {\n this.calculateMatrix();\n filters.BaseFilter.prototype.applyTo.call(this, options);\n },\n\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.HueRotation} Instance of fabric.Image.filters.HueRotation\n */\n fabric.Image.filters.HueRotation.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n clone = fabric.util.object.clone;\n\n if (fabric.Text) {\n fabric.warn('fabric.Text is already defined');\n return;\n }\n\n var additionalProps =\n ('fontFamily fontWeight fontSize text underline overline linethrough' +\n ' textAlign fontStyle lineHeight textBackgroundColor charSpacing styles' +\n ' direction path pathStartOffset pathSide pathAlign').split(' ');\n\n /**\n * Text class\n * @class fabric.Text\n * @extends fabric.Object\n * @return {fabric.Text} thisArg\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#text}\n * @see {@link fabric.Text#initialize} for constructor definition\n */\n fabric.Text = fabric.util.createClass(fabric.Object, /** @lends fabric.Text.prototype */ {\n\n /**\n * Properties which when set cause object to change dimensions\n * @type Array\n * @private\n */\n _dimensionAffectingProps: [\n 'fontSize',\n 'fontWeight',\n 'fontFamily',\n 'fontStyle',\n 'lineHeight',\n 'text',\n 'charSpacing',\n 'textAlign',\n 'styles',\n 'path',\n 'pathStartOffset',\n 'pathSide',\n 'pathAlign'\n ],\n\n /**\n * @private\n */\n _reNewline: /\\r?\\n/,\n\n /**\n * Use this regular expression to filter for whitespaces that is not a new line.\n * Mostly used when text is 'justify' aligned.\n * @private\n */\n _reSpacesAndTabs: /[ \\t\\r]/g,\n\n /**\n * Use this regular expression to filter for whitespace that is not a new line.\n * Mostly used when text is 'justify' aligned.\n * @private\n */\n _reSpaceAndTab: /[ \\t\\r]/,\n\n /**\n * Use this regular expression to filter consecutive groups of non spaces.\n * Mostly used when text is 'justify' aligned.\n * @private\n */\n _reWords: /\\S+/g,\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'text',\n\n /**\n * Font size (in pixels)\n * @type Number\n * @default\n */\n fontSize: 40,\n\n /**\n * Font weight (e.g. bold, normal, 400, 600, 800)\n * @type {(Number|String)}\n * @default\n */\n fontWeight: 'normal',\n\n /**\n * Font family\n * @type String\n * @default\n */\n fontFamily: 'Times New Roman',\n\n /**\n * Text decoration underline.\n * @type Boolean\n * @default\n */\n underline: false,\n\n /**\n * Text decoration overline.\n * @type Boolean\n * @default\n */\n overline: false,\n\n /**\n * Text decoration linethrough.\n * @type Boolean\n * @default\n */\n linethrough: false,\n\n /**\n * Text alignment. Possible values: \"left\", \"center\", \"right\", \"justify\",\n * \"justify-left\", \"justify-center\" or \"justify-right\".\n * @type String\n * @default\n */\n textAlign: 'left',\n\n /**\n * Font style . Possible values: \"\", \"normal\", \"italic\" or \"oblique\".\n * @type String\n * @default\n */\n fontStyle: 'normal',\n\n /**\n * Line height\n * @type Number\n * @default\n */\n lineHeight: 1.16,\n\n /**\n * Superscript schema object (minimum overlap)\n * @type {Object}\n * @default\n */\n superscript: {\n size: 0.60, // fontSize factor\n baseline: -0.35 // baseline-shift factor (upwards)\n },\n\n /**\n * Subscript schema object (minimum overlap)\n * @type {Object}\n * @default\n */\n subscript: {\n size: 0.60, // fontSize factor\n baseline: 0.11 // baseline-shift factor (downwards)\n },\n\n /**\n * Background color of text lines\n * @type String\n * @default\n */\n textBackgroundColor: '',\n\n /**\n * List of properties to consider when checking if\n * state of an object is changed ({@link fabric.Object#hasStateChanged})\n * as well as for history (undo/redo) purposes\n * @type Array\n */\n stateProperties: fabric.Object.prototype.stateProperties.concat(additionalProps),\n\n /**\n * List of properties to consider when checking if cache needs refresh\n * @type Array\n */\n cacheProperties: fabric.Object.prototype.cacheProperties.concat(additionalProps),\n\n /**\n * When defined, an object is rendered via stroke and this property specifies its color.\n * Backwards incompatibility note: This property was named \"strokeStyle\" until v1.1.6\n * @type String\n * @default\n */\n stroke: null,\n\n /**\n * Shadow object representing shadow of this shape.\n * Backwards incompatibility note: This property was named \"textShadow\" (String) until v1.2.11\n * @type fabric.Shadow\n * @default\n */\n shadow: null,\n\n /**\n * fabric.Path that the text should follow.\n * since 4.6.0 the path will be drawn automatically.\n * if you want to make the path visible, give it a stroke and strokeWidth or fill value\n * if you want it to be hidden, assign visible = false to the path.\n * This feature is in BETA, and SVG import/export is not yet supported.\n * @type fabric.Path\n * @example\n * var textPath = new fabric.Text('Text on a path', {\n * top: 150,\n * left: 150,\n * textAlign: 'center',\n * charSpacing: -50,\n * path: new fabric.Path('M 0 0 C 50 -100 150 -100 200 0', {\n * strokeWidth: 1,\n * visible: false\n * }),\n * pathSide: 'left',\n * pathStartOffset: 0\n * });\n * @default\n */\n path: null,\n\n /**\n * Offset amount for text path starting position\n * Only used when text has a path\n * @type Number\n * @default\n */\n pathStartOffset: 0,\n\n /**\n * Which side of the path the text should be drawn on.\n * Only used when text has a path\n * @type {String} 'left|right'\n * @default\n */\n pathSide: 'left',\n\n /**\n * How text is aligned to the path. This property determines\n * the perpendicular position of each character relative to the path.\n * (one of \"baseline\", \"center\", \"ascender\", \"descender\")\n * This feature is in BETA, and its behavior may change\n * @type String\n * @default\n */\n pathAlign: 'baseline',\n\n /**\n * @private\n */\n _fontSizeFraction: 0.222,\n\n /**\n * @private\n */\n offsets: {\n underline: 0.10,\n linethrough: -0.315,\n overline: -0.88\n },\n\n /**\n * Text Line proportion to font Size (in pixels)\n * @type Number\n * @default\n */\n _fontSizeMult: 1.13,\n\n /**\n * additional space between characters\n * expressed in thousands of em unit\n * @type Number\n * @default\n */\n charSpacing: 0,\n\n /**\n * Object containing character styles - top-level properties -> line numbers,\n * 2nd-level properties - character numbers\n * @type Object\n * @default\n */\n styles: null,\n\n /**\n * Reference to a context to measure text char or couple of chars\n * the cacheContext of the canvas will be used or a freshly created one if the object is not on canvas\n * once created it will be referenced on fabric._measuringContext to avoid creating a canvas for every\n * text object created.\n * @type {CanvasRenderingContext2D}\n * @default\n */\n _measuringContext: null,\n\n /**\n * Baseline shift, styles only, keep at 0 for the main text object\n * @type {Number}\n * @default\n */\n deltaY: 0,\n\n /**\n * WARNING: EXPERIMENTAL. NOT SUPPORTED YET\n * determine the direction of the text.\n * This has to be set manually together with textAlign and originX for proper\n * experience.\n * some interesting link for the future\n * https://www.w3.org/International/questions/qa-bidi-unicode-controls\n * @since 4.5.0\n * @type {String} 'ltr|rtl'\n * @default\n */\n direction: 'ltr',\n\n /**\n * Array of properties that define a style unit (of 'styles').\n * @type {Array}\n * @default\n */\n _styleProperties: [\n 'stroke',\n 'strokeWidth',\n 'fill',\n 'fontFamily',\n 'fontSize',\n 'fontWeight',\n 'fontStyle',\n 'underline',\n 'overline',\n 'linethrough',\n 'deltaY',\n 'textBackgroundColor',\n ],\n\n /**\n * contains characters bounding boxes\n */\n __charBounds: [],\n\n /**\n * use this size when measuring text. To avoid IE11 rounding errors\n * @type {Number}\n * @default\n * @readonly\n * @private\n */\n CACHE_FONT_SIZE: 400,\n\n /**\n * contains the min text width to avoid getting 0\n * @type {Number}\n * @default\n */\n MIN_TEXT_WIDTH: 2,\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n * @return {fabric.Text} thisArg\n */\n initialize: function(text, options) {\n this.styles = options ? (options.styles || { }) : { };\n this.text = text;\n this.__skipDimension = true;\n this.callSuper('initialize', options);\n if (this.path) {\n this.setPathInfo();\n }\n this.__skipDimension = false;\n this.initDimensions();\n this.setCoords();\n this.setupState({ propertySet: '_dimensionAffectingProps' });\n },\n\n /**\n * If text has a path, it will add the extra information needed\n * for path and text calculations\n * @return {fabric.Text} thisArg\n */\n setPathInfo: function() {\n var path = this.path;\n if (path) {\n path.segmentsInfo = fabric.util.getPathSegmentsInfo(path.path);\n }\n },\n\n /**\n * Return a context for measurement of text string.\n * if created it gets stored for reuse\n * this is for internal use, please do not use it\n * @private\n * @param {String} text Text string\n * @param {Object} [options] Options object\n * @return {fabric.Text} thisArg\n */\n getMeasuringContext: function() {\n // if we did not return we have to measure something.\n if (!fabric._measuringContext) {\n fabric._measuringContext = this.canvas && this.canvas.contextCache ||\n fabric.util.createCanvasElement().getContext('2d');\n }\n return fabric._measuringContext;\n },\n\n /**\n * @private\n * Divides text into lines of text and lines of graphemes.\n */\n _splitText: function() {\n var newLines = this._splitTextIntoLines(this.text);\n this.textLines = newLines.lines;\n this._textLines = newLines.graphemeLines;\n this._unwrappedTextLines = newLines._unwrappedLines;\n this._text = newLines.graphemeText;\n return newLines;\n },\n\n /**\n * Initialize or update text dimensions.\n * Updates this.width and this.height with the proper values.\n * Does not return dimensions.\n */\n initDimensions: function() {\n if (this.__skipDimension) {\n return;\n }\n this._splitText();\n this._clearCache();\n if (this.path) {\n this.width = this.path.width;\n this.height = this.path.height;\n }\n else {\n this.width = this.calcTextWidth() || this.cursorWidth || this.MIN_TEXT_WIDTH;\n this.height = this.calcTextHeight();\n }\n if (this.textAlign.indexOf('justify') !== -1) {\n // once text is measured we need to make space fatter to make justified text.\n this.enlargeSpaces();\n }\n this.saveState({ propertySet: '_dimensionAffectingProps' });\n },\n\n /**\n * Enlarge space boxes and shift the others\n */\n enlargeSpaces: function() {\n var diffSpace, currentLineWidth, numberOfSpaces, accumulatedSpace, line, charBound, spaces;\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n if (this.textAlign !== 'justify' && (i === len - 1 || this.isEndOfWrapping(i))) {\n continue;\n }\n accumulatedSpace = 0;\n line = this._textLines[i];\n currentLineWidth = this.getLineWidth(i);\n if (currentLineWidth < this.width && (spaces = this.textLines[i].match(this._reSpacesAndTabs))) {\n numberOfSpaces = spaces.length;\n diffSpace = (this.width - currentLineWidth) / numberOfSpaces;\n for (var j = 0, jlen = line.length; j <= jlen; j++) {\n charBound = this.__charBounds[i][j];\n if (this._reSpaceAndTab.test(line[j])) {\n charBound.width += diffSpace;\n charBound.kernedWidth += diffSpace;\n charBound.left += accumulatedSpace;\n accumulatedSpace += diffSpace;\n }\n else {\n charBound.left += accumulatedSpace;\n }\n }\n }\n }\n },\n\n /**\n * Detect if the text line is ended with an hard break\n * text and itext do not have wrapping, return false\n * @return {Boolean}\n */\n isEndOfWrapping: function(lineIndex) {\n return lineIndex === this._textLines.length - 1;\n },\n\n /**\n * Detect if a line has a linebreak and so we need to account for it when moving\n * and counting style.\n * It return always for text and Itext.\n * @return Number\n */\n missingNewlineOffset: function() {\n return 1;\n },\n\n /**\n * Returns string representation of an instance\n * @return {String} String representation of text object\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Return the dimension and the zoom level needed to create a cache canvas\n * big enough to host the object to be cached.\n * @private\n * @param {Object} dim.x width of object to be cached\n * @param {Object} dim.y height of object to be cached\n * @return {Object}.width width of canvas\n * @return {Object}.height height of canvas\n * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\n * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\n */\n _getCacheCanvasDimensions: function() {\n var dims = this.callSuper('_getCacheCanvasDimensions');\n var fontSize = this.fontSize;\n dims.width += fontSize * dims.zoomX;\n dims.height += fontSize * dims.zoomY;\n return dims;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n var path = this.path;\n path && !path.isNotVisible() && path._render(ctx);\n this._setTextStyles(ctx);\n this._renderTextLinesBackground(ctx);\n this._renderTextDecoration(ctx, 'underline');\n this._renderText(ctx);\n this._renderTextDecoration(ctx, 'overline');\n this._renderTextDecoration(ctx, 'linethrough');\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderText: function(ctx) {\n if (this.paintFirst === 'stroke') {\n this._renderTextStroke(ctx);\n this._renderTextFill(ctx);\n }\n else {\n this._renderTextFill(ctx);\n this._renderTextStroke(ctx);\n }\n },\n\n /**\n * Set the font parameter of the context with the object properties or with charStyle\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Object} [charStyle] object with font style properties\n * @param {String} [charStyle.fontFamily] Font Family\n * @param {Number} [charStyle.fontSize] Font size in pixels. ( without px suffix )\n * @param {String} [charStyle.fontWeight] Font weight\n * @param {String} [charStyle.fontStyle] Font style (italic|normal)\n */\n _setTextStyles: function(ctx, charStyle, forMeasuring) {\n ctx.textBaseline = 'alphabetical';\n if (this.path) {\n switch (this.pathAlign) {\n case 'center':\n ctx.textBaseline = 'middle';\n break;\n case 'ascender':\n ctx.textBaseline = 'top';\n break;\n case 'descender':\n ctx.textBaseline = 'bottom';\n break;\n }\n }\n ctx.font = this._getFontDeclaration(charStyle, forMeasuring);\n },\n\n /**\n * calculate and return the text Width measuring each line.\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @return {Number} Maximum width of fabric.Text object\n */\n calcTextWidth: function() {\n var maxWidth = this.getLineWidth(0);\n\n for (var i = 1, len = this._textLines.length; i < len; i++) {\n var currentLineWidth = this.getLineWidth(i);\n if (currentLineWidth > maxWidth) {\n maxWidth = currentLineWidth;\n }\n }\n return maxWidth;\n },\n\n /**\n * @private\n * @param {String} method Method name (\"fillText\" or \"strokeText\")\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} line Text to render\n * @param {Number} left Left position of text\n * @param {Number} top Top position of text\n * @param {Number} lineIndex Index of a line in a text\n */\n _renderTextLine: function(method, ctx, line, left, top, lineIndex) {\n this._renderChars(method, ctx, line, left, top, lineIndex);\n },\n\n /**\n * Renders the text background for lines, taking care of style\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextLinesBackground: function(ctx) {\n if (!this.textBackgroundColor && !this.styleHas('textBackgroundColor')) {\n return;\n }\n var heightOfLine,\n lineLeftOffset, originalFill = ctx.fillStyle,\n line, lastColor,\n leftOffset = this._getLeftOffset(),\n lineTopOffset = this._getTopOffset(),\n boxStart = 0, boxWidth = 0, charBox, currentColor, path = this.path,\n drawStart;\n\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n heightOfLine = this.getHeightOfLine(i);\n if (!this.textBackgroundColor && !this.styleHas('textBackgroundColor', i)) {\n lineTopOffset += heightOfLine;\n continue;\n }\n line = this._textLines[i];\n lineLeftOffset = this._getLineLeftOffset(i);\n boxWidth = 0;\n boxStart = 0;\n lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\n for (var j = 0, jlen = line.length; j < jlen; j++) {\n charBox = this.__charBounds[i][j];\n currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\n if (path) {\n ctx.save();\n ctx.translate(charBox.renderLeft, charBox.renderTop);\n ctx.rotate(charBox.angle);\n ctx.fillStyle = currentColor;\n currentColor && ctx.fillRect(\n -charBox.width / 2,\n -heightOfLine / this.lineHeight * (1 - this._fontSizeFraction),\n charBox.width,\n heightOfLine / this.lineHeight\n );\n ctx.restore();\n }\n else if (currentColor !== lastColor) {\n drawStart = leftOffset + lineLeftOffset + boxStart;\n if (this.direction === 'rtl') {\n drawStart = this.width - drawStart - boxWidth;\n }\n ctx.fillStyle = lastColor;\n lastColor && ctx.fillRect(\n drawStart,\n lineTopOffset,\n boxWidth,\n heightOfLine / this.lineHeight\n );\n boxStart = charBox.left;\n boxWidth = charBox.width;\n lastColor = currentColor;\n }\n else {\n boxWidth += charBox.kernedWidth;\n }\n }\n if (currentColor && !path) {\n drawStart = leftOffset + lineLeftOffset + boxStart;\n if (this.direction === 'rtl') {\n drawStart = this.width - drawStart - boxWidth;\n }\n ctx.fillStyle = currentColor;\n ctx.fillRect(\n drawStart,\n lineTopOffset,\n boxWidth,\n heightOfLine / this.lineHeight\n );\n }\n lineTopOffset += heightOfLine;\n }\n ctx.fillStyle = originalFill;\n // if there is text background color no\n // other shadows should be casted\n this._removeShadow(ctx);\n },\n\n /**\n * @private\n * @param {Object} decl style declaration for cache\n * @param {String} decl.fontFamily fontFamily\n * @param {String} decl.fontStyle fontStyle\n * @param {String} decl.fontWeight fontWeight\n * @return {Object} reference to cache\n */\n getFontCache: function(decl) {\n var fontFamily = decl.fontFamily.toLowerCase();\n if (!fabric.charWidthsCache[fontFamily]) {\n fabric.charWidthsCache[fontFamily] = { };\n }\n var cache = fabric.charWidthsCache[fontFamily],\n cacheProp = decl.fontStyle.toLowerCase() + '_' + (decl.fontWeight + '').toLowerCase();\n if (!cache[cacheProp]) {\n cache[cacheProp] = { };\n }\n return cache[cacheProp];\n },\n\n /**\n * measure and return the width of a single character.\n * possibly overridden to accommodate different measure logic or\n * to hook some external lib for character measurement\n * @private\n * @param {String} _char, char to be measured\n * @param {Object} charStyle style of char to be measured\n * @param {String} [previousChar] previous char\n * @param {Object} [prevCharStyle] style of previous char\n */\n _measureChar: function(_char, charStyle, previousChar, prevCharStyle) {\n // first i try to return from cache\n var fontCache = this.getFontCache(charStyle), fontDeclaration = this._getFontDeclaration(charStyle),\n previousFontDeclaration = this._getFontDeclaration(prevCharStyle), couple = previousChar + _char,\n stylesAreEqual = fontDeclaration === previousFontDeclaration, width, coupleWidth, previousWidth,\n fontMultiplier = charStyle.fontSize / this.CACHE_FONT_SIZE, kernedWidth;\n\n if (previousChar && fontCache[previousChar] !== undefined) {\n previousWidth = fontCache[previousChar];\n }\n if (fontCache[_char] !== undefined) {\n kernedWidth = width = fontCache[_char];\n }\n if (stylesAreEqual && fontCache[couple] !== undefined) {\n coupleWidth = fontCache[couple];\n kernedWidth = coupleWidth - previousWidth;\n }\n if (width === undefined || previousWidth === undefined || coupleWidth === undefined) {\n var ctx = this.getMeasuringContext();\n // send a TRUE to specify measuring font size CACHE_FONT_SIZE\n this._setTextStyles(ctx, charStyle, true);\n }\n if (width === undefined) {\n kernedWidth = width = ctx.measureText(_char).width;\n fontCache[_char] = width;\n }\n if (previousWidth === undefined && stylesAreEqual && previousChar) {\n previousWidth = ctx.measureText(previousChar).width;\n fontCache[previousChar] = previousWidth;\n }\n if (stylesAreEqual && coupleWidth === undefined) {\n // we can measure the kerning couple and subtract the width of the previous character\n coupleWidth = ctx.measureText(couple).width;\n fontCache[couple] = coupleWidth;\n kernedWidth = coupleWidth - previousWidth;\n }\n return { width: width * fontMultiplier, kernedWidth: kernedWidth * fontMultiplier };\n },\n\n /**\n * Computes height of character at given position\n * @param {Number} line the line index number\n * @param {Number} _char the character index number\n * @return {Number} fontSize of the character\n */\n getHeightOfChar: function(line, _char) {\n return this.getValueOfPropertyAt(line, _char, 'fontSize');\n },\n\n /**\n * measure a text line measuring all characters.\n * @param {Number} lineIndex line number\n * @return {Number} Line width\n */\n measureLine: function(lineIndex) {\n var lineInfo = this._measureLine(lineIndex);\n if (this.charSpacing !== 0) {\n lineInfo.width -= this._getWidthOfCharSpacing();\n }\n if (lineInfo.width < 0) {\n lineInfo.width = 0;\n }\n return lineInfo;\n },\n\n /**\n * measure every grapheme of a line, populating __charBounds\n * @param {Number} lineIndex\n * @return {Object} object.width total width of characters\n * @return {Object} object.widthOfSpaces length of chars that match this._reSpacesAndTabs\n */\n _measureLine: function(lineIndex) {\n var width = 0, i, grapheme, line = this._textLines[lineIndex], prevGrapheme,\n graphemeInfo, numOfSpaces = 0, lineBounds = new Array(line.length),\n positionInPath = 0, startingPoint, totalPathLength, path = this.path,\n reverse = this.pathSide === 'right';\n\n this.__charBounds[lineIndex] = lineBounds;\n for (i = 0; i < line.length; i++) {\n grapheme = line[i];\n graphemeInfo = this._getGraphemeBox(grapheme, lineIndex, i, prevGrapheme);\n lineBounds[i] = graphemeInfo;\n width += graphemeInfo.kernedWidth;\n prevGrapheme = grapheme;\n }\n // this latest bound box represent the last character of the line\n // to simplify cursor handling in interactive mode.\n lineBounds[i] = {\n left: graphemeInfo ? graphemeInfo.left + graphemeInfo.width : 0,\n width: 0,\n kernedWidth: 0,\n height: this.fontSize\n };\n if (path) {\n totalPathLength = path.segmentsInfo[path.segmentsInfo.length - 1].length;\n startingPoint = fabric.util.getPointOnPath(path.path, 0, path.segmentsInfo);\n startingPoint.x += path.pathOffset.x;\n startingPoint.y += path.pathOffset.y;\n switch (this.textAlign) {\n case 'left':\n positionInPath = reverse ? (totalPathLength - width) : 0;\n break;\n case 'center':\n positionInPath = (totalPathLength - width) / 2;\n break;\n case 'right':\n positionInPath = reverse ? 0 : (totalPathLength - width);\n break;\n //todo - add support for justify\n }\n positionInPath += this.pathStartOffset * (reverse ? -1 : 1);\n for (i = reverse ? line.length - 1 : 0;\n reverse ? i >= 0 : i < line.length;\n reverse ? i-- : i++) {\n graphemeInfo = lineBounds[i];\n if (positionInPath > totalPathLength) {\n positionInPath %= totalPathLength;\n }\n else if (positionInPath < 0) {\n positionInPath += totalPathLength;\n }\n // it would probably much faster to send all the grapheme position for a line\n // and calculate path position/angle at once.\n this._setGraphemeOnPath(positionInPath, graphemeInfo, startingPoint);\n positionInPath += graphemeInfo.kernedWidth;\n }\n }\n return { width: width, numOfSpaces: numOfSpaces };\n },\n\n /**\n * Calculate the angle and the left,top position of the char that follow a path.\n * It appends it to graphemeInfo to be reused later at rendering\n * @private\n * @param {Number} positionInPath to be measured\n * @param {Object} graphemeInfo current grapheme box information\n * @param {Object} startingPoint position of the point\n */\n _setGraphemeOnPath: function(positionInPath, graphemeInfo, startingPoint) {\n var centerPosition = positionInPath + graphemeInfo.kernedWidth / 2,\n path = this.path;\n\n // we are at currentPositionOnPath. we want to know what point on the path is.\n var info = fabric.util.getPointOnPath(path.path, centerPosition, path.segmentsInfo);\n graphemeInfo.renderLeft = info.x - startingPoint.x;\n graphemeInfo.renderTop = info.y - startingPoint.y;\n graphemeInfo.angle = info.angle + (this.pathSide === 'right' ? Math.PI : 0);\n },\n\n /**\n * Measure and return the info of a single grapheme.\n * needs the the info of previous graphemes already filled\n * @private\n * @param {String} grapheme to be measured\n * @param {Number} lineIndex index of the line where the char is\n * @param {Number} charIndex position in the line\n * @param {String} [prevGrapheme] character preceding the one to be measured\n */\n _getGraphemeBox: function(grapheme, lineIndex, charIndex, prevGrapheme, skipLeft) {\n var style = this.getCompleteStyleDeclaration(lineIndex, charIndex),\n prevStyle = prevGrapheme ? this.getCompleteStyleDeclaration(lineIndex, charIndex - 1) : { },\n info = this._measureChar(grapheme, style, prevGrapheme, prevStyle),\n kernedWidth = info.kernedWidth,\n width = info.width, charSpacing;\n\n if (this.charSpacing !== 0) {\n charSpacing = this._getWidthOfCharSpacing();\n width += charSpacing;\n kernedWidth += charSpacing;\n }\n\n var box = {\n width: width,\n left: 0,\n height: style.fontSize,\n kernedWidth: kernedWidth,\n deltaY: style.deltaY,\n };\n if (charIndex > 0 && !skipLeft) {\n var previousBox = this.__charBounds[lineIndex][charIndex - 1];\n box.left = previousBox.left + previousBox.width + info.kernedWidth - info.width;\n }\n return box;\n },\n\n /**\n * Calculate height of line at 'lineIndex'\n * @param {Number} lineIndex index of line to calculate\n * @return {Number}\n */\n getHeightOfLine: function(lineIndex) {\n if (this.__lineHeights[lineIndex]) {\n return this.__lineHeights[lineIndex];\n }\n\n var line = this._textLines[lineIndex],\n // char 0 is measured before the line cycle because it nneds to char\n // emptylines\n maxHeight = this.getHeightOfChar(lineIndex, 0);\n for (var i = 1, len = line.length; i < len; i++) {\n maxHeight = Math.max(this.getHeightOfChar(lineIndex, i), maxHeight);\n }\n\n return this.__lineHeights[lineIndex] = maxHeight * this.lineHeight * this._fontSizeMult;\n },\n\n /**\n * Calculate text box height\n */\n calcTextHeight: function() {\n var lineHeight, height = 0;\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n lineHeight = this.getHeightOfLine(i);\n height += (i === len - 1 ? lineHeight / this.lineHeight : lineHeight);\n }\n return height;\n },\n\n /**\n * @private\n * @return {Number} Left offset\n */\n _getLeftOffset: function() {\n return this.direction === 'ltr' ? -this.width / 2 : this.width / 2;\n },\n\n /**\n * @private\n * @return {Number} Top offset\n */\n _getTopOffset: function() {\n return -this.height / 2;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} method Method name (\"fillText\" or \"strokeText\")\n */\n _renderTextCommon: function(ctx, method) {\n ctx.save();\n var lineHeights = 0, left = this._getLeftOffset(), top = this._getTopOffset();\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n var heightOfLine = this.getHeightOfLine(i),\n maxHeight = heightOfLine / this.lineHeight,\n leftOffset = this._getLineLeftOffset(i);\n this._renderTextLine(\n method,\n ctx,\n this._textLines[i],\n left + leftOffset,\n top + lineHeights + maxHeight,\n i\n );\n lineHeights += heightOfLine;\n }\n ctx.restore();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextFill: function(ctx) {\n if (!this.fill && !this.styleHas('fill')) {\n return;\n }\n\n this._renderTextCommon(ctx, 'fillText');\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextStroke: function(ctx) {\n if ((!this.stroke || this.strokeWidth === 0) && this.isEmptyStyles()) {\n return;\n }\n\n if (this.shadow && !this.shadow.affectStroke) {\n this._removeShadow(ctx);\n }\n\n ctx.save();\n this._setLineDash(ctx, this.strokeDashArray);\n ctx.beginPath();\n this._renderTextCommon(ctx, 'strokeText');\n ctx.closePath();\n ctx.restore();\n },\n\n /**\n * @private\n * @param {String} method fillText or strokeText.\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Array} line Content of the line, splitted in an array by grapheme\n * @param {Number} left\n * @param {Number} top\n * @param {Number} lineIndex\n */\n _renderChars: function(method, ctx, line, left, top, lineIndex) {\n // set proper line offset\n var lineHeight = this.getHeightOfLine(lineIndex),\n isJustify = this.textAlign.indexOf('justify') !== -1,\n actualStyle,\n nextStyle,\n charsToRender = '',\n charBox,\n boxWidth = 0,\n timeToRender,\n path = this.path,\n shortCut = !isJustify && this.charSpacing === 0 && this.isEmptyStyles(lineIndex) && !path,\n isLtr = this.direction === 'ltr', sign = this.direction === 'ltr' ? 1 : -1,\n drawingLeft, currentDirection = ctx.canvas.getAttribute('dir');\n ctx.save();\n if (currentDirection !== this.direction) {\n ctx.canvas.setAttribute('dir', isLtr ? 'ltr' : 'rtl');\n ctx.direction = isLtr ? 'ltr' : 'rtl';\n ctx.textAlign = isLtr ? 'left' : 'right';\n }\n top -= lineHeight * this._fontSizeFraction / this.lineHeight;\n if (shortCut) {\n // render all the line in one pass without checking\n // drawingLeft = isLtr ? left : left - this.getLineWidth(lineIndex);\n this._renderChar(method, ctx, lineIndex, 0, line.join(''), left, top, lineHeight);\n ctx.restore();\n return;\n }\n for (var i = 0, len = line.length - 1; i <= len; i++) {\n timeToRender = i === len || this.charSpacing || path;\n charsToRender += line[i];\n charBox = this.__charBounds[lineIndex][i];\n if (boxWidth === 0) {\n left += sign * (charBox.kernedWidth - charBox.width);\n boxWidth += charBox.width;\n }\n else {\n boxWidth += charBox.kernedWidth;\n }\n if (isJustify && !timeToRender) {\n if (this._reSpaceAndTab.test(line[i])) {\n timeToRender = true;\n }\n }\n if (!timeToRender) {\n // if we have charSpacing, we render char by char\n actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\n nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\n timeToRender = fabric.util.hasStyleChanged(actualStyle, nextStyle, false);\n }\n if (timeToRender) {\n if (path) {\n ctx.save();\n ctx.translate(charBox.renderLeft, charBox.renderTop);\n ctx.rotate(charBox.angle);\n this._renderChar(method, ctx, lineIndex, i, charsToRender, -boxWidth / 2, 0, lineHeight);\n ctx.restore();\n }\n else {\n drawingLeft = left;\n this._renderChar(method, ctx, lineIndex, i, charsToRender, drawingLeft, top, lineHeight);\n }\n charsToRender = '';\n actualStyle = nextStyle;\n left += sign * boxWidth;\n boxWidth = 0;\n }\n }\n ctx.restore();\n },\n\n /**\n * This function try to patch the missing gradientTransform on canvas gradients.\n * transforming a context to transform the gradient, is going to transform the stroke too.\n * we want to transform the gradient but not the stroke operation, so we create\n * a transformed gradient on a pattern and then we use the pattern instead of the gradient.\n * this method has drawbacks: is slow, is in low resolution, needs a patch for when the size\n * is limited.\n * @private\n * @param {fabric.Gradient} filler a fabric gradient instance\n * @return {CanvasPattern} a pattern to use as fill/stroke style\n */\n _applyPatternGradientTransformText: function(filler) {\n var pCanvas = fabric.util.createCanvasElement(), pCtx,\n // TODO: verify compatibility with strokeUniform\n width = this.width + this.strokeWidth, height = this.height + this.strokeWidth;\n pCanvas.width = width;\n pCanvas.height = height;\n pCtx = pCanvas.getContext('2d');\n pCtx.beginPath(); pCtx.moveTo(0, 0); pCtx.lineTo(width, 0); pCtx.lineTo(width, height);\n pCtx.lineTo(0, height); pCtx.closePath();\n pCtx.translate(width / 2, height / 2);\n pCtx.fillStyle = filler.toLive(pCtx);\n this._applyPatternGradientTransform(pCtx, filler);\n pCtx.fill();\n return pCtx.createPattern(pCanvas, 'no-repeat');\n },\n\n handleFiller: function(ctx, property, filler) {\n var offsetX, offsetY;\n if (filler.toLive) {\n if (filler.gradientUnits === 'percentage' || filler.gradientTransform || filler.patternTransform) {\n // need to transform gradient in a pattern.\n // this is a slow process. If you are hitting this codepath, and the object\n // is not using caching, you should consider switching it on.\n // we need a canvas as big as the current object caching canvas.\n offsetX = -this.width / 2;\n offsetY = -this.height / 2;\n ctx.translate(offsetX, offsetY);\n ctx[property] = this._applyPatternGradientTransformText(filler);\n return { offsetX: offsetX, offsetY: offsetY };\n }\n else {\n // is a simple gradient or pattern\n ctx[property] = filler.toLive(ctx, this);\n return this._applyPatternGradientTransform(ctx, filler);\n }\n }\n else {\n // is a color\n ctx[property] = filler;\n }\n return { offsetX: 0, offsetY: 0 };\n },\n\n _setStrokeStyles: function(ctx, decl) {\n ctx.lineWidth = decl.strokeWidth;\n ctx.lineCap = this.strokeLineCap;\n ctx.lineDashOffset = this.strokeDashOffset;\n ctx.lineJoin = this.strokeLineJoin;\n ctx.miterLimit = this.strokeMiterLimit;\n return this.handleFiller(ctx, 'strokeStyle', decl.stroke);\n },\n\n _setFillStyles: function(ctx, decl) {\n return this.handleFiller(ctx, 'fillStyle', decl.fill);\n },\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {String} _char\n * @param {Number} left Left coordinate\n * @param {Number} top Top coordinate\n * @param {Number} lineHeight Height of the line\n */\n _renderChar: function(method, ctx, lineIndex, charIndex, _char, left, top) {\n var decl = this._getStyleDeclaration(lineIndex, charIndex),\n fullDecl = this.getCompleteStyleDeclaration(lineIndex, charIndex),\n shouldFill = method === 'fillText' && fullDecl.fill,\n shouldStroke = method === 'strokeText' && fullDecl.stroke && fullDecl.strokeWidth,\n fillOffsets, strokeOffsets;\n\n if (!shouldStroke && !shouldFill) {\n return;\n }\n ctx.save();\n\n shouldFill && (fillOffsets = this._setFillStyles(ctx, fullDecl));\n shouldStroke && (strokeOffsets = this._setStrokeStyles(ctx, fullDecl));\n\n ctx.font = this._getFontDeclaration(fullDecl);\n\n\n if (decl && decl.textBackgroundColor) {\n this._removeShadow(ctx);\n }\n if (decl && decl.deltaY) {\n top += decl.deltaY;\n }\n shouldFill && ctx.fillText(_char, left - fillOffsets.offsetX, top - fillOffsets.offsetY);\n shouldStroke && ctx.strokeText(_char, left - strokeOffsets.offsetX, top - strokeOffsets.offsetY);\n ctx.restore();\n },\n\n /**\n * Turns the character into a 'superior figure' (i.e. 'superscript')\n * @param {Number} start selection start\n * @param {Number} end selection end\n * @returns {fabric.Text} thisArg\n * @chainable\n */\n setSuperscript: function(start, end) {\n return this._setScript(start, end, this.superscript);\n },\n\n /**\n * Turns the character into an 'inferior figure' (i.e. 'subscript')\n * @param {Number} start selection start\n * @param {Number} end selection end\n * @returns {fabric.Text} thisArg\n * @chainable\n */\n setSubscript: function(start, end) {\n return this._setScript(start, end, this.subscript);\n },\n\n /**\n * Applies 'schema' at given position\n * @private\n * @param {Number} start selection start\n * @param {Number} end selection end\n * @param {Number} schema\n * @returns {fabric.Text} thisArg\n * @chainable\n */\n _setScript: function(start, end, schema) {\n var loc = this.get2DCursorLocation(start, true),\n fontSize = this.getValueOfPropertyAt(loc.lineIndex, loc.charIndex, 'fontSize'),\n dy = this.getValueOfPropertyAt(loc.lineIndex, loc.charIndex, 'deltaY'),\n style = { fontSize: fontSize * schema.size, deltaY: dy + fontSize * schema.baseline };\n this.setSelectionStyles(style, start, end);\n return this;\n },\n\n /**\n * @private\n * @param {Number} lineIndex index text line\n * @return {Number} Line left offset\n */\n _getLineLeftOffset: function(lineIndex) {\n var lineWidth = this.getLineWidth(lineIndex),\n lineDiff = this.width - lineWidth, textAlign = this.textAlign, direction = this.direction,\n isEndOfWrapping, leftOffset = 0, isEndOfWrapping = this.isEndOfWrapping(lineIndex);\n if (textAlign === 'justify'\n || (textAlign === 'justify-center' && !isEndOfWrapping)\n || (textAlign === 'justify-right' && !isEndOfWrapping)\n || (textAlign === 'justify-left' && !isEndOfWrapping)\n ) {\n return 0;\n }\n if (textAlign === 'center') {\n leftOffset = lineDiff / 2;\n }\n if (textAlign === 'right') {\n leftOffset = lineDiff;\n }\n if (textAlign === 'justify-center') {\n leftOffset = lineDiff / 2;\n }\n if (textAlign === 'justify-right') {\n leftOffset = lineDiff;\n }\n if (direction === 'rtl') {\n leftOffset -= lineDiff;\n }\n return leftOffset;\n },\n\n /**\n * @private\n */\n _clearCache: function() {\n this.__lineWidths = [];\n this.__lineHeights = [];\n this.__charBounds = [];\n },\n\n /**\n * @private\n */\n _shouldClearDimensionCache: function() {\n var shouldClear = this._forceClearCache;\n shouldClear || (shouldClear = this.hasStateChanged('_dimensionAffectingProps'));\n if (shouldClear) {\n this.dirty = true;\n this._forceClearCache = false;\n }\n return shouldClear;\n },\n\n /**\n * Measure a single line given its index. Used to calculate the initial\n * text bounding box. The values are calculated and stored in __lineWidths cache.\n * @private\n * @param {Number} lineIndex line number\n * @return {Number} Line width\n */\n getLineWidth: function(lineIndex) {\n if (this.__lineWidths[lineIndex] !== undefined) {\n return this.__lineWidths[lineIndex];\n }\n\n var lineInfo = this.measureLine(lineIndex);\n var width = lineInfo.width;\n this.__lineWidths[lineIndex] = width;\n return width;\n },\n\n _getWidthOfCharSpacing: function() {\n if (this.charSpacing !== 0) {\n return this.fontSize * this.charSpacing / 1000;\n }\n return 0;\n },\n\n /**\n * Retrieves the value of property at given character position\n * @param {Number} lineIndex the line number\n * @param {Number} charIndex the character number\n * @param {String} property the property name\n * @returns the value of 'property'\n */\n getValueOfPropertyAt: function(lineIndex, charIndex, property) {\n var charStyle = this._getStyleDeclaration(lineIndex, charIndex);\n if (charStyle && typeof charStyle[property] !== 'undefined') {\n return charStyle[property];\n }\n return this[property];\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextDecoration: function(ctx, type) {\n if (!this[type] && !this.styleHas(type)) {\n return;\n }\n ctx.save();\n // if type is overline or linethrough we shouldn't cast shadow\n if (type === 'overline' || type === 'linethrough') {\n this._removeShadow(ctx);\n }\n var heightOfLine, size, _size,\n lineLeftOffset, dy, _dy,\n line, lastDecoration,\n leftOffset = this._getLeftOffset(),\n topOffset = this._getTopOffset(), top,\n boxStart, boxWidth, charBox, currentDecoration,\n maxHeight, currentFill, lastFill, path = this.path,\n charSpacing = this._getWidthOfCharSpacing(),\n offsetY = this.offsets[type];\n\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n heightOfLine = this.getHeightOfLine(i);\n if (!this[type] && !this.styleHas(type, i)) {\n topOffset += heightOfLine;\n continue;\n }\n line = this._textLines[i];\n maxHeight = heightOfLine / this.lineHeight;\n lineLeftOffset = this._getLineLeftOffset(i);\n boxStart = 0;\n boxWidth = 0;\n lastDecoration = this.getValueOfPropertyAt(i, 0, type);\n lastFill = this.getValueOfPropertyAt(i, 0, 'fill');\n top = topOffset + maxHeight * (1 - this._fontSizeFraction);\n size = this.getHeightOfChar(i, 0);\n dy = this.getValueOfPropertyAt(i, 0, 'deltaY');\n for (var j = 0, jlen = line.length; j < jlen; j++) {\n charBox = this.__charBounds[i][j];\n currentDecoration = this.getValueOfPropertyAt(i, j, type);\n currentFill = this.getValueOfPropertyAt(i, j, 'fill');\n _size = this.getHeightOfChar(i, j);\n _dy = this.getValueOfPropertyAt(i, j, 'deltaY');\n if (path && currentDecoration && currentFill) {\n ctx.save();\n ctx.fillStyle = lastFill;\n ctx.translate(charBox.renderLeft, charBox.renderTop);\n ctx.rotate(charBox.angle);\n ctx.fillRect(\n -charBox.kernedWidth / 2,\n offsetY * _size + _dy,\n charBox.kernedWidth,\n this.fontSize / 15\n );\n ctx.restore();\n }\n else if (\n (currentDecoration !== lastDecoration || currentFill !== lastFill || _size !== size || _dy !== dy)\n && boxWidth > 0\n ) {\n var drawStart = leftOffset + lineLeftOffset + boxStart;\n if (this.direction === 'rtl') {\n drawStart = this.width - drawStart - boxWidth;\n }\n if (lastDecoration && lastFill) {\n ctx.fillStyle = lastFill;\n ctx.fillRect(\n drawStart,\n top + offsetY * size + dy,\n boxWidth,\n this.fontSize / 15\n );\n }\n boxStart = charBox.left;\n boxWidth = charBox.width;\n lastDecoration = currentDecoration;\n lastFill = currentFill;\n size = _size;\n dy = _dy;\n }\n else {\n boxWidth += charBox.kernedWidth;\n }\n }\n var drawStart = leftOffset + lineLeftOffset + boxStart;\n if (this.direction === 'rtl') {\n drawStart = this.width - drawStart - boxWidth;\n }\n ctx.fillStyle = currentFill;\n currentDecoration && currentFill && ctx.fillRect(\n drawStart,\n top + offsetY * size + dy,\n boxWidth - charSpacing,\n this.fontSize / 15\n );\n topOffset += heightOfLine;\n }\n ctx.restore();\n },\n\n /**\n * return font declaration string for canvas context\n * @param {Object} [styleObject] object\n * @returns {String} font declaration formatted for canvas context.\n */\n _getFontDeclaration: function(styleObject, forMeasuring) {\n var style = styleObject || this, family = this.fontFamily,\n fontIsGeneric = fabric.Text.genericFonts.indexOf(family.toLowerCase()) > -1;\n var fontFamily = family === undefined ||\n family.indexOf('\\'') > -1 || family.indexOf(',') > -1 ||\n family.indexOf('\"') > -1 || fontIsGeneric\n ? style.fontFamily : '\"' + style.fontFamily + '\"';\n return [\n // node-canvas needs \"weight style\", while browsers need \"style weight\"\n // verify if this can be fixed in JSDOM\n (fabric.isLikelyNode ? style.fontWeight : style.fontStyle),\n (fabric.isLikelyNode ? style.fontStyle : style.fontWeight),\n forMeasuring ? this.CACHE_FONT_SIZE + 'px' : style.fontSize + 'px',\n fontFamily\n ].join(' ');\n },\n\n /**\n * Renders text instance on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n render: function(ctx) {\n // do not render if object is not visible\n if (!this.visible) {\n return;\n }\n if (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) {\n return;\n }\n if (this._shouldClearDimensionCache()) {\n this.initDimensions();\n }\n this.callSuper('render', ctx);\n },\n\n /**\n * Returns the text as an array of lines.\n * @param {String} text text to split\n * @returns {Array} Lines in the text\n */\n _splitTextIntoLines: function(text) {\n var lines = text.split(this._reNewline),\n newLines = new Array(lines.length),\n newLine = ['\\n'],\n newText = [];\n for (var i = 0; i < lines.length; i++) {\n newLines[i] = fabric.util.string.graphemeSplit(lines[i]);\n newText = newText.concat(newLines[i], newLine);\n }\n newText.pop();\n return { _unwrappedLines: newLines, lines: lines, graphemeText: newText, graphemeLines: newLines };\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n var allProperties = additionalProps.concat(propertiesToInclude);\n var obj = this.callSuper('toObject', allProperties);\n obj.styles = fabric.util.stylesToArray(this.styles, this.text);\n if (obj.path) {\n obj.path = this.path.toObject();\n }\n return obj;\n },\n\n /**\n * Sets property to a given value. When changing position/dimension -related properties (left, top, scale, angle, etc.) `set` does not update position of object's borders/controls. If you need to update those, call `setCoords()`.\n * @param {String|Object} key Property name or object (if object, iterate over the object properties)\n * @param {Object|Function} value Property value (if function, the value is passed into it and its return value is used as a new one)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n set: function(key, value) {\n this.callSuper('set', key, value);\n var needsDims = false;\n var isAddingPath = false;\n if (typeof key === 'object') {\n for (var _key in key) {\n if (_key === 'path') {\n this.setPathInfo();\n }\n needsDims = needsDims || this._dimensionAffectingProps.indexOf(_key) !== -1;\n isAddingPath = isAddingPath || _key === 'path';\n }\n }\n else {\n needsDims = this._dimensionAffectingProps.indexOf(key) !== -1;\n isAddingPath = key === 'path';\n }\n if (isAddingPath) {\n this.setPathInfo();\n }\n if (needsDims) {\n this.initDimensions();\n this.setCoords();\n }\n return this;\n },\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity\n */\n complexity: function() {\n return 1;\n }\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Text.fromElement})\n * @static\n * @memberOf fabric.Text\n * @see: http://www.w3.org/TR/SVG/text.html#TextElement\n */\n fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(\n 'x y dx dy font-family font-style font-weight font-size letter-spacing text-decoration text-anchor'.split(' '));\n\n /**\n * Default SVG font size\n * @static\n * @memberOf fabric.Text\n */\n fabric.Text.DEFAULT_SVG_FONT_SIZE = 16;\n\n /**\n * Returns fabric.Text instance from an SVG element (not yet implemented)\n * @static\n * @memberOf fabric.Text\n * @param {SVGElement} element Element to parse\n * @param {Function} callback callback function invoked after parsing\n * @param {Object} [options] Options object\n */\n fabric.Text.fromElement = function(element, callback, options) {\n if (!element) {\n return callback(null);\n }\n\n var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES),\n parsedAnchor = parsedAttributes.textAnchor || 'left';\n options = fabric.util.object.extend((options ? clone(options) : { }), parsedAttributes);\n\n options.top = options.top || 0;\n options.left = options.left || 0;\n if (parsedAttributes.textDecoration) {\n var textDecoration = parsedAttributes.textDecoration;\n if (textDecoration.indexOf('underline') !== -1) {\n options.underline = true;\n }\n if (textDecoration.indexOf('overline') !== -1) {\n options.overline = true;\n }\n if (textDecoration.indexOf('line-through') !== -1) {\n options.linethrough = true;\n }\n delete options.textDecoration;\n }\n if ('dx' in parsedAttributes) {\n options.left += parsedAttributes.dx;\n }\n if ('dy' in parsedAttributes) {\n options.top += parsedAttributes.dy;\n }\n if (!('fontSize' in options)) {\n options.fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;\n }\n\n var textContent = '';\n\n // The XML is not properly parsed in IE9 so a workaround to get\n // textContent is through firstChild.data. Another workaround would be\n // to convert XML loaded from a file to be converted using DOMParser (same way loadSVGFromString() does)\n if (!('textContent' in element)) {\n if ('firstChild' in element && element.firstChild !== null) {\n if ('data' in element.firstChild && element.firstChild.data !== null) {\n textContent = element.firstChild.data;\n }\n }\n }\n else {\n textContent = element.textContent;\n }\n\n textContent = textContent.replace(/^\\s+|\\s+$|\\n+/g, '').replace(/\\s+/g, ' ');\n var originalStrokeWidth = options.strokeWidth;\n options.strokeWidth = 0;\n\n var text = new fabric.Text(textContent, options),\n textHeightScaleFactor = text.getScaledHeight() / text.height,\n lineHeightDiff = (text.height + text.strokeWidth) * text.lineHeight - text.height,\n scaledDiff = lineHeightDiff * textHeightScaleFactor,\n textHeight = text.getScaledHeight() + scaledDiff,\n offX = 0;\n /*\n Adjust positioning:\n x/y attributes in SVG correspond to the bottom-left corner of text bounding box\n fabric output by default at top, left.\n */\n if (parsedAnchor === 'center') {\n offX = text.getScaledWidth() / 2;\n }\n if (parsedAnchor === 'right') {\n offX = text.getScaledWidth();\n }\n text.set({\n left: text.left - offX,\n top: text.top - (textHeight - text.fontSize * (0.07 + text._fontSizeFraction)) / text.lineHeight,\n strokeWidth: typeof originalStrokeWidth !== 'undefined' ? originalStrokeWidth : 1,\n });\n callback(text);\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Returns fabric.Text instance from an object representation\n * @static\n * @memberOf fabric.Text\n * @param {Object} object plain js Object to create an instance from\n * @param {Function} [callback] Callback to invoke when an fabric.Text instance is created\n */\n fabric.Text.fromObject = function(object, callback) {\n var objectCopy = clone(object), path = object.path;\n delete objectCopy.path;\n return fabric.Object._fromObject('Text', objectCopy, function(textInstance) {\n textInstance.styles = fabric.util.stylesFromArray(object.styles, object.text);\n if (path) {\n fabric.Object._fromObject('Path', path, function(pathInstance) {\n textInstance.set('path', pathInstance);\n callback(textInstance);\n }, 'path');\n }\n else {\n callback(textInstance);\n }\n }, 'text');\n };\n\n fabric.Text.genericFonts = ['sans-serif', 'serif', 'cursive', 'fantasy', 'monospace'];\n\n fabric.util.createAccessors && fabric.util.createAccessors(fabric.Text);\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n fabric.util.object.extend(fabric.Text.prototype, /** @lends fabric.Text.prototype */ {\n /**\n * Returns true if object has no styling or no styling in a line\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\n * @return {Boolean}\n */\n isEmptyStyles: function(lineIndex) {\n if (!this.styles) {\n return true;\n }\n if (typeof lineIndex !== 'undefined' && !this.styles[lineIndex]) {\n return true;\n }\n var obj = typeof lineIndex === 'undefined' ? this.styles : { line: this.styles[lineIndex] };\n for (var p1 in obj) {\n for (var p2 in obj[p1]) {\n // eslint-disable-next-line no-unused-vars\n for (var p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n return true;\n },\n\n /**\n * Returns true if object has a style property or has it ina specified line\n * This function is used to detect if a text will use a particular property or not.\n * @param {String} property to check for\n * @param {Number} lineIndex to check the style on\n * @return {Boolean}\n */\n styleHas: function(property, lineIndex) {\n if (!this.styles || !property || property === '') {\n return false;\n }\n if (typeof lineIndex !== 'undefined' && !this.styles[lineIndex]) {\n return false;\n }\n var obj = typeof lineIndex === 'undefined' ? this.styles : { 0: this.styles[lineIndex] };\n // eslint-disable-next-line\n for (var p1 in obj) {\n // eslint-disable-next-line\n for (var p2 in obj[p1]) {\n if (typeof obj[p1][p2][property] !== 'undefined') {\n return true;\n }\n }\n }\n return false;\n },\n\n /**\n * Check if characters in a text have a value for a property\n * whose value matches the textbox's value for that property. If so,\n * the character-level property is deleted. If the character\n * has no other properties, then it is also deleted. Finally,\n * if the line containing that character has no other characters\n * then it also is deleted.\n *\n * @param {string} property The property to compare between characters and text.\n */\n cleanStyle: function(property) {\n if (!this.styles || !property || property === '') {\n return false;\n }\n var obj = this.styles, stylesCount = 0, letterCount, stylePropertyValue,\n allStyleObjectPropertiesMatch = true, graphemeCount = 0, styleObject;\n // eslint-disable-next-line\n for (var p1 in obj) {\n letterCount = 0;\n // eslint-disable-next-line\n for (var p2 in obj[p1]) {\n var styleObject = obj[p1][p2],\n stylePropertyHasBeenSet = styleObject.hasOwnProperty(property);\n\n stylesCount++;\n\n if (stylePropertyHasBeenSet) {\n if (!stylePropertyValue) {\n stylePropertyValue = styleObject[property];\n }\n else if (styleObject[property] !== stylePropertyValue) {\n allStyleObjectPropertiesMatch = false;\n }\n\n if (styleObject[property] === this[property]) {\n delete styleObject[property];\n }\n }\n else {\n allStyleObjectPropertiesMatch = false;\n }\n\n if (Object.keys(styleObject).length !== 0) {\n letterCount++;\n }\n else {\n delete obj[p1][p2];\n }\n }\n\n if (letterCount === 0) {\n delete obj[p1];\n }\n }\n // if every grapheme has the same style set then\n // delete those styles and set it on the parent\n for (var i = 0; i < this._textLines.length; i++) {\n graphemeCount += this._textLines[i].length;\n }\n if (allStyleObjectPropertiesMatch && stylesCount === graphemeCount) {\n this[property] = stylePropertyValue;\n this.removeStyle(property);\n }\n },\n\n /**\n * Remove a style property or properties from all individual character styles\n * in a text object. Deletes the character style object if it contains no other style\n * props. Deletes a line style object if it contains no other character styles.\n *\n * @param {String} props The property to remove from character styles.\n */\n removeStyle: function(property) {\n if (!this.styles || !property || property === '') {\n return;\n }\n var obj = this.styles, line, lineNum, charNum;\n for (lineNum in obj) {\n line = obj[lineNum];\n for (charNum in line) {\n delete line[charNum][property];\n if (Object.keys(line[charNum]).length === 0) {\n delete line[charNum];\n }\n }\n if (Object.keys(line).length === 0) {\n delete obj[lineNum];\n }\n }\n },\n\n /**\n * @private\n */\n _extendStyles: function(index, styles) {\n var loc = this.get2DCursorLocation(index);\n\n if (!this._getLineStyle(loc.lineIndex)) {\n this._setLineStyle(loc.lineIndex);\n }\n\n if (!this._getStyleDeclaration(loc.lineIndex, loc.charIndex)) {\n this._setStyleDeclaration(loc.lineIndex, loc.charIndex, {});\n }\n\n fabric.util.object.extend(this._getStyleDeclaration(loc.lineIndex, loc.charIndex), styles);\n },\n\n /**\n * Returns 2d representation (lineIndex and charIndex) of cursor (or selection start)\n * @param {Number} [selectionStart] Optional index. When not given, current selectionStart is used.\n * @param {Boolean} [skipWrapping] consider the location for unwrapped lines. useful to manage styles.\n */\n get2DCursorLocation: function(selectionStart, skipWrapping) {\n if (typeof selectionStart === 'undefined') {\n selectionStart = this.selectionStart;\n }\n var lines = skipWrapping ? this._unwrappedTextLines : this._textLines,\n len = lines.length;\n for (var i = 0; i < len; i++) {\n if (selectionStart <= lines[i].length) {\n return {\n lineIndex: i,\n charIndex: selectionStart\n };\n }\n selectionStart -= lines[i].length + this.missingNewlineOffset(i, skipWrapping);\n }\n return {\n lineIndex: i - 1,\n charIndex: lines[i - 1].length < selectionStart ? lines[i - 1].length : selectionStart\n };\n },\n\n /**\n * Gets style of a current selection/cursor (at the start position)\n * if startIndex or endIndex are not provided, selectionStart or selectionEnd will be used.\n * @param {Number} [startIndex] Start index to get styles at\n * @param {Number} [endIndex] End index to get styles at, if not specified selectionEnd or startIndex + 1\n * @param {Boolean} [complete] get full style or not\n * @return {Array} styles an array with one, zero or more Style objects\n */\n getSelectionStyles: function(startIndex, endIndex, complete) {\n if (typeof startIndex === 'undefined') {\n startIndex = this.selectionStart || 0;\n }\n if (typeof endIndex === 'undefined') {\n endIndex = this.selectionEnd || startIndex;\n }\n var styles = [];\n for (var i = startIndex; i < endIndex; i++) {\n styles.push(this.getStyleAtPosition(i, complete));\n }\n return styles;\n },\n\n /**\n * Gets style of a current selection/cursor position\n * @param {Number} position to get styles at\n * @param {Boolean} [complete] full style if true\n * @return {Object} style Style object at a specified index\n * @private\n */\n getStyleAtPosition: function(position, complete) {\n var loc = this.get2DCursorLocation(position),\n style = complete ? this.getCompleteStyleDeclaration(loc.lineIndex, loc.charIndex) :\n this._getStyleDeclaration(loc.lineIndex, loc.charIndex);\n return style || {};\n },\n\n /**\n * Sets style of a current selection, if no selection exist, do not set anything.\n * @param {Object} [styles] Styles object\n * @param {Number} [startIndex] Start index to get styles at\n * @param {Number} [endIndex] End index to get styles at, if not specified selectionEnd or startIndex + 1\n * @return {fabric.IText} thisArg\n * @chainable\n */\n setSelectionStyles: function(styles, startIndex, endIndex) {\n if (typeof startIndex === 'undefined') {\n startIndex = this.selectionStart || 0;\n }\n if (typeof endIndex === 'undefined') {\n endIndex = this.selectionEnd || startIndex;\n }\n for (var i = startIndex; i < endIndex; i++) {\n this._extendStyles(i, styles);\n }\n /* not included in _extendStyles to avoid clearing cache more than once */\n this._forceClearCache = true;\n return this;\n },\n\n /**\n * get the reference, not a clone, of the style object for a given character\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @return {Object} style object\n */\n _getStyleDeclaration: function(lineIndex, charIndex) {\n var lineStyle = this.styles && this.styles[lineIndex];\n if (!lineStyle) {\n return null;\n }\n return lineStyle[charIndex];\n },\n\n /**\n * return a new object that contains all the style property for a character\n * the object returned is newly created\n * @param {Number} lineIndex of the line where the character is\n * @param {Number} charIndex position of the character on the line\n * @return {Object} style object\n */\n getCompleteStyleDeclaration: function(lineIndex, charIndex) {\n var style = this._getStyleDeclaration(lineIndex, charIndex) || { },\n styleObject = { }, prop;\n for (var i = 0; i < this._styleProperties.length; i++) {\n prop = this._styleProperties[i];\n styleObject[prop] = typeof style[prop] === 'undefined' ? this[prop] : style[prop];\n }\n return styleObject;\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n _setStyleDeclaration: function(lineIndex, charIndex, style) {\n this.styles[lineIndex][charIndex] = style;\n },\n\n /**\n *\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n _deleteStyleDeclaration: function(lineIndex, charIndex) {\n delete this.styles[lineIndex][charIndex];\n },\n\n /**\n * @param {Number} lineIndex\n * @return {Boolean} if the line exists or not\n * @private\n */\n _getLineStyle: function(lineIndex) {\n return !!this.styles[lineIndex];\n },\n\n /**\n * Set the line style to an empty object so that is initialized\n * @param {Number} lineIndex\n * @private\n */\n _setLineStyle: function(lineIndex) {\n this.styles[lineIndex] = {};\n },\n\n /**\n * @param {Number} lineIndex\n * @private\n */\n _deleteLineStyle: function(lineIndex) {\n delete this.styles[lineIndex];\n }\n });\n})();\n\n\n(function() {\n\n function parseDecoration(object) {\n if (object.textDecoration) {\n object.textDecoration.indexOf('underline') > -1 && (object.underline = true);\n object.textDecoration.indexOf('line-through') > -1 && (object.linethrough = true);\n object.textDecoration.indexOf('overline') > -1 && (object.overline = true);\n delete object.textDecoration;\n }\n }\n\n /**\n * IText class (introduced in v1.4) Events are also fired with \"text:\"\n * prefix when observing canvas.\n * @class fabric.IText\n * @extends fabric.Text\n * @mixes fabric.Observable\n *\n * @fires changed\n * @fires selection:changed\n * @fires editing:entered\n * @fires editing:exited\n *\n * @return {fabric.IText} thisArg\n * @see {@link fabric.IText#initialize} for constructor definition\n *\n *

Supported key combinations:

\n *
\n   *   Move cursor:                    left, right, up, down\n   *   Select character:               shift + left, shift + right\n   *   Select text vertically:         shift + up, shift + down\n   *   Move cursor by word:            alt + left, alt + right\n   *   Select words:                   shift + alt + left, shift + alt + right\n   *   Move cursor to line start/end:  cmd + left, cmd + right or home, end\n   *   Select till start/end of line:  cmd + shift + left, cmd + shift + right or shift + home, shift + end\n   *   Jump to start/end of text:      cmd + up, cmd + down\n   *   Select till start/end of text:  cmd + shift + up, cmd + shift + down or shift + pgUp, shift + pgDown\n   *   Delete character:               backspace\n   *   Delete word:                    alt + backspace\n   *   Delete line:                    cmd + backspace\n   *   Forward delete:                 delete\n   *   Copy text:                      ctrl/cmd + c\n   *   Paste text:                     ctrl/cmd + v\n   *   Cut text:                       ctrl/cmd + x\n   *   Select entire text:             ctrl/cmd + a\n   *   Quit editing                    tab or esc\n   * 
\n *\n *

Supported mouse/touch combination

\n *
\n   *   Position cursor:                click/touch\n   *   Create selection:               click/touch & drag\n   *   Create selection:               click & shift + click\n   *   Select word:                    double click\n   *   Select line:                    triple click\n   * 
\n */\n fabric.IText = fabric.util.createClass(fabric.Text, fabric.Observable, /** @lends fabric.IText.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'i-text',\n\n /**\n * Index where text selection starts (or where cursor is when there is no selection)\n * @type Number\n * @default\n */\n selectionStart: 0,\n\n /**\n * Index where text selection ends\n * @type Number\n * @default\n */\n selectionEnd: 0,\n\n /**\n * Color of text selection\n * @type String\n * @default\n */\n selectionColor: 'rgba(17,119,255,0.3)',\n\n /**\n * Indicates whether text is in editing mode\n * @type Boolean\n * @default\n */\n isEditing: false,\n\n /**\n * Indicates whether a text can be edited\n * @type Boolean\n * @default\n */\n editable: true,\n\n /**\n * Border color of text object while it's in editing mode\n * @type String\n * @default\n */\n editingBorderColor: 'rgba(102,153,255,0.25)',\n\n /**\n * Width of cursor (in px)\n * @type Number\n * @default\n */\n cursorWidth: 2,\n\n /**\n * Color of text cursor color in editing mode.\n * if not set (default) will take color from the text.\n * if set to a color value that fabric can understand, it will\n * be used instead of the color of the text at the current position.\n * @type String\n * @default\n */\n cursorColor: '',\n\n /**\n * Delay between cursor blink (in ms)\n * @type Number\n * @default\n */\n cursorDelay: 1000,\n\n /**\n * Duration of cursor fadein (in ms)\n * @type Number\n * @default\n */\n cursorDuration: 600,\n\n /**\n * Indicates whether internal text char widths can be cached\n * @type Boolean\n * @default\n */\n caching: true,\n\n /**\n * DOM container to append the hiddenTextarea.\n * An alternative to attaching to the document.body.\n * Useful to reduce laggish redraw of the full document.body tree and\n * also with modals event capturing that won't let the textarea take focus.\n * @type HTMLElement\n * @default\n */\n hiddenTextareaContainer: null,\n\n /**\n * @private\n */\n _reSpace: /\\s|\\n/,\n\n /**\n * @private\n */\n _currentCursorOpacity: 0,\n\n /**\n * @private\n */\n _selectionDirection: null,\n\n /**\n * @private\n */\n _abortCursorAnimation: false,\n\n /**\n * @private\n */\n __widthOfSpace: [],\n\n /**\n * Helps determining when the text is in composition, so that the cursor\n * rendering is altered.\n */\n inCompositionMode: false,\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n * @return {fabric.IText} thisArg\n */\n initialize: function(text, options) {\n this.callSuper('initialize', text, options);\n this.initBehavior();\n },\n\n /**\n * Sets selection start (left boundary of a selection)\n * @param {Number} index Index to set selection start to\n */\n setSelectionStart: function(index) {\n index = Math.max(index, 0);\n this._updateAndFire('selectionStart', index);\n },\n\n /**\n * Sets selection end (right boundary of a selection)\n * @param {Number} index Index to set selection end to\n */\n setSelectionEnd: function(index) {\n index = Math.min(index, this.text.length);\n this._updateAndFire('selectionEnd', index);\n },\n\n /**\n * @private\n * @param {String} property 'selectionStart' or 'selectionEnd'\n * @param {Number} index new position of property\n */\n _updateAndFire: function(property, index) {\n if (this[property] !== index) {\n this._fireSelectionChanged();\n this[property] = index;\n }\n this._updateTextarea();\n },\n\n /**\n * Fires the even of selection changed\n * @private\n */\n _fireSelectionChanged: function() {\n this.fire('selection:changed');\n this.canvas && this.canvas.fire('text:selection:changed', { target: this });\n },\n\n /**\n * Initialize text dimensions. Render all text on given context\n * or on a offscreen canvas to get the text width with measureText.\n * Updates this.width and this.height with the proper values.\n * Does not return dimensions.\n * @private\n */\n initDimensions: function() {\n this.isEditing && this.initDelayedCursor();\n this.clearContextTop();\n this.callSuper('initDimensions');\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n render: function(ctx) {\n this.clearContextTop();\n this.callSuper('render', ctx);\n // clear the cursorOffsetCache, so we ensure to calculate once per renderCursor\n // the correct position but not at every cursor animation.\n this.cursorOffsetCache = { };\n this.renderCursorOrSelection();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n this.callSuper('_render', ctx);\n },\n\n /**\n * Prepare and clean the contextTop\n */\n clearContextTop: function(skipRestore) {\n if (!this.isEditing || !this.canvas || !this.canvas.contextTop) {\n return;\n }\n var ctx = this.canvas.contextTop, v = this.canvas.viewportTransform;\n ctx.save();\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n this.transform(ctx);\n this._clearTextArea(ctx);\n skipRestore || ctx.restore();\n },\n /**\n * Renders cursor or selection (depending on what exists)\n * it does on the contextTop. If contextTop is not available, do nothing.\n */\n renderCursorOrSelection: function() {\n if (!this.isEditing || !this.canvas || !this.canvas.contextTop) {\n return;\n }\n var boundaries = this._getCursorBoundaries(),\n ctx = this.canvas.contextTop;\n this.clearContextTop(true);\n if (this.selectionStart === this.selectionEnd) {\n this.renderCursor(boundaries, ctx);\n }\n else {\n this.renderSelection(boundaries, ctx);\n }\n ctx.restore();\n },\n\n _clearTextArea: function(ctx) {\n // we add 4 pixel, to be sure to do not leave any pixel out\n var width = this.width + 4, height = this.height + 4;\n ctx.clearRect(-width / 2, -height / 2, width, height);\n },\n\n /**\n * Returns cursor boundaries (left, top, leftOffset, topOffset)\n * @private\n * @param {Array} chars Array of characters\n * @param {String} typeOfBoundaries\n */\n _getCursorBoundaries: function(position) {\n\n // left/top are left/top of entire text box\n // leftOffset/topOffset are offset from that left/top point of a text box\n\n if (typeof position === 'undefined') {\n position = this.selectionStart;\n }\n\n var left = this._getLeftOffset(),\n top = this._getTopOffset(),\n offsets = this._getCursorBoundariesOffsets(position);\n return {\n left: left,\n top: top,\n leftOffset: offsets.left,\n topOffset: offsets.top\n };\n },\n\n /**\n * @private\n */\n _getCursorBoundariesOffsets: function(position) {\n if (this.cursorOffsetCache && 'top' in this.cursorOffsetCache) {\n return this.cursorOffsetCache;\n }\n var lineLeftOffset,\n lineIndex,\n charIndex,\n topOffset = 0,\n leftOffset = 0,\n boundaries,\n cursorPosition = this.get2DCursorLocation(position);\n charIndex = cursorPosition.charIndex;\n lineIndex = cursorPosition.lineIndex;\n for (var i = 0; i < lineIndex; i++) {\n topOffset += this.getHeightOfLine(i);\n }\n lineLeftOffset = this._getLineLeftOffset(lineIndex);\n var bound = this.__charBounds[lineIndex][charIndex];\n bound && (leftOffset = bound.left);\n if (this.charSpacing !== 0 && charIndex === this._textLines[lineIndex].length) {\n leftOffset -= this._getWidthOfCharSpacing();\n }\n boundaries = {\n top: topOffset,\n left: lineLeftOffset + (leftOffset > 0 ? leftOffset : 0),\n };\n if (this.direction === 'rtl') {\n boundaries.left *= -1;\n }\n this.cursorOffsetCache = boundaries;\n return this.cursorOffsetCache;\n },\n\n /**\n * Renders cursor\n * @param {Object} boundaries\n * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n */\n renderCursor: function(boundaries, ctx) {\n var cursorLocation = this.get2DCursorLocation(),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex > 0 ? cursorLocation.charIndex - 1 : 0,\n charHeight = this.getValueOfPropertyAt(lineIndex, charIndex, 'fontSize'),\n multiplier = this.scaleX * this.canvas.getZoom(),\n cursorWidth = this.cursorWidth / multiplier,\n topOffset = boundaries.topOffset,\n dy = this.getValueOfPropertyAt(lineIndex, charIndex, 'deltaY');\n topOffset += (1 - this._fontSizeFraction) * this.getHeightOfLine(lineIndex) / this.lineHeight\n - charHeight * (1 - this._fontSizeFraction);\n\n if (this.inCompositionMode) {\n this.renderSelection(boundaries, ctx);\n }\n ctx.fillStyle = this.cursorColor || this.getValueOfPropertyAt(lineIndex, charIndex, 'fill');\n ctx.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity;\n ctx.fillRect(\n boundaries.left + boundaries.leftOffset - cursorWidth / 2,\n topOffset + boundaries.top + dy,\n cursorWidth,\n charHeight);\n },\n\n /**\n * Renders text selection\n * @param {Object} boundaries Object with left/top/leftOffset/topOffset\n * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n */\n renderSelection: function(boundaries, ctx) {\n\n var selectionStart = this.inCompositionMode ? this.hiddenTextarea.selectionStart : this.selectionStart,\n selectionEnd = this.inCompositionMode ? this.hiddenTextarea.selectionEnd : this.selectionEnd,\n isJustify = this.textAlign.indexOf('justify') !== -1,\n start = this.get2DCursorLocation(selectionStart),\n end = this.get2DCursorLocation(selectionEnd),\n startLine = start.lineIndex,\n endLine = end.lineIndex,\n startChar = start.charIndex < 0 ? 0 : start.charIndex,\n endChar = end.charIndex < 0 ? 0 : end.charIndex;\n\n for (var i = startLine; i <= endLine; i++) {\n var lineOffset = this._getLineLeftOffset(i) || 0,\n lineHeight = this.getHeightOfLine(i),\n realLineHeight = 0, boxStart = 0, boxEnd = 0;\n\n if (i === startLine) {\n boxStart = this.__charBounds[startLine][startChar].left;\n }\n if (i >= startLine && i < endLine) {\n boxEnd = isJustify && !this.isEndOfWrapping(i) ? this.width : this.getLineWidth(i) || 5; // WTF is this 5?\n }\n else if (i === endLine) {\n if (endChar === 0) {\n boxEnd = this.__charBounds[endLine][endChar].left;\n }\n else {\n var charSpacing = this._getWidthOfCharSpacing();\n boxEnd = this.__charBounds[endLine][endChar - 1].left\n + this.__charBounds[endLine][endChar - 1].width - charSpacing;\n }\n }\n realLineHeight = lineHeight;\n if (this.lineHeight < 1 || (i === endLine && this.lineHeight > 1)) {\n lineHeight /= this.lineHeight;\n }\n var drawStart = boundaries.left + lineOffset + boxStart,\n drawWidth = boxEnd - boxStart,\n drawHeight = lineHeight, extraTop = 0;\n if (this.inCompositionMode) {\n ctx.fillStyle = this.compositionColor || 'black';\n drawHeight = 1;\n extraTop = lineHeight;\n }\n else {\n ctx.fillStyle = this.selectionColor;\n }\n if (this.direction === 'rtl') {\n drawStart = this.width - drawStart - drawWidth;\n }\n ctx.fillRect(\n drawStart,\n boundaries.top + boundaries.topOffset + extraTop,\n drawWidth,\n drawHeight);\n boundaries.topOffset += realLineHeight;\n }\n },\n\n /**\n * High level function to know the height of the cursor.\n * the currentChar is the one that precedes the cursor\n * Returns fontSize of char at the current cursor\n * Unused from the library, is for the end user\n * @return {Number} Character font size\n */\n getCurrentCharFontSize: function() {\n var cp = this._getCurrentCharIndex();\n return this.getValueOfPropertyAt(cp.l, cp.c, 'fontSize');\n },\n\n /**\n * High level function to know the color of the cursor.\n * the currentChar is the one that precedes the cursor\n * Returns color (fill) of char at the current cursor\n * if the text object has a pattern or gradient for filler, it will return that.\n * Unused by the library, is for the end user\n * @return {String | fabric.Gradient | fabric.Pattern} Character color (fill)\n */\n getCurrentCharColor: function() {\n var cp = this._getCurrentCharIndex();\n return this.getValueOfPropertyAt(cp.l, cp.c, 'fill');\n },\n\n /**\n * Returns the cursor position for the getCurrent.. functions\n * @private\n */\n _getCurrentCharIndex: function() {\n var cursorPosition = this.get2DCursorLocation(this.selectionStart, true),\n charIndex = cursorPosition.charIndex > 0 ? cursorPosition.charIndex - 1 : 0;\n return { l: cursorPosition.lineIndex, c: charIndex };\n }\n });\n\n /**\n * Returns fabric.IText instance from an object representation\n * @static\n * @memberOf fabric.IText\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] invoked with new instance as argument\n */\n fabric.IText.fromObject = function(object, callback) {\n var styles = fabric.util.stylesFromArray(object.styles, object.text);\n //copy object to prevent mutation\n var objCopy = Object.assign({}, object, { styles: styles });\n delete objCopy.path;\n parseDecoration(objCopy);\n if (objCopy.styles) {\n for (var i in objCopy.styles) {\n for (var j in objCopy.styles[i]) {\n parseDecoration(objCopy.styles[i][j]);\n }\n }\n }\n fabric.Object._fromObject('IText', objCopy, function(textInstance) {\n if (object.path) {\n fabric.Object._fromObject('Path', object.path, function(pathInstance) {\n textInstance.set('path', pathInstance);\n callback(textInstance);\n }, 'path');\n }\n else {\n callback(textInstance);\n }\n }, 'text');\n };\n})();\n\n\n(function() {\n\n var clone = fabric.util.object.clone;\n\n fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ {\n\n /**\n * Initializes all the interactive behavior of IText\n */\n initBehavior: function() {\n this.initAddedHandler();\n this.initRemovedHandler();\n this.initCursorSelectionHandlers();\n this.initDoubleClickSimulation();\n this.mouseMoveHandler = this.mouseMoveHandler.bind(this);\n },\n\n onDeselect: function() {\n this.isEditing && this.exitEditing();\n this.selected = false;\n },\n\n /**\n * Initializes \"added\" event handler\n */\n initAddedHandler: function() {\n var _this = this;\n this.on('added', function() {\n var canvas = _this.canvas;\n if (canvas) {\n if (!canvas._hasITextHandlers) {\n canvas._hasITextHandlers = true;\n _this._initCanvasHandlers(canvas);\n }\n canvas._iTextInstances = canvas._iTextInstances || [];\n canvas._iTextInstances.push(_this);\n }\n });\n },\n\n initRemovedHandler: function() {\n var _this = this;\n this.on('removed', function() {\n var canvas = _this.canvas;\n if (canvas) {\n canvas._iTextInstances = canvas._iTextInstances || [];\n fabric.util.removeFromArray(canvas._iTextInstances, _this);\n if (canvas._iTextInstances.length === 0) {\n canvas._hasITextHandlers = false;\n _this._removeCanvasHandlers(canvas);\n }\n }\n });\n },\n\n /**\n * register canvas event to manage exiting on other instances\n * @private\n */\n _initCanvasHandlers: function(canvas) {\n canvas._mouseUpITextHandler = function() {\n if (canvas._iTextInstances) {\n canvas._iTextInstances.forEach(function(obj) {\n obj.__isMousedown = false;\n });\n }\n };\n canvas.on('mouse:up', canvas._mouseUpITextHandler);\n },\n\n /**\n * remove canvas event to manage exiting on other instances\n * @private\n */\n _removeCanvasHandlers: function(canvas) {\n canvas.off('mouse:up', canvas._mouseUpITextHandler);\n },\n\n /**\n * @private\n */\n _tick: function() {\n this._currentTickState = this._animateCursor(this, 1, this.cursorDuration, '_onTickComplete');\n },\n\n /**\n * @private\n */\n _animateCursor: function(obj, targetOpacity, duration, completeMethod) {\n\n var tickState;\n\n tickState = {\n isAborted: false,\n abort: function() {\n this.isAborted = true;\n },\n };\n\n obj.animate('_currentCursorOpacity', targetOpacity, {\n duration: duration,\n onComplete: function() {\n if (!tickState.isAborted) {\n obj[completeMethod]();\n }\n },\n onChange: function() {\n // we do not want to animate a selection, only cursor\n if (obj.canvas && obj.selectionStart === obj.selectionEnd) {\n obj.renderCursorOrSelection();\n }\n },\n abort: function() {\n return tickState.isAborted;\n }\n });\n return tickState;\n },\n\n /**\n * @private\n */\n _onTickComplete: function() {\n\n var _this = this;\n\n if (this._cursorTimeout1) {\n clearTimeout(this._cursorTimeout1);\n }\n this._cursorTimeout1 = setTimeout(function() {\n _this._currentTickCompleteState = _this._animateCursor(_this, 0, this.cursorDuration / 2, '_tick');\n }, 100);\n },\n\n /**\n * Initializes delayed cursor\n */\n initDelayedCursor: function(restart) {\n var _this = this,\n delay = restart ? 0 : this.cursorDelay;\n\n this.abortCursorAnimation();\n this._currentCursorOpacity = 1;\n this._cursorTimeout2 = setTimeout(function() {\n _this._tick();\n }, delay);\n },\n\n /**\n * Aborts cursor animation and clears all timeouts\n */\n abortCursorAnimation: function() {\n var shouldClear = this._currentTickState || this._currentTickCompleteState,\n canvas = this.canvas;\n this._currentTickState && this._currentTickState.abort();\n this._currentTickCompleteState && this._currentTickCompleteState.abort();\n\n clearTimeout(this._cursorTimeout1);\n clearTimeout(this._cursorTimeout2);\n\n this._currentCursorOpacity = 0;\n // to clear just itext area we need to transform the context\n // it may not be worth it\n if (shouldClear && canvas) {\n canvas.clearContext(canvas.contextTop || canvas.contextContainer);\n }\n\n },\n\n /**\n * Selects entire text\n * @return {fabric.IText} thisArg\n * @chainable\n */\n selectAll: function() {\n this.selectionStart = 0;\n this.selectionEnd = this._text.length;\n this._fireSelectionChanged();\n this._updateTextarea();\n return this;\n },\n\n /**\n * Returns selected text\n * @return {String}\n */\n getSelectedText: function() {\n return this._text.slice(this.selectionStart, this.selectionEnd).join('');\n },\n\n /**\n * Find new selection index representing start of current word according to current selection index\n * @param {Number} startFrom Current selection index\n * @return {Number} New selection index\n */\n findWordBoundaryLeft: function(startFrom) {\n var offset = 0, index = startFrom - 1;\n\n // remove space before cursor first\n if (this._reSpace.test(this._text[index])) {\n while (this._reSpace.test(this._text[index])) {\n offset++;\n index--;\n }\n }\n while (/\\S/.test(this._text[index]) && index > -1) {\n offset++;\n index--;\n }\n\n return startFrom - offset;\n },\n\n /**\n * Find new selection index representing end of current word according to current selection index\n * @param {Number} startFrom Current selection index\n * @return {Number} New selection index\n */\n findWordBoundaryRight: function(startFrom) {\n var offset = 0, index = startFrom;\n\n // remove space after cursor first\n if (this._reSpace.test(this._text[index])) {\n while (this._reSpace.test(this._text[index])) {\n offset++;\n index++;\n }\n }\n while (/\\S/.test(this._text[index]) && index < this._text.length) {\n offset++;\n index++;\n }\n\n return startFrom + offset;\n },\n\n /**\n * Find new selection index representing start of current line according to current selection index\n * @param {Number} startFrom Current selection index\n * @return {Number} New selection index\n */\n findLineBoundaryLeft: function(startFrom) {\n var offset = 0, index = startFrom - 1;\n\n while (!/\\n/.test(this._text[index]) && index > -1) {\n offset++;\n index--;\n }\n\n return startFrom - offset;\n },\n\n /**\n * Find new selection index representing end of current line according to current selection index\n * @param {Number} startFrom Current selection index\n * @return {Number} New selection index\n */\n findLineBoundaryRight: function(startFrom) {\n var offset = 0, index = startFrom;\n\n while (!/\\n/.test(this._text[index]) && index < this._text.length) {\n offset++;\n index++;\n }\n\n return startFrom + offset;\n },\n\n /**\n * Finds index corresponding to beginning or end of a word\n * @param {Number} selectionStart Index of a character\n * @param {Number} direction 1 or -1\n * @return {Number} Index of the beginning or end of a word\n */\n searchWordBoundary: function(selectionStart, direction) {\n var text = this._text,\n index = this._reSpace.test(text[selectionStart]) ? selectionStart - 1 : selectionStart,\n _char = text[index],\n // wrong\n reNonWord = fabric.reNonWord;\n\n while (!reNonWord.test(_char) && index > 0 && index < text.length) {\n index += direction;\n _char = text[index];\n }\n if (reNonWord.test(_char)) {\n index += direction === 1 ? 0 : 1;\n }\n return index;\n },\n\n /**\n * Selects a word based on the index\n * @param {Number} selectionStart Index of a character\n */\n selectWord: function(selectionStart) {\n selectionStart = selectionStart || this.selectionStart;\n var newSelectionStart = this.searchWordBoundary(selectionStart, -1), /* search backwards */\n newSelectionEnd = this.searchWordBoundary(selectionStart, 1); /* search forward */\n\n this.selectionStart = newSelectionStart;\n this.selectionEnd = newSelectionEnd;\n this._fireSelectionChanged();\n this._updateTextarea();\n this.renderCursorOrSelection();\n },\n\n /**\n * Selects a line based on the index\n * @param {Number} selectionStart Index of a character\n * @return {fabric.IText} thisArg\n * @chainable\n */\n selectLine: function(selectionStart) {\n selectionStart = selectionStart || this.selectionStart;\n var newSelectionStart = this.findLineBoundaryLeft(selectionStart),\n newSelectionEnd = this.findLineBoundaryRight(selectionStart);\n\n this.selectionStart = newSelectionStart;\n this.selectionEnd = newSelectionEnd;\n this._fireSelectionChanged();\n this._updateTextarea();\n return this;\n },\n\n /**\n * Enters editing state\n * @return {fabric.IText} thisArg\n * @chainable\n */\n enterEditing: function(e) {\n if (this.isEditing || !this.editable) {\n return;\n }\n\n if (this.canvas) {\n this.canvas.calcOffset();\n this.exitEditingOnOthers(this.canvas);\n }\n\n this.isEditing = true;\n\n this.initHiddenTextarea(e);\n this.hiddenTextarea.focus();\n this.hiddenTextarea.value = this.text;\n this._updateTextarea();\n this._saveEditingProps();\n this._setEditingProps();\n this._textBeforeEdit = this.text;\n\n this._tick();\n this.fire('editing:entered');\n this._fireSelectionChanged();\n if (!this.canvas) {\n return this;\n }\n this.canvas.fire('text:editing:entered', { target: this });\n this.initMouseMoveHandler();\n this.canvas.requestRenderAll();\n return this;\n },\n\n exitEditingOnOthers: function(canvas) {\n if (canvas._iTextInstances) {\n canvas._iTextInstances.forEach(function(obj) {\n obj.selected = false;\n if (obj.isEditing) {\n obj.exitEditing();\n }\n });\n }\n },\n\n /**\n * Initializes \"mousemove\" event handler\n */\n initMouseMoveHandler: function() {\n this.canvas.on('mouse:move', this.mouseMoveHandler);\n },\n\n /**\n * @private\n */\n mouseMoveHandler: function(options) {\n if (!this.__isMousedown || !this.isEditing) {\n return;\n }\n\n // regain focus\n document.activeElement !== this.hiddenTextarea && this.hiddenTextarea.focus();\n\n var newSelectionStart = this.getSelectionStartFromPointer(options.e),\n currentStart = this.selectionStart,\n currentEnd = this.selectionEnd;\n if (\n (newSelectionStart !== this.__selectionStartOnMouseDown || currentStart === currentEnd)\n &&\n (currentStart === newSelectionStart || currentEnd === newSelectionStart)\n ) {\n return;\n }\n if (newSelectionStart > this.__selectionStartOnMouseDown) {\n this.selectionStart = this.__selectionStartOnMouseDown;\n this.selectionEnd = newSelectionStart;\n }\n else {\n this.selectionStart = newSelectionStart;\n this.selectionEnd = this.__selectionStartOnMouseDown;\n }\n if (this.selectionStart !== currentStart || this.selectionEnd !== currentEnd) {\n this.restartCursorIfNeeded();\n this._fireSelectionChanged();\n this._updateTextarea();\n this.renderCursorOrSelection();\n }\n },\n\n /**\n * @private\n */\n _setEditingProps: function() {\n this.hoverCursor = 'text';\n\n if (this.canvas) {\n this.canvas.defaultCursor = this.canvas.moveCursor = 'text';\n }\n\n this.borderColor = this.editingBorderColor;\n this.hasControls = this.selectable = false;\n this.lockMovementX = this.lockMovementY = true;\n },\n\n /**\n * convert from textarea to grapheme indexes\n */\n fromStringToGraphemeSelection: function(start, end, text) {\n var smallerTextStart = text.slice(0, start),\n graphemeStart = fabric.util.string.graphemeSplit(smallerTextStart).length;\n if (start === end) {\n return { selectionStart: graphemeStart, selectionEnd: graphemeStart };\n }\n var smallerTextEnd = text.slice(start, end),\n graphemeEnd = fabric.util.string.graphemeSplit(smallerTextEnd).length;\n return { selectionStart: graphemeStart, selectionEnd: graphemeStart + graphemeEnd };\n },\n\n /**\n * convert from fabric to textarea values\n */\n fromGraphemeToStringSelection: function(start, end, _text) {\n var smallerTextStart = _text.slice(0, start),\n graphemeStart = smallerTextStart.join('').length;\n if (start === end) {\n return { selectionStart: graphemeStart, selectionEnd: graphemeStart };\n }\n var smallerTextEnd = _text.slice(start, end),\n graphemeEnd = smallerTextEnd.join('').length;\n return { selectionStart: graphemeStart, selectionEnd: graphemeStart + graphemeEnd };\n },\n\n /**\n * @private\n */\n _updateTextarea: function() {\n this.cursorOffsetCache = { };\n if (!this.hiddenTextarea) {\n return;\n }\n if (!this.inCompositionMode) {\n var newSelection = this.fromGraphemeToStringSelection(this.selectionStart, this.selectionEnd, this._text);\n this.hiddenTextarea.selectionStart = newSelection.selectionStart;\n this.hiddenTextarea.selectionEnd = newSelection.selectionEnd;\n }\n this.updateTextareaPosition();\n },\n\n /**\n * @private\n */\n updateFromTextArea: function() {\n if (!this.hiddenTextarea) {\n return;\n }\n this.cursorOffsetCache = { };\n this.text = this.hiddenTextarea.value;\n if (this._shouldClearDimensionCache()) {\n this.initDimensions();\n this.setCoords();\n }\n var newSelection = this.fromStringToGraphemeSelection(\n this.hiddenTextarea.selectionStart, this.hiddenTextarea.selectionEnd, this.hiddenTextarea.value);\n this.selectionEnd = this.selectionStart = newSelection.selectionEnd;\n if (!this.inCompositionMode) {\n this.selectionStart = newSelection.selectionStart;\n }\n this.updateTextareaPosition();\n },\n\n /**\n * @private\n */\n updateTextareaPosition: function() {\n if (this.selectionStart === this.selectionEnd) {\n var style = this._calcTextareaPosition();\n this.hiddenTextarea.style.left = style.left;\n this.hiddenTextarea.style.top = style.top;\n }\n },\n\n /**\n * @private\n * @return {Object} style contains style for hiddenTextarea\n */\n _calcTextareaPosition: function() {\n if (!this.canvas) {\n return { x: 1, y: 1 };\n }\n var desiredPosition = this.inCompositionMode ? this.compositionStart : this.selectionStart,\n boundaries = this._getCursorBoundaries(desiredPosition),\n cursorLocation = this.get2DCursorLocation(desiredPosition),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex,\n charHeight = this.getValueOfPropertyAt(lineIndex, charIndex, 'fontSize') * this.lineHeight,\n leftOffset = boundaries.leftOffset,\n m = this.calcTransformMatrix(),\n p = {\n x: boundaries.left + leftOffset,\n y: boundaries.top + boundaries.topOffset + charHeight\n },\n retinaScaling = this.canvas.getRetinaScaling(),\n upperCanvas = this.canvas.upperCanvasEl,\n upperCanvasWidth = upperCanvas.width / retinaScaling,\n upperCanvasHeight = upperCanvas.height / retinaScaling,\n maxWidth = upperCanvasWidth - charHeight,\n maxHeight = upperCanvasHeight - charHeight,\n scaleX = upperCanvas.clientWidth / upperCanvasWidth,\n scaleY = upperCanvas.clientHeight / upperCanvasHeight;\n\n p = fabric.util.transformPoint(p, m);\n p = fabric.util.transformPoint(p, this.canvas.viewportTransform);\n p.x *= scaleX;\n p.y *= scaleY;\n if (p.x < 0) {\n p.x = 0;\n }\n if (p.x > maxWidth) {\n p.x = maxWidth;\n }\n if (p.y < 0) {\n p.y = 0;\n }\n if (p.y > maxHeight) {\n p.y = maxHeight;\n }\n\n // add canvas offset on document\n p.x += this.canvas._offset.left;\n p.y += this.canvas._offset.top;\n\n return { left: p.x + 'px', top: p.y + 'px', fontSize: charHeight + 'px', charHeight: charHeight };\n },\n\n /**\n * @private\n */\n _saveEditingProps: function() {\n this._savedProps = {\n hasControls: this.hasControls,\n borderColor: this.borderColor,\n lockMovementX: this.lockMovementX,\n lockMovementY: this.lockMovementY,\n hoverCursor: this.hoverCursor,\n selectable: this.selectable,\n defaultCursor: this.canvas && this.canvas.defaultCursor,\n moveCursor: this.canvas && this.canvas.moveCursor\n };\n },\n\n /**\n * @private\n */\n _restoreEditingProps: function() {\n if (!this._savedProps) {\n return;\n }\n\n this.hoverCursor = this._savedProps.hoverCursor;\n this.hasControls = this._savedProps.hasControls;\n this.borderColor = this._savedProps.borderColor;\n this.selectable = this._savedProps.selectable;\n this.lockMovementX = this._savedProps.lockMovementX;\n this.lockMovementY = this._savedProps.lockMovementY;\n\n if (this.canvas) {\n this.canvas.defaultCursor = this._savedProps.defaultCursor;\n this.canvas.moveCursor = this._savedProps.moveCursor;\n }\n },\n\n /**\n * Exits from editing state\n * @return {fabric.IText} thisArg\n * @chainable\n */\n exitEditing: function() {\n var isTextChanged = (this._textBeforeEdit !== this.text);\n var hiddenTextarea = this.hiddenTextarea;\n this.selected = false;\n this.isEditing = false;\n\n this.selectionEnd = this.selectionStart;\n\n if (hiddenTextarea) {\n hiddenTextarea.blur && hiddenTextarea.blur();\n hiddenTextarea.parentNode && hiddenTextarea.parentNode.removeChild(hiddenTextarea);\n }\n this.hiddenTextarea = null;\n this.abortCursorAnimation();\n this._restoreEditingProps();\n this._currentCursorOpacity = 0;\n if (this._shouldClearDimensionCache()) {\n this.initDimensions();\n this.setCoords();\n }\n this.fire('editing:exited');\n isTextChanged && this.fire('modified');\n if (this.canvas) {\n this.canvas.off('mouse:move', this.mouseMoveHandler);\n this.canvas.fire('text:editing:exited', { target: this });\n isTextChanged && this.canvas.fire('object:modified', { target: this });\n }\n return this;\n },\n\n /**\n * @private\n */\n _removeExtraneousStyles: function() {\n for (var prop in this.styles) {\n if (!this._textLines[prop]) {\n delete this.styles[prop];\n }\n }\n },\n\n /**\n * remove and reflow a style block from start to end.\n * @param {Number} start linear start position for removal (included in removal)\n * @param {Number} end linear end position for removal ( excluded from removal )\n */\n removeStyleFromTo: function(start, end) {\n var cursorStart = this.get2DCursorLocation(start, true),\n cursorEnd = this.get2DCursorLocation(end, true),\n lineStart = cursorStart.lineIndex,\n charStart = cursorStart.charIndex,\n lineEnd = cursorEnd.lineIndex,\n charEnd = cursorEnd.charIndex,\n i, styleObj;\n if (lineStart !== lineEnd) {\n // step1 remove the trailing of lineStart\n if (this.styles[lineStart]) {\n for (i = charStart; i < this._unwrappedTextLines[lineStart].length; i++) {\n delete this.styles[lineStart][i];\n }\n }\n // step2 move the trailing of lineEnd to lineStart if needed\n if (this.styles[lineEnd]) {\n for (i = charEnd; i < this._unwrappedTextLines[lineEnd].length; i++) {\n styleObj = this.styles[lineEnd][i];\n if (styleObj) {\n this.styles[lineStart] || (this.styles[lineStart] = { });\n this.styles[lineStart][charStart + i - charEnd] = styleObj;\n }\n }\n }\n // step3 detects lines will be completely removed.\n for (i = lineStart + 1; i <= lineEnd; i++) {\n delete this.styles[i];\n }\n // step4 shift remaining lines.\n this.shiftLineStyles(lineEnd, lineStart - lineEnd);\n }\n else {\n // remove and shift left on the same line\n if (this.styles[lineStart]) {\n styleObj = this.styles[lineStart];\n var diff = charEnd - charStart, numericChar, _char;\n for (i = charStart; i < charEnd; i++) {\n delete styleObj[i];\n }\n for (_char in this.styles[lineStart]) {\n numericChar = parseInt(_char, 10);\n if (numericChar >= charEnd) {\n styleObj[numericChar - diff] = styleObj[_char];\n delete styleObj[_char];\n }\n }\n }\n }\n },\n\n /**\n * Shifts line styles up or down\n * @param {Number} lineIndex Index of a line\n * @param {Number} offset Can any number?\n */\n shiftLineStyles: function(lineIndex, offset) {\n // shift all line styles by offset upward or downward\n // do not clone deep. we need new array, not new style objects\n var clonedStyles = clone(this.styles);\n for (var line in this.styles) {\n var numericLine = parseInt(line, 10);\n if (numericLine > lineIndex) {\n this.styles[numericLine + offset] = clonedStyles[numericLine];\n if (!clonedStyles[numericLine - offset]) {\n delete this.styles[numericLine];\n }\n }\n }\n },\n\n restartCursorIfNeeded: function() {\n if (!this._currentTickState || this._currentTickState.isAborted\n || !this._currentTickCompleteState || this._currentTickCompleteState.isAborted\n ) {\n this.initDelayedCursor();\n }\n },\n\n /**\n * Handle insertion of more consecutive style lines for when one or more\n * newlines gets added to the text. Since current style needs to be shifted\n * first we shift the current style of the number lines needed, then we add\n * new lines from the last to the first.\n * @param {Number} lineIndex Index of a line\n * @param {Number} charIndex Index of a char\n * @param {Number} qty number of lines to add\n * @param {Array} copiedStyle Array of objects styles\n */\n insertNewlineStyleObject: function(lineIndex, charIndex, qty, copiedStyle) {\n var currentCharStyle,\n newLineStyles = {},\n someStyleIsCarryingOver = false,\n originalLineLength = this._unwrappedTextLines[lineIndex].length,\n isEndOfLine = originalLineLength === charIndex;\n\n qty || (qty = 1);\n this.shiftLineStyles(lineIndex, qty);\n if (this.styles[lineIndex]) {\n currentCharStyle = this.styles[lineIndex][charIndex === 0 ? charIndex : charIndex - 1];\n }\n // we clone styles of all chars\n // after cursor onto the current line\n for (var index in this.styles[lineIndex]) {\n var numIndex = parseInt(index, 10);\n if (numIndex >= charIndex) {\n someStyleIsCarryingOver = true;\n newLineStyles[numIndex - charIndex] = this.styles[lineIndex][index];\n // remove lines from the previous line since they're on a new line now\n if (!(isEndOfLine && charIndex === 0)) {\n delete this.styles[lineIndex][index];\n }\n }\n }\n var styleCarriedOver = false;\n if (someStyleIsCarryingOver && !isEndOfLine) {\n // if is end of line, the extra style we copied\n // is probably not something we want\n this.styles[lineIndex + qty] = newLineStyles;\n styleCarriedOver = true;\n }\n if (styleCarriedOver || originalLineLength > charIndex) {\n // skip the last line of since we already prepared it\n // or contains text without style that we don't want to style\n // just because it changed lines\n qty--;\n }\n // for the all the lines or all the other lines\n // we clone current char style onto the next (otherwise empty) line\n while (qty > 0) {\n if (copiedStyle && copiedStyle[qty - 1]) {\n this.styles[lineIndex + qty] = { 0: clone(copiedStyle[qty - 1]) };\n }\n else if (currentCharStyle) {\n this.styles[lineIndex + qty] = { 0: clone(currentCharStyle) };\n }\n else {\n delete this.styles[lineIndex + qty];\n }\n qty--;\n }\n this._forceClearCache = true;\n },\n\n /**\n * Inserts style object for a given line/char index\n * @param {Number} lineIndex Index of a line\n * @param {Number} charIndex Index of a char\n * @param {Number} quantity number Style object to insert, if given\n * @param {Array} copiedStyle array of style objects\n */\n insertCharStyleObject: function(lineIndex, charIndex, quantity, copiedStyle) {\n if (!this.styles) {\n this.styles = {};\n }\n var currentLineStyles = this.styles[lineIndex],\n currentLineStylesCloned = currentLineStyles ? clone(currentLineStyles) : {};\n\n quantity || (quantity = 1);\n // shift all char styles by quantity forward\n // 0,1,2,3 -> (charIndex=2) -> 0,1,3,4 -> (insert 2) -> 0,1,2,3,4\n for (var index in currentLineStylesCloned) {\n var numericIndex = parseInt(index, 10);\n if (numericIndex >= charIndex) {\n currentLineStyles[numericIndex + quantity] = currentLineStylesCloned[numericIndex];\n // only delete the style if there was nothing moved there\n if (!currentLineStylesCloned[numericIndex - quantity]) {\n delete currentLineStyles[numericIndex];\n }\n }\n }\n this._forceClearCache = true;\n if (copiedStyle) {\n while (quantity--) {\n if (!Object.keys(copiedStyle[quantity]).length) {\n continue;\n }\n if (!this.styles[lineIndex]) {\n this.styles[lineIndex] = {};\n }\n this.styles[lineIndex][charIndex + quantity] = clone(copiedStyle[quantity]);\n }\n return;\n }\n if (!currentLineStyles) {\n return;\n }\n var newStyle = currentLineStyles[charIndex ? charIndex - 1 : 1];\n while (newStyle && quantity--) {\n this.styles[lineIndex][charIndex + quantity] = clone(newStyle);\n }\n },\n\n /**\n * Inserts style object(s)\n * @param {Array} insertedText Characters at the location where style is inserted\n * @param {Number} start cursor index for inserting style\n * @param {Array} [copiedStyle] array of style objects to insert.\n */\n insertNewStyleBlock: function(insertedText, start, copiedStyle) {\n var cursorLoc = this.get2DCursorLocation(start, true),\n addedLines = [0], linesLength = 0;\n // get an array of how many char per lines are being added.\n for (var i = 0; i < insertedText.length; i++) {\n if (insertedText[i] === '\\n') {\n linesLength++;\n addedLines[linesLength] = 0;\n }\n else {\n addedLines[linesLength]++;\n }\n }\n // for the first line copy the style from the current char position.\n if (addedLines[0] > 0) {\n this.insertCharStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addedLines[0], copiedStyle);\n copiedStyle = copiedStyle && copiedStyle.slice(addedLines[0] + 1);\n }\n linesLength && this.insertNewlineStyleObject(\n cursorLoc.lineIndex, cursorLoc.charIndex + addedLines[0], linesLength);\n for (var i = 1; i < linesLength; i++) {\n if (addedLines[i] > 0) {\n this.insertCharStyleObject(cursorLoc.lineIndex + i, 0, addedLines[i], copiedStyle);\n }\n else if (copiedStyle) {\n // this test is required in order to close #6841\n // when a pasted buffer begins with a newline then\n // this.styles[cursorLoc.lineIndex + i] and copiedStyle[0]\n // may be undefined for some reason\n if (this.styles[cursorLoc.lineIndex + i] && copiedStyle[0]) {\n this.styles[cursorLoc.lineIndex + i][0] = copiedStyle[0];\n }\n }\n copiedStyle = copiedStyle && copiedStyle.slice(addedLines[i] + 1);\n }\n // we use i outside the loop to get it like linesLength\n if (addedLines[i] > 0) {\n this.insertCharStyleObject(cursorLoc.lineIndex + i, 0, addedLines[i], copiedStyle);\n }\n },\n\n /**\n * Set the selectionStart and selectionEnd according to the new position of cursor\n * mimic the key - mouse navigation when shift is pressed.\n */\n setSelectionStartEndWithShift: function(start, end, newSelection) {\n if (newSelection <= start) {\n if (end === start) {\n this._selectionDirection = 'left';\n }\n else if (this._selectionDirection === 'right') {\n this._selectionDirection = 'left';\n this.selectionEnd = start;\n }\n this.selectionStart = newSelection;\n }\n else if (newSelection > start && newSelection < end) {\n if (this._selectionDirection === 'right') {\n this.selectionEnd = newSelection;\n }\n else {\n this.selectionStart = newSelection;\n }\n }\n else {\n // newSelection is > selection start and end\n if (end === start) {\n this._selectionDirection = 'right';\n }\n else if (this._selectionDirection === 'left') {\n this._selectionDirection = 'right';\n this.selectionStart = end;\n }\n this.selectionEnd = newSelection;\n }\n },\n\n setSelectionInBoundaries: function() {\n var length = this.text.length;\n if (this.selectionStart > length) {\n this.selectionStart = length;\n }\n else if (this.selectionStart < 0) {\n this.selectionStart = 0;\n }\n if (this.selectionEnd > length) {\n this.selectionEnd = length;\n }\n else if (this.selectionEnd < 0) {\n this.selectionEnd = 0;\n }\n }\n });\n})();\n\n\nfabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ {\n /**\n * Initializes \"dbclick\" event handler\n */\n initDoubleClickSimulation: function() {\n\n // for double click\n this.__lastClickTime = +new Date();\n\n // for triple click\n this.__lastLastClickTime = +new Date();\n\n this.__lastPointer = { };\n\n this.on('mousedown', this.onMouseDown);\n },\n\n /**\n * Default event handler to simulate triple click\n * @private\n */\n onMouseDown: function(options) {\n if (!this.canvas) {\n return;\n }\n this.__newClickTime = +new Date();\n var newPointer = options.pointer;\n if (this.isTripleClick(newPointer)) {\n this.fire('tripleclick', options);\n this._stopEvent(options.e);\n }\n this.__lastLastClickTime = this.__lastClickTime;\n this.__lastClickTime = this.__newClickTime;\n this.__lastPointer = newPointer;\n this.__lastIsEditing = this.isEditing;\n this.__lastSelected = this.selected;\n },\n\n isTripleClick: function(newPointer) {\n return this.__newClickTime - this.__lastClickTime < 500 &&\n this.__lastClickTime - this.__lastLastClickTime < 500 &&\n this.__lastPointer.x === newPointer.x &&\n this.__lastPointer.y === newPointer.y;\n },\n\n /**\n * @private\n */\n _stopEvent: function(e) {\n e.preventDefault && e.preventDefault();\n e.stopPropagation && e.stopPropagation();\n },\n\n /**\n * Initializes event handlers related to cursor or selection\n */\n initCursorSelectionHandlers: function() {\n this.initMousedownHandler();\n this.initMouseupHandler();\n this.initClicks();\n },\n\n /**\n * Default handler for double click, select a word\n */\n doubleClickHandler: function(options) {\n if (!this.isEditing) {\n return;\n }\n this.selectWord(this.getSelectionStartFromPointer(options.e));\n },\n\n /**\n * Default handler for triple click, select a line\n */\n tripleClickHandler: function(options) {\n if (!this.isEditing) {\n return;\n }\n this.selectLine(this.getSelectionStartFromPointer(options.e));\n },\n\n /**\n * Initializes double and triple click event handlers\n */\n initClicks: function() {\n this.on('mousedblclick', this.doubleClickHandler);\n this.on('tripleclick', this.tripleClickHandler);\n },\n\n /**\n * Default event handler for the basic functionalities needed on _mouseDown\n * can be overridden to do something different.\n * Scope of this implementation is: find the click position, set selectionStart\n * find selectionEnd, initialize the drawing of either cursor or selection area\n * initializing a mousedDown on a text area will cancel fabricjs knowledge of\n * current compositionMode. It will be set to false.\n */\n _mouseDownHandler: function(options) {\n if (!this.canvas || !this.editable || (options.e.button && options.e.button !== 1)) {\n return;\n }\n\n this.__isMousedown = true;\n\n if (this.selected) {\n this.inCompositionMode = false;\n this.setCursorByClick(options.e);\n }\n\n if (this.isEditing) {\n this.__selectionStartOnMouseDown = this.selectionStart;\n if (this.selectionStart === this.selectionEnd) {\n this.abortCursorAnimation();\n }\n this.renderCursorOrSelection();\n }\n },\n\n /**\n * Default event handler for the basic functionalities needed on mousedown:before\n * can be overridden to do something different.\n * Scope of this implementation is: verify the object is already selected when mousing down\n */\n _mouseDownHandlerBefore: function(options) {\n if (!this.canvas || !this.editable || (options.e.button && options.e.button !== 1)) {\n return;\n }\n // we want to avoid that an object that was selected and then becomes unselectable,\n // may trigger editing mode in some way.\n this.selected = this === this.canvas._activeObject;\n },\n\n /**\n * Initializes \"mousedown\" event handler\n */\n initMousedownHandler: function() {\n this.on('mousedown', this._mouseDownHandler);\n this.on('mousedown:before', this._mouseDownHandlerBefore);\n },\n\n /**\n * Initializes \"mouseup\" event handler\n */\n initMouseupHandler: function() {\n this.on('mouseup', this.mouseUpHandler);\n },\n\n /**\n * standard handler for mouse up, overridable\n * @private\n */\n mouseUpHandler: function(options) {\n this.__isMousedown = false;\n if (!this.editable || this.group ||\n (options.transform && options.transform.actionPerformed) ||\n (options.e.button && options.e.button !== 1)) {\n return;\n }\n\n if (this.canvas) {\n var currentActive = this.canvas._activeObject;\n if (currentActive && currentActive !== this) {\n // avoid running this logic when there is an active object\n // this because is possible with shift click and fast clicks,\n // to rapidly deselect and reselect this object and trigger an enterEdit\n return;\n }\n }\n\n if (this.__lastSelected && !this.__corner) {\n this.selected = false;\n this.__lastSelected = false;\n this.enterEditing(options.e);\n if (this.selectionStart === this.selectionEnd) {\n this.initDelayedCursor(true);\n }\n else {\n this.renderCursorOrSelection();\n }\n }\n else {\n this.selected = true;\n }\n },\n\n /**\n * Changes cursor location in a text depending on passed pointer (x/y) object\n * @param {Event} e Event object\n */\n setCursorByClick: function(e) {\n var newSelection = this.getSelectionStartFromPointer(e),\n start = this.selectionStart, end = this.selectionEnd;\n if (e.shiftKey) {\n this.setSelectionStartEndWithShift(start, end, newSelection);\n }\n else {\n this.selectionStart = newSelection;\n this.selectionEnd = newSelection;\n }\n if (this.isEditing) {\n this._fireSelectionChanged();\n this._updateTextarea();\n }\n },\n\n /**\n * Returns index of a character corresponding to where an object was clicked\n * @param {Event} e Event object\n * @return {Number} Index of a character\n */\n getSelectionStartFromPointer: function(e) {\n var mouseOffset = this.getLocalPointer(e),\n prevWidth = 0,\n width = 0,\n height = 0,\n charIndex = 0,\n lineIndex = 0,\n lineLeftOffset,\n line;\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n if (height <= mouseOffset.y) {\n height += this.getHeightOfLine(i) * this.scaleY;\n lineIndex = i;\n if (i > 0) {\n charIndex += this._textLines[i - 1].length + this.missingNewlineOffset(i - 1);\n }\n }\n else {\n break;\n }\n }\n lineLeftOffset = this._getLineLeftOffset(lineIndex);\n width = lineLeftOffset * this.scaleX;\n line = this._textLines[lineIndex];\n // handling of RTL: in order to get things work correctly,\n // we assume RTL writing is mirrored compared to LTR writing.\n // so in position detection we mirror the X offset, and when is time\n // of rendering it, we mirror it again.\n if (this.direction === 'rtl') {\n mouseOffset.x = this.width * this.scaleX - mouseOffset.x + width;\n }\n for (var j = 0, jlen = line.length; j < jlen; j++) {\n prevWidth = width;\n // i removed something about flipX here, check.\n width += this.__charBounds[lineIndex][j].kernedWidth * this.scaleX;\n if (width <= mouseOffset.x) {\n charIndex++;\n }\n else {\n break;\n }\n }\n return this._getNewSelectionStartFromOffset(mouseOffset, prevWidth, width, charIndex, jlen);\n },\n\n /**\n * @private\n */\n _getNewSelectionStartFromOffset: function(mouseOffset, prevWidth, width, index, jlen) {\n // we need Math.abs because when width is after the last char, the offset is given as 1, while is 0\n var distanceBtwLastCharAndCursor = mouseOffset.x - prevWidth,\n distanceBtwNextCharAndCursor = width - mouseOffset.x,\n offset = distanceBtwNextCharAndCursor > distanceBtwLastCharAndCursor ||\n distanceBtwNextCharAndCursor < 0 ? 0 : 1,\n newSelectionStart = index + offset;\n // if object is horizontally flipped, mirror cursor location from the end\n if (this.flipX) {\n newSelectionStart = jlen - newSelectionStart;\n }\n\n if (newSelectionStart > this._text.length) {\n newSelectionStart = this._text.length;\n }\n\n return newSelectionStart;\n }\n});\n\n\nfabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ {\n\n /**\n * Initializes hidden textarea (needed to bring up keyboard in iOS)\n */\n initHiddenTextarea: function() {\n this.hiddenTextarea = fabric.document.createElement('textarea');\n this.hiddenTextarea.setAttribute('autocapitalize', 'off');\n this.hiddenTextarea.setAttribute('autocorrect', 'off');\n this.hiddenTextarea.setAttribute('autocomplete', 'off');\n this.hiddenTextarea.setAttribute('spellcheck', 'false');\n this.hiddenTextarea.setAttribute('data-fabric-hiddentextarea', '');\n this.hiddenTextarea.setAttribute('wrap', 'off');\n var style = this._calcTextareaPosition();\n // line-height: 1px; was removed from the style to fix this:\n // https://bugs.chromium.org/p/chromium/issues/detail?id=870966\n this.hiddenTextarea.style.cssText = 'position: absolute; top: ' + style.top +\n '; left: ' + style.left + '; z-index: -999; opacity: 0; width: 1px; height: 1px; font-size: 1px;' +\n ' padding-top: ' + style.fontSize + ';';\n\n if (this.hiddenTextareaContainer) {\n this.hiddenTextareaContainer.appendChild(this.hiddenTextarea);\n }\n else {\n fabric.document.body.appendChild(this.hiddenTextarea);\n }\n\n fabric.util.addListener(this.hiddenTextarea, 'keydown', this.onKeyDown.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'keyup', this.onKeyUp.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'input', this.onInput.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'copy', this.copy.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'cut', this.copy.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'paste', this.paste.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'compositionstart', this.onCompositionStart.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'compositionupdate', this.onCompositionUpdate.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'compositionend', this.onCompositionEnd.bind(this));\n\n if (!this._clickHandlerInitialized && this.canvas) {\n fabric.util.addListener(this.canvas.upperCanvasEl, 'click', this.onClick.bind(this));\n this._clickHandlerInitialized = true;\n }\n },\n\n /**\n * For functionalities on keyDown\n * Map a special key to a function of the instance/prototype\n * If you need different behaviour for ESC or TAB or arrows, you have to change\n * this map setting the name of a function that you build on the fabric.Itext or\n * your prototype.\n * the map change will affect all Instances unless you need for only some text Instances\n * in that case you have to clone this object and assign your Instance.\n * this.keysMap = fabric.util.object.clone(this.keysMap);\n * The function must be in fabric.Itext.prototype.myFunction And will receive event as args[0]\n */\n keysMap: {\n 9: 'exitEditing',\n 27: 'exitEditing',\n 33: 'moveCursorUp',\n 34: 'moveCursorDown',\n 35: 'moveCursorRight',\n 36: 'moveCursorLeft',\n 37: 'moveCursorLeft',\n 38: 'moveCursorUp',\n 39: 'moveCursorRight',\n 40: 'moveCursorDown',\n },\n\n keysMapRtl: {\n 9: 'exitEditing',\n 27: 'exitEditing',\n 33: 'moveCursorUp',\n 34: 'moveCursorDown',\n 35: 'moveCursorLeft',\n 36: 'moveCursorRight',\n 37: 'moveCursorRight',\n 38: 'moveCursorUp',\n 39: 'moveCursorLeft',\n 40: 'moveCursorDown',\n },\n\n /**\n * For functionalities on keyUp + ctrl || cmd\n */\n ctrlKeysMapUp: {\n 67: 'copy',\n 88: 'cut'\n },\n\n /**\n * For functionalities on keyDown + ctrl || cmd\n */\n ctrlKeysMapDown: {\n 65: 'selectAll'\n },\n\n onClick: function() {\n // No need to trigger click event here, focus is enough to have the keyboard appear on Android\n this.hiddenTextarea && this.hiddenTextarea.focus();\n },\n\n /**\n * Handles keydown event\n * only used for arrows and combination of modifier keys.\n * @param {Event} e Event object\n */\n onKeyDown: function(e) {\n if (!this.isEditing) {\n return;\n }\n var keyMap = this.direction === 'rtl' ? this.keysMapRtl : this.keysMap;\n if (e.keyCode in keyMap) {\n this[keyMap[e.keyCode]](e);\n }\n else if ((e.keyCode in this.ctrlKeysMapDown) && (e.ctrlKey || e.metaKey)) {\n this[this.ctrlKeysMapDown[e.keyCode]](e);\n }\n else {\n return;\n }\n e.stopImmediatePropagation();\n e.preventDefault();\n if (e.keyCode >= 33 && e.keyCode <= 40) {\n // if i press an arrow key just update selection\n this.inCompositionMode = false;\n this.clearContextTop();\n this.renderCursorOrSelection();\n }\n else {\n this.canvas && this.canvas.requestRenderAll();\n }\n },\n\n /**\n * Handles keyup event\n * We handle KeyUp because ie11 and edge have difficulties copy/pasting\n * if a copy/cut event fired, keyup is dismissed\n * @param {Event} e Event object\n */\n onKeyUp: function(e) {\n if (!this.isEditing || this._copyDone || this.inCompositionMode) {\n this._copyDone = false;\n return;\n }\n if ((e.keyCode in this.ctrlKeysMapUp) && (e.ctrlKey || e.metaKey)) {\n this[this.ctrlKeysMapUp[e.keyCode]](e);\n }\n else {\n return;\n }\n e.stopImmediatePropagation();\n e.preventDefault();\n this.canvas && this.canvas.requestRenderAll();\n },\n\n /**\n * Handles onInput event\n * @param {Event} e Event object\n */\n onInput: function(e) {\n var fromPaste = this.fromPaste;\n this.fromPaste = false;\n e && e.stopPropagation();\n if (!this.isEditing) {\n return;\n }\n // decisions about style changes.\n var nextText = this._splitTextIntoLines(this.hiddenTextarea.value).graphemeText,\n charCount = this._text.length,\n nextCharCount = nextText.length,\n removedText, insertedText,\n charDiff = nextCharCount - charCount,\n selectionStart = this.selectionStart, selectionEnd = this.selectionEnd,\n selection = selectionStart !== selectionEnd,\n copiedStyle, removeFrom, removeTo;\n if (this.hiddenTextarea.value === '') {\n this.styles = { };\n this.updateFromTextArea();\n this.fire('changed');\n if (this.canvas) {\n this.canvas.fire('text:changed', { target: this });\n this.canvas.requestRenderAll();\n }\n return;\n }\n\n var textareaSelection = this.fromStringToGraphemeSelection(\n this.hiddenTextarea.selectionStart,\n this.hiddenTextarea.selectionEnd,\n this.hiddenTextarea.value\n );\n var backDelete = selectionStart > textareaSelection.selectionStart;\n\n if (selection) {\n removedText = this._text.slice(selectionStart, selectionEnd);\n charDiff += selectionEnd - selectionStart;\n }\n else if (nextCharCount < charCount) {\n if (backDelete) {\n removedText = this._text.slice(selectionEnd + charDiff, selectionEnd);\n }\n else {\n removedText = this._text.slice(selectionStart, selectionStart - charDiff);\n }\n }\n insertedText = nextText.slice(textareaSelection.selectionEnd - charDiff, textareaSelection.selectionEnd);\n if (removedText && removedText.length) {\n if (insertedText.length) {\n // let's copy some style before deleting.\n // we want to copy the style before the cursor OR the style at the cursor if selection\n // is bigger than 0.\n copiedStyle = this.getSelectionStyles(selectionStart, selectionStart + 1, false);\n // now duplicate the style one for each inserted text.\n copiedStyle = insertedText.map(function() {\n // this return an array of references, but that is fine since we are\n // copying the style later.\n return copiedStyle[0];\n });\n }\n if (selection) {\n removeFrom = selectionStart;\n removeTo = selectionEnd;\n }\n else if (backDelete) {\n // detect differences between forwardDelete and backDelete\n removeFrom = selectionEnd - removedText.length;\n removeTo = selectionEnd;\n }\n else {\n removeFrom = selectionEnd;\n removeTo = selectionEnd + removedText.length;\n }\n this.removeStyleFromTo(removeFrom, removeTo);\n }\n if (insertedText.length) {\n if (fromPaste && insertedText.join('') === fabric.copiedText && !fabric.disableStyleCopyPaste) {\n copiedStyle = fabric.copiedTextStyle;\n }\n this.insertNewStyleBlock(insertedText, selectionStart, copiedStyle);\n }\n this.updateFromTextArea();\n this.fire('changed');\n if (this.canvas) {\n this.canvas.fire('text:changed', { target: this });\n this.canvas.requestRenderAll();\n }\n },\n /**\n * Composition start\n */\n onCompositionStart: function() {\n this.inCompositionMode = true;\n },\n\n /**\n * Composition end\n */\n onCompositionEnd: function() {\n this.inCompositionMode = false;\n },\n\n // /**\n // * Composition update\n // */\n onCompositionUpdate: function(e) {\n this.compositionStart = e.target.selectionStart;\n this.compositionEnd = e.target.selectionEnd;\n this.updateTextareaPosition();\n },\n\n /**\n * Copies selected text\n * @param {Event} e Event object\n */\n copy: function() {\n if (this.selectionStart === this.selectionEnd) {\n //do not cut-copy if no selection\n return;\n }\n\n fabric.copiedText = this.getSelectedText();\n if (!fabric.disableStyleCopyPaste) {\n fabric.copiedTextStyle = this.getSelectionStyles(this.selectionStart, this.selectionEnd, true);\n }\n else {\n fabric.copiedTextStyle = null;\n }\n this._copyDone = true;\n },\n\n /**\n * Pastes text\n * @param {Event} e Event object\n */\n paste: function() {\n this.fromPaste = true;\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @return {Object} Clipboard data object\n */\n _getClipboardData: function(e) {\n return (e && e.clipboardData) || fabric.window.clipboardData;\n },\n\n /**\n * Finds the width in pixels before the cursor on the same line\n * @private\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @return {Number} widthBeforeCursor width before cursor\n */\n _getWidthBeforeCursor: function(lineIndex, charIndex) {\n var widthBeforeCursor = this._getLineLeftOffset(lineIndex), bound;\n\n if (charIndex > 0) {\n bound = this.__charBounds[lineIndex][charIndex - 1];\n widthBeforeCursor += bound.left + bound.width;\n }\n return widthBeforeCursor;\n },\n\n /**\n * Gets start offset of a selection\n * @param {Event} e Event object\n * @param {Boolean} isRight\n * @return {Number}\n */\n getDownCursorOffset: function(e, isRight) {\n var selectionProp = this._getSelectionForOffset(e, isRight),\n cursorLocation = this.get2DCursorLocation(selectionProp),\n lineIndex = cursorLocation.lineIndex;\n // if on last line, down cursor goes to end of line\n if (lineIndex === this._textLines.length - 1 || e.metaKey || e.keyCode === 34) {\n // move to the end of a text\n return this._text.length - selectionProp;\n }\n var charIndex = cursorLocation.charIndex,\n widthBeforeCursor = this._getWidthBeforeCursor(lineIndex, charIndex),\n indexOnOtherLine = this._getIndexOnLine(lineIndex + 1, widthBeforeCursor),\n textAfterCursor = this._textLines[lineIndex].slice(charIndex);\n return textAfterCursor.length + indexOnOtherLine + 1 + this.missingNewlineOffset(lineIndex);\n },\n\n /**\n * private\n * Helps finding if the offset should be counted from Start or End\n * @param {Event} e Event object\n * @param {Boolean} isRight\n * @return {Number}\n */\n _getSelectionForOffset: function(e, isRight) {\n if (e.shiftKey && this.selectionStart !== this.selectionEnd && isRight) {\n return this.selectionEnd;\n }\n else {\n return this.selectionStart;\n }\n },\n\n /**\n * @param {Event} e Event object\n * @param {Boolean} isRight\n * @return {Number}\n */\n getUpCursorOffset: function(e, isRight) {\n var selectionProp = this._getSelectionForOffset(e, isRight),\n cursorLocation = this.get2DCursorLocation(selectionProp),\n lineIndex = cursorLocation.lineIndex;\n if (lineIndex === 0 || e.metaKey || e.keyCode === 33) {\n // if on first line, up cursor goes to start of line\n return -selectionProp;\n }\n var charIndex = cursorLocation.charIndex,\n widthBeforeCursor = this._getWidthBeforeCursor(lineIndex, charIndex),\n indexOnOtherLine = this._getIndexOnLine(lineIndex - 1, widthBeforeCursor),\n textBeforeCursor = this._textLines[lineIndex].slice(0, charIndex),\n missingNewlineOffset = this.missingNewlineOffset(lineIndex - 1);\n // return a negative offset\n return -this._textLines[lineIndex - 1].length\n + indexOnOtherLine - textBeforeCursor.length + (1 - missingNewlineOffset);\n },\n\n /**\n * for a given width it founds the matching character.\n * @private\n */\n _getIndexOnLine: function(lineIndex, width) {\n\n var line = this._textLines[lineIndex],\n lineLeftOffset = this._getLineLeftOffset(lineIndex),\n widthOfCharsOnLine = lineLeftOffset,\n indexOnLine = 0, charWidth, foundMatch;\n\n for (var j = 0, jlen = line.length; j < jlen; j++) {\n charWidth = this.__charBounds[lineIndex][j].width;\n widthOfCharsOnLine += charWidth;\n if (widthOfCharsOnLine > width) {\n foundMatch = true;\n var leftEdge = widthOfCharsOnLine - charWidth,\n rightEdge = widthOfCharsOnLine,\n offsetFromLeftEdge = Math.abs(leftEdge - width),\n offsetFromRightEdge = Math.abs(rightEdge - width);\n\n indexOnLine = offsetFromRightEdge < offsetFromLeftEdge ? j : (j - 1);\n break;\n }\n }\n\n // reached end\n if (!foundMatch) {\n indexOnLine = line.length - 1;\n }\n\n return indexOnLine;\n },\n\n\n /**\n * Moves cursor down\n * @param {Event} e Event object\n */\n moveCursorDown: function(e) {\n if (this.selectionStart >= this._text.length && this.selectionEnd >= this._text.length) {\n return;\n }\n this._moveCursorUpOrDown('Down', e);\n },\n\n /**\n * Moves cursor up\n * @param {Event} e Event object\n */\n moveCursorUp: function(e) {\n if (this.selectionStart === 0 && this.selectionEnd === 0) {\n return;\n }\n this._moveCursorUpOrDown('Up', e);\n },\n\n /**\n * Moves cursor up or down, fires the events\n * @param {String} direction 'Up' or 'Down'\n * @param {Event} e Event object\n */\n _moveCursorUpOrDown: function(direction, e) {\n // getUpCursorOffset\n // getDownCursorOffset\n var action = 'get' + direction + 'CursorOffset',\n offset = this[action](e, this._selectionDirection === 'right');\n if (e.shiftKey) {\n this.moveCursorWithShift(offset);\n }\n else {\n this.moveCursorWithoutShift(offset);\n }\n if (offset !== 0) {\n this.setSelectionInBoundaries();\n this.abortCursorAnimation();\n this._currentCursorOpacity = 1;\n this.initDelayedCursor();\n this._fireSelectionChanged();\n this._updateTextarea();\n }\n },\n\n /**\n * Moves cursor with shift\n * @param {Number} offset\n */\n moveCursorWithShift: function(offset) {\n var newSelection = this._selectionDirection === 'left'\n ? this.selectionStart + offset\n : this.selectionEnd + offset;\n this.setSelectionStartEndWithShift(this.selectionStart, this.selectionEnd, newSelection);\n return offset !== 0;\n },\n\n /**\n * Moves cursor up without shift\n * @param {Number} offset\n */\n moveCursorWithoutShift: function(offset) {\n if (offset < 0) {\n this.selectionStart += offset;\n this.selectionEnd = this.selectionStart;\n }\n else {\n this.selectionEnd += offset;\n this.selectionStart = this.selectionEnd;\n }\n return offset !== 0;\n },\n\n /**\n * Moves cursor left\n * @param {Event} e Event object\n */\n moveCursorLeft: function(e) {\n if (this.selectionStart === 0 && this.selectionEnd === 0) {\n return;\n }\n this._moveCursorLeftOrRight('Left', e);\n },\n\n /**\n * @private\n * @return {Boolean} true if a change happened\n */\n _move: function(e, prop, direction) {\n var newValue;\n if (e.altKey) {\n newValue = this['findWordBoundary' + direction](this[prop]);\n }\n else if (e.metaKey || e.keyCode === 35 || e.keyCode === 36 ) {\n newValue = this['findLineBoundary' + direction](this[prop]);\n }\n else {\n this[prop] += direction === 'Left' ? -1 : 1;\n return true;\n }\n if (typeof newValue !== 'undefined' && this[prop] !== newValue) {\n this[prop] = newValue;\n return true;\n }\n },\n\n /**\n * @private\n */\n _moveLeft: function(e, prop) {\n return this._move(e, prop, 'Left');\n },\n\n /**\n * @private\n */\n _moveRight: function(e, prop) {\n return this._move(e, prop, 'Right');\n },\n\n /**\n * Moves cursor left without keeping selection\n * @param {Event} e\n */\n moveCursorLeftWithoutShift: function(e) {\n var change = true;\n this._selectionDirection = 'left';\n\n // only move cursor when there is no selection,\n // otherwise we discard it, and leave cursor on same place\n if (this.selectionEnd === this.selectionStart && this.selectionStart !== 0) {\n change = this._moveLeft(e, 'selectionStart');\n\n }\n this.selectionEnd = this.selectionStart;\n return change;\n },\n\n /**\n * Moves cursor left while keeping selection\n * @param {Event} e\n */\n moveCursorLeftWithShift: function(e) {\n if (this._selectionDirection === 'right' && this.selectionStart !== this.selectionEnd) {\n return this._moveLeft(e, 'selectionEnd');\n }\n else if (this.selectionStart !== 0){\n this._selectionDirection = 'left';\n return this._moveLeft(e, 'selectionStart');\n }\n },\n\n /**\n * Moves cursor right\n * @param {Event} e Event object\n */\n moveCursorRight: function(e) {\n if (this.selectionStart >= this._text.length && this.selectionEnd >= this._text.length) {\n return;\n }\n this._moveCursorLeftOrRight('Right', e);\n },\n\n /**\n * Moves cursor right or Left, fires event\n * @param {String} direction 'Left', 'Right'\n * @param {Event} e Event object\n */\n _moveCursorLeftOrRight: function(direction, e) {\n var actionName = 'moveCursor' + direction + 'With';\n this._currentCursorOpacity = 1;\n\n if (e.shiftKey) {\n actionName += 'Shift';\n }\n else {\n actionName += 'outShift';\n }\n if (this[actionName](e)) {\n this.abortCursorAnimation();\n this.initDelayedCursor();\n this._fireSelectionChanged();\n this._updateTextarea();\n }\n },\n\n /**\n * Moves cursor right while keeping selection\n * @param {Event} e\n */\n moveCursorRightWithShift: function(e) {\n if (this._selectionDirection === 'left' && this.selectionStart !== this.selectionEnd) {\n return this._moveRight(e, 'selectionStart');\n }\n else if (this.selectionEnd !== this._text.length) {\n this._selectionDirection = 'right';\n return this._moveRight(e, 'selectionEnd');\n }\n },\n\n /**\n * Moves cursor right without keeping selection\n * @param {Event} e Event object\n */\n moveCursorRightWithoutShift: function(e) {\n var changed = true;\n this._selectionDirection = 'right';\n\n if (this.selectionStart === this.selectionEnd) {\n changed = this._moveRight(e, 'selectionStart');\n this.selectionEnd = this.selectionStart;\n }\n else {\n this.selectionStart = this.selectionEnd;\n }\n return changed;\n },\n\n /**\n * Removes characters from start/end\n * start/end ar per grapheme position in _text array.\n *\n * @param {Number} start\n * @param {Number} end default to start + 1\n */\n removeChars: function(start, end) {\n if (typeof end === 'undefined') {\n end = start + 1;\n }\n this.removeStyleFromTo(start, end);\n this._text.splice(start, end - start);\n this.text = this._text.join('');\n this.set('dirty', true);\n if (this._shouldClearDimensionCache()) {\n this.initDimensions();\n this.setCoords();\n }\n this._removeExtraneousStyles();\n },\n\n /**\n * insert characters at start position, before start position.\n * start equal 1 it means the text get inserted between actual grapheme 0 and 1\n * if style array is provided, it must be as the same length of text in graphemes\n * if end is provided and is bigger than start, old text is replaced.\n * start/end ar per grapheme position in _text array.\n *\n * @param {String} text text to insert\n * @param {Array} style array of style objects\n * @param {Number} start\n * @param {Number} end default to start + 1\n */\n insertChars: function(text, style, start, end) {\n if (typeof end === 'undefined') {\n end = start;\n }\n if (end > start) {\n this.removeStyleFromTo(start, end);\n }\n var graphemes = fabric.util.string.graphemeSplit(text);\n this.insertNewStyleBlock(graphemes, start, style);\n this._text = [].concat(this._text.slice(0, start), graphemes, this._text.slice(end));\n this.text = this._text.join('');\n this.set('dirty', true);\n if (this._shouldClearDimensionCache()) {\n this.initDimensions();\n this.setCoords();\n }\n this._removeExtraneousStyles();\n },\n\n});\n\n\n/* _TO_SVG_START_ */\n(function() {\n var toFixed = fabric.util.toFixed,\n multipleSpacesRegex = / +/g;\n\n fabric.util.object.extend(fabric.Text.prototype, /** @lends fabric.Text.prototype */ {\n\n /**\n * Returns SVG representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n _toSVG: function() {\n var offsets = this._getSVGLeftTopOffsets(),\n textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft);\n return this._wrapSVGTextAndBg(textAndBg);\n },\n\n /**\n * Returns svg representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n return this._createBaseSVGMarkup(\n this._toSVG(),\n { reviver: reviver, noStyle: true, withShadow: true }\n );\n },\n\n /**\n * @private\n */\n _getSVGLeftTopOffsets: function() {\n return {\n textLeft: -this.width / 2,\n textTop: -this.height / 2,\n lineTop: this.getHeightOfLine(0)\n };\n },\n\n /**\n * @private\n */\n _wrapSVGTextAndBg: function(textAndBg) {\n var noShadow = true,\n textDecoration = this.getSvgTextDecoration(this);\n return [\n textAndBg.textBgRects.join(''),\n '\\t\\t',\n textAndBg.textSpans.join(''),\n '\\n'\n ];\n },\n\n /**\n * @private\n * @param {Number} textTopOffset Text top offset\n * @param {Number} textLeftOffset Text left offset\n * @return {Object}\n */\n _getSVGTextAndBg: function(textTopOffset, textLeftOffset) {\n var textSpans = [],\n textBgRects = [],\n height = textTopOffset, lineOffset;\n // bounding-box background\n this._setSVGBg(textBgRects);\n\n // text and text-background\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n lineOffset = this._getLineLeftOffset(i);\n if (this.textBackgroundColor || this.styleHas('textBackgroundColor', i)) {\n this._setSVGTextLineBg(textBgRects, i, textLeftOffset + lineOffset, height);\n }\n this._setSVGTextLineText(textSpans, i, textLeftOffset + lineOffset, height);\n height += this.getHeightOfLine(i);\n }\n\n return {\n textSpans: textSpans,\n textBgRects: textBgRects\n };\n },\n\n /**\n * @private\n */\n _createTextCharSpan: function(_char, styleDecl, left, top) {\n var shouldUseWhitespace = _char !== _char.trim() || _char.match(multipleSpacesRegex),\n styleProps = this.getSvgSpanStyles(styleDecl, shouldUseWhitespace),\n fillStyles = styleProps ? 'style=\"' + styleProps + '\"' : '',\n dy = styleDecl.deltaY, dySpan = '',\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n if (dy) {\n dySpan = ' dy=\"' + toFixed(dy, NUM_FRACTION_DIGITS) + '\" ';\n }\n return [\n '',\n fabric.util.string.escapeXml(_char),\n ''\n ].join('');\n },\n\n _setSVGTextLineText: function(textSpans, lineIndex, textLeftOffset, textTopOffset) {\n // set proper line offset\n var lineHeight = this.getHeightOfLine(lineIndex),\n isJustify = this.textAlign.indexOf('justify') !== -1,\n actualStyle,\n nextStyle,\n charsToRender = '',\n charBox, style,\n boxWidth = 0,\n line = this._textLines[lineIndex],\n timeToRender;\n\n textTopOffset += lineHeight * (1 - this._fontSizeFraction) / this.lineHeight;\n for (var i = 0, len = line.length - 1; i <= len; i++) {\n timeToRender = i === len || this.charSpacing;\n charsToRender += line[i];\n charBox = this.__charBounds[lineIndex][i];\n if (boxWidth === 0) {\n textLeftOffset += charBox.kernedWidth - charBox.width;\n boxWidth += charBox.width;\n }\n else {\n boxWidth += charBox.kernedWidth;\n }\n if (isJustify && !timeToRender) {\n if (this._reSpaceAndTab.test(line[i])) {\n timeToRender = true;\n }\n }\n if (!timeToRender) {\n // if we have charSpacing, we render char by char\n actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\n nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\n timeToRender = fabric.util.hasStyleChanged(actualStyle, nextStyle, true);\n }\n if (timeToRender) {\n style = this._getStyleDeclaration(lineIndex, i) || { };\n textSpans.push(this._createTextCharSpan(charsToRender, style, textLeftOffset, textTopOffset));\n charsToRender = '';\n actualStyle = nextStyle;\n textLeftOffset += boxWidth;\n boxWidth = 0;\n }\n }\n },\n\n _pushTextBgRect: function(textBgRects, color, left, top, width, height) {\n var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n textBgRects.push(\n '\\t\\t\\n');\n },\n\n _setSVGTextLineBg: function(textBgRects, i, leftOffset, textTopOffset) {\n var line = this._textLines[i],\n heightOfLine = this.getHeightOfLine(i) / this.lineHeight,\n boxWidth = 0,\n boxStart = 0,\n charBox, currentColor,\n lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\n for (var j = 0, jlen = line.length; j < jlen; j++) {\n charBox = this.__charBounds[i][j];\n currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\n if (currentColor !== lastColor) {\n lastColor && this._pushTextBgRect(textBgRects, lastColor, leftOffset + boxStart,\n textTopOffset, boxWidth, heightOfLine);\n boxStart = charBox.left;\n boxWidth = charBox.width;\n lastColor = currentColor;\n }\n else {\n boxWidth += charBox.kernedWidth;\n }\n }\n currentColor && this._pushTextBgRect(textBgRects, currentColor, leftOffset + boxStart,\n textTopOffset, boxWidth, heightOfLine);\n },\n\n /**\n * Adobe Illustrator (at least CS5) is unable to render rgba()-based fill values\n * we work around it by \"moving\" alpha channel into opacity attribute and setting fill's alpha to 1\n *\n * @private\n * @param {*} value\n * @return {String}\n */\n _getFillAttributes: function(value) {\n var fillColor = (value && typeof value === 'string') ? new fabric.Color(value) : '';\n if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) {\n return 'fill=\"' + value + '\"';\n }\n return 'opacity=\"' + fillColor.getAlpha() + '\" fill=\"' + fillColor.setAlpha(1).toRgb() + '\"';\n },\n\n /**\n * @private\n */\n _getSVGLineTopOffset: function(lineIndex) {\n var lineTopOffset = 0, lastHeight = 0;\n for (var j = 0; j < lineIndex; j++) {\n lineTopOffset += this.getHeightOfLine(j);\n }\n lastHeight = this.getHeightOfLine(j);\n return {\n lineTop: lineTopOffset,\n offset: (this._fontSizeMult - this._fontSizeFraction) * lastHeight / (this.lineHeight * this._fontSizeMult)\n };\n },\n\n /**\n * Returns styles-string for svg-export\n * @param {Boolean} skipShadow a boolean to skip shadow filter output\n * @return {String}\n */\n getSvgStyles: function(skipShadow) {\n var svgStyle = fabric.Object.prototype.getSvgStyles.call(this, skipShadow);\n return svgStyle + ' white-space: pre;';\n },\n });\n})();\n/* _TO_SVG_END_ */\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = {});\n\n /**\n * Textbox class, based on IText, allows the user to resize the text rectangle\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\n * user can only change width. Height is adjusted automatically based on the\n * wrapping of lines.\n * @class fabric.Textbox\n * @extends fabric.IText\n * @mixes fabric.Observable\n * @return {fabric.Textbox} thisArg\n * @see {@link fabric.Textbox#initialize} for constructor definition\n */\n fabric.Textbox = fabric.util.createClass(fabric.IText, fabric.Observable, {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'textbox',\n\n /**\n * Minimum width of textbox, in pixels.\n * @type Number\n * @default\n */\n minWidth: 20,\n\n /**\n * Minimum calculated width of a textbox, in pixels.\n * fixed to 2 so that an empty textbox cannot go to 0\n * and is still selectable without text.\n * @type Number\n * @default\n */\n dynamicMinWidth: 2,\n\n /**\n * Cached array of text wrapping.\n * @type Array\n */\n __cachedLines: null,\n\n /**\n * Override standard Object class values\n */\n lockScalingFlip: true,\n\n /**\n * Override standard Object class values\n * Textbox needs this on false\n */\n noScaleCache: false,\n\n /**\n * Properties which when set cause object to change dimensions\n * @type Object\n * @private\n */\n _dimensionAffectingProps: fabric.Text.prototype._dimensionAffectingProps.concat('width'),\n\n /**\n * Use this regular expression to split strings in breakable lines\n * @private\n */\n _wordJoiners: /[ \\t\\r]/,\n\n /**\n * Use this boolean property in order to split strings that have no white space concept.\n * this is a cheap way to help with chinese/japanese\n * @type Boolean\n * @since 2.6.0\n */\n splitByGrapheme: false,\n\n /**\n * Unlike superclass's version of this function, Textbox does not update\n * its width.\n * @private\n * @override\n */\n initDimensions: function() {\n if (this.__skipDimension) {\n return;\n }\n this.isEditing && this.initDelayedCursor();\n this.clearContextTop();\n this._clearCache();\n // clear dynamicMinWidth as it will be different after we re-wrap line\n this.dynamicMinWidth = 0;\n // wrap lines\n this._styleMap = this._generateStyleMap(this._splitText());\n // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n if (this.dynamicMinWidth > this.width) {\n this._set('width', this.dynamicMinWidth);\n }\n if (this.textAlign.indexOf('justify') !== -1) {\n // once text is measured we need to make space fatter to make justified text.\n this.enlargeSpaces();\n }\n // clear cache and re-calculate height\n this.height = this.calcTextHeight();\n this.saveState({ propertySet: '_dimensionAffectingProps' });\n },\n\n /**\n * Generate an object that translates the style object so that it is\n * broken up by visual lines (new lines and automatic wrapping).\n * The original text styles object is broken up by actual lines (new lines only),\n * which is only sufficient for Text / IText\n * @private\n */\n _generateStyleMap: function(textInfo) {\n var realLineCount = 0,\n realLineCharCount = 0,\n charCount = 0,\n map = {};\n\n for (var i = 0; i < textInfo.graphemeLines.length; i++) {\n if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n realLineCharCount = 0;\n charCount++;\n realLineCount++;\n }\n else if (!this.splitByGrapheme && this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) && i > 0) {\n // this case deals with space's that are removed from end of lines when wrapping\n realLineCharCount++;\n charCount++;\n }\n\n map[i] = { line: realLineCount, offset: realLineCharCount };\n\n charCount += textInfo.graphemeLines[i].length;\n realLineCharCount += textInfo.graphemeLines[i].length;\n }\n\n return map;\n },\n\n /**\n * Returns true if object has a style property or has it on a specified line\n * @param {Number} lineIndex\n * @return {Boolean}\n */\n styleHas: function(property, lineIndex) {\n if (this._styleMap && !this.isWrapping) {\n var map = this._styleMap[lineIndex];\n if (map) {\n lineIndex = map.line;\n }\n }\n return fabric.Text.prototype.styleHas.call(this, property, lineIndex);\n },\n\n /**\n * Returns true if object has no styling or no styling in a line\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\n * @return {Boolean}\n */\n isEmptyStyles: function(lineIndex) {\n if (!this.styles) {\n return true;\n }\n var offset = 0, nextLineIndex = lineIndex + 1, nextOffset, obj, shouldLimit = false,\n map = this._styleMap[lineIndex], mapNextLine = this._styleMap[lineIndex + 1];\n if (map) {\n lineIndex = map.line;\n offset = map.offset;\n }\n if (mapNextLine) {\n nextLineIndex = mapNextLine.line;\n shouldLimit = nextLineIndex === lineIndex;\n nextOffset = mapNextLine.offset;\n }\n obj = typeof lineIndex === 'undefined' ? this.styles : { line: this.styles[lineIndex] };\n for (var p1 in obj) {\n for (var p2 in obj[p1]) {\n if (p2 >= offset && (!shouldLimit || p2 < nextOffset)) {\n // eslint-disable-next-line no-unused-vars\n for (var p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n }\n return true;\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n _getStyleDeclaration: function(lineIndex, charIndex) {\n if (this._styleMap && !this.isWrapping) {\n var map = this._styleMap[lineIndex];\n if (!map) {\n return null;\n }\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n }\n return this.callSuper('_getStyleDeclaration', lineIndex, charIndex);\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n _setStyleDeclaration: function(lineIndex, charIndex, style) {\n var map = this._styleMap[lineIndex];\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n\n this.styles[lineIndex][charIndex] = style;\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n _deleteStyleDeclaration: function(lineIndex, charIndex) {\n var map = this._styleMap[lineIndex];\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n delete this.styles[lineIndex][charIndex];\n },\n\n /**\n * probably broken need a fix\n * Returns the real style line that correspond to the wrapped lineIndex line\n * Used just to verify if the line does exist or not.\n * @param {Number} lineIndex\n * @returns {Boolean} if the line exists or not\n * @private\n */\n _getLineStyle: function(lineIndex) {\n var map = this._styleMap[lineIndex];\n return !!this.styles[map.line];\n },\n\n /**\n * Set the line style to an empty object so that is initialized\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n _setLineStyle: function(lineIndex) {\n var map = this._styleMap[lineIndex];\n this.styles[map.line] = {};\n },\n\n /**\n * Wraps text using the 'width' property of Textbox. First this function\n * splits text on newlines, so we preserve newlines entered by the user.\n * Then it wraps each line using the width of the Textbox by calling\n * _wrapLine().\n * @param {Array} lines The string array of text that is split into lines\n * @param {Number} desiredWidth width you want to wrap to\n * @returns {Array} Array of lines\n */\n _wrapText: function(lines, desiredWidth) {\n var wrapped = [], i;\n this.isWrapping = true;\n for (i = 0; i < lines.length; i++) {\n wrapped = wrapped.concat(this._wrapLine(lines[i], i, desiredWidth));\n }\n this.isWrapping = false;\n return wrapped;\n },\n\n /**\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\n * it gets called when charBounds are not available yet.\n * @param {CanvasRenderingContext2D} ctx\n * @param {String} text\n * @param {number} lineIndex\n * @param {number} charOffset\n * @returns {number}\n * @private\n */\n _measureWord: function(word, lineIndex, charOffset) {\n var width = 0, prevGrapheme, skipLeft = true;\n charOffset = charOffset || 0;\n for (var i = 0, len = word.length; i < len; i++) {\n var box = this._getGraphemeBox(word[i], lineIndex, i + charOffset, prevGrapheme, skipLeft);\n width += box.kernedWidth;\n prevGrapheme = word[i];\n }\n return width;\n },\n\n /**\n * Wraps a line of text using the width of the Textbox and a context.\n * @param {Array} line The grapheme array that represent the line\n * @param {Number} lineIndex\n * @param {Number} desiredWidth width you want to wrap the line to\n * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n * @returns {Array} Array of line(s) into which the given text is wrapped\n * to.\n */\n _wrapLine: function(_line, lineIndex, desiredWidth, reservedSpace) {\n var lineWidth = 0,\n splitByGrapheme = this.splitByGrapheme,\n graphemeLines = [],\n line = [],\n // spaces in different languages?\n words = splitByGrapheme ? fabric.util.string.graphemeSplit(_line) : _line.split(this._wordJoiners),\n word = '',\n offset = 0,\n infix = splitByGrapheme ? '' : ' ',\n wordWidth = 0,\n infixWidth = 0,\n largestWordWidth = 0,\n lineJustStarted = true,\n additionalSpace = this._getWidthOfCharSpacing(),\n reservedSpace = reservedSpace || 0;\n // fix a difference between split and graphemeSplit\n if (words.length === 0) {\n words.push([]);\n }\n desiredWidth -= reservedSpace;\n for (var i = 0; i < words.length; i++) {\n // if using splitByGrapheme words are already in graphemes.\n word = splitByGrapheme ? words[i] : fabric.util.string.graphemeSplit(words[i]);\n wordWidth = this._measureWord(word, lineIndex, offset);\n offset += word.length;\n\n lineWidth += infixWidth + wordWidth - additionalSpace;\n if (lineWidth > desiredWidth && !lineJustStarted) {\n graphemeLines.push(line);\n line = [];\n lineWidth = wordWidth;\n lineJustStarted = true;\n }\n else {\n lineWidth += additionalSpace;\n }\n\n if (!lineJustStarted && !splitByGrapheme) {\n line.push(infix);\n }\n line = line.concat(word);\n\n infixWidth = splitByGrapheme ? 0 : this._measureWord([infix], lineIndex, offset);\n offset++;\n lineJustStarted = false;\n // keep track of largest word\n if (wordWidth > largestWordWidth) {\n largestWordWidth = wordWidth;\n }\n }\n\n i && graphemeLines.push(line);\n\n if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n }\n return graphemeLines;\n },\n\n /**\n * Detect if the text line is ended with an hard break\n * text and itext do not have wrapping, return false\n * @param {Number} lineIndex text to split\n * @return {Boolean}\n */\n isEndOfWrapping: function(lineIndex) {\n if (!this._styleMap[lineIndex + 1]) {\n // is last line, return true;\n return true;\n }\n if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n // this is last line before a line break, return true;\n return true;\n }\n return false;\n },\n\n /**\n * Detect if a line has a linebreak and so we need to account for it when moving\n * and counting style.\n * This is important only for splitByGrapheme at the end of wrapping.\n * If we are not wrapping the offset is always 1\n * @return Number\n */\n missingNewlineOffset: function(lineIndex, skipWrapping) {\n if (this.splitByGrapheme && !skipWrapping) {\n return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n }\n return 1;\n },\n\n /**\n * Gets lines of text to render in the Textbox. This function calculates\n * text wrapping on the fly every time it is called.\n * @param {String} text text to split\n * @returns {Array} Array of lines in the Textbox.\n * @override\n */\n _splitTextIntoLines: function(text) {\n var newText = fabric.Text.prototype._splitTextIntoLines.call(this, text),\n graphemeLines = this._wrapText(newText.lines, this.width),\n lines = new Array(graphemeLines.length);\n for (var i = 0; i < graphemeLines.length; i++) {\n lines[i] = graphemeLines[i].join('');\n }\n newText.lines = lines;\n newText.graphemeLines = graphemeLines;\n return newText;\n },\n\n getMinWidth: function() {\n return Math.max(this.minWidth, this.dynamicMinWidth);\n },\n\n _removeExtraneousStyles: function() {\n var linesToKeep = {};\n for (var prop in this._styleMap) {\n if (this._textLines[prop]) {\n linesToKeep[this._styleMap[prop].line] = 1;\n }\n }\n for (var prop in this.styles) {\n if (!linesToKeep[prop]) {\n delete this.styles[prop];\n }\n }\n },\n\n /**\n * Returns object representation of an instance\n * @method toObject\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return this.callSuper('toObject', ['minWidth', 'splitByGrapheme'].concat(propertiesToInclude));\n }\n });\n\n /**\n * Returns fabric.Textbox instance from an object representation\n * @static\n * @memberOf fabric.Textbox\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] Callback to invoke when an fabric.Textbox instance is created\n */\n fabric.Textbox.fromObject = function(object, callback) {\n var styles = fabric.util.stylesFromArray(object.styles, object.text);\n //copy object to prevent mutation\n var objCopy = Object.assign({}, object, { styles: styles });\n delete objCopy.path;\n return fabric.Object._fromObject('Textbox', objCopy, function(textInstance) {\n if (object.path) {\n fabric.Object._fromObject('Path', object.path, function(pathInstance) {\n textInstance.set('path', pathInstance);\n callback(textInstance);\n }, 'path');\n }\n else {\n callback(textInstance);\n }\n }, 'text');\n };\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n var controlsUtils = fabric.controlsUtils,\n scaleSkewStyleHandler = controlsUtils.scaleSkewCursorStyleHandler,\n scaleStyleHandler = controlsUtils.scaleCursorStyleHandler,\n scalingEqually = controlsUtils.scalingEqually,\n scalingYOrSkewingX = controlsUtils.scalingYOrSkewingX,\n scalingXOrSkewingY = controlsUtils.scalingXOrSkewingY,\n scaleOrSkewActionName = controlsUtils.scaleOrSkewActionName,\n objectControls = fabric.Object.prototype.controls;\n\n objectControls.ml = new fabric.Control({\n x: -0.5,\n y: 0,\n cursorStyleHandler: scaleSkewStyleHandler,\n actionHandler: scalingXOrSkewingY,\n getActionName: scaleOrSkewActionName,\n });\n\n objectControls.mr = new fabric.Control({\n x: 0.5,\n y: 0,\n cursorStyleHandler: scaleSkewStyleHandler,\n actionHandler: scalingXOrSkewingY,\n getActionName: scaleOrSkewActionName,\n });\n\n objectControls.mb = new fabric.Control({\n x: 0,\n y: 0.5,\n cursorStyleHandler: scaleSkewStyleHandler,\n actionHandler: scalingYOrSkewingX,\n getActionName: scaleOrSkewActionName,\n });\n\n objectControls.mt = new fabric.Control({\n x: 0,\n y: -0.5,\n cursorStyleHandler: scaleSkewStyleHandler,\n actionHandler: scalingYOrSkewingX,\n getActionName: scaleOrSkewActionName,\n });\n\n objectControls.tl = new fabric.Control({\n x: -0.5,\n y: -0.5,\n cursorStyleHandler: scaleStyleHandler,\n actionHandler: scalingEqually\n });\n\n objectControls.tr = new fabric.Control({\n x: 0.5,\n y: -0.5,\n cursorStyleHandler: scaleStyleHandler,\n actionHandler: scalingEqually\n });\n\n objectControls.bl = new fabric.Control({\n x: -0.5,\n y: 0.5,\n cursorStyleHandler: scaleStyleHandler,\n actionHandler: scalingEqually\n });\n\n objectControls.br = new fabric.Control({\n x: 0.5,\n y: 0.5,\n cursorStyleHandler: scaleStyleHandler,\n actionHandler: scalingEqually\n });\n\n objectControls.mtr = new fabric.Control({\n x: 0,\n y: -0.5,\n actionHandler: controlsUtils.rotationWithSnapping,\n cursorStyleHandler: controlsUtils.rotationStyleHandler,\n offsetY: -40,\n withConnection: true,\n actionName: 'rotate',\n });\n\n if (fabric.Textbox) {\n // this is breaking the prototype inheritance, no time / ideas to fix it.\n // is important to document that if you want to have all objects to have a\n // specific custom control, you have to add it to Object prototype and to Textbox\n // prototype. The controls are shared as references. So changes to control `tr`\n // can still apply to all objects if needed.\n var textBoxControls = fabric.Textbox.prototype.controls = { };\n\n textBoxControls.mtr = objectControls.mtr;\n textBoxControls.tr = objectControls.tr;\n textBoxControls.br = objectControls.br;\n textBoxControls.tl = objectControls.tl;\n textBoxControls.bl = objectControls.bl;\n textBoxControls.mt = objectControls.mt;\n textBoxControls.mb = objectControls.mb;\n\n textBoxControls.mr = new fabric.Control({\n x: 0.5,\n y: 0,\n actionHandler: controlsUtils.changeWidth,\n cursorStyleHandler: scaleSkewStyleHandler,\n actionName: 'resizing',\n });\n\n textBoxControls.ml = new fabric.Control({\n x: -0.5,\n y: 0,\n actionHandler: controlsUtils.changeWidth,\n cursorStyleHandler: scaleSkewStyleHandler,\n actionName: 'resizing',\n });\n }\n})();\n\n","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--7-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--7-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--7-oneOf-1-2!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./requestJobInfo.vue?vue&type=style&index=0&id=7b21d213&prod&scoped=true&lang=css&\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--7-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--7-oneOf-1-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--7-oneOf-1-2!../../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./imageCroper.vue?vue&type=style&index=0&id=5594bef0&prod&scoped=true&lang=css&\""],"sourceRoot":""}