{"version":3,"sources":["fabric.js"],"names":["fabric","version","exports","document","window","require","jsdom","decodeURIComponent","createWindow","parentWindow","isTouchSupported","isLikelyNode","Buffer","SHARED_ATTRIBUTES","DPI","reNum","fontPaths","iMatrix","canvasModule","perfLimitSizeTotal","maxCacheSideLimit","minCacheSideLimit","charWidthsCache","devicePixelRatio","webkitDevicePixelRatio","mozDevicePixelRatio","_removeEventListener","eventName","handler","this","__eventListeners","eventListener","indexOf","util","array","fill","observe","arguments","length","prop","on","push","stopObserving","call","fire","options","listenersForEvent","i","len","filter","value","Observable","off","trigger","Collection","_objects","add","apply","_onObjectAdded","renderOnAddRemove","renderAll","insertAt","object","index","nonSplicing","objects","getObjects","splice","remove","somethingRemoved","_onObjectRemoved","forEachObject","callback","context","type","o","item","isEmpty","size","contains","complexity","reduce","memo","current","CommonMethods","_setOptions","set","_initGradient","filler","property","colorStops","Gradient","_initPattern","source","Pattern","_initClipping","clipTo","functionBody","getFunctionBody","Function","_setObject","obj","_set","key","get","toggle","global","sqrt","Math","atan2","pow","abs","PiBy180","PI","removeFromArray","idx","getRandomInt","min","max","floor","random","degreesToRadians","degrees","radiansToDegrees","radians","rotatePoint","point","origin","subtractEquals","v","rotateVector","Point","x","y","addEquals","vector","sin","cos","transformPoint","p","t","ignoreOffset","makeBoundingBoxFromPoints","points","xPoints","minX","maxX","width","yPoints","minY","maxY","left","top","height","invertTransform","a","r","toFixed","number","fractionDigits","parseFloat","Number","parseUnit","fontSize","unit","exec","Text","DEFAULT_SVG_FONT_SIZE","falseFunction","getKlass","namespace","string","camelize","charAt","toUpperCase","slice","resolveNamespace","parts","split","loadImage","url","crossOrigin","img","createImage","onload","onerror","log","src","enlivenObjects","reviver","onLoaded","numLoadedObjects","numTotalObjects","enlivenedObjects","forEach","fromObject","error","enlivenPatterns","patterns","numLoadedPatterns","numPatterns","enlivenedPatterns","pattern","groupSVGElements","elements","path","PathGroup","sourcePath","populateWithProperties","destination","properties","Object","prototype","toString","drawDashedLine","ctx","x2","y2","da","dx","dy","rot","dc","di","draw","save","translate","moveTo","rotate","restore","createCanvasElement","canvasEl","createElement","getContext","G_vmlCanvasManager","initElement","createAccessors","klass","propName","capitalizedPropName","setterName","getterName","proto","stateProperties","clipContext","receiver","beginPath","clip","multiplyTransformMatrices","b","is2x2","qrDecompose","angle","denom","scaleX","scaleY","skewX","skewY","translateX","translateY","customTransformMatrix","skewMatrixX","tan","scaleMatrix","resetObjectTransform","target","flipX","flipY","setAngle","fn","String","match","isTransparent","tolerance","_isTransparent","imageData","getImageData","l","data","parsePreserveAspectRatioAttribute","attribute","align","meetOrSlice","aspectRatioAttrs","pop","alignX","alignY","clearFabricFontCache","fontFamily","limitDimsByArea","ar","maximumArea","roughWidth","perfLimitSizeY","capValue","arcToSegmentsCache","segmentToBezierCache","boundsOfCurveCache","_join","Array","join","arcToSegments","toX","toY","rx","ry","large","sweep","rotateX","argsString","th","sinTh","cosTh","fromX","fromY","px","py","rx2","ry2","py2","px2","pl","root","s","cx","cy","cx1","cy1","mTheta","calcVectorAngle","dtheta","segments","ceil","result","mDelta","mT","th3","segmentToBezier","th2","argsString2","costh2","sinth2","costh3","sinth3","cp1X","cp1Y","cp2X","cp2Y","ux","uy","vx","vy","ta","tb","getBoundsOfCurve","x0","y0","x1","y1","x3","y3","c","t1","t2","b2ac","sqrtb2ac","tvalues","bounds","mt","j","jlen","drawArc","fx","fy","coords","segs","segsNorm","bezierCurveTo","getBoundsOfArc","tx","ty","bound","find","byProperty","condition","searchElement","TypeError","n","POSITIVE_INFINITY","NEGATIVE_INFINITY","k","map","every","some","val","rv","invoke","method","args","value1","value2","extend","deep","Element","hasOwnProperty","clone","trim","replace","character","capitalize","firstLetterOnly","toLowerCase","escapeXml","Dummy","bind","thisArg","_this","concat","emptyFunction","IS_DONTENUM_BUGGY","addMethods","parent","superclass","constructor","returnValue","valueOf","Subclass","callSuper","methodName","parentMethod","superClassMethod","console","createClass","initialize","shift","subclasses","areHostMethods","methodNames","test","getElement","setElement","uid","getUniqueId","element","__uniqueID","createWrappedHandler","e","event","addListener","removeListener","shouldUseAddListenerRemoveListener","documentElement","shouldUseAttachEventDetachEvent","listeners","handlers","addEventListener","removeEventListener","listener","wrappedHandler","createListener","attachEvent","detachEvent","existingHandler","handlersForEvent","createDispatcher","pointerX","clientX","pointerY","clientY","_getPointer","pageProp","clientProp","touchProp","getPointer","srcElement","scroll","getScrollLeftTop","parseEl","supportsOpacity","style","opacity","supportsFilters","reOpacity","setOpacity","es","currentStyle","hasLayout","zoom","setStyle","styles","elementStyle","cssText","styleFloat","_slice","sliceCanConvertNodelists","getElementStyle","selectProp","toArray","arrayLike","childNodes","err","makeElement","tagName","attributes","el","className","htmlFor","setAttribute","docElement","body","scrollLeft","scrollTop","parentNode","host","nodeType","arr","defaultView","getComputedStyle","attr","undefined","makeElementUnselectable","onselectstart","unselectable","makeElementSelectable","getScript","headEl","getElementsByTagName","scriptEl","loading","onreadystatechange","readyState","appendChild","getById","id","getElementById","addClass","wrapElement","wrapper","replaceChild","getElementOffset","docElem","scrollLeftTop","doc","ownerDocument","box","offset","offsetAttributes","borderLeftWidth","borderTopWidth","paddingLeft","paddingTop","parseInt","getBoundingClientRect","clientLeft","clientTop","makeXHR","factories","ActiveXObject","XMLHttpRequest","emptyFn","request","onComplete","xhr","parameters","param","addParamToUrl","open","setRequestHeader","send","warn","noop","_requestAnimFrame","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","setTimeout","requestAnimFrame","animate","timestamp","time","start","Date","duration","finish","onChange","abort","easing","d","startValue","endValue","byValue","onStart","tick","ticktime","currentTime","timePerc","valuePerc","animateColor","fromColor","toColor","startColor","Color","getSource","endColor","begin","end","pos","color","posValue","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","reAllowedSVGTagNames","reViewBoxTagNames","reNotAllowedAncestors","reAllowedParents","attributesMap","display","visibility","transform","fill-opacity","fill-rule","font-family","font-size","font-style","font-weight","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-decoration","text-anchor","colorAttributes","stroke","normalizeAttr","normalizeValue","parentAttributes","parsed","isArray","transformMatrix","parseTransformAttribute","visible","isNaN","_getMultipleNodes","nodeNames","nodeName","nodeList","nodeArray","elementMatchesRule","selectors","firstMatching","parentMatching","selectorMatches","selector","doesSomeParentMatch","matcher","classNames","getAttribute","RegExp","elementById","node","nodelist","cssRules","gradientDefs","skewMatrix","matrix","commaWsp","reTransformList","reTransform","attributeValue","matrices","m","operation","translateMatrix","rotateMatrix","multiplierX","multiplierY","combinedMatrix","reViewBoxAttrValue","applyViewboxTransform","viewBoxWidth","viewBoxHeight","viewBoxAttr","widthAttr","heightAttr","preserveAspectRatio","missingViewBox","missingDimAttr","toBeParsed","parsedDim","firstChild","parseSVGDocument","parsingOptions","attrs","xlink","substr","el2","cloneNode","currentTrans","oldLength","el3","nodeValue","removeAttribute","parseUseDirectives","svgUid","__uid","descendants","selectNodes","hasAncestorWithNodeName","getGradientDefs","getCSSRules","parseElements","instances","reFontDeclaration","parseFontDeclaration","oStyle","fontStyle","fontWeight","lineHeight","elList","idsToXlinkMap","parseAttributes","ownAttributes","rule","getGlobalStylesForElement","parseStyleAttribute","normalizedAttr","normalizedValue","normalizedStyle","font","mergedAttrs","setAlpha","getAlpha","toRgba","_setStrokeFillOpacity","ElementsParser","parse","chunk","pair","parseStyleString","parseStyleObject","parsePointsAttribute","parsedPoints","allRules","styleContents","textContent","text","ruleObj","propertyValuePairs","_rule","loadSVGFromURL","xml","responseXML","responseText","async","loadXML","results","_options","loadSVGFromString","DOMParser","parser","parseFromString","numElements","createObjects","_obj","createObject","fromElement","_createObject","checkIfDone","createCallback","resolveGradient","instanceFillValue","gradientId","that","scalarAdd","scalar","scalarAddEquals","subtract","scalarSubtract","scalarSubtractEquals","multiply","multiplyEquals","divide","divideEquals","eq","lt","lte","gt","gte","lerp","distanceFrom","midPointFrom","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","q","colorNameMap","sourceFromHex","sourceFromRgb","sourceFromHsl","_rgbToHsl","g","h","round","_source","toRgb","toHsl","hsl","toHsla","toHex","toHexa","alpha","toGrayscale","average","currentAlpha","toBlackWhite","threshold","overlayWith","otherColor","otherSource","reRGBa","reHSLa","reHex","aqua","black","blue","fuchsia","gray","grey","green","lime","maroon","navy","olive","orange","purple","red","silver","teal","white","yellow","fromRgb","fromSource","fromRgba","fromHsl","fromHsla","fromHex","isShortNotation","isRGBa","substring","oColor","getColorStop","colorAlpha","keyValuePairs","_convertPercentUnitsToValues","gradientUnits","propValue","addFactor","multFactor","ellipseMatrix","scaleFactor","offsetX","offsetY","gradientTransform","addColorStop","position","toObject","propertiesToInclude","toSVG","markup","commonAttributes","needsSwap","sort","group","reverse","minRadius","percentageShift","colorStop","toLive","gradient","createLinearGradient","createRadialGradient","instance","colorStopEls","getLinearCoords","getRadialCoords","forObject","repeat","setOptions","NUM_FRACTION_DIGITS","toDataURL","patternSource","patternWidth","patternHeight","patternOffsetX","patternOffsetY","patternImgSrc","complete","naturalWidth","naturalHeight","createPattern","Shadow","blur","affectStroke","includeDefaultValues","_parseShadow","shadow","shadowStr","offsetsAndBlur","reOffsetsAndBlur","fBoxX","fBoxY","StaticCanvas","CANVAS_INIT_ERROR","Error","_initStatic","backgroundColor","backgroundImage","overlayColor","overlayImage","stateful","controlsAboveOverlay","allowTouchScrolling","imageSmoothingEnabled","viewportTransform","backgroundVpt","overlayVpt","onBeforeScaleRotate","enableRetinaScaling","vptCoords","skipOffscreen","cb","_createLowerCanvas","_initOptions","_setImageSmoothing","interactive","_initRetinaScaling","setOverlayImage","setBackgroundImage","setBackgroundColor","setOverlayColor","calcOffset","_isRetinaScaling","getRetinaScaling","lowerCanvasEl","contextContainer","scale","_offset","image","__setBgOverlayImage","__setBgOverlayColor","webkitImageSmoothingEnabled","mozImageSmoothingEnabled","msImageSmoothingEnabled","oImageSmoothingEnabled","Image","_createCanvasElement","_applyCanvasStyle","getWidth","getHeight","setWidth","setDimensions","setHeight","dimensions","cssValue","cssOnly","_setBackstoreDimension","backstoreOnly","_setCssDimension","upperCanvasEl","cacheCanvasEl","wrapperEl","getZoom","setViewportTransform","vpt","activeGroup","_activeGroup","setCoords","calcViewportBoundaries","zoomToPoint","before","after","setZoom","absolutePan","relativePan","setupState","canvas","clearContext","clearRect","clear","_hasITextHandlers","_mouseUpITextHandler","_iTextInstances","canvasToDrawOn","renderCanvas","iVpt","tl","br","tr","bl","_renderBackground","_renderObjects","drawControls","_renderOverlay","render","_renderBackgroundOrOverlay","fillStyle","fillRect","getCenter","centerObjectH","_centerObject","getCenterPoint","centerObjectV","centerObject","center","viewportCenterObject","vpCenter","getVpCenter","viewportCenterObjectH","viewportCenterObjectV","setPositionByOrigin","toDatalessJSON","toDatalessObject","_toObjectMethod","_toObjects","__serializeBgOverlay","excludeFromExport","_toObject","originalValue","bgImage","overlay","background","svgViewportTransformation","_setSVGPreamble","_setSVGHeader","_setSVGBgOverlayColor","_setSVGBgOverlayImage","_setSVGObjects","suppressPreamble","encoding","viewBox","createSVGFontFacesMarkup","createSVGRefElementsMarkup","row","rowIndex","charIndex","fontList","_setSVGObject","sendToBack","objs","unshift","bringToFront","sendBackwards","intersecting","newIdx","objsMoved","_findNewLowerIndex","intersectsWithObject","isContainedWithinObject","bringForward","_findNewUpperIndex","dispose","DataURLExporter","EMPTY_JSON","supports","setLineDash","toJSON","BaseBrush","strokeLineCap","strokeLineJoin","strokeDashArray","setShadow","_setBrushStyles","contextTop","strokeStyle","lineWidth","lineCap","lineJoin","_setShadow","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY","_resetShadow","PencilBrush","_points","onMouseDown","pointer","_prepareForDrawing","_captureDrawingPath","_render","onMouseMove","onMouseUp","_finalizeAndAddPath","_reset","_addPoint","pointerPoint","p1","p2","midPoint","quadraticCurveTo","lineTo","convertPointsToSVGPath","multSignX","multSignY","manyPoints","createPath","pathData","Path","strokeWidth","originX","originY","translateToGivenOrigin","closePath","CircleBrush","drawDot","addPoint","arc","radius","originalRenderOnAddRemove","circles","circle","Circle","Group","circleRadius","circleColor","SprayBrush","density","dotWidth","dotWidthVariance","randomOpacity","optimizeOverlapping","sprayChunks","addSprayChunk","rects","ilen","sprayChunk","rect","Rect","_getOptimizedRects","uniqueRects","uniqueRectsArray","sprayChunkPoints","globalAlpha","PatternBrush","getPatternSrc","patternCanvas","patternCtx","getPatternSrcFunction","getPattern","topLeft","_getLeftTopCoords","supportLineDash","Canvas","_initInteractive","_createCacheCanvas","uniScaleTransform","uniScaleKey","centeredScaling","centeredRotation","centeredKey","altActionKey","selection","selectionKey","altSelectionKey","selectionColor","selectionDashArray","selectionBorderColor","selectionLineWidth","hoverCursor","moveCursor","defaultCursor","freeDrawingCursor","rotationCursor","containerClass","perPixelTargetFind","targetFindTolerance","skipTargetFind","isDrawingMode","preserveObjectStacking","snapAngle","snapThreshold","stopContextMenu","fireRightClick","fireMiddleClick","_currentTransform","_groupSelector","_initWrapperElement","_createUpperCanvas","_initEventListeners","freeDrawingBrush","_chooseObjectsToRender","getActiveGroup","activeObject","getActiveObject","objsToRender","activeGroupObjects","contextTopDirty","renderTop","_drawSelection","_resetCurrentTransform","original","_shouldCenterTransform","action","_setOriginToCenter","mouseXSign","mouseYSign","containsPoint","xy","_normalizePointer","_findTargetCorner","calcTransformMatrix","invertedM","vptPointer","restorePointerVpt","isTargetTransparent","hasBorders","transparentCorners","contextCache","originalColor","selectionBackgroundColor","active","_renderControls","_shouldClearSelection","evented","selectable","centerTransform","altKey","_getOriginFromCorner","corner","_getActionFromCorner","_setupCurrentTransform","ex","ey","lastX","lastY","theta","shiftKey","_translateObject","newLeft","newTop","moveX","moveY","_changeSkewTransformOrigin","mouseMove","by","origins","0","skew","originA","originB","flipSign","skewSign","_skewObject","skewed","lockSkewingX","lockSkewingY","actualMouseByOrigin","constraintPosition","actualMouseByCenter","toLocalPoint","lastMouseByCenter","dim","_getTransformedDimensions","translateToOriginPoint","_setObjectSkew","localMouse","_dim","newValue","newDim","dimNoSkew","otherBy","_otherBy","_by","newDimMouse","atan","_scaleObject","lockScalingX","lockScalingY","lockScalingFlip","scaled","_setLocalMouse","_setObjectScale","changeX","changeY","forbidScalingX","forbidScalingY","_scaleObjectEqually","newScaleX","newScaleY","_flipObject","dist","lastDist","signX","signY","padding","_rotateObject","lastAngle","curAngle","hasRoated","rightAngleLocked","leftAngleLocked","setCursor","cursor","_resetObjectTransform","groupSelector","aleft","atop","_setLineDash","strokeRect","findTarget","skipGroup","activeTarget","activeTargetSubs","targets","_searchPossibleTargets","_fireOverOutEvents","overOpt","outOpt","hoveredTarget","_hoveredTarget","previousTarget","nextTarget","_checkTarget","isEditing","normalizedPointer","subTarget","subTargetCheck","ignoreZoom","cssScale","boundsWidth","boundsHeight","bottom","right","lowerCanvasClass","_copyCanvasStyle","class","touch-action","fromEl","toEl","getSelectionContext","getSelectionElement","_setActiveObject","_activeObject","onDeselect","setActiveObject","currentActiveObject","_discardActiveObject","discardActiveObject","_setActiveGroup","setActiveGroup","_discardActiveGroup","destroy","discardActiveGroup","deactivateAll","allObjects","deactivateAllWithDispatch","removeListeners","removeChild","_drawObjectsControls","originalProperties","_realizeGroupTransformOnObject","_unwindGroupTransformOnObject","originalValues","realizeTransform","_setCursorFromEvent","cursorOffset","mr","mb","ml","checkClick","which","button","cursorMap","_bindEvents","_onResize","_onMouseDown","_onMouseMove","_onMouseOut","_onMouseEnter","_onMouseWheel","_onContextMenu","passive","eventjs","_onGesture","_onDrag","_onOrientationChange","_onShake","_onLongPress","eventsBinded","_onMouseUp","self","__onTransformGesture","__onDrag","__onMouseWheel","hiddenTextarea","focus","__onOrientationChange","__onShake","__onLongPress","stopPropagation","preventDefault","__onMouseDown","__onMouseUp","__onMouseMove","_shouldRender","isMoving","_previousPointer","_handleEvent","_isCurrentlyDrawing","_onMouseUpInDrawingMode","searchTarget","isClick","_finalizeCurrentTransform","actionPerformed","shouldRender","_maybeGroupObjects","__corner","eventType","targetObj","subTargets","_scaling","_restoreOriginXY","hasStateChanged","_previousOriginX","_previousOriginY","originPoint","_onMouseDownInDrawingMode","_onMouseMoveInDrawingMode","shouldGroup","_shouldGroup","_handleGrouping","_beforeTransform","saveState","_setCenterToOrigin","touches","_transformObject","reset","_beforeScaleTransform","_performTransformAction","_fire","_onScale","currentAction","_setCornerCursor","_getRotatedCornerCursor","hasRotatingPoint","getAngle","_updateActiveGroup","_createActiveGroup","saveCoords","removeWithUpdate","addWithUpdate","_createGroup","groupObjects","exitEditing","_groupSelectedObjects","_collectObjects","currentObject","selectionX1Y1","selectionX2Y2","intersectsWithRect","isContainedWithinRect","setObjectsCoords","supportQuality","format","quality","multiplier","cropping","__toDataURLWithMultiplier","origWidth","origHeight","scaledWidth","scaledHeight","newZoom","vp","newVp","originalInteractive","__toDataURL","toDataURLWithMultiplier","loadFromDatalessJSON","json","loadFromJSON","serialized","JSON","_enlivenObjects","_setBgOverlay","loaded","cbIfLoaded","__setBgOverlay","enlivedObject","_toDataURL","_toDataURLWithMultiplier","stringify","cloneWithoutData","backgroundImageOpacity","backgroundImageStretch","supportsLineDash","objectCaching","cornerSize","borderColor","borderDashArray","cornerColor","cornerStrokeColor","cornerStyle","cornerDashArray","fillRule","globalCompositeOperation","strokeMiterLimit","borderOpacityWhenMoving","borderScaleFactor","minScaleLimit","hasControls","rotatingPointOffset","lockMovementX","lockMovementY","lockRotation","lockUniScaling","statefullCache","noScaleCache","dirty","cacheProperties","_cacheProperties","_cacheCanvas","_cacheContext","_updateCacheCanvas","_limitCacheSize","dims","limitedDims","zoomX","capped","zoomY","_getCacheCanvasDimensions","objectScale","getObjectScaling","retina","_getNonTransformedDimensions","drawingWidth","drawingHeight","minCacheSize","dimensionsChanged","cacheWidth","cacheHeight","zoomChanged","shouldRedraw","additionalWidth","additionalHeight","shouldResizeCanvas","canvasWidth","canvasHeight","sizeGrowing","setTransform","cacheTranslationX","cacheTranslationY","fromLeft","_transformDone","_removeDefaultValues","scaling","shouldConstrainValue","isChanged","_constrainScale","setOnGroup","setSourcePath","getViewportTransform","isNotVisible","noTransform","isOnScreen","_setupCompositeOperation","drawSelectionBackground","_setOpacity","shouldCache","isCacheDirty","propertySet","drawObject","drawCacheOnCanvas","_removeCacheCanvas","needsItsOwnCache","isCaching","willDrawShadow","_setStrokeStyles","_setFillStyles","drawImage","skipCanvas","_removeShadow","miterLimit","dashArray","alternative","drawBordersInGroup","drawBorders","multX","multY","_applyPatternGradientTransform","patternTransform","_renderFill","_renderStroke","_renderDashedStroke","cloneAsImage","dataUrl","boundingRect","getBoundingRect","origParams","getLeft","getTop","originalCanvas","isType","setGradient","setPatternFill","setColor","shouldCenterOrigin","_resetOrigin","centerH","viewportCenterH","centerV","viewportCenterV","viewportCenter","getLocalPointer","pClicked","objectLeftTop","_fromObject","forceAsync","extraParam","originXOffset","originYOffset","fromOriginX","fromOriginY","toOriginX","toOriginY","translateToCenterPoint","leftTop","getPointByOrigin","adjustPosition","to","offsetFrom","offsetTo","hypotFull","xFull","yFull","_originalOriginX","_originalOriginY","multiplyMatrices","oCoords","aCoords","getCoords","absolute","calculate","calcCoords","pointTL","pointBR","other","lines","_getImageLines","_findCrossPoints","centerPoint","topline","rightline","bottomline","leftline","xi","iLine","xcount","lineKey","getBoundingRectWidth","getBoundingRectHeight","scaleToWidth","boundingRectFactor","scaleToHeight","_calculateCurrentDimensions","currentWidth","currentHeight","_angle","_hypotenuse","mtr","skipAbsolute","_setCornerCoords","_calcRotateMatrix","dimensionMatrix","_calcDimensionsTransformMatrix","flipping","bbox","dimX","dimY","getSvgColorString","str","getSvgStyles","skipShadow","getSvgFilter","getSvgId","getSvgTransform","getSkewX","getSkewY","translatePart","anglePart","scalePart","skewXPart","skewYPart","addTranslateX","flipXPart","addTranslateY","getSvgTransformMatrix","_createBaseSVGMarkup","saveProps","props","tmpObj","dashedPropertySet","keys","_isEqual","origValue","currentValue","firstPass","_controlsVisibility","isControlVisible","newTheta","cornerHypotenuse","cosHalfOffset","sinHalfOffset","wh","rotateHeight","scaleOffset","_drawControl","control","controlName","_getControlsVisibility","setControlVisible","setControlsVisibility","FX_DURATION","fxCenterObjectH","callbacks","empty","fxCenterObjectV","fxRemove","skipCallbacks","propsToAnimate","_animate","propPair","from","valueProgress","timeProgress","coordProps","makeEdgeToOriginGetter","propertyNames","originValues","axis1","axis2","dimension","nearest","farthest","Line","_setWidthHeight","_getLeftToOriginX","_getTopToOriginY","cp","calcLinePoints","origStrokeStyle","xMult","yMult","ATTRIBUTE_NAMES","parsedAttributes","line","pi","startAngle","endAngle","setRadius","startX","startY","endX","endY","largeFlag","getRadiusX","getRadiusY","Triangle","widthBy2","heightBy2","piBy2","Ellipse","getRx","getRy","ellipse","_initRxRy","w","isRounded","Polyline","_calcDimensions","pathOffset","diffX","diffY","commonRender","Polygon","_toString","commandLengths","repeatedCommands","M","fromArray","_parsePath","_setPositionDimensions","calcDim","_parseDimensions","_renderPathCommands","tempX","tempY","previous","subpathStartX","subpathStartY","controlX","controlY","chunks","addTransform","currentPath","coordsStr","coordsParsed","re","command","commandLength","repeatedCommand","klen","aX","aY","pathUrl","paths","parseDimensionsFromPaths","xC","yC","parentCache","caching","isSameColor","pathsToObject","originalDefaults","firstPathFill","pathFill","total","originalPaths","pathGroup","_lockProperties","isAlreadyGrouped","_updateObjectsCoords","_updateObjectsACoords","_calcBounds","skipCoordsChange","_updateObjectCoords","__origHasControls","objectLeft","objectTop","_restoreObjectsState","_setObjectActive","delegatedProperties","textDecoration","textAlign","objsToObject","_renderObject","originalHasRotatingPoint","_restoreObjectState","_originalLeft","_originalTop","hasMoved","onlyWidthHeight","iLen","jLen","_getBounds","minXY","maxXY","_lastScaleX","_lastScaleY","minimumScaleTrigger","filters","resizeFilters","_initElement","_element","_callback","_originalElement","_initConfig","applyFilters","_filteredEl","setCrossOrigin","getOriginalSize","_stroke","filterObj","getSrc","getSvgSrc","origFill","filtered","_src","setSrc","imgElement","forResizing","replacement","retinaScaling","minimumScale","applyTo","toBuffer","pngCompression","elementToDraw","imageMargins","_findMargins","_needsResize","marginX","marginY","scales","_resetWidthHeight","CSS_CANVAS","_initFilters","fromURL","imgOptions","preserveAR","_getAngleValueForStraighten","straighten","fxStraighten","straightenObject","fxStraightenObject","BaseFilter","Brightness","brightness","putImageData","Convolute","opaque","dstOff","scx","scy","srcOff","wt","weights","pixels","side","halfSide","sw","sh","output","createImageData","dst","alphaFac","GradientTransparency","Grayscale","Invert","Mask","mask","channel","maskEl","maskCanvasEl","maskData","Noise","noise","rand","Pixelate","blocksize","_i","_ilen","_j","_jlen","RemoveWhite","distance","limit","Sepia","avg","Sepia2","Tint","tintR","tintG","tintB","alpha1","Multiply","Blend","mode","tg","_r","_g","_b","isImage","_el","tmpCanvas","Resize","resizeType","lanczosLobes","rcpScaleX","rcpScaleY","oW","oH","dW","dH","sliceByTwo","hermiteFastResize","bilinearFiltering","lanczosResize","multW","multH","signW","signH","doneW","doneH","stepW","stepH","tmpCtx","lobes","srcImg","destImg","srcData","destData","lanczos","xx","ratioX","ratioY","rcpRatioX","rcpRatioY","range2X","range2Y","cacheLanc","icenter","process","u","weight","fX","fY","xDiff","yDiff","chnl","origPix","w4","destImage","destPixels","ratioW","ratioH","ratioWHalf","ratioHHalf","img2","data2","weightsAlpha","gxR","gxG","gxB","gxA","centerY","yy","centerX","w0","ColorMatrix","Contrast","contrast","contrastF","Saturate","saturate","adjust","_dimensionAffectingProps","_reNewline","_reSpacesAndTabs","textBackgroundColor","_fontSizeFraction","_fontSizeMult","charSpacing","__skipDimension","_initDimensions","_setTextStyles","_textLines","_splitTextIntoLines","_clearCache","_getTextWidth","cursorWidth","_getTextHeight","_renderTextLinesBackground","_renderText","_renderTextDecoration","_renderTextFill","_renderTextStroke","textBaseline","_getFontDeclaration","_getHeightOfSingleLine","_getHeightOfLine","maxWidth","_getLineWidth","currentLineWidth","_renderChars","chars","_char","shortM","additionalSpace","_getWidthOfCharSpacing","measureText","_renderTextLine","lineIndex","word","words","charOffset","wordsWidth","_getWidthOfWords","widthDiff","numSpaces","spaceWidth","leftOffset","_getLeftOffset","_getTopOffset","isEmptyStyles","_renderTextCommon","lineHeights","heightOfLine","maxHeight","_getLineLeftOffset","lineLeftOffset","lineTopOffset","originalFill","__lineWidths","__lineHeights","_shouldClearDimensionCache","shouldClear","_forceClearCache","_measureLine","finalWidth","halfOfVerticalBox","offsets","oLen","renderLinesAtOffset","additionalProperties","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","lineTop","textBgRects","textSpans","textTopOffset","textLeftOffset","_setSVGBg","_setSVGTextLineBg","_setSVGTextLineText","yPos","_getFillAttributes","_setSVGTextLineJustifed","fillColor","textHeightScaleFactor","scaledDiff","textHeight","offX","IText","selectionStart","selectionEnd","editable","editingBorderColor","cursorColor","cursorDelay","cursorDuration","_reSpace","_currentCursorOpacity","_selectionDirection","_abortCursorAnimation","__widthOfSpace","initBehavior","p3","setSelectionStart","_updateAndFire","setSelectionEnd","_fireSelectionChanged","_updateTextarea","getSelectionStyles","startIndex","endIndex","loc","get2DCursorLocation","_getStyleDeclaration","setSelectionStyles","_extendStyles","_getLineStyle","_setLineStyle","_setStyleDeclaration","clearContextTop","cursorOffsetCache","renderCursorOrSelection","_clearTextArea","boundaries","_getCursorBoundaries","renderCursor","renderSelection","getCurrentCharStyle","getCurrentCharFontSize","getCurrentCharColor","typeOfBoundaries","_getCursorBoundariesOffsets","lineLeft","topOffset","_getWidthOfChar","cursorLocation","charHeight","__isMousedown","startLine","endLine","realLineHeight","lineOffset","boxWidth","j2","j2len","_renderCharsFast","prevStyle","thisStyle","charsToRender","_hasStyleChanged","_renderChar","skipFillStrokeCheck","charWidth","shouldFill","shouldStroke","_charWidth","decl","_getHeightOfChar","_applyCharStylesGetWidth","jChar","fillText","strokeText","_renderCharDecoration","decoration","decorationWeight","positions","underline","line-through","overline","decorations","leftCache","topCache","widthCache","heightCache","colorCache","_getWidthOfCharsAt","_getCacheProp","styleDeclaration","_getFontCache","cacheProp","charDecl","_applyFontStyles","returnCloneOrEmpty","_deleteStyleDeclaration","_deleteLineStyle","_isMeasuring","_getWidthOfSpace","currentCharHeight","initAddedHandler","initRemovedHandler","initCursorSelectionHandlers","initDoubleClickSimulation","mouseMoveHandler","selected","_initCanvasHandlers","_removeCanvasHandlers","_tick","_currentTickState","_animateCursor","targetOpacity","completeMethod","tickState","isAborted","_onTickComplete","_cursorTimeout1","clearTimeout","_currentTickCompleteState","initDelayedCursor","restart","delay","abortCursorAnimation","_cursorTimeout2","selectAll","getSelectedText","findWordBoundaryLeft","startFrom","findWordBoundaryRight","findLineBoundaryLeft","findLineBoundaryRight","getNumNewLinesInSelectedText","selectedText","numNewLines","searchWordBoundary","direction","reNonWord","selectWord","newSelectionStart","newSelectionEnd","selectLine","enterEditing","exitEditingOnOthers","initHiddenTextarea","_saveEditingProps","_setEditingProps","_textBeforeEdit","initMouseMoveHandler","getSelectionStartFromPointer","currentStart","currentEnd","__selectionStartOnMouseDown","restartCursorIfNeeded","inCompositionMode","_calcTextareaPosition","upperCanvas","_savedProps","_restoreEditingProps","overCursor","isTextChanged","_removeExtraneousStyles","_removeCharsFromTo","_removeSingleCharAndStyle","isBeginningOfLine","indexStyle","removeStyleObject","insertChars","_chars","useCopiedStyle","copiedTextStyle","insertChar","skipUpdate","styleObject","isEndOfLine","insertStyleObjects","insertNewlineStyleObject","shiftLineStyles","currentCharStyle","newLineStyles","somethingAdded","numIndex","insertCharStyleObject","currentLineStyles","currentLineStylesCloned","numericIndex","newStyle","clonedStyles","numericLine","_removeStyleObject","_getTextOnPreviousLine","lIndex","textOnPreviousLine","newCharIndexOnPrevLine","insertNewline","setSelectionStartEndWithShift","newSelection","setSelectionInBoundaries","__lastClickTime","__lastLastClickTime","__lastPointer","__newClickTime","newPointer","isTripleClick","_stopEvent","isDoubleClick","__lastIsEditing","__lastSelected","initMousedownHandler","initMouseupHandler","initClicks","__mousedownX","__mousedownY","setCursorByClick","_isObjectMoved","mouseOffset","prevWidth","widthOfLine","_getNewSelectionStartFromOffset","distanceBtwLastCharAndCursor","onKeyDown","onKeyUp","onInput","copy","cut","paste","onCompositionStart","onCompositionUpdate","onCompositionEnd","_clickHandlerInitialized","onClick","keysMap","8","9","27","13","33","34","35","36","37","38","39","40","46","ctrlKeysMapUp","67","88","ctrlKeysMapDown","65","keyCode","ctrlKey","metaKey","stopImmediatePropagation","_copyDone","diff","charsToInsert","offsetEnd","textLength","newTextLength","prevCompositionLength","compositionStart","forwardDelete","moveCursorRight","removeChars","clipboardData","_getClipboardData","setData","copiedText","getData","_getWidthBeforeCursor","textBeforeCursor","widthBeforeCursor","getDownCursorOffset","isRight","selectionProp","_getSelectionForOffset","indexOnOtherLine","_getIndexOnLine","getUpCursorOffset","foundMatch","textOnLine","widthOfCharsOnLine","indexOnLine","widthOfChar","leftEdge","rightEdge","offsetFromLeftEdge","moveCursorDown","_moveCursorUpOrDown","moveCursorUp","moveCursorWithShift","moveCursorWithoutShift","moveCursorLeft","_moveCursorLeftOrRight","_move","_moveLeft","_moveRight","moveCursorLeftWithoutShift","change","moveCursorLeftWithShift","actionName","moveCursorRightWithShift","moveCursorRightWithoutShift","changed","_removeCharsNearCursor","leftLineBoundary","leftWordBoundary","_setSVGTextLineChars","_getSVGLineTopOffset","styleDecl","_createTextCharSpan","_createTextCharBg","lastHeight","fillStyles","Textbox","minWidth","dynamicMinWidth","__cachedLines","getTextboxControlVisibility","_generateStyleMap","realLineCount","realLineCharCount","charCount","_styleMap","_wrapText","wrapped","_wrapLine","_measureText","wordWidth","infixWidth","largestWordWidth","lineJustStarted","originalAlign","__oldScaleX","numLines","removed","lineLen","lineChars","getMinWidth","setObjectScaleOverridden","_refreshControlsVisibility","override","tmp","URL","HTTP","HTTPS","createImageAndCallBack","requestFs","eval","createCanvasForNode","nodeCanvasOptions","nodeCanvas","nodeCacheCanvas","fabricCanvas","Font","originaInitStatic","createPNGStream","createJPEGStream","origSetBackstoreDimension","oURL","port","protocol","req","hostname","response","setEncoding","statusCode","errno","ECONNREFUSED","message","readFile"],"mappings":"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","file":"fabric.js","sourcesContent":["/* build: `node build.js modules=ALL exclude=json,gestures minifier=uglifyjs` */\n /*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */\n\nvar fabric = fabric || { version: \"1.7.22\" };\nif (typeof exports !== 'undefined') {\n exports.fabric = fabric;\n}\n\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\n fabric.document = document;\n fabric.window = window;\n // ensure globality even if entire library were function wrapped (as in Meteor.js packaging system)\n window.fabric = fabric;\n}\nelse {\n // assume we're running under node.js when document/window are not present\n fabric.document = require(\"jsdom\")\n .jsdom(\n decodeURIComponent(\"%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E\")\n );\n\n if (fabric.document.createWindow) {\n fabric.window = fabric.document.createWindow();\n } else {\n fabric.window = fabric.document.parentWindow;\n }\n}\n\n/**\n * True when in environment that supports touch events\n * @type boolean\n */\n\nfabric.isTouchSupported = 'ontouchstart' in fabric.window;\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\",\n \"stroke-linejoin\", \"stroke-miterlimit\",\n \"stroke-opacity\", \"stroke-width\",\n \"id\"\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+)(?:e[-+]?\\\\d+)?)';\nfabric.fontPaths = { };\nfabric.iMatrix = [1, 0, 0, 1, 0, 0];\nfabric.canvasModule = 'canvas';\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 * 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\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 * @deprecated `observe` deprecated since 0.8.34 (use `on` instead)\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 observe(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 /**\n * Stops event observing for a particular event handler. Calling this method\n * without arguments removes all handlers for all events\n * @deprecated `stopObserving` deprecated since 0.8.34 (use `off` instead)\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 stopObserving(eventName, handler) {\n if (!this.__eventListeners) {\n return;\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 * @deprecated `fire` deprecated since 1.0.7 (use `trigger` instead)\n * @memberOf fabric.Observable\n * @alias trigger\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;\n }\n\n var listenersForEvent = this.__eventListeners[eventName];\n if (!listenersForEvent) {\n return;\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 observe: observe,\n stopObserving: stopObserving,\n fire: fire,\n\n on: observe,\n off: stopObserving,\n trigger: fire\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.renderAll();\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.getObjects();\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.renderAll();\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.getObjects(),\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.renderAll();\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 * @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;\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.getObjects()[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.getObjects().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.getObjects().length;\n },\n\n /**\n * Returns true if collection contains an object\n * @param {Object} object Object to check against\n * @return {Boolean} `true` if collection contains an object\n */\n contains: function(object) {\n return this.getObjects().indexOf(object) > -1;\n },\n\n /**\n * Returns number representation of a collection complexity\n * @return {Number} complexity\n */\n complexity: function () {\n return this.getObjects().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 * @param {Object} [options] Options object\n */\n _initClipping: function(options) {\n if (!options.clipTo || typeof options.clipTo !== 'string') {\n return;\n }\n\n var functionBody = fabric.util.getFunctionBody(options.clipTo);\n if (typeof functionBody !== 'undefined') {\n this.clipTo = new Function('ctx', functionBody);\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 if (typeof value === 'function' && key !== 'clipTo') {\n this._set(key, value(this.get(key)));\n }\n else {\n this._set(key, value);\n }\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 abs = Math.abs,\n PiBy180 = Math.PI / 180;\n\n /**\n * @namespace fabric.util\n */\n fabric.util = {\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 point.subtractEquals(origin);\n var v = fabric.util.rotateVector(point, 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 = Math.sin(radians),\n cos = Math.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 * 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 * @return {Object} Object with left, top, width, height properties\n */\n makeBoundingBoxFromPoints: function(points) {\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 = Math.abs(minX - maxX),\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 = Math.abs(minY - maxY);\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 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 img.onload = function () {\n callback && callback.call(context, img);\n img = img.onload = img.onerror = null;\n };\n\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 if (url.indexOf('data') !== 0 && crossOrigin) {\n img.crossOrigin = crossOrigin;\n }\n\n img.src = url;\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 function onLoaded() {\n if (++numLoadedObjects === numTotalObjects) {\n callback && callback(enlivenedObjects);\n }\n }\n\n var enlivenedObjects = [],\n numLoadedObjects = 0,\n numTotalObjects = objects.length,\n forceAsync = true;\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 }, forceAsync);\n });\n },\n\n /**\n * Create and wait for loading of patterns\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 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.PathGroup}\n */\n groupSVGElements: function(elements, options, path) {\n var object;\n\n object = new fabric.PathGroup(elements, options);\n\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 Propertie names to include\n */\n populateWithProperties: function(source, destination, properties) {\n if (properties && Object.prototype.toString.call(properties) === '[object Array]') {\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 * Draws a dashed line between two points\n *\n * This method is used to draw dashed line around selection area.\n * See dotted stroke in canvas\n *\n * @param {CanvasRenderingContext2D} ctx context\n * @param {Number} x start x coordinate\n * @param {Number} y start y coordinate\n * @param {Number} x2 end x coordinate\n * @param {Number} y2 end y coordinate\n * @param {Array} da dash array pattern\n */\n drawDashedLine: function(ctx, x, y, x2, y2, da) {\n var dx = x2 - x,\n dy = y2 - y,\n len = sqrt(dx * dx + dy * dy),\n rot = atan2(dy, dx),\n dc = da.length,\n di = 0,\n draw = true;\n\n ctx.save();\n ctx.translate(x, y);\n ctx.moveTo(0, 0);\n ctx.rotate(rot);\n\n x = 0;\n while (len > x) {\n x += da[di++ % dc];\n if (x > len) {\n x = len;\n }\n ctx[draw ? 'lineTo' : 'moveTo'](x, 0);\n draw = !draw;\n }\n\n ctx.restore();\n },\n\n /**\n * Creates canvas element and initializes it via excanvas if necessary\n * @static\n * @memberOf fabric.util\n * @param {CanvasElement} [canvasEl] optional canvas element to initialize;\n * when not given, element is created implicitly\n * @return {CanvasElement} initialized canvas element\n */\n createCanvasElement: function(canvasEl) {\n canvasEl || (canvasEl = fabric.document.createElement('canvas'));\n /* eslint-disable camelcase */\n if (!canvasEl.getContext && typeof G_vmlCanvasManager !== 'undefined') {\n G_vmlCanvasManager.initElement(canvasEl);\n }\n /* eslint-enable camelcase */\n return canvasEl;\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.isLikelyNode\n ? new (require('canvas').Image)()\n : fabric.document.createElement('img');\n },\n\n /**\n * Creates accessors (getXXX, setXXX) for a \"class\", based on \"stateProperties\" array\n * @static\n * @memberOf fabric.util\n * @param {Object} klass \"Class\" to create accessors for\n */\n createAccessors: function(klass) {\n var proto = klass.prototype, i, propName,\n capitalizedPropName, setterName, getterName;\n\n for (i = proto.stateProperties.length; i--; ) {\n\n propName = proto.stateProperties[i];\n capitalizedPropName = propName.charAt(0).toUpperCase() + propName.slice(1);\n setterName = 'set' + capitalizedPropName;\n getterName = 'get' + capitalizedPropName;\n\n // using `new Function` for better introspection\n if (!proto[getterName]) {\n proto[getterName] = (function(property) {\n return new Function('return this.get(\"' + property + '\")');\n })(propName);\n }\n if (!proto[setterName]) {\n proto[setterName] = (function(property) {\n return new Function('value', 'return this.set(\"' + property + '\", value)');\n })(propName);\n }\n }\n },\n\n /**\n * @static\n * @memberOf fabric.util\n * @param {fabric.Object} receiver Object implementing `clipTo` method\n * @param {CanvasRenderingContext2D} ctx Context to clip\n */\n clipContext: function(receiver, ctx) {\n ctx.save();\n ctx.beginPath();\n receiver.clipTo(ctx);\n ctx.clip();\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 2x2 matrix into transform componentes\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 customTransformMatrix: function(scaleX, scaleY, skewX) {\n var skewMatrixX = [1, 0, abs(Math.tan(skewX * PiBy180)), 1],\n scaleMatrix = [abs(scaleX), 0, 0, abs(scaleY)];\n return fabric.util.multiplyTransformMatrices(scaleMatrix, skewMatrixX, true);\n },\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.setAngle(0);\n },\n\n /**\n * Returns string representation of function body\n * @param {Function} fn Function to get body of\n * @return {String} Function body\n */\n getFunctionBody: function(fn) {\n return (String(fn).match(/function[^{]*\\{([\\s\\S]*)\\}/) || {})[1];\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 a font family.\n * @memberOf fabric.util\n * @param {String} [fontFamily] font family to clear\n */\n clearFabricFontCache: function(fontFamily) {\n if (!fontFamily) {\n fabric.charWidthsCache = { };\n }\n else if (fabric.charWidthsCache[fontFamily]) {\n delete fabric.charWidthsCache[fontFamily];\n }\n },\n\n /**\n * Clear char widths cache for a font family.\n * @memberOf fabric.util\n * @param {Number} ar aspect ratio\n * @param {Number} maximumArea Maximum area you want to achieve\n * @param {Number} maximumSide biggest side allowed\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})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n var arcToSegmentsCache = { },\n segmentToBezierCache = { },\n boundsOfCurveCache = { },\n _join = Array.prototype.join;\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 argsString = _join.call(arguments);\n if (arcToSegmentsCache[argsString]) {\n return arcToSegmentsCache[argsString];\n }\n\n var PI = Math.PI, th = rotateX * PI / 180,\n sinTh = Math.sin(th),\n cosTh = Math.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][4];\n fromY = result[i][5];\n mTheta = th3;\n th3 += mDelta;\n }\n arcToSegmentsCache[argsString] = result;\n return result;\n }\n\n function segmentToBezier(th2, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY) {\n var argsString2 = _join.call(arguments);\n if (segmentToBezierCache[argsString2]) {\n return segmentToBezierCache[argsString2];\n }\n\n var costh2 = Math.cos(th2),\n sinth2 = Math.sin(th2),\n costh3 = Math.cos(th3),\n sinth3 = Math.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 segmentToBezierCache[argsString2] = [\n cp1X, cp1Y,\n cp2X, cp2Y,\n toX, toY\n ];\n return segmentToBezierCache[argsString2];\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 * Draws arc\n * @param {CanvasRenderingContext2D} ctx\n * @param {Number} fx\n * @param {Number} fy\n * @param {Array} coords\n */\n fabric.util.drawArc = function(ctx, fx, fy, coords) {\n var rx = coords[0],\n ry = coords[1],\n rot = coords[2],\n large = coords[3],\n sweep = coords[4],\n tx = coords[5],\n ty = coords[6],\n segs = [[], [], [], []],\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 segs[i][0] = segsNorm[i][0] + fx;\n segs[i][1] = segsNorm[i][1] + fy;\n segs[i][2] = segsNorm[i][2] + fx;\n segs[i][3] = segsNorm[i][3] + fy;\n segs[i][4] = segsNorm[i][4] + fx;\n segs[i][5] = segsNorm[i][5] + fy;\n ctx.bezierCurveTo.apply(ctx, segs[i]);\n }\n };\n\n /**\n * Calculate bounding box of a elliptic-arc\n * @param {Number} fx start point of arc\n * @param {Number} fy\n * @param {Number} rx horizontal radius\n * @param {Number} ry vertical radius\n * @param {Number} rot angle of horizontal axe\n * @param {Number} large 1 or 0, whatever the arc is the big or the small on the 2 points\n * @param {Number} sweep 1 or 0, 1 clockwise or counterclockwise direction\n * @param {Number} tx end point of arc\n * @param {Number} ty\n */\n fabric.util.getBoundsOfArc = function(fx, fy, rx, ry, rot, large, sweep, tx, ty) {\n\n var fromX = 0, fromY = 0, bound, bounds = [],\n segs = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);\n\n for (var i = 0, len = segs.length; i < len; i++) {\n bound = getBoundsOfCurve(fromX, fromY, segs[i][0], segs[i][1], segs[i][2], segs[i][3], segs[i][4], segs[i][5]);\n bounds.push({ x: bound[0].x + fx, y: bound[0].y + fy });\n bounds.push({ x: bound[1].x + fx, y: bound[1].y + fy });\n fromX = segs[i][4];\n fromY = segs[i][5];\n }\n return bounds;\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 beizer\n * @param {Number} y3\n */\n // taken from http://jsbin.com/ivomiq/56/edit no credits available for that.\n function getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3) {\n var argsString = _join.call(arguments);\n if (boundsOfCurveCache[argsString]) {\n return boundsOfCurveCache[argsString];\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 boundsOfCurveCache[argsString] = result;\n return result;\n }\n\n fabric.util.getBoundsOfCurve = getBoundsOfCurve;\n\n})();\n\n\n(function() {\n\n var slice = Array.prototype.slice;\n\n /* _ES5_COMPAT_START_ */\n\n if (!Array.prototype.indexOf) {\n /**\n * Finds index of an element in an array\n * @param {*} searchElement\n * @return {Number}\n */\n Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {\n if (this === void 0 || this === null) {\n throw new TypeError();\n }\n var t = Object(this), len = t.length >>> 0;\n if (len === 0) {\n return -1;\n }\n var n = 0;\n if (arguments.length > 0) {\n n = Number(arguments[1]);\n if (n !== n) { // shortcut for verifying if it's NaN\n n = 0;\n }\n else if (n !== 0 && n !== Number.POSITIVE_INFINITY && n !== Number.NEGATIVE_INFINITY) {\n n = (n > 0 || -1) * Math.floor(Math.abs(n));\n }\n }\n if (n >= len) {\n return -1;\n }\n var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);\n for (; k < len; k++) {\n if (k in t && t[k] === searchElement) {\n return k;\n }\n }\n return -1;\n };\n }\n\n if (!Array.prototype.forEach) {\n /**\n * Iterates an array, invoking callback for each element\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Array}\n */\n Array.prototype.forEach = function(fn, context) {\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this) {\n fn.call(context, this[i], i, this);\n }\n }\n };\n }\n\n if (!Array.prototype.map) {\n /**\n * Returns a result of iterating over an array, invoking callback for each element\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Array}\n */\n Array.prototype.map = function(fn, context) {\n var result = [];\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this) {\n result[i] = fn.call(context, this[i], i, this);\n }\n }\n return result;\n };\n }\n\n if (!Array.prototype.every) {\n /**\n * Returns true if a callback returns truthy value for all elements in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Boolean}\n */\n Array.prototype.every = function(fn, context) {\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this && !fn.call(context, this[i], i, this)) {\n return false;\n }\n }\n return true;\n };\n }\n\n if (!Array.prototype.some) {\n /**\n * Returns true if a callback returns truthy value for at least one element in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Boolean}\n */\n Array.prototype.some = function(fn, context) {\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this && fn.call(context, this[i], i, this)) {\n return true;\n }\n }\n return false;\n };\n }\n\n if (!Array.prototype.filter) {\n /**\n * Returns the result of iterating over elements in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Array}\n */\n Array.prototype.filter = function(fn, context) {\n var result = [], val;\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this) {\n val = this[i]; // in case fn mutates this\n if (fn.call(context, val, i, this)) {\n result.push(val);\n }\n }\n }\n return result;\n };\n }\n\n if (!Array.prototype.reduce) {\n /**\n * Returns \"folded\" (reduced) result of iterating over elements in an array\n * @param {Function} fn Callback to invoke for each element\n * @return {*}\n */\n Array.prototype.reduce = function(fn /*, initial*/) {\n var len = this.length >>> 0,\n i = 0,\n rv;\n\n if (arguments.length > 1) {\n rv = arguments[1];\n }\n else {\n do {\n if (i in this) {\n rv = this[i++];\n break;\n }\n // if array contains no values, no initial value to return\n if (++i >= len) {\n throw new TypeError();\n }\n }\n while (true);\n }\n for (; i < len; i++) {\n if (i in this) {\n rv = fn.call(null, rv, this[i], i, this);\n }\n }\n return rv;\n };\n }\n\n /* _ES5_COMPAT_END_ */\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 * Does not clone or extend fabric.Object subclasses.\n * @memberOf fabric.util.object\n * @param {Object} destination Where to copy to\n * @param {Object} source Where to copy from\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 (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 * @memberOf fabric.util.object\n * @param {Object} object Object to clone\n * @return {Object}\n */\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\n})();\n\n\n(function() {\n\n /* _ES5_COMPAT_START_ */\n if (!String.prototype.trim) {\n /**\n * Trims a string (removing whitespace from the beginning and the end)\n * @function external:String#trim\n * @see String#trim on MDN\n */\n String.prototype.trim = function () {\n // this trim is not fully ES3 or ES5 compliant, but it should cover most cases for now\n return this.replace(/^[\\s\\xA0]+/, '').replace(/[\\s\\xA0]+$/, '');\n };\n }\n /* _ES5_COMPAT_END_ */\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 * String utilities\n * @namespace fabric.util.string\n */\n fabric.util.string = {\n camelize: camelize,\n capitalize: capitalize,\n escapeXml: escapeXml\n };\n})();\n\n\n/* _ES5_COMPAT_START_ */\n(function() {\n\n var slice = Array.prototype.slice,\n apply = Function.prototype.apply,\n Dummy = function() { };\n\n if (!Function.prototype.bind) {\n /**\n * Cross-browser approximation of ES5 Function.prototype.bind (not fully spec conforming)\n * @see Function#bind on MDN\n * @param {Object} thisArg Object to bind function to\n * @param {Any[]} Values to pass to a bound function\n * @return {Function}\n */\n Function.prototype.bind = function(thisArg) {\n var _this = this, args = slice.call(arguments, 1), bound;\n if (args.length) {\n bound = function() {\n return apply.call(_this, this instanceof Dummy ? this : thisArg, args.concat(slice.call(arguments)));\n };\n }\n else {\n /** @ignore */\n bound = function() {\n return apply.call(_this, this instanceof Dummy ? this : thisArg, arguments);\n };\n }\n Dummy.prototype = this.prototype;\n bound.prototype = new Dummy();\n\n return bound;\n };\n }\n\n})();\n/* _ES5_COMPAT_END_ */\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\n var unknown = 'unknown';\n\n /* EVENT HANDLING */\n\n function areHostMethods(object) {\n var methodNames = Array.prototype.slice.call(arguments, 1),\n t, i, len = methodNames.length;\n for (i = 0; i < len; i++) {\n t = typeof object[methodNames[i]];\n if (!(/^(?:function|object|unknown)$/).test(t)) {\n return false;\n }\n }\n return true;\n }\n\n /** @ignore */\n var getElement,\n setElement,\n getUniqueId = (function () {\n var uid = 0;\n return function (element) {\n return element.__uniqueID || (element.__uniqueID = 'uniqueID__' + uid++);\n };\n })();\n\n (function () {\n var elements = { };\n /** @ignore */\n getElement = function (uid) {\n return elements[uid];\n };\n /** @ignore */\n setElement = function (uid, element) {\n elements[uid] = element;\n };\n })();\n\n function createListener(uid, handler) {\n return {\n handler: handler,\n wrappedHandler: createWrappedHandler(uid, handler)\n };\n }\n\n function createWrappedHandler(uid, handler) {\n return function (e) {\n handler.call(getElement(uid), e || fabric.window.event);\n };\n }\n\n function createDispatcher(uid, eventName) {\n return function (e) {\n if (handlers[uid] && handlers[uid][eventName]) {\n var handlersForEvent = handlers[uid][eventName];\n for (var i = 0, len = handlersForEvent.length; i < len; i++) {\n handlersForEvent[i].call(this, e || fabric.window.event);\n }\n }\n };\n }\n\n var shouldUseAddListenerRemoveListener = (\n areHostMethods(fabric.document.documentElement, 'addEventListener', 'removeEventListener') &&\n areHostMethods(fabric.window, 'addEventListener', 'removeEventListener')),\n\n shouldUseAttachEventDetachEvent = (\n areHostMethods(fabric.document.documentElement, 'attachEvent', 'detachEvent') &&\n areHostMethods(fabric.window, 'attachEvent', 'detachEvent')),\n\n // IE branch\n listeners = { },\n\n // DOM L0 branch\n handlers = { },\n\n addListener, removeListener;\n\n if (shouldUseAddListenerRemoveListener) {\n /** @ignore */\n addListener = function (element, eventName, handler, options) {\n // since ie10 or ie9 can use addEventListener but they do not support options, i need to check\n element && element.addEventListener(eventName, handler, shouldUseAttachEventDetachEvent ? false : options);\n };\n /** @ignore */\n removeListener = function (element, eventName, handler, options) {\n element && element.removeEventListener(eventName, handler, shouldUseAttachEventDetachEvent ? false : options);\n };\n }\n\n else if (shouldUseAttachEventDetachEvent) {\n /** @ignore */\n addListener = function (element, eventName, handler) {\n if (!element) {\n return;\n }\n var uid = getUniqueId(element);\n setElement(uid, element);\n if (!listeners[uid]) {\n listeners[uid] = { };\n }\n if (!listeners[uid][eventName]) {\n listeners[uid][eventName] = [];\n\n }\n var listener = createListener(uid, handler);\n listeners[uid][eventName].push(listener);\n element.attachEvent('on' + eventName, listener.wrappedHandler);\n };\n /** @ignore */\n removeListener = function (element, eventName, handler) {\n if (!element) {\n return;\n }\n var uid = getUniqueId(element), listener;\n if (listeners[uid] && listeners[uid][eventName]) {\n for (var i = 0, len = listeners[uid][eventName].length; i < len; i++) {\n listener = listeners[uid][eventName][i];\n if (listener && listener.handler === handler) {\n element.detachEvent('on' + eventName, listener.wrappedHandler);\n listeners[uid][eventName][i] = null;\n }\n }\n }\n };\n }\n else {\n /** @ignore */\n addListener = function (element, eventName, handler) {\n if (!element) {\n return;\n }\n var uid = getUniqueId(element);\n if (!handlers[uid]) {\n handlers[uid] = { };\n }\n if (!handlers[uid][eventName]) {\n handlers[uid][eventName] = [];\n var existingHandler = element['on' + eventName];\n if (existingHandler) {\n handlers[uid][eventName].push(existingHandler);\n }\n element['on' + eventName] = createDispatcher(uid, eventName);\n }\n handlers[uid][eventName].push(handler);\n };\n /** @ignore */\n removeListener = function (element, eventName, handler) {\n if (!element) {\n return;\n }\n var uid = getUniqueId(element);\n if (handlers[uid] && handlers[uid][eventName]) {\n var handlersForEvent = handlers[uid][eventName];\n for (var i = 0, len = handlersForEvent.length; i < len; i++) {\n if (handlersForEvent[i] === handler) {\n handlersForEvent.splice(i, 1);\n }\n }\n }\n };\n }\n\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 = addListener;\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 = removeListener;\n\n /**\n * Cross-browser wrapper for getting event's coordinates\n * @memberOf fabric.util\n * @param {Event} event Event object\n */\n function getPointer(event) {\n event || (event = fabric.window.event);\n\n var element = event.target ||\n (typeof event.srcElement !== unknown ? event.srcElement : null),\n\n scroll = fabric.util.getScrollLeftTop(element);\n\n return {\n x: pointerX(event) + scroll.left,\n y: pointerY(event) + scroll.top\n };\n }\n\n var pointerX = function(event) {\n // looks like in IE (<9) clientX at certain point (apparently when mouseup fires on VML element)\n // is represented as COM object, with all the consequences, like \"unknown\" type and error on [[Get]]\n // need to investigate later\n return (typeof event.clientX !== unknown ? event.clientX : 0);\n },\n\n pointerY = function(event) {\n return (typeof event.clientY !== unknown ? event.clientY : 0);\n };\n\n function _getPointer(event, pageProp, clientProp) {\n var touchProp = event.type === 'touchend' ? 'changedTouches' : 'touches';\n\n return (event[touchProp] && event[touchProp][0]\n ? (event[touchProp][0][pageProp] - (event[touchProp][0][pageProp] - event[touchProp][0][clientProp]))\n || event[clientProp]\n : event[clientProp]);\n }\n\n if (fabric.isTouchSupported) {\n pointerX = function(event) {\n return _getPointer(event, 'pageX', 'clientX');\n };\n pointerY = function(event) {\n return _getPointer(event, 'pageY', 'clientY');\n };\n }\n\n fabric.util.getPointer = getPointer;\n\n fabric.util.object.extend(fabric.util, fabric.Observable);\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[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 &&\n fabric.util.getElementStyle(element, '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() {\n\n /**\n * Inserts a script element with a given url into a document; invokes callback, when that script is finished loading\n * @memberOf fabric.util\n * @param {String} url URL of a script to load\n * @param {Function} callback Callback to execute when script is finished loading\n */\n function getScript(url, callback) {\n var headEl = fabric.document.getElementsByTagName('head')[0],\n scriptEl = fabric.document.createElement('script'),\n loading = true;\n\n /** @ignore */\n scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) {\n if (loading) {\n if (typeof this.readyState === 'string' &&\n this.readyState !== 'loaded' &&\n this.readyState !== 'complete') {\n return;\n }\n loading = false;\n callback(e || fabric.window.event);\n scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null;\n }\n };\n scriptEl.src = url;\n headEl.appendChild(scriptEl);\n // causes issue in Opera\n // headEl.removeChild(scriptEl);\n }\n\n fabric.util.getScript = getScript;\n })();\n\n fabric.util.getById = getById;\n fabric.util.toArray = toArray;\n fabric.util.makeElement = makeElement;\n fabric.util.addClass = addClass;\n fabric.util.wrapElement = wrapElement;\n fabric.util.getScrollLeftTop = getScrollLeftTop;\n fabric.util.getElementOffset = getElementOffset;\n fabric.util.getElementStyle = getElementStyle;\n\n})();\n\n\n(function() {\n\n function addParamToUrl(url, param) {\n return url + (/\\?/.test(url) ? '&' : '?') + param;\n }\n\n var makeXHR = (function() {\n var factories = [\n function() { return new ActiveXObject('Microsoft.XMLHTTP'); },\n function() { return new ActiveXObject('Msxml2.XMLHTTP'); },\n function() { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); },\n function() { return new XMLHttpRequest(); }\n ];\n for (var i = factories.length; i--; ) {\n try {\n var req = factories[i]();\n if (req) {\n return factories[i];\n }\n }\n catch (err) { }\n }\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\n options || (options = { });\n\n var method = options.method ? options.method.toUpperCase() : 'GET',\n onComplete = options.onComplete || function() { },\n xhr = makeXHR(),\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 = function() { };\n\n/**\n * Wrapper around `console.warn` (when available)\n * @param {*} [values] Values to log as a warning\n */\nfabric.warn = function() { };\n\n/* eslint-disable */\nif (typeof console !== 'undefined') {\n\n ['log', 'warn'].forEach(function(methodName) {\n\n if (typeof console[methodName] !== 'undefined' &&\n typeof console[methodName].apply === 'function') {\n\n fabric[methodName] = function() {\n return console[methodName].apply(console, arguments);\n };\n }\n });\n}\n/* eslint-enable */\n\n\n(function() {\n\n function noop() {\n return false;\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 {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 {Number} [options.startValue=0] Starting value\n * @param {Number} [options.endValue=100] Ending value\n * @param {Number} [options.byValue=100] Value to modify the property by\n * @param {Function} [options.easing] Easing function\n * @param {Number} [options.duration=500] Duration of change (in ms)\n */\n function animate(options) {\n\n requestAnimFrame(function(timestamp) {\n options || (options = { });\n\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 || function(t, b, c, d) {return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;},\n startValue = 'startValue' in options ? options.startValue : 0,\n endValue = 'endValue' in options ? options.endValue : 100,\n byValue = options.byValue || endValue - startValue;\n\n options.onStart && options.onStart();\n\n (function tick(ticktime) {\n if (abort()) {\n onComplete(endValue, 1, 1);\n return;\n }\n time = ticktime || +new Date();\n var currentTime = time > finish ? duration : (time - start),\n timePerc = currentTime / duration,\n current = easing(currentTime, startValue, byValue, duration),\n valuePerc = Math.abs((current - startValue) / byValue);\n onChange(current, valuePerc, timePerc);\n if (time > finish) {\n options.onComplete && options.onComplete();\n return;\n }\n requestAnimFrame(tick);\n })(start);\n });\n\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 fabric.window.setTimeout(callback, 1000 / 60);\n };\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 fabric.util.animate = animate;\n fabric.util.requestAnimFrame = requestAnimFrame;\n\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 */\n function animateColor(fromColor, toColor, duration, options) {\n var startColor = new fabric.Color(fromColor).getSource(),\n endColor = new fabric.Color(toColor).getSource();\n\n options = options || {};\n\n 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 }));\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 reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/i,\n reViewBoxTagNames = /^(symbol|image|marker|pattern|view|svg)$/i,\n reNotAllowedAncestors = /^(?:pattern|defs|symbol|metadata|clipPath|mask)$/i,\n reAllowedParents = /^(symbol|g|a|svg)$/i,\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 'stroke-dasharray': 'strokeDashArray',\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': 'originX',\n opacity: 'opacity'\n },\n\n colorAttributes = {\n stroke: 'strokeOpacity',\n fill: 'fillOpacity'\n };\n\n fabric.cssRules = { };\n fabric.gradientDefs = { };\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 = Object.prototype.toString.call(value) === '[object Array]',\n parsed;\n\n if ((attr === 'fill' || attr === 'stroke') && value === 'none') {\n value = '';\n }\n else if (attr === 'strokeDashArray') {\n if (value === 'none') {\n value = null;\n }\n else {\n value = value.replace(/,/g, ' ').split(/\\s+/).map(function(n) {\n return parseFloat(n);\n });\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') ? false : true;\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 === 'originX' /* text-anchor */) {\n value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center';\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 * @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;\n for (var i = 0; i < nodeNames.length; 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 = Math.cos(args[0]), sin = Math.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 = [\n 1, // a\n 0, // b\n 0, // c\n 1, // d\n 0, // e\n 0 // f\n ],\n\n // == begin transform regexp\n number = fabric.reNum,\n\n commaWsp = '(?:\\\\s+,?\\\\s*|,\\\\s*)',\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;\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 (var 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\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, nodelist = doc.getElementsByTagName('*');\n for (i = 0; i < nodelist.length; 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\n while (nodelist.length && i < nodelist.length) {\n var el = nodelist[i],\n xlink = el.getAttribute('xlink:href').substr(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, oldLength = nodelist.length, attr, j, attrs, l;\n\n applyViewboxTransform(el2);\n if (/^svg$/i.test(el2.nodeName)) {\n var el3 = el2.ownerDocument.createElement('g');\n for (j = 0, attrs = el2.attributes, l = attrs.length; j < l; j++) {\n attr = attrs.item(j);\n el3.setAttribute(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, l = attrs.length; j < l; j++) {\n attr = attrs.item(j);\n if (attr.nodeName === 'x' || attr.nodeName === 'y' || attr.nodeName === 'xlink: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\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 || !reViewBoxTagNames.test(element.nodeName)\n || !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))),\n missingDimAttr = (!widthAttr || !heightAttr || widthAttr === '100%' || heightAttr === '100%'),\n toBeParsed = missingViewBox && missingDimAttr,\n parsedDim = { }, translateMatrix = '';\n\n parsedDim.width = 0;\n parsedDim.height = 0;\n parsedDim.toBeParsed = toBeParsed;\n\n if (toBeParsed) {\n return parsedDim;\n }\n\n if (missingViewBox) {\n parsedDim.width = parseUnit(widthAttr);\n parsedDim.height = parseUnit(heightAttr);\n return parsedDim;\n }\n\n minX = -parseFloat(viewBoxAttr[1]);\n minY = -parseFloat(viewBoxAttr[2]);\n viewBoxWidth = parseFloat(viewBoxAttr[3]);\n viewBoxHeight = parseFloat(viewBoxAttr[4]);\n\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 scaleY = scaleX = (scaleX > scaleY ? scaleY : scaleX);\n }\n\n if (scaleX === 1 && scaleY === 1 && minX === 0 && minY === 0 && x === 0 && y === 0) {\n return parsedDim;\n }\n\n if (x || y) {\n translateMatrix = ' translate(' + parseUnit(x) + ' ' + parseUnit(y) + ') ';\n }\n\n matrix = translateMatrix + ' matrix(' + scaleX +\n ' 0' +\n ' 0 ' +\n scaleY + ' ' +\n (minX * scaleX) + ' ' +\n (minY * scaleY) + ') ';\n\n if (element.nodeName === 'svg') {\n el = element.ownerDocument.createElement('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 matrix = el.getAttribute('transform') + matrix;\n }\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++,\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 (var 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 reAllowedSVGTagNames.test(el.nodeName.replace('svg:', '')) &&\n !hasAncestorWithNodeName(el, reNotAllowedAncestors); // http://www.w3.org/TR/SVG/struct.html#DefsElement\n });\n\n if (!elements || (elements && !elements.length)) {\n callback && callback([], {});\n return;\n }\n\n fabric.gradientDefs[svgUid] = fabric.getGradientDefs(doc);\n fabric.cssRules[svgUid] = fabric.getCSSRules(doc);\n // Precedence of rules: style > class > attribute\n fabric.parseElements(elements, function(instances) {\n if (callback) {\n callback(instances, options);\n }\n }, clone(options), reviver, parsingOptions);\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, id, xlink,\n gradientDefs = { }, idsToXlinkMap = { };\n\n j = elList.length;\n\n while (j--) {\n el = elList[j];\n xlink = el.getAttribute('xlink:href');\n id = el.getAttribute('id');\n if (xlink) {\n idsToXlinkMap[id] = xlink.substr(1);\n }\n gradientDefs[id] = el;\n }\n\n for (id in idsToXlinkMap) {\n var el2 = gradientDefs[idsToXlinkMap[id]].cloneNode(true);\n el = gradientDefs[id];\n while (el2.firstChild) {\n el.appendChild(el2.firstChild);\n }\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;\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 && reAllowedParents.test(element.parentNode.nodeName)) {\n parentAttributes = fabric.parseAttributes(element.parentNode, attributes, svgUid);\n }\n fontSize = (parentAttributes && parentAttributes.fontSize ) ||\n element.getAttribute('font-size') || fabric.Text.DEFAULT_SVG_FONT_SIZE;\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 ownAttributes = extend(ownAttributes,\n extend(getGlobalStylesForElement(element, svgUid), fabric.parseStyleAttribute(element)));\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 reAllowedParents.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 i = 0;\n len = points.length;\n for (; 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'),\n allRules = { }, rules;\n\n // very crude parsing of style contents\n for (var i = 0, len = styles.length; i < len; i++) {\n // IE9 doesn't support textContent, but provides text instead.\n var styleContents = styles[i].textContent || styles[i].text;\n\n // remove comments\n styleContents = styleContents.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n if (styleContents.trim() === '') {\n continue;\n }\n rules = styleContents.match(/[^{]*\\{[\\s\\S]*?\\}/g);\n rules = rules.map(function(rule) { return rule.trim(); });\n rules.forEach(function(rule) {\n\n var match = rule.match(/([\\s\\S]*?)\\s*\\{([^}]*)\\}/),\n ruleObj = { }, declaration = match[2].trim(),\n propertyValuePairs = declaration.replace(/;$/, '').split(/\\s*;\\s*/);\n\n for (var i = 0, len = propertyValuePairs.length; i < len; i++) {\n var pair = propertyValuePairs[i].split(/\\s*:\\s*/),\n property = pair[0],\n value = pair[1];\n ruleObj[property] = value;\n }\n rule = match[1];\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 && fabric.window.ActiveXObject && r.responseText) {\n xml = new ActiveXObject('Microsoft.XMLDOM');\n xml.async = 'false';\n //IE chokes on DOCTYPE\n xml.loadXML(r.responseText.replace(//i, ''));\n }\n if (!xml || !xml.documentElement) {\n callback && callback(null);\n }\n\n fabric.parseSVGDocument(xml.documentElement, function (results, _options) {\n callback && callback(results, _options);\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 string = string.trim();\n var doc;\n if (typeof DOMParser !== 'undefined') {\n var parser = new DOMParser();\n if (parser && parser.parseFromString) {\n doc = parser.parseFromString(string, 'text/xml');\n }\n }\n else if (fabric.window.ActiveXObject) {\n doc = new ActiveXObject('Microsoft.XMLDOM');\n doc.async = 'false';\n // IE chokes on DOCTYPE\n doc.loadXML(string.replace(//i, ''));\n }\n\n fabric.parseSVGDocument(doc.documentElement, function (results, _options) {\n callback(results, _options);\n }, reviver, options);\n }\n });\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\nfabric.ElementsParser = function(elements, callback, options, reviver, parsingOptions) {\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};\n\nfabric.ElementsParser.prototype.parse = function() {\n this.instances = new Array(this.elements.length);\n this.numElements = this.elements.length;\n\n this.createObjects();\n};\n\nfabric.ElementsParser.prototype.createObjects = function() {\n for (var i = 0, len = this.elements.length; i < len; i++) {\n this.elements[i].setAttribute('svgUid', this.svgUid);\n (function(_obj, i) {\n setTimeout(function() {\n _obj.createObject(_obj.elements[i], i);\n }, 0);\n })(this, i);\n }\n};\n\nfabric.ElementsParser.prototype.createObject = function(el, index) {\n var klass = fabric[fabric.util.string.capitalize(el.tagName.replace('svg:', ''))];\n if (klass && klass.fromElement) {\n try {\n this._createObject(klass, el, index);\n }\n catch (err) {\n fabric.log(err);\n }\n }\n else {\n this.checkIfDone();\n }\n};\n\nfabric.ElementsParser.prototype._createObject = function(klass, el, index) {\n if (klass.async) {\n klass.fromElement(el, this.createCallback(index, el), this.options);\n }\n else {\n var obj = klass.fromElement(el, this.options);\n this.resolveGradient(obj, 'fill');\n this.resolveGradient(obj, 'stroke');\n this.reviver && this.reviver(el, obj);\n this.instances[index] = obj;\n this.checkIfDone();\n }\n};\n\nfabric.ElementsParser.prototype.createCallback = function(index, el) {\n var _this = this;\n return function(obj) {\n _this.resolveGradient(obj, 'fill');\n _this.resolveGradient(obj, 'stroke');\n _this.reviver && _this.reviver(el, obj);\n _this.instances[index] = obj;\n _this.checkIfDone();\n };\n};\n\nfabric.ElementsParser.prototype.resolveGradient = function(obj, property) {\n\n var instanceFillValue = obj.get(property);\n if (!(/^url\\(/).test(instanceFillValue)) {\n return;\n }\n var gradientId = instanceFillValue.slice(5, instanceFillValue.length - 1);\n if (fabric.gradientDefs[this.svgUid][gradientId]) {\n obj.set(property,\n fabric.Gradient.fromElement(fabric.gradientDefs[this.svgUid][gradientId], obj));\n }\n};\n\nfabric.ElementsParser.prototype.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);\n }\n};\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 * Miltiplies 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 * Miltiplies 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;\n\n for (var 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;\n\n for (var 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 = 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();\n\n for (var 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*)?\\)$/;\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*)?\\)$/;\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 17 basic color names with HEX code\n * @static\n * @field\n * @memberOf fabric.Color\n * @see: http://www.w3.org/TR/CSS2/syndata.html#color-units\n */\n fabric.Color.colorNameMap = {\n aqua: '#00FFFF',\n black: '#000000',\n blue: '#0000FF',\n fuchsia: '#FF00FF',\n gray: '#808080',\n grey: '#808080',\n green: '#008000',\n lime: '#00FF00',\n maroon: '#800000',\n navy: '#000080',\n olive: '#808000',\n orange: '#FFA500',\n purple: '#800080',\n red: '#FF0000',\n silver: '#C0C0C0',\n teal: '#008080',\n white: '#FFFFFF',\n yellow: '#FFFF00'\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() {\n\n /* _FROM_SVG_START_ */\n function getColorStop(el) {\n var style = el.getAttribute('style'),\n offset = el.getAttribute('offset') || 0,\n color, colorAlpha, opacity;\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 (var 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;\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 * Constructor\n * @param {Object} [options] Options object with type, coords, gradientUnits and colorStops\n * @return {fabric.Gradient} thisArg\n */\n initialize: function(options) {\n options || (options = { });\n\n var coords = { };\n\n this.id = fabric.Object.__uid++;\n this.type = options.type || 'linear';\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 this.coords = coords;\n this.colorStops = options.colorStops.slice();\n if (options.gradientTransform) {\n this.gradientTransform = options.gradientTransform;\n }\n this.offsetX = options.offsetX || this.offsetX;\n this.offsetY = options.offsetY || this.offsetY;\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 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) {\n var coords = clone(this.coords, true),\n markup, commonAttributes, colorStops = clone(this.colorStops, true),\n needsSwap = coords.r1 > coords.r2;\n // colorStops must be sorted ascending\n colorStops.sort(function(a, b) {\n return a.offset - b.offset;\n });\n\n if (!(object.group && object.group.type === 'path-group')) {\n for (var prop in coords) {\n if (prop === 'x1' || prop === 'x2') {\n coords[prop] += this.offsetX - object.width / 2;\n }\n else if (prop === 'y1' || prop === 'y2') {\n coords[prop] += this.offsetY - object.height / 2;\n }\n }\n }\n\n commonAttributes = 'id=\"SVGID_' + this.id +\n '\" gradientUnits=\"userSpaceOnUse\"';\n if (this.gradientTransform) {\n commonAttributes += ' gradientTransform=\"matrix(' + this.gradientTransform.join(' ') + ')\" ';\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 (var i = 0; i < colorStops.length; 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 (var i = 0; i < colorStops.length; i++) {\n colorStops[i].offset += percentageShift * (1 - colorStops[i].offset);\n }\n }\n }\n\n for (var i = 0; i < colorStops.length; 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 * @param {Object} object\n * @return {CanvasGradient}\n */\n toLive: function(ctx, object) {\n var gradient, prop, coords = fabric.util.object.clone(this.coords);\n\n if (!this.type) {\n return;\n }\n\n if (object.group && object.group.type === 'path-group') {\n for (prop in coords) {\n if (prop === 'x1' || prop === 'x2') {\n coords[prop] += -this.offsetX + object.width / 2;\n }\n else if (prop === 'y1' || prop === 'y2') {\n coords[prop] += -this.offsetY + object.height / 2;\n }\n }\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 (var 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 * @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) {\n\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 colorStopEls = el.getElementsByTagName('stop'),\n type,\n gradientUnits = el.getAttribute('gradientUnits') || 'objectBoundingBox',\n gradientTransform = el.getAttribute('gradientTransform'),\n colorStops = [],\n coords, ellipseMatrix;\n\n if (el.nodeName === 'linearGradient' || el.nodeName === 'LINEARGRADIENT') {\n type = 'linear';\n }\n else {\n type = 'radial';\n }\n\n if (type === 'linear') {\n coords = getLinearCoords(el);\n }\n else if (type === 'radial') {\n coords = getRadialCoords(el);\n }\n\n for (var i = colorStopEls.length; i--; ) {\n colorStops.push(getColorStop(colorStopEls[i]));\n }\n\n ellipseMatrix = _convertPercentUnitsToValues(instance, coords, gradientUnits);\n\n var gradient = new fabric.Gradient({\n type: type,\n coords: coords,\n colorStops: colorStops,\n offsetX: -instance.left,\n offsetY: -instance.top\n });\n\n if (gradientTransform || ellipseMatrix !== '') {\n gradient.gradientTransform = fabric.parseTransformAttribute((gradientTransform || '') + ellipseMatrix);\n }\n return gradient;\n },\n /* _FROM_SVG_END_ */\n\n /**\n * Returns {@link fabric.Gradient} instance from its object representation\n * @static\n * @memberOf fabric.Gradient\n * @param {Object} obj\n * @param {Object} [options] Options object\n */\n forObject: function(obj, options) {\n options || (options = { });\n _convertPercentUnitsToValues(obj, options.coords, 'userSpaceOnUse');\n return new fabric.Gradient(options);\n }\n });\n\n /**\n * @private\n */\n function _convertPercentUnitsToValues(object, options, gradientUnits) {\n var propValue, addFactor = 0, multFactor = 1, ellipseMatrix = '';\n for (var prop in options) {\n if (options[prop] === 'Infinity') {\n options[prop] = 1;\n }\n else if (options[prop] === '-Infinity') {\n options[prop] = 0;\n }\n propValue = parseFloat(options[prop], 10);\n if (typeof options[prop] === 'string' && /^\\d+%$/.test(options[prop])) {\n multFactor = 0.01;\n }\n else {\n multFactor = 1;\n }\n if (prop === 'x1' || prop === 'x2' || prop === 'r2') {\n multFactor *= gradientUnits === 'objectBoundingBox' ? object.width : 1;\n addFactor = gradientUnits === 'objectBoundingBox' ? object.left || 0 : 0;\n }\n else if (prop === 'y1' || prop === 'y2') {\n multFactor *= gradientUnits === 'objectBoundingBox' ? object.height : 1;\n addFactor = gradientUnits === 'objectBoundingBox' ? object.top || 0 : 0;\n }\n options[prop] = propValue * multFactor + addFactor;\n }\n if (object.type === 'ellipse' &&\n options.r2 !== null &&\n gradientUnits === 'objectBoundingBox' &&\n object.rx !== object.ry) {\n\n var scaleFactor = object.ry / object.rx;\n ellipseMatrix = ' scale(1, ' + scaleFactor + ')';\n if (options.y1) {\n options.y1 /= scaleFactor;\n }\n if (options.y2) {\n options.y2 /= scaleFactor;\n }\n }\n return ellipseMatrix;\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 * 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 // function string\n if (typeof fabric.util.getFunctionBody(options.source) !== 'undefined') {\n this.source = new Function(fabric.util.getFunctionBody(options.source));\n callback && callback(this);\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) {\n _this.source = img;\n callback && callback(_this);\n });\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 // callback\n if (typeof this.source === 'function') {\n source = String(this.source);\n }\n // element\n else 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 offsetX: toFixed(this.offsetX, NUM_FRACTION_DIGITS),\n offsetY: toFixed(this.offsetY, NUM_FRACTION_DIGITS),\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 }\n if (this.repeat === 'repeat-y' || this.repeat === 'no-repeat') {\n patternWidth = 1;\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 = typeof this.source === 'function' ? this.source() : this.source;\n\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 * Constructor\n * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetX properties or string (e.g. \"rgba(0,0,0,0.2) 2px 2px 10px, \"2px 2px 10px rgba(0,0,0,0.2)\")\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: parseInt(offsetsAndBlur[1], 10) || 0,\n offsetY: parseInt(offsetsAndBlur[2], 10) || 0,\n blur: parseInt(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;\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 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 };\n }\n var obj = { }, proto = fabric.Shadow.prototype;\n\n ['color', 'blur', 'offsetX', 'offsetY', 'affectStroke'].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+(?:px)?(?:\\s?|$))?(-?\\d+(?:px)?(?:\\s?|$))?(\\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\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\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 * Should be set via {@link fabric.StaticCanvas#setBackgroundImage}.\n * Backwards incompatibility note: The \"backgroundImageOpacity\"\n * and \"backgroundImageStretch\" properties are deprecated since 1.3.9.\n * Use {@link fabric.Image#opacity}, {@link fabric.Image#width} and {@link fabric.Image#height}.\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 * Should be set via {@link fabric.StaticCanvas#setOverlayImage}.\n * Backwards incompatibility note: The \"overlayImageLeft\"\n * and \"overlayImageTop\" properties are deprecated since 1.3.9.\n * Use {@link fabric.Image#left} and {@link fabric.Image#top}.\n * @type fabric.Image\n * @default\n */\n overlayImage: null,\n\n /**\n * Indicates whether toObject/toDatalessObject should include default values\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} should also re-render canvas.\n * Disabling this option could give a great performance boost when adding/removing a lot of objects to/from canvas at once\n * (followed by a manual rendering after addition/deletion)\n * @type Boolean\n * @default\n */\n renderOnAddRemove: true,\n\n /**\n * Function that determines clipping of entire canvas area\n * Being passed context as first argument. See clipping canvas area in {@link https://github.com/kangax/fabric.js/wiki/FAQ}\n * @type Function\n * @default\n */\n clipTo: null,\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 (in the format of Canvas transform) which focuses the viewport\n * @type Array\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 * Callback; invoked right before object is about to be scaled/rotated\n */\n onBeforeScaleRotate: function () {\n /* NOOP */\n },\n\n /**\n * When true, canvas is scaled by devicePixelRatio for better rendering on retina screens\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 */\n skipOffscreen: false,\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 = fabric.StaticCanvas.prototype.renderAll.bind(this);\n this._objects = [];\n this._createLowerCanvas(el);\n this._initOptions(options);\n this._setImageSmoothing();\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() ? fabric.devicePixelRatio : 1;\n },\n\n /**\n * @private\n */\n _initRetinaScaling: function() {\n if (!this._isRetinaScaling()) {\n return;\n }\n this.lowerCanvasEl.setAttribute('width', this.width * fabric.devicePixelRatio);\n this.lowerCanvasEl.setAttribute('height', this.height * fabric.devicePixelRatio);\n\n this.contextContainer.scale(fabric.devicePixelRatio, fabric.devicePixelRatio);\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) {\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/fabricjs/YH9yD/|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) {\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 setBackgroundImage: function (image, callback, options) {\n return this.__setBgOverlayImage('backgroundImage', image, callback, options);\n },\n\n /**\n * Sets {@link fabric.StaticCanvas#overlayColor|background color} for this canvas\n * @param {(String|fabric.Pattern)} overlayColor 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/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 * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-imagesmoothingenabled|WhatWG Canvas Standard}\n */\n _setImageSmoothing: function() {\n var ctx = this.getContext();\n\n ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled || ctx.webkitImageSmoothingEnabled\n || ctx.mozImageSmoothingEnabled || ctx.msImageSmoothingEnabled || ctx.oImageSmoothingEnabled;\n ctx.imageSmoothingEnabled = this.imageSmoothingEnabled;\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\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) {\n img && (this[property] = new fabric.Image(img, options));\n callback && callback(img);\n }, this, options && options.crossOrigin);\n }\n else {\n options && image.setOptions(options);\n this[property] = image;\n callback && callback(image);\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(canvasEl) {\n var element = fabric.util.createCanvasElement(canvasEl);\n if (!element.style) {\n element.style = { };\n }\n if (!element) {\n throw CANVAS_INIT_ERROR;\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 this._setOptions(options);\n\n this.width = this.width || parseInt(this.lowerCanvasEl.width, 10) || 0;\n this.height = this.height || parseInt(this.lowerCanvasEl.height, 10) || 0;\n\n if (!this.lowerCanvasEl.style) {\n return;\n }\n\n this.lowerCanvasEl.width = this.width;\n this.lowerCanvasEl.height = this.height;\n\n this.lowerCanvasEl.style.width = this.width + 'px';\n this.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 this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement(canvasEl);\n\n fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas');\n\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 }\n\n if (!options.backstoreOnly) {\n this._setCssDimension(prop, cssValue);\n }\n }\n this._initRetinaScaling();\n this._setImageSmoothing();\n this.calcOffset();\n\n if (!options.cssOnly) {\n this.renderAll();\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 transform of this canvas instance\n * @param {Array} vpt the transform in the form of context.transform\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n setViewportTransform: function (vpt) {\n var activeGroup = this._activeGroup, object, ignoreVpt = false, skipAbsolute = true;\n this.viewportTransform = vpt;\n for (var i = 0, len = this._objects.length; i < len; i++) {\n object = this._objects[i];\n object.group || object.setCoords(ignoreVpt, skipAbsolute);\n }\n if (activeGroup) {\n activeGroup.setCoords(ignoreVpt, skipAbsolute);\n }\n this.calcViewportBoundaries();\n this.renderAll();\n return this;\n },\n\n /**\n * Sets zoom level of this canvas instance, zoom centered around point\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._objects.length = 0;\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.renderAll();\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 * 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.getWidth(), height = this.getHeight(),\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 /**\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 this.calcViewportBoundaries();\n this.clearContext(ctx);\n this.fire('before:render');\n if (this.clipTo) {\n fabric.util.clipContext(this, ctx);\n }\n this._renderBackground(ctx);\n\n ctx.save();\n //apply viewport transform once for all rendering process\n ctx.transform.apply(ctx, this.viewportTransform);\n this._renderObjects(ctx, objects);\n ctx.restore();\n if (!this.controlsAboveOverlay && this.interactive) {\n this.drawControls(ctx);\n }\n if (this.clipTo) {\n ctx.restore();\n }\n this._renderOverlay(ctx);\n if (this.controlsAboveOverlay && this.interactive) {\n this.drawControls(ctx);\n }\n this.fire('after:render');\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 for (var i = 0, length = objects.length; i < length; ++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 object = this[property + 'Color'];\n if (object) {\n ctx.fillStyle = object.toLive\n ? object.toLive(ctx, this)\n : object;\n\n ctx.fillRect(\n object.offsetX || 0,\n object.offsetY || 0,\n this.width,\n this.height);\n }\n object = this[property + 'Image'];\n if (object) {\n if (this[property + 'Vpt']) {\n ctx.save();\n ctx.transform.apply(ctx, this.viewportTransform);\n }\n object.render(ctx);\n this[property + 'Vpt'] && 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 */\n getCenter: function () {\n return {\n top: this.getHeight() / 2,\n left: this.getWidth() / 2\n };\n },\n\n /**\n * Centers object horizontally in the canvas\n * You might need to call `setCoords` on an object after centering, to update controls area.\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.getCenter().left, object.getCenterPoint().y));\n },\n\n /**\n * Centers object vertically in the canvas\n * You might need to call `setCoords` on an object after centering, to update controls area.\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.getCenter().top));\n },\n\n /**\n * Centers object vertically and horizontally in the canvas\n * You might need to call `setCoords` on an object after centering, to update controls area.\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.getCenter();\n\n return this._centerObject(object, new fabric.Point(center.left, center.top));\n },\n\n /**\n * Centers object vertically and horizontally in the viewport\n * You might need to call `setCoords` on an object after centering, to update controls area.\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\n return this._centerObject(object, vpCenter);\n },\n\n /**\n * Centers object horizontally in the viewport, object.top is unchanged\n * You might need to call `setCoords` on an object after centering, to update controls area.\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 * You might need to call `setCoords` on an object after centering, to update controls area.\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.getCenter(),\n iVpt = invertTransform(this.viewportTransform);\n return transformPoint({ x: center.left, y: center.top }, 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 this.renderAll();\n return this;\n },\n\n /**\n * Returs 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 data = {\n objects: this._toObjects(methodName, propertiesToInclude)\n };\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.getObjects().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, overlay = this.overlayImage;\n\n if (this.backgroundColor) {\n data.background = this.backgroundColor.toObject\n ? this.backgroundColor.toObject(propertiesToInclude)\n : this.backgroundColor;\n }\n\n if (this.overlayColor) {\n data.overlay = this.overlayColor.toObject\n ? this.overlayColor.toObject(propertiesToInclude)\n : this.overlayColor;\n }\n if (bgImage && !bgImage.excludeFromExport) {\n data.backgroundImage = this._toObject(bgImage, methodName, propertiesToInclude);\n }\n if (overlay && !overlay.excludeFromExport) {\n data.overlayImage = this._toObject(overlay, 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-cooridnate 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\n var markup = [];\n\n this._setSVGPreamble(markup, options);\n this._setSVGHeader(markup, options);\n\n this._setSVGBgOverlayColor(markup, 'backgroundColor');\n this._setSVGBgOverlayImage(markup, 'backgroundImage', reviver);\n\n this._setSVGObjects(markup, reviver);\n\n this._setSVGBgOverlayColor(markup, 'overlayColor');\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 '\\n'\n );\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 = ['backgroundColor', 'overlayColor'].map(function(prop) {\n var fill = _this[prop];\n if (fill && fill.toLive) {\n return fill.toSVG(_this, false);\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,\n fontPaths = fabric.fontPaths, objects = this.getObjects();\n\n for (var 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;\n for (var i = 0, objects = this.getObjects(), 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 * push single object svg representation in the markup\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].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];\n if (!filler) {\n return;\n }\n if (filler.toLive) {\n var repeat = filler.repeat;\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 activeGroup = this._activeGroup,\n i, obj, objs;\n if (object === activeGroup) {\n objs = activeGroup._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 return this.renderAll && this.renderAll();\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 activeGroup = this._activeGroup,\n i, obj, objs;\n if (object === activeGroup) {\n objs = activeGroup._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 return this.renderAll && this.renderAll();\n },\n\n /**\n * Moves an object or a selection down in stack of drawn objects\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\n var activeGroup = this._activeGroup,\n i, obj, idx, newIdx, objs, objsMoved = 0;\n\n if (object === activeGroup) {\n objs = activeGroup._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.renderAll && this.renderAll();\n return this;\n },\n\n /**\n * @private\n */\n _findNewLowerIndex: function(object, idx, intersecting) {\n var newIdx;\n\n if (intersecting) {\n newIdx = idx;\n\n // traverse down the stack looking for the nearest intersecting object\n for (var 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 * @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\n var activeGroup = this._activeGroup,\n i, obj, idx, newIdx, objs, objsMoved = 0;\n\n if (object === activeGroup) {\n objs = activeGroup._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.renderAll && this.renderAll();\n return this;\n },\n\n /**\n * @private\n */\n _findNewUpperIndex: function(object, idx, intersecting) {\n var newIdx;\n\n if (intersecting) {\n newIdx = idx;\n\n // traverse up the stack looking for the nearest intersecting object\n for (var i = idx + 1; i < this._objects.length; ++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.renderAll && this.renderAll();\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 this.clear();\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 \"getImageData\", \"toDataURL\", \"toDataURLWithQuality\" or \"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 = fabric.util.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 'getImageData':\n return typeof ctx.getImageData !== 'undefined';\n\n case 'setLineDash':\n return typeof ctx.setLineDash !== 'undefined';\n\n case 'toDataURL':\n return typeof el.toDataURL !== 'undefined';\n\n case 'toDataURLWithQuality':\n try {\n el.toDataURL('image/jpeg', 0);\n return true;\n }\n catch (e) { }\n return false;\n\n default:\n return null;\n }\n }\n });\n\n /**\n * Returns JSON representation of canvas\n * @function\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {String} JSON string\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', 'lockUniScaling']);\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})();\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\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 \"bevil\", \"round\", \"miter\")\n * @type String\n * @default\n */\n strokeLineJoin: 'round',\n\n /**\n * Stroke Dash Array.\n * @type Array\n * @default\n */\n strokeDashArray: null,\n\n /**\n * Sets shadow of an object\n * @param {Object|String} [options] Options object or string (e.g. \"2px 2px 10px rgba(0,0,0,0.2)\")\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setShadow: function(options) {\n this.shadow = new fabric.Shadow(options);\n return this;\n },\n\n /**\n * Sets brush styles\n * @private\n */\n _setBrushStyles: function() {\n var ctx = this.canvas.contextTop;\n\n ctx.strokeStyle = this.color;\n ctx.lineWidth = this.width;\n ctx.lineCap = this.strokeLineCap;\n ctx.lineJoin = this.strokeLineJoin;\n if (this.strokeDashArray && fabric.StaticCanvas.supports('setLineDash')) {\n ctx.setLineDash(this.strokeDashArray);\n }\n },\n\n /**\n * Sets brush shadow styles\n * @private\n */\n _setShadow: function() {\n if (!this.shadow) {\n return;\n }\n\n var ctx = this.canvas.contextTop,\n zoom = this.canvas.getZoom();\n\n ctx.shadowColor = this.shadow.color;\n ctx.shadowBlur = this.shadow.blur * zoom;\n ctx.shadowOffsetX = this.shadow.offsetX * zoom;\n ctx.shadowOffsetY = this.shadow.offsetY * zoom;\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\n(function() {\n\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 * 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 /**\n * Inovoked on mouse down\n * @param {Object} pointer\n */\n onMouseDown: function(pointer) {\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 * Inovoked on mouse move\n * @param {Object} pointer\n */\n onMouseMove: function(pointer) {\n this._captureDrawingPath(pointer);\n // redraw curve\n // clear top canvas\n this.canvas.clearContext(this.canvas.contextTop);\n this._render();\n },\n\n /**\n * Invoked on mouse up\n */\n onMouseUp: function() {\n this._finalizeAndAddPath();\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\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;\n }\n this._points.push(point);\n },\n\n /**\n * Clear points array and set contextTop canvas style.\n * @private\n */\n _reset: function() {\n this._points.length = 0;\n\n this._setBrushStyles();\n this._setShadow();\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 this._addPoint(pointerPoint);\n },\n\n /**\n * Draw a smooth path on the topCanvas using quadraticCurveTo\n * @private\n */\n _render: function() {\n var ctx = this.canvas.contextTop, i, len,\n v = this.canvas.viewportTransform,\n p1 = this._points[0],\n p2 = this._points[1];\n\n ctx.save();\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n ctx.beginPath();\n\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 var midPoint = p1.midPointFrom(p2);\n ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);\n\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} SVG path\n */\n convertPointsToSVGPath: function(points) {\n var path = [], i, width = this.width / 1000,\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 = 1, manyPoints = len > 2;\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 * width, ' ', p1.y - multSignY * width, ' ');\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 * width, ' ', p1.y + multSignY * width);\n return path;\n },\n\n /**\n * Creates fabric.Path object to add on canvas\n * @param {String} 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 strokeLineJoin: this.strokeLineJoin,\n strokeDashArray: this.strokeDashArray,\n originX: 'center',\n originY: 'center'\n });\n var position = new fabric.Point(path.left, path.top);\n path.originX = fabric.Object.prototype.originX;\n path.originY = fabric.Object.prototype.originY;\n position = path.translateToGivenOrigin(\n position, 'center', 'center', path.originX, path.originY);\n path.top = position.y;\n path.left = position.x;\n if (this.shadow) {\n this.shadow.affectStroke = true;\n path.setShadow(this.shadow);\n }\n\n return path;\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\n var pathData = this.convertPointsToSVGPath(this._points).join('');\n if (pathData === 'M 0 0 Q 0 0 0 0 L 0 0') {\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.renderAll();\n return;\n }\n\n var path = this.createPath(pathData);\n\n this.canvas.add(path);\n path.setCoords();\n\n this.canvas.clearContext(this.canvas.contextTop);\n this._resetShadow();\n this.canvas.renderAll();\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 v = this.canvas.viewportTransform;\n ctx.save();\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n\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 ctx.restore();\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 * Invoked on mouse move\n * @param {Object} pointer\n */\n onMouseMove: function(pointer) {\n this.drawDot(pointer);\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 circles = [];\n\n for (var 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.setShadow(this.shadow);\n\n circles.push(circle);\n }\n var group = new fabric.Group(circles, { originX: 'center', originY: 'center' });\n group.canvas = this.canvas;\n\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.renderAll();\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();\n },\n\n /**\n * Invoked on mouse move\n * @param {Object} pointer\n */\n onMouseMove: function(pointer) {\n this.addSprayChunk(pointer);\n this.render();\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\n this.shadow && rect.setShadow(this.shadow);\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, { originX: 'center', originY: 'center' });\n group.canvas = this.canvas;\n\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.renderAll();\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;\n\n for (var 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 * Renders brush\n */\n render: function() {\n var ctx = this.canvas.contextTop;\n ctx.fillStyle = this.color;\n\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 for (var i = 0, len = this.sprayChunkPoints.length; i < len; i++) {\n var point = this.sprayChunkPoints[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 * @param {Object} pointer\n */\n addSprayChunk: function(pointer) {\n this.sprayChunkPoints = [];\n\n var x, y, width, radius = this.width / 2;\n\n for (var 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.document.createElement('canvas'),\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 */\n getPattern: function() {\n return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), 'repeat');\n },\n\n /**\n * Sets brush styles\n */\n _setBrushStyles: function() {\n this.callSuper('_setBrushStyles');\n this.canvas.contextTop.strokeStyle = this.getPattern();\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 radiansToDegrees = fabric.util.radiansToDegrees,\n atan2 = Math.atan2,\n abs = Math.abs,\n supportLineDash = fabric.StaticCanvas.supports('setLineDash'),\n\n STROKE_OFFSET = 0.5;\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:added\n * @fires object:modified\n * @fires object:rotating\n * @fires object:scaling\n * @fires object:moving\n * @fires object:selected\n *\n * @fires before:selection:cleared\n * @fires selection:cleared\n * @fires selection:created\n *\n * @fires path:created\n * @fires mouse:down\n * @fires mouse:move\n * @fires mouse:up\n * @fires mouse:over\n * @fires mouse:out\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\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 * @type Boolean\n * @default\n */\n uniScaleTransform: false,\n\n /**\n * Indicates which key enable unproportional 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 feature disabled.\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 Transfrom\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 enable multiple click selection\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 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 * If `null` or 'none' or any other string that is not a modifier key\n * feature is disabled feature 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 * 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 rotation point\n * @type String\n * @default\n */\n rotationCursor: 'crosshair',\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 when hovering over canvas. This can be used to improve performance.\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 * @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 activeGroup = this.getActiveGroup(),\n activeObject = this.getActiveObject(),\n object, objsToRender = [], activeGroupObjects = [];\n\n if ((activeGroup || activeObject) && !this.preserveObjectStacking) {\n for (var i = 0, length = this._objects.length; i < length; i++) {\n object = this._objects[i];\n if ((!activeGroup || !activeGroup.contains(object)) && object !== activeObject) {\n objsToRender.push(object);\n }\n else {\n activeGroupObjects.push(object);\n }\n }\n if (activeGroup) {\n activeGroup._set('_objects', activeGroupObjects);\n objsToRender.push(activeGroup);\n }\n activeObject && objsToRender.push(activeObject);\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 var canvasToDrawOn = this.contextContainer;\n this.renderCanvas(canvasToDrawOn, this._chooseObjectsToRender());\n return this;\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\n // we render the top context - last object\n if (this.selection && this._groupSelector) {\n this._drawSelection(ctx);\n }\n\n this.fire('after:render');\n this.contextTopDirty = true;\n return this;\n },\n\n /**\n * Resets the current transform to its original values and chooses the type of resizing based on the event\n * @private\n */\n _resetCurrentTransform: function() {\n var t = this._currentTransform;\n\n t.target.set({\n scaleX: t.original.scaleX,\n scaleY: t.original.scaleY,\n skewX: t.original.skewX,\n skewY: t.original.skewY,\n left: t.original.left,\n top: t.original.top\n });\n\n if (this._shouldCenterTransform(t.target)) {\n if (t.action === 'rotate') {\n this._setOriginToCenter(t.target);\n }\n else {\n if (t.originX !== 'center') {\n if (t.originX === 'right') {\n t.mouseXSign = -1;\n }\n else {\n t.mouseXSign = 1;\n }\n }\n if (t.originY !== 'center') {\n if (t.originY === 'bottom') {\n t.mouseYSign = -1;\n }\n else {\n t.mouseYSign = 1;\n }\n }\n\n t.originX = 'center';\n t.originY = 'center';\n }\n }\n else {\n t.originX = t.original.originX;\n t.originY = t.original.originY;\n }\n },\n\n /**\n * Checks if point is contained within an area of given object\n * @param {Event} e Event object\n * @param {fabric.Object} target Object to test against\n * @param {Object} [point] x,y object of point coordinates we want to check.\n * @return {Boolean} true if point is contained within an area of given object\n */\n containsPoint: function (e, target, point) {\n var ignoreZoom = true,\n pointer = point || this.getPointer(e, ignoreZoom),\n xy;\n\n if (target.group && target.group === this.getActiveGroup()) {\n xy = this._normalizePointer(target.group, pointer);\n }\n else {\n xy = { x: pointer.x, y: pointer.y };\n }\n // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html\n // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html\n return (target.containsPoint(xy) || target._findTargetCorner(pointer));\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 var hasBorders = target.hasBorders,\n transparentCorners = target.transparentCorners,\n ctx = this.contextCache,\n originalColor = target.selectionBackgroundColor;\n\n target.hasBorders = target.transparentCorners = false;\n target.selectionBackgroundColor = '';\n\n ctx.save();\n ctx.transform.apply(ctx, this.viewportTransform);\n target.render(ctx);\n ctx.restore();\n\n target.active && target._renderControls(ctx);\n\n target.hasBorders = hasBorders;\n target.transparentCorners = transparentCorners;\n target.selectionBackgroundColor = originalColor;\n\n var isTransparent = fabric.util.isTransparent(\n ctx, x, y, this.targetFindTolerance);\n\n this.clearContext(ctx);\n\n return isTransparent;\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n */\n _shouldClearSelection: function (e, target) {\n var activeGroup = this.getActiveGroup(),\n activeObject = this.getActiveObject();\n\n return (\n !target\n ||\n (target &&\n activeGroup &&\n !activeGroup.contains(target) &&\n activeGroup !== target &&\n !e[this.selectionKey])\n ||\n (target && !target.evented)\n ||\n (target &&\n !target.selectable &&\n activeObject &&\n activeObject !== target)\n );\n },\n\n /**\n * @private\n * @param {fabric.Object} target\n */\n _shouldCenterTransform: function (target) {\n if (!target) {\n return;\n }\n\n var t = this._currentTransform,\n centerTransform;\n\n if (t.action === 'scale' || t.action === 'scaleX' || t.action === 'scaleY') {\n centerTransform = this.centeredScaling || target.centeredScaling;\n }\n else if (t.action === 'rotate') {\n centerTransform = this.centeredRotation || target.centeredRotation;\n }\n\n return centerTransform ? !t.altKey : t.altKey;\n },\n\n /**\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\n return origin;\n },\n\n /**\n * @private\n */\n _getActionFromCorner: function(target, corner, e) {\n if (!corner) {\n return 'drag';\n }\n\n switch (corner) {\n case 'mtr':\n return 'rotate';\n case 'ml':\n case 'mr':\n return e[this.altActionKey] ? 'skewY' : 'scaleX';\n case 'mt':\n case 'mb':\n return e[this.altActionKey] ? 'skewX' : 'scaleY';\n default:\n return 'scale';\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n */\n _setupCurrentTransform: function (e, target) {\n if (!target) {\n return;\n }\n\n var pointer = this.getPointer(e),\n corner = target._findTargetCorner(this.getPointer(e, true)),\n action = this._getActionFromCorner(target, corner, e),\n origin = this._getOriginFromCorner(target, corner);\n\n this._currentTransform = {\n target: target,\n action: action,\n corner: corner,\n scaleX: target.scaleX,\n scaleY: target.scaleY,\n skewX: target.skewX,\n skewY: target.skewY,\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 left: target.left,\n top: target.top,\n theta: degreesToRadians(target.angle),\n width: target.width * target.scaleX,\n mouseXSign: 1,\n mouseYSign: 1,\n shiftKey: e.shiftKey,\n altKey: e[this.centeredKey]\n };\n\n this._currentTransform.original = {\n left: target.left,\n top: target.top,\n scaleX: target.scaleX,\n scaleY: target.scaleY,\n skewX: target.skewX,\n skewY: target.skewY,\n originX: origin.x,\n originY: origin.y\n };\n\n this._resetCurrentTransform();\n },\n\n /**\n * Translates object by \"setting\" its left/top\n * @private\n * @param {Number} x pointer's x coordinate\n * @param {Number} y pointer's y coordinate\n * @return {Boolean} true if the translation occurred\n */\n _translateObject: function (x, y) {\n var transform = this._currentTransform,\n 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\n moveX && target.set('left', newLeft);\n moveY && target.set('top', newTop);\n return moveX || moveY;\n },\n\n /**\n * Check if we are increasing a positive skew or lower it,\n * checking mouse direction and pressed corner.\n * @private\n */\n _changeSkewTransformOrigin: function(mouseMove, t, by) {\n var property = 'originX', origins = { 0: 'center' },\n skew = t.target.skewX, originA = 'left', originB = 'right',\n corner = t.corner === 'mt' || t.corner === 'ml' ? 1 : -1,\n flipSign = 1;\n\n mouseMove = mouseMove > 0 ? 1 : -1;\n if (by === 'y') {\n skew = t.target.skewY;\n originA = 'top';\n originB = 'bottom';\n property = 'originY';\n }\n origins[-1] = originA;\n origins[1] = originB;\n\n t.target.flipX && (flipSign *= -1);\n t.target.flipY && (flipSign *= -1);\n\n if (skew === 0) {\n t.skewSign = -corner * mouseMove * flipSign;\n t[property] = origins[-mouseMove];\n }\n else {\n skew = skew > 0 ? 1 : -1;\n t.skewSign = skew;\n t[property] = origins[skew * corner * flipSign];\n }\n },\n\n /**\n * Skew object by mouse events\n * @private\n * @param {Number} x pointer's x coordinate\n * @param {Number} y pointer's y coordinate\n * @param {String} by Either 'x' or 'y'\n * @return {Boolean} true if the skewing occurred\n */\n _skewObject: function (x, y, by) {\n var t = this._currentTransform,\n target = t.target, skewed = false,\n lockSkewingX = target.get('lockSkewingX'),\n lockSkewingY = target.get('lockSkewingY');\n\n if ((lockSkewingX && by === 'x') || (lockSkewingY && by === 'y')) {\n return false;\n }\n\n // Get the constraint point\n var center = target.getCenterPoint(),\n actualMouseByCenter = target.toLocalPoint(new fabric.Point(x, y), 'center', 'center')[by],\n lastMouseByCenter = target.toLocalPoint(new fabric.Point(t.lastX, t.lastY), 'center', 'center')[by],\n actualMouseByOrigin, constraintPosition, dim = target._getTransformedDimensions();\n\n this._changeSkewTransformOrigin(actualMouseByCenter - lastMouseByCenter, t, by);\n actualMouseByOrigin = target.toLocalPoint(new fabric.Point(x, y), t.originX, t.originY)[by];\n constraintPosition = target.translateToOriginPoint(center, t.originX, t.originY);\n // Actually skew the object\n skewed = this._setObjectSkew(actualMouseByOrigin, t, by, dim);\n t.lastX = x;\n t.lastY = y;\n // Make sure the constraints apply\n target.setPositionByOrigin(constraintPosition, t.originX, t.originY);\n return skewed;\n },\n\n /**\n * Set object skew\n * @private\n * @return {Boolean} true if the skewing occurred\n */\n _setObjectSkew: function(localMouse, transform, by, _dim) {\n var target = transform.target, newValue, skewed = false,\n skewSign = transform.skewSign, newDim, dimNoSkew,\n otherBy, _otherBy, _by, newDimMouse, skewX, skewY;\n\n if (by === 'x') {\n otherBy = 'y';\n _otherBy = 'Y';\n _by = 'X';\n skewX = 0;\n skewY = target.skewY;\n }\n else {\n otherBy = 'x';\n _otherBy = 'X';\n _by = 'Y';\n skewX = target.skewX;\n skewY = 0;\n }\n\n dimNoSkew = target._getTransformedDimensions(skewX, skewY);\n newDimMouse = 2 * Math.abs(localMouse) - dimNoSkew[by];\n if (newDimMouse <= 2) {\n newValue = 0;\n }\n else {\n newValue = skewSign * Math.atan((newDimMouse / target['scale' + _by]) /\n (dimNoSkew[otherBy] / target['scale' + _otherBy]));\n newValue = fabric.util.radiansToDegrees(newValue);\n }\n skewed = target['skew' + _by] !== newValue;\n target.set('skew' + _by, newValue);\n if (target['skew' + _otherBy] !== 0) {\n newDim = target._getTransformedDimensions();\n newValue = (_dim[otherBy] / newDim[otherBy]) * target['scale' + _otherBy];\n target.set('scale' + _otherBy, newValue);\n }\n return skewed;\n },\n\n /**\n * Scales object by invoking its scaleX/scaleY methods\n * @private\n * @param {Number} x pointer's x coordinate\n * @param {Number} y pointer's y coordinate\n * @param {String} by Either 'x' or 'y' - specifies dimension constraint by which to scale an object.\n * When not provided, an object is scaled by both dimensions equally\n * @return {Boolean} true if the scaling occurred\n */\n _scaleObject: function (x, y, by) {\n var t = this._currentTransform,\n target = t.target,\n lockScalingX = target.get('lockScalingX'),\n lockScalingY = target.get('lockScalingY'),\n lockScalingFlip = target.get('lockScalingFlip');\n\n if (lockScalingX && lockScalingY) {\n return false;\n }\n\n // Get the constraint point\n var constraintPosition = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY),\n localMouse = target.toLocalPoint(new fabric.Point(x, y), t.originX, t.originY),\n dim = target._getTransformedDimensions(), scaled = false;\n\n this._setLocalMouse(localMouse, t);\n\n // Actually scale the object\n scaled = this._setObjectScale(localMouse, t, lockScalingX, lockScalingY, by, lockScalingFlip, dim);\n\n // Make sure the constraints apply\n target.setPositionByOrigin(constraintPosition, t.originX, t.originY);\n return scaled;\n },\n\n /**\n * @private\n * @return {Boolean} true if the scaling occurred\n */\n _setObjectScale: function(localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip, _dim) {\n var target = transform.target, forbidScalingX = false, forbidScalingY = false, scaled = false,\n changeX, changeY, scaleX, scaleY;\n\n scaleX = localMouse.x * target.scaleX / _dim.x;\n scaleY = localMouse.y * target.scaleY / _dim.y;\n changeX = target.scaleX !== scaleX;\n changeY = target.scaleY !== scaleY;\n\n if (lockScalingFlip && scaleX <= 0 && scaleX < target.scaleX) {\n forbidScalingX = true;\n }\n\n if (lockScalingFlip && scaleY <= 0 && scaleY < target.scaleY) {\n forbidScalingY = true;\n }\n\n if (by === 'equally' && !lockScalingX && !lockScalingY) {\n forbidScalingX || forbidScalingY || (scaled = this._scaleObjectEqually(localMouse, target, transform, _dim));\n }\n else if (!by) {\n forbidScalingX || lockScalingX || (target.set('scaleX', scaleX) && (scaled = scaled || changeX));\n forbidScalingY || lockScalingY || (target.set('scaleY', scaleY) && (scaled = scaled || changeY));\n }\n else if (by === 'x' && !target.get('lockUniScaling')) {\n forbidScalingX || lockScalingX || (target.set('scaleX', scaleX) && (scaled = scaled || changeX));\n }\n else if (by === 'y' && !target.get('lockUniScaling')) {\n forbidScalingY || lockScalingY || (target.set('scaleY', scaleY) && (scaled = scaled || changeY));\n }\n transform.newScaleX = scaleX;\n transform.newScaleY = scaleY;\n forbidScalingX || forbidScalingY || this._flipObject(transform, by);\n return scaled;\n },\n\n /**\n * @private\n * @return {Boolean} true if the scaling occurred\n */\n _scaleObjectEqually: function(localMouse, target, transform, _dim) {\n\n var dist = localMouse.y + localMouse.x,\n lastDist = _dim.y * transform.original.scaleY / target.scaleY +\n _dim.x * transform.original.scaleX / target.scaleX,\n scaled, signX = localMouse.x / Math.abs(localMouse.x),\n signY = localMouse.y / Math.abs(localMouse.y);\n\n // We use transform.scaleX/Y instead of target.scaleX/Y\n // because the object may have a min scale and we'll loose the proportions\n transform.newScaleX = signX * Math.abs(transform.original.scaleX * dist / lastDist);\n transform.newScaleY = signY * Math.abs(transform.original.scaleY * dist / lastDist);\n scaled = transform.newScaleX !== target.scaleX || transform.newScaleY !== target.scaleY;\n target.set('scaleX', transform.newScaleX);\n target.set('scaleY', transform.newScaleY);\n return scaled;\n },\n\n /**\n * @private\n */\n _flipObject: function(transform, by) {\n if (transform.newScaleX < 0 && by !== 'y') {\n if (transform.originX === 'left') {\n transform.originX = 'right';\n }\n else if (transform.originX === 'right') {\n transform.originX = 'left';\n }\n }\n\n if (transform.newScaleY < 0 && by !== 'x') {\n if (transform.originY === 'top') {\n transform.originY = 'bottom';\n }\n else if (transform.originY === 'bottom') {\n transform.originY = 'top';\n }\n }\n },\n\n /**\n * @private\n */\n _setLocalMouse: function(localMouse, t) {\n var target = t.target, zoom = this.getZoom(),\n padding = target.padding / zoom;\n\n if (t.originX === 'right') {\n localMouse.x *= -1;\n }\n else if (t.originX === 'center') {\n localMouse.x *= t.mouseXSign * 2;\n if (localMouse.x < 0) {\n t.mouseXSign = -t.mouseXSign;\n }\n }\n\n if (t.originY === 'bottom') {\n localMouse.y *= -1;\n }\n else if (t.originY === 'center') {\n localMouse.y *= t.mouseYSign * 2;\n if (localMouse.y < 0) {\n t.mouseYSign = -t.mouseYSign;\n }\n }\n\n // adjust the mouse coordinates when dealing with padding\n if (abs(localMouse.x) > padding) {\n if (localMouse.x < 0) {\n localMouse.x += padding;\n }\n else {\n localMouse.x -= padding;\n }\n }\n else { // mouse is within the padding, set to 0\n localMouse.x = 0;\n }\n\n if (abs(localMouse.y) > padding) {\n if (localMouse.y < 0) {\n localMouse.y += padding;\n }\n else {\n localMouse.y -= padding;\n }\n }\n else {\n localMouse.y = 0;\n }\n },\n\n /**\n * Rotates object by invoking its rotate method\n * @private\n * @param {Number} x pointer's x coordinate\n * @param {Number} y pointer's y coordinate\n * @return {Boolean} true if the rotation occurred\n */\n _rotateObject: function (x, y) {\n\n var t = this._currentTransform;\n\n if (t.target.get('lockRotation')) {\n return false;\n }\n\n var lastAngle = atan2(t.ey - t.top, t.ex - t.left),\n curAngle = atan2(y - t.top, x - t.left),\n angle = radiansToDegrees(curAngle - lastAngle + t.theta),\n hasRoated = true;\n\n if (t.target.snapAngle > 0) {\n var snapAngle = t.target.snapAngle,\n snapThreshold = t.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 if (t.target.angle === angle) {\n hasRoated = false;\n }\n else {\n t.target.angle = angle;\n }\n\n return hasRoated;\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 * @param {fabric.Object} target to reset transform\n * @private\n */\n _resetObjectTransform: function (target) {\n target.scaleX = 1;\n target.scaleY = 1;\n target.skewX = 0;\n target.skewY = 0;\n target.setAngle(0);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx to draw the selection on\n */\n _drawSelection: function (ctx) {\n var groupSelector = this._groupSelector,\n left = groupSelector.left,\n top = groupSelector.top,\n aleft = abs(left),\n atop = abs(top);\n\n if (this.selectionColor) {\n ctx.fillStyle = this.selectionColor;\n\n ctx.fillRect(\n groupSelector.ex - ((left > 0) ? 0 : -left),\n groupSelector.ey - ((top > 0) ? 0 : -top),\n aleft,\n atop\n );\n }\n\n if (!this.selectionLineWidth || !this.selectionBorderColor) {\n return;\n }\n ctx.lineWidth = this.selectionLineWidth;\n ctx.strokeStyle = this.selectionBorderColor;\n\n // selection border\n if (this.selectionDashArray.length > 1 && !supportLineDash) {\n\n var px = groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft),\n py = groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop);\n\n ctx.beginPath();\n\n fabric.util.drawDashedLine(ctx, px, py, px + aleft, py, this.selectionDashArray);\n fabric.util.drawDashedLine(ctx, px, py + atop - 1, px + aleft, py + atop - 1, this.selectionDashArray);\n fabric.util.drawDashedLine(ctx, px, py, px, py + atop, this.selectionDashArray);\n fabric.util.drawDashedLine(ctx, px + aleft - 1, py, px + aleft - 1, py + atop, this.selectionDashArray);\n\n ctx.closePath();\n ctx.stroke();\n }\n else {\n fabric.Object.prototype._setLineDash.call(this, ctx, this.selectionDashArray);\n ctx.strokeRect(\n groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft),\n groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop),\n aleft,\n atop\n );\n }\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 * @param {Event} e mouse event\n * @param {Boolean} skipGroup when true, activeGroup is skipped and only objects are traversed through\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 activeGroup = this.getActiveGroup(),\n activeObject = this.getActiveObject(),\n activeTarget, activeTargetSubs;\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 if (activeGroup && !skipGroup && activeGroup === this._searchPossibleTargets([activeGroup], pointer)) {\n this._fireOverOutEvents(activeGroup, e);\n return activeGroup;\n }\n // if we hit the corner of an activeObject, let's return that.\n if (activeObject && activeObject._findTargetCorner(pointer)) {\n this._fireOverOutEvents(activeObject, e);\n return activeObject;\n }\n if (activeObject && activeObject === this._searchPossibleTargets([activeObject], pointer)) {\n if (!this.preserveObjectStacking) {\n this._fireOverOutEvents(activeObject, e);\n return activeObject;\n }\n else {\n activeTarget = activeObject;\n activeTargetSubs = this.targets;\n this.targets = [];\n }\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 this._fireOverOutEvents(target, e);\n return target;\n },\n\n /**\n * @private\n */\n _fireOverOutEvents: function(target, e) {\n var overOpt, outOpt, hoveredTarget = this._hoveredTarget;\n if (hoveredTarget !== target) {\n overOpt = { e: e, target: target, previousTarget: this._hoveredTarget };\n outOpt = { e: e, target: this._hoveredTarget, nextTarget: target };\n this._hoveredTarget = target;\n }\n if (target) {\n if (hoveredTarget !== target) {\n if (hoveredTarget) {\n this.fire('mouse:out', outOpt);\n hoveredTarget.fire('mouseout', outOpt);\n }\n this.fire('mouse:over', overOpt);\n target.fire('mouseover', overOpt);\n }\n }\n else if (hoveredTarget) {\n this.fire('mouse:out', outOpt);\n hoveredTarget.fire('mouseout', outOpt);\n }\n },\n\n /**\n * @private\n */\n _checkTarget: function(pointer, obj) {\n if (obj &&\n obj.visible &&\n obj.evented &&\n this.containsPoint(null, obj, pointer)){\n if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) {\n var isTransparent = this.isTargetTransparent(obj, pointer.x, pointer.y);\n if (!isTransparent) {\n return true;\n }\n }\n else {\n return true;\n }\n }\n },\n\n /**\n * @private\n */\n _searchPossibleTargets: function(objects, pointer) {\n\n // Cache all targets where their bounding box contains point.\n var target, i = objects.length, normalizedPointer, subTarget;\n // Do not check for currently grouped objects, since we check the parent group itself.\n // untill we call this function specifically to search inside the activeGroup\n while (i--) {\n if (this._checkTarget(pointer, objects[i])) {\n target = objects[i];\n if (target.type === 'group' && target.subTargetCheck) {\n normalizedPointer = this._normalizePointer(target, pointer);\n subTarget = this._searchPossibleTargets(target._objects, normalizedPointer);\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 * 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, upperCanvasEl) {\n if (!upperCanvasEl) {\n upperCanvasEl = this.upperCanvasEl;\n }\n var pointer = getPointer(e),\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\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 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\n if (this.upperCanvasEl) {\n this.upperCanvasEl.className = '';\n }\n else {\n this.upperCanvasEl = this._createCanvasElement();\n }\n fabric.util.addClass(this.upperCanvasEl, 'upper-canvas ' + lowerCanvasClass);\n\n this.wrapperEl.appendChild(this.upperCanvasEl);\n\n this._copyCanvasStyle(this.lowerCanvasEl, this.upperCanvasEl);\n this._applyCanvasStyle(this.upperCanvasEl);\n this.contextTop = this.upperCanvasEl.getContext('2d');\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.getWidth() + 'px',\n height: this.getHeight() + '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.getWidth() || element.width,\n height = this.getHeight() || 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': 'none'\n });\n element.width = width;\n element.height = height;\n fabric.util.makeElementUnselectable(element);\n },\n\n /**\n * Copys the 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 * @private\n * @param {Object} object\n */\n _setActiveObject: function(object) {\n var obj = this._activeObject;\n if (obj) {\n obj.set('active', false);\n if (object !== obj && obj.onDeselect && typeof obj.onDeselect === 'function') {\n obj.onDeselect();\n }\n }\n this._activeObject = object;\n object.set('active', true);\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 currentActiveObject = this.getActiveObject();\n if (currentActiveObject && currentActiveObject !== object) {\n currentActiveObject.fire('deselected', { e: e });\n }\n this._setActiveObject(object);\n this.fire('object:selected', { target: object, e: e });\n object.fire('selected', { e: e });\n this.renderAll();\n return this;\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 * @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 (this.getActiveObject() === obj) {\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 (this._hoveredTarget === obj) {\n this._hoveredTarget = null;\n }\n this.callSuper('_onObjectRemoved', obj);\n },\n\n /**\n * @private\n */\n _discardActiveObject: function() {\n var obj = this._activeObject;\n if (obj) {\n obj.set('active', false);\n if (obj.onDeselect && typeof obj.onDeselect === 'function') {\n obj.onDeselect();\n }\n }\n this._activeObject = null;\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 parmater 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 activeObject = this._activeObject;\n if (activeObject) {\n this.fire('before:selection:cleared', { target: activeObject, e: e });\n this._discardActiveObject();\n this.fire('selection:cleared', { e: e });\n activeObject.fire('deselected', { e: e });\n }\n return this;\n },\n\n /**\n * @private\n * @param {fabric.Group} group\n */\n _setActiveGroup: function(group) {\n this._activeGroup = group;\n if (group) {\n group.set('active', true);\n }\n },\n\n /**\n * Sets active group to a specified one. If the function is called by fabric\n * as a consequence of a mouse event, the event is passed as a parmater 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 {fabric.Group} group Group to set as a current one\n * @param {Event} e Event object\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n setActiveGroup: function (group, e) {\n this._setActiveGroup(group);\n if (group) {\n this.fire('object:selected', { target: group, e: e });\n group.fire('selected', { e: e });\n }\n return this;\n },\n\n /**\n * Returns currently active group\n * @return {fabric.Group} Current group\n */\n getActiveGroup: function () {\n return this._activeGroup;\n },\n\n /**\n * @private\n */\n _discardActiveGroup: function() {\n var g = this.getActiveGroup();\n if (g) {\n g.destroy();\n }\n this.setActiveGroup(null);\n },\n\n /**\n * Discards currently active group and fire events If the function is called by fabric\n * as a consequence of a mouse event, the event is passed as a parmater 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 * @return {fabric.Canvas} thisArg\n * @chainable\n */\n discardActiveGroup: function (e) {\n var g = this.getActiveGroup();\n if (g) {\n this.fire('before:selection:cleared', { e: e, target: g });\n this._discardActiveGroup();\n this.fire('selection:cleared', { e: e });\n }\n return this;\n },\n\n /**\n * Deactivates all objects on canvas, removing any active group or object\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n deactivateAll: function () {\n var allObjects = this.getObjects(),\n i = 0,\n len = allObjects.length,\n obj;\n for ( ; i < len; i++) {\n obj = allObjects[i];\n obj && obj.set('active', false);\n }\n this._discardActiveGroup();\n this._discardActiveObject();\n return this;\n },\n\n /**\n * Deactivates all objects and dispatches appropriate events If the function is called by fabric\n * as a consequence of a mouse event, the event is passed as a parmater 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 * @return {fabric.Canvas} thisArg\n * @chainable\n */\n deactivateAllWithDispatch: function (e) {\n var allObjects = this.getObjects(),\n i = 0,\n len = allObjects.length,\n obj;\n for ( ; i < len; i++) {\n obj = allObjects[i];\n obj && obj.set('active', false);\n }\n this.discardActiveGroup(e);\n this.discardActiveObject(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 fabric.StaticCanvas.prototype.dispose.call(this);\n var wrapper = this.wrapperEl;\n this.removeListeners();\n wrapper.removeChild(this.upperCanvasEl);\n wrapper.removeChild(this.lowerCanvasEl);\n delete this.upperCanvasEl;\n if (wrapper.parentNode) {\n wrapper.parentNode.replaceChild(this.lowerCanvasEl, this.wrapperEl);\n }\n delete this.wrapperEl;\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 activeGroup = this.getActiveGroup();\n\n if (activeGroup) {\n activeGroup._renderControls(ctx);\n }\n else {\n this._drawObjectsControls(ctx);\n }\n },\n\n /**\n * @private\n */\n _drawObjectsControls: function(ctx) {\n for (var i = 0, len = this._objects.length; i < len; ++i) {\n if (!this._objects[i] || !this._objects[i].active) {\n continue;\n }\n this._objects[i]._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 === this.getActiveGroup()) {\n //Copy all the positionally relevant properties across now\n var originalValues = {},\n layoutProps = ['angle', 'flipX', 'flipY', 'left', 'scaleX', 'scaleY', 'skewX', 'skewY', 'top'];\n layoutProps.forEach(function(prop) {\n originalValues[prop] = instance[prop];\n });\n this.getActiveGroup().realizeTransform(instance);\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 var originalProperties;\n //If the object is in a selection group, simulate what would happen to that\n //object when the group is deselected\n originalProperties = this._realizeGroupTransformOnObject(instance);\n this.callSuper('_setSVGObject', markup, instance, reviver);\n this._unwindGroupTransformOnObject(instance, originalProperties);\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 if (fabric.isTouchSupported) {\n /** @ignore */\n fabric.Canvas.prototype._setCursorFromEvent = function() { };\n }\n\n /**\n * @ignore\n * @class fabric.Element\n * @alias fabric.Canvas\n * @deprecated Use {@link fabric.Canvas} instead.\n * @constructor\n */\n fabric.Element = fabric.Canvas;\n})();\n\n\n(function() {\n\n var cursorOffset = {\n mt: 0, // n\n tr: 1, // ne\n mr: 2, // e\n br: 3, // se\n mb: 4, // s\n bl: 5, // sw\n ml: 6, // w\n tl: 7 // nw\n },\n addListener = fabric.util.addListener,\n removeListener = fabric.util.removeListener,\n RIGHT_CLICK = 3, MIDDLE_CLICK = 2, LEFT_CLICK = 1;\n\n function checkClick(e, value) {\n return 'which' in e ? e.which === value : e.button === value - 1;\n }\n\n fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ {\n\n /**\n * Map of cursor style values for each of the object controls\n * @private\n */\n cursorMap: [\n 'n-resize',\n 'ne-resize',\n 'e-resize',\n 'se-resize',\n 's-resize',\n 'sw-resize',\n 'w-resize',\n 'nw-resize'\n ],\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\n addListener(fabric.window, 'resize', this._onResize);\n\n // mouse events\n addListener(this.upperCanvasEl, 'mousedown', this._onMouseDown);\n addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);\n addListener(this.upperCanvasEl, 'mouseout', this._onMouseOut);\n addListener(this.upperCanvasEl, 'mouseenter', this._onMouseEnter);\n addListener(this.upperCanvasEl, 'wheel', this._onMouseWheel);\n addListener(this.upperCanvasEl, 'contextmenu', this._onContextMenu);\n\n // touch events\n addListener(this.upperCanvasEl, 'touchstart', this._onMouseDown, { passive: false });\n addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove, { passive: false });\n\n if (typeof eventjs !== 'undefined' && 'add' in eventjs) {\n eventjs.add(this.upperCanvasEl, 'gesture', this._onGesture);\n eventjs.add(this.upperCanvasEl, 'drag', this._onDrag);\n eventjs.add(this.upperCanvasEl, 'orientation', this._onOrientationChange);\n eventjs.add(this.upperCanvasEl, 'shake', this._onShake);\n eventjs.add(this.upperCanvasEl, 'longpress', this._onLongPress);\n }\n },\n\n /**\n * @private\n */\n _bindEvents: function() {\n if (this.eventsBinded) {\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._onMouseMove = this._onMouseMove.bind(this);\n this._onMouseUp = this._onMouseUp.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.eventsBinded = true;\n },\n\n /**\n * Removes all event listeners\n */\n removeListeners: function() {\n removeListener(fabric.window, 'resize', this._onResize);\n\n removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown);\n removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);\n removeListener(this.upperCanvasEl, 'mouseout', this._onMouseOut);\n removeListener(this.upperCanvasEl, 'mouseenter', this._onMouseEnter);\n removeListener(this.upperCanvasEl, 'wheel', this._onMouseWheel);\n removeListener(this.upperCanvasEl, 'contextmenu', this._onContextMenu);\n\n removeListener(this.upperCanvasEl, 'touchstart', this._onMouseDown);\n removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);\n\n if (typeof eventjs !== 'undefined' && 'remove' in eventjs) {\n eventjs.remove(this.upperCanvasEl, 'gesture', this._onGesture);\n eventjs.remove(this.upperCanvasEl, 'drag', this._onDrag);\n eventjs.remove(this.upperCanvasEl, 'orientation', this._onOrientationChange);\n eventjs.remove(this.upperCanvasEl, 'shake', this._onShake);\n eventjs.remove(this.upperCanvasEl, 'longpress', this._onLongPress);\n }\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 if (this._iTextInstances) {\n this._iTextInstances.forEach(function(obj) {\n if (obj.isEditing) {\n obj.hiddenTextarea.focus();\n }\n });\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mouseenter\n */\n _onMouseEnter: function(e) {\n if (!this.findTarget(e)) {\n this.fire('mouse:over', { target: null, e: e });\n this._hoveredTarget = null;\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 * @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 _onMouseDown: function (e) {\n this.__onMouseDown(e);\n\n addListener(fabric.document, 'touchend', this._onMouseUp, { passive: false });\n addListener(fabric.document, 'touchmove', this._onMouseMove, { passive: false });\n\n removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);\n removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);\n\n if (e.type === 'touchstart') {\n // Unbind mousedown to prevent double triggers from touch devices\n removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown);\n }\n else {\n addListener(fabric.document, 'mouseup', this._onMouseUp);\n addListener(fabric.document, 'mousemove', this._onMouseMove);\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mouseup\n */\n _onMouseUp: function (e) {\n this.__onMouseUp(e);\n\n removeListener(fabric.document, 'mouseup', this._onMouseUp);\n removeListener(fabric.document, 'touchend', this._onMouseUp);\n\n removeListener(fabric.document, 'mousemove', this._onMouseMove);\n removeListener(fabric.document, 'touchmove', this._onMouseMove);\n\n addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);\n addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove, { passive: false });\n\n if (e.type === 'touchend') {\n // Wait 400ms before rebinding mousedown to prevent double triggers\n // from touch devices\n var _this = this;\n setTimeout(function() {\n addListener(_this.upperCanvasEl, 'mousedown', _this._onMouseDown);\n }, 400);\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 * @param {Object} pointer\n */\n _shouldRender: function(target, pointer) {\n var activeObject = this.getActiveGroup() || this.getActiveObject();\n\n if (activeObject && activeObject.isEditing && target === activeObject) {\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 !!(\n (target && (\n target.isMoving ||\n target !== activeObject))\n ||\n (!target && !!activeObject)\n ||\n (!target && !activeObject && !this._groupSelector)\n ||\n (pointer &&\n this._previousPointer &&\n this.selection && (\n pointer.x !== this._previousPointer.x ||\n pointer.y !== this._previousPointer.y))\n );\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\n var target;\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', target, RIGHT_CLICK);\n }\n return;\n }\n\n if (checkClick(e, MIDDLE_CLICK)) {\n if (this.fireMiddleClick) {\n this._handleEvent(e, 'up', target, MIDDLE_CLICK);\n }\n return;\n }\n\n if (this.isDrawingMode && this._isCurrentlyDrawing) {\n this._onMouseUpInDrawingMode(e);\n return;\n }\n\n var searchTarget = true, transform = this._currentTransform,\n groupSelector = this._groupSelector,\n isClick = (!groupSelector || (groupSelector.left === 0 && groupSelector.top === 0));\n\n if (transform) {\n this._finalizeCurrentTransform(e);\n searchTarget = !transform.actionPerformed;\n }\n\n target = searchTarget ? this.findTarget(e, true) : transform.target;\n\n var shouldRender = this._shouldRender(target, this.getPointer(e));\n\n if (target || !isClick) {\n this._maybeGroupObjects(e);\n }\n else {\n // those are done by default on mouse up\n // by _maybeGroupObjects, we are skipping it in case of no target find\n this._groupSelector = null;\n this._currentTransform = null;\n }\n\n if (target) {\n target.isMoving = false;\n }\n this._setCursorFromEvent(e, target);\n this._handleEvent(e, 'up', target ? target : null, LEFT_CLICK, isClick);\n target && (target.__corner = 0);\n shouldRender && this.renderAll();\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, targetObj, button, isClick) {\n var target = typeof targetObj === 'undefined' ? this.findTarget(e) : targetObj,\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 };\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\n if (target._scaling) {\n target._scaling = false;\n }\n\n target.setCoords();\n this._restoreOriginXY(target);\n\n if (transform.actionPerformed || (this.stateful && target.hasStateChanged())) {\n this.fire('object:modified', { target: target, e: e });\n target.fire('modified', { e: e });\n }\n },\n\n /**\n * @private\n * @param {Object} target Object to restore\n */\n _restoreOriginXY: function(target) {\n if (this._previousOriginX && this._previousOriginY) {\n\n var originPoint = target.translateToOriginPoint(\n target.getCenterPoint(),\n this._previousOriginX,\n this._previousOriginY);\n\n target.originX = this._previousOriginX;\n target.originY = this._previousOriginY;\n\n target.left = originPoint.x;\n target.top = originPoint.y;\n\n this._previousOriginX = null;\n this._previousOriginY = null;\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 this.discardActiveObject(e).renderAll();\n if (this.clipTo) {\n fabric.util.clipContext(this, this.contextTop);\n }\n var pointer = this.getPointer(e);\n this.freeDrawingBrush.onMouseDown(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);\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 this._isCurrentlyDrawing = false;\n if (this.clipTo) {\n this.contextTop.restore();\n }\n this.freeDrawingBrush.onMouseUp();\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\n var target = this.findTarget(e);\n\n // if right click just fire events\n if (checkClick(e, RIGHT_CLICK)) {\n if (this.fireRightClick) {\n this._handleEvent(e, 'down', target ? target : null, RIGHT_CLICK);\n }\n return;\n }\n\n if (checkClick(e, MIDDLE_CLICK)) {\n if (this.fireMiddleClick) {\n this._handleEvent(e, 'down', target ? target : null, MIDDLE_CLICK);\n }\n return;\n }\n\n if (this.isDrawingMode) {\n this._onMouseDownInDrawingMode(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 // save pointer for check in __onMouseUp event\n var pointer = this.getPointer(e, true);\n this._previousPointer = pointer;\n\n var shouldRender = this._shouldRender(target, pointer),\n shouldGroup = this._shouldGroup(e, target);\n\n if (this._shouldClearSelection(e, target)) {\n this.deactivateAllWithDispatch(e);\n }\n else if (shouldGroup) {\n this._handleGrouping(e, target);\n target = this.getActiveGroup();\n }\n\n if (this.selection && (!target || (!target.selectable && !target.isEditing))) {\n this._groupSelector = {\n ex: pointer.x,\n ey: pointer.y,\n top: 0,\n left: 0\n };\n }\n\n if (target) {\n if (target.selectable && (target.__corner || !shouldGroup)) {\n this._beforeTransform(e, target);\n this._setupCurrentTransform(e, target);\n }\n var activeObject = this.getActiveObject();\n if (target !== this.getActiveGroup() && target !== activeObject) {\n this.deactivateAll();\n if (target.selectable) {\n activeObject && activeObject.fire('deselected', { e: e });\n this.setActiveObject(target, e);\n }\n }\n }\n this._handleEvent(e, 'down', target ? target : null);\n // we must renderAll so that we update the visuals\n shouldRender && this.renderAll();\n },\n\n /**\n * @private\n */\n _beforeTransform: function(e, target) {\n this.stateful && target.saveState();\n\n // determine if it's a drag or rotate case\n if (target._findTargetCorner(this.getPointer(e))) {\n this.onBeforeScaleRotate(target);\n }\n\n },\n\n /**\n * @private\n * @param {Object} target Object for that origin is set to center\n */\n _setOriginToCenter: function(target) {\n this._previousOriginX = this._currentTransform.target.originX;\n this._previousOriginY = this._currentTransform.target.originY;\n\n var center = target.getCenterPoint();\n\n target.originX = 'center';\n target.originY = 'center';\n\n target.left = center.x;\n target.top = center.y;\n\n this._currentTransform.left = target.left;\n this._currentTransform.top = target.top;\n },\n\n /**\n * @private\n * @param {Object} target Object for that center is set to origin\n */\n _setCenterToOrigin: function(target) {\n var originPoint = target.translateToOriginPoint(\n target.getCenterPoint(),\n this._previousOriginX,\n this._previousOriginY);\n\n target.originX = this._previousOriginX;\n target.originY = this._previousOriginY;\n\n target.left = originPoint.x;\n target.top = originPoint.y;\n\n this._previousOriginX = null;\n this._previousOriginY = null;\n },\n\n /**\n * Method that defines the actions when mouse is hovering the canvas.\n * The currentTransform parameter will definde 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\n var target, pointer;\n\n if (this.isDrawingMode) {\n this._onMouseMoveInDrawingMode(e);\n return;\n }\n if (typeof e.touches !== 'undefined' && e.touches.length > 1) {\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.getPointer(e, true);\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);\n this._setCursorFromEvent(e, target);\n }\n else {\n this._transformObject(e);\n }\n this._handleEvent(e, 'move', target ? target : null);\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._handleEvent(e, 'wheel');\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.target.isMoving = true;\n transform.shiftKey = e.shiftKey;\n transform.altKey = e[this.centeredKey];\n\n this._beforeScaleTransform(e, transform);\n this._performTransformAction(e, transform, pointer);\n\n transform.actionPerformed && this.renderAll();\n },\n\n /**\n * @private\n */\n _performTransformAction: function(e, transform, pointer) {\n var x = pointer.x,\n y = pointer.y,\n target = transform.target,\n action = transform.action,\n actionPerformed = false;\n\n if (action === 'rotate') {\n (actionPerformed = this._rotateObject(x, y)) && this._fire('rotating', target, e);\n }\n else if (action === 'scale') {\n (actionPerformed = this._onScale(e, transform, x, y)) && this._fire('scaling', target, e);\n }\n else if (action === 'scaleX') {\n (actionPerformed = this._scaleObject(x, y, 'x')) && this._fire('scaling', target, e);\n }\n else if (action === 'scaleY') {\n (actionPerformed = this._scaleObject(x, y, 'y')) && this._fire('scaling', target, e);\n }\n else if (action === 'skewX') {\n (actionPerformed = this._skewObject(x, y, 'x')) && this._fire('skewing', target, e);\n }\n else if (action === 'skewY') {\n (actionPerformed = this._skewObject(x, y, 'y')) && this._fire('skewing', target, e);\n }\n else {\n actionPerformed = this._translateObject(x, y);\n if (actionPerformed) {\n this._fire('moving', target, e);\n this.setCursor(target.moveCursor || this.moveCursor);\n }\n }\n transform.actionPerformed = transform.actionPerformed || actionPerformed;\n },\n\n /**\n * @private\n */\n _fire: function(eventName, target, e) {\n this.fire('object:' + eventName, { target: target, e: e });\n target.fire(eventName, { e: e });\n },\n\n /**\n * @private\n */\n _beforeScaleTransform: function(e, transform) {\n if (transform.action === 'scale' || transform.action === 'scaleX' || transform.action === 'scaleY') {\n var centerTransform = this._shouldCenterTransform(transform.target);\n\n // Switch from a normal resize to center-based\n if ((centerTransform && (transform.originX !== 'center' || transform.originY !== 'center')) ||\n // Switch from center-based resize to normal one\n (!centerTransform && transform.originX === 'center' && transform.originY === 'center')\n ) {\n this._resetCurrentTransform();\n transform.reset = true;\n }\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {Object} transform current tranform\n * @param {Number} x mouse position x from origin\n * @param {Number} y mouse poistion y from origin\n * @return {Boolean} true if the scaling occurred\n */\n _onScale: function(e, transform, x, y) {\n if ((e[this.uniScaleKey] || this.uniScaleTransform) && !transform.target.get('lockUniScaling')) {\n transform.currentAction = 'scale';\n return this._scaleObject(x, y);\n }\n else {\n // Switch from a normal resize to proportional\n if (!transform.reset && transform.currentAction === 'scale') {\n this._resetCurrentTransform();\n }\n\n transform.currentAction = 'scaleEqually';\n return this._scaleObject(x, y, 'equally');\n }\n },\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\n var hoverCursor = target.hoverCursor || this.hoverCursor,\n activeGroup = this.getActiveGroup(),\n // only show proper corner when group selection is not active\n corner = target._findTargetCorner\n && (!activeGroup || !activeGroup.contains(target))\n && target._findTargetCorner(this.getPointer(e, true));\n\n if (!corner) {\n this.setCursor(hoverCursor);\n }\n else {\n this._setCornerCursor(corner, target, e);\n }\n //actually unclear why it should return something\n //is never evaluated\n return true;\n },\n\n /**\n * @private\n */\n _setCornerCursor: function(corner, target, e) {\n if (corner in cursorOffset) {\n this.setCursor(this._getRotatedCornerCursor(corner, target, e));\n }\n else if (corner === 'mtr' && target.hasRotatingPoint) {\n this.setCursor(this.rotationCursor);\n }\n else {\n this.setCursor(this.defaultCursor);\n return false;\n }\n },\n\n /**\n * @private\n */\n _getRotatedCornerCursor: function(corner, target, e) {\n var n = Math.round((target.getAngle() % 360) / 45);\n\n if (n < 0) {\n n += 8; // full circle ahead\n }\n n += cursorOffset[corner];\n if (e[this.altActionKey] && cursorOffset[corner] % 2 === 0) {\n //if we are holding shift and we are on a mx corner...\n n += 2;\n }\n // normalize n to be from 0 to 7\n n %= 8;\n\n return this.cursorMap[n];\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.getActiveObject();\n return e[this.selectionKey] && target && target.selectable &&\n (this.getActiveGroup() || (activeObject && activeObject !== target))\n && this.selection;\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n */\n _handleGrouping: function (e, target) {\n var activeGroup = this.getActiveGroup();\n\n if (target === activeGroup) {\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, bail out\n if (!target) {\n return;\n }\n }\n if (activeGroup) {\n this._updateActiveGroup(target, e);\n }\n else {\n this._createActiveGroup(target, e);\n }\n\n if (this._activeGroup) {\n this._activeGroup.saveCoords();\n }\n },\n\n /**\n * @private\n */\n _updateActiveGroup: function(target, e) {\n var activeGroup = this.getActiveGroup();\n\n if (activeGroup.contains(target)) {\n\n activeGroup.removeWithUpdate(target);\n target.set('active', false);\n\n if (activeGroup.size() === 1) {\n // remove group alltogether if after removal it only contains 1 object\n this.discardActiveGroup(e);\n // activate last remaining object\n this.setActiveObject(activeGroup.item(0), e);\n return;\n }\n }\n else {\n activeGroup.addWithUpdate(target);\n }\n this.fire('selection:created', { target: activeGroup, e: e });\n activeGroup.set('active', true);\n },\n\n /**\n * @private\n */\n _createActiveGroup: function(target, e) {\n\n if (this._activeObject && target !== this._activeObject) {\n\n var group = this._createGroup(target);\n group.addWithUpdate();\n\n this.setActiveGroup(group, e);\n this._activeObject = null;\n\n this.fire('selection:created', { target: group, e: e });\n }\n\n target.set('active', true);\n },\n\n /**\n * @private\n * @param {Object} target\n */\n _createGroup: function(target) {\n\n var objects = this.getObjects(),\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.Group(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();\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 group = new fabric.Group(group.reverse(), {\n canvas: this\n });\n group.addWithUpdate();\n this.setActiveGroup(group, e);\n group.saveCoords();\n this.fire('selection:created', { target: group, e: e });\n this.renderAll();\n }\n },\n\n /**\n * @private\n */\n _collectObjects: function() {\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 isClick = x1 === x2 && y1 === y2;\n\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 (currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2) ||\n currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) ||\n currentObject.containsPoint(selectionX1Y1) ||\n currentObject.containsPoint(selectionX2Y2)\n ) {\n currentObject.set('active', true);\n group.push(currentObject);\n\n // only add one object if it's a click\n if (isClick) {\n break;\n }\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\n var activeGroup = this.getActiveGroup();\n if (activeGroup) {\n activeGroup.setObjectsCoords().setCoords();\n activeGroup.isMoving = false;\n this.setCursor(this.defaultCursor);\n }\n\n // clear selection and current transformation\n this._groupSelector = null;\n this._currentTransform = null;\n }\n });\n\n})();\n\n\n(function () {\n\n var supportQuality = fabric.StaticCanvas.supports('toDataURLWithQuality');\n\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\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 * @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,\n cropping = {\n left: options.left || 0,\n top: options.top || 0,\n width: options.width || 0,\n height: options.height || 0,\n };\n return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier);\n },\n\n /**\n * @private\n */\n __toDataURLWithMultiplier: function(format, quality, cropping, multiplier) {\n\n var origWidth = this.getWidth(),\n origHeight = this.getHeight(),\n scaledWidth = (cropping.width || this.getWidth()) * multiplier,\n scaledHeight = (cropping.height || this.getHeight()) * multiplier,\n zoom = this.getZoom(),\n newZoom = zoom * multiplier,\n vp = this.viewportTransform,\n translateX = (vp[4] - cropping.left) * multiplier,\n translateY = (vp[5] - cropping.top) * multiplier,\n newVp = [newZoom, 0, 0, newZoom, translateX, translateY],\n originalInteractive = this.interactive;\n\n this.viewportTransform = newVp;\n // setting interactive to false avoid exporting controls\n this.interactive && (this.interactive = false);\n if (origWidth !== scaledWidth || origHeight !== scaledHeight) {\n // this.setDimensions is going to renderAll also;\n this.setDimensions({ width: scaledWidth, height: scaledHeight }, { backstoreOnly: true });\n }\n else {\n this.renderAll();\n }\n var data = this.__toDataURL(format, quality, cropping);\n originalInteractive && (this.interactive = originalInteractive);\n this.viewportTransform = vp;\n //setDimensions with no option object is taking care of:\n //this.width, this.height, this.renderAll()\n this.setDimensions({ width: origWidth, height: origHeight }, { backstoreOnly: true });\n return data;\n },\n\n /**\n * @private\n */\n __toDataURL: function(format, quality) {\n\n var canvasEl = this.contextContainer.canvas;\n // to avoid common confusion https://github.com/kangax/fabric.js/issues/806\n if (format === 'jpg') {\n format = 'jpeg';\n }\n\n var data = supportQuality\n ? canvasEl.toDataURL('image/' + format, quality)\n : canvasEl.toDataURL('image/' + format);\n\n return data;\n },\n\n /**\n * Exports canvas element to a dataurl image (allowing to change image size via multiplier).\n * @deprecated since 1.0.13\n * @param {String} format (png|jpeg)\n * @param {Number} multiplier\n * @param {Number} quality (0..1)\n * @return {String}\n */\n toDataURLWithMultiplier: function (format, multiplier, quality) {\n return this.toDataURL({\n format: format,\n multiplier: multiplier,\n quality: quality\n });\n },\n });\n\n})();\n\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n /**\n * Populates canvas with data from the specified dataless JSON.\n * JSON format must conform to the one of {@link fabric.Canvas#toDatalessJSON}\n * @deprecated since 1.2.2\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 */\n loadFromDatalessJSON: function (json, callback, reviver) {\n return this.loadFromJSON(json, callback, reviver);\n },\n\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 renderOnAddRemove = this.renderOnAddRemove;\n this.renderOnAddRemove = false;\n\n this._enlivenObjects(serialized.objects, function (enlivenedObjects) {\n _this.clear();\n _this._setBgOverlay(serialized, function () {\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 }, reviver);\n return this;\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.document.createElement('canvas');\n\n el.width = this.getWidth();\n el.height = this.getHeight();\n\n var clone = new fabric.Canvas(el);\n clone.clipTo = this.clipTo;\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 supportsLineDash = fabric.StaticCanvas.supports('setLineDash'),\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 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 */\n fabric.Object = fabric.util.createClass(fabric.CommonMethods, /** @lends fabric.Object.prototype */ {\n\n /**\n * Retrieves object's {@link fabric.Object#clipTo|clipping function}\n * @method getClipTo\n * @memberOf fabric.Object.prototype\n * @return {Function}\n */\n\n /**\n * Sets object's {@link fabric.Object#clipTo|clipping function}\n * @method setClipTo\n * @memberOf fabric.Object.prototype\n * @param {Function} clipTo Clipping function\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#transformMatrix|transformMatrix}\n * @method getTransformMatrix\n * @memberOf fabric.Object.prototype\n * @return {Array} transformMatrix\n */\n\n /**\n * Sets object's {@link fabric.Object#transformMatrix|transformMatrix}\n * @method setTransformMatrix\n * @memberOf fabric.Object.prototype\n * @param {Array} transformMatrix\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#visible|visible} state\n * @method getVisible\n * @memberOf fabric.Object.prototype\n * @return {Boolean} True if visible\n */\n\n /**\n * Sets object's {@link fabric.Object#visible|visible} state\n * @method setVisible\n * @memberOf fabric.Object.prototype\n * @param {Boolean} value visible value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#shadow|shadow}\n * @method getShadow\n * @memberOf fabric.Object.prototype\n * @return {Object} Shadow instance\n */\n\n /**\n * Retrieves object's {@link fabric.Object#stroke|stroke}\n * @method getStroke\n * @memberOf fabric.Object.prototype\n * @return {String} stroke value\n */\n\n /**\n * Sets object's {@link fabric.Object#stroke|stroke}\n * @method setStroke\n * @memberOf fabric.Object.prototype\n * @param {String} value stroke value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#strokeWidth|strokeWidth}\n * @method getStrokeWidth\n * @memberOf fabric.Object.prototype\n * @return {Number} strokeWidth value\n */\n\n /**\n * Sets object's {@link fabric.Object#strokeWidth|strokeWidth}\n * @method setStrokeWidth\n * @memberOf fabric.Object.prototype\n * @param {Number} value strokeWidth value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#originX|originX}\n * @method getOriginX\n * @memberOf fabric.Object.prototype\n * @return {String} originX value\n */\n\n /**\n * Sets object's {@link fabric.Object#originX|originX}\n * @method setOriginX\n * @memberOf fabric.Object.prototype\n * @param {String} value originX value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#originY|originY}\n * @method getOriginY\n * @memberOf fabric.Object.prototype\n * @return {String} originY value\n */\n\n /**\n * Sets object's {@link fabric.Object#originY|originY}\n * @method setOriginY\n * @memberOf fabric.Object.prototype\n * @param {String} value originY value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#fill|fill}\n * @method getFill\n * @memberOf fabric.Object.prototype\n * @return {String} Fill value\n */\n\n /**\n * Sets object's {@link fabric.Object#fill|fill}\n * @method setFill\n * @memberOf fabric.Object.prototype\n * @param {String} value Fill value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#opacity|opacity}\n * @method getOpacity\n * @memberOf fabric.Object.prototype\n * @return {Number} Opacity value (0-1)\n */\n\n /**\n * Sets object's {@link fabric.Object#opacity|opacity}\n * @method setOpacity\n * @memberOf fabric.Object.prototype\n * @param {Number} value Opacity value (0-1)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#angle|angle} (in degrees)\n * @method getAngle\n * @memberOf fabric.Object.prototype\n * @return {Number}\n */\n\n /**\n * Retrieves object's {@link fabric.Object#top|top position}\n * @method getTop\n * @memberOf fabric.Object.prototype\n * @return {Number} Top value (in pixels)\n */\n\n /**\n * Sets object's {@link fabric.Object#top|top position}\n * @method setTop\n * @memberOf fabric.Object.prototype\n * @param {Number} value Top value (in pixels)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#left|left position}\n * @method getLeft\n * @memberOf fabric.Object.prototype\n * @return {Number} Left value (in pixels)\n */\n\n /**\n * Sets object's {@link fabric.Object#left|left position}\n * @method setLeft\n * @memberOf fabric.Object.prototype\n * @param {Number} value Left value (in pixels)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#scaleX|scaleX} value\n * @method getScaleX\n * @memberOf fabric.Object.prototype\n * @return {Number} scaleX value\n */\n\n /**\n * Sets object's {@link fabric.Object#scaleX|scaleX} value\n * @method setScaleX\n * @memberOf fabric.Object.prototype\n * @param {Number} value scaleX value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#scaleY|scaleY} value\n * @method getScaleY\n * @memberOf fabric.Object.prototype\n * @return {Number} scaleY value\n */\n\n /**\n * Sets object's {@link fabric.Object#scaleY|scaleY} value\n * @method setScaleY\n * @memberOf fabric.Object.prototype\n * @param {Number} value scaleY value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#flipX|flipX} value\n * @method getFlipX\n * @memberOf fabric.Object.prototype\n * @return {Boolean} flipX value\n */\n\n /**\n * Sets object's {@link fabric.Object#flipX|flipX} value\n * @method setFlipX\n * @memberOf fabric.Object.prototype\n * @param {Boolean} value flipX value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#flipY|flipY} value\n * @method getFlipY\n * @memberOf fabric.Object.prototype\n * @return {Boolean} flipY value\n */\n\n /**\n * Sets object's {@link fabric.Object#flipY|flipY} value\n * @method setFlipY\n * @memberOf fabric.Object.prototype\n * @param {Boolean} value flipY value\n * @return {fabric.Object} thisArg\n * @chainable\n */\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/40/ 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/40/ 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 * 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: 'rgba(102,153,255,0.75)',\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: 'rgba(102,153,255,0.5)',\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 * @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 * @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 * @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 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 \"bevil\", \"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: 10,\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 * @type Number\n * @default\n */\n borderScaleFactor: 1,\n\n /**\n * Transform matrix (similar to SVG's transform matrix)\n * @type Array\n */\n transformMatrix: null,\n\n /**\n * Minimum allowed scale value of an object\n * @type Number\n * @default\n */\n minScaleLimit: 0.01,\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 `false`, object's controlling rotating point will not be visible or selectable\n * @type Boolean\n * @default\n */\n hasRotatingPoint: true,\n\n /**\n * Offset for object's controlling rotating point (when enabled via `hasRotatingPoint`)\n * @type Number\n * @default\n */\n rotatingPointOffset: 40,\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 * Function that determines clipping of an object (context is passed as a first argument)\n * Note that context origin is at the object's center point (not left/top corner)\n * @type Function\n */\n clipTo: null,\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 non-uniform scaling is locked\n * @type Boolean\n * @default\n */\n lockUniScaling: 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 SVG or 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 * 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 pathgroups, 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 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 * 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 strokeLineJoin strokeMiterLimit ' +\n 'angle opacity fill globalCompositeOperation shadow clipTo visible backgroundColor ' +\n 'skewX skewY fillRule'\n ).split(' '),\n\n /**\n * List of properties to consider when checking if cache needs refresh\n * @type Array\n */\n cacheProperties: (\n 'fill stroke strokeWidth strokeDashArray width height' +\n ' strokeLineCap strokeLineJoin strokeMiterLimit backgroundColor'\n ).split(' '),\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n initialize: function(options) {\n options = 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.document.createElement('canvas');\n this._cacheContext = this._cacheCanvas.getContext('2d');\n this._updateCacheCanvas();\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 * @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 zoom = this.canvas && this.canvas.getZoom() || 1,\n objectScale = this.getObjectScaling(),\n retina = this.canvas && this.canvas._isRetinaScaling() ? fabric.devicePixelRatio : 1,\n dim = this._getNonTransformedDimensions(),\n zoomX = objectScale.scaleX * zoom * retina,\n zoomY = objectScale.scaleY * zoom * retina,\n width = dim.x * zoomX,\n height = dim.y * zoomY;\n return {\n width: width + ALIASING_LIMIT,\n height: height + ALIASING_LIMIT,\n zoomX: zoomX,\n zoomY: zoomY,\n x: dim.x,\n y: dim.y\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 if (this.noScaleCache && this.canvas && this.canvas._currentTransform) {\n var target = this.canvas._currentTransform.target,\n action = this.canvas._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 (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 * zoomX / 2;\n drawingHeight = dims.y * zoomY / 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._initClipping(options);\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 * @param {Boolean} fromLeft When true, context is transformed to object's top/left corner. This is used when rendering text on Node\n */\n transform: function(ctx, fromLeft) {\n if (this.group && !this.group._transformDone && this.group === this.canvas._activeGroup) {\n this.group.transform(ctx);\n }\n var center = fromLeft ? this._getLeftTopCoords() : this.getCenterPoint();\n ctx.translate(center.x, center.y);\n this.angle && ctx.rotate(degreesToRadians(this.angle));\n ctx.scale(\n this.scaleX * (this.flipX ? -1 : 1),\n this.scaleY * (this.flipY ? -1 : 1)\n );\n this.skewX && ctx.transform(1, 0, Math.tan(degreesToRadians(this.skewX)), 1, 0, 0);\n this.skewY && ctx.transform(1, Math.tan(degreesToRadians(this.skewY)), 0, 1, 0, 0);\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 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 strokeLineJoin: this.strokeLineJoin,\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.getAngle(), 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 clipTo: this.clipTo && String(this.clipTo),\n backgroundColor: this.backgroundColor,\n fillRule: this.fillRule,\n globalCompositeOperation: this.globalCompositeOperation,\n transformMatrix: this.transformMatrix ? this.transformMatrix.concat() : null,\n skewX: toFixed(this.skewX, NUM_FRACTION_DIGITS),\n skewY: toFixed(this.skewY, NUM_FRACTION_DIGITS)\n };\n\n fabric.util.populateWithProperties(this, object, propertiesToInclude);\n\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 (object[prop] === prototype[prop]) {\n delete object[prop];\n }\n var isArray = Object.prototype.toString.call(object[prop]) === '[object Array]' &&\n Object.prototype.toString.call(prototype[prop]) === '[object Array]';\n\n // basically a check for [] === []\n if (isArray && 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 var scaleX = this.scaleX, scaleY = this.scaleY;\n if (this.group) {\n var scaling = this.group.getObjectScaling();\n scaleX *= scaling.scaleX;\n scaleY *= scaling.scaleY;\n }\n return { scaleX: scaleX, scaleY: scaleY };\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;\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 && this.cacheProperties.indexOf(key) > -1) {\n if (this.group) {\n this.group.set('dirty', true);\n }\n this.dirty = true;\n }\n\n if (isChanged && this.group && this.stateProperties.indexOf(key) > -1) {\n this.group.set('dirty', true);\n }\n\n if (key === 'width' || key === 'height') {\n this.minScaleLimit = Math.min(0.1, 1 / Math.max(this.width, this.height));\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 * Sets sourcePath of an object\n * @param {String} value Value to set sourcePath to\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setSourcePath: function(value) {\n this.sourcePath = value;\n return this;\n },\n\n /**\n * Retrieves viewportTransform from Object's canvas if possible\n * @method getViewportTransform\n * @memberOf fabric.Object.prototype\n * @return {Boolean}\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 || (this.width === 0 && this.height === 0) || !this.visible;\n },\n\n /**\n * Renders an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n render: function(ctx, noTransform) {\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 //setup fill rule for current object\n this._setupCompositeOperation(ctx);\n this.drawSelectionBackground(ctx);\n if (!noTransform) {\n this.transform(ctx);\n }\n this._setOpacity(ctx);\n this._setShadow(ctx);\n if (this.transformMatrix) {\n ctx.transform.apply(ctx, this.transformMatrix);\n }\n this.clipTo && fabric.util.clipContext(this, ctx);\n if (this.shouldCache(noTransform)) {\n if (!this._cacheCanvas) {\n this._createCacheCanvas();\n }\n if (this.isCacheDirty(noTransform)) {\n this.statefullCache && this.saveState({ propertySet: 'cacheProperties' });\n this.drawObject(this._cacheContext, noTransform);\n this.dirty = false;\n }\n this.drawCacheOnCanvas(ctx);\n }\n else {\n this._removeCacheCanvas();\n this.dirty = false;\n this.drawObject(ctx, noTransform);\n if (noTransform && this.objectCaching && this.statefullCache) {\n this.saveState({ propertySet: 'cacheProperties' });\n }\n }\n this.clipTo && ctx.restore();\n ctx.restore();\n },\n\n /**\n * Remove cacheCanvas and its dimensions from the objects\n */\n _removeCacheCanvas: function() {\n this._cacheCanvas = null;\n this.cacheWidth = 0;\n this.cacheHeight = 0;\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 * This function is created to be subclassed by custom classes.\n * since 1.7.12\n * @type function\n * @return false\n */\n needsItsOwnCache: function() {\n return false;\n },\n\n /**\n * Decide if the object should cache or not.\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 * @param {Boolean} noTransform if rendereing in pathGroup, caching is not supported at object level\n * @return {Boolean}\n */\n shouldCache: function(noTransform) {\n return !noTransform && this.objectCaching &&\n (!this.group || this.needsItsOwnCache() || !this.group.isCaching());\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 on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n drawObject: function(ctx, noTransform) {\n this._renderBackground(ctx);\n this._setStrokeStyles(ctx);\n this._setFillStyles(ctx);\n this._render(ctx, noTransform);\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 && !skipCanvas && this._updateCacheCanvas()) {\n // in this case the context is already cleared.\n return true;\n }\n else {\n if (this.dirty || (this.statefullCache && this.hasStateChanged('cacheProperties'))) {\n if (this._cacheCanvas && !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 untrasformed 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 ctx.globalAlpha *= this.opacity;\n },\n\n _setStrokeStyles: function(ctx) {\n if (this.stroke) {\n ctx.lineWidth = this.strokeWidth;\n ctx.lineCap = this.strokeLineCap;\n ctx.lineJoin = this.strokeLineJoin;\n ctx.miterLimit = this.strokeMiterLimit;\n ctx.strokeStyle = this.stroke.toLive\n ? this.stroke.toLive(ctx, this)\n : this.stroke;\n }\n },\n\n _setFillStyles: function(ctx) {\n if (this.fill) {\n ctx.fillStyle = this.fill.toLive\n ? this.fill.toLive(ctx, this)\n : this.fill;\n }\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 * @param {Function} alternative function to call if browaser does not support lineDash\n */\n _setLineDash: function(ctx, dashArray, alternative) {\n if (!dashArray) {\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 if (supportsLineDash) {\n ctx.setLineDash(dashArray);\n }\n else {\n alternative && alternative(ctx);\n }\n },\n\n /**\n * Renders controls and borders for the object\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderControls: function(ctx) {\n if (!this.active || (this.group && this.group !== this.canvas.getActiveGroup())) {\n return;\n }\n\n var vpt = this.getViewportTransform(),\n matrix = this.calcTransformMatrix(),\n options;\n matrix = fabric.util.multiplyTransformMatrices(vpt, matrix);\n options = fabric.util.qrDecompose(matrix);\n\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.group && this.group === this.canvas.getActiveGroup()) {\n ctx.rotate(degreesToRadians(options.angle));\n this.drawBordersInGroup(ctx, options);\n }\n else {\n ctx.rotate(degreesToRadians(this.angle));\n this.drawBorders(ctx);\n }\n this.drawControls(ctx);\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 multX = (this.canvas && this.canvas.viewportTransform[0]) || 1,\n multY = (this.canvas && this.canvas.viewportTransform[3]) || 1,\n scaling = this.getObjectScaling();\n if (this.canvas && this.canvas._isRetinaScaling()) {\n multX *= fabric.devicePixelRatio;\n multY *= fabric.devicePixelRatio;\n }\n ctx.shadowColor = this.shadow.color;\n ctx.shadowBlur = this.shadow.blur * (multX + multY) * (scaling.scaleX + scaling.scaleY) / 4;\n ctx.shadowOffsetX = this.shadow.offsetX * multX * scaling.scaleX;\n ctx.shadowOffsetY = this.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 */\n _applyPatternGradientTransform: function(ctx, filler) {\n if (!filler.toLive) {\n return;\n }\n var transform = filler.gradientTransform || filler.patternTransform;\n if (transform) {\n ctx.transform.apply(ctx, transform);\n }\n var offsetX = -this.width / 2 + filler.offsetX || 0,\n offsetY = -this.height / 2 + filler.offsetY || 0;\n ctx.translate(offsetX, offsetY);\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._applyPatternGradientTransform(ctx, this.fill);\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 this._setLineDash(ctx, this.strokeDashArray, this._renderDashedStroke);\n this._applyPatternGradientTransform(ctx, this.stroke);\n ctx.stroke();\n ctx.restore();\n },\n\n /**\n * Clones an instance, some objects are async, so using callback method will work for every object.\n * Using the direct return does not work for images and groups.\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 * @return {fabric.Object} clone of an instance\n */\n clone: function(callback, propertiesToInclude) {\n if (this.constructor.fromObject) {\n return this.constructor.fromObject(this.toObject(propertiesToInclude), callback);\n }\n return new fabric.Object(this.toObject(propertiesToInclude));\n },\n\n /**\n * Creates an instance of fabric.Image out of an object\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 {Boolean} [options.enableRetinaScaling] enable retina scaling for the cloned image\n * @return {fabric.Object} thisArg\n */\n cloneAsImage: function(callback, options) {\n var dataUrl = this.toDataURL(options);\n fabric.util.loadImage(dataUrl, function(img) {\n if (callback) {\n callback(new fabric.Image(img));\n }\n });\n return this;\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.enableRetina] Enable retina scaling for clone image. Introduce in 1.6.4\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\n var el = fabric.util.createCanvasElement(),\n boundingRect = this.getBoundingRect();\n\n el.width = boundingRect.width;\n el.height = boundingRect.height;\n fabric.util.wrapElement(el, 'div');\n var canvas = new fabric.StaticCanvas(el, { enableRetinaScaling: options.enableRetinaScaling });\n // to avoid common confusion https://github.com/kangax/fabric.js/issues/806\n if (options.format === 'jpg') {\n options.format = 'jpeg';\n }\n\n if (options.format === 'jpeg') {\n canvas.backgroundColor = '#fff';\n }\n\n var origParams = {\n active: this.get('active'),\n left: this.getLeft(),\n top: this.getTop()\n };\n\n this.set('active', false);\n this.setPositionByOrigin(new fabric.Point(canvas.getWidth() / 2, canvas.getHeight() / 2), 'center', 'center');\n\n var originalCanvas = this.canvas;\n canvas.add(this);\n var data = canvas.toDataURL(options);\n\n this.set(origParams).setCoords();\n this.canvas = originalCanvas;\n\n canvas.dispose();\n canvas = null;\n\n return data;\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 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 gradient (fill or stroke) of an object\n * Backwards incompatibility note: This method was named \"setGradientFill\" until v1.1.0\n * @param {String} property Property name 'stroke' or 'fill'\n * @param {Object} [options] Options object\n * @param {String} [options.type] Type of gradient 'radial' or 'linear'\n * @param {Number} [options.x1=0] x-coordinate of start point\n * @param {Number} [options.y1=0] y-coordinate of start point\n * @param {Number} [options.x2=0] x-coordinate of end point\n * @param {Number} [options.y2=0] y-coordinate of end point\n * @param {Number} [options.r1=0] Radius of start point (only for radial gradients)\n * @param {Number} [options.r2=0] Radius of end point (only for radial gradients)\n * @param {Object} [options.colorStops] Color stops object eg. {0: 'ff0000', 1: '000000'}\n * @param {Object} [options.gradientTransform] transforMatrix for gradient\n * @return {fabric.Object} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/58y8b/|jsFiddle demo}\n * @example Set linear gradient\n * object.setGradient('fill', {\n * type: 'linear',\n * x1: -object.width / 2,\n * y1: 0,\n * x2: object.width / 2,\n * y2: 0,\n * colorStops: {\n * 0: 'red',\n * 0.5: '#005555',\n * 1: 'rgba(0,0,255,0.5)'\n * }\n * });\n * canvas.renderAll();\n * @example Set radial gradient\n * object.setGradient('fill', {\n * type: 'radial',\n * x1: 0,\n * y1: 0,\n * x2: 0,\n * y2: 0,\n * r1: object.width / 2,\n * r2: 10,\n * colorStops: {\n * 0: 'red',\n * 0.5: '#005555',\n * 1: 'rgba(0,0,255,0.5)'\n * }\n * });\n * canvas.renderAll();\n */\n setGradient: function(property, options) {\n options || (options = { });\n\n var gradient = { colorStops: [] };\n\n gradient.type = options.type || (options.r1 || options.r2 ? 'radial' : 'linear');\n gradient.coords = {\n x1: options.x1,\n y1: options.y1,\n x2: options.x2,\n y2: options.y2\n };\n\n if (options.r1 || options.r2) {\n gradient.coords.r1 = options.r1;\n gradient.coords.r2 = options.r2;\n }\n\n gradient.gradientTransform = options.gradientTransform;\n fabric.Gradient.prototype.addColorStop.call(gradient, options.colorStops);\n\n return this.set(property, fabric.Gradient.forObject(this, gradient));\n },\n\n /**\n * Sets pattern fill of an object\n * @param {Object} options Options object\n * @param {(String|HTMLImageElement)} options.source Pattern source\n * @param {String} [options.repeat=repeat] Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat)\n * @param {Number} [options.offsetX=0] Pattern horizontal offset from object's left/top corner\n * @param {Number} [options.offsetY=0] Pattern vertical offset from object's left/top corner\n * @return {fabric.Object} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/QT3pa/|jsFiddle demo}\n * @example Set pattern\n * fabric.util.loadImage('http://fabricjs.com/assets/escheresque_ste.png', function(img) {\n * object.setPatternFill({\n * source: img,\n * repeat: 'repeat'\n * });\n * canvas.renderAll();\n * });\n */\n setPatternFill: function(options) {\n return this.set('fill', new fabric.Pattern(options));\n },\n\n /**\n * Sets {@link fabric.Object#shadow|shadow} of an object\n * @param {Object|String} [options] Options object or string (e.g. \"2px 2px 10px rgba(0,0,0,0.2)\")\n * @param {String} [options.color=rgb(0,0,0)] Shadow color\n * @param {Number} [options.blur=0] Shadow blur\n * @param {Number} [options.offsetX=0] Shadow horizontal offset\n * @param {Number} [options.offsetY=0] Shadow vertical offset\n * @return {fabric.Object} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/7gvJG/|jsFiddle demo}\n * @example Set shadow with string notation\n * object.setShadow('2px 2px 10px rgba(0,0,0,0.2)');\n * canvas.renderAll();\n * @example Set shadow with object notation\n * object.setShadow({\n * color: 'red',\n * blur: 10,\n * offsetX: 20,\n * offsetY: 20\n * });\n * canvas.renderAll();\n */\n setShadow: function(options) {\n return this.set('shadow', options ? new fabric.Shadow(options) : null);\n },\n\n /**\n * Sets \"color\" of an instance (alias of `set('fill', …)`)\n * @param {String} color Color value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setColor: function(color) {\n this.set('fill', color);\n return this;\n },\n\n /**\n * Sets \"angle\" of an instance\n * @param {Number} angle Angle value (in degrees)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setAngle: 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 * Removes object from canvas to which it was added last\n * @return {fabric.Object} thisArg\n * @chainable\n */\n remove: function() {\n if (this.canvas) {\n if (this.group && this.group === this.canvas._activeGroup) {\n this.group.remove(this);\n }\n this.canvas.remove(this);\n }\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 specifed 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 fabric.util.createAccessors(fabric.Object);\n\n /**\n * Alias for {@link fabric.Object.prototype.setAngle}\n * @alias rotate -> setAngle\n * @memberOf fabric.Object\n */\n fabric.Object.prototype.rotate = fabric.Object.prototype.setAngle;\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 fabric.Object._fromObject = function(className, object, callback, forceAsync, extraParam) {\n var klass = fabric[className];\n object = clone(object, true);\n if (forceAsync) {\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 var instance = extraParam ? new klass(object[extraParam], object) : new klass(object);\n callback && callback(instance);\n });\n }\n else {\n var instance = extraParam ? new klass(object[extraParam], object) : new klass(object);\n callback && callback(instance);\n return instance;\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\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 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} 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\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.getWidth(),\n xFull = Math.cos(angle) * hypotFull,\n yFull = Math.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 * Callback; invoked right before object is about to go from active to inactive\n */\n onDeselect: function() {\n /* NOOP */\n }\n });\n\n})();\n\n\n(function() {\n\n function getCoords(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 degreesToRadians = fabric.util.degreesToRadians,\n multiplyMatrices = fabric.util.multiplyTransformMatrices;\n\n fabric.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 tl,mt,tr,ml,mr,bl,mb,br,mtr for 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 this properties: width, height, scaleX, scaleY\n * skewX, skewY, angle, strokeWidth, viewportTransform, top, left, padding.\n * The coordinates get updated with @method setCoords.\n * You can calculate them without updating with @method calcCoords;\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 usefull 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 calcCoords(true);\n * @memberOf fabric.Object.prototype\n */\n aCoords: null,\n\n /**\n * return correct set of coordinates for intersection\n */\n getCoords: function(absolute, calculate) {\n if (!this.oCoords) {\n this.setCoords();\n }\n var coords = absolute ? this.aCoords : this.oCoords;\n return getCoords(calculate ? this.calcCoords(absolute) : coords);\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 i = 0, lines = other._getImageLines(\n calculate ? other.calcCoords(absolute) : absolute ? other.aCoords : other.oCoords\n );\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 lines = lines || this._getImageLines(\n calculate ? this.calcCoords(absolute) : absolute ? this.aCoords : this.oCoords\n ),\n xPoints = this._findCrossPoints(point, lines);\n\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 appear on screen\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Boolean} true if object is fully 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), point;\n for (var i = 0; i < 4; i++) {\n point = points[i];\n if (point.x <= pointBR.x && point.x >= pointTL.x && point.y <= pointBR.y && point.y >= pointTL.y) {\n return true;\n }\n }\n // no points on screen, check intersection with absolute coordinates\n if (this.intersectsWithRect(pointTL, pointBR, true)) {\n return true;\n }\n // worst case scenario the object is so big that contanins the screen\n var centerPoint = { x: (pointTL.x + pointBR.x) / 2, y: (pointTL.y + pointBR.y) / 2 };\n if (this.containsPoint(centerPoint, null, true)) {\n return true;\n }\n return false;\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 return {\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\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 width of an object's bounding rectangle\n * @deprecated since 1.0.4\n * @return {Number} width value\n */\n getBoundingRectWidth: function() {\n return this.getBoundingRect().width;\n },\n\n /**\n * Returns height of an object's bounding rectangle\n * @deprecated since 1.0.4\n * @return {Number} height value\n */\n getBoundingRectHeight: function() {\n return this.getBoundingRect().height;\n },\n\n /**\n * Returns coordinates of object's bounding rectangle (left, top, width, height)\n * the box is intented 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\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 fabric.util.makeBoundingBoxFromPoints(coords);\n },\n\n /**\n * Returns width of an object bounding box counting transformations\n * @return {Number} width value\n */\n getWidth: function() {\n return this._getTransformedDimensions().x;\n },\n\n /**\n * Returns height of an object bounding box counting transformations\n * to be renamed in 2.0\n * @return {Number} height value\n */\n getHeight: 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 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 value = this._constrainScale(value);\n\n if (value < 0) {\n this.flipX = !this.flipX;\n this.flipY = !this.flipY;\n value *= -1;\n }\n\n this.scaleX = value;\n this.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 * @return {fabric.Object} thisArg\n * @chainable\n */\n scaleToWidth: function(value) {\n // adjust to bounding rect factor so that rotated shapes would fit as well\n var boundingRectFactor = this.getBoundingRect().width / this.getWidth();\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 * @return {fabric.Object} thisArg\n * @chainable\n */\n scaleToHeight: function(value) {\n // adjust to bounding rect factor so that rotated shapes would fit as well\n var boundingRectFactor = this.getBoundingRect().height / this.getHeight();\n return this.scale(value / this.height / boundingRectFactor);\n },\n\n /**\n * Calculate and returns the .coords of an object.\n * @return {Object} Object with tl, tr, br, bl ....\n * @chainable\n */\n calcCoords: function(absolute) {\n var theta = degreesToRadians(this.angle),\n vpt = this.getViewportTransform(),\n dim = absolute ? this._getTransformedDimensions() : this._calculateCurrentDimensions(),\n currentWidth = dim.x, currentHeight = dim.y,\n sinTh = Math.sin(theta),\n cosTh = Math.cos(theta),\n _angle = currentWidth > 0 ? Math.atan(currentHeight / currentWidth) : 0,\n _hypotenuse = (currentWidth / Math.cos(_angle)) / 2,\n offsetX = Math.cos(_angle + theta) * _hypotenuse,\n offsetY = Math.sin(_angle + theta) * _hypotenuse,\n center = this.getCenterPoint(),\n // offset added for rotate and scale actions\n coords = absolute ? center : fabric.util.transformPoint(center, vpt),\n tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY),\n tr = new fabric.Point(tl.x + (currentWidth * cosTh), tl.y + (currentWidth * sinTh)),\n bl = new fabric.Point(tl.x - (currentHeight * sinTh), tl.y + (currentHeight * cosTh)),\n br = new fabric.Point(coords.x + offsetX, coords.y + offsetY);\n if (!absolute) {\n var ml = new fabric.Point((tl.x + bl.x) / 2, (tl.y + bl.y) / 2),\n mt = new fabric.Point((tr.x + tl.x) / 2, (tr.y + tl.y) / 2),\n mr = new fabric.Point((br.x + tr.x) / 2, (br.y + tr.y) / 2),\n mb = new fabric.Point((br.x + bl.x) / 2, (br.y + bl.y) / 2),\n mtr = new fabric.Point(mt.x + sinTh * this.rotatingPointOffset, mt.y - cosTh * this.rotatingPointOffset);\n }\n\n // debugging\n\n /* setTimeout(function() {\n canvas.contextTop.fillStyle = 'green';\n canvas.contextTop.fillRect(mb.x, mb.y, 3, 3);\n canvas.contextTop.fillRect(bl.x, bl.y, 3, 3);\n canvas.contextTop.fillRect(br.x, br.y, 3, 3);\n canvas.contextTop.fillRect(tl.x, tl.y, 3, 3);\n canvas.contextTop.fillRect(tr.x, tr.y, 3, 3);\n canvas.contextTop.fillRect(ml.x, ml.y, 3, 3);\n canvas.contextTop.fillRect(mr.x, mr.y, 3, 3);\n canvas.contextTop.fillRect(mt.x, mt.y, 3, 3);\n canvas.contextTop.fillRect(mtr.x, mtr.y, 3, 3);\n }, 50); */\n\n var coords = {\n // corners\n tl: tl, tr: tr, br: br, bl: bl,\n };\n if (!absolute) {\n // middle\n coords.ml = ml;\n coords.mt = mt;\n coords.mr = mr;\n coords.mb = mb;\n // rotating point\n coords.mtr = mtr;\n }\n return coords;\n },\n\n /**\n * Sets corner position coordinates based on current angle, width and height\n * See https://github.com/kangax/fabric.js/wiki/When-to-call-setCoords\n * @param {Boolean} [ignoreZoom] set oCoords with or without the viewport transform.\n * @param {Boolean} [skipAbsolute] skip calculation of aCoords, usefull in setViewportTransform\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setCoords: function(ignoreZoom, skipAbsolute) {\n this.oCoords = this.calcCoords(ignoreZoom);\n if (!skipAbsolute) {\n this.aCoords = this.calcCoords(true);\n }\n\n // set coordinates of the draggable boxes in the corners used to scale/rotate the image\n ignoreZoom || (this._setCornerCoords && this._setCornerCoords());\n\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 if (this.angle) {\n var theta = degreesToRadians(this.angle), cos = Math.cos(theta), sin = Math.sin(theta);\n // trying to keep rounding error small, ugly but it works.\n if (cos === 6.123233995736766e-17 || cos === -1.8369701987210297e-16) {\n cos = 0;\n }\n return [cos, sin, -sin, cos, 0, 0];\n }\n return fabric.iMatrix.concat();\n },\n\n /**\n * calculate trasform Matrix that represent current transformation from\n * object properties.\n * @param {Boolean} [skipGroup] return transformMatrix for object and not go upward with parents\n * @return {Array} matrix Transform Matrix for the object\n */\n calcTransformMatrix: function(skipGroup) {\n var center = this.getCenterPoint(),\n translateMatrix = [1, 0, 0, 1, center.x, center.y],\n rotateMatrix,\n dimensionMatrix = this._calcDimensionsTransformMatrix(this.skewX, this.skewY, true),\n matrix;\n if (this.group && !skipGroup) {\n matrix = multiplyMatrices(this.group.calcTransformMatrix(), translateMatrix);\n }\n else {\n matrix = translateMatrix;\n }\n if (this.angle) {\n rotateMatrix = this._calcRotateMatrix();\n matrix = multiplyMatrices(matrix, rotateMatrix);\n }\n matrix = multiplyMatrices(matrix, dimensionMatrix);\n return matrix;\n },\n\n _calcDimensionsTransformMatrix: function(skewX, skewY, flipping) {\n var skewMatrix,\n scaleX = this.scaleX * (flipping && this.flipX ? -1 : 1),\n scaleY = this.scaleY * (flipping && this.flipY ? -1 : 1),\n scaleMatrix = [scaleX, 0, 0, scaleY, 0, 0];\n if (skewX) {\n skewMatrix = [1, 0, Math.tan(degreesToRadians(skewX)), 1];\n scaleMatrix = multiplyMatrices(scaleMatrix, skewMatrix, true);\n }\n if (skewY) {\n skewMatrix = [1, Math.tan(degreesToRadians(skewY)), 0, 1];\n scaleMatrix = multiplyMatrices(scaleMatrix, skewMatrix, true);\n }\n return scaleMatrix;\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 boxdimensions from its properties scale, skew.\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 = this._getNonTransformedDimensions(),\n dimX = dimensions.x / 2, dimY = dimensions.y / 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 i, transformMatrix = this._calcDimensionsTransformMatrix(skewX, skewY, false),\n bbox;\n for (i = 0; i < points.length; i++) {\n points[i] = fabric.util.transformPoint(points[i], transformMatrix);\n }\n bbox = fabric.util.makeBoundingBoxFromPoints(points);\n return { x: bbox.width, y: bbox.height };\n },\n\n /*\n * Calculate object dimensions for controls. include padding and canvas zoom\n * private\n */\n _calculateCurrentDimensions: function() {\n var vpt = this.getViewportTransform(),\n dim = this._getTransformedDimensions(),\n p = fabric.util.transformPoint(dim, vpt, true);\n\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 {\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 {\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 {\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 {\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) {\n fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index);\n }\n else {\n this.canvas.moveTo(this, index);\n }\n return this;\n }\n});\n\n\n/* _TO_SVG_START_ */\n(function() {\n\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 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,\n strokeWidth = this.strokeWidth ? this.strokeWidth : '0',\n strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : 'none',\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-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 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 getSvgId: function() {\n return this.id ? 'id=\"' + this.id + '\" ' : '';\n },\n\n /**\n * Returns transform-string for svg-export\n * @return {String}\n */\n getSvgTransform: function() {\n if (this.group && this.group.type === 'path-group') {\n return '';\n }\n var toFixed = fabric.util.toFixed,\n angle = this.getAngle(),\n skewX = (this.getSkewX() % 360),\n skewY = (this.getSkewY() % 360),\n center = this.getCenterPoint(),\n\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n\n translatePart = this.type === 'path-group' ? '' : 'translate(' +\n toFixed(center.x, NUM_FRACTION_DIGITS) +\n ' ' +\n toFixed(center.y, NUM_FRACTION_DIGITS) +\n ')',\n\n anglePart = angle !== 0\n ? (' rotate(' + toFixed(angle, NUM_FRACTION_DIGITS) + ')')\n : '',\n\n scalePart = (this.scaleX === 1 && this.scaleY === 1)\n ? '' :\n (' scale(' +\n toFixed(this.scaleX, NUM_FRACTION_DIGITS) +\n ' ' +\n toFixed(this.scaleY, NUM_FRACTION_DIGITS) +\n ')'),\n\n skewXPart = skewX !== 0 ? ' skewX(' + toFixed(skewX, NUM_FRACTION_DIGITS) + ')' : '',\n\n skewYPart = skewY !== 0 ? ' skewY(' + toFixed(skewY, NUM_FRACTION_DIGITS) + ')' : '',\n\n addTranslateX = this.type === 'path-group' ? this.width : 0,\n\n flipXPart = this.flipX ? ' matrix(-1 0 0 1 ' + addTranslateX + ' 0) ' : '',\n\n addTranslateY = this.type === 'path-group' ? this.height : 0,\n\n flipYPart = this.flipY ? ' matrix(1 0 0 -1 0 ' + addTranslateY + ')' : '';\n\n return [\n translatePart, anglePart, scalePart, flipXPart, flipYPart, skewXPart, skewYPart\n ].join('');\n },\n\n /**\n * Returns transform-string for svg-export from the transform matrix of single elements\n * @return {String}\n */\n getSvgTransformMatrix: function() {\n return this.transformMatrix ? ' matrix(' + this.transformMatrix.join(' ') + ') ' : '';\n },\n\n /**\n * @private\n */\n _createBaseSVGMarkup: function() {\n var markup = [];\n\n if (this.fill && this.fill.toLive) {\n markup.push(this.fill.toSVG(this, false));\n }\n if (this.stroke && this.stroke.toLive) {\n markup.push(this.stroke.toSVG(this, false));\n }\n if (this.shadow) {\n markup.push(this.shadow.toSVG(this));\n }\n return markup;\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 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 (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 (!firstPass && keys.length !== Object.keys(currentValue).length) {\n return false;\n }\n for (var i = 0, len = keys.length; i < len; i++) {\n key = keys[i];\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 /* eslint-disable camelcase */\n isVML = function() { return typeof G_vmlCanvasManager !== 'undefined'; };\n /* eslint-enable camelcase */\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * The object interactivity controls.\n * @private\n */\n _controlsVisibility: null,\n\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) {\n if (!this.hasControls || !this.active) {\n return false;\n }\n\n var ex = pointer.x,\n ey = pointer.y,\n xPoints,\n lines;\n this.__corner = 0;\n for (var i in this.oCoords) {\n\n if (!this.isControlVisible(i)) {\n continue;\n }\n\n if (i === 'mtr' && !this.hasRotatingPoint) {\n continue;\n }\n\n if (this.get('lockUniScaling') &&\n (i === 'mt' || i === 'mr' || i === 'mb' || i === 'ml')) {\n continue;\n }\n\n lines = this._getImageLines(this.oCoords[i].corner);\n\n // debugging\n\n // canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);\n // canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);\n\n // canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);\n // canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);\n\n // canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);\n // canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);\n\n // canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);\n // 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 * Sets the coordinates of the draggable boxes in the corners of\n * the image used to scale/rotate it.\n * @private\n */\n _setCornerCoords: function() {\n var coords = this.oCoords,\n newTheta = degreesToRadians(45 - this.angle),\n /* Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, */\n /* 0.707106 stands for sqrt(2)/2 */\n cornerHypotenuse = this.cornerSize * 0.707106,\n cosHalfOffset = cornerHypotenuse * Math.cos(newTheta),\n sinHalfOffset = cornerHypotenuse * Math.sin(newTheta),\n x, y;\n\n for (var point in coords) {\n x = coords[point].x;\n y = coords[point].y;\n coords[point].corner = {\n tl: {\n x: x - sinHalfOffset,\n y: y - cosHalfOffset\n },\n tr: {\n x: x + cosHalfOffset,\n y: y - sinHalfOffset\n },\n bl: {\n x: x - cosHalfOffset,\n y: y + sinHalfOffset\n },\n br: {\n x: x + sinHalfOffset,\n y: y + cosHalfOffset\n }\n };\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 || this.group || !this.active ||\n (this.canvas && !this.canvas.interactive)) {\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 * @return {fabric.Object} thisArg\n * @chainable\n */\n drawBorders: function(ctx) {\n if (!this.hasBorders) {\n return this;\n }\n\n var wh = this._calculateCurrentDimensions(),\n strokeWidth = 1 / this.borderScaleFactor,\n width = wh.x + strokeWidth,\n height = wh.y + strokeWidth;\n\n ctx.save();\n ctx.strokeStyle = this.borderColor;\n this._setLineDash(ctx, this.borderDashArray, null);\n\n ctx.strokeRect(\n -width / 2,\n -height / 2,\n width,\n height\n );\n\n if (this.hasRotatingPoint && this.isControlVisible('mtr') && !this.get('lockRotation') && this.hasControls) {\n\n var rotateHeight = -height / 2;\n\n ctx.beginPath();\n ctx.moveTo(0, rotateHeight);\n ctx.lineTo(0, rotateHeight - this.rotatingPointOffset);\n ctx.closePath();\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 * @return {fabric.Object} thisArg\n * @chainable\n */\n drawBordersInGroup: function(ctx, options) {\n if (!this.hasBorders) {\n return this;\n }\n\n var p = this._getNonTransformedDimensions(),\n matrix = fabric.util.customTransformMatrix(options.scaleX, options.scaleY, options.skewX),\n wh = fabric.util.transformPoint(p, matrix),\n strokeWidth = 1 / this.borderScaleFactor,\n width = wh.x + strokeWidth,\n height = wh.y + strokeWidth;\n\n ctx.save();\n this._setLineDash(ctx, this.borderDashArray, null);\n ctx.strokeStyle = this.borderColor;\n\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 * @return {fabric.Object} thisArg\n * @chainable\n */\n drawControls: function(ctx) {\n if (!this.hasControls) {\n return this;\n }\n\n var wh = this._calculateCurrentDimensions(),\n width = wh.x,\n height = wh.y,\n scaleOffset = this.cornerSize,\n left = -(width + scaleOffset) / 2,\n top = -(height + scaleOffset) / 2,\n methodName = this.transparentCorners ? 'stroke' : 'fill';\n\n ctx.save();\n ctx.strokeStyle = ctx.fillStyle = this.cornerColor;\n if (!this.transparentCorners) {\n ctx.strokeStyle = this.cornerStrokeColor;\n }\n this._setLineDash(ctx, this.cornerDashArray, null);\n\n // top-left\n this._drawControl('tl', ctx, methodName,\n left,\n top);\n\n // top-right\n this._drawControl('tr', ctx, methodName,\n left + width,\n top);\n\n // bottom-left\n this._drawControl('bl', ctx, methodName,\n left,\n top + height);\n\n // bottom-right\n this._drawControl('br', ctx, methodName,\n left + width,\n top + height);\n\n if (!this.get('lockUniScaling')) {\n\n // middle-top\n this._drawControl('mt', ctx, methodName,\n left + width / 2,\n top);\n\n // middle-bottom\n this._drawControl('mb', ctx, methodName,\n left + width / 2,\n top + height);\n\n // middle-right\n this._drawControl('mr', ctx, methodName,\n left + width,\n top + height / 2);\n\n // middle-left\n this._drawControl('ml', ctx, methodName,\n left,\n top + height / 2);\n }\n\n // middle-top-rotate\n if (this.hasRotatingPoint) {\n this._drawControl('mtr', ctx, methodName,\n left + width / 2,\n top - this.rotatingPointOffset);\n }\n\n ctx.restore();\n\n return this;\n },\n\n /**\n * @private\n */\n _drawControl: function(control, ctx, methodName, left, top) {\n if (!this.isControlVisible(control)) {\n return;\n }\n var size = this.cornerSize, stroke = !this.transparentCorners && this.cornerStrokeColor;\n switch (this.cornerStyle) {\n case 'circle':\n ctx.beginPath();\n ctx.arc(left + size / 2, top + size / 2, size / 2, 0, 2 * Math.PI, false);\n ctx[methodName]();\n if (stroke) {\n ctx.stroke();\n }\n break;\n default:\n isVML() || this.transparentCorners || ctx.clearRect(left, top, size, size);\n ctx[methodName + 'Rect'](left, top, size, size);\n if (stroke) {\n ctx.strokeRect(left, top, size, size);\n }\n }\n },\n\n /**\n * Returns true if the specified control is visible, false otherwise.\n * @param {String} controlName The name 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(controlName) {\n return this._getControlsVisibility()[controlName];\n },\n\n /**\n * Sets the visibility of the specified control.\n * @param {String} controlName The name 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(controlName, visible) {\n this._getControlsVisibility()[controlName] = 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 * Returns the instance of the control visibility set for this object.\n * @private\n * @returns {Object}\n */\n _getControlsVisibility: function() {\n if (!this._controlsVisibility) {\n this._controlsVisibility = {\n tl: true,\n tr: true,\n br: true,\n bl: true,\n ml: true,\n mt: true,\n mr: true,\n mb: true,\n mtr: true\n };\n }\n return this._controlsVisibility;\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.Canvas} thisArg\n * @chainable\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 fabric.util.animate({\n startValue: object.get('left'),\n endValue: this.getCenter().left,\n duration: this.FX_DURATION,\n onChange: function(value) {\n object.set('left', value);\n _this.renderAll();\n onChange();\n },\n onComplete: function() {\n object.setCoords();\n onComplete();\n }\n });\n\n return this;\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.Canvas} thisArg\n * @chainable\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 fabric.util.animate({\n startValue: object.get('top'),\n endValue: this.getCenter().top,\n duration: this.FX_DURATION,\n onChange: function(value) {\n object.set('top', value);\n _this.renderAll();\n onChange();\n },\n onComplete: function() {\n object.setCoords();\n onComplete();\n }\n });\n\n return this;\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.Canvas} thisArg\n * @chainable\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 fabric.util.animate({\n startValue: object.get('opacity'),\n endValue: 0,\n duration: this.FX_DURATION,\n onStart: function() {\n object.set('active', false);\n },\n onChange: function(value) {\n object.set('opacity', value);\n _this.renderAll();\n onChange();\n },\n onComplete: function () {\n _this.remove(object);\n onComplete();\n }\n });\n\n return this;\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 * @chainable\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;\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 this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks);\n }\n }\n else {\n this._animate.apply(this, arguments);\n }\n return this;\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 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 (~to.indexOf('=')) {\n to = currentValue + parseFloat(to.replace('=', ''));\n }\n else {\n to = parseFloat(to);\n }\n\n fabric.util.animate({\n startValue: options.from,\n endValue: to,\n byValue: options.by,\n easing: options.easing,\n duration: options.duration,\n abort: options.abort && function() {\n return options.abort.call(_this);\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});\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 supportsLineDash = fabric.StaticCanvas.supports('setLineDash');\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 * @param {Boolean} noTransform\n */\n _render: function(ctx, noTransform) {\n ctx.beginPath();\n\n if (noTransform) {\n // Line coords are distances from left-top of canvas to origin of line.\n // To render line in a path-group, we need to translate them to\n // distances from center of path-group to center of line.\n var cp = this.getCenterPoint(),\n offset = this.strokeWidth / 2;\n ctx.translate(\n cp.x - (this.strokeLineCap === 'butt' && this.height === 0 ? 0 : offset),\n cp.y - (this.strokeLineCap === 'butt' && this.width === 0 ? 0 : offset)\n );\n }\n\n if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) {\n // move from center (of virtual box) to its left/top corner\n // we can't assume x1, y1 is top left and x2, y2 is bottom right\n var p = this.calcLinePoints();\n ctx.moveTo(p.x1, p.y1);\n ctx.lineTo(p.x2, p.y2);\n }\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 * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var p = this.calcLinePoints();\n\n ctx.beginPath();\n fabric.util.drawDashedLine(ctx, p.x1, p.y1, p.x2, p.y2, this.strokeDashArray);\n ctx.closePath();\n },\n\n /**\n * Returns object representation of an instance\n * @methd 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 * @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 markup = this._createBaseSVGMarkup(),\n p = { x1: this.x1, x2: this.x2, y1: this.y1, y2: this.y2 };\n\n if (!(this.group && this.group.type === 'path-group')) {\n p = this.calcLinePoints();\n }\n markup.push(\n '\\n'\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\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 * @return {fabric.Line} instance of fabric.Line\n */\n fabric.Line.fromElement = function(element, 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 options.originX = 'left';\n options.originY = 'top';\n return 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 * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Line} instance of fabric.Line\n */\n fabric.Line.fromObject = function(object, callback, forceAsync) {\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 var line = fabric.Object._fromObject('Line', options, _callback, forceAsync, 'points');\n if (line) {\n delete line.points;\n }\n return line;\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 pi = Math.PI,\n extend = fabric.util.object.extend;\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 * Start angle of the circle, moving clockwise\n * @type Number\n * @default 0\n */\n startAngle: 0,\n\n /**\n * End angle of the circle\n * @type Number\n * @default 2Pi\n */\n endAngle: pi * 2,\n\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('radius'),\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n * @return {fabric.Circle} thisArg\n */\n initialize: function(options) {\n this.callSuper('initialize', options);\n this.set('radius', options && options.radius || 0);\n },\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 * 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 markup = this._createBaseSVGMarkup(), x = 0, y = 0,\n angle = (this.endAngle - this.startAngle) % ( 2 * pi);\n\n if (angle === 0) {\n if (this.group && this.group.type === 'path-group') {\n x = this.left + this.radius;\n y = this.top + this.radius;\n }\n markup.push(\n '\\n'\n );\n }\n else {\n var startX = Math.cos(this.startAngle) * this.radius,\n startY = Math.sin(this.startAngle) * this.radius,\n endX = Math.cos(this.endAngle) * this.radius,\n endY = Math.sin(this.endAngle) * this.radius,\n largeFlag = angle > pi ? '1' : '0';\n\n markup.push(\n '\\n'\n );\n }\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n _render: function(ctx, noTransform) {\n ctx.beginPath();\n ctx.arc(noTransform ? this.left + this.radius : 0,\n noTransform ? this.top + this.radius : 0,\n this.radius,\n this.startAngle,\n this.endAngle, false);\n this._renderFill(ctx);\n this._renderStroke(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 {Object} [options] Options object\n * @throws {Error} If value of `r` attribute is missing or invalid\n * @return {fabric.Circle} Instance of fabric.Circle\n */\n fabric.Circle.fromElement = function(element, options) {\n options || (options = { });\n\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;\n parsedAttributes.top = parsedAttributes.top || 0;\n\n var obj = new fabric.Circle(extend(parsedAttributes, options));\n\n obj.left -= obj.radius;\n obj.top -= obj.radius;\n return obj;\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 * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {Object} Instance of fabric.Circle\n */\n fabric.Circle.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Circle', object, callback, forceAsync);\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 * Constructor\n * @param {Object} [options] Options object\n * @return {Object} thisArg\n */\n initialize: function(options) {\n this.callSuper('initialize', options);\n this.set('width', options && options.width || 100)\n .set('height', options && options.height || 100);\n },\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._renderFill(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var widthBy2 = this.width / 2,\n heightBy2 = this.height / 2;\n\n ctx.beginPath();\n fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray);\n ctx.closePath();\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 markup = this._createBaseSVGMarkup(),\n widthBy2 = this.width / 2,\n heightBy2 = this.height / 2,\n points = [\n -widthBy2 + ' ' + heightBy2,\n '0 ' + -heightBy2,\n widthBy2 + ' ' + heightBy2\n ]\n .join(',');\n\n markup.push(\n ''\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\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 * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Triangle}\n */\n fabric.Triangle.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Triangle', object, callback, forceAsync);\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 extend = fabric.util.object.extend;\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 * @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 markup = this._createBaseSVGMarkup(), x = 0, y = 0;\n if (this.group && this.group.type === 'path-group') {\n x = this.left + this.rx;\n y = this.top + this.ry;\n }\n markup.push(\n '\\n'\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n _render: function(ctx, noTransform) {\n ctx.beginPath();\n ctx.save();\n ctx.transform(1, 0, 0, this.ry / this.rx, 0, 0);\n ctx.arc(\n noTransform ? this.left + this.rx : 0,\n noTransform ? (this.top + this.ry) * this.rx / this.ry : 0,\n this.rx,\n 0,\n piBy2,\n false);\n ctx.restore();\n this._renderFill(ctx);\n this._renderStroke(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 {Object} [options] Options object\n * @return {fabric.Ellipse}\n */\n fabric.Ellipse.fromElement = function(element, options) {\n options || (options = { });\n\n var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES);\n\n parsedAttributes.left = parsedAttributes.left || 0;\n parsedAttributes.top = parsedAttributes.top || 0;\n\n var ellipse = new fabric.Ellipse(extend(parsedAttributes, options));\n\n ellipse.top -= ellipse.ry;\n ellipse.left -= ellipse.rx;\n return ellipse;\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 * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Ellipse}\n */\n fabric.Ellipse.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Ellipse', object, callback, forceAsync);\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 * @param {Boolean} noTransform\n */\n _render: function(ctx, noTransform) {\n\n // optimize 1x1 case (used in spray brush)\n if (this.width === 1 && this.height === 1) {\n ctx.fillRect(-0.5, -0.5, 1, 1);\n return;\n }\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 = noTransform ? this.left : -this.width / 2,\n y = noTransform ? this.top : -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._renderFill(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var x = -this.width / 2,\n y = -this.height / 2,\n w = this.width,\n h = this.height;\n\n ctx.beginPath();\n fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);\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 return this.callSuper('toObject', ['rx', 'ry'].concat(propertiesToInclude));\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 markup = this._createBaseSVGMarkup(), x = this.left, y = this.top;\n if (!(this.group && this.group.type === 'path-group')) {\n x = -this.width / 2;\n y = -this.height / 2;\n }\n markup.push(\n '\\n');\n\n return reviver ? reviver(markup.join('')) : markup.join('');\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 {Object} [options] Options object\n * @return {fabric.Rect} Instance of fabric.Rect\n */\n fabric.Rect.fromElement = function(element, options) {\n if (!element) {\n return null;\n }\n options = options || { };\n\n var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);\n\n parsedAttributes.left = parsedAttributes.left || 0;\n parsedAttributes.top = parsedAttributes.top || 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 return 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 * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {Object} instance of fabric.Rect\n */\n fabric.Rect.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Rect', object, callback, forceAsync);\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 NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\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 * Minimum X from points values, necessary to offset points\n * @type Number\n * @default\n */\n minX: 0,\n\n /**\n * Minimum Y from points values, necessary to offset points\n * @type Number\n * @default\n */\n minY: 0,\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._calcDimensions();\n if (!('top' in options)) {\n this.top = this.minY;\n }\n if (!('left' in options)) {\n this.left = this.minX;\n }\n this.pathOffset = {\n x: this.minX + this.width / 2,\n y: this.minY + this.height / 2\n };\n },\n\n /**\n * @private\n */\n _calcDimensions: function() {\n\n var points = this.points,\n minX = min(points, 'x'),\n minY = min(points, 'y'),\n maxX = max(points, 'x'),\n maxY = max(points, 'y');\n\n this.width = (maxX - minX) || 0;\n this.height = (maxY - minY) || 0;\n this.minX = minX || 0;\n this.minY = minY || 0;\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 * @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 points = [],\n diffX = 0,\n diffY = 0,\n markup = this._createBaseSVGMarkup();\n\n if (!(this.group && this.group.type === 'path-group')) {\n diffX = this.pathOffset.x;\n diffY = this.pathOffset.y;\n }\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 markup.push(\n '<', this.type, ' ', this.getSvgId(),\n 'points=\"', points.join(''),\n '\" style=\"', this.getSvgStyles(),\n '\" transform=\"', this.getSvgTransform(),\n ' ', this.getSvgTransformMatrix(),\n '\"/>\\n'\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} noTransform\n */\n commonRender: function(ctx, noTransform) {\n var point, len = this.points.length,\n x = noTransform ? 0 : this.pathOffset.x,\n y = noTransform ? 0 : 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 * @param {Boolean} noTransform\n */\n _render: function(ctx, noTransform) {\n if (!this.commonRender(ctx, noTransform)) {\n return;\n }\n this._renderFill(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var p1, p2;\n\n ctx.beginPath();\n for (var i = 0, len = this.points.length; i < len; i++) {\n p1 = this.points[i];\n p2 = this.points[i + 1] || p1;\n fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray);\n }\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 parse\n * @param {Object} [options] Options object\n * @return {fabric.Polyline} Instance of fabric.Polyline\n */\n fabric.Polyline.fromElement = function(element, options) {\n if (!element) {\n return null;\n }\n options || (options = { });\n\n var points = fabric.parsePointsAttribute(element.getAttribute('points')),\n parsedAttributes = fabric.parseAttributes(element, fabric.Polyline.ATTRIBUTE_NAMES);\n\n return new fabric.Polyline(points, fabric.util.object.extend(parsedAttributes, options));\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 * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Polyline} Instance of fabric.Polyline\n */\n fabric.Polyline.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Polyline', object, callback, forceAsync, '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 extend = fabric.util.object.extend;\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 * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} noTransform\n */\n _render: function(ctx, noTransform) {\n if (!this.commonRender(ctx, noTransform)) {\n return;\n }\n ctx.closePath();\n this._renderFill(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n this.callSuper('_renderDashedStroke', ctx);\n ctx.closePath();\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 {Object} [options] Options object\n * @return {fabric.Polygon} Instance of fabric.Polygon\n */\n fabric.Polygon.fromElement = function(element, options) {\n if (!element) {\n return null;\n }\n\n options || (options = { });\n\n var points = fabric.parsePointsAttribute(element.getAttribute('points')),\n parsedAttributes = fabric.parseAttributes(element, fabric.Polygon.ATTRIBUTE_NAMES);\n\n return new fabric.Polygon(points, extend(parsedAttributes, options));\n };\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 * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Polygon} Instance of fabric.Polygon\n */\n fabric.Polygon.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Polygon', object, callback, forceAsync, '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 _toString = Object.prototype.toString,\n drawArc = fabric.util.drawArc,\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\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 /**\n * Minimum X from points values, necessary to offset points\n * @type Number\n * @default\n */\n minX: 0,\n\n /**\n * Minimum Y from points values, necessary to offset points\n * @type Number\n * @default\n */\n minY: 0,\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 = options || { };\n this.callSuper('initialize', options);\n\n if (!path) {\n path = [];\n }\n\n var fromArray = _toString.call(path) === '[object Array]';\n\n this.path = fromArray\n ? path\n // one of commands (m,M,l,L,q,Q,c,C,etc.) followed by non-command characters (i.e. command values)\n : path.match && path.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi);\n\n if (!this.path) {\n return;\n }\n\n if (!fromArray) {\n this.path = this._parsePath();\n }\n\n this._setPositionDimensions(options);\n },\n\n /**\n * @private\n * @param {Object} options Options object\n */\n _setPositionDimensions: function(options) {\n var calcDim = this._parseDimensions();\n\n this.minX = calcDim.left;\n this.minY = calcDim.top;\n this.width = calcDim.width;\n this.height = calcDim.height;\n\n if (typeof options.left === 'undefined') {\n this.left = calcDim.left + (this.originX === 'center'\n ? this.width / 2\n : this.originX === 'right'\n ? this.width\n : 0);\n }\n\n if (typeof options.top === 'undefined') {\n this.top = calcDim.top + (this.originY === 'center'\n ? this.height / 2\n : this.originY === 'bottom'\n ? this.height\n : 0);\n }\n\n this.pathOffset = this.pathOffset || {\n x: this.minX + this.width / 2,\n y: this.minY + this.height / 2\n };\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 previous = null,\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 tempX,\n tempY,\n l = -this.pathOffset.x,\n t = -this.pathOffset.y;\n\n if (this.group && this.group.type === 'path-group') {\n l = 0;\n t = 0;\n }\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, relative\n x += current[1];\n y += current[2];\n ctx.lineTo(x + l, y + t);\n break;\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 'h': // horizontal lineto, relative\n x += current[1];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'H': // horizontal lineto, absolute\n x = current[1];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'v': // vertical lineto, relative\n y += current[1];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'V': // verical lineto, absolute\n y = current[1];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'm': // moveTo, relative\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 '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, relative\n tempX = x + current[5];\n tempY = y + current[6];\n controlX = x + current[3];\n controlY = y + current[4];\n ctx.bezierCurveTo(\n x + current[1] + l, // x1\n y + current[2] + t, // y1\n controlX + l, // x2\n controlY + t, // y2\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\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 's': // shorthand cubic bezierCurveTo, relative\n\n // transform to absolute x,y\n tempX = x + current[3];\n tempY = y + current[4];\n\n if (previous[0].match(/[CcSs]/) === null) {\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 else {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n\n ctx.bezierCurveTo(\n controlX + l,\n controlY + t,\n x + current[1] + l,\n y + current[2] + t,\n tempX + l,\n tempY + t\n );\n // set control point to 2nd one of this command\n // \"... the first control point is assumed to be\n // the reflection of the second control point on\n // the previous command relative to the current point.\"\n controlX = x + current[1];\n controlY = y + current[2];\n\n x = tempX;\n y = tempY;\n break;\n\n case 'S': // shorthand cubic bezierCurveTo, absolute\n tempX = current[3];\n tempY = current[4];\n if (previous[0].match(/[CcSs]/) === null) {\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 else {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n ctx.bezierCurveTo(\n controlX + l,\n controlY + t,\n current[1] + l,\n current[2] + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n\n // set control point to 2nd one of this command\n // \"... the first control point is assumed to be\n // the reflection of the second control point on\n // the previous command relative to the current point.\"\n controlX = current[1];\n controlY = current[2];\n\n break;\n\n case 'q': // quadraticCurveTo, relative\n // transform to absolute x,y\n tempX = x + current[3];\n tempY = y + current[4];\n\n controlX = x + current[1];\n controlY = y + current[2];\n\n ctx.quadraticCurveTo(\n controlX + l,\n controlY + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'Q': // quadraticCurveTo, absolute\n tempX = current[3];\n tempY = current[4];\n\n ctx.quadraticCurveTo(\n current[1] + l,\n current[2] + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n controlX = current[1];\n controlY = current[2];\n break;\n\n case 't': // shorthand quadraticCurveTo, relative\n\n // transform to absolute x,y\n tempX = x + current[1];\n tempY = y + current[2];\n\n if (previous[0].match(/[QqTt]/) === null) {\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 else {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n\n ctx.quadraticCurveTo(\n controlX + l,\n controlY + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n\n break;\n\n case 'T':\n tempX = current[1];\n tempY = current[2];\n\n if (previous[0].match(/[QqTt]/) === null) {\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 else {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n ctx.quadraticCurveTo(\n controlX + l,\n controlY + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'a':\n // TODO: optimize this\n drawArc(ctx, x + l, y + t, [\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6] + x + l,\n current[7] + y + t\n ]);\n x += current[6];\n y += current[7];\n break;\n\n case 'A':\n // TODO: optimize this\n drawArc(ctx, x + l, y + t, [\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6] + l,\n current[7] + t\n ]);\n x = current[6];\n y = current[7];\n break;\n\n case 'z':\n case 'Z':\n x = subpathStartX;\n y = subpathStartY;\n ctx.closePath();\n break;\n }\n previous = current;\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._renderFill(ctx);\n this._renderStroke(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 var o = extend(this.callSuper('toObject', ['sourcePath', 'pathOffset'].concat(propertiesToInclude)), {\n path: this.path.map(function(item) { return item.slice(); }),\n top: this.top,\n left: this.left,\n });\n return o;\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(propertiesToInclude);\n if (this.sourcePath) {\n o.path = this.sourcePath;\n }\n delete o.sourcePath;\n return o;\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 chunks = [],\n markup = this._createBaseSVGMarkup(), addTransform = '';\n\n for (var i = 0, len = this.path.length; i < len; i++) {\n chunks.push(this.path[i].join(' '));\n }\n var path = chunks.join(' ');\n if (!(this.group && this.group.type === 'path-group')) {\n addTransform = ' translate(' + (-this.pathOffset.x) + ', ' + (-this.pathOffset.y) + ') ';\n }\n markup.push(\n '\\n'\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\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 _parsePath: function() {\n var result = [],\n coords = [],\n currentPath,\n parsed,\n re = /([-+]?((\\d+\\.\\d+)|((\\d+)|(\\.\\d+)))(?:e[-+]?\\d+)?)/ig,\n match,\n coordsStr;\n\n for (var i = 0, coordsParsed, len = this.path.length; i < len; i++) {\n currentPath = this.path[i];\n\n coordsStr = currentPath.slice(1).trim();\n coords.length = 0;\n\n while ((match = re.exec(coordsStr))) {\n coords.push(match[0]);\n }\n\n coordsParsed = [currentPath.charAt(0)];\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 command = coordsParsed[0],\n 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 * @private\n */\n _parseDimensions: function() {\n\n var aX = [],\n aY = [],\n current, // current instruction\n previous = null,\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 tempX,\n tempY,\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, relative\n x += current[1];\n y += current[2];\n bounds = [];\n break;\n\n case 'L': // lineto, absolute\n x = current[1];\n y = current[2];\n bounds = [];\n break;\n\n case 'h': // horizontal lineto, relative\n x += current[1];\n bounds = [];\n break;\n\n case 'H': // horizontal lineto, absolute\n x = current[1];\n bounds = [];\n break;\n\n case 'v': // vertical lineto, relative\n y += current[1];\n bounds = [];\n break;\n\n case 'V': // verical lineto, absolute\n y = current[1];\n bounds = [];\n break;\n\n case 'm': // moveTo, relative\n x += current[1];\n y += current[2];\n subpathStartX = x;\n subpathStartY = y;\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, relative\n tempX = x + current[5];\n tempY = y + current[6];\n controlX = x + current[3];\n controlY = y + current[4];\n bounds = fabric.util.getBoundsOfCurve(x, y,\n x + current[1], // x1\n y + current[2], // y1\n controlX, // x2\n controlY, // y2\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'C': // bezierCurveTo, absolute\n controlX = current[3];\n controlY = current[4];\n bounds = fabric.util.getBoundsOfCurve(x, y,\n current[1],\n current[2],\n controlX,\n controlY,\n current[5],\n current[6]\n );\n x = current[5];\n y = current[6];\n break;\n\n case 's': // shorthand cubic bezierCurveTo, relative\n\n // transform to absolute x,y\n tempX = x + current[3];\n tempY = y + current[4];\n\n if (previous[0].match(/[CcSs]/) === null) {\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 else {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n x + current[1],\n y + current[2],\n tempX,\n tempY\n );\n // set control point to 2nd one of this command\n // \"... the first control point is assumed to be\n // the reflection of the second control point on\n // the previous command relative to the current point.\"\n controlX = x + current[1];\n controlY = y + current[2];\n x = tempX;\n y = tempY;\n break;\n\n case 'S': // shorthand cubic bezierCurveTo, absolute\n tempX = current[3];\n tempY = current[4];\n if (previous[0].match(/[CcSs]/) === null) {\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 else {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n current[1],\n current[2],\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n // set control point to 2nd one of this command\n // \"... the first control point is assumed to be\n // the reflection of the second control point on\n // the previous command relative to the current point.\"\n controlX = current[1];\n controlY = current[2];\n break;\n\n case 'q': // quadraticCurveTo, relative\n // transform to absolute x,y\n tempX = x + current[3];\n tempY = y + current[4];\n controlX = x + current[1];\n controlY = y + current[2];\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n controlX,\n controlY,\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'Q': // quadraticCurveTo, absolute\n controlX = current[1];\n controlY = current[2];\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n controlX,\n controlY,\n current[3],\n current[4]\n );\n x = current[3];\n y = current[4];\n break;\n\n case 't': // shorthand quadraticCurveTo, relative\n // transform to absolute x,y\n tempX = x + current[1];\n tempY = y + current[2];\n if (previous[0].match(/[QqTt]/) === null) {\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 else {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n controlX,\n controlY,\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n\n break;\n\n case 'T':\n tempX = current[1];\n tempY = current[2];\n\n if (previous[0].match(/[QqTt]/) === null) {\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 else {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n controlX,\n controlY,\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'a':\n // TODO: optimize this\n bounds = fabric.util.getBoundsOfArc(x, y,\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6] + x,\n current[7] + y\n );\n x += current[6];\n y += current[7];\n break;\n\n case 'A':\n // TODO: optimize this\n bounds = fabric.util.getBoundsOfArc(x, y,\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6],\n current[7]\n );\n x = current[6];\n y = current[7];\n break;\n\n case 'z':\n case 'Z':\n x = subpathStartX;\n y = subpathStartY;\n break;\n }\n previous = current;\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 o = {\n left: minX,\n top: minY,\n width: deltaX,\n height: deltaY\n };\n\n return o;\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 * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n */\n fabric.Path.fromObject = function(object, callback, forceAsync) {\n // remove this pattern rom 2.0, accept just object.\n var path;\n if (typeof object.path === 'string') {\n fabric.loadSVGFromURL(object.path, function (elements) {\n var pathUrl = object.path;\n path = elements[0];\n delete object.path;\n\n path.setOptions(object);\n path.setSourcePath(pathUrl);\n\n callback && callback(path);\n });\n }\n else {\n return fabric.Object._fromObject('Path', object, callback, forceAsync, '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 */\n fabric.Path.fromElement = function(element, callback, options) {\n var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES);\n callback && callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options)));\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @memberOf fabric.Path\n * @type Boolean\n * @default\n */\n fabric.Path.async = true;\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.PathGroup) {\n fabric.warn('fabric.PathGroup is already defined');\n return;\n }\n\n /**\n * Path group class\n * @class fabric.PathGroup\n * @extends fabric.Path\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#path_and_pathgroup}\n * @see {@link fabric.PathGroup#initialize} for constructor definition\n */\n fabric.PathGroup = fabric.util.createClass(fabric.Object, /** @lends fabric.PathGroup.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'path-group',\n\n /**\n * Fill value\n * @type String\n * @default\n */\n fill: '',\n\n /**\n * Pathgroups are container, do not render anything on theyr own, ence no cache properties\n * @type Boolean\n * @default\n */\n cacheProperties: [],\n\n /**\n * Constructor\n * @param {Array} paths\n * @param {Object} [options] Options object\n * @return {fabric.PathGroup} thisArg\n */\n initialize: function(paths, options) {\n\n options = options || { };\n this.paths = paths || [];\n\n for (var i = this.paths.length; i--;) {\n this.paths[i].group = this;\n }\n\n if (options.toBeParsed) {\n this.parseDimensionsFromPaths(options);\n delete options.toBeParsed;\n }\n this.setOptions(options);\n this.setCoords();\n },\n\n /**\n * Calculate width and height based on paths contained\n */\n parseDimensionsFromPaths: function(options) {\n var points, p, xC = [], yC = [], path, height, width,\n m;\n for (var j = this.paths.length; j--;) {\n path = this.paths[j];\n height = path.height + path.strokeWidth;\n width = path.width + path.strokeWidth;\n points = [\n { x: path.left, y: path.top },\n { x: path.left + width, y: path.top },\n { x: path.left, y: path.top + height },\n { x: path.left + width, y: path.top + height }\n ];\n m = this.paths[j].transformMatrix;\n for (var i = 0; i < points.length; i++) {\n p = points[i];\n if (m) {\n p = fabric.util.transformPoint(p, m, false);\n }\n xC.push(p.x);\n yC.push(p.y);\n }\n }\n options.width = Math.max.apply(null, xC);\n options.height = Math.max.apply(null, yC);\n },\n\n /**\n * Execute the drawing operation for an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n drawObject: function(ctx) {\n ctx.save();\n ctx.translate(-this.width / 2, -this.height / 2);\n for (var i = 0, l = this.paths.length; i < l; ++i) {\n this.paths[i].render(ctx, true);\n }\n ctx.restore();\n },\n\n /**\n * Decide if the object should cache or not.\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 var parentCache = this.objectCaching && (!this.group || this.needsItsOwnCache() || !this.group.isCaching());\n this.caching = parentCache;\n if (parentCache) {\n for (var i = 0, len = this.paths.length; i < len; i++) {\n if (this.paths[i].willDrawShadow()) {\n this.caching = false;\n return false;\n }\n }\n }\n return parentCache;\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 (this.shadow) {\n return true;\n }\n for (var i = 0, len = this.paths.length; i < len; i++) {\n if (this.paths[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 isCaching: function() {\n return this.caching || this.group && this.group.isCaching();\n },\n\n /**\n * Check if cache is dirty\n */\n isCacheDirty: function() {\n if (this.callSuper('isCacheDirty')) {\n return true;\n }\n if (!this.statefullCache) {\n return false;\n }\n for (var i = 0, len = this.paths.length; i < len; i++) {\n if (this.paths[i].isCacheDirty(true)) {\n if (this._cacheCanvas) {\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 * Sets certain property to a certain value\n * @param {String} prop\n * @param {*} value\n * @return {fabric.PathGroup} thisArg\n */\n _set: function(prop, value) {\n\n if (prop === 'fill' && value && this.isSameColor()) {\n var i = this.paths.length;\n while (i--) {\n this.paths[i]._set(prop, value);\n }\n }\n\n return this.callSuper('_set', prop, value);\n },\n\n /**\n * Returns object representation of this path group\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 pathsToObject = this.paths.map(function(path) {\n var originalDefaults = path.includeDefaultValues;\n path.includeDefaultValues = path.group.includeDefaultValues;\n var obj = path.toObject(propertiesToInclude);\n path.includeDefaultValues = originalDefaults;\n return obj;\n });\n var o = extend(this.callSuper('toObject', ['sourcePath'].concat(propertiesToInclude)), {\n paths: pathsToObject\n });\n return o;\n },\n\n /**\n * Returns dataless object representation of this path group\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} dataless object representation of an instance\n */\n toDatalessObject: function(propertiesToInclude) {\n var o = this.toObject(propertiesToInclude);\n if (this.sourcePath) {\n o.paths = this.sourcePath;\n }\n return o;\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 objects = this.getObjects(),\n p = this.getPointByOrigin('left', 'top'),\n translatePart = 'translate(' + p.x + ' ' + p.y + ')',\n markup = this._createBaseSVGMarkup();\n markup.push(\n '\\n'\n );\n\n for (var i = 0, len = objects.length; i < len; i++) {\n markup.push('\\t', objects[i].toSVG(reviver));\n }\n markup.push('\\n');\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns a string representation of this path group\n * @return {String} string representation of an object\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Returns true if all paths in this group are of same color\n * @return {Boolean} true if all paths are of the same color (`fill`)\n */\n isSameColor: function() {\n var firstPathFill = this.getObjects()[0].get('fill') || '';\n if (typeof firstPathFill !== 'string') {\n return false;\n }\n firstPathFill = firstPathFill.toLowerCase();\n return this.getObjects().every(function(path) {\n var pathFill = path.get('fill') || '';\n return typeof pathFill === 'string' && (pathFill).toLowerCase() === firstPathFill;\n });\n },\n\n /**\n * Returns number representation of object's complexity\n * @return {Number} complexity\n */\n complexity: function() {\n return this.paths.reduce(function(total, path) {\n return total + ((path && path.complexity) ? path.complexity() : 0);\n }, 0);\n },\n\n /**\n * Returns all paths in this path group\n * @return {Array} array of path objects included in this path group\n */\n getObjects: function() {\n return this.paths;\n }\n });\n\n /**\n * Creates fabric.PathGroup instance from an object representation\n * @static\n * @memberOf fabric.PathGroup\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] Callback to invoke when an fabric.PathGroup instance is created\n */\n fabric.PathGroup.fromObject = function(object, callback) {\n var originalPaths = object.paths;\n delete object.paths;\n if (typeof originalPaths === 'string') {\n fabric.loadSVGFromURL(originalPaths, function (elements) {\n var pathUrl = originalPaths;\n var pathGroup = fabric.util.groupSVGElements(elements, object, pathUrl);\n object.paths = originalPaths;\n callback(pathGroup);\n });\n }\n else {\n fabric.util.enlivenObjects(originalPaths, function(enlivenedObjects) {\n var pathGroup = new fabric.PathGroup(enlivenedObjects, object);\n object.paths = originalPaths;\n callback(pathGroup);\n });\n }\n };\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @memberOf fabric.PathGroup\n * @type Boolean\n * @default\n */\n fabric.PathGroup.async = true;\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\n if (fabric.Group) {\n return;\n }\n\n // lock-related properties, for use in fabric.Group#get\n // to enable locking behavior on group\n // when one of its objects has lock-related properties set\n var _lockProperties = {\n lockMovementX: true,\n lockMovementY: true,\n lockRotation: true,\n lockScalingX: true,\n lockScalingY: true,\n lockUniScaling: true\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 events 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 Boolean\n * @default\n */\n cacheProperties: [],\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\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 // because delegatedProperties propagate to objects.\n isAlreadyGrouped && this.callSuper('initialize', options);\n\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\n if (isAlreadyGrouped) {\n // do not change coordinate of objects enclosed in a group,\n // because objects coordinate system have been group coodinate system already.\n this._updateObjectsCoords(true);\n this._updateObjectsACoords();\n }\n else {\n this._calcBounds();\n this._updateObjectsCoords();\n this.callSuper('initialize', options);\n }\n\n this.setCoords();\n this.saveCoords();\n },\n\n _updateObjectsACoords: function() {\n var ignoreZoom = true, skipAbsolute = true;\n for (var i = this._objects.length; i--; ){\n this._objects[i].setCoords(ignoreZoom, skipAbsolute);\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(skipCoordsChange) {\n var center = this.getCenterPoint();\n for (var i = this._objects.length; i--; ){\n this._updateObjectCoords(this._objects[i], center, skipCoordsChange);\n }\n },\n\n /**\n * @private\n * @param {Object} object\n * @param {fabric.Point} center, current center of group.\n * @param {Boolean} [skipCoordsChange] if true, coordinates of object dose not change\n */\n _updateObjectCoords: function(object, center, skipCoordsChange) {\n // do not display corners of objects enclosed in a group\n object.__origHasControls = object.hasControls;\n object.hasControls = false;\n\n if (skipCoordsChange) {\n return;\n }\n\n var objectLeft = object.getLeft(),\n objectTop = object.getTop(),\n ignoreZoom = true, skipAbsolute = true;\n\n object.set({\n left: objectLeft - center.x,\n top: objectTop - center.y\n });\n object.setCoords(ignoreZoom, skipAbsolute);\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 this._restoreObjectsState();\n fabric.util.resetObjectTransform(this);\n if (object) {\n this._objects.push(object);\n object.group = this;\n object._set('canvas', this.canvas);\n }\n // since _restoreObjectsState set objects inactive\n this.forEachObject(this._setObjectActive, this);\n this._calcBounds();\n this._updateObjectsCoords();\n this.setCoords();\n this.dirty = true;\n return this;\n },\n\n /**\n * @private\n */\n _setObjectActive: function(object) {\n object.set('active', true);\n object.group = 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 // since _restoreObjectsState set objects inactive\n this.forEachObject(this._setObjectActive, 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 object.set('active', false);\n },\n\n /**\n * Properties that are delegated to group objects when reading/writing\n * @param {Object} delegatedProperties\n */\n delegatedProperties: {\n fill: true,\n stroke: true,\n strokeWidth: true,\n fontFamily: true,\n fontWeight: true,\n fontSize: true,\n fontStyle: true,\n lineHeight: true,\n textDecoration: true,\n textAlign: true,\n backgroundColor: true\n },\n\n /**\n * @private\n */\n _set: function(key, value) {\n var i = this._objects.length;\n\n if (this.delegatedProperties[key] || key === 'canvas') {\n while (i--) {\n this._objects[i].set(key, value);\n }\n }\n else {\n while (i--) {\n this._objects[i].setOnGroup(key, value);\n }\n }\n\n this.callSuper('_set', 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 objsToObject = this.getObjects().map(function(obj) {\n var originalDefaults = obj.includeDefaultValues;\n obj.includeDefaultValues = obj.group.includeDefaultValues;\n var _obj = obj.toObject(propertiesToInclude);\n obj.includeDefaultValues = originalDefaults;\n return _obj;\n });\n return extend(this.callSuper('toObject', propertiesToInclude), {\n objects: objsToObject\n });\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 = this.getObjects().map(function(obj) {\n var originalDefaults = obj.includeDefaultValues;\n obj.includeDefaultValues = obj.group.includeDefaultValues;\n var _obj = obj.toDatalessObject(propertiesToInclude);\n obj.includeDefaultValues = originalDefaults;\n return _obj;\n });\n return extend(this.callSuper('toDatalessObject', propertiesToInclude), {\n objects: objsToObject\n });\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.\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 var parentCache = this.objectCaching && (!this.group || this.needsItsOwnCache() || !this.group.isCaching());\n this.caching = parentCache;\n if (parentCache) {\n for (var i = 0, len = this._objects.length; i < len; i++) {\n if (this._objects[i].willDrawShadow()) {\n this.caching = false;\n return false;\n }\n }\n }\n return parentCache;\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 (this.callSuper('willDrawShadow')) {\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 isCaching: function() {\n return this.caching || this.group && this.group.isCaching();\n },\n\n /**\n * Execute the drawing operation for an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n drawObject: function(ctx) {\n for (var i = 0, len = this._objects.length; i < len; i++) {\n this._renderObject(this._objects[i], ctx);\n }\n },\n\n /**\n * Check if cache is dirty\n */\n isCacheDirty: function() {\n if (this.callSuper('isCacheDirty')) {\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 * Renders controls and borders for the object\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n _renderControls: function(ctx, noTransform) {\n ctx.save();\n ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n this.callSuper('_renderControls', ctx, noTransform);\n for (var i = 0, len = this._objects.length; i < len; i++) {\n this._objects[i]._renderControls(ctx);\n }\n ctx.restore();\n },\n\n /**\n * @private\n */\n _renderObject: function(object, ctx) {\n // do not render if object is not visible\n if (!object.visible) {\n return;\n }\n\n var originalHasRotatingPoint = object.hasRotatingPoint;\n object.hasRotatingPoint = false;\n object.render(ctx);\n object.hasRotatingPoint = originalHasRotatingPoint;\n },\n\n /**\n * Retores original state of each of group objects (original state is that which was before group was created).\n * @private\n * @return {fabric.Group} thisArg\n * @chainable\n */\n _restoreObjectsState: function() {\n this._objects.forEach(this._restoreObjectState, this);\n return this;\n },\n\n /**\n * Realises the transform from this group onto the supplied object\n * i.e. it tells you what would happen if the supplied object was in\n * the group, and then the group was destroyed. It mutates the supplied\n * object.\n * @param {fabric.Object} object\n * @return {fabric.Object} transformedObject\n */\n realizeTransform: function(object) {\n var matrix = object.calcTransformMatrix(),\n options = fabric.util.qrDecompose(matrix),\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 return object;\n },\n\n /**\n * Restores original state of a specified object in group\n * @private\n * @param {fabric.Object} object\n * @return {fabric.Group} thisArg\n */\n _restoreObjectState: function(object) {\n this.realizeTransform(object);\n object.setCoords();\n object.hasControls = object.__origHasControls;\n delete object.__origHasControls;\n object.set('active', false);\n delete object.group;\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 /**\n * Saves coordinates of this instance (to be used together with `hasMoved`)\n * @saveCoords\n * @return {fabric.Group} thisArg\n * @chainable\n */\n saveCoords: function() {\n this._originalLeft = this.get('left');\n this._originalTop = this.get('top');\n return this;\n },\n\n /**\n * Checks whether this group was moved (since `saveCoords` was called last)\n * @return {Boolean} true if an object was moved (since fabric.Group#saveCoords was called)\n */\n hasMoved: function() {\n return this._originalLeft !== this.get('left') ||\n this._originalTop !== this.get('top');\n },\n\n /**\n * Sets coordinates of all objects inside group\n * @return {fabric.Group} thisArg\n * @chainable\n */\n setObjectsCoords: function() {\n var ignoreZoom = true, skipAbsolute = true;\n this.forEachObject(function(object) {\n object.setCoords(ignoreZoom, skipAbsolute);\n });\n return this;\n },\n\n /**\n * @private\n */\n _calcBounds: function(onlyWidthHeight) {\n var aX = [],\n aY = [],\n o, prop,\n props = ['tr', 'br', 'bl', 'tl'],\n i = 0, iLen = this._objects.length,\n j, jLen = props.length,\n ignoreZoom = true;\n\n for ( ; i < iLen; ++i) {\n o = this._objects[i];\n o.setCoords(ignoreZoom);\n for (j = 0; j < jLen; j++) {\n prop = props[j];\n aX.push(o.oCoords[prop].x);\n aY.push(o.oCoords[prop].y);\n }\n }\n\n this.set(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 obj = {\n width: (maxXY.x - minXY.x) || 0,\n height: (maxXY.y - minXY.y) || 0\n };\n\n if (!onlyWidthHeight) {\n obj.left = minXY.x || 0;\n obj.top = minXY.y || 0;\n if (this.originX === 'center') {\n obj.left += obj.width / 2;\n }\n if (this.originX === 'right') {\n obj.left += obj.width;\n }\n if (this.originY === 'center') {\n obj.top += obj.height / 2;\n }\n if (this.originY === 'bottom') {\n obj.top += obj.height;\n }\n }\n return obj;\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 markup = this._createBaseSVGMarkup();\n markup.push(\n '\\n'\n );\n\n for (var i = 0, len = this._objects.length; i < len; i++) {\n markup.push('\\t', this._objects[i].toSVG(reviver));\n }\n\n markup.push('\\n');\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns requested property\n * @param {String} prop Property to get\n * @return {*}\n */\n get: function(prop) {\n if (prop in _lockProperties) {\n if (this[prop]) {\n return this[prop];\n }\n else {\n for (var i = 0, len = this._objects.length; i < len; i++) {\n if (this._objects[i][prop]) {\n return true;\n }\n }\n return false;\n }\n }\n else {\n if (prop in this.delegatedProperties) {\n return this._objects[0] && this._objects[0].get(prop);\n }\n return this[prop];\n }\n }\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 fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) {\n var options = fabric.util.object.clone(object, true);\n delete options.objects;\n callback && callback(new fabric.Group(enlivenedObjects, options, true));\n });\n };\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @memberOf fabric.Group\n * @type Boolean\n * @default\n */\n fabric.Group.async = true;\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 * 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 * AlignX value, part of preserveAspectRatio (one of \"none\", \"mid\", \"min\", \"max\")\n * @see http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute\n * This parameter defines how the picture is aligned to its viewport when image element width differs from image width.\n * @type String\n * @default\n */\n alignX: 'none',\n\n /**\n * AlignY value, part of preserveAspectRatio (one of \"none\", \"mid\", \"min\", \"max\")\n * @see http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute\n * This parameter defines how the picture is aligned to its viewport when image element height differs from image height.\n * @type String\n * @default\n */\n alignY: 'none',\n\n /**\n * meetOrSlice value, part of preserveAspectRatio (one of \"meet\", \"slice\").\n * if meet the image is always fully visibile, if slice the viewport is always filled with image.\n * @see http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute\n * @type String\n * @default\n */\n meetOrSlice: 'meet',\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 * 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 * 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 can be used in case we want to scale with some filter above\n * the natural image dimensions\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(\n 'alignX',\n 'alignY',\n 'meetOrSlice'),\n\n /**\n * When `true`, object is cached on an additional canvas.\n * default to false for images\n * since 1.7.0\n * @type Boolean\n * @default\n */\n objectCaching: false,\n\n /**\n * Constructor\n * @param {HTMLImageElement | 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, callback) {\n options || (options = { });\n this.filters = [];\n this.resizeFilters = [];\n this.callSuper('initialize', options);\n this._initElement(element, options, callback);\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 {Function} [callback] Callback is invoked when all filters have been applied and new image is generated\n * @param {Object} [options] Options object\n * @return {fabric.Image} thisArg\n * @chainable\n */\n setElement: function(element, callback, options) {\n\n var _callback, _this;\n\n this._element = element;\n this._originalElement = element;\n this._initConfig(options);\n\n if (this.resizeFilters.length === 0) {\n _callback = callback;\n }\n else {\n _this = this;\n _callback = function() {\n _this.applyFilters(callback, _this.resizeFilters, _this._filteredEl || _this._originalElement, true);\n };\n }\n\n if (this.filters.length !== 0) {\n this.applyFilters(_callback);\n }\n else if (_callback) {\n _callback(this);\n }\n\n return this;\n },\n\n /**\n * Sets crossOrigin value (on an instance and corresponding image element)\n * @return {fabric.Image} thisArg\n * @chainable\n */\n setCrossOrigin: function(value) {\n this.crossOrigin = value;\n this._element.crossOrigin = value;\n\n return this;\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.width,\n height: 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 * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var x = -this.width / 2,\n y = -this.height / 2,\n w = this.width,\n h = this.height;\n\n ctx.save();\n this._setStrokeStyles(ctx);\n\n ctx.beginPath();\n fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);\n ctx.closePath();\n ctx.restore();\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 = [], resizeFilters = [],\n scaleX = 1, scaleY = 1;\n\n this.filters.forEach(function(filterObj) {\n if (filterObj) {\n if (filterObj.type === 'Resize') {\n scaleX *= filterObj.scaleX;\n scaleY *= filterObj.scaleY;\n }\n filters.push(filterObj.toObject());\n }\n });\n\n this.resizeFilters.forEach(function(filterObj) {\n filterObj && resizeFilters.push(filterObj.toObject());\n });\n var object = extend(\n this.callSuper(\n 'toObject',\n ['crossOrigin', 'alignX', 'alignY', 'meetOrSlice'].concat(propertiesToInclude)\n ), {\n src: this.getSrc(),\n filters: filters,\n resizeFilters: resizeFilters,\n });\n\n object.width /= scaleX;\n object.height /= scaleY;\n\n return object;\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 markup = this._createBaseSVGMarkup(), x = -this.width / 2, y = -this.height / 2,\n preserveAspectRatio = 'none', filtered = true;\n if (this.group && this.group.type === 'path-group') {\n x = this.left;\n y = this.top;\n }\n if (this.alignX !== 'none' && this.alignY !== 'none') {\n preserveAspectRatio = 'x' + this.alignX + 'Y' + this.alignY + ' ' + this.meetOrSlice;\n }\n markup.push(\n '\\n',\n ' 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=\"', this.width,\n '\" height=\"', this.height,\n '\" preserveAspectRatio=\"', preserveAspectRatio, '\"',\n '>\\n'\n );\n\n if (this.stroke || this.strokeDashArray) {\n var origFill = this.fill;\n this.fill = null;\n markup.push(\n '\\n'\n );\n this.fill = origFill;\n }\n\n markup.push('\\n');\n\n return reviver ? reviver(markup.join('')) : markup.join('');\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 return fabric.isLikelyNode ? element._src : element.src;\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 * @return {fabric.Image} thisArg\n * @chainable\n */\n setSrc: function(src, callback, options) {\n fabric.util.loadImage(src, function(img) {\n return this.setElement(img, callback, options);\n }, this, options && options.crossOrigin);\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 * Applies filters assigned to this image (from \"filters\" array)\n * @method applyFilters\n * @param {Function} callback Callback is invoked when all filters have been applied and new image is generated\n * @param {Array} filters to be applied\n * @param {fabric.Image} imgElement image to filter ( default to this._element )\n * @param {Boolean} forResizing\n * @return {CanvasElement} canvasEl to be drawn immediately\n * @chainable\n */\n applyFilters: function(callback, filters, imgElement, forResizing) {\n\n filters = filters || this.filters;\n imgElement = imgElement || this._originalElement;\n\n if (!imgElement) {\n return;\n }\n\n var replacement = fabric.util.createImage(),\n retinaScaling = this.canvas ? this.canvas.getRetinaScaling() : fabric.devicePixelRatio,\n minimumScale = this.minimumScaleTrigger / retinaScaling,\n _this = this, scaleX, scaleY;\n\n if (filters.length === 0) {\n this._element = imgElement;\n callback && callback(this);\n return imgElement;\n }\n\n var canvasEl = fabric.util.createCanvasElement();\n canvasEl.width = imgElement.width;\n canvasEl.height = imgElement.height;\n canvasEl.getContext('2d').drawImage(imgElement, 0, 0, imgElement.width, imgElement.height);\n\n filters.forEach(function(filter) {\n if (!filter) {\n return;\n }\n if (forResizing) {\n scaleX = _this.scaleX < minimumScale ? _this.scaleX : 1;\n scaleY = _this.scaleY < minimumScale ? _this.scaleY : 1;\n if (scaleX * retinaScaling < 1) {\n scaleX *= retinaScaling;\n }\n if (scaleY * retinaScaling < 1) {\n scaleY *= retinaScaling;\n }\n }\n else {\n scaleX = filter.scaleX;\n scaleY = filter.scaleY;\n }\n filter.applyTo(canvasEl, scaleX, scaleY);\n if (!forResizing && filter.type === 'Resize') {\n _this.width *= filter.scaleX;\n _this.height *= filter.scaleY;\n }\n });\n\n /** @ignore */\n replacement.width = canvasEl.width;\n replacement.height = canvasEl.height;\n if (fabric.isLikelyNode) {\n replacement.src = canvasEl.toBuffer(undefined, fabric.Image.pngCompression);\n // onload doesn't fire in some node versions, so we invoke callback manually\n _this._element = replacement;\n !forResizing && (_this._filteredEl = replacement);\n callback && callback(_this);\n }\n else {\n replacement.onload = function() {\n _this._element = replacement;\n !forResizing && (_this._filteredEl = replacement);\n callback && callback(_this);\n replacement.onload = canvasEl = null;\n };\n replacement.src = canvasEl.toDataURL('image/png');\n }\n return canvasEl;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} noTransform\n */\n _render: function(ctx, noTransform) {\n var x, y, imageMargins = this._findMargins(), elementToDraw;\n\n x = (noTransform ? this.left : -this.width / 2);\n y = (noTransform ? this.top : -this.height / 2);\n\n if (this.meetOrSlice === 'slice') {\n ctx.beginPath();\n ctx.rect(x, y, this.width, this.height);\n ctx.clip();\n }\n\n if (this.isMoving === false && this.resizeFilters.length && this._needsResize()) {\n this._lastScaleX = this.scaleX;\n this._lastScaleY = this.scaleY;\n elementToDraw = this.applyFilters(null, this.resizeFilters, this._filteredEl || this._originalElement, true);\n }\n else {\n elementToDraw = this._element;\n }\n elementToDraw && ctx.drawImage(elementToDraw,\n x + imageMargins.marginX,\n y + imageMargins.marginY,\n imageMargins.width,\n imageMargins.height\n );\n\n this._stroke(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * @private, needed to check if image needs resize\n */\n _needsResize: function() {\n return (this.scaleX !== this._lastScaleX || this.scaleY !== this._lastScaleY);\n },\n\n /**\n * @private\n */\n _findMargins: function() {\n var width = this.width, height = this.height, scales,\n scale, marginX = 0, marginY = 0;\n\n if (this.alignX !== 'none' || this.alignY !== 'none') {\n scales = [this.width / this._element.width, this.height / this._element.height];\n scale = this.meetOrSlice === 'meet'\n ? Math.min.apply(null, scales) : Math.max.apply(null, scales);\n width = this._element.width * scale;\n height = this._element.height * scale;\n if (this.alignX === 'Mid') {\n marginX = (this.width - width) / 2;\n }\n if (this.alignX === 'Max') {\n marginX = this.width - width;\n }\n if (this.alignY === 'Mid') {\n marginY = (this.height - height) / 2;\n }\n if (this.alignY === 'Max') {\n marginY = this.height - height;\n }\n }\n return {\n width: width,\n height: height,\n marginX: marginX,\n marginY: marginY\n };\n },\n\n /**\n * @private\n */\n _resetWidthHeight: function() {\n var element = this.getElement();\n\n this.set('width', element.width);\n this.set('height', element.height);\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, callback) {\n this.setElement(fabric.util.getById(element), callback, 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 if (this._element && this.crossOrigin) {\n this._element.crossOrigin = this.crossOrigin;\n }\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 * @param {Object} [options] Object with width/height properties\n */\n _setWidthHeight: function(options) {\n this.width = 'width' in options\n ? options.width\n : (this.getElement()\n ? this.getElement().width || 0\n : 0);\n\n this.height = 'height' in options\n ? options.height\n : (this.getElement()\n ? this.getElement().height || 0\n : 0);\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 fabric.util.loadImage(object.src, function(img, error) {\n if (error) {\n callback && callback(null, error);\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.resizeFilters, function(resizeFilters) {\n object.resizeFilters = resizeFilters || [];\n return new fabric.Image(img, object, callback);\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)\n * @param {Object} [imgOptions] Options object\n */\n fabric.Image.fromURL = function(url, callback, imgOptions) {\n fabric.util.loadImage(url, function(img) {\n callback && callback(new fabric.Image(img, imgOptions));\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('x y width height preserveAspectRatio xlink:href crossOrigin'.split(' '));\n\n /**\n * Returns {@link fabric.Image} instance from an SVG element\n * @static\n * @param {SVGElement} element Element to parse\n * @param {Function} callback Callback to execute when fabric.Image object is created\n * @param {Object} [options] Options object\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 preserveAR;\n\n if (parsedAttributes.preserveAspectRatio) {\n preserveAR = fabric.util.parsePreserveAspectRatioAttribute(parsedAttributes.preserveAspectRatio);\n extend(parsedAttributes, preserveAR);\n }\n\n fabric.Image.fromURL(parsedAttributes['xlink:href'], callback,\n extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @type Boolean\n * @default\n */\n fabric.Image.async = true;\n\n /**\n * Indicates compression level used when generating PNG under Node (in applyFilters). Any of 0-9\n * @static\n * @type Number\n * @default\n */\n fabric.Image.pngCompression = 1;\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.getAngle() % 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 this.setAngle(this._getAngleValueForStraighten());\n return this;\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 * @chainable\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 fabric.util.animate({\n startValue: this.get('angle'),\n endValue: this._getAngleValueForStraighten(),\n duration: this.FX_DURATION,\n onChange: function(value) {\n _this.setAngle(value);\n onChange();\n },\n onComplete: function() {\n _this.setCoords();\n onComplete();\n },\n onStart: function() {\n _this.set('active', false);\n }\n });\n\n return this;\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.renderAll();\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 * @chainable\n */\n fxStraightenObject: function (object) {\n object.fxStraighten({\n onChange: this.renderAll.bind(this)\n });\n return this;\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.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 * 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 * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return { type: this.type };\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 extend = fabric.util.object.extend,\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: 200\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\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 * Constructor\n * @memberOf fabric.Image.filters.Brightness.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.brightness=0] Value to brighten the image up (-255..255)\n */\n initialize: function(options) {\n options = options || { };\n this.brightness = options.brightness || 0;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n brightness = this.brightness;\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n data[i] += brightness;\n data[i + 1] += brightness;\n data[i + 2] += brightness;\n }\n\n context.putImageData(imageData, 0, 0);\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 brightness: this.brightness\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.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(canvas.renderAll.bind(canvas));\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(canvas.renderAll.bind(canvas));\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(canvas.renderAll.bind(canvas));\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(canvas.renderAll.bind(canvas));\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 * 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 initialize: function(options) {\n options = options || { };\n\n this.opaque = options.opaque;\n this.matrix = options.matrix || [\n 0, 0, 0,\n 0, 1, 0,\n 0, 0, 0\n ];\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n\n var weights = this.matrix,\n context = canvasEl.getContext('2d'),\n pixels = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n\n side = Math.round(Math.sqrt(weights.length)),\n halfSide = Math.floor(side / 2),\n src = pixels.data,\n sw = pixels.width,\n sh = pixels.height,\n output = context.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\n for (var y = 0; y < sh; y++) {\n for (var 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 (var cy = 0; cy < side; cy++) {\n for (var 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 += src[srcOff] * wt;\n g += src[srcOff + 1] * wt;\n b += src[srcOff + 2] * wt;\n a += src[srcOff + 3] * wt;\n }\n }\n dst[dstOff] = r;\n dst[dstOff + 1] = g;\n dst[dstOff + 2] = b;\n dst[dstOff + 3] = a + alphaFac * (255 - a);\n }\n }\n\n context.putImageData(output, 0, 0);\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 extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * GradientTransparency filter class\n * @class fabric.Image.filters.GradientTransparency\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.GradientTransparency#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.GradientTransparency({\n * threshold: 200\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n // eslint-disable-next-line max-len\n filters.GradientTransparency = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.GradientTransparency.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'GradientTransparency',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.GradientTransparency.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.threshold=100] Threshold value\n */\n initialize: function(options) {\n options = options || { };\n this.threshold = options.threshold || 100;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n threshold = this.threshold,\n total = data.length;\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n data[i + 3] = threshold + 255 * (total - i) / total;\n }\n\n context.putImageData(imageData, 0, 0);\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 threshold: this.threshold\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.GradientTransparency} Instance of fabric.Image.filters.GradientTransparency\n */\n fabric.Image.filters.GradientTransparency.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(canvas.renderAll.bind(canvas));\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 /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Grayscale.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n len = imageData.width * imageData.height * 4,\n index = 0,\n average;\n\n while (index < len) {\n average = (data[index] + data[index + 1] + data[index + 2]) / 3;\n data[index] = average;\n data[index + 1] = average;\n data[index + 2] = average;\n index += 4;\n }\n\n context.putImageData(imageData, 0, 0);\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 = function(object, callback) {\n object = object || { };\n object.type = 'Grayscale';\n return fabric.Image.filters.BaseFilter.fromObject(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 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 /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Invert.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i;\n\n for (i = 0; i < iLen; 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 context.putImageData(imageData, 0, 0);\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 = function(object, callback) {\n object = object || { };\n object.type = 'Invert';\n return fabric.Image.filters.BaseFilter.fromObject(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 filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Mask filter class\n * See http://resources.aleph-1.com/mask/\n * @class fabric.Image.filters.Mask\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Mask#initialize} for constructor definition\n */\n filters.Mask = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Mask.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Mask',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Mask.prototype\n * @param {Object} [options] Options object\n * @param {fabric.Image} [options.mask] Mask image object\n * @param {Number} [options.channel=0] Rgb channel (0, 1, 2 or 3)\n */\n initialize: function(options) {\n options = options || { };\n\n this.mask = options.mask;\n this.channel = [0, 1, 2, 3].indexOf(options.channel) > -1 ? options.channel : 0;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n if (!this.mask) {\n return;\n }\n\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n maskEl = this.mask.getElement(),\n maskCanvasEl = fabric.util.createCanvasElement(),\n channel = this.channel,\n i,\n iLen = imageData.width * imageData.height * 4;\n\n maskCanvasEl.width = canvasEl.width;\n maskCanvasEl.height = canvasEl.height;\n\n maskCanvasEl.getContext('2d').drawImage(maskEl, 0, 0, canvasEl.width, canvasEl.height);\n\n var maskImageData = maskCanvasEl.getContext('2d').getImageData(0, 0, canvasEl.width, canvasEl.height),\n maskData = maskImageData.data;\n\n for (i = 0; i < iLen; i += 4) {\n data[i + 3] = maskData[i + channel];\n }\n\n context.putImageData(imageData, 0, 0);\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 mask: this.mask.toObject(),\n channel: this.channel\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] Callback to invoke when a mask filter instance is created\n */\n fabric.Image.filters.Mask.fromObject = function(object, callback) {\n fabric.util.loadImage(object.mask.src, function(img) {\n object.mask = new fabric.Image(img, object.mask);\n return fabric.Image.filters.BaseFilter.fromObject(object, callback);\n });\n };\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @type Boolean\n * @default\n */\n fabric.Image.filters.Mask.async = true;\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(canvas.renderAll.bind(canvas));\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 * Constructor\n * @memberOf fabric.Image.filters.Noise.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.noise=0] Noise value\n */\n initialize: function(options) {\n options = options || { };\n this.noise = options.noise || 0;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n noise = this.noise, rand;\n\n for (var 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 context.putImageData(imageData, 0, 0);\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 extend = fabric.util.object.extend,\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(canvas.renderAll.bind(canvas));\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 /**\n * Constructor\n * @memberOf fabric.Image.filters.Pixelate.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.blocksize=4] Blocksize for pixelate\n */\n initialize: function(options) {\n options = options || { };\n this.blocksize = options.blocksize || 4;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = imageData.height,\n jLen = imageData.width,\n index, i, j, r, g, b, a;\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 /*\n blocksize: 4\n\n [1,x,x,x,1]\n [x,x,x,x,1]\n [x,x,x,x,1]\n [x,x,x,x,1]\n [1,1,1,1,1]\n */\n\n for (var _i = i, _ilen = i + this.blocksize; _i < _ilen; _i++) {\n for (var _j = j, _jlen = j + this.blocksize; _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 context.putImageData(imageData, 0, 0);\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 blocksize: this.blocksize\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.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.RemoveWhite\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.RemoveWhite#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.RemoveWhite({\n * threshold: 40,\n * distance: 140\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.RemoveWhite = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.RemoveWhite.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'RemoveWhite',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.RemoveWhite.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.threshold=30] Threshold value\n * @param {Number} [options.distance=20] Distance value\n */\n initialize: function(options) {\n options = options || { };\n this.threshold = options.threshold || 30;\n this.distance = options.distance || 20;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n threshold = this.threshold,\n distance = this.distance,\n limit = 255 - threshold,\n abs = Math.abs,\n r, g, b;\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n if (r > limit &&\n g > limit &&\n b > limit &&\n abs(r - g) < distance &&\n abs(r - b) < distance &&\n abs(g - b) < distance\n ) {\n data[i + 3] = 0;\n }\n }\n\n context.putImageData(imageData, 0, 0);\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 threshold: this.threshold,\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.RemoveWhite} Instance of fabric.Image.filters.RemoveWhite\n */\n fabric.Image.filters.RemoveWhite.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 * Sepia filter class\n * @class fabric.Image.filters.Sepia\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.Sepia();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Sepia = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Sepia.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Sepia',\n\n /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Sepia.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i, avg;\n\n for (i = 0; i < iLen; i += 4) {\n avg = 0.3 * data[i] + 0.59 * data[i + 1] + 0.11 * data[i + 2];\n data[i] = avg + 100;\n data[i + 1] = avg + 50;\n data[i + 2] = avg + 255;\n }\n\n context.putImageData(imageData, 0, 0);\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.Sepia} Instance of fabric.Image.filters.Sepia\n */\n fabric.Image.filters.Sepia.fromObject = function(object, callback) {\n object = object || { };\n object.type = 'Sepia';\n return new fabric.Image.filters.BaseFilter.fromObject(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 filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Sepia2 filter class\n * @class fabric.Image.filters.Sepia2\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.Sepia2();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Sepia2 = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Sepia2.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Sepia2',\n\n /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Sepia.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i, r, g, b;\n\n for (i = 0; i < iLen; i += 4) {\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n data[i] = (r * 0.393 + g * 0.769 + b * 0.189 ) / 1.351;\n data[i + 1] = (r * 0.349 + g * 0.686 + b * 0.168 ) / 1.203;\n data[i + 2] = (r * 0.272 + g * 0.534 + b * 0.131 ) / 2.140;\n }\n\n context.putImageData(imageData, 0, 0);\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.Sepia2} Instance of fabric.Image.filters.Sepia2\n */\n fabric.Image.filters.Sepia2.fromObject = function(object, callback) {\n object = object || { };\n object.type = 'Sepia2';\n return new fabric.Image.filters.BaseFilter.fromObject(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 filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Tint filter class\n * Adapted from https://github.com/mezzoblue/PaintbrushJS\n * @class fabric.Image.filters.Tint\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Tint#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example Tint filter with hex color and opacity\n * var filter = new fabric.Image.filters.Tint({\n * color: '#3513B0',\n * opacity: 0.5\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n * @example Tint filter with rgba color\n * var filter = new fabric.Image.filters.Tint({\n * color: 'rgba(53, 21, 176, 0.5)'\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Tint = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Tint.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Tint',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Tint.prototype\n * @param {Object} [options] Options object\n * @param {String} [options.color=#000000] Color to tint the image with\n * @param {Number} [options.opacity] Opacity value that controls the tint effect's transparency (0..1)\n */\n initialize: function(options) {\n options = options || { };\n\n this.color = options.color || '#000000';\n this.opacity = typeof options.opacity !== 'undefined'\n ? options.opacity\n : new fabric.Color(this.color).getAlpha();\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i,\n tintR, tintG, tintB,\n r, g, b, alpha1,\n source;\n\n source = new fabric.Color(this.color).getSource();\n\n tintR = source[0] * this.opacity;\n tintG = source[1] * this.opacity;\n tintB = source[2] * this.opacity;\n\n alpha1 = 1 - this.opacity;\n\n for (i = 0; i < iLen; i += 4) {\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n // alpha compositing\n data[i] = tintR + r * alpha1;\n data[i + 1] = tintG + g * alpha1;\n data[i + 2] = tintB + b * alpha1;\n }\n\n context.putImageData(imageData, 0, 0);\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 opacity: this.opacity\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.Tint} Instance of fabric.Image.filters.Tint\n */\n fabric.Image.filters.Tint.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 * Multiply filter class\n * Adapted from http://www.laurenscorijn.com/articles/colormath-basics\n * @class fabric.Image.filters.Multiply\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @example Multiply filter with hex color\n * var filter = new fabric.Image.filters.Multiply({\n * color: '#F0F'\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n * @example Multiply filter with rgb color\n * var filter = new fabric.Image.filters.Multiply({\n * color: 'rgb(53, 21, 176)'\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Multiply = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Multiply.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Multiply',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Multiply.prototype\n * @param {Object} [options] Options object\n * @param {String} [options.color=#000000] Color to multiply the image pixels with\n */\n initialize: function(options) {\n options = options || { };\n\n this.color = options.color || '#000000';\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i,\n source;\n\n source = new fabric.Color(this.color).getSource();\n\n for (i = 0; i < iLen; i += 4) {\n data[i] *= source[0] / 255;\n data[i + 1] *= source[1] / 255;\n data[i + 2] *= source[2] / 255;\n }\n\n context.putImageData(imageData, 0, 0);\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 });\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.Multiply} Instance of fabric.Image.filters.Multiply\n */\n fabric.Image.filters.Multiply.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.Blend\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @example\n * var filter = new fabric.Image.filters.Blend({\n * color: '#000',\n * mode: 'multiply'\n * });\n *\n * var filter = new fabric.Image.filters.Blend({\n * image: fabricImageObject,\n * mode: 'multiply',\n * alpha: 0.5\n * });\n\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n\n filters.Blend = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Blend.prototype */ {\n type: 'Blend',\n\n initialize: function(options) {\n options = options || {};\n this.color = options.color || '#000';\n this.image = options.image || false;\n this.mode = options.mode || 'multiply';\n this.alpha = options.alpha || 1;\n },\n\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n tr, tg, tb,\n r, g, b,\n _r, _g, _b,\n source,\n isImage = false;\n\n if (this.image) {\n // Blend images\n isImage = true;\n\n var _el = fabric.util.createCanvasElement();\n _el.width = this.image.width;\n _el.height = this.image.height;\n\n var tmpCanvas = new fabric.StaticCanvas(_el);\n tmpCanvas.add(this.image);\n var context2 = tmpCanvas.getContext('2d');\n source = context2.getImageData(0, 0, tmpCanvas.width, tmpCanvas.height).data;\n }\n else {\n // Blend color\n source = new fabric.Color(this.color).getSource();\n\n tr = source[0] * this.alpha;\n tg = source[1] * this.alpha;\n tb = source[2] * this.alpha;\n }\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n if (isImage) {\n tr = source[i] * this.alpha;\n tg = source[i + 1] * this.alpha;\n tb = source[i + 2] * this.alpha;\n }\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] = 1 - (1 - r) * (1 - tr);\n data[i + 1] = 1 - (1 - g) * (1 - tg);\n data[i + 2] = 1 - (1 - b) * (1 - tb);\n break;\n case 'add':\n data[i] = Math.min(255, r + tr);\n data[i + 1] = Math.min(255, g + tg);\n data[i + 2] = Math.min(255, 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 _r = r - tr;\n _g = g - tg;\n _b = b - tb;\n\n data[i] = (_r < 0) ? 0 : _r;\n data[i + 1] = (_g < 0) ? 0 : _g;\n data[i + 2] = (_b < 0) ? 0 : _b;\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 }\n }\n\n context.putImageData(imageData, 0, 0);\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 color: this.color,\n image: this.image,\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.Blend} Instance of fabric.Image.filters.Blend\n */\n fabric.Image.filters.Blend.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 = { }), pow = Math.pow, floor = Math.floor,\n sqrt = Math.sqrt, abs = Math.abs, max = Math.max, 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 * @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: 0,\n\n /**\n * Scale factor for resizing, y axis\n * @param {Number} scaleY\n * @default\n */\n scaleY: 0,\n\n /**\n * LanczosLobes parameter for lanczos filter\n * @param {Number} lanczosLobes\n * @default\n */\n lanczosLobes: 3,\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 applyTo: function(canvasEl, scaleX, scaleY) {\n if (scaleX === 1 && scaleY === 1) {\n return;\n }\n\n this.rcpScaleX = 1 / scaleX;\n this.rcpScaleY = 1 / scaleY;\n\n var oW = canvasEl.width, oH = canvasEl.height,\n dW = round(oW * scaleX), dH = round(oH * scaleY),\n imageData;\n\n if (this.resizeType === 'sliceHack') {\n imageData = this.sliceByTwo(canvasEl, oW, oH, dW, dH);\n }\n if (this.resizeType === 'hermite') {\n imageData = this.hermiteFastResize(canvasEl, oW, oH, dW, dH);\n }\n if (this.resizeType === 'bilinear') {\n imageData = this.bilinearFiltering(canvasEl, oW, oH, dW, dH);\n }\n if (this.resizeType === 'lanczos') {\n imageData = this.lanczosResize(canvasEl, oW, oH, dW, dH);\n }\n canvasEl.width = dW;\n canvasEl.height = dH;\n canvasEl.getContext('2d').putImageData(imageData, 0, 0);\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(canvasEl, oW, oH, dW, dH) {\n var context = canvasEl.getContext('2d'), imageData,\n multW = 0.5, multH = 0.5, signW = 1, signH = 1,\n doneW = false, doneH = false, stepW = oW, stepH = oH,\n tmpCanvas = fabric.util.createCanvasElement(),\n tmpCtx = tmpCanvas.getContext('2d');\n dW = floor(dW);\n dH = floor(dH);\n tmpCanvas.width = max(dW, oW);\n tmpCanvas.height = max(dH, oH);\n\n if (dW > oW) {\n multW = 2;\n signW = -1;\n }\n if (dH > oH) {\n multH = 2;\n signH = -1;\n }\n imageData = context.getImageData(0, 0, oW, oH);\n canvasEl.width = max(dW, oW);\n canvasEl.height = max(dH, oH);\n context.putImageData(imageData, 0, 0);\n\n while (!doneW || !doneH) {\n oW = stepW;\n oH = stepH;\n if (dW * signW < floor(stepW * multW * signW)) {\n stepW = floor(stepW * multW);\n }\n else {\n stepW = dW;\n doneW = true;\n }\n if (dH * signH < floor(stepH * multH * signH)) {\n stepH = floor(stepH * multH);\n }\n else {\n stepH = dH;\n doneH = true;\n }\n imageData = context.getImageData(0, 0, oW, oH);\n tmpCtx.putImageData(imageData, 0, 0);\n context.clearRect(0, 0, stepW, stepH);\n context.drawImage(tmpCanvas, 0, 0, oW, oH, 0, 0, stepW, stepH);\n }\n return context.getImageData(0, 0, 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(canvasEl, oW, oH, dW, dH) {\n\n function lanczosCreate(lobes) {\n return function(x) {\n if (x > lobes) {\n return 0;\n }\n x *= Math.PI;\n if (abs(x) < 1e-16) {\n return 1;\n }\n var xx = x / lobes;\n return sin(x) * sin(xx) / x / xx;\n };\n }\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 context = canvasEl.getContext('2d'),\n srcImg = context.getImageData(0, 0, oW, oH),\n destImg = context.getImageData(0, 0, dW, dH),\n srcData = srcImg.data, destData = destImg.data,\n lanczos = 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(canvasEl, 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, context = canvasEl.getContext('2d'),\n w4 = 4 * (oW - 1), img = context.getImageData(0, 0, oW, oH),\n pixels = img.data, destImage = context.getImageData(0, 0, 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(canvasEl, oW, oH, dW, dH) {\n var ratioW = this.rcpScaleX, ratioH = this.rcpScaleY,\n ratioWHalf = ceil(ratioW / 2),\n ratioHHalf = ceil(ratioH / 2),\n context = canvasEl.getContext('2d'),\n img = context.getImageData(0, 0, oW, oH), data = img.data,\n img2 = context.getImageData(0, 0, 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 extend = fabric.util.object.extend,\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(canvas.renderAll.bind(canvas));\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 /**\n * Constructor\n * @memberOf fabric.Image.filters.ColorMatrix.prototype\n * @param {Object} [options] Options object\n * @param {Array} [options.matrix] Color Matrix to modify the image data with\n */\n initialize: function( options ) {\n options || ( options = {} );\n this.matrix = options.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\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function( canvasEl ) {\n var context = canvasEl.getContext( '2d' ),\n imageData = context.getImageData( 0, 0, canvasEl.width, canvasEl.height ),\n data = imageData.data,\n iLen = data.length,\n i,\n r,\n g,\n b,\n a,\n m = this.matrix;\n\n for ( i = 0; i < iLen; i += 4 ) {\n r = data[ i ];\n g = data[ i + 1 ];\n b = data[ i + 2 ];\n a = data[ i + 3 ];\n\n data[ i ] = r * m[ 0 ] + g * m[ 1 ] + b * m[ 2 ] + a * m[ 3 ] + m[ 4 ];\n data[ i + 1 ] = r * m[ 5 ] + g * m[ 6 ] + b * m[ 7 ] + a * m[ 8 ] + m[ 9 ];\n data[ i + 2 ] = r * m[ 10 ] + g * m[ 11 ] + b * m[ 12 ] + a * m[ 13 ] + m[ 14 ];\n data[ i + 3 ] = r * m[ 15 ] + g * m[ 16 ] + b * m[ 17 ] + a * m[ 18 ] + m[ 19 ];\n }\n\n context.putImageData( imageData, 0, 0 );\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 type: this.type,\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] 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 extend = fabric.util.object.extend,\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: 40\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\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 /**\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 (-255...255)\n */\n initialize: function(options) {\n options = options || { };\n this.contrast = options.contrast || 0;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n contrastF = 259 * (this.contrast + 255) / (255 * (259 - this.contrast));\n\n for (var i = 0, len = data.length; 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 context.putImageData(imageData, 0, 0);\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 contrast: this.contrast\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.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 extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Saturate filter class\n * @class fabric.Image.filters.Saturate\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Saturate#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Saturate({\n * saturate: 100\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Saturate = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Saturate.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Saturate',\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 (-100...100)\n */\n initialize: function(options) {\n options = options || { };\n this.saturate = options.saturate || 0;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n max, adjust = -this.saturate * 0.01;\n\n for (var i = 0, len = data.length; 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 context.putImageData(imageData, 0, 0);\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 saturate: this.saturate\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.Saturate} Instance of fabric.Image.filters.Saturate\n */\n fabric.Image.filters.Saturate.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 toFixed = fabric.util.toFixed,\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n MIN_TEXT_WIDTH = 2;\n\n if (fabric.Text) {\n fabric.warn('fabric.Text is already defined');\n return;\n }\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 Object\n * @private\n */\n _dimensionAffectingProps: [\n 'fontSize',\n 'fontWeight',\n 'fontFamily',\n 'fontStyle',\n 'lineHeight',\n 'text',\n 'charSpacing',\n 'textAlign'\n ],\n\n /**\n * @private\n */\n _reNewline: /\\r?\\n/,\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 _reSpacesAndTabs: /[ \\t\\r]+/g,\n\n /**\n * Retrieves object's fontSize\n * @method getFontSize\n * @memberOf fabric.Text.prototype\n * @return {String} Font size (in pixels)\n */\n\n /**\n * Sets object's fontSize\n * Does not update the object .width and .height,\n * call ._initDimensions() to update the values.\n * @method setFontSize\n * @memberOf fabric.Text.prototype\n * @param {Number} fontSize Font size (in pixels)\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's fontWeight\n * @method getFontWeight\n * @memberOf fabric.Text.prototype\n * @return {(String|Number)} Font weight\n */\n\n /**\n * Sets object's fontWeight\n * Does not update the object .width and .height,\n * call ._initDimensions() to update the values.\n * @method setFontWeight\n * @memberOf fabric.Text.prototype\n * @param {(Number|String)} fontWeight Font weight\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's fontFamily\n * @method getFontFamily\n * @memberOf fabric.Text.prototype\n * @return {String} Font family\n */\n\n /**\n * Sets object's fontFamily\n * Does not update the object .width and .height,\n * call ._initDimensions() to update the values.\n * @method setFontFamily\n * @memberOf fabric.Text.prototype\n * @param {String} fontFamily Font family\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's text\n * @method getText\n * @memberOf fabric.Text.prototype\n * @return {String} text\n */\n\n /**\n * Sets object's text\n * Does not update the object .width and .height,\n * call ._initDimensions() to update the values.\n * @method setText\n * @memberOf fabric.Text.prototype\n * @param {String} text Text\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's textDecoration\n * @method getTextDecoration\n * @memberOf fabric.Text.prototype\n * @return {String} Text decoration\n */\n\n /**\n * Sets object's textDecoration\n * @method setTextDecoration\n * @memberOf fabric.Text.prototype\n * @param {String} textDecoration Text decoration\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's fontStyle\n * @method getFontStyle\n * @memberOf fabric.Text.prototype\n * @return {String} Font style\n */\n\n /**\n * Sets object's fontStyle\n * Does not update the object .width and .height,\n * call ._initDimensions() to update the values.\n * @method setFontStyle\n * @memberOf fabric.Text.prototype\n * @param {String} fontStyle Font style\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's lineHeight\n * @method getLineHeight\n * @memberOf fabric.Text.prototype\n * @return {Number} Line height\n */\n\n /**\n * Sets object's lineHeight\n * @method setLineHeight\n * @memberOf fabric.Text.prototype\n * @param {Number} lineHeight Line height\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's textAlign\n * @method getTextAlign\n * @memberOf fabric.Text.prototype\n * @return {String} Text alignment\n */\n\n /**\n * Sets object's textAlign\n * @method setTextAlign\n * @memberOf fabric.Text.prototype\n * @param {String} textAlign Text alignment\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's textBackgroundColor\n * @method getTextBackgroundColor\n * @memberOf fabric.Text.prototype\n * @return {String} Text background color\n */\n\n /**\n * Sets object's textBackgroundColor\n * @method setTextBackgroundColor\n * @memberOf fabric.Text.prototype\n * @param {String} textBackgroundColor Text background color\n * @return {fabric.Text}\n * @chainable\n */\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 Possible values: \"\", \"underline\", \"overline\" or \"line-through\".\n * @type String\n * @default\n */\n textDecoration: '',\n\n /**\n * Text alignment. Possible values: \"left\", \"center\", \"right\" or \"justify\".\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: '',\n\n /**\n * Line height\n * @type Number\n * @default\n */\n lineHeight: 1.16,\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(\n 'fontFamily',\n 'fontWeight',\n 'fontSize',\n 'text',\n 'textDecoration',\n 'textAlign',\n 'fontStyle',\n 'lineHeight',\n 'textBackgroundColor',\n 'charSpacing'),\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(\n 'fontFamily',\n 'fontWeight',\n 'fontSize',\n 'text',\n 'textDecoration',\n 'textAlign',\n 'fontStyle',\n 'lineHeight',\n 'textBackgroundColor',\n 'charSpacing',\n 'styles'),\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 * @private\n */\n _fontSizeFraction: 0.25,\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 * 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 options = options || { };\n this.text = text;\n this.__skipDimension = true;\n this.callSuper('initialize', options);\n this.__skipDimension = false;\n this._initDimensions();\n this.setCoords();\n this.setupState({ propertySet: '_dimensionAffectingProps' });\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 * @param {CanvasRenderingContext2D} [ctx] Context to render on\n * @private\n */\n _initDimensions: function(ctx) {\n if (this.__skipDimension) {\n return;\n }\n if (!ctx) {\n ctx = fabric.util.createCanvasElement().getContext('2d');\n this._setTextStyles(ctx);\n }\n this._textLines = this._splitTextIntoLines();\n this._clearCache();\n this.width = this._getTextWidth(ctx) || this.cursorWidth || MIN_TEXT_WIDTH;\n this.height = this._getTextHeight(ctx);\n this.setCoords();\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 this._setTextStyles(ctx);\n if (this.group && this.group.type === 'path-group') {\n ctx.translate(this.left, this.top);\n }\n this._renderTextLinesBackground(ctx);\n this._renderText(ctx);\n this._renderTextDecoration(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderText: function(ctx) {\n this._renderTextFill(ctx);\n this._renderTextStroke(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _setTextStyles: function(ctx) {\n ctx.textBaseline = 'alphabetic';\n ctx.font = this._getFontDeclaration();\n },\n\n /**\n * @private\n * @return {Number} Height of fabric.Text object\n */\n _getTextHeight: function() {\n return this._getHeightOfSingleLine() + (this._textLines.length - 1) * this._getHeightOfLine();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @return {Number} Maximum width of fabric.Text object\n */\n _getTextWidth: function(ctx) {\n var maxWidth = this._getLineWidth(ctx, 0);\n\n for (var i = 1, len = this._textLines.length; i < len; i++) {\n var currentLineWidth = this._getLineWidth(ctx, 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} chars Chars to render\n * @param {Number} left Left position of text\n * @param {Number} top Top position of text\n */\n _renderChars: function(method, ctx, chars, left, top) {\n // remove Text word from method var\n var shortM = method.slice(0, -4), _char, width;\n if (this[shortM].toLive) {\n var offsetX = -this.width / 2 + this[shortM].offsetX || 0,\n offsetY = -this.height / 2 + this[shortM].offsetY || 0;\n ctx.save();\n ctx.translate(offsetX, offsetY);\n left -= offsetX;\n top -= offsetY;\n }\n if (this.charSpacing !== 0) {\n var additionalSpace = this._getWidthOfCharSpacing();\n chars = chars.split('');\n for (var i = 0, len = chars.length; i < len; i++) {\n _char = chars[i];\n width = ctx.measureText(_char).width + additionalSpace;\n ctx[method](_char, left, top);\n left += width > 0 ? width : 0;\n }\n }\n else {\n ctx[method](chars, left, top);\n }\n this[shortM].toLive && ctx.restore();\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 // lift the line by quarter of fontSize\n top -= this.fontSize * this._fontSizeFraction;\n\n // short-circuit\n var lineWidth = this._getLineWidth(ctx, lineIndex);\n if (this.textAlign !== 'justify' || this.width < lineWidth) {\n this._renderChars(method, ctx, line, left, top, lineIndex);\n return;\n }\n\n // stretch the line\n var words = line.split(/\\s+/),\n charOffset = 0,\n wordsWidth = this._getWidthOfWords(ctx, words.join(' '), lineIndex, 0),\n widthDiff = this.width - wordsWidth,\n numSpaces = words.length - 1,\n spaceWidth = numSpaces > 0 ? widthDiff / numSpaces : 0,\n leftOffset = 0, word;\n\n for (var i = 0, len = words.length; i < len; i++) {\n while (line[charOffset] === ' ' && charOffset < line.length) {\n charOffset++;\n }\n word = words[i];\n this._renderChars(method, ctx, word, left + leftOffset, top, lineIndex, charOffset);\n leftOffset += this._getWidthOfWords(ctx, word, lineIndex, charOffset) + spaceWidth;\n charOffset += word.length;\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} word\n */\n _getWidthOfWords: function (ctx, word) {\n var width = ctx.measureText(word).width, charCount, additionalSpace;\n if (this.charSpacing !== 0) {\n charCount = word.split('').length;\n additionalSpace = charCount * this._getWidthOfCharSpacing();\n width += additionalSpace;\n }\n return width > 0 ? width : 0;\n },\n\n /**\n * @private\n * @return {Number} Left offset\n */\n _getLeftOffset: function() {\n return -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 * Returns true because text has no style\n */\n isEmptyStyles: function() {\n return true;\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\n var lineHeights = 0, left = this._getLeftOffset(), top = this._getTopOffset();\n\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n var heightOfLine = this._getHeightOfLine(ctx, i),\n maxHeight = heightOfLine / this.lineHeight,\n lineWidth = this._getLineWidth(ctx, i),\n leftOffset = this._getLineLeftOffset(lineWidth);\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 },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextFill: function(ctx) {\n if (!this.fill && this.isEmptyStyles()) {\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 * @return {Number} height of line\n */\n _getHeightOfLine: function() {\n return this._getHeightOfSingleLine() * this.lineHeight;\n },\n\n /**\n * @private\n * @return {Number} height of line without lineHeight\n */\n _getHeightOfSingleLine: function() {\n return this.fontSize * this._fontSizeMult;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextLinesBackground: function(ctx) {\n if (!this.textBackgroundColor) {\n return;\n }\n var lineTopOffset = 0, heightOfLine,\n lineWidth, lineLeftOffset, originalFill = ctx.fillStyle;\n\n ctx.fillStyle = this.textBackgroundColor;\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n heightOfLine = this._getHeightOfLine(ctx, i);\n lineWidth = this._getLineWidth(ctx, i);\n if (lineWidth > 0) {\n lineLeftOffset = this._getLineLeftOffset(lineWidth);\n ctx.fillRect(\n this._getLeftOffset() + lineLeftOffset,\n this._getTopOffset() + lineTopOffset,\n lineWidth,\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 {Number} lineWidth Width of text line\n * @return {Number} Line left offset\n */\n _getLineLeftOffset: function(lineWidth) {\n if (this.textAlign === 'center') {\n return (this.width - lineWidth) / 2;\n }\n if (this.textAlign === 'right') {\n return this.width - lineWidth;\n }\n return 0;\n },\n\n /**\n * @private\n */\n _clearCache: function() {\n this.__lineWidths = [];\n this.__lineHeights = [];\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.saveState({ propertySet: '_dimensionAffectingProps' });\n this.dirty = true;\n }\n return shouldClear;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex line number\n * @return {Number} Line width\n */\n _getLineWidth: function(ctx, lineIndex) {\n if (this.__lineWidths[lineIndex]) {\n return this.__lineWidths[lineIndex] === -1 ? this.width : this.__lineWidths[lineIndex];\n }\n\n var width, wordCount, line = this._textLines[lineIndex];\n\n if (line === '') {\n width = 0;\n }\n else {\n width = this._measureLine(ctx, lineIndex);\n }\n this.__lineWidths[lineIndex] = width;\n\n if (width && this.textAlign === 'justify') {\n wordCount = line.split(/\\s+/);\n if (wordCount.length > 1) {\n this.__lineWidths[lineIndex] = -1;\n }\n }\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 * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex line number\n * @return {Number} Line width\n */\n _measureLine: function(ctx, lineIndex) {\n var line = this._textLines[lineIndex],\n width = ctx.measureText(line).width,\n additionalSpace = 0, charCount, finalWidth;\n if (this.charSpacing !== 0) {\n charCount = line.split('').length;\n additionalSpace = (charCount - 1) * this._getWidthOfCharSpacing();\n }\n finalWidth = width + additionalSpace;\n return finalWidth > 0 ? finalWidth : 0;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextDecoration: function(ctx) {\n if (!this.textDecoration) {\n return;\n }\n var halfOfVerticalBox = this.height / 2,\n _this = this, offsets = [];\n\n /** @ignore */\n function renderLinesAtOffset(offsets) {\n var i, lineHeight = 0, len, j, oLen, lineWidth,\n lineLeftOffset, heightOfLine;\n\n for (i = 0, len = _this._textLines.length; i < len; i++) {\n\n lineWidth = _this._getLineWidth(ctx, i);\n lineLeftOffset = _this._getLineLeftOffset(lineWidth);\n heightOfLine = _this._getHeightOfLine(ctx, i);\n\n for (j = 0, oLen = offsets.length; j < oLen; j++) {\n ctx.fillRect(\n _this._getLeftOffset() + lineLeftOffset,\n lineHeight + (_this._fontSizeMult - 1 + offsets[j] ) * _this.fontSize - halfOfVerticalBox,\n lineWidth,\n _this.fontSize / 15);\n }\n lineHeight += heightOfLine;\n }\n }\n\n if (this.textDecoration.indexOf('underline') > -1) {\n offsets.push(0.85); // 1 - 3/16\n }\n if (this.textDecoration.indexOf('line-through') > -1) {\n offsets.push(0.43);\n }\n if (this.textDecoration.indexOf('overline') > -1) {\n offsets.push(-0.12);\n }\n if (offsets.length > 0) {\n renderLinesAtOffset(offsets);\n }\n },\n\n /**\n * return font declaration string for canvas context\n * @returns {String} font declaration formatted for canvas context.\n */\n _getFontDeclaration: function() {\n return [\n // node-canvas needs \"weight style\", while browsers need \"style weight\"\n (fabric.isLikelyNode ? this.fontWeight : this.fontStyle),\n (fabric.isLikelyNode ? this.fontStyle : this.fontWeight),\n this.fontSize + 'px',\n (fabric.isLikelyNode ? ('\"' + this.fontFamily + '\"') : this.fontFamily)\n ].join(' ');\n },\n\n /**\n * Renders text instance on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} noTransform\n */\n render: function(ctx, noTransform) {\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._setTextStyles(ctx);\n this._initDimensions(ctx);\n }\n this.callSuper('render', ctx, noTransform);\n },\n\n /**\n * Returns the text as an array of lines.\n * @returns {Array} Lines in the text\n */\n _splitTextIntoLines: function() {\n return this.text.split(this._reNewline);\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 additionalProperties = [\n 'text',\n 'fontSize',\n 'fontWeight',\n 'fontFamily',\n 'fontStyle',\n 'lineHeight',\n 'textDecoration',\n 'textAlign',\n 'textBackgroundColor',\n 'charSpacing'\n ].concat(propertiesToInclude);\n return this.callSuper('toObject', additionalProperties);\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 if (!this.ctx) {\n this.ctx = fabric.util.createCanvasElement().getContext('2d');\n }\n var markup = this._createBaseSVGMarkup(),\n offsets = this._getSVGLeftTopOffsets(this.ctx),\n textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft);\n this._wrapSVGTextAndBg(markup, textAndBg);\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n\n /**\n * @private\n */\n _getSVGLeftTopOffsets: function(ctx) {\n var lineTop = this._getHeightOfLine(ctx, 0),\n textLeft = -this.width / 2,\n textTop = 0;\n\n return {\n textLeft: textLeft + (this.group && this.group.type === 'path-group' ? this.left : 0),\n textTop: textTop + (this.group && this.group.type === 'path-group' ? -this.top : 0),\n lineTop: lineTop\n };\n },\n\n /**\n * @private\n */\n _wrapSVGTextAndBg: function(markup, textAndBg) {\n var noShadow = true, filter = this.getSvgFilter(),\n style = filter === '' ? '' : ' style=\"' + filter + '\"';\n\n markup.push(\n '\\t\\n',\n textAndBg.textBgRects.join(''),\n '\\t\\t\\n',\n textAndBg.textSpans.join(''),\n '\\t\\t\\n',\n '\\t\\n'\n );\n },\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 * @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 = 0;\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 if (this.textBackgroundColor) {\n this._setSVGTextLineBg(textBgRects, i, textLeftOffset, textTopOffset, height);\n }\n this._setSVGTextLineText(i, textSpans, height, textLeftOffset, textTopOffset, textBgRects);\n height += this._getHeightOfLine(this.ctx, i);\n }\n\n return {\n textSpans: textSpans,\n textBgRects: textBgRects\n };\n },\n\n _setSVGTextLineText: function(i, textSpans, height, textLeftOffset, textTopOffset) {\n var yPos = this.fontSize * (this._fontSizeMult - this._fontSizeFraction)\n - textTopOffset + height - this.height / 2;\n if (this.textAlign === 'justify') {\n // i call from here to do not intefere with IText\n this._setSVGTextLineJustifed(i, textSpans, yPos, textLeftOffset);\n return;\n }\n textSpans.push(\n '\\t\\t\\t elements since setting opacity\n // on containing one doesn't work in Illustrator\n this._getFillAttributes(this.fill), '>',\n fabric.util.string.escapeXml(this._textLines[i]),\n '\\n'\n );\n },\n\n _setSVGTextLineJustifed: function(i, textSpans, yPos, textLeftOffset) {\n var ctx = fabric.util.createCanvasElement().getContext('2d');\n\n this._setTextStyles(ctx);\n\n var line = this._textLines[i],\n words = line.split(/\\s+/),\n wordsWidth = this._getWidthOfWords(ctx, words.join('')),\n widthDiff = this.width - wordsWidth,\n numSpaces = words.length - 1,\n spaceWidth = numSpaces > 0 ? widthDiff / numSpaces : 0,\n word, attributes = this._getFillAttributes(this.fill),\n len;\n\n textLeftOffset += this._getLineLeftOffset(this._getLineWidth(ctx, i));\n\n for (i = 0, len = words.length; i < len; i++) {\n word = words[i];\n textSpans.push(\n '\\t\\t\\t elements since setting opacity\n // on containing one doesn't work in Illustrator\n attributes, '>',\n fabric.util.string.escapeXml(word),\n '\\n'\n );\n textLeftOffset += this._getWidthOfWords(ctx, word) + spaceWidth;\n }\n },\n\n _setSVGTextLineBg: function(textBgRects, i, textLeftOffset, textTopOffset, height) {\n textBgRects.push(\n '\\t\\t\\n');\n },\n\n _setSVGBg: function(textBgRects) {\n if (this.backgroundColor) {\n textBgRects.push(\n '\\t\\t\\n');\n }\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 /* _TO_SVG_END_ */\n\n /**\n * Sets specified property to a specified value\n * @param {String} key\n * @param {*} value\n * @return {fabric.Text} thisArg\n * @chainable\n */\n _set: function(key, value) {\n this.callSuper('_set', key, value);\n\n if (this._dimensionAffectingProps.indexOf(key) > -1) {\n this._initDimensions();\n this.setCoords();\n }\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 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 {Object} [options] Options object\n * @return {fabric.Text} Instance of fabric.Text\n */\n fabric.Text.fromElement = function(element, options) {\n if (!element) {\n return null;\n }\n\n var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES);\n options = fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes);\n\n options.top = options.top || 0;\n options.left = options.left || 0;\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 if (!options.originX) {\n options.originX = 'left';\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\n var text = new fabric.Text(textContent, options),\n textHeightScaleFactor = text.getHeight() / text.height,\n lineHeightDiff = (text.height + text.strokeWidth) * text.lineHeight - text.height,\n scaledDiff = lineHeightDiff * textHeightScaleFactor,\n textHeight = text.getHeight() + 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 top/left properties in Fabric correspond to center point of text bounding box\n */\n if (text.originX === 'left') {\n offX = text.getWidth() / 2;\n }\n if (text.originX === 'right') {\n offX = -text.getWidth() / 2;\n }\n text.set({\n left: text.getLeft() + offX,\n top: text.getTop() - textHeight / 2 + text.fontSize * (0.18 + text._fontSizeFraction) / text.lineHeight /* 0.3 is the old lineHeight */\n });\n\n return 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 Object to create an instance from\n * @param {Function} [callback] Callback to invoke when an fabric.Text instance is created\n * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Text} Instance of fabric.Text\n */\n fabric.Text.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Text', object, callback, forceAsync, 'text');\n };\n\n fabric.util.createAccessors(fabric.Text);\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n var clone = fabric.util.object.clone;\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 default cursor (when not overwritten by character style)\n * @type String\n * @default\n */\n cursorColor: '#333',\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 * Object containing character styles\n * (where top-level properties corresponds to line number and 2nd-level properties -- to char number in a line)\n * @type Object\n * @default\n */\n styles: null,\n\n /**\n * Indicates whether internal text char widths can be cached\n * @type Boolean\n * @default\n */\n caching: true,\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 * 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.styles = options ? (options.styles || { }) : { };\n this.callSuper('initialize', text, options);\n this.initBehavior();\n },\n\n /**\n * @private\n */\n _clearCache: function() {\n this.callSuper('_clearCache');\n this.__widthOfSpace = [];\n },\n\n /**\n * Returns true if object has no styling\n */\n isEmptyStyles: function() {\n if (!this.styles) {\n return true;\n }\n var obj = this.styles;\n\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 * 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 * Gets style of a current selection/cursor (at the start position)\n * @param {Number} [startIndex] Start index to get styles at\n * @param {Number} [endIndex] End index to get styles at\n * @return {Object} styles Style object at a specified (or current) index\n */\n getSelectionStyles: function(startIndex, endIndex) {\n\n if (arguments.length === 2) {\n var styles = [];\n for (var i = startIndex; i < endIndex; i++) {\n styles.push(this.getSelectionStyles(i));\n }\n return styles;\n }\n\n var loc = this.get2DCursorLocation(startIndex),\n style = this._getStyleDeclaration(loc.lineIndex, loc.charIndex);\n\n return style || {};\n },\n\n /**\n * Sets style of a current selection\n * @param {Object} [styles] Styles object\n * @return {fabric.IText} thisArg\n * @chainable\n */\n setSelectionStyles: function(styles) {\n if (this.selectionStart === this.selectionEnd) {\n this._extendStyles(this.selectionStart, styles);\n }\n else {\n for (var i = this.selectionStart; i < this.selectionEnd; i++) {\n this._extendStyles(i, styles);\n }\n }\n /* not included in _extendStyles to avoid clearing cache more than once */\n this._forceClearCache = true;\n return this;\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 * 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 * @param {CanvasRenderingContext2D} [ctx] Context to render on\n * @private\n */\n _initDimensions: function(ctx) {\n if (!ctx) {\n this.clearContextTop();\n }\n this.callSuper('_initDimensions', ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} noTransform\n */\n render: function(ctx, noTransform) {\n this.clearContextTop();\n this.callSuper('render', ctx, noTransform);\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 this.ctx = ctx;\n },\n\n /**\n * Prepare and clean the contextTop\n */\n clearContextTop: function() {\n if (!this.active || !this.isEditing) {\n return;\n }\n if (this.canvas && this.canvas.contextTop) {\n var ctx = this.canvas.contextTop;\n ctx.save();\n ctx.transform.apply(ctx, this.canvas.viewportTransform);\n this.transform(ctx);\n this.transformMatrix && ctx.transform.apply(ctx, this.transformMatrix);\n this._clearTextArea(ctx);\n ctx.restore();\n }\n },\n\n /**\n * Renders cursor or selection (depending on what exists)\n */\n renderCursorOrSelection: function() {\n if (!this.active || !this.isEditing) {\n return;\n }\n var chars = this.text.split(''),\n boundaries, ctx;\n if (this.canvas && this.canvas.contextTop) {\n ctx = this.canvas.contextTop;\n ctx.save();\n ctx.transform.apply(ctx, this.canvas.viewportTransform);\n this.transform(ctx);\n this.transformMatrix && ctx.transform.apply(ctx, this.transformMatrix);\n this._clearTextArea(ctx);\n }\n else {\n ctx = this.ctx;\n ctx.save();\n }\n if (this.selectionStart === this.selectionEnd) {\n boundaries = this._getCursorBoundaries(chars, 'cursor');\n this.renderCursor(boundaries, ctx);\n }\n else {\n boundaries = this._getCursorBoundaries(chars, 'selection');\n this.renderSelection(chars, 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 * 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 */\n get2DCursorLocation: function(selectionStart) {\n if (typeof selectionStart === 'undefined') {\n selectionStart = this.selectionStart;\n }\n var len = this._textLines.length;\n for (var i = 0; i < len; i++) {\n if (selectionStart <= this._textLines[i].length) {\n return {\n lineIndex: i,\n charIndex: selectionStart\n };\n }\n selectionStart -= this._textLines[i].length + 1;\n }\n return {\n lineIndex: i - 1,\n charIndex: this._textLines[i - 1].length < selectionStart ? this._textLines[i - 1].length : selectionStart\n };\n },\n\n /**\n * Returns complete style of char at the current cursor\n * @param {Number} lineIndex Line index\n * @param {Number} charIndex Char index\n * @return {Object} Character style\n */\n getCurrentCharStyle: function(lineIndex, charIndex) {\n var style = this._getStyleDeclaration(lineIndex, charIndex === 0 ? 0 : charIndex - 1);\n\n return {\n fontSize: style && style.fontSize || this.fontSize,\n fill: style && style.fill || this.fill,\n textBackgroundColor: style && style.textBackgroundColor || this.textBackgroundColor,\n textDecoration: style && style.textDecoration || this.textDecoration,\n fontFamily: style && style.fontFamily || this.fontFamily,\n fontWeight: style && style.fontWeight || this.fontWeight,\n fontStyle: style && style.fontStyle || this.fontStyle,\n stroke: style && style.stroke || this.stroke,\n strokeWidth: style && style.strokeWidth || this.strokeWidth\n };\n },\n\n /**\n * Returns fontSize of char at the current cursor\n * @param {Number} lineIndex Line index\n * @param {Number} charIndex Char index\n * @return {Number} Character font size\n */\n getCurrentCharFontSize: function(lineIndex, charIndex) {\n var style = this._getStyleDeclaration(lineIndex, charIndex === 0 ? 0 : charIndex - 1);\n return style && style.fontSize ? style.fontSize : this.fontSize;\n },\n\n /**\n * Returns color (fill) of char at the current cursor\n * @param {Number} lineIndex Line index\n * @param {Number} charIndex Char index\n * @return {String} Character color (fill)\n */\n getCurrentCharColor: function(lineIndex, charIndex) {\n var style = this._getStyleDeclaration(lineIndex, charIndex === 0 ? 0 : charIndex - 1);\n return style && style.fill ? style.fill : this.cursorColor;\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(chars, typeOfBoundaries) {\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 var left = Math.round(this._getLeftOffset()),\n top = this._getTopOffset(),\n\n offsets = this._getCursorBoundariesOffsets(\n chars, typeOfBoundaries);\n\n return {\n left: left,\n top: top,\n leftOffset: offsets.left + offsets.lineLeft,\n topOffset: offsets.top\n };\n },\n\n /**\n * @private\n */\n _getCursorBoundariesOffsets: function(chars, typeOfBoundaries) {\n if (this.cursorOffsetCache && 'top' in this.cursorOffsetCache) {\n return this.cursorOffsetCache;\n }\n var lineLeftOffset = 0,\n lineIndex = 0,\n charIndex = 0,\n topOffset = 0,\n leftOffset = 0,\n boundaries;\n\n for (var i = 0; i < this.selectionStart; i++) {\n if (chars[i] === '\\n') {\n leftOffset = 0;\n topOffset += this._getHeightOfLine(this.ctx, lineIndex);\n\n lineIndex++;\n charIndex = 0;\n }\n else {\n leftOffset += this._getWidthOfChar(this.ctx, chars[i], lineIndex, charIndex);\n charIndex++;\n }\n\n lineLeftOffset = this._getLineLeftOffset(this._getLineWidth(this.ctx, lineIndex));\n }\n if (typeOfBoundaries === 'cursor') {\n topOffset += (1 - this._fontSizeFraction) * this._getHeightOfLine(this.ctx, lineIndex) / this.lineHeight\n - this.getCurrentCharFontSize(lineIndex, charIndex) * (1 - this._fontSizeFraction);\n }\n if (this.charSpacing !== 0 && charIndex === this._textLines[lineIndex].length) {\n leftOffset -= this._getWidthOfCharSpacing();\n }\n boundaries = {\n top: topOffset,\n left: leftOffset > 0 ? leftOffset : 0,\n lineLeft: lineLeftOffset\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\n var cursorLocation = this.get2DCursorLocation(),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex,\n charHeight = this.getCurrentCharFontSize(lineIndex, charIndex),\n leftOffset = boundaries.leftOffset,\n multiplier = this.scaleX * this.canvas.getZoom(),\n cursorWidth = this.cursorWidth / multiplier;\n\n ctx.fillStyle = this.getCurrentCharColor(lineIndex, charIndex);\n ctx.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity;\n\n ctx.fillRect(\n boundaries.left + leftOffset - cursorWidth / 2,\n boundaries.top + boundaries.topOffset,\n cursorWidth,\n charHeight);\n },\n\n /**\n * Renders text selection\n * @param {Array} chars Array of characters\n * @param {Object} boundaries Object with left/top/leftOffset/topOffset\n * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n */\n renderSelection: function(chars, boundaries, ctx) {\n\n ctx.fillStyle = this.selectionColor;\n\n var start = this.get2DCursorLocation(this.selectionStart),\n end = this.get2DCursorLocation(this.selectionEnd),\n startLine = start.lineIndex,\n endLine = end.lineIndex;\n for (var i = startLine; i <= endLine; i++) {\n var lineOffset = this._getLineLeftOffset(this._getLineWidth(ctx, i)) || 0,\n lineHeight = this._getHeightOfLine(this.ctx, i),\n realLineHeight = 0, boxWidth = 0, line = this._textLines[i];\n\n if (i === startLine) {\n for (var j = 0, len = line.length; j < len; j++) {\n if (j >= start.charIndex && (i !== endLine || j < end.charIndex)) {\n boxWidth += this._getWidthOfChar(ctx, line[j], i, j);\n }\n if (j < start.charIndex) {\n lineOffset += this._getWidthOfChar(ctx, line[j], i, j);\n }\n }\n if (j === line.length) {\n boxWidth -= this._getWidthOfCharSpacing();\n }\n }\n else if (i > startLine && i < endLine) {\n boxWidth += this._getLineWidth(ctx, i) || 5;\n }\n else if (i === endLine) {\n for (var j2 = 0, j2len = end.charIndex; j2 < j2len; j2++) {\n boxWidth += this._getWidthOfChar(ctx, line[j2], i, j2);\n }\n if (end.charIndex === line.length) {\n boxWidth -= this._getWidthOfCharSpacing();\n }\n }\n realLineHeight = lineHeight;\n if (this.lineHeight < 1 || (i === endLine && this.lineHeight > 1)) {\n lineHeight /= this.lineHeight;\n }\n ctx.fillRect(\n boundaries.left + lineOffset,\n boundaries.top + boundaries.topOffset,\n boxWidth > 0 ? boxWidth : 0,\n lineHeight);\n\n boundaries.topOffset += realLineHeight;\n }\n },\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} line Content of the line\n * @param {Number} left\n * @param {Number} top\n * @param {Number} lineIndex\n * @param {Number} charOffset\n */\n _renderChars: function(method, ctx, line, left, top, lineIndex, charOffset) {\n\n if (this.isEmptyStyles()) {\n return this._renderCharsFast(method, ctx, line, left, top);\n }\n\n charOffset = charOffset || 0;\n\n // set proper line offset\n var lineHeight = this._getHeightOfLine(ctx, lineIndex),\n prevStyle,\n thisStyle,\n charsToRender = '';\n\n ctx.save();\n top -= lineHeight / this.lineHeight * this._fontSizeFraction;\n for (var i = charOffset, len = line.length + charOffset; i <= len; i++) {\n prevStyle = prevStyle || this.getCurrentCharStyle(lineIndex, i);\n thisStyle = this.getCurrentCharStyle(lineIndex, i + 1);\n\n if (this._hasStyleChanged(prevStyle, thisStyle) || i === len) {\n this._renderChar(method, ctx, lineIndex, i - 1, charsToRender, left, top, lineHeight);\n charsToRender = '';\n prevStyle = thisStyle;\n }\n charsToRender += line[i - charOffset];\n }\n ctx.restore();\n },\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} line Content of the line\n * @param {Number} left Left coordinate\n * @param {Number} top Top coordinate\n */\n _renderCharsFast: function(method, ctx, line, left, top) {\n\n if (method === 'fillText' && this.fill) {\n this.callSuper('_renderChars', method, ctx, line, left, top);\n }\n if (method === 'strokeText' && ((this.stroke && this.strokeWidth > 0) || this.skipFillStrokeCheck)) {\n this.callSuper('_renderChars', method, ctx, line, left, top);\n }\n },\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex\n * @param {Number} i\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, i, _char, left, top, lineHeight) {\n var charWidth, charHeight, shouldFill, shouldStroke,\n decl = this._getStyleDeclaration(lineIndex, i),\n offset, textDecoration, chars, additionalSpace, _charWidth;\n\n if (decl) {\n charHeight = this._getHeightOfChar(ctx, _char, lineIndex, i);\n shouldStroke = decl.stroke;\n shouldFill = decl.fill;\n textDecoration = decl.textDecoration;\n }\n else {\n charHeight = this.fontSize;\n }\n\n shouldStroke = (shouldStroke || this.stroke) && method === 'strokeText';\n shouldFill = (shouldFill || this.fill) && method === 'fillText';\n\n decl && ctx.save();\n\n charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i, decl || null);\n textDecoration = textDecoration || this.textDecoration;\n\n if (decl && decl.textBackgroundColor) {\n this._removeShadow(ctx);\n }\n if (this.charSpacing !== 0) {\n additionalSpace = this._getWidthOfCharSpacing();\n chars = _char.split('');\n charWidth = 0;\n for (var j = 0, len = chars.length, jChar; j < len; j++) {\n jChar = chars[j];\n shouldFill && ctx.fillText(jChar, left + charWidth, top);\n shouldStroke && ctx.strokeText(jChar, left + charWidth, top);\n _charWidth = ctx.measureText(jChar).width + additionalSpace;\n charWidth += _charWidth > 0 ? _charWidth : 0;\n }\n }\n else {\n shouldFill && ctx.fillText(_char, left, top);\n shouldStroke && ctx.strokeText(_char, left, top);\n }\n\n if (textDecoration || textDecoration !== '') {\n offset = this._fontSizeFraction * lineHeight / this.lineHeight;\n this._renderCharDecoration(ctx, textDecoration, left, top, offset, charWidth, charHeight);\n }\n\n decl && ctx.restore();\n ctx.translate(charWidth, 0);\n },\n\n /**\n * @private\n * @param {Object} prevStyle\n * @param {Object} thisStyle\n */\n _hasStyleChanged: function(prevStyle, thisStyle) {\n return (prevStyle.fill !== thisStyle.fill ||\n prevStyle.fontSize !== thisStyle.fontSize ||\n prevStyle.textBackgroundColor !== thisStyle.textBackgroundColor ||\n prevStyle.textDecoration !== thisStyle.textDecoration ||\n prevStyle.fontFamily !== thisStyle.fontFamily ||\n prevStyle.fontWeight !== thisStyle.fontWeight ||\n prevStyle.fontStyle !== thisStyle.fontStyle ||\n prevStyle.stroke !== thisStyle.stroke ||\n prevStyle.strokeWidth !== thisStyle.strokeWidth\n );\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderCharDecoration: function(ctx, textDecoration, left, top, offset, charWidth, charHeight) {\n\n if (!textDecoration) {\n return;\n }\n\n var decorationWeight = charHeight / 15,\n positions = {\n underline: top + charHeight / 10,\n 'line-through': top - charHeight * (this._fontSizeFraction + this._fontSizeMult - 1) + decorationWeight,\n overline: top - (this._fontSizeMult - this._fontSizeFraction) * charHeight\n },\n decorations = ['underline', 'line-through', 'overline'], i, decoration;\n\n for (i = 0; i < decorations.length; i++) {\n decoration = decorations[i];\n if (textDecoration.indexOf(decoration) > -1) {\n ctx.fillRect(left, positions[decoration], charWidth , decorationWeight);\n }\n }\n },\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} line\n * @param {Number} left\n * @param {Number} top\n * @param {Number} lineIndex\n */\n _renderTextLine: function(method, ctx, line, left, top, lineIndex) {\n // to \"cancel\" this.fontSize subtraction in fabric.Text#_renderTextLine\n // the adding 0.03 is just to align text with itext by overlap test\n if (!this.isEmptyStyles()) {\n top += this.fontSize * (this._fontSizeFraction + 0.03);\n }\n this.callSuper('_renderTextLine', method, ctx, line, left, top, lineIndex);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextDecoration: function(ctx) {\n if (this.isEmptyStyles()) {\n return this.callSuper('_renderTextDecoration', ctx);\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextLinesBackground: function(ctx) {\n this.callSuper('_renderTextLinesBackground', ctx);\n\n var lineTopOffset = 0, heightOfLine,\n lineWidth, lineLeftOffset,\n leftOffset = this._getLeftOffset(),\n topOffset = this._getTopOffset(),\n colorCache = '',\n line, _char, style, leftCache,\n topCache, widthCache, heightCache;\n ctx.save();\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n heightOfLine = this._getHeightOfLine(ctx, i);\n line = this._textLines[i];\n\n if (line === '' || !this.styles || !this._getLineStyle(i)) {\n lineTopOffset += heightOfLine;\n continue;\n }\n\n lineWidth = this._getLineWidth(ctx, i);\n lineLeftOffset = this._getLineLeftOffset(lineWidth);\n leftCache = topCache = widthCache = heightCache = 0;\n for (var j = 0, jlen = line.length; j < jlen; j++) {\n style = this._getStyleDeclaration(i, j) || {};\n\n if (colorCache !== style.textBackgroundColor) {\n if (heightCache && widthCache) {\n ctx.fillStyle = colorCache;\n ctx.fillRect(leftCache, topCache, widthCache, heightCache);\n }\n leftCache = topCache = widthCache = heightCache = 0;\n colorCache = style.textBackgroundColor || '';\n }\n\n if (!style.textBackgroundColor) {\n colorCache = '';\n continue;\n }\n _char = line[j];\n\n if (colorCache === style.textBackgroundColor) {\n colorCache = style.textBackgroundColor;\n if (!leftCache) {\n leftCache = leftOffset + lineLeftOffset + this._getWidthOfCharsAt(ctx, i, j);\n }\n topCache = topOffset + lineTopOffset;\n widthCache += this._getWidthOfChar(ctx, _char, i, j);\n heightCache = heightOfLine / this.lineHeight;\n }\n }\n // if a textBackgroundColor ends on the last character of a line\n if (heightCache && widthCache) {\n ctx.fillStyle = colorCache;\n ctx.fillRect(leftCache, topCache, widthCache, heightCache);\n leftCache = topCache = widthCache = heightCache = 0;\n }\n lineTopOffset += heightOfLine;\n }\n ctx.restore();\n },\n\n /**\n * @private\n */\n _getCacheProp: function(_char, styleDeclaration) {\n return _char +\n styleDeclaration.fontSize +\n styleDeclaration.fontWeight +\n styleDeclaration.fontStyle;\n },\n\n /**\n * @private\n * @param {String} fontFamily name\n * @return {Object} reference to cache\n */\n _getFontCache: function(fontFamily) {\n if (!fabric.charWidthsCache[fontFamily]) {\n fabric.charWidthsCache[fontFamily] = { };\n }\n return fabric.charWidthsCache[fontFamily];\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} _char\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} [decl]\n */\n _applyCharStylesGetWidth: function(ctx, _char, lineIndex, charIndex, decl) {\n var charDecl = decl || this._getStyleDeclaration(lineIndex, charIndex),\n styleDeclaration = clone(charDecl),\n width, cacheProp, charWidthsCache;\n\n this._applyFontStyles(styleDeclaration);\n charWidthsCache = this._getFontCache(styleDeclaration.fontFamily);\n cacheProp = this._getCacheProp(_char, styleDeclaration);\n\n // short-circuit if no styles for this char\n // global style from object is always applyed and handled by save and restore\n if (!charDecl && charWidthsCache[cacheProp] && this.caching) {\n return charWidthsCache[cacheProp];\n }\n\n if (typeof styleDeclaration.shadow === 'string') {\n styleDeclaration.shadow = new fabric.Shadow(styleDeclaration.shadow);\n }\n\n var fill = styleDeclaration.fill || this.fill;\n ctx.fillStyle = fill.toLive\n ? fill.toLive(ctx, this)\n : fill;\n\n if (styleDeclaration.stroke) {\n ctx.strokeStyle = (styleDeclaration.stroke && styleDeclaration.stroke.toLive)\n ? styleDeclaration.stroke.toLive(ctx, this)\n : styleDeclaration.stroke;\n }\n\n ctx.lineWidth = styleDeclaration.strokeWidth || this.strokeWidth;\n ctx.font = this._getFontDeclaration.call(styleDeclaration);\n\n //if we want this._setShadow.call to work with styleDeclarion\n //we have to add those references\n if (styleDeclaration.shadow) {\n styleDeclaration.scaleX = this.scaleX;\n styleDeclaration.scaleY = this.scaleY;\n styleDeclaration.canvas = this.canvas;\n styleDeclaration.getObjectScaling = this.getObjectScaling;\n this._setShadow.call(styleDeclaration, ctx);\n }\n\n if (!this.caching || !charWidthsCache[cacheProp]) {\n width = ctx.measureText(_char).width;\n this.caching && (charWidthsCache[cacheProp] = width);\n return width;\n }\n\n return charWidthsCache[cacheProp];\n },\n\n /**\n * @private\n * @param {Object} styleDeclaration\n */\n _applyFontStyles: function(styleDeclaration) {\n if (!styleDeclaration.fontFamily) {\n styleDeclaration.fontFamily = this.fontFamily;\n }\n if (!styleDeclaration.fontSize) {\n styleDeclaration.fontSize = this.fontSize;\n }\n if (!styleDeclaration.fontWeight) {\n styleDeclaration.fontWeight = this.fontWeight;\n }\n if (!styleDeclaration.fontStyle) {\n styleDeclaration.fontStyle = this.fontStyle;\n }\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Boolean} [returnCloneOrEmpty=false]\n * @private\n */\n _getStyleDeclaration: function(lineIndex, charIndex, returnCloneOrEmpty) {\n if (returnCloneOrEmpty) {\n return (this.styles[lineIndex] && this.styles[lineIndex][charIndex])\n ? clone(this.styles[lineIndex][charIndex])\n : { };\n }\n\n return this.styles[lineIndex] && this.styles[lineIndex][charIndex] ? this.styles[lineIndex][charIndex] : null;\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 * @private\n */\n _getLineStyle: function(lineIndex) {\n return this.styles[lineIndex];\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n _setLineStyle: function(lineIndex, style) {\n this.styles[lineIndex] = style;\n },\n\n /**\n * @param {Number} lineIndex\n * @private\n */\n _deleteLineStyle: function(lineIndex) {\n delete this.styles[lineIndex];\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _getWidthOfChar: function(ctx, _char, lineIndex, charIndex) {\n if (!this._isMeasuring && this.textAlign === 'justify' && this._reSpacesAndTabs.test(_char)) {\n return this._getWidthOfSpace(ctx, lineIndex);\n }\n ctx.save();\n var width = this._applyCharStylesGetWidth(ctx, _char, lineIndex, charIndex);\n if (this.charSpacing !== 0) {\n width += this._getWidthOfCharSpacing();\n }\n ctx.restore();\n return width > 0 ? width : 0;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex\n * @param {Number} charIndex\n */\n _getHeightOfChar: function(ctx, lineIndex, charIndex) {\n var style = this._getStyleDeclaration(lineIndex, charIndex);\n return style && style.fontSize ? style.fontSize : this.fontSize;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex\n * @param {Number} charIndex\n */\n _getWidthOfCharsAt: function(ctx, lineIndex, charIndex) {\n var width = 0, i, _char;\n for (i = 0; i < charIndex; i++) {\n _char = this._textLines[lineIndex][i];\n width += this._getWidthOfChar(ctx, _char, lineIndex, i);\n }\n return width;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex line number\n * @return {Number} Line width\n */\n _measureLine: function(ctx, lineIndex) {\n this._isMeasuring = true;\n var width = this._getWidthOfCharsAt(ctx, lineIndex, this._textLines[lineIndex].length);\n if (this.charSpacing !== 0) {\n width -= this._getWidthOfCharSpacing();\n }\n this._isMeasuring = false;\n return width > 0 ? width : 0;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex\n */\n _getWidthOfSpace: function (ctx, lineIndex) {\n if (this.__widthOfSpace[lineIndex]) {\n return this.__widthOfSpace[lineIndex];\n }\n var line = this._textLines[lineIndex],\n wordsWidth = this._getWidthOfWords(ctx, line, lineIndex, 0),\n widthDiff = this.width - wordsWidth,\n numSpaces = line.length - line.replace(this._reSpacesAndTabs, '').length,\n width = Math.max(widthDiff / numSpaces, ctx.measureText(' ').width);\n this.__widthOfSpace[lineIndex] = width;\n return width;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} line\n * @param {Number} lineIndex\n * @param {Number} charOffset\n */\n _getWidthOfWords: function (ctx, line, lineIndex, charOffset) {\n var width = 0;\n\n for (var charIndex = 0; charIndex < line.length; charIndex++) {\n var _char = line[charIndex];\n\n if (!_char.match(/\\s/)) {\n width += this._getWidthOfChar(ctx, _char, lineIndex, charIndex + charOffset);\n }\n }\n\n return width;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _getHeightOfLine: function(ctx, lineIndex) {\n if (this.__lineHeights[lineIndex]) {\n return this.__lineHeights[lineIndex];\n }\n\n var line = this._textLines[lineIndex],\n maxHeight = this._getHeightOfChar(ctx, lineIndex, 0);\n\n for (var i = 1, len = line.length; i < len; i++) {\n var currentCharHeight = this._getHeightOfChar(ctx, lineIndex, i);\n if (currentCharHeight > maxHeight) {\n maxHeight = currentCharHeight;\n }\n }\n this.__lineHeights[lineIndex] = maxHeight * this.lineHeight * this._fontSizeMult;\n return this.__lineHeights[lineIndex];\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _getTextHeight: function(ctx) {\n var lineHeight, height = 0;\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n lineHeight = this._getHeightOfLine(ctx, i);\n height += (i === len - 1 ? lineHeight / this.lineHeight : lineHeight);\n }\n return height;\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 fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), {\n styles: clone(this.styles, true)\n });\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 * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.IText} instance of fabric.IText\n */\n fabric.IText.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('IText', object, callback, forceAsync, '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 this.callSuper('onDeselect');\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 }).bind(this);\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 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) {\n this.canvas && this.canvas.clearContext(this.canvas.contextTop || this.ctx);\n }\n\n },\n\n /**\n * Selects entire text\n */\n selectAll: function() {\n this.selectionStart = 0;\n this.selectionEnd = this.text.length;\n this._fireSelectionChanged();\n this._updateTextarea();\n },\n\n /**\n * Returns selected text\n * @return {String}\n */\n getSelectedText: function() {\n return this.text.slice(this.selectionStart, this.selectionEnd);\n },\n\n /**\n * Find new selection index representing start of current word according to current selection index\n * @param {Number} startFrom Surrent 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.charAt(index))) {\n while (this._reSpace.test(this.text.charAt(index))) {\n offset++;\n index--;\n }\n }\n while (/\\S/.test(this.text.charAt(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.charAt(index))) {\n while (this._reSpace.test(this.text.charAt(index))) {\n offset++;\n index++;\n }\n }\n while (/\\S/.test(this.text.charAt(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.charAt(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.charAt(index)) && index < this.text.length) {\n offset++;\n index++;\n }\n\n return startFrom + offset;\n },\n\n /**\n * Returns number of newlines in selected text\n * @return {Number} Number of newlines in selected text\n */\n getNumNewLinesInSelectedText: function() {\n var selectedText = this.getSelectedText(),\n numNewLines = 0;\n\n for (var i = 0, len = selectedText.length; i < len; i++) {\n if (selectedText[i] === '\\n') {\n numNewLines++;\n }\n }\n return numNewLines;\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 index = this._reSpace.test(this.text.charAt(selectionStart)) ? selectionStart - 1 : selectionStart,\n _char = this.text.charAt(index),\n reNonWord = /[ \\n\\.,;!\\?\\-]/;\n\n while (!reNonWord.test(_char) && index > 0 && index < this.text.length) {\n index += direction;\n _char = this.text.charAt(index);\n }\n if (reNonWord.test(_char) && _char !== '\\n') {\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 */\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 },\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.exitEditingOnOthers(this.canvas);\n }\n\n this.isEditing = true;\n this.selected = true;\n this.initHiddenTextarea(e);\n this.hiddenTextarea.focus();\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.renderAll();\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 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\n this.hasControls = this.selectable = false;\n this.lockMovementX = this.lockMovementY = true;\n },\n\n /**\n * @private\n */\n _updateTextarea: function() {\n if (!this.hiddenTextarea || this.inCompositionMode) {\n return;\n }\n this.cursorOffsetCache = { };\n this.hiddenTextarea.value = this.text;\n this.hiddenTextarea.selectionStart = this.selectionStart;\n this.hiddenTextarea.selectionEnd = this.selectionEnd;\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 this.hiddenTextarea.style.fontSize = style.fontSize;\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 chars = this.text.split(''),\n boundaries = this._getCursorBoundaries(chars, 'cursor'),\n cursorLocation = this.get2DCursorLocation(),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex,\n charHeight = this.getCurrentCharFontSize(lineIndex, charIndex),\n leftOffset = boundaries.leftOffset,\n m = this.calcTransformMatrix(),\n p = {\n x: boundaries.left + leftOffset,\n y: boundaries.top + boundaries.topOffset + charHeight\n },\n upperCanvas = this.canvas.upperCanvasEl,\n maxWidth = upperCanvas.width - charHeight,\n maxHeight = upperCanvas.height - charHeight;\n\n p = fabric.util.transformPoint(p, m);\n p = fabric.util.transformPoint(p, this.canvas.viewportTransform);\n\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 };\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 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.overCursor;\n this.hasControls = this._savedProps.hasControls;\n this.borderColor = this._savedProps.borderColor;\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 this.selected = false;\n this.isEditing = false;\n this.selectable = true;\n\n this.selectionEnd = this.selectionStart;\n\n if (this.hiddenTextarea) {\n this.hiddenTextarea.blur && this.hiddenTextarea.blur();\n this.canvas && this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea);\n this.hiddenTextarea = null;\n }\n\n this.abortCursorAnimation();\n this._restoreEditingProps();\n this._currentCursorOpacity = 0;\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 * @private\n */\n _removeCharsFromTo: function(start, end) {\n while (end !== start) {\n this._removeSingleCharAndStyle(start + 1);\n end--;\n }\n this.selectionStart = start;\n this.selectionEnd = start;\n },\n\n _removeSingleCharAndStyle: function(index) {\n var isBeginningOfLine = this.text[index - 1] === '\\n',\n indexStyle = isBeginningOfLine ? index : index - 1;\n this.removeStyleObject(isBeginningOfLine, indexStyle);\n this.text = this.text.slice(0, index - 1) +\n this.text.slice(index);\n\n this._textLines = this._splitTextIntoLines();\n },\n\n /**\n * Inserts characters where cursor is (replacing selection if one exists)\n * @param {String} _chars Characters to insert\n * @param {Boolean} useCopiedStyle use fabric.copiedTextStyle\n */\n insertChars: function(_chars, useCopiedStyle) {\n var style;\n\n if (this.selectionEnd - this.selectionStart > 1) {\n this._removeCharsFromTo(this.selectionStart, this.selectionEnd);\n }\n //short circuit for block paste\n if (!useCopiedStyle && this.isEmptyStyles()) {\n this.insertChar(_chars, false);\n return;\n }\n for (var i = 0, len = _chars.length; i < len; i++) {\n if (useCopiedStyle) {\n style = fabric.util.object.clone(fabric.copiedTextStyle[i], true);\n }\n this.insertChar(_chars[i], i < len - 1, style);\n }\n },\n\n /**\n * Inserts a character where cursor is\n * @param {String} _char Characters to insert\n * @param {Boolean} skipUpdate trigger rendering and updates at the end of text insert\n * @param {Object} styleObject Style to be inserted for the new char\n */\n insertChar: function(_char, skipUpdate, styleObject) {\n var isEndOfLine = this.text[this.selectionStart] === '\\n';\n this.text = this.text.slice(0, this.selectionStart) +\n _char + this.text.slice(this.selectionEnd);\n this._textLines = this._splitTextIntoLines();\n this.insertStyleObjects(_char, isEndOfLine, styleObject);\n this.selectionStart += _char.length;\n this.selectionEnd = this.selectionStart;\n if (skipUpdate) {\n return;\n }\n this._updateTextarea();\n this.setCoords();\n this._fireSelectionChanged();\n this.fire('changed');\n this.restartCursorIfNeeded();\n if (this.canvas) {\n this.canvas.fire('text:changed', { target: this });\n this.canvas.renderAll();\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 * Inserts new style object\n * @param {Number} lineIndex Index of a line\n * @param {Number} charIndex Index of a char\n * @param {Boolean} isEndOfLine True if it's end of line\n */\n insertNewlineStyleObject: function(lineIndex, charIndex, isEndOfLine) {\n\n this.shiftLineStyles(lineIndex, +1);\n\n var currentCharStyle = {},\n newLineStyles = {};\n\n if (this.styles[lineIndex] && this.styles[lineIndex][charIndex - 1]) {\n currentCharStyle = this.styles[lineIndex][charIndex - 1];\n }\n\n // if there's nothing after cursor,\n // we clone current char style onto the next (otherwise empty) line\n if (isEndOfLine && currentCharStyle) {\n newLineStyles[0] = clone(currentCharStyle);\n this.styles[lineIndex + 1] = newLineStyles;\n }\n // otherwise we clone styles of all chars\n // after cursor onto the next line, from the beginning\n else {\n var somethingAdded = false;\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 delete this.styles[lineIndex][index];\n }\n }\n somethingAdded && (this.styles[lineIndex + 1] = newLineStyles);\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 {Object} [style] Style object to insert, if given\n */\n insertCharStyleObject: function(lineIndex, charIndex, style) {\n\n var currentLineStyles = this.styles[lineIndex],\n currentLineStylesCloned = clone(currentLineStyles);\n\n if (charIndex === 0 && !style) {\n charIndex = 1;\n }\n\n // shift all char styles by 1 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\n if (numericIndex >= charIndex) {\n currentLineStyles[numericIndex + 1] = currentLineStylesCloned[numericIndex];\n\n // only delete the style if there was nothing moved there\n if (!currentLineStylesCloned[numericIndex - 1]) {\n delete currentLineStyles[numericIndex];\n }\n }\n }\n var newStyle = style || clone(currentLineStyles[charIndex - 1]);\n newStyle && (this.styles[lineIndex][charIndex] = newStyle);\n this._forceClearCache = true;\n },\n\n /**\n * Inserts style object(s)\n * @param {String} _chars Characters at the location where style is inserted\n * @param {Boolean} isEndOfLine True if it's end of line\n * @param {Object} [styleObject] Style to insert\n */\n insertStyleObjects: function(_chars, isEndOfLine, styleObject) {\n // removed shortcircuit over isEmptyStyles\n\n var cursorLocation = this.get2DCursorLocation(),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex;\n\n if (!this._getLineStyle(lineIndex)) {\n this._setLineStyle(lineIndex, {});\n }\n\n if (_chars === '\\n') {\n this.insertNewlineStyleObject(lineIndex, charIndex, isEndOfLine);\n }\n else {\n this.insertCharStyleObject(lineIndex, charIndex, styleObject);\n }\n },\n\n /**\n * Shifts line styles up or down\n * @param {Number} lineIndex Index of a line\n * @param {Number} offset Can be -1 or +1\n */\n shiftLineStyles: function(lineIndex, offset) {\n // shift all line styles by 1 upward or downward\n var clonedStyles = clone(this.styles);\n for (var line in clonedStyles) {\n var numericLine = parseInt(line, 10);\n if (numericLine <= lineIndex) {\n delete clonedStyles[numericLine];\n }\n }\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 //TODO: evaluate if delete old style lines with offset -1\n },\n\n /**\n * Removes style object\n * @param {Boolean} isBeginningOfLine True if cursor is at the beginning of line\n * @param {Number} [index] Optional index. When not given, current selectionStart is used.\n */\n removeStyleObject: function(isBeginningOfLine, index) {\n\n var cursorLocation = this.get2DCursorLocation(index),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex;\n\n this._removeStyleObject(isBeginningOfLine, cursorLocation, lineIndex, charIndex);\n },\n\n _getTextOnPreviousLine: function(lIndex) {\n return this._textLines[lIndex - 1];\n },\n\n _removeStyleObject: function(isBeginningOfLine, cursorLocation, lineIndex, charIndex) {\n\n if (isBeginningOfLine) {\n var textOnPreviousLine = this._getTextOnPreviousLine(cursorLocation.lineIndex),\n newCharIndexOnPrevLine = textOnPreviousLine ? textOnPreviousLine.length : 0;\n\n if (!this.styles[lineIndex - 1]) {\n this.styles[lineIndex - 1] = {};\n }\n for (charIndex in this.styles[lineIndex]) {\n this.styles[lineIndex - 1][parseInt(charIndex, 10) + newCharIndexOnPrevLine]\n = this.styles[lineIndex][charIndex];\n }\n this.shiftLineStyles(cursorLocation.lineIndex, -1);\n }\n else {\n var currentLineStyles = this.styles[lineIndex];\n\n if (currentLineStyles) {\n delete currentLineStyles[charIndex];\n }\n var currentLineStylesCloned = clone(currentLineStyles);\n // shift all styles by 1 backwards\n for (var i in currentLineStylesCloned) {\n var numericIndex = parseInt(i, 10);\n if (numericIndex >= charIndex && numericIndex !== 0) {\n currentLineStyles[numericIndex - 1] = currentLineStylesCloned[numericIndex];\n delete currentLineStyles[numericIndex];\n }\n }\n }\n },\n\n /**\n * Inserts new line\n */\n insertNewline: function() {\n this.insertChars('\\n');\n },\n\n /**\n * Set the selectionStart and selectionEnd according to the ne postion 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.bind(this));\n },\n\n onMouseDown: function(options) {\n\n this.__newClickTime = +new Date();\n var newPointer = this.canvas.getPointer(options.e);\n\n if (this.isTripleClick(newPointer, options.e)) {\n this.fire('tripleclick', options);\n this._stopEvent(options.e);\n }\n else if (this.isDoubleClick(newPointer)) {\n this.fire('dblclick', options);\n this._stopEvent(options.e);\n }\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 isDoubleClick: function(newPointer) {\n return this.__newClickTime - this.__lastClickTime < 500 &&\n this.__lastPointer.x === newPointer.x &&\n this.__lastPointer.y === newPointer.y && this.__lastIsEditing;\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 * Initializes double and triple click event handlers\n */\n initClicks: function() {\n this.on('dblclick', function(options) {\n this.selectWord(this.getSelectionStartFromPointer(options.e));\n });\n this.on('tripleclick', function(options) {\n this.selectLine(this.getSelectionStartFromPointer(options.e));\n });\n },\n\n /**\n * Initializes \"mousedown\" event handler\n */\n initMousedownHandler: function() {\n this.on('mousedown', function(options) {\n if (!this.editable || (options.e.button && options.e.button !== 1)) {\n return;\n }\n var pointer = this.canvas.getPointer(options.e);\n this.__mousedownX = pointer.x;\n this.__mousedownY = pointer.y;\n this.__isMousedown = true;\n\n if (this.selected) {\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 /**\n * @private\n */\n _isObjectMoved: function(e) {\n var pointer = this.canvas.getPointer(e);\n\n return this.__mousedownX !== pointer.x ||\n this.__mousedownY !== pointer.y;\n },\n\n /**\n * Initializes \"mouseup\" event handler\n */\n initMouseupHandler: function() {\n this.on('mouseup', function(options) {\n this.__isMousedown = false;\n if (!this.editable || this._isObjectMoved(options.e) || (options.e.button && options.e.button !== 1)) {\n return;\n }\n\n if (this.__lastSelected && !this.__corner) {\n this.enterEditing(options.e);\n if (this.selectionStart === this.selectionEnd) {\n this.initDelayedCursor(true);\n }\n else {\n this.renderCursorOrSelection();\n }\n }\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 newSelectionStart,\n line;\n\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n line = this._textLines[i];\n height += this._getHeightOfLine(this.ctx, i) * this.scaleY;\n\n var widthOfLine = this._getLineWidth(this.ctx, i),\n lineLeftOffset = this._getLineLeftOffset(widthOfLine);\n\n width = lineLeftOffset * this.scaleX;\n\n for (var j = 0, jlen = line.length; j < jlen; j++) {\n\n prevWidth = width;\n\n width += this._getWidthOfChar(this.ctx, line[j], i, this.flipX ? jlen - j : j) *\n this.scaleX;\n\n if (height <= mouseOffset.y || width <= mouseOffset.x) {\n charIndex++;\n continue;\n }\n\n return this._getNewSelectionStartFromOffset(\n mouseOffset, prevWidth, width, charIndex + i, jlen);\n }\n\n if (mouseOffset.y < height) {\n //this happens just on end of lines.\n return this._getNewSelectionStartFromOffset(\n mouseOffset, prevWidth, width, charIndex + i - 1, jlen);\n }\n }\n\n // clicked somewhere after all chars, so set at the end\n if (typeof newSelectionStart === 'undefined') {\n return this.text.length;\n }\n },\n\n /**\n * @private\n */\n _getNewSelectionStartFromOffset: function(mouseOffset, prevWidth, width, index, jlen) {\n\n var distanceBtwLastCharAndCursor = mouseOffset.x - prevWidth,\n distanceBtwNextCharAndCursor = width - mouseOffset.x,\n offset = distanceBtwNextCharAndCursor > distanceBtwLastCharAndCursor ? 0 : 1,\n newSelectionStart = index + offset;\n\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 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 ' line-height: 1px; paddingーtop: ' + style.fontSize + ';';\n fabric.document.body.appendChild(this.hiddenTextarea);\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.cut.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 8: 'removeChars',\n 9: 'exitEditing',\n 27: 'exitEditing',\n 13: 'insertNewline',\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 46: 'forwardDelete'\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 keyup event\n * @param {Event} e Event object\n */\n onKeyDown: function(e) {\n if (!this.isEditing) {\n return;\n }\n if (e.keyCode in this.keysMap) {\n this[this.keysMap[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.clearContextTop();\n this.renderCursorOrSelection();\n }\n else {\n this.canvas && this.canvas.renderAll();\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) {\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.renderAll();\n },\n\n /**\n * Handles onInput event\n * @param {Event} e Event object\n */\n onInput: function(e) {\n if (!this.isEditing || this.inCompositionMode) {\n return;\n }\n var offset = this.selectionStart || 0,\n offsetEnd = this.selectionEnd || 0,\n textLength = this.text.length,\n newTextLength = this.hiddenTextarea.value.length,\n diff, charsToInsert, start;\n if (newTextLength > textLength) {\n //we added some character\n start = this._selectionDirection === 'left' ? offsetEnd : offset;\n diff = newTextLength - textLength;\n charsToInsert = this.hiddenTextarea.value.slice(start, start + diff);\n }\n else {\n //we selected a portion of text and then input something else.\n //Internet explorer does not trigger this else\n diff = newTextLength - textLength + offsetEnd - offset;\n charsToInsert = this.hiddenTextarea.value.slice(offset, offset + diff);\n }\n this.insertChars(charsToInsert);\n e.stopPropagation();\n },\n\n /**\n * Composition start\n */\n onCompositionStart: function() {\n this.inCompositionMode = true;\n this.prevCompositionLength = 0;\n this.compositionStart = this.selectionStart;\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 var data = e.data;\n this.selectionStart = this.compositionStart;\n this.selectionEnd = this.selectionEnd === this.selectionStart ?\n this.compositionStart + this.prevCompositionLength : this.selectionEnd;\n this.insertChars(data, false);\n this.prevCompositionLength = data.length;\n },\n\n /**\n * Forward delete\n */\n forwardDelete: function(e) {\n if (this.selectionStart === this.selectionEnd) {\n if (this.selectionStart === this.text.length) {\n return;\n }\n this.moveCursorRight(e);\n }\n this.removeChars(e);\n },\n\n /**\n * Copies selected text\n * @param {Event} e Event object\n */\n copy: function(e) {\n if (this.selectionStart === this.selectionEnd) {\n //do not cut-copy if no selection\n return;\n }\n var selectedText = this.getSelectedText(),\n clipboardData = this._getClipboardData(e);\n\n // Check for backward compatibility with old browsers\n if (clipboardData) {\n clipboardData.setData('text', selectedText);\n }\n\n fabric.copiedText = selectedText;\n fabric.copiedTextStyle = this.getSelectionStyles(this.selectionStart, this.selectionEnd);\n e.stopImmediatePropagation();\n e.preventDefault();\n this._copyDone = true;\n },\n\n /**\n * Pastes text\n * @param {Event} e Event object\n */\n paste: function(e) {\n var copiedText = null,\n clipboardData = this._getClipboardData(e),\n useCopiedStyle = true;\n\n // Check for backward compatibility with old browsers\n if (clipboardData) {\n copiedText = clipboardData.getData('text').replace(/\\r/g, '');\n if (!fabric.copiedTextStyle || fabric.copiedText !== copiedText) {\n useCopiedStyle = false;\n }\n }\n else {\n copiedText = fabric.copiedText;\n }\n\n if (copiedText) {\n this.insertChars(copiedText, useCopiedStyle);\n }\n e.stopImmediatePropagation();\n e.preventDefault();\n },\n\n /**\n * Cuts text\n * @param {Event} e Event object\n */\n cut: function(e) {\n if (this.selectionStart === this.selectionEnd) {\n return;\n }\n\n this.copy(e);\n this.removeChars(e);\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 textBeforeCursor = this._textLines[lineIndex].slice(0, charIndex),\n widthOfLine = this._getLineWidth(this.ctx, lineIndex),\n widthBeforeCursor = this._getLineLeftOffset(widthOfLine), _char;\n\n for (var i = 0, len = textBeforeCursor.length; i < len; i++) {\n _char = textBeforeCursor[i];\n widthBeforeCursor += this._getWidthOfChar(this.ctx, _char, lineIndex, i);\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\n return textAfterCursor.length + indexOnOtherLine + 2;\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 // return a negative offset\n return -this._textLines[lineIndex - 1].length + indexOnOtherLine - textBeforeCursor.length;\n },\n\n /**\n * find for a given width it founds the matching character.\n * @private\n */\n _getIndexOnLine: function(lineIndex, width) {\n\n var widthOfLine = this._getLineWidth(this.ctx, lineIndex),\n textOnLine = this._textLines[lineIndex],\n lineLeftOffset = this._getLineLeftOffset(widthOfLine),\n widthOfCharsOnLine = lineLeftOffset,\n indexOnLine = 0,\n foundMatch;\n\n for (var j = 0, jlen = textOnLine.length; j < jlen; j++) {\n\n var _char = textOnLine[j],\n widthOfChar = this._getWidthOfChar(this.ctx, _char, lineIndex, j);\n\n widthOfCharsOnLine += widthOfChar;\n\n if (widthOfCharsOnLine > width) {\n\n foundMatch = true;\n\n var leftEdge = widthOfCharsOnLine - widthOfChar,\n rightEdge = widthOfCharsOnLine,\n offsetFromLeftEdge = Math.abs(leftEdge - width),\n offsetFromRightEdge = Math.abs(rightEdge - width);\n\n indexOnLine = offsetFromRightEdge < offsetFromLeftEdge ? j : (j - 1);\n\n break;\n }\n }\n\n // reached end\n if (!foundMatch) {\n indexOnLine = textOnLine.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 selected by selection\n * @param {Event} e Event object\n */\n removeChars: function(e) {\n if (this.selectionStart === this.selectionEnd) {\n this._removeCharsNearCursor(e);\n }\n else {\n this._removeCharsFromTo(this.selectionStart, this.selectionEnd);\n }\n\n this.set('dirty', true);\n this.setSelectionEnd(this.selectionStart);\n\n this._removeExtraneousStyles();\n\n this.canvas && this.canvas.renderAll();\n\n this.setCoords();\n this.fire('changed');\n this.canvas && this.canvas.fire('text:changed', { target: this });\n },\n\n /**\n * @private\n * @param {Event} e Event object\n */\n _removeCharsNearCursor: function(e) {\n if (this.selectionStart === 0) {\n return;\n }\n if (e.metaKey) {\n // remove all till the start of current line\n var leftLineBoundary = this.findLineBoundaryLeft(this.selectionStart);\n\n this._removeCharsFromTo(leftLineBoundary, this.selectionStart);\n this.setSelectionStart(leftLineBoundary);\n }\n else if (e.altKey) {\n // remove all till the start of current word\n var leftWordBoundary = this.findWordBoundaryLeft(this.selectionStart);\n\n this._removeCharsFromTo(leftWordBoundary, this.selectionStart);\n this.setSelectionStart(leftWordBoundary);\n }\n else {\n this._removeSingleCharAndStyle(this.selectionStart);\n this.setSelectionStart(this.selectionStart - 1);\n }\n }\n});\n\n\n/* _TO_SVG_START_ */\n(function() {\n var toFixed = fabric.util.toFixed,\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n\n fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ {\n\n /**\n * @private\n */\n _setSVGTextLineText: function(lineIndex, textSpans, height, textLeftOffset, textTopOffset, textBgRects) {\n if (!this._getLineStyle(lineIndex)) {\n fabric.Text.prototype._setSVGTextLineText.call(this,\n lineIndex, textSpans, height, textLeftOffset, textTopOffset);\n }\n else {\n this._setSVGTextLineChars(\n lineIndex, textSpans, height, textLeftOffset, textBgRects);\n }\n },\n\n /**\n * @private\n */\n _setSVGTextLineChars: function(lineIndex, textSpans, height, textLeftOffset, textBgRects) {\n\n var chars = this._textLines[lineIndex],\n charOffset = 0,\n lineLeftOffset = this._getLineLeftOffset(this._getLineWidth(this.ctx, lineIndex)) - this.width / 2,\n lineOffset = this._getSVGLineTopOffset(lineIndex),\n heightOfLine = this._getHeightOfLine(this.ctx, lineIndex);\n\n for (var i = 0, len = chars.length; i < len; i++) {\n var styleDecl = this._getStyleDeclaration(lineIndex, i) || { };\n\n textSpans.push(\n this._createTextCharSpan(\n chars[i], styleDecl, lineLeftOffset, lineOffset.lineTop + lineOffset.offset, charOffset));\n\n var charWidth = this._getWidthOfChar(this.ctx, chars[i], lineIndex, i);\n\n if (styleDecl.textBackgroundColor) {\n textBgRects.push(\n this._createTextCharBg(\n styleDecl, lineLeftOffset, lineOffset.lineTop, heightOfLine, charWidth, charOffset));\n }\n\n charOffset += charWidth;\n }\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(this.ctx, j);\n }\n lastHeight = this._getHeightOfLine(this.ctx, j);\n return {\n lineTop: lineTopOffset,\n offset: (this._fontSizeMult - this._fontSizeFraction) * lastHeight / (this.lineHeight * this._fontSizeMult)\n };\n },\n\n /**\n * @private\n */\n _createTextCharBg: function(styleDecl, lineLeftOffset, lineTopOffset, heightOfLine, charWidth, charOffset) {\n return [\n '\\t\\t\\n'\n ].join('');\n },\n\n /**\n * @private\n */\n _createTextCharSpan: function(_char, styleDecl, lineLeftOffset, lineTopOffset, charOffset) {\n\n var fillStyles = this.getSvgStyles.call(fabric.util.object.extend({\n visible: true,\n fill: this.fill,\n stroke: this.stroke,\n type: 'text',\n getSvgFilter: fabric.Object.prototype.getSvgFilter\n }, styleDecl));\n\n return [\n '\\t\\t\\t',\n fabric.util.string.escapeXml(_char),\n '\\n'\n ].join('');\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 lockScalingY: true,\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 * Constructor. Some scaling related property values are forced. Visibility\n * of controls is also fixed; only the rotation and width controls are\n * made available.\n * @param {String} text Text string\n * @param {Object} [options] Options object\n * @return {fabric.Textbox} thisArg\n */\n initialize: function(text, options) {\n\n this.callSuper('initialize', text, options);\n this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());\n this.ctx = this.objectCaching ? this._cacheContext : fabric.util.createCanvasElement().getContext('2d');\n },\n\n /**\n * Unlike superclass's version of this function, Textbox does not update\n * its width.\n * @param {CanvasRenderingContext2D} ctx Context to use for measurements\n * @private\n * @override\n */\n _initDimensions: function(ctx) {\n if (this.__skipDimension) {\n return;\n }\n\n if (!ctx) {\n ctx = fabric.util.createCanvasElement().getContext('2d');\n this._setTextStyles(ctx);\n this.clearContextTop();\n }\n\n // clear dynamicMinWidth as it will be different after we re-wrap line\n this.dynamicMinWidth = 0;\n\n // wrap lines\n this._textLines = this._splitTextIntoLines(ctx);\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\n // clear cache and re-calculate height\n this._clearCache();\n this.height = this._getTextHeight(ctx);\n this.setCoords();\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() {\n var realLineCount = 0,\n realLineCharCount = 0,\n charCount = 0,\n map = {};\n\n for (var i = 0; i < this._textLines.length; i++) {\n if (this.text[charCount] === '\\n' && i > 0) {\n realLineCharCount = 0;\n charCount++;\n realLineCount++;\n }\n else if (this.text[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 += this._textLines[i].length;\n realLineCharCount += this._textLines[i].length;\n }\n\n return map;\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Boolean} [returnCloneOrEmpty=false]\n * @private\n */\n _getStyleDeclaration: function(lineIndex, charIndex, returnCloneOrEmpty) {\n if (this._styleMap) {\n var map = this._styleMap[lineIndex];\n if (!map) {\n return returnCloneOrEmpty ? { } : null;\n }\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n }\n return this.callSuper('_getStyleDeclaration', lineIndex, charIndex, returnCloneOrEmpty);\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\n delete this.styles[lineIndex][charIndex];\n },\n\n /**\n * @param {Number} lineIndex\n * @private\n */\n _getLineStyle: function(lineIndex) {\n var map = this._styleMap[lineIndex];\n return this.styles[map.line];\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n _setLineStyle: function(lineIndex, style) {\n var map = this._styleMap[lineIndex];\n this.styles[map.line] = style;\n },\n\n /**\n * @param {Number} lineIndex\n * @private\n */\n _deleteLineStyle: function(lineIndex) {\n var map = this._styleMap[lineIndex];\n delete 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 {CanvasRenderingContext2D} ctx Context to use for measurements\n * @param {String} text The string of text that is split into lines\n * @returns {Array} Array of lines\n */\n _wrapText: function(ctx, text) {\n var lines = text.split(this._reNewline), wrapped = [], i;\n\n for (i = 0; i < lines.length; i++) {\n wrapped = wrapped.concat(this._wrapLine(ctx, lines[i], i));\n }\n\n return wrapped;\n },\n\n /**\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {String} text\n * @param {number} lineIndex\n * @param {number} charOffset\n * @returns {number}\n * @private\n */\n _measureText: function(ctx, text, lineIndex, charOffset) {\n var width = 0;\n charOffset = charOffset || 0;\n for (var i = 0, len = text.length; i < len; i++) {\n width += this._getWidthOfChar(ctx, text[i], lineIndex, i + charOffset);\n }\n return width;\n },\n\n /**\n * Wraps a line of text using the width of the Textbox and a context.\n * @param {CanvasRenderingContext2D} ctx Context to use for measurements\n * @param {String} text The string of text to split into lines\n * @param {Number} lineIndex\n * @returns {Array} Array of line(s) into which the given text is wrapped\n * to.\n */\n _wrapLine: function(ctx, text, lineIndex) {\n var lineWidth = 0,\n lines = [],\n line = '',\n words = text.split(' '),\n word = '',\n offset = 0,\n infix = ' ',\n wordWidth = 0,\n infixWidth = 0,\n largestWordWidth = 0,\n lineJustStarted = true,\n additionalSpace = this._getWidthOfCharSpacing();\n\n for (var i = 0; i < words.length; i++) {\n word = words[i];\n wordWidth = this._measureText(ctx, word, lineIndex, offset);\n\n offset += word.length;\n\n lineWidth += infixWidth + wordWidth - additionalSpace;\n\n if (lineWidth >= this.width && !lineJustStarted) {\n lines.push(line);\n line = '';\n lineWidth = wordWidth;\n lineJustStarted = true;\n }\n else {\n lineWidth += additionalSpace;\n }\n\n if (!lineJustStarted) {\n line += infix;\n }\n line += word;\n\n infixWidth = this._measureText(ctx, 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 && lines.push(line);\n\n if (largestWordWidth > this.dynamicMinWidth) {\n this.dynamicMinWidth = largestWordWidth - additionalSpace;\n }\n\n return lines;\n },\n /**\n * Gets lines of text to render in the Textbox. This function calculates\n * text wrapping on the fly everytime it is called.\n * @returns {Array} Array of lines in the Textbox.\n * @override\n */\n _splitTextIntoLines: function(ctx) {\n ctx = ctx || this.ctx;\n var originalAlign = this.textAlign;\n this._styleMap = null;\n ctx.save();\n this._setTextStyles(ctx);\n this.textAlign = 'left';\n var lines = this._wrapText(ctx, this.text);\n this.textAlign = originalAlign;\n ctx.restore();\n this._textLines = lines;\n this._styleMap = this._generateStyleMap();\n return lines;\n },\n\n /**\n * When part of a group, we don't want the Textbox's scale to increase if\n * the group's increases. That's why we reduce the scale of the Textbox by\n * the amount that the group's increases. This is to maintain the effective\n * scale of the Textbox at 1, so that font-size values make sense. Otherwise\n * the same font-size value would result in different actual size depending\n * on the value of the scale.\n * @param {String} key\n * @param {*} value\n */\n setOnGroup: function(key, value) {\n if (key === 'scaleX') {\n this.set('scaleX', Math.abs(1 / value));\n this.set('width', (this.get('width') * value) /\n (typeof this.__oldScaleX === 'undefined' ? 1 : this.__oldScaleX));\n this.__oldScaleX = value;\n }\n },\n\n /**\n * Returns 2d representation (lineIndex and charIndex) of cursor (or selection start).\n * Overrides the superclass function to take into account text wrapping.\n *\n * @param {Number} [selectionStart] Optional index. When not given, current selectionStart is used.\n */\n get2DCursorLocation: function(selectionStart) {\n if (typeof selectionStart === 'undefined') {\n selectionStart = this.selectionStart;\n }\n\n var numLines = this._textLines.length,\n removed = 0;\n\n for (var i = 0; i < numLines; i++) {\n var line = this._textLines[i],\n lineLen = line.length;\n\n if (selectionStart <= removed + lineLen) {\n return {\n lineIndex: i,\n charIndex: selectionStart - removed\n };\n }\n\n removed += lineLen;\n\n if (this.text[removed] === '\\n' || this.text[removed] === ' ') {\n removed++;\n }\n }\n\n return {\n lineIndex: numLines - 1,\n charIndex: this._textLines[numLines - 1].length\n };\n },\n\n /**\n * Overrides superclass function and uses text wrapping data to get cursor\n * boundary offsets instead of the array of chars.\n * @param {Array} chars Unused\n * @param {String} typeOfBoundaries Can be 'cursor' or 'selection'\n * @returns {Object} Object with 'top', 'left', and 'lineLeft' properties set.\n */\n _getCursorBoundariesOffsets: function(chars, typeOfBoundaries) {\n var topOffset = 0,\n leftOffset = 0,\n cursorLocation = this.get2DCursorLocation(),\n lineChars = this._textLines[cursorLocation.lineIndex].split(''),\n lineLeftOffset = this._getLineLeftOffset(this._getLineWidth(this.ctx, cursorLocation.lineIndex));\n\n for (var i = 0; i < cursorLocation.charIndex; i++) {\n leftOffset += this._getWidthOfChar(this.ctx, lineChars[i], cursorLocation.lineIndex, i);\n }\n\n for (i = 0; i < cursorLocation.lineIndex; i++) {\n topOffset += this._getHeightOfLine(this.ctx, i);\n }\n\n if (typeOfBoundaries === 'cursor') {\n topOffset += (1 - this._fontSizeFraction) * this._getHeightOfLine(this.ctx, cursorLocation.lineIndex)\n / this.lineHeight - this.getCurrentCharFontSize(cursorLocation.lineIndex, cursorLocation.charIndex)\n * (1 - this._fontSizeFraction);\n }\n\n return {\n top: topOffset,\n left: leftOffset,\n lineLeft: lineLeftOffset\n };\n },\n\n getMinWidth: function() {\n return Math.max(this.minWidth, this.dynamicMinWidth);\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'].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 * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Textbox} instance of fabric.Textbox\n */\n fabric.Textbox.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Textbox', object, callback, forceAsync, 'text');\n };\n\n /**\n * Returns the default controls visibility required for Textboxes.\n * @returns {Object}\n */\n fabric.Textbox.getTextboxControlVisibility = function() {\n return {\n tl: false,\n tr: false,\n br: false,\n bl: false,\n ml: true,\n mt: false,\n mr: true,\n mb: false,\n mtr: true\n };\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n /**\n * Override _setObjectScale and add Textbox specific resizing behavior. Resizing\n * a Textbox doesn't scale text, it only changes width and makes text wrap automatically.\n */\n var setObjectScaleOverridden = fabric.Canvas.prototype._setObjectScale;\n\n fabric.Canvas.prototype._setObjectScale = function(localMouse, transform,\n lockScalingX, lockScalingY, by, lockScalingFlip, _dim) {\n\n var t = transform.target;\n if (t instanceof fabric.Textbox) {\n var w = t.width * ((localMouse.x / transform.scaleX) / (t.width + t.strokeWidth));\n if (w >= t.getMinWidth()) {\n t.set('width', w);\n return true;\n }\n }\n else {\n return setObjectScaleOverridden.call(fabric.Canvas.prototype, localMouse, transform,\n lockScalingX, lockScalingY, by, lockScalingFlip, _dim);\n }\n };\n\n /**\n * Sets controls of this group to the Textbox's special configuration if\n * one is present in the group. Deletes _controlsVisibility otherwise, so that\n * it gets initialized to default value at runtime.\n */\n fabric.Group.prototype._refreshControlsVisibility = function() {\n if (typeof fabric.Textbox === 'undefined') {\n return;\n }\n for (var i = this._objects.length; i--;) {\n if (this._objects[i] instanceof fabric.Textbox) {\n this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());\n return;\n }\n }\n };\n\n fabric.util.object.extend(fabric.Textbox.prototype, /** @lends fabric.IText.prototype */ {\n /**\n * @private\n */\n _removeExtraneousStyles: function() {\n for (var prop in this._styleMap) {\n if (!this._textLines[prop]) {\n delete this.styles[this._styleMap[prop].line];\n }\n }\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 {Object} [style] Style object to insert, if given\n */\n insertCharStyleObject: function(lineIndex, charIndex, style) {\n // adjust lineIndex and charIndex\n var map = this._styleMap[lineIndex];\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n\n fabric.IText.prototype.insertCharStyleObject.apply(this, [lineIndex, charIndex, style]);\n },\n\n /**\n * Inserts new style object\n * @param {Number} lineIndex Index of a line\n * @param {Number} charIndex Index of a char\n * @param {Boolean} isEndOfLine True if it's end of line\n */\n insertNewlineStyleObject: function(lineIndex, charIndex, isEndOfLine) {\n // adjust lineIndex and charIndex\n var map = this._styleMap[lineIndex];\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n\n fabric.IText.prototype.insertNewlineStyleObject.apply(this, [lineIndex, charIndex, isEndOfLine]);\n },\n\n /**\n * Shifts line styles up or down. This function is slightly different than the one in\n * itext_behaviour as it takes into account the styleMap.\n *\n * @param {Number} lineIndex Index of a line\n * @param {Number} offset Can be -1 or +1\n */\n shiftLineStyles: function(lineIndex, offset) {\n // shift all line styles by 1 upward\n var map = this._styleMap[lineIndex];\n // adjust line index\n lineIndex = map.line;\n fabric.IText.prototype.shiftLineStyles.call(this, lineIndex, offset);\n },\n\n /**\n * Figure out programatically the text on previous actual line (actual = separated by \\n);\n *\n * @param {Number} lIndex\n * @returns {String}\n * @private\n */\n _getTextOnPreviousLine: function(lIndex) {\n var textOnPreviousLine = this._textLines[lIndex - 1];\n\n while (this._styleMap[lIndex - 2] && this._styleMap[lIndex - 2].line === this._styleMap[lIndex - 1].line) {\n textOnPreviousLine = this._textLines[lIndex - 2] + textOnPreviousLine;\n\n lIndex--;\n }\n\n return textOnPreviousLine;\n },\n\n /**\n * Removes style object\n * @param {Boolean} isBeginningOfLine True if cursor is at the beginning of line\n * @param {Number} [index] Optional index. When not given, current selectionStart is used.\n */\n removeStyleObject: function(isBeginningOfLine, index) {\n\n var cursorLocation = this.get2DCursorLocation(index),\n map = this._styleMap[cursorLocation.lineIndex],\n lineIndex = map.line,\n charIndex = map.offset + cursorLocation.charIndex;\n this._removeStyleObject(isBeginningOfLine, cursorLocation, lineIndex, charIndex);\n }\n });\n})();\n\n\n(function() {\n var override = fabric.IText.prototype._getNewSelectionStartFromOffset;\n /**\n * Overrides the IText implementation and adjusts character index as there is not always a linebreak\n *\n * @param {Number} mouseOffset\n * @param {Number} prevWidth\n * @param {Number} width\n * @param {Number} index\n * @param {Number} jlen\n * @returns {Number}\n */\n fabric.IText.prototype._getNewSelectionStartFromOffset = function(mouseOffset, prevWidth, width, index, jlen) {\n index = override.call(this, mouseOffset, prevWidth, width, index, jlen);\n\n // the index passed into the function is padded by the amount of lines from _textLines (to account for \\n)\n // we need to remove this padding, and pad it by actual lines, and / or spaces that are meant to be there\n var tmp = 0,\n removed = 0;\n\n // account for removed characters\n for (var i = 0; i < this._textLines.length; i++) {\n tmp += this._textLines[i].length;\n\n if (tmp + removed >= index) {\n break;\n }\n\n if (this.text[tmp + removed] === '\\n' || this.text[tmp + removed] === ' ') {\n removed++;\n }\n }\n\n return index - i + removed;\n };\n})();\n\n\n(function() {\n\n if (typeof document !== 'undefined' && typeof window !== 'undefined') {\n return;\n }\n\n var DOMParser = require('xmldom').DOMParser,\n URL = require('url'),\n HTTP = require('http'),\n HTTPS = require('https'),\n\n Canvas = require('canvas'),\n Image = require('canvas').Image;\n\n /** @private */\n function request(url, encoding, callback) {\n var oURL = URL.parse(url);\n\n // detect if http or https is used\n if ( !oURL.port ) {\n oURL.port = ( oURL.protocol.indexOf('https:') === 0 ) ? 443 : 80;\n }\n\n // assign request handler based on protocol\n var reqHandler = (oURL.protocol.indexOf('https:') === 0 ) ? HTTPS : HTTP,\n req = reqHandler.request({\n hostname: oURL.hostname,\n port: oURL.port,\n path: oURL.path,\n method: 'GET'\n }, function(response) {\n var body = '';\n if (encoding) {\n response.setEncoding(encoding);\n }\n response.on('end', function () {\n callback(body);\n });\n response.on('data', function (chunk) {\n if (response.statusCode === 200) {\n body += chunk;\n }\n });\n });\n\n req.on('error', function(err) {\n if (err.errno === process.ECONNREFUSED) {\n fabric.log('ECONNREFUSED: connection refused to ' + oURL.hostname + ':' + oURL.port);\n }\n else {\n fabric.log(err.message);\n }\n callback(null);\n });\n\n req.end();\n }\n\n /** @private */\n function requestFs(path, callback) {\n var fs = require('fs');\n fs.readFile(path, function (err, data) {\n if (err) {\n fabric.log(err);\n throw err;\n }\n else {\n callback(data);\n }\n });\n }\n\n fabric.util.loadImage = function(url, callback, context) {\n function createImageAndCallBack(data) {\n if (data) {\n img.src = new Buffer(data, 'binary');\n // preserving original url, which seems to be lost in node-canvas\n img._src = url;\n callback && callback.call(context, img);\n }\n else {\n img = null;\n callback && callback.call(context, null, true);\n }\n }\n var img = new Image();\n if (url && (url instanceof Buffer || url.indexOf('data') === 0)) {\n img.src = img._src = url;\n callback && callback.call(context, img);\n }\n else if (url && url.indexOf('http') !== 0) {\n requestFs(url, createImageAndCallBack);\n }\n else if (url) {\n request(url, 'binary', createImageAndCallBack);\n }\n else {\n callback && callback.call(context, url);\n }\n };\n\n fabric.loadSVGFromURL = function(url, callback, reviver) {\n url = url.replace(/^\\n\\s*/, '').replace(/\\?.*$/, '').trim();\n if (url.indexOf('http') !== 0) {\n requestFs(url, function(body) {\n fabric.loadSVGFromString(body.toString(), callback, reviver);\n });\n }\n else {\n request(url, '', function(body) {\n fabric.loadSVGFromString(body, callback, reviver);\n });\n }\n };\n\n fabric.loadSVGFromString = function(string, callback, reviver) {\n var doc = new DOMParser().parseFromString(string);\n fabric.parseSVGDocument(doc.documentElement, function(results, options) {\n callback && callback(results, options);\n }, reviver);\n };\n\n fabric.util.getScript = function(url, callback) {\n request(url, '', function(body) {\n // eslint-disable-next-line no-eval\n eval(body);\n callback && callback();\n });\n };\n\n // fabric.util.createCanvasElement = function(_, width, height) {\n // return new Canvas(width, height);\n // }\n\n /**\n * Only available when running fabric on node.js\n * @param {Number} width Canvas width\n * @param {Number} height Canvas height\n * @param {Object} [options] Options to pass to FabricCanvas.\n * @param {Object} [nodeCanvasOptions] Options to pass to NodeCanvas.\n * @return {Object} wrapped canvas instance\n */\n fabric.createCanvasForNode = function(width, height, options, nodeCanvasOptions) {\n nodeCanvasOptions = nodeCanvasOptions || options;\n\n var canvasEl = fabric.document.createElement('canvas'),\n nodeCanvas = new Canvas(width || 600, height || 600, nodeCanvasOptions),\n nodeCacheCanvas = new Canvas(width || 600, height || 600, nodeCanvasOptions);\n\n // jsdom doesn't create style on canvas element, so here be temp. workaround\n canvasEl.style = { };\n\n canvasEl.width = nodeCanvas.width;\n canvasEl.height = nodeCanvas.height;\n options = options || { };\n options.nodeCanvas = nodeCanvas;\n options.nodeCacheCanvas = nodeCacheCanvas;\n var FabricCanvas = fabric.Canvas || fabric.StaticCanvas,\n fabricCanvas = new FabricCanvas(canvasEl, options);\n fabricCanvas.nodeCanvas = nodeCanvas;\n fabricCanvas.nodeCacheCanvas = nodeCacheCanvas;\n fabricCanvas.contextContainer = nodeCanvas.getContext('2d');\n fabricCanvas.contextCache = nodeCacheCanvas.getContext('2d');\n fabricCanvas.Font = Canvas.Font;\n return fabricCanvas;\n };\n\n var originaInitStatic = fabric.StaticCanvas.prototype._initStatic;\n fabric.StaticCanvas.prototype._initStatic = function(el, options) {\n el = el || fabric.document.createElement('canvas');\n this.nodeCanvas = new Canvas(el.width, el.height);\n this.nodeCacheCanvas = new Canvas(el.width, el.height);\n originaInitStatic.call(this, el, options);\n this.contextContainer = this.nodeCanvas.getContext('2d');\n this.contextCache = this.nodeCacheCanvas.getContext('2d');\n this.Font = Canvas.Font;\n };\n\n /** @ignore */\n fabric.StaticCanvas.prototype.createPNGStream = function() {\n return this.nodeCanvas.createPNGStream();\n };\n\n fabric.StaticCanvas.prototype.createJPEGStream = function(opts) {\n return this.nodeCanvas.createJPEGStream(opts);\n };\n\n fabric.StaticCanvas.prototype._initRetinaScaling = function() {\n if (!this._isRetinaScaling()) {\n return;\n }\n\n this.lowerCanvasEl.setAttribute('width', this.width * fabric.devicePixelRatio);\n this.lowerCanvasEl.setAttribute('height', this.height * fabric.devicePixelRatio);\n this.nodeCanvas.width = this.width * fabric.devicePixelRatio;\n this.nodeCanvas.height = this.height * fabric.devicePixelRatio;\n this.contextContainer.scale(fabric.devicePixelRatio, fabric.devicePixelRatio);\n return this;\n };\n if (fabric.Canvas) {\n fabric.Canvas.prototype._initRetinaScaling = fabric.StaticCanvas.prototype._initRetinaScaling;\n }\n\n var origSetBackstoreDimension = fabric.StaticCanvas.prototype._setBackstoreDimension;\n fabric.StaticCanvas.prototype._setBackstoreDimension = function(prop, value) {\n origSetBackstoreDimension.call(this, prop, value);\n this.nodeCanvas[prop] = value;\n return this;\n };\n if (fabric.Canvas) {\n fabric.Canvas.prototype._setBackstoreDimension = fabric.StaticCanvas.prototype._setBackstoreDimension;\n }\n\n})();\n\n"]}