{"version":3,"sources":["webpack:///(webpack)/buildin/module.js","webpack:///./node_modules/fabric/dist/fabric.js","webpack:///(webpack)/buildin/global.js","webpack:///./node_modules/buffer/index.js","webpack:///./node_modules/base64-js/index.js","webpack:///./node_modules/ieee754/index.js","webpack:///./node_modules/isarray/index.js"],"names":["module","exports","webpackPolyfill","deprecate","paths","children","Object","defineProperty","enumerable","get","l","i","global","sqrt","atan2","pow","PiBy180","PiBy2","couldUseAttachEvent","touchEvents","parseEl","supportsOpacity","supportsFilters","reOpacity","setOpacity","proto","min","max","degreesToRadians","originXOffset","originYOffset","clone","toFixed","multipleSpacesRegex","fabric","version","document","window","HTMLDocument","Document","implementation","createHTMLDocument","virtualWindow","JSDOM","decodeURIComponent","features","FetchExternalResources","resources","jsdomImplForWrapper","implForWrapper","nodeCanvas","Canvas","DOMParser","copyGLTo2DDrawImage","gl","pipelineState","glCanvas","canvas","targetCanvas","ctx","getContext","translate","height","scale","sourceY","drawImage","width","copyGLTo2DPutImageData","dWidth","destinationWidth","dHeight","destinationHeight","numBytes","u8","Uint8Array","this","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","handler","__eventListeners","eventListener","indexOf","util","array","fill","_once","_handler","apply","arguments","off","bind","on","Observable","fire","options","listenersForEvent","len","length","call","filter","value","prop","push","once","Collection","_objects","add","_onObjectAdded","renderOnAddRemove","requestRenderAll","insertAt","object","index","nonSplicing","objects","splice","remove","somethingRemoved","_onObjectRemoved","forEachObject","callback","context","getObjects","type","concat","o","item","isEmpty","size","contains","deep","some","obj","complexity","reduce","memo","current","CommonMethods","_setOptions","set","_initGradient","filler","property","colorStops","Gradient","_initPattern","source","Pattern","_setObject","_set","key","toggle","Math","PI","cos","angle","sin","sign","removeFromArray","idx","getRandomInt","floor","random","degrees","radiansToDegrees","radians","rotatePoint","point","origin","newPoint","Point","x","y","v","rotateVector","addEquals","vector","createVector","from","to","calcAngleBetweenVectors","a","b","acos","hypot","getHatVector","multiply","getBisector","A","B","C","AB","AC","alpha","phi","projectStrokeOnPoints","points","openPath","coords","s","strokeWidth","strokeUniformScalar","strokeUniform","scaleX","scaleY","getStrokeHatVector","scalar","forEach","p","miterVector","bisector","bisectorVector","strokeLineJoin","strokeMiterLimit","subtract","SQRT2","transformPoint","t","ignoreOffset","makeBoundingBoxFromPoints","transform","xPoints","minX","yPoints","minY","left","top","invertTransform","r","number","fractionDigits","parseFloat","Number","parseUnit","fontSize","unit","exec","Text","DEFAULT_SVG_FONT_SIZE","falseFunction","getKlass","namespace","string","camelize","charAt","toUpperCase","slice","resolveNamespace","getSvgAttributes","attributes","parts","split","loadImage","url","crossOrigin","img","createImage","onLoadCallback","onload","onerror","src","undefined","substring","loadImageInDom","div","createElement","style","position","appendChild","querySelector","parentNode","removeChild","enlivenObjects","reviver","enlivenedObjects","numLoadedObjects","numTotalObjects","onLoaded","fromObject","error","enlivenObjectEnlivables","enlivenProps","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","target","rotate","saveObjectTransform","isTransparent","tolerance","_isTransparent","imageData","getImageData","data","parsePreserveAspectRatioAttribute","attribute","align","meetOrSlice","aspectRatioAttrs","pop","alignX","alignY","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","stroke","fontWeight","fontStyle","textBackgroundColor","deltaY","overline","underline","linethrough","stylesToArray","styles","text","textLines","charIndex","stylesArray","c","keys","start","end","stylesFromArray","styleIndex","stylesObject","assign","_join","prototype","commandLengths","m","h","q","repeatedCommands","M","segmentToBezier","th2","th3","cosTh","sinTh","rx","ry","cx1","cy1","mT","fromX","fromY","costh2","sinth2","costh3","sinth3","toX","toY","calcVectorAngle","ux","uy","vx","vy","ta","tb","fromArcToBeziers","fx","fy","rot","large","sweep","segsNorm","rotateX","th","px","py","rx2","abs","ry2","py2","px2","pl","root","cx","cy","mTheta","dtheta","segments","ceil","result","mDelta","arcToSegments","calcLineLength","x1","y1","x2","y2","getPointOnCubicBezierIterator","p1x","p1y","p2x","p2y","p3x","p3y","p4x","p4y","pct","CB2","c3","CB3","c4","CB4","getTangentCubicIterator","invT","tangentX","tangentY","getPointOnQuadraticBezierIterator","QB2","QB3","getTangentQuadraticIterator","pathIterator","iterator","perc","tempP","tmpLen","findPercentageForDistance","segInfo","distance","nextLen","lastPerc","nextStep","angleFinder","getPathSegmentsInfo","tempInfo","totalLength","info","command","destX","destY","joinPath","pathData","segment","parsePath","pathString","currentPath","parsed","match","coordsStr","re","rNumber","rNumberCommaWsp","rFlagCommaWsp","regArcArgumentSequence","RegExp","coordsParsed","trim","args","j","jlen","isNaN","commandLength","repeatedCommand","k","klen","makePathSimpler","converted","previous","controlX","controlY","destinationPath","getSmoothPathFromPoints","correction","p1","p2","multSignX","multSignY","manyPoints","eq","midPoint","midPointFrom","getBoundsOfCurve","x0","y0","x3","y3","argsString","t1","t2","b2ac","sqrtb2ac","tvalues","bounds","mt","getPointOnPath","infos","segPercent","lerp","transformPath","pathOffset","pathSegment","newSegment","find","byProperty","condition","invoke","method","value1","value2","extend","Element","hasOwnProperty","getWholeChar","str","code","charCodeAt","next","prev","replace","character","capitalize","firstLetterOnly","escapeXml","graphemeSplit","textstring","chr","graphemes","emptyFunction","IS_DONTENUM_BUGGY","toString","addMethods","klass","parent","superclass","constructor","returnValue","valueOf","Subclass","callSuper","methodName","parentMethod","_this","superClassMethod","createClass","initialize","shift","subclasses","attachEvent","addListener","element","addEventListener","removeListener","removeEventListener","getPointer","event","scroll","getScrollLeftTop","_evt","touchProp","changedTouches","getTouchInfo","clientX","clientY","isTouchEvent","pointerType","opacity","es","currentStyle","hasLayout","zoom","test","setStyle","elementStyle","cssText","normalizedProperty","styleFloat","setProperty","_slice","sliceCanConvertNodelists","getElementStyle","selectProp","toArray","arrayLike","childNodes","err","makeElement","tagName","el","className","htmlFor","setAttribute","docElement","documentElement","body","scrollLeft","scrollTop","host","nodeType","arr","defaultView","getComputedStyle","attr","makeElementUnselectable","onselectstart","unselectable","makeElementSelectable","setImageSmoothing","imageSmoothingEnabled","webkitImageSmoothingEnabled","mozImageSmoothingEnabled","msImageSmoothingEnabled","oImageSmoothingEnabled","getById","id","getElementById","addClass","wrapElement","wrapper","replaceChild","getElementOffset","docElem","scrollLeftTop","doc","ownerDocument","box","offset","offsetAttributes","borderLeftWidth","borderTopWidth","paddingLeft","paddingTop","parseInt","getBoundingClientRect","clientLeft","clientTop","getNodeCanvas","impl","_canvas","_image","cleanUpJsdomNode","_currentSrc","_attributes","_classList","emptyFn","request","onComplete","xhr","XMLHttpRequest","parameters","onreadystatechange","readyState","param","addParamToUrl","open","setRequestHeader","send","warn","RUNNING_ANIMATIONS","noop","defaultEasing","d","cancelAll","animations","animation","cancel","cancelByCanvas","cancelled","cancelByTarget","findAnimationsByTarget","findAnimationIndex","cancelFunc","findAnimation","_requestAnimFrame","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","setTimeout","_cancelAnimFrame","cancelAnimationFrame","clearTimeout","requestAnimFrame","animate","removeFromRegistry","runningAnimations","currentValue","startValue","completionRate","durationRate","timestamp","time","Date","duration","finish","onChange","abort","easing","isMany","endValue","byValue","onStart","tick","ticktime","currentTime","timePerc","_value","valuePerc","cancelAnimFrame","calculateColor","begin","pos","color","animateColor","fromColor","toColor","startColor","Color","getSource","endColor","originalOnComplete","originalOnChange","colorEasing","normalize","asin","elastic","opts","easeInBounce","easeOutBounce","ease","easeInQuad","easeOutQuad","easeInOutQuad","easeInCubic","easeOutCubic","easeInOutCubic","easeInQuart","easeOutQuart","easeInOutQuart","easeInQuint","easeOutQuint","easeInOutQuint","easeInSine","easeOutSine","easeInOutSine","easeInExpo","easeOutExpo","easeInOutExpo","easeInCirc","easeOutCirc","easeInOutCirc","easeInElastic","easeOutElastic","easeInOutElastic","easeInBack","easeOutBack","easeInOutBack","easeInOutBounce","attributesMap","display","visibility","colorAttributes","fSize","cPath","normalizeAttr","normalizeValue","parentAttributes","parseTransformAttribute","visible","fillIndex","strokeIndex","getSvgRegex","_getMultipleNodes","nodeNames","nodeName","nodeList","nodeArray","getElementsByTagName","elementMatchesRule","selectors","firstMatching","parentMatching","selectorMatches","selector","doesSomeParentMatch","matcher","classNames","getAttribute","elementById","node","nodelist","svgValidTagNamesRegEx","svgViewBoxElementsRegEx","svgInvalidAncestorsRegEx","svgValidParentsRegEx","cssRules","gradientDefs","clipPaths","skewMatrix","reTransformList","reTransform","attributeValue","matrices","operation","translateMatrix","rotateMatrix","multiplierX","multiplierY","combinedMatrix","reViewBoxAttrValue","applyViewboxTransform","viewBoxWidth","viewBoxHeight","viewBoxAttr","widthAttr","heightAttr","preserveAspectRatio","missingViewBox","missingDimAttr","toBeParsed","parsedDim","widthDiff","heightDiff","removeAttribute","createElementNS","firstChild","recursivelyParseGradientsXlink","gradient","xlinkAttr","referencedGradient","hasAttribute","referenceClone","cloneNode","parseSVGDocument","parsingOptions","xlinkAttribute","attrs","xlink","el2","currentTrans","oldLength","el3","setAttributeNS","nodeValue","parseUseDirectives","svgUid","__uid","descendants","selectNodes","hasAncestorWithNodeName","getGradientDefs","getCSSRules","parseElements","instances","reFontDeclaration","parseFontDeclaration","oStyle","lineHeight","elList","parseAttributes","parentFontSize","ownAttributes","cssAttrs","rule","getGlobalStylesForElement","parseStyleAttribute","normalizedAttr","normalizedValue","normalizedStyle","font","mergedAttrs","setAlpha","getAlpha","toRgba","_setStrokeFillOpacity","ElementsParser","parse","chunk","pair","parseStyleString","parseStyleObject","parsePointsAttribute","parsedPoints","allRules","styleContents","textContent","ruleObj","propertyValuePairs","_rule","loadSVGFromURL","xml","responseXML","results","_options","allElements","loadSVGFromString","parseFromString","regexUrl","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","status","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","g","round","_source","toRgb","toHsl","hsl","toHsla","toHex","toHexa","toGrayscale","average","currentAlpha","toBlackWhite","threshold","overlayWith","otherColor","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","uniformIsToggled","uniScaleKey","uniformScaling","isTransformCentered","originX","originY","scalingIsForbidden","by","scaleProportionally","lockX","lockScalingX","lockY","lockScalingY","commonEventInfo","e","pointer","wrapWithFixedAnchor","actionHandler","getCenterPoint","constraint","translateToOriginPoint","actionPerformed","wrapWithFireEvent","getLocalPoint","corner","getZoom","padding","localPoint","toLocalPoint","offsetX","offsetY","targetHasOneFlip","compensateScaleForSkew","oppositeSkew","scaleToCompensate","axis","reference","newValue","_getTransformedDimensions","skewObjectX","newSkew","dimNoSkew","totalSkewSize","currentSkew","hasSkewed","dimBeforeSkewing","skewObjectY","scaleObject","dim","signX","signY","forbidScaling","gestureScale","lockScalingFlip","original","oldScaleX","oldScaleY","scaleCursorStyleHandler","n","skewCursorStyleHandler","notAllowed","lockSkewingY","lockSkewingX","scaleSkewCursorStyleHandler","altActionKey","rotationWithSnapping","pivotPoint","lockRotation","hasRotated","lastAngle","ey","ex","curAngle","snapAngle","snapThreshold","rightAngleLocked","leftAngleLocked","scalingEqually","scalingX","scalingY","scalingYOrSkewingX","skewHandlerX","scalingXOrSkewingY","skewHandlerY","changeWidth","strokePadding","multiplier","oldWidth","newWidth","finalHandler","dragHandler","newLeft","newTop","moveX","moveY","scaleOrSkewActionName","isAlternative","rotationStyleHandler","cursorStyle","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","render","cornerStyle","getColorStop","colorAlpha","keyValuePairs","gradientTransform","gradientUnits","option","addColorStop","toObject","propertiesToInclude","toSVG","markup","commonAttributes","needsSwap","withViewport","additionalTransform","sort","reverse","minRadius","percentageShift","colorStop","toLive","createLinearGradient","createRadialGradient","instance","svgOptions","colorStopEls","getLinearCoords","getRadialCoords","propValue","finalValue","__convertPercentUnitsToValues","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","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","image","__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","bgColor","background","overlay","svgViewportTransformation","_setSVGPreamble","_setSVGHeader","clipPathId","_setSVGBgOverlayColor","_setSVGBgOverlayImage","_setSVGObjects","suppressPreamble","encoding","viewBox","createSVGFontFacesMarkup","createSVGRefElementsMarkup","createSVGClipPathMarkup","toClipPathSVG","shouldTransform","row","rowIndex","fontList","_setSVGObject","finalWidth","finalHeight","sendToBack","objs","activeSelection","unshift","bringToFront","sendBackwards","intersecting","newIdx","objsMoved","_findNewLowerIndex","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","adjustedDistance","lastPoint","newPoints","CircleBrush","drawDot","addPoint","dot","radius","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","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","isDrawingMode","preserveObjectStacking","stopContextMenu","fireRightClick","fireMiddleClick","targets","enablePointerEvents","_hoveredTarget","_hoveredTargets","_currentTransform","_groupSelector","_initWrapperElement","_createUpperCanvas","_initEventListeners","_chooseObjectsToRender","objsToRender","activeGroupObjects","activeObjects","getActiveObjects","contextTopDirty","renderTopLayer","_drawSelection","renderTop","_normalizePointer","invertedM","vptPointer","restorePointerVpt","isTargetTransparent","normalizedPointer","targetRelativeX","targetRelativeY","_cacheContext","contextCache","originalColor","selectionBackgroundColor","_isSelectionKeyPressed","_shouldClearSelection","evented","selectable","_shouldCenterTransform","action","altKey","centerTransform","_getOriginFromCorner","_getActionFromCorner","alreadySelected","_setupCurrentTransform","__corner","lastX","lastY","shiftKey","_beforeTransform","setCursor","cursor","viewportStart","viewportExtent","extent","maxX","maxY","strokeOffset","_setLineDash","findTarget","skipGroup","activeTarget","activeTargetSubs","aObjects","shouldLookForActive","_findTargetCorner","_searchPossibleTargets","_checkTarget","globalPointer","containsPoint","isEditing","subTarget","objToCheck","pointerToUse","subTargetCheck","ignoreZoom","_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","originalValues","clearContextTop","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","preventDefault","_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","inFires","targetChanged","previousTarget","nextTarget","reset","_performTransformAction","getCornerCursor","_updateActiveSelection","_createActiveSelection","currentActiveObjects","removeWithUpdate","addWithUpdate","_createGroup","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","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","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","translateToGivenOrigin","fromOriginX","fromOriginY","toOriginX","toOriginY","translateToCenterPoint","leftTop","getPointByOrigin","adjustPosition","offsetFrom","offsetTo","hypotFull","getScaledWidth","xFull","yFull","_originalOriginX","_originalOriginY","originPoint","multiplyMatrices","oCoords","aCoords","lineCoords","ownMatrixCache","matrixCache","_getCoords","absolute","calculate","calcACoords","calcLineCoords","getCoords","pointTL","pointBR","other","otherCoords","lines","_getImageLines","_findCrossPoints","_containsCenterOfCanvas","isPartiallyOnScreen","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","_setSVGBg","textBgRects","_getFillAttributes","_createBaseSVGMarkup","_toSVG","_createBaseClipPathSVGMarkup","objectMarkup","commonPieces","clipPathMarkup","noStyle","styleInfo","shadowInfo","withShadow","vectorEffect","absoluteClipPath","addPaintOrder","originalSet","saveProps","props","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","startAngle","endAngle","setRadius","svgString","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","pathUrl","elivenedObjects","useSetOnGroup","isAlreadyGrouped","_updateObjectsACoords","_calcBounds","_updateObjectsCoords","_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","testContext","now","glOptions","premultipliedAlpha","depth","stencil","antialias","clearColor","cachedTexture","getCachedTexture","sourceTexture","createTexture","targetTexture","originalTexture","passes","webgl","programCache","pass","tempFbo","createFramebuffer","bindFramebuffer","FRAMEBUFFER","applyTo","resizeCanvasIfNeeded","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","originalEl","originalImageData","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","temp","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","srcData","destImg","destData","lanczos","ratioX","ratioY","rcpRatioX","rcpRatioY","range2X","range2Y","cacheLanc","icenter","process","u","weight","fX","fY","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","_char","previousChar","prevCharStyle","coupleWidth","previousWidth","fontCache","couple","stylesAreEqual","fontMultiplier","measureText","getHeightOfChar","measureLine","lineInfo","_measureLine","_getWidthOfCharSpacing","grapheme","prevGrapheme","graphemeInfo","startingPoint","totalPathLength","lineBounds","positionInPath","_getGraphemeBox","_setGraphemeOnPath","numOfSpaces","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","scaledDiff","textHeight","offX","objectCopy","textInstance","pathInstance","p3","cleanStyle","letterCount","stylePropertyValue","stylesCount","allStyleObjectPropertiesMatch","graphemeCount","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","realLineHeight","lineOffset","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","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","somethingAdded","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","keysMapRtl","ctrlKeysMapUp","ctrlKeysMapDown","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","getUpCursorOffset","textBeforeCursor","charWidth","foundMatch","widthOfCharsOnLine","indexOnLine","leftEdge","rightEdge","offsetFromLeftEdge","moveCursorDown","_moveCursorUpOrDown","moveCursorUp","moveCursorWithShift","moveCursorWithoutShift","moveCursorLeft","_moveCursorLeftOrRight","_move","_moveLeft","_moveRight","moveCursorLeftWithoutShift","change","moveCursorLeftWithShift","moveCursorRight","moveCursorRightWithShift","moveCursorRightWithoutShift","changed","removeChars","insertChars","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","lineTop","textSpans","textTopOffset","textLeftOffset","_setSVGTextLineBg","_setSVGTextLineText","_createTextCharSpan","styleDecl","shouldUseWhitespace","styleProps","fillStyles","dySpan","_pushTextBgRect","fillColor","_getSVGLineTopOffset","lastHeight","Textbox","minWidth","dynamicMinWidth","__cachedLines","_wordJoiners","splitByGrapheme","_styleMap","_generateStyleMap","textInfo","realLineCount","realLineCharCount","isWrapping","nextOffset","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","Function","base64","ieee754","kMaxLength","TYPED_ARRAY_SUPPORT","RangeError","__proto__","arg","encodingOrOffset","allocUnsafe","TypeError","byteOffset","byteLength","fromArrayLike","fromArrayBuffer","isEncoding","actual","write","fromString","isBuffer","checked","val","assertSize","isView","loweredCase","utf8ToBytes","base64ToBytes","slowToString","hexSlice","utf8Slice","asciiSlice","latin1Slice","base64Slice","utf16leSlice","bidirectionalIndexOf","dir","arrayIndexOf","lastIndexOf","indexSize","arrLength","valLength","read","buf","readUInt16BE","foundIndex","found","hexWrite","remaining","strLen","substr","utf8Write","blitBuffer","asciiWrite","byteArray","asciiToBytes","latin1Write","base64Write","ucs2Write","units","hi","lo","utf16leToBytes","fromByteArray","res","secondByte","thirdByte","fourthByte","tempCodePoint","firstByte","codePoint","bytesPerSequence","codePoints","MAX_ARGUMENTS_LENGTH","fromCharCode","decodeCodePointsArray","SlowBuffer","alloc","INSPECT_MAX_BYTES","foo","subarray","typedArraySupport","poolSize","_augment","Symbol","species","configurable","allocUnsafeSlow","_isBuffer","compare","list","swap16","swap32","swap64","equals","inspect","thisStart","thisEnd","thisCopy","targetCopy","isFinite","_arr","ret","bytes","checkOffset","checkInt","objectWriteUInt16","littleEndian","objectWriteUInt32","checkIEEE754","writeFloat","noAssert","writeDouble","newBuf","sliceLen","readUIntLE","mul","readUIntBE","readUInt8","readUInt16LE","readUInt32LE","readUInt32BE","readIntLE","readIntBE","readInt8","readInt16LE","readInt16BE","readInt32LE","readInt32BE","readFloatLE","readFloatBE","readDoubleLE","readDoubleBE","writeUIntLE","writeUIntBE","writeUInt8","writeUInt16LE","writeUInt16BE","writeUInt32LE","writeUInt32BE","writeIntLE","limit","sub","writeIntBE","writeInt8","writeInt16LE","writeInt16BE","writeInt32LE","writeInt32BE","writeFloatLE","writeFloatBE","writeDoubleLE","writeDoubleBE","targetStart","INVALID_BASE64_RE","Infinity","leadSurrogate","toByteArray","stringtrim","base64clean","b64","lens","getLens","validLen","placeHoldersLen","tmp","Arr","_byteLength","curByte","revLookup","uint8","extraBytes","maxChunkLength","len2","encodeChunk","lookup","num","isLE","mLen","nBytes","eLen","eMax","eBias","nBits","NaN","rt","LN2"],"mappings":"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","file":"js/vendors~game~hello_react~kitchen_app~spriter_app~tile_editor_app-1b8e8786fb08603dbb36.chunk.js","sourcesContent":["module.exports = function(module) {\n\tif (!module.webpackPolyfill) {\n\t\tmodule.deprecate = function() {};\n\t\tmodule.paths = [];\n\t\t// module.parent = undefined by default\n\t\tif (!module.children) module.children = [];\n\t\tObject.defineProperty(module, \"loaded\", {\n\t\t\tenumerable: true,\n\t\t\tget: function() {\n\t\t\t\treturn module.l;\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(module, \"id\", {\n\t\t\tenumerable: true,\n\t\t\tget: function() {\n\t\t\t\treturn module.i;\n\t\t\t}\n\t\t});\n\t\tmodule.webpackPolyfill = 1;\n\t}\n\treturn module;\n};\n","/* 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.3.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 if (needsVpt) {\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n }\n object.render(ctx);\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 = 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.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 = this.canvas.getRetinaScaling(), matrix, p;\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 this.callSuper('_renderControls', ctx, styleOverride);\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 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 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 // if there is text background color no\n // other shadows should be casted\n this._removeShadow(ctx);\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);\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 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, callback, '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 somethingAdded = false,\n isEndOfLine = this._unwrappedTextLines[lineIndex].length === 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 somethingAdded = 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 (somethingAdded && !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) {\n // skip the last line of since we already prepared it.\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 * @return Number\n */\n missingNewlineOffset: function(lineIndex) {\n if (this.splitByGrapheme) {\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 return fabric.Object._fromObject('Textbox', objCopy, callback, '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","var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn this;\n})();\n\ntry {\n\t// This works if eval is allowed (see CSP)\n\tg = g || new Function(\"return this\")();\n} catch (e) {\n\t// This works if the window reference is available\n\tif (typeof window === \"object\") g = window;\n}\n\n// g can still be undefined, but nothing to do about it...\n// We return undefined, instead of nothing here, so it's\n// easier to handle this case. if(!global) { ...}\n\nmodule.exports = g;\n","/*!\n * The buffer module from node.js, for the browser.\n *\n * @author Feross Aboukhadijeh \n * @license MIT\n */\n/* eslint-disable no-proto */\n\n'use strict'\n\nvar base64 = require('base64-js')\nvar ieee754 = require('ieee754')\nvar isArray = require('isarray')\n\nexports.Buffer = Buffer\nexports.SlowBuffer = SlowBuffer\nexports.INSPECT_MAX_BYTES = 50\n\n/**\n * If `Buffer.TYPED_ARRAY_SUPPORT`:\n * === true Use Uint8Array implementation (fastest)\n * === false Use Object implementation (most compatible, even IE6)\n *\n * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,\n * Opera 11.6+, iOS 4.2+.\n *\n * Due to various browser bugs, sometimes the Object implementation will be used even\n * when the browser supports typed arrays.\n *\n * Note:\n *\n * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,\n * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.\n *\n * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.\n *\n * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of\n * incorrect length in some situations.\n\n * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they\n * get the Object implementation, which is slower but behaves correctly.\n */\nBuffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined\n ? global.TYPED_ARRAY_SUPPORT\n : typedArraySupport()\n\n/*\n * Export kMaxLength after typed array support is determined.\n */\nexports.kMaxLength = kMaxLength()\n\nfunction typedArraySupport () {\n try {\n var arr = new Uint8Array(1)\n arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}\n return arr.foo() === 42 && // typed array instances can be augmented\n typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`\n arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`\n } catch (e) {\n return false\n }\n}\n\nfunction kMaxLength () {\n return Buffer.TYPED_ARRAY_SUPPORT\n ? 0x7fffffff\n : 0x3fffffff\n}\n\nfunction createBuffer (that, length) {\n if (kMaxLength() < length) {\n throw new RangeError('Invalid typed array length')\n }\n if (Buffer.TYPED_ARRAY_SUPPORT) {\n // Return an augmented `Uint8Array` instance, for best performance\n that = new Uint8Array(length)\n that.__proto__ = Buffer.prototype\n } else {\n // Fallback: Return an object instance of the Buffer class\n if (that === null) {\n that = new Buffer(length)\n }\n that.length = length\n }\n\n return that\n}\n\n/**\n * The Buffer constructor returns instances of `Uint8Array` that have their\n * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of\n * `Uint8Array`, so the returned instances will have all the node `Buffer` methods\n * and the `Uint8Array` methods. Square bracket notation works as expected -- it\n * returns a single octet.\n *\n * The `Uint8Array` prototype remains unmodified.\n */\n\nfunction Buffer (arg, encodingOrOffset, length) {\n if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {\n return new Buffer(arg, encodingOrOffset, length)\n }\n\n // Common case.\n if (typeof arg === 'number') {\n if (typeof encodingOrOffset === 'string') {\n throw new Error(\n 'If encoding is specified then the first argument must be a string'\n )\n }\n return allocUnsafe(this, arg)\n }\n return from(this, arg, encodingOrOffset, length)\n}\n\nBuffer.poolSize = 8192 // not used by this implementation\n\n// TODO: Legacy, not needed anymore. Remove in next major version.\nBuffer._augment = function (arr) {\n arr.__proto__ = Buffer.prototype\n return arr\n}\n\nfunction from (that, value, encodingOrOffset, length) {\n if (typeof value === 'number') {\n throw new TypeError('\"value\" argument must not be a number')\n }\n\n if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {\n return fromArrayBuffer(that, value, encodingOrOffset, length)\n }\n\n if (typeof value === 'string') {\n return fromString(that, value, encodingOrOffset)\n }\n\n return fromObject(that, value)\n}\n\n/**\n * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError\n * if value is a number.\n * Buffer.from(str[, encoding])\n * Buffer.from(array)\n * Buffer.from(buffer)\n * Buffer.from(arrayBuffer[, byteOffset[, length]])\n **/\nBuffer.from = function (value, encodingOrOffset, length) {\n return from(null, value, encodingOrOffset, length)\n}\n\nif (Buffer.TYPED_ARRAY_SUPPORT) {\n Buffer.prototype.__proto__ = Uint8Array.prototype\n Buffer.__proto__ = Uint8Array\n if (typeof Symbol !== 'undefined' && Symbol.species &&\n Buffer[Symbol.species] === Buffer) {\n // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97\n Object.defineProperty(Buffer, Symbol.species, {\n value: null,\n configurable: true\n })\n }\n}\n\nfunction assertSize (size) {\n if (typeof size !== 'number') {\n throw new TypeError('\"size\" argument must be a number')\n } else if (size < 0) {\n throw new RangeError('\"size\" argument must not be negative')\n }\n}\n\nfunction alloc (that, size, fill, encoding) {\n assertSize(size)\n if (size <= 0) {\n return createBuffer(that, size)\n }\n if (fill !== undefined) {\n // Only pay attention to encoding if it's a string. This\n // prevents accidentally sending in a number that would\n // be interpretted as a start offset.\n return typeof encoding === 'string'\n ? createBuffer(that, size).fill(fill, encoding)\n : createBuffer(that, size).fill(fill)\n }\n return createBuffer(that, size)\n}\n\n/**\n * Creates a new filled Buffer instance.\n * alloc(size[, fill[, encoding]])\n **/\nBuffer.alloc = function (size, fill, encoding) {\n return alloc(null, size, fill, encoding)\n}\n\nfunction allocUnsafe (that, size) {\n assertSize(size)\n that = createBuffer(that, size < 0 ? 0 : checked(size) | 0)\n if (!Buffer.TYPED_ARRAY_SUPPORT) {\n for (var i = 0; i < size; ++i) {\n that[i] = 0\n }\n }\n return that\n}\n\n/**\n * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.\n * */\nBuffer.allocUnsafe = function (size) {\n return allocUnsafe(null, size)\n}\n/**\n * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.\n */\nBuffer.allocUnsafeSlow = function (size) {\n return allocUnsafe(null, size)\n}\n\nfunction fromString (that, string, encoding) {\n if (typeof encoding !== 'string' || encoding === '') {\n encoding = 'utf8'\n }\n\n if (!Buffer.isEncoding(encoding)) {\n throw new TypeError('\"encoding\" must be a valid string encoding')\n }\n\n var length = byteLength(string, encoding) | 0\n that = createBuffer(that, length)\n\n var actual = that.write(string, encoding)\n\n if (actual !== length) {\n // Writing a hex string, for example, that contains invalid characters will\n // cause everything after the first invalid character to be ignored. (e.g.\n // 'abxxcd' will be treated as 'ab')\n that = that.slice(0, actual)\n }\n\n return that\n}\n\nfunction fromArrayLike (that, array) {\n var length = array.length < 0 ? 0 : checked(array.length) | 0\n that = createBuffer(that, length)\n for (var i = 0; i < length; i += 1) {\n that[i] = array[i] & 255\n }\n return that\n}\n\nfunction fromArrayBuffer (that, array, byteOffset, length) {\n array.byteLength // this throws if `array` is not a valid ArrayBuffer\n\n if (byteOffset < 0 || array.byteLength < byteOffset) {\n throw new RangeError('\\'offset\\' is out of bounds')\n }\n\n if (array.byteLength < byteOffset + (length || 0)) {\n throw new RangeError('\\'length\\' is out of bounds')\n }\n\n if (byteOffset === undefined && length === undefined) {\n array = new Uint8Array(array)\n } else if (length === undefined) {\n array = new Uint8Array(array, byteOffset)\n } else {\n array = new Uint8Array(array, byteOffset, length)\n }\n\n if (Buffer.TYPED_ARRAY_SUPPORT) {\n // Return an augmented `Uint8Array` instance, for best performance\n that = array\n that.__proto__ = Buffer.prototype\n } else {\n // Fallback: Return an object instance of the Buffer class\n that = fromArrayLike(that, array)\n }\n return that\n}\n\nfunction fromObject (that, obj) {\n if (Buffer.isBuffer(obj)) {\n var len = checked(obj.length) | 0\n that = createBuffer(that, len)\n\n if (that.length === 0) {\n return that\n }\n\n obj.copy(that, 0, 0, len)\n return that\n }\n\n if (obj) {\n if ((typeof ArrayBuffer !== 'undefined' &&\n obj.buffer instanceof ArrayBuffer) || 'length' in obj) {\n if (typeof obj.length !== 'number' || isnan(obj.length)) {\n return createBuffer(that, 0)\n }\n return fromArrayLike(that, obj)\n }\n\n if (obj.type === 'Buffer' && isArray(obj.data)) {\n return fromArrayLike(that, obj.data)\n }\n }\n\n throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')\n}\n\nfunction checked (length) {\n // Note: cannot use `length < kMaxLength()` here because that fails when\n // length is NaN (which is otherwise coerced to zero.)\n if (length >= kMaxLength()) {\n throw new RangeError('Attempt to allocate Buffer larger than maximum ' +\n 'size: 0x' + kMaxLength().toString(16) + ' bytes')\n }\n return length | 0\n}\n\nfunction SlowBuffer (length) {\n if (+length != length) { // eslint-disable-line eqeqeq\n length = 0\n }\n return Buffer.alloc(+length)\n}\n\nBuffer.isBuffer = function isBuffer (b) {\n return !!(b != null && b._isBuffer)\n}\n\nBuffer.compare = function compare (a, b) {\n if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {\n throw new TypeError('Arguments must be Buffers')\n }\n\n if (a === b) return 0\n\n var x = a.length\n var y = b.length\n\n for (var i = 0, len = Math.min(x, y); i < len; ++i) {\n if (a[i] !== b[i]) {\n x = a[i]\n y = b[i]\n break\n }\n }\n\n if (x < y) return -1\n if (y < x) return 1\n return 0\n}\n\nBuffer.isEncoding = function isEncoding (encoding) {\n switch (String(encoding).toLowerCase()) {\n case 'hex':\n case 'utf8':\n case 'utf-8':\n case 'ascii':\n case 'latin1':\n case 'binary':\n case 'base64':\n case 'ucs2':\n case 'ucs-2':\n case 'utf16le':\n case 'utf-16le':\n return true\n default:\n return false\n }\n}\n\nBuffer.concat = function concat (list, length) {\n if (!isArray(list)) {\n throw new TypeError('\"list\" argument must be an Array of Buffers')\n }\n\n if (list.length === 0) {\n return Buffer.alloc(0)\n }\n\n var i\n if (length === undefined) {\n length = 0\n for (i = 0; i < list.length; ++i) {\n length += list[i].length\n }\n }\n\n var buffer = Buffer.allocUnsafe(length)\n var pos = 0\n for (i = 0; i < list.length; ++i) {\n var buf = list[i]\n if (!Buffer.isBuffer(buf)) {\n throw new TypeError('\"list\" argument must be an Array of Buffers')\n }\n buf.copy(buffer, pos)\n pos += buf.length\n }\n return buffer\n}\n\nfunction byteLength (string, encoding) {\n if (Buffer.isBuffer(string)) {\n return string.length\n }\n if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' &&\n (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) {\n return string.byteLength\n }\n if (typeof string !== 'string') {\n string = '' + string\n }\n\n var len = string.length\n if (len === 0) return 0\n\n // Use a for loop to avoid recursion\n var loweredCase = false\n for (;;) {\n switch (encoding) {\n case 'ascii':\n case 'latin1':\n case 'binary':\n return len\n case 'utf8':\n case 'utf-8':\n case undefined:\n return utf8ToBytes(string).length\n case 'ucs2':\n case 'ucs-2':\n case 'utf16le':\n case 'utf-16le':\n return len * 2\n case 'hex':\n return len >>> 1\n case 'base64':\n return base64ToBytes(string).length\n default:\n if (loweredCase) return utf8ToBytes(string).length // assume utf8\n encoding = ('' + encoding).toLowerCase()\n loweredCase = true\n }\n }\n}\nBuffer.byteLength = byteLength\n\nfunction slowToString (encoding, start, end) {\n var loweredCase = false\n\n // No need to verify that \"this.length <= MAX_UINT32\" since it's a read-only\n // property of a typed array.\n\n // This behaves neither like String nor Uint8Array in that we set start/end\n // to their upper/lower bounds if the value passed is out of range.\n // undefined is handled specially as per ECMA-262 6th Edition,\n // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.\n if (start === undefined || start < 0) {\n start = 0\n }\n // Return early if start > this.length. Done here to prevent potential uint32\n // coercion fail below.\n if (start > this.length) {\n return ''\n }\n\n if (end === undefined || end > this.length) {\n end = this.length\n }\n\n if (end <= 0) {\n return ''\n }\n\n // Force coersion to uint32. This will also coerce falsey/NaN values to 0.\n end >>>= 0\n start >>>= 0\n\n if (end <= start) {\n return ''\n }\n\n if (!encoding) encoding = 'utf8'\n\n while (true) {\n switch (encoding) {\n case 'hex':\n return hexSlice(this, start, end)\n\n case 'utf8':\n case 'utf-8':\n return utf8Slice(this, start, end)\n\n case 'ascii':\n return asciiSlice(this, start, end)\n\n case 'latin1':\n case 'binary':\n return latin1Slice(this, start, end)\n\n case 'base64':\n return base64Slice(this, start, end)\n\n case 'ucs2':\n case 'ucs-2':\n case 'utf16le':\n case 'utf-16le':\n return utf16leSlice(this, start, end)\n\n default:\n if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)\n encoding = (encoding + '').toLowerCase()\n loweredCase = true\n }\n }\n}\n\n// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect\n// Buffer instances.\nBuffer.prototype._isBuffer = true\n\nfunction swap (b, n, m) {\n var i = b[n]\n b[n] = b[m]\n b[m] = i\n}\n\nBuffer.prototype.swap16 = function swap16 () {\n var len = this.length\n if (len % 2 !== 0) {\n throw new RangeError('Buffer size must be a multiple of 16-bits')\n }\n for (var i = 0; i < len; i += 2) {\n swap(this, i, i + 1)\n }\n return this\n}\n\nBuffer.prototype.swap32 = function swap32 () {\n var len = this.length\n if (len % 4 !== 0) {\n throw new RangeError('Buffer size must be a multiple of 32-bits')\n }\n for (var i = 0; i < len; i += 4) {\n swap(this, i, i + 3)\n swap(this, i + 1, i + 2)\n }\n return this\n}\n\nBuffer.prototype.swap64 = function swap64 () {\n var len = this.length\n if (len % 8 !== 0) {\n throw new RangeError('Buffer size must be a multiple of 64-bits')\n }\n for (var i = 0; i < len; i += 8) {\n swap(this, i, i + 7)\n swap(this, i + 1, i + 6)\n swap(this, i + 2, i + 5)\n swap(this, i + 3, i + 4)\n }\n return this\n}\n\nBuffer.prototype.toString = function toString () {\n var length = this.length | 0\n if (length === 0) return ''\n if (arguments.length === 0) return utf8Slice(this, 0, length)\n return slowToString.apply(this, arguments)\n}\n\nBuffer.prototype.equals = function equals (b) {\n if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')\n if (this === b) return true\n return Buffer.compare(this, b) === 0\n}\n\nBuffer.prototype.inspect = function inspect () {\n var str = ''\n var max = exports.INSPECT_MAX_BYTES\n if (this.length > 0) {\n str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')\n if (this.length > max) str += ' ... '\n }\n return ''\n}\n\nBuffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {\n if (!Buffer.isBuffer(target)) {\n throw new TypeError('Argument must be a Buffer')\n }\n\n if (start === undefined) {\n start = 0\n }\n if (end === undefined) {\n end = target ? target.length : 0\n }\n if (thisStart === undefined) {\n thisStart = 0\n }\n if (thisEnd === undefined) {\n thisEnd = this.length\n }\n\n if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {\n throw new RangeError('out of range index')\n }\n\n if (thisStart >= thisEnd && start >= end) {\n return 0\n }\n if (thisStart >= thisEnd) {\n return -1\n }\n if (start >= end) {\n return 1\n }\n\n start >>>= 0\n end >>>= 0\n thisStart >>>= 0\n thisEnd >>>= 0\n\n if (this === target) return 0\n\n var x = thisEnd - thisStart\n var y = end - start\n var len = Math.min(x, y)\n\n var thisCopy = this.slice(thisStart, thisEnd)\n var targetCopy = target.slice(start, end)\n\n for (var i = 0; i < len; ++i) {\n if (thisCopy[i] !== targetCopy[i]) {\n x = thisCopy[i]\n y = targetCopy[i]\n break\n }\n }\n\n if (x < y) return -1\n if (y < x) return 1\n return 0\n}\n\n// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,\n// OR the last index of `val` in `buffer` at offset <= `byteOffset`.\n//\n// Arguments:\n// - buffer - a Buffer to search\n// - val - a string, Buffer, or number\n// - byteOffset - an index into `buffer`; will be clamped to an int32\n// - encoding - an optional encoding, relevant is val is a string\n// - dir - true for indexOf, false for lastIndexOf\nfunction bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {\n // Empty buffer means no match\n if (buffer.length === 0) return -1\n\n // Normalize byteOffset\n if (typeof byteOffset === 'string') {\n encoding = byteOffset\n byteOffset = 0\n } else if (byteOffset > 0x7fffffff) {\n byteOffset = 0x7fffffff\n } else if (byteOffset < -0x80000000) {\n byteOffset = -0x80000000\n }\n byteOffset = +byteOffset // Coerce to Number.\n if (isNaN(byteOffset)) {\n // byteOffset: it it's undefined, null, NaN, \"foo\", etc, search whole buffer\n byteOffset = dir ? 0 : (buffer.length - 1)\n }\n\n // Normalize byteOffset: negative offsets start from the end of the buffer\n if (byteOffset < 0) byteOffset = buffer.length + byteOffset\n if (byteOffset >= buffer.length) {\n if (dir) return -1\n else byteOffset = buffer.length - 1\n } else if (byteOffset < 0) {\n if (dir) byteOffset = 0\n else return -1\n }\n\n // Normalize val\n if (typeof val === 'string') {\n val = Buffer.from(val, encoding)\n }\n\n // Finally, search either indexOf (if dir is true) or lastIndexOf\n if (Buffer.isBuffer(val)) {\n // Special case: looking for empty string/buffer always fails\n if (val.length === 0) {\n return -1\n }\n return arrayIndexOf(buffer, val, byteOffset, encoding, dir)\n } else if (typeof val === 'number') {\n val = val & 0xFF // Search for a byte value [0-255]\n if (Buffer.TYPED_ARRAY_SUPPORT &&\n typeof Uint8Array.prototype.indexOf === 'function') {\n if (dir) {\n return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)\n } else {\n return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)\n }\n }\n return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)\n }\n\n throw new TypeError('val must be string, number or Buffer')\n}\n\nfunction arrayIndexOf (arr, val, byteOffset, encoding, dir) {\n var indexSize = 1\n var arrLength = arr.length\n var valLength = val.length\n\n if (encoding !== undefined) {\n encoding = String(encoding).toLowerCase()\n if (encoding === 'ucs2' || encoding === 'ucs-2' ||\n encoding === 'utf16le' || encoding === 'utf-16le') {\n if (arr.length < 2 || val.length < 2) {\n return -1\n }\n indexSize = 2\n arrLength /= 2\n valLength /= 2\n byteOffset /= 2\n }\n }\n\n function read (buf, i) {\n if (indexSize === 1) {\n return buf[i]\n } else {\n return buf.readUInt16BE(i * indexSize)\n }\n }\n\n var i\n if (dir) {\n var foundIndex = -1\n for (i = byteOffset; i < arrLength; i++) {\n if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {\n if (foundIndex === -1) foundIndex = i\n if (i - foundIndex + 1 === valLength) return foundIndex * indexSize\n } else {\n if (foundIndex !== -1) i -= i - foundIndex\n foundIndex = -1\n }\n }\n } else {\n if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength\n for (i = byteOffset; i >= 0; i--) {\n var found = true\n for (var j = 0; j < valLength; j++) {\n if (read(arr, i + j) !== read(val, j)) {\n found = false\n break\n }\n }\n if (found) return i\n }\n }\n\n return -1\n}\n\nBuffer.prototype.includes = function includes (val, byteOffset, encoding) {\n return this.indexOf(val, byteOffset, encoding) !== -1\n}\n\nBuffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {\n return bidirectionalIndexOf(this, val, byteOffset, encoding, true)\n}\n\nBuffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {\n return bidirectionalIndexOf(this, val, byteOffset, encoding, false)\n}\n\nfunction hexWrite (buf, string, offset, length) {\n offset = Number(offset) || 0\n var remaining = buf.length - offset\n if (!length) {\n length = remaining\n } else {\n length = Number(length)\n if (length > remaining) {\n length = remaining\n }\n }\n\n // must be an even number of digits\n var strLen = string.length\n if (strLen % 2 !== 0) throw new TypeError('Invalid hex string')\n\n if (length > strLen / 2) {\n length = strLen / 2\n }\n for (var i = 0; i < length; ++i) {\n var parsed = parseInt(string.substr(i * 2, 2), 16)\n if (isNaN(parsed)) return i\n buf[offset + i] = parsed\n }\n return i\n}\n\nfunction utf8Write (buf, string, offset, length) {\n return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)\n}\n\nfunction asciiWrite (buf, string, offset, length) {\n return blitBuffer(asciiToBytes(string), buf, offset, length)\n}\n\nfunction latin1Write (buf, string, offset, length) {\n return asciiWrite(buf, string, offset, length)\n}\n\nfunction base64Write (buf, string, offset, length) {\n return blitBuffer(base64ToBytes(string), buf, offset, length)\n}\n\nfunction ucs2Write (buf, string, offset, length) {\n return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)\n}\n\nBuffer.prototype.write = function write (string, offset, length, encoding) {\n // Buffer#write(string)\n if (offset === undefined) {\n encoding = 'utf8'\n length = this.length\n offset = 0\n // Buffer#write(string, encoding)\n } else if (length === undefined && typeof offset === 'string') {\n encoding = offset\n length = this.length\n offset = 0\n // Buffer#write(string, offset[, length][, encoding])\n } else if (isFinite(offset)) {\n offset = offset | 0\n if (isFinite(length)) {\n length = length | 0\n if (encoding === undefined) encoding = 'utf8'\n } else {\n encoding = length\n length = undefined\n }\n // legacy write(string, encoding, offset, length) - remove in v0.13\n } else {\n throw new Error(\n 'Buffer.write(string, encoding, offset[, length]) is no longer supported'\n )\n }\n\n var remaining = this.length - offset\n if (length === undefined || length > remaining) length = remaining\n\n if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {\n throw new RangeError('Attempt to write outside buffer bounds')\n }\n\n if (!encoding) encoding = 'utf8'\n\n var loweredCase = false\n for (;;) {\n switch (encoding) {\n case 'hex':\n return hexWrite(this, string, offset, length)\n\n case 'utf8':\n case 'utf-8':\n return utf8Write(this, string, offset, length)\n\n case 'ascii':\n return asciiWrite(this, string, offset, length)\n\n case 'latin1':\n case 'binary':\n return latin1Write(this, string, offset, length)\n\n case 'base64':\n // Warning: maxLength not taken into account in base64Write\n return base64Write(this, string, offset, length)\n\n case 'ucs2':\n case 'ucs-2':\n case 'utf16le':\n case 'utf-16le':\n return ucs2Write(this, string, offset, length)\n\n default:\n if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)\n encoding = ('' + encoding).toLowerCase()\n loweredCase = true\n }\n }\n}\n\nBuffer.prototype.toJSON = function toJSON () {\n return {\n type: 'Buffer',\n data: Array.prototype.slice.call(this._arr || this, 0)\n }\n}\n\nfunction base64Slice (buf, start, end) {\n if (start === 0 && end === buf.length) {\n return base64.fromByteArray(buf)\n } else {\n return base64.fromByteArray(buf.slice(start, end))\n }\n}\n\nfunction utf8Slice (buf, start, end) {\n end = Math.min(buf.length, end)\n var res = []\n\n var i = start\n while (i < end) {\n var firstByte = buf[i]\n var codePoint = null\n var bytesPerSequence = (firstByte > 0xEF) ? 4\n : (firstByte > 0xDF) ? 3\n : (firstByte > 0xBF) ? 2\n : 1\n\n if (i + bytesPerSequence <= end) {\n var secondByte, thirdByte, fourthByte, tempCodePoint\n\n switch (bytesPerSequence) {\n case 1:\n if (firstByte < 0x80) {\n codePoint = firstByte\n }\n break\n case 2:\n secondByte = buf[i + 1]\n if ((secondByte & 0xC0) === 0x80) {\n tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)\n if (tempCodePoint > 0x7F) {\n codePoint = tempCodePoint\n }\n }\n break\n case 3:\n secondByte = buf[i + 1]\n thirdByte = buf[i + 2]\n if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {\n tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)\n if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {\n codePoint = tempCodePoint\n }\n }\n break\n case 4:\n secondByte = buf[i + 1]\n thirdByte = buf[i + 2]\n fourthByte = buf[i + 3]\n if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {\n tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)\n if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {\n codePoint = tempCodePoint\n }\n }\n }\n }\n\n if (codePoint === null) {\n // we did not generate a valid codePoint so insert a\n // replacement char (U+FFFD) and advance only 1 byte\n codePoint = 0xFFFD\n bytesPerSequence = 1\n } else if (codePoint > 0xFFFF) {\n // encode to utf16 (surrogate pair dance)\n codePoint -= 0x10000\n res.push(codePoint >>> 10 & 0x3FF | 0xD800)\n codePoint = 0xDC00 | codePoint & 0x3FF\n }\n\n res.push(codePoint)\n i += bytesPerSequence\n }\n\n return decodeCodePointsArray(res)\n}\n\n// Based on http://stackoverflow.com/a/22747272/680742, the browser with\n// the lowest limit is Chrome, with 0x10000 args.\n// We go 1 magnitude less, for safety\nvar MAX_ARGUMENTS_LENGTH = 0x1000\n\nfunction decodeCodePointsArray (codePoints) {\n var len = codePoints.length\n if (len <= MAX_ARGUMENTS_LENGTH) {\n return String.fromCharCode.apply(String, codePoints) // avoid extra slice()\n }\n\n // Decode in chunks to avoid \"call stack size exceeded\".\n var res = ''\n var i = 0\n while (i < len) {\n res += String.fromCharCode.apply(\n String,\n codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)\n )\n }\n return res\n}\n\nfunction asciiSlice (buf, start, end) {\n var ret = ''\n end = Math.min(buf.length, end)\n\n for (var i = start; i < end; ++i) {\n ret += String.fromCharCode(buf[i] & 0x7F)\n }\n return ret\n}\n\nfunction latin1Slice (buf, start, end) {\n var ret = ''\n end = Math.min(buf.length, end)\n\n for (var i = start; i < end; ++i) {\n ret += String.fromCharCode(buf[i])\n }\n return ret\n}\n\nfunction hexSlice (buf, start, end) {\n var len = buf.length\n\n if (!start || start < 0) start = 0\n if (!end || end < 0 || end > len) end = len\n\n var out = ''\n for (var i = start; i < end; ++i) {\n out += toHex(buf[i])\n }\n return out\n}\n\nfunction utf16leSlice (buf, start, end) {\n var bytes = buf.slice(start, end)\n var res = ''\n for (var i = 0; i < bytes.length; i += 2) {\n res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)\n }\n return res\n}\n\nBuffer.prototype.slice = function slice (start, end) {\n var len = this.length\n start = ~~start\n end = end === undefined ? len : ~~end\n\n if (start < 0) {\n start += len\n if (start < 0) start = 0\n } else if (start > len) {\n start = len\n }\n\n if (end < 0) {\n end += len\n if (end < 0) end = 0\n } else if (end > len) {\n end = len\n }\n\n if (end < start) end = start\n\n var newBuf\n if (Buffer.TYPED_ARRAY_SUPPORT) {\n newBuf = this.subarray(start, end)\n newBuf.__proto__ = Buffer.prototype\n } else {\n var sliceLen = end - start\n newBuf = new Buffer(sliceLen, undefined)\n for (var i = 0; i < sliceLen; ++i) {\n newBuf[i] = this[i + start]\n }\n }\n\n return newBuf\n}\n\n/*\n * Need to make sure that buffer isn't trying to write out of bounds.\n */\nfunction checkOffset (offset, ext, length) {\n if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')\n if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')\n}\n\nBuffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {\n offset = offset | 0\n byteLength = byteLength | 0\n if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n var val = this[offset]\n var mul = 1\n var i = 0\n while (++i < byteLength && (mul *= 0x100)) {\n val += this[offset + i] * mul\n }\n\n return val\n}\n\nBuffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {\n offset = offset | 0\n byteLength = byteLength | 0\n if (!noAssert) {\n checkOffset(offset, byteLength, this.length)\n }\n\n var val = this[offset + --byteLength]\n var mul = 1\n while (byteLength > 0 && (mul *= 0x100)) {\n val += this[offset + --byteLength] * mul\n }\n\n return val\n}\n\nBuffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 1, this.length)\n return this[offset]\n}\n\nBuffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 2, this.length)\n return this[offset] | (this[offset + 1] << 8)\n}\n\nBuffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 2, this.length)\n return (this[offset] << 8) | this[offset + 1]\n}\n\nBuffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 4, this.length)\n\n return ((this[offset]) |\n (this[offset + 1] << 8) |\n (this[offset + 2] << 16)) +\n (this[offset + 3] * 0x1000000)\n}\n\nBuffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 4, this.length)\n\n return (this[offset] * 0x1000000) +\n ((this[offset + 1] << 16) |\n (this[offset + 2] << 8) |\n this[offset + 3])\n}\n\nBuffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {\n offset = offset | 0\n byteLength = byteLength | 0\n if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n var val = this[offset]\n var mul = 1\n var i = 0\n while (++i < byteLength && (mul *= 0x100)) {\n val += this[offset + i] * mul\n }\n mul *= 0x80\n\n if (val >= mul) val -= Math.pow(2, 8 * byteLength)\n\n return val\n}\n\nBuffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {\n offset = offset | 0\n byteLength = byteLength | 0\n if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n var i = byteLength\n var mul = 1\n var val = this[offset + --i]\n while (i > 0 && (mul *= 0x100)) {\n val += this[offset + --i] * mul\n }\n mul *= 0x80\n\n if (val >= mul) val -= Math.pow(2, 8 * byteLength)\n\n return val\n}\n\nBuffer.prototype.readInt8 = function readInt8 (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 1, this.length)\n if (!(this[offset] & 0x80)) return (this[offset])\n return ((0xff - this[offset] + 1) * -1)\n}\n\nBuffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 2, this.length)\n var val = this[offset] | (this[offset + 1] << 8)\n return (val & 0x8000) ? val | 0xFFFF0000 : val\n}\n\nBuffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 2, this.length)\n var val = this[offset + 1] | (this[offset] << 8)\n return (val & 0x8000) ? val | 0xFFFF0000 : val\n}\n\nBuffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 4, this.length)\n\n return (this[offset]) |\n (this[offset + 1] << 8) |\n (this[offset + 2] << 16) |\n (this[offset + 3] << 24)\n}\n\nBuffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 4, this.length)\n\n return (this[offset] << 24) |\n (this[offset + 1] << 16) |\n (this[offset + 2] << 8) |\n (this[offset + 3])\n}\n\nBuffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 4, this.length)\n return ieee754.read(this, offset, true, 23, 4)\n}\n\nBuffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 4, this.length)\n return ieee754.read(this, offset, false, 23, 4)\n}\n\nBuffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 8, this.length)\n return ieee754.read(this, offset, true, 52, 8)\n}\n\nBuffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {\n if (!noAssert) checkOffset(offset, 8, this.length)\n return ieee754.read(this, offset, false, 52, 8)\n}\n\nfunction checkInt (buf, value, offset, ext, max, min) {\n if (!Buffer.isBuffer(buf)) throw new TypeError('\"buffer\" argument must be a Buffer instance')\n if (value > max || value < min) throw new RangeError('\"value\" argument is out of bounds')\n if (offset + ext > buf.length) throw new RangeError('Index out of range')\n}\n\nBuffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {\n value = +value\n offset = offset | 0\n byteLength = byteLength | 0\n if (!noAssert) {\n var maxBytes = Math.pow(2, 8 * byteLength) - 1\n checkInt(this, value, offset, byteLength, maxBytes, 0)\n }\n\n var mul = 1\n var i = 0\n this[offset] = value & 0xFF\n while (++i < byteLength && (mul *= 0x100)) {\n this[offset + i] = (value / mul) & 0xFF\n }\n\n return offset + byteLength\n}\n\nBuffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {\n value = +value\n offset = offset | 0\n byteLength = byteLength | 0\n if (!noAssert) {\n var maxBytes = Math.pow(2, 8 * byteLength) - 1\n checkInt(this, value, offset, byteLength, maxBytes, 0)\n }\n\n var i = byteLength - 1\n var mul = 1\n this[offset + i] = value & 0xFF\n while (--i >= 0 && (mul *= 0x100)) {\n this[offset + i] = (value / mul) & 0xFF\n }\n\n return offset + byteLength\n}\n\nBuffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {\n value = +value\n offset = offset | 0\n if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)\n if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)\n this[offset] = (value & 0xff)\n return offset + 1\n}\n\nfunction objectWriteUInt16 (buf, value, offset, littleEndian) {\n if (value < 0) value = 0xffff + value + 1\n for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) {\n buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>\n (littleEndian ? i : 1 - i) * 8\n }\n}\n\nBuffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {\n value = +value\n offset = offset | 0\n if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)\n if (Buffer.TYPED_ARRAY_SUPPORT) {\n this[offset] = (value & 0xff)\n this[offset + 1] = (value >>> 8)\n } else {\n objectWriteUInt16(this, value, offset, true)\n }\n return offset + 2\n}\n\nBuffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {\n value = +value\n offset = offset | 0\n if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)\n if (Buffer.TYPED_ARRAY_SUPPORT) {\n this[offset] = (value >>> 8)\n this[offset + 1] = (value & 0xff)\n } else {\n objectWriteUInt16(this, value, offset, false)\n }\n return offset + 2\n}\n\nfunction objectWriteUInt32 (buf, value, offset, littleEndian) {\n if (value < 0) value = 0xffffffff + value + 1\n for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) {\n buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff\n }\n}\n\nBuffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {\n value = +value\n offset = offset | 0\n if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)\n if (Buffer.TYPED_ARRAY_SUPPORT) {\n this[offset + 3] = (value >>> 24)\n this[offset + 2] = (value >>> 16)\n this[offset + 1] = (value >>> 8)\n this[offset] = (value & 0xff)\n } else {\n objectWriteUInt32(this, value, offset, true)\n }\n return offset + 4\n}\n\nBuffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {\n value = +value\n offset = offset | 0\n if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)\n if (Buffer.TYPED_ARRAY_SUPPORT) {\n this[offset] = (value >>> 24)\n this[offset + 1] = (value >>> 16)\n this[offset + 2] = (value >>> 8)\n this[offset + 3] = (value & 0xff)\n } else {\n objectWriteUInt32(this, value, offset, false)\n }\n return offset + 4\n}\n\nBuffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {\n value = +value\n offset = offset | 0\n if (!noAssert) {\n var limit = Math.pow(2, 8 * byteLength - 1)\n\n checkInt(this, value, offset, byteLength, limit - 1, -limit)\n }\n\n var i = 0\n var mul = 1\n var sub = 0\n this[offset] = value & 0xFF\n while (++i < byteLength && (mul *= 0x100)) {\n if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {\n sub = 1\n }\n this[offset + i] = ((value / mul) >> 0) - sub & 0xFF\n }\n\n return offset + byteLength\n}\n\nBuffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {\n value = +value\n offset = offset | 0\n if (!noAssert) {\n var limit = Math.pow(2, 8 * byteLength - 1)\n\n checkInt(this, value, offset, byteLength, limit - 1, -limit)\n }\n\n var i = byteLength - 1\n var mul = 1\n var sub = 0\n this[offset + i] = value & 0xFF\n while (--i >= 0 && (mul *= 0x100)) {\n if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {\n sub = 1\n }\n this[offset + i] = ((value / mul) >> 0) - sub & 0xFF\n }\n\n return offset + byteLength\n}\n\nBuffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {\n value = +value\n offset = offset | 0\n if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)\n if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)\n if (value < 0) value = 0xff + value + 1\n this[offset] = (value & 0xff)\n return offset + 1\n}\n\nBuffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {\n value = +value\n offset = offset | 0\n if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)\n if (Buffer.TYPED_ARRAY_SUPPORT) {\n this[offset] = (value & 0xff)\n this[offset + 1] = (value >>> 8)\n } else {\n objectWriteUInt16(this, value, offset, true)\n }\n return offset + 2\n}\n\nBuffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {\n value = +value\n offset = offset | 0\n if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)\n if (Buffer.TYPED_ARRAY_SUPPORT) {\n this[offset] = (value >>> 8)\n this[offset + 1] = (value & 0xff)\n } else {\n objectWriteUInt16(this, value, offset, false)\n }\n return offset + 2\n}\n\nBuffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {\n value = +value\n offset = offset | 0\n if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)\n if (Buffer.TYPED_ARRAY_SUPPORT) {\n this[offset] = (value & 0xff)\n this[offset + 1] = (value >>> 8)\n this[offset + 2] = (value >>> 16)\n this[offset + 3] = (value >>> 24)\n } else {\n objectWriteUInt32(this, value, offset, true)\n }\n return offset + 4\n}\n\nBuffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {\n value = +value\n offset = offset | 0\n if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)\n if (value < 0) value = 0xffffffff + value + 1\n if (Buffer.TYPED_ARRAY_SUPPORT) {\n this[offset] = (value >>> 24)\n this[offset + 1] = (value >>> 16)\n this[offset + 2] = (value >>> 8)\n this[offset + 3] = (value & 0xff)\n } else {\n objectWriteUInt32(this, value, offset, false)\n }\n return offset + 4\n}\n\nfunction checkIEEE754 (buf, value, offset, ext, max, min) {\n if (offset + ext > buf.length) throw new RangeError('Index out of range')\n if (offset < 0) throw new RangeError('Index out of range')\n}\n\nfunction writeFloat (buf, value, offset, littleEndian, noAssert) {\n if (!noAssert) {\n checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)\n }\n ieee754.write(buf, value, offset, littleEndian, 23, 4)\n return offset + 4\n}\n\nBuffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {\n return writeFloat(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {\n return writeFloat(this, value, offset, false, noAssert)\n}\n\nfunction writeDouble (buf, value, offset, littleEndian, noAssert) {\n if (!noAssert) {\n checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)\n }\n ieee754.write(buf, value, offset, littleEndian, 52, 8)\n return offset + 8\n}\n\nBuffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {\n return writeDouble(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {\n return writeDouble(this, value, offset, false, noAssert)\n}\n\n// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)\nBuffer.prototype.copy = function copy (target, targetStart, start, end) {\n if (!start) start = 0\n if (!end && end !== 0) end = this.length\n if (targetStart >= target.length) targetStart = target.length\n if (!targetStart) targetStart = 0\n if (end > 0 && end < start) end = start\n\n // Copy 0 bytes; we're done\n if (end === start) return 0\n if (target.length === 0 || this.length === 0) return 0\n\n // Fatal error conditions\n if (targetStart < 0) {\n throw new RangeError('targetStart out of bounds')\n }\n if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')\n if (end < 0) throw new RangeError('sourceEnd out of bounds')\n\n // Are we oob?\n if (end > this.length) end = this.length\n if (target.length - targetStart < end - start) {\n end = target.length - targetStart + start\n }\n\n var len = end - start\n var i\n\n if (this === target && start < targetStart && targetStart < end) {\n // descending copy from end\n for (i = len - 1; i >= 0; --i) {\n target[i + targetStart] = this[i + start]\n }\n } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {\n // ascending copy from start\n for (i = 0; i < len; ++i) {\n target[i + targetStart] = this[i + start]\n }\n } else {\n Uint8Array.prototype.set.call(\n target,\n this.subarray(start, start + len),\n targetStart\n )\n }\n\n return len\n}\n\n// Usage:\n// buffer.fill(number[, offset[, end]])\n// buffer.fill(buffer[, offset[, end]])\n// buffer.fill(string[, offset[, end]][, encoding])\nBuffer.prototype.fill = function fill (val, start, end, encoding) {\n // Handle string cases:\n if (typeof val === 'string') {\n if (typeof start === 'string') {\n encoding = start\n start = 0\n end = this.length\n } else if (typeof end === 'string') {\n encoding = end\n end = this.length\n }\n if (val.length === 1) {\n var code = val.charCodeAt(0)\n if (code < 256) {\n val = code\n }\n }\n if (encoding !== undefined && typeof encoding !== 'string') {\n throw new TypeError('encoding must be a string')\n }\n if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {\n throw new TypeError('Unknown encoding: ' + encoding)\n }\n } else if (typeof val === 'number') {\n val = val & 255\n }\n\n // Invalid ranges are not set to a default, so can range check early.\n if (start < 0 || this.length < start || this.length < end) {\n throw new RangeError('Out of range index')\n }\n\n if (end <= start) {\n return this\n }\n\n start = start >>> 0\n end = end === undefined ? this.length : end >>> 0\n\n if (!val) val = 0\n\n var i\n if (typeof val === 'number') {\n for (i = start; i < end; ++i) {\n this[i] = val\n }\n } else {\n var bytes = Buffer.isBuffer(val)\n ? val\n : utf8ToBytes(new Buffer(val, encoding).toString())\n var len = bytes.length\n for (i = 0; i < end - start; ++i) {\n this[i + start] = bytes[i % len]\n }\n }\n\n return this\n}\n\n// HELPER FUNCTIONS\n// ================\n\nvar INVALID_BASE64_RE = /[^+\\/0-9A-Za-z-_]/g\n\nfunction base64clean (str) {\n // Node strips out invalid characters like \\n and \\t from the string, base64-js does not\n str = stringtrim(str).replace(INVALID_BASE64_RE, '')\n // Node converts strings with length < 2 to ''\n if (str.length < 2) return ''\n // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not\n while (str.length % 4 !== 0) {\n str = str + '='\n }\n return str\n}\n\nfunction stringtrim (str) {\n if (str.trim) return str.trim()\n return str.replace(/^\\s+|\\s+$/g, '')\n}\n\nfunction toHex (n) {\n if (n < 16) return '0' + n.toString(16)\n return n.toString(16)\n}\n\nfunction utf8ToBytes (string, units) {\n units = units || Infinity\n var codePoint\n var length = string.length\n var leadSurrogate = null\n var bytes = []\n\n for (var i = 0; i < length; ++i) {\n codePoint = string.charCodeAt(i)\n\n // is surrogate component\n if (codePoint > 0xD7FF && codePoint < 0xE000) {\n // last char was a lead\n if (!leadSurrogate) {\n // no lead yet\n if (codePoint > 0xDBFF) {\n // unexpected trail\n if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n continue\n } else if (i + 1 === length) {\n // unpaired lead\n if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n continue\n }\n\n // valid lead\n leadSurrogate = codePoint\n\n continue\n }\n\n // 2 leads in a row\n if (codePoint < 0xDC00) {\n if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n leadSurrogate = codePoint\n continue\n }\n\n // valid surrogate pair\n codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000\n } else if (leadSurrogate) {\n // valid bmp char, but last char was a lead\n if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n }\n\n leadSurrogate = null\n\n // encode utf8\n if (codePoint < 0x80) {\n if ((units -= 1) < 0) break\n bytes.push(codePoint)\n } else if (codePoint < 0x800) {\n if ((units -= 2) < 0) break\n bytes.push(\n codePoint >> 0x6 | 0xC0,\n codePoint & 0x3F | 0x80\n )\n } else if (codePoint < 0x10000) {\n if ((units -= 3) < 0) break\n bytes.push(\n codePoint >> 0xC | 0xE0,\n codePoint >> 0x6 & 0x3F | 0x80,\n codePoint & 0x3F | 0x80\n )\n } else if (codePoint < 0x110000) {\n if ((units -= 4) < 0) break\n bytes.push(\n codePoint >> 0x12 | 0xF0,\n codePoint >> 0xC & 0x3F | 0x80,\n codePoint >> 0x6 & 0x3F | 0x80,\n codePoint & 0x3F | 0x80\n )\n } else {\n throw new Error('Invalid code point')\n }\n }\n\n return bytes\n}\n\nfunction asciiToBytes (str) {\n var byteArray = []\n for (var i = 0; i < str.length; ++i) {\n // Node's code seems to be doing this and not & 0x7F..\n byteArray.push(str.charCodeAt(i) & 0xFF)\n }\n return byteArray\n}\n\nfunction utf16leToBytes (str, units) {\n var c, hi, lo\n var byteArray = []\n for (var i = 0; i < str.length; ++i) {\n if ((units -= 2) < 0) break\n\n c = str.charCodeAt(i)\n hi = c >> 8\n lo = c % 256\n byteArray.push(lo)\n byteArray.push(hi)\n }\n\n return byteArray\n}\n\nfunction base64ToBytes (str) {\n return base64.toByteArray(base64clean(str))\n}\n\nfunction blitBuffer (src, dst, offset, length) {\n for (var i = 0; i < length; ++i) {\n if ((i + offset >= dst.length) || (i >= src.length)) break\n dst[i + offset] = src[i]\n }\n return i\n}\n\nfunction isnan (val) {\n return val !== val // eslint-disable-line no-self-compare\n}\n","'use strict'\n\nexports.byteLength = byteLength\nexports.toByteArray = toByteArray\nexports.fromByteArray = fromByteArray\n\nvar lookup = []\nvar revLookup = []\nvar Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array\n\nvar code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nfor (var i = 0, len = code.length; i < len; ++i) {\n lookup[i] = code[i]\n revLookup[code.charCodeAt(i)] = i\n}\n\n// Support decoding URL-safe base64 strings, as Node.js does.\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\nrevLookup['-'.charCodeAt(0)] = 62\nrevLookup['_'.charCodeAt(0)] = 63\n\nfunction getLens (b64) {\n var len = b64.length\n\n if (len % 4 > 0) {\n throw new Error('Invalid string. Length must be a multiple of 4')\n }\n\n // Trim off extra bytes after placeholder bytes are found\n // See: https://github.com/beatgammit/base64-js/issues/42\n var validLen = b64.indexOf('=')\n if (validLen === -1) validLen = len\n\n var placeHoldersLen = validLen === len\n ? 0\n : 4 - (validLen % 4)\n\n return [validLen, placeHoldersLen]\n}\n\n// base64 is 4/3 + up to two characters of the original data\nfunction byteLength (b64) {\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction _byteLength (b64, validLen, placeHoldersLen) {\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction toByteArray (b64) {\n var tmp\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n\n var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))\n\n var curByte = 0\n\n // if there are placeholders, only get up to the last complete 4 chars\n var len = placeHoldersLen > 0\n ? validLen - 4\n : validLen\n\n var i\n for (i = 0; i < len; i += 4) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 18) |\n (revLookup[b64.charCodeAt(i + 1)] << 12) |\n (revLookup[b64.charCodeAt(i + 2)] << 6) |\n revLookup[b64.charCodeAt(i + 3)]\n arr[curByte++] = (tmp >> 16) & 0xFF\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 2) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 2) |\n (revLookup[b64.charCodeAt(i + 1)] >> 4)\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 1) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 10) |\n (revLookup[b64.charCodeAt(i + 1)] << 4) |\n (revLookup[b64.charCodeAt(i + 2)] >> 2)\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n return arr\n}\n\nfunction tripletToBase64 (num) {\n return lookup[num >> 18 & 0x3F] +\n lookup[num >> 12 & 0x3F] +\n lookup[num >> 6 & 0x3F] +\n lookup[num & 0x3F]\n}\n\nfunction encodeChunk (uint8, start, end) {\n var tmp\n var output = []\n for (var i = start; i < end; i += 3) {\n tmp =\n ((uint8[i] << 16) & 0xFF0000) +\n ((uint8[i + 1] << 8) & 0xFF00) +\n (uint8[i + 2] & 0xFF)\n output.push(tripletToBase64(tmp))\n }\n return output.join('')\n}\n\nfunction fromByteArray (uint8) {\n var tmp\n var len = uint8.length\n var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes\n var parts = []\n var maxChunkLength = 16383 // must be multiple of 3\n\n // go through the array every three bytes, we'll deal with trailing stuff later\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))\n }\n\n // pad the end with zeros, but make sure to not forget the extra bytes\n if (extraBytes === 1) {\n tmp = uint8[len - 1]\n parts.push(\n lookup[tmp >> 2] +\n lookup[(tmp << 4) & 0x3F] +\n '=='\n )\n } else if (extraBytes === 2) {\n tmp = (uint8[len - 2] << 8) + uint8[len - 1]\n parts.push(\n lookup[tmp >> 10] +\n lookup[(tmp >> 4) & 0x3F] +\n lookup[(tmp << 2) & 0x3F] +\n '='\n )\n }\n\n return parts.join('')\n}\n","/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */\nexports.read = function (buffer, offset, isLE, mLen, nBytes) {\n var e, m\n var eLen = (nBytes * 8) - mLen - 1\n var eMax = (1 << eLen) - 1\n var eBias = eMax >> 1\n var nBits = -7\n var i = isLE ? (nBytes - 1) : 0\n var d = isLE ? -1 : 1\n var s = buffer[offset + i]\n\n i += d\n\n e = s & ((1 << (-nBits)) - 1)\n s >>= (-nBits)\n nBits += eLen\n for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}\n\n m = e & ((1 << (-nBits)) - 1)\n e >>= (-nBits)\n nBits += mLen\n for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}\n\n if (e === 0) {\n e = 1 - eBias\n } else if (e === eMax) {\n return m ? NaN : ((s ? -1 : 1) * Infinity)\n } else {\n m = m + Math.pow(2, mLen)\n e = e - eBias\n }\n return (s ? -1 : 1) * m * Math.pow(2, e - mLen)\n}\n\nexports.write = function (buffer, value, offset, isLE, mLen, nBytes) {\n var e, m, c\n var eLen = (nBytes * 8) - mLen - 1\n var eMax = (1 << eLen) - 1\n var eBias = eMax >> 1\n var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)\n var i = isLE ? 0 : (nBytes - 1)\n var d = isLE ? 1 : -1\n var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0\n\n value = Math.abs(value)\n\n if (isNaN(value) || value === Infinity) {\n m = isNaN(value) ? 1 : 0\n e = eMax\n } else {\n e = Math.floor(Math.log(value) / Math.LN2)\n if (value * (c = Math.pow(2, -e)) < 1) {\n e--\n c *= 2\n }\n if (e + eBias >= 1) {\n value += rt / c\n } else {\n value += rt * Math.pow(2, 1 - eBias)\n }\n if (value * c >= 2) {\n e++\n c /= 2\n }\n\n if (e + eBias >= eMax) {\n m = 0\n e = eMax\n } else if (e + eBias >= 1) {\n m = ((value * c) - 1) * Math.pow(2, mLen)\n e = e + eBias\n } else {\n m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)\n e = 0\n }\n }\n\n for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}\n\n e = (e << mLen) | m\n eLen += mLen\n for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}\n\n buffer[offset + i - d] |= s * 128\n}\n","var toString = {}.toString;\n\nmodule.exports = Array.isArray || function (arr) {\n return toString.call(arr) == '[object Array]';\n};\n"],"sourceRoot":""}