{"version":3,"file":"fabric.js","names":["fabric","version","exports","define","amd","document","window","HTMLDocument","Document","implementation","createHTMLDocument","jsdom","require","virtualWindow","JSDOM","decodeURIComponent","features","FetchExternalResources","resources","jsdomImplForWrapper","implForWrapper","nodeCanvas","Canvas","DOMParser","isTouchSupported","navigator","maxTouchPoints","isLikelyNode","Buffer","SHARED_ATTRIBUTES","DPI","reNum","commaWsp","rePathCommand","reNonWord","fontPaths","iMatrix","svgNS","perfLimitSizeTotal","maxCacheSideLimit","minCacheSideLimit","charWidthsCache","textureSize","disableStyleCopyPaste","enableGLFiltering","devicePixelRatio","webkitDevicePixelRatio","mozDevicePixelRatio","browserShadowBlurConstant","arcToSegmentsCache","boundsOfCurveCache","cachesBoundsOfCurve","forceGLPutImageData","initFilterBackend","isWebglSupported","console","log","maxTextureSize","WebglFilterBackend","tileSize","Canvas2dFilterBackend","_removeEventListener","eventName","handler","this","__eventListeners","eventListener","indexOf","util","array","fill","on","arguments","length","prop","push","_once","_handler","apply","off","bind","once","call","fire","options","listenersForEvent","i","len","filter","value","Observable","Collection","_objects","add","_onObjectAdded","renderOnAddRemove","requestRenderAll","insertAt","object","index","nonSplicing","objects","splice","remove","somethingRemoved","_onObjectRemoved","forEachObject","callback","context","getObjects","type","concat","o","item","isEmpty","size","contains","deep","some","obj","complexity","reduce","memo","current","CommonMethods","_setOptions","set","_initGradient","filler","property","colorStops","Gradient","_initPattern","source","Pattern","_setObject","_set","key","toggle","get","global","sqrt","Math","atan2","pow","PiBy180","PI","PiBy2","cos","angle","angleSlice","sin","sign","removeFromArray","idx","getRandomInt","min","max","floor","random","degreesToRadians","degrees","radiansToDegrees","radians","rotatePoint","point","origin","newPoint","Point","x","y","v","rotateVector","addEquals","vector","rx","ry","createVector","from","to","calcAngleBetweenVectors","a","b","acos","hypot","getHatVector","multiply","getBisector","A","B","C","AB","AC","alpha","ro","phi","projectStrokeOnPoints","points","openPath","coords","s","strokeWidth","strokeUniformScalar","strokeUniform","scaleX","scaleY","getStrokeHatVector","scalar","forEach","p","bisector","bisectorVector","miterVector","strokeLineJoin","strokeMiterLimit","subtract","SQRT2","transformPoint","t","ignoreOffset","makeBoundingBoxFromPoints","transform","xPoints","minX","maxX","width","yPoints","minY","maxY","height","left","top","invertTransform","r","toFixed","number","fractionDigits","parseFloat","Number","parseUnit","fontSize","unit","exec","Text","DEFAULT_SVG_FONT_SIZE","falseFunction","getKlass","namespace","string","camelize","charAt","toUpperCase","slice","resolveNamespace","getSvgAttributes","attributes","parts","split","loadImage","url","crossOrigin","img","createImage","onLoadCallback","onload","onerror","src","undefined","substring","loadImageInDom","div","createElement","style","position","appendChild","querySelector","parentNode","removeChild","enlivenObjects","reviver","enlivenedObjects","numLoadedObjects","numTotalObjects","onLoaded","klass","fromObject","error","enlivenObjectEnlivables","enlivenProps","Object","ENLIVEN_PROPS","map","enlivedProps","enlivenPatterns","patterns","numLoadedPatterns","numPatterns","enlivenedPatterns","pattern","groupSVGElements","elements","path","sourcePath","centerPoint","Group","populateWithProperties","destination","properties","Array","isArray","createCanvasElement","copyCanvasElement","canvas","newCanvas","getContext","willReadFrequently","drawImage","toDataURL","canvasEl","format","quality","multiplyTransformMatrices","is2x2","qrDecompose","denom","skewX","skewY","translateX","translateY","calcRotateMatrix","theta","calcDimensionsMatrix","scaleMatrix","flipX","flipY","tan","composeMatrix","matrix","resetObjectTransform","target","rotate","saveObjectTransform","isTransparent","ctx","tolerance","_isTransparent","temp","imageData","getImageData","l","data","parsePreserveAspectRatioAttribute","attribute","meetOrSlice","alignX","alignY","aspectRatioAttrs","align","pop","clearFabricFontCache","fontFamily","toLowerCase","limitDimsByArea","ar","maximumArea","roughWidth","perfLimitSizeY","capValue","findScaleToFit","findScaleToCover","matrixToSVG","NUM_FRACTION_DIGITS","join","removeTransformFromObject","inverted","finalTransform","calcOwnMatrix","applyTransformToObject","addTransformToObject","center","setPositionByOrigin","sizeAfterTransform","dimX","dimY","transformMatrix","bbox","mergeClipPaths","c1","c2","calcTransformMatrix","clipPath","hasStyleChanged","prevStyle","thisStyle","forTextSpans","stroke","fontWeight","fontStyle","textBackgroundColor","deltaY","overline","underline","linethrough","stylesToArray","styles","text","clone","textLines","charIndex","stylesArray","c","keys","styleChanged","start","end","stylesFromArray","styleIndex","stylesObject","assign","_join","prototype","commandLengths","m","h","q","repeatedCommands","M","segmentToBezier","th2","th3","cosTh","sinTh","cx1","cy1","mT","fromX","fromY","costh2","sinth2","costh3","sinth3","toX","toY","cp1X","cp1Y","cp2X","cp2Y","arcToSegments","large","sweep","rotateX","th","abs","px","py","rx2","ry2","py2","px2","pl","root","cx","cy","mTheta","calcVectorAngle","dtheta","segments","ceil","result","mDelta","ux","uy","vx","vy","ta","tb","getBoundsOfCurve","x0","y0","x1","y1","x2","y2","x3","y3","argsString","tvalues","bounds","t1","t2","b2ac","sqrtb2ac","j","jlen","mt","fromArcToBeziers","fx","fy","rot","tx","ty","segsNorm","makePathSimpler","converted","destinationPath","previous","controlX","controlY","calcLineLength","CB1","CB2","CB3","CB4","getPointOnCubicBezierIterator","p1x","p1y","p2x","p2y","p3x","p3y","p4x","p4y","pct","c3","c4","getTangentCubicIterator","invT","tangentX","tangentY","QB1","QB2","QB3","getPointOnQuadraticBezierIterator","getTangentQuadraticIterator","pathIterator","iterator","tempP","tmpLen","perc","findPercentageForDistance","segInfo","distance","nextLen","nextStep","angleFinder","lastPerc","getPathSegmentsInfo","totalLength","info","tempInfo","command","destX","destY","getPointOnPath","infos","segPercent","segment","lerp","parsePath","pathString","currentPath","parsed","re","rNumber","rNumberCommaWsp","rFlagCommaWsp","rArcSeq","regArcArgumentSequence","RegExp","match","coordsStr","coordsParsed","trim","args","isNaN","commandLength","repeatedCommand","k","klen","getSmoothPathFromPoints","correction","p1","p2","multSignX","multSignY","manyPoints","eq","midPoint","midPointFrom","transformPath","pathOffset","pathSegment","newSegment","joinPath","pathData","invoke","method","byProperty","find","value1","value2","condition","extend","Element","hasOwnProperty","replace","character","capitalize","firstLetterOnly","escapeXml","graphemeSplit","textstring","chr","graphemes","getWholeChar","str","code","charCodeAt","next","prev","emptyFunction","IS_DONTENUM_BUGGY","toString","addMethods","parent","superclass","constructor","returnValue","valueOf","Subclass","callSuper","methodName","parentMethod","_this","superClassMethod","createClass","shift","initialize","subclasses","couldUseAttachEvent","attachEvent","touchEvents","addListener","element","addEventListener","removeListener","removeEventListener","getTouchInfo","event","touchProp","changedTouches","getPointer","scroll","getScrollLeftTop","_evt","clientX","clientY","isTouchEvent","pointerType","setStyle","elementStyle","cssText","setOpacity","normalizedProperty","styleFloat","setProperty","parseEl","supportsOpacity","opacity","supportsFilters","reOpacity","es","currentStyle","hasLayout","zoom","test","_slice","getById","id","getElementById","sliceCanConvertNodelists","toArray","arrayLike","childNodes","err","arr","makeElement","tagName","el","className","htmlFor","setAttribute","addClass","wrapElement","wrapper","replaceChild","docElement","documentElement","body","scrollLeft","scrollTop","host","nodeType","getElementOffset","docElem","doc","ownerDocument","box","offset","scrollLeftTop","offsetAttributes","borderLeftWidth","borderTopWidth","paddingLeft","paddingTop","attr","parseInt","getElementStyle","getBoundingClientRect","clientLeft","clientTop","defaultView","getComputedStyle","selectProp","makeElementUnselectable","onselectstart","unselectable","makeElementSelectable","getNodeCanvas","impl","_canvas","_image","cleanUpJsdomNode","_currentSrc","_attributes","_classList","setImageSmoothing","imageSmoothingEnabled","webkitImageSmoothingEnabled","mozImageSmoothingEnabled","msImageSmoothingEnabled","oImageSmoothingEnabled","addParamToUrl","param","emptyFn","request","onComplete","xhr","XMLHttpRequest","parameters","onreadystatechange","readyState","open","setRequestHeader","send","warn","message","RUNNING_ANIMATIONS","cancelAll","animations","animation","cancel","cancelByCanvas","cancelled","cancelByTarget","findAnimationsByTarget","findAnimationIndex","cancelFunc","findAnimation","noop","defaultEasing","d","animate","removeFromRegistry","runningAnimations","currentValue","startValue","completionRate","durationRate","requestAnimFrame","timestamp","Date","duration","finish","time","onChange","abort","easing","isMany","endValue","byValue","onStart","tick","ticktime","currentTime","timePerc","_value","valuePerc","_requestAnimFrame","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","setTimeout","_cancelAnimFrame","cancelAnimationFrame","clearTimeout","cancelAnimFrame","calculateColor","begin","pos","color","animateColor","fromColor","toColor","startColor","Color","getSource","endColor","originalOnComplete","originalOnChange","posValue","colorEasing","normalize","asin","elastic","opts","easeOutCubic","easeInOutCubic","easeInQuart","easeOutQuart","easeInOutQuart","easeInQuint","easeOutQuint","easeInOutQuint","easeInSine","easeOutSine","easeInOutSine","easeInExpo","easeOutExpo","easeInOutExpo","easeInCirc","easeOutCirc","easeInOutCirc","easeInElastic","easeOutElastic","easeInOutElastic","easeInBack","easeOutBack","easeInOutBack","easeInBounce","easeOutBounce","easeInOutBounce","ease","easeInQuad","easeOutQuad","easeInOutQuad","easeInCubic","svgValidTagNames","svgViewBoxElements","svgInvalidAncestors","svgValidParents","attributesMap","display","visibility","colorAttributes","fSize","cPath","svgValidTagNamesRegEx","getSvgRegex","svgViewBoxElementsRegEx","svgInvalidAncestorsRegEx","svgValidParentsRegEx","cssRules","gradientDefs","clipPaths","normalizeAttr","normalizeValue","parentAttributes","parseTransformAttribute","visible","fillIndex","strokeIndex","_setStrokeFillOpacity","setAlpha","getAlpha","toRgba","_getMultipleNodes","nodeNames","nodeName","nodeArray","nodeList","getElementsByTagName","rotateMatrix","multiplierX","multiplierY","skewMatrix","translateMatrix","scale","translate","transforms","transformList","reTransformList","reTransform","attributeValue","matrices","operation","combinedMatrix","parseStyleString","oStyle","chunk","pair","parseStyleObject","getGlobalStylesForElement","svgUid","rule","elementMatchesRule","selectors","firstMatching","parentMatching","selectorMatches","doesSomeParentMatch","selector","classNames","getAttribute","matcher","elementById","node","nodelist","parseUseDirectives","xlinkAttribute","xlink","el2","cloneNode","currentTrans","oldLength","attrs","applyViewboxTransform","el3","createElementNS","setAttributeNS","nodeValue","firstChild","removeAttribute","reViewBoxAttrValue","viewBoxAttr","viewBoxWidth","viewBoxHeight","widthAttr","heightAttr","preserveAspectRatio","missingViewBox","missingDimAttr","toBeParsed","parsedDim","widthDiff","heightDiff","hasAncestorWithNodeName","parseSVGDocument","parsingOptions","__uid","descendants","selectNodes","getGradientDefs","getCSSRules","parseElements","instances","recursivelyParseGradientsXlink","gradient","gradientsAttrs","xlinkAttr","xLink","referencedGradient","hasAttribute","children","referenceClone","reFontDeclaration","parseFontDeclaration","lineHeight","tagArray","elList","parseAttributes","parentFontSize","ownAttributes","cssAttrs","parseStyleAttribute","normalizedAttr","normalizedValue","normalizedStyle","font","mergedAttrs","ElementsParser","parse","parsePointsAttribute","parsedPoints","allRules","rules","styleContents","textContent","ruleObj","declaration","propertyValuePairs","_rule","loadSVGFromURL","xml","responseXML","results","_options","allElements","loadSVGFromString","parser","parseFromString","regexUrl","proto","numElements","createObjects","createObject","findTag","fromElement","createCallback","checkIfDone","resolveGradient","Image","_originalElement","_removeTransformMatrix","resolveClipPath","extractPropertyDefinition","storage","regex","lastIndex","gradientDef","opacityAttr","createClipPathCallback","container","_newObj","fillRule","clipRule","usingElement","objTransformInv","gTransform","clipPathTag","clipPathOwner","that","scalarAdd","scalarAddEquals","subtractEquals","scalarSubtract","scalarSubtractEquals","multiplyEquals","divide","divideEquals","lt","lte","gt","gte","distanceFrom","dx","dy","setXY","setX","setY","setFromPoint","swap","Intersection","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","setSource","_tryParsingColor","colorNameMap","sourceFromHex","sourceFromRgb","sourceFromHsl","_rgbToHsl","g","round","_source","toRgb","toHsl","hsl","toHsla","toHex","toHexa","toGrayscale","average","currentAlpha","toBlackWhite","threshold","overlayWith","otherColor","otherAlpha","otherSource","reRGBa","reHSLa","reHex","aliceblue","antiquewhite","aqua","aquamarine","EntraID","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgrey","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgrey","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen","hue2rgb","fromRgb","fromSource","fromRgba","fromHsl","fromHsla","fromHex","isShortNotation","isRGBa","oColor","scaleMap","skewMap","controls","LEFT","TOP","RIGHT","BOTTOM","CENTER","opposite","bottom","right","findCornerQuadrant","fabricObject","control","cornerAngle","fireEvent","canvasOptions","scaleIsProportional","eventData","uniScaleKey","uniformIsToggled","uniformScaling","isTransformCentered","originX","originY","scalingIsForbidden","by","scaleProportionally","lockX","lockScalingX","lockY","lockScalingY","scaleCursorStyleHandler","notAllowed","n","skewCursorStyleHandler","lockSkewingY","lockSkewingX","scaleSkewCursorStyleHandler","altActionKey","scaleOrSkewActionName","isAlternative","rotationStyleHandler","lockRotation","cursorStyle","commonEventInfo","e","pointer","wrapWithFixedAnchor","actionHandler","getCenterPoint","constraint","translateToOriginPoint","actionPerformed","wrapWithFireEvent","getLocalPoint","corner","getZoom","padding","localPoint","toLocalPoint","offsetX","offsetY","targetHasOneFlip","compensateScaleForSkew","oppositeSkew","scaleToCompensate","axis","reference","newDim","_getTransformedDimensions","newValue","skewObjectX","dimNoSkew","totalSkewSize","currentSkew","newSkew","hasSkewed","dimBeforeSkewing","skewObjectY","skewHandlerX","localPointFromCenter","finalHandler","skewHandlerY","rotationWithSnapping","pivotPoint","lastAngle","ey","ex","curAngle","hasRotated","snapAngle","snapThreshold","rightAngleLocked","leftAngleLocked","scaleObject","dim","forbidScaling","signX","signY","gestureScale","lockScalingFlip","original","originalDistance","oldScaleX","oldScaleY","scaleObjectFromCorner","scaleObjectX","scaleObjectY","scalingYOrSkewingX","scalingY","scalingXOrSkewingY","scalingX","changeWidth","strokePadding","multiplier","oldWidth","newWidth","dragHandler","newLeft","newTop","moveX","moveY","scalingEqually","controlsUtils","renderCircleControl","styleOverride","xSize","sizeX","cornerSize","ySize","sizeY","transparentCorners","cornerStrokeColor","myLeft","myTop","save","fillStyle","cornerColor","strokeStyle","lineWidth","beginPath","arc","restore","renderSquareControl","xSizeBy2","ySizeBy2","strokeRect","Control","actionName","touchSizeX","touchSizeY","withConnection","mouseDownHandler","mouseUpHandler","getActionHandler","getMouseDownHandler","getMouseUpHandler","cursorStyleHandler","getActionName","getVisibility","controlKey","objectVisibility","_controlsVisibility","setVisibility","positionHandler","finalMatrix","calcCornerCoords","objectAngle","objectCornerSize","centerX","centerY","isTouch","cosHalfOffset","sinHalfOffset","cosHalfOffsetComp","sinHalfOffsetComp","controlTriangleAngle","cornerHypotenuse","newTheta","newThetaComp","tl","tr","bl","br","render","cornerStyle","getColorStop","colorAlpha","keyValuePairs","getLinearCoords","getRadialCoords","gradientTransform","gradientUnits","option","addColorStop","toObject","propertiesToInclude","toSVG","markup","commonAttributes","needsSwap","withViewport","additionalTransform","sort","reverse","minRadius","maxRadius","percentageShift","colorStop","toLive","createLinearGradient","createRadialGradient","instance","svgOptions","colorStopEls","__convertPercentUnitsToValues","propValue","finalValue","repeat","patternTransform","setOptions","isError","patternSource","patternWidth","patternHeight","patternOffsetX","patternOffsetY","patternImgSrc","complete","naturalWidth","naturalHeight","createPattern","Shadow","blur","affectStroke","includeDefaultValues","nonScaling","_parseShadow","shadow","shadowStr","offsetsAndBlur","reOffsetsAndBlur","fBoxX","fBoxY","BLUR_BOX","StaticCanvas","CANVAS_INIT_ERROR","Error","renderAndResetBound","renderAndReset","requestRenderAllBound","_initStatic","backgroundColor","backgroundImage","overlayColor","overlayImage","stateful","controlsAboveOverlay","allowTouchScrolling","viewportTransform","backgroundVpt","overlayVpt","enableRetinaScaling","vptCoords","skipOffscreen","cb","_createLowerCanvas","_initOptions","interactive","_initRetinaScaling","setOverlayImage","setBackgroundImage","setBackgroundColor","setOverlayColor","calcOffset","_isRetinaScaling","getRetinaScaling","scaleRatio","__initRetinaScaling","lowerCanvasEl","contextContainer","upperCanvasEl","contextTop","_offset","image","__setBgOverlayImage","__setBgOverlayColor","_createCanvasElement","_originalCanvasStyle","_applyCanvasStyle","getWidth","getHeight","setWidth","setDimensions","setHeight","dimensions","cssValue","cssOnly","_setBackstoreDimension","hasLostContext","backstoreOnly","_setCssDimension","_isCurrentlyDrawing","freeDrawingBrush","_setBrushStyles","cacheCanvasEl","wrapperEl","setViewportTransform","vpt","activeObject","_activeObject","backgroundObject","overlayObject","group","setCoords","calcViewportBoundaries","zoomToPoint","before","after","setZoom","absolutePan","relativePan","getElement","setupState","clearContext","clearRect","clear","_hasITextHandlers","_mouseUpITextHandler","_iTextInstances","renderAll","canvasToDrawOn","renderCanvas","isRendering","iVpt","cancelRequestedRender","_renderBackground","_renderObjects","drawControls","shouldCache","_transformDone","renderCache","forClipping","drawClipPathOnCanvas","_renderOverlay","globalCompositeOperation","zoomX","zoomY","_cacheCanvas","cacheTranslationX","cacheTranslationY","_renderBackgroundOrOverlay","needsVpt","moveTo","lineTo","closePath","getCenter","centerObjectH","_centerObject","centerObjectV","centerObject","viewportCenterObject","vpCenter","getVpCenter","viewportCenterObjectH","viewportCenterObjectV","toDatalessJSON","toDatalessObject","_toObjectMethod","_toObjects","excludeFromExport","_toObject","__serializeBgOverlay","originalValue","bgImage","bgColor","background","overlay","svgViewportTransformation","_setSVGPreamble","_setSVGHeader","clipPathId","_setSVGBgOverlayColor","_setSVGBgOverlayImage","_setSVGObjects","suppressPreamble","encoding","viewBox","createSVGFontFacesMarkup","createSVGRefElementsMarkup","createSVGClipPathMarkup","toClipPathSVG","shouldTransform","fontList","row","rowIndex","_char","_setSVGObject","finalWidth","finalHeight","shouldInvert","sendToBack","activeSelection","objs","unshift","bringToFront","sendBackwards","intersecting","newIdx","objsMoved","_findNewLowerIndex","isIntersecting","intersectsWithObject","isContainedWithinObject","bringForward","_findNewUpperIndex","dispose","classList","DataURLExporter","EMPTY_JSON","supports","setLineDash","toJSON","createPNGStream","createJPEGStream","BaseBrush","strokeLineCap","strokeDashArray","limitedToCanvasSize","lineCap","miterLimit","lineJoin","_saveAndTransform","_setShadow","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY","needsFullRender","_resetShadow","_isOutSideCanvas","PencilBrush","decimate","drawStraightLine","straightLineKey","_points","_hasStraightLine","_drawSegment","quadraticCurveTo","onMouseDown","_isMainEvent","_prepareForDrawing","_captureDrawingPath","_render","onMouseMove","oldEnd","onMouseUp","_finalizeAndAddPath","_reset","_addPoint","pointerPoint","convertPointsToSVGPath","_isEmptySVGPath","createPath","Path","decimatePoints","adjustedDistance","lastPoint","newPoints","cDistance","CircleBrush","drawDot","addPoint","dot","radius","originalRenderOnAddRemove","circles","circle","Circle","circleRadius","circleColor","SprayBrush","density","dotWidth","dotWidthVariance","randomOpacity","optimizeOverlapping","sprayChunks","addSprayChunk","sprayChunkPoints","rects","ilen","sprayChunk","rect","Rect","_getOptimizedRects","uniqueRects","uniqueRectsArray","globalAlpha","fillRect","PatternBrush","getPatternSrc","dotDistance","patternCanvas","patternCtx","getPatternSrcFunction","String","getPattern","topLeft","_getLeftTopCoords","_initInteractive","_createCacheCanvas","centeredScaling","centeredRotation","centeredKey","selection","selectionKey","altSelectionKey","selectionColor","selectionDashArray","selectionBorderColor","selectionLineWidth","selectionFullyContained","hoverCursor","moveCursor","defaultCursor","freeDrawingCursor","notAllowedCursor","containerClass","perPixelTargetFind","targetFindTolerance","skipTargetFind","isDrawingMode","preserveObjectStacking","stopContextMenu","fireRightClick","fireMiddleClick","targets","enablePointerEvents","_hoveredTarget","_hoveredTargets","_currentTransform","_groupSelector","_initWrapperElement","_createUpperCanvas","_initEventListeners","_chooseObjectsToRender","activeObjects","getActiveObjects","objsToRender","activeGroupObjects","contextTopDirty","renderTopLayer","_drawSelection","renderTop","_normalizePointer","invertedM","vptPointer","restorePointerVpt","isTargetTransparent","normalizedPointer","targetRelativeX","targetRelativeY","_cacheContext","contextCache","originalColor","selectionBackgroundColor","_isSelectionKeyPressed","selectionKeyPressed","_shouldClearSelection","evented","selectable","_shouldCenterTransform","action","altKey","centerTransform","_getOriginFromCorner","_getActionFromCorner","alreadySelected","_setupCurrentTransform","__corner","lastX","lastY","shiftKey","_beforeTransform","setCursor","cursor","viewportStart","viewportExtent","extent","strokeOffset","_setLineDash","findTarget","skipGroup","ignoreZoom","aObjects","activeTarget","activeTargetSubs","shouldLookForActive","_findTargetCorner","_searchPossibleTargets","_checkTarget","globalPointer","containsPoint","isEditing","subTarget","objToCheck","pointerToUse","subTargetCheck","_absolutePointer","_pointer","boundsWidth","boundsHeight","cssScale","retinaScaling","lowerCanvasClass","_copyCanvasStyle","getTopContext","class","fromEl","toEl","getSelectionContext","getSelectionElement","getActiveObject","active","_discardActiveObject","_fireSelectionEvents","oldObjects","somethingChanged","added","removed","oldObject","selected","deselected","setActiveObject","currentActives","_setActiveObject","onSelect","onDeselect","discardActiveObject","removeListeners","_renderControls","originalProperties","_realizeGroupTransformOnObject","_unwindGroupTransformOnObject","layoutProps","originalValues","clearContextTop","RIGHT_CLICK","MIDDLE_CLICK","LEFT_CLICK","addEventOptions","passive","checkClick","button","mainTouchId","_bindEvents","addOrRemove","_getEventPrefix","functor","eventjsFunctor","canvasElement","eventTypePrefix","_onResize","_onMouseDown","_onMouseMove","_onMouseOut","_onMouseEnter","_onMouseWheel","_onContextMenu","_onDoubleClick","_onDragOver","_onDragEnter","_onDragLeave","_onDrop","_onTouchStart","eventjs","_onGesture","_onDrag","_onOrientationChange","_onShake","_onLongPress","_onMouseUp","_onTouchEnd","eventsBound","_simpleEventHandler","self","__onTransformGesture","__onDrag","__onMouseWheel","_target","__onOrientationChange","__onShake","__onLongPress","preventDefault","_fireEnterLeaveEvents","stopPropagation","_cacheTransformEventData","_handleEvent","_resetTransformEventData","getPointerId","evt","identifier","pointerId","isPrimary","touches","__onMouseDown","__onMouseUp","_willAddMouseDown","__onMouseMove","_shouldRender","groupSelector","shouldRender","isClick","_onMouseUpInDrawingMode","_finalizeCurrentTransform","targetWasActive","_maybeGroupObjects","activeOn","isMoving","originalControl","originalMouseUpHandler","_setCursorFromEvent","eventType","subTargets","absolutePointer","currentTarget","currentSubTargets","_scaling","hasStateChanged","_fire","_onMouseDownInDrawingMode","_onMouseMoveInDrawingMode","_previousPointer","shouldGroup","_shouldGroup","_handleGrouping","saveState","_fireOverOutEvents","_transformObject","fireSyntheticInOutEvents","oldTarget","evtOut","canvasEvtOut","evtIn","canvasEvtIn","_draggedoverTarget","config","inOpt","outOpt","outFires","inFires","targetChanged","previousTarget","nextTarget","reset","_performTransformAction","getCornerCursor","_updateActiveSelection","_createActiveSelection","currentActiveObjects","removeWithUpdate","addWithUpdate","_createGroup","isActiveLower","groupObjects","exitEditing","ActiveSelection","_groupSelectedObjects","_collectObjects","aGroup","currentObject","selectionX1Y1","selectionX2Y2","allowIntersect","intersectsWithRect","isContainedWithinRect","toCanvasElement","cropping","scaledWidth","scaledHeight","originalWidth","originalHeight","newZoom","vp","originalInteractive","newVp","originalRetina","originalContextTop","loadFromJSON","json","serialized","JSON","_enlivenObjects","_setBgOverlay","enlivenedCanvasClip","__setupCanvas","loaded","cbIfLoaded","__setBgOverlay","enlivedObject","_toDataURL","_toDataURLWithMultiplier","toDataURLWithMultiplier","stringify","cloneWithoutData","backgroundImageOpacity","backgroundImageStretch","objectCaching","ALIASING_LIMIT","touchCornerSize","borderColor","borderDashArray","cornerDashArray","strokeDashOffset","borderOpacityWhenMoving","borderScaleFactor","minScaleLimit","hasControls","hasBorders","lockMovementX","lockMovementY","statefullCache","noScaleCache","dirty","paintFirst","stateProperties","cacheProperties","colorProperties","absolutePositioned","_cacheProperties","_updateCacheCanvas","_limitCacheSize","dims","limitedDims","capped","_getCacheCanvasDimensions","objectScale","getTotalObjectScaling","neededX","neededY","targetCanvas","minCacheSize","drawingWidth","drawingHeight","dimensionsChanged","cacheWidth","cacheHeight","zoomChanged","shouldRedraw","additionalWidth","additionalHeight","shouldResizeCanvas","canvasWidth","canvasHeight","sizeGrowing","sizeShrinking","getHeightOfLine","setTransform","needFullTransform","_removeDefaultValues","getObjectScaling","retina","getObjectOpacity","shouldConstrainValue","isChanged","groupNeedsUpdate","_constrainScale","isOnACache","setOnGroup","getViewportTransform","isNotVisible","isOnScreen","_setupCompositeOperation","drawSelectionBackground","_setOpacity","drawCacheOnCanvas","_removeCacheCanvas","drawObject","propertySet","isCacheDirty","hasStroke","hasFill","needsItsOwnCache","ownCaching","willDrawShadow","drawClipPathOnCache","originalFill","originalStroke","_setClippingProperties","_drawClipPath","skipCanvas","_getNonTransformedDimensions","_removeShadow","_setStrokeStyles","decl","lineDashOffset","_applyPatternForTransformedGradient","_applyPatternGradientTransform","_setFillStyles","dashArray","drawBorders","forActiveSelection","drawBordersInGroup","scaling","multX","multY","_renderPaintInOrder","_renderStroke","_renderFill","pCanvas","pCtx","_findCenterFromElement","_assignTransformMatrixProps","preserveAspectRatioOptions","cropX","cropY","offsetLeft","offsetTop","objectForm","_fromObject","cloneAsImage","utils","origParams","originalGroup","originalShadow","withoutTransform","withoutShadow","boundingRect","getBoundingRect","shadowOffset","originalCanvas","isType","includes","shouldCenterOrigin","_setOriginToCenter","_resetOrigin","centerH","viewportCenterH","centerV","viewportCenterV","viewportCenter","getLocalPointer","pClicked","objectLeftTop","createAccessors","extraParam","originXOffset","originYOffset","translateToGivenOrigin","fromOriginX","fromOriginY","toOriginX","toOriginY","translateToCenterPoint","leftTop","getPointByOrigin","adjustPosition","hypotFull","getScaledWidth","xFull","yFull","offsetFrom","offsetTo","_originalOriginX","_originalOriginY","originPoint","arrayFromCoords","multiplyMatrices","oCoords","aCoords","lineCoords","ownMatrixCache","matrixCache","_getCoords","absolute","calculate","calcACoords","calcLineCoords","getCoords","pointTL","pointBR","intersection","other","otherCoords","lines","_getImageLines","_findCrossPoints","_containsCenterOfCanvas","isPartiallyOnScreen","allPointsAreOutside","every","topline","rightline","bottomline","leftline","xi","xcount","iLine","lineKey","getScaledHeight","scaleToWidth","boundingRectFactor","scaleToHeight","cosP","sinP","cosPSinP","cosPMinusSinP","calcOCoords","_calcRotateMatrix","_calcTranslateMatrix","startMatrix","_calculateCurrentDimensions","forEachControl","w","skipCorners","_setCornerCoords","transformMatrixKey","sep","prefix","cache","tMatrix","noSkew","_finalizeDimensions","getSvgColorString","getSvgStyles","skipShadow","getSvgFilter","getSvgSpanStyles","useWhiteSpace","term","textDecoration","getSvgTextDecoration","decoration","getSvgCommons","getSvgTransform","full","svgTransform","_setSVGBg","textBgRects","_getFillAttributes","_createBaseSVGMarkup","_toSVG","_createBaseClipPathSVGMarkup","objectMarkup","commonPieces","noStyle","styleInfo","shadowInfo","withShadow","vectorEffect","absoluteClipPath","clipPathMarkup","addPaintOrder","originalSet","saveProps","props","tmpObj","_isEqual","origValue","firstPass","dashedPropertySet","forTouch","isControlVisible","touchCorner","fn","controlObject","wh","shouldStroke","setControlVisible","setControlsVisibility","FX_DURATION","fxCenterObjectH","callbacks","empty","fxCenterObjectV","fxRemove","propsToAnimate","skipCallbacks","out","_animate","propPair","propIsColor","valueProgress","timeProgress","coordProps","Line","_setWidthHeight","_getLeftToOriginX","_getTopToOriginY","makeEdgeToOriginGetter","axis1","axis2","dimension","nearest","farthest","calcLinePoints","origStrokeStyle","xMult","yMult","ATTRIBUTE_NAMES","parsedAttributes","_callback","propertyNames","originValues","startAngle","endAngle","setRadius","svgString","startX","startY","endX","endY","largeFlag","getRadiusX","getRadiusY","isValidRadius","Triangle","widthBy2","heightBy2","piBy2","Ellipse","getRx","getRy","_initRxRy","isRounded","bezierCurveTo","Polyline","exactBoundingBox","_setPositionDimensions","_projectStrokeOnPoints","calcDim","_calcDimensions","correctLeftTop","correctSize","fromSVG","diffX","diffY","commonRender","fromElementGenerator","_class","Polygon","_setPath","_renderPathCommands","subpathStartX","subpathStartY","_getOffsetTransform","digits","aX","aY","deltaX","pathUrl","elivenedObjects","useSetOnGroup","isAlreadyGrouped","_calcBounds","_updateObjectsCoords","_updateObjectsACoords","skipControls","_updateObjectCoords","objectLeft","objectTop","nested","_restoreObjectsState","_includeDefaultValues","objsToObject","originalDefaults","_obj","ownCache","groupMatrix","destroy","toActiveSelection","ungroupOnCanvas","setObjectsCoords","onlyWidthHeight","iLen","jLen","_getBounds","minXY","maxXY","toGroup","newGroup","childrenOverride","srcFromAttribute","_lastScaleX","_lastScaleY","_filterScalingX","_filterScalingY","minimumScaleTrigger","cacheKey","imageSmoothing","filters","_initElement","_element","setElement","removeTexture","_initConfig","applyFilters","resizeFilter","applyResizeFilters","backend","filterBackend","evictCachesForKey","getCrossOrigin","getOriginalSize","_stroke","filterObj","getSrc","hasCrop","imageMarkup","strokeSvg","imageRendering","getSvgSrc","origFill","filtered","setSrc","minimumScale","elementToFilter","_filteredEl","sourceWidth","sourceHeight","isNeutralState","imgElement","_needsResize","elementToDraw","elWidth","elHeight","sX","sY","sW","sH","maxDestW","maxDestH","_resetWidthHeight","CSS_CANVAS","_initFilters","pAR","rWidth","rHeight","pWidth","pHeight","_object","resizeFilters","fromURL","imgOptions","_getAngleValueForStraighten","straighten","fxStraighten","straightenObject","fxStraightenObject","testPrecision","gl","precision","fragmentSource","fragmentShader","createShader","FRAGMENT_SHADER","shaderSource","compileShader","getShaderParameter","COMPILE_STATUS","isSupported","getParameter","MAX_TEXTURE_SIZE","precisions","webGlPrecision","setupGLContext","captureGPUInfo","createWebGLCanvas","aPosition","Float32Array","chooseFastestCopyGLTo2DMethod","canMeasurePerf","performance","canUseImageData","ImageData","canUseArrayBuffer","ArrayBuffer","canUseUint8Clamped","Uint8ClampedArray","imageBuffer","copyGLTo2D","copyGLTo2DPutImageData","testContext","destinationWidth","destinationHeight","startTime","drawImageTime","putImageDataTime","now","copyGLTo2DDrawImage","glOptions","premultipliedAlpha","depth","stencil","antialias","clearColor","cachedTexture","getCachedTexture","pipelineState","sourceTexture","createTexture","targetTexture","originalTexture","passes","webgl","programCache","pass","tempFbo","createFramebuffer","bindFramebuffer","FRAMEBUFFER","applyTo","resizeCanvasIfNeeded","bindTexture","TEXTURE_2D","deleteTexture","deleteFramebuffer","clearWebGLCaches","textureCache","textureImageSource","filterType","texture","texParameteri","TEXTURE_MAG_FILTER","NEAREST","TEXTURE_MIN_FILTER","TEXTURE_WRAP_S","CLAMP_TO_EDGE","TEXTURE_WRAP_T","texImage2D","RGBA","UNSIGNED_BYTE","uniqueId","gpuInfo","renderer","vendor","ext","getExtension","UNMASKED_RENDERER_WEBGL","UNMASKED_VENDOR_WEBGL","dWidth","dHeight","glCanvas","sourceY","numBytes","u8","Uint8Array","u8Clamped","readPixels","imgData","putImageData","sourceElement","originalImageData","originalEl","BaseFilter","vertexSource","createProgram","vertexShader","VERTEX_SHADER","getShaderInfoLog","program","attachShader","linkProgram","getProgramParameter","LINK_STATUS","getProgramInfoLog","attributeLocations","getAttributeLocations","uniformLocations","getUniformLocations","uStepW","getUniformLocation","uStepH","getAttribLocation","sendAttributeData","aPositionData","attributeLocation","buffer","createBuffer","bindBuffer","ARRAY_BUFFER","enableVertexAttribArray","vertexAttribPointer","FLOAT","bufferData","STATIC_DRAW","_setupFrameBuffer","framebufferTexture2D","COLOR_ATTACHMENT0","_swapTextures","main","mainParameter","applyToWebGL","applyTo2d","retrieveShader","shader","useProgram","uniform1f","sendUniformData","viewport","drawArrays","TRIANGLE_STRIP","bindAdditionalTexture","textureUnit","activeTexture","TEXTURE0","unbindAdditionalTexture","getMainParameter","setMainParameter","createHelpLayer","helpLayer","mainP","ColorMatrix","colorsOnly","uColorMatrix","uConstants","constants","uniformMatrix4fv","uniform4fv","Brightness","brightness","uBrightness","Convolute","opaque","Convolute_3_1","Convolute_3_0","Convolute_5_1","Convolute_5_0","Convolute_7_1","Convolute_7_0","Convolute_9_1","Convolute_9_0","weights","side","halfSide","sw","sh","output","createImageData","dst","alphaFac","dstOff","scx","scy","srcOff","wt","uMatrix","uOpaque","uHalfSize","uSize","uniform1fv","Grayscale","lightness","luminosity","mode","uMode","uniform1i","Invert","invert","uInvert","Noise","noise","rand","uNoise","uSeed","Pixelate","blocksize","_i","_j","_iLen","_jLen","uBlocksize","RemoveColor","useAlpha","lowC","highC","uLow","uHigh","Brownie","Vintage","Kodachrome","Technicolor","Polaroid","Sepia","BlackWhite","BlendColor","screen","diff","lighten","darken","exclusion","tint","buildSource","tg","alpha1","uColor","BlendImage","mask","TEXTURE1","calculateMatrix","canvas1","blendData","blendImage","uTransformMatrix","uImage","uniformMatrix3fv","Resize","resizeType","lanczosLobes","uDelta","uTaps","uniform2fv","horizontal","taps","filterWindow","getFilterWindow","generateShader","tempScale","getTaps","lobeFunction","lanczosCreate","offsets","fragmentSourceTOP","dW","dH","lobes","xx","rcpScaleX","rcpScaleY","oW","oH","newData","sliceByTwo","hermiteFastResize","bilinearFiltering","lanczosResize","mult","doneW","doneH","stepW","stepH","tmpCanvas","dX","dY","process","u","weight","fX","fY","ratioX","icenter","ratioY","range2X","cacheLanc","range2Y","lanczos","rcpRatioX","rcpRatioY","srcData","destData","destImg","xDiff","yDiff","chnl","origPix","w4","pixels","destImage","destPixels","ratioW","ratioH","ratioWHalf","ratioHHalf","img2","data2","weightsAlpha","gxR","gxG","gxB","gxA","yy","w0","Contrast","contrast","contrastF","uContrast","Saturation","saturation","adjust","uSaturation","Vibrance","vibrance","avg","amt","uVibrance","Blur","aspectRatio","simpleBlur","canvas2","blurLayer1","blurLayer2","ctx1","ctx2","nSamples","percent","newImageData","delta","chooseRightDelta","blurScale","Gamma","gamma","rInv","gInv","bInv","rVals","gVals","bVals","uGamma","uniform3fv","Composed","subFilters","HueRotation","rotation","rad","aThird","aThirdSqtSin","OneMinusCos","additionalProps","_dimensionAffectingProps","_reNewline","_reSpacesAndTabs","_reSpaceAndTab","_reWords","textAlign","superscript","baseline","subscript","pathStartOffset","pathSide","pathAlign","_fontSizeFraction","_fontSizeMult","charSpacing","_measuringContext","direction","_styleProperties","__charBounds","CACHE_FONT_SIZE","MIN_TEXT_WIDTH","__skipDimension","setPathInfo","initDimensions","segmentsInfo","getMeasuringContext","_splitText","newLines","_splitTextIntoLines","_textLines","graphemeLines","_unwrappedTextLines","_unwrappedLines","_text","graphemeText","_clearCache","calcTextWidth","cursorWidth","calcTextHeight","enlargeSpaces","diffSpace","currentLineWidth","numberOfSpaces","accumulatedSpace","line","charBound","spaces","isEndOfWrapping","getLineWidth","kernedWidth","lineIndex","missingNewlineOffset","_setTextStyles","_renderTextLinesBackground","_renderTextDecoration","_renderText","_renderTextStroke","_renderTextFill","charStyle","forMeasuring","textBaseline","_getFontDeclaration","maxWidth","_renderTextLine","_renderChars","styleHas","heightOfLine","lineLeftOffset","lastColor","leftOffset","_getLeftOffset","lineTopOffset","_getTopOffset","boxStart","boxWidth","charBox","currentColor","drawStart","_getLineLeftOffset","getValueOfPropertyAt","renderLeft","getFontCache","cacheProp","_measureChar","previousChar","prevCharStyle","fontCache","fontDeclaration","previousFontDeclaration","couple","stylesAreEqual","coupleWidth","previousWidth","fontMultiplier","measureText","getHeightOfChar","measureLine","lineInfo","_measureLine","_getWidthOfCharSpacing","grapheme","prevGrapheme","graphemeInfo","numOfSpaces","lineBounds","positionInPath","startingPoint","totalPathLength","_getGraphemeBox","_setGraphemeOnPath","centerPosition","skipLeft","getCompleteStyleDeclaration","previousBox","__lineHeights","maxHeight","_renderTextCommon","lineHeights","isEmptyStyles","isJustify","actualStyle","nextStyle","charsToRender","timeToRender","shortCut","isLtr","drawingLeft","currentDirection","_renderChar","_applyPatternGradientTransformText","handleFiller","_getStyleDeclaration","fullDecl","shouldFill","fillOffsets","strokeOffsets","fillText","strokeText","setSuperscript","_setScript","setSubscript","schema","loc","get2DCursorLocation","setSelectionStyles","lineDiff","__lineWidths","_shouldClearDimensionCache","shouldClear","_forceClearCache","_size","_dy","lastDecoration","topOffset","currentDecoration","currentFill","lastFill","styleObject","family","fontIsGeneric","genericFonts","newLine","newText","allProperties","needsDims","isAddingPath","_key","parsedAnchor","textAnchor","originalStrokeWidth","textHeightScaleFactor","lineHeightDiff","scaledDiff","textHeight","offX","objectCopy","textInstance","pathInstance","p3","cleanStyle","stylesCount","letterCount","stylePropertyValue","allStyleObjectPropertiesMatch","graphemeCount","stylePropertyHasBeenSet","removeStyle","lineNum","charNum","_extendStyles","_getLineStyle","_setLineStyle","_setStyleDeclaration","selectionStart","skipWrapping","getSelectionStyles","startIndex","endIndex","selectionEnd","getStyleAtPosition","lineStyle","_deleteStyleDeclaration","_deleteLineStyle","parseDecoration","IText","editable","editingBorderColor","cursorColor","cursorDelay","cursorDuration","caching","hiddenTextareaContainer","_reSpace","_currentCursorOpacity","_selectionDirection","_abortCursorAnimation","__widthOfSpace","inCompositionMode","initBehavior","setSelectionStart","_updateAndFire","setSelectionEnd","_fireSelectionChanged","_updateTextarea","initDelayedCursor","cursorOffsetCache","renderCursorOrSelection","skipRestore","_clearTextArea","boundaries","_getCursorBoundaries","renderCursor","renderSelection","_getCursorBoundariesOffsets","cursorPosition","bound","cursorLocation","charHeight","__isMousedown","hiddenTextarea","startLine","endLine","startChar","endChar","lineOffset","realLineHeight","boxEnd","drawWidth","drawHeight","extraTop","compositionColor","getCurrentCharFontSize","cp","_getCurrentCharIndex","getCurrentCharColor","objCopy","initAddedHandler","initRemovedHandler","initCursorSelectionHandlers","initDoubleClickSimulation","mouseMoveHandler","_initCanvasHandlers","_removeCanvasHandlers","_tick","_currentTickState","_animateCursor","targetOpacity","completeMethod","tickState","isAborted","_onTickComplete","_cursorTimeout1","_currentTickCompleteState","restart","delay","abortCursorAnimation","_cursorTimeout2","selectAll","getSelectedText","findWordBoundaryLeft","startFrom","findWordBoundaryRight","findLineBoundaryLeft","findLineBoundaryRight","searchWordBoundary","selectWord","newSelectionStart","newSelectionEnd","selectLine","enterEditing","exitEditingOnOthers","initHiddenTextarea","focus","_saveEditingProps","_setEditingProps","_textBeforeEdit","initMouseMoveHandler","activeElement","getSelectionStartFromPointer","currentStart","currentEnd","__selectionStartOnMouseDown","restartCursorIfNeeded","fromStringToGraphemeSelection","smallerTextStart","graphemeStart","smallerTextEnd","graphemeEnd","fromGraphemeToStringSelection","newSelection","updateTextareaPosition","updateFromTextArea","_calcTextareaPosition","desiredPosition","compositionStart","upperCanvas","upperCanvasWidth","upperCanvasHeight","clientWidth","clientHeight","_savedProps","_restoreEditingProps","isTextChanged","_removeExtraneousStyles","removeStyleFromTo","cursorStart","cursorEnd","lineStart","charStart","lineEnd","charEnd","styleObj","shiftLineStyles","numericChar","clonedStyles","numericLine","insertNewlineStyleObject","qty","copiedStyle","currentCharStyle","newLineStyles","somethingAdded","isEndOfLine","numIndex","styleCarriedOver","insertCharStyleObject","quantity","currentLineStyles","currentLineStylesCloned","numericIndex","newStyle","insertNewStyleBlock","insertedText","cursorLoc","addedLines","linesLength","setSelectionStartEndWithShift","setSelectionInBoundaries","__lastClickTime","__lastLastClickTime","__lastPointer","__newClickTime","newPointer","isTripleClick","_stopEvent","__lastIsEditing","__lastSelected","initMousedownHandler","initMouseupHandler","initClicks","doubleClickHandler","tripleClickHandler","_mouseDownHandler","setCursorByClick","_mouseDownHandlerBefore","currentActive","mouseOffset","prevWidth","_getNewSelectionStartFromOffset","distanceBtwLastCharAndCursor","distanceBtwNextCharAndCursor","onKeyDown","onKeyUp","onInput","copy","paste","onCompositionStart","onCompositionUpdate","onCompositionEnd","_clickHandlerInitialized","onClick","keysMap","keysMapRtl","ctrlKeysMapUp","ctrlKeysMapDown","keyMap","keyCode","ctrlKey","metaKey","stopImmediatePropagation","_copyDone","fromPaste","nextText","charCount","nextCharCount","removedText","charDiff","removeFrom","removeTo","textareaSelection","backDelete","copiedText","copiedTextStyle","compositionEnd","_getClipboardData","clipboardData","_getWidthBeforeCursor","widthBeforeCursor","getDownCursorOffset","isRight","selectionProp","_getSelectionForOffset","indexOnOtherLine","_getIndexOnLine","textAfterCursor","getUpCursorOffset","textBeforeCursor","widthOfCharsOnLine","indexOnLine","charWidth","foundMatch","leftEdge","rightEdge","offsetFromLeftEdge","offsetFromRightEdge","moveCursorDown","_moveCursorUpOrDown","moveCursorUp","moveCursorWithShift","moveCursorWithoutShift","moveCursorLeft","_moveCursorLeftOrRight","_move","_moveLeft","_moveRight","moveCursorLeftWithoutShift","change","moveCursorLeftWithShift","moveCursorRight","moveCursorRightWithShift","moveCursorRightWithoutShift","changed","removeChars","insertChars","multipleSpacesRegex","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","lineTop","noShadow","textSpans","textTopOffset","textLeftOffset","_setSVGTextLineBg","_setSVGTextLineText","_createTextCharSpan","styleDecl","shouldUseWhitespace","styleProps","fillStyles","dySpan","_pushTextBgRect","fillColor","_getSVGLineTopOffset","lastHeight","svgStyle","Textbox","minWidth","dynamicMinWidth","__cachedLines","_wordJoiners","splitByGrapheme","_styleMap","_generateStyleMap","textInfo","realLineCount","realLineCharCount","isWrapping","nextLineIndex","nextOffset","shouldLimit","mapNextLine","_wrapText","desiredWidth","wrapped","_wrapLine","_measureWord","word","charOffset","_line","reservedSpace","words","infix","wordWidth","infixWidth","largestWordWidth","lineJustStarted","additionalSpace","getMinWidth","linesToKeep","scaleSkewStyleHandler","scaleStyleHandler","objectControls","ml","mr","mb","mtr","textBoxControls","defaultOnTouchStartHandler"],"sources":["../../../scripts/leanforms/fabric.js"],"sourcesContent":["/* build: `node build.js modules=ALL exclude=gestures,accessors,erasing requirejs minifier=uglifyjs` */\r\n/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */\r\n\r\nvar fabric = fabric || { version: '5.3.0' };\r\nif (typeof exports !== 'undefined') {\r\n exports.fabric = fabric;\r\n}\r\n/* _AMD_START_ */\r\nelse if (typeof define === 'function' && define.amd) {\r\n define([], function() { return fabric; });\r\n}\r\n/* _AMD_END_ */\r\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\r\n if (document instanceof (typeof HTMLDocument !== 'undefined' ? HTMLDocument : Document)) {\r\n fabric.document = document;\r\n }\r\n else {\r\n fabric.document = document.implementation.createHTMLDocument('');\r\n }\r\n fabric.window = window;\r\n}\r\nelse {\r\n // assume we're running under node.js when document/window are not present\r\n var jsdom = require('jsdom');\r\n var virtualWindow = new jsdom.JSDOM(\r\n decodeURIComponent('%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E'),\r\n {\r\n features: {\r\n FetchExternalResources: ['img']\r\n },\r\n resources: 'usable'\r\n }).window;\r\n fabric.document = virtualWindow.document;\r\n fabric.jsdomImplForWrapper = require('jsdom/lib/jsdom/living/generated/utils').implForWrapper;\r\n fabric.nodeCanvas = require('jsdom/lib/jsdom/utils').Canvas;\r\n fabric.window = virtualWindow;\r\n DOMParser = fabric.window.DOMParser;\r\n}\r\n\r\n/**\r\n * True when in environment that supports touch events\r\n * @type boolean\r\n */\r\nfabric.isTouchSupported = 'ontouchstart' in fabric.window || 'ontouchstart' in fabric.document ||\r\n (fabric.window && fabric.window.navigator && fabric.window.navigator.maxTouchPoints > 0);\r\n\r\n/**\r\n * True when in environment that's probably Node.js\r\n * @type boolean\r\n */\r\nfabric.isLikelyNode = typeof Buffer !== 'undefined' &&\r\n typeof window === 'undefined';\r\n\r\n/* _FROM_SVG_START_ */\r\n/**\r\n * Attributes parsed from all SVG elements\r\n * @type array\r\n */\r\nfabric.SHARED_ATTRIBUTES = [\r\n 'display',\r\n 'transform',\r\n 'fill', 'fill-opacity', 'fill-rule',\r\n 'opacity',\r\n 'stroke', 'stroke-dasharray', 'stroke-linecap', 'stroke-dashoffset',\r\n 'stroke-linejoin', 'stroke-miterlimit',\r\n 'stroke-opacity', 'stroke-width',\r\n 'id', 'paint-order', 'vector-effect',\r\n 'instantiated_by_use', 'clip-path',\r\n];\r\n/* _FROM_SVG_END_ */\r\n\r\n/**\r\n * Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion.\r\n */\r\nfabric.DPI = 96;\r\nfabric.reNum = '(?:[-+]?(?:\\\\d+|\\\\d*\\\\.\\\\d+)(?:[eE][-+]?\\\\d+)?)';\r\nfabric.commaWsp = '(?:\\\\s+,?\\\\s*|,\\\\s*)';\r\nfabric.rePathCommand = /([-+]?((\\d+\\.\\d+)|((\\d+)|(\\.\\d+)))(?:[eE][-+]?\\d+)?)/ig;\r\nfabric.reNonWord = /[ \\n\\.,;!\\?\\-]/;\r\nfabric.fontPaths = { };\r\nfabric.iMatrix = [1, 0, 0, 1, 0, 0];\r\nfabric.svgNS = 'http://www.w3.org/2000/svg';\r\n\r\n/**\r\n * Pixel limit for cache canvases. 1Mpx , 4Mpx should be fine.\r\n * @since 1.7.14\r\n * @type Number\r\n * @default\r\n */\r\nfabric.perfLimitSizeTotal = 2097152;\r\n\r\n/**\r\n * Pixel limit for cache canvases width or height. IE fixes the maximum at 5000\r\n * @since 1.7.14\r\n * @type Number\r\n * @default\r\n */\r\nfabric.maxCacheSideLimit = 4096;\r\n\r\n/**\r\n * Lowest pixel limit for cache canvases, set at 256PX\r\n * @since 1.7.14\r\n * @type Number\r\n * @default\r\n */\r\nfabric.minCacheSideLimit = 256;\r\n\r\n/**\r\n * Cache Object for widths of chars in text rendering.\r\n */\r\nfabric.charWidthsCache = { };\r\n\r\n/**\r\n * if webgl is enabled and available, textureSize will determine the size\r\n * of the canvas backend\r\n * @since 2.0.0\r\n * @type Number\r\n * @default\r\n */\r\nfabric.textureSize = 2048;\r\n\r\n/**\r\n * When 'true', style information is not retained when copy/pasting text, making\r\n * pasted text use destination style.\r\n * Defaults to 'false'.\r\n * @type Boolean\r\n * @default\r\n */\r\nfabric.disableStyleCopyPaste = false;\r\n\r\n/**\r\n * Enable webgl for filtering picture is available\r\n * A filtering backend will be initialized, this will both take memory and\r\n * time since a default 2048x2048 canvas will be created for the gl context\r\n * @since 2.0.0\r\n * @type Boolean\r\n * @default\r\n */\r\nfabric.enableGLFiltering = true;\r\n\r\n/**\r\n * Device Pixel Ratio\r\n * @see https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/SettingUptheCanvas.html\r\n */\r\nfabric.devicePixelRatio = fabric.window.devicePixelRatio ||\r\n fabric.window.webkitDevicePixelRatio ||\r\n fabric.window.mozDevicePixelRatio ||\r\n 1;\r\n/**\r\n * Browser-specific constant to adjust CanvasRenderingContext2D.shadowBlur value,\r\n * which is unitless and not rendered equally across browsers.\r\n *\r\n * Values that work quite well (as of October 2017) are:\r\n * - Chrome: 1.5\r\n * - Edge: 1.75\r\n * - Firefox: 0.9\r\n * - Safari: 0.95\r\n *\r\n * @since 2.0.0\r\n * @type Number\r\n * @default 1\r\n */\r\nfabric.browserShadowBlurConstant = 1;\r\n\r\n/**\r\n * This object contains the result of arc to bezier conversion for faster retrieving if the same arc needs to be converted again.\r\n * It was an internal variable, is accessible since version 2.3.4\r\n */\r\nfabric.arcToSegmentsCache = { };\r\n\r\n/**\r\n * This object keeps the results of the boundsOfCurve calculation mapped by the joined arguments necessary to calculate it.\r\n * It does speed up calculation, if you parse and add always the same paths, but in case of heavy usage of freedrawing\r\n * you do not get any speed benefit and you get a big object in memory.\r\n * The object was a private variable before, while now is appended to the lib so that you have access to it and you\r\n * can eventually clear it.\r\n * It was an internal variable, is accessible since version 2.3.4\r\n */\r\nfabric.boundsOfCurveCache = { };\r\n\r\n/**\r\n * If disabled boundsOfCurveCache is not used. For apps that make heavy usage of pencil drawing probably disabling it is better\r\n * @default true\r\n */\r\nfabric.cachesBoundsOfCurve = true;\r\n\r\n/**\r\n * Skip performance testing of setupGLContext and force the use of putImageData that seems to be the one that works best on\r\n * Chrome + old hardware. if your users are experiencing empty images after filtering you may try to force this to true\r\n * this has to be set before instantiating the filtering backend ( before filtering the first image )\r\n * @type Boolean\r\n * @default false\r\n */\r\nfabric.forceGLPutImageData = false;\r\n\r\nfabric.initFilterBackend = function() {\r\n if (fabric.enableGLFiltering && fabric.isWebglSupported && fabric.isWebglSupported(fabric.textureSize)) {\r\n console.log('max texture size: ' + fabric.maxTextureSize);\r\n return (new fabric.WebglFilterBackend({ tileSize: fabric.textureSize }));\r\n }\r\n else if (fabric.Canvas2dFilterBackend) {\r\n return (new fabric.Canvas2dFilterBackend());\r\n }\r\n};\r\n\r\n\r\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\r\n // ensure globality even if entire library were function wrapped (as in Meteor.js packaging system)\r\n window.fabric = fabric;\r\n}\r\n\r\n\r\n(function() {\r\n\r\n /**\r\n * @private\r\n * @param {String} eventName\r\n * @param {Function} handler\r\n */\r\n function _removeEventListener(eventName, handler) {\r\n if (!this.__eventListeners[eventName]) {\r\n return;\r\n }\r\n var eventListener = this.__eventListeners[eventName];\r\n if (handler) {\r\n eventListener[eventListener.indexOf(handler)] = false;\r\n }\r\n else {\r\n fabric.util.array.fill(eventListener, false);\r\n }\r\n }\r\n\r\n /**\r\n * Observes specified event\r\n * @memberOf fabric.Observable\r\n * @alias on\r\n * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\r\n * @param {Function} handler Function that receives a notification when an event of the specified type occurs\r\n * @return {Self} thisArg\r\n * @chainable\r\n */\r\n function on(eventName, handler) {\r\n if (!this.__eventListeners) {\r\n this.__eventListeners = { };\r\n }\r\n // one object with key/value pairs was passed\r\n if (arguments.length === 1) {\r\n for (var prop in eventName) {\r\n this.on(prop, eventName[prop]);\r\n }\r\n }\r\n else {\r\n if (!this.__eventListeners[eventName]) {\r\n this.__eventListeners[eventName] = [];\r\n }\r\n this.__eventListeners[eventName].push(handler);\r\n }\r\n return this;\r\n }\r\n\r\n function _once(eventName, handler) {\r\n var _handler = function () {\r\n handler.apply(this, arguments);\r\n this.off(eventName, _handler);\r\n }.bind(this);\r\n this.on(eventName, _handler);\r\n }\r\n\r\n function once(eventName, handler) {\r\n // one object with key/value pairs was passed\r\n if (arguments.length === 1) {\r\n for (var prop in eventName) {\r\n _once.call(this, prop, eventName[prop]);\r\n }\r\n }\r\n else {\r\n _once.call(this, eventName, handler);\r\n }\r\n return this;\r\n }\r\n\r\n /**\r\n * Stops event observing for a particular event handler. Calling this method\r\n * without arguments removes all handlers for all events\r\n * @memberOf fabric.Observable\r\n * @alias off\r\n * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\r\n * @param {Function} handler Function to be deleted from EventListeners\r\n * @return {Self} thisArg\r\n * @chainable\r\n */\r\n function off(eventName, handler) {\r\n if (!this.__eventListeners) {\r\n return this;\r\n }\r\n\r\n // remove all key/value pairs (event name -> event handler)\r\n if (arguments.length === 0) {\r\n for (eventName in this.__eventListeners) {\r\n _removeEventListener.call(this, eventName);\r\n }\r\n }\r\n // one object with key/value pairs was passed\r\n else if (arguments.length === 1 && typeof arguments[0] === 'object') {\r\n for (var prop in eventName) {\r\n _removeEventListener.call(this, prop, eventName[prop]);\r\n }\r\n }\r\n else {\r\n _removeEventListener.call(this, eventName, handler);\r\n }\r\n return this;\r\n }\r\n\r\n /**\r\n * Fires event with an optional options object\r\n * @memberOf fabric.Observable\r\n * @param {String} eventName Event name to fire\r\n * @param {Object} [options] Options object\r\n * @return {Self} thisArg\r\n * @chainable\r\n */\r\n function fire(eventName, options) {\r\n if (!this.__eventListeners) {\r\n return this;\r\n }\r\n\r\n var listenersForEvent = this.__eventListeners[eventName];\r\n if (!listenersForEvent) {\r\n return this;\r\n }\r\n\r\n for (var i = 0, len = listenersForEvent.length; i < len; i++) {\r\n listenersForEvent[i] && listenersForEvent[i].call(this, options || { });\r\n }\r\n this.__eventListeners[eventName] = listenersForEvent.filter(function(value) {\r\n return value !== false;\r\n });\r\n return this;\r\n }\r\n\r\n /**\r\n * @namespace fabric.Observable\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#events}\r\n * @see {@link http://fabricjs.com/events|Events demo}\r\n */\r\n fabric.Observable = {\r\n fire: fire,\r\n on: on,\r\n once: once,\r\n off: off,\r\n };\r\n})();\r\n\r\n\r\n/**\r\n * @namespace fabric.Collection\r\n */\r\nfabric.Collection = {\r\n\r\n _objects: [],\r\n\r\n /**\r\n * Adds objects to collection, Canvas or Group, then renders canvas\r\n * (if `renderOnAddRemove` is not `false`).\r\n * in case of Group no changes to bounding box are made.\r\n * Objects should be instances of (or inherit from) fabric.Object\r\n * Use of this function is highly discouraged for groups.\r\n * you can add a bunch of objects with the add method but then you NEED\r\n * to run a addWithUpdate call for the Group class or position/bbox will be wrong.\r\n * @param {...fabric.Object} object Zero or more fabric instances\r\n * @return {Self} thisArg\r\n * @chainable\r\n */\r\n add: function () {\r\n this._objects.push.apply(this._objects, arguments);\r\n if (this._onObjectAdded) {\r\n for (var i = 0, length = arguments.length; i < length; i++) {\r\n this._onObjectAdded(arguments[i]);\r\n }\r\n }\r\n this.renderOnAddRemove && this.requestRenderAll();\r\n return this;\r\n },\r\n\r\n /**\r\n * Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`)\r\n * An object should be an instance of (or inherit from) fabric.Object\r\n * Use of this function is highly discouraged for groups.\r\n * you can add a bunch of objects with the insertAt method but then you NEED\r\n * to run a addWithUpdate call for the Group class or position/bbox will be wrong.\r\n * @param {Object} object Object to insert\r\n * @param {Number} index Index to insert object at\r\n * @param {Boolean} nonSplicing When `true`, no splicing (shifting) of objects occurs\r\n * @return {Self} thisArg\r\n * @chainable\r\n */\r\n insertAt: function (object, index, nonSplicing) {\r\n var objects = this._objects;\r\n if (nonSplicing) {\r\n objects[index] = object;\r\n }\r\n else {\r\n objects.splice(index, 0, object);\r\n }\r\n this._onObjectAdded && this._onObjectAdded(object);\r\n this.renderOnAddRemove && this.requestRenderAll();\r\n return this;\r\n },\r\n\r\n /**\r\n * Removes objects from a collection, then renders canvas (if `renderOnAddRemove` is not `false`)\r\n * @param {...fabric.Object} object Zero or more fabric instances\r\n * @return {Self} thisArg\r\n * @chainable\r\n */\r\n remove: function() {\r\n var objects = this._objects,\r\n index, somethingRemoved = false;\r\n\r\n for (var i = 0, length = arguments.length; i < length; i++) {\r\n index = objects.indexOf(arguments[i]);\r\n\r\n // only call onObjectRemoved if an object was actually removed\r\n if (index !== -1) {\r\n somethingRemoved = true;\r\n objects.splice(index, 1);\r\n this._onObjectRemoved && this._onObjectRemoved(arguments[i]);\r\n }\r\n }\r\n\r\n this.renderOnAddRemove && somethingRemoved && this.requestRenderAll();\r\n return this;\r\n },\r\n\r\n /**\r\n * Executes given function for each object in this group\r\n * @param {Function} callback\r\n * Callback invoked with current object as first argument,\r\n * index - as second and an array of all objects - as third.\r\n * Callback is invoked in a context of Global Object (e.g. `window`)\r\n * when no `context` argument is given\r\n *\r\n * @param {Object} context Context (aka thisObject)\r\n * @return {Self} thisArg\r\n * @chainable\r\n */\r\n forEachObject: function(callback, context) {\r\n var objects = this.getObjects();\r\n for (var i = 0, len = objects.length; i < len; i++) {\r\n callback.call(context, objects[i], i, objects);\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Returns an array of children objects of this instance\r\n * Type parameter introduced in 1.3.10\r\n * since 2.3.5 this method return always a COPY of the array;\r\n * @param {String} [type] When specified, only objects of this type are returned\r\n * @return {Array}\r\n */\r\n getObjects: function(type) {\r\n if (typeof type === 'undefined') {\r\n return this._objects.concat();\r\n }\r\n return this._objects.filter(function(o) {\r\n return o.type === type;\r\n });\r\n },\r\n\r\n /**\r\n * Returns object at specified index\r\n * @param {Number} index\r\n * @return {Self} thisArg\r\n */\r\n item: function (index) {\r\n return this._objects[index];\r\n },\r\n\r\n /**\r\n * Returns true if collection contains no objects\r\n * @return {Boolean} true if collection is empty\r\n */\r\n isEmpty: function () {\r\n return this._objects.length === 0;\r\n },\r\n\r\n /**\r\n * Returns a size of a collection (i.e: length of an array containing its objects)\r\n * @return {Number} Collection size\r\n */\r\n size: function() {\r\n return this._objects.length;\r\n },\r\n\r\n /**\r\n * Returns true if collection contains an object\r\n * @param {Object} object Object to check against\r\n * @param {Boolean} [deep=false] `true` to check all descendants, `false` to check only `_objects`\r\n * @return {Boolean} `true` if collection contains an object\r\n */\r\n contains: function (object, deep) {\r\n if (this._objects.indexOf(object) > -1) {\r\n return true;\r\n }\r\n else if (deep) {\r\n return this._objects.some(function (obj) {\r\n return typeof obj.contains === 'function' && obj.contains(object, true);\r\n });\r\n }\r\n return false;\r\n },\r\n\r\n /**\r\n * Returns number representation of a collection complexity\r\n * @return {Number} complexity\r\n */\r\n complexity: function () {\r\n return this._objects.reduce(function (memo, current) {\r\n memo += current.complexity ? current.complexity() : 0;\r\n return memo;\r\n }, 0);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * @namespace fabric.CommonMethods\r\n */\r\nfabric.CommonMethods = {\r\n\r\n /**\r\n * Sets object's properties from options\r\n * @param {Object} [options] Options object\r\n */\r\n _setOptions: function(options) {\r\n for (var prop in options) {\r\n this.set(prop, options[prop]);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Object} [filler] Options object\r\n * @param {String} [property] property to set the Gradient to\r\n */\r\n _initGradient: function(filler, property) {\r\n if (filler && filler.colorStops && !(filler instanceof fabric.Gradient)) {\r\n this.set(property, new fabric.Gradient(filler));\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Object} [filler] Options object\r\n * @param {String} [property] property to set the Pattern to\r\n * @param {Function} [callback] callback to invoke after pattern load\r\n */\r\n _initPattern: function(filler, property, callback) {\r\n if (filler && filler.source && !(filler instanceof fabric.Pattern)) {\r\n this.set(property, new fabric.Pattern(filler, callback));\r\n }\r\n else {\r\n callback && callback();\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _setObject: function(obj) {\r\n for (var prop in obj) {\r\n this._set(prop, obj[prop]);\r\n }\r\n },\r\n\r\n /**\r\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()`.\r\n * @param {String|Object} key Property name or object (if object, iterate over the object properties)\r\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)\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n set: function(key, value) {\r\n if (typeof key === 'object') {\r\n this._setObject(key);\r\n }\r\n else {\r\n this._set(key, value);\r\n }\r\n return this;\r\n },\r\n\r\n _set: function(key, value) {\r\n this[key] = value;\r\n },\r\n\r\n /**\r\n * Toggles specified property from `true` to `false` or from `false` to `true`\r\n * @param {String} property Property to toggle\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n toggle: function(property) {\r\n var value = this.get(property);\r\n if (typeof value === 'boolean') {\r\n this.set(property, !value);\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Basic getter\r\n * @param {String} property Property name\r\n * @return {*} value of a property\r\n */\r\n get: function(property) {\r\n return this[property];\r\n }\r\n};\r\n\r\n\r\n(function(global) {\r\n\r\n var sqrt = Math.sqrt,\r\n atan2 = Math.atan2,\r\n pow = Math.pow,\r\n PiBy180 = Math.PI / 180,\r\n PiBy2 = Math.PI / 2;\r\n\r\n /**\r\n * @namespace fabric.util\r\n */\r\n fabric.util = {\r\n\r\n /**\r\n * Calculate the cos of an angle, avoiding returning floats for known results\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Number} angle the angle in radians or in degree\r\n * @return {Number}\r\n */\r\n cos: function(angle) {\r\n if (angle === 0) { return 1; }\r\n if (angle < 0) {\r\n // cos(a) = cos(-a)\r\n angle = -angle;\r\n }\r\n var angleSlice = angle / PiBy2;\r\n switch (angleSlice) {\r\n case 1: case 3: return 0;\r\n case 2: return -1;\r\n }\r\n return Math.cos(angle);\r\n },\r\n\r\n /**\r\n * Calculate the sin of an angle, avoiding returning floats for known results\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Number} angle the angle in radians or in degree\r\n * @return {Number}\r\n */\r\n sin: function(angle) {\r\n if (angle === 0) { return 0; }\r\n var angleSlice = angle / PiBy2, sign = 1;\r\n if (angle < 0) {\r\n // sin(-a) = -sin(a)\r\n sign = -1;\r\n }\r\n switch (angleSlice) {\r\n case 1: return sign;\r\n case 2: return 0;\r\n case 3: return -sign;\r\n }\r\n return Math.sin(angle);\r\n },\r\n\r\n /**\r\n * Removes value from an array.\r\n * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf`\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Array} array\r\n * @param {*} value\r\n * @return {Array} original array\r\n */\r\n removeFromArray: function(array, value) {\r\n var idx = array.indexOf(value);\r\n if (idx !== -1) {\r\n array.splice(idx, 1);\r\n }\r\n return array;\r\n },\r\n\r\n /**\r\n * Returns random number between 2 specified ones.\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Number} min lower limit\r\n * @param {Number} max upper limit\r\n * @return {Number} random value (between min and max)\r\n */\r\n getRandomInt: function(min, max) {\r\n return Math.floor(Math.random() * (max - min + 1)) + min;\r\n },\r\n\r\n /**\r\n * Transforms degrees to radians.\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Number} degrees value in degrees\r\n * @return {Number} value in radians\r\n */\r\n degreesToRadians: function(degrees) {\r\n return degrees * PiBy180;\r\n },\r\n\r\n /**\r\n * Transforms radians to degrees.\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Number} radians value in radians\r\n * @return {Number} value in degrees\r\n */\r\n radiansToDegrees: function(radians) {\r\n return radians / PiBy180;\r\n },\r\n\r\n /**\r\n * Rotates `point` around `origin` with `radians`\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {fabric.Point} point The point to rotate\r\n * @param {fabric.Point} origin The origin of the rotation\r\n * @param {Number} radians The radians of the angle for the rotation\r\n * @return {fabric.Point} The new rotated point\r\n */\r\n rotatePoint: function(point, origin, radians) {\r\n var newPoint = new fabric.Point(point.x - origin.x, point.y - origin.y),\r\n v = fabric.util.rotateVector(newPoint, radians);\r\n return new fabric.Point(v.x, v.y).addEquals(origin);\r\n },\r\n\r\n /**\r\n * Rotates `vector` with `radians`\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Object} vector The vector to rotate (x and y)\r\n * @param {Number} radians The radians of the angle for the rotation\r\n * @return {Object} The new rotated point\r\n */\r\n rotateVector: function(vector, radians) {\r\n var sin = fabric.util.sin(radians),\r\n cos = fabric.util.cos(radians),\r\n rx = vector.x * cos - vector.y * sin,\r\n ry = vector.x * sin + vector.y * cos;\r\n return {\r\n x: rx,\r\n y: ry\r\n };\r\n },\r\n\r\n /**\r\n * Creates a vetor from points represented as a point\r\n * @static\r\n * @memberOf fabric.util\r\n *\r\n * @typedef {Object} Point\r\n * @property {number} x\r\n * @property {number} y\r\n *\r\n * @param {Point} from\r\n * @param {Point} to\r\n * @returns {Point} vector\r\n */\r\n createVector: function (from, to) {\r\n return new fabric.Point(to.x - from.x, to.y - from.y);\r\n },\r\n\r\n /**\r\n * Calculates angle between 2 vectors using dot product\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Point} a\r\n * @param {Point} b\r\n * @returns the angle in radian between the vectors\r\n */\r\n calcAngleBetweenVectors: function (a, b) {\r\n return Math.acos((a.x * b.x + a.y * b.y) / (Math.hypot(a.x, a.y) * Math.hypot(b.x, b.y)));\r\n },\r\n\r\n /**\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Point} v\r\n * @returns {Point} vector representing the unit vector of pointing to the direction of `v`\r\n */\r\n getHatVector: function (v) {\r\n return new fabric.Point(v.x, v.y).multiply(1 / Math.hypot(v.x, v.y));\r\n },\r\n\r\n /**\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Point} A\r\n * @param {Point} B\r\n * @param {Point} C\r\n * @returns {{ vector: Point, angle: number }} vector representing the bisector of A and A's angle\r\n */\r\n getBisector: function (A, B, C) {\r\n var AB = fabric.util.createVector(A, B), AC = fabric.util.createVector(A, C);\r\n var alpha = fabric.util.calcAngleBetweenVectors(AB, AC);\r\n // check if alpha is relative to AB->BC\r\n var ro = fabric.util.calcAngleBetweenVectors(fabric.util.rotateVector(AB, alpha), AC);\r\n var phi = alpha * (ro === 0 ? 1 : -1) / 2;\r\n return {\r\n vector: fabric.util.getHatVector(fabric.util.rotateVector(AB, phi)),\r\n angle: alpha\r\n };\r\n },\r\n\r\n /**\r\n * Project stroke width on points returning 2 projections for each point as follows:\r\n * - `miter`: 2 points corresponding to the outer boundary and the inner boundary of stroke.\r\n * - `bevel`: 2 points corresponding to the bevel boundaries, tangent to the bisector.\r\n * - `round`: same as `bevel`\r\n * Used to calculate object's bounding box\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Point[]} points\r\n * @param {Object} options\r\n * @param {number} options.strokeWidth\r\n * @param {'miter'|'bevel'|'round'} options.strokeLineJoin\r\n * @param {number} options.strokeMiterLimit https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit\r\n * @param {boolean} options.strokeUniform\r\n * @param {number} options.scaleX\r\n * @param {number} options.scaleY\r\n * @param {boolean} [openPath] whether the shape is open or not, affects the calculations of the first and last points\r\n * @returns {fabric.Point[]} array of size 2n/4n of all suspected points\r\n */\r\n projectStrokeOnPoints: function (points, options, openPath) {\r\n var coords = [], s = options.strokeWidth / 2,\r\n strokeUniformScalar = options.strokeUniform ?\r\n new fabric.Point(1 / options.scaleX, 1 / options.scaleY) : new fabric.Point(1, 1),\r\n getStrokeHatVector = function (v) {\r\n var scalar = s / (Math.hypot(v.x, v.y));\r\n return new fabric.Point(v.x * scalar * strokeUniformScalar.x, v.y * scalar * strokeUniformScalar.y);\r\n };\r\n if (points.length <= 1) {return coords;}\r\n points.forEach(function (p, index) {\r\n var A = new fabric.Point(p.x, p.y), B, C;\r\n if (index === 0) {\r\n C = points[index + 1];\r\n B = openPath ? getStrokeHatVector(fabric.util.createVector(C, A)).addEquals(A) : points[points.length - 1];\r\n }\r\n else if (index === points.length - 1) {\r\n B = points[index - 1];\r\n C = openPath ? getStrokeHatVector(fabric.util.createVector(B, A)).addEquals(A) : points[0];\r\n }\r\n else {\r\n B = points[index - 1];\r\n C = points[index + 1];\r\n }\r\n var bisector = fabric.util.getBisector(A, B, C),\r\n bisectorVector = bisector.vector,\r\n alpha = bisector.angle,\r\n scalar,\r\n miterVector;\r\n if (options.strokeLineJoin === 'miter') {\r\n scalar = -s / Math.sin(alpha / 2);\r\n miterVector = new fabric.Point(\r\n bisectorVector.x * scalar * strokeUniformScalar.x,\r\n bisectorVector.y * scalar * strokeUniformScalar.y\r\n );\r\n if (Math.hypot(miterVector.x, miterVector.y) / s <= options.strokeMiterLimit) {\r\n coords.push(A.add(miterVector));\r\n coords.push(A.subtract(miterVector));\r\n return;\r\n }\r\n }\r\n scalar = -s * Math.SQRT2;\r\n miterVector = new fabric.Point(\r\n bisectorVector.x * scalar * strokeUniformScalar.x,\r\n bisectorVector.y * scalar * strokeUniformScalar.y\r\n );\r\n coords.push(A.add(miterVector));\r\n coords.push(A.subtract(miterVector));\r\n });\r\n return coords;\r\n },\r\n\r\n /**\r\n * Apply transform t to point p\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {fabric.Point} p The point to transform\r\n * @param {Array} t The transform\r\n * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied\r\n * @return {fabric.Point} The transformed point\r\n */\r\n transformPoint: function(p, t, ignoreOffset) {\r\n if (ignoreOffset) {\r\n return new fabric.Point(\r\n t[0] * p.x + t[2] * p.y,\r\n t[1] * p.x + t[3] * p.y\r\n );\r\n }\r\n return new fabric.Point(\r\n t[0] * p.x + t[2] * p.y + t[4],\r\n t[1] * p.x + t[3] * p.y + t[5]\r\n );\r\n },\r\n\r\n /**\r\n * Returns coordinates of points's bounding rectangle (left, top, width, height)\r\n * @param {Array} points 4 points array\r\n * @param {Array} [transform] an array of 6 numbers representing a 2x3 transform matrix\r\n * @return {Object} Object with left, top, width, height properties\r\n */\r\n makeBoundingBoxFromPoints: function(points, transform) {\r\n if (transform) {\r\n for (var i = 0; i < points.length; i++) {\r\n points[i] = fabric.util.transformPoint(points[i], transform);\r\n }\r\n }\r\n var xPoints = [points[0].x, points[1].x, points[2].x, points[3].x],\r\n minX = fabric.util.array.min(xPoints),\r\n maxX = fabric.util.array.max(xPoints),\r\n width = maxX - minX,\r\n yPoints = [points[0].y, points[1].y, points[2].y, points[3].y],\r\n minY = fabric.util.array.min(yPoints),\r\n maxY = fabric.util.array.max(yPoints),\r\n height = maxY - minY;\r\n\r\n return {\r\n left: minX,\r\n top: minY,\r\n width: width,\r\n height: height\r\n };\r\n },\r\n\r\n /**\r\n * Invert transformation t\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Array} t The transform\r\n * @return {Array} The inverted transform\r\n */\r\n invertTransform: function(t) {\r\n var a = 1 / (t[0] * t[3] - t[1] * t[2]),\r\n r = [a * t[3], -a * t[1], -a * t[2], a * t[0]],\r\n o = fabric.util.transformPoint({ x: t[4], y: t[5] }, r, true);\r\n r[4] = -o.x;\r\n r[5] = -o.y;\r\n return r;\r\n },\r\n\r\n /**\r\n * A wrapper around Number#toFixed, which contrary to native method returns number, not string.\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Number|String} number number to operate on\r\n * @param {Number} fractionDigits number of fraction digits to \"leave\"\r\n * @return {Number}\r\n */\r\n toFixed: function(number, fractionDigits) {\r\n return parseFloat(Number(number).toFixed(fractionDigits));\r\n },\r\n\r\n /**\r\n * Converts from attribute value to pixel value if applicable.\r\n * Returns converted pixels or original value not converted.\r\n * @param {Number|String} value number to operate on\r\n * @param {Number} fontSize\r\n * @return {Number|String}\r\n */\r\n parseUnit: function(value, fontSize) {\r\n var unit = /\\D{0,2}$/.exec(value),\r\n number = parseFloat(value);\r\n if (!fontSize) {\r\n fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;\r\n }\r\n switch (unit[0]) {\r\n case 'mm':\r\n return number * fabric.DPI / 25.4;\r\n\r\n case 'cm':\r\n return number * fabric.DPI / 2.54;\r\n\r\n case 'in':\r\n return number * fabric.DPI;\r\n\r\n case 'pt':\r\n return number * fabric.DPI / 72; // or * 4 / 3\r\n\r\n case 'pc':\r\n return number * fabric.DPI / 72 * 12; // or * 16\r\n\r\n case 'em':\r\n return number * fontSize;\r\n\r\n default:\r\n return number;\r\n }\r\n },\r\n\r\n /**\r\n * Function which always returns `false`.\r\n * @static\r\n * @memberOf fabric.util\r\n * @return {Boolean}\r\n */\r\n falseFunction: function() {\r\n return false;\r\n },\r\n\r\n /**\r\n * Returns klass \"Class\" object of given namespace\r\n * @memberOf fabric.util\r\n * @param {String} type Type of object (eg. 'circle')\r\n * @param {String} namespace Namespace to get klass \"Class\" object from\r\n * @return {Object} klass \"Class\"\r\n */\r\n getKlass: function(type, namespace) {\r\n // capitalize first letter only\r\n type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1));\r\n return fabric.util.resolveNamespace(namespace)[type];\r\n },\r\n\r\n /**\r\n * Returns array of attributes for given svg that fabric parses\r\n * @memberOf fabric.util\r\n * @param {String} type Type of svg element (eg. 'circle')\r\n * @return {Array} string names of supported attributes\r\n */\r\n getSvgAttributes: function(type) {\r\n var attributes = [\r\n 'instantiated_by_use',\r\n 'style',\r\n 'id',\r\n 'class'\r\n ];\r\n switch (type) {\r\n case 'linearGradient':\r\n attributes = attributes.concat(['x1', 'y1', 'x2', 'y2', 'gradientUnits', 'gradientTransform']);\r\n break;\r\n case 'radialGradient':\r\n attributes = attributes.concat(['gradientUnits', 'gradientTransform', 'cx', 'cy', 'r', 'fx', 'fy', 'fr']);\r\n break;\r\n case 'stop':\r\n attributes = attributes.concat(['offset', 'stop-color', 'stop-opacity']);\r\n break;\r\n }\r\n return attributes;\r\n },\r\n\r\n /**\r\n * Returns object of given namespace\r\n * @memberOf fabric.util\r\n * @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric'\r\n * @return {Object} Object for given namespace (default fabric)\r\n */\r\n resolveNamespace: function(namespace) {\r\n if (!namespace) {\r\n return fabric;\r\n }\r\n\r\n var parts = namespace.split('.'),\r\n len = parts.length, i,\r\n obj = global || fabric.window;\r\n\r\n for (i = 0; i < len; ++i) {\r\n obj = obj[parts[i]];\r\n }\r\n\r\n return obj;\r\n },\r\n\r\n /**\r\n * Loads image element from given url and passes it to a callback\r\n * @memberOf fabric.util\r\n * @param {String} url URL representing an image\r\n * @param {Function} callback Callback; invoked with loaded image\r\n * @param {*} [context] Context to invoke callback in\r\n * @param {Object} [crossOrigin] crossOrigin value to set image element to\r\n */\r\n loadImage: function(url, callback, context, crossOrigin) {\r\n if (!url) {\r\n callback && callback.call(context, url);\r\n return;\r\n }\r\n\r\n var img = fabric.util.createImage();\r\n\r\n /** @ignore */\r\n var onLoadCallback = function () {\r\n callback && callback.call(context, img, false);\r\n img = img.onload = img.onerror = null;\r\n };\r\n\r\n img.onload = onLoadCallback;\r\n /** @ignore */\r\n img.onerror = function() {\r\n fabric.log('Error loading ' + img.src);\r\n callback && callback.call(context, null, true);\r\n img = img.onload = img.onerror = null;\r\n };\r\n\r\n // data-urls appear to be buggy with crossOrigin\r\n // https://github.com/kangax/fabric.js/commit/d0abb90f1cd5c5ef9d2a94d3fb21a22330da3e0a#commitcomment-4513767\r\n // see https://code.google.com/p/chromium/issues/detail?id=315152\r\n // https://bugzilla.mozilla.org/show_bug.cgi?id=935069\r\n // crossOrigin null is the same as not set.\r\n if (url.indexOf('data') !== 0 &&\r\n crossOrigin !== undefined &&\r\n crossOrigin !== null) {\r\n img.crossOrigin = crossOrigin;\r\n }\r\n\r\n // IE10 / IE11-Fix: SVG contents from data: URI\r\n // will only be available if the IMG is present\r\n // in the DOM (and visible)\r\n if (url.substring(0,14) === 'data:image/svg') {\r\n img.onload = null;\r\n fabric.util.loadImageInDom(img, onLoadCallback);\r\n }\r\n\r\n img.src = url;\r\n },\r\n\r\n /**\r\n * Attaches SVG image with data: URL to the dom\r\n * @memberOf fabric.util\r\n * @param {Object} img Image object with data:image/svg src\r\n * @param {Function} callback Callback; invoked with loaded image\r\n * @return {Object} DOM element (div containing the SVG image)\r\n */\r\n loadImageInDom: function(img, onLoadCallback) {\r\n var div = fabric.document.createElement('div');\r\n div.style.width = div.style.height = '1px';\r\n div.style.left = div.style.top = '-100%';\r\n div.style.position = 'absolute';\r\n div.appendChild(img);\r\n fabric.document.querySelector('body').appendChild(div);\r\n /**\r\n * Wrap in function to:\r\n * 1. Call existing callback\r\n * 2. Cleanup DOM\r\n */\r\n img.onload = function () {\r\n onLoadCallback();\r\n div.parentNode.removeChild(div);\r\n div = null;\r\n };\r\n },\r\n\r\n /**\r\n * Creates corresponding fabric instances from their object representations\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Array} objects Objects to enliven\r\n * @param {Function} callback Callback to invoke when all objects are created\r\n * @param {String} namespace Namespace to get klass \"Class\" object from\r\n * @param {Function} reviver Method for further parsing of object elements,\r\n * called after each fabric object created.\r\n */\r\n enlivenObjects: function(objects, callback, namespace, reviver) {\r\n objects = objects || [];\r\n\r\n var enlivenedObjects = [],\r\n numLoadedObjects = 0,\r\n numTotalObjects = objects.length;\r\n\r\n function onLoaded() {\r\n if (++numLoadedObjects === numTotalObjects) {\r\n callback && callback(enlivenedObjects.filter(function(obj) {\r\n // filter out undefined objects (objects that gave error)\r\n return obj;\r\n }));\r\n }\r\n }\r\n\r\n if (!numTotalObjects) {\r\n callback && callback(enlivenedObjects);\r\n return;\r\n }\r\n\r\n objects.forEach(function (o, index) {\r\n // if sparse array\r\n if (!o || !o.type) {\r\n onLoaded();\r\n return;\r\n }\r\n var klass = fabric.util.getKlass(o.type, namespace);\r\n klass.fromObject(o, function (obj, error) {\r\n error || (enlivenedObjects[index] = obj);\r\n reviver && reviver(o, obj, error);\r\n onLoaded();\r\n });\r\n });\r\n },\r\n\r\n /**\r\n * Creates corresponding fabric instances residing in an object, e.g. `clipPath`\r\n * @see {@link fabric.Object.ENLIVEN_PROPS}\r\n * @param {Object} object\r\n * @param {Object} [context] assign enlived props to this object (pass null to skip this)\r\n * @param {(objects:fabric.Object[]) => void} callback\r\n */\r\n enlivenObjectEnlivables: function (object, context, callback) {\r\n var enlivenProps = fabric.Object.ENLIVEN_PROPS.filter(function (key) { return !!object[key]; });\r\n fabric.util.enlivenObjects(enlivenProps.map(function (key) { return object[key]; }), function (enlivedProps) {\r\n var objects = {};\r\n enlivenProps.forEach(function (key, index) {\r\n objects[key] = enlivedProps[index];\r\n context && (context[key] = enlivedProps[index]);\r\n });\r\n callback && callback(objects);\r\n });\r\n },\r\n\r\n /**\r\n * Create and wait for loading of patterns\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Array} patterns Objects to enliven\r\n * @param {Function} callback Callback to invoke when all objects are created\r\n * called after each fabric object created.\r\n */\r\n enlivenPatterns: function(patterns, callback) {\r\n patterns = patterns || [];\r\n\r\n function onLoaded() {\r\n if (++numLoadedPatterns === numPatterns) {\r\n callback && callback(enlivenedPatterns);\r\n }\r\n }\r\n\r\n var enlivenedPatterns = [],\r\n numLoadedPatterns = 0,\r\n numPatterns = patterns.length;\r\n\r\n if (!numPatterns) {\r\n callback && callback(enlivenedPatterns);\r\n return;\r\n }\r\n\r\n patterns.forEach(function (p, index) {\r\n if (p && p.source) {\r\n new fabric.Pattern(p, function(pattern) {\r\n enlivenedPatterns[index] = pattern;\r\n onLoaded();\r\n });\r\n }\r\n else {\r\n enlivenedPatterns[index] = p;\r\n onLoaded();\r\n }\r\n });\r\n },\r\n\r\n /**\r\n * Groups SVG elements (usually those retrieved from SVG document)\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Array} elements SVG elements to group\r\n * @param {Object} [options] Options object\r\n * @param {String} path Value to set sourcePath to\r\n * @return {fabric.Object|fabric.Group}\r\n */\r\n groupSVGElements: function(elements, options, path) {\r\n var object;\r\n if (elements && elements.length === 1) {\r\n if (typeof path !== 'undefined') {\r\n elements[0].sourcePath = path;\r\n }\r\n return elements[0];\r\n }\r\n if (options) {\r\n if (options.width && options.height) {\r\n options.centerPoint = {\r\n x: options.width / 2,\r\n y: options.height / 2\r\n };\r\n }\r\n else {\r\n delete options.width;\r\n delete options.height;\r\n }\r\n }\r\n object = new fabric.Group(elements, options);\r\n if (typeof path !== 'undefined') {\r\n object.sourcePath = path;\r\n }\r\n return object;\r\n },\r\n\r\n /**\r\n * Populates an object with properties of another object\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Object} source Source object\r\n * @param {Object} destination Destination object\r\n * @return {Array} properties Properties names to include\r\n */\r\n populateWithProperties: function(source, destination, properties) {\r\n if (properties && Array.isArray(properties)) {\r\n for (var i = 0, len = properties.length; i < len; i++) {\r\n if (properties[i] in source) {\r\n destination[properties[i]] = source[properties[i]];\r\n }\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * Creates canvas element\r\n * @static\r\n * @memberOf fabric.util\r\n * @return {CanvasElement} initialized canvas element\r\n */\r\n createCanvasElement: function() {\r\n return fabric.document.createElement('canvas');\r\n },\r\n\r\n /**\r\n * Creates a canvas element that is a copy of another and is also painted\r\n * @param {CanvasElement} canvas to copy size and content of\r\n * @static\r\n * @memberOf fabric.util\r\n * @return {CanvasElement} initialized canvas element\r\n */\r\n copyCanvasElement: function(canvas) {\r\n var newCanvas = fabric.util.createCanvasElement();\r\n newCanvas.width = canvas.width;\r\n newCanvas.height = canvas.height;\r\n newCanvas.getContext('2d', { willReadFrequently: true }).drawImage(canvas, 0, 0);\r\n return newCanvas;\r\n },\r\n\r\n /**\r\n * since 2.6.0 moved from canvas instance to utility.\r\n * @param {CanvasElement} canvasEl to copy size and content of\r\n * @param {String} format 'jpeg' or 'png', in some browsers 'webp' is ok too\r\n * @param {Number} quality <= 1 and > 0\r\n * @static\r\n * @memberOf fabric.util\r\n * @return {String} data url\r\n */\r\n toDataURL: function(canvasEl, format, quality) {\r\n return canvasEl.toDataURL('image/' + format, quality);\r\n },\r\n\r\n /**\r\n * Creates image element (works on client and node)\r\n * @static\r\n * @memberOf fabric.util\r\n * @return {HTMLImageElement} HTML image element\r\n */\r\n createImage: function() {\r\n return fabric.document.createElement('img');\r\n },\r\n\r\n /**\r\n * Multiply matrix A by matrix B to nest transformations\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Array} a First transformMatrix\r\n * @param {Array} b Second transformMatrix\r\n * @param {Boolean} is2x2 flag to multiply matrices as 2x2 matrices\r\n * @return {Array} The product of the two transform matrices\r\n */\r\n multiplyTransformMatrices: function(a, b, is2x2) {\r\n // Matrix multiply a * b\r\n return [\r\n a[0] * b[0] + a[2] * b[1],\r\n a[1] * b[0] + a[3] * b[1],\r\n a[0] * b[2] + a[2] * b[3],\r\n a[1] * b[2] + a[3] * b[3],\r\n is2x2 ? 0 : a[0] * b[4] + a[2] * b[5] + a[4],\r\n is2x2 ? 0 : a[1] * b[4] + a[3] * b[5] + a[5]\r\n ];\r\n },\r\n\r\n /**\r\n * Decomposes standard 2x3 matrix into transform components\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Array} a transformMatrix\r\n * @return {Object} Components of transform\r\n */\r\n qrDecompose: function(a) {\r\n var angle = atan2(a[1], a[0]),\r\n denom = pow(a[0], 2) + pow(a[1], 2),\r\n scaleX = sqrt(denom),\r\n scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX,\r\n skewX = atan2(a[0] * a[2] + a[1] * a [3], denom);\r\n return {\r\n angle: angle / PiBy180,\r\n scaleX: scaleX,\r\n scaleY: scaleY,\r\n skewX: skewX / PiBy180,\r\n skewY: 0,\r\n translateX: a[4],\r\n translateY: a[5]\r\n };\r\n },\r\n\r\n /**\r\n * Returns a transform matrix starting from an object of the same kind of\r\n * the one returned from qrDecompose, useful also if you want to calculate some\r\n * transformations from an object that is not enlived yet\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Object} options\r\n * @param {Number} [options.angle] angle in degrees\r\n * @return {Number[]} transform matrix\r\n */\r\n calcRotateMatrix: function(options) {\r\n if (!options.angle) {\r\n return fabric.iMatrix.concat();\r\n }\r\n var theta = fabric.util.degreesToRadians(options.angle),\r\n cos = fabric.util.cos(theta),\r\n sin = fabric.util.sin(theta);\r\n return [cos, sin, -sin, cos, 0, 0];\r\n },\r\n\r\n /**\r\n * Returns a transform matrix starting from an object of the same kind of\r\n * the one returned from qrDecompose, useful also if you want to calculate some\r\n * transformations from an object that is not enlived yet.\r\n * is called DimensionsTransformMatrix because those properties are the one that influence\r\n * the size of the resulting box of the object.\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Object} options\r\n * @param {Number} [options.scaleX]\r\n * @param {Number} [options.scaleY]\r\n * @param {Boolean} [options.flipX]\r\n * @param {Boolean} [options.flipY]\r\n * @param {Number} [options.skewX]\r\n * @param {Number} [options.skewY]\r\n * @return {Number[]} transform matrix\r\n */\r\n calcDimensionsMatrix: function(options) {\r\n var scaleX = typeof options.scaleX === 'undefined' ? 1 : options.scaleX,\r\n scaleY = typeof options.scaleY === 'undefined' ? 1 : options.scaleY,\r\n scaleMatrix = [\r\n options.flipX ? -scaleX : scaleX,\r\n 0,\r\n 0,\r\n options.flipY ? -scaleY : scaleY,\r\n 0,\r\n 0],\r\n multiply = fabric.util.multiplyTransformMatrices,\r\n degreesToRadians = fabric.util.degreesToRadians;\r\n if (options.skewX) {\r\n scaleMatrix = multiply(\r\n scaleMatrix,\r\n [1, 0, Math.tan(degreesToRadians(options.skewX)), 1],\r\n true);\r\n }\r\n if (options.skewY) {\r\n scaleMatrix = multiply(\r\n scaleMatrix,\r\n [1, Math.tan(degreesToRadians(options.skewY)), 0, 1],\r\n true);\r\n }\r\n return scaleMatrix;\r\n },\r\n\r\n /**\r\n * Returns a transform matrix starting from an object of the same kind of\r\n * the one returned from qrDecompose, useful also if you want to calculate some\r\n * transformations from an object that is not enlived yet\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {Object} options\r\n * @param {Number} [options.angle]\r\n * @param {Number} [options.scaleX]\r\n * @param {Number} [options.scaleY]\r\n * @param {Boolean} [options.flipX]\r\n * @param {Boolean} [options.flipY]\r\n * @param {Number} [options.skewX]\r\n * @param {Number} [options.skewX]\r\n * @param {Number} [options.translateX]\r\n * @param {Number} [options.translateY]\r\n * @return {Number[]} transform matrix\r\n */\r\n composeMatrix: function(options) {\r\n var matrix = [1, 0, 0, 1, options.translateX || 0, options.translateY || 0],\r\n multiply = fabric.util.multiplyTransformMatrices;\r\n if (options.angle) {\r\n matrix = multiply(matrix, fabric.util.calcRotateMatrix(options));\r\n }\r\n if (options.scaleX !== 1 || options.scaleY !== 1 ||\r\n options.skewX || options.skewY || options.flipX || options.flipY) {\r\n matrix = multiply(matrix, fabric.util.calcDimensionsMatrix(options));\r\n }\r\n return matrix;\r\n },\r\n\r\n /**\r\n * reset an object transform state to neutral. Top and left are not accounted for\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {fabric.Object} target object to transform\r\n */\r\n resetObjectTransform: function (target) {\r\n target.scaleX = 1;\r\n target.scaleY = 1;\r\n target.skewX = 0;\r\n target.skewY = 0;\r\n target.flipX = false;\r\n target.flipY = false;\r\n target.rotate(0);\r\n },\r\n\r\n /**\r\n * Extract Object transform values\r\n * @static\r\n * @memberOf fabric.util\r\n * @param {fabric.Object} target object to read from\r\n * @return {Object} Components of transform\r\n */\r\n saveObjectTransform: function (target) {\r\n return {\r\n scaleX: target.scaleX,\r\n scaleY: target.scaleY,\r\n skewX: target.skewX,\r\n skewY: target.skewY,\r\n angle: target.angle,\r\n left: target.left,\r\n flipX: target.flipX,\r\n flipY: target.flipY,\r\n top: target.top\r\n };\r\n },\r\n\r\n /**\r\n * Returns true if context has transparent pixel\r\n * at specified location (taking tolerance into account)\r\n * @param {CanvasRenderingContext2D} ctx context\r\n * @param {Number} x x coordinate\r\n * @param {Number} y y coordinate\r\n * @param {Number} tolerance Tolerance\r\n */\r\n isTransparent: function(ctx, x, y, tolerance) {\r\n\r\n // If tolerance is > 0 adjust start coords to take into account.\r\n // If moves off Canvas fix to 0\r\n if (tolerance > 0) {\r\n if (x > tolerance) {\r\n x -= tolerance;\r\n }\r\n else {\r\n x = 0;\r\n }\r\n if (y > tolerance) {\r\n y -= tolerance;\r\n }\r\n else {\r\n y = 0;\r\n }\r\n }\r\n\r\n var _isTransparent = true, i, temp,\r\n imageData = ctx.getImageData(x, y, (tolerance * 2) || 1, (tolerance * 2) || 1),\r\n l = imageData.data.length;\r\n\r\n // Split image data - for tolerance > 1, pixelDataSize = 4;\r\n for (i = 3; i < l; i += 4) {\r\n temp = imageData.data[i];\r\n _isTransparent = temp <= 0;\r\n if (_isTransparent === false) {\r\n break; // Stop if colour found\r\n }\r\n }\r\n\r\n imageData = null;\r\n\r\n return _isTransparent;\r\n },\r\n\r\n /**\r\n * Parse preserveAspectRatio attribute from element\r\n * @param {string} attribute to be parsed\r\n * @return {Object} an object containing align and meetOrSlice attribute\r\n */\r\n parsePreserveAspectRatioAttribute: function(attribute) {\r\n var meetOrSlice = 'meet', alignX = 'Mid', alignY = 'Mid',\r\n aspectRatioAttrs = attribute.split(' '), align;\r\n\r\n if (aspectRatioAttrs && aspectRatioAttrs.length) {\r\n meetOrSlice = aspectRatioAttrs.pop();\r\n if (meetOrSlice !== 'meet' && meetOrSlice !== 'slice') {\r\n align = meetOrSlice;\r\n meetOrSlice = 'meet';\r\n }\r\n else if (aspectRatioAttrs.length) {\r\n align = aspectRatioAttrs.pop();\r\n }\r\n }\r\n //divide align in alignX and alignY\r\n alignX = align !== 'none' ? align.slice(1, 4) : 'none';\r\n alignY = align !== 'none' ? align.slice(5, 8) : 'none';\r\n return {\r\n meetOrSlice: meetOrSlice,\r\n alignX: alignX,\r\n alignY: alignY\r\n };\r\n },\r\n\r\n /**\r\n * Clear char widths cache for the given font family or all the cache if no\r\n * fontFamily is specified.\r\n * Use it if you know you are loading fonts in a lazy way and you are not waiting\r\n * for custom fonts to load properly when adding text objects to the canvas.\r\n * If a text object is added when its own font is not loaded yet, you will get wrong\r\n * measurement and so wrong bounding boxes.\r\n * After the font cache is cleared, either change the textObject text content or call\r\n * initDimensions() to trigger a recalculation\r\n * @memberOf fabric.util\r\n * @param {String} [fontFamily] font family to clear\r\n */\r\n clearFabricFontCache: function(fontFamily) {\r\n fontFamily = (fontFamily || '').toLowerCase();\r\n if (!fontFamily) {\r\n fabric.charWidthsCache = { };\r\n }\r\n else if (fabric.charWidthsCache[fontFamily]) {\r\n delete fabric.charWidthsCache[fontFamily];\r\n }\r\n },\r\n\r\n /**\r\n * Given current aspect ratio, determines the max width and height that can\r\n * respect the total allowed area for the cache.\r\n * @memberOf fabric.util\r\n * @param {Number} ar aspect ratio\r\n * @param {Number} maximumArea Maximum area you want to achieve\r\n * @return {Object.x} Limited dimensions by X\r\n * @return {Object.y} Limited dimensions by Y\r\n */\r\n limitDimsByArea: function(ar, maximumArea) {\r\n var roughWidth = Math.sqrt(maximumArea * ar),\r\n perfLimitSizeY = Math.floor(maximumArea / roughWidth);\r\n return { x: Math.floor(roughWidth), y: perfLimitSizeY };\r\n },\r\n\r\n capValue: function(min, value, max) {\r\n return Math.max(min, Math.min(value, max));\r\n },\r\n\r\n /**\r\n * Finds the scale for the object source to fit inside the object destination,\r\n * keeping aspect ratio intact.\r\n * respect the total allowed area for the cache.\r\n * @memberOf fabric.util\r\n * @param {Object | fabric.Object} source\r\n * @param {Number} source.height natural unscaled height of the object\r\n * @param {Number} source.width natural unscaled width of the object\r\n * @param {Object | fabric.Object} destination\r\n * @param {Number} destination.height natural unscaled height of the object\r\n * @param {Number} destination.width natural unscaled width of the object\r\n * @return {Number} scale factor to apply to source to fit into destination\r\n */\r\n findScaleToFit: function(source, destination) {\r\n return Math.min(destination.width / source.width, destination.height / source.height);\r\n },\r\n\r\n /**\r\n * Finds the scale for the object source to cover entirely the object destination,\r\n * keeping aspect ratio intact.\r\n * respect the total allowed area for the cache.\r\n * @memberOf fabric.util\r\n * @param {Object | fabric.Object} source\r\n * @param {Number} source.height natural unscaled height of the object\r\n * @param {Number} source.width natural unscaled width of the object\r\n * @param {Object | fabric.Object} destination\r\n * @param {Number} destination.height natural unscaled height of the object\r\n * @param {Number} destination.width natural unscaled width of the object\r\n * @return {Number} scale factor to apply to source to cover destination\r\n */\r\n findScaleToCover: function(source, destination) {\r\n return Math.max(destination.width / source.width, destination.height / source.height);\r\n },\r\n\r\n /**\r\n * given an array of 6 number returns something like `\"matrix(...numbers)\"`\r\n * @memberOf fabric.util\r\n * @param {Array} transform an array with 6 numbers\r\n * @return {String} transform matrix for svg\r\n * @return {Object.y} Limited dimensions by Y\r\n */\r\n matrixToSVG: function(transform) {\r\n return 'matrix(' + transform.map(function(value) {\r\n return fabric.util.toFixed(value, fabric.Object.NUM_FRACTION_DIGITS);\r\n }).join(' ') + ')';\r\n },\r\n\r\n /**\r\n * given an object and a transform, apply the inverse transform to the object,\r\n * this is equivalent to remove from that object that transformation, so that\r\n * added in a space with the removed transform, the object will be the same as before.\r\n * Removing from an object a transform that scale by 2 is like scaling it by 1/2.\r\n * Removing from an object a transfrom that rotate by 30deg is like rotating by 30deg\r\n * in the opposite direction.\r\n * This util is used to add objects inside transformed groups or nested groups.\r\n * @memberOf fabric.util\r\n * @param {fabric.Object} object the object you want to transform\r\n * @param {Array} transform the destination transform\r\n */\r\n removeTransformFromObject: function(object, transform) {\r\n var inverted = fabric.util.invertTransform(transform),\r\n finalTransform = fabric.util.multiplyTransformMatrices(inverted, object.calcOwnMatrix());\r\n fabric.util.applyTransformToObject(object, finalTransform);\r\n },\r\n\r\n /**\r\n * given an object and a transform, apply the transform to the object.\r\n * this is equivalent to change the space where the object is drawn.\r\n * Adding to an object a transform that scale by 2 is like scaling it by 2.\r\n * This is used when removing an object from an active selection for example.\r\n * @memberOf fabric.util\r\n * @param {fabric.Object} object the object you want to transform\r\n * @param {Array} transform the destination transform\r\n */\r\n addTransformToObject: function(object, transform) {\r\n fabric.util.applyTransformToObject(\r\n object,\r\n fabric.util.multiplyTransformMatrices(transform, object.calcOwnMatrix())\r\n );\r\n },\r\n\r\n /**\r\n * discard an object transform state and apply the one from the matrix.\r\n * @memberOf fabric.util\r\n * @param {fabric.Object} object the object you want to transform\r\n * @param {Array} transform the destination transform\r\n */\r\n applyTransformToObject: function(object, transform) {\r\n var options = fabric.util.qrDecompose(transform),\r\n center = new fabric.Point(options.translateX, options.translateY);\r\n object.flipX = false;\r\n object.flipY = false;\r\n object.set('scaleX', options.scaleX);\r\n object.set('scaleY', options.scaleY);\r\n object.skewX = options.skewX;\r\n object.skewY = options.skewY;\r\n object.angle = options.angle;\r\n object.setPositionByOrigin(center, 'center', 'center');\r\n },\r\n\r\n /**\r\n * given a width and height, return the size of the bounding box\r\n * that can contains the box with width/height with applied transform\r\n * described in options.\r\n * Use to calculate the boxes around objects for controls.\r\n * @memberOf fabric.util\r\n * @param {Number} width\r\n * @param {Number} height\r\n * @param {Object} options\r\n * @param {Number} options.scaleX\r\n * @param {Number} options.scaleY\r\n * @param {Number} options.skewX\r\n * @param {Number} options.skewY\r\n * @return {Object.x} width of containing\r\n * @return {Object.y} height of containing\r\n */\r\n sizeAfterTransform: function(width, height, options) {\r\n var dimX = width / 2, dimY = height / 2,\r\n points = [\r\n {\r\n x: -dimX,\r\n y: -dimY\r\n },\r\n {\r\n x: dimX,\r\n y: -dimY\r\n },\r\n {\r\n x: -dimX,\r\n y: dimY\r\n },\r\n {\r\n x: dimX,\r\n y: dimY\r\n }],\r\n transformMatrix = fabric.util.calcDimensionsMatrix(options),\r\n bbox = fabric.util.makeBoundingBoxFromPoints(points, transformMatrix);\r\n return {\r\n x: bbox.width,\r\n y: bbox.height,\r\n };\r\n },\r\n\r\n /**\r\n * Merges 2 clip paths into one visually equal clip path\r\n *\r\n * **IMPORTANT**:\\\r\n * Does **NOT** clone the arguments, clone them proir if necessary.\r\n *\r\n * Creates a wrapper (group) that contains one clip path and is clipped by the other so content is kept where both overlap.\r\n * Use this method if both the clip paths may have nested clip paths of their own, so assigning one to the other's clip path property is not possible.\r\n *\r\n * In order to handle the `inverted` property we follow logic described in the following cases:\\\r\n * **(1)** both clip paths are inverted - the clip paths pass the inverted prop to the wrapper and loose it themselves.\\\r\n * **(2)** one is inverted and the other isn't - the wrapper shouldn't become inverted and the inverted clip path must clip the non inverted one to produce an identical visual effect.\\\r\n * **(3)** both clip paths are not inverted - wrapper and clip paths remain unchanged.\r\n *\r\n * @memberOf fabric.util\r\n * @param {fabric.Object} c1\r\n * @param {fabric.Object} c2\r\n * @returns {fabric.Object} merged clip path\r\n */\r\n mergeClipPaths: function (c1, c2) {\r\n var a = c1, b = c2;\r\n if (a.inverted && !b.inverted) {\r\n // case (2)\r\n a = c2;\r\n b = c1;\r\n }\r\n // `b` becomes `a`'s clip path so we transform `b` to `a` coordinate plane\r\n fabric.util.applyTransformToObject(\r\n b,\r\n fabric.util.multiplyTransformMatrices(\r\n fabric.util.invertTransform(a.calcTransformMatrix()),\r\n b.calcTransformMatrix()\r\n )\r\n );\r\n // assign the `inverted` prop to the wrapping group\r\n var inverted = a.inverted && b.inverted;\r\n if (inverted) {\r\n // case (1)\r\n a.inverted = b.inverted = false;\r\n }\r\n return new fabric.Group([a], { clipPath: b, inverted: inverted });\r\n },\r\n\r\n /**\r\n * @memberOf fabric.util\r\n * @param {Object} prevStyle first style to compare\r\n * @param {Object} thisStyle second style to compare\r\n * @param {boolean} forTextSpans whether to check overline, underline, and line-through properties\r\n * @return {boolean} true if the style changed\r\n */\r\n hasStyleChanged: function(prevStyle, thisStyle, forTextSpans) {\r\n forTextSpans = forTextSpans || false;\r\n return (prevStyle.fill !== thisStyle.fill ||\r\n prevStyle.stroke !== thisStyle.stroke ||\r\n prevStyle.strokeWidth !== thisStyle.strokeWidth ||\r\n prevStyle.fontSize !== thisStyle.fontSize ||\r\n prevStyle.fontFamily !== thisStyle.fontFamily ||\r\n prevStyle.fontWeight !== thisStyle.fontWeight ||\r\n prevStyle.fontStyle !== thisStyle.fontStyle ||\r\n prevStyle.textBackgroundColor !== thisStyle.textBackgroundColor ||\r\n prevStyle.deltaY !== thisStyle.deltaY) ||\r\n (forTextSpans &&\r\n (prevStyle.overline !== thisStyle.overline ||\r\n prevStyle.underline !== thisStyle.underline ||\r\n prevStyle.linethrough !== thisStyle.linethrough));\r\n },\r\n\r\n /**\r\n * Returns the array form of a text object's inline styles property with styles grouped in ranges\r\n * rather than per character. This format is less verbose, and is better suited for storage\r\n * so it is used in serialization (not during runtime).\r\n * @memberOf fabric.util\r\n * @param {object} styles per character styles for a text object\r\n * @param {String} text the text string that the styles are applied to\r\n * @return {{start: number, end: number, style: object}[]}\r\n */\r\n stylesToArray: function(styles, text) {\r\n // clone style structure to prevent mutation\r\n var styles = fabric.util.object.clone(styles, true),\r\n textLines = text.split('\\n'),\r\n charIndex = -1, prevStyle = {}, stylesArray = [];\r\n //loop through each textLine\r\n for (var i = 0; i < textLines.length; i++) {\r\n if (!styles[i]) {\r\n //no styles exist for this line, so add the line's length to the charIndex total\r\n charIndex += textLines[i].length;\r\n continue;\r\n }\r\n //loop through each character of the current line\r\n for (var c = 0; c < textLines[i].length; c++) {\r\n charIndex++;\r\n var thisStyle = styles[i][c];\r\n //check if style exists for this character\r\n if (thisStyle && Object.keys(thisStyle).length > 0) {\r\n var styleChanged = fabric.util.hasStyleChanged(prevStyle, thisStyle, true);\r\n if (styleChanged) {\r\n stylesArray.push({\r\n start: charIndex,\r\n end: charIndex + 1,\r\n style: thisStyle\r\n });\r\n }\r\n else {\r\n //if style is the same as previous character, increase end index\r\n stylesArray[stylesArray.length - 1].end++;\r\n }\r\n }\r\n prevStyle = thisStyle || {};\r\n }\r\n }\r\n return stylesArray;\r\n },\r\n\r\n /**\r\n * Returns the object form of the styles property with styles that are assigned per\r\n * character rather than grouped by range. This format is more verbose, and is\r\n * only used during runtime (not for serialization/storage)\r\n * @memberOf fabric.util\r\n * @param {Array} styles the serialized form of a text object's styles\r\n * @param {String} text the text string that the styles are applied to\r\n * @return {Object}\r\n */\r\n stylesFromArray: function(styles, text) {\r\n if (!Array.isArray(styles)) {\r\n return styles;\r\n }\r\n var textLines = text.split('\\n'),\r\n charIndex = -1, styleIndex = 0, stylesObject = {};\r\n //loop through each textLine\r\n for (var i = 0; i < textLines.length; i++) {\r\n //loop through each character of the current line\r\n for (var c = 0; c < textLines[i].length; c++) {\r\n charIndex++;\r\n //check if there's a style collection that includes the current character\r\n if (styles[styleIndex]\r\n && styles[styleIndex].start <= charIndex\r\n && charIndex < styles[styleIndex].end) {\r\n //create object for line index if it doesn't exist\r\n stylesObject[i] = stylesObject[i] || {};\r\n //assign a style at this character's index\r\n stylesObject[i][c] = Object.assign({}, styles[styleIndex].style);\r\n //if character is at the end of the current style collection, move to the next\r\n if (charIndex === styles[styleIndex].end - 1) {\r\n styleIndex++;\r\n }\r\n }\r\n }\r\n }\r\n return stylesObject;\r\n }\r\n };\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function() {\r\n var _join = Array.prototype.join,\r\n commandLengths = {\r\n m: 2,\r\n l: 2,\r\n h: 1,\r\n v: 1,\r\n c: 6,\r\n s: 4,\r\n q: 4,\r\n t: 2,\r\n a: 7\r\n },\r\n repeatedCommands = {\r\n m: 'l',\r\n M: 'L'\r\n };\r\n function segmentToBezier(th2, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY) {\r\n var costh2 = fabric.util.cos(th2),\r\n sinth2 = fabric.util.sin(th2),\r\n costh3 = fabric.util.cos(th3),\r\n sinth3 = fabric.util.sin(th3),\r\n toX = cosTh * rx * costh3 - sinTh * ry * sinth3 + cx1,\r\n toY = sinTh * rx * costh3 + cosTh * ry * sinth3 + cy1,\r\n cp1X = fromX + mT * ( -cosTh * rx * sinth2 - sinTh * ry * costh2),\r\n cp1Y = fromY + mT * ( -sinTh * rx * sinth2 + cosTh * ry * costh2),\r\n cp2X = toX + mT * ( cosTh * rx * sinth3 + sinTh * ry * costh3),\r\n cp2Y = toY + mT * ( sinTh * rx * sinth3 - cosTh * ry * costh3);\r\n\r\n return ['C',\r\n cp1X, cp1Y,\r\n cp2X, cp2Y,\r\n toX, toY\r\n ];\r\n }\r\n\r\n /* Adapted from http://dxr.mozilla.org/mozilla-central/source/content/svg/content/src/nsSVGPathDataParser.cpp\r\n * by Andrea Bogazzi code is under MPL. if you don't have a copy of the license you can take it here\r\n * http://mozilla.org/MPL/2.0/\r\n */\r\n function arcToSegments(toX, toY, rx, ry, large, sweep, rotateX) {\r\n var PI = Math.PI, th = rotateX * PI / 180,\r\n sinTh = fabric.util.sin(th),\r\n cosTh = fabric.util.cos(th),\r\n fromX = 0, fromY = 0;\r\n\r\n rx = Math.abs(rx);\r\n ry = Math.abs(ry);\r\n\r\n var px = -cosTh * toX * 0.5 - sinTh * toY * 0.5,\r\n py = -cosTh * toY * 0.5 + sinTh * toX * 0.5,\r\n rx2 = rx * rx, ry2 = ry * ry, py2 = py * py, px2 = px * px,\r\n pl = rx2 * ry2 - rx2 * py2 - ry2 * px2,\r\n root = 0;\r\n\r\n if (pl < 0) {\r\n var s = Math.sqrt(1 - pl / (rx2 * ry2));\r\n rx *= s;\r\n ry *= s;\r\n }\r\n else {\r\n root = (large === sweep ? -1.0 : 1.0) *\r\n Math.sqrt( pl / (rx2 * py2 + ry2 * px2));\r\n }\r\n\r\n var cx = root * rx * py / ry,\r\n cy = -root * ry * px / rx,\r\n cx1 = cosTh * cx - sinTh * cy + toX * 0.5,\r\n cy1 = sinTh * cx + cosTh * cy + toY * 0.5,\r\n mTheta = calcVectorAngle(1, 0, (px - cx) / rx, (py - cy) / ry),\r\n dtheta = calcVectorAngle((px - cx) / rx, (py - cy) / ry, (-px - cx) / rx, (-py - cy) / ry);\r\n\r\n if (sweep === 0 && dtheta > 0) {\r\n dtheta -= 2 * PI;\r\n }\r\n else if (sweep === 1 && dtheta < 0) {\r\n dtheta += 2 * PI;\r\n }\r\n\r\n // Convert into cubic bezier segments <= 90deg\r\n var segments = Math.ceil(Math.abs(dtheta / PI * 2)),\r\n result = [], mDelta = dtheta / segments,\r\n mT = 8 / 3 * Math.sin(mDelta / 4) * Math.sin(mDelta / 4) / Math.sin(mDelta / 2),\r\n th3 = mTheta + mDelta;\r\n\r\n for (var i = 0; i < segments; i++) {\r\n result[i] = segmentToBezier(mTheta, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY);\r\n fromX = result[i][5];\r\n fromY = result[i][6];\r\n mTheta = th3;\r\n th3 += mDelta;\r\n }\r\n return result;\r\n }\r\n\r\n /*\r\n * Private\r\n */\r\n function calcVectorAngle(ux, uy, vx, vy) {\r\n var ta = Math.atan2(uy, ux),\r\n tb = Math.atan2(vy, vx);\r\n if (tb >= ta) {\r\n return tb - ta;\r\n }\r\n else {\r\n return 2 * Math.PI - (ta - tb);\r\n }\r\n }\r\n\r\n /**\r\n * Calculate bounding box of a beziercurve\r\n * @param {Number} x0 starting point\r\n * @param {Number} y0\r\n * @param {Number} x1 first control point\r\n * @param {Number} y1\r\n * @param {Number} x2 secondo control point\r\n * @param {Number} y2\r\n * @param {Number} x3 end of bezier\r\n * @param {Number} y3\r\n */\r\n // taken from http://jsbin.com/ivomiq/56/edit no credits available for that.\r\n // TODO: can we normalize this with the starting points set at 0 and then translated the bbox?\r\n function getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3) {\r\n var argsString;\r\n if (fabric.cachesBoundsOfCurve) {\r\n argsString = _join.call(arguments);\r\n if (fabric.boundsOfCurveCache[argsString]) {\r\n return fabric.boundsOfCurveCache[argsString];\r\n }\r\n }\r\n\r\n var sqrt = Math.sqrt,\r\n min = Math.min, max = Math.max,\r\n abs = Math.abs, tvalues = [],\r\n bounds = [[], []],\r\n a, b, c, t, t1, t2, b2ac, sqrtb2ac;\r\n\r\n b = 6 * x0 - 12 * x1 + 6 * x2;\r\n a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;\r\n c = 3 * x1 - 3 * x0;\r\n\r\n for (var i = 0; i < 2; ++i) {\r\n if (i > 0) {\r\n b = 6 * y0 - 12 * y1 + 6 * y2;\r\n a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;\r\n c = 3 * y1 - 3 * y0;\r\n }\r\n\r\n if (abs(a) < 1e-12) {\r\n if (abs(b) < 1e-12) {\r\n continue;\r\n }\r\n t = -c / b;\r\n if (0 < t && t < 1) {\r\n tvalues.push(t);\r\n }\r\n continue;\r\n }\r\n b2ac = b * b - 4 * c * a;\r\n if (b2ac < 0) {\r\n continue;\r\n }\r\n sqrtb2ac = sqrt(b2ac);\r\n t1 = (-b + sqrtb2ac) / (2 * a);\r\n if (0 < t1 && t1 < 1) {\r\n tvalues.push(t1);\r\n }\r\n t2 = (-b - sqrtb2ac) / (2 * a);\r\n if (0 < t2 && t2 < 1) {\r\n tvalues.push(t2);\r\n }\r\n }\r\n\r\n var x, y, j = tvalues.length, jlen = j, mt;\r\n while (j--) {\r\n t = tvalues[j];\r\n mt = 1 - t;\r\n x = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3);\r\n bounds[0][j] = x;\r\n\r\n y = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3);\r\n bounds[1][j] = y;\r\n }\r\n\r\n bounds[0][jlen] = x0;\r\n bounds[1][jlen] = y0;\r\n bounds[0][jlen + 1] = x3;\r\n bounds[1][jlen + 1] = y3;\r\n var result = [\r\n {\r\n x: min.apply(null, bounds[0]),\r\n y: min.apply(null, bounds[1])\r\n },\r\n {\r\n x: max.apply(null, bounds[0]),\r\n y: max.apply(null, bounds[1])\r\n }\r\n ];\r\n if (fabric.cachesBoundsOfCurve) {\r\n fabric.boundsOfCurveCache[argsString] = result;\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Converts arc to a bunch of bezier curves\r\n * @param {Number} fx starting point x\r\n * @param {Number} fy starting point y\r\n * @param {Array} coords Arc command\r\n */\r\n function fromArcToBeziers(fx, fy, coords) {\r\n var rx = coords[1],\r\n ry = coords[2],\r\n rot = coords[3],\r\n large = coords[4],\r\n sweep = coords[5],\r\n tx = coords[6],\r\n ty = coords[7],\r\n segsNorm = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);\r\n\r\n for (var i = 0, len = segsNorm.length; i < len; i++) {\r\n segsNorm[i][1] += fx;\r\n segsNorm[i][2] += fy;\r\n segsNorm[i][3] += fx;\r\n segsNorm[i][4] += fy;\r\n segsNorm[i][5] += fx;\r\n segsNorm[i][6] += fy;\r\n }\r\n return segsNorm;\r\n };\r\n\r\n /**\r\n * This function take a parsed SVG path and make it simpler for fabricJS logic.\r\n * simplification consist of: only UPPERCASE absolute commands ( relative converted to absolute )\r\n * S converted in C, T converted in Q, A converted in C.\r\n * @param {Array} path the array of commands of a parsed svg path for fabric.Path\r\n * @return {Array} the simplified array of commands of a parsed svg path for fabric.Path\r\n */\r\n function makePathSimpler(path) {\r\n // x and y represent the last point of the path. the previous command point.\r\n // we add them to each relative command to make it an absolute comment.\r\n // we also swap the v V h H with L, because are easier to transform.\r\n var x = 0, y = 0, len = path.length,\r\n // x1 and y1 represent the last point of the subpath. the subpath is started with\r\n // m or M command. When a z or Z command is drawn, x and y need to be resetted to\r\n // the last x1 and y1.\r\n x1 = 0, y1 = 0, current, i, converted,\r\n // previous will host the letter of the previous command, to handle S and T.\r\n // controlX and controlY will host the previous reflected control point\r\n destinationPath = [], previous, controlX, controlY;\r\n for (i = 0; i < len; ++i) {\r\n converted = false;\r\n current = path[i].slice(0);\r\n switch (current[0]) { // first letter\r\n case 'l': // lineto, relative\r\n current[0] = 'L';\r\n current[1] += x;\r\n current[2] += y;\r\n // falls through\r\n case 'L':\r\n x = current[1];\r\n y = current[2];\r\n break;\r\n case 'h': // horizontal lineto, relative\r\n current[1] += x;\r\n // falls through\r\n case 'H':\r\n current[0] = 'L';\r\n current[2] = y;\r\n x = current[1];\r\n break;\r\n case 'v': // vertical lineto, relative\r\n current[1] += y;\r\n // falls through\r\n case 'V':\r\n current[0] = 'L';\r\n y = current[1];\r\n current[1] = x;\r\n current[2] = y;\r\n break;\r\n case 'm': // moveTo, relative\r\n current[0] = 'M';\r\n current[1] += x;\r\n current[2] += y;\r\n // falls through\r\n case 'M':\r\n x = current[1];\r\n y = current[2];\r\n x1 = current[1];\r\n y1 = current[2];\r\n break;\r\n case 'c': // bezierCurveTo, relative\r\n current[0] = 'C';\r\n current[1] += x;\r\n current[2] += y;\r\n current[3] += x;\r\n current[4] += y;\r\n current[5] += x;\r\n current[6] += y;\r\n // falls through\r\n case 'C':\r\n controlX = current[3];\r\n controlY = current[4];\r\n x = current[5];\r\n y = current[6];\r\n break;\r\n case 's': // shorthand cubic bezierCurveTo, relative\r\n current[0] = 'S';\r\n current[1] += x;\r\n current[2] += y;\r\n current[3] += x;\r\n current[4] += y;\r\n // falls through\r\n case 'S':\r\n // would be sScC but since we are swapping sSc for C, we check just that.\r\n if (previous === 'C') {\r\n // calculate reflection of previous control points\r\n controlX = 2 * x - controlX;\r\n controlY = 2 * y - controlY;\r\n }\r\n else {\r\n // If there is no previous command or if the previous command was not a C, c, S, or s,\r\n // the control point is coincident with the current point\r\n controlX = x;\r\n controlY = y;\r\n }\r\n x = current[3];\r\n y = current[4];\r\n current[0] = 'C';\r\n current[5] = current[3];\r\n current[6] = current[4];\r\n current[3] = current[1];\r\n current[4] = current[2];\r\n current[1] = controlX;\r\n current[2] = controlY;\r\n // current[3] and current[4] are NOW the second control point.\r\n // we keep it for the next reflection.\r\n controlX = current[3];\r\n controlY = current[4];\r\n break;\r\n case 'q': // quadraticCurveTo, relative\r\n current[0] = 'Q';\r\n current[1] += x;\r\n current[2] += y;\r\n current[3] += x;\r\n current[4] += y;\r\n // falls through\r\n case 'Q':\r\n controlX = current[1];\r\n controlY = current[2];\r\n x = current[3];\r\n y = current[4];\r\n break;\r\n case 't': // shorthand quadraticCurveTo, relative\r\n current[0] = 'T';\r\n current[1] += x;\r\n current[2] += y;\r\n // falls through\r\n case 'T':\r\n if (previous === 'Q') {\r\n // calculate reflection of previous control point\r\n controlX = 2 * x - controlX;\r\n controlY = 2 * y - controlY;\r\n }\r\n else {\r\n // If there is no previous command or if the previous command was not a Q, q, T or t,\r\n // assume the control point is coincident with the current point\r\n controlX = x;\r\n controlY = y;\r\n }\r\n current[0] = 'Q';\r\n x = current[1];\r\n y = current[2];\r\n current[1] = controlX;\r\n current[2] = controlY;\r\n current[3] = x;\r\n current[4] = y;\r\n break;\r\n case 'a':\r\n current[0] = 'A';\r\n current[6] += x;\r\n current[7] += y;\r\n // falls through\r\n case 'A':\r\n converted = true;\r\n destinationPath = destinationPath.concat(fromArcToBeziers(x, y, current));\r\n x = current[6];\r\n y = current[7];\r\n break;\r\n case 'z':\r\n case 'Z':\r\n x = x1;\r\n y = y1;\r\n break;\r\n default:\r\n }\r\n if (!converted) {\r\n destinationPath.push(current);\r\n }\r\n previous = current[0];\r\n }\r\n return destinationPath;\r\n };\r\n\r\n /**\r\n * Calc length from point x1,y1 to x2,y2\r\n * @param {Number} x1 starting point x\r\n * @param {Number} y1 starting point y\r\n * @param {Number} x2 starting point x\r\n * @param {Number} y2 starting point y\r\n * @return {Number} length of segment\r\n */\r\n function calcLineLength(x1, y1, x2, y2) {\r\n return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));\r\n }\r\n\r\n // functions for the Cubic beizer\r\n // taken from: https://github.com/konvajs/konva/blob/7.0.5/src/shapes/Path.ts#L350\r\n function CB1(t) {\r\n return t * t * t;\r\n }\r\n function CB2(t) {\r\n return 3 * t * t * (1 - t);\r\n }\r\n function CB3(t) {\r\n return 3 * t * (1 - t) * (1 - t);\r\n }\r\n function CB4(t) {\r\n return (1 - t) * (1 - t) * (1 - t);\r\n }\r\n\r\n function getPointOnCubicBezierIterator(p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y) {\r\n return function(pct) {\r\n var c1 = CB1(pct), c2 = CB2(pct), c3 = CB3(pct), c4 = CB4(pct);\r\n return {\r\n x: p4x * c1 + p3x * c2 + p2x * c3 + p1x * c4,\r\n y: p4y * c1 + p3y * c2 + p2y * c3 + p1y * c4\r\n };\r\n };\r\n }\r\n\r\n function getTangentCubicIterator(p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y) {\r\n return function (pct) {\r\n var invT = 1 - pct,\r\n tangentX = (3 * invT * invT * (p2x - p1x)) + (6 * invT * pct * (p3x - p2x)) +\r\n (3 * pct * pct * (p4x - p3x)),\r\n tangentY = (3 * invT * invT * (p2y - p1y)) + (6 * invT * pct * (p3y - p2y)) +\r\n (3 * pct * pct * (p4y - p3y));\r\n return Math.atan2(tangentY, tangentX);\r\n };\r\n }\r\n\r\n function QB1(t) {\r\n return t * t;\r\n }\r\n\r\n function QB2(t) {\r\n return 2 * t * (1 - t);\r\n }\r\n\r\n function QB3(t) {\r\n return (1 - t) * (1 - t);\r\n }\r\n\r\n function getPointOnQuadraticBezierIterator(p1x, p1y, p2x, p2y, p3x, p3y) {\r\n return function(pct) {\r\n var c1 = QB1(pct), c2 = QB2(pct), c3 = QB3(pct);\r\n return {\r\n x: p3x * c1 + p2x * c2 + p1x * c3,\r\n y: p3y * c1 + p2y * c2 + p1y * c3\r\n };\r\n };\r\n }\r\n\r\n function getTangentQuadraticIterator(p1x, p1y, p2x, p2y, p3x, p3y) {\r\n return function (pct) {\r\n var invT = 1 - pct,\r\n tangentX = (2 * invT * (p2x - p1x)) + (2 * pct * (p3x - p2x)),\r\n tangentY = (2 * invT * (p2y - p1y)) + (2 * pct * (p3y - p2y));\r\n return Math.atan2(tangentY, tangentX);\r\n };\r\n }\r\n\r\n\r\n // this will run over a path segment ( a cubic or quadratic segment) and approximate it\r\n // with 100 segemnts. This will good enough to calculate the length of the curve\r\n function pathIterator(iterator, x1, y1) {\r\n var tempP = { x: x1, y: y1 }, p, tmpLen = 0, perc;\r\n for (perc = 1; perc <= 100; perc += 1) {\r\n p = iterator(perc / 100);\r\n tmpLen += calcLineLength(tempP.x, tempP.y, p.x, p.y);\r\n tempP = p;\r\n }\r\n return tmpLen;\r\n }\r\n\r\n /**\r\n * Given a pathInfo, and a distance in pixels, find the percentage from 0 to 1\r\n * that correspond to that pixels run over the path.\r\n * The percentage will be then used to find the correct point on the canvas for the path.\r\n * @param {Array} segInfo fabricJS collection of information on a parsed path\r\n * @param {Number} distance from starting point, in pixels.\r\n * @return {Object} info object with x and y ( the point on canvas ) and angle, the tangent on that point;\r\n */\r\n function findPercentageForDistance(segInfo, distance) {\r\n var perc = 0, tmpLen = 0, iterator = segInfo.iterator, tempP = { x: segInfo.x, y: segInfo.y },\r\n p, nextLen, nextStep = 0.01, angleFinder = segInfo.angleFinder, lastPerc;\r\n // nextStep > 0.0001 covers 0.00015625 that 1/64th of 1/100\r\n // the path\r\n while (tmpLen < distance && nextStep > 0.0001) {\r\n p = iterator(perc);\r\n lastPerc = perc;\r\n nextLen = calcLineLength(tempP.x, tempP.y, p.x, p.y);\r\n // compare tmpLen each cycle with distance, decide next perc to test.\r\n if ((nextLen + tmpLen) > distance) {\r\n // we discard this step and we make smaller steps.\r\n perc -= nextStep;\r\n nextStep /= 2;\r\n }\r\n else {\r\n tempP = p;\r\n perc += nextStep;\r\n tmpLen += nextLen;\r\n }\r\n }\r\n p.angle = angleFinder(lastPerc);\r\n return p;\r\n }\r\n\r\n /**\r\n * Run over a parsed and simplifed path and extrac some informations.\r\n * informations are length of each command and starting point\r\n * @param {Array} path fabricJS parsed path commands\r\n * @return {Array} path commands informations\r\n */\r\n function getPathSegmentsInfo(path) {\r\n var totalLength = 0, len = path.length, current,\r\n //x2 and y2 are the coords of segment start\r\n //x1 and y1 are the coords of the current point\r\n x1 = 0, y1 = 0, x2 = 0, y2 = 0, info = [], iterator, tempInfo, angleFinder;\r\n for (var i = 0; i < len; i++) {\r\n current = path[i];\r\n tempInfo = {\r\n x: x1,\r\n y: y1,\r\n command: current[0],\r\n };\r\n switch (current[0]) { //first letter\r\n case 'M':\r\n tempInfo.length = 0;\r\n x2 = x1 = current[1];\r\n y2 = y1 = current[2];\r\n break;\r\n case 'L':\r\n tempInfo.length = calcLineLength(x1, y1, current[1], current[2]);\r\n x1 = current[1];\r\n y1 = current[2];\r\n break;\r\n case 'C':\r\n iterator = getPointOnCubicBezierIterator(\r\n x1,\r\n y1,\r\n current[1],\r\n current[2],\r\n current[3],\r\n current[4],\r\n current[5],\r\n current[6]\r\n );\r\n angleFinder = getTangentCubicIterator(\r\n x1,\r\n y1,\r\n current[1],\r\n current[2],\r\n current[3],\r\n current[4],\r\n current[5],\r\n current[6]\r\n );\r\n tempInfo.iterator = iterator;\r\n tempInfo.angleFinder = angleFinder;\r\n tempInfo.length = pathIterator(iterator, x1, y1);\r\n x1 = current[5];\r\n y1 = current[6];\r\n break;\r\n case 'Q':\r\n iterator = getPointOnQuadraticBezierIterator(\r\n x1,\r\n y1,\r\n current[1],\r\n current[2],\r\n current[3],\r\n current[4]\r\n );\r\n angleFinder = getTangentQuadraticIterator(\r\n x1,\r\n y1,\r\n current[1],\r\n current[2],\r\n current[3],\r\n current[4]\r\n );\r\n tempInfo.iterator = iterator;\r\n tempInfo.angleFinder = angleFinder;\r\n tempInfo.length = pathIterator(iterator, x1, y1);\r\n x1 = current[3];\r\n y1 = current[4];\r\n break;\r\n case 'Z':\r\n case 'z':\r\n // we add those in order to ease calculations later\r\n tempInfo.destX = x2;\r\n tempInfo.destY = y2;\r\n tempInfo.length = calcLineLength(x1, y1, x2, y2);\r\n x1 = x2;\r\n y1 = y2;\r\n break;\r\n }\r\n totalLength += tempInfo.length;\r\n info.push(tempInfo);\r\n }\r\n info.push({ length: totalLength, x: x1, y: y1 });\r\n return info;\r\n }\r\n\r\n function getPointOnPath(path, distance, infos) {\r\n if (!infos) {\r\n infos = getPathSegmentsInfo(path);\r\n }\r\n var i = 0;\r\n while ((distance - infos[i].length > 0) && i < (infos.length - 2)) {\r\n distance -= infos[i].length;\r\n i++;\r\n }\r\n // var distance = infos[infos.length - 1] * perc;\r\n var segInfo = infos[i], segPercent = distance / segInfo.length,\r\n command = segInfo.command, segment = path[i], info;\r\n\r\n switch (command) {\r\n case 'M':\r\n return { x: segInfo.x, y: segInfo.y, angle: 0 };\r\n case 'Z':\r\n case 'z':\r\n info = new fabric.Point(segInfo.x, segInfo.y).lerp(\r\n new fabric.Point(segInfo.destX, segInfo.destY),\r\n segPercent\r\n );\r\n info.angle = Math.atan2(segInfo.destY - segInfo.y, segInfo.destX - segInfo.x);\r\n return info;\r\n case 'L':\r\n info = new fabric.Point(segInfo.x, segInfo.y).lerp(\r\n new fabric.Point(segment[1], segment[2]),\r\n segPercent\r\n );\r\n info.angle = Math.atan2(segment[2] - segInfo.y, segment[1] - segInfo.x);\r\n return info;\r\n case 'C':\r\n return findPercentageForDistance(segInfo, distance);\r\n case 'Q':\r\n return findPercentageForDistance(segInfo, distance);\r\n }\r\n }\r\n\r\n /**\r\n *\r\n * @param {string} pathString\r\n * @return {(string|number)[][]} An array of SVG path commands\r\n * @example Usage\r\n * parsePath('M 3 4 Q 3 5 2 1 4 0 Q 9 12 2 1 4 0') === [\r\n * ['M', 3, 4],\r\n * ['Q', 3, 5, 2, 1, 4, 0],\r\n * ['Q', 9, 12, 2, 1, 4, 0],\r\n * ];\r\n *\r\n */\r\n function parsePath(pathString) {\r\n var result = [],\r\n coords = [],\r\n currentPath,\r\n parsed,\r\n re = fabric.rePathCommand,\r\n rNumber = '[-+]?(?:\\\\d*\\\\.\\\\d+|\\\\d+\\\\.?)(?:[eE][-+]?\\\\d+)?\\\\s*',\r\n rNumberCommaWsp = '(' + rNumber + ')' + fabric.commaWsp,\r\n rFlagCommaWsp = '([01])' + fabric.commaWsp + '?',\r\n rArcSeq = rNumberCommaWsp + '?' + rNumberCommaWsp + '?' + rNumberCommaWsp + rFlagCommaWsp + rFlagCommaWsp +\r\n rNumberCommaWsp + '?(' + rNumber + ')',\r\n regArcArgumentSequence = new RegExp(rArcSeq, 'g'),\r\n match,\r\n coordsStr,\r\n // one of commands (m,M,l,L,q,Q,c,C,etc.) followed by non-command characters (i.e. command values)\r\n path;\r\n if (!pathString || !pathString.match) {\r\n return result;\r\n }\r\n path = pathString.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi);\r\n\r\n for (var i = 0, coordsParsed, len = path.length; i < len; i++) {\r\n currentPath = path[i];\r\n\r\n coordsStr = currentPath.slice(1).trim();\r\n coords.length = 0;\r\n\r\n var command = currentPath.charAt(0);\r\n coordsParsed = [command];\r\n\r\n if (command.toLowerCase() === 'a') {\r\n // arcs have special flags that apparently don't require spaces so handle special\r\n for (var args; (args = regArcArgumentSequence.exec(coordsStr));) {\r\n for (var j = 1; j < args.length; j++) {\r\n coords.push(args[j]);\r\n }\r\n }\r\n }\r\n else {\r\n while ((match = re.exec(coordsStr))) {\r\n coords.push(match[0]);\r\n }\r\n }\r\n\r\n for (var j = 0, jlen = coords.length; j < jlen; j++) {\r\n parsed = parseFloat(coords[j]);\r\n if (!isNaN(parsed)) {\r\n coordsParsed.push(parsed);\r\n }\r\n }\r\n\r\n var commandLength = commandLengths[command.toLowerCase()],\r\n repeatedCommand = repeatedCommands[command] || command;\r\n\r\n if (coordsParsed.length - 1 > commandLength) {\r\n for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) {\r\n result.push([command].concat(coordsParsed.slice(k, k + commandLength)));\r\n command = repeatedCommand;\r\n }\r\n }\r\n else {\r\n result.push(coordsParsed);\r\n }\r\n }\r\n\r\n return result;\r\n };\r\n\r\n /**\r\n *\r\n * Converts points to a smooth SVG path\r\n * @param {{ x: number,y: number }[]} points Array of points\r\n * @param {number} [correction] Apply a correction to the path (usually we use `width / 1000`). If value is undefined 0 is used as the correction value.\r\n * @return {(string|number)[][]} An array of SVG path commands\r\n */\r\n function getSmoothPathFromPoints(points, correction) {\r\n var path = [], i,\r\n p1 = new fabric.Point(points[0].x, points[0].y),\r\n p2 = new fabric.Point(points[1].x, points[1].y),\r\n len = points.length, multSignX = 1, multSignY = 0, manyPoints = len > 2;\r\n correction = correction || 0;\r\n\r\n if (manyPoints) {\r\n multSignX = points[2].x < p2.x ? -1 : points[2].x === p2.x ? 0 : 1;\r\n multSignY = points[2].y < p2.y ? -1 : points[2].y === p2.y ? 0 : 1;\r\n }\r\n path.push(['M', p1.x - multSignX * correction, p1.y - multSignY * correction]);\r\n for (i = 1; i < len; i++) {\r\n if (!p1.eq(p2)) {\r\n var midPoint = p1.midPointFrom(p2);\r\n // p1 is our bezier control point\r\n // midpoint is our endpoint\r\n // start point is p(i-1) value.\r\n path.push(['Q', p1.x, p1.y, midPoint.x, midPoint.y]);\r\n }\r\n p1 = points[i];\r\n if ((i + 1) < points.length) {\r\n p2 = points[i + 1];\r\n }\r\n }\r\n if (manyPoints) {\r\n multSignX = p1.x > points[i - 2].x ? 1 : p1.x === points[i - 2].x ? 0 : -1;\r\n multSignY = p1.y > points[i - 2].y ? 1 : p1.y === points[i - 2].y ? 0 : -1;\r\n }\r\n path.push(['L', p1.x + multSignX * correction, p1.y + multSignY * correction]);\r\n return path;\r\n }\r\n /**\r\n * Transform a path by transforming each segment.\r\n * it has to be a simplified path or it won't work.\r\n * WARNING: this depends from pathOffset for correct operation\r\n * @param {Array} path fabricJS parsed and simplified path commands\r\n * @param {Array} transform matrix that represent the transformation\r\n * @param {Object} [pathOffset] the fabric.Path pathOffset\r\n * @param {Number} pathOffset.x\r\n * @param {Number} pathOffset.y\r\n * @returns {Array} the transformed path\r\n */\r\n function transformPath(path, transform, pathOffset) {\r\n if (pathOffset) {\r\n transform = fabric.util.multiplyTransformMatrices(\r\n transform,\r\n [1, 0, 0, 1, -pathOffset.x, -pathOffset.y]\r\n );\r\n }\r\n return path.map(function(pathSegment) {\r\n var newSegment = pathSegment.slice(0), point = {};\r\n for (var i = 1; i < pathSegment.length - 1; i += 2) {\r\n point.x = pathSegment[i];\r\n point.y = pathSegment[i + 1];\r\n point = fabric.util.transformPoint(point, transform);\r\n newSegment[i] = point.x;\r\n newSegment[i + 1] = point.y;\r\n }\r\n return newSegment;\r\n });\r\n }\r\n\r\n /**\r\n * Join path commands to go back to svg format\r\n * @param {Array} pathData fabricJS parsed path commands\r\n * @return {String} joined path 'M 0 0 L 20 30'\r\n */\r\n fabric.util.joinPath = function(pathData) {\r\n return pathData.map(function (segment) { return segment.join(' '); }).join(' ');\r\n };\r\n fabric.util.parsePath = parsePath;\r\n fabric.util.makePathSimpler = makePathSimpler;\r\n fabric.util.getSmoothPathFromPoints = getSmoothPathFromPoints;\r\n fabric.util.getPathSegmentsInfo = getPathSegmentsInfo;\r\n fabric.util.getBoundsOfCurve = getBoundsOfCurve;\r\n fabric.util.getPointOnPath = getPointOnPath;\r\n fabric.util.transformPath = transformPath;\r\n})();\r\n\r\n\r\n(function() {\r\n\r\n var slice = Array.prototype.slice;\r\n\r\n /**\r\n * Invokes method on all items in a given array\r\n * @memberOf fabric.util.array\r\n * @param {Array} array Array to iterate over\r\n * @param {String} method Name of a method to invoke\r\n * @return {Array}\r\n */\r\n function invoke(array, method) {\r\n var args = slice.call(arguments, 2), result = [];\r\n for (var i = 0, len = array.length; i < len; i++) {\r\n result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]);\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Finds maximum value in array (not necessarily \"first\" one)\r\n * @memberOf fabric.util.array\r\n * @param {Array} array Array to iterate over\r\n * @param {String} byProperty\r\n * @return {*}\r\n */\r\n function max(array, byProperty) {\r\n return find(array, byProperty, function(value1, value2) {\r\n return value1 >= value2;\r\n });\r\n }\r\n\r\n /**\r\n * Finds minimum value in array (not necessarily \"first\" one)\r\n * @memberOf fabric.util.array\r\n * @param {Array} array Array to iterate over\r\n * @param {String} byProperty\r\n * @return {*}\r\n */\r\n function min(array, byProperty) {\r\n return find(array, byProperty, function(value1, value2) {\r\n return value1 < value2;\r\n });\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n function fill(array, value) {\r\n var k = array.length;\r\n while (k--) {\r\n array[k] = value;\r\n }\r\n return array;\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n function find(array, byProperty, condition) {\r\n if (!array || array.length === 0) {\r\n return;\r\n }\r\n\r\n var i = array.length - 1,\r\n result = byProperty ? array[i][byProperty] : array[i];\r\n if (byProperty) {\r\n while (i--) {\r\n if (condition(array[i][byProperty], result)) {\r\n result = array[i][byProperty];\r\n }\r\n }\r\n }\r\n else {\r\n while (i--) {\r\n if (condition(array[i], result)) {\r\n result = array[i];\r\n }\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * @namespace fabric.util.array\r\n */\r\n fabric.util.array = {\r\n fill: fill,\r\n invoke: invoke,\r\n min: min,\r\n max: max\r\n };\r\n\r\n})();\r\n\r\n\r\n(function() {\r\n /**\r\n * Copies all enumerable properties of one js object to another\r\n * this does not and cannot compete with generic utils.\r\n * Does not clone or extend fabric.Object subclasses.\r\n * This is mostly for internal use and has extra handling for fabricJS objects\r\n * it skips the canvas and group properties in deep cloning.\r\n * @memberOf fabric.util.object\r\n * @param {Object} destination Where to copy to\r\n * @param {Object} source Where to copy from\r\n * @param {Boolean} [deep] Whether to extend nested objects\r\n * @return {Object}\r\n */\r\n\r\n function extend(destination, source, deep) {\r\n // JScript DontEnum bug is not taken care of\r\n // the deep clone is for internal use, is not meant to avoid\r\n // javascript traps or cloning html element or self referenced objects.\r\n if (deep) {\r\n if (!fabric.isLikelyNode && source instanceof Element) {\r\n // avoid cloning deep images, canvases,\r\n destination = source;\r\n }\r\n else if (source instanceof Array) {\r\n destination = [];\r\n for (var i = 0, len = source.length; i < len; i++) {\r\n destination[i] = extend({ }, source[i], deep);\r\n }\r\n }\r\n else if (source && typeof source === 'object') {\r\n for (var property in source) {\r\n if (property === 'canvas' || property === 'group') {\r\n // we do not want to clone this props at all.\r\n // we want to keep the keys in the copy\r\n destination[property] = null;\r\n }\r\n else if (source.hasOwnProperty(property)) {\r\n destination[property] = extend({ }, source[property], deep);\r\n }\r\n }\r\n }\r\n else {\r\n // this sounds odd for an extend but is ok for recursive use\r\n destination = source;\r\n }\r\n }\r\n else {\r\n for (var property in source) {\r\n destination[property] = source[property];\r\n }\r\n }\r\n return destination;\r\n }\r\n\r\n /**\r\n * Creates an empty object and copies all enumerable properties of another object to it\r\n * This method is mostly for internal use, and not intended for duplicating shapes in canvas. \r\n * @memberOf fabric.util.object\r\n * @param {Object} object Object to clone\r\n * @param {Boolean} [deep] Whether to clone nested objects\r\n * @return {Object}\r\n */\r\n\r\n //TODO: this function return an empty object if you try to clone null\r\n function clone(object, deep) {\r\n return extend({ }, object, deep);\r\n }\r\n\r\n /** @namespace fabric.util.object */\r\n fabric.util.object = {\r\n extend: extend,\r\n clone: clone\r\n };\r\n fabric.util.object.extend(fabric.util, fabric.Observable);\r\n})();\r\n\r\n\r\n(function() {\r\n\r\n /**\r\n * Camelizes a string\r\n * @memberOf fabric.util.string\r\n * @param {String} string String to camelize\r\n * @return {String} Camelized version of a string\r\n */\r\n function camelize(string) {\r\n return string.replace(/-+(.)?/g, function(match, character) {\r\n return character ? character.toUpperCase() : '';\r\n });\r\n }\r\n\r\n /**\r\n * Capitalizes a string\r\n * @memberOf fabric.util.string\r\n * @param {String} string String to capitalize\r\n * @param {Boolean} [firstLetterOnly] If true only first letter is capitalized\r\n * and other letters stay untouched, if false first letter is capitalized\r\n * and other letters are converted to lowercase.\r\n * @return {String} Capitalized version of a string\r\n */\r\n function capitalize(string, firstLetterOnly) {\r\n return string.charAt(0).toUpperCase() +\r\n (firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase());\r\n }\r\n\r\n /**\r\n * Escapes XML in a string\r\n * @memberOf fabric.util.string\r\n * @param {String} string String to escape\r\n * @return {String} Escaped version of a string\r\n */\r\n function escapeXml(string) {\r\n return string.replace(/&/g, '&')\r\n .replace(/\"/g, '"')\r\n .replace(/'/g, ''')\r\n .replace(//g, '>');\r\n }\r\n\r\n /**\r\n * Divide a string in the user perceived single units\r\n * @memberOf fabric.util.string\r\n * @param {String} textstring String to escape\r\n * @return {Array} array containing the graphemes\r\n */\r\n function graphemeSplit(textstring) {\r\n var i = 0, chr, graphemes = [];\r\n for (i = 0, chr; i < textstring.length; i++) {\r\n if ((chr = getWholeChar(textstring, i)) === false) {\r\n continue;\r\n }\r\n graphemes.push(chr);\r\n }\r\n return graphemes;\r\n }\r\n\r\n // taken from mdn in the charAt doc page.\r\n function getWholeChar(str, i) {\r\n var code = str.charCodeAt(i);\r\n\r\n if (isNaN(code)) {\r\n return ''; // Position not found\r\n }\r\n if (code < 0xD800 || code > 0xDFFF) {\r\n return str.charAt(i);\r\n }\r\n\r\n // High surrogate (could change last hex to 0xDB7F to treat high private\r\n // surrogates as single characters)\r\n if (0xD800 <= code && code <= 0xDBFF) {\r\n if (str.length <= (i + 1)) {\r\n throw 'High surrogate without following low surrogate';\r\n }\r\n var next = str.charCodeAt(i + 1);\r\n if (0xDC00 > next || next > 0xDFFF) {\r\n throw 'High surrogate without following low surrogate';\r\n }\r\n return str.charAt(i) + str.charAt(i + 1);\r\n }\r\n // Low surrogate (0xDC00 <= code && code <= 0xDFFF)\r\n if (i === 0) {\r\n throw 'Low surrogate without preceding high surrogate';\r\n }\r\n var prev = str.charCodeAt(i - 1);\r\n\r\n // (could change last hex to 0xDB7F to treat high private\r\n // surrogates as single characters)\r\n if (0xD800 > prev || prev > 0xDBFF) {\r\n throw 'Low surrogate without preceding high surrogate';\r\n }\r\n // We can pass over low surrogates now as the second component\r\n // in a pair which we have already processed\r\n return false;\r\n }\r\n\r\n\r\n /**\r\n * String utilities\r\n * @namespace fabric.util.string\r\n */\r\n fabric.util.string = {\r\n camelize: camelize,\r\n capitalize: capitalize,\r\n escapeXml: escapeXml,\r\n graphemeSplit: graphemeSplit\r\n };\r\n})();\r\n\r\n\r\n(function() {\r\n\r\n var slice = Array.prototype.slice, emptyFunction = function() { },\r\n\r\n IS_DONTENUM_BUGGY = (function() {\r\n for (var p in { toString: 1 }) {\r\n if (p === 'toString') {\r\n return false;\r\n }\r\n }\r\n return true;\r\n })(),\r\n\r\n /** @ignore */\r\n addMethods = function(klass, source, parent) {\r\n for (var property in source) {\r\n\r\n if (property in klass.prototype &&\r\n typeof klass.prototype[property] === 'function' &&\r\n (source[property] + '').indexOf('callSuper') > -1) {\r\n\r\n klass.prototype[property] = (function(property) {\r\n return function() {\r\n\r\n var superclass = this.constructor.superclass;\r\n this.constructor.superclass = parent;\r\n var returnValue = source[property].apply(this, arguments);\r\n this.constructor.superclass = superclass;\r\n\r\n if (property !== 'initialize') {\r\n return returnValue;\r\n }\r\n };\r\n })(property);\r\n }\r\n else {\r\n klass.prototype[property] = source[property];\r\n }\r\n\r\n if (IS_DONTENUM_BUGGY) {\r\n if (source.toString !== Object.prototype.toString) {\r\n klass.prototype.toString = source.toString;\r\n }\r\n if (source.valueOf !== Object.prototype.valueOf) {\r\n klass.prototype.valueOf = source.valueOf;\r\n }\r\n }\r\n }\r\n };\r\n\r\n function Subclass() { }\r\n\r\n function callSuper(methodName) {\r\n var parentMethod = null,\r\n _this = this;\r\n\r\n // climb prototype chain to find method not equal to callee's method\r\n while (_this.constructor.superclass) {\r\n var superClassMethod = _this.constructor.superclass.prototype[methodName];\r\n if (_this[methodName] !== superClassMethod) {\r\n parentMethod = superClassMethod;\r\n break;\r\n }\r\n // eslint-disable-next-line\r\n _this = _this.constructor.superclass.prototype;\r\n }\r\n\r\n if (!parentMethod) {\r\n return console.log('tried to callSuper ' + methodName + ', method not found in prototype chain', this);\r\n }\r\n\r\n return (arguments.length > 1)\r\n ? parentMethod.apply(this, slice.call(arguments, 1))\r\n : parentMethod.call(this);\r\n }\r\n\r\n /**\r\n * Helper for creation of \"classes\".\r\n * @memberOf fabric.util\r\n * @param {Function} [parent] optional \"Class\" to inherit from\r\n * @param {Object} [properties] Properties shared by all instances of this class\r\n * (be careful modifying objects defined here as this would affect all instances)\r\n */\r\n function createClass() {\r\n var parent = null,\r\n properties = slice.call(arguments, 0);\r\n\r\n if (typeof properties[0] === 'function') {\r\n parent = properties.shift();\r\n }\r\n function klass() {\r\n this.initialize.apply(this, arguments);\r\n }\r\n\r\n klass.superclass = parent;\r\n klass.subclasses = [];\r\n\r\n if (parent) {\r\n Subclass.prototype = parent.prototype;\r\n klass.prototype = new Subclass();\r\n parent.subclasses.push(klass);\r\n }\r\n for (var i = 0, length = properties.length; i < length; i++) {\r\n addMethods(klass, properties[i], parent);\r\n }\r\n if (!klass.prototype.initialize) {\r\n klass.prototype.initialize = emptyFunction;\r\n }\r\n klass.prototype.constructor = klass;\r\n klass.prototype.callSuper = callSuper;\r\n return klass;\r\n }\r\n\r\n fabric.util.createClass = createClass;\r\n})();\r\n\r\n\r\n(function () {\r\n // since ie11 can use addEventListener but they do not support options, i need to check\r\n var couldUseAttachEvent = !!fabric.document.createElement('div').attachEvent,\r\n touchEvents = ['touchstart', 'touchmove', 'touchend'];\r\n /**\r\n * Adds an event listener to an element\r\n * @function\r\n * @memberOf fabric.util\r\n * @param {HTMLElement} element\r\n * @param {String} eventName\r\n * @param {Function} handler\r\n */\r\n fabric.util.addListener = function(element, eventName, handler, options) {\r\n element && element.addEventListener(eventName, handler, couldUseAttachEvent ? false : options);\r\n };\r\n\r\n /**\r\n * Removes an event listener from an element\r\n * @function\r\n * @memberOf fabric.util\r\n * @param {HTMLElement} element\r\n * @param {String} eventName\r\n * @param {Function} handler\r\n */\r\n fabric.util.removeListener = function(element, eventName, handler, options) {\r\n element && element.removeEventListener(eventName, handler, couldUseAttachEvent ? false : options);\r\n };\r\n\r\n function getTouchInfo(event) {\r\n var touchProp = event.changedTouches;\r\n if (touchProp && touchProp[0]) {\r\n return touchProp[0];\r\n }\r\n return event;\r\n }\r\n\r\n fabric.util.getPointer = function(event) {\r\n var element = event.target,\r\n scroll = fabric.util.getScrollLeftTop(element),\r\n _evt = getTouchInfo(event);\r\n return {\r\n x: _evt.clientX + scroll.left,\r\n y: _evt.clientY + scroll.top\r\n };\r\n };\r\n\r\n fabric.util.isTouchEvent = function(event) {\r\n return touchEvents.indexOf(event.type) > -1 || event.pointerType === 'touch';\r\n };\r\n})();\r\n\r\n\r\n(function () {\r\n\r\n /**\r\n * Cross-browser wrapper for setting element's style\r\n * @memberOf fabric.util\r\n * @param {HTMLElement} element\r\n * @param {Object} styles\r\n * @return {HTMLElement} Element that was passed as a first argument\r\n */\r\n function setStyle(element, styles) {\r\n var elementStyle = element.style;\r\n if (!elementStyle) {\r\n return element;\r\n }\r\n if (typeof styles === 'string') {\r\n element.style.cssText += ';' + styles;\r\n return styles.indexOf('opacity') > -1\r\n ? setOpacity(element, styles.match(/opacity:\\s*(\\d?\\.?\\d*)/)[1])\r\n : element;\r\n }\r\n for (var property in styles) {\r\n if (property === 'opacity') {\r\n setOpacity(element, styles[property]);\r\n }\r\n else {\r\n var normalizedProperty = (property === 'float' || property === 'cssFloat')\r\n ? (typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat')\r\n : property;\r\n elementStyle.setProperty(normalizedProperty, styles[property]);\r\n }\r\n }\r\n return element;\r\n }\r\n\r\n var parseEl = fabric.document.createElement('div'),\r\n supportsOpacity = typeof parseEl.style.opacity === 'string',\r\n supportsFilters = typeof parseEl.style.filter === 'string',\r\n reOpacity = /alpha\\s*\\(\\s*opacity\\s*=\\s*([^\\)]+)\\)/,\r\n\r\n /** @ignore */\r\n setOpacity = function (element) { return element; };\r\n\r\n if (supportsOpacity) {\r\n /** @ignore */\r\n setOpacity = function(element, value) {\r\n element.style.opacity = value;\r\n return element;\r\n };\r\n }\r\n else if (supportsFilters) {\r\n /** @ignore */\r\n setOpacity = function(element, value) {\r\n var es = element.style;\r\n if (element.currentStyle && !element.currentStyle.hasLayout) {\r\n es.zoom = 1;\r\n }\r\n if (reOpacity.test(es.filter)) {\r\n value = value >= 0.9999 ? '' : ('alpha(opacity=' + (value * 100) + ')');\r\n es.filter = es.filter.replace(reOpacity, value);\r\n }\r\n else {\r\n es.filter += ' alpha(opacity=' + (value * 100) + ')';\r\n }\r\n return element;\r\n };\r\n }\r\n\r\n fabric.util.setStyle = setStyle;\r\n\r\n})();\r\n\r\n\r\n(function() {\r\n\r\n var _slice = Array.prototype.slice;\r\n\r\n /**\r\n * Takes id and returns an element with that id (if one exists in a document)\r\n * @memberOf fabric.util\r\n * @param {String|HTMLElement} id\r\n * @return {HTMLElement|null}\r\n */\r\n function getById(id) {\r\n return typeof id === 'string' ? fabric.document.getElementById(id) : id;\r\n }\r\n\r\n var sliceCanConvertNodelists,\r\n /**\r\n * Converts an array-like object (e.g. arguments or NodeList) to an array\r\n * @memberOf fabric.util\r\n * @param {Object} arrayLike\r\n * @return {Array}\r\n */\r\n toArray = function(arrayLike) {\r\n return _slice.call(arrayLike, 0);\r\n };\r\n\r\n try {\r\n sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array;\r\n }\r\n catch (err) { }\r\n\r\n if (!sliceCanConvertNodelists) {\r\n toArray = function(arrayLike) {\r\n var arr = new Array(arrayLike.length), i = arrayLike.length;\r\n while (i--) {\r\n arr[i] = arrayLike[i];\r\n }\r\n return arr;\r\n };\r\n }\r\n\r\n /**\r\n * Creates specified element with specified attributes\r\n * @memberOf fabric.util\r\n * @param {String} tagName Type of an element to create\r\n * @param {Object} [attributes] Attributes to set on an element\r\n * @return {HTMLElement} Newly created element\r\n */\r\n function makeElement(tagName, attributes) {\r\n var el = fabric.document.createElement(tagName);\r\n for (var prop in attributes) {\r\n if (prop === 'class') {\r\n el.className = attributes[prop];\r\n }\r\n else if (prop === 'for') {\r\n el.htmlFor = attributes[prop];\r\n }\r\n else {\r\n el.setAttribute(prop, attributes[prop]);\r\n }\r\n }\r\n return el;\r\n }\r\n\r\n /**\r\n * Adds class to an element\r\n * @memberOf fabric.util\r\n * @param {HTMLElement} element Element to add class to\r\n * @param {String} className Class to add to an element\r\n */\r\n function addClass(element, className) {\r\n if (element && (' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) {\r\n element.className += (element.className ? ' ' : '') + className;\r\n }\r\n }\r\n\r\n /**\r\n * Wraps element with another element\r\n * @memberOf fabric.util\r\n * @param {HTMLElement} element Element to wrap\r\n * @param {HTMLElement|String} wrapper Element to wrap with\r\n * @param {Object} [attributes] Attributes to set on a wrapper\r\n * @return {HTMLElement} wrapper\r\n */\r\n function wrapElement(element, wrapper, attributes) {\r\n if (typeof wrapper === 'string') {\r\n wrapper = makeElement(wrapper, attributes);\r\n }\r\n if (element.parentNode) {\r\n element.parentNode.replaceChild(wrapper, element);\r\n }\r\n wrapper.appendChild(element);\r\n return wrapper;\r\n }\r\n\r\n /**\r\n * Returns element scroll offsets\r\n * @memberOf fabric.util\r\n * @param {HTMLElement} element Element to operate on\r\n * @return {Object} Object with left/top values\r\n */\r\n function getScrollLeftTop(element) {\r\n\r\n var left = 0,\r\n top = 0,\r\n docElement = fabric.document.documentElement,\r\n body = fabric.document.body || {\r\n scrollLeft: 0, scrollTop: 0\r\n };\r\n\r\n // While loop checks (and then sets element to) .parentNode OR .host\r\n // to account for ShadowDOM. We still want to traverse up out of ShadowDOM,\r\n // but the .parentNode of a root ShadowDOM node will always be null, instead\r\n // it should be accessed through .host. See http://stackoverflow.com/a/24765528/4383938\r\n while (element && (element.parentNode || element.host)) {\r\n\r\n // Set element to element parent, or 'host' in case of ShadowDOM\r\n element = element.parentNode || element.host;\r\n\r\n if (element === fabric.document) {\r\n left = body.scrollLeft || docElement.scrollLeft || 0;\r\n top = body.scrollTop || docElement.scrollTop || 0;\r\n }\r\n else {\r\n left += element.scrollLeft || 0;\r\n top += element.scrollTop || 0;\r\n }\r\n\r\n if (element.nodeType === 1 && element.style.position === 'fixed') {\r\n break;\r\n }\r\n }\r\n\r\n return { left: left, top: top };\r\n }\r\n\r\n /**\r\n * Returns offset for a given element\r\n * @function\r\n * @memberOf fabric.util\r\n * @param {HTMLElement} element Element to get offset for\r\n * @return {Object} Object with \"left\" and \"top\" properties\r\n */\r\n function getElementOffset(element) {\r\n var docElem,\r\n doc = element && element.ownerDocument,\r\n box = { left: 0, top: 0 },\r\n offset = { left: 0, top: 0 },\r\n scrollLeftTop,\r\n offsetAttributes = {\r\n borderLeftWidth: 'left',\r\n borderTopWidth: 'top',\r\n paddingLeft: 'left',\r\n paddingTop: 'top'\r\n };\r\n\r\n if (!doc) {\r\n return offset;\r\n }\r\n\r\n for (var attr in offsetAttributes) {\r\n offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0;\r\n }\r\n\r\n docElem = doc.documentElement;\r\n if ( typeof element.getBoundingClientRect !== 'undefined' ) {\r\n box = element.getBoundingClientRect();\r\n }\r\n\r\n scrollLeftTop = getScrollLeftTop(element);\r\n\r\n return {\r\n left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left,\r\n top: box.top + scrollLeftTop.top - (docElem.clientTop || 0) + offset.top\r\n };\r\n }\r\n\r\n /**\r\n * Returns style attribute value of a given element\r\n * @memberOf fabric.util\r\n * @param {HTMLElement} element Element to get style attribute for\r\n * @param {String} attr Style attribute to get for element\r\n * @return {String} Style attribute value of the given element.\r\n */\r\n var getElementStyle;\r\n if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) {\r\n getElementStyle = function(element, attr) {\r\n var style = fabric.document.defaultView.getComputedStyle(element, null);\r\n return style ? style[attr] : undefined;\r\n };\r\n }\r\n else {\r\n getElementStyle = function(element, attr) {\r\n var value = element.style[attr];\r\n if (!value && element.currentStyle) {\r\n value = element.currentStyle[attr];\r\n }\r\n return value;\r\n };\r\n }\r\n\r\n (function () {\r\n var style = fabric.document.documentElement.style,\r\n selectProp = 'userSelect' in style\r\n ? 'userSelect'\r\n : 'MozUserSelect' in style\r\n ? 'MozUserSelect'\r\n : 'WebkitUserSelect' in style\r\n ? 'WebkitUserSelect'\r\n : 'KhtmlUserSelect' in style\r\n ? 'KhtmlUserSelect'\r\n : '';\r\n\r\n /**\r\n * Makes element unselectable\r\n * @memberOf fabric.util\r\n * @param {HTMLElement} element Element to make unselectable\r\n * @return {HTMLElement} Element that was passed in\r\n */\r\n function makeElementUnselectable(element) {\r\n if (typeof element.onselectstart !== 'undefined') {\r\n element.onselectstart = fabric.util.falseFunction;\r\n }\r\n if (selectProp) {\r\n element.style[selectProp] = 'none';\r\n }\r\n else if (typeof element.unselectable === 'string') {\r\n element.unselectable = 'on';\r\n }\r\n return element;\r\n }\r\n\r\n /**\r\n * Makes element selectable\r\n * @memberOf fabric.util\r\n * @param {HTMLElement} element Element to make selectable\r\n * @return {HTMLElement} Element that was passed in\r\n */\r\n function makeElementSelectable(element) {\r\n if (typeof element.onselectstart !== 'undefined') {\r\n element.onselectstart = null;\r\n }\r\n if (selectProp) {\r\n element.style[selectProp] = '';\r\n }\r\n else if (typeof element.unselectable === 'string') {\r\n element.unselectable = '';\r\n }\r\n return element;\r\n }\r\n\r\n fabric.util.makeElementUnselectable = makeElementUnselectable;\r\n fabric.util.makeElementSelectable = makeElementSelectable;\r\n })();\r\n\r\n function getNodeCanvas(element) {\r\n var impl = fabric.jsdomImplForWrapper(element);\r\n return impl._canvas || impl._image;\r\n };\r\n\r\n function cleanUpJsdomNode(element) {\r\n if (!fabric.isLikelyNode) {\r\n return;\r\n }\r\n var impl = fabric.jsdomImplForWrapper(element);\r\n if (impl) {\r\n impl._image = null;\r\n impl._canvas = null;\r\n // unsure if necessary\r\n impl._currentSrc = null;\r\n impl._attributes = null;\r\n impl._classList = null;\r\n }\r\n }\r\n\r\n function setImageSmoothing(ctx, value) {\r\n ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled || ctx.webkitImageSmoothingEnabled\r\n || ctx.mozImageSmoothingEnabled || ctx.msImageSmoothingEnabled || ctx.oImageSmoothingEnabled;\r\n ctx.imageSmoothingEnabled = value;\r\n }\r\n\r\n /**\r\n * setImageSmoothing sets the context imageSmoothingEnabled property.\r\n * Used by canvas and by ImageObject.\r\n * @memberOf fabric.util\r\n * @since 4.0.0\r\n * @param {HTMLRenderingContext2D} ctx to set on\r\n * @param {Boolean} value true or false\r\n */\r\n fabric.util.setImageSmoothing = setImageSmoothing;\r\n fabric.util.getById = getById;\r\n fabric.util.toArray = toArray;\r\n fabric.util.addClass = addClass;\r\n fabric.util.makeElement = makeElement;\r\n fabric.util.wrapElement = wrapElement;\r\n fabric.util.getScrollLeftTop = getScrollLeftTop;\r\n fabric.util.getElementOffset = getElementOffset;\r\n fabric.util.getNodeCanvas = getNodeCanvas;\r\n fabric.util.cleanUpJsdomNode = cleanUpJsdomNode;\r\n\r\n})();\r\n\r\n\r\n(function() {\r\n\r\n function addParamToUrl(url, param) {\r\n return url + (/\\?/.test(url) ? '&' : '?') + param;\r\n }\r\n\r\n function emptyFn() { }\r\n\r\n /**\r\n * Cross-browser abstraction for sending XMLHttpRequest\r\n * @memberOf fabric.util\r\n * @param {String} url URL to send XMLHttpRequest to\r\n * @param {Object} [options] Options object\r\n * @param {String} [options.method=\"GET\"]\r\n * @param {String} [options.parameters] parameters to append to url in GET or in body\r\n * @param {String} [options.body] body to send with POST or PUT request\r\n * @param {Function} options.onComplete Callback to invoke when request is completed\r\n * @return {XMLHttpRequest} request\r\n */\r\n function request(url, options) {\r\n options || (options = { });\r\n\r\n var method = options.method ? options.method.toUpperCase() : 'GET',\r\n onComplete = options.onComplete || function() { },\r\n xhr = new fabric.window.XMLHttpRequest(),\r\n body = options.body || options.parameters;\r\n\r\n /** @ignore */\r\n xhr.onreadystatechange = function() {\r\n if (xhr.readyState === 4) {\r\n onComplete(xhr);\r\n xhr.onreadystatechange = emptyFn;\r\n }\r\n };\r\n\r\n if (method === 'GET') {\r\n body = null;\r\n if (typeof options.parameters === 'string') {\r\n url = addParamToUrl(url, options.parameters);\r\n }\r\n }\r\n\r\n xhr.open(method, url, true);\r\n\r\n if (method === 'POST' || method === 'PUT') {\r\n xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\r\n }\r\n\r\n xhr.send(body);\r\n return xhr;\r\n }\r\n\r\n fabric.util.request = request;\r\n})();\r\n\r\n\r\n/**\r\n * Wrapper around `console.log` (when available)\r\n * @param {*} [values] Values to log\r\n */\r\nfabric.log = console.log;\r\n\r\n/**\r\n * Wrapper around `console.warn` (when available)\r\n * @param {*} [values] Values to log as a warning\r\n */\r\nfabric.warn = (message) => {\r\n // Swallow.\r\n};\r\n\r\n\r\n(function () {\r\n\r\n var extend = fabric.util.object.extend,\r\n clone = fabric.util.object.clone;\r\n\r\n /**\r\n * @typedef {Object} AnimationOptions\r\n * Animation of a value or list of values.\r\n * When using lists, think of something like this:\r\n * fabric.util.animate({\r\n * startValue: [1, 2, 3],\r\n * endValue: [2, 4, 6],\r\n * onChange: function([a, b, c]) {\r\n * canvas.zoomToPoint({x: b, y: c}, a)\r\n * canvas.renderAll()\r\n * }\r\n * });\r\n * @example\r\n * @property {Function} [onChange] Callback; invoked on every value change\r\n * @property {Function} [onComplete] Callback; invoked when value change is completed\r\n * @example\r\n * // Note: startValue, endValue, and byValue must match the type\r\n * var animationOptions = { startValue: 0, endValue: 1, byValue: 0.25 }\r\n * var animationOptions = { startValue: [0, 1], endValue: [1, 2], byValue: [0.25, 0.25] }\r\n * @property {number | number[]} [startValue=0] Starting value\r\n * @property {number | number[]} [endValue=100] Ending value\r\n * @property {number | number[]} [byValue=100] Value to modify the property by\r\n * @property {Function} [easing] Easing function\r\n * @property {Number} [duration=500] Duration of change (in ms)\r\n * @property {Function} [abort] Additional function with logic. If returns true, animation aborts.\r\n *\r\n * @typedef {() => void} CancelFunction\r\n *\r\n * @typedef {Object} AnimationCurrentState\r\n * @property {number | number[]} currentValue value in range [`startValue`, `endValue`]\r\n * @property {number} completionRate value in range [0, 1]\r\n * @property {number} durationRate value in range [0, 1]\r\n *\r\n * @typedef {(AnimationOptions & AnimationCurrentState & { cancel: CancelFunction }} AnimationContext\r\n */\r\n\r\n /**\r\n * Array holding all running animations\r\n * @memberof fabric\r\n * @type {AnimationContext[]}\r\n */\r\n var RUNNING_ANIMATIONS = [];\r\n fabric.util.object.extend(RUNNING_ANIMATIONS, {\r\n\r\n /**\r\n * cancel all running animations at the next requestAnimFrame\r\n * @returns {AnimationContext[]}\r\n */\r\n cancelAll: function () {\r\n var animations = this.splice(0);\r\n animations.forEach(function (animation) {\r\n animation.cancel();\r\n });\r\n return animations;\r\n },\r\n\r\n /**\r\n * cancel all running animations attached to canvas at the next requestAnimFrame\r\n * @param {fabric.Canvas} canvas\r\n * @returns {AnimationContext[]}\r\n */\r\n cancelByCanvas: function (canvas) {\r\n if (!canvas) {\r\n return [];\r\n }\r\n var cancelled = this.filter(function (animation) {\r\n return typeof animation.target === 'object' && animation.target.canvas === canvas;\r\n });\r\n cancelled.forEach(function (animation) {\r\n animation.cancel();\r\n });\r\n return cancelled;\r\n },\r\n\r\n /**\r\n * cancel all running animations for target at the next requestAnimFrame\r\n * @param {*} target\r\n * @returns {AnimationContext[]}\r\n */\r\n cancelByTarget: function (target) {\r\n var cancelled = this.findAnimationsByTarget(target);\r\n cancelled.forEach(function (animation) {\r\n animation.cancel();\r\n });\r\n return cancelled;\r\n },\r\n\r\n /**\r\n *\r\n * @param {CancelFunction} cancelFunc the function returned by animate\r\n * @returns {number}\r\n */\r\n findAnimationIndex: function (cancelFunc) {\r\n return this.indexOf(this.findAnimation(cancelFunc));\r\n },\r\n\r\n /**\r\n *\r\n * @param {CancelFunction} cancelFunc the function returned by animate\r\n * @returns {AnimationContext | undefined} animation's options object\r\n */\r\n findAnimation: function (cancelFunc) {\r\n return this.find(function (animation) {\r\n return animation.cancel === cancelFunc;\r\n });\r\n },\r\n\r\n /**\r\n *\r\n * @param {*} target the object that is assigned to the target property of the animation context\r\n * @returns {AnimationContext[]} array of animation options object associated with target\r\n */\r\n findAnimationsByTarget: function (target) {\r\n if (!target) {\r\n return [];\r\n }\r\n return this.filter(function (animation) {\r\n return animation.target === target;\r\n });\r\n }\r\n });\r\n\r\n function noop() {\r\n return false;\r\n }\r\n\r\n function defaultEasing(t, b, c, d) {\r\n return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;\r\n }\r\n\r\n /**\r\n * Changes value from one to another within certain period of time, invoking callbacks as value is being changed.\r\n * @memberOf fabric.util\r\n * @param {AnimationOptions} [options] Animation options\r\n * @example\r\n * // Note: startValue, endValue, and byValue must match the type\r\n * fabric.util.animate({ startValue: 0, endValue: 1, byValue: 0.25 })\r\n * fabric.util.animate({ startValue: [0, 1], endValue: [1, 2], byValue: [0.25, 0.25] })\r\n * @returns {CancelFunction} cancel function\r\n */\r\n function animate(options) {\r\n options || (options = {});\r\n var cancel = false,\r\n context,\r\n removeFromRegistry = function () {\r\n var index = fabric.runningAnimations.indexOf(context);\r\n return index > -1 && fabric.runningAnimations.splice(index, 1)[0];\r\n };\r\n\r\n context = extend(clone(options), {\r\n cancel: function () {\r\n cancel = true;\r\n return removeFromRegistry();\r\n },\r\n currentValue: 'startValue' in options ? options.startValue : 0,\r\n completionRate: 0,\r\n durationRate: 0\r\n });\r\n fabric.runningAnimations.push(context);\r\n\r\n requestAnimFrame(function(timestamp) {\r\n var start = timestamp || +new Date(),\r\n duration = options.duration || 500,\r\n finish = start + duration, time,\r\n onChange = options.onChange || noop,\r\n abort = options.abort || noop,\r\n onComplete = options.onComplete || noop,\r\n easing = options.easing || defaultEasing,\r\n isMany = 'startValue' in options ? options.startValue.length > 0 : false,\r\n startValue = 'startValue' in options ? options.startValue : 0,\r\n endValue = 'endValue' in options ? options.endValue : 100,\r\n byValue = options.byValue || (isMany ? startValue.map(function(value, i) {\r\n return endValue[i] - startValue[i];\r\n }) : endValue - startValue);\r\n\r\n options.onStart && options.onStart();\r\n\r\n (function tick(ticktime) {\r\n time = ticktime || +new Date();\r\n var currentTime = time > finish ? duration : (time - start),\r\n timePerc = currentTime / duration,\r\n current = isMany ? startValue.map(function(_value, i) {\r\n return easing(currentTime, startValue[i], byValue[i], duration);\r\n }) : easing(currentTime, startValue, byValue, duration),\r\n valuePerc = isMany ? Math.abs((current[0] - startValue[0]) / byValue[0])\r\n : Math.abs((current - startValue) / byValue);\r\n // update context\r\n context.currentValue = isMany ? current.slice() : current;\r\n context.completionRate = valuePerc;\r\n context.durationRate = timePerc;\r\n if (cancel) {\r\n return;\r\n }\r\n if (abort(current, valuePerc, timePerc)) {\r\n removeFromRegistry();\r\n return;\r\n }\r\n if (time > finish) {\r\n // update context\r\n context.currentValue = isMany ? endValue.slice() : endValue;\r\n context.completionRate = 1;\r\n context.durationRate = 1;\r\n // execute callbacks\r\n onChange(isMany ? endValue.slice() : endValue, 1, 1);\r\n onComplete(endValue, 1, 1);\r\n removeFromRegistry();\r\n return;\r\n }\r\n else {\r\n onChange(current, valuePerc, timePerc);\r\n requestAnimFrame(tick);\r\n }\r\n })(start);\r\n });\r\n\r\n return context.cancel;\r\n }\r\n\r\n var _requestAnimFrame = fabric.window.requestAnimationFrame ||\r\n fabric.window.webkitRequestAnimationFrame ||\r\n fabric.window.mozRequestAnimationFrame ||\r\n fabric.window.oRequestAnimationFrame ||\r\n fabric.window.msRequestAnimationFrame ||\r\n function(callback) {\r\n return fabric.window.setTimeout(callback, 1000 / 60);\r\n };\r\n\r\n var _cancelAnimFrame = fabric.window.cancelAnimationFrame || fabric.window.clearTimeout;\r\n\r\n /**\r\n * requestAnimationFrame polyfill based on http://paulirish.com/2011/requestanimationframe-for-smart-animating/\r\n * In order to get a precise start time, `requestAnimFrame` should be called as an entry into the method\r\n * @memberOf fabric.util\r\n * @param {Function} callback Callback to invoke\r\n * @param {DOMElement} element optional Element to associate with animation\r\n */\r\n function requestAnimFrame() {\r\n return _requestAnimFrame.apply(fabric.window, arguments);\r\n }\r\n\r\n function cancelAnimFrame() {\r\n return _cancelAnimFrame.apply(fabric.window, arguments);\r\n }\r\n\r\n fabric.util.animate = animate;\r\n fabric.util.requestAnimFrame = requestAnimFrame;\r\n fabric.util.cancelAnimFrame = cancelAnimFrame;\r\n fabric.runningAnimations = RUNNING_ANIMATIONS;\r\n})();\r\n\r\n\r\n(function() {\r\n // Calculate an in-between color. Returns a \"rgba()\" string.\r\n // Credit: Edwin Martin \r\n // http://www.bitstorm.org/jquery/color-animation/jquery.animate-colors.js\r\n function calculateColor(begin, end, pos) {\r\n var color = 'rgba('\r\n + parseInt((begin[0] + pos * (end[0] - begin[0])), 10) + ','\r\n + parseInt((begin[1] + pos * (end[1] - begin[1])), 10) + ','\r\n + parseInt((begin[2] + pos * (end[2] - begin[2])), 10);\r\n\r\n color += ',' + (begin && end ? parseFloat(begin[3] + pos * (end[3] - begin[3])) : 1);\r\n color += ')';\r\n return color;\r\n }\r\n\r\n /**\r\n * Changes the color from one to another within certain period of time, invoking callbacks as value is being changed.\r\n * @memberOf fabric.util\r\n * @param {String} fromColor The starting color in hex or rgb(a) format.\r\n * @param {String} toColor The starting color in hex or rgb(a) format.\r\n * @param {Number} [duration] Duration of change (in ms).\r\n * @param {Object} [options] Animation options\r\n * @param {Function} [options.onChange] Callback; invoked on every value change\r\n * @param {Function} [options.onComplete] Callback; invoked when value change is completed\r\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.\r\n * @param {Function} [options.abort] Additional function with logic. If returns true, onComplete is called.\r\n * @returns {Function} abort function\r\n */\r\n function animateColor(fromColor, toColor, duration, options) {\r\n var startColor = new fabric.Color(fromColor).getSource(),\r\n endColor = new fabric.Color(toColor).getSource(),\r\n originalOnComplete = options.onComplete,\r\n originalOnChange = options.onChange;\r\n options = options || {};\r\n\r\n return fabric.util.animate(fabric.util.object.extend(options, {\r\n duration: duration || 500,\r\n startValue: startColor,\r\n endValue: endColor,\r\n byValue: endColor,\r\n easing: function (currentTime, startValue, byValue, duration) {\r\n var posValue = options.colorEasing\r\n ? options.colorEasing(currentTime, duration)\r\n : 1 - Math.cos(currentTime / duration * (Math.PI / 2));\r\n return calculateColor(startValue, byValue, posValue);\r\n },\r\n // has to take in account for color restoring;\r\n onComplete: function(current, valuePerc, timePerc) {\r\n if (originalOnComplete) {\r\n return originalOnComplete(\r\n calculateColor(endColor, endColor, 0),\r\n valuePerc,\r\n timePerc\r\n );\r\n }\r\n },\r\n onChange: function(current, valuePerc, timePerc) {\r\n if (originalOnChange) {\r\n if (Array.isArray(current)) {\r\n return originalOnChange(\r\n calculateColor(current, current, 0),\r\n valuePerc,\r\n timePerc\r\n );\r\n }\r\n originalOnChange(current, valuePerc, timePerc);\r\n }\r\n }\r\n }));\r\n }\r\n\r\n fabric.util.animateColor = animateColor;\r\n\r\n})();\r\n\r\n\r\n(function() {\r\n\r\n function normalize(a, c, p, s) {\r\n if (a < Math.abs(c)) {\r\n a = c;\r\n s = p / 4;\r\n }\r\n else {\r\n //handle the 0/0 case:\r\n if (c === 0 && a === 0) {\r\n s = p / (2 * Math.PI) * Math.asin(1);\r\n }\r\n else {\r\n s = p / (2 * Math.PI) * Math.asin(c / a);\r\n }\r\n }\r\n return { a: a, c: c, p: p, s: s };\r\n }\r\n\r\n function elastic(opts, t, d) {\r\n return opts.a *\r\n Math.pow(2, 10 * (t -= 1)) *\r\n Math.sin( (t * d - opts.s) * (2 * Math.PI) / opts.p );\r\n }\r\n\r\n /**\r\n * Cubic easing out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeOutCubic(t, b, c, d) {\r\n return c * ((t = t / d - 1) * t * t + 1) + b;\r\n }\r\n\r\n /**\r\n * Cubic easing in and out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInOutCubic(t, b, c, d) {\r\n t /= d / 2;\r\n if (t < 1) {\r\n return c / 2 * t * t * t + b;\r\n }\r\n return c / 2 * ((t -= 2) * t * t + 2) + b;\r\n }\r\n\r\n /**\r\n * Quartic easing in\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInQuart(t, b, c, d) {\r\n return c * (t /= d) * t * t * t + b;\r\n }\r\n\r\n /**\r\n * Quartic easing out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeOutQuart(t, b, c, d) {\r\n return -c * ((t = t / d - 1) * t * t * t - 1) + b;\r\n }\r\n\r\n /**\r\n * Quartic easing in and out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInOutQuart(t, b, c, d) {\r\n t /= d / 2;\r\n if (t < 1) {\r\n return c / 2 * t * t * t * t + b;\r\n }\r\n return -c / 2 * ((t -= 2) * t * t * t - 2) + b;\r\n }\r\n\r\n /**\r\n * Quintic easing in\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInQuint(t, b, c, d) {\r\n return c * (t /= d) * t * t * t * t + b;\r\n }\r\n\r\n /**\r\n * Quintic easing out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeOutQuint(t, b, c, d) {\r\n return c * ((t = t / d - 1) * t * t * t * t + 1) + b;\r\n }\r\n\r\n /**\r\n * Quintic easing in and out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInOutQuint(t, b, c, d) {\r\n t /= d / 2;\r\n if (t < 1) {\r\n return c / 2 * t * t * t * t * t + b;\r\n }\r\n return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;\r\n }\r\n\r\n /**\r\n * Sinusoidal easing in\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInSine(t, b, c, d) {\r\n return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;\r\n }\r\n\r\n /**\r\n * Sinusoidal easing out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeOutSine(t, b, c, d) {\r\n return c * Math.sin(t / d * (Math.PI / 2)) + b;\r\n }\r\n\r\n /**\r\n * Sinusoidal easing in and out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInOutSine(t, b, c, d) {\r\n return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;\r\n }\r\n\r\n /**\r\n * Exponential easing in\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInExpo(t, b, c, d) {\r\n return (t === 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;\r\n }\r\n\r\n /**\r\n * Exponential easing out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeOutExpo(t, b, c, d) {\r\n return (t === d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;\r\n }\r\n\r\n /**\r\n * Exponential easing in and out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInOutExpo(t, b, c, d) {\r\n if (t === 0) {\r\n return b;\r\n }\r\n if (t === d) {\r\n return b + c;\r\n }\r\n t /= d / 2;\r\n if (t < 1) {\r\n return c / 2 * Math.pow(2, 10 * (t - 1)) + b;\r\n }\r\n return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;\r\n }\r\n\r\n /**\r\n * Circular easing in\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInCirc(t, b, c, d) {\r\n return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;\r\n }\r\n\r\n /**\r\n * Circular easing out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeOutCirc(t, b, c, d) {\r\n return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;\r\n }\r\n\r\n /**\r\n * Circular easing in and out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInOutCirc(t, b, c, d) {\r\n t /= d / 2;\r\n if (t < 1) {\r\n return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;\r\n }\r\n return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;\r\n }\r\n\r\n /**\r\n * Elastic easing in\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInElastic(t, b, c, d) {\r\n var s = 1.70158, p = 0, a = c;\r\n if (t === 0) {\r\n return b;\r\n }\r\n t /= d;\r\n if (t === 1) {\r\n return b + c;\r\n }\r\n if (!p) {\r\n p = d * 0.3;\r\n }\r\n var opts = normalize(a, c, p, s);\r\n return -elastic(opts, t, d) + b;\r\n }\r\n\r\n /**\r\n * Elastic easing out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeOutElastic(t, b, c, d) {\r\n var s = 1.70158, p = 0, a = c;\r\n if (t === 0) {\r\n return b;\r\n }\r\n t /= d;\r\n if (t === 1) {\r\n return b + c;\r\n }\r\n if (!p) {\r\n p = d * 0.3;\r\n }\r\n var opts = normalize(a, c, p, s);\r\n return opts.a * Math.pow(2, -10 * t) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) + opts.c + b;\r\n }\r\n\r\n /**\r\n * Elastic easing in and out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInOutElastic(t, b, c, d) {\r\n var s = 1.70158, p = 0, a = c;\r\n if (t === 0) {\r\n return b;\r\n }\r\n t /= d / 2;\r\n if (t === 2) {\r\n return b + c;\r\n }\r\n if (!p) {\r\n p = d * (0.3 * 1.5);\r\n }\r\n var opts = normalize(a, c, p, s);\r\n if (t < 1) {\r\n return -0.5 * elastic(opts, t, d) + b;\r\n }\r\n return opts.a * Math.pow(2, -10 * (t -= 1)) *\r\n Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) * 0.5 + opts.c + b;\r\n }\r\n\r\n /**\r\n * Backwards easing in\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInBack(t, b, c, d, s) {\r\n if (s === undefined) {\r\n s = 1.70158;\r\n }\r\n return c * (t /= d) * t * ((s + 1) * t - s) + b;\r\n }\r\n\r\n /**\r\n * Backwards easing out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeOutBack(t, b, c, d, s) {\r\n if (s === undefined) {\r\n s = 1.70158;\r\n }\r\n return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;\r\n }\r\n\r\n /**\r\n * Backwards easing in and out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInOutBack(t, b, c, d, s) {\r\n if (s === undefined) {\r\n s = 1.70158;\r\n }\r\n t /= d / 2;\r\n if (t < 1) {\r\n return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;\r\n }\r\n return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;\r\n }\r\n\r\n /**\r\n * Bouncing easing in\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInBounce(t, b, c, d) {\r\n return c - easeOutBounce (d - t, 0, c, d) + b;\r\n }\r\n\r\n /**\r\n * Bouncing easing out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeOutBounce(t, b, c, d) {\r\n if ((t /= d) < (1 / 2.75)) {\r\n return c * (7.5625 * t * t) + b;\r\n }\r\n else if (t < (2 / 2.75)) {\r\n return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;\r\n }\r\n else if (t < (2.5 / 2.75)) {\r\n return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;\r\n }\r\n else {\r\n return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;\r\n }\r\n }\r\n\r\n /**\r\n * Bouncing easing in and out\r\n * @memberOf fabric.util.ease\r\n */\r\n function easeInOutBounce(t, b, c, d) {\r\n if (t < d / 2) {\r\n return easeInBounce (t * 2, 0, c, d) * 0.5 + b;\r\n }\r\n return easeOutBounce(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;\r\n }\r\n\r\n /**\r\n * Easing functions\r\n * See Easing Equations by Robert Penner\r\n * @namespace fabric.util.ease\r\n */\r\n fabric.util.ease = {\r\n\r\n /**\r\n * Quadratic easing in\r\n * @memberOf fabric.util.ease\r\n */\r\n easeInQuad: function(t, b, c, d) {\r\n return c * (t /= d) * t + b;\r\n },\r\n\r\n /**\r\n * Quadratic easing out\r\n * @memberOf fabric.util.ease\r\n */\r\n easeOutQuad: function(t, b, c, d) {\r\n return -c * (t /= d) * (t - 2) + b;\r\n },\r\n\r\n /**\r\n * Quadratic easing in and out\r\n * @memberOf fabric.util.ease\r\n */\r\n easeInOutQuad: function(t, b, c, d) {\r\n t /= (d / 2);\r\n if (t < 1) {\r\n return c / 2 * t * t + b;\r\n }\r\n return -c / 2 * ((--t) * (t - 2) - 1) + b;\r\n },\r\n\r\n /**\r\n * Cubic easing in\r\n * @memberOf fabric.util.ease\r\n */\r\n easeInCubic: function(t, b, c, d) {\r\n return c * (t /= d) * t * t + b;\r\n },\r\n\r\n easeOutCubic: easeOutCubic,\r\n easeInOutCubic: easeInOutCubic,\r\n easeInQuart: easeInQuart,\r\n easeOutQuart: easeOutQuart,\r\n easeInOutQuart: easeInOutQuart,\r\n easeInQuint: easeInQuint,\r\n easeOutQuint: easeOutQuint,\r\n easeInOutQuint: easeInOutQuint,\r\n easeInSine: easeInSine,\r\n easeOutSine: easeOutSine,\r\n easeInOutSine: easeInOutSine,\r\n easeInExpo: easeInExpo,\r\n easeOutExpo: easeOutExpo,\r\n easeInOutExpo: easeInOutExpo,\r\n easeInCirc: easeInCirc,\r\n easeOutCirc: easeOutCirc,\r\n easeInOutCirc: easeInOutCirc,\r\n easeInElastic: easeInElastic,\r\n easeOutElastic: easeOutElastic,\r\n easeInOutElastic: easeInOutElastic,\r\n easeInBack: easeInBack,\r\n easeOutBack: easeOutBack,\r\n easeInOutBack: easeInOutBack,\r\n easeInBounce: easeInBounce,\r\n easeOutBounce: easeOutBounce,\r\n easeInOutBounce: easeInOutBounce\r\n };\r\n\r\n})();\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n /**\r\n * @name fabric\r\n * @namespace\r\n */\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n extend = fabric.util.object.extend,\r\n clone = fabric.util.object.clone,\r\n toFixed = fabric.util.toFixed,\r\n parseUnit = fabric.util.parseUnit,\r\n multiplyTransformMatrices = fabric.util.multiplyTransformMatrices,\r\n\r\n svgValidTagNames = ['path', 'circle', 'polygon', 'polyline', 'ellipse', 'rect', 'line',\r\n 'image', 'text'],\r\n svgViewBoxElements = ['symbol', 'image', 'marker', 'pattern', 'view', 'svg'],\r\n svgInvalidAncestors = ['pattern', 'defs', 'symbol', 'metadata', 'clipPath', 'mask', 'desc'],\r\n svgValidParents = ['symbol', 'g', 'a', 'svg', 'clipPath', 'defs'],\r\n\r\n attributesMap = {\r\n cx: 'left',\r\n x: 'left',\r\n r: 'radius',\r\n cy: 'top',\r\n y: 'top',\r\n display: 'visible',\r\n visibility: 'visible',\r\n transform: 'transformMatrix',\r\n 'fill-opacity': 'fillOpacity',\r\n 'fill-rule': 'fillRule',\r\n 'font-family': 'fontFamily',\r\n 'font-size': 'fontSize',\r\n 'font-style': 'fontStyle',\r\n 'font-weight': 'fontWeight',\r\n 'letter-spacing': 'charSpacing',\r\n 'paint-order': 'paintFirst',\r\n 'stroke-dasharray': 'strokeDashArray',\r\n 'stroke-dashoffset': 'strokeDashOffset',\r\n 'stroke-linecap': 'strokeLineCap',\r\n 'stroke-linejoin': 'strokeLineJoin',\r\n 'stroke-miterlimit': 'strokeMiterLimit',\r\n 'stroke-opacity': 'strokeOpacity',\r\n 'stroke-width': 'strokeWidth',\r\n 'text-decoration': 'textDecoration',\r\n 'text-anchor': 'textAnchor',\r\n opacity: 'opacity',\r\n 'clip-path': 'clipPath',\r\n 'clip-rule': 'clipRule',\r\n 'vector-effect': 'strokeUniform',\r\n 'image-rendering': 'imageSmoothing',\r\n },\r\n\r\n colorAttributes = {\r\n stroke: 'strokeOpacity',\r\n fill: 'fillOpacity'\r\n },\r\n\r\n fSize = 'font-size', cPath = 'clip-path';\r\n\r\n fabric.svgValidTagNamesRegEx = getSvgRegex(svgValidTagNames);\r\n fabric.svgViewBoxElementsRegEx = getSvgRegex(svgViewBoxElements);\r\n fabric.svgInvalidAncestorsRegEx = getSvgRegex(svgInvalidAncestors);\r\n fabric.svgValidParentsRegEx = getSvgRegex(svgValidParents);\r\n\r\n fabric.cssRules = { };\r\n fabric.gradientDefs = { };\r\n fabric.clipPaths = { };\r\n\r\n function normalizeAttr(attr) {\r\n // transform attribute names\r\n if (attr in attributesMap) {\r\n return attributesMap[attr];\r\n }\r\n return attr;\r\n }\r\n\r\n function normalizeValue(attr, value, parentAttributes, fontSize) {\r\n var isArray = Array.isArray(value), parsed;\r\n\r\n if ((attr === 'fill' || attr === 'stroke') && value === 'none') {\r\n value = '';\r\n }\r\n else if (attr === 'strokeUniform') {\r\n return (value === 'non-scaling-stroke');\r\n }\r\n else if (attr === 'strokeDashArray') {\r\n if (value === 'none') {\r\n value = null;\r\n }\r\n else {\r\n value = value.replace(/,/g, ' ').split(/\\s+/).map(parseFloat);\r\n }\r\n }\r\n else if (attr === 'transformMatrix') {\r\n if (parentAttributes && parentAttributes.transformMatrix) {\r\n value = multiplyTransformMatrices(\r\n parentAttributes.transformMatrix, fabric.parseTransformAttribute(value));\r\n }\r\n else {\r\n value = fabric.parseTransformAttribute(value);\r\n }\r\n }\r\n else if (attr === 'visible') {\r\n value = value !== 'none' && value !== 'hidden';\r\n // display=none on parent element always takes precedence over child element\r\n if (parentAttributes && parentAttributes.visible === false) {\r\n value = false;\r\n }\r\n }\r\n else if (attr === 'opacity') {\r\n value = parseFloat(value);\r\n if (parentAttributes && typeof parentAttributes.opacity !== 'undefined') {\r\n value *= parentAttributes.opacity;\r\n }\r\n }\r\n else if (attr === 'textAnchor' /* text-anchor */) {\r\n value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center';\r\n }\r\n else if (attr === 'charSpacing') {\r\n // parseUnit returns px and we convert it to em\r\n parsed = parseUnit(value, fontSize) / fontSize * 1000;\r\n }\r\n else if (attr === 'paintFirst') {\r\n var fillIndex = value.indexOf('fill');\r\n var strokeIndex = value.indexOf('stroke');\r\n var value = 'fill';\r\n if (fillIndex > -1 && strokeIndex > -1 && strokeIndex < fillIndex) {\r\n value = 'stroke';\r\n }\r\n else if (fillIndex === -1 && strokeIndex > -1) {\r\n value = 'stroke';\r\n }\r\n }\r\n else if (attr === 'href' || attr === 'xlink:href' || attr === 'font') {\r\n return value;\r\n }\r\n else if (attr === 'imageSmoothing') {\r\n return (value === 'optimizeQuality');\r\n }\r\n else {\r\n parsed = isArray ? value.map(parseUnit) : parseUnit(value, fontSize);\r\n }\r\n\r\n return (!isArray && isNaN(parsed) ? value : parsed);\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n function getSvgRegex(arr) {\r\n return new RegExp('^(' + arr.join('|') + ')\\\\b', 'i');\r\n }\r\n\r\n /**\r\n * @private\r\n * @param {Object} attributes Array of attributes to parse\r\n */\r\n function _setStrokeFillOpacity(attributes) {\r\n for (var attr in colorAttributes) {\r\n\r\n if (typeof attributes[colorAttributes[attr]] === 'undefined' || attributes[attr] === '') {\r\n continue;\r\n }\r\n\r\n if (typeof attributes[attr] === 'undefined') {\r\n if (!fabric.Object.prototype[attr]) {\r\n continue;\r\n }\r\n attributes[attr] = fabric.Object.prototype[attr];\r\n }\r\n\r\n if (attributes[attr].indexOf('url(') === 0) {\r\n continue;\r\n }\r\n\r\n var color = new fabric.Color(attributes[attr]);\r\n attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba();\r\n }\r\n return attributes;\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n function _getMultipleNodes(doc, nodeNames) {\r\n var nodeName, nodeArray = [], nodeList, i, len;\r\n for (i = 0, len = nodeNames.length; i < len; i++) {\r\n nodeName = nodeNames[i];\r\n nodeList = doc.getElementsByTagName(nodeName);\r\n nodeArray = nodeArray.concat(Array.prototype.slice.call(nodeList));\r\n }\r\n return nodeArray;\r\n }\r\n\r\n /**\r\n * Parses \"transform\" attribute, returning an array of values\r\n * @static\r\n * @function\r\n * @memberOf fabric\r\n * @param {String} attributeValue String containing attribute value\r\n * @return {Array} Array of 6 elements representing transformation matrix\r\n */\r\n fabric.parseTransformAttribute = (function() {\r\n function rotateMatrix(matrix, args) {\r\n var cos = fabric.util.cos(args[0]), sin = fabric.util.sin(args[0]),\r\n x = 0, y = 0;\r\n if (args.length === 3) {\r\n x = args[1];\r\n y = args[2];\r\n }\r\n\r\n matrix[0] = cos;\r\n matrix[1] = sin;\r\n matrix[2] = -sin;\r\n matrix[3] = cos;\r\n matrix[4] = x - (cos * x - sin * y);\r\n matrix[5] = y - (sin * x + cos * y);\r\n }\r\n\r\n function scaleMatrix(matrix, args) {\r\n var multiplierX = args[0],\r\n multiplierY = (args.length === 2) ? args[1] : args[0];\r\n\r\n matrix[0] = multiplierX;\r\n matrix[3] = multiplierY;\r\n }\r\n\r\n function skewMatrix(matrix, args, pos) {\r\n matrix[pos] = Math.tan(fabric.util.degreesToRadians(args[0]));\r\n }\r\n\r\n function translateMatrix(matrix, args) {\r\n matrix[4] = args[0];\r\n if (args.length === 2) {\r\n matrix[5] = args[1];\r\n }\r\n }\r\n\r\n // identity matrix\r\n var iMatrix = fabric.iMatrix,\r\n\r\n // == begin transform regexp\r\n number = fabric.reNum,\r\n\r\n commaWsp = fabric.commaWsp,\r\n\r\n skewX = '(?:(skewX)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*\\\\))',\r\n\r\n skewY = '(?:(skewY)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*\\\\))',\r\n\r\n rotate = '(?:(rotate)\\\\s*\\\\(\\\\s*(' + number + ')(?:' +\r\n commaWsp + '(' + number + ')' +\r\n commaWsp + '(' + number + '))?\\\\s*\\\\))',\r\n\r\n scale = '(?:(scale)\\\\s*\\\\(\\\\s*(' + number + ')(?:' +\r\n commaWsp + '(' + number + '))?\\\\s*\\\\))',\r\n\r\n translate = '(?:(translate)\\\\s*\\\\(\\\\s*(' + number + ')(?:' +\r\n commaWsp + '(' + number + '))?\\\\s*\\\\))',\r\n\r\n matrix = '(?:(matrix)\\\\s*\\\\(\\\\s*' +\r\n '(' + number + ')' + commaWsp +\r\n '(' + number + ')' + commaWsp +\r\n '(' + number + ')' + commaWsp +\r\n '(' + number + ')' + commaWsp +\r\n '(' + number + ')' + commaWsp +\r\n '(' + number + ')' +\r\n '\\\\s*\\\\))',\r\n\r\n transform = '(?:' +\r\n matrix + '|' +\r\n translate + '|' +\r\n scale + '|' +\r\n rotate + '|' +\r\n skewX + '|' +\r\n skewY +\r\n ')',\r\n\r\n transforms = '(?:' + transform + '(?:' + commaWsp + '*' + transform + ')*' + ')',\r\n\r\n transformList = '^\\\\s*(?:' + transforms + '?)\\\\s*$',\r\n\r\n // http://www.w3.org/TR/SVG/coords.html#TransformAttribute\r\n reTransformList = new RegExp(transformList),\r\n // == end transform regexp\r\n\r\n reTransform = new RegExp(transform, 'g');\r\n\r\n return function(attributeValue) {\r\n\r\n // start with identity matrix\r\n var matrix = iMatrix.concat(),\r\n matrices = [];\r\n\r\n // return if no argument was given or\r\n // an argument does not match transform attribute regexp\r\n if (!attributeValue || (attributeValue && !reTransformList.test(attributeValue))) {\r\n return matrix;\r\n }\r\n\r\n attributeValue.replace(reTransform, function(match) {\r\n\r\n var m = new RegExp(transform).exec(match).filter(function (match) {\r\n // match !== '' && match != null\r\n return (!!match);\r\n }),\r\n operation = m[1],\r\n args = m.slice(2).map(parseFloat);\r\n\r\n switch (operation) {\r\n case 'translate':\r\n translateMatrix(matrix, args);\r\n break;\r\n case 'rotate':\r\n args[0] = fabric.util.degreesToRadians(args[0]);\r\n rotateMatrix(matrix, args);\r\n break;\r\n case 'scale':\r\n scaleMatrix(matrix, args);\r\n break;\r\n case 'skewX':\r\n skewMatrix(matrix, args, 2);\r\n break;\r\n case 'skewY':\r\n skewMatrix(matrix, args, 1);\r\n break;\r\n case 'matrix':\r\n matrix = args;\r\n break;\r\n }\r\n\r\n // snapshot current matrix into matrices array\r\n matrices.push(matrix.concat());\r\n // reset\r\n matrix = iMatrix.concat();\r\n });\r\n\r\n var combinedMatrix = matrices[0];\r\n while (matrices.length > 1) {\r\n matrices.shift();\r\n combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]);\r\n }\r\n return combinedMatrix;\r\n };\r\n })();\r\n\r\n /**\r\n * @private\r\n */\r\n function parseStyleString(style, oStyle) {\r\n var attr, value;\r\n style.replace(/;\\s*$/, '').split(';').forEach(function (chunk) {\r\n var pair = chunk.split(':');\r\n\r\n attr = pair[0].trim().toLowerCase();\r\n value = pair[1].trim();\r\n\r\n oStyle[attr] = value;\r\n });\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n function parseStyleObject(style, oStyle) {\r\n var attr, value;\r\n for (var prop in style) {\r\n if (typeof style[prop] === 'undefined') {\r\n continue;\r\n }\r\n\r\n attr = prop.toLowerCase();\r\n value = style[prop];\r\n\r\n oStyle[attr] = value;\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n function getGlobalStylesForElement(element, svgUid) {\r\n var styles = { };\r\n for (var rule in fabric.cssRules[svgUid]) {\r\n if (elementMatchesRule(element, rule.split(' '))) {\r\n for (var property in fabric.cssRules[svgUid][rule]) {\r\n styles[property] = fabric.cssRules[svgUid][rule][property];\r\n }\r\n }\r\n }\r\n return styles;\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n function elementMatchesRule(element, selectors) {\r\n var firstMatching, parentMatching = true;\r\n //start from rightmost selector.\r\n firstMatching = selectorMatches(element, selectors.pop());\r\n if (firstMatching && selectors.length) {\r\n parentMatching = doesSomeParentMatch(element, selectors);\r\n }\r\n return firstMatching && parentMatching && (selectors.length === 0);\r\n }\r\n\r\n function doesSomeParentMatch(element, selectors) {\r\n var selector, parentMatching = true;\r\n while (element.parentNode && element.parentNode.nodeType === 1 && selectors.length) {\r\n if (parentMatching) {\r\n selector = selectors.pop();\r\n }\r\n element = element.parentNode;\r\n parentMatching = selectorMatches(element, selector);\r\n }\r\n return selectors.length === 0;\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n function selectorMatches(element, selector) {\r\n var nodeName = element.nodeName,\r\n classNames = element.getAttribute('class'),\r\n id = element.getAttribute('id'), matcher, i;\r\n // i check if a selector matches slicing away part from it.\r\n // if i get empty string i should match\r\n matcher = new RegExp('^' + nodeName, 'i');\r\n selector = selector.replace(matcher, '');\r\n if (id && selector.length) {\r\n matcher = new RegExp('#' + id + '(?![a-zA-Z\\\\-]+)', 'i');\r\n selector = selector.replace(matcher, '');\r\n }\r\n if (classNames && selector.length) {\r\n classNames = classNames.split(' ');\r\n for (i = classNames.length; i--;) {\r\n matcher = new RegExp('\\\\.' + classNames[i] + '(?![a-zA-Z\\\\-]+)', 'i');\r\n selector = selector.replace(matcher, '');\r\n }\r\n }\r\n return selector.length === 0;\r\n }\r\n\r\n /**\r\n * @private\r\n * to support IE8 missing getElementById on SVGdocument and on node xmlDOM\r\n */\r\n function elementById(doc, id) {\r\n var el;\r\n doc.getElementById && (el = doc.getElementById(id));\r\n if (el) {\r\n return el;\r\n }\r\n var node, i, len, nodelist = doc.getElementsByTagName('*');\r\n for (i = 0, len = nodelist.length; i < len; i++) {\r\n node = nodelist[i];\r\n if (id === node.getAttribute('id')) {\r\n return node;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n function parseUseDirectives(doc) {\r\n var nodelist = _getMultipleNodes(doc, ['use', 'svg:use']), i = 0;\r\n while (nodelist.length && i < nodelist.length) {\r\n var el = nodelist[i],\r\n xlinkAttribute = el.getAttribute('xlink:href') || el.getAttribute('href');\r\n\r\n if (xlinkAttribute === null) {\r\n return;\r\n }\r\n\r\n var xlink = xlinkAttribute.slice(1),\r\n x = el.getAttribute('x') || 0,\r\n y = el.getAttribute('y') || 0,\r\n el2 = elementById(doc, xlink).cloneNode(true),\r\n currentTrans = (el2.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')',\r\n parentNode,\r\n oldLength = nodelist.length, attr,\r\n j,\r\n attrs,\r\n len,\r\n namespace = fabric.svgNS;\r\n\r\n applyViewboxTransform(el2);\r\n if (/^svg$/i.test(el2.nodeName)) {\r\n var el3 = el2.ownerDocument.createElementNS(namespace, 'g');\r\n for (j = 0, attrs = el2.attributes, len = attrs.length; j < len; j++) {\r\n attr = attrs.item(j);\r\n el3.setAttributeNS(namespace, attr.nodeName, attr.nodeValue);\r\n }\r\n // el2.firstChild != null\r\n while (el2.firstChild) {\r\n el3.appendChild(el2.firstChild);\r\n }\r\n el2 = el3;\r\n }\r\n\r\n for (j = 0, attrs = el.attributes, len = attrs.length; j < len; j++) {\r\n attr = attrs.item(j);\r\n if (attr.nodeName === 'x' || attr.nodeName === 'y' ||\r\n attr.nodeName === 'xlink:href' || attr.nodeName === 'href') {\r\n continue;\r\n }\r\n\r\n if (attr.nodeName === 'transform') {\r\n currentTrans = attr.nodeValue + ' ' + currentTrans;\r\n }\r\n else {\r\n el2.setAttribute(attr.nodeName, attr.nodeValue);\r\n }\r\n }\r\n\r\n el2.setAttribute('transform', currentTrans);\r\n el2.setAttribute('instantiated_by_use', '1');\r\n el2.removeAttribute('id');\r\n parentNode = el.parentNode;\r\n parentNode.replaceChild(el2, el);\r\n // some browsers do not shorten nodelist after replaceChild (IE8)\r\n if (nodelist.length === oldLength) {\r\n i++;\r\n }\r\n }\r\n }\r\n\r\n // http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute\r\n // matches, e.g.: +14.56e-12, etc.\r\n var reViewBoxAttrValue = new RegExp(\r\n '^' +\r\n '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' +\r\n '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' +\r\n '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' +\r\n '\\\\s*(' + fabric.reNum + '+)\\\\s*' +\r\n '$'\r\n );\r\n\r\n /**\r\n * Add a element that envelop all child elements and makes the viewbox transformMatrix descend on all elements\r\n */\r\n function applyViewboxTransform(element) {\r\n if (!fabric.svgViewBoxElementsRegEx.test(element.nodeName)) {\r\n return {};\r\n }\r\n var viewBoxAttr = element.getAttribute('viewBox'),\r\n scaleX = 1,\r\n scaleY = 1,\r\n minX = 0,\r\n minY = 0,\r\n viewBoxWidth, viewBoxHeight, matrix, el,\r\n widthAttr = element.getAttribute('width'),\r\n heightAttr = element.getAttribute('height'),\r\n x = element.getAttribute('x') || 0,\r\n y = element.getAttribute('y') || 0,\r\n preserveAspectRatio = element.getAttribute('preserveAspectRatio') || '',\r\n missingViewBox = (!viewBoxAttr || !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))),\r\n missingDimAttr = (!widthAttr || !heightAttr || widthAttr === '100%' || heightAttr === '100%'),\r\n toBeParsed = missingViewBox && missingDimAttr,\r\n parsedDim = { }, translateMatrix = '', widthDiff = 0, heightDiff = 0;\r\n\r\n parsedDim.width = 0;\r\n parsedDim.height = 0;\r\n parsedDim.toBeParsed = toBeParsed;\r\n\r\n if (missingViewBox) {\r\n if (((x || y) && element.parentNode && element.parentNode.nodeName !== '#document')) {\r\n translateMatrix = ' translate(' + parseUnit(x) + ' ' + parseUnit(y) + ') ';\r\n matrix = (element.getAttribute('transform') || '') + translateMatrix;\r\n element.setAttribute('transform', matrix);\r\n element.removeAttribute('x');\r\n element.removeAttribute('y');\r\n }\r\n }\r\n\r\n if (toBeParsed) {\r\n return parsedDim;\r\n }\r\n\r\n if (missingViewBox) {\r\n parsedDim.width = parseUnit(widthAttr);\r\n parsedDim.height = parseUnit(heightAttr);\r\n // set a transform for elements that have x y and are inner(only) SVGs\r\n return parsedDim;\r\n }\r\n minX = -parseFloat(viewBoxAttr[1]);\r\n minY = -parseFloat(viewBoxAttr[2]);\r\n viewBoxWidth = parseFloat(viewBoxAttr[3]);\r\n viewBoxHeight = parseFloat(viewBoxAttr[4]);\r\n parsedDim.minX = minX;\r\n parsedDim.minY = minY;\r\n parsedDim.viewBoxWidth = viewBoxWidth;\r\n parsedDim.viewBoxHeight = viewBoxHeight;\r\n if (!missingDimAttr) {\r\n parsedDim.width = parseUnit(widthAttr);\r\n parsedDim.height = parseUnit(heightAttr);\r\n scaleX = parsedDim.width / viewBoxWidth;\r\n scaleY = parsedDim.height / viewBoxHeight;\r\n }\r\n else {\r\n parsedDim.width = viewBoxWidth;\r\n parsedDim.height = viewBoxHeight;\r\n }\r\n\r\n // default is to preserve aspect ratio\r\n preserveAspectRatio = fabric.util.parsePreserveAspectRatioAttribute(preserveAspectRatio);\r\n if (preserveAspectRatio.alignX !== 'none') {\r\n //translate all container for the effect of Mid, Min, Max\r\n if (preserveAspectRatio.meetOrSlice === 'meet') {\r\n scaleY = scaleX = (scaleX > scaleY ? scaleY : scaleX);\r\n // calculate additional translation to move the viewbox\r\n }\r\n if (preserveAspectRatio.meetOrSlice === 'slice') {\r\n scaleY = scaleX = (scaleX > scaleY ? scaleX : scaleY);\r\n // calculate additional translation to move the viewbox\r\n }\r\n widthDiff = parsedDim.width - viewBoxWidth * scaleX;\r\n heightDiff = parsedDim.height - viewBoxHeight * scaleX;\r\n if (preserveAspectRatio.alignX === 'Mid') {\r\n widthDiff /= 2;\r\n }\r\n if (preserveAspectRatio.alignY === 'Mid') {\r\n heightDiff /= 2;\r\n }\r\n if (preserveAspectRatio.alignX === 'Min') {\r\n widthDiff = 0;\r\n }\r\n if (preserveAspectRatio.alignY === 'Min') {\r\n heightDiff = 0;\r\n }\r\n }\r\n\r\n if (scaleX === 1 && scaleY === 1 && minX === 0 && minY === 0 && x === 0 && y === 0) {\r\n return parsedDim;\r\n }\r\n if ((x || y) && element.parentNode.nodeName !== '#document') {\r\n translateMatrix = ' translate(' + parseUnit(x) + ' ' + parseUnit(y) + ') ';\r\n }\r\n\r\n matrix = translateMatrix + ' matrix(' + scaleX +\r\n ' 0' +\r\n ' 0 ' +\r\n scaleY + ' ' +\r\n (minX * scaleX + widthDiff) + ' ' +\r\n (minY * scaleY + heightDiff) + ') ';\r\n // seems unused.\r\n // parsedDim.viewboxTransform = fabric.parseTransformAttribute(matrix);\r\n if (element.nodeName === 'svg') {\r\n el = element.ownerDocument.createElementNS(fabric.svgNS, 'g');\r\n // element.firstChild != null\r\n while (element.firstChild) {\r\n el.appendChild(element.firstChild);\r\n }\r\n element.appendChild(el);\r\n }\r\n else {\r\n el = element;\r\n el.removeAttribute('x');\r\n el.removeAttribute('y');\r\n matrix = el.getAttribute('transform') + matrix;\r\n }\r\n el.setAttribute('transform', matrix);\r\n return parsedDim;\r\n }\r\n\r\n function hasAncestorWithNodeName(element, nodeName) {\r\n while (element && (element = element.parentNode)) {\r\n if (element.nodeName && nodeName.test(element.nodeName.replace('svg:', ''))\r\n && !element.getAttribute('instantiated_by_use')) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Parses an SVG document, converts it to an array of corresponding fabric.* instances and passes them to a callback\r\n * @static\r\n * @function\r\n * @memberOf fabric\r\n * @param {SVGDocument} doc SVG document to parse\r\n * @param {Function} callback Callback to call when parsing is finished;\r\n * It's being passed an array of elements (parsed from a document).\r\n * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\r\n * @param {Object} [parsingOptions] options for parsing document\r\n * @param {String} [parsingOptions.crossOrigin] crossOrigin settings\r\n */\r\n fabric.parseSVGDocument = function(doc, callback, reviver, parsingOptions) {\r\n if (!doc) {\r\n return;\r\n }\r\n\r\n parseUseDirectives(doc);\r\n\r\n var svgUid = fabric.Object.__uid++, i, len,\r\n options = applyViewboxTransform(doc),\r\n descendants = fabric.util.toArray(doc.getElementsByTagName('*'));\r\n options.crossOrigin = parsingOptions && parsingOptions.crossOrigin;\r\n options.svgUid = svgUid;\r\n\r\n if (descendants.length === 0 && fabric.isLikelyNode) {\r\n // we're likely in node, where \"o3-xml\" library fails to gEBTN(\"*\")\r\n // https://github.com/ajaxorg/node-o3-xml/issues/21\r\n descendants = doc.selectNodes('//*[name(.)!=\"svg\"]');\r\n var arr = [];\r\n for (i = 0, len = descendants.length; i < len; i++) {\r\n arr[i] = descendants[i];\r\n }\r\n descendants = arr;\r\n }\r\n\r\n var elements = descendants.filter(function(el) {\r\n applyViewboxTransform(el);\r\n return fabric.svgValidTagNamesRegEx.test(el.nodeName.replace('svg:', '')) &&\r\n !hasAncestorWithNodeName(el, fabric.svgInvalidAncestorsRegEx); // http://www.w3.org/TR/SVG/struct.html#DefsElement\r\n });\r\n if (!elements || (elements && !elements.length)) {\r\n callback && callback([], {});\r\n return;\r\n }\r\n var clipPaths = { };\r\n descendants.filter(function(el) {\r\n return el.nodeName.replace('svg:', '') === 'clipPath';\r\n }).forEach(function(el) {\r\n var id = el.getAttribute('id');\r\n clipPaths[id] = fabric.util.toArray(el.getElementsByTagName('*')).filter(function(el) {\r\n return fabric.svgValidTagNamesRegEx.test(el.nodeName.replace('svg:', ''));\r\n });\r\n });\r\n fabric.gradientDefs[svgUid] = fabric.getGradientDefs(doc);\r\n fabric.cssRules[svgUid] = fabric.getCSSRules(doc);\r\n fabric.clipPaths[svgUid] = clipPaths;\r\n // Precedence of rules: style > class > attribute\r\n fabric.parseElements(elements, function(instances, elements) {\r\n if (callback) {\r\n callback(instances, options, elements, descendants);\r\n delete fabric.gradientDefs[svgUid];\r\n delete fabric.cssRules[svgUid];\r\n delete fabric.clipPaths[svgUid];\r\n }\r\n }, clone(options), reviver, parsingOptions);\r\n };\r\n\r\n function recursivelyParseGradientsXlink(doc, gradient) {\r\n var gradientsAttrs = ['gradientTransform', 'x1', 'x2', 'y1', 'y2', 'gradientUnits', 'cx', 'cy', 'r', 'fx', 'fy'],\r\n xlinkAttr = 'xlink:href',\r\n xLink = gradient.getAttribute(xlinkAttr).slice(1),\r\n referencedGradient = elementById(doc, xLink);\r\n if (referencedGradient && referencedGradient.getAttribute(xlinkAttr)) {\r\n recursivelyParseGradientsXlink(doc, referencedGradient);\r\n }\r\n gradientsAttrs.forEach(function(attr) {\r\n if (referencedGradient && !gradient.hasAttribute(attr) && referencedGradient.hasAttribute(attr)) {\r\n gradient.setAttribute(attr, referencedGradient.getAttribute(attr));\r\n }\r\n });\r\n if (!gradient.children.length) {\r\n var referenceClone = referencedGradient.cloneNode(true);\r\n while (referenceClone.firstChild) {\r\n gradient.appendChild(referenceClone.firstChild);\r\n }\r\n }\r\n gradient.removeAttribute(xlinkAttr);\r\n }\r\n\r\n var reFontDeclaration = new RegExp(\r\n '(normal|italic)?\\\\s*(normal|small-caps)?\\\\s*' +\r\n '(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\\\\s*(' +\r\n fabric.reNum +\r\n '(?:px|cm|mm|em|pt|pc|in)*)(?:\\\\/(normal|' + fabric.reNum + '))?\\\\s+(.*)');\r\n\r\n extend(fabric, {\r\n /**\r\n * Parses a short font declaration, building adding its properties to a style object\r\n * @static\r\n * @function\r\n * @memberOf fabric\r\n * @param {String} value font declaration\r\n * @param {Object} oStyle definition\r\n */\r\n parseFontDeclaration: function(value, oStyle) {\r\n var match = value.match(reFontDeclaration);\r\n\r\n if (!match) {\r\n return;\r\n }\r\n var fontStyle = match[1],\r\n // font variant is not used\r\n // fontVariant = match[2],\r\n fontWeight = match[3],\r\n fontSize = match[4],\r\n lineHeight = match[5],\r\n fontFamily = match[6];\r\n\r\n if (fontStyle) {\r\n oStyle.fontStyle = fontStyle;\r\n }\r\n if (fontWeight) {\r\n oStyle.fontWeight = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight);\r\n }\r\n if (fontSize) {\r\n oStyle.fontSize = parseUnit(fontSize);\r\n }\r\n if (fontFamily) {\r\n oStyle.fontFamily = fontFamily;\r\n }\r\n if (lineHeight) {\r\n oStyle.lineHeight = lineHeight === 'normal' ? 1 : lineHeight;\r\n }\r\n },\r\n\r\n /**\r\n * Parses an SVG document, returning all of the gradient declarations found in it\r\n * @static\r\n * @function\r\n * @memberOf fabric\r\n * @param {SVGDocument} doc SVG document to parse\r\n * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element\r\n */\r\n getGradientDefs: function(doc) {\r\n var tagArray = [\r\n 'linearGradient',\r\n 'radialGradient',\r\n 'svg:linearGradient',\r\n 'svg:radialGradient'],\r\n elList = _getMultipleNodes(doc, tagArray),\r\n el, j = 0, gradientDefs = { };\r\n j = elList.length;\r\n while (j--) {\r\n el = elList[j];\r\n if (el.getAttribute('xlink:href')) {\r\n recursivelyParseGradientsXlink(doc, el);\r\n }\r\n gradientDefs[el.getAttribute('id')] = el;\r\n }\r\n return gradientDefs;\r\n },\r\n\r\n /**\r\n * Returns an object of attributes' name/value, given element and an array of attribute names;\r\n * Parses parent \"g\" nodes recursively upwards.\r\n * @static\r\n * @memberOf fabric\r\n * @param {DOMElement} element Element to parse\r\n * @param {Array} attributes Array of attributes to parse\r\n * @return {Object} object containing parsed attributes' names/values\r\n */\r\n parseAttributes: function(element, attributes, svgUid) {\r\n\r\n if (!element) {\r\n return;\r\n }\r\n\r\n var value,\r\n parentAttributes = { },\r\n fontSize, parentFontSize;\r\n\r\n if (typeof svgUid === 'undefined') {\r\n svgUid = element.getAttribute('svgUid');\r\n }\r\n // if there's a parent container (`g` or `a` or `symbol` node), parse its attributes recursively upwards\r\n if (element.parentNode && fabric.svgValidParentsRegEx.test(element.parentNode.nodeName)) {\r\n parentAttributes = fabric.parseAttributes(element.parentNode, attributes, svgUid);\r\n }\r\n\r\n var ownAttributes = attributes.reduce(function(memo, attr) {\r\n value = element.getAttribute(attr);\r\n if (value) { // eslint-disable-line\r\n memo[attr] = value;\r\n }\r\n return memo;\r\n }, { });\r\n // add values parsed from style, which take precedence over attributes\r\n // (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes)\r\n var cssAttrs = extend(\r\n getGlobalStylesForElement(element, svgUid),\r\n fabric.parseStyleAttribute(element)\r\n );\r\n ownAttributes = extend(\r\n ownAttributes,\r\n cssAttrs\r\n );\r\n if (cssAttrs[cPath]) {\r\n element.setAttribute(cPath, cssAttrs[cPath]);\r\n }\r\n fontSize = parentFontSize = parentAttributes.fontSize || fabric.Text.DEFAULT_SVG_FONT_SIZE;\r\n if (ownAttributes[fSize]) {\r\n // looks like the minimum should be 9px when dealing with ems. this is what looks like in browsers.\r\n ownAttributes[fSize] = fontSize = parseUnit(ownAttributes[fSize], parentFontSize);\r\n }\r\n\r\n var normalizedAttr, normalizedValue, normalizedStyle = {};\r\n for (var attr in ownAttributes) {\r\n normalizedAttr = normalizeAttr(attr);\r\n normalizedValue = normalizeValue(normalizedAttr, ownAttributes[attr], parentAttributes, fontSize);\r\n normalizedStyle[normalizedAttr] = normalizedValue;\r\n }\r\n if (normalizedStyle && normalizedStyle.font) {\r\n fabric.parseFontDeclaration(normalizedStyle.font, normalizedStyle);\r\n }\r\n var mergedAttrs = extend(parentAttributes, normalizedStyle);\r\n return fabric.svgValidParentsRegEx.test(element.nodeName) ? mergedAttrs : _setStrokeFillOpacity(mergedAttrs);\r\n },\r\n\r\n /**\r\n * Transforms an array of svg elements to corresponding fabric.* instances\r\n * @static\r\n * @memberOf fabric\r\n * @param {Array} elements Array of elements to parse\r\n * @param {Function} callback Being passed an array of fabric instances (transformed from SVG elements)\r\n * @param {Object} [options] Options object\r\n * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\r\n */\r\n parseElements: function(elements, callback, options, reviver, parsingOptions) {\r\n new fabric.ElementsParser(elements, callback, options, reviver, parsingOptions).parse();\r\n },\r\n\r\n /**\r\n * Parses \"style\" attribute, retuning an object with values\r\n * @static\r\n * @memberOf fabric\r\n * @param {SVGElement} element Element to parse\r\n * @return {Object} Objects with values parsed from style attribute of an element\r\n */\r\n parseStyleAttribute: function(element) {\r\n var oStyle = { },\r\n style = element.getAttribute('style');\r\n\r\n if (!style) {\r\n return oStyle;\r\n }\r\n\r\n if (typeof style === 'string') {\r\n parseStyleString(style, oStyle);\r\n }\r\n else {\r\n parseStyleObject(style, oStyle);\r\n }\r\n\r\n return oStyle;\r\n },\r\n\r\n /**\r\n * Parses \"points\" attribute, returning an array of values\r\n * @static\r\n * @memberOf fabric\r\n * @param {String} points points attribute string\r\n * @return {Array} array of points\r\n */\r\n parsePointsAttribute: function(points) {\r\n\r\n // points attribute is required and must not be empty\r\n if (!points) {\r\n return null;\r\n }\r\n\r\n // replace commas with whitespace and remove bookending whitespace\r\n points = points.replace(/,/g, ' ').trim();\r\n\r\n points = points.split(/\\s+/);\r\n var parsedPoints = [], i, len;\r\n\r\n for (i = 0, len = points.length; i < len; i += 2) {\r\n parsedPoints.push({\r\n x: parseFloat(points[i]),\r\n y: parseFloat(points[i + 1])\r\n });\r\n }\r\n\r\n // odd number of points is an error\r\n // if (parsedPoints.length % 2 !== 0) {\r\n // return null;\r\n // }\r\n\r\n return parsedPoints;\r\n },\r\n\r\n /**\r\n * Returns CSS rules for a given SVG document\r\n * @static\r\n * @function\r\n * @memberOf fabric\r\n * @param {SVGDocument} doc SVG document to parse\r\n * @return {Object} CSS rules of this document\r\n */\r\n getCSSRules: function(doc) {\r\n var styles = doc.getElementsByTagName('style'), i, len,\r\n allRules = { }, rules;\r\n\r\n // very crude parsing of style contents\r\n for (i = 0, len = styles.length; i < len; i++) {\r\n var styleContents = styles[i].textContent;\r\n\r\n // remove comments\r\n styleContents = styleContents.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\r\n if (styleContents.trim() === '') {\r\n continue;\r\n }\r\n // recovers all the rule in this form `body { style code... }`\r\n // rules = styleContents.match(/[^{]*\\{[\\s\\S]*?\\}/g);\r\n rules = styleContents.split('}');\r\n // remove empty rules.\r\n rules = rules.filter(function(rule) { return rule.trim(); });\r\n // at this point we have hopefully an array of rules `body { style code... `\r\n // eslint-disable-next-line no-loop-func\r\n rules.forEach(function(rule) {\r\n\r\n var match = rule.split('{'),\r\n ruleObj = { }, declaration = match[1].trim(),\r\n propertyValuePairs = declaration.split(';').filter(function(pair) { return pair.trim(); });\r\n\r\n for (i = 0, len = propertyValuePairs.length; i < len; i++) {\r\n var pair = propertyValuePairs[i].split(':'),\r\n property = pair[0].trim(),\r\n value = pair[1].trim();\r\n ruleObj[property] = value;\r\n }\r\n rule = match[0].trim();\r\n rule.split(',').forEach(function(_rule) {\r\n _rule = _rule.replace(/^svg/i, '').trim();\r\n if (_rule === '') {\r\n return;\r\n }\r\n if (allRules[_rule]) {\r\n fabric.util.object.extend(allRules[_rule], ruleObj);\r\n }\r\n else {\r\n allRules[_rule] = fabric.util.object.clone(ruleObj);\r\n }\r\n });\r\n });\r\n }\r\n return allRules;\r\n },\r\n\r\n /**\r\n * Takes url corresponding to an SVG document, and parses it into a set of fabric objects.\r\n * Note that SVG is fetched via XMLHttpRequest, so it needs to conform to SOP (Same Origin Policy)\r\n * @memberOf fabric\r\n * @param {String} url\r\n * @param {Function} callback\r\n * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\r\n * @param {Object} [options] Object containing options for parsing\r\n * @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources\r\n */\r\n loadSVGFromURL: function(url, callback, reviver, options) {\r\n\r\n url = url.replace(/^\\n\\s*/, '').trim();\r\n new fabric.util.request(url, {\r\n method: 'get',\r\n onComplete: onComplete\r\n });\r\n\r\n function onComplete(r) {\r\n\r\n var xml = r.responseXML;\r\n if (!xml || !xml.documentElement) {\r\n callback && callback(null);\r\n return false;\r\n }\r\n\r\n fabric.parseSVGDocument(xml.documentElement, function (results, _options, elements, allElements) {\r\n callback && callback(results, _options, elements, allElements);\r\n }, reviver, options);\r\n }\r\n },\r\n\r\n /**\r\n * Takes string corresponding to an SVG document, and parses it into a set of fabric objects\r\n * @memberOf fabric\r\n * @param {String} string\r\n * @param {Function} callback\r\n * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\r\n * @param {Object} [options] Object containing options for parsing\r\n * @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources\r\n */\r\n loadSVGFromString: function(string, callback, reviver, options) {\r\n var parser = new fabric.window.DOMParser(),\r\n doc = parser.parseFromString(string.trim(), 'text/xml');\r\n fabric.parseSVGDocument(doc.documentElement, function (results, _options, elements, allElements) {\r\n callback(results, _options, elements, allElements);\r\n }, reviver, options);\r\n }\r\n });\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\nfabric.ElementsParser = function(elements, callback, options, reviver, parsingOptions, doc) {\r\n this.elements = elements;\r\n this.callback = callback;\r\n this.options = options;\r\n this.reviver = reviver;\r\n this.svgUid = (options && options.svgUid) || 0;\r\n this.parsingOptions = parsingOptions;\r\n this.regexUrl = /^url\\(['\"]?#([^'\"]+)['\"]?\\)/g;\r\n this.doc = doc;\r\n};\r\n\r\n(function(proto) {\r\n proto.parse = function() {\r\n this.instances = new Array(this.elements.length);\r\n this.numElements = this.elements.length;\r\n this.createObjects();\r\n };\r\n\r\n proto.createObjects = function() {\r\n var _this = this;\r\n this.elements.forEach(function(element, i) {\r\n element.setAttribute('svgUid', _this.svgUid);\r\n _this.createObject(element, i);\r\n });\r\n };\r\n\r\n proto.findTag = function(el) {\r\n return fabric[fabric.util.string.capitalize(el.tagName.replace('svg:', ''))];\r\n };\r\n\r\n proto.createObject = function(el, index) {\r\n var klass = this.findTag(el);\r\n if (klass && klass.fromElement) {\r\n try {\r\n klass.fromElement(el, this.createCallback(index, el), this.options);\r\n }\r\n catch (err) {\r\n fabric.log(err);\r\n }\r\n }\r\n else {\r\n this.checkIfDone();\r\n }\r\n };\r\n\r\n proto.createCallback = function(index, el) {\r\n var _this = this;\r\n return function(obj) {\r\n var _options;\r\n _this.resolveGradient(obj, el, 'fill');\r\n _this.resolveGradient(obj, el, 'stroke');\r\n if (obj instanceof fabric.Image && obj._originalElement) {\r\n _options = obj.parsePreserveAspectRatioAttribute(el);\r\n }\r\n obj._removeTransformMatrix(_options);\r\n _this.resolveClipPath(obj, el);\r\n _this.reviver && _this.reviver(el, obj);\r\n _this.instances[index] = obj;\r\n _this.checkIfDone();\r\n };\r\n };\r\n\r\n proto.extractPropertyDefinition = function(obj, property, storage) {\r\n var value = obj[property], regex = this.regexUrl;\r\n if (!regex.test(value)) {\r\n return;\r\n }\r\n regex.lastIndex = 0;\r\n var id = regex.exec(value)[1];\r\n regex.lastIndex = 0;\r\n return fabric[storage][this.svgUid][id];\r\n };\r\n\r\n proto.resolveGradient = function(obj, el, property) {\r\n var gradientDef = this.extractPropertyDefinition(obj, property, 'gradientDefs');\r\n if (gradientDef) {\r\n var opacityAttr = el.getAttribute(property + '-opacity');\r\n var gradient = fabric.Gradient.fromElement(gradientDef, obj, opacityAttr, this.options);\r\n obj.set(property, gradient);\r\n }\r\n };\r\n\r\n proto.createClipPathCallback = function(obj, container) {\r\n return function(_newObj) {\r\n _newObj._removeTransformMatrix();\r\n _newObj.fillRule = _newObj.clipRule;\r\n container.push(_newObj);\r\n };\r\n };\r\n\r\n proto.resolveClipPath = function(obj, usingElement) {\r\n var clipPath = this.extractPropertyDefinition(obj, 'clipPath', 'clipPaths'),\r\n element, klass, objTransformInv, container, gTransform, options;\r\n if (clipPath) {\r\n container = [];\r\n objTransformInv = fabric.util.invertTransform(obj.calcTransformMatrix());\r\n // move the clipPath tag as sibling to the real element that is using it\r\n var clipPathTag = clipPath[0].parentNode;\r\n var clipPathOwner = usingElement;\r\n while (clipPathOwner.parentNode && clipPathOwner.getAttribute('clip-path') !== obj.clipPath) {\r\n clipPathOwner = clipPathOwner.parentNode;\r\n }\r\n clipPathOwner.parentNode.appendChild(clipPathTag);\r\n for (var i = 0; i < clipPath.length; i++) {\r\n element = clipPath[i];\r\n klass = this.findTag(element);\r\n klass.fromElement(\r\n element,\r\n this.createClipPathCallback(obj, container),\r\n this.options\r\n );\r\n }\r\n if (container.length === 1) {\r\n clipPath = container[0];\r\n }\r\n else {\r\n clipPath = new fabric.Group(container);\r\n }\r\n gTransform = fabric.util.multiplyTransformMatrices(\r\n objTransformInv,\r\n clipPath.calcTransformMatrix()\r\n );\r\n if (clipPath.clipPath) {\r\n this.resolveClipPath(clipPath, clipPathOwner);\r\n }\r\n var options = fabric.util.qrDecompose(gTransform);\r\n clipPath.flipX = false;\r\n clipPath.flipY = false;\r\n clipPath.set('scaleX', options.scaleX);\r\n clipPath.set('scaleY', options.scaleY);\r\n clipPath.angle = options.angle;\r\n clipPath.skewX = options.skewX;\r\n clipPath.skewY = 0;\r\n clipPath.setPositionByOrigin({ x: options.translateX, y: options.translateY }, 'center', 'center');\r\n obj.clipPath = clipPath;\r\n }\r\n else {\r\n // if clip-path does not resolve to any element, delete the property.\r\n delete obj.clipPath;\r\n }\r\n };\r\n\r\n proto.checkIfDone = function() {\r\n if (--this.numElements === 0) {\r\n this.instances = this.instances.filter(function(el) {\r\n // eslint-disable-next-line no-eq-null, eqeqeq\r\n return el != null;\r\n });\r\n this.callback(this.instances, this.elements);\r\n }\r\n };\r\n})(fabric.ElementsParser.prototype);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */\r\n\r\n var fabric = global.fabric || (global.fabric = { });\r\n\r\n if (fabric.Point) {\r\n fabric.warn('fabric.Point is already defined');\r\n return;\r\n }\r\n\r\n fabric.Point = Point;\r\n\r\n /**\r\n * Point class\r\n * @class fabric.Point\r\n * @memberOf fabric\r\n * @constructor\r\n * @param {Number} x\r\n * @param {Number} y\r\n * @return {fabric.Point} thisArg\r\n */\r\n function Point(x, y) {\r\n this.x = x;\r\n this.y = y;\r\n }\r\n\r\n Point.prototype = /** @lends fabric.Point.prototype */ {\r\n\r\n type: 'point',\r\n\r\n constructor: Point,\r\n\r\n /**\r\n * Adds another point to this one and returns another one\r\n * @param {fabric.Point} that\r\n * @return {fabric.Point} new Point instance with added values\r\n */\r\n add: function (that) {\r\n return new Point(this.x + that.x, this.y + that.y);\r\n },\r\n\r\n /**\r\n * Adds another point to this one\r\n * @param {fabric.Point} that\r\n * @return {fabric.Point} thisArg\r\n * @chainable\r\n */\r\n addEquals: function (that) {\r\n this.x += that.x;\r\n this.y += that.y;\r\n return this;\r\n },\r\n\r\n /**\r\n * Adds value to this point and returns a new one\r\n * @param {Number} scalar\r\n * @return {fabric.Point} new Point with added value\r\n */\r\n scalarAdd: function (scalar) {\r\n return new Point(this.x + scalar, this.y + scalar);\r\n },\r\n\r\n /**\r\n * Adds value to this point\r\n * @param {Number} scalar\r\n * @return {fabric.Point} thisArg\r\n * @chainable\r\n */\r\n scalarAddEquals: function (scalar) {\r\n this.x += scalar;\r\n this.y += scalar;\r\n return this;\r\n },\r\n\r\n /**\r\n * Subtracts another point from this point and returns a new one\r\n * @param {fabric.Point} that\r\n * @return {fabric.Point} new Point object with subtracted values\r\n */\r\n subtract: function (that) {\r\n return new Point(this.x - that.x, this.y - that.y);\r\n },\r\n\r\n /**\r\n * Subtracts another point from this point\r\n * @param {fabric.Point} that\r\n * @return {fabric.Point} thisArg\r\n * @chainable\r\n */\r\n subtractEquals: function (that) {\r\n this.x -= that.x;\r\n this.y -= that.y;\r\n return this;\r\n },\r\n\r\n /**\r\n * Subtracts value from this point and returns a new one\r\n * @param {Number} scalar\r\n * @return {fabric.Point}\r\n */\r\n scalarSubtract: function (scalar) {\r\n return new Point(this.x - scalar, this.y - scalar);\r\n },\r\n\r\n /**\r\n * Subtracts value from this point\r\n * @param {Number} scalar\r\n * @return {fabric.Point} thisArg\r\n * @chainable\r\n */\r\n scalarSubtractEquals: function (scalar) {\r\n this.x -= scalar;\r\n this.y -= scalar;\r\n return this;\r\n },\r\n\r\n /**\r\n * Multiplies this point by a value and returns a new one\r\n * TODO: rename in scalarMultiply in 2.0\r\n * @param {Number} scalar\r\n * @return {fabric.Point}\r\n */\r\n multiply: function (scalar) {\r\n return new Point(this.x * scalar, this.y * scalar);\r\n },\r\n\r\n /**\r\n * Multiplies this point by a value\r\n * TODO: rename in scalarMultiplyEquals in 2.0\r\n * @param {Number} scalar\r\n * @return {fabric.Point} thisArg\r\n * @chainable\r\n */\r\n multiplyEquals: function (scalar) {\r\n this.x *= scalar;\r\n this.y *= scalar;\r\n return this;\r\n },\r\n\r\n /**\r\n * Divides this point by a value and returns a new one\r\n * TODO: rename in scalarDivide in 2.0\r\n * @param {Number} scalar\r\n * @return {fabric.Point}\r\n */\r\n divide: function (scalar) {\r\n return new Point(this.x / scalar, this.y / scalar);\r\n },\r\n\r\n /**\r\n * Divides this point by a value\r\n * TODO: rename in scalarDivideEquals in 2.0\r\n * @param {Number} scalar\r\n * @return {fabric.Point} thisArg\r\n * @chainable\r\n */\r\n divideEquals: function (scalar) {\r\n this.x /= scalar;\r\n this.y /= scalar;\r\n return this;\r\n },\r\n\r\n /**\r\n * Returns true if this point is equal to another one\r\n * @param {fabric.Point} that\r\n * @return {Boolean}\r\n */\r\n eq: function (that) {\r\n return (this.x === that.x && this.y === that.y);\r\n },\r\n\r\n /**\r\n * Returns true if this point is less than another one\r\n * @param {fabric.Point} that\r\n * @return {Boolean}\r\n */\r\n lt: function (that) {\r\n return (this.x < that.x && this.y < that.y);\r\n },\r\n\r\n /**\r\n * Returns true if this point is less than or equal to another one\r\n * @param {fabric.Point} that\r\n * @return {Boolean}\r\n */\r\n lte: function (that) {\r\n return (this.x <= that.x && this.y <= that.y);\r\n },\r\n\r\n /**\r\n\r\n * Returns true if this point is greater another one\r\n * @param {fabric.Point} that\r\n * @return {Boolean}\r\n */\r\n gt: function (that) {\r\n return (this.x > that.x && this.y > that.y);\r\n },\r\n\r\n /**\r\n * Returns true if this point is greater than or equal to another one\r\n * @param {fabric.Point} that\r\n * @return {Boolean}\r\n */\r\n gte: function (that) {\r\n return (this.x >= that.x && this.y >= that.y);\r\n },\r\n\r\n /**\r\n * Returns new point which is the result of linear interpolation with this one and another one\r\n * @param {fabric.Point} that\r\n * @param {Number} t , position of interpolation, between 0 and 1 default 0.5\r\n * @return {fabric.Point}\r\n */\r\n lerp: function (that, t) {\r\n if (typeof t === 'undefined') {\r\n t = 0.5;\r\n }\r\n t = Math.max(Math.min(1, t), 0);\r\n return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t);\r\n },\r\n\r\n /**\r\n * Returns distance from this point and another one\r\n * @param {fabric.Point} that\r\n * @return {Number}\r\n */\r\n distanceFrom: function (that) {\r\n var dx = this.x - that.x,\r\n dy = this.y - that.y;\r\n return Math.sqrt(dx * dx + dy * dy);\r\n },\r\n\r\n /**\r\n * Returns the point between this point and another one\r\n * @param {fabric.Point} that\r\n * @return {fabric.Point}\r\n */\r\n midPointFrom: function (that) {\r\n return this.lerp(that);\r\n },\r\n\r\n /**\r\n * Returns a new point which is the min of this and another one\r\n * @param {fabric.Point} that\r\n * @return {fabric.Point}\r\n */\r\n min: function (that) {\r\n return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y));\r\n },\r\n\r\n /**\r\n * Returns a new point which is the max of this and another one\r\n * @param {fabric.Point} that\r\n * @return {fabric.Point}\r\n */\r\n max: function (that) {\r\n return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y));\r\n },\r\n\r\n /**\r\n * Returns string representation of this point\r\n * @return {String}\r\n */\r\n toString: function () {\r\n return this.x + ',' + this.y;\r\n },\r\n\r\n /**\r\n * Sets x/y of this point\r\n * @param {Number} x\r\n * @param {Number} y\r\n * @chainable\r\n */\r\n setXY: function (x, y) {\r\n this.x = x;\r\n this.y = y;\r\n return this;\r\n },\r\n\r\n /**\r\n * Sets x of this point\r\n * @param {Number} x\r\n * @chainable\r\n */\r\n setX: function (x) {\r\n this.x = x;\r\n return this;\r\n },\r\n\r\n /**\r\n * Sets y of this point\r\n * @param {Number} y\r\n * @chainable\r\n */\r\n setY: function (y) {\r\n this.y = y;\r\n return this;\r\n },\r\n\r\n /**\r\n * Sets x/y of this point from another point\r\n * @param {fabric.Point} that\r\n * @chainable\r\n */\r\n setFromPoint: function (that) {\r\n this.x = that.x;\r\n this.y = that.y;\r\n return this;\r\n },\r\n\r\n /**\r\n * Swaps x/y of this point and another point\r\n * @param {fabric.Point} that\r\n */\r\n swap: function (that) {\r\n var x = this.x,\r\n y = this.y;\r\n this.x = that.x;\r\n this.y = that.y;\r\n that.x = x;\r\n that.y = y;\r\n },\r\n\r\n /**\r\n * return a cloned instance of the point\r\n * @return {fabric.Point}\r\n */\r\n clone: function () {\r\n return new Point(this.x, this.y);\r\n }\r\n };\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */\r\n var fabric = global.fabric || (global.fabric = { });\r\n\r\n if (fabric.Intersection) {\r\n fabric.warn('fabric.Intersection is already defined');\r\n return;\r\n }\r\n\r\n /**\r\n * Intersection class\r\n * @class fabric.Intersection\r\n * @memberOf fabric\r\n * @constructor\r\n */\r\n function Intersection(status) {\r\n this.status = status;\r\n this.points = [];\r\n }\r\n\r\n fabric.Intersection = Intersection;\r\n\r\n fabric.Intersection.prototype = /** @lends fabric.Intersection.prototype */ {\r\n\r\n constructor: Intersection,\r\n\r\n /**\r\n * Appends a point to intersection\r\n * @param {fabric.Point} point\r\n * @return {fabric.Intersection} thisArg\r\n * @chainable\r\n */\r\n appendPoint: function (point) {\r\n this.points.push(point);\r\n return this;\r\n },\r\n\r\n /**\r\n * Appends points to intersection\r\n * @param {Array} points\r\n * @return {fabric.Intersection} thisArg\r\n * @chainable\r\n */\r\n appendPoints: function (points) {\r\n this.points = this.points.concat(points);\r\n return this;\r\n }\r\n };\r\n\r\n /**\r\n * Checks if one line intersects another\r\n * TODO: rename in intersectSegmentSegment\r\n * @static\r\n * @param {fabric.Point} a1\r\n * @param {fabric.Point} a2\r\n * @param {fabric.Point} b1\r\n * @param {fabric.Point} b2\r\n * @return {fabric.Intersection}\r\n */\r\n fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) {\r\n var result,\r\n uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x),\r\n ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x),\r\n uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);\r\n if (uB !== 0) {\r\n var ua = uaT / uB,\r\n ub = ubT / uB;\r\n if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {\r\n result = new Intersection('Intersection');\r\n result.appendPoint(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y)));\r\n }\r\n else {\r\n result = new Intersection();\r\n }\r\n }\r\n else {\r\n if (uaT === 0 || ubT === 0) {\r\n result = new Intersection('Coincident');\r\n }\r\n else {\r\n result = new Intersection('Parallel');\r\n }\r\n }\r\n return result;\r\n };\r\n\r\n /**\r\n * Checks if line intersects polygon\r\n * TODO: rename in intersectSegmentPolygon\r\n * fix detection of coincident\r\n * @static\r\n * @param {fabric.Point} a1\r\n * @param {fabric.Point} a2\r\n * @param {Array} points\r\n * @return {fabric.Intersection}\r\n */\r\n fabric.Intersection.intersectLinePolygon = function(a1, a2, points) {\r\n var result = new Intersection(),\r\n length = points.length,\r\n b1, b2, inter, i;\r\n\r\n for (i = 0; i < length; i++) {\r\n b1 = points[i];\r\n b2 = points[(i + 1) % length];\r\n inter = Intersection.intersectLineLine(a1, a2, b1, b2);\r\n\r\n result.appendPoints(inter.points);\r\n }\r\n if (result.points.length > 0) {\r\n result.status = 'Intersection';\r\n }\r\n return result;\r\n };\r\n\r\n /**\r\n * Checks if polygon intersects another polygon\r\n * @static\r\n * @param {Array} points1\r\n * @param {Array} points2\r\n * @return {fabric.Intersection}\r\n */\r\n fabric.Intersection.intersectPolygonPolygon = function (points1, points2) {\r\n var result = new Intersection(),\r\n length = points1.length, i;\r\n\r\n for (i = 0; i < length; i++) {\r\n var a1 = points1[i],\r\n a2 = points1[(i + 1) % length],\r\n inter = Intersection.intersectLinePolygon(a1, a2, points2);\r\n\r\n result.appendPoints(inter.points);\r\n }\r\n if (result.points.length > 0) {\r\n result.status = 'Intersection';\r\n }\r\n return result;\r\n };\r\n\r\n /**\r\n * Checks if polygon intersects rectangle\r\n * @static\r\n * @param {Array} points\r\n * @param {fabric.Point} r1\r\n * @param {fabric.Point} r2\r\n * @return {fabric.Intersection}\r\n */\r\n fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) {\r\n var min = r1.min(r2),\r\n max = r1.max(r2),\r\n topRight = new fabric.Point(max.x, min.y),\r\n bottomLeft = new fabric.Point(min.x, max.y),\r\n inter1 = Intersection.intersectLinePolygon(min, topRight, points),\r\n inter2 = Intersection.intersectLinePolygon(topRight, max, points),\r\n inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points),\r\n inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points),\r\n result = new Intersection();\r\n\r\n result.appendPoints(inter1.points);\r\n result.appendPoints(inter2.points);\r\n result.appendPoints(inter3.points);\r\n result.appendPoints(inter4.points);\r\n\r\n if (result.points.length > 0) {\r\n result.status = 'Intersection';\r\n }\r\n return result;\r\n };\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { });\r\n\r\n if (fabric.Color) {\r\n fabric.warn('fabric.Color is already defined.');\r\n return;\r\n }\r\n\r\n /**\r\n * Color class\r\n * The purpose of {@link fabric.Color} is to abstract and encapsulate common color operations;\r\n * {@link fabric.Color} is a constructor and creates instances of {@link fabric.Color} objects.\r\n *\r\n * @class fabric.Color\r\n * @param {String} color optional in hex or rgb(a) or hsl format or from known color list\r\n * @return {fabric.Color} thisArg\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#colors}\r\n */\r\n function Color(color) {\r\n if (!color) {\r\n this.setSource([0, 0, 0, 1]);\r\n }\r\n else {\r\n this._tryParsingColor(color);\r\n }\r\n }\r\n\r\n fabric.Color = Color;\r\n\r\n fabric.Color.prototype = /** @lends fabric.Color.prototype */ {\r\n\r\n /**\r\n * @private\r\n * @param {String|Array} color Color value to parse\r\n */\r\n _tryParsingColor: function(color) {\r\n var source;\r\n\r\n if (color in Color.colorNameMap) {\r\n color = Color.colorNameMap[color];\r\n }\r\n\r\n if (color === 'transparent') {\r\n source = [255, 255, 255, 0];\r\n }\r\n\r\n if (!source) {\r\n source = Color.sourceFromHex(color);\r\n }\r\n if (!source) {\r\n source = Color.sourceFromRgb(color);\r\n }\r\n if (!source) {\r\n source = Color.sourceFromHsl(color);\r\n }\r\n if (!source) {\r\n //if color is not recognize let's make black as canvas does\r\n source = [0, 0, 0, 1];\r\n }\r\n if (source) {\r\n this.setSource(source);\r\n }\r\n },\r\n\r\n /**\r\n * Adapted from https://github.com/mjijackson\r\n * @private\r\n * @param {Number} r Red color value\r\n * @param {Number} g Green color value\r\n * @param {Number} b Blue color value\r\n * @return {Array} Hsl color\r\n */\r\n _rgbToHsl: function(r, g, b) {\r\n r /= 255; g /= 255; b /= 255;\r\n\r\n var h, s, l,\r\n max = fabric.util.array.max([r, g, b]),\r\n min = fabric.util.array.min([r, g, b]);\r\n\r\n l = (max + min) / 2;\r\n\r\n if (max === min) {\r\n h = s = 0; // achromatic\r\n }\r\n else {\r\n var d = max - min;\r\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\r\n switch (max) {\r\n case r:\r\n h = (g - b) / d + (g < b ? 6 : 0);\r\n break;\r\n case g:\r\n h = (b - r) / d + 2;\r\n break;\r\n case b:\r\n h = (r - g) / d + 4;\r\n break;\r\n }\r\n h /= 6;\r\n }\r\n\r\n return [\r\n Math.round(h * 360),\r\n Math.round(s * 100),\r\n Math.round(l * 100)\r\n ];\r\n },\r\n\r\n /**\r\n * Returns source of this color (where source is an array representation; ex: [200, 200, 100, 1])\r\n * @return {Array}\r\n */\r\n getSource: function() {\r\n return this._source;\r\n },\r\n\r\n /**\r\n * Sets source of this color (where source is an array representation; ex: [200, 200, 100, 1])\r\n * @param {Array} source\r\n */\r\n setSource: function(source) {\r\n this._source = source;\r\n },\r\n\r\n /**\r\n * Returns color representation in RGB format\r\n * @return {String} ex: rgb(0-255,0-255,0-255)\r\n */\r\n toRgb: function() {\r\n var source = this.getSource();\r\n return 'rgb(' + source[0] + ',' + source[1] + ',' + source[2] + ')';\r\n },\r\n\r\n /**\r\n * Returns color representation in RGBA format\r\n * @return {String} ex: rgba(0-255,0-255,0-255,0-1)\r\n */\r\n toRgba: function() {\r\n var source = this.getSource();\r\n return 'rgba(' + source[0] + ',' + source[1] + ',' + source[2] + ',' + source[3] + ')';\r\n },\r\n\r\n /**\r\n * Returns color representation in HSL format\r\n * @return {String} ex: hsl(0-360,0%-100%,0%-100%)\r\n */\r\n toHsl: function() {\r\n var source = this.getSource(),\r\n hsl = this._rgbToHsl(source[0], source[1], source[2]);\r\n\r\n return 'hsl(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%)';\r\n },\r\n\r\n /**\r\n * Returns color representation in HSLA format\r\n * @return {String} ex: hsla(0-360,0%-100%,0%-100%,0-1)\r\n */\r\n toHsla: function() {\r\n var source = this.getSource(),\r\n hsl = this._rgbToHsl(source[0], source[1], source[2]);\r\n\r\n return 'hsla(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%,' + source[3] + ')';\r\n },\r\n\r\n /**\r\n * Returns color representation in HEX format\r\n * @return {String} ex: FF5555\r\n */\r\n toHex: function() {\r\n var source = this.getSource(), r, g, b;\r\n\r\n r = source[0].toString(16);\r\n r = (r.length === 1) ? ('0' + r) : r;\r\n\r\n g = source[1].toString(16);\r\n g = (g.length === 1) ? ('0' + g) : g;\r\n\r\n b = source[2].toString(16);\r\n b = (b.length === 1) ? ('0' + b) : b;\r\n\r\n return r.toUpperCase() + g.toUpperCase() + b.toUpperCase();\r\n },\r\n\r\n /**\r\n * Returns color representation in HEXA format\r\n * @return {String} ex: FF5555CC\r\n */\r\n toHexa: function() {\r\n var source = this.getSource(), a;\r\n\r\n a = Math.round(source[3] * 255);\r\n a = a.toString(16);\r\n a = (a.length === 1) ? ('0' + a) : a;\r\n\r\n return this.toHex() + a.toUpperCase();\r\n },\r\n\r\n /**\r\n * Gets value of alpha channel for this color\r\n * @return {Number} 0-1\r\n */\r\n getAlpha: function() {\r\n return this.getSource()[3];\r\n },\r\n\r\n /**\r\n * Sets value of alpha channel for this color\r\n * @param {Number} alpha Alpha value 0-1\r\n * @return {fabric.Color} thisArg\r\n */\r\n setAlpha: function(alpha) {\r\n var source = this.getSource();\r\n source[3] = alpha;\r\n this.setSource(source);\r\n return this;\r\n },\r\n\r\n /**\r\n * Transforms color to its grayscale representation\r\n * @return {fabric.Color} thisArg\r\n */\r\n toGrayscale: function() {\r\n var source = this.getSource(),\r\n average = parseInt((source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), 10),\r\n currentAlpha = source[3];\r\n this.setSource([average, average, average, currentAlpha]);\r\n return this;\r\n },\r\n\r\n /**\r\n * Transforms color to its black and white representation\r\n * @param {Number} threshold\r\n * @return {fabric.Color} thisArg\r\n */\r\n toBlackWhite: function(threshold) {\r\n var source = this.getSource(),\r\n average = (source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0),\r\n currentAlpha = source[3];\r\n\r\n threshold = threshold || 127;\r\n\r\n average = (Number(average) < Number(threshold)) ? 0 : 255;\r\n this.setSource([average, average, average, currentAlpha]);\r\n return this;\r\n },\r\n\r\n /**\r\n * Overlays color with another color\r\n * @param {String|fabric.Color} otherColor\r\n * @return {fabric.Color} thisArg\r\n */\r\n overlayWith: function(otherColor) {\r\n if (!(otherColor instanceof Color)) {\r\n otherColor = new Color(otherColor);\r\n }\r\n\r\n var result = [],\r\n alpha = this.getAlpha(),\r\n otherAlpha = 0.5,\r\n source = this.getSource(),\r\n otherSource = otherColor.getSource(), i;\r\n\r\n for (i = 0; i < 3; i++) {\r\n result.push(Math.round((source[i] * (1 - otherAlpha)) + (otherSource[i] * otherAlpha)));\r\n }\r\n\r\n result[3] = alpha;\r\n this.setSource(result);\r\n return this;\r\n }\r\n };\r\n\r\n /**\r\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))\r\n * @static\r\n * @field\r\n * @memberOf fabric.Color\r\n */\r\n // eslint-disable-next-line max-len\r\n fabric.Color.reRGBa = /^rgba?\\(\\s*(\\d{1,3}(?:\\.\\d+)?\\%?)\\s*,\\s*(\\d{1,3}(?:\\.\\d+)?\\%?)\\s*,\\s*(\\d{1,3}(?:\\.\\d+)?\\%?)\\s*(?:\\s*,\\s*((?:\\d*\\.?\\d+)?)\\s*)?\\)$/i;\r\n\r\n /**\r\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 ))\r\n * @static\r\n * @field\r\n * @memberOf fabric.Color\r\n */\r\n fabric.Color.reHSLa = /^hsla?\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3}\\%)\\s*,\\s*(\\d{1,3}\\%)\\s*(?:\\s*,\\s*(\\d+(?:\\.\\d+)?)\\s*)?\\)$/i;\r\n\r\n /**\r\n * Regex matching color in HEX format (ex: #FF5544CC, #FF5555, 010155, aff)\r\n * @static\r\n * @field\r\n * @memberOf fabric.Color\r\n */\r\n fabric.Color.reHex = /^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i;\r\n\r\n /**\r\n * Map of the 148 color names with HEX code\r\n * @static\r\n * @field\r\n * @memberOf fabric.Color\r\n * @see: https://www.w3.org/TR/css3-color/#svg-color\r\n */\r\n fabric.Color.colorNameMap = {\r\n aliceblue: '#F0F8FF',\r\n antiquewhite: '#FAEBD7',\r\n aqua: '#00FFFF',\r\n aquamarine: '#7FFFD4',\r\n EntraID: '#F0FFFF',\r\n beige: '#F5F5DC',\r\n bisque: '#FFE4C4',\r\n black: '#000000',\r\n blanchedalmond: '#FFEBCD',\r\n blue: '#0000FF',\r\n blueviolet: '#8A2BE2',\r\n brown: '#A52A2A',\r\n burlywood: '#DEB887',\r\n cadetblue: '#5F9EA0',\r\n chartreuse: '#7FFF00',\r\n chocolate: '#D2691E',\r\n coral: '#FF7F50',\r\n cornflowerblue: '#6495ED',\r\n cornsilk: '#FFF8DC',\r\n crimson: '#DC143C',\r\n cyan: '#00FFFF',\r\n darkblue: '#00008B',\r\n darkcyan: '#008B8B',\r\n darkgoldenrod: '#B8860B',\r\n darkgray: '#A9A9A9',\r\n darkgrey: '#A9A9A9',\r\n darkgreen: '#006400',\r\n darkkhaki: '#BDB76B',\r\n darkmagenta: '#8B008B',\r\n darkolivegreen: '#556B2F',\r\n darkorange: '#FF8C00',\r\n darkorchid: '#9932CC',\r\n darkred: '#8B0000',\r\n darksalmon: '#E9967A',\r\n darkseagreen: '#8FBC8F',\r\n darkslateblue: '#483D8B',\r\n darkslategray: '#2F4F4F',\r\n darkslategrey: '#2F4F4F',\r\n darkturquoise: '#00CED1',\r\n darkviolet: '#9400D3',\r\n deeppink: '#FF1493',\r\n deepskyblue: '#00BFFF',\r\n dimgray: '#696969',\r\n dimgrey: '#696969',\r\n dodgerblue: '#1E90FF',\r\n firebrick: '#B22222',\r\n floralwhite: '#FFFAF0',\r\n forestgreen: '#228B22',\r\n fuchsia: '#FF00FF',\r\n gainsboro: '#DCDCDC',\r\n ghostwhite: '#F8F8FF',\r\n gold: '#FFD700',\r\n goldenrod: '#DAA520',\r\n gray: '#808080',\r\n grey: '#808080',\r\n green: '#008000',\r\n greenyellow: '#ADFF2F',\r\n honeydew: '#F0FFF0',\r\n hotpink: '#FF69B4',\r\n indianred: '#CD5C5C',\r\n indigo: '#4B0082',\r\n ivory: '#FFFFF0',\r\n khaki: '#F0E68C',\r\n lavender: '#E6E6FA',\r\n lavenderblush: '#FFF0F5',\r\n lawngreen: '#7CFC00',\r\n lemonchiffon: '#FFFACD',\r\n lightblue: '#ADD8E6',\r\n lightcoral: '#F08080',\r\n lightcyan: '#E0FFFF',\r\n lightgoldenrodyellow: '#FAFAD2',\r\n lightgray: '#D3D3D3',\r\n lightgrey: '#D3D3D3',\r\n lightgreen: '#90EE90',\r\n lightpink: '#FFB6C1',\r\n lightsalmon: '#FFA07A',\r\n lightseagreen: '#20B2AA',\r\n lightskyblue: '#87CEFA',\r\n lightslategray: '#778899',\r\n lightslategrey: '#778899',\r\n lightsteelblue: '#B0C4DE',\r\n lightyellow: '#FFFFE0',\r\n lime: '#00FF00',\r\n limegreen: '#32CD32',\r\n linen: '#FAF0E6',\r\n magenta: '#FF00FF',\r\n maroon: '#800000',\r\n mediumaquamarine: '#66CDAA',\r\n mediumblue: '#0000CD',\r\n mediumorchid: '#BA55D3',\r\n mediumpurple: '#9370DB',\r\n mediumseagreen: '#3CB371',\r\n mediumslateblue: '#7B68EE',\r\n mediumspringgreen: '#00FA9A',\r\n mediumturquoise: '#48D1CC',\r\n mediumvioletred: '#C71585',\r\n midnightblue: '#191970',\r\n mintcream: '#F5FFFA',\r\n mistyrose: '#FFE4E1',\r\n moccasin: '#FFE4B5',\r\n navajowhite: '#FFDEAD',\r\n navy: '#000080',\r\n oldlace: '#FDF5E6',\r\n olive: '#808000',\r\n olivedrab: '#6B8E23',\r\n orange: '#FFA500',\r\n orangered: '#FF4500',\r\n orchid: '#DA70D6',\r\n palegoldenrod: '#EEE8AA',\r\n palegreen: '#98FB98',\r\n paleturquoise: '#AFEEEE',\r\n palevioletred: '#DB7093',\r\n papayawhip: '#FFEFD5',\r\n peachpuff: '#FFDAB9',\r\n peru: '#CD853F',\r\n pink: '#FFC0CB',\r\n plum: '#DDA0DD',\r\n powderblue: '#B0E0E6',\r\n purple: '#800080',\r\n rebeccapurple: '#663399',\r\n red: '#FF0000',\r\n rosybrown: '#BC8F8F',\r\n royalblue: '#4169E1',\r\n saddlebrown: '#8B4513',\r\n salmon: '#FA8072',\r\n sandybrown: '#F4A460',\r\n seagreen: '#2E8B57',\r\n seashell: '#FFF5EE',\r\n sienna: '#A0522D',\r\n silver: '#C0C0C0',\r\n skyblue: '#87CEEB',\r\n slateblue: '#6A5ACD',\r\n slategray: '#708090',\r\n slategrey: '#708090',\r\n snow: '#FFFAFA',\r\n springgreen: '#00FF7F',\r\n steelblue: '#4682B4',\r\n tan: '#D2B48C',\r\n teal: '#008080',\r\n thistle: '#D8BFD8',\r\n tomato: '#FF6347',\r\n turquoise: '#40E0D0',\r\n violet: '#EE82EE',\r\n wheat: '#F5DEB3',\r\n white: '#FFFFFF',\r\n whitesmoke: '#F5F5F5',\r\n yellow: '#FFFF00',\r\n yellowgreen: '#9ACD32'\r\n };\r\n\r\n /**\r\n * @private\r\n * @param {Number} p\r\n * @param {Number} q\r\n * @param {Number} t\r\n * @return {Number}\r\n */\r\n function hue2rgb(p, q, t) {\r\n if (t < 0) {\r\n t += 1;\r\n }\r\n if (t > 1) {\r\n t -= 1;\r\n }\r\n if (t < 1 / 6) {\r\n return p + (q - p) * 6 * t;\r\n }\r\n if (t < 1 / 2) {\r\n return q;\r\n }\r\n if (t < 2 / 3) {\r\n return p + (q - p) * (2 / 3 - t) * 6;\r\n }\r\n return p;\r\n }\r\n\r\n /**\r\n * Returns new color object, when given a color in RGB format\r\n * @memberOf fabric.Color\r\n * @param {String} color Color value ex: rgb(0-255,0-255,0-255)\r\n * @return {fabric.Color}\r\n */\r\n fabric.Color.fromRgb = function(color) {\r\n return Color.fromSource(Color.sourceFromRgb(color));\r\n };\r\n\r\n /**\r\n * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format\r\n * @memberOf fabric.Color\r\n * @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%)\r\n * @return {Array} source\r\n */\r\n fabric.Color.sourceFromRgb = function(color) {\r\n var match = color.match(Color.reRGBa);\r\n if (match) {\r\n var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1),\r\n g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1),\r\n b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1);\r\n\r\n return [\r\n parseInt(r, 10),\r\n parseInt(g, 10),\r\n parseInt(b, 10),\r\n match[4] ? parseFloat(match[4]) : 1\r\n ];\r\n }\r\n };\r\n\r\n /**\r\n * Returns new color object, when given a color in RGBA format\r\n * @static\r\n * @function\r\n * @memberOf fabric.Color\r\n * @param {String} color\r\n * @return {fabric.Color}\r\n */\r\n fabric.Color.fromRgba = Color.fromRgb;\r\n\r\n /**\r\n * Returns new color object, when given a color in HSL format\r\n * @param {String} color Color value ex: hsl(0-260,0%-100%,0%-100%)\r\n * @memberOf fabric.Color\r\n * @return {fabric.Color}\r\n */\r\n fabric.Color.fromHsl = function(color) {\r\n return Color.fromSource(Color.sourceFromHsl(color));\r\n };\r\n\r\n /**\r\n * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format.\r\n * Adapted from https://github.com/mjijackson\r\n * @memberOf fabric.Color\r\n * @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1)\r\n * @return {Array} source\r\n * @see http://http://www.w3.org/TR/css3-color/#hsl-color\r\n */\r\n fabric.Color.sourceFromHsl = function(color) {\r\n var match = color.match(Color.reHSLa);\r\n if (!match) {\r\n return;\r\n }\r\n\r\n var h = (((parseFloat(match[1]) % 360) + 360) % 360) / 360,\r\n s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1),\r\n l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1),\r\n r, g, b;\r\n\r\n if (s === 0) {\r\n r = g = b = l;\r\n }\r\n else {\r\n var q = l <= 0.5 ? l * (s + 1) : l + s - l * s,\r\n p = l * 2 - q;\r\n\r\n r = hue2rgb(p, q, h + 1 / 3);\r\n g = hue2rgb(p, q, h);\r\n b = hue2rgb(p, q, h - 1 / 3);\r\n }\r\n\r\n return [\r\n Math.round(r * 255),\r\n Math.round(g * 255),\r\n Math.round(b * 255),\r\n match[4] ? parseFloat(match[4]) : 1\r\n ];\r\n };\r\n\r\n /**\r\n * Returns new color object, when given a color in HSLA format\r\n * @static\r\n * @function\r\n * @memberOf fabric.Color\r\n * @param {String} color\r\n * @return {fabric.Color}\r\n */\r\n fabric.Color.fromHsla = Color.fromHsl;\r\n\r\n /**\r\n * Returns new color object, when given a color in HEX format\r\n * @static\r\n * @memberOf fabric.Color\r\n * @param {String} color Color value ex: FF5555\r\n * @return {fabric.Color}\r\n */\r\n fabric.Color.fromHex = function(color) {\r\n return Color.fromSource(Color.sourceFromHex(color));\r\n };\r\n\r\n /**\r\n * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HEX format\r\n * @static\r\n * @memberOf fabric.Color\r\n * @param {String} color ex: FF5555 or FF5544CC (RGBa)\r\n * @return {Array} source\r\n */\r\n fabric.Color.sourceFromHex = function(color) {\r\n if (color.match(Color.reHex)) {\r\n var value = color.slice(color.indexOf('#') + 1),\r\n isShortNotation = (value.length === 3 || value.length === 4),\r\n isRGBa = (value.length === 8 || value.length === 4),\r\n r = isShortNotation ? (value.charAt(0) + value.charAt(0)) : value.substring(0, 2),\r\n g = isShortNotation ? (value.charAt(1) + value.charAt(1)) : value.substring(2, 4),\r\n b = isShortNotation ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6),\r\n a = isRGBa ? (isShortNotation ? (value.charAt(3) + value.charAt(3)) : value.substring(6, 8)) : 'FF';\r\n\r\n return [\r\n parseInt(r, 16),\r\n parseInt(g, 16),\r\n parseInt(b, 16),\r\n parseFloat((parseInt(a, 16) / 255).toFixed(2))\r\n ];\r\n }\r\n };\r\n\r\n /**\r\n * Returns new color object, when given color in array representation (ex: [200, 100, 100, 0.5])\r\n * @static\r\n * @memberOf fabric.Color\r\n * @param {Array} source\r\n * @return {fabric.Color}\r\n */\r\n fabric.Color.fromSource = function(source) {\r\n var oColor = new Color();\r\n oColor.setSource(source);\r\n return oColor;\r\n };\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n scaleMap = ['e', 'se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e'],\r\n skewMap = ['ns', 'nesw', 'ew', 'nwse'],\r\n controls = {},\r\n LEFT = 'left', TOP = 'top', RIGHT = 'right', BOTTOM = 'bottom', CENTER = 'center',\r\n opposite = {\r\n top: BOTTOM,\r\n bottom: TOP,\r\n left: RIGHT,\r\n right: LEFT,\r\n center: CENTER,\r\n }, radiansToDegrees = fabric.util.radiansToDegrees,\r\n sign = (Math.sign || function(x) { return ((x > 0) - (x < 0)) || +x; });\r\n\r\n /**\r\n * Combine control position and object angle to find the control direction compared\r\n * to the object center.\r\n * @param {fabric.Object} fabricObject the fabric object for which we are rendering controls\r\n * @param {fabric.Control} control the control class\r\n * @return {Number} 0 - 7 a quadrant number\r\n */\r\n function findCornerQuadrant(fabricObject, control) {\r\n var cornerAngle = fabricObject.angle + radiansToDegrees(Math.atan2(control.y, control.x)) + 360;\r\n return Math.round((cornerAngle % 360) / 45);\r\n }\r\n\r\n function fireEvent(eventName, options) {\r\n var target = options.transform.target,\r\n canvas = target.canvas,\r\n canvasOptions = fabric.util.object.clone(options);\r\n canvasOptions.target = target;\r\n canvas && canvas.fire('object:' + eventName, canvasOptions);\r\n target.fire(eventName, options);\r\n }\r\n\r\n /**\r\n * Inspect event and fabricObject properties to understand if the scaling action\r\n * @param {Event} eventData from the user action\r\n * @param {fabric.Object} fabricObject the fabric object about to scale\r\n * @return {Boolean} true if scale is proportional\r\n */\r\n function scaleIsProportional(eventData, fabricObject) {\r\n var canvas = fabricObject.canvas, uniScaleKey = canvas.uniScaleKey,\r\n uniformIsToggled = eventData[uniScaleKey];\r\n return (canvas.uniformScaling && !uniformIsToggled) ||\r\n (!canvas.uniformScaling && uniformIsToggled);\r\n }\r\n\r\n /**\r\n * Checks if transform is centered\r\n * @param {Object} transform transform data\r\n * @return {Boolean} true if transform is centered\r\n */\r\n function isTransformCentered(transform) {\r\n return transform.originX === CENTER && transform.originY === CENTER;\r\n }\r\n\r\n /**\r\n * Inspect fabricObject to understand if the current scaling action is allowed\r\n * @param {fabric.Object} fabricObject the fabric object about to scale\r\n * @param {String} by 'x' or 'y' or ''\r\n * @param {Boolean} scaleProportionally true if we are trying to scale proportionally\r\n * @return {Boolean} true if scaling is not allowed at current conditions\r\n */\r\n function scalingIsForbidden(fabricObject, by, scaleProportionally) {\r\n var lockX = fabricObject.lockScalingX, lockY = fabricObject.lockScalingY;\r\n if (lockX && lockY) {\r\n return true;\r\n }\r\n if (!by && (lockX || lockY) && scaleProportionally) {\r\n return true;\r\n }\r\n if (lockX && by === 'x') {\r\n return true;\r\n }\r\n if (lockY && by === 'y') {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * return the correct cursor style for the scale action\r\n * @param {Event} eventData the javascript event that is causing the scale\r\n * @param {fabric.Control} control the control that is interested in the action\r\n * @param {fabric.Object} fabricObject the fabric object that is interested in the action\r\n * @return {String} a valid css string for the cursor\r\n */\r\n function scaleCursorStyleHandler(eventData, control, fabricObject) {\r\n var notAllowed = 'not-allowed',\r\n scaleProportionally = scaleIsProportional(eventData, fabricObject),\r\n by = '';\r\n if (control.x !== 0 && control.y === 0) {\r\n by = 'x';\r\n }\r\n else if (control.x === 0 && control.y !== 0) {\r\n by = 'y';\r\n }\r\n if (scalingIsForbidden(fabricObject, by, scaleProportionally)) {\r\n return notAllowed;\r\n }\r\n var n = findCornerQuadrant(fabricObject, control);\r\n return scaleMap[n] + '-resize';\r\n }\r\n\r\n /**\r\n * return the correct cursor style for the skew action\r\n * @param {Event} eventData the javascript event that is causing the scale\r\n * @param {fabric.Control} control the control that is interested in the action\r\n * @param {fabric.Object} fabricObject the fabric object that is interested in the action\r\n * @return {String} a valid css string for the cursor\r\n */\r\n function skewCursorStyleHandler(eventData, control, fabricObject) {\r\n var notAllowed = 'not-allowed';\r\n if (control.x !== 0 && fabricObject.lockSkewingY) {\r\n return notAllowed;\r\n }\r\n if (control.y !== 0 && fabricObject.lockSkewingX) {\r\n return notAllowed;\r\n }\r\n var n = findCornerQuadrant(fabricObject, control) % 4;\r\n return skewMap[n] + '-resize';\r\n }\r\n\r\n /**\r\n * Combine skew and scale style handlers to cover fabric standard use case\r\n * @param {Event} eventData the javascript event that is causing the scale\r\n * @param {fabric.Control} control the control that is interested in the action\r\n * @param {fabric.Object} fabricObject the fabric object that is interested in the action\r\n * @return {String} a valid css string for the cursor\r\n */\r\n function scaleSkewCursorStyleHandler(eventData, control, fabricObject) {\r\n if (eventData[fabricObject.canvas.altActionKey]) {\r\n return controls.skewCursorStyleHandler(eventData, control, fabricObject);\r\n }\r\n return controls.scaleCursorStyleHandler(eventData, control, fabricObject);\r\n }\r\n\r\n /**\r\n * Inspect event, control and fabricObject to return the correct action name\r\n * @param {Event} eventData the javascript event that is causing the scale\r\n * @param {fabric.Control} control the control that is interested in the action\r\n * @param {fabric.Object} fabricObject the fabric object that is interested in the action\r\n * @return {String} an action name\r\n */\r\n function scaleOrSkewActionName(eventData, control, fabricObject) {\r\n var isAlternative = eventData[fabricObject.canvas.altActionKey];\r\n if (control.x === 0) {\r\n // then is scaleY or skewX\r\n return isAlternative ? 'skewX' : 'scaleY';\r\n }\r\n if (control.y === 0) {\r\n // then is scaleY or skewX\r\n return isAlternative ? 'skewY' : 'scaleX';\r\n }\r\n }\r\n\r\n /**\r\n * Find the correct style for the control that is used for rotation.\r\n * this function is very simple and it just take care of not-allowed or standard cursor\r\n * @param {Event} eventData the javascript event that is causing the scale\r\n * @param {fabric.Control} control the control that is interested in the action\r\n * @param {fabric.Object} fabricObject the fabric object that is interested in the action\r\n * @return {String} a valid css string for the cursor\r\n */\r\n function rotationStyleHandler(eventData, control, fabricObject) {\r\n if (fabricObject.lockRotation) {\r\n return 'not-allowed';\r\n }\r\n return control.cursorStyle;\r\n }\r\n\r\n function commonEventInfo(eventData, transform, x, y) {\r\n return {\r\n e: eventData,\r\n transform: transform,\r\n pointer: {\r\n x: x,\r\n y: y,\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * Wrap an action handler with saving/restoring object position on the transform.\r\n * this is the code that permits to objects to keep their position while transforming.\r\n * @param {Function} actionHandler the function to wrap\r\n * @return {Function} a function with an action handler signature\r\n */\r\n function wrapWithFixedAnchor(actionHandler) {\r\n return function(eventData, transform, x, y) {\r\n var target = transform.target, centerPoint = target.getCenterPoint(),\r\n constraint = target.translateToOriginPoint(centerPoint, transform.originX, transform.originY),\r\n actionPerformed = actionHandler(eventData, transform, x, y);\r\n target.setPositionByOrigin(constraint, transform.originX, transform.originY);\r\n return actionPerformed;\r\n };\r\n }\r\n\r\n /**\r\n * Wrap an action handler with firing an event if the action is performed\r\n * @param {Function} actionHandler the function to wrap\r\n * @return {Function} a function with an action handler signature\r\n */\r\n function wrapWithFireEvent(eventName, actionHandler) {\r\n return function(eventData, transform, x, y) {\r\n var actionPerformed = actionHandler(eventData, transform, x, y);\r\n if (actionPerformed) {\r\n fireEvent(eventName, commonEventInfo(eventData, transform, x, y));\r\n }\r\n return actionPerformed;\r\n };\r\n }\r\n\r\n /**\r\n * Transforms a point described by x and y in a distance from the top left corner of the object\r\n * bounding box.\r\n * @param {Object} transform\r\n * @param {String} originX\r\n * @param {String} originY\r\n * @param {number} x\r\n * @param {number} y\r\n * @return {Fabric.Point} the normalized point\r\n */\r\n function getLocalPoint(transform, originX, originY, x, y) {\r\n var target = transform.target,\r\n control = target.controls[transform.corner],\r\n zoom = target.canvas.getZoom(),\r\n padding = target.padding / zoom,\r\n localPoint = target.toLocalPoint(new fabric.Point(x, y), originX, originY);\r\n if (localPoint.x >= padding) {\r\n localPoint.x -= padding;\r\n }\r\n if (localPoint.x <= -padding) {\r\n localPoint.x += padding;\r\n }\r\n if (localPoint.y >= padding) {\r\n localPoint.y -= padding;\r\n }\r\n if (localPoint.y <= padding) {\r\n localPoint.y += padding;\r\n }\r\n localPoint.x -= control.offsetX;\r\n localPoint.y -= control.offsetY;\r\n return localPoint;\r\n }\r\n\r\n /**\r\n * Detect if the fabric object is flipped on one side.\r\n * @param {fabric.Object} target\r\n * @return {Boolean} true if one flip, but not two.\r\n */\r\n function targetHasOneFlip(target) {\r\n return target.flipX !== target.flipY;\r\n }\r\n\r\n /**\r\n * Utility function to compensate the scale factor when skew is applied on both axes\r\n * @private\r\n */\r\n function compensateScaleForSkew(target, oppositeSkew, scaleToCompensate, axis, reference) {\r\n if (target[oppositeSkew] !== 0) {\r\n var newDim = target._getTransformedDimensions()[axis];\r\n var newValue = reference / newDim * target[scaleToCompensate];\r\n target.set(scaleToCompensate, newValue);\r\n }\r\n }\r\n\r\n /**\r\n * Action handler for skewing on the X axis\r\n * @private\r\n */\r\n function skewObjectX(eventData, transform, x, y) {\r\n var target = transform.target,\r\n // find how big the object would be, if there was no skewX. takes in account scaling\r\n dimNoSkew = target._getTransformedDimensions(0, target.skewY),\r\n localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y),\r\n // the mouse is in the center of the object, and we want it to stay there.\r\n // so the object will grow twice as much as the mouse.\r\n // this makes the skew growth to localPoint * 2 - dimNoSkew.\r\n totalSkewSize = Math.abs(localPoint.x * 2) - dimNoSkew.x,\r\n currentSkew = target.skewX, newSkew;\r\n if (totalSkewSize < 2) {\r\n // let's make it easy to go back to position 0.\r\n newSkew = 0;\r\n }\r\n else {\r\n newSkew = radiansToDegrees(\r\n Math.atan2((totalSkewSize / target.scaleX), (dimNoSkew.y / target.scaleY))\r\n );\r\n // now we have to find the sign of the skew.\r\n // it mostly depend on the origin of transformation.\r\n if (transform.originX === LEFT && transform.originY === BOTTOM) {\r\n newSkew = -newSkew;\r\n }\r\n if (transform.originX === RIGHT && transform.originY === TOP) {\r\n newSkew = -newSkew;\r\n }\r\n if (targetHasOneFlip(target)) {\r\n newSkew = -newSkew;\r\n }\r\n }\r\n var hasSkewed = currentSkew !== newSkew;\r\n if (hasSkewed) {\r\n var dimBeforeSkewing = target._getTransformedDimensions().y;\r\n target.set('skewX', newSkew);\r\n compensateScaleForSkew(target, 'skewY', 'scaleY', 'y', dimBeforeSkewing);\r\n }\r\n return hasSkewed;\r\n }\r\n\r\n /**\r\n * Action handler for skewing on the Y axis\r\n * @private\r\n */\r\n function skewObjectY(eventData, transform, x, y) {\r\n var target = transform.target,\r\n // find how big the object would be, if there was no skewX. takes in account scaling\r\n dimNoSkew = target._getTransformedDimensions(target.skewX, 0),\r\n localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y),\r\n // the mouse is in the center of the object, and we want it to stay there.\r\n // so the object will grow twice as much as the mouse.\r\n // this makes the skew growth to localPoint * 2 - dimNoSkew.\r\n totalSkewSize = Math.abs(localPoint.y * 2) - dimNoSkew.y,\r\n currentSkew = target.skewY, newSkew;\r\n if (totalSkewSize < 2) {\r\n // let's make it easy to go back to position 0.\r\n newSkew = 0;\r\n }\r\n else {\r\n newSkew = radiansToDegrees(\r\n Math.atan2((totalSkewSize / target.scaleY), (dimNoSkew.x / target.scaleX))\r\n );\r\n // now we have to find the sign of the skew.\r\n // it mostly depend on the origin of transformation.\r\n if (transform.originX === LEFT && transform.originY === BOTTOM) {\r\n newSkew = -newSkew;\r\n }\r\n if (transform.originX === RIGHT && transform.originY === TOP) {\r\n newSkew = -newSkew;\r\n }\r\n if (targetHasOneFlip(target)) {\r\n newSkew = -newSkew;\r\n }\r\n }\r\n var hasSkewed = currentSkew !== newSkew;\r\n if (hasSkewed) {\r\n var dimBeforeSkewing = target._getTransformedDimensions().x;\r\n target.set('skewY', newSkew);\r\n compensateScaleForSkew(target, 'skewX', 'scaleX', 'x', dimBeforeSkewing);\r\n }\r\n return hasSkewed;\r\n }\r\n\r\n /**\r\n * Wrapped Action handler for skewing on the Y axis, takes care of the\r\n * skew direction and determine the correct transform origin for the anchor point\r\n * @param {Event} eventData javascript event that is doing the transform\r\n * @param {Object} transform javascript object containing a series of information around the current transform\r\n * @param {number} x current mouse x position, canvas normalized\r\n * @param {number} y current mouse y position, canvas normalized\r\n * @return {Boolean} true if some change happened\r\n */\r\n function skewHandlerX(eventData, transform, x, y) {\r\n // step1 figure out and change transform origin.\r\n // if skewX > 0 and originY bottom we anchor on right\r\n // if skewX > 0 and originY top we anchor on left\r\n // if skewX < 0 and originY bottom we anchor on left\r\n // if skewX < 0 and originY top we anchor on right\r\n // if skewX is 0, we look for mouse position to understand where are we going.\r\n var target = transform.target, currentSkew = target.skewX, originX, originY = transform.originY;\r\n if (target.lockSkewingX) {\r\n return false;\r\n }\r\n if (currentSkew === 0) {\r\n var localPointFromCenter = getLocalPoint(transform, CENTER, CENTER, x, y);\r\n if (localPointFromCenter.x > 0) {\r\n // we are pulling right, anchor left;\r\n originX = LEFT;\r\n }\r\n else {\r\n // we are pulling right, anchor right\r\n originX = RIGHT;\r\n }\r\n }\r\n else {\r\n if (currentSkew > 0) {\r\n originX = originY === TOP ? LEFT : RIGHT;\r\n }\r\n if (currentSkew < 0) {\r\n originX = originY === TOP ? RIGHT : LEFT;\r\n }\r\n // is the object flipped on one side only? swap the origin.\r\n if (targetHasOneFlip(target)) {\r\n originX = originX === LEFT ? RIGHT : LEFT;\r\n }\r\n }\r\n\r\n // once we have the origin, we find the anchor point\r\n transform.originX = originX;\r\n var finalHandler = wrapWithFireEvent('skewing', wrapWithFixedAnchor(skewObjectX));\r\n return finalHandler(eventData, transform, x, y);\r\n }\r\n\r\n /**\r\n * Wrapped Action handler for skewing on the Y axis, takes care of the\r\n * skew direction and determine the correct transform origin for the anchor point\r\n * @param {Event} eventData javascript event that is doing the transform\r\n * @param {Object} transform javascript object containing a series of information around the current transform\r\n * @param {number} x current mouse x position, canvas normalized\r\n * @param {number} y current mouse y position, canvas normalized\r\n * @return {Boolean} true if some change happened\r\n */\r\n function skewHandlerY(eventData, transform, x, y) {\r\n // step1 figure out and change transform origin.\r\n // if skewY > 0 and originX left we anchor on top\r\n // if skewY > 0 and originX right we anchor on bottom\r\n // if skewY < 0 and originX left we anchor on bottom\r\n // if skewY < 0 and originX right we anchor on top\r\n // if skewY is 0, we look for mouse position to understand where are we going.\r\n var target = transform.target, currentSkew = target.skewY, originY, originX = transform.originX;\r\n if (target.lockSkewingY) {\r\n return false;\r\n }\r\n if (currentSkew === 0) {\r\n var localPointFromCenter = getLocalPoint(transform, CENTER, CENTER, x, y);\r\n if (localPointFromCenter.y > 0) {\r\n // we are pulling down, anchor up;\r\n originY = TOP;\r\n }\r\n else {\r\n // we are pulling up, anchor down\r\n originY = BOTTOM;\r\n }\r\n }\r\n else {\r\n if (currentSkew > 0) {\r\n originY = originX === LEFT ? TOP : BOTTOM;\r\n }\r\n if (currentSkew < 0) {\r\n originY = originX === LEFT ? BOTTOM : TOP;\r\n }\r\n // is the object flipped on one side only? swap the origin.\r\n if (targetHasOneFlip(target)) {\r\n originY = originY === TOP ? BOTTOM : TOP;\r\n }\r\n }\r\n\r\n // once we have the origin, we find the anchor point\r\n transform.originY = originY;\r\n var finalHandler = wrapWithFireEvent('skewing', wrapWithFixedAnchor(skewObjectY));\r\n return finalHandler(eventData, transform, x, y);\r\n }\r\n\r\n /**\r\n * Action handler for rotation and snapping, without anchor point.\r\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\r\n * @param {Event} eventData javascript event that is doing the transform\r\n * @param {Object} transform javascript object containing a series of information around the current transform\r\n * @param {number} x current mouse x position, canvas normalized\r\n * @param {number} y current mouse y position, canvas normalized\r\n * @return {Boolean} true if some change happened\r\n * @private\r\n */\r\n function rotationWithSnapping(eventData, transform, x, y) {\r\n var t = transform,\r\n target = t.target,\r\n pivotPoint = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY);\r\n\r\n if (target.lockRotation) {\r\n return false;\r\n }\r\n\r\n var lastAngle = Math.atan2(t.ey - pivotPoint.y, t.ex - pivotPoint.x),\r\n curAngle = Math.atan2(y - pivotPoint.y, x - pivotPoint.x),\r\n angle = radiansToDegrees(curAngle - lastAngle + t.theta),\r\n hasRotated = true;\r\n\r\n if (target.snapAngle > 0) {\r\n var snapAngle = target.snapAngle,\r\n snapThreshold = target.snapThreshold || snapAngle,\r\n rightAngleLocked = Math.ceil(angle / snapAngle) * snapAngle,\r\n leftAngleLocked = Math.floor(angle / snapAngle) * snapAngle;\r\n\r\n if (Math.abs(angle - leftAngleLocked) < snapThreshold) {\r\n angle = leftAngleLocked;\r\n }\r\n else if (Math.abs(angle - rightAngleLocked) < snapThreshold) {\r\n angle = rightAngleLocked;\r\n }\r\n }\r\n\r\n // normalize angle to positive value\r\n if (angle < 0) {\r\n angle = 360 + angle;\r\n }\r\n angle %= 360;\r\n\r\n hasRotated = target.angle !== angle;\r\n target.angle = angle;\r\n return hasRotated;\r\n }\r\n\r\n /**\r\n * Basic scaling logic, reused with different constrain for scaling X,Y, freely or equally.\r\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\r\n * @param {Event} eventData javascript event that is doing the transform\r\n * @param {Object} transform javascript object containing a series of information around the current transform\r\n * @param {number} x current mouse x position, canvas normalized\r\n * @param {number} y current mouse y position, canvas normalized\r\n * @param {Object} options additional information for scaling\r\n * @param {String} options.by 'x', 'y', 'equally' or '' to indicate type of scaling\r\n * @return {Boolean} true if some change happened\r\n * @private\r\n */\r\n function scaleObject(eventData, transform, x, y, options) {\r\n options = options || {};\r\n var target = transform.target,\r\n lockScalingX = target.lockScalingX, lockScalingY = target.lockScalingY,\r\n by = options.by, newPoint, scaleX, scaleY, dim,\r\n scaleProportionally = scaleIsProportional(eventData, target),\r\n forbidScaling = scalingIsForbidden(target, by, scaleProportionally),\r\n signX, signY, gestureScale = transform.gestureScale;\r\n\r\n if (forbidScaling) {\r\n return false;\r\n }\r\n if (gestureScale) {\r\n scaleX = transform.scaleX * gestureScale;\r\n scaleY = transform.scaleY * gestureScale;\r\n }\r\n else {\r\n newPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y);\r\n // use of sign: We use sign to detect change of direction of an action. sign usually change when\r\n // we cross the origin point with the mouse. So a scale flip for example. There is an issue when scaling\r\n // by center and scaling using one middle control ( default: mr, mt, ml, mb), the mouse movement can easily\r\n // cross many time the origin point and flip the object. so we need a way to filter out the noise.\r\n // This ternary here should be ok to filter out X scaling when we want Y only and vice versa.\r\n signX = by !== 'y' ? sign(newPoint.x) : 1;\r\n signY = by !== 'x' ? sign(newPoint.y) : 1;\r\n if (!transform.signX) {\r\n transform.signX = signX;\r\n }\r\n if (!transform.signY) {\r\n transform.signY = signY;\r\n }\r\n\r\n if (target.lockScalingFlip &&\r\n (transform.signX !== signX || transform.signY !== signY)\r\n ) {\r\n return false;\r\n }\r\n\r\n dim = target._getTransformedDimensions();\r\n // missing detection of flip and logic to switch the origin\r\n if (scaleProportionally && !by) {\r\n // uniform scaling\r\n var distance = Math.abs(newPoint.x) + Math.abs(newPoint.y),\r\n original = transform.original,\r\n originalDistance = Math.abs(dim.x * original.scaleX / target.scaleX) +\r\n Math.abs(dim.y * original.scaleY / target.scaleY),\r\n scale = distance / originalDistance;\r\n scaleX = original.scaleX * scale;\r\n scaleY = original.scaleY * scale;\r\n }\r\n else {\r\n scaleX = Math.abs(newPoint.x * target.scaleX / dim.x);\r\n scaleY = Math.abs(newPoint.y * target.scaleY / dim.y);\r\n }\r\n // if we are scaling by center, we need to double the scale\r\n if (isTransformCentered(transform)) {\r\n scaleX *= 2;\r\n scaleY *= 2;\r\n }\r\n if (transform.signX !== signX && by !== 'y') {\r\n transform.originX = opposite[transform.originX];\r\n scaleX *= -1;\r\n transform.signX = signX;\r\n }\r\n if (transform.signY !== signY && by !== 'x') {\r\n transform.originY = opposite[transform.originY];\r\n scaleY *= -1;\r\n transform.signY = signY;\r\n }\r\n }\r\n // minScale is taken are in the setter.\r\n var oldScaleX = target.scaleX, oldScaleY = target.scaleY;\r\n if (!by) {\r\n !lockScalingX && target.set('scaleX', scaleX);\r\n !lockScalingY && target.set('scaleY', scaleY);\r\n }\r\n else {\r\n // forbidden cases already handled on top here.\r\n by === 'x' && target.set('scaleX', scaleX);\r\n by === 'y' && target.set('scaleY', scaleY);\r\n }\r\n return oldScaleX !== target.scaleX || oldScaleY !== target.scaleY;\r\n }\r\n\r\n /**\r\n * Generic scaling logic, to scale from corners either equally or freely.\r\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\r\n * @param {Event} eventData javascript event that is doing the transform\r\n * @param {Object} transform javascript object containing a series of information around the current transform\r\n * @param {number} x current mouse x position, canvas normalized\r\n * @param {number} y current mouse y position, canvas normalized\r\n * @return {Boolean} true if some change happened\r\n */\r\n function scaleObjectFromCorner(eventData, transform, x, y) {\r\n return scaleObject(eventData, transform, x, y);\r\n }\r\n\r\n /**\r\n * Scaling logic for the X axis.\r\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\r\n * @param {Event} eventData javascript event that is doing the transform\r\n * @param {Object} transform javascript object containing a series of information around the current transform\r\n * @param {number} x current mouse x position, canvas normalized\r\n * @param {number} y current mouse y position, canvas normalized\r\n * @return {Boolean} true if some change happened\r\n */\r\n function scaleObjectX(eventData, transform, x, y) {\r\n return scaleObject(eventData, transform, x, y , { by: 'x' });\r\n }\r\n\r\n /**\r\n * Scaling logic for the Y axis.\r\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\r\n * @param {Event} eventData javascript event that is doing the transform\r\n * @param {Object} transform javascript object containing a series of information around the current transform\r\n * @param {number} x current mouse x position, canvas normalized\r\n * @param {number} y current mouse y position, canvas normalized\r\n * @return {Boolean} true if some change happened\r\n */\r\n function scaleObjectY(eventData, transform, x, y) {\r\n return scaleObject(eventData, transform, x, y , { by: 'y' });\r\n }\r\n\r\n /**\r\n * Composed action handler to either scale Y or skew X\r\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\r\n * @param {Event} eventData javascript event that is doing the transform\r\n * @param {Object} transform javascript object containing a series of information around the current transform\r\n * @param {number} x current mouse x position, canvas normalized\r\n * @param {number} y current mouse y position, canvas normalized\r\n * @return {Boolean} true if some change happened\r\n */\r\n function scalingYOrSkewingX(eventData, transform, x, y) {\r\n // ok some safety needed here.\r\n if (eventData[transform.target.canvas.altActionKey]) {\r\n return controls.skewHandlerX(eventData, transform, x, y);\r\n }\r\n return controls.scalingY(eventData, transform, x, y);\r\n }\r\n\r\n /**\r\n * Composed action handler to either scale X or skew Y\r\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\r\n * @param {Event} eventData javascript event that is doing the transform\r\n * @param {Object} transform javascript object containing a series of information around the current transform\r\n * @param {number} x current mouse x position, canvas normalized\r\n * @param {number} y current mouse y position, canvas normalized\r\n * @return {Boolean} true if some change happened\r\n */\r\n function scalingXOrSkewingY(eventData, transform, x, y) {\r\n // ok some safety needed here.\r\n if (eventData[transform.target.canvas.altActionKey]) {\r\n return controls.skewHandlerY(eventData, transform, x, y);\r\n }\r\n return controls.scalingX(eventData, transform, x, y);\r\n }\r\n\r\n /**\r\n * Action handler to change textbox width\r\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\r\n * @param {Event} eventData javascript event that is doing the transform\r\n * @param {Object} transform javascript object containing a series of information around the current transform\r\n * @param {number} x current mouse x position, canvas normalized\r\n * @param {number} y current mouse y position, canvas normalized\r\n * @return {Boolean} true if some change happened\r\n */\r\n function changeWidth(eventData, transform, x, y) {\r\n var target = transform.target, localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y),\r\n strokePadding = target.strokeWidth / (target.strokeUniform ? target.scaleX : 1),\r\n multiplier = isTransformCentered(transform) ? 2 : 1,\r\n oldWidth = target.width,\r\n newWidth = Math.abs(localPoint.x * multiplier / target.scaleX) - strokePadding;\r\n target.set('width', Math.max(newWidth, 0));\r\n return oldWidth !== newWidth;\r\n }\r\n\r\n /**\r\n * Action handler\r\n * @private\r\n * @param {Event} eventData javascript event that is doing the transform\r\n * @param {Object} transform javascript object containing a series of information around the current transform\r\n * @param {number} x current mouse x position, canvas normalized\r\n * @param {number} y current mouse y position, canvas normalized\r\n * @return {Boolean} true if the translation occurred\r\n */\r\n function dragHandler(eventData, transform, x, y) {\r\n var target = transform.target,\r\n newLeft = x - transform.offsetX,\r\n newTop = y - transform.offsetY,\r\n moveX = !target.get('lockMovementX') && target.left !== newLeft,\r\n moveY = !target.get('lockMovementY') && target.top !== newTop;\r\n moveX && target.set('left', newLeft);\r\n moveY && target.set('top', newTop);\r\n if (moveX || moveY) {\r\n fireEvent('moving', commonEventInfo(eventData, transform, x, y));\r\n }\r\n return moveX || moveY;\r\n }\r\n\r\n controls.scaleCursorStyleHandler = scaleCursorStyleHandler;\r\n controls.skewCursorStyleHandler = skewCursorStyleHandler;\r\n controls.scaleSkewCursorStyleHandler = scaleSkewCursorStyleHandler;\r\n controls.rotationWithSnapping = wrapWithFireEvent('rotating', wrapWithFixedAnchor(rotationWithSnapping));\r\n controls.scalingEqually = wrapWithFireEvent('scaling', wrapWithFixedAnchor( scaleObjectFromCorner));\r\n controls.scalingX = wrapWithFireEvent('scaling', wrapWithFixedAnchor(scaleObjectX));\r\n controls.scalingY = wrapWithFireEvent('scaling', wrapWithFixedAnchor(scaleObjectY));\r\n controls.scalingYOrSkewingX = scalingYOrSkewingX;\r\n controls.scalingXOrSkewingY = scalingXOrSkewingY;\r\n controls.changeWidth = wrapWithFireEvent('resizing', wrapWithFixedAnchor(changeWidth));\r\n controls.skewHandlerX = skewHandlerX;\r\n controls.skewHandlerY = skewHandlerY;\r\n controls.dragHandler = dragHandler;\r\n controls.scaleOrSkewActionName = scaleOrSkewActionName;\r\n controls.rotationStyleHandler = rotationStyleHandler;\r\n controls.fireEvent = fireEvent;\r\n controls.wrapWithFixedAnchor = wrapWithFixedAnchor;\r\n controls.wrapWithFireEvent = wrapWithFireEvent;\r\n controls.getLocalPoint = getLocalPoint;\r\n fabric.controlsUtils = controls;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n degreesToRadians = fabric.util.degreesToRadians,\r\n controls = fabric.controlsUtils;\r\n\r\n /**\r\n * Render a round control, as per fabric features.\r\n * This function is written to respect object properties like transparentCorners, cornerSize\r\n * cornerColor, cornerStrokeColor\r\n * plus the addition of offsetY and offsetX.\r\n * @param {CanvasRenderingContext2D} ctx context to render on\r\n * @param {Number} left x coordinate where the control center should be\r\n * @param {Number} top y coordinate where the control center should be\r\n * @param {Object} styleOverride override for fabric.Object controls style\r\n * @param {fabric.Object} fabricObject the fabric object for which we are rendering controls\r\n */\r\n function renderCircleControl (ctx, left, top, styleOverride, fabricObject) {\r\n styleOverride = styleOverride || {};\r\n var xSize = this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize,\r\n ySize = this.sizeY || styleOverride.cornerSize || fabricObject.cornerSize,\r\n transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ?\r\n styleOverride.transparentCorners : fabricObject.transparentCorners,\r\n methodName = transparentCorners ? 'stroke' : 'fill',\r\n stroke = !transparentCorners && (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor),\r\n myLeft = left,\r\n myTop = top, size;\r\n ctx.save();\r\n ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor;\r\n ctx.strokeStyle = styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor;\r\n // as soon as fabric react v5, remove ie11, use proper ellipse code.\r\n if (xSize > ySize) {\r\n size = xSize;\r\n ctx.scale(1.0, ySize / xSize);\r\n myTop = top * xSize / ySize;\r\n }\r\n else if (ySize > xSize) {\r\n size = ySize;\r\n ctx.scale(xSize / ySize, 1.0);\r\n myLeft = left * ySize / xSize;\r\n }\r\n else {\r\n size = xSize;\r\n }\r\n // this is still wrong\r\n ctx.lineWidth = 1;\r\n ctx.beginPath();\r\n ctx.arc(myLeft, myTop, size / 2, 0, 2 * Math.PI, false);\r\n ctx[methodName]();\r\n if (stroke) {\r\n ctx.stroke();\r\n }\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Render a square control, as per fabric features.\r\n * This function is written to respect object properties like transparentCorners, cornerSize\r\n * cornerColor, cornerStrokeColor\r\n * plus the addition of offsetY and offsetX.\r\n * @param {CanvasRenderingContext2D} ctx context to render on\r\n * @param {Number} left x coordinate where the control center should be\r\n * @param {Number} top y coordinate where the control center should be\r\n * @param {Object} styleOverride override for fabric.Object controls style\r\n * @param {fabric.Object} fabricObject the fabric object for which we are rendering controls\r\n */\r\n function renderSquareControl(ctx, left, top, styleOverride, fabricObject) {\r\n styleOverride = styleOverride || {};\r\n var xSize = this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize,\r\n ySize = this.sizeY || styleOverride.cornerSize || fabricObject.cornerSize,\r\n transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ?\r\n styleOverride.transparentCorners : fabricObject.transparentCorners,\r\n methodName = transparentCorners ? 'stroke' : 'fill',\r\n stroke = !transparentCorners && (\r\n styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor\r\n ), xSizeBy2 = xSize / 2, ySizeBy2 = ySize / 2;\r\n ctx.save();\r\n ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor;\r\n ctx.strokeStyle = styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor;\r\n // this is still wrong\r\n ctx.lineWidth = 1;\r\n ctx.translate(left, top);\r\n ctx.rotate(degreesToRadians(fabricObject.angle));\r\n // this does not work, and fixed with ( && ) does not make sense.\r\n // to have real transparent corners we need the controls on upperCanvas\r\n // transparentCorners || ctx.clearRect(-xSizeBy2, -ySizeBy2, xSize, ySize);\r\n ctx[methodName + 'Rect'](-xSizeBy2, -ySizeBy2, xSize, ySize);\r\n if (stroke) {\r\n ctx.strokeRect(-xSizeBy2, -ySizeBy2, xSize, ySize);\r\n }\r\n ctx.restore();\r\n }\r\n\r\n controls.renderCircleControl = renderCircleControl;\r\n controls.renderSquareControl = renderSquareControl;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { });\r\n\r\n function Control(options) {\r\n for (var i in options) {\r\n this[i] = options[i];\r\n }\r\n }\r\n\r\n fabric.Control = Control;\r\n\r\n fabric.Control.prototype = /** @lends fabric.Control.prototype */ {\r\n\r\n /**\r\n * keep track of control visibility.\r\n * mainly for backward compatibility.\r\n * if you do not want to see a control, you can remove it\r\n * from the controlset.\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n visible: true,\r\n\r\n /**\r\n * Name of the action that the control will likely execute.\r\n * This is optional. FabricJS uses to identify what the user is doing for some\r\n * extra optimizations. If you are writing a custom control and you want to know\r\n * somewhere else in the code what is going on, you can use this string here.\r\n * you can also provide a custom getActionName if your control run multiple actions\r\n * depending on some external state.\r\n * default to scale since is the most common, used on 4 corners by default\r\n * @type {String}\r\n * @default 'scale'\r\n */\r\n actionName: 'scale',\r\n\r\n /**\r\n * Drawing angle of the control.\r\n * NOT used for now, but name marked as needed for internal logic\r\n * example: to reuse the same drawing function for different rotated controls\r\n * @type {Number}\r\n * @default 0\r\n */\r\n angle: 0,\r\n\r\n /**\r\n * Relative position of the control. X\r\n * 0,0 is the center of the Object, while -0.5 (left) or 0.5 (right) are the extremities\r\n * of the bounding box.\r\n * @type {Number}\r\n * @default 0\r\n */\r\n x: 0,\r\n\r\n /**\r\n * Relative position of the control. Y\r\n * 0,0 is the center of the Object, while -0.5 (top) or 0.5 (bottom) are the extremities\r\n * of the bounding box.\r\n * @type {Number}\r\n * @default 0\r\n */\r\n y: 0,\r\n\r\n /**\r\n * Horizontal offset of the control from the defined position. In pixels\r\n * Positive offset moves the control to the right, negative to the left.\r\n * It used when you want to have position of control that does not scale with\r\n * the bounding box. Example: rotation control is placed at x:0, y: 0.5 on\r\n * the boundindbox, with an offset of 30 pixels vertically. Those 30 pixels will\r\n * stay 30 pixels no matter how the object is big. Another example is having 2\r\n * controls in the corner, that stay in the same position when the object scale.\r\n * of the bounding box.\r\n * @type {Number}\r\n * @default 0\r\n */\r\n offsetX: 0,\r\n\r\n /**\r\n * Vertical offset of the control from the defined position. In pixels\r\n * Positive offset moves the control to the bottom, negative to the top.\r\n * @type {Number}\r\n * @default 0\r\n */\r\n offsetY: 0,\r\n\r\n /**\r\n * Sets the length of the control. If null, defaults to object's cornerSize.\r\n * Expects both sizeX and sizeY to be set when set.\r\n * @type {?Number}\r\n * @default null\r\n */\r\n sizeX: null,\r\n\r\n /**\r\n * Sets the height of the control. If null, defaults to object's cornerSize.\r\n * Expects both sizeX and sizeY to be set when set.\r\n * @type {?Number}\r\n * @default null\r\n */\r\n sizeY: null,\r\n\r\n /**\r\n * Sets the length of the touch area of the control. If null, defaults to object's touchCornerSize.\r\n * Expects both touchSizeX and touchSizeY to be set when set.\r\n * @type {?Number}\r\n * @default null\r\n */\r\n touchSizeX: null,\r\n\r\n /**\r\n * Sets the height of the touch area of the control. If null, defaults to object's touchCornerSize.\r\n * Expects both touchSizeX and touchSizeY to be set when set.\r\n * @type {?Number}\r\n * @default null\r\n */\r\n touchSizeY: null,\r\n\r\n /**\r\n * Css cursor style to display when the control is hovered.\r\n * if the method `cursorStyleHandler` is provided, this property is ignored.\r\n * @type {String}\r\n * @default 'crosshair'\r\n */\r\n cursorStyle: 'crosshair',\r\n\r\n /**\r\n * If controls has an offsetY or offsetX, draw a line that connects\r\n * the control to the bounding box\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n withConnection: false,\r\n\r\n /**\r\n * The control actionHandler, provide one to handle action ( control being moved )\r\n * @param {Event} eventData the native mouse event\r\n * @param {Object} transformData properties of the current transform\r\n * @param {Number} x x position of the cursor\r\n * @param {Number} y y position of the cursor\r\n * @return {Boolean} true if the action/event modified the object\r\n */\r\n actionHandler: function(/* eventData, transformData, x, y */) { },\r\n\r\n /**\r\n * The control handler for mouse down, provide one to handle mouse down on control\r\n * @param {Event} eventData the native mouse event\r\n * @param {Object} transformData properties of the current transform\r\n * @param {Number} x x position of the cursor\r\n * @param {Number} y y position of the cursor\r\n * @return {Boolean} true if the action/event modified the object\r\n */\r\n mouseDownHandler: function(/* eventData, transformData, x, y */) { },\r\n\r\n /**\r\n * The control mouseUpHandler, provide one to handle an effect on mouse up.\r\n * @param {Event} eventData the native mouse event\r\n * @param {Object} transformData properties of the current transform\r\n * @param {Number} x x position of the cursor\r\n * @param {Number} y y position of the cursor\r\n * @return {Boolean} true if the action/event modified the object\r\n */\r\n mouseUpHandler: function(/* eventData, transformData, x, y */) { },\r\n\r\n /**\r\n * Returns control actionHandler\r\n * @param {Event} eventData the native mouse event\r\n * @param {fabric.Object} fabricObject on which the control is displayed\r\n * @param {fabric.Control} control control for which the action handler is being asked\r\n * @return {Function} the action handler\r\n */\r\n getActionHandler: function(/* eventData, fabricObject, control */) {\r\n return this.actionHandler;\r\n },\r\n\r\n /**\r\n * Returns control mouseDown handler\r\n * @param {Event} eventData the native mouse event\r\n * @param {fabric.Object} fabricObject on which the control is displayed\r\n * @param {fabric.Control} control control for which the action handler is being asked\r\n * @return {Function} the action handler\r\n */\r\n getMouseDownHandler: function(/* eventData, fabricObject, control */) {\r\n return this.mouseDownHandler;\r\n },\r\n\r\n /**\r\n * Returns control mouseUp handler\r\n * @param {Event} eventData the native mouse event\r\n * @param {fabric.Object} fabricObject on which the control is displayed\r\n * @param {fabric.Control} control control for which the action handler is being asked\r\n * @return {Function} the action handler\r\n */\r\n getMouseUpHandler: function(/* eventData, fabricObject, control */) {\r\n return this.mouseUpHandler;\r\n },\r\n\r\n /**\r\n * Returns control cursorStyle for css using cursorStyle. If you need a more elaborate\r\n * function you can pass one in the constructor\r\n * the cursorStyle property\r\n * @param {Event} eventData the native mouse event\r\n * @param {fabric.Control} control the current control ( likely this)\r\n * @param {fabric.Object} object on which the control is displayed\r\n * @return {String}\r\n */\r\n cursorStyleHandler: function(eventData, control /* fabricObject */) {\r\n return control.cursorStyle;\r\n },\r\n\r\n /**\r\n * Returns the action name. The basic implementation just return the actionName property.\r\n * @param {Event} eventData the native mouse event\r\n * @param {fabric.Control} control the current control ( likely this)\r\n * @param {fabric.Object} object on which the control is displayed\r\n * @return {String}\r\n */\r\n getActionName: function(eventData, control /* fabricObject */) {\r\n return control.actionName;\r\n },\r\n\r\n /**\r\n * Returns controls visibility\r\n * @param {fabric.Object} object on which the control is displayed\r\n * @param {String} controlKey key where the control is memorized on the\r\n * @return {Boolean}\r\n */\r\n getVisibility: function(fabricObject, controlKey) {\r\n var objectVisibility = fabricObject._controlsVisibility;\r\n if (objectVisibility && typeof objectVisibility[controlKey] !== 'undefined') {\r\n return objectVisibility[controlKey];\r\n }\r\n return this.visible;\r\n },\r\n\r\n /**\r\n * Sets controls visibility\r\n * @param {Boolean} visibility for the object\r\n * @return {Void}\r\n */\r\n setVisibility: function(visibility /* name, fabricObject */) {\r\n this.visible = visibility;\r\n },\r\n\r\n\r\n positionHandler: function(dim, finalMatrix /*, fabricObject, currentControl */) {\r\n var point = fabric.util.transformPoint({\r\n x: this.x * dim.x + this.offsetX,\r\n y: this.y * dim.y + this.offsetY }, finalMatrix);\r\n return point;\r\n },\r\n\r\n /**\r\n * Returns the coords for this control based on object values.\r\n * @param {Number} objectAngle angle from the fabric object holding the control\r\n * @param {Number} objectCornerSize cornerSize from the fabric object holding the control (or touchCornerSize if\r\n * isTouch is true)\r\n * @param {Number} centerX x coordinate where the control center should be\r\n * @param {Number} centerY y coordinate where the control center should be\r\n * @param {boolean} isTouch true if touch corner, false if normal corner\r\n */\r\n calcCornerCoords: function(objectAngle, objectCornerSize, centerX, centerY, isTouch) {\r\n var cosHalfOffset,\r\n sinHalfOffset,\r\n cosHalfOffsetComp,\r\n sinHalfOffsetComp,\r\n xSize = (isTouch) ? this.touchSizeX : this.sizeX,\r\n ySize = (isTouch) ? this.touchSizeY : this.sizeY;\r\n if (xSize && ySize && xSize !== ySize) {\r\n // handle rectangular corners\r\n var controlTriangleAngle = Math.atan2(ySize, xSize);\r\n var cornerHypotenuse = Math.sqrt(xSize * xSize + ySize * ySize) / 2;\r\n var newTheta = controlTriangleAngle - fabric.util.degreesToRadians(objectAngle);\r\n var newThetaComp = Math.PI / 2 - controlTriangleAngle - fabric.util.degreesToRadians(objectAngle);\r\n cosHalfOffset = cornerHypotenuse * fabric.util.cos(newTheta);\r\n sinHalfOffset = cornerHypotenuse * fabric.util.sin(newTheta);\r\n // use complementary angle for two corners\r\n cosHalfOffsetComp = cornerHypotenuse * fabric.util.cos(newThetaComp);\r\n sinHalfOffsetComp = cornerHypotenuse * fabric.util.sin(newThetaComp);\r\n }\r\n else {\r\n // handle square corners\r\n // use default object corner size unless size is defined\r\n var cornerSize = (xSize && ySize) ? xSize : objectCornerSize;\r\n /* 0.7071067812 stands for sqrt(2)/2 */\r\n cornerHypotenuse = cornerSize * 0.7071067812;\r\n // complementary angles are equal since they're both 45 degrees\r\n var newTheta = fabric.util.degreesToRadians(45 - objectAngle);\r\n cosHalfOffset = cosHalfOffsetComp = cornerHypotenuse * fabric.util.cos(newTheta);\r\n sinHalfOffset = sinHalfOffsetComp = cornerHypotenuse * fabric.util.sin(newTheta);\r\n }\r\n\r\n return {\r\n tl: {\r\n x: centerX - sinHalfOffsetComp,\r\n y: centerY - cosHalfOffsetComp,\r\n },\r\n tr: {\r\n x: centerX + cosHalfOffset,\r\n y: centerY - sinHalfOffset,\r\n },\r\n bl: {\r\n x: centerX - cosHalfOffset,\r\n y: centerY + sinHalfOffset,\r\n },\r\n br: {\r\n x: centerX + sinHalfOffsetComp,\r\n y: centerY + cosHalfOffsetComp,\r\n },\r\n };\r\n },\r\n\r\n /**\r\n * Render function for the control.\r\n * When this function runs the context is unscaled. unrotate. Just retina scaled.\r\n * all the functions will have to translate to the point left,top before starting Drawing\r\n * if they want to draw a control where the position is detected.\r\n * left and top are the result of the positionHandler function\r\n * @param {RenderingContext2D} ctx the context where the control will be drawn\r\n * @param {Number} left position of the canvas where we are about to render the control.\r\n * @param {Number} top position of the canvas where we are about to render the control.\r\n * @param {Object} styleOverride\r\n * @param {fabric.Object} fabricObject the object where the control is about to be rendered\r\n */\r\n render: function(ctx, left, top, styleOverride, fabricObject) {\r\n styleOverride = styleOverride || {};\r\n switch (styleOverride.cornerStyle || fabricObject.cornerStyle) {\r\n case 'circle':\r\n fabric.controlsUtils.renderCircleControl.call(this, ctx, left, top, styleOverride, fabricObject);\r\n break;\r\n default:\r\n fabric.controlsUtils.renderSquareControl.call(this, ctx, left, top, styleOverride, fabricObject);\r\n }\r\n },\r\n };\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function() {\r\n\r\n /* _FROM_SVG_START_ */\r\n function getColorStop(el, multiplier) {\r\n var style = el.getAttribute('style'),\r\n offset = el.getAttribute('offset') || 0,\r\n color, colorAlpha, opacity, i;\r\n\r\n // convert percents to absolute values\r\n offset = parseFloat(offset) / (/%$/.test(offset) ? 100 : 1);\r\n offset = offset < 0 ? 0 : offset > 1 ? 1 : offset;\r\n if (style) {\r\n var keyValuePairs = style.split(/\\s*;\\s*/);\r\n\r\n if (keyValuePairs[keyValuePairs.length - 1] === '') {\r\n keyValuePairs.pop();\r\n }\r\n\r\n for (i = keyValuePairs.length; i--; ) {\r\n\r\n var split = keyValuePairs[i].split(/\\s*:\\s*/),\r\n key = split[0].trim(),\r\n value = split[1].trim();\r\n\r\n if (key === 'stop-color') {\r\n color = value;\r\n }\r\n else if (key === 'stop-opacity') {\r\n opacity = value;\r\n }\r\n }\r\n }\r\n\r\n if (!color) {\r\n color = el.getAttribute('stop-color') || 'rgb(0,0,0)';\r\n }\r\n if (!opacity) {\r\n opacity = el.getAttribute('stop-opacity');\r\n }\r\n\r\n color = new fabric.Color(color);\r\n colorAlpha = color.getAlpha();\r\n opacity = isNaN(parseFloat(opacity)) ? 1 : parseFloat(opacity);\r\n opacity *= colorAlpha * multiplier;\r\n\r\n return {\r\n offset: offset,\r\n color: color.toRgb(),\r\n opacity: opacity\r\n };\r\n }\r\n\r\n function getLinearCoords(el) {\r\n return {\r\n x1: el.getAttribute('x1') || 0,\r\n y1: el.getAttribute('y1') || 0,\r\n x2: el.getAttribute('x2') || '100%',\r\n y2: el.getAttribute('y2') || 0\r\n };\r\n }\r\n\r\n function getRadialCoords(el) {\r\n return {\r\n x1: el.getAttribute('fx') || el.getAttribute('cx') || '50%',\r\n y1: el.getAttribute('fy') || el.getAttribute('cy') || '50%',\r\n r1: 0,\r\n x2: el.getAttribute('cx') || '50%',\r\n y2: el.getAttribute('cy') || '50%',\r\n r2: el.getAttribute('r') || '50%'\r\n };\r\n }\r\n /* _FROM_SVG_END_ */\r\n\r\n var clone = fabric.util.object.clone;\r\n\r\n /**\r\n * Gradient class\r\n * @class fabric.Gradient\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#gradients}\r\n * @see {@link fabric.Gradient#initialize} for constructor definition\r\n */\r\n fabric.Gradient = fabric.util.createClass(/** @lends fabric.Gradient.prototype */ {\r\n\r\n /**\r\n * Horizontal offset for aligning gradients coming from SVG when outside pathgroups\r\n * @type Number\r\n * @default 0\r\n */\r\n offsetX: 0,\r\n\r\n /**\r\n * Vertical offset for aligning gradients coming from SVG when outside pathgroups\r\n * @type Number\r\n * @default 0\r\n */\r\n offsetY: 0,\r\n\r\n /**\r\n * A transform matrix to apply to the gradient before painting.\r\n * Imported from svg gradients, is not applied with the current transform in the center.\r\n * Before this transform is applied, the origin point is at the top left corner of the object\r\n * plus the addition of offsetY and offsetX.\r\n * @type Number[]\r\n * @default null\r\n */\r\n gradientTransform: null,\r\n\r\n /**\r\n * coordinates units for coords.\r\n * If `pixels`, the number of coords are in the same unit of width / height.\r\n * If set as `percentage` the coords are still a number, but 1 means 100% of width\r\n * for the X and 100% of the height for the y. It can be bigger than 1 and negative.\r\n * allowed values pixels or percentage.\r\n * @type String\r\n * @default 'pixels'\r\n */\r\n gradientUnits: 'pixels',\r\n\r\n /**\r\n * Gradient type linear or radial\r\n * @type String\r\n * @default 'pixels'\r\n */\r\n type: 'linear',\r\n\r\n /**\r\n * Constructor\r\n * @param {Object} options Options object with type, coords, gradientUnits and colorStops\r\n * @param {Object} [options.type] gradient type linear or radial\r\n * @param {Object} [options.gradientUnits] gradient units\r\n * @param {Object} [options.offsetX] SVG import compatibility\r\n * @param {Object} [options.offsetY] SVG import compatibility\r\n * @param {Object[]} options.colorStops contains the colorstops.\r\n * @param {Object} options.coords contains the coords of the gradient\r\n * @param {Number} [options.coords.x1] X coordiante of the first point for linear or of the focal point for radial\r\n * @param {Number} [options.coords.y1] Y coordiante of the first point for linear or of the focal point for radial\r\n * @param {Number} [options.coords.x2] X coordiante of the second point for linear or of the center point for radial\r\n * @param {Number} [options.coords.y2] Y coordiante of the second point for linear or of the center point for radial\r\n * @param {Number} [options.coords.r1] only for radial gradient, radius of the inner circle\r\n * @param {Number} [options.coords.r2] only for radial gradient, radius of the external circle\r\n * @return {fabric.Gradient} thisArg\r\n */\r\n initialize: function(options) {\r\n options || (options = { });\r\n options.coords || (options.coords = { });\r\n\r\n var coords, _this = this;\r\n\r\n // sets everything, then coords and colorstops get sets again\r\n Object.keys(options).forEach(function(option) {\r\n _this[option] = options[option];\r\n });\r\n\r\n if (this.id) {\r\n this.id += '_' + fabric.Object.__uid++;\r\n }\r\n else {\r\n this.id = fabric.Object.__uid++;\r\n }\r\n\r\n coords = {\r\n x1: options.coords.x1 || 0,\r\n y1: options.coords.y1 || 0,\r\n x2: options.coords.x2 || 0,\r\n y2: options.coords.y2 || 0\r\n };\r\n\r\n if (this.type === 'radial') {\r\n coords.r1 = options.coords.r1 || 0;\r\n coords.r2 = options.coords.r2 || 0;\r\n }\r\n\r\n this.coords = coords;\r\n this.colorStops = options.colorStops.slice();\r\n },\r\n\r\n /**\r\n * Adds another colorStop\r\n * @param {Object} colorStop Object with offset and color\r\n * @return {fabric.Gradient} thisArg\r\n */\r\n addColorStop: function(colorStops) {\r\n for (var position in colorStops) {\r\n var color = new fabric.Color(colorStops[position]);\r\n this.colorStops.push({\r\n offset: parseFloat(position),\r\n color: color.toRgb(),\r\n opacity: color.getAlpha()\r\n });\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Returns object representation of a gradient\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object}\r\n */\r\n toObject: function(propertiesToInclude) {\r\n var object = {\r\n type: this.type,\r\n coords: this.coords,\r\n colorStops: this.colorStops,\r\n offsetX: this.offsetX,\r\n offsetY: this.offsetY,\r\n gradientUnits: this.gradientUnits,\r\n gradientTransform: this.gradientTransform ? this.gradientTransform.concat() : this.gradientTransform\r\n };\r\n fabric.util.populateWithProperties(this, object, propertiesToInclude);\r\n\r\n return object;\r\n },\r\n\r\n /* _TO_SVG_START_ */\r\n /**\r\n * Returns SVG representation of an gradient\r\n * @param {Object} object Object to create a gradient for\r\n * @return {String} SVG representation of an gradient (linear/radial)\r\n */\r\n toSVG: function(object, options) {\r\n var coords = clone(this.coords, true), i, len, options = options || {},\r\n markup, commonAttributes, colorStops = clone(this.colorStops, true),\r\n needsSwap = coords.r1 > coords.r2,\r\n transform = this.gradientTransform ? this.gradientTransform.concat() : fabric.iMatrix.concat(),\r\n offsetX = -this.offsetX, offsetY = -this.offsetY,\r\n withViewport = !!options.additionalTransform,\r\n gradientUnits = this.gradientUnits === 'pixels' ? 'userSpaceOnUse' : 'objectBoundingBox';\r\n // colorStops must be sorted ascending\r\n colorStops.sort(function(a, b) {\r\n return a.offset - b.offset;\r\n });\r\n\r\n if (gradientUnits === 'objectBoundingBox') {\r\n offsetX /= object.width;\r\n offsetY /= object.height;\r\n }\r\n else {\r\n offsetX += object.width / 2;\r\n offsetY += object.height / 2;\r\n }\r\n if (object.type === 'path' && this.gradientUnits !== 'percentage') {\r\n offsetX -= object.pathOffset.x;\r\n offsetY -= object.pathOffset.y;\r\n }\r\n\r\n\r\n transform[4] -= offsetX;\r\n transform[5] -= offsetY;\r\n\r\n commonAttributes = 'id=\"SVGID_' + this.id +\r\n '\" gradientUnits=\"' + gradientUnits + '\"';\r\n commonAttributes += ' gradientTransform=\"' + (withViewport ?\r\n options.additionalTransform + ' ' : '') + fabric.util.matrixToSVG(transform) + '\" ';\r\n\r\n if (this.type === 'linear') {\r\n markup = [\r\n '\\n'\r\n ];\r\n }\r\n else if (this.type === 'radial') {\r\n // svg radial gradient has just 1 radius. the biggest.\r\n markup = [\r\n '\\n'\r\n ];\r\n }\r\n\r\n if (this.type === 'radial') {\r\n if (needsSwap) {\r\n // svg goes from internal to external radius. if radius are inverted, swap color stops.\r\n colorStops = colorStops.concat();\r\n colorStops.reverse();\r\n for (i = 0, len = colorStops.length; i < len; i++) {\r\n colorStops[i].offset = 1 - colorStops[i].offset;\r\n }\r\n }\r\n var minRadius = Math.min(coords.r1, coords.r2);\r\n if (minRadius > 0) {\r\n // i have to shift all colorStops and add new one in 0.\r\n var maxRadius = Math.max(coords.r1, coords.r2),\r\n percentageShift = minRadius / maxRadius;\r\n for (i = 0, len = colorStops.length; i < len; i++) {\r\n colorStops[i].offset += percentageShift * (1 - colorStops[i].offset);\r\n }\r\n }\r\n }\r\n\r\n for (i = 0, len = colorStops.length; i < len; i++) {\r\n var colorStop = colorStops[i];\r\n markup.push(\r\n '\\n'\r\n );\r\n }\r\n\r\n markup.push((this.type === 'linear' ? '\\n' : '\\n'));\r\n\r\n return markup.join('');\r\n },\r\n /* _TO_SVG_END_ */\r\n\r\n /**\r\n * Returns an instance of CanvasGradient\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @return {CanvasGradient}\r\n */\r\n toLive: function(ctx) {\r\n var gradient, coords = fabric.util.object.clone(this.coords), i, len;\r\n\r\n if (!this.type) {\r\n return;\r\n }\r\n\r\n if (this.type === 'linear') {\r\n gradient = ctx.createLinearGradient(\r\n coords.x1, coords.y1, coords.x2, coords.y2);\r\n }\r\n else if (this.type === 'radial') {\r\n gradient = ctx.createRadialGradient(\r\n coords.x1, coords.y1, coords.r1, coords.x2, coords.y2, coords.r2);\r\n }\r\n\r\n for (i = 0, len = this.colorStops.length; i < len; i++) {\r\n var color = this.colorStops[i].color,\r\n opacity = this.colorStops[i].opacity,\r\n offset = this.colorStops[i].offset;\r\n\r\n if (typeof opacity !== 'undefined') {\r\n color = new fabric.Color(color).setAlpha(opacity).toRgba();\r\n }\r\n gradient.addColorStop(offset, color);\r\n }\r\n\r\n return gradient;\r\n }\r\n });\r\n\r\n fabric.util.object.extend(fabric.Gradient, {\r\n\r\n /* _FROM_SVG_START_ */\r\n /**\r\n * Returns {@link fabric.Gradient} instance from an SVG element\r\n * @static\r\n * @memberOf fabric.Gradient\r\n * @param {SVGGradientElement} el SVG gradient element\r\n * @param {fabric.Object} instance\r\n * @param {String} opacityAttr A fill-opacity or stroke-opacity attribute to multiply to each stop's opacity.\r\n * @param {Object} svgOptions an object containing the size of the SVG in order to parse correctly gradients\r\n * that uses gradientUnits as 'userSpaceOnUse' and percentages.\r\n * @param {Object.number} viewBoxWidth width part of the viewBox attribute on svg\r\n * @param {Object.number} viewBoxHeight height part of the viewBox attribute on svg\r\n * @param {Object.number} width width part of the svg tag if viewBox is not specified\r\n * @param {Object.number} height height part of the svg tag if viewBox is not specified\r\n * @return {fabric.Gradient} Gradient instance\r\n * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement\r\n * @see http://www.w3.org/TR/SVG/pservers.html#RadialGradientElement\r\n */\r\n fromElement: function(el, instance, opacityAttr, svgOptions) {\r\n /**\r\n * @example:\r\n *\r\n * \r\n * \r\n * \r\n * \r\n *\r\n * OR\r\n *\r\n * \r\n * \r\n * \r\n * \r\n *\r\n * OR\r\n *\r\n * \r\n * \r\n * \r\n * \r\n * \r\n *\r\n * OR\r\n *\r\n * \r\n * \r\n * \r\n * \r\n * \r\n *\r\n */\r\n\r\n var multiplier = parseFloat(opacityAttr) / (/%$/.test(opacityAttr) ? 100 : 1);\r\n multiplier = multiplier < 0 ? 0 : multiplier > 1 ? 1 : multiplier;\r\n if (isNaN(multiplier)) {\r\n multiplier = 1;\r\n }\r\n\r\n var colorStopEls = el.getElementsByTagName('stop'),\r\n type,\r\n gradientUnits = el.getAttribute('gradientUnits') === 'userSpaceOnUse' ?\r\n 'pixels' : 'percentage',\r\n gradientTransform = el.getAttribute('gradientTransform') || '',\r\n colorStops = [],\r\n coords, i, offsetX = 0, offsetY = 0,\r\n transformMatrix;\r\n if (el.nodeName === 'linearGradient' || el.nodeName === 'LINEARGRADIENT') {\r\n type = 'linear';\r\n coords = getLinearCoords(el);\r\n }\r\n else {\r\n type = 'radial';\r\n coords = getRadialCoords(el);\r\n }\r\n\r\n for (i = colorStopEls.length; i--; ) {\r\n colorStops.push(getColorStop(colorStopEls[i], multiplier));\r\n }\r\n\r\n transformMatrix = fabric.parseTransformAttribute(gradientTransform);\r\n\r\n __convertPercentUnitsToValues(instance, coords, svgOptions, gradientUnits);\r\n\r\n if (gradientUnits === 'pixels') {\r\n offsetX = -instance.left;\r\n offsetY = -instance.top;\r\n }\r\n\r\n var gradient = new fabric.Gradient({\r\n id: el.getAttribute('id'),\r\n type: type,\r\n coords: coords,\r\n colorStops: colorStops,\r\n gradientUnits: gradientUnits,\r\n gradientTransform: transformMatrix,\r\n offsetX: offsetX,\r\n offsetY: offsetY,\r\n });\r\n\r\n return gradient;\r\n }\r\n /* _FROM_SVG_END_ */\r\n });\r\n\r\n /**\r\n * @private\r\n */\r\n function __convertPercentUnitsToValues(instance, options, svgOptions, gradientUnits) {\r\n var propValue, finalValue;\r\n Object.keys(options).forEach(function(prop) {\r\n propValue = options[prop];\r\n if (propValue === 'Infinity') {\r\n finalValue = 1;\r\n }\r\n else if (propValue === '-Infinity') {\r\n finalValue = 0;\r\n }\r\n else {\r\n finalValue = parseFloat(options[prop], 10);\r\n if (typeof propValue === 'string' && /^(\\d+\\.\\d+)%|(\\d+)%$/.test(propValue)) {\r\n finalValue *= 0.01;\r\n if (gradientUnits === 'pixels') {\r\n // then we need to fix those percentages here in svg parsing\r\n if (prop === 'x1' || prop === 'x2' || prop === 'r2') {\r\n finalValue *= svgOptions.viewBoxWidth || svgOptions.width;\r\n }\r\n if (prop === 'y1' || prop === 'y2') {\r\n finalValue *= svgOptions.viewBoxHeight || svgOptions.height;\r\n }\r\n }\r\n }\r\n }\r\n options[prop] = finalValue;\r\n });\r\n }\r\n})();\r\n\r\n\r\n(function() {\r\n\r\n 'use strict';\r\n\r\n var toFixed = fabric.util.toFixed;\r\n\r\n /**\r\n * Pattern class\r\n * @class fabric.Pattern\r\n * @see {@link http://fabricjs.com/patterns|Pattern demo}\r\n * @see {@link http://fabricjs.com/dynamic-patterns|DynamicPattern demo}\r\n * @see {@link fabric.Pattern#initialize} for constructor definition\r\n */\r\n\r\n\r\n fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ {\r\n\r\n /**\r\n * Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat)\r\n * @type String\r\n * @default\r\n */\r\n repeat: 'repeat',\r\n\r\n /**\r\n * Pattern horizontal offset from object's left/top corner\r\n * @type Number\r\n * @default\r\n */\r\n offsetX: 0,\r\n\r\n /**\r\n * Pattern vertical offset from object's left/top corner\r\n * @type Number\r\n * @default\r\n */\r\n offsetY: 0,\r\n\r\n /**\r\n * crossOrigin value (one of \"\", \"anonymous\", \"use-credentials\")\r\n * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes\r\n * @type String\r\n * @default\r\n */\r\n crossOrigin: '',\r\n\r\n /**\r\n * transform matrix to change the pattern, imported from svgs.\r\n * @type Array\r\n * @default\r\n */\r\n patternTransform: null,\r\n\r\n /**\r\n * Constructor\r\n * @param {Object} [options] Options object\r\n * @param {Function} [callback] function to invoke after callback init.\r\n * @return {fabric.Pattern} thisArg\r\n */\r\n initialize: function(options, callback) {\r\n options || (options = { });\r\n\r\n this.id = fabric.Object.__uid++;\r\n this.setOptions(options);\r\n if (!options.source || (options.source && typeof options.source !== 'string')) {\r\n callback && callback(this);\r\n return;\r\n }\r\n else {\r\n // img src string\r\n var _this = this;\r\n this.source = fabric.util.createImage();\r\n fabric.util.loadImage(options.source, function(img, isError) {\r\n _this.source = img;\r\n callback && callback(_this, isError);\r\n }, null, this.crossOrigin);\r\n }\r\n },\r\n\r\n /**\r\n * Returns object representation of a pattern\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} Object representation of a pattern instance\r\n */\r\n toObject: function(propertiesToInclude) {\r\n var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\r\n source, object;\r\n\r\n // element\r\n if (typeof this.source.src === 'string') {\r\n source = this.source.src;\r\n }\r\n // element\r\n else if (typeof this.source === 'object' && this.source.toDataURL) {\r\n source = this.source.toDataURL();\r\n }\r\n\r\n object = {\r\n type: 'pattern',\r\n source: source,\r\n repeat: this.repeat,\r\n crossOrigin: this.crossOrigin,\r\n offsetX: toFixed(this.offsetX, NUM_FRACTION_DIGITS),\r\n offsetY: toFixed(this.offsetY, NUM_FRACTION_DIGITS),\r\n patternTransform: this.patternTransform ? this.patternTransform.concat() : null\r\n };\r\n fabric.util.populateWithProperties(this, object, propertiesToInclude);\r\n\r\n return object;\r\n },\r\n\r\n /* _TO_SVG_START_ */\r\n /**\r\n * Returns SVG representation of a pattern\r\n * @param {fabric.Object} object\r\n * @return {String} SVG representation of a pattern\r\n */\r\n toSVG: function(object) {\r\n var patternSource = typeof this.source === 'function' ? this.source() : this.source,\r\n patternWidth = patternSource.width / object.width,\r\n patternHeight = patternSource.height / object.height,\r\n patternOffsetX = this.offsetX / object.width,\r\n patternOffsetY = this.offsetY / object.height,\r\n patternImgSrc = '';\r\n if (this.repeat === 'repeat-x' || this.repeat === 'no-repeat') {\r\n patternHeight = 1;\r\n if (patternOffsetY) {\r\n patternHeight += Math.abs(patternOffsetY);\r\n }\r\n }\r\n if (this.repeat === 'repeat-y' || this.repeat === 'no-repeat') {\r\n patternWidth = 1;\r\n if (patternOffsetX) {\r\n patternWidth += Math.abs(patternOffsetX);\r\n }\r\n\r\n }\r\n if (patternSource.src) {\r\n patternImgSrc = patternSource.src;\r\n }\r\n else if (patternSource.toDataURL) {\r\n patternImgSrc = patternSource.toDataURL();\r\n }\r\n\r\n return '\\n' +\r\n '\\n' +\r\n '\\n';\r\n },\r\n /* _TO_SVG_END_ */\r\n\r\n setOptions: function(options) {\r\n for (var prop in options) {\r\n this[prop] = options[prop];\r\n }\r\n },\r\n\r\n /**\r\n * Returns an instance of CanvasPattern\r\n * @param {CanvasRenderingContext2D} ctx Context to create pattern\r\n * @return {CanvasPattern}\r\n */\r\n toLive: function(ctx) {\r\n var source = this.source;\r\n // if the image failed to load, return, and allow rest to continue loading\r\n if (!source) {\r\n return '';\r\n }\r\n\r\n // if an image\r\n if (typeof source.src !== 'undefined') {\r\n if (!source.complete) {\r\n return '';\r\n }\r\n if (source.naturalWidth === 0 || source.naturalHeight === 0) {\r\n return '';\r\n }\r\n }\r\n return ctx.createPattern(source, this.repeat);\r\n }\r\n });\r\n})();\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n toFixed = fabric.util.toFixed;\r\n\r\n if (fabric.Shadow) {\r\n fabric.warn('fabric.Shadow is already defined.');\r\n return;\r\n }\r\n\r\n /**\r\n * Shadow class\r\n * @class fabric.Shadow\r\n * @see {@link http://fabricjs.com/shadows|Shadow demo}\r\n * @see {@link fabric.Shadow#initialize} for constructor definition\r\n */\r\n fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ {\r\n\r\n /**\r\n * Shadow color\r\n * @type String\r\n * @default\r\n */\r\n color: 'rgb(0,0,0)',\r\n\r\n /**\r\n * Shadow blur\r\n * @type Number\r\n */\r\n blur: 0,\r\n\r\n /**\r\n * Shadow horizontal offset\r\n * @type Number\r\n * @default\r\n */\r\n offsetX: 0,\r\n\r\n /**\r\n * Shadow vertical offset\r\n * @type Number\r\n * @default\r\n */\r\n offsetY: 0,\r\n\r\n /**\r\n * Whether the shadow should affect stroke operations\r\n * @type Boolean\r\n * @default\r\n */\r\n affectStroke: false,\r\n\r\n /**\r\n * Indicates whether toObject should include default values\r\n * @type Boolean\r\n * @default\r\n */\r\n includeDefaultValues: true,\r\n\r\n /**\r\n * When `false`, the shadow will scale with the object.\r\n * When `true`, the shadow's offsetX, offsetY, and blur will not be affected by the object's scale.\r\n * default to false\r\n * @type Boolean\r\n * @default\r\n */\r\n nonScaling: false,\r\n\r\n /**\r\n * Constructor\r\n * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetY properties or string (e.g. \"rgba(0,0,0,0.2) 2px 2px 10px\")\r\n * @return {fabric.Shadow} thisArg\r\n */\r\n initialize: function(options) {\r\n\r\n if (typeof options === 'string') {\r\n options = this._parseShadow(options);\r\n }\r\n\r\n for (var prop in options) {\r\n this[prop] = options[prop];\r\n }\r\n\r\n this.id = fabric.Object.__uid++;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {String} shadow Shadow value to parse\r\n * @return {Object} Shadow object with color, offsetX, offsetY and blur\r\n */\r\n _parseShadow: function(shadow) {\r\n var shadowStr = shadow.trim(),\r\n offsetsAndBlur = fabric.Shadow.reOffsetsAndBlur.exec(shadowStr) || [],\r\n color = shadowStr.replace(fabric.Shadow.reOffsetsAndBlur, '') || 'rgb(0,0,0)';\r\n\r\n return {\r\n color: color.trim(),\r\n offsetX: parseFloat(offsetsAndBlur[1], 10) || 0,\r\n offsetY: parseFloat(offsetsAndBlur[2], 10) || 0,\r\n blur: parseFloat(offsetsAndBlur[3], 10) || 0\r\n };\r\n },\r\n\r\n /**\r\n * Returns a string representation of an instance\r\n * @see http://www.w3.org/TR/css-text-decor-3/#text-shadow\r\n * @return {String} Returns CSS3 text-shadow declaration\r\n */\r\n toString: function() {\r\n return [this.offsetX, this.offsetY, this.blur, this.color].join('px ');\r\n },\r\n\r\n /* _TO_SVG_START_ */\r\n /**\r\n * Returns SVG representation of a shadow\r\n * @param {fabric.Object} object\r\n * @return {String} SVG representation of a shadow\r\n */\r\n toSVG: function(object) {\r\n var fBoxX = 40, fBoxY = 40, NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\r\n offset = fabric.util.rotateVector(\r\n { x: this.offsetX, y: this.offsetY },\r\n fabric.util.degreesToRadians(-object.angle)),\r\n BLUR_BOX = 20, color = new fabric.Color(this.color);\r\n\r\n if (object.width && object.height) {\r\n //http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion\r\n // we add some extra space to filter box to contain the blur ( 20 )\r\n fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;\r\n fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;\r\n }\r\n if (object.flipX) {\r\n offset.x *= -1;\r\n }\r\n if (object.flipY) {\r\n offset.y *= -1;\r\n }\r\n\r\n return (\r\n '\\n' +\r\n '\\t\\n' +\r\n '\\t\\n' +\r\n '\\t\\n' +\r\n '\\t\\n' +\r\n '\\t\\n' +\r\n '\\t\\t\\n' +\r\n '\\t\\t\\n' +\r\n '\\t\\n' +\r\n '\\n');\r\n },\r\n /* _TO_SVG_END_ */\r\n\r\n /**\r\n * Returns object representation of a shadow\r\n * @return {Object} Object representation of a shadow instance\r\n */\r\n toObject: function() {\r\n if (this.includeDefaultValues) {\r\n return {\r\n color: this.color,\r\n blur: this.blur,\r\n offsetX: this.offsetX,\r\n offsetY: this.offsetY,\r\n affectStroke: this.affectStroke,\r\n nonScaling: this.nonScaling\r\n };\r\n }\r\n var obj = { }, proto = fabric.Shadow.prototype;\r\n\r\n ['color', 'blur', 'offsetX', 'offsetY', 'affectStroke', 'nonScaling'].forEach(function(prop) {\r\n if (this[prop] !== proto[prop]) {\r\n obj[prop] = this[prop];\r\n }\r\n }, this);\r\n\r\n return obj;\r\n }\r\n });\r\n\r\n /**\r\n * Regex matching shadow offsetX, offsetY and blur (ex: \"2px 2px 10px rgba(0,0,0,0.2)\", \"rgb(0,255,0) 2px 2px\")\r\n * @static\r\n * @field\r\n * @memberOf fabric.Shadow\r\n */\r\n // eslint-disable-next-line max-len\r\n fabric.Shadow.reOffsetsAndBlur = /(?:\\s|^)(-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?(-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?(\\d+(?:\\.\\d*)?(?:px)?)?(?:\\s?|$)(?:$|\\s)/;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function () {\r\n\r\n 'use strict';\r\n\r\n if (fabric.StaticCanvas) {\r\n fabric.warn('fabric.StaticCanvas is already defined.');\r\n return;\r\n }\r\n\r\n // aliases for faster resolution\r\n var extend = fabric.util.object.extend,\r\n getElementOffset = fabric.util.getElementOffset,\r\n removeFromArray = fabric.util.removeFromArray,\r\n toFixed = fabric.util.toFixed,\r\n transformPoint = fabric.util.transformPoint,\r\n invertTransform = fabric.util.invertTransform,\r\n getNodeCanvas = fabric.util.getNodeCanvas,\r\n createCanvasElement = fabric.util.createCanvasElement,\r\n\r\n CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element');\r\n\r\n /**\r\n * Static canvas class\r\n * @class fabric.StaticCanvas\r\n * @mixes fabric.Collection\r\n * @mixes fabric.Observable\r\n * @see {@link http://fabricjs.com/static_canvas|StaticCanvas demo}\r\n * @see {@link fabric.StaticCanvas#initialize} for constructor definition\r\n * @fires before:render\r\n * @fires after:render\r\n * @fires canvas:cleared\r\n * @fires object:added\r\n * @fires object:removed\r\n */\r\n fabric.StaticCanvas = fabric.util.createClass(fabric.CommonMethods, /** @lends fabric.StaticCanvas.prototype */ {\r\n\r\n /**\r\n * Constructor\r\n * @param {HTMLElement | String} el <canvas> element to initialize instance on\r\n * @param {Object} [options] Options object\r\n * @return {Object} thisArg\r\n */\r\n initialize: function(el, options) {\r\n options || (options = { });\r\n this.renderAndResetBound = this.renderAndReset.bind(this);\r\n this.requestRenderAllBound = this.requestRenderAll.bind(this);\r\n this._initStatic(el, options);\r\n },\r\n\r\n /**\r\n * Background color of canvas instance.\r\n * Should be set via {@link fabric.StaticCanvas#setBackgroundColor}.\r\n * @type {(String|fabric.Pattern)}\r\n * @default\r\n */\r\n backgroundColor: '',\r\n\r\n /**\r\n * Background image of canvas instance.\r\n * since 2.4.0 image caching is active, please when putting an image as background, add to the\r\n * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom\r\n * vale. As an alternative you can disable image objectCaching\r\n * @type fabric.Image\r\n * @default\r\n */\r\n backgroundImage: null,\r\n\r\n /**\r\n * Overlay color of canvas instance.\r\n * Should be set via {@link fabric.StaticCanvas#setOverlayColor}\r\n * @since 1.3.9\r\n * @type {(String|fabric.Pattern)}\r\n * @default\r\n */\r\n overlayColor: '',\r\n\r\n /**\r\n * Overlay image of canvas instance.\r\n * since 2.4.0 image caching is active, please when putting an image as overlay, add to the\r\n * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom\r\n * vale. As an alternative you can disable image objectCaching\r\n * @type fabric.Image\r\n * @default\r\n */\r\n overlayImage: null,\r\n\r\n /**\r\n * Indicates whether toObject/toDatalessObject should include default values\r\n * if set to false, takes precedence over the object value.\r\n * @type Boolean\r\n * @default\r\n */\r\n includeDefaultValues: true,\r\n\r\n /**\r\n * Indicates whether objects' state should be saved\r\n * @type Boolean\r\n * @default\r\n */\r\n stateful: false,\r\n\r\n /**\r\n * Indicates whether {@link fabric.Collection.add}, {@link fabric.Collection.insertAt} and {@link fabric.Collection.remove},\r\n * {@link fabric.StaticCanvas.moveTo}, {@link fabric.StaticCanvas.clear} and many more, should also re-render canvas.\r\n * Disabling this option will not give a performance boost when adding/removing a lot of objects to/from canvas at once\r\n * since the renders are quequed and executed one per frame.\r\n * Disabling is suggested anyway and managing the renders of the app manually is not a big effort ( canvas.requestRenderAll() )\r\n * Left default to true to do not break documentation and old app, fiddles.\r\n * @type Boolean\r\n * @default\r\n */\r\n renderOnAddRemove: true,\r\n\r\n /**\r\n * Indicates whether object controls (borders/controls) are rendered above overlay image\r\n * @type Boolean\r\n * @default\r\n */\r\n controlsAboveOverlay: false,\r\n\r\n /**\r\n * Indicates whether the browser can be scrolled when using a touchscreen and dragging on the canvas\r\n * @type Boolean\r\n * @default\r\n */\r\n allowTouchScrolling: false,\r\n\r\n /**\r\n * Indicates whether this canvas will use image smoothing, this is on by default in browsers\r\n * @type Boolean\r\n * @default\r\n */\r\n imageSmoothingEnabled: true,\r\n\r\n /**\r\n * The transformation (a Canvas 2D API transform matrix) which focuses the viewport\r\n * @type Array\r\n * @example Default transform\r\n * canvas.viewportTransform = [1, 0, 0, 1, 0, 0];\r\n * @example Scale by 70% and translate toward bottom-right by 50, without skewing\r\n * canvas.viewportTransform = [0.7, 0, 0, 0.7, 50, 50];\r\n * @default\r\n */\r\n viewportTransform: fabric.iMatrix.concat(),\r\n\r\n /**\r\n * if set to false background image is not affected by viewport transform\r\n * @since 1.6.3\r\n * @type Boolean\r\n * @default\r\n */\r\n backgroundVpt: true,\r\n\r\n /**\r\n * if set to false overlya image is not affected by viewport transform\r\n * @since 1.6.3\r\n * @type Boolean\r\n * @default\r\n */\r\n overlayVpt: true,\r\n\r\n /**\r\n * When true, canvas is scaled by devicePixelRatio for better rendering on retina screens\r\n * @type Boolean\r\n * @default\r\n */\r\n enableRetinaScaling: true,\r\n\r\n /**\r\n * Describe canvas element extension over design\r\n * properties are tl,tr,bl,br.\r\n * if canvas is not zoomed/panned those points are the four corner of canvas\r\n * if canvas is viewportTransformed you those points indicate the extension\r\n * of canvas element in plain untrasformed coordinates\r\n * The coordinates get updated with @method calcViewportBoundaries.\r\n * @memberOf fabric.StaticCanvas.prototype\r\n */\r\n vptCoords: { },\r\n\r\n /**\r\n * Based on vptCoords and object.aCoords, skip rendering of objects that\r\n * are not included in current viewport.\r\n * May greatly help in applications with crowded canvas and use of zoom/pan\r\n * If One of the corner of the bounding box of the object is on the canvas\r\n * the objects get rendered.\r\n * @memberOf fabric.StaticCanvas.prototype\r\n * @type Boolean\r\n * @default\r\n */\r\n skipOffscreen: true,\r\n\r\n /**\r\n * a fabricObject that, without stroke define a clipping area with their shape. filled in black\r\n * the clipPath object gets used when the canvas has rendered, and the context is placed in the\r\n * top left corner of the canvas.\r\n * clipPath will clip away controls, if you do not want this to happen use controlsAboveOverlay = true\r\n * @type fabric.Object\r\n */\r\n clipPath: undefined,\r\n\r\n /**\r\n * @private\r\n * @param {HTMLElement | String} el <canvas> element to initialize instance on\r\n * @param {Object} [options] Options object\r\n */\r\n _initStatic: function(el, options) {\r\n var cb = this.requestRenderAllBound;\r\n this._objects = [];\r\n this._createLowerCanvas(el);\r\n this._initOptions(options);\r\n // only initialize retina scaling once\r\n if (!this.interactive) {\r\n this._initRetinaScaling();\r\n }\r\n\r\n if (options.overlayImage) {\r\n this.setOverlayImage(options.overlayImage, cb);\r\n }\r\n if (options.backgroundImage) {\r\n this.setBackgroundImage(options.backgroundImage, cb);\r\n }\r\n if (options.backgroundColor) {\r\n this.setBackgroundColor(options.backgroundColor, cb);\r\n }\r\n if (options.overlayColor) {\r\n this.setOverlayColor(options.overlayColor, cb);\r\n }\r\n this.calcOffset();\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _isRetinaScaling: function() {\r\n return (fabric.devicePixelRatio > 1 && this.enableRetinaScaling);\r\n },\r\n\r\n /**\r\n * @private\r\n * @return {Number} retinaScaling if applied, otherwise 1;\r\n */\r\n getRetinaScaling: function() {\r\n return this._isRetinaScaling() ? Math.max(1, fabric.devicePixelRatio) : 1;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _initRetinaScaling: function() {\r\n if (!this._isRetinaScaling()) {\r\n return;\r\n }\r\n var scaleRatio = fabric.devicePixelRatio;\r\n this.__initRetinaScaling(scaleRatio, this.lowerCanvasEl, this.contextContainer);\r\n if (this.upperCanvasEl) {\r\n this.__initRetinaScaling(scaleRatio, this.upperCanvasEl, this.contextTop);\r\n }\r\n },\r\n\r\n __initRetinaScaling: function(scaleRatio, canvas, context) {\r\n canvas.setAttribute('width', this.width * scaleRatio);\r\n canvas.setAttribute('height', this.height * scaleRatio);\r\n context.scale(scaleRatio, scaleRatio);\r\n },\r\n\r\n\r\n /**\r\n * Calculates canvas element offset relative to the document\r\n * This method is also attached as \"resize\" event handler of window\r\n * @return {fabric.Canvas} instance\r\n * @chainable\r\n */\r\n calcOffset: function () {\r\n this._offset = getElementOffset(this.lowerCanvasEl);\r\n return this;\r\n },\r\n\r\n /**\r\n * Sets {@link fabric.StaticCanvas#overlayImage|overlay image} for this canvas\r\n * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set overlay to\r\n * @param {Function} callback callback to invoke when image is loaded and set as an overlay\r\n * @param {Object} [options] Optional options to set for the {@link fabric.Image|overlay image}.\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n * @see {@link http://jsfiddle.net/fabricjs/MnzHT/|jsFiddle demo}\r\n * @example Normal overlayImage with left/top = 0\r\n * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\r\n * // Needed to position overlayImage at 0/0\r\n * originX: 'left',\r\n * originY: 'top'\r\n * });\r\n * @example overlayImage with different properties\r\n * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\r\n * opacity: 0.5,\r\n * angle: 45,\r\n * left: 400,\r\n * top: 400,\r\n * originX: 'left',\r\n * originY: 'top'\r\n * });\r\n * @example Stretched overlayImage #1 - width/height correspond to canvas width/height\r\n * fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img, isError) {\r\n * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'});\r\n * canvas.setOverlayImage(img, canvas.renderAll.bind(canvas));\r\n * });\r\n * @example Stretched overlayImage #2 - width/height correspond to canvas width/height\r\n * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\r\n * width: canvas.width,\r\n * height: canvas.height,\r\n * // Needed to position overlayImage at 0/0\r\n * originX: 'left',\r\n * originY: 'top'\r\n * });\r\n * @example overlayImage loaded from cross-origin\r\n * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\r\n * opacity: 0.5,\r\n * angle: 45,\r\n * left: 400,\r\n * top: 400,\r\n * originX: 'left',\r\n * originY: 'top',\r\n * crossOrigin: 'anonymous'\r\n * });\r\n */\r\n setOverlayImage: function (image, callback, options) {\r\n return this.__setBgOverlayImage('overlayImage', image, callback, options);\r\n },\r\n\r\n /**\r\n * Sets {@link fabric.StaticCanvas#backgroundImage|background image} for this canvas\r\n * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set background to\r\n * @param {Function} callback Callback to invoke when image is loaded and set as background\r\n * @param {Object} [options] Optional options to set for the {@link fabric.Image|background image}.\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n * @see {@link http://jsfiddle.net/djnr8o7a/28/|jsFiddle demo}\r\n * @example Normal backgroundImage with left/top = 0\r\n * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\r\n * // Needed to position backgroundImage at 0/0\r\n * originX: 'left',\r\n * originY: 'top'\r\n * });\r\n * @example backgroundImage with different properties\r\n * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\r\n * opacity: 0.5,\r\n * angle: 45,\r\n * left: 400,\r\n * top: 400,\r\n * originX: 'left',\r\n * originY: 'top'\r\n * });\r\n * @example Stretched backgroundImage #1 - width/height correspond to canvas width/height\r\n * fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img, isError) {\r\n * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'});\r\n * canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas));\r\n * });\r\n * @example Stretched backgroundImage #2 - width/height correspond to canvas width/height\r\n * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\r\n * width: canvas.width,\r\n * height: canvas.height,\r\n * // Needed to position backgroundImage at 0/0\r\n * originX: 'left',\r\n * originY: 'top'\r\n * });\r\n * @example backgroundImage loaded from cross-origin\r\n * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\r\n * opacity: 0.5,\r\n * angle: 45,\r\n * left: 400,\r\n * top: 400,\r\n * originX: 'left',\r\n * originY: 'top',\r\n * crossOrigin: 'anonymous'\r\n * });\r\n */\r\n // TODO: fix stretched examples\r\n setBackgroundImage: function (image, callback, options) {\r\n return this.__setBgOverlayImage('backgroundImage', image, callback, options);\r\n },\r\n\r\n /**\r\n * Sets {@link fabric.StaticCanvas#overlayColor|foreground color} for this canvas\r\n * @param {(String|fabric.Pattern)} overlayColor Color or pattern to set foreground color to\r\n * @param {Function} callback Callback to invoke when foreground color is set\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n * @see {@link http://jsfiddle.net/fabricjs/pB55h/|jsFiddle demo}\r\n * @example Normal overlayColor - color value\r\n * canvas.setOverlayColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));\r\n * @example fabric.Pattern used as overlayColor\r\n * canvas.setOverlayColor({\r\n * source: 'http://fabricjs.com/assets/escheresque_ste.png'\r\n * }, canvas.renderAll.bind(canvas));\r\n * @example fabric.Pattern used as overlayColor with repeat and offset\r\n * canvas.setOverlayColor({\r\n * source: 'http://fabricjs.com/assets/escheresque_ste.png',\r\n * repeat: 'repeat',\r\n * offsetX: 200,\r\n * offsetY: 100\r\n * }, canvas.renderAll.bind(canvas));\r\n */\r\n setOverlayColor: function(overlayColor, callback) {\r\n return this.__setBgOverlayColor('overlayColor', overlayColor, callback);\r\n },\r\n\r\n /**\r\n * Sets {@link fabric.StaticCanvas#backgroundColor|background color} for this canvas\r\n * @param {(String|fabric.Pattern)} backgroundColor Color or pattern to set background color to\r\n * @param {Function} callback Callback to invoke when background color is set\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n * @see {@link http://jsfiddle.net/fabricjs/hXzvk/|jsFiddle demo}\r\n * @example Normal backgroundColor - color value\r\n * canvas.setBackgroundColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));\r\n * @example fabric.Pattern used as backgroundColor\r\n * canvas.setBackgroundColor({\r\n * source: 'http://fabricjs.com/assets/escheresque_ste.png'\r\n * }, canvas.renderAll.bind(canvas));\r\n * @example fabric.Pattern used as backgroundColor with repeat and offset\r\n * canvas.setBackgroundColor({\r\n * source: 'http://fabricjs.com/assets/escheresque_ste.png',\r\n * repeat: 'repeat',\r\n * offsetX: 200,\r\n * offsetY: 100\r\n * }, canvas.renderAll.bind(canvas));\r\n */\r\n setBackgroundColor: function(backgroundColor, callback) {\r\n return this.__setBgOverlayColor('backgroundColor', backgroundColor, callback);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundImage|backgroundImage}\r\n * or {@link fabric.StaticCanvas#overlayImage|overlayImage})\r\n * @param {(fabric.Image|String|null)} image fabric.Image instance, URL of an image or null to set background or overlay to\r\n * @param {Function} callback Callback to invoke when image is loaded and set as background or overlay. The first argument is the created image, the second argument is a flag indicating whether an error occurred or not.\r\n * @param {Object} [options] Optional options to set for the {@link fabric.Image|image}.\r\n */\r\n __setBgOverlayImage: function(property, image, callback, options) {\r\n if (typeof image === 'string') {\r\n fabric.util.loadImage(image, function(img, isError) {\r\n if (img) {\r\n var instance = new fabric.Image(img, options);\r\n this[property] = instance;\r\n instance.canvas = this;\r\n }\r\n callback && callback(img, isError);\r\n }, this, options && options.crossOrigin);\r\n }\r\n else {\r\n options && image.setOptions(options);\r\n this[property] = image;\r\n image && (image.canvas = this);\r\n callback && callback(image, false);\r\n }\r\n\r\n return this;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundColor|backgroundColor}\r\n * or {@link fabric.StaticCanvas#overlayColor|overlayColor})\r\n * @param {(Object|String|null)} color Object with pattern information, color value or null\r\n * @param {Function} [callback] Callback is invoked when color is set\r\n */\r\n __setBgOverlayColor: function(property, color, callback) {\r\n this[property] = color;\r\n this._initGradient(color, property);\r\n this._initPattern(color, property, callback);\r\n return this;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _createCanvasElement: function() {\r\n var element = createCanvasElement();\r\n if (!element) {\r\n throw CANVAS_INIT_ERROR;\r\n }\r\n if (!element.style) {\r\n element.style = { };\r\n }\r\n if (typeof element.getContext === 'undefined') {\r\n throw CANVAS_INIT_ERROR;\r\n }\r\n return element;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Object} [options] Options object\r\n */\r\n _initOptions: function (options) {\r\n var lowerCanvasEl = this.lowerCanvasEl;\r\n this._setOptions(options);\r\n\r\n this.width = this.width || parseInt(lowerCanvasEl.width, 10) || 0;\r\n this.height = this.height || parseInt(lowerCanvasEl.height, 10) || 0;\r\n\r\n if (!this.lowerCanvasEl.style) {\r\n return;\r\n }\r\n\r\n lowerCanvasEl.width = this.width;\r\n lowerCanvasEl.height = this.height;\r\n\r\n lowerCanvasEl.style.width = this.width + 'px';\r\n lowerCanvasEl.style.height = this.height + 'px';\r\n\r\n this.viewportTransform = this.viewportTransform.slice();\r\n },\r\n\r\n /**\r\n * Creates a bottom canvas\r\n * @private\r\n * @param {HTMLElement} [canvasEl]\r\n */\r\n _createLowerCanvas: function (canvasEl) {\r\n // canvasEl === 'HTMLCanvasElement' does not work on jsdom/node\r\n if (canvasEl && canvasEl.getContext) {\r\n this.lowerCanvasEl = canvasEl;\r\n }\r\n else {\r\n this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement();\r\n }\r\n\r\n fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas');\r\n this._originalCanvasStyle = this.lowerCanvasEl.style;\r\n if (this.interactive) {\r\n this._applyCanvasStyle(this.lowerCanvasEl);\r\n }\r\n\r\n this.contextContainer = this.lowerCanvasEl.getContext('2d', { willReadFrequently: true });\r\n },\r\n\r\n /**\r\n * Returns canvas width (in px)\r\n * @return {Number}\r\n */\r\n getWidth: function () {\r\n return this.width;\r\n },\r\n\r\n /**\r\n * Returns canvas height (in px)\r\n * @return {Number}\r\n */\r\n getHeight: function () {\r\n return this.height;\r\n },\r\n\r\n /**\r\n * Sets width of this canvas instance\r\n * @param {Number|String} value Value to set width to\r\n * @param {Object} [options] Options object\r\n * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\r\n * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions\r\n * @return {fabric.Canvas} instance\r\n * @chainable true\r\n */\r\n setWidth: function (value, options) {\r\n return this.setDimensions({ width: value }, options);\r\n },\r\n\r\n /**\r\n * Sets height of this canvas instance\r\n * @param {Number|String} value Value to set height to\r\n * @param {Object} [options] Options object\r\n * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\r\n * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions\r\n * @return {fabric.Canvas} instance\r\n * @chainable true\r\n */\r\n setHeight: function (value, options) {\r\n return this.setDimensions({ height: value }, options);\r\n },\r\n\r\n /**\r\n * Sets dimensions (width, height) of this canvas instance. when options.cssOnly flag active you should also supply the unit of measure (px/%/em)\r\n * @param {Object} dimensions Object with width/height properties\r\n * @param {Number|String} [dimensions.width] Width of canvas element\r\n * @param {Number|String} [dimensions.height] Height of canvas element\r\n * @param {Object} [options] Options object\r\n * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\r\n * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n setDimensions: function (dimensions, options) {\r\n var cssValue;\r\n\r\n options = options || {};\r\n\r\n for (var prop in dimensions) {\r\n cssValue = dimensions[prop];\r\n\r\n if (!options.cssOnly) {\r\n this._setBackstoreDimension(prop, dimensions[prop]);\r\n cssValue += 'px';\r\n this.hasLostContext = true;\r\n }\r\n\r\n if (!options.backstoreOnly) {\r\n this._setCssDimension(prop, cssValue);\r\n }\r\n }\r\n if (this._isCurrentlyDrawing) {\r\n this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles(this.contextTop);\r\n }\r\n this._initRetinaScaling();\r\n this.calcOffset();\r\n\r\n if (!options.cssOnly) {\r\n this.requestRenderAll();\r\n }\r\n\r\n return this;\r\n },\r\n\r\n /**\r\n * Helper for setting width/height\r\n * @private\r\n * @param {String} prop property (width|height)\r\n * @param {Number} value value to set property to\r\n * @return {fabric.Canvas} instance\r\n * @chainable true\r\n */\r\n _setBackstoreDimension: function (prop, value) {\r\n this.lowerCanvasEl[prop] = value;\r\n\r\n if (this.upperCanvasEl) {\r\n this.upperCanvasEl[prop] = value;\r\n }\r\n\r\n if (this.cacheCanvasEl) {\r\n this.cacheCanvasEl[prop] = value;\r\n }\r\n\r\n this[prop] = value;\r\n\r\n return this;\r\n },\r\n\r\n /**\r\n * Helper for setting css width/height\r\n * @private\r\n * @param {String} prop property (width|height)\r\n * @param {String} value value to set property to\r\n * @return {fabric.Canvas} instance\r\n * @chainable true\r\n */\r\n _setCssDimension: function (prop, value) {\r\n this.lowerCanvasEl.style[prop] = value;\r\n\r\n if (this.upperCanvasEl) {\r\n this.upperCanvasEl.style[prop] = value;\r\n }\r\n\r\n if (this.wrapperEl) {\r\n this.wrapperEl.style[prop] = value;\r\n }\r\n\r\n return this;\r\n },\r\n\r\n /**\r\n * Returns canvas zoom level\r\n * @return {Number}\r\n */\r\n getZoom: function () {\r\n return this.viewportTransform[0];\r\n },\r\n\r\n /**\r\n * Sets viewport transformation of this canvas instance\r\n * @param {Array} vpt a Canvas 2D API transform matrix\r\n * @return {fabric.Canvas} instance\r\n * @chainable true\r\n */\r\n setViewportTransform: function (vpt) {\r\n var activeObject = this._activeObject,\r\n backgroundObject = this.backgroundImage,\r\n overlayObject = this.overlayImage,\r\n object, i, len;\r\n this.viewportTransform = vpt;\r\n for (i = 0, len = this._objects.length; i < len; i++) {\r\n object = this._objects[i];\r\n object.group || object.setCoords(true);\r\n }\r\n if (activeObject) {\r\n activeObject.setCoords();\r\n }\r\n if (backgroundObject) {\r\n backgroundObject.setCoords(true);\r\n }\r\n if (overlayObject) {\r\n overlayObject.setCoords(true);\r\n }\r\n this.calcViewportBoundaries();\r\n this.renderOnAddRemove && this.requestRenderAll();\r\n return this;\r\n },\r\n\r\n /**\r\n * Sets zoom level of this canvas instance, the zoom centered around point\r\n * meaning that following zoom to point with the same point will have the visual\r\n * effect of the zoom originating from that point. The point won't move.\r\n * It has nothing to do with canvas center or visual center of the viewport.\r\n * @param {fabric.Point} point to zoom with respect to\r\n * @param {Number} value to set zoom to, less than 1 zooms out\r\n * @return {fabric.Canvas} instance\r\n * @chainable true\r\n */\r\n zoomToPoint: function (point, value) {\r\n // TODO: just change the scale, preserve other transformations\r\n var before = point, vpt = this.viewportTransform.slice(0);\r\n point = transformPoint(point, invertTransform(this.viewportTransform));\r\n vpt[0] = value;\r\n vpt[3] = value;\r\n var after = transformPoint(point, vpt);\r\n vpt[4] += before.x - after.x;\r\n vpt[5] += before.y - after.y;\r\n return this.setViewportTransform(vpt);\r\n },\r\n\r\n /**\r\n * Sets zoom level of this canvas instance\r\n * @param {Number} value to set zoom to, less than 1 zooms out\r\n * @return {fabric.Canvas} instance\r\n * @chainable true\r\n */\r\n setZoom: function (value) {\r\n this.zoomToPoint(new fabric.Point(0, 0), value);\r\n return this;\r\n },\r\n\r\n /**\r\n * Pan viewport so as to place point at top left corner of canvas\r\n * @param {fabric.Point} point to move to\r\n * @return {fabric.Canvas} instance\r\n * @chainable true\r\n */\r\n absolutePan: function (point) {\r\n var vpt = this.viewportTransform.slice(0);\r\n vpt[4] = -point.x;\r\n vpt[5] = -point.y;\r\n return this.setViewportTransform(vpt);\r\n },\r\n\r\n /**\r\n * Pans viewpoint relatively\r\n * @param {fabric.Point} point (position vector) to move by\r\n * @return {fabric.Canvas} instance\r\n * @chainable true\r\n */\r\n relativePan: function (point) {\r\n return this.absolutePan(new fabric.Point(\r\n -point.x - this.viewportTransform[4],\r\n -point.y - this.viewportTransform[5]\r\n ));\r\n },\r\n\r\n /**\r\n * Returns <canvas> element corresponding to this instance\r\n * @return {HTMLCanvasElement}\r\n */\r\n getElement: function () {\r\n return this.lowerCanvasEl;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {fabric.Object} obj Object that was added\r\n */\r\n _onObjectAdded: function(obj) {\r\n this.stateful && obj.setupState();\r\n obj._set('canvas', this);\r\n obj.setCoords();\r\n this.fire('object:added', { target: obj });\r\n obj.fire('added');\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {fabric.Object} obj Object that was removed\r\n */\r\n _onObjectRemoved: function(obj) {\r\n this.fire('object:removed', { target: obj });\r\n obj.fire('removed');\r\n delete obj.canvas;\r\n },\r\n\r\n /**\r\n * Clears specified context of canvas element\r\n * @param {CanvasRenderingContext2D} ctx Context to clear\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n clearContext: function(ctx) {\r\n ctx.clearRect(0, 0, this.width, this.height);\r\n return this;\r\n },\r\n\r\n /**\r\n * Returns context of canvas where objects are drawn\r\n * @return {CanvasRenderingContext2D}\r\n */\r\n getContext: function () {\r\n return this.contextContainer;\r\n },\r\n\r\n /**\r\n * Clears all contexts (background, main, top) of an instance\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n clear: function () {\r\n this.remove.apply(this, this.getObjects());\r\n this.backgroundImage = null;\r\n this.overlayImage = null;\r\n this.backgroundColor = '';\r\n this.overlayColor = '';\r\n if (this._hasITextHandlers) {\r\n this.off('mouse:up', this._mouseUpITextHandler);\r\n this._iTextInstances = null;\r\n this._hasITextHandlers = false;\r\n }\r\n this.clearContext(this.contextContainer);\r\n this.fire('canvas:cleared');\r\n this.renderOnAddRemove && this.requestRenderAll();\r\n return this;\r\n },\r\n\r\n /**\r\n * Renders the canvas\r\n * @return {fabric.Canvas} instance\r\n * @chainable\r\n */\r\n renderAll: function () {\r\n var canvasToDrawOn = this.contextContainer;\r\n this.renderCanvas(canvasToDrawOn, this._objects);\r\n return this;\r\n },\r\n\r\n /**\r\n * Function created to be instance bound at initialization\r\n * used in requestAnimationFrame rendering\r\n * Let the fabricJS call it. If you call it manually you could have more\r\n * animationFrame stacking on to of each other\r\n * for an imperative rendering, use canvas.renderAll\r\n * @private\r\n * @return {fabric.Canvas} instance\r\n * @chainable\r\n */\r\n renderAndReset: function() {\r\n this.isRendering = 0;\r\n this.renderAll();\r\n },\r\n\r\n /**\r\n * Append a renderAll request to next animation frame.\r\n * unless one is already in progress, in that case nothing is done\r\n * a boolean flag will avoid appending more.\r\n * @return {fabric.Canvas} instance\r\n * @chainable\r\n */\r\n requestRenderAll: function () {\r\n if (!this.isRendering) {\r\n this.isRendering = fabric.util.requestAnimFrame(this.renderAndResetBound);\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Calculate the position of the 4 corner of canvas with current viewportTransform.\r\n * helps to determinate when an object is in the current rendering viewport using\r\n * object absolute coordinates ( aCoords )\r\n * @return {Object} points.tl\r\n * @chainable\r\n */\r\n calcViewportBoundaries: function() {\r\n var points = { }, width = this.width, height = this.height,\r\n iVpt = invertTransform(this.viewportTransform);\r\n points.tl = transformPoint({ x: 0, y: 0 }, iVpt);\r\n points.br = transformPoint({ x: width, y: height }, iVpt);\r\n points.tr = new fabric.Point(points.br.x, points.tl.y);\r\n points.bl = new fabric.Point(points.tl.x, points.br.y);\r\n this.vptCoords = points;\r\n return points;\r\n },\r\n\r\n cancelRequestedRender: function() {\r\n if (this.isRendering) {\r\n fabric.util.cancelAnimFrame(this.isRendering);\r\n this.isRendering = 0;\r\n }\r\n },\r\n\r\n /**\r\n * Renders background, objects, overlay and controls.\r\n * @param {CanvasRenderingContext2D} ctx\r\n * @param {Array} objects to render\r\n * @return {fabric.Canvas} instance\r\n * @chainable\r\n */\r\n renderCanvas: function(ctx, objects) {\r\n var v = this.viewportTransform, path = this.clipPath;\r\n this.cancelRequestedRender();\r\n this.calcViewportBoundaries();\r\n this.clearContext(ctx);\r\n fabric.util.setImageSmoothing(ctx, this.imageSmoothingEnabled);\r\n this.fire('before:render', { ctx: ctx, });\r\n this._renderBackground(ctx);\r\n\r\n ctx.save();\r\n //apply viewport transform once for all rendering process\r\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\r\n this._renderObjects(ctx, objects);\r\n ctx.restore();\r\n if (!this.controlsAboveOverlay && this.interactive) {\r\n this.drawControls(ctx);\r\n }\r\n if (path) {\r\n path.canvas = this;\r\n // needed to setup a couple of variables\r\n path.shouldCache();\r\n path._transformDone = true;\r\n path.renderCache({ forClipping: true });\r\n this.drawClipPathOnCanvas(ctx);\r\n }\r\n this._renderOverlay(ctx);\r\n if (this.controlsAboveOverlay && this.interactive) {\r\n this.drawControls(ctx);\r\n }\r\n this.fire('after:render', { ctx: ctx, });\r\n },\r\n\r\n /**\r\n * Paint the cached clipPath on the lowerCanvasEl\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n drawClipPathOnCanvas: function(ctx) {\r\n var v = this.viewportTransform, path = this.clipPath;\r\n ctx.save();\r\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\r\n // DEBUG: uncomment this line, comment the following\r\n // ctx.globalAlpha = 0.4;\r\n ctx.globalCompositeOperation = 'destination-in';\r\n path.transform(ctx);\r\n ctx.scale(1 / path.zoomX, 1 / path.zoomY);\r\n ctx.drawImage(path._cacheCanvas, -path.cacheTranslationX, -path.cacheTranslationY);\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @param {Array} objects to render\r\n */\r\n _renderObjects: function(ctx, objects) {\r\n var i, len;\r\n for (i = 0, len = objects.length; i < len; ++i) {\r\n objects[i] && objects[i].render(ctx);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @param {string} property 'background' or 'overlay'\r\n */\r\n _renderBackgroundOrOverlay: function(ctx, property) {\r\n var fill = this[property + 'Color'], object = this[property + 'Image'],\r\n v = this.viewportTransform, needsVpt = this[property + 'Vpt'];\r\n if (!fill && !object) {\r\n return;\r\n }\r\n if (fill) {\r\n ctx.save();\r\n ctx.beginPath();\r\n ctx.moveTo(0, 0);\r\n ctx.lineTo(this.width, 0);\r\n ctx.lineTo(this.width, this.height);\r\n ctx.lineTo(0, this.height);\r\n ctx.closePath();\r\n ctx.fillStyle = fill.toLive\r\n ? fill.toLive(ctx, this)\r\n : fill;\r\n if (needsVpt) {\r\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\r\n }\r\n ctx.transform(1, 0, 0, 1, fill.offsetX || 0, fill.offsetY || 0);\r\n var m = fill.gradientTransform || fill.patternTransform;\r\n m && ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n if (object) {\r\n ctx.save();\r\n if (needsVpt) {\r\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\r\n }\r\n object.render(ctx);\r\n ctx.restore();\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _renderBackground: function(ctx) {\r\n this._renderBackgroundOrOverlay(ctx, 'background');\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _renderOverlay: function(ctx) {\r\n this._renderBackgroundOrOverlay(ctx, 'overlay');\r\n },\r\n\r\n /**\r\n * Returns coordinates of a center of canvas.\r\n * Returned value is an object with top and left properties\r\n * @return {Object} object with \"top\" and \"left\" number values\r\n * @deprecated migrate to `getCenterPoint`\r\n */\r\n getCenter: function () {\r\n return {\r\n top: this.height / 2,\r\n left: this.width / 2\r\n };\r\n },\r\n\r\n /**\r\n * Returns coordinates of a center of canvas.\r\n * @return {fabric.Point} \r\n */\r\n getCenterPoint: function () {\r\n return new fabric.Point(this.width / 2, this.height / 2);\r\n },\r\n\r\n /**\r\n * Centers object horizontally in the canvas\r\n * @param {fabric.Object} object Object to center horizontally\r\n * @return {fabric.Canvas} thisArg\r\n */\r\n centerObjectH: function (object) {\r\n return this._centerObject(object, new fabric.Point(this.getCenterPoint().x, object.getCenterPoint().y));\r\n },\r\n\r\n /**\r\n * Centers object vertically in the canvas\r\n * @param {fabric.Object} object Object to center vertically\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n centerObjectV: function (object) {\r\n return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenterPoint().y));\r\n },\r\n\r\n /**\r\n * Centers object vertically and horizontally in the canvas\r\n * @param {fabric.Object} object Object to center vertically and horizontally\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n centerObject: function(object) {\r\n var center = this.getCenterPoint();\r\n return this._centerObject(object, center);\r\n },\r\n\r\n /**\r\n * Centers object vertically and horizontally in the viewport\r\n * @param {fabric.Object} object Object to center vertically and horizontally\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n viewportCenterObject: function(object) {\r\n var vpCenter = this.getVpCenter();\r\n return this._centerObject(object, vpCenter);\r\n },\r\n\r\n /**\r\n * Centers object horizontally in the viewport, object.top is unchanged\r\n * @param {fabric.Object} object Object to center vertically and horizontally\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n viewportCenterObjectH: function(object) {\r\n var vpCenter = this.getVpCenter();\r\n this._centerObject(object, new fabric.Point(vpCenter.x, object.getCenterPoint().y));\r\n return this;\r\n },\r\n\r\n /**\r\n * Centers object Vertically in the viewport, object.top is unchanged\r\n * @param {fabric.Object} object Object to center vertically and horizontally\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n viewportCenterObjectV: function(object) {\r\n var vpCenter = this.getVpCenter();\r\n\r\n return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, vpCenter.y));\r\n },\r\n\r\n /**\r\n * Calculate the point in canvas that correspond to the center of actual viewport.\r\n * @return {fabric.Point} vpCenter, viewport center\r\n * @chainable\r\n */\r\n getVpCenter: function() {\r\n var center = this.getCenterPoint(),\r\n iVpt = invertTransform(this.viewportTransform);\r\n return transformPoint(center, iVpt);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {fabric.Object} object Object to center\r\n * @param {fabric.Point} center Center point\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n _centerObject: function(object, center) {\r\n object.setPositionByOrigin(center, 'center', 'center');\r\n object.setCoords();\r\n this.renderOnAddRemove && this.requestRenderAll();\r\n return this;\r\n },\r\n\r\n /**\r\n * Returns dataless JSON representation of canvas\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {String} json string\r\n */\r\n toDatalessJSON: function (propertiesToInclude) {\r\n return this.toDatalessObject(propertiesToInclude);\r\n },\r\n\r\n /**\r\n * Returns object representation of canvas\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} object representation of an instance\r\n */\r\n toObject: function (propertiesToInclude) {\r\n return this._toObjectMethod('toObject', propertiesToInclude);\r\n },\r\n\r\n /**\r\n * Returns dataless object representation of canvas\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} object representation of an instance\r\n */\r\n toDatalessObject: function (propertiesToInclude) {\r\n return this._toObjectMethod('toDatalessObject', propertiesToInclude);\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _toObjectMethod: function (methodName, propertiesToInclude) {\r\n\r\n var clipPath = this.clipPath, data = {\r\n version: fabric.version,\r\n objects: this._toObjects(methodName, propertiesToInclude),\r\n };\r\n if (clipPath && !clipPath.excludeFromExport) {\r\n data.clipPath = this._toObject(this.clipPath, methodName, propertiesToInclude);\r\n }\r\n extend(data, this.__serializeBgOverlay(methodName, propertiesToInclude));\r\n\r\n fabric.util.populateWithProperties(this, data, propertiesToInclude);\r\n\r\n return data;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _toObjects: function(methodName, propertiesToInclude) {\r\n return this._objects.filter(function(object) {\r\n return !object.excludeFromExport;\r\n }).map(function(instance) {\r\n return this._toObject(instance, methodName, propertiesToInclude);\r\n }, this);\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _toObject: function(instance, methodName, propertiesToInclude) {\r\n var originalValue;\r\n\r\n if (!this.includeDefaultValues) {\r\n originalValue = instance.includeDefaultValues;\r\n instance.includeDefaultValues = false;\r\n }\r\n\r\n var object = instance[methodName](propertiesToInclude);\r\n if (!this.includeDefaultValues) {\r\n instance.includeDefaultValues = originalValue;\r\n }\r\n return object;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n __serializeBgOverlay: function(methodName, propertiesToInclude) {\r\n var data = {}, bgImage = this.backgroundImage, overlayImage = this.overlayImage,\r\n bgColor = this.backgroundColor, overlayColor = this.overlayColor;\r\n\r\n if (bgColor && bgColor.toObject) {\r\n if (!bgColor.excludeFromExport) {\r\n data.background = bgColor.toObject(propertiesToInclude);\r\n }\r\n }\r\n else if (bgColor) {\r\n data.background = bgColor;\r\n }\r\n\r\n if (overlayColor && overlayColor.toObject) {\r\n if (!overlayColor.excludeFromExport) {\r\n data.overlay = overlayColor.toObject(propertiesToInclude);\r\n }\r\n }\r\n else if (overlayColor) {\r\n data.overlay = overlayColor;\r\n }\r\n\r\n if (bgImage && !bgImage.excludeFromExport) {\r\n data.backgroundImage = this._toObject(bgImage, methodName, propertiesToInclude);\r\n }\r\n if (overlayImage && !overlayImage.excludeFromExport) {\r\n data.overlayImage = this._toObject(overlayImage, methodName, propertiesToInclude);\r\n }\r\n\r\n return data;\r\n },\r\n\r\n /* _TO_SVG_START_ */\r\n /**\r\n * When true, getSvgTransform() will apply the StaticCanvas.viewportTransform to the SVG transformation. When true,\r\n * a zoomed canvas will then produce zoomed SVG output.\r\n * @type Boolean\r\n * @default\r\n */\r\n svgViewportTransformation: true,\r\n\r\n /**\r\n * Returns SVG representation of canvas\r\n * @function\r\n * @param {Object} [options] Options object for SVG output\r\n * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included\r\n * @param {Object} [options.viewBox] SVG viewbox object\r\n * @param {Number} [options.viewBox.x] x-coordinate of viewbox\r\n * @param {Number} [options.viewBox.y] y-coordinate of viewbox\r\n * @param {Number} [options.viewBox.width] Width of viewbox\r\n * @param {Number} [options.viewBox.height] Height of viewbox\r\n * @param {String} [options.encoding=UTF-8] Encoding of SVG output\r\n * @param {String} [options.width] desired width of svg with or without units\r\n * @param {String} [options.height] desired height of svg with or without units\r\n * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation.\r\n * @return {String} SVG string\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}\r\n * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo}\r\n * @example Normal SVG output\r\n * var svg = canvas.toSVG();\r\n * @example SVG output without preamble (without <?xml ../>)\r\n * var svg = canvas.toSVG({suppressPreamble: true});\r\n * @example SVG output with viewBox attribute\r\n * var svg = canvas.toSVG({\r\n * viewBox: {\r\n * x: 100,\r\n * y: 100,\r\n * width: 200,\r\n * height: 300\r\n * }\r\n * });\r\n * @example SVG output with different encoding (default: UTF-8)\r\n * var svg = canvas.toSVG({encoding: 'ISO-8859-1'});\r\n * @example Modify SVG output with reviver function\r\n * var svg = canvas.toSVG(null, function(svg) {\r\n * return svg.replace('stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; ', '');\r\n * });\r\n */\r\n toSVG: function(options, reviver) {\r\n options || (options = { });\r\n options.reviver = reviver;\r\n var markup = [];\r\n\r\n this._setSVGPreamble(markup, options);\r\n this._setSVGHeader(markup, options);\r\n if (this.clipPath) {\r\n markup.push('\\n');\r\n }\r\n this._setSVGBgOverlayColor(markup, 'background');\r\n this._setSVGBgOverlayImage(markup, 'backgroundImage', reviver);\r\n this._setSVGObjects(markup, reviver);\r\n if (this.clipPath) {\r\n markup.push('\\n');\r\n }\r\n this._setSVGBgOverlayColor(markup, 'overlay');\r\n this._setSVGBgOverlayImage(markup, 'overlayImage', reviver);\r\n\r\n markup.push('');\r\n\r\n return markup.join('');\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _setSVGPreamble: function(markup, options) {\r\n if (options.suppressPreamble) {\r\n return;\r\n }\r\n markup.push(\r\n '\\n',\r\n '\\n'\r\n );\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _setSVGHeader: function(markup, options) {\r\n var width = options.width || this.width,\r\n height = options.height || this.height,\r\n vpt, viewBox = 'viewBox=\"0 0 ' + this.width + ' ' + this.height + '\" ',\r\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\r\n\r\n if (options.viewBox) {\r\n viewBox = 'viewBox=\"' +\r\n options.viewBox.x + ' ' +\r\n options.viewBox.y + ' ' +\r\n options.viewBox.width + ' ' +\r\n options.viewBox.height + '\" ';\r\n }\r\n else {\r\n if (this.svgViewportTransformation) {\r\n vpt = this.viewportTransform;\r\n viewBox = 'viewBox=\"' +\r\n toFixed(-vpt[4] / vpt[0], NUM_FRACTION_DIGITS) + ' ' +\r\n toFixed(-vpt[5] / vpt[3], NUM_FRACTION_DIGITS) + ' ' +\r\n toFixed(this.width / vpt[0], NUM_FRACTION_DIGITS) + ' ' +\r\n toFixed(this.height / vpt[3], NUM_FRACTION_DIGITS) + '\" ';\r\n }\r\n }\r\n\r\n markup.push(\r\n '\\n',\r\n 'Created with Fabric.js ', fabric.version, '\\n',\r\n '\\n',\r\n this.createSVGFontFacesMarkup(),\r\n this.createSVGRefElementsMarkup(),\r\n this.createSVGClipPathMarkup(options),\r\n '\\n'\r\n );\r\n },\r\n\r\n createSVGClipPathMarkup: function(options) {\r\n var clipPath = this.clipPath;\r\n if (clipPath) {\r\n clipPath.clipPathId = 'CLIPPATH_' + fabric.Object.__uid++;\r\n return '\\n' +\r\n this.clipPath.toClipPathSVG(options.reviver) +\r\n '\\n';\r\n }\r\n return '';\r\n },\r\n\r\n /**\r\n * Creates markup containing SVG referenced elements like patterns, gradients etc.\r\n * @return {String}\r\n */\r\n createSVGRefElementsMarkup: function() {\r\n var _this = this,\r\n markup = ['background', 'overlay'].map(function(prop) {\r\n var fill = _this[prop + 'Color'];\r\n if (fill && fill.toLive) {\r\n var shouldTransform = _this[prop + 'Vpt'], vpt = _this.viewportTransform,\r\n object = {\r\n width: _this.width / (shouldTransform ? vpt[0] : 1),\r\n height: _this.height / (shouldTransform ? vpt[3] : 1)\r\n };\r\n return fill.toSVG(\r\n object,\r\n { additionalTransform: shouldTransform ? fabric.util.matrixToSVG(vpt) : '' }\r\n );\r\n }\r\n });\r\n return markup.join('');\r\n },\r\n\r\n /**\r\n * Creates markup containing SVG font faces,\r\n * font URLs for font faces must be collected by developers\r\n * and are not extracted from the DOM by fabricjs\r\n * @param {Array} objects Array of fabric objects\r\n * @return {String}\r\n */\r\n createSVGFontFacesMarkup: function() {\r\n var markup = '', fontList = { }, obj, fontFamily,\r\n style, row, rowIndex, _char, charIndex, i, len,\r\n fontPaths = fabric.fontPaths, objects = [];\r\n\r\n this._objects.forEach(function add(object) {\r\n objects.push(object);\r\n if (object._objects) {\r\n object._objects.forEach(add);\r\n }\r\n });\r\n\r\n for (i = 0, len = objects.length; i < len; i++) {\r\n obj = objects[i];\r\n fontFamily = obj.fontFamily;\r\n if (obj.type.indexOf('text') === -1 || fontList[fontFamily] || !fontPaths[fontFamily]) {\r\n continue;\r\n }\r\n fontList[fontFamily] = true;\r\n if (!obj.styles) {\r\n continue;\r\n }\r\n style = obj.styles;\r\n for (rowIndex in style) {\r\n row = style[rowIndex];\r\n for (charIndex in row) {\r\n _char = row[charIndex];\r\n fontFamily = _char.fontFamily;\r\n if (!fontList[fontFamily] && fontPaths[fontFamily]) {\r\n fontList[fontFamily] = true;\r\n }\r\n }\r\n }\r\n }\r\n\r\n for (var j in fontList) {\r\n markup += [\r\n '\\t\\t@font-face {\\n',\r\n '\\t\\t\\tfont-family: \\'', j, '\\';\\n',\r\n '\\t\\t\\tsrc: url(\\'', fontPaths[j], '\\');\\n',\r\n '\\t\\t}\\n'\r\n ].join('');\r\n }\r\n\r\n if (markup) {\r\n markup = [\r\n '\\t\\n'\r\n ].join('');\r\n }\r\n\r\n return markup;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _setSVGObjects: function(markup, reviver) {\r\n var instance, i, len, objects = this._objects;\r\n for (i = 0, len = objects.length; i < len; i++) {\r\n instance = objects[i];\r\n if (instance.excludeFromExport) {\r\n continue;\r\n }\r\n this._setSVGObject(markup, instance, reviver);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _setSVGObject: function(markup, instance, reviver) {\r\n markup.push(instance.toSVG(reviver));\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _setSVGBgOverlayImage: function(markup, property, reviver) {\r\n if (this[property] && !this[property].excludeFromExport && this[property].toSVG) {\r\n markup.push(this[property].toSVG(reviver));\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _setSVGBgOverlayColor: function(markup, property) {\r\n var filler = this[property + 'Color'], vpt = this.viewportTransform, finalWidth = this.width,\r\n finalHeight = this.height;\r\n if (!filler) {\r\n return;\r\n }\r\n if (filler.toLive) {\r\n var repeat = filler.repeat, iVpt = fabric.util.invertTransform(vpt), shouldInvert = this[property + 'Vpt'],\r\n additionalTransform = shouldInvert ? fabric.util.matrixToSVG(iVpt) : '';\r\n markup.push(\r\n '\\n'\r\n );\r\n }\r\n else {\r\n markup.push(\r\n '\\n'\r\n );\r\n }\r\n },\r\n /* _TO_SVG_END_ */\r\n\r\n /**\r\n * Moves an object or the objects of a multiple selection\r\n * to the bottom of the stack of drawn objects\r\n * @param {fabric.Object} object Object to send to back\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n sendToBack: function (object) {\r\n if (!object) {\r\n return this;\r\n }\r\n var activeSelection = this._activeObject,\r\n i, obj, objs;\r\n if (object === activeSelection && object.type === 'activeSelection') {\r\n objs = activeSelection._objects;\r\n for (i = objs.length; i--;) {\r\n obj = objs[i];\r\n removeFromArray(this._objects, obj);\r\n this._objects.unshift(obj);\r\n }\r\n }\r\n else {\r\n removeFromArray(this._objects, object);\r\n this._objects.unshift(object);\r\n }\r\n this.renderOnAddRemove && this.requestRenderAll();\r\n return this;\r\n },\r\n\r\n /**\r\n * Moves an object or the objects of a multiple selection\r\n * to the top of the stack of drawn objects\r\n * @param {fabric.Object} object Object to send\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n bringToFront: function (object) {\r\n if (!object) {\r\n return this;\r\n }\r\n var activeSelection = this._activeObject,\r\n i, obj, objs;\r\n if (object === activeSelection && object.type === 'activeSelection') {\r\n objs = activeSelection._objects;\r\n for (i = 0; i < objs.length; i++) {\r\n obj = objs[i];\r\n removeFromArray(this._objects, obj);\r\n this._objects.push(obj);\r\n }\r\n }\r\n else {\r\n removeFromArray(this._objects, object);\r\n this._objects.push(object);\r\n }\r\n this.renderOnAddRemove && this.requestRenderAll();\r\n return this;\r\n },\r\n\r\n /**\r\n * Moves an object or a selection down in stack of drawn objects\r\n * An optional parameter, intersecting allows to move the object in behind\r\n * the first intersecting object. Where intersection is calculated with\r\n * bounding box. If no intersection is found, there will not be change in the\r\n * stack.\r\n * @param {fabric.Object} object Object to send\r\n * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n sendBackwards: function (object, intersecting) {\r\n if (!object) {\r\n return this;\r\n }\r\n var activeSelection = this._activeObject,\r\n i, obj, idx, newIdx, objs, objsMoved = 0;\r\n\r\n if (object === activeSelection && object.type === 'activeSelection') {\r\n objs = activeSelection._objects;\r\n for (i = 0; i < objs.length; i++) {\r\n obj = objs[i];\r\n idx = this._objects.indexOf(obj);\r\n if (idx > 0 + objsMoved) {\r\n newIdx = idx - 1;\r\n removeFromArray(this._objects, obj);\r\n this._objects.splice(newIdx, 0, obj);\r\n }\r\n objsMoved++;\r\n }\r\n }\r\n else {\r\n idx = this._objects.indexOf(object);\r\n if (idx !== 0) {\r\n // if object is not on the bottom of stack\r\n newIdx = this._findNewLowerIndex(object, idx, intersecting);\r\n removeFromArray(this._objects, object);\r\n this._objects.splice(newIdx, 0, object);\r\n }\r\n }\r\n this.renderOnAddRemove && this.requestRenderAll();\r\n return this;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _findNewLowerIndex: function(object, idx, intersecting) {\r\n var newIdx, i;\r\n\r\n if (intersecting) {\r\n newIdx = idx;\r\n\r\n // traverse down the stack looking for the nearest intersecting object\r\n for (i = idx - 1; i >= 0; --i) {\r\n\r\n var isIntersecting = object.intersectsWithObject(this._objects[i]) ||\r\n object.isContainedWithinObject(this._objects[i]) ||\r\n this._objects[i].isContainedWithinObject(object);\r\n\r\n if (isIntersecting) {\r\n newIdx = i;\r\n break;\r\n }\r\n }\r\n }\r\n else {\r\n newIdx = idx - 1;\r\n }\r\n\r\n return newIdx;\r\n },\r\n\r\n /**\r\n * Moves an object or a selection up in stack of drawn objects\r\n * An optional parameter, intersecting allows to move the object in front\r\n * of the first intersecting object. Where intersection is calculated with\r\n * bounding box. If no intersection is found, there will not be change in the\r\n * stack.\r\n * @param {fabric.Object} object Object to send\r\n * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n bringForward: function (object, intersecting) {\r\n if (!object) {\r\n return this;\r\n }\r\n var activeSelection = this._activeObject,\r\n i, obj, idx, newIdx, objs, objsMoved = 0;\r\n\r\n if (object === activeSelection && object.type === 'activeSelection') {\r\n objs = activeSelection._objects;\r\n for (i = objs.length; i--;) {\r\n obj = objs[i];\r\n idx = this._objects.indexOf(obj);\r\n if (idx < this._objects.length - 1 - objsMoved) {\r\n newIdx = idx + 1;\r\n removeFromArray(this._objects, obj);\r\n this._objects.splice(newIdx, 0, obj);\r\n }\r\n objsMoved++;\r\n }\r\n }\r\n else {\r\n idx = this._objects.indexOf(object);\r\n if (idx !== this._objects.length - 1) {\r\n // if object is not on top of stack (last item in an array)\r\n newIdx = this._findNewUpperIndex(object, idx, intersecting);\r\n removeFromArray(this._objects, object);\r\n this._objects.splice(newIdx, 0, object);\r\n }\r\n }\r\n this.renderOnAddRemove && this.requestRenderAll();\r\n return this;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _findNewUpperIndex: function(object, idx, intersecting) {\r\n var newIdx, i, len;\r\n\r\n if (intersecting) {\r\n newIdx = idx;\r\n\r\n // traverse up the stack looking for the nearest intersecting object\r\n for (i = idx + 1, len = this._objects.length; i < len; ++i) {\r\n\r\n var isIntersecting = object.intersectsWithObject(this._objects[i]) ||\r\n object.isContainedWithinObject(this._objects[i]) ||\r\n this._objects[i].isContainedWithinObject(object);\r\n\r\n if (isIntersecting) {\r\n newIdx = i;\r\n break;\r\n }\r\n }\r\n }\r\n else {\r\n newIdx = idx + 1;\r\n }\r\n\r\n return newIdx;\r\n },\r\n\r\n /**\r\n * Moves an object to specified level in stack of drawn objects\r\n * @param {fabric.Object} object Object to send\r\n * @param {Number} index Position to move to\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n moveTo: function (object, index) {\r\n removeFromArray(this._objects, object);\r\n this._objects.splice(index, 0, object);\r\n return this.renderOnAddRemove && this.requestRenderAll();\r\n },\r\n\r\n /**\r\n * Clears a canvas element and dispose objects\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n dispose: function () {\r\n // cancel eventually ongoing renders\r\n if (this.isRendering) {\r\n fabric.util.cancelAnimFrame(this.isRendering);\r\n this.isRendering = 0;\r\n }\r\n this.forEachObject(function(object) {\r\n object.dispose && object.dispose();\r\n });\r\n this._objects = [];\r\n if (this.backgroundImage && this.backgroundImage.dispose) {\r\n this.backgroundImage.dispose();\r\n }\r\n this.backgroundImage = null;\r\n if (this.overlayImage && this.overlayImage.dispose) {\r\n this.overlayImage.dispose();\r\n }\r\n this.overlayImage = null;\r\n this._iTextInstances = null;\r\n this.contextContainer = null;\r\n // restore canvas style\r\n this.lowerCanvasEl.classList.remove('lower-canvas');\r\n fabric.util.setStyle(this.lowerCanvasEl, this._originalCanvasStyle);\r\n delete this._originalCanvasStyle;\r\n // restore canvas size to original size in case retina scaling was applied\r\n this.lowerCanvasEl.setAttribute('width', this.width);\r\n this.lowerCanvasEl.setAttribute('height', this.height);\r\n fabric.util.cleanUpJsdomNode(this.lowerCanvasEl);\r\n this.lowerCanvasEl = undefined;\r\n return this;\r\n },\r\n\r\n /**\r\n * Returns a string representation of an instance\r\n * @return {String} string representation of an instance\r\n */\r\n toString: function () {\r\n return '#';\r\n }\r\n });\r\n\r\n extend(fabric.StaticCanvas.prototype, fabric.Observable);\r\n extend(fabric.StaticCanvas.prototype, fabric.Collection);\r\n extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter);\r\n\r\n extend(fabric.StaticCanvas, /** @lends fabric.StaticCanvas */ {\r\n\r\n /**\r\n * @static\r\n * @type String\r\n * @default\r\n */\r\n EMPTY_JSON: '{\"objects\": [], \"background\": \"white\"}',\r\n\r\n /**\r\n * Provides a way to check support of some of the canvas methods\r\n * (either those of HTMLCanvasElement itself, or rendering context)\r\n *\r\n * @param {String} methodName Method to check support for;\r\n * Could be one of \"setLineDash\"\r\n * @return {Boolean | null} `true` if method is supported (or at least exists),\r\n * `null` if canvas element or context can not be initialized\r\n */\r\n supports: function (methodName) {\r\n var el = createCanvasElement();\r\n\r\n if (!el || !el.getContext) {\r\n return null;\r\n }\r\n\r\n var ctx = el.getContext('2d', { willReadFrequently: true });\r\n if (!ctx) {\r\n return null;\r\n }\r\n\r\n switch (methodName) {\r\n\r\n case 'setLineDash':\r\n return typeof ctx.setLineDash !== 'undefined';\r\n\r\n default:\r\n return null;\r\n }\r\n }\r\n });\r\n\r\n /**\r\n * Returns Object representation of canvas\r\n * this alias is provided because if you call JSON.stringify on an instance,\r\n * the toJSON object will be invoked if it exists.\r\n * Having a toJSON method means you can do JSON.stringify(myCanvas)\r\n * @function\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} JSON compatible object\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}\r\n * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo}\r\n * @example JSON without additional properties\r\n * var json = canvas.toJSON();\r\n * @example JSON with additional properties included\r\n * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY']);\r\n * @example JSON without default values\r\n * canvas.includeDefaultValues = false;\r\n * var json = canvas.toJSON();\r\n */\r\n fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject;\r\n\r\n if (fabric.isLikelyNode) {\r\n fabric.StaticCanvas.prototype.createPNGStream = function() {\r\n var impl = getNodeCanvas(this.lowerCanvasEl);\r\n return impl && impl.createPNGStream();\r\n };\r\n fabric.StaticCanvas.prototype.createJPEGStream = function(opts) {\r\n var impl = getNodeCanvas(this.lowerCanvasEl);\r\n return impl && impl.createJPEGStream(opts);\r\n };\r\n }\r\n})();\r\n\r\n\r\n/**\r\n * BaseBrush class\r\n * @class fabric.BaseBrush\r\n * @see {@link http://fabricjs.com/freedrawing|Freedrawing demo}\r\n */\r\nfabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype */ {\r\n\r\n /**\r\n * Color of a brush\r\n * @type String\r\n * @default\r\n */\r\n color: 'rgb(0, 0, 0)',\r\n\r\n /**\r\n * Width of a brush, has to be a Number, no string literals\r\n * @type Number\r\n * @default\r\n */\r\n width: 1,\r\n\r\n /**\r\n * Shadow object representing shadow of this shape.\r\n * Backwards incompatibility note: This property replaces \"shadowColor\" (String), \"shadowOffsetX\" (Number),\r\n * \"shadowOffsetY\" (Number) and \"shadowBlur\" (Number) since v1.2.12\r\n * @type fabric.Shadow\r\n * @default\r\n */\r\n shadow: null,\r\n\r\n /**\r\n * Line endings style of a brush (one of \"butt\", \"round\", \"square\")\r\n * @type String\r\n * @default\r\n */\r\n strokeLineCap: 'round',\r\n\r\n /**\r\n * Corner style of a brush (one of \"bevel\", \"round\", \"miter\")\r\n * @type String\r\n * @default\r\n */\r\n strokeLineJoin: 'round',\r\n\r\n /**\r\n * Maximum miter length (used for strokeLineJoin = \"miter\") of a brush's\r\n * @type Number\r\n * @default\r\n */\r\n strokeMiterLimit: 10,\r\n\r\n /**\r\n * Stroke Dash Array.\r\n * @type Array\r\n * @default\r\n */\r\n strokeDashArray: null,\r\n\r\n /**\r\n * When `true`, the free drawing is limited to the whiteboard size. Default to false.\r\n * @type Boolean\r\n * @default false\r\n */\r\n\r\n limitedToCanvasSize: false,\r\n\r\n\r\n /**\r\n * Sets brush styles\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n _setBrushStyles: function (ctx) {\r\n ctx.strokeStyle = this.color;\r\n ctx.lineWidth = this.width;\r\n ctx.lineCap = this.strokeLineCap;\r\n ctx.miterLimit = this.strokeMiterLimit;\r\n ctx.lineJoin = this.strokeLineJoin;\r\n ctx.setLineDash(this.strokeDashArray || []);\r\n },\r\n\r\n /**\r\n * Sets the transformation on given context\r\n * @param {RenderingContext2d} ctx context to render on\r\n * @private\r\n */\r\n _saveAndTransform: function(ctx) {\r\n var v = this.canvas.viewportTransform;\r\n ctx.save();\r\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\r\n },\r\n\r\n /**\r\n * Sets brush shadow styles\r\n * @private\r\n */\r\n _setShadow: function() {\r\n if (!this.shadow) {\r\n return;\r\n }\r\n\r\n var canvas = this.canvas,\r\n shadow = this.shadow,\r\n ctx = canvas.contextTop,\r\n zoom = canvas.getZoom();\r\n if (canvas && canvas._isRetinaScaling()) {\r\n zoom *= fabric.devicePixelRatio;\r\n }\r\n\r\n ctx.shadowColor = shadow.color;\r\n ctx.shadowBlur = shadow.blur * zoom;\r\n ctx.shadowOffsetX = shadow.offsetX * zoom;\r\n ctx.shadowOffsetY = shadow.offsetY * zoom;\r\n },\r\n\r\n needsFullRender: function() {\r\n var color = new fabric.Color(this.color);\r\n return color.getAlpha() < 1 || !!this.shadow;\r\n },\r\n\r\n /**\r\n * Removes brush shadow styles\r\n * @private\r\n */\r\n _resetShadow: function() {\r\n var ctx = this.canvas.contextTop;\r\n\r\n ctx.shadowColor = '';\r\n ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;\r\n },\r\n\r\n /**\r\n * Check is pointer is outside canvas boundaries\r\n * @param {Object} pointer\r\n * @private\r\n */\r\n _isOutSideCanvas: function(pointer) {\r\n return pointer.x < 0 || pointer.x > this.canvas.getWidth() || pointer.y < 0 || pointer.y > this.canvas.getHeight();\r\n }\r\n});\r\n\r\n\r\n(function() {\r\n /**\r\n * PencilBrush class\r\n * @class fabric.PencilBrush\r\n * @extends fabric.BaseBrush\r\n */\r\n fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.PencilBrush.prototype */ {\r\n\r\n /**\r\n * Discard points that are less than `decimate` pixel distant from each other\r\n * @type Number\r\n * @default 0.4\r\n */\r\n decimate: 0.4,\r\n\r\n /**\r\n * Draws a straight line between last recorded point to current pointer\r\n * Used for `shift` functionality\r\n *\r\n * @type boolean\r\n * @default false\r\n */\r\n drawStraightLine: false,\r\n\r\n /**\r\n * The event modifier key that makes the brush draw a straight line.\r\n * If `null` or 'none' or any other string that is not a modifier key the feature is disabled.\r\n * @type {'altKey' | 'shiftKey' | 'ctrlKey' | 'none' | undefined | null}\r\n */\r\n straightLineKey: 'shiftKey',\r\n\r\n /**\r\n * Constructor\r\n * @param {fabric.Canvas} canvas\r\n * @return {fabric.PencilBrush} Instance of a pencil brush\r\n */\r\n initialize: function(canvas) {\r\n this.canvas = canvas;\r\n this._points = [];\r\n },\r\n\r\n needsFullRender: function () {\r\n return this.callSuper('needsFullRender') || this._hasStraightLine;\r\n },\r\n\r\n /**\r\n * Invoked inside on mouse down and mouse move\r\n * @param {Object} pointer\r\n */\r\n _drawSegment: function (ctx, p1, p2) {\r\n var midPoint = p1.midPointFrom(p2);\r\n ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);\r\n return midPoint;\r\n },\r\n\r\n /**\r\n * Invoked on mouse down\r\n * @param {Object} pointer\r\n */\r\n onMouseDown: function(pointer, options) {\r\n if (!this.canvas._isMainEvent(options.e)) {\r\n return;\r\n }\r\n this.drawStraightLine = options.e[this.straightLineKey];\r\n this._prepareForDrawing(pointer);\r\n // capture coordinates immediately\r\n // this allows to draw dots (when movement never occurs)\r\n this._captureDrawingPath(pointer);\r\n this._render();\r\n },\r\n\r\n /**\r\n * Invoked on mouse move\r\n * @param {Object} pointer\r\n */\r\n onMouseMove: function(pointer, options) {\r\n if (!this.canvas._isMainEvent(options.e)) {\r\n return;\r\n }\r\n this.drawStraightLine = options.e[this.straightLineKey];\r\n if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\r\n return;\r\n }\r\n if (this._captureDrawingPath(pointer) && this._points.length > 1) {\r\n if (this.needsFullRender()) {\r\n // redraw curve\r\n // clear top canvas\r\n this.canvas.clearContext(this.canvas.contextTop);\r\n this._render();\r\n }\r\n else {\r\n var points = this._points, length = points.length, ctx = this.canvas.contextTop;\r\n // draw the curve update\r\n this._saveAndTransform(ctx);\r\n if (this.oldEnd) {\r\n ctx.beginPath();\r\n ctx.moveTo(this.oldEnd.x, this.oldEnd.y);\r\n }\r\n this.oldEnd = this._drawSegment(ctx, points[length - 2], points[length - 1], true);\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * Invoked on mouse up\r\n */\r\n onMouseUp: function(options) {\r\n if (!this.canvas._isMainEvent(options.e)) {\r\n return true;\r\n }\r\n this.drawStraightLine = false;\r\n this.oldEnd = undefined;\r\n this._finalizeAndAddPath();\r\n return false;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Object} pointer Actual mouse position related to the canvas.\r\n */\r\n _prepareForDrawing: function(pointer) {\r\n\r\n var p = new fabric.Point(pointer.x, pointer.y);\r\n\r\n this._reset();\r\n this._addPoint(p);\r\n this.canvas.contextTop.moveTo(p.x, p.y);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {fabric.Point} point Point to be added to points array\r\n */\r\n _addPoint: function(point) {\r\n if (this._points.length > 1 && point.eq(this._points[this._points.length - 1])) {\r\n return false;\r\n }\r\n if (this.drawStraightLine && this._points.length > 1) {\r\n this._hasStraightLine = true;\r\n this._points.pop();\r\n }\r\n this._points.push(point);\r\n return true;\r\n },\r\n\r\n /**\r\n * Clear points array and set contextTop canvas style.\r\n * @private\r\n */\r\n _reset: function() {\r\n this._points = [];\r\n this._setBrushStyles(this.canvas.contextTop);\r\n this._setShadow();\r\n this._hasStraightLine = false;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Object} pointer Actual mouse position related to the canvas.\r\n */\r\n _captureDrawingPath: function(pointer) {\r\n var pointerPoint = new fabric.Point(pointer.x, pointer.y);\r\n return this._addPoint(pointerPoint);\r\n },\r\n\r\n /**\r\n * Draw a smooth path on the topCanvas using quadraticCurveTo\r\n * @private\r\n * @param {CanvasRenderingContext2D} [ctx]\r\n */\r\n _render: function(ctx) {\r\n var i, len,\r\n p1 = this._points[0],\r\n p2 = this._points[1];\r\n ctx = ctx || this.canvas.contextTop;\r\n this._saveAndTransform(ctx);\r\n ctx.beginPath();\r\n //if we only have 2 points in the path and they are the same\r\n //it means that the user only clicked the canvas without moving the mouse\r\n //then we should be drawing a dot. A path isn't drawn between two identical dots\r\n //that's why we set them apart a bit\r\n if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) {\r\n var width = this.width / 1000;\r\n p1 = new fabric.Point(p1.x, p1.y);\r\n p2 = new fabric.Point(p2.x, p2.y);\r\n p1.x -= width;\r\n p2.x += width;\r\n }\r\n ctx.moveTo(p1.x, p1.y);\r\n\r\n for (i = 1, len = this._points.length; i < len; i++) {\r\n // we pick the point between pi + 1 & pi + 2 as the\r\n // end point and p1 as our control point.\r\n this._drawSegment(ctx, p1, p2);\r\n p1 = this._points[i];\r\n p2 = this._points[i + 1];\r\n }\r\n // Draw last line as a straight line while\r\n // we wait for the next point to be able to calculate\r\n // the bezier control point\r\n ctx.lineTo(p1.x, p1.y);\r\n ctx.stroke();\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * Converts points to SVG path\r\n * @param {Array} points Array of points\r\n * @return {(string|number)[][]} SVG path commands\r\n */\r\n convertPointsToSVGPath: function (points) {\r\n var correction = this.width / 1000;\r\n return fabric.util.getSmoothPathFromPoints(points, correction);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {(string|number)[][]} pathData SVG path commands\r\n * @returns {boolean}\r\n */\r\n _isEmptySVGPath: function (pathData) {\r\n var pathString = fabric.util.joinPath(pathData);\r\n return pathString === 'M 0 0 Q 0 0 0 0 L 0 0';\r\n },\r\n\r\n /**\r\n * Creates fabric.Path object to add on canvas\r\n * @param {(string|number)[][]} pathData Path data\r\n * @return {fabric.Path} Path to add on canvas\r\n */\r\n createPath: function(pathData) {\r\n var path = new fabric.Path(pathData, {\r\n fill: null,\r\n stroke: this.color,\r\n strokeWidth: this.width,\r\n strokeLineCap: this.strokeLineCap,\r\n strokeMiterLimit: this.strokeMiterLimit,\r\n strokeLineJoin: this.strokeLineJoin,\r\n strokeDashArray: this.strokeDashArray,\r\n });\r\n if (this.shadow) {\r\n this.shadow.affectStroke = true;\r\n path.shadow = new fabric.Shadow(this.shadow);\r\n }\r\n\r\n return path;\r\n },\r\n\r\n /**\r\n * Decimate points array with the decimate value\r\n */\r\n decimatePoints: function(points, distance) {\r\n if (points.length <= 2) {\r\n return points;\r\n }\r\n var zoom = this.canvas.getZoom(), adjustedDistance = Math.pow(distance / zoom, 2),\r\n i, l = points.length - 1, lastPoint = points[0], newPoints = [lastPoint],\r\n cDistance;\r\n for (i = 1; i < l - 1; i++) {\r\n cDistance = Math.pow(lastPoint.x - points[i].x, 2) + Math.pow(lastPoint.y - points[i].y, 2);\r\n if (cDistance >= adjustedDistance) {\r\n lastPoint = points[i];\r\n newPoints.push(lastPoint);\r\n }\r\n }\r\n /**\r\n * Add the last point from the original line to the end of the array.\r\n * This ensures decimate doesn't delete the last point on the line, and ensures the line is > 1 point.\r\n */\r\n newPoints.push(points[l]);\r\n return newPoints;\r\n },\r\n\r\n /**\r\n * On mouseup after drawing the path on contextTop canvas\r\n * we use the points captured to create an new fabric path object\r\n * and add it to the fabric canvas.\r\n */\r\n _finalizeAndAddPath: function() {\r\n var ctx = this.canvas.contextTop;\r\n ctx.closePath();\r\n if (this.decimate) {\r\n this._points = this.decimatePoints(this._points, this.decimate);\r\n }\r\n var pathData = this.convertPointsToSVGPath(this._points);\r\n if (this._isEmptySVGPath(pathData)) {\r\n // do not create 0 width/height paths, as they are\r\n // rendered inconsistently across browsers\r\n // Firefox 4, for example, renders a dot,\r\n // whereas Chrome 10 renders nothing\r\n this.canvas.requestRenderAll();\r\n return;\r\n }\r\n\r\n var path = this.createPath(pathData);\r\n this.canvas.clearContext(this.canvas.contextTop);\r\n this.canvas.fire('before:path:created', { path: path });\r\n this.canvas.add(path);\r\n this.canvas.requestRenderAll();\r\n path.setCoords();\r\n this._resetShadow();\r\n\r\n\r\n // fire event 'path' created\r\n this.canvas.fire('path:created', { path: path });\r\n }\r\n });\r\n})();\r\n\r\n\r\n/**\r\n * CircleBrush class\r\n * @class fabric.CircleBrush\r\n */\r\nfabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.CircleBrush.prototype */ {\r\n\r\n /**\r\n * Width of a brush\r\n * @type Number\r\n * @default\r\n */\r\n width: 10,\r\n\r\n /**\r\n * Constructor\r\n * @param {fabric.Canvas} canvas\r\n * @return {fabric.CircleBrush} Instance of a circle brush\r\n */\r\n initialize: function(canvas) {\r\n this.canvas = canvas;\r\n this.points = [];\r\n },\r\n\r\n /**\r\n * Invoked inside on mouse down and mouse move\r\n * @param {Object} pointer\r\n */\r\n drawDot: function(pointer) {\r\n var point = this.addPoint(pointer),\r\n ctx = this.canvas.contextTop;\r\n this._saveAndTransform(ctx);\r\n this.dot(ctx, point);\r\n ctx.restore();\r\n },\r\n\r\n dot: function(ctx, point) {\r\n ctx.fillStyle = point.fill;\r\n ctx.beginPath();\r\n ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false);\r\n ctx.closePath();\r\n ctx.fill();\r\n },\r\n\r\n /**\r\n * Invoked on mouse down\r\n */\r\n onMouseDown: function(pointer) {\r\n this.points.length = 0;\r\n this.canvas.clearContext(this.canvas.contextTop);\r\n this._setShadow();\r\n this.drawDot(pointer);\r\n },\r\n\r\n /**\r\n * Render the full state of the brush\r\n * @private\r\n */\r\n _render: function() {\r\n var ctx = this.canvas.contextTop, i, len,\r\n points = this.points;\r\n this._saveAndTransform(ctx);\r\n for (i = 0, len = points.length; i < len; i++) {\r\n this.dot(ctx, points[i]);\r\n }\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * Invoked on mouse move\r\n * @param {Object} pointer\r\n */\r\n onMouseMove: function(pointer) {\r\n if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\r\n return;\r\n }\r\n if (this.needsFullRender()) {\r\n this.canvas.clearContext(this.canvas.contextTop);\r\n this.addPoint(pointer);\r\n this._render();\r\n }\r\n else {\r\n this.drawDot(pointer);\r\n }\r\n },\r\n\r\n /**\r\n * Invoked on mouse up\r\n */\r\n onMouseUp: function() {\r\n var originalRenderOnAddRemove = this.canvas.renderOnAddRemove, i, len;\r\n this.canvas.renderOnAddRemove = false;\r\n\r\n var circles = [];\r\n\r\n for (i = 0, len = this.points.length; i < len; i++) {\r\n var point = this.points[i],\r\n circle = new fabric.Circle({\r\n radius: point.radius,\r\n left: point.x,\r\n top: point.y,\r\n originX: 'center',\r\n originY: 'center',\r\n fill: point.fill\r\n });\r\n\r\n this.shadow && (circle.shadow = new fabric.Shadow(this.shadow));\r\n\r\n circles.push(circle);\r\n }\r\n var group = new fabric.Group(circles);\r\n group.canvas = this.canvas;\r\n\r\n this.canvas.fire('before:path:created', { path: group });\r\n this.canvas.add(group);\r\n this.canvas.fire('path:created', { path: group });\r\n\r\n this.canvas.clearContext(this.canvas.contextTop);\r\n this._resetShadow();\r\n this.canvas.renderOnAddRemove = originalRenderOnAddRemove;\r\n this.canvas.requestRenderAll();\r\n },\r\n\r\n /**\r\n * @param {Object} pointer\r\n * @return {fabric.Point} Just added pointer point\r\n */\r\n addPoint: function(pointer) {\r\n var pointerPoint = new fabric.Point(pointer.x, pointer.y),\r\n\r\n circleRadius = fabric.util.getRandomInt(\r\n Math.max(0, this.width - 20), this.width + 20) / 2,\r\n\r\n circleColor = new fabric.Color(this.color)\r\n .setAlpha(fabric.util.getRandomInt(0, 100) / 100)\r\n .toRgba();\r\n\r\n pointerPoint.radius = circleRadius;\r\n pointerPoint.fill = circleColor;\r\n\r\n this.points.push(pointerPoint);\r\n\r\n return pointerPoint;\r\n }\r\n});\r\n\r\n\r\n/**\r\n * SprayBrush class\r\n * @class fabric.SprayBrush\r\n */\r\nfabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric.SprayBrush.prototype */ {\r\n\r\n /**\r\n * Width of a spray\r\n * @type Number\r\n * @default\r\n */\r\n width: 10,\r\n\r\n /**\r\n * Density of a spray (number of dots per chunk)\r\n * @type Number\r\n * @default\r\n */\r\n density: 20,\r\n\r\n /**\r\n * Width of spray dots\r\n * @type Number\r\n * @default\r\n */\r\n dotWidth: 1,\r\n\r\n /**\r\n * Width variance of spray dots\r\n * @type Number\r\n * @default\r\n */\r\n dotWidthVariance: 1,\r\n\r\n /**\r\n * Whether opacity of a dot should be random\r\n * @type Boolean\r\n * @default\r\n */\r\n randomOpacity: false,\r\n\r\n /**\r\n * Whether overlapping dots (rectangles) should be removed (for performance reasons)\r\n * @type Boolean\r\n * @default\r\n */\r\n optimizeOverlapping: true,\r\n\r\n /**\r\n * Constructor\r\n * @param {fabric.Canvas} canvas\r\n * @return {fabric.SprayBrush} Instance of a spray brush\r\n */\r\n initialize: function(canvas) {\r\n this.canvas = canvas;\r\n this.sprayChunks = [];\r\n },\r\n\r\n /**\r\n * Invoked on mouse down\r\n * @param {Object} pointer\r\n */\r\n onMouseDown: function(pointer) {\r\n this.sprayChunks.length = 0;\r\n this.canvas.clearContext(this.canvas.contextTop);\r\n this._setShadow();\r\n\r\n this.addSprayChunk(pointer);\r\n this.render(this.sprayChunkPoints);\r\n },\r\n\r\n /**\r\n * Invoked on mouse move\r\n * @param {Object} pointer\r\n */\r\n onMouseMove: function(pointer) {\r\n if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\r\n return;\r\n }\r\n this.addSprayChunk(pointer);\r\n this.render(this.sprayChunkPoints);\r\n },\r\n\r\n /**\r\n * Invoked on mouse up\r\n */\r\n onMouseUp: function() {\r\n var originalRenderOnAddRemove = this.canvas.renderOnAddRemove;\r\n this.canvas.renderOnAddRemove = false;\r\n\r\n var rects = [];\r\n\r\n for (var i = 0, ilen = this.sprayChunks.length; i < ilen; i++) {\r\n var sprayChunk = this.sprayChunks[i];\r\n\r\n for (var j = 0, jlen = sprayChunk.length; j < jlen; j++) {\r\n\r\n var rect = new fabric.Rect({\r\n width: sprayChunk[j].width,\r\n height: sprayChunk[j].width,\r\n left: sprayChunk[j].x + 1,\r\n top: sprayChunk[j].y + 1,\r\n originX: 'center',\r\n originY: 'center',\r\n fill: this.color\r\n });\r\n rects.push(rect);\r\n }\r\n }\r\n\r\n if (this.optimizeOverlapping) {\r\n rects = this._getOptimizedRects(rects);\r\n }\r\n\r\n var group = new fabric.Group(rects);\r\n this.shadow && group.set('shadow', new fabric.Shadow(this.shadow));\r\n this.canvas.fire('before:path:created', { path: group });\r\n this.canvas.add(group);\r\n this.canvas.fire('path:created', { path: group });\r\n\r\n this.canvas.clearContext(this.canvas.contextTop);\r\n this._resetShadow();\r\n this.canvas.renderOnAddRemove = originalRenderOnAddRemove;\r\n this.canvas.requestRenderAll();\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Array} rects\r\n */\r\n _getOptimizedRects: function(rects) {\r\n\r\n // avoid creating duplicate rects at the same coordinates\r\n var uniqueRects = { }, key, i, len;\r\n\r\n for (i = 0, len = rects.length; i < len; i++) {\r\n key = rects[i].left + '' + rects[i].top;\r\n if (!uniqueRects[key]) {\r\n uniqueRects[key] = rects[i];\r\n }\r\n }\r\n var uniqueRectsArray = [];\r\n for (key in uniqueRects) {\r\n uniqueRectsArray.push(uniqueRects[key]);\r\n }\r\n\r\n return uniqueRectsArray;\r\n },\r\n\r\n /**\r\n * Render new chunk of spray brush\r\n */\r\n render: function(sprayChunk) {\r\n var ctx = this.canvas.contextTop, i, len;\r\n ctx.fillStyle = this.color;\r\n\r\n this._saveAndTransform(ctx);\r\n\r\n for (i = 0, len = sprayChunk.length; i < len; i++) {\r\n var point = sprayChunk[i];\r\n if (typeof point.opacity !== 'undefined') {\r\n ctx.globalAlpha = point.opacity;\r\n }\r\n ctx.fillRect(point.x, point.y, point.width, point.width);\r\n }\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * Render all spray chunks\r\n */\r\n _render: function() {\r\n var ctx = this.canvas.contextTop, i, ilen;\r\n ctx.fillStyle = this.color;\r\n\r\n this._saveAndTransform(ctx);\r\n\r\n for (i = 0, ilen = this.sprayChunks.length; i < ilen; i++) {\r\n this.render(this.sprayChunks[i]);\r\n }\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * @param {Object} pointer\r\n */\r\n addSprayChunk: function(pointer) {\r\n this.sprayChunkPoints = [];\r\n\r\n var x, y, width, radius = this.width / 2, i;\r\n\r\n for (i = 0; i < this.density; i++) {\r\n\r\n x = fabric.util.getRandomInt(pointer.x - radius, pointer.x + radius);\r\n y = fabric.util.getRandomInt(pointer.y - radius, pointer.y + radius);\r\n\r\n if (this.dotWidthVariance) {\r\n width = fabric.util.getRandomInt(\r\n // bottom clamp width to 1\r\n Math.max(1, this.dotWidth - this.dotWidthVariance),\r\n this.dotWidth + this.dotWidthVariance);\r\n }\r\n else {\r\n width = this.dotWidth;\r\n }\r\n\r\n var point = new fabric.Point(x, y);\r\n point.width = width;\r\n\r\n if (this.randomOpacity) {\r\n point.opacity = fabric.util.getRandomInt(0, 100) / 100;\r\n }\r\n\r\n this.sprayChunkPoints.push(point);\r\n }\r\n\r\n this.sprayChunks.push(this.sprayChunkPoints);\r\n }\r\n});\r\n\r\n\r\n/**\r\n * PatternBrush class\r\n * @class fabric.PatternBrush\r\n * @extends fabric.BaseBrush\r\n */\r\nfabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fabric.PatternBrush.prototype */ {\r\n\r\n getPatternSrc: function() {\r\n\r\n var dotWidth = 20,\r\n dotDistance = 5,\r\n patternCanvas = fabric.util.createCanvasElement(),\r\n patternCtx = patternCanvas.getContext('2d', { willReadFrequently: true });\r\n\r\n patternCanvas.width = patternCanvas.height = dotWidth + dotDistance;\r\n\r\n patternCtx.fillStyle = this.color;\r\n patternCtx.beginPath();\r\n patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false);\r\n patternCtx.closePath();\r\n patternCtx.fill();\r\n\r\n return patternCanvas;\r\n },\r\n\r\n getPatternSrcFunction: function() {\r\n return String(this.getPatternSrc).replace('this.color', '\"' + this.color + '\"');\r\n },\r\n\r\n /**\r\n * Creates \"pattern\" instance property\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n getPattern: function(ctx) {\r\n return ctx.createPattern(this.source || this.getPatternSrc(), 'repeat');\r\n },\r\n\r\n /**\r\n * Sets brush styles\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n _setBrushStyles: function(ctx) {\r\n this.callSuper('_setBrushStyles', ctx);\r\n ctx.strokeStyle = this.getPattern(ctx);\r\n },\r\n\r\n /**\r\n * Creates path\r\n */\r\n createPath: function(pathData) {\r\n var path = this.callSuper('createPath', pathData),\r\n topLeft = path._getLeftTopCoords().scalarAdd(path.strokeWidth / 2);\r\n\r\n path.stroke = new fabric.Pattern({\r\n source: this.source || this.getPatternSrcFunction(),\r\n offsetX: -topLeft.x,\r\n offsetY: -topLeft.y\r\n });\r\n return path;\r\n }\r\n});\r\n\r\n\r\n(function() {\r\n\r\n var getPointer = fabric.util.getPointer,\r\n degreesToRadians = fabric.util.degreesToRadians,\r\n isTouchEvent = fabric.util.isTouchEvent;\r\n\r\n /**\r\n * Canvas class\r\n * @class fabric.Canvas\r\n * @extends fabric.StaticCanvas\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#canvas}\r\n * @see {@link fabric.Canvas#initialize} for constructor definition\r\n *\r\n * @fires object:modified at the end of a transform or any change when statefull is true\r\n * @fires object:rotating while an object is being rotated from the control\r\n * @fires object:scaling while an object is being scaled by controls\r\n * @fires object:moving while an object is being dragged\r\n * @fires object:skewing while an object is being skewed from the controls\r\n *\r\n * @fires before:transform before a transform is is started\r\n * @fires before:selection:cleared\r\n * @fires selection:cleared\r\n * @fires selection:updated\r\n * @fires selection:created\r\n *\r\n * @fires path:created after a drawing operation ends and the path is added\r\n * @fires mouse:down\r\n * @fires mouse:move\r\n * @fires mouse:up\r\n * @fires mouse:down:before on mouse down, before the inner fabric logic runs\r\n * @fires mouse:move:before on mouse move, before the inner fabric logic runs\r\n * @fires mouse:up:before on mouse up, before the inner fabric logic runs\r\n * @fires mouse:over\r\n * @fires mouse:out\r\n * @fires mouse:dblclick whenever a native dbl click event fires on the canvas.\r\n *\r\n * @fires dragover\r\n * @fires dragenter\r\n * @fires dragleave\r\n * @fires drop:before before drop event. same native event. This is added to handle edge cases\r\n * @fires drop\r\n * @fires after:render at the end of the render process, receives the context in the callback\r\n * @fires before:render at start the render process, receives the context in the callback\r\n *\r\n */\r\n fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ {\r\n\r\n /**\r\n * Constructor\r\n * @param {HTMLElement | String} el <canvas> element to initialize instance on\r\n * @param {Object} [options] Options object\r\n * @return {Object} thisArg\r\n */\r\n initialize: function(el, options) {\r\n options || (options = { });\r\n this.renderAndResetBound = this.renderAndReset.bind(this);\r\n this.requestRenderAllBound = this.requestRenderAll.bind(this);\r\n this._initStatic(el, options);\r\n this._initInteractive();\r\n this._createCacheCanvas();\r\n },\r\n\r\n /**\r\n * When true, objects can be transformed by one side (unproportionally)\r\n * when dragged on the corners that normally would not do that.\r\n * @type Boolean\r\n * @default\r\n * @since fabric 4.0 // changed name and default value\r\n */\r\n uniformScaling: true,\r\n\r\n /**\r\n * Indicates which key switches uniform scaling.\r\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\r\n * If `null` or 'none' or any other string that is not a modifier key\r\n * feature is disabled.\r\n * totally wrong named. this sounds like `uniform scaling`\r\n * if Canvas.uniformScaling is true, pressing this will set it to false\r\n * and viceversa.\r\n * @since 1.6.2\r\n * @type String\r\n * @default\r\n */\r\n uniScaleKey: 'shiftKey',\r\n\r\n /**\r\n * When true, objects use center point as the origin of scale transformation.\r\n * Backwards incompatibility note: This property replaces \"centerTransform\" (Boolean).\r\n * @since 1.3.4\r\n * @type Boolean\r\n * @default\r\n */\r\n centeredScaling: false,\r\n\r\n /**\r\n * When true, objects use center point as the origin of rotate transformation.\r\n * Backwards incompatibility note: This property replaces \"centerTransform\" (Boolean).\r\n * @since 1.3.4\r\n * @type Boolean\r\n * @default\r\n */\r\n centeredRotation: false,\r\n\r\n /**\r\n * Indicates which key enable centered Transform\r\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\r\n * If `null` or 'none' or any other string that is not a modifier key\r\n * feature is disabled feature disabled.\r\n * @since 1.6.2\r\n * @type String\r\n * @default\r\n */\r\n centeredKey: 'altKey',\r\n\r\n /**\r\n * Indicates which key enable alternate action on corner\r\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\r\n * If `null` or 'none' or any other string that is not a modifier key\r\n * feature is disabled feature disabled.\r\n * @since 1.6.2\r\n * @type String\r\n * @default\r\n */\r\n altActionKey: 'shiftKey',\r\n\r\n /**\r\n * Indicates that canvas is interactive. This property should not be changed.\r\n * @type Boolean\r\n * @default\r\n */\r\n interactive: true,\r\n\r\n /**\r\n * Indicates whether group selection should be enabled\r\n * @type Boolean\r\n * @default\r\n */\r\n selection: true,\r\n\r\n /**\r\n * Indicates which key or keys enable multiple click selection\r\n * Pass value as a string or array of strings\r\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\r\n * If `null` or empty or containing any other string that is not a modifier key\r\n * feature is disabled.\r\n * @since 1.6.2\r\n * @type String|Array\r\n * @default\r\n */\r\n selectionKey: 'shiftKey',\r\n\r\n /**\r\n * Indicates which key enable alternative selection\r\n * in case of target overlapping with active object\r\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\r\n * For a series of reason that come from the general expectations on how\r\n * things should work, this feature works only for preserveObjectStacking true.\r\n * If `null` or 'none' or any other string that is not a modifier key\r\n * feature is disabled.\r\n * @since 1.6.5\r\n * @type null|String\r\n * @default\r\n */\r\n altSelectionKey: null,\r\n\r\n /**\r\n * Color of selection\r\n * @type String\r\n * @default\r\n */\r\n selectionColor: 'rgba(100, 100, 255, 0.3)', // blue\r\n\r\n /**\r\n * Default dash array pattern\r\n * If not empty the selection border is dashed\r\n * @type Array\r\n */\r\n selectionDashArray: [],\r\n\r\n /**\r\n * Color of the border of selection (usually slightly darker than color of selection itself)\r\n * @type String\r\n * @default\r\n */\r\n selectionBorderColor: 'rgba(255, 255, 255, 0.3)',\r\n\r\n /**\r\n * Width of a line used in object/group selection\r\n * @type Number\r\n * @default\r\n */\r\n selectionLineWidth: 1,\r\n\r\n /**\r\n * Select only shapes that are fully contained in the dragged selection rectangle.\r\n * @type Boolean\r\n * @default\r\n */\r\n selectionFullyContained: false,\r\n\r\n /**\r\n * Default cursor value used when hovering over an object on canvas\r\n * @type String\r\n * @default\r\n */\r\n hoverCursor: 'move',\r\n\r\n /**\r\n * Default cursor value used when moving an object on canvas\r\n * @type String\r\n * @default\r\n */\r\n moveCursor: 'move',\r\n\r\n /**\r\n * Default cursor value used for the entire canvas\r\n * @type String\r\n * @default\r\n */\r\n defaultCursor: 'default',\r\n\r\n /**\r\n * Cursor value used during free drawing\r\n * @type String\r\n * @default\r\n */\r\n freeDrawingCursor: 'crosshair',\r\n\r\n /**\r\n * Cursor value used for disabled elements ( corners with disabled action )\r\n * @type String\r\n * @since 2.0.0\r\n * @default\r\n */\r\n notAllowedCursor: 'not-allowed',\r\n\r\n /**\r\n * Default element class that's given to wrapper (div) element of canvas\r\n * @type String\r\n * @default\r\n */\r\n containerClass: 'canvas-container',\r\n\r\n /**\r\n * When true, object detection happens on per-pixel basis rather than on per-bounding-box\r\n * @type Boolean\r\n * @default\r\n */\r\n perPixelTargetFind: false,\r\n\r\n /**\r\n * Number of pixels around target pixel to tolerate (consider active) during object detection\r\n * @type Number\r\n * @default\r\n */\r\n targetFindTolerance: 0,\r\n\r\n /**\r\n * When true, target detection is skipped. Target detection will return always undefined.\r\n * click selection won't work anymore, events will fire with no targets.\r\n * if something is selected before setting it to true, it will be deselected at the first click.\r\n * area selection will still work. check the `selection` property too.\r\n * if you deactivate both, you should look into staticCanvas.\r\n * @type Boolean\r\n * @default\r\n */\r\n skipTargetFind: false,\r\n\r\n /**\r\n * When true, mouse events on canvas (mousedown/mousemove/mouseup) result in free drawing.\r\n * After mousedown, mousemove creates a shape,\r\n * and then mouseup finalizes it and adds an instance of `fabric.Path` onto canvas.\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-4#free_drawing}\r\n * @type Boolean\r\n * @default\r\n */\r\n isDrawingMode: false,\r\n\r\n /**\r\n * Indicates whether objects should remain in current stack position when selected.\r\n * When false objects are brought to top and rendered as part of the selection group\r\n * @type Boolean\r\n * @default\r\n */\r\n preserveObjectStacking: false,\r\n\r\n /**\r\n * Indicates the angle that an object will lock to while rotating.\r\n * @type Number\r\n * @since 1.6.7\r\n * @default\r\n */\r\n snapAngle: 0,\r\n\r\n /**\r\n * Indicates the distance from the snapAngle the rotation will lock to the snapAngle.\r\n * When `null`, the snapThreshold will default to the snapAngle.\r\n * @type null|Number\r\n * @since 1.6.7\r\n * @default\r\n */\r\n snapThreshold: null,\r\n\r\n /**\r\n * Indicates if the right click on canvas can output the context menu or not\r\n * @type Boolean\r\n * @since 1.6.5\r\n * @default\r\n */\r\n stopContextMenu: false,\r\n\r\n /**\r\n * Indicates if the canvas can fire right click events\r\n * @type Boolean\r\n * @since 1.6.5\r\n * @default\r\n */\r\n fireRightClick: false,\r\n\r\n /**\r\n * Indicates if the canvas can fire middle click events\r\n * @type Boolean\r\n * @since 1.7.8\r\n * @default\r\n */\r\n fireMiddleClick: false,\r\n\r\n /**\r\n * Keep track of the subTargets for Mouse Events\r\n * @type fabric.Object[]\r\n */\r\n targets: [],\r\n\r\n /**\r\n * When the option is enabled, PointerEvent is used instead of MouseEvent.\r\n * @type Boolean\r\n * @default\r\n */\r\n enablePointerEvents: false,\r\n\r\n /**\r\n * Keep track of the hovered target\r\n * @type fabric.Object\r\n * @private\r\n */\r\n _hoveredTarget: null,\r\n\r\n /**\r\n * hold the list of nested targets hovered\r\n * @type fabric.Object[]\r\n * @private\r\n */\r\n _hoveredTargets: [],\r\n\r\n /**\r\n * @private\r\n */\r\n _initInteractive: function() {\r\n this._currentTransform = null;\r\n this._groupSelector = null;\r\n this._initWrapperElement();\r\n this._createUpperCanvas();\r\n this._initEventListeners();\r\n\r\n this._initRetinaScaling();\r\n\r\n this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this);\r\n\r\n this.calcOffset();\r\n },\r\n\r\n /**\r\n * Divides objects in two groups, one to render immediately\r\n * and one to render as activeGroup.\r\n * @return {Array} objects to render immediately and pushes the other in the activeGroup.\r\n */\r\n _chooseObjectsToRender: function() {\r\n var activeObjects = this.getActiveObjects(),\r\n object, objsToRender, activeGroupObjects;\r\n\r\n if (activeObjects.length > 0 && !this.preserveObjectStacking) {\r\n objsToRender = [];\r\n activeGroupObjects = [];\r\n for (var i = 0, length = this._objects.length; i < length; i++) {\r\n object = this._objects[i];\r\n if (activeObjects.indexOf(object) === -1 ) {\r\n objsToRender.push(object);\r\n }\r\n else {\r\n activeGroupObjects.push(object);\r\n }\r\n }\r\n if (activeObjects.length > 1) {\r\n this._activeObject._objects = activeGroupObjects;\r\n }\r\n objsToRender.push.apply(objsToRender, activeGroupObjects);\r\n }\r\n else {\r\n objsToRender = this._objects;\r\n }\r\n return objsToRender;\r\n },\r\n\r\n /**\r\n * Renders both the top canvas and the secondary container canvas.\r\n * @return {fabric.Canvas} instance\r\n * @chainable\r\n */\r\n renderAll: function () {\r\n if (this.contextTopDirty && !this._groupSelector && !this.isDrawingMode) {\r\n this.clearContext(this.contextTop);\r\n this.contextTopDirty = false;\r\n }\r\n if (this.hasLostContext) {\r\n this.renderTopLayer(this.contextTop);\r\n this.hasLostContext = false;\r\n }\r\n var canvasToDrawOn = this.contextContainer;\r\n this.renderCanvas(canvasToDrawOn, this._chooseObjectsToRender());\r\n return this;\r\n },\r\n\r\n renderTopLayer: function(ctx) {\r\n ctx.save();\r\n if (this.isDrawingMode && this._isCurrentlyDrawing) {\r\n this.freeDrawingBrush && this.freeDrawingBrush._render();\r\n this.contextTopDirty = true;\r\n }\r\n // we render the top context - last object\r\n if (this.selection && this._groupSelector) {\r\n this._drawSelection(ctx);\r\n this.contextTopDirty = true;\r\n }\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * Method to render only the top canvas.\r\n * Also used to render the group selection box.\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n renderTop: function () {\r\n var ctx = this.contextTop;\r\n this.clearContext(ctx);\r\n this.renderTopLayer(ctx);\r\n this.fire('after:render');\r\n return this;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _normalizePointer: function (object, pointer) {\r\n var m = object.calcTransformMatrix(),\r\n invertedM = fabric.util.invertTransform(m),\r\n vptPointer = this.restorePointerVpt(pointer);\r\n return fabric.util.transformPoint(vptPointer, invertedM);\r\n },\r\n\r\n /**\r\n * Returns true if object is transparent at a certain location\r\n * @param {fabric.Object} target Object to check\r\n * @param {Number} x Left coordinate\r\n * @param {Number} y Top coordinate\r\n * @return {Boolean}\r\n */\r\n isTargetTransparent: function (target, x, y) {\r\n // in case the target is the activeObject, we cannot execute this optimization\r\n // because we need to draw controls too.\r\n if (target.shouldCache() && target._cacheCanvas && target !== this._activeObject) {\r\n var normalizedPointer = this._normalizePointer(target, {x: x, y: y}),\r\n targetRelativeX = Math.max(target.cacheTranslationX + (normalizedPointer.x * target.zoomX), 0),\r\n targetRelativeY = Math.max(target.cacheTranslationY + (normalizedPointer.y * target.zoomY), 0);\r\n\r\n var isTransparent = fabric.util.isTransparent(\r\n target._cacheContext, Math.round(targetRelativeX), Math.round(targetRelativeY), this.targetFindTolerance);\r\n\r\n return isTransparent;\r\n }\r\n\r\n var ctx = this.contextCache,\r\n originalColor = target.selectionBackgroundColor, v = this.viewportTransform;\r\n\r\n target.selectionBackgroundColor = '';\r\n\r\n this.clearContext(ctx);\r\n\r\n ctx.save();\r\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\r\n target.render(ctx);\r\n ctx.restore();\r\n\r\n target.selectionBackgroundColor = originalColor;\r\n\r\n var isTransparent = fabric.util.isTransparent(\r\n ctx, x, y, this.targetFindTolerance);\r\n\r\n return isTransparent;\r\n },\r\n\r\n /**\r\n * takes an event and determines if selection key has been pressed\r\n * @private\r\n * @param {Event} e Event object\r\n */\r\n _isSelectionKeyPressed: function(e) {\r\n var selectionKeyPressed = false;\r\n\r\n if (Array.isArray(this.selectionKey)) {\r\n selectionKeyPressed = !!this.selectionKey.find(function(key) { return e[key] === true; });\r\n }\r\n else {\r\n selectionKeyPressed = e[this.selectionKey];\r\n }\r\n\r\n return selectionKeyPressed;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object\r\n * @param {fabric.Object} target\r\n */\r\n _shouldClearSelection: function (e, target) {\r\n var activeObjects = this.getActiveObjects(),\r\n activeObject = this._activeObject;\r\n\r\n return (\r\n !target\r\n ||\r\n (target &&\r\n activeObject &&\r\n activeObjects.length > 1 &&\r\n activeObjects.indexOf(target) === -1 &&\r\n activeObject !== target &&\r\n !this._isSelectionKeyPressed(e))\r\n ||\r\n (target && !target.evented)\r\n ||\r\n (target &&\r\n !target.selectable &&\r\n activeObject &&\r\n activeObject !== target)\r\n );\r\n },\r\n\r\n /**\r\n * centeredScaling from object can't override centeredScaling from canvas.\r\n * this should be fixed, since object setting should take precedence over canvas.\r\n * also this should be something that will be migrated in the control properties.\r\n * as ability to define the origin of the transformation that the control provide.\r\n * @private\r\n * @param {fabric.Object} target\r\n * @param {String} action\r\n * @param {Boolean} altKey\r\n */\r\n _shouldCenterTransform: function (target, action, altKey) {\r\n if (!target) {\r\n return;\r\n }\r\n\r\n var centerTransform;\r\n\r\n if (action === 'scale' || action === 'scaleX' || action === 'scaleY' || action === 'resizing') {\r\n centerTransform = this.centeredScaling || target.centeredScaling;\r\n }\r\n else if (action === 'rotate') {\r\n centerTransform = this.centeredRotation || target.centeredRotation;\r\n }\r\n\r\n return centerTransform ? !altKey : altKey;\r\n },\r\n\r\n /**\r\n * should disappear before release 4.0\r\n * @private\r\n */\r\n _getOriginFromCorner: function(target, corner) {\r\n var origin = {\r\n x: target.originX,\r\n y: target.originY\r\n };\r\n\r\n if (corner === 'ml' || corner === 'tl' || corner === 'bl') {\r\n origin.x = 'right';\r\n }\r\n else if (corner === 'mr' || corner === 'tr' || corner === 'br') {\r\n origin.x = 'left';\r\n }\r\n\r\n if (corner === 'tl' || corner === 'mt' || corner === 'tr') {\r\n origin.y = 'bottom';\r\n }\r\n else if (corner === 'bl' || corner === 'mb' || corner === 'br') {\r\n origin.y = 'top';\r\n }\r\n return origin;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Boolean} alreadySelected true if target is already selected\r\n * @param {String} corner a string representing the corner ml, mr, tl ...\r\n * @param {Event} e Event object\r\n * @param {fabric.Object} [target] inserted back to help overriding. Unused\r\n */\r\n _getActionFromCorner: function(alreadySelected, corner, e, target) {\r\n if (!corner || !alreadySelected) {\r\n return 'drag';\r\n }\r\n var control = target.controls[corner];\r\n return control.getActionName(e, control, target);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object\r\n * @param {fabric.Object} target\r\n */\r\n _setupCurrentTransform: function (e, target, alreadySelected) {\r\n if (!target) {\r\n return;\r\n }\r\n\r\n var pointer = this.getPointer(e), corner = target.__corner,\r\n control = target.controls[corner],\r\n actionHandler = (alreadySelected && corner) ?\r\n control.getActionHandler(e, target, control) : fabric.controlsUtils.dragHandler,\r\n action = this._getActionFromCorner(alreadySelected, corner, e, target),\r\n origin = this._getOriginFromCorner(target, corner),\r\n altKey = e[this.centeredKey],\r\n transform = {\r\n target: target,\r\n action: action,\r\n actionHandler: actionHandler,\r\n corner: corner,\r\n scaleX: target.scaleX,\r\n scaleY: target.scaleY,\r\n skewX: target.skewX,\r\n skewY: target.skewY,\r\n // used by transation\r\n offsetX: pointer.x - target.left,\r\n offsetY: pointer.y - target.top,\r\n originX: origin.x,\r\n originY: origin.y,\r\n ex: pointer.x,\r\n ey: pointer.y,\r\n lastX: pointer.x,\r\n lastY: pointer.y,\r\n // unsure they are useful anymore.\r\n // left: target.left,\r\n // top: target.top,\r\n theta: degreesToRadians(target.angle),\r\n // end of unsure\r\n width: target.width * target.scaleX,\r\n shiftKey: e.shiftKey,\r\n altKey: altKey,\r\n original: fabric.util.saveObjectTransform(target),\r\n };\r\n\r\n if (this._shouldCenterTransform(target, action, altKey)) {\r\n transform.originX = 'center';\r\n transform.originY = 'center';\r\n }\r\n transform.original.originX = origin.x;\r\n transform.original.originY = origin.y;\r\n this._currentTransform = transform;\r\n this._beforeTransform(e);\r\n },\r\n\r\n /**\r\n * Set the cursor type of the canvas element\r\n * @param {String} value Cursor type of the canvas element.\r\n * @see http://www.w3.org/TR/css3-ui/#cursor\r\n */\r\n setCursor: function (value) {\r\n this.upperCanvasEl.style.cursor = value;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx to draw the selection on\r\n */\r\n _drawSelection: function (ctx) {\r\n var selector = this._groupSelector,\r\n viewportStart = new fabric.Point(selector.ex, selector.ey),\r\n start = fabric.util.transformPoint(viewportStart, this.viewportTransform),\r\n viewportExtent = new fabric.Point(selector.ex + selector.left, selector.ey + selector.top),\r\n extent = fabric.util.transformPoint(viewportExtent, this.viewportTransform),\r\n minX = Math.min(start.x, extent.x),\r\n minY = Math.min(start.y, extent.y),\r\n maxX = Math.max(start.x, extent.x),\r\n maxY = Math.max(start.y, extent.y),\r\n strokeOffset = this.selectionLineWidth / 2;\r\n\r\n if (this.selectionColor) {\r\n ctx.fillStyle = this.selectionColor;\r\n ctx.fillRect(minX, minY, maxX - minX, maxY - minY);\r\n }\r\n\r\n if (!this.selectionLineWidth || !this.selectionBorderColor) {\r\n return;\r\n }\r\n ctx.lineWidth = this.selectionLineWidth;\r\n ctx.strokeStyle = this.selectionBorderColor;\r\n\r\n minX += strokeOffset;\r\n minY += strokeOffset;\r\n maxX -= strokeOffset;\r\n maxY -= strokeOffset;\r\n // selection border\r\n fabric.Object.prototype._setLineDash.call(this, ctx, this.selectionDashArray);\r\n ctx.strokeRect(minX, minY, maxX - minX, maxY - minY);\r\n },\r\n\r\n /**\r\n * Method that determines what object we are clicking on\r\n * the skipGroup parameter is for internal use, is needed for shift+click action\r\n * 11/09/2018 TODO: would be cool if findTarget could discern between being a full target\r\n * or the outside part of the corner.\r\n * @param {Event} e mouse event\r\n * @param {Boolean} skipGroup when true, activeGroup is skipped and only objects are traversed through\r\n * @return {fabric.Object} the target found\r\n */\r\n findTarget: function (e, skipGroup) {\r\n if (this.skipTargetFind) {\r\n return;\r\n }\r\n\r\n var ignoreZoom = true,\r\n pointer = this.getPointer(e, ignoreZoom),\r\n activeObject = this._activeObject,\r\n aObjects = this.getActiveObjects(),\r\n activeTarget, activeTargetSubs,\r\n isTouch = isTouchEvent(e),\r\n shouldLookForActive = (aObjects.length > 1 && !skipGroup) || aObjects.length === 1;\r\n\r\n // first check current group (if one exists)\r\n // active group does not check sub targets like normal groups.\r\n // if active group just exits.\r\n this.targets = [];\r\n\r\n // if we hit the corner of an activeObject, let's return that.\r\n if (shouldLookForActive && activeObject._findTargetCorner(pointer, isTouch)) {\r\n return activeObject;\r\n }\r\n if (aObjects.length > 1 && !skipGroup && activeObject === this._searchPossibleTargets([activeObject], pointer)) {\r\n return activeObject;\r\n }\r\n if (aObjects.length === 1 &&\r\n activeObject === this._searchPossibleTargets([activeObject], pointer)) {\r\n if (!this.preserveObjectStacking) {\r\n return activeObject;\r\n }\r\n else {\r\n activeTarget = activeObject;\r\n activeTargetSubs = this.targets;\r\n this.targets = [];\r\n }\r\n }\r\n var target = this._searchPossibleTargets(this._objects, pointer);\r\n if (e[this.altSelectionKey] && target && activeTarget && target !== activeTarget) {\r\n target = activeTarget;\r\n this.targets = activeTargetSubs;\r\n }\r\n return target;\r\n },\r\n\r\n /**\r\n * Checks point is inside the object.\r\n * @param {Object} [pointer] x,y object of point coordinates we want to check.\r\n * @param {fabric.Object} obj Object to test against\r\n * @param {Object} [globalPointer] x,y object of point coordinates relative to canvas used to search per pixel target.\r\n * @return {Boolean} true if point is contained within an area of given object\r\n * @private\r\n */\r\n _checkTarget: function(pointer, obj, globalPointer) {\r\n if (obj &&\r\n obj.visible &&\r\n obj.evented &&\r\n // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html\r\n // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html\r\n obj.containsPoint(pointer)\r\n ) {\r\n if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) {\r\n var isTransparent = this.isTargetTransparent(obj, globalPointer.x, globalPointer.y);\r\n if (!isTransparent) {\r\n return true;\r\n }\r\n }\r\n else {\r\n return true;\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * Function used to search inside objects an object that contains pointer in bounding box or that contains pointerOnCanvas when painted\r\n * @param {Array} [objects] objects array to look into\r\n * @param {Object} [pointer] x,y object of point coordinates we want to check.\r\n * @return {fabric.Object} object that contains pointer\r\n * @private\r\n */\r\n _searchPossibleTargets: function(objects, pointer) {\r\n // Cache all targets where their bounding box contains point.\r\n var target, i = objects.length, subTarget;\r\n // Do not check for currently grouped objects, since we check the parent group itself.\r\n // until we call this function specifically to search inside the activeGroup\r\n while (i--) {\r\n var objToCheck = objects[i];\r\n var pointerToUse = objToCheck.group ?\r\n this._normalizePointer(objToCheck.group, pointer) : pointer;\r\n if (this._checkTarget(pointerToUse, objToCheck, pointer)) {\r\n target = objects[i];\r\n if (target.subTargetCheck && target instanceof fabric.Group) {\r\n subTarget = this._searchPossibleTargets(target._objects, pointer);\r\n subTarget && this.targets.push(subTarget);\r\n }\r\n break;\r\n }\r\n }\r\n return target;\r\n },\r\n\r\n /**\r\n * Returns pointer coordinates without the effect of the viewport\r\n * @param {Object} pointer with \"x\" and \"y\" number values\r\n * @return {Object} object with \"x\" and \"y\" number values\r\n */\r\n restorePointerVpt: function(pointer) {\r\n return fabric.util.transformPoint(\r\n pointer,\r\n fabric.util.invertTransform(this.viewportTransform)\r\n );\r\n },\r\n\r\n /**\r\n * Returns pointer coordinates relative to canvas.\r\n * Can return coordinates with or without viewportTransform.\r\n * ignoreZoom false gives back coordinates that represent\r\n * the point clicked on canvas element.\r\n * ignoreZoom true gives back coordinates after being processed\r\n * by the viewportTransform ( sort of coordinates of what is displayed\r\n * on the canvas where you are clicking.\r\n * ignoreZoom true = HTMLElement coordinates relative to top,left\r\n * ignoreZoom false, default = fabric space coordinates, the same used for shape position\r\n * To interact with your shapes top and left you want to use ignoreZoom true\r\n * most of the time, while ignoreZoom false will give you coordinates\r\n * compatible with the object.oCoords system.\r\n * of the time.\r\n * @param {Event} e\r\n * @param {Boolean} ignoreZoom\r\n * @return {Object} object with \"x\" and \"y\" number values\r\n */\r\n getPointer: function (e, ignoreZoom) {\r\n // return cached values if we are in the event processing chain\r\n if (this._absolutePointer && !ignoreZoom) {\r\n return this._absolutePointer;\r\n }\r\n if (this._pointer && ignoreZoom) {\r\n return this._pointer;\r\n }\r\n\r\n var pointer = getPointer(e),\r\n upperCanvasEl = this.upperCanvasEl,\r\n bounds = upperCanvasEl.getBoundingClientRect(),\r\n boundsWidth = bounds.width || 0,\r\n boundsHeight = bounds.height || 0,\r\n cssScale;\r\n\r\n if (!boundsWidth || !boundsHeight ) {\r\n if ('top' in bounds && 'bottom' in bounds) {\r\n boundsHeight = Math.abs( bounds.top - bounds.bottom );\r\n }\r\n if ('right' in bounds && 'left' in bounds) {\r\n boundsWidth = Math.abs( bounds.right - bounds.left );\r\n }\r\n }\r\n\r\n this.calcOffset();\r\n pointer.x = pointer.x - this._offset.left;\r\n pointer.y = pointer.y - this._offset.top;\r\n if (!ignoreZoom) {\r\n pointer = this.restorePointerVpt(pointer);\r\n }\r\n\r\n var retinaScaling = this.getRetinaScaling();\r\n if (retinaScaling !== 1) {\r\n pointer.x /= retinaScaling;\r\n pointer.y /= retinaScaling;\r\n }\r\n\r\n if (boundsWidth === 0 || boundsHeight === 0) {\r\n // If bounds are not available (i.e. not visible), do not apply scale.\r\n cssScale = { width: 1, height: 1 };\r\n }\r\n else {\r\n cssScale = {\r\n width: upperCanvasEl.width / boundsWidth,\r\n height: upperCanvasEl.height / boundsHeight\r\n };\r\n }\r\n\r\n return {\r\n x: pointer.x * cssScale.width,\r\n y: pointer.y * cssScale.height\r\n };\r\n },\r\n\r\n /**\r\n * @private\r\n * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized\r\n */\r\n _createUpperCanvas: function () {\r\n var lowerCanvasClass = this.lowerCanvasEl.className.replace(/\\s*lower-canvas\\s*/, ''),\r\n lowerCanvasEl = this.lowerCanvasEl, upperCanvasEl = this.upperCanvasEl;\r\n\r\n // there is no need to create a new upperCanvas element if we have already one.\r\n if (upperCanvasEl) {\r\n upperCanvasEl.className = '';\r\n }\r\n else {\r\n upperCanvasEl = this._createCanvasElement();\r\n this.upperCanvasEl = upperCanvasEl;\r\n }\r\n fabric.util.addClass(upperCanvasEl, 'upper-canvas ' + lowerCanvasClass);\r\n\r\n this.wrapperEl.appendChild(upperCanvasEl);\r\n\r\n this._copyCanvasStyle(lowerCanvasEl, upperCanvasEl);\r\n this._applyCanvasStyle(upperCanvasEl);\r\n this.contextTop = upperCanvasEl.getContext('2d', { willReadFrequently: true });\r\n },\r\n\r\n /**\r\n * Returns context of top canvas where interactions are drawn\r\n * @returns {CanvasRenderingContext2D}\r\n */\r\n getTopContext: function () {\r\n return this.contextTop;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _createCacheCanvas: function () {\r\n this.cacheCanvasEl = this._createCanvasElement();\r\n this.cacheCanvasEl.setAttribute('width', this.width);\r\n this.cacheCanvasEl.setAttribute('height', this.height);\r\n this.contextCache = this.cacheCanvasEl.getContext('2d', { willReadFrequently: true });\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _initWrapperElement: function () {\r\n this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', {\r\n 'class': this.containerClass\r\n });\r\n fabric.util.setStyle(this.wrapperEl, {\r\n width: this.width + 'px',\r\n height: this.height + 'px',\r\n position: 'relative'\r\n });\r\n fabric.util.makeElementUnselectable(this.wrapperEl);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {HTMLElement} element canvas element to apply styles on\r\n */\r\n _applyCanvasStyle: function (element) {\r\n var width = this.width || element.width,\r\n height = this.height || element.height;\r\n\r\n fabric.util.setStyle(element, {\r\n position: 'absolute',\r\n width: width + 'px',\r\n height: height + 'px',\r\n left: 0,\r\n top: 0,\r\n 'touch-action': this.allowTouchScrolling ? 'manipulation' : 'none',\r\n '-ms-touch-action': this.allowTouchScrolling ? 'manipulation' : 'none'\r\n });\r\n element.width = width;\r\n element.height = height;\r\n fabric.util.makeElementUnselectable(element);\r\n },\r\n\r\n /**\r\n * Copy the entire inline style from one element (fromEl) to another (toEl)\r\n * @private\r\n * @param {Element} fromEl Element style is copied from\r\n * @param {Element} toEl Element copied style is applied to\r\n */\r\n _copyCanvasStyle: function (fromEl, toEl) {\r\n toEl.style.cssText = fromEl.style.cssText;\r\n },\r\n\r\n /**\r\n * Returns context of canvas where object selection is drawn\r\n * @return {CanvasRenderingContext2D}\r\n */\r\n getSelectionContext: function() {\r\n return this.contextTop;\r\n },\r\n\r\n /**\r\n * Returns <canvas> element on which object selection is drawn\r\n * @return {HTMLCanvasElement}\r\n */\r\n getSelectionElement: function () {\r\n return this.upperCanvasEl;\r\n },\r\n\r\n /**\r\n * Returns currently active object\r\n * @return {fabric.Object} active object\r\n */\r\n getActiveObject: function () {\r\n return this._activeObject;\r\n },\r\n\r\n /**\r\n * Returns an array with the current selected objects\r\n * @return {fabric.Object} active object\r\n */\r\n getActiveObjects: function () {\r\n var active = this._activeObject;\r\n if (active) {\r\n if (active.type === 'activeSelection' && active._objects) {\r\n return active._objects.slice(0);\r\n }\r\n else {\r\n return [active];\r\n }\r\n }\r\n return [];\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {fabric.Object} obj Object that was removed\r\n */\r\n _onObjectRemoved: function(obj) {\r\n // removing active object should fire \"selection:cleared\" events\r\n if (obj === this._activeObject) {\r\n this.fire('before:selection:cleared', { target: obj });\r\n this._discardActiveObject();\r\n this.fire('selection:cleared', { target: obj });\r\n obj.fire('deselected');\r\n }\r\n if (obj === this._hoveredTarget){\r\n this._hoveredTarget = null;\r\n this._hoveredTargets = [];\r\n }\r\n this.callSuper('_onObjectRemoved', obj);\r\n },\r\n\r\n /**\r\n * @private\r\n * Compares the old activeObject with the current one and fires correct events\r\n * @param {fabric.Object} obj old activeObject\r\n */\r\n _fireSelectionEvents: function(oldObjects, e) {\r\n var somethingChanged = false, objects = this.getActiveObjects(),\r\n added = [], removed = [];\r\n oldObjects.forEach(function(oldObject) {\r\n if (objects.indexOf(oldObject) === -1) {\r\n somethingChanged = true;\r\n oldObject.fire('deselected', {\r\n e: e,\r\n target: oldObject\r\n });\r\n removed.push(oldObject);\r\n }\r\n });\r\n objects.forEach(function(object) {\r\n if (oldObjects.indexOf(object) === -1) {\r\n somethingChanged = true;\r\n object.fire('selected', {\r\n e: e,\r\n target: object\r\n });\r\n added.push(object);\r\n }\r\n });\r\n if (oldObjects.length > 0 && objects.length > 0) {\r\n somethingChanged && this.fire('selection:updated', {\r\n e: e,\r\n selected: added,\r\n deselected: removed,\r\n });\r\n }\r\n else if (objects.length > 0) {\r\n this.fire('selection:created', {\r\n e: e,\r\n selected: added,\r\n });\r\n }\r\n else if (oldObjects.length > 0) {\r\n this.fire('selection:cleared', {\r\n e: e,\r\n deselected: removed,\r\n });\r\n }\r\n },\r\n\r\n /**\r\n * Sets given object as the only active object on canvas\r\n * @param {fabric.Object} object Object to set as an active one\r\n * @param {Event} [e] Event (passed along when firing \"object:selected\")\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n setActiveObject: function (object, e) {\r\n var currentActives = this.getActiveObjects();\r\n this._setActiveObject(object, e);\r\n this._fireSelectionEvents(currentActives, e);\r\n return this;\r\n },\r\n\r\n /**\r\n * This is a private method for now.\r\n * This is supposed to be equivalent to setActiveObject but without firing\r\n * any event. There is commitment to have this stay this way.\r\n * This is the functional part of setActiveObject.\r\n * @private\r\n * @param {Object} object to set as active\r\n * @param {Event} [e] Event (passed along when firing \"object:selected\")\r\n * @return {Boolean} true if the selection happened\r\n */\r\n _setActiveObject: function(object, e) {\r\n if (this._activeObject === object) {\r\n return false;\r\n }\r\n if (!this._discardActiveObject(e, object)) {\r\n return false;\r\n }\r\n if (object.onSelect({ e: e })) {\r\n return false;\r\n }\r\n this._activeObject = object;\r\n return true;\r\n },\r\n\r\n /**\r\n * This is a private method for now.\r\n * This is supposed to be equivalent to discardActiveObject but without firing\r\n * any events. There is commitment to have this stay this way.\r\n * This is the functional part of discardActiveObject.\r\n * @param {Event} [e] Event (passed along when firing \"object:deselected\")\r\n * @param {Object} object to set as active\r\n * @return {Boolean} true if the selection happened\r\n * @private\r\n */\r\n _discardActiveObject: function(e, object) {\r\n var obj = this._activeObject;\r\n if (obj) {\r\n // onDeselect return TRUE to cancel selection;\r\n if (obj.onDeselect({ e: e, object: object })) {\r\n return false;\r\n }\r\n this._activeObject = null;\r\n }\r\n return true;\r\n },\r\n\r\n /**\r\n * Discards currently active object and fire events. If the function is called by fabric\r\n * as a consequence of a mouse event, the event is passed as a parameter and\r\n * sent to the fire function for the custom events. When used as a method the\r\n * e param does not have any application.\r\n * @param {event} e\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n discardActiveObject: function (e) {\r\n var currentActives = this.getActiveObjects(), activeObject = this.getActiveObject();\r\n if (currentActives.length) {\r\n this.fire('before:selection:cleared', { target: activeObject, e: e });\r\n }\r\n this._discardActiveObject(e);\r\n this._fireSelectionEvents(currentActives, e);\r\n return this;\r\n },\r\n\r\n /**\r\n * Clears a canvas element and removes all event listeners\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n dispose: function () {\r\n var wrapper = this.wrapperEl;\r\n this.removeListeners();\r\n wrapper.removeChild(this.upperCanvasEl);\r\n wrapper.removeChild(this.lowerCanvasEl);\r\n this.contextCache = null;\r\n this.contextTop = null;\r\n ['upperCanvasEl', 'cacheCanvasEl'].forEach((function(element) {\r\n fabric.util.cleanUpJsdomNode(this[element]);\r\n this[element] = undefined;\r\n }).bind(this));\r\n if (wrapper.parentNode) {\r\n wrapper.parentNode.replaceChild(this.lowerCanvasEl, this.wrapperEl);\r\n }\r\n delete this.wrapperEl;\r\n fabric.StaticCanvas.prototype.dispose.call(this);\r\n return this;\r\n },\r\n\r\n /**\r\n * Clears all contexts (background, main, top) of an instance\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n clear: function () {\r\n // this.discardActiveGroup();\r\n this.discardActiveObject();\r\n this.clearContext(this.contextTop);\r\n return this.callSuper('clear');\r\n },\r\n\r\n /**\r\n * Draws objects' controls (borders/controls)\r\n * @param {CanvasRenderingContext2D} ctx Context to render controls on\r\n */\r\n drawControls: function(ctx) {\r\n var activeObject = this._activeObject;\r\n\r\n if (activeObject) {\r\n activeObject._renderControls(ctx);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _toObject: function(instance, methodName, propertiesToInclude) {\r\n //If the object is part of the current selection group, it should\r\n //be transformed appropriately\r\n //i.e. it should be serialised as it would appear if the selection group\r\n //were to be destroyed.\r\n var originalProperties = this._realizeGroupTransformOnObject(instance),\r\n object = this.callSuper('_toObject', instance, methodName, propertiesToInclude);\r\n //Undo the damage we did by changing all of its properties\r\n this._unwindGroupTransformOnObject(instance, originalProperties);\r\n return object;\r\n },\r\n\r\n /**\r\n * Realises an object's group transformation on it\r\n * @private\r\n * @param {fabric.Object} [instance] the object to transform (gets mutated)\r\n * @returns the original values of instance which were changed\r\n */\r\n _realizeGroupTransformOnObject: function(instance) {\r\n if (instance.group && instance.group.type === 'activeSelection' && this._activeObject === instance.group) {\r\n var layoutProps = ['angle', 'flipX', 'flipY', 'left', 'scaleX', 'scaleY', 'skewX', 'skewY', 'top'];\r\n //Copy all the positionally relevant properties across now\r\n var originalValues = {};\r\n layoutProps.forEach(function(prop) {\r\n originalValues[prop] = instance[prop];\r\n });\r\n fabric.util.addTransformToObject(instance, this._activeObject.calcOwnMatrix());\r\n return originalValues;\r\n }\r\n else {\r\n return null;\r\n }\r\n },\r\n\r\n /**\r\n * Restores the changed properties of instance\r\n * @private\r\n * @param {fabric.Object} [instance] the object to un-transform (gets mutated)\r\n * @param {Object} [originalValues] the original values of instance, as returned by _realizeGroupTransformOnObject\r\n */\r\n _unwindGroupTransformOnObject: function(instance, originalValues) {\r\n if (originalValues) {\r\n instance.set(originalValues);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _setSVGObject: function(markup, instance, reviver) {\r\n //If the object is in a selection group, simulate what would happen to that\r\n //object when the group is deselected\r\n var originalProperties = this._realizeGroupTransformOnObject(instance);\r\n this.callSuper('_setSVGObject', markup, instance, reviver);\r\n this._unwindGroupTransformOnObject(instance, originalProperties);\r\n },\r\n\r\n setViewportTransform: function (vpt) {\r\n if (this.renderOnAddRemove && this._activeObject && this._activeObject.isEditing) {\r\n this._activeObject.clearContextTop();\r\n }\r\n fabric.StaticCanvas.prototype.setViewportTransform.call(this, vpt);\r\n }\r\n });\r\n\r\n // copying static properties manually to work around Opera's bug,\r\n // where \"prototype\" property is enumerable and overrides existing prototype\r\n for (var prop in fabric.StaticCanvas) {\r\n if (prop !== 'prototype') {\r\n fabric.Canvas[prop] = fabric.StaticCanvas[prop];\r\n }\r\n }\r\n})();\r\n\r\n\r\n(function() {\r\n\r\n var addListener = fabric.util.addListener,\r\n removeListener = fabric.util.removeListener,\r\n RIGHT_CLICK = 3, MIDDLE_CLICK = 2, LEFT_CLICK = 1,\r\n addEventOptions = { passive: false };\r\n\r\n function checkClick(e, value) {\r\n return e.button && (e.button === value - 1);\r\n }\r\n\r\n fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ {\r\n\r\n /**\r\n * Contains the id of the touch event that owns the fabric transform\r\n * @type Number\r\n * @private\r\n */\r\n mainTouchId: null,\r\n\r\n /**\r\n * Adds mouse listeners to canvas\r\n * @private\r\n */\r\n _initEventListeners: function () {\r\n // in case we initialized the class twice. This should not happen normally\r\n // but in some kind of applications where the canvas element may be changed\r\n // this is a workaround to having double listeners.\r\n this.removeListeners();\r\n this._bindEvents();\r\n this.addOrRemove(addListener, 'add');\r\n },\r\n\r\n /**\r\n * return an event prefix pointer or mouse.\r\n * @private\r\n */\r\n _getEventPrefix: function () {\r\n return this.enablePointerEvents ? 'pointer' : 'mouse';\r\n },\r\n\r\n addOrRemove: function(functor, eventjsFunctor) {\r\n var canvasElement = this.upperCanvasEl,\r\n eventTypePrefix = this._getEventPrefix();\r\n functor(fabric.window, 'resize', this._onResize);\r\n functor(canvasElement, eventTypePrefix + 'down', this._onMouseDown);\r\n functor(canvasElement, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\r\n functor(canvasElement, eventTypePrefix + 'out', this._onMouseOut);\r\n functor(canvasElement, eventTypePrefix + 'enter', this._onMouseEnter);\r\n functor(canvasElement, 'wheel', this._onMouseWheel);\r\n functor(canvasElement, 'contextmenu', this._onContextMenu);\r\n functor(canvasElement, 'dblclick', this._onDoubleClick);\r\n functor(canvasElement, 'dragover', this._onDragOver);\r\n functor(canvasElement, 'dragenter', this._onDragEnter);\r\n functor(canvasElement, 'dragleave', this._onDragLeave);\r\n functor(canvasElement, 'drop', this._onDrop);\r\n if (!this.enablePointerEvents) {\r\n functor(canvasElement, 'touchstart', this._onTouchStart, addEventOptions);\r\n }\r\n if (typeof eventjs !== 'undefined' && eventjsFunctor in eventjs) {\r\n eventjs[eventjsFunctor](canvasElement, 'gesture', this._onGesture);\r\n eventjs[eventjsFunctor](canvasElement, 'drag', this._onDrag);\r\n eventjs[eventjsFunctor](canvasElement, 'orientation', this._onOrientationChange);\r\n eventjs[eventjsFunctor](canvasElement, 'shake', this._onShake);\r\n eventjs[eventjsFunctor](canvasElement, 'longpress', this._onLongPress);\r\n }\r\n },\r\n\r\n /**\r\n * Removes all event listeners\r\n */\r\n removeListeners: function() {\r\n this.addOrRemove(removeListener, 'remove');\r\n // if you dispose on a mouseDown, before mouse up, you need to clean document to...\r\n var eventTypePrefix = this._getEventPrefix();\r\n removeListener(fabric.document, eventTypePrefix + 'up', this._onMouseUp);\r\n removeListener(fabric.document, 'touchend', this._onTouchEnd, addEventOptions);\r\n removeListener(fabric.document, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\r\n removeListener(fabric.document, 'touchmove', this._onMouseMove, addEventOptions);\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _bindEvents: function() {\r\n if (this.eventsBound) {\r\n // for any reason we pass here twice we do not want to bind events twice.\r\n return;\r\n }\r\n this._onMouseDown = this._onMouseDown.bind(this);\r\n this._onTouchStart = this._onTouchStart.bind(this);\r\n this._onMouseMove = this._onMouseMove.bind(this);\r\n this._onMouseUp = this._onMouseUp.bind(this);\r\n this._onTouchEnd = this._onTouchEnd.bind(this);\r\n this._onResize = this._onResize.bind(this);\r\n this._onGesture = this._onGesture.bind(this);\r\n this._onDrag = this._onDrag.bind(this);\r\n this._onShake = this._onShake.bind(this);\r\n this._onLongPress = this._onLongPress.bind(this);\r\n this._onOrientationChange = this._onOrientationChange.bind(this);\r\n this._onMouseWheel = this._onMouseWheel.bind(this);\r\n this._onMouseOut = this._onMouseOut.bind(this);\r\n this._onMouseEnter = this._onMouseEnter.bind(this);\r\n this._onContextMenu = this._onContextMenu.bind(this);\r\n this._onDoubleClick = this._onDoubleClick.bind(this);\r\n this._onDragOver = this._onDragOver.bind(this);\r\n this._onDragEnter = this._simpleEventHandler.bind(this, 'dragenter');\r\n this._onDragLeave = this._simpleEventHandler.bind(this, 'dragleave');\r\n this._onDrop = this._onDrop.bind(this);\r\n this.eventsBound = true;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} [e] Event object fired on Event.js gesture\r\n * @param {Event} [self] Inner Event object\r\n */\r\n _onGesture: function(e, self) {\r\n this.__onTransformGesture && this.__onTransformGesture(e, self);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} [e] Event object fired on Event.js drag\r\n * @param {Event} [self] Inner Event object\r\n */\r\n _onDrag: function(e, self) {\r\n this.__onDrag && this.__onDrag(e, self);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} [e] Event object fired on wheel event\r\n */\r\n _onMouseWheel: function(e) {\r\n this.__onMouseWheel(e);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object fired on mousedown\r\n */\r\n _onMouseOut: function(e) {\r\n var target = this._hoveredTarget;\r\n this.fire('mouse:out', { target: target, e: e });\r\n this._hoveredTarget = null;\r\n target && target.fire('mouseout', { e: e });\r\n\r\n var _this = this;\r\n this._hoveredTargets.forEach(function(_target){\r\n _this.fire('mouse:out', { target: target, e: e });\r\n _target && target.fire('mouseout', { e: e });\r\n });\r\n this._hoveredTargets = [];\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object fired on mouseenter\r\n */\r\n _onMouseEnter: function(e) {\r\n // This find target and consequent 'mouse:over' is used to\r\n // clear old instances on hovered target.\r\n // calling findTarget has the side effect of killing target.__corner.\r\n // as a short term fix we are not firing this if we are currently transforming.\r\n // as a long term fix we need to separate the action of finding a target with the\r\n // side effects we added to it.\r\n if (!this._currentTransform && !this.findTarget(e)) {\r\n this.fire('mouse:over', { target: null, e: e });\r\n this._hoveredTarget = null;\r\n this._hoveredTargets = [];\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} [e] Event object fired on Event.js orientation change\r\n * @param {Event} [self] Inner Event object\r\n */\r\n _onOrientationChange: function(e, self) {\r\n this.__onOrientationChange && this.__onOrientationChange(e, self);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} [e] Event object fired on Event.js shake\r\n * @param {Event} [self] Inner Event object\r\n */\r\n _onShake: function(e, self) {\r\n this.__onShake && this.__onShake(e, self);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} [e] Event object fired on Event.js shake\r\n * @param {Event} [self] Inner Event object\r\n */\r\n _onLongPress: function(e, self) {\r\n this.__onLongPress && this.__onLongPress(e, self);\r\n },\r\n\r\n /**\r\n * prevent default to allow drop event to be fired\r\n * @private\r\n * @param {Event} [e] Event object fired on Event.js shake\r\n */\r\n _onDragOver: function(e) {\r\n e.preventDefault();\r\n var target = this._simpleEventHandler('dragover', e);\r\n this._fireEnterLeaveEvents(target, e);\r\n },\r\n\r\n /**\r\n * `drop:before` is a an event that allow you to schedule logic\r\n * before the `drop` event. Prefer `drop` event always, but if you need\r\n * to run some drop-disabling logic on an event, since there is no way\r\n * to handle event handlers ordering, use `drop:before`\r\n * @param {Event} e\r\n */\r\n _onDrop: function (e) {\r\n this._simpleEventHandler('drop:before', e);\r\n return this._simpleEventHandler('drop', e);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object fired on mousedown\r\n */\r\n _onContextMenu: function (e) {\r\n if (this.stopContextMenu) {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n }\r\n return false;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object fired on mousedown\r\n */\r\n _onDoubleClick: function (e) {\r\n this._cacheTransformEventData(e);\r\n this._handleEvent(e, 'dblclick');\r\n this._resetTransformEventData(e);\r\n },\r\n\r\n /**\r\n * Return a the id of an event.\r\n * returns either the pointerId or the identifier or 0 for the mouse event\r\n * @private\r\n * @param {Event} evt Event object\r\n */\r\n getPointerId: function(evt) {\r\n var changedTouches = evt.changedTouches;\r\n\r\n if (changedTouches) {\r\n return changedTouches[0] && changedTouches[0].identifier;\r\n }\r\n\r\n if (this.enablePointerEvents) {\r\n return evt.pointerId;\r\n }\r\n\r\n return -1;\r\n },\r\n\r\n /**\r\n * Determines if an event has the id of the event that is considered main\r\n * @private\r\n * @param {evt} event Event object\r\n */\r\n _isMainEvent: function(evt) {\r\n if (evt.isPrimary === true) {\r\n return true;\r\n }\r\n if (evt.isPrimary === false) {\r\n return false;\r\n }\r\n if (evt.type === 'touchend' && evt.touches.length === 0) {\r\n return true;\r\n }\r\n if (evt.changedTouches) {\r\n return evt.changedTouches[0].identifier === this.mainTouchId;\r\n }\r\n return true;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object fired on mousedown\r\n */\r\n _onTouchStart: function(e) {\r\n e.preventDefault();\r\n if (this.mainTouchId === null) {\r\n this.mainTouchId = this.getPointerId(e);\r\n }\r\n this.__onMouseDown(e);\r\n this._resetTransformEventData();\r\n var canvasElement = this.upperCanvasEl,\r\n eventTypePrefix = this._getEventPrefix();\r\n addListener(fabric.document, 'touchend', this._onTouchEnd, addEventOptions);\r\n addListener(fabric.document, 'touchmove', this._onMouseMove, addEventOptions);\r\n // Unbind mousedown to prevent double triggers from touch devices\r\n removeListener(canvasElement, eventTypePrefix + 'down', this._onMouseDown);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object fired on mousedown\r\n */\r\n _onMouseDown: function (e) {\r\n this.__onMouseDown(e);\r\n this._resetTransformEventData();\r\n var canvasElement = this.upperCanvasEl,\r\n eventTypePrefix = this._getEventPrefix();\r\n removeListener(canvasElement, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\r\n addListener(fabric.document, eventTypePrefix + 'up', this._onMouseUp);\r\n addListener(fabric.document, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object fired on mousedown\r\n */\r\n _onTouchEnd: function(e) {\r\n if (e.touches.length > 0) {\r\n // if there are still touches stop here\r\n return;\r\n }\r\n this.__onMouseUp(e);\r\n this._resetTransformEventData();\r\n this.mainTouchId = null;\r\n var eventTypePrefix = this._getEventPrefix();\r\n removeListener(fabric.document, 'touchend', this._onTouchEnd, addEventOptions);\r\n removeListener(fabric.document, 'touchmove', this._onMouseMove, addEventOptions);\r\n var _this = this;\r\n if (this._willAddMouseDown) {\r\n clearTimeout(this._willAddMouseDown);\r\n }\r\n this._willAddMouseDown = setTimeout(function() {\r\n // Wait 400ms before rebinding mousedown to prevent double triggers\r\n // from touch devices\r\n addListener(_this.upperCanvasEl, eventTypePrefix + 'down', _this._onMouseDown);\r\n _this._willAddMouseDown = 0;\r\n }, 400);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object fired on mouseup\r\n */\r\n _onMouseUp: function (e) {\r\n this.__onMouseUp(e);\r\n this._resetTransformEventData();\r\n var canvasElement = this.upperCanvasEl,\r\n eventTypePrefix = this._getEventPrefix();\r\n if (this._isMainEvent(e)) {\r\n removeListener(fabric.document, eventTypePrefix + 'up', this._onMouseUp);\r\n removeListener(fabric.document, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\r\n addListener(canvasElement, eventTypePrefix + 'move', this._onMouseMove, addEventOptions);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object fired on mousemove\r\n */\r\n _onMouseMove: function (e) {\r\n !this.allowTouchScrolling && e.preventDefault && e.preventDefault();\r\n this.__onMouseMove(e);\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _onResize: function () {\r\n this.calcOffset();\r\n },\r\n\r\n /**\r\n * Decides whether the canvas should be redrawn in mouseup and mousedown events.\r\n * @private\r\n * @param {Object} target\r\n */\r\n _shouldRender: function(target) {\r\n var activeObject = this._activeObject;\r\n\r\n if (\r\n !!activeObject !== !!target ||\r\n (activeObject && target && (activeObject !== target))\r\n ) {\r\n // this covers: switch of target, from target to no target, selection of target\r\n // multiSelection with key and mouse\r\n return true;\r\n }\r\n else if (activeObject && activeObject.isEditing) {\r\n // if we mouse up/down over a editing textbox a cursor change,\r\n // there is no need to re render\r\n return false;\r\n }\r\n return false;\r\n },\r\n\r\n /**\r\n * Method that defines the actions when mouse is released on canvas.\r\n * The method resets the currentTransform parameters, store the image corner\r\n * position in the image object and render the canvas on top.\r\n * @private\r\n * @param {Event} e Event object fired on mouseup\r\n */\r\n __onMouseUp: function (e) {\r\n var target, transform = this._currentTransform,\r\n groupSelector = this._groupSelector, shouldRender = false,\r\n isClick = (!groupSelector || (groupSelector.left === 0 && groupSelector.top === 0));\r\n this._cacheTransformEventData(e);\r\n target = this._target;\r\n this._handleEvent(e, 'up:before');\r\n // if right/middle click just fire events and return\r\n // target undefined will make the _handleEvent search the target\r\n if (checkClick(e, RIGHT_CLICK)) {\r\n if (this.fireRightClick) {\r\n this._handleEvent(e, 'up', RIGHT_CLICK, isClick);\r\n }\r\n return;\r\n }\r\n\r\n if (checkClick(e, MIDDLE_CLICK)) {\r\n if (this.fireMiddleClick) {\r\n this._handleEvent(e, 'up', MIDDLE_CLICK, isClick);\r\n }\r\n this._resetTransformEventData();\r\n return;\r\n }\r\n\r\n if (this.isDrawingMode && this._isCurrentlyDrawing) {\r\n this._onMouseUpInDrawingMode(e);\r\n return;\r\n }\r\n\r\n if (!this._isMainEvent(e)) {\r\n return;\r\n }\r\n if (transform) {\r\n this._finalizeCurrentTransform(e);\r\n shouldRender = transform.actionPerformed;\r\n }\r\n if (!isClick) {\r\n var targetWasActive = target === this._activeObject;\r\n this._maybeGroupObjects(e);\r\n if (!shouldRender) {\r\n shouldRender = (\r\n this._shouldRender(target) ||\r\n (!targetWasActive && target === this._activeObject)\r\n );\r\n }\r\n }\r\n var corner, pointer;\r\n if (target) {\r\n corner = target._findTargetCorner(\r\n this.getPointer(e, true),\r\n fabric.util.isTouchEvent(e)\r\n );\r\n if (target.selectable && target !== this._activeObject && target.activeOn === 'up') {\r\n this.setActiveObject(target, e);\r\n shouldRender = true;\r\n }\r\n else {\r\n var control = target.controls[corner],\r\n mouseUpHandler = control && control.getMouseUpHandler(e, target, control);\r\n if (mouseUpHandler) {\r\n pointer = this.getPointer(e);\r\n mouseUpHandler(e, transform, pointer.x, pointer.y);\r\n }\r\n }\r\n target.isMoving = false;\r\n }\r\n // if we are ending up a transform on a different control or a new object\r\n // fire the original mouse up from the corner that started the transform\r\n if (transform && (transform.target !== target || transform.corner !== corner)) {\r\n var originalControl = transform.target && transform.target.controls[transform.corner],\r\n originalMouseUpHandler = originalControl && originalControl.getMouseUpHandler(e, target, control);\r\n pointer = pointer || this.getPointer(e);\r\n originalMouseUpHandler && originalMouseUpHandler(e, transform, pointer.x, pointer.y);\r\n }\r\n this._setCursorFromEvent(e, target);\r\n this._handleEvent(e, 'up', LEFT_CLICK, isClick);\r\n this._groupSelector = null;\r\n this._currentTransform = null;\r\n // reset the target information about which corner is selected\r\n target && (target.__corner = 0);\r\n if (shouldRender) {\r\n this.requestRenderAll();\r\n }\r\n else if (!isClick) {\r\n this.renderTop();\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * Handle event firing for target and subtargets\r\n * @param {Event} e event from mouse\r\n * @param {String} eventType event to fire (up, down or move)\r\n * @return {Fabric.Object} target return the the target found, for internal reasons.\r\n */\r\n _simpleEventHandler: function(eventType, e) {\r\n var target = this.findTarget(e),\r\n targets = this.targets,\r\n options = {\r\n e: e,\r\n target: target,\r\n subTargets: targets,\r\n };\r\n this.fire(eventType, options);\r\n target && target.fire(eventType, options);\r\n if (!targets) {\r\n return target;\r\n }\r\n for (var i = 0; i < targets.length; i++) {\r\n targets[i].fire(eventType, options);\r\n }\r\n return target;\r\n },\r\n\r\n /**\r\n * @private\r\n * Handle event firing for target and subtargets\r\n * @param {Event} e event from mouse\r\n * @param {String} eventType event to fire (up, down or move)\r\n * @param {fabric.Object} targetObj receiving event\r\n * @param {Number} [button] button used in the event 1 = left, 2 = middle, 3 = right\r\n * @param {Boolean} isClick for left button only, indicates that the mouse up happened without move.\r\n */\r\n _handleEvent: function(e, eventType, button, isClick) {\r\n var target = this._target,\r\n targets = this.targets || [],\r\n options = {\r\n e: e,\r\n target: target,\r\n subTargets: targets,\r\n button: button || LEFT_CLICK,\r\n isClick: isClick || false,\r\n pointer: this._pointer,\r\n absolutePointer: this._absolutePointer,\r\n transform: this._currentTransform\r\n };\r\n if (eventType === 'up') {\r\n options.currentTarget = this.findTarget(e);\r\n options.currentSubTargets = this.targets;\r\n }\r\n this.fire('mouse:' + eventType, options);\r\n target && target.fire('mouse' + eventType, options);\r\n for (var i = 0; i < targets.length; i++) {\r\n targets[i].fire('mouse' + eventType, options);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e send the mouse event that generate the finalize down, so it can be used in the event\r\n */\r\n _finalizeCurrentTransform: function(e) {\r\n\r\n var transform = this._currentTransform,\r\n target = transform.target,\r\n options = {\r\n e: e,\r\n target: target,\r\n transform: transform,\r\n action: transform.action,\r\n };\r\n\r\n if (target._scaling) {\r\n target._scaling = false;\r\n }\r\n\r\n target.setCoords();\r\n\r\n if (transform.actionPerformed || (this.stateful && target.hasStateChanged())) {\r\n this._fire('modified', options);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object fired on mousedown\r\n */\r\n _onMouseDownInDrawingMode: function(e) {\r\n this._isCurrentlyDrawing = true;\r\n if (this.getActiveObject()) {\r\n this.discardActiveObject(e).requestRenderAll();\r\n }\r\n var pointer = this.getPointer(e);\r\n this.freeDrawingBrush.onMouseDown(pointer, { e: e, pointer: pointer });\r\n this._handleEvent(e, 'down');\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object fired on mousemove\r\n */\r\n _onMouseMoveInDrawingMode: function(e) {\r\n if (this._isCurrentlyDrawing) {\r\n var pointer = this.getPointer(e);\r\n this.freeDrawingBrush.onMouseMove(pointer, { e: e, pointer: pointer });\r\n }\r\n this.setCursor(this.freeDrawingCursor);\r\n this._handleEvent(e, 'move');\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object fired on mouseup\r\n */\r\n _onMouseUpInDrawingMode: function(e) {\r\n var pointer = this.getPointer(e);\r\n this._isCurrentlyDrawing = this.freeDrawingBrush.onMouseUp({ e: e, pointer: pointer });\r\n this._handleEvent(e, 'up');\r\n },\r\n\r\n /**\r\n * Method that defines the actions when mouse is clicked on canvas.\r\n * The method inits the currentTransform parameters and renders all the\r\n * canvas so the current image can be placed on the top canvas and the rest\r\n * in on the container one.\r\n * @private\r\n * @param {Event} e Event object fired on mousedown\r\n */\r\n __onMouseDown: function (e) {\r\n this._cacheTransformEventData(e);\r\n this._handleEvent(e, 'down:before');\r\n var target = this._target;\r\n // if right click just fire events\r\n if (checkClick(e, RIGHT_CLICK)) {\r\n if (this.fireRightClick) {\r\n this._handleEvent(e, 'down', RIGHT_CLICK);\r\n }\r\n return;\r\n }\r\n\r\n if (checkClick(e, MIDDLE_CLICK)) {\r\n if (this.fireMiddleClick) {\r\n this._handleEvent(e, 'down', MIDDLE_CLICK);\r\n }\r\n return;\r\n }\r\n\r\n if (this.isDrawingMode) {\r\n this._onMouseDownInDrawingMode(e);\r\n return;\r\n }\r\n\r\n if (!this._isMainEvent(e)) {\r\n return;\r\n }\r\n\r\n // ignore if some object is being transformed at this moment\r\n if (this._currentTransform) {\r\n return;\r\n }\r\n\r\n var pointer = this._pointer;\r\n // save pointer for check in __onMouseUp event\r\n this._previousPointer = pointer;\r\n var shouldRender = this._shouldRender(target),\r\n shouldGroup = this._shouldGroup(e, target);\r\n if (this._shouldClearSelection(e, target)) {\r\n this.discardActiveObject(e);\r\n }\r\n else if (shouldGroup) {\r\n this._handleGrouping(e, target);\r\n target = this._activeObject;\r\n }\r\n\r\n if (this.selection && (!target ||\r\n (!target.selectable && !target.isEditing && target !== this._activeObject))) {\r\n this._groupSelector = {\r\n ex: this._absolutePointer.x,\r\n ey: this._absolutePointer.y,\r\n top: 0,\r\n left: 0\r\n };\r\n }\r\n\r\n if (target) {\r\n var alreadySelected = target === this._activeObject;\r\n if (target.selectable && target.activeOn === 'down') {\r\n this.setActiveObject(target, e);\r\n }\r\n var corner = target._findTargetCorner(\r\n this.getPointer(e, true),\r\n fabric.util.isTouchEvent(e)\r\n );\r\n target.__corner = corner;\r\n if (target === this._activeObject && (corner || !shouldGroup)) {\r\n this._setupCurrentTransform(e, target, alreadySelected);\r\n var control = target.controls[corner],\r\n pointer = this.getPointer(e),\r\n mouseDownHandler = control && control.getMouseDownHandler(e, target, control);\r\n if (mouseDownHandler) {\r\n mouseDownHandler(e, this._currentTransform, pointer.x, pointer.y);\r\n }\r\n }\r\n }\r\n this._handleEvent(e, 'down');\r\n // we must renderAll so that we update the visuals\r\n (shouldRender || shouldGroup) && this.requestRenderAll();\r\n },\r\n\r\n /**\r\n * reset cache form common information needed during event processing\r\n * @private\r\n */\r\n _resetTransformEventData: function() {\r\n this._target = null;\r\n this._pointer = null;\r\n this._absolutePointer = null;\r\n },\r\n\r\n /**\r\n * Cache common information needed during event processing\r\n * @private\r\n * @param {Event} e Event object fired on event\r\n */\r\n _cacheTransformEventData: function(e) {\r\n // reset in order to avoid stale caching\r\n this._resetTransformEventData();\r\n this._pointer = this.getPointer(e, true);\r\n this._absolutePointer = this.restorePointerVpt(this._pointer);\r\n this._target = this._currentTransform ? this._currentTransform.target : this.findTarget(e) || null;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _beforeTransform: function(e) {\r\n var t = this._currentTransform;\r\n this.stateful && t.target.saveState();\r\n this.fire('before:transform', {\r\n e: e,\r\n transform: t,\r\n });\r\n },\r\n\r\n /**\r\n * Method that defines the actions when mouse is hovering the canvas.\r\n * The currentTransform parameter will define whether the user is rotating/scaling/translating\r\n * an image or neither of them (only hovering). A group selection is also possible and would cancel\r\n * all any other type of action.\r\n * In case of an image transformation only the top canvas will be rendered.\r\n * @private\r\n * @param {Event} e Event object fired on mousemove\r\n */\r\n __onMouseMove: function (e) {\r\n this._handleEvent(e, 'move:before');\r\n this._cacheTransformEventData(e);\r\n var target, pointer;\r\n\r\n if (this.isDrawingMode) {\r\n this._onMouseMoveInDrawingMode(e);\r\n return;\r\n }\r\n\r\n if (!this._isMainEvent(e)) {\r\n return;\r\n }\r\n\r\n var groupSelector = this._groupSelector;\r\n\r\n // We initially clicked in an empty area, so we draw a box for multiple selection\r\n if (groupSelector) {\r\n pointer = this._absolutePointer;\r\n\r\n groupSelector.left = pointer.x - groupSelector.ex;\r\n groupSelector.top = pointer.y - groupSelector.ey;\r\n\r\n this.renderTop();\r\n }\r\n else if (!this._currentTransform) {\r\n target = this.findTarget(e) || null;\r\n this._setCursorFromEvent(e, target);\r\n this._fireOverOutEvents(target, e);\r\n }\r\n else {\r\n this._transformObject(e);\r\n }\r\n this._handleEvent(e, 'move');\r\n this._resetTransformEventData();\r\n },\r\n\r\n /**\r\n * Manage the mouseout, mouseover events for the fabric object on the canvas\r\n * @param {Fabric.Object} target the target where the target from the mousemove event\r\n * @param {Event} e Event object fired on mousemove\r\n * @private\r\n */\r\n _fireOverOutEvents: function(target, e) {\r\n var _hoveredTarget = this._hoveredTarget,\r\n _hoveredTargets = this._hoveredTargets, targets = this.targets,\r\n length = Math.max(_hoveredTargets.length, targets.length);\r\n\r\n this.fireSyntheticInOutEvents(target, e, {\r\n oldTarget: _hoveredTarget,\r\n evtOut: 'mouseout',\r\n canvasEvtOut: 'mouse:out',\r\n evtIn: 'mouseover',\r\n canvasEvtIn: 'mouse:over',\r\n });\r\n for (var i = 0; i < length; i++){\r\n this.fireSyntheticInOutEvents(targets[i], e, {\r\n oldTarget: _hoveredTargets[i],\r\n evtOut: 'mouseout',\r\n evtIn: 'mouseover',\r\n });\r\n }\r\n this._hoveredTarget = target;\r\n this._hoveredTargets = this.targets.concat();\r\n },\r\n\r\n /**\r\n * Manage the dragEnter, dragLeave events for the fabric objects on the canvas\r\n * @param {Fabric.Object} target the target where the target from the onDrag event\r\n * @param {Event} e Event object fired on ondrag\r\n * @private\r\n */\r\n _fireEnterLeaveEvents: function(target, e) {\r\n var _draggedoverTarget = this._draggedoverTarget,\r\n _hoveredTargets = this._hoveredTargets, targets = this.targets,\r\n length = Math.max(_hoveredTargets.length, targets.length);\r\n\r\n this.fireSyntheticInOutEvents(target, e, {\r\n oldTarget: _draggedoverTarget,\r\n evtOut: 'dragleave',\r\n evtIn: 'dragenter',\r\n });\r\n for (var i = 0; i < length; i++) {\r\n this.fireSyntheticInOutEvents(targets[i], e, {\r\n oldTarget: _hoveredTargets[i],\r\n evtOut: 'dragleave',\r\n evtIn: 'dragenter',\r\n });\r\n }\r\n this._draggedoverTarget = target;\r\n },\r\n\r\n /**\r\n * Manage the synthetic in/out events for the fabric objects on the canvas\r\n * @param {Fabric.Object} target the target where the target from the supported events\r\n * @param {Event} e Event object fired\r\n * @param {Object} config configuration for the function to work\r\n * @param {String} config.targetName property on the canvas where the old target is stored\r\n * @param {String} [config.canvasEvtOut] name of the event to fire at canvas level for out\r\n * @param {String} config.evtOut name of the event to fire for out\r\n * @param {String} [config.canvasEvtIn] name of the event to fire at canvas level for in\r\n * @param {String} config.evtIn name of the event to fire for in\r\n * @private\r\n */\r\n fireSyntheticInOutEvents: function(target, e, config) {\r\n var inOpt, outOpt, oldTarget = config.oldTarget, outFires, inFires,\r\n targetChanged = oldTarget !== target, canvasEvtIn = config.canvasEvtIn, canvasEvtOut = config.canvasEvtOut;\r\n if (targetChanged) {\r\n inOpt = { e: e, target: target, previousTarget: oldTarget };\r\n outOpt = { e: e, target: oldTarget, nextTarget: target };\r\n }\r\n inFires = target && targetChanged;\r\n outFires = oldTarget && targetChanged;\r\n if (outFires) {\r\n canvasEvtOut && this.fire(canvasEvtOut, outOpt);\r\n oldTarget.fire(config.evtOut, outOpt);\r\n }\r\n if (inFires) {\r\n canvasEvtIn && this.fire(canvasEvtIn, inOpt);\r\n target.fire(config.evtIn, inOpt);\r\n }\r\n },\r\n\r\n /**\r\n * Method that defines actions when an Event Mouse Wheel\r\n * @param {Event} e Event object fired on mouseup\r\n */\r\n __onMouseWheel: function(e) {\r\n this._cacheTransformEventData(e);\r\n this._handleEvent(e, 'wheel');\r\n this._resetTransformEventData();\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event fired on mousemove\r\n */\r\n _transformObject: function(e) {\r\n var pointer = this.getPointer(e),\r\n transform = this._currentTransform;\r\n\r\n transform.reset = false;\r\n transform.shiftKey = e.shiftKey;\r\n transform.altKey = e[this.centeredKey];\r\n\r\n this._performTransformAction(e, transform, pointer);\r\n transform.actionPerformed && this.requestRenderAll();\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _performTransformAction: function(e, transform, pointer) {\r\n var x = pointer.x,\r\n y = pointer.y,\r\n action = transform.action,\r\n actionPerformed = false,\r\n actionHandler = transform.actionHandler;\r\n // this object could be created from the function in the control handlers\r\n\r\n\r\n if (actionHandler) {\r\n actionPerformed = actionHandler(e, transform, x, y);\r\n }\r\n if (action === 'drag' && actionPerformed) {\r\n transform.target.isMoving = true;\r\n this.setCursor(transform.target.moveCursor || this.moveCursor);\r\n }\r\n transform.actionPerformed = transform.actionPerformed || actionPerformed;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _fire: fabric.controlsUtils.fireEvent,\r\n\r\n /**\r\n * Sets the cursor depending on where the canvas is being hovered.\r\n * Note: very buggy in Opera\r\n * @param {Event} e Event object\r\n * @param {Object} target Object that the mouse is hovering, if so.\r\n */\r\n _setCursorFromEvent: function (e, target) {\r\n if (!target) {\r\n this.setCursor(this.defaultCursor);\r\n return false;\r\n }\r\n var hoverCursor = target.hoverCursor || this.hoverCursor,\r\n activeSelection = this._activeObject && this._activeObject.type === 'activeSelection' ?\r\n this._activeObject : null,\r\n // only show proper corner when group selection is not active\r\n corner = (!activeSelection || !activeSelection.contains(target))\r\n // here we call findTargetCorner always with undefined for the touch parameter.\r\n // we assume that if you are using a cursor you do not need to interact with\r\n // the bigger touch area.\r\n && target._findTargetCorner(this.getPointer(e, true));\r\n\r\n if (!corner) {\r\n if (target.subTargetCheck){\r\n // hoverCursor should come from top-most subTarget,\r\n // so we walk the array backwards\r\n this.targets.concat().reverse().map(function(_target){\r\n hoverCursor = _target.hoverCursor || hoverCursor;\r\n });\r\n }\r\n this.setCursor(hoverCursor);\r\n }\r\n else {\r\n this.setCursor(this.getCornerCursor(corner, target, e));\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n getCornerCursor: function(corner, target, e) {\r\n var control = target.controls[corner];\r\n return control.cursorStyleHandler(e, control, target);\r\n }\r\n });\r\n})();\r\n\r\n\r\n(function() {\r\n\r\n var min = Math.min,\r\n max = Math.max;\r\n\r\n fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ {\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object\r\n * @param {fabric.Object} target\r\n * @return {Boolean}\r\n */\r\n _shouldGroup: function(e, target) {\r\n var activeObject = this._activeObject;\r\n return activeObject && this._isSelectionKeyPressed(e) && target && target.selectable && this.selection &&\r\n (activeObject !== target || activeObject.type === 'activeSelection') && !target.onSelect({ e: e });\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e Event object\r\n * @param {fabric.Object} target\r\n */\r\n _handleGrouping: function (e, target) {\r\n var activeObject = this._activeObject;\r\n // avoid multi select when shift click on a corner\r\n if (activeObject.__corner) {\r\n return;\r\n }\r\n if (target === activeObject) {\r\n // if it's a group, find target again, using activeGroup objects\r\n target = this.findTarget(e, true);\r\n // if even object is not found or we are on activeObjectCorner, bail out\r\n if (!target || !target.selectable) {\r\n return;\r\n }\r\n }\r\n if (activeObject && activeObject.type === 'activeSelection') {\r\n this._updateActiveSelection(target, e);\r\n }\r\n else {\r\n this._createActiveSelection(target, e);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _updateActiveSelection: function(target, e) {\r\n var activeSelection = this._activeObject,\r\n currentActiveObjects = activeSelection._objects.slice(0);\r\n if (activeSelection.contains(target)) {\r\n activeSelection.removeWithUpdate(target);\r\n this._hoveredTarget = target;\r\n this._hoveredTargets = this.targets.concat();\r\n if (activeSelection.size() === 1) {\r\n // activate last remaining object\r\n this._setActiveObject(activeSelection.item(0), e);\r\n }\r\n }\r\n else {\r\n activeSelection.addWithUpdate(target);\r\n this._hoveredTarget = activeSelection;\r\n this._hoveredTargets = this.targets.concat();\r\n }\r\n this._fireSelectionEvents(currentActiveObjects, e);\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _createActiveSelection: function(target, e) {\r\n var currentActives = this.getActiveObjects(), group = this._createGroup(target);\r\n this._hoveredTarget = group;\r\n // ISSUE 4115: should we consider subTargets here?\r\n // this._hoveredTargets = [];\r\n // this._hoveredTargets = this.targets.concat();\r\n this._setActiveObject(group, e);\r\n this._fireSelectionEvents(currentActives, e);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Object} target\r\n */\r\n _createGroup: function(target) {\r\n var objects = this._objects,\r\n isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target),\r\n groupObjects = isActiveLower\r\n ? [this._activeObject, target]\r\n : [target, this._activeObject];\r\n this._activeObject.isEditing && this._activeObject.exitEditing();\r\n return new fabric.ActiveSelection(groupObjects, {\r\n canvas: this\r\n });\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Event} e mouse event\r\n */\r\n _groupSelectedObjects: function (e) {\r\n\r\n var group = this._collectObjects(e),\r\n aGroup;\r\n\r\n // do not create group for 1 element only\r\n if (group.length === 1) {\r\n this.setActiveObject(group[0], e);\r\n }\r\n else if (group.length > 1) {\r\n aGroup = new fabric.ActiveSelection(group.reverse(), {\r\n canvas: this\r\n });\r\n this.setActiveObject(aGroup, e);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _collectObjects: function(e) {\r\n var group = [],\r\n currentObject,\r\n x1 = this._groupSelector.ex,\r\n y1 = this._groupSelector.ey,\r\n x2 = x1 + this._groupSelector.left,\r\n y2 = y1 + this._groupSelector.top,\r\n selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)),\r\n selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)),\r\n allowIntersect = !this.selectionFullyContained,\r\n isClick = x1 === x2 && y1 === y2;\r\n // we iterate reverse order to collect top first in case of click.\r\n for (var i = this._objects.length; i--; ) {\r\n currentObject = this._objects[i];\r\n\r\n if (!currentObject || !currentObject.selectable || !currentObject.visible) {\r\n continue;\r\n }\r\n\r\n if ((allowIntersect && currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2, true)) ||\r\n currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2, true) ||\r\n (allowIntersect && currentObject.containsPoint(selectionX1Y1, null, true)) ||\r\n (allowIntersect && currentObject.containsPoint(selectionX2Y2, null, true))\r\n ) {\r\n group.push(currentObject);\r\n // only add one object if it's a click\r\n if (isClick) {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (group.length > 1) {\r\n group = group.filter(function(object) {\r\n return !object.onSelect({ e: e });\r\n });\r\n }\r\n\r\n return group;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _maybeGroupObjects: function(e) {\r\n if (this.selection && this._groupSelector) {\r\n this._groupSelectedObjects(e);\r\n }\r\n this.setCursor(this.defaultCursor);\r\n // clear selection and current transformation\r\n this._groupSelector = null;\r\n }\r\n });\r\n\r\n})();\r\n\r\n\r\n(function () {\r\n fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\r\n\r\n /**\r\n * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately\r\n * @param {Object} [options] Options object\r\n * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\r\n * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\r\n * @param {Number} [options.multiplier=1] Multiplier to scale by, to have consistent\r\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\r\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\r\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\r\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\r\n * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 2.0.0\r\n * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format\r\n * @see {@link http://jsfiddle.net/fabricjs/NfZVb/|jsFiddle demo}\r\n * @example Generate jpeg dataURL with lower quality\r\n * var dataURL = canvas.toDataURL({\r\n * format: 'jpeg',\r\n * quality: 0.8\r\n * });\r\n * @example Generate cropped png dataURL (clipping of canvas)\r\n * var dataURL = canvas.toDataURL({\r\n * format: 'png',\r\n * left: 100,\r\n * top: 100,\r\n * width: 200,\r\n * height: 200\r\n * });\r\n * @example Generate double scaled png dataURL\r\n * var dataURL = canvas.toDataURL({\r\n * format: 'png',\r\n * multiplier: 2\r\n * });\r\n */\r\n toDataURL: function (options) {\r\n options || (options = { });\r\n\r\n var format = options.format || 'png',\r\n quality = options.quality || 1,\r\n multiplier = (options.multiplier || 1) * (options.enableRetinaScaling ? this.getRetinaScaling() : 1),\r\n canvasEl = this.toCanvasElement(multiplier, options);\r\n return fabric.util.toDataURL(canvasEl, format, quality);\r\n },\r\n\r\n /**\r\n * Create a new HTMLCanvas element painted with the current canvas content.\r\n * No need to resize the actual one or repaint it.\r\n * Will transfer object ownership to a new canvas, paint it, and set everything back.\r\n * This is an intermediary step used to get to a dataUrl but also it is useful to\r\n * create quick image copies of a canvas without passing for the dataUrl string\r\n * @param {Number} [multiplier] a zoom factor.\r\n * @param {Object} [cropping] Cropping informations\r\n * @param {Number} [cropping.left] Cropping left offset.\r\n * @param {Number} [cropping.top] Cropping top offset.\r\n * @param {Number} [cropping.width] Cropping width.\r\n * @param {Number} [cropping.height] Cropping height.\r\n */\r\n toCanvasElement: function(multiplier, cropping) {\r\n multiplier = multiplier || 1;\r\n cropping = cropping || { };\r\n var scaledWidth = (cropping.width || this.width) * multiplier,\r\n scaledHeight = (cropping.height || this.height) * multiplier,\r\n zoom = this.getZoom(),\r\n originalWidth = this.width,\r\n originalHeight = this.height,\r\n newZoom = zoom * multiplier,\r\n vp = this.viewportTransform,\r\n translateX = (vp[4] - (cropping.left || 0)) * multiplier,\r\n translateY = (vp[5] - (cropping.top || 0)) * multiplier,\r\n originalInteractive = this.interactive,\r\n newVp = [newZoom, 0, 0, newZoom, translateX, translateY],\r\n originalRetina = this.enableRetinaScaling,\r\n canvasEl = fabric.util.createCanvasElement(),\r\n originalContextTop = this.contextTop;\r\n canvasEl.width = scaledWidth;\r\n canvasEl.height = scaledHeight;\r\n this.contextTop = null;\r\n this.enableRetinaScaling = false;\r\n this.interactive = false;\r\n this.viewportTransform = newVp;\r\n this.width = scaledWidth;\r\n this.height = scaledHeight;\r\n this.calcViewportBoundaries();\r\n this.renderCanvas(canvasEl.getContext('2d', { willReadFrequently: true }), this._objects);\r\n this.viewportTransform = vp;\r\n this.width = originalWidth;\r\n this.height = originalHeight;\r\n this.calcViewportBoundaries();\r\n this.interactive = originalInteractive;\r\n this.enableRetinaScaling = originalRetina;\r\n this.contextTop = originalContextTop;\r\n return canvasEl;\r\n },\r\n });\r\n\r\n})();\r\n\r\n\r\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\r\n /**\r\n * Populates canvas with data from the specified JSON.\r\n * JSON format must conform to the one of {@link fabric.Canvas#toJSON}\r\n * @param {String|Object} json JSON string or object\r\n * @param {Function} callback Callback, invoked when json is parsed\r\n * and corresponding objects (e.g: {@link fabric.Image})\r\n * are initialized\r\n * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created.\r\n * @return {fabric.Canvas} instance\r\n * @chainable\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#deserialization}\r\n * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo}\r\n * @example loadFromJSON\r\n * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));\r\n * @example loadFromJSON with reviver\r\n * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas), function(o, object) {\r\n * // `o` = json object\r\n * // `object` = fabric.Object instance\r\n * // ... do some stuff ...\r\n * });\r\n */\r\n loadFromJSON: function (json, callback, reviver) {\r\n if (!json) {\r\n return;\r\n }\r\n\r\n // serialize if it wasn't already\r\n var serialized = (typeof json === 'string')\r\n ? JSON.parse(json)\r\n : fabric.util.object.clone(json);\r\n\r\n var _this = this,\r\n clipPath = serialized.clipPath,\r\n renderOnAddRemove = this.renderOnAddRemove;\r\n\r\n this.renderOnAddRemove = false;\r\n\r\n delete serialized.clipPath;\r\n\r\n this._enlivenObjects(serialized.objects, function (enlivenedObjects) {\r\n _this.clear();\r\n _this._setBgOverlay(serialized, function () {\r\n if (clipPath) {\r\n _this._enlivenObjects([clipPath], function (enlivenedCanvasClip) {\r\n _this.clipPath = enlivenedCanvasClip[0];\r\n _this.__setupCanvas.call(_this, serialized, enlivenedObjects, renderOnAddRemove, callback);\r\n });\r\n }\r\n else {\r\n _this.__setupCanvas.call(_this, serialized, enlivenedObjects, renderOnAddRemove, callback);\r\n }\r\n });\r\n }, reviver);\r\n return this;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Object} serialized Object with background and overlay information\r\n * @param {Array} restored canvas objects\r\n * @param {Function} cached renderOnAddRemove callback\r\n * @param {Function} callback Invoked after all background and overlay images/patterns loaded\r\n */\r\n __setupCanvas: function(serialized, enlivenedObjects, renderOnAddRemove, callback) {\r\n var _this = this;\r\n enlivenedObjects.forEach(function(obj, index) {\r\n // we splice the array just in case some custom classes restored from JSON\r\n // will add more object to canvas at canvas init.\r\n _this.insertAt(obj, index);\r\n });\r\n this.renderOnAddRemove = renderOnAddRemove;\r\n // remove parts i cannot set as options\r\n delete serialized.objects;\r\n delete serialized.backgroundImage;\r\n delete serialized.overlayImage;\r\n delete serialized.background;\r\n delete serialized.overlay;\r\n // this._initOptions does too many things to just\r\n // call it. Normally loading an Object from JSON\r\n // create the Object instance. Here the Canvas is\r\n // already an instance and we are just loading things over it\r\n this._setOptions(serialized);\r\n this.renderAll();\r\n callback && callback();\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Object} serialized Object with background and overlay information\r\n * @param {Function} callback Invoked after all background and overlay images/patterns loaded\r\n */\r\n _setBgOverlay: function(serialized, callback) {\r\n var loaded = {\r\n backgroundColor: false,\r\n overlayColor: false,\r\n backgroundImage: false,\r\n overlayImage: false\r\n };\r\n\r\n if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background && !serialized.overlay) {\r\n callback && callback();\r\n return;\r\n }\r\n\r\n var cbIfLoaded = function () {\r\n if (loaded.backgroundImage && loaded.overlayImage && loaded.backgroundColor && loaded.overlayColor) {\r\n callback && callback();\r\n }\r\n };\r\n\r\n this.__setBgOverlay('backgroundImage', serialized.backgroundImage, loaded, cbIfLoaded);\r\n this.__setBgOverlay('overlayImage', serialized.overlayImage, loaded, cbIfLoaded);\r\n this.__setBgOverlay('backgroundColor', serialized.background, loaded, cbIfLoaded);\r\n this.__setBgOverlay('overlayColor', serialized.overlay, loaded, cbIfLoaded);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {String} property Property to set (backgroundImage, overlayImage, backgroundColor, overlayColor)\r\n * @param {(Object|String)} value Value to set\r\n * @param {Object} loaded Set loaded property to true if property is set\r\n * @param {Object} callback Callback function to invoke after property is set\r\n */\r\n __setBgOverlay: function(property, value, loaded, callback) {\r\n var _this = this;\r\n\r\n if (!value) {\r\n loaded[property] = true;\r\n callback && callback();\r\n return;\r\n }\r\n\r\n if (property === 'backgroundImage' || property === 'overlayImage') {\r\n fabric.util.enlivenObjects([value], function(enlivedObject){\r\n _this[property] = enlivedObject[0];\r\n loaded[property] = true;\r\n callback && callback();\r\n });\r\n }\r\n else {\r\n this['set' + fabric.util.string.capitalize(property, true)](value, function() {\r\n loaded[property] = true;\r\n callback && callback();\r\n });\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Array} objects\r\n * @param {Function} callback\r\n * @param {Function} [reviver]\r\n */\r\n _enlivenObjects: function (objects, callback, reviver) {\r\n if (!objects || objects.length === 0) {\r\n callback && callback([]);\r\n return;\r\n }\r\n\r\n fabric.util.enlivenObjects(objects, function(enlivenedObjects) {\r\n callback && callback(enlivenedObjects);\r\n }, null, reviver);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {String} format\r\n * @param {Function} callback\r\n */\r\n _toDataURL: function (format, callback) {\r\n this.clone(function (clone) {\r\n callback(clone.toDataURL(format));\r\n });\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {String} format\r\n * @param {Number} multiplier\r\n * @param {Function} callback\r\n */\r\n _toDataURLWithMultiplier: function (format, multiplier, callback) {\r\n this.clone(function (clone) {\r\n callback(clone.toDataURLWithMultiplier(format, multiplier));\r\n });\r\n },\r\n\r\n /**\r\n * Clones canvas instance\r\n * @param {Object} [callback] Receives cloned instance as a first argument\r\n * @param {Array} [properties] Array of properties to include in the cloned canvas and children\r\n */\r\n clone: function (callback, properties) {\r\n var data = JSON.stringify(this.toJSON(properties));\r\n this.cloneWithoutData(function(clone) {\r\n clone.loadFromJSON(data, function() {\r\n callback && callback(clone);\r\n });\r\n });\r\n },\r\n\r\n /**\r\n * Clones canvas instance without cloning existing data.\r\n * This essentially copies canvas dimensions, clipping properties, etc.\r\n * but leaves data empty (so that you can populate it with your own)\r\n * @param {Object} [callback] Receives cloned instance as a first argument\r\n */\r\n cloneWithoutData: function(callback) {\r\n var el = fabric.util.createCanvasElement();\r\n\r\n el.width = this.width;\r\n el.height = this.height;\r\n\r\n var clone = new fabric.Canvas(el);\r\n if (this.backgroundImage) {\r\n clone.setBackgroundImage(this.backgroundImage.src, function() {\r\n clone.renderAll();\r\n callback && callback(clone);\r\n });\r\n clone.backgroundImageOpacity = this.backgroundImageOpacity;\r\n clone.backgroundImageStretch = this.backgroundImageStretch;\r\n }\r\n else {\r\n callback && callback(clone);\r\n }\r\n }\r\n});\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n extend = fabric.util.object.extend,\r\n clone = fabric.util.object.clone,\r\n toFixed = fabric.util.toFixed,\r\n capitalize = fabric.util.string.capitalize,\r\n degreesToRadians = fabric.util.degreesToRadians,\r\n objectCaching = !fabric.isLikelyNode,\r\n ALIASING_LIMIT = 2;\r\n\r\n if (fabric.Object) {\r\n return;\r\n }\r\n\r\n /**\r\n * Root object class from which all 2d shape classes inherit from\r\n * @class fabric.Object\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#objects}\r\n * @see {@link fabric.Object#initialize} for constructor definition\r\n *\r\n * @fires added\r\n * @fires removed\r\n *\r\n * @fires selected\r\n * @fires deselected\r\n * @fires modified\r\n * @fires modified\r\n * @fires moved\r\n * @fires scaled\r\n * @fires rotated\r\n * @fires skewed\r\n *\r\n * @fires rotating\r\n * @fires scaling\r\n * @fires moving\r\n * @fires skewing\r\n *\r\n * @fires mousedown\r\n * @fires mouseup\r\n * @fires mouseover\r\n * @fires mouseout\r\n * @fires mousewheel\r\n * @fires mousedblclick\r\n *\r\n * @fires dragover\r\n * @fires dragenter\r\n * @fires dragleave\r\n * @fires drop\r\n */\r\n fabric.Object = fabric.util.createClass(fabric.CommonMethods, /** @lends fabric.Object.prototype */ {\r\n\r\n /**\r\n * Type of an object (rect, circle, path, etc.).\r\n * Note that this property is meant to be read-only and not meant to be modified.\r\n * If you modify, certain parts of Fabric (such as JSON loading) won't work correctly.\r\n * @type String\r\n * @default\r\n */\r\n type: 'object',\r\n\r\n /**\r\n * Horizontal origin of transformation of an object (one of \"left\", \"right\", \"center\")\r\n * See http://jsfiddle.net/1ow02gea/244/ on how originX/originY affect objects in groups\r\n * @type String\r\n * @default\r\n */\r\n originX: 'left',\r\n\r\n /**\r\n * Vertical origin of transformation of an object (one of \"top\", \"bottom\", \"center\")\r\n * See http://jsfiddle.net/1ow02gea/244/ on how originX/originY affect objects in groups\r\n * @type String\r\n * @default\r\n */\r\n originY: 'top',\r\n\r\n /**\r\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}\r\n * @type Number\r\n * @default\r\n */\r\n top: 0,\r\n\r\n /**\r\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}\r\n * @type Number\r\n * @default\r\n */\r\n left: 0,\r\n\r\n /**\r\n * Object width\r\n * @type Number\r\n * @default\r\n */\r\n width: 0,\r\n\r\n /**\r\n * Object height\r\n * @type Number\r\n * @default\r\n */\r\n height: 0,\r\n\r\n /**\r\n * Object scale factor (horizontal)\r\n * @type Number\r\n * @default\r\n */\r\n scaleX: 1,\r\n\r\n /**\r\n * Object scale factor (vertical)\r\n * @type Number\r\n * @default\r\n */\r\n scaleY: 1,\r\n\r\n /**\r\n * When true, an object is rendered as flipped horizontally\r\n * @type Boolean\r\n * @default\r\n */\r\n flipX: false,\r\n\r\n /**\r\n * When true, an object is rendered as flipped vertically\r\n * @type Boolean\r\n * @default\r\n */\r\n flipY: false,\r\n\r\n /**\r\n * Opacity of an object\r\n * @type Number\r\n * @default\r\n */\r\n opacity: 1,\r\n\r\n /**\r\n * Angle of rotation of an object (in degrees)\r\n * @type Number\r\n * @default\r\n */\r\n angle: 0,\r\n\r\n /**\r\n * Angle of skew on x axes of an object (in degrees)\r\n * @type Number\r\n * @default\r\n */\r\n skewX: 0,\r\n\r\n /**\r\n * Angle of skew on y axes of an object (in degrees)\r\n * @type Number\r\n * @default\r\n */\r\n skewY: 0,\r\n\r\n /**\r\n * Size of object's controlling corners (in pixels)\r\n * @type Number\r\n * @default\r\n */\r\n cornerSize: 13,\r\n\r\n /**\r\n * Size of object's controlling corners when touch interaction is detected\r\n * @type Number\r\n * @default\r\n */\r\n touchCornerSize: 24,\r\n\r\n /**\r\n * When true, object's controlling corners are rendered as transparent inside (i.e. stroke instead of fill)\r\n * @type Boolean\r\n * @default\r\n */\r\n transparentCorners: true,\r\n\r\n /**\r\n * Default cursor value used when hovering over this object on canvas\r\n * @type String\r\n * @default\r\n */\r\n hoverCursor: null,\r\n\r\n /**\r\n * Default cursor value used when moving this object on canvas\r\n * @type String\r\n * @default\r\n */\r\n moveCursor: null,\r\n\r\n /**\r\n * Padding between object and its controlling borders (in pixels)\r\n * @type Number\r\n * @default\r\n */\r\n padding: 0,\r\n\r\n /**\r\n * Color of controlling borders of an object (when it's active)\r\n * @type String\r\n * @default\r\n */\r\n borderColor: 'rgb(178,204,255)',\r\n\r\n /**\r\n * Array specifying dash pattern of an object's borders (hasBorder must be true)\r\n * @since 1.6.2\r\n * @type Array\r\n */\r\n borderDashArray: null,\r\n\r\n /**\r\n * Color of controlling corners of an object (when it's active)\r\n * @type String\r\n * @default\r\n */\r\n cornerColor: 'rgb(178,204,255)',\r\n\r\n /**\r\n * Color of controlling corners of an object (when it's active and transparentCorners false)\r\n * @since 1.6.2\r\n * @type String\r\n * @default\r\n */\r\n cornerStrokeColor: null,\r\n\r\n /**\r\n * Specify style of control, 'rect' or 'circle'\r\n * @since 1.6.2\r\n * @type String\r\n */\r\n cornerStyle: 'rect',\r\n\r\n /**\r\n * Array specifying dash pattern of an object's control (hasBorder must be true)\r\n * @since 1.6.2\r\n * @type Array\r\n */\r\n cornerDashArray: null,\r\n\r\n /**\r\n * When true, this object will use center point as the origin of transformation\r\n * when being scaled via the controls.\r\n * Backwards incompatibility note: This property replaces \"centerTransform\" (Boolean).\r\n * @since 1.3.4\r\n * @type Boolean\r\n * @default\r\n */\r\n centeredScaling: false,\r\n\r\n /**\r\n * When true, this object will use center point as the origin of transformation\r\n * when being rotated via the controls.\r\n * Backwards incompatibility note: This property replaces \"centerTransform\" (Boolean).\r\n * @since 1.3.4\r\n * @type Boolean\r\n * @default\r\n */\r\n centeredRotation: true,\r\n\r\n /**\r\n * Color of object's fill\r\n * takes css colors https://www.w3.org/TR/css-color-3/\r\n * @type String\r\n * @default\r\n */\r\n fill: 'rgb(0,0,0)',\r\n\r\n /**\r\n * Fill rule used to fill an object\r\n * accepted values are nonzero, evenodd\r\n * Backwards incompatibility note: This property was used for setting globalCompositeOperation until v1.4.12 (use `fabric.Object#globalCompositeOperation` instead)\r\n * @type String\r\n * @default\r\n */\r\n fillRule: 'nonzero',\r\n\r\n /**\r\n * Composite rule used for canvas globalCompositeOperation\r\n * @type String\r\n * @default\r\n */\r\n globalCompositeOperation: 'source-over',\r\n\r\n /**\r\n * Background color of an object.\r\n * takes css colors https://www.w3.org/TR/css-color-3/\r\n * @type String\r\n * @default\r\n */\r\n backgroundColor: '',\r\n\r\n /**\r\n * Selection Background color of an object. colored layer behind the object when it is active.\r\n * does not mix good with globalCompositeOperation methods.\r\n * @type String\r\n * @default\r\n */\r\n selectionBackgroundColor: '',\r\n\r\n /**\r\n * When defined, an object is rendered via stroke and this property specifies its color\r\n * takes css colors https://www.w3.org/TR/css-color-3/\r\n * @type String\r\n * @default\r\n */\r\n stroke: null,\r\n\r\n /**\r\n * Width of a stroke used to render this object\r\n * @type Number\r\n * @default\r\n */\r\n strokeWidth: 1,\r\n\r\n /**\r\n * Array specifying dash pattern of an object's stroke (stroke must be defined)\r\n * @type Array\r\n */\r\n strokeDashArray: null,\r\n\r\n /**\r\n * Line offset of an object's stroke\r\n * @type Number\r\n * @default\r\n */\r\n strokeDashOffset: 0,\r\n\r\n /**\r\n * Line endings style of an object's stroke (one of \"butt\", \"round\", \"square\")\r\n * @type String\r\n * @default\r\n */\r\n strokeLineCap: 'butt',\r\n\r\n /**\r\n * Corner style of an object's stroke (one of \"bevel\", \"round\", \"miter\")\r\n * @type String\r\n * @default\r\n */\r\n strokeLineJoin: 'miter',\r\n\r\n /**\r\n * Maximum miter length (used for strokeLineJoin = \"miter\") of an object's stroke\r\n * @type Number\r\n * @default\r\n */\r\n strokeMiterLimit: 4,\r\n\r\n /**\r\n * Shadow object representing shadow of this shape\r\n * @type fabric.Shadow\r\n * @default\r\n */\r\n shadow: null,\r\n\r\n /**\r\n * Opacity of object's controlling borders when object is active and moving\r\n * @type Number\r\n * @default\r\n */\r\n borderOpacityWhenMoving: 0.4,\r\n\r\n /**\r\n * Scale factor of object's controlling borders\r\n * bigger number will make a thicker border\r\n * border is 1, so this is basically a border thickness\r\n * since there is no way to change the border itself.\r\n * @type Number\r\n * @default\r\n */\r\n borderScaleFactor: 1,\r\n\r\n /**\r\n * Minimum allowed scale value of an object\r\n * @type Number\r\n * @default\r\n */\r\n minScaleLimit: 0,\r\n\r\n /**\r\n * When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection).\r\n * But events still fire on it.\r\n * @type Boolean\r\n * @default\r\n */\r\n selectable: true,\r\n\r\n /**\r\n * When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4\r\n * @type Boolean\r\n * @default\r\n */\r\n evented: true,\r\n\r\n /**\r\n * When set to `false`, an object is not rendered on canvas\r\n * @type Boolean\r\n * @default\r\n */\r\n visible: true,\r\n\r\n /**\r\n * When set to `false`, object's controls are not displayed and can not be used to manipulate object\r\n * @type Boolean\r\n * @default\r\n */\r\n hasControls: true,\r\n\r\n /**\r\n * When set to `false`, object's controlling borders are not rendered\r\n * @type Boolean\r\n * @default\r\n */\r\n hasBorders: true,\r\n\r\n /**\r\n * When set to `true`, objects are \"found\" on canvas on per-pixel basis rather than according to bounding box\r\n * @type Boolean\r\n * @default\r\n */\r\n perPixelTargetFind: false,\r\n\r\n /**\r\n * When `false`, default object's values are not included in its serialization\r\n * @type Boolean\r\n * @default\r\n */\r\n includeDefaultValues: true,\r\n\r\n /**\r\n * When `true`, object horizontal movement is locked\r\n * @type Boolean\r\n * @default\r\n */\r\n lockMovementX: false,\r\n\r\n /**\r\n * When `true`, object vertical movement is locked\r\n * @type Boolean\r\n * @default\r\n */\r\n lockMovementY: false,\r\n\r\n /**\r\n * When `true`, object rotation is locked\r\n * @type Boolean\r\n * @default\r\n */\r\n lockRotation: false,\r\n\r\n /**\r\n * When `true`, object horizontal scaling is locked\r\n * @type Boolean\r\n * @default\r\n */\r\n lockScalingX: false,\r\n\r\n /**\r\n * When `true`, object vertical scaling is locked\r\n * @type Boolean\r\n * @default\r\n */\r\n lockScalingY: false,\r\n\r\n /**\r\n * When `true`, object horizontal skewing is locked\r\n * @type Boolean\r\n * @default\r\n */\r\n lockSkewingX: false,\r\n\r\n /**\r\n * When `true`, object vertical skewing is locked\r\n * @type Boolean\r\n * @default\r\n */\r\n lockSkewingY: false,\r\n\r\n /**\r\n * When `true`, object cannot be flipped by scaling into negative values\r\n * @type Boolean\r\n * @default\r\n */\r\n lockScalingFlip: false,\r\n\r\n /**\r\n * When `true`, object is not exported in OBJECT/JSON\r\n * @since 1.6.3\r\n * @type Boolean\r\n * @default\r\n */\r\n excludeFromExport: false,\r\n\r\n /**\r\n * When `true`, object is cached on an additional canvas.\r\n * When `false`, object is not cached unless necessary ( clipPath )\r\n * default to true\r\n * @since 1.7.0\r\n * @type Boolean\r\n * @default true\r\n */\r\n objectCaching: objectCaching,\r\n\r\n /**\r\n * When `true`, object properties are checked for cache invalidation. In some particular\r\n * situation you may want this to be disabled ( spray brush, very big, groups)\r\n * or if your application does not allow you to modify properties for groups child you want\r\n * to disable it for groups.\r\n * default to false\r\n * since 1.7.0\r\n * @type Boolean\r\n * @default false\r\n */\r\n statefullCache: false,\r\n\r\n /**\r\n * When `true`, cache does not get updated during scaling. The picture will get blocky if scaled\r\n * too much and will be redrawn with correct details at the end of scaling.\r\n * this setting is performance and application dependant.\r\n * default to true\r\n * since 1.7.0\r\n * @type Boolean\r\n * @default true\r\n */\r\n noScaleCache: true,\r\n\r\n /**\r\n * When `false`, the stoke width will scale with the object.\r\n * When `true`, the stroke will always match the exact pixel size entered for stroke width.\r\n * this Property does not work on Text classes or drawing call that uses strokeText,fillText methods\r\n * default to false\r\n * @since 2.6.0\r\n * @type Boolean\r\n * @default false\r\n * @type Boolean\r\n * @default false\r\n */\r\n strokeUniform: false,\r\n\r\n /**\r\n * When set to `true`, object's cache will be rerendered next render call.\r\n * since 1.7.0\r\n * @type Boolean\r\n * @default true\r\n */\r\n dirty: true,\r\n\r\n /**\r\n * keeps the value of the last hovered corner during mouse move.\r\n * 0 is no corner, or 'mt', 'ml', 'mtr' etc..\r\n * It should be private, but there is no harm in using it as\r\n * a read-only property.\r\n * @type number|string|any\r\n * @default 0\r\n */\r\n __corner: 0,\r\n\r\n /**\r\n * Determines if the fill or the stroke is drawn first (one of \"fill\" or \"stroke\")\r\n * @type String\r\n * @default\r\n */\r\n paintFirst: 'fill',\r\n\r\n /**\r\n * When 'down', object is set to active on mousedown/touchstart\r\n * When 'up', object is set to active on mouseup/touchend\r\n * Experimental. Let's see if this breaks anything before supporting officially\r\n * @private\r\n * since 4.4.0\r\n * @type String\r\n * @default 'down'\r\n */\r\n activeOn: 'down',\r\n\r\n /**\r\n * List of properties to consider when checking if state\r\n * of an object is changed (fabric.Object#hasStateChanged)\r\n * as well as for history (undo/redo) purposes\r\n * @type Array\r\n */\r\n stateProperties: (\r\n 'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' +\r\n 'stroke strokeWidth strokeDashArray strokeLineCap strokeDashOffset strokeLineJoin strokeMiterLimit ' +\r\n 'angle opacity fill globalCompositeOperation shadow visible backgroundColor ' +\r\n 'skewX skewY fillRule paintFirst clipPath strokeUniform'\r\n ).split(' '),\r\n\r\n /**\r\n * List of properties to consider when checking if cache needs refresh\r\n * Those properties are checked by statefullCache ON ( or lazy mode if we want ) or from single\r\n * calls to Object.set(key, value). If the key is in this list, the object is marked as dirty\r\n * and refreshed at the next render\r\n * @type Array\r\n */\r\n cacheProperties: (\r\n 'fill stroke strokeWidth strokeDashArray width height paintFirst strokeUniform' +\r\n ' strokeLineCap strokeDashOffset strokeLineJoin strokeMiterLimit backgroundColor clipPath'\r\n ).split(' '),\r\n\r\n /**\r\n * List of properties to consider for animating colors.\r\n * @type Array\r\n */\r\n colorProperties: (\r\n 'fill stroke backgroundColor'\r\n ).split(' '),\r\n\r\n /**\r\n * a fabricObject that, without stroke define a clipping area with their shape. filled in black\r\n * the clipPath object gets used when the object has rendered, and the context is placed in the center\r\n * of the object cacheCanvas.\r\n * If you want 0,0 of a clipPath to align with an object center, use clipPath.originX/Y to 'center'\r\n * @type fabric.Object\r\n */\r\n clipPath: undefined,\r\n\r\n /**\r\n * Meaningful ONLY when the object is used as clipPath.\r\n * if true, the clipPath will make the object clip to the outside of the clipPath\r\n * since 2.4.0\r\n * @type boolean\r\n * @default false\r\n */\r\n inverted: false,\r\n\r\n /**\r\n * Meaningful ONLY when the object is used as clipPath.\r\n * if true, the clipPath will have its top and left relative to canvas, and will\r\n * not be influenced by the object transform. This will make the clipPath relative\r\n * to the canvas, but clipping just a particular object.\r\n * WARNING this is beta, this feature may change or be renamed.\r\n * since 2.4.0\r\n * @type boolean\r\n * @default false\r\n */\r\n absolutePositioned: false,\r\n\r\n /**\r\n * Constructor\r\n * @param {Object} [options] Options object\r\n */\r\n initialize: function(options) {\r\n if (options) {\r\n this.setOptions(options);\r\n }\r\n },\r\n\r\n /**\r\n * Create a the canvas used to keep the cached copy of the object\r\n * @private\r\n */\r\n _createCacheCanvas: function() {\r\n this._cacheProperties = {};\r\n this._cacheCanvas = fabric.util.createCanvasElement();\r\n this._cacheContext = this._cacheCanvas.getContext('2d', { willReadFrequently: true });\r\n this._updateCacheCanvas();\r\n // if canvas gets created, is empty, so dirty.\r\n this.dirty = true;\r\n },\r\n\r\n /**\r\n * Limit the cache dimensions so that X * Y do not cross fabric.perfLimitSizeTotal\r\n * and each side do not cross fabric.cacheSideLimit\r\n * those numbers are configurable so that you can get as much detail as you want\r\n * making bargain with performances.\r\n * @param {Object} dims\r\n * @param {Object} dims.width width of canvas\r\n * @param {Object} dims.height height of canvas\r\n * @param {Object} dims.zoomX zoomX zoom value to unscale the canvas before drawing cache\r\n * @param {Object} dims.zoomY zoomY zoom value to unscale the canvas before drawing cache\r\n * @return {Object}.width width of canvas\r\n * @return {Object}.height height of canvas\r\n * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\r\n * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\r\n */\r\n _limitCacheSize: function(dims) {\r\n var perfLimitSizeTotal = fabric.perfLimitSizeTotal,\r\n width = dims.width, height = dims.height,\r\n max = fabric.maxCacheSideLimit, min = fabric.minCacheSideLimit;\r\n if (width <= max && height <= max && width * height <= perfLimitSizeTotal) {\r\n if (width < min) {\r\n dims.width = min;\r\n }\r\n if (height < min) {\r\n dims.height = min;\r\n }\r\n return dims;\r\n }\r\n var ar = width / height, limitedDims = fabric.util.limitDimsByArea(ar, perfLimitSizeTotal),\r\n capValue = fabric.util.capValue,\r\n x = capValue(min, limitedDims.x, max),\r\n y = capValue(min, limitedDims.y, max);\r\n if (width > x) {\r\n dims.zoomX /= width / x;\r\n dims.width = x;\r\n dims.capped = true;\r\n }\r\n if (height > y) {\r\n dims.zoomY /= height / y;\r\n dims.height = y;\r\n dims.capped = true;\r\n }\r\n return dims;\r\n },\r\n\r\n /**\r\n * Return the dimension and the zoom level needed to create a cache canvas\r\n * big enough to host the object to be cached.\r\n * @private\r\n * @return {Object}.x width of object to be cached\r\n * @return {Object}.y height of object to be cached\r\n * @return {Object}.width width of canvas\r\n * @return {Object}.height height of canvas\r\n * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\r\n * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\r\n */\r\n _getCacheCanvasDimensions: function() {\r\n var objectScale = this.getTotalObjectScaling(),\r\n // caculate dimensions without skewing\r\n dim = this._getTransformedDimensions(0, 0),\r\n neededX = dim.x * objectScale.scaleX / this.scaleX,\r\n neededY = dim.y * objectScale.scaleY / this.scaleY;\r\n return {\r\n // for sure this ALIASING_LIMIT is slightly creating problem\r\n // in situation in which the cache canvas gets an upper limit\r\n // also objectScale contains already scaleX and scaleY\r\n width: neededX + ALIASING_LIMIT,\r\n height: neededY + ALIASING_LIMIT,\r\n zoomX: objectScale.scaleX,\r\n zoomY: objectScale.scaleY,\r\n x: neededX,\r\n y: neededY\r\n };\r\n },\r\n\r\n /**\r\n * Update width and height of the canvas for cache\r\n * returns true or false if canvas needed resize.\r\n * @private\r\n * @return {Boolean} true if the canvas has been resized\r\n */\r\n _updateCacheCanvas: function() {\r\n var targetCanvas = this.canvas;\r\n if (this.noScaleCache && targetCanvas && targetCanvas._currentTransform) {\r\n var target = targetCanvas._currentTransform.target,\r\n action = targetCanvas._currentTransform.action;\r\n if (this === target && action.slice && action.slice(0, 5) === 'scale') {\r\n return false;\r\n }\r\n }\r\n var canvas = this._cacheCanvas,\r\n dims = this._limitCacheSize(this._getCacheCanvasDimensions()),\r\n minCacheSize = fabric.minCacheSideLimit,\r\n width = dims.width, height = dims.height, drawingWidth, drawingHeight,\r\n zoomX = dims.zoomX, zoomY = dims.zoomY,\r\n dimensionsChanged = width !== this.cacheWidth || height !== this.cacheHeight,\r\n zoomChanged = this.zoomX !== zoomX || this.zoomY !== zoomY,\r\n shouldRedraw = dimensionsChanged || zoomChanged,\r\n additionalWidth = 0, additionalHeight = 0, shouldResizeCanvas = false;\r\n if (dimensionsChanged) {\r\n var canvasWidth = this._cacheCanvas.width,\r\n canvasHeight = this._cacheCanvas.height,\r\n sizeGrowing = width > canvasWidth || height > canvasHeight,\r\n sizeShrinking = (width < canvasWidth * 0.9 || height < canvasHeight * 0.9) &&\r\n canvasWidth > minCacheSize && canvasHeight > minCacheSize;\r\n shouldResizeCanvas = sizeGrowing || sizeShrinking;\r\n if (sizeGrowing && !dims.capped && (width > minCacheSize || height > minCacheSize)) {\r\n additionalWidth = width * 0.1;\r\n additionalHeight = height * 0.1;\r\n }\r\n }\r\n if (this instanceof fabric.Text && this.path) {\r\n shouldRedraw = true;\r\n shouldResizeCanvas = true;\r\n additionalWidth += this.getHeightOfLine(0) * this.zoomX;\r\n additionalHeight += this.getHeightOfLine(0) * this.zoomY;\r\n }\r\n if (shouldRedraw) {\r\n if (shouldResizeCanvas) {\r\n canvas.width = Math.ceil(width + additionalWidth);\r\n canvas.height = Math.ceil(height + additionalHeight);\r\n }\r\n else {\r\n this._cacheContext.setTransform(1, 0, 0, 1, 0, 0);\r\n this._cacheContext.clearRect(0, 0, canvas.width, canvas.height);\r\n }\r\n drawingWidth = dims.x / 2;\r\n drawingHeight = dims.y / 2;\r\n this.cacheTranslationX = Math.round(canvas.width / 2 - drawingWidth) + drawingWidth;\r\n this.cacheTranslationY = Math.round(canvas.height / 2 - drawingHeight) + drawingHeight;\r\n this.cacheWidth = width;\r\n this.cacheHeight = height;\r\n this._cacheContext.translate(this.cacheTranslationX, this.cacheTranslationY);\r\n this._cacheContext.scale(zoomX, zoomY);\r\n this.zoomX = zoomX;\r\n this.zoomY = zoomY;\r\n return true;\r\n }\r\n return false;\r\n },\r\n\r\n /**\r\n * Sets object's properties from options\r\n * @param {Object} [options] Options object\r\n */\r\n setOptions: function(options) {\r\n this._setOptions(options);\r\n this._initGradient(options.fill, 'fill');\r\n this._initGradient(options.stroke, 'stroke');\r\n this._initPattern(options.fill, 'fill');\r\n this._initPattern(options.stroke, 'stroke');\r\n },\r\n\r\n /**\r\n * Transforms context when rendering an object\r\n * @param {CanvasRenderingContext2D} ctx Context\r\n */\r\n transform: function(ctx) {\r\n var needFullTransform = (this.group && !this.group._transformDone) ||\r\n (this.group && this.canvas && ctx === this.canvas.contextTop);\r\n var m = this.calcTransformMatrix(!needFullTransform);\r\n ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\r\n },\r\n\r\n /**\r\n * Returns an object representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} Object representation of an instance\r\n */\r\n toObject: function(propertiesToInclude) {\r\n var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\r\n\r\n object = {\r\n type: this.type,\r\n version: fabric.version,\r\n originX: this.originX,\r\n originY: this.originY,\r\n left: toFixed(this.left, NUM_FRACTION_DIGITS),\r\n top: toFixed(this.top, NUM_FRACTION_DIGITS),\r\n width: toFixed(this.width, NUM_FRACTION_DIGITS),\r\n height: toFixed(this.height, NUM_FRACTION_DIGITS),\r\n fill: (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill,\r\n stroke: (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke,\r\n strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS),\r\n strokeDashArray: this.strokeDashArray ? this.strokeDashArray.concat() : this.strokeDashArray,\r\n strokeLineCap: this.strokeLineCap,\r\n strokeDashOffset: this.strokeDashOffset,\r\n strokeLineJoin: this.strokeLineJoin,\r\n strokeUniform: this.strokeUniform,\r\n strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS),\r\n scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS),\r\n scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS),\r\n angle: toFixed(this.angle, NUM_FRACTION_DIGITS),\r\n flipX: this.flipX,\r\n flipY: this.flipY,\r\n opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS),\r\n shadow: (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow,\r\n visible: this.visible,\r\n backgroundColor: this.backgroundColor,\r\n fillRule: this.fillRule,\r\n paintFirst: this.paintFirst,\r\n globalCompositeOperation: this.globalCompositeOperation,\r\n skewX: toFixed(this.skewX, NUM_FRACTION_DIGITS),\r\n skewY: toFixed(this.skewY, NUM_FRACTION_DIGITS),\r\n };\r\n\r\n if (this.clipPath && !this.clipPath.excludeFromExport) {\r\n object.clipPath = this.clipPath.toObject(propertiesToInclude);\r\n object.clipPath.inverted = this.clipPath.inverted;\r\n object.clipPath.absolutePositioned = this.clipPath.absolutePositioned;\r\n }\r\n\r\n fabric.util.populateWithProperties(this, object, propertiesToInclude);\r\n if (!this.includeDefaultValues) {\r\n object = this._removeDefaultValues(object);\r\n }\r\n\r\n return object;\r\n },\r\n\r\n /**\r\n * Returns (dataless) object representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} Object representation of an instance\r\n */\r\n toDatalessObject: function(propertiesToInclude) {\r\n // will be overwritten by subclasses\r\n return this.toObject(propertiesToInclude);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Object} object\r\n */\r\n _removeDefaultValues: function(object) {\r\n var prototype = fabric.util.getKlass(object.type).prototype,\r\n stateProperties = prototype.stateProperties;\r\n stateProperties.forEach(function(prop) {\r\n if (prop === 'left' || prop === 'top') {\r\n return;\r\n }\r\n if (object[prop] === prototype[prop]) {\r\n delete object[prop];\r\n }\r\n // basically a check for [] === []\r\n if (Array.isArray(object[prop]) && Array.isArray(prototype[prop])\r\n && object[prop].length === 0 && prototype[prop].length === 0) {\r\n delete object[prop];\r\n }\r\n });\r\n\r\n return object;\r\n },\r\n\r\n /**\r\n * Returns a string representation of an instance\r\n * @return {String}\r\n */\r\n toString: function() {\r\n return '#';\r\n },\r\n\r\n /**\r\n * Return the object scale factor counting also the group scaling\r\n * @return {Object} object with scaleX and scaleY properties\r\n */\r\n getObjectScaling: function() {\r\n // if the object is a top level one, on the canvas, we go for simple aritmetic\r\n // otherwise the complex method with angles will return approximations and decimals\r\n // and will likely kill the cache when not needed\r\n // https://github.com/fabricjs/fabric.js/issues/7157\r\n if (!this.group) {\r\n return {\r\n scaleX: this.scaleX,\r\n scaleY: this.scaleY,\r\n };\r\n }\r\n // if we are inside a group total zoom calculation is complex, we defer to generic matrices\r\n var options = fabric.util.qrDecompose(this.calcTransformMatrix());\r\n return { scaleX: Math.abs(options.scaleX), scaleY: Math.abs(options.scaleY) };\r\n },\r\n\r\n /**\r\n * Return the object scale factor counting also the group scaling, zoom and retina\r\n * @return {Object} object with scaleX and scaleY properties\r\n */\r\n getTotalObjectScaling: function() {\r\n var scale = this.getObjectScaling(), scaleX = scale.scaleX, scaleY = scale.scaleY;\r\n if (this.canvas) {\r\n var zoom = this.canvas.getZoom();\r\n var retina = this.canvas.getRetinaScaling();\r\n scaleX *= zoom * retina;\r\n scaleY *= zoom * retina;\r\n }\r\n return { scaleX: scaleX, scaleY: scaleY };\r\n },\r\n\r\n /**\r\n * Return the object opacity counting also the group property\r\n * @return {Number}\r\n */\r\n getObjectOpacity: function() {\r\n var opacity = this.opacity;\r\n if (this.group) {\r\n opacity *= this.group.getObjectOpacity();\r\n }\r\n return opacity;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {String} key\r\n * @param {*} value\r\n * @return {fabric.Object} thisArg\r\n */\r\n _set: function(key, value) {\r\n var shouldConstrainValue = (key === 'scaleX' || key === 'scaleY'),\r\n isChanged = this[key] !== value, groupNeedsUpdate = false;\r\n\r\n if (shouldConstrainValue) {\r\n value = this._constrainScale(value);\r\n }\r\n if (key === 'scaleX' && value < 0) {\r\n this.flipX = !this.flipX;\r\n value *= -1;\r\n }\r\n else if (key === 'scaleY' && value < 0) {\r\n this.flipY = !this.flipY;\r\n value *= -1;\r\n }\r\n else if (key === 'shadow' && value && !(value instanceof fabric.Shadow)) {\r\n value = new fabric.Shadow(value);\r\n }\r\n else if (key === 'dirty' && this.group) {\r\n this.group.set('dirty', value);\r\n }\r\n\r\n this[key] = value;\r\n\r\n if (isChanged) {\r\n groupNeedsUpdate = this.group && this.group.isOnACache();\r\n if (this.cacheProperties.indexOf(key) > -1) {\r\n this.dirty = true;\r\n groupNeedsUpdate && this.group.set('dirty', true);\r\n }\r\n else if (groupNeedsUpdate && this.stateProperties.indexOf(key) > -1) {\r\n this.group.set('dirty', true);\r\n }\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * This callback function is called by the parent group of an object every\r\n * time a non-delegated property changes on the group. It is passed the key\r\n * and value as parameters. Not adding in this function's signature to avoid\r\n * Travis build error about unused variables.\r\n */\r\n setOnGroup: function() {\r\n // implemented by sub-classes, as needed.\r\n },\r\n\r\n /**\r\n * Retrieves viewportTransform from Object's canvas if possible\r\n * @method getViewportTransform\r\n * @memberOf fabric.Object.prototype\r\n * @return {Array}\r\n */\r\n getViewportTransform: function() {\r\n if (this.canvas && this.canvas.viewportTransform) {\r\n return this.canvas.viewportTransform;\r\n }\r\n return fabric.iMatrix.concat();\r\n },\r\n\r\n /*\r\n * @private\r\n * return if the object would be visible in rendering\r\n * @memberOf fabric.Object.prototype\r\n * @return {Boolean}\r\n */\r\n isNotVisible: function() {\r\n return this.opacity === 0 ||\r\n (!this.width && !this.height && this.strokeWidth === 0) ||\r\n !this.visible;\r\n },\r\n\r\n /**\r\n * Renders an object on a specified context\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n render: function(ctx) {\r\n // do not render if width/height are zeros or object is not visible\r\n if (this.isNotVisible()) {\r\n return;\r\n }\r\n if (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) {\r\n return;\r\n }\r\n ctx.save();\r\n this._setupCompositeOperation(ctx);\r\n this.drawSelectionBackground(ctx);\r\n this.transform(ctx);\r\n this._setOpacity(ctx);\r\n this._setShadow(ctx, this);\r\n if (this.shouldCache()) {\r\n this.renderCache();\r\n this.drawCacheOnCanvas(ctx);\r\n }\r\n else {\r\n this._removeCacheCanvas();\r\n this.dirty = false;\r\n this.drawObject(ctx);\r\n if (this.objectCaching && this.statefullCache) {\r\n this.saveState({ propertySet: 'cacheProperties' });\r\n }\r\n }\r\n ctx.restore();\r\n },\r\n\r\n renderCache: function(options) {\r\n options = options || {};\r\n if (!this._cacheCanvas || !this._cacheContext) {\r\n this._createCacheCanvas();\r\n }\r\n if (this.isCacheDirty()) {\r\n this.statefullCache && this.saveState({ propertySet: 'cacheProperties' });\r\n this.drawObject(this._cacheContext, options.forClipping);\r\n this.dirty = false;\r\n }\r\n },\r\n\r\n /**\r\n * Remove cacheCanvas and its dimensions from the objects\r\n */\r\n _removeCacheCanvas: function() {\r\n this._cacheCanvas = null;\r\n this._cacheContext = null;\r\n this.cacheWidth = 0;\r\n this.cacheHeight = 0;\r\n },\r\n\r\n /**\r\n * return true if the object will draw a stroke\r\n * Does not consider text styles. This is just a shortcut used at rendering time\r\n * We want it to be an approximation and be fast.\r\n * wrote to avoid extra caching, it has to return true when stroke happens,\r\n * can guess when it will not happen at 100% chance, does not matter if it misses\r\n * some use case where the stroke is invisible.\r\n * @since 3.0.0\r\n * @returns Boolean\r\n */\r\n hasStroke: function() {\r\n return this.stroke && this.stroke !== 'transparent' && this.strokeWidth !== 0;\r\n },\r\n\r\n /**\r\n * return true if the object will draw a fill\r\n * Does not consider text styles. This is just a shortcut used at rendering time\r\n * We want it to be an approximation and be fast.\r\n * wrote to avoid extra caching, it has to return true when fill happens,\r\n * can guess when it will not happen at 100% chance, does not matter if it misses\r\n * some use case where the fill is invisible.\r\n * @since 3.0.0\r\n * @returns Boolean\r\n */\r\n hasFill: function() {\r\n return this.fill && this.fill !== 'transparent';\r\n },\r\n\r\n /**\r\n * When set to `true`, force the object to have its own cache, even if it is inside a group\r\n * it may be needed when your object behave in a particular way on the cache and always needs\r\n * its own isolated canvas to render correctly.\r\n * Created to be overridden\r\n * since 1.7.12\r\n * @returns Boolean\r\n */\r\n needsItsOwnCache: function() {\r\n if (this.paintFirst === 'stroke' &&\r\n this.hasFill() && this.hasStroke() && typeof this.shadow === 'object') {\r\n return true;\r\n }\r\n if (this.clipPath) {\r\n return true;\r\n }\r\n return false;\r\n },\r\n\r\n /**\r\n * Decide if the object should cache or not. Create its own cache level\r\n * objectCaching is a global flag, wins over everything\r\n * needsItsOwnCache should be used when the object drawing method requires\r\n * a cache step. None of the fabric classes requires it.\r\n * Generally you do not cache objects in groups because the group outside is cached.\r\n * Read as: cache if is needed, or if the feature is enabled but we are not already caching.\r\n * @return {Boolean}\r\n */\r\n shouldCache: function() {\r\n this.ownCaching = this.needsItsOwnCache() || (\r\n this.objectCaching &&\r\n (!this.group || !this.group.isOnACache())\r\n );\r\n return this.ownCaching;\r\n },\r\n\r\n /**\r\n * Check if this object or a child object will cast a shadow\r\n * used by Group.shouldCache to know if child has a shadow recursively\r\n * @return {Boolean}\r\n */\r\n willDrawShadow: function() {\r\n return !!this.shadow && (this.shadow.offsetX !== 0 || this.shadow.offsetY !== 0);\r\n },\r\n\r\n /**\r\n * Execute the drawing operation for an object clipPath\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @param {fabric.Object} clipPath\r\n */\r\n drawClipPathOnCache: function(ctx, clipPath) {\r\n ctx.save();\r\n // DEBUG: uncomment this line, comment the following\r\n // ctx.globalAlpha = 0.4\r\n if (clipPath.inverted) {\r\n ctx.globalCompositeOperation = 'destination-out';\r\n }\r\n else {\r\n ctx.globalCompositeOperation = 'destination-in';\r\n }\r\n //ctx.scale(1 / 2, 1 / 2);\r\n if (clipPath.absolutePositioned) {\r\n var m = fabric.util.invertTransform(this.calcTransformMatrix());\r\n ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\r\n }\r\n clipPath.transform(ctx);\r\n ctx.scale(1 / clipPath.zoomX, 1 / clipPath.zoomY);\r\n ctx.drawImage(clipPath._cacheCanvas, -clipPath.cacheTranslationX, -clipPath.cacheTranslationY);\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * Execute the drawing operation for an object on a specified context\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n drawObject: function(ctx, forClipping) {\r\n var originalFill = this.fill, originalStroke = this.stroke;\r\n if (forClipping) {\r\n this.fill = 'black';\r\n this.stroke = '';\r\n this._setClippingProperties(ctx);\r\n }\r\n else {\r\n this._renderBackground(ctx);\r\n }\r\n this._render(ctx);\r\n this._drawClipPath(ctx, this.clipPath);\r\n this.fill = originalFill;\r\n this.stroke = originalStroke;\r\n },\r\n\r\n /**\r\n * Prepare clipPath state and cache and draw it on instance's cache\r\n * @param {CanvasRenderingContext2D} ctx\r\n * @param {fabric.Object} clipPath\r\n */\r\n _drawClipPath: function (ctx, clipPath) {\r\n if (!clipPath) { return; }\r\n // needed to setup a couple of variables\r\n // path canvas gets overridden with this one.\r\n // TODO find a better solution?\r\n clipPath.canvas = this.canvas;\r\n clipPath.shouldCache();\r\n clipPath._transformDone = true;\r\n clipPath.renderCache({ forClipping: true });\r\n this.drawClipPathOnCache(ctx, clipPath);\r\n },\r\n\r\n /**\r\n * Paint the cached copy of the object on the target context.\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n drawCacheOnCanvas: function(ctx) {\r\n ctx.scale(1 / this.zoomX, 1 / this.zoomY);\r\n ctx.drawImage(this._cacheCanvas, -this.cacheTranslationX, -this.cacheTranslationY);\r\n },\r\n\r\n /**\r\n * Check if cache is dirty\r\n * @param {Boolean} skipCanvas skip canvas checks because this object is painted\r\n * on parent canvas.\r\n */\r\n isCacheDirty: function(skipCanvas) {\r\n if (this.isNotVisible()) {\r\n return false;\r\n }\r\n if (this._cacheCanvas && this._cacheContext && !skipCanvas && this._updateCacheCanvas()) {\r\n // in this case the context is already cleared.\r\n return true;\r\n }\r\n else {\r\n if (this.dirty ||\r\n (this.clipPath && this.clipPath.absolutePositioned) ||\r\n (this.statefullCache && this.hasStateChanged('cacheProperties'))\r\n ) {\r\n if (this._cacheCanvas && this._cacheContext && !skipCanvas) {\r\n var width = this.cacheWidth / this.zoomX;\r\n var height = this.cacheHeight / this.zoomY;\r\n this._cacheContext.clearRect(-width / 2, -height / 2, width, height);\r\n }\r\n return true;\r\n }\r\n }\r\n return false;\r\n },\r\n\r\n /**\r\n * Draws a background for the object big as its untransformed dimensions\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _renderBackground: function(ctx) {\r\n if (!this.backgroundColor) {\r\n return;\r\n }\r\n var dim = this._getNonTransformedDimensions();\r\n ctx.fillStyle = this.backgroundColor;\r\n\r\n ctx.fillRect(\r\n -dim.x / 2,\r\n -dim.y / 2,\r\n dim.x,\r\n dim.y\r\n );\r\n // if there is background color no other shadows\r\n // should be casted\r\n this._removeShadow(ctx);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _setOpacity: function(ctx) {\r\n if (this.group && !this.group._transformDone) {\r\n ctx.globalAlpha = this.getObjectOpacity();\r\n }\r\n else {\r\n ctx.globalAlpha *= this.opacity;\r\n }\r\n },\r\n\r\n _setStrokeStyles: function(ctx, decl) {\r\n var stroke = decl.stroke;\r\n if (stroke) {\r\n ctx.lineWidth = decl.strokeWidth;\r\n ctx.lineCap = decl.strokeLineCap;\r\n ctx.lineDashOffset = decl.strokeDashOffset;\r\n ctx.lineJoin = decl.strokeLineJoin;\r\n ctx.miterLimit = decl.strokeMiterLimit;\r\n if (stroke.toLive) {\r\n if (stroke.gradientUnits === 'percentage' || stroke.gradientTransform || stroke.patternTransform) {\r\n // need to transform gradient in a pattern.\r\n // this is a slow process. If you are hitting this codepath, and the object\r\n // is not using caching, you should consider switching it on.\r\n // we need a canvas as big as the current object caching canvas.\r\n this._applyPatternForTransformedGradient(ctx, stroke);\r\n }\r\n else {\r\n // is a simple gradient or pattern\r\n ctx.strokeStyle = stroke.toLive(ctx, this);\r\n this._applyPatternGradientTransform(ctx, stroke);\r\n }\r\n }\r\n else {\r\n // is a color\r\n ctx.strokeStyle = decl.stroke;\r\n }\r\n }\r\n },\r\n\r\n _setFillStyles: function(ctx, decl) {\r\n var fill = decl.fill;\r\n if (fill) {\r\n if (fill.toLive) {\r\n ctx.fillStyle = fill.toLive(ctx, this);\r\n this._applyPatternGradientTransform(ctx, decl.fill);\r\n }\r\n else {\r\n ctx.fillStyle = fill;\r\n }\r\n }\r\n },\r\n\r\n _setClippingProperties: function(ctx) {\r\n ctx.globalAlpha = 1;\r\n ctx.strokeStyle = 'transparent';\r\n ctx.fillStyle = '#000000';\r\n },\r\n\r\n /**\r\n * @private\r\n * Sets line dash\r\n * @param {CanvasRenderingContext2D} ctx Context to set the dash line on\r\n * @param {Array} dashArray array representing dashes\r\n */\r\n _setLineDash: function(ctx, dashArray) {\r\n if (!dashArray || dashArray.length === 0) {\r\n return;\r\n }\r\n // Spec requires the concatenation of two copies the dash list when the number of elements is odd\r\n if (1 & dashArray.length) {\r\n dashArray.push.apply(dashArray, dashArray);\r\n }\r\n ctx.setLineDash(dashArray);\r\n },\r\n\r\n /**\r\n * Renders controls and borders for the object\r\n * the context here is not transformed\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @param {Object} [styleOverride] properties to override the object style\r\n */\r\n _renderControls: function(ctx, styleOverride) {\r\n var vpt = this.getViewportTransform(),\r\n matrix = this.calcTransformMatrix(),\r\n options, drawBorders, drawControls;\r\n styleOverride = styleOverride || { };\r\n drawBorders = typeof styleOverride.hasBorders !== 'undefined' ? styleOverride.hasBorders : this.hasBorders;\r\n drawControls = typeof styleOverride.hasControls !== 'undefined' ? styleOverride.hasControls : this.hasControls;\r\n matrix = fabric.util.multiplyTransformMatrices(vpt, matrix);\r\n options = fabric.util.qrDecompose(matrix);\r\n ctx.save();\r\n ctx.translate(options.translateX, options.translateY);\r\n ctx.lineWidth = 1 * this.borderScaleFactor;\r\n if (!this.group) {\r\n ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\r\n }\r\n if (this.flipX) {\r\n options.angle -= 180;\r\n }\r\n ctx.rotate(degreesToRadians(this.group ? options.angle : this.angle));\r\n if (styleOverride.forActiveSelection || this.group) {\r\n drawBorders && this.drawBordersInGroup(ctx, options, styleOverride);\r\n }\r\n else {\r\n drawBorders && this.drawBorders(ctx, styleOverride);\r\n }\r\n drawControls && this.drawControls(ctx, styleOverride);\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _setShadow: function(ctx) {\r\n if (!this.shadow) {\r\n return;\r\n }\r\n\r\n var shadow = this.shadow, canvas = this.canvas, scaling,\r\n multX = (canvas && canvas.viewportTransform[0]) || 1,\r\n multY = (canvas && canvas.viewportTransform[3]) || 1;\r\n if (shadow.nonScaling) {\r\n scaling = { scaleX: 1, scaleY: 1 };\r\n }\r\n else {\r\n scaling = this.getObjectScaling();\r\n }\r\n if (canvas && canvas._isRetinaScaling()) {\r\n multX *= fabric.devicePixelRatio;\r\n multY *= fabric.devicePixelRatio;\r\n }\r\n ctx.shadowColor = shadow.color;\r\n ctx.shadowBlur = shadow.blur * fabric.browserShadowBlurConstant *\r\n (multX + multY) * (scaling.scaleX + scaling.scaleY) / 4;\r\n ctx.shadowOffsetX = shadow.offsetX * multX * scaling.scaleX;\r\n ctx.shadowOffsetY = shadow.offsetY * multY * scaling.scaleY;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _removeShadow: function(ctx) {\r\n if (!this.shadow) {\r\n return;\r\n }\r\n\r\n ctx.shadowColor = '';\r\n ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @param {Object} filler fabric.Pattern or fabric.Gradient\r\n * @return {Object} offset.offsetX offset for text rendering\r\n * @return {Object} offset.offsetY offset for text rendering\r\n */\r\n _applyPatternGradientTransform: function(ctx, filler) {\r\n if (!filler || !filler.toLive) {\r\n return { offsetX: 0, offsetY: 0 };\r\n }\r\n var t = filler.gradientTransform || filler.patternTransform;\r\n var offsetX = -this.width / 2 + filler.offsetX || 0,\r\n offsetY = -this.height / 2 + filler.offsetY || 0;\r\n\r\n if (filler.gradientUnits === 'percentage') {\r\n ctx.transform(this.width, 0, 0, this.height, offsetX, offsetY);\r\n }\r\n else {\r\n ctx.transform(1, 0, 0, 1, offsetX, offsetY);\r\n }\r\n if (t) {\r\n ctx.transform(t[0], t[1], t[2], t[3], t[4], t[5]);\r\n }\r\n return { offsetX: offsetX, offsetY: offsetY };\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _renderPaintInOrder: function(ctx) {\r\n if (this.paintFirst === 'stroke') {\r\n this._renderStroke(ctx);\r\n this._renderFill(ctx);\r\n }\r\n else {\r\n this._renderFill(ctx);\r\n this._renderStroke(ctx);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * function that actually render something on the context.\r\n * empty here to allow Obects to work on tests to benchmark fabric functionalites\r\n * not related to rendering\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _render: function(/* ctx */) {\r\n\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _renderFill: function(ctx) {\r\n if (!this.fill) {\r\n return;\r\n }\r\n\r\n ctx.save();\r\n this._setFillStyles(ctx, this);\r\n if (this.fillRule === 'evenodd') {\r\n ctx.fill('evenodd');\r\n }\r\n else {\r\n ctx.fill();\r\n }\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _renderStroke: function(ctx) {\r\n if (!this.stroke || this.strokeWidth === 0) {\r\n return;\r\n }\r\n\r\n if (this.shadow && !this.shadow.affectStroke) {\r\n this._removeShadow(ctx);\r\n }\r\n\r\n ctx.save();\r\n if (this.strokeUniform && this.group) {\r\n var scaling = this.getObjectScaling();\r\n ctx.scale(1 / scaling.scaleX, 1 / scaling.scaleY);\r\n }\r\n else if (this.strokeUniform) {\r\n ctx.scale(1 / this.scaleX, 1 / this.scaleY);\r\n }\r\n this._setLineDash(ctx, this.strokeDashArray);\r\n this._setStrokeStyles(ctx, this);\r\n ctx.stroke();\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * This function try to patch the missing gradientTransform on canvas gradients.\r\n * transforming a context to transform the gradient, is going to transform the stroke too.\r\n * we want to transform the gradient but not the stroke operation, so we create\r\n * a transformed gradient on a pattern and then we use the pattern instead of the gradient.\r\n * this method has drwabacks: is slow, is in low resolution, needs a patch for when the size\r\n * is limited.\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @param {fabric.Gradient} filler a fabric gradient instance\r\n */\r\n _applyPatternForTransformedGradient: function(ctx, filler) {\r\n var dims = this._limitCacheSize(this._getCacheCanvasDimensions()),\r\n pCanvas = fabric.util.createCanvasElement(), pCtx, retinaScaling = this.canvas.getRetinaScaling(),\r\n width = dims.x / this.scaleX / retinaScaling, height = dims.y / this.scaleY / retinaScaling;\r\n pCanvas.width = width;\r\n pCanvas.height = height;\r\n pCtx = pCanvas.getContext('2d', { willReadFrequently: true });\r\n pCtx.beginPath(); pCtx.moveTo(0, 0); pCtx.lineTo(width, 0); pCtx.lineTo(width, height);\r\n pCtx.lineTo(0, height); pCtx.closePath();\r\n pCtx.translate(width / 2, height / 2);\r\n pCtx.scale(\r\n dims.zoomX / this.scaleX / retinaScaling,\r\n dims.zoomY / this.scaleY / retinaScaling\r\n );\r\n this._applyPatternGradientTransform(pCtx, filler);\r\n pCtx.fillStyle = filler.toLive(ctx);\r\n pCtx.fill();\r\n ctx.translate(-this.width / 2 - this.strokeWidth / 2, -this.height / 2 - this.strokeWidth / 2);\r\n ctx.scale(\r\n retinaScaling * this.scaleX / dims.zoomX,\r\n retinaScaling * this.scaleY / dims.zoomY\r\n );\r\n ctx.strokeStyle = pCtx.createPattern(pCanvas, 'no-repeat');\r\n },\r\n\r\n /**\r\n * This function is an helper for svg import. it returns the center of the object in the svg\r\n * untransformed coordinates\r\n * @private\r\n * @return {Object} center point from element coordinates\r\n */\r\n _findCenterFromElement: function() {\r\n return { x: this.left + this.width / 2, y: this.top + this.height / 2 };\r\n },\r\n\r\n /**\r\n * This function is an helper for svg import. it decompose the transformMatrix\r\n * and assign properties to object.\r\n * untransformed coordinates\r\n * @private\r\n * @chainable\r\n */\r\n _assignTransformMatrixProps: function() {\r\n if (this.transformMatrix) {\r\n var options = fabric.util.qrDecompose(this.transformMatrix);\r\n this.flipX = false;\r\n this.flipY = false;\r\n this.set('scaleX', options.scaleX);\r\n this.set('scaleY', options.scaleY);\r\n this.angle = options.angle;\r\n this.skewX = options.skewX;\r\n this.skewY = 0;\r\n }\r\n },\r\n\r\n /**\r\n * This function is an helper for svg import. it removes the transform matrix\r\n * and set to object properties that fabricjs can handle\r\n * @private\r\n * @param {Object} preserveAspectRatioOptions\r\n * @return {thisArg}\r\n */\r\n _removeTransformMatrix: function(preserveAspectRatioOptions) {\r\n var center = this._findCenterFromElement();\r\n if (this.transformMatrix) {\r\n this._assignTransformMatrixProps();\r\n center = fabric.util.transformPoint(center, this.transformMatrix);\r\n }\r\n this.transformMatrix = null;\r\n if (preserveAspectRatioOptions) {\r\n this.scaleX *= preserveAspectRatioOptions.scaleX;\r\n this.scaleY *= preserveAspectRatioOptions.scaleY;\r\n this.cropX = preserveAspectRatioOptions.cropX;\r\n this.cropY = preserveAspectRatioOptions.cropY;\r\n center.x += preserveAspectRatioOptions.offsetLeft;\r\n center.y += preserveAspectRatioOptions.offsetTop;\r\n this.width = preserveAspectRatioOptions.width;\r\n this.height = preserveAspectRatioOptions.height;\r\n }\r\n this.setPositionByOrigin(center, 'center', 'center');\r\n },\r\n\r\n /**\r\n * Clones an instance, using a callback method will work for every object.\r\n * @param {Function} callback Callback is invoked with a clone as a first argument\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n */\r\n clone: function(callback, propertiesToInclude) {\r\n var objectForm = this.toObject(propertiesToInclude);\r\n if (this.constructor.fromObject) {\r\n this.constructor.fromObject(objectForm, callback);\r\n }\r\n else {\r\n fabric.Object._fromObject('Object', objectForm, callback);\r\n }\r\n },\r\n\r\n /**\r\n * Creates an instance of fabric.Image out of an object\r\n * makes use of toCanvasElement.\r\n * Once this method was based on toDataUrl and loadImage, so it also had a quality\r\n * and format option. toCanvasElement is faster and produce no loss of quality.\r\n * If you need to get a real Jpeg or Png from an object, using toDataURL is the right way to do it.\r\n * toCanvasElement and then toBlob from the obtained canvas is also a good option.\r\n * This method is sync now, but still support the callback because we did not want to break.\r\n * When fabricJS 5.0 will be planned, this will probably be changed to not have a callback.\r\n * @param {Function} callback callback, invoked with an instance as a first argument\r\n * @param {Object} [options] for clone as image, passed to toDataURL\r\n * @param {Number} [options.multiplier=1] Multiplier to scale by\r\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\r\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\r\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\r\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\r\n * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\r\n * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\r\n * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\r\n * @return {fabric.Object} thisArg\r\n */\r\n cloneAsImage: function(callback, options) {\r\n var canvasEl = this.toCanvasElement(options);\r\n if (callback) {\r\n callback(new fabric.Image(canvasEl));\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Converts an object into a HTMLCanvas element\r\n * @param {Object} options Options object\r\n * @param {Number} [options.multiplier=1] Multiplier to scale by\r\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\r\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\r\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\r\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\r\n * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\r\n * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\r\n * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\r\n * @return {HTMLCanvasElement} Returns DOM element with the fabric.Object\r\n */\r\n toCanvasElement: function(options) {\r\n options || (options = { });\r\n\r\n var utils = fabric.util, origParams = utils.saveObjectTransform(this),\r\n originalGroup = this.group,\r\n originalShadow = this.shadow, abs = Math.abs,\r\n multiplier = (options.multiplier || 1) * (options.enableRetinaScaling ? fabric.devicePixelRatio : 1);\r\n delete this.group;\r\n if (options.withoutTransform) {\r\n utils.resetObjectTransform(this);\r\n }\r\n if (options.withoutShadow) {\r\n this.shadow = null;\r\n }\r\n\r\n var el = fabric.util.createCanvasElement(),\r\n // skip canvas zoom and calculate with setCoords now.\r\n boundingRect = this.getBoundingRect(true, true),\r\n shadow = this.shadow, scaling,\r\n shadowOffset = { x: 0, y: 0 }, shadowBlur,\r\n width, height;\r\n\r\n if (shadow) {\r\n shadowBlur = shadow.blur;\r\n if (shadow.nonScaling) {\r\n scaling = { scaleX: 1, scaleY: 1 };\r\n }\r\n else {\r\n scaling = this.getObjectScaling();\r\n }\r\n // consider non scaling shadow.\r\n shadowOffset.x = 2 * Math.round(abs(shadow.offsetX) + shadowBlur) * (abs(scaling.scaleX));\r\n shadowOffset.y = 2 * Math.round(abs(shadow.offsetY) + shadowBlur) * (abs(scaling.scaleY));\r\n }\r\n width = boundingRect.width + shadowOffset.x;\r\n height = boundingRect.height + shadowOffset.y;\r\n // if the current width/height is not an integer\r\n // we need to make it so.\r\n el.width = Math.ceil(width);\r\n el.height = Math.ceil(height);\r\n var canvas = new fabric.StaticCanvas(el, {\r\n enableRetinaScaling: false,\r\n renderOnAddRemove: false,\r\n skipOffscreen: false,\r\n });\r\n if (options.format === 'jpeg') {\r\n canvas.backgroundColor = '#fff';\r\n }\r\n this.setPositionByOrigin(new fabric.Point(canvas.width / 2, canvas.height / 2), 'center', 'center');\r\n\r\n var originalCanvas = this.canvas;\r\n canvas.add(this);\r\n var canvasEl = canvas.toCanvasElement(multiplier || 1, options);\r\n this.shadow = originalShadow;\r\n this.set('canvas', originalCanvas);\r\n if (originalGroup) {\r\n this.group = originalGroup;\r\n }\r\n this.set(origParams).setCoords();\r\n // canvas.dispose will call image.dispose that will nullify the elements\r\n // since this canvas is a simple element for the process, we remove references\r\n // to objects in this way in order to avoid object trashing.\r\n canvas._objects = [];\r\n canvas.dispose();\r\n canvas = null;\r\n\r\n return canvasEl;\r\n },\r\n\r\n /**\r\n * Converts an object into a data-url-like string\r\n * @param {Object} options Options object\r\n * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\r\n * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\r\n * @param {Number} [options.multiplier=1] Multiplier to scale by\r\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\r\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\r\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\r\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\r\n * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\r\n * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\r\n * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\r\n * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format\r\n */\r\n toDataURL: function(options) {\r\n options || (options = { });\r\n return fabric.util.toDataURL(this.toCanvasElement(options), options.format || 'png', options.quality || 1);\r\n },\r\n\r\n /**\r\n * Returns true if specified type is identical to the type of an instance\r\n * @param {String} type Type to check against\r\n * @return {Boolean}\r\n */\r\n isType: function(type) {\r\n return arguments.length > 1 ? Array.from(arguments).includes(this.type) : this.type === type;\r\n },\r\n\r\n /**\r\n * Returns complexity of an instance\r\n * @return {Number} complexity of this instance (is 1 unless subclassed)\r\n */\r\n complexity: function() {\r\n return 1;\r\n },\r\n\r\n /**\r\n * Returns a JSON representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} JSON\r\n */\r\n toJSON: function(propertiesToInclude) {\r\n // delegate, not alias\r\n return this.toObject(propertiesToInclude);\r\n },\r\n\r\n /**\r\n * Sets \"angle\" of an instance with centered rotation\r\n * @param {Number} angle Angle value (in degrees)\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n rotate: function(angle) {\r\n var shouldCenterOrigin = (this.originX !== 'center' || this.originY !== 'center') && this.centeredRotation;\r\n\r\n if (shouldCenterOrigin) {\r\n this._setOriginToCenter();\r\n }\r\n\r\n this.set('angle', angle);\r\n\r\n if (shouldCenterOrigin) {\r\n this._resetOrigin();\r\n }\r\n\r\n return this;\r\n },\r\n\r\n /**\r\n * Centers object horizontally on canvas to which it was added last.\r\n * You might need to call `setCoords` on an object after centering, to update controls area.\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n centerH: function () {\r\n this.canvas && this.canvas.centerObjectH(this);\r\n return this;\r\n },\r\n\r\n /**\r\n * Centers object horizontally on current viewport of canvas to which it was added last.\r\n * You might need to call `setCoords` on an object after centering, to update controls area.\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n viewportCenterH: function () {\r\n this.canvas && this.canvas.viewportCenterObjectH(this);\r\n return this;\r\n },\r\n\r\n /**\r\n * Centers object vertically on canvas to which it was added last.\r\n * You might need to call `setCoords` on an object after centering, to update controls area.\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n centerV: function () {\r\n this.canvas && this.canvas.centerObjectV(this);\r\n return this;\r\n },\r\n\r\n /**\r\n * Centers object vertically on current viewport of canvas to which it was added last.\r\n * You might need to call `setCoords` on an object after centering, to update controls area.\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n viewportCenterV: function () {\r\n this.canvas && this.canvas.viewportCenterObjectV(this);\r\n return this;\r\n },\r\n\r\n /**\r\n * Centers object vertically and horizontally on canvas to which is was added last\r\n * You might need to call `setCoords` on an object after centering, to update controls area.\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n center: function () {\r\n this.canvas && this.canvas.centerObject(this);\r\n return this;\r\n },\r\n\r\n /**\r\n * Centers object on current viewport of canvas to which it was added last.\r\n * You might need to call `setCoords` on an object after centering, to update controls area.\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n viewportCenter: function () {\r\n this.canvas && this.canvas.viewportCenterObject(this);\r\n return this;\r\n },\r\n\r\n /**\r\n * Returns coordinates of a pointer relative to an object\r\n * @param {Event} e Event to operate upon\r\n * @param {Object} [pointer] Pointer to operate upon (instead of event)\r\n * @return {Object} Coordinates of a pointer (x, y)\r\n */\r\n getLocalPointer: function(e, pointer) {\r\n pointer = pointer || this.canvas.getPointer(e);\r\n var pClicked = new fabric.Point(pointer.x, pointer.y),\r\n objectLeftTop = this._getLeftTopCoords();\r\n if (this.angle) {\r\n pClicked = fabric.util.rotatePoint(\r\n pClicked, objectLeftTop, degreesToRadians(-this.angle));\r\n }\r\n return {\r\n x: pClicked.x - objectLeftTop.x,\r\n y: pClicked.y - objectLeftTop.y\r\n };\r\n },\r\n\r\n /**\r\n * Sets canvas globalCompositeOperation for specific object\r\n * custom composition operation for the particular object can be specified using globalCompositeOperation property\r\n * @param {CanvasRenderingContext2D} ctx Rendering canvas context\r\n */\r\n _setupCompositeOperation: function (ctx) {\r\n if (this.globalCompositeOperation) {\r\n ctx.globalCompositeOperation = this.globalCompositeOperation;\r\n }\r\n },\r\n\r\n /**\r\n * cancel instance's running animations\r\n * override if necessary to dispose artifacts such as `clipPath`\r\n */\r\n dispose: function () {\r\n if (fabric.runningAnimations) {\r\n fabric.runningAnimations.cancelByTarget(this);\r\n }\r\n }\r\n });\r\n\r\n fabric.util.createAccessors && fabric.util.createAccessors(fabric.Object);\r\n\r\n extend(fabric.Object.prototype, fabric.Observable);\r\n\r\n /**\r\n * Defines the number of fraction digits to use when serializing object values.\r\n * You can use it to increase/decrease precision of such values like left, top, scaleX, scaleY, etc.\r\n * @static\r\n * @memberOf fabric.Object\r\n * @constant\r\n * @type Number\r\n */\r\n fabric.Object.NUM_FRACTION_DIGITS = 2;\r\n\r\n /**\r\n * Defines which properties should be enlivened from the object passed to {@link fabric.Object._fromObject}\r\n * @static\r\n * @memberOf fabric.Object\r\n * @constant\r\n * @type string[]\r\n */\r\n fabric.Object.ENLIVEN_PROPS = ['clipPath'];\r\n\r\n fabric.Object._fromObject = function(className, object, callback, extraParam) {\r\n var klass = fabric[className];\r\n object = clone(object, true);\r\n fabric.util.enlivenPatterns([object.fill, object.stroke], function(patterns) {\r\n if (typeof patterns[0] !== 'undefined') {\r\n object.fill = patterns[0];\r\n }\r\n if (typeof patterns[1] !== 'undefined') {\r\n object.stroke = patterns[1];\r\n }\r\n fabric.util.enlivenObjectEnlivables(object, object, function () {\r\n var instance = extraParam ? new klass(object[extraParam], object) : new klass(object);\r\n callback && callback(instance);\r\n });\r\n });\r\n };\r\n\r\n /**\r\n * Unique id used internally when creating SVG elements\r\n * @static\r\n * @memberOf fabric.Object\r\n * @type Number\r\n */\r\n fabric.Object.__uid = 0;\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function() {\r\n\r\n var degreesToRadians = fabric.util.degreesToRadians,\r\n originXOffset = {\r\n left: -0.5,\r\n center: 0,\r\n right: 0.5\r\n },\r\n originYOffset = {\r\n top: -0.5,\r\n center: 0,\r\n bottom: 0.5\r\n };\r\n\r\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\r\n\r\n /**\r\n * Translates the coordinates from a set of origin to another (based on the object's dimensions)\r\n * @param {fabric.Point} point The point which corresponds to the originX and originY params\r\n * @param {String} fromOriginX Horizontal origin: 'left', 'center' or 'right'\r\n * @param {String} fromOriginY Vertical origin: 'top', 'center' or 'bottom'\r\n * @param {String} toOriginX Horizontal origin: 'left', 'center' or 'right'\r\n * @param {String} toOriginY Vertical origin: 'top', 'center' or 'bottom'\r\n * @return {fabric.Point}\r\n */\r\n translateToGivenOrigin: function(point, fromOriginX, fromOriginY, toOriginX, toOriginY) {\r\n var x = point.x,\r\n y = point.y,\r\n offsetX, offsetY, dim;\r\n\r\n if (typeof fromOriginX === 'string') {\r\n fromOriginX = originXOffset[fromOriginX];\r\n }\r\n else {\r\n fromOriginX -= 0.5;\r\n }\r\n\r\n if (typeof toOriginX === 'string') {\r\n toOriginX = originXOffset[toOriginX];\r\n }\r\n else {\r\n toOriginX -= 0.5;\r\n }\r\n\r\n offsetX = toOriginX - fromOriginX;\r\n\r\n if (typeof fromOriginY === 'string') {\r\n fromOriginY = originYOffset[fromOriginY];\r\n }\r\n else {\r\n fromOriginY -= 0.5;\r\n }\r\n\r\n if (typeof toOriginY === 'string') {\r\n toOriginY = originYOffset[toOriginY];\r\n }\r\n else {\r\n toOriginY -= 0.5;\r\n }\r\n\r\n offsetY = toOriginY - fromOriginY;\r\n\r\n if (offsetX || offsetY) {\r\n dim = this._getTransformedDimensions();\r\n x = point.x + offsetX * dim.x;\r\n y = point.y + offsetY * dim.y;\r\n }\r\n\r\n return new fabric.Point(x, y);\r\n },\r\n\r\n /**\r\n * Translates the coordinates from origin to center coordinates (based on the object's dimensions)\r\n * @param {fabric.Point} point The point which corresponds to the originX and originY params\r\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\r\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\r\n * @return {fabric.Point}\r\n */\r\n translateToCenterPoint: function(point, originX, originY) {\r\n var p = this.translateToGivenOrigin(point, originX, originY, 'center', 'center');\r\n if (this.angle) {\r\n return fabric.util.rotatePoint(p, point, degreesToRadians(this.angle));\r\n }\r\n return p;\r\n },\r\n\r\n /**\r\n * Translates the coordinates from center to origin coordinates (based on the object's dimensions)\r\n * @param {fabric.Point} center The point which corresponds to center of the object\r\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\r\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\r\n * @return {fabric.Point}\r\n */\r\n translateToOriginPoint: function(center, originX, originY) {\r\n var p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY);\r\n if (this.angle) {\r\n return fabric.util.rotatePoint(p, center, degreesToRadians(this.angle));\r\n }\r\n return p;\r\n },\r\n\r\n /**\r\n * Returns the real center coordinates of the object\r\n * @return {fabric.Point}\r\n */\r\n getCenterPoint: function() {\r\n var leftTop = new fabric.Point(this.left, this.top);\r\n return this.translateToCenterPoint(leftTop, this.originX, this.originY);\r\n },\r\n\r\n /**\r\n * Returns the coordinates of the object based on center coordinates\r\n * @param {fabric.Point} point The point which corresponds to the originX and originY params\r\n * @return {fabric.Point}\r\n */\r\n // getOriginPoint: function(center) {\r\n // return this.translateToOriginPoint(center, this.originX, this.originY);\r\n // },\r\n\r\n /**\r\n * Returns the coordinates of the object as if it has a different origin\r\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\r\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\r\n * @return {fabric.Point}\r\n */\r\n getPointByOrigin: function(originX, originY) {\r\n var center = this.getCenterPoint();\r\n return this.translateToOriginPoint(center, originX, originY);\r\n },\r\n\r\n /**\r\n * Returns the point in local coordinates\r\n * @param {fabric.Point} point The point relative to the global coordinate system\r\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\r\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\r\n * @return {fabric.Point}\r\n */\r\n toLocalPoint: function(point, originX, originY) {\r\n var center = this.getCenterPoint(),\r\n p, p2;\r\n\r\n if (typeof originX !== 'undefined' && typeof originY !== 'undefined' ) {\r\n p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY);\r\n }\r\n else {\r\n p = new fabric.Point(this.left, this.top);\r\n }\r\n\r\n p2 = new fabric.Point(point.x, point.y);\r\n if (this.angle) {\r\n p2 = fabric.util.rotatePoint(p2, center, -degreesToRadians(this.angle));\r\n }\r\n return p2.subtractEquals(p);\r\n },\r\n\r\n /**\r\n * Returns the point in global coordinates\r\n * @param {fabric.Point} The point relative to the local coordinate system\r\n * @return {fabric.Point}\r\n */\r\n // toGlobalPoint: function(point) {\r\n // return fabric.util.rotatePoint(point, this.getCenterPoint(), degreesToRadians(this.angle)).addEquals(new fabric.Point(this.left, this.top));\r\n // },\r\n\r\n /**\r\n * Sets the position of the object taking into consideration the object's origin\r\n * @param {fabric.Point} pos The new position of the object\r\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\r\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\r\n * @return {void}\r\n */\r\n setPositionByOrigin: function(pos, originX, originY) {\r\n var center = this.translateToCenterPoint(pos, originX, originY),\r\n position = this.translateToOriginPoint(center, this.originX, this.originY);\r\n this.set('left', position.x);\r\n this.set('top', position.y);\r\n },\r\n\r\n /**\r\n * @param {String} to One of 'left', 'center', 'right'\r\n */\r\n adjustPosition: function(to) {\r\n var angle = degreesToRadians(this.angle),\r\n hypotFull = this.getScaledWidth(),\r\n xFull = fabric.util.cos(angle) * hypotFull,\r\n yFull = fabric.util.sin(angle) * hypotFull,\r\n offsetFrom, offsetTo;\r\n\r\n //TODO: this function does not consider mixed situation like top, center.\r\n if (typeof this.originX === 'string') {\r\n offsetFrom = originXOffset[this.originX];\r\n }\r\n else {\r\n offsetFrom = this.originX - 0.5;\r\n }\r\n if (typeof to === 'string') {\r\n offsetTo = originXOffset[to];\r\n }\r\n else {\r\n offsetTo = to - 0.5;\r\n }\r\n this.left += xFull * (offsetTo - offsetFrom);\r\n this.top += yFull * (offsetTo - offsetFrom);\r\n this.setCoords();\r\n this.originX = to;\r\n },\r\n\r\n /**\r\n * Sets the origin/position of the object to it's center point\r\n * @private\r\n * @return {void}\r\n */\r\n _setOriginToCenter: function() {\r\n this._originalOriginX = this.originX;\r\n this._originalOriginY = this.originY;\r\n\r\n var center = this.getCenterPoint();\r\n\r\n this.originX = 'center';\r\n this.originY = 'center';\r\n\r\n this.left = center.x;\r\n this.top = center.y;\r\n },\r\n\r\n /**\r\n * Resets the origin/position of the object to it's original origin\r\n * @private\r\n * @return {void}\r\n */\r\n _resetOrigin: function() {\r\n var originPoint = this.translateToOriginPoint(\r\n this.getCenterPoint(),\r\n this._originalOriginX,\r\n this._originalOriginY);\r\n\r\n this.originX = this._originalOriginX;\r\n this.originY = this._originalOriginY;\r\n\r\n this.left = originPoint.x;\r\n this.top = originPoint.y;\r\n\r\n this._originalOriginX = null;\r\n this._originalOriginY = null;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _getLeftTopCoords: function() {\r\n return this.translateToOriginPoint(this.getCenterPoint(), 'left', 'top');\r\n },\r\n });\r\n\r\n})();\r\n\r\n\r\n(function() {\r\n\r\n function arrayFromCoords(coords) {\r\n return [\r\n new fabric.Point(coords.tl.x, coords.tl.y),\r\n new fabric.Point(coords.tr.x, coords.tr.y),\r\n new fabric.Point(coords.br.x, coords.br.y),\r\n new fabric.Point(coords.bl.x, coords.bl.y)\r\n ];\r\n }\r\n\r\n var util = fabric.util,\r\n degreesToRadians = util.degreesToRadians,\r\n multiplyMatrices = util.multiplyTransformMatrices,\r\n transformPoint = util.transformPoint;\r\n\r\n util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\r\n\r\n /**\r\n * Describe object's corner position in canvas element coordinates.\r\n * properties are depending on control keys and padding the main controls.\r\n * each property is an object with x, y and corner.\r\n * The `corner` property contains in a similar manner the 4 points of the\r\n * interactive area of the corner.\r\n * The coordinates depends from the controls positionHandler and are used\r\n * to draw and locate controls\r\n * @memberOf fabric.Object.prototype\r\n */\r\n oCoords: null,\r\n\r\n /**\r\n * Describe object's corner position in canvas object absolute coordinates\r\n * properties are tl,tr,bl,br and describe the four main corner.\r\n * each property is an object with x, y, instance of Fabric.Point.\r\n * The coordinates depends from this properties: width, height, scaleX, scaleY\r\n * skewX, skewY, angle, strokeWidth, top, left.\r\n * Those coordinates are useful to understand where an object is. They get updated\r\n * with oCoords but they do not need to be updated when zoom or panning change.\r\n * The coordinates get updated with @method setCoords.\r\n * You can calculate them without updating with @method calcACoords();\r\n * @memberOf fabric.Object.prototype\r\n */\r\n aCoords: null,\r\n\r\n /**\r\n * Describe object's corner position in canvas element coordinates.\r\n * includes padding. Used of object detection.\r\n * set and refreshed with setCoords.\r\n * @memberOf fabric.Object.prototype\r\n */\r\n lineCoords: null,\r\n\r\n /**\r\n * storage for object transform matrix\r\n */\r\n ownMatrixCache: null,\r\n\r\n /**\r\n * storage for object full transform matrix\r\n */\r\n matrixCache: null,\r\n\r\n /**\r\n * custom controls interface\r\n * controls are added by default_controls.js\r\n */\r\n controls: { },\r\n\r\n /**\r\n * return correct set of coordinates for intersection\r\n * this will return either aCoords or lineCoords.\r\n * @param {Boolean} absolute will return aCoords if true or lineCoords\r\n * @return {Object} {tl, tr, br, bl} points\r\n */\r\n _getCoords: function(absolute, calculate) {\r\n if (calculate) {\r\n return (absolute ? this.calcACoords() : this.calcLineCoords());\r\n }\r\n if (!this.aCoords || !this.lineCoords) {\r\n this.setCoords(true);\r\n }\r\n return (absolute ? this.aCoords : this.lineCoords);\r\n },\r\n\r\n /**\r\n * return correct set of coordinates for intersection\r\n * this will return either aCoords or lineCoords.\r\n * The coords are returned in an array.\r\n * @return {Array} [tl, tr, br, bl] of points\r\n */\r\n getCoords: function(absolute, calculate) {\r\n return arrayFromCoords(this._getCoords(absolute, calculate));\r\n },\r\n\r\n /**\r\n * Checks if object intersects with an area formed by 2 points\r\n * @param {Object} pointTL top-left point of area\r\n * @param {Object} pointBR bottom-right point of area\r\n * @param {Boolean} [absolute] use coordinates without viewportTransform\r\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\r\n * @return {Boolean} true if object intersects with an area formed by 2 points\r\n */\r\n intersectsWithRect: function(pointTL, pointBR, absolute, calculate) {\r\n var coords = this.getCoords(absolute, calculate),\r\n intersection = fabric.Intersection.intersectPolygonRectangle(\r\n coords,\r\n pointTL,\r\n pointBR\r\n );\r\n return intersection.status === 'Intersection';\r\n },\r\n\r\n /**\r\n * Checks if object intersects with another object\r\n * @param {Object} other Object to test\r\n * @param {Boolean} [absolute] use coordinates without viewportTransform\r\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\r\n * @return {Boolean} true if object intersects with another object\r\n */\r\n intersectsWithObject: function(other, absolute, calculate) {\r\n var intersection = fabric.Intersection.intersectPolygonPolygon(\r\n this.getCoords(absolute, calculate),\r\n other.getCoords(absolute, calculate)\r\n );\r\n\r\n return intersection.status === 'Intersection'\r\n || other.isContainedWithinObject(this, absolute, calculate)\r\n || this.isContainedWithinObject(other, absolute, calculate);\r\n },\r\n\r\n /**\r\n * Checks if object is fully contained within area of another object\r\n * @param {Object} other Object to test\r\n * @param {Boolean} [absolute] use coordinates without viewportTransform\r\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\r\n * @return {Boolean} true if object is fully contained within area of another object\r\n */\r\n isContainedWithinObject: function(other, absolute, calculate) {\r\n var points = this.getCoords(absolute, calculate),\r\n otherCoords = absolute ? other.aCoords : other.lineCoords,\r\n i = 0, lines = other._getImageLines(otherCoords);\r\n for (; i < 4; i++) {\r\n if (!other.containsPoint(points[i], lines)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n },\r\n\r\n /**\r\n * Checks if object is fully contained within area formed by 2 points\r\n * @param {Object} pointTL top-left point of area\r\n * @param {Object} pointBR bottom-right point of area\r\n * @param {Boolean} [absolute] use coordinates without viewportTransform\r\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\r\n * @return {Boolean} true if object is fully contained within area formed by 2 points\r\n */\r\n isContainedWithinRect: function(pointTL, pointBR, absolute, calculate) {\r\n var boundingRect = this.getBoundingRect(absolute, calculate);\r\n\r\n return (\r\n boundingRect.left >= pointTL.x &&\r\n boundingRect.left + boundingRect.width <= pointBR.x &&\r\n boundingRect.top >= pointTL.y &&\r\n boundingRect.top + boundingRect.height <= pointBR.y\r\n );\r\n },\r\n\r\n /**\r\n * Checks if point is inside the object\r\n * @param {fabric.Point} point Point to check against\r\n * @param {Object} [lines] object returned from @method _getImageLines\r\n * @param {Boolean} [absolute] use coordinates without viewportTransform\r\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\r\n * @return {Boolean} true if point is inside the object\r\n */\r\n containsPoint: function(point, lines, absolute, calculate) {\r\n var coords = this._getCoords(absolute, calculate),\r\n lines = lines || this._getImageLines(coords),\r\n xPoints = this._findCrossPoints(point, lines);\r\n // if xPoints is odd then point is inside the object\r\n return (xPoints !== 0 && xPoints % 2 === 1);\r\n },\r\n\r\n /**\r\n * Checks if object is contained within the canvas with current viewportTransform\r\n * the check is done stopping at first point that appears on screen\r\n * @param {Boolean} [calculate] use coordinates of current position instead of .aCoords\r\n * @return {Boolean} true if object is fully or partially contained within canvas\r\n */\r\n isOnScreen: function(calculate) {\r\n if (!this.canvas) {\r\n return false;\r\n }\r\n var pointTL = this.canvas.vptCoords.tl, pointBR = this.canvas.vptCoords.br;\r\n var points = this.getCoords(true, calculate);\r\n // if some point is on screen, the object is on screen.\r\n if (points.some(function(point) {\r\n return point.x <= pointBR.x && point.x >= pointTL.x &&\r\n point.y <= pointBR.y && point.y >= pointTL.y;\r\n })) {\r\n return true;\r\n }\r\n // no points on screen, check intersection with absolute coordinates\r\n if (this.intersectsWithRect(pointTL, pointBR, true, calculate)) {\r\n return true;\r\n }\r\n return this._containsCenterOfCanvas(pointTL, pointBR, calculate);\r\n },\r\n\r\n /**\r\n * Checks if the object contains the midpoint between canvas extremities\r\n * Does not make sense outside the context of isOnScreen and isPartiallyOnScreen\r\n * @private\r\n * @param {Fabric.Point} pointTL Top Left point\r\n * @param {Fabric.Point} pointBR Top Right point\r\n * @param {Boolean} calculate use coordinates of current position instead of .oCoords\r\n * @return {Boolean} true if the object contains the point\r\n */\r\n _containsCenterOfCanvas: function(pointTL, pointBR, calculate) {\r\n // worst case scenario the object is so big that contains the screen\r\n var centerPoint = { x: (pointTL.x + pointBR.x) / 2, y: (pointTL.y + pointBR.y) / 2 };\r\n if (this.containsPoint(centerPoint, null, true, calculate)) {\r\n return true;\r\n }\r\n return false;\r\n },\r\n\r\n /**\r\n * Checks if object is partially contained within the canvas with current viewportTransform\r\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\r\n * @return {Boolean} true if object is partially contained within canvas\r\n */\r\n isPartiallyOnScreen: function(calculate) {\r\n if (!this.canvas) {\r\n return false;\r\n }\r\n var pointTL = this.canvas.vptCoords.tl, pointBR = this.canvas.vptCoords.br;\r\n if (this.intersectsWithRect(pointTL, pointBR, true, calculate)) {\r\n return true;\r\n }\r\n var allPointsAreOutside = this.getCoords(true, calculate).every(function(point) {\r\n return (point.x >= pointBR.x || point.x <= pointTL.x) &&\r\n (point.y >= pointBR.y || point.y <= pointTL.y);\r\n });\r\n return allPointsAreOutside && this._containsCenterOfCanvas(pointTL, pointBR, calculate);\r\n },\r\n\r\n /**\r\n * Method that returns an object with the object edges in it, given the coordinates of the corners\r\n * @private\r\n * @param {Object} oCoords Coordinates of the object corners\r\n */\r\n _getImageLines: function(oCoords) {\r\n\r\n var lines = {\r\n topline: {\r\n o: oCoords.tl,\r\n d: oCoords.tr\r\n },\r\n rightline: {\r\n o: oCoords.tr,\r\n d: oCoords.br\r\n },\r\n bottomline: {\r\n o: oCoords.br,\r\n d: oCoords.bl\r\n },\r\n leftline: {\r\n o: oCoords.bl,\r\n d: oCoords.tl\r\n }\r\n };\r\n\r\n // // debugging\r\n // if (this.canvas.contextTop) {\r\n // this.canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);\r\n // this.canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);\r\n //\r\n // this.canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);\r\n // this.canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);\r\n //\r\n // this.canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);\r\n // this.canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);\r\n //\r\n // this.canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);\r\n // this.canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);\r\n // }\r\n\r\n return lines;\r\n },\r\n\r\n /**\r\n * Helper method to determine how many cross points are between the 4 object edges\r\n * and the horizontal line determined by a point on canvas\r\n * @private\r\n * @param {fabric.Point} point Point to check\r\n * @param {Object} lines Coordinates of the object being evaluated\r\n */\r\n // remove yi, not used but left code here just in case.\r\n _findCrossPoints: function(point, lines) {\r\n var b1, b2, a1, a2, xi, // yi,\r\n xcount = 0,\r\n iLine;\r\n\r\n for (var lineKey in lines) {\r\n iLine = lines[lineKey];\r\n // optimisation 1: line below point. no cross\r\n if ((iLine.o.y < point.y) && (iLine.d.y < point.y)) {\r\n continue;\r\n }\r\n // optimisation 2: line above point. no cross\r\n if ((iLine.o.y >= point.y) && (iLine.d.y >= point.y)) {\r\n continue;\r\n }\r\n // optimisation 3: vertical line case\r\n if ((iLine.o.x === iLine.d.x) && (iLine.o.x >= point.x)) {\r\n xi = iLine.o.x;\r\n // yi = point.y;\r\n }\r\n // calculate the intersection point\r\n else {\r\n b1 = 0;\r\n b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x);\r\n a1 = point.y - b1 * point.x;\r\n a2 = iLine.o.y - b2 * iLine.o.x;\r\n\r\n xi = -(a1 - a2) / (b1 - b2);\r\n // yi = a1 + b1 * xi;\r\n }\r\n // dont count xi < point.x cases\r\n if (xi >= point.x) {\r\n xcount += 1;\r\n }\r\n // optimisation 4: specific for square images\r\n if (xcount === 2) {\r\n break;\r\n }\r\n }\r\n return xcount;\r\n },\r\n\r\n /**\r\n * Returns coordinates of object's bounding rectangle (left, top, width, height)\r\n * the box is intended as aligned to axis of canvas.\r\n * @param {Boolean} [absolute] use coordinates without viewportTransform\r\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords / .aCoords\r\n * @return {Object} Object with left, top, width, height properties\r\n */\r\n getBoundingRect: function(absolute, calculate) {\r\n var coords = this.getCoords(absolute, calculate);\r\n return util.makeBoundingBoxFromPoints(coords);\r\n },\r\n\r\n /**\r\n * Returns width of an object's bounding box counting transformations\r\n * before 2.0 it was named getWidth();\r\n * @return {Number} width value\r\n */\r\n getScaledWidth: function() {\r\n return this._getTransformedDimensions().x;\r\n },\r\n\r\n /**\r\n * Returns height of an object bounding box counting transformations\r\n * before 2.0 it was named getHeight();\r\n * @return {Number} height value\r\n */\r\n getScaledHeight: function() {\r\n return this._getTransformedDimensions().y;\r\n },\r\n\r\n /**\r\n * Makes sure the scale is valid and modifies it if necessary\r\n * @private\r\n * @param {Number} value\r\n * @return {Number}\r\n */\r\n _constrainScale: function(value) {\r\n if (Math.abs(value) < this.minScaleLimit) {\r\n if (value < 0) {\r\n return -this.minScaleLimit;\r\n }\r\n else {\r\n return this.minScaleLimit;\r\n }\r\n }\r\n else if (value === 0) {\r\n return 0.0001;\r\n }\r\n return value;\r\n },\r\n\r\n /**\r\n * Scales an object (equally by x and y)\r\n * @param {Number} value Scale factor\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n scale: function(value) {\r\n this._set('scaleX', value);\r\n this._set('scaleY', value);\r\n return this.setCoords();\r\n },\r\n\r\n /**\r\n * Scales an object to a given width, with respect to bounding box (scaling by x/y equally)\r\n * @param {Number} value New width value\r\n * @param {Boolean} absolute ignore viewport\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n scaleToWidth: function(value, absolute) {\r\n // adjust to bounding rect factor so that rotated shapes would fit as well\r\n var boundingRectFactor = this.getBoundingRect(absolute).width / this.getScaledWidth();\r\n return this.scale(value / this.width / boundingRectFactor);\r\n },\r\n\r\n /**\r\n * Scales an object to a given height, with respect to bounding box (scaling by x/y equally)\r\n * @param {Number} value New height value\r\n * @param {Boolean} absolute ignore viewport\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n scaleToHeight: function(value, absolute) {\r\n // adjust to bounding rect factor so that rotated shapes would fit as well\r\n var boundingRectFactor = this.getBoundingRect(absolute).height / this.getScaledHeight();\r\n return this.scale(value / this.height / boundingRectFactor);\r\n },\r\n\r\n calcLineCoords: function() {\r\n var vpt = this.getViewportTransform(),\r\n padding = this.padding, angle = degreesToRadians(this.angle),\r\n cos = util.cos(angle), sin = util.sin(angle),\r\n cosP = cos * padding, sinP = sin * padding, cosPSinP = cosP + sinP,\r\n cosPMinusSinP = cosP - sinP, aCoords = this.calcACoords();\r\n\r\n var lineCoords = {\r\n tl: transformPoint(aCoords.tl, vpt),\r\n tr: transformPoint(aCoords.tr, vpt),\r\n bl: transformPoint(aCoords.bl, vpt),\r\n br: transformPoint(aCoords.br, vpt),\r\n };\r\n\r\n if (padding) {\r\n lineCoords.tl.x -= cosPMinusSinP;\r\n lineCoords.tl.y -= cosPSinP;\r\n lineCoords.tr.x += cosPSinP;\r\n lineCoords.tr.y -= cosPMinusSinP;\r\n lineCoords.bl.x -= cosPSinP;\r\n lineCoords.bl.y += cosPMinusSinP;\r\n lineCoords.br.x += cosPMinusSinP;\r\n lineCoords.br.y += cosPSinP;\r\n }\r\n\r\n return lineCoords;\r\n },\r\n\r\n calcOCoords: function() {\r\n var rotateMatrix = this._calcRotateMatrix(),\r\n translateMatrix = this._calcTranslateMatrix(),\r\n vpt = this.getViewportTransform(),\r\n startMatrix = multiplyMatrices(vpt, translateMatrix),\r\n finalMatrix = multiplyMatrices(startMatrix, rotateMatrix),\r\n finalMatrix = multiplyMatrices(finalMatrix, [1 / vpt[0], 0, 0, 1 / vpt[3], 0, 0]),\r\n dim = this._calculateCurrentDimensions(),\r\n coords = {};\r\n this.forEachControl(function(control, key, fabricObject) {\r\n coords[key] = control.positionHandler(dim, finalMatrix, fabricObject);\r\n });\r\n\r\n // debug code\r\n // var canvas = this.canvas;\r\n // setTimeout(function() {\r\n // canvas.contextTop.clearRect(0, 0, 700, 700);\r\n // canvas.contextTop.fillStyle = 'green';\r\n // Object.keys(coords).forEach(function(key) {\r\n // var control = coords[key];\r\n // canvas.contextTop.fillRect(control.x, control.y, 3, 3);\r\n // });\r\n // }, 50);\r\n return coords;\r\n },\r\n\r\n calcACoords: function() {\r\n var rotateMatrix = this._calcRotateMatrix(),\r\n translateMatrix = this._calcTranslateMatrix(),\r\n finalMatrix = multiplyMatrices(translateMatrix, rotateMatrix),\r\n dim = this._getTransformedDimensions(),\r\n w = dim.x / 2, h = dim.y / 2;\r\n return {\r\n // corners\r\n tl: transformPoint({ x: -w, y: -h }, finalMatrix),\r\n tr: transformPoint({ x: w, y: -h }, finalMatrix),\r\n bl: transformPoint({ x: -w, y: h }, finalMatrix),\r\n br: transformPoint({ x: w, y: h }, finalMatrix)\r\n };\r\n },\r\n\r\n /**\r\n * Sets corner and controls position coordinates based on current angle, width and height, left and top.\r\n * oCoords are used to find the corners\r\n * aCoords are used to quickly find an object on the canvas\r\n * lineCoords are used to quickly find object during pointer events.\r\n * See {@link https://github.com/fabricjs/fabric.js/wiki/When-to-call-setCoords} and {@link http://fabricjs.com/fabric-gotchas}\r\n *\r\n * @param {Boolean} [skipCorners] skip calculation of oCoords.\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n setCoords: function(skipCorners) {\r\n this.aCoords = this.calcACoords();\r\n // in case we are in a group, for how the inner group target check works,\r\n // lineCoords are exactly aCoords. Since the vpt gets absorbed by the normalized pointer.\r\n this.lineCoords = this.group ? this.aCoords : this.calcLineCoords();\r\n if (skipCorners) {\r\n return this;\r\n }\r\n // set coordinates of the draggable boxes in the corners used to scale/rotate the image\r\n this.oCoords = this.calcOCoords();\r\n this._setCornerCoords && this._setCornerCoords();\r\n return this;\r\n },\r\n\r\n /**\r\n * calculate rotation matrix of an object\r\n * @return {Array} rotation matrix for the object\r\n */\r\n _calcRotateMatrix: function() {\r\n return util.calcRotateMatrix(this);\r\n },\r\n\r\n /**\r\n * calculate the translation matrix for an object transform\r\n * @return {Array} rotation matrix for the object\r\n */\r\n _calcTranslateMatrix: function() {\r\n var center = this.getCenterPoint();\r\n return [1, 0, 0, 1, center.x, center.y];\r\n },\r\n\r\n transformMatrixKey: function(skipGroup) {\r\n var sep = '_', prefix = '';\r\n if (!skipGroup && this.group) {\r\n prefix = this.group.transformMatrixKey(skipGroup) + sep;\r\n };\r\n return prefix + this.top + sep + this.left + sep + this.scaleX + sep + this.scaleY +\r\n sep + this.skewX + sep + this.skewY + sep + this.angle + sep + this.originX + sep + this.originY +\r\n sep + this.width + sep + this.height + sep + this.strokeWidth + this.flipX + this.flipY;\r\n },\r\n\r\n /**\r\n * calculate transform matrix that represents the current transformations from the\r\n * object's properties.\r\n * @param {Boolean} [skipGroup] return transform matrix for object not counting parent transformations\r\n * There are some situation in which this is useful to avoid the fake rotation.\r\n * @return {Array} transform matrix for the object\r\n */\r\n calcTransformMatrix: function(skipGroup) {\r\n var matrix = this.calcOwnMatrix();\r\n if (skipGroup || !this.group) {\r\n return matrix;\r\n }\r\n var key = this.transformMatrixKey(skipGroup), cache = this.matrixCache || (this.matrixCache = {});\r\n if (cache.key === key) {\r\n return cache.value;\r\n }\r\n if (this.group) {\r\n matrix = multiplyMatrices(this.group.calcTransformMatrix(false), matrix);\r\n }\r\n cache.key = key;\r\n cache.value = matrix;\r\n return matrix;\r\n },\r\n\r\n /**\r\n * calculate transform matrix that represents the current transformations from the\r\n * object's properties, this matrix does not include the group transformation\r\n * @return {Array} transform matrix for the object\r\n */\r\n calcOwnMatrix: function() {\r\n var key = this.transformMatrixKey(true), cache = this.ownMatrixCache || (this.ownMatrixCache = {});\r\n if (cache.key === key) {\r\n return cache.value;\r\n }\r\n var tMatrix = this._calcTranslateMatrix(),\r\n options = {\r\n angle: this.angle,\r\n translateX: tMatrix[4],\r\n translateY: tMatrix[5],\r\n scaleX: this.scaleX,\r\n scaleY: this.scaleY,\r\n skewX: this.skewX,\r\n skewY: this.skewY,\r\n flipX: this.flipX,\r\n flipY: this.flipY,\r\n };\r\n cache.key = key;\r\n cache.value = util.composeMatrix(options);\r\n return cache.value;\r\n },\r\n\r\n /*\r\n * Calculate object dimensions from its properties\r\n * @private\r\n * @return {Object} .x width dimension\r\n * @return {Object} .y height dimension\r\n */\r\n _getNonTransformedDimensions: function() {\r\n var strokeWidth = this.strokeWidth,\r\n w = this.width + strokeWidth,\r\n h = this.height + strokeWidth;\r\n return { x: w, y: h };\r\n },\r\n\r\n /*\r\n * Calculate object bounding box dimensions from its properties scale, skew.\r\n * @param {Number} skewX, a value to override current skewX\r\n * @param {Number} skewY, a value to override current skewY\r\n * @private\r\n * @return {Object} .x width dimension\r\n * @return {Object} .y height dimension\r\n */\r\n _getTransformedDimensions: function(skewX, skewY) {\r\n if (typeof skewX === 'undefined') {\r\n skewX = this.skewX;\r\n }\r\n if (typeof skewY === 'undefined') {\r\n skewY = this.skewY;\r\n }\r\n var dimensions, dimX, dimY,\r\n noSkew = skewX === 0 && skewY === 0;\r\n\r\n if (this.strokeUniform) {\r\n dimX = this.width;\r\n dimY = this.height;\r\n }\r\n else {\r\n dimensions = this._getNonTransformedDimensions();\r\n dimX = dimensions.x;\r\n dimY = dimensions.y;\r\n }\r\n if (noSkew) {\r\n return this._finalizeDimensions(dimX * this.scaleX, dimY * this.scaleY);\r\n }\r\n var bbox = util.sizeAfterTransform(dimX, dimY, {\r\n scaleX: this.scaleX,\r\n scaleY: this.scaleY,\r\n skewX: skewX,\r\n skewY: skewY,\r\n });\r\n return this._finalizeDimensions(bbox.x, bbox.y);\r\n },\r\n\r\n /*\r\n * Calculate object bounding box dimensions from its properties scale, skew.\r\n * @param Number width width of the bbox\r\n * @param Number height height of the bbox\r\n * @private\r\n * @return {Object} .x finalized width dimension\r\n * @return {Object} .y finalized height dimension\r\n */\r\n _finalizeDimensions: function(width, height) {\r\n return this.strokeUniform ?\r\n { x: width + this.strokeWidth, y: height + this.strokeWidth }\r\n :\r\n { x: width, y: height };\r\n },\r\n\r\n /*\r\n * Calculate object dimensions for controls box, including padding and canvas zoom.\r\n * and active selection\r\n * private\r\n */\r\n _calculateCurrentDimensions: function() {\r\n var vpt = this.getViewportTransform(),\r\n dim = this._getTransformedDimensions(),\r\n p = transformPoint(dim, vpt, true);\r\n return p.scalarAdd(2 * this.padding);\r\n },\r\n });\r\n})();\r\n\r\n\r\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\r\n\r\n /**\r\n * Moves an object to the bottom of the stack of drawn objects\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n sendToBack: function() {\r\n if (this.group) {\r\n fabric.StaticCanvas.prototype.sendToBack.call(this.group, this);\r\n }\r\n else if (this.canvas) {\r\n this.canvas.sendToBack(this);\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Moves an object to the top of the stack of drawn objects\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n bringToFront: function() {\r\n if (this.group) {\r\n fabric.StaticCanvas.prototype.bringToFront.call(this.group, this);\r\n }\r\n else if (this.canvas) {\r\n this.canvas.bringToFront(this);\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Moves an object down in stack of drawn objects\r\n * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n sendBackwards: function(intersecting) {\r\n if (this.group) {\r\n fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting);\r\n }\r\n else if (this.canvas) {\r\n this.canvas.sendBackwards(this, intersecting);\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Moves an object up in stack of drawn objects\r\n * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n bringForward: function(intersecting) {\r\n if (this.group) {\r\n fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting);\r\n }\r\n else if (this.canvas) {\r\n this.canvas.bringForward(this, intersecting);\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Moves an object to specified level in stack of drawn objects\r\n * @param {Number} index New position of object\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n moveTo: function(index) {\r\n if (this.group && this.group.type !== 'activeSelection') {\r\n fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index);\r\n }\r\n else if (this.canvas) {\r\n this.canvas.moveTo(this, index);\r\n }\r\n return this;\r\n }\r\n});\r\n\r\n\r\n/* _TO_SVG_START_ */\r\n(function() {\r\n function getSvgColorString(prop, value) {\r\n if (!value) {\r\n return prop + ': none; ';\r\n }\r\n else if (value.toLive) {\r\n return prop + ': url(#SVGID_' + value.id + '); ';\r\n }\r\n else {\r\n var color = new fabric.Color(value),\r\n str = prop + ': ' + color.toRgb() + '; ',\r\n opacity = color.getAlpha();\r\n if (opacity !== 1) {\r\n //change the color in rgb + opacity\r\n str += prop + '-opacity: ' + opacity.toString() + '; ';\r\n }\r\n return str;\r\n }\r\n }\r\n\r\n var toFixed = fabric.util.toFixed;\r\n\r\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\r\n /**\r\n * Returns styles-string for svg-export\r\n * @param {Boolean} skipShadow a boolean to skip shadow filter output\r\n * @return {String}\r\n */\r\n getSvgStyles: function(skipShadow) {\r\n\r\n var fillRule = this.fillRule ? this.fillRule : 'nonzero',\r\n strokeWidth = this.strokeWidth ? this.strokeWidth : '0',\r\n strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : 'none',\r\n strokeDashOffset = this.strokeDashOffset ? this.strokeDashOffset : '0',\r\n strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt',\r\n strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter',\r\n strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4',\r\n opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1',\r\n visibility = this.visible ? '' : ' visibility: hidden;',\r\n filter = skipShadow ? '' : this.getSvgFilter(),\r\n fill = getSvgColorString('fill', this.fill),\r\n stroke = getSvgColorString('stroke', this.stroke);\r\n\r\n return [\r\n stroke,\r\n 'stroke-width: ', strokeWidth, '; ',\r\n 'stroke-dasharray: ', strokeDashArray, '; ',\r\n 'stroke-linecap: ', strokeLineCap, '; ',\r\n 'stroke-dashoffset: ', strokeDashOffset, '; ',\r\n 'stroke-linejoin: ', strokeLineJoin, '; ',\r\n 'stroke-miterlimit: ', strokeMiterLimit, '; ',\r\n fill,\r\n 'fill-rule: ', fillRule, '; ',\r\n 'opacity: ', opacity, ';',\r\n filter,\r\n visibility\r\n ].join('');\r\n },\r\n\r\n /**\r\n * Returns styles-string for svg-export\r\n * @param {Object} style the object from which to retrieve style properties\r\n * @param {Boolean} useWhiteSpace a boolean to include an additional attribute in the style.\r\n * @return {String}\r\n */\r\n getSvgSpanStyles: function(style, useWhiteSpace) {\r\n var term = '; ';\r\n var fontFamily = style.fontFamily ?\r\n 'font-family: ' + (((style.fontFamily.indexOf('\\'') === -1 && style.fontFamily.indexOf('\"') === -1) ?\r\n '\\'' + style.fontFamily + '\\'' : style.fontFamily)) + term : '';\r\n var strokeWidth = style.strokeWidth ? 'stroke-width: ' + style.strokeWidth + term : '',\r\n fontFamily = fontFamily,\r\n fontSize = style.fontSize ? 'font-size: ' + style.fontSize + 'px' + term : '',\r\n fontStyle = style.fontStyle ? 'font-style: ' + style.fontStyle + term : '',\r\n fontWeight = style.fontWeight ? 'font-weight: ' + style.fontWeight + term : '',\r\n fill = style.fill ? getSvgColorString('fill', style.fill) : '',\r\n stroke = style.stroke ? getSvgColorString('stroke', style.stroke) : '',\r\n textDecoration = this.getSvgTextDecoration(style),\r\n deltaY = style.deltaY ? 'baseline-shift: ' + (-style.deltaY) + '; ' : '';\r\n if (textDecoration) {\r\n textDecoration = 'text-decoration: ' + textDecoration + term;\r\n }\r\n\r\n return [\r\n stroke,\r\n strokeWidth,\r\n fontFamily,\r\n fontSize,\r\n fontStyle,\r\n fontWeight,\r\n textDecoration,\r\n fill,\r\n deltaY,\r\n useWhiteSpace ? 'white-space: pre; ' : ''\r\n ].join('');\r\n },\r\n\r\n /**\r\n * Returns text-decoration property for svg-export\r\n * @param {Object} style the object from which to retrieve style properties\r\n * @return {String}\r\n */\r\n getSvgTextDecoration: function(style) {\r\n return ['overline', 'underline', 'line-through'].filter(function(decoration) {\r\n return style[decoration.replace('-', '')];\r\n }).join(' ');\r\n },\r\n\r\n /**\r\n * Returns filter for svg shadow\r\n * @return {String}\r\n */\r\n getSvgFilter: function() {\r\n return this.shadow ? 'filter: url(#SVGID_' + this.shadow.id + ');' : '';\r\n },\r\n\r\n /**\r\n * Returns id attribute for svg output\r\n * @return {String}\r\n */\r\n getSvgCommons: function() {\r\n return [\r\n this.id ? 'id=\"' + this.id + '\" ' : '',\r\n this.clipPath ? 'clip-path=\"url(#' + this.clipPath.clipPathId + ')\" ' : '',\r\n ].join('');\r\n },\r\n\r\n /**\r\n * Returns transform-string for svg-export\r\n * @param {Boolean} use the full transform or the single object one.\r\n * @return {String}\r\n */\r\n getSvgTransform: function(full, additionalTransform) {\r\n var transform = full ? this.calcTransformMatrix() : this.calcOwnMatrix(),\r\n svgTransform = 'transform=\"' + fabric.util.matrixToSVG(transform);\r\n return svgTransform +\r\n (additionalTransform || '') + '\" ';\r\n },\r\n\r\n _setSVGBg: function(textBgRects) {\r\n if (this.backgroundColor) {\r\n var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\r\n textBgRects.push(\r\n '\\t\\t\\n');\r\n }\r\n },\r\n\r\n /**\r\n * Returns svg representation of an instance\r\n * @param {Function} [reviver] Method for further parsing of svg representation.\r\n * @return {String} svg representation of an instance\r\n */\r\n toSVG: function(reviver) {\r\n return this._createBaseSVGMarkup(this._toSVG(reviver), { reviver: reviver });\r\n },\r\n\r\n /**\r\n * Returns svg clipPath representation of an instance\r\n * @param {Function} [reviver] Method for further parsing of svg representation.\r\n * @return {String} svg representation of an instance\r\n */\r\n toClipPathSVG: function(reviver) {\r\n return '\\t' + this._createBaseClipPathSVGMarkup(this._toSVG(reviver), { reviver: reviver });\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _createBaseClipPathSVGMarkup: function(objectMarkup, options) {\r\n options = options || {};\r\n var reviver = options.reviver,\r\n additionalTransform = options.additionalTransform || '',\r\n commonPieces = [\r\n this.getSvgTransform(true, additionalTransform),\r\n this.getSvgCommons(),\r\n ].join(''),\r\n // insert commons in the markup, style and svgCommons\r\n index = objectMarkup.indexOf('COMMON_PARTS');\r\n objectMarkup[index] = commonPieces;\r\n return reviver ? reviver(objectMarkup.join('')) : objectMarkup.join('');\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _createBaseSVGMarkup: function(objectMarkup, options) {\r\n options = options || {};\r\n var noStyle = options.noStyle,\r\n reviver = options.reviver,\r\n styleInfo = noStyle ? '' : 'style=\"' + this.getSvgStyles() + '\" ',\r\n shadowInfo = options.withShadow ? 'style=\"' + this.getSvgFilter() + '\" ' : '',\r\n clipPath = this.clipPath,\r\n vectorEffect = this.strokeUniform ? 'vector-effect=\"non-scaling-stroke\" ' : '',\r\n absoluteClipPath = clipPath && clipPath.absolutePositioned,\r\n stroke = this.stroke, fill = this.fill, shadow = this.shadow,\r\n commonPieces, markup = [], clipPathMarkup,\r\n // insert commons in the markup, style and svgCommons\r\n index = objectMarkup.indexOf('COMMON_PARTS'),\r\n additionalTransform = options.additionalTransform;\r\n if (clipPath) {\r\n clipPath.clipPathId = 'CLIPPATH_' + fabric.Object.__uid++;\r\n clipPathMarkup = '\\n' +\r\n clipPath.toClipPathSVG(reviver) +\r\n '\\n';\r\n }\r\n if (absoluteClipPath) {\r\n markup.push(\r\n '\\n'\r\n );\r\n }\r\n markup.push(\r\n '\\n'\r\n );\r\n commonPieces = [\r\n styleInfo,\r\n vectorEffect,\r\n noStyle ? '' : this.addPaintOrder(), ' ',\r\n additionalTransform ? 'transform=\"' + additionalTransform + '\" ' : '',\r\n ].join('');\r\n objectMarkup[index] = commonPieces;\r\n if (fill && fill.toLive) {\r\n markup.push(fill.toSVG(this));\r\n }\r\n if (stroke && stroke.toLive) {\r\n markup.push(stroke.toSVG(this));\r\n }\r\n if (shadow) {\r\n markup.push(shadow.toSVG(this));\r\n }\r\n if (clipPath) {\r\n markup.push(clipPathMarkup);\r\n }\r\n markup.push(objectMarkup.join(''));\r\n markup.push('\\n');\r\n absoluteClipPath && markup.push('\\n');\r\n return reviver ? reviver(markup.join('')) : markup.join('');\r\n },\r\n\r\n addPaintOrder: function() {\r\n return this.paintFirst !== 'fill' ? ' paint-order=\"' + this.paintFirst + '\" ' : '';\r\n }\r\n });\r\n})();\r\n/* _TO_SVG_END_ */\r\n\r\n\r\n(function() {\r\n\r\n var extend = fabric.util.object.extend,\r\n originalSet = 'stateProperties';\r\n\r\n /*\r\n Depends on `stateProperties`\r\n */\r\n function saveProps(origin, destination, props) {\r\n var tmpObj = { }, deep = true;\r\n props.forEach(function(prop) {\r\n tmpObj[prop] = origin[prop];\r\n });\r\n\r\n extend(origin[destination], tmpObj, deep);\r\n }\r\n\r\n function _isEqual(origValue, currentValue, firstPass) {\r\n if (origValue === currentValue) {\r\n // if the objects are identical, return\r\n return true;\r\n }\r\n else if (Array.isArray(origValue)) {\r\n if (!Array.isArray(currentValue) || origValue.length !== currentValue.length) {\r\n return false;\r\n }\r\n for (var i = 0, len = origValue.length; i < len; i++) {\r\n if (!_isEqual(origValue[i], currentValue[i])) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n else if (origValue && typeof origValue === 'object') {\r\n var keys = Object.keys(origValue), key;\r\n if (!currentValue ||\r\n typeof currentValue !== 'object' ||\r\n (!firstPass && keys.length !== Object.keys(currentValue).length)\r\n ) {\r\n return false;\r\n }\r\n for (var i = 0, len = keys.length; i < len; i++) {\r\n key = keys[i];\r\n // since clipPath is in the statefull cache list and the clipPath objects\r\n // would be iterated as an object, this would lead to possible infinite recursion\r\n // we do not want to compare those.\r\n if (key === 'canvas' || key === 'group') {\r\n continue;\r\n }\r\n if (!_isEqual(origValue[key], currentValue[key])) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n }\r\n\r\n\r\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\r\n\r\n /**\r\n * Returns true if object state (one of its state properties) was changed\r\n * @param {String} [propertySet] optional name for the set of property we want to save\r\n * @return {Boolean} true if instance' state has changed since `{@link fabric.Object#saveState}` was called\r\n */\r\n hasStateChanged: function(propertySet) {\r\n propertySet = propertySet || originalSet;\r\n var dashedPropertySet = '_' + propertySet;\r\n if (Object.keys(this[dashedPropertySet]).length < this[propertySet].length) {\r\n return true;\r\n }\r\n return !_isEqual(this[dashedPropertySet], this, true);\r\n },\r\n\r\n /**\r\n * Saves state of an object\r\n * @param {Object} [options] Object with additional `stateProperties` array to include when saving state\r\n * @return {fabric.Object} thisArg\r\n */\r\n saveState: function(options) {\r\n var propertySet = options && options.propertySet || originalSet,\r\n destination = '_' + propertySet;\r\n if (!this[destination]) {\r\n return this.setupState(options);\r\n }\r\n saveProps(this, destination, this[propertySet]);\r\n if (options && options.stateProperties) {\r\n saveProps(this, destination, options.stateProperties);\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Setups state of an object\r\n * @param {Object} [options] Object with additional `stateProperties` array to include when saving state\r\n * @return {fabric.Object} thisArg\r\n */\r\n setupState: function(options) {\r\n options = options || { };\r\n var propertySet = options.propertySet || originalSet;\r\n options.propertySet = propertySet;\r\n this['_' + propertySet] = { };\r\n this.saveState(options);\r\n return this;\r\n }\r\n });\r\n})();\r\n\r\n\r\n(function() {\r\n\r\n var degreesToRadians = fabric.util.degreesToRadians;\r\n\r\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\r\n /**\r\n * Determines which corner has been clicked\r\n * @private\r\n * @param {Object} pointer The pointer indicating the mouse position\r\n * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or false if nothing is found\r\n */\r\n _findTargetCorner: function(pointer, forTouch) {\r\n // objects in group, anykind, are not self modificable,\r\n // must not return an hovered corner.\r\n if (!this.hasControls || this.group || (!this.canvas || this.canvas._activeObject !== this)) {\r\n return false;\r\n }\r\n\r\n var ex = pointer.x,\r\n ey = pointer.y,\r\n xPoints,\r\n lines, keys = Object.keys(this.oCoords),\r\n j = keys.length - 1, i;\r\n this.__corner = 0;\r\n\r\n // cycle in reverse order so we pick first the one on top\r\n for (; j >= 0; j--) {\r\n i = keys[j];\r\n if (!this.isControlVisible(i)) {\r\n continue;\r\n }\r\n\r\n lines = this._getImageLines(forTouch ? this.oCoords[i].touchCorner : this.oCoords[i].corner);\r\n // // debugging\r\n //\r\n // this.canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);\r\n // this.canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);\r\n //\r\n // this.canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);\r\n // this.canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);\r\n //\r\n // this.canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);\r\n // this.canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);\r\n //\r\n // this.canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);\r\n // this.canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);\r\n\r\n xPoints = this._findCrossPoints({ x: ex, y: ey }, lines);\r\n if (xPoints !== 0 && xPoints % 2 === 1) {\r\n this.__corner = i;\r\n return i;\r\n }\r\n }\r\n return false;\r\n },\r\n\r\n /**\r\n * Calls a function for each control. The function gets called,\r\n * with the control, the object that is calling the iterator and the control's key\r\n * @param {Function} fn function to iterate over the controls over\r\n */\r\n forEachControl: function(fn) {\r\n for (var i in this.controls) {\r\n fn(this.controls[i], i, this);\r\n };\r\n },\r\n\r\n /**\r\n * Sets the coordinates of the draggable boxes in the corners of\r\n * the image used to scale/rotate it.\r\n * note: if we would switch to ROUND corner area, all of this would disappear.\r\n * everything would resolve to a single point and a pythagorean theorem for the distance\r\n * @private\r\n */\r\n _setCornerCoords: function() {\r\n var coords = this.oCoords;\r\n\r\n for (var control in coords) {\r\n var controlObject = this.controls[control];\r\n coords[control].corner = controlObject.calcCornerCoords(\r\n this.angle, this.cornerSize, coords[control].x, coords[control].y, false);\r\n coords[control].touchCorner = controlObject.calcCornerCoords(\r\n this.angle, this.touchCornerSize, coords[control].x, coords[control].y, true);\r\n }\r\n },\r\n\r\n /**\r\n * Draws a colored layer behind the object, inside its selection borders.\r\n * Requires public options: padding, selectionBackgroundColor\r\n * this function is called when the context is transformed\r\n * has checks to be skipped when the object is on a staticCanvas\r\n * @param {CanvasRenderingContext2D} ctx Context to draw on\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n drawSelectionBackground: function(ctx) {\r\n if (!this.selectionBackgroundColor ||\r\n (this.canvas && !this.canvas.interactive) ||\r\n (this.canvas && this.canvas._activeObject !== this)\r\n ) {\r\n return this;\r\n }\r\n ctx.save();\r\n var center = this.getCenterPoint(), wh = this._calculateCurrentDimensions(),\r\n vpt = this.canvas.viewportTransform;\r\n ctx.translate(center.x, center.y);\r\n ctx.scale(1 / vpt[0], 1 / vpt[3]);\r\n ctx.rotate(degreesToRadians(this.angle));\r\n ctx.fillStyle = this.selectionBackgroundColor;\r\n ctx.fillRect(-wh.x / 2, -wh.y / 2, wh.x, wh.y);\r\n ctx.restore();\r\n return this;\r\n },\r\n\r\n /**\r\n * Draws borders of an object's bounding box.\r\n * Requires public properties: width, height\r\n * Requires public options: padding, borderColor\r\n * @param {CanvasRenderingContext2D} ctx Context to draw on\r\n * @param {Object} styleOverride object to override the object style\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n drawBorders: function(ctx, styleOverride) {\r\n styleOverride = styleOverride || {};\r\n var wh = this._calculateCurrentDimensions(),\r\n strokeWidth = this.borderScaleFactor,\r\n width = wh.x + strokeWidth,\r\n height = wh.y + strokeWidth,\r\n hasControls = typeof styleOverride.hasControls !== 'undefined' ?\r\n styleOverride.hasControls : this.hasControls,\r\n shouldStroke = false;\r\n\r\n ctx.save();\r\n ctx.strokeStyle = styleOverride.borderColor || this.borderColor;\r\n this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray);\r\n\r\n ctx.strokeRect(\r\n -width / 2,\r\n -height / 2,\r\n width,\r\n height\r\n );\r\n\r\n if (hasControls) {\r\n ctx.beginPath();\r\n this.forEachControl(function(control, key, fabricObject) {\r\n // in this moment, the ctx is centered on the object.\r\n // width and height of the above function are the size of the bbox.\r\n if (control.withConnection && control.getVisibility(fabricObject, key)) {\r\n // reset movement for each control\r\n shouldStroke = true;\r\n ctx.moveTo(control.x * width, control.y * height);\r\n ctx.lineTo(\r\n control.x * width + control.offsetX,\r\n control.y * height + control.offsetY\r\n );\r\n }\r\n });\r\n if (shouldStroke) {\r\n ctx.stroke();\r\n }\r\n }\r\n ctx.restore();\r\n return this;\r\n },\r\n\r\n /**\r\n * Draws borders of an object's bounding box when it is inside a group.\r\n * Requires public properties: width, height\r\n * Requires public options: padding, borderColor\r\n * @param {CanvasRenderingContext2D} ctx Context to draw on\r\n * @param {object} options object representing current object parameters\r\n * @param {Object} styleOverride object to override the object style\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n drawBordersInGroup: function(ctx, options, styleOverride) {\r\n styleOverride = styleOverride || {};\r\n var bbox = fabric.util.sizeAfterTransform(this.width, this.height, options),\r\n strokeWidth = this.strokeWidth,\r\n strokeUniform = this.strokeUniform,\r\n borderScaleFactor = this.borderScaleFactor,\r\n width =\r\n bbox.x + strokeWidth * (strokeUniform ? this.canvas.getZoom() : options.scaleX) + borderScaleFactor,\r\n height =\r\n bbox.y + strokeWidth * (strokeUniform ? this.canvas.getZoom() : options.scaleY) + borderScaleFactor;\r\n ctx.save();\r\n this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray);\r\n ctx.strokeStyle = styleOverride.borderColor || this.borderColor;\r\n ctx.strokeRect(\r\n -width / 2,\r\n -height / 2,\r\n width,\r\n height\r\n );\r\n\r\n ctx.restore();\r\n return this;\r\n },\r\n\r\n /**\r\n * Draws corners of an object's bounding box.\r\n * Requires public properties: width, height\r\n * Requires public options: cornerSize, padding\r\n * @param {CanvasRenderingContext2D} ctx Context to draw on\r\n * @param {Object} styleOverride object to override the object style\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n drawControls: function(ctx, styleOverride) {\r\n styleOverride = styleOverride || {};\r\n ctx.save();\r\n var retinaScaling = this.canvas.getRetinaScaling(), matrix, p;\r\n ctx.setTransform(retinaScaling, 0, 0, retinaScaling, 0, 0);\r\n ctx.strokeStyle = ctx.fillStyle = styleOverride.cornerColor || this.cornerColor;\r\n if (!this.transparentCorners) {\r\n ctx.strokeStyle = styleOverride.cornerStrokeColor || this.cornerStrokeColor;\r\n }\r\n this._setLineDash(ctx, styleOverride.cornerDashArray || this.cornerDashArray);\r\n this.setCoords();\r\n if (this.group) {\r\n // fabricJS does not really support drawing controls inside groups,\r\n // this piece of code here helps having at least the control in places.\r\n // If an application needs to show some objects as selected because of some UI state\r\n // can still call Object._renderControls() on any object they desire, independently of groups.\r\n // using no padding, circular controls and hiding the rotating cursor is higly suggested,\r\n matrix = this.group.calcTransformMatrix();\r\n }\r\n this.forEachControl(function(control, key, fabricObject) {\r\n p = fabricObject.oCoords[key];\r\n if (control.getVisibility(fabricObject, key)) {\r\n if (matrix) {\r\n p = fabric.util.transformPoint(p, matrix);\r\n }\r\n control.render(ctx, p.x, p.y, styleOverride, fabricObject);\r\n }\r\n });\r\n ctx.restore();\r\n\r\n return this;\r\n },\r\n\r\n /**\r\n * Returns true if the specified control is visible, false otherwise.\r\n * @param {String} controlKey The key of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'.\r\n * @returns {Boolean} true if the specified control is visible, false otherwise\r\n */\r\n isControlVisible: function(controlKey) {\r\n return this.controls[controlKey] && this.controls[controlKey].getVisibility(this, controlKey);\r\n },\r\n\r\n /**\r\n * Sets the visibility of the specified control.\r\n * @param {String} controlKey The key of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'.\r\n * @param {Boolean} visible true to set the specified control visible, false otherwise\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n setControlVisible: function(controlKey, visible) {\r\n if (!this._controlsVisibility) {\r\n this._controlsVisibility = {};\r\n }\r\n this._controlsVisibility[controlKey] = visible;\r\n return this;\r\n },\r\n\r\n /**\r\n * Sets the visibility state of object controls.\r\n * @param {Object} [options] Options object\r\n * @param {Boolean} [options.bl] true to enable the bottom-left control, false to disable it\r\n * @param {Boolean} [options.br] true to enable the bottom-right control, false to disable it\r\n * @param {Boolean} [options.mb] true to enable the middle-bottom control, false to disable it\r\n * @param {Boolean} [options.ml] true to enable the middle-left control, false to disable it\r\n * @param {Boolean} [options.mr] true to enable the middle-right control, false to disable it\r\n * @param {Boolean} [options.mt] true to enable the middle-top control, false to disable it\r\n * @param {Boolean} [options.tl] true to enable the top-left control, false to disable it\r\n * @param {Boolean} [options.tr] true to enable the top-right control, false to disable it\r\n * @param {Boolean} [options.mtr] true to enable the middle-top-rotate control, false to disable it\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n setControlsVisibility: function(options) {\r\n options || (options = { });\r\n\r\n for (var p in options) {\r\n this.setControlVisible(p, options[p]);\r\n }\r\n return this;\r\n },\r\n\r\n\r\n /**\r\n * This callback function is called every time _discardActiveObject or _setActiveObject\r\n * try to to deselect this object. If the function returns true, the process is cancelled\r\n * @param {Object} [options] options sent from the upper functions\r\n * @param {Event} [options.e] event if the process is generated by an event\r\n */\r\n onDeselect: function() {\r\n // implemented by sub-classes, as needed.\r\n },\r\n\r\n\r\n /**\r\n * This callback function is called every time _discardActiveObject or _setActiveObject\r\n * try to to select this object. If the function returns true, the process is cancelled\r\n * @param {Object} [options] options sent from the upper functions\r\n * @param {Event} [options.e] event if the process is generated by an event\r\n */\r\n onSelect: function() {\r\n // implemented by sub-classes, as needed.\r\n }\r\n });\r\n})();\r\n\r\n\r\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\r\n\r\n /**\r\n * Animation duration (in ms) for fx* methods\r\n * @type Number\r\n * @default\r\n */\r\n FX_DURATION: 500,\r\n\r\n /**\r\n * Centers object horizontally with animation.\r\n * @param {fabric.Object} object Object to center\r\n * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\r\n * @param {Function} [callbacks.onComplete] Invoked on completion\r\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\r\n * @return {fabric.AnimationContext} context\r\n */\r\n fxCenterObjectH: function (object, callbacks) {\r\n callbacks = callbacks || { };\r\n\r\n var empty = function() { },\r\n onComplete = callbacks.onComplete || empty,\r\n onChange = callbacks.onChange || empty,\r\n _this = this;\r\n\r\n return fabric.util.animate({\r\n target: this,\r\n startValue: object.left,\r\n endValue: this.getCenterPoint().x,\r\n duration: this.FX_DURATION,\r\n onChange: function(value) {\r\n object.set('left', value);\r\n _this.requestRenderAll();\r\n onChange();\r\n },\r\n onComplete: function() {\r\n object.setCoords();\r\n onComplete();\r\n }\r\n });\r\n },\r\n\r\n /**\r\n * Centers object vertically with animation.\r\n * @param {fabric.Object} object Object to center\r\n * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\r\n * @param {Function} [callbacks.onComplete] Invoked on completion\r\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\r\n * @return {fabric.AnimationContext} context\r\n */\r\n fxCenterObjectV: function (object, callbacks) {\r\n callbacks = callbacks || { };\r\n\r\n var empty = function() { },\r\n onComplete = callbacks.onComplete || empty,\r\n onChange = callbacks.onChange || empty,\r\n _this = this;\r\n\r\n return fabric.util.animate({\r\n target: this,\r\n startValue: object.top,\r\n endValue: this.getCenterPoint().y,\r\n duration: this.FX_DURATION,\r\n onChange: function(value) {\r\n object.set('top', value);\r\n _this.requestRenderAll();\r\n onChange();\r\n },\r\n onComplete: function() {\r\n object.setCoords();\r\n onComplete();\r\n }\r\n });\r\n },\r\n\r\n /**\r\n * Same as `fabric.Canvas#remove` but animated\r\n * @param {fabric.Object} object Object to remove\r\n * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\r\n * @param {Function} [callbacks.onComplete] Invoked on completion\r\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\r\n * @return {fabric.AnimationContext} context\r\n */\r\n fxRemove: function (object, callbacks) {\r\n callbacks = callbacks || { };\r\n\r\n var empty = function() { },\r\n onComplete = callbacks.onComplete || empty,\r\n onChange = callbacks.onChange || empty,\r\n _this = this;\r\n\r\n return fabric.util.animate({\r\n target: this,\r\n startValue: object.opacity,\r\n endValue: 0,\r\n duration: this.FX_DURATION,\r\n onChange: function(value) {\r\n object.set('opacity', value);\r\n _this.requestRenderAll();\r\n onChange();\r\n },\r\n onComplete: function () {\r\n _this.remove(object);\r\n onComplete();\r\n }\r\n });\r\n }\r\n});\r\n\r\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\r\n /**\r\n * Animates object's properties\r\n * @param {String|Object} property Property to animate (if string) or properties to animate (if object)\r\n * @param {Number|Object} value Value to animate property to (if string was given first) or options object\r\n * @return {fabric.Object} thisArg\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#animation}\r\n * @return {fabric.AnimationContext | fabric.AnimationContext[]} animation context (or an array if passed multiple properties)\r\n *\r\n * As object — multiple properties\r\n *\r\n * object.animate({ left: ..., top: ... });\r\n * object.animate({ left: ..., top: ... }, { duration: ... });\r\n *\r\n * As string — one property\r\n *\r\n * object.animate('left', ...);\r\n * object.animate('left', { duration: ... });\r\n *\r\n */\r\n animate: function () {\r\n if (arguments[0] && typeof arguments[0] === 'object') {\r\n var propsToAnimate = [], prop, skipCallbacks, out = [];\r\n for (prop in arguments[0]) {\r\n propsToAnimate.push(prop);\r\n }\r\n for (var i = 0, len = propsToAnimate.length; i < len; i++) {\r\n prop = propsToAnimate[i];\r\n skipCallbacks = i !== len - 1;\r\n out.push(this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks));\r\n }\r\n return out;\r\n }\r\n else {\r\n return this._animate.apply(this, arguments);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {String} property Property to animate\r\n * @param {String} to Value to animate to\r\n * @param {Object} [options] Options object\r\n * @param {Boolean} [skipCallbacks] When true, callbacks like onchange and oncomplete are not invoked\r\n */\r\n _animate: function(property, to, options, skipCallbacks) {\r\n var _this = this, propPair;\r\n\r\n to = to.toString();\r\n\r\n if (!options) {\r\n options = { };\r\n }\r\n else {\r\n options = fabric.util.object.clone(options);\r\n }\r\n\r\n if (~property.indexOf('.')) {\r\n propPair = property.split('.');\r\n }\r\n\r\n var propIsColor =\r\n _this.colorProperties.indexOf(property) > -1 ||\r\n (propPair && _this.colorProperties.indexOf(propPair[1]) > -1);\r\n\r\n var currentValue = propPair\r\n ? this.get(propPair[0])[propPair[1]]\r\n : this.get(property);\r\n\r\n if (!('from' in options)) {\r\n options.from = currentValue;\r\n }\r\n\r\n if (!propIsColor) {\r\n if (~to.indexOf('=')) {\r\n to = currentValue + parseFloat(to.replace('=', ''));\r\n }\r\n else {\r\n to = parseFloat(to);\r\n }\r\n }\r\n\r\n var _options = {\r\n target: this,\r\n startValue: options.from,\r\n endValue: to,\r\n byValue: options.by,\r\n easing: options.easing,\r\n duration: options.duration,\r\n abort: options.abort && function(value, valueProgress, timeProgress) {\r\n return options.abort.call(_this, value, valueProgress, timeProgress);\r\n },\r\n onChange: function (value, valueProgress, timeProgress) {\r\n if (propPair) {\r\n _this[propPair[0]][propPair[1]] = value;\r\n }\r\n else {\r\n _this.set(property, value);\r\n }\r\n if (skipCallbacks) {\r\n return;\r\n }\r\n options.onChange && options.onChange(value, valueProgress, timeProgress);\r\n },\r\n onComplete: function (value, valueProgress, timeProgress) {\r\n if (skipCallbacks) {\r\n return;\r\n }\r\n\r\n _this.setCoords();\r\n options.onComplete && options.onComplete(value, valueProgress, timeProgress);\r\n }\r\n };\r\n\r\n if (propIsColor) {\r\n return fabric.util.animateColor(_options.startValue, _options.endValue, _options.duration, _options);\r\n }\r\n else {\r\n return fabric.util.animate(_options);\r\n }\r\n }\r\n});\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n extend = fabric.util.object.extend,\r\n clone = fabric.util.object.clone,\r\n coordProps = { x1: 1, x2: 1, y1: 1, y2: 1 };\r\n\r\n if (fabric.Line) {\r\n fabric.warn('fabric.Line is already defined');\r\n return;\r\n }\r\n\r\n /**\r\n * Line class\r\n * @class fabric.Line\r\n * @extends fabric.Object\r\n * @see {@link fabric.Line#initialize} for constructor definition\r\n */\r\n fabric.Line = fabric.util.createClass(fabric.Object, /** @lends fabric.Line.prototype */ {\r\n\r\n /**\r\n * Type of an object\r\n * @type String\r\n * @default\r\n */\r\n type: 'line',\r\n\r\n /**\r\n * x value or first line edge\r\n * @type Number\r\n * @default\r\n */\r\n x1: 0,\r\n\r\n /**\r\n * y value or first line edge\r\n * @type Number\r\n * @default\r\n */\r\n y1: 0,\r\n\r\n /**\r\n * x value or second line edge\r\n * @type Number\r\n * @default\r\n */\r\n x2: 0,\r\n\r\n /**\r\n * y value or second line edge\r\n * @type Number\r\n * @default\r\n */\r\n y2: 0,\r\n\r\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('x1', 'x2', 'y1', 'y2'),\r\n\r\n /**\r\n * Constructor\r\n * @param {Array} [points] Array of points\r\n * @param {Object} [options] Options object\r\n * @return {fabric.Line} thisArg\r\n */\r\n initialize: function(points, options) {\r\n if (!points) {\r\n points = [0, 0, 0, 0];\r\n }\r\n\r\n this.callSuper('initialize', options);\r\n\r\n this.set('x1', points[0]);\r\n this.set('y1', points[1]);\r\n this.set('x2', points[2]);\r\n this.set('y2', points[3]);\r\n\r\n this._setWidthHeight(options);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Object} [options] Options\r\n */\r\n _setWidthHeight: function(options) {\r\n options || (options = { });\r\n\r\n this.width = Math.abs(this.x2 - this.x1);\r\n this.height = Math.abs(this.y2 - this.y1);\r\n\r\n this.left = 'left' in options\r\n ? options.left\r\n : this._getLeftToOriginX();\r\n\r\n this.top = 'top' in options\r\n ? options.top\r\n : this._getTopToOriginY();\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {String} key\r\n * @param {*} value\r\n */\r\n _set: function(key, value) {\r\n this.callSuper('_set', key, value);\r\n if (typeof coordProps[key] !== 'undefined') {\r\n this._setWidthHeight();\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * @private\r\n * @return {Number} leftToOriginX Distance from left edge of canvas to originX of Line.\r\n */\r\n _getLeftToOriginX: makeEdgeToOriginGetter(\r\n { // property names\r\n origin: 'originX',\r\n axis1: 'x1',\r\n axis2: 'x2',\r\n dimension: 'width'\r\n },\r\n { // possible values of origin\r\n nearest: 'left',\r\n center: 'center',\r\n farthest: 'right'\r\n }\r\n ),\r\n\r\n /**\r\n * @private\r\n * @return {Number} topToOriginY Distance from top edge of canvas to originY of Line.\r\n */\r\n _getTopToOriginY: makeEdgeToOriginGetter(\r\n { // property names\r\n origin: 'originY',\r\n axis1: 'y1',\r\n axis2: 'y2',\r\n dimension: 'height'\r\n },\r\n { // possible values of origin\r\n nearest: 'top',\r\n center: 'center',\r\n farthest: 'bottom'\r\n }\r\n ),\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _render: function(ctx) {\r\n ctx.beginPath();\r\n\r\n\r\n var p = this.calcLinePoints();\r\n ctx.moveTo(p.x1, p.y1);\r\n ctx.lineTo(p.x2, p.y2);\r\n\r\n ctx.lineWidth = this.strokeWidth;\r\n\r\n // TODO: test this\r\n // make sure setting \"fill\" changes color of a line\r\n // (by copying fillStyle to strokeStyle, since line is stroked, not filled)\r\n var origStrokeStyle = ctx.strokeStyle;\r\n ctx.strokeStyle = this.stroke || ctx.fillStyle;\r\n this.stroke && this._renderStroke(ctx);\r\n ctx.strokeStyle = origStrokeStyle;\r\n },\r\n\r\n /**\r\n * This function is an helper for svg import. it returns the center of the object in the svg\r\n * untransformed coordinates\r\n * @private\r\n * @return {Object} center point from element coordinates\r\n */\r\n _findCenterFromElement: function() {\r\n return {\r\n x: (this.x1 + this.x2) / 2,\r\n y: (this.y1 + this.y2) / 2,\r\n };\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @method toObject\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} object representation of an instance\r\n */\r\n toObject: function(propertiesToInclude) {\r\n return extend(this.callSuper('toObject', propertiesToInclude), this.calcLinePoints());\r\n },\r\n\r\n /*\r\n * Calculate object dimensions from its properties\r\n * @private\r\n */\r\n _getNonTransformedDimensions: function() {\r\n var dim = this.callSuper('_getNonTransformedDimensions');\r\n if (this.strokeLineCap === 'butt') {\r\n if (this.width === 0) {\r\n dim.y -= this.strokeWidth;\r\n }\r\n if (this.height === 0) {\r\n dim.x -= this.strokeWidth;\r\n }\r\n }\r\n return dim;\r\n },\r\n\r\n /**\r\n * Recalculates line points given width and height\r\n * @private\r\n */\r\n calcLinePoints: function() {\r\n var xMult = this.x1 <= this.x2 ? -1 : 1,\r\n yMult = this.y1 <= this.y2 ? -1 : 1,\r\n x1 = (xMult * this.width * 0.5),\r\n y1 = (yMult * this.height * 0.5),\r\n x2 = (xMult * this.width * -0.5),\r\n y2 = (yMult * this.height * -0.5);\r\n\r\n return {\r\n x1: x1,\r\n x2: x2,\r\n y1: y1,\r\n y2: y2\r\n };\r\n },\r\n\r\n /* _TO_SVG_START_ */\r\n /**\r\n * Returns svg representation of an instance\r\n * @return {Array} an array of strings with the specific svg representation\r\n * of the instance\r\n */\r\n _toSVG: function() {\r\n var p = this.calcLinePoints();\r\n return [\r\n '\\n'\r\n ];\r\n },\r\n /* _TO_SVG_END_ */\r\n });\r\n\r\n /* _FROM_SVG_START_ */\r\n /**\r\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement})\r\n * @static\r\n * @memberOf fabric.Line\r\n * @see http://www.w3.org/TR/SVG/shapes.html#LineElement\r\n */\r\n fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' '));\r\n\r\n /**\r\n * Returns fabric.Line instance from an SVG element\r\n * @static\r\n * @memberOf fabric.Line\r\n * @param {SVGElement} element Element to parse\r\n * @param {Object} [options] Options object\r\n * @param {Function} [callback] callback function invoked after parsing\r\n */\r\n fabric.Line.fromElement = function(element, callback, options) {\r\n options = options || { };\r\n var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES),\r\n points = [\r\n parsedAttributes.x1 || 0,\r\n parsedAttributes.y1 || 0,\r\n parsedAttributes.x2 || 0,\r\n parsedAttributes.y2 || 0\r\n ];\r\n callback(new fabric.Line(points, extend(parsedAttributes, options)));\r\n };\r\n /* _FROM_SVG_END_ */\r\n\r\n /**\r\n * Returns fabric.Line instance from an object representation\r\n * @static\r\n * @memberOf fabric.Line\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} [callback] invoked with new instance as first argument\r\n */\r\n fabric.Line.fromObject = function(object, callback) {\r\n function _callback(instance) {\r\n delete instance.points;\r\n callback && callback(instance);\r\n };\r\n var options = clone(object, true);\r\n options.points = [object.x1, object.y1, object.x2, object.y2];\r\n fabric.Object._fromObject('Line', options, _callback, 'points');\r\n };\r\n\r\n /**\r\n * Produces a function that calculates distance from canvas edge to Line origin.\r\n */\r\n function makeEdgeToOriginGetter(propertyNames, originValues) {\r\n var origin = propertyNames.origin,\r\n axis1 = propertyNames.axis1,\r\n axis2 = propertyNames.axis2,\r\n dimension = propertyNames.dimension,\r\n nearest = originValues.nearest,\r\n center = originValues.center,\r\n farthest = originValues.farthest;\r\n\r\n return function() {\r\n switch (this.get(origin)) {\r\n case nearest:\r\n return Math.min(this.get(axis1), this.get(axis2));\r\n case center:\r\n return Math.min(this.get(axis1), this.get(axis2)) + (0.5 * this.get(dimension));\r\n case farthest:\r\n return Math.max(this.get(axis1), this.get(axis2));\r\n }\r\n };\r\n\r\n }\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n degreesToRadians = fabric.util.degreesToRadians;\r\n\r\n if (fabric.Circle) {\r\n fabric.warn('fabric.Circle is already defined.');\r\n return;\r\n }\r\n\r\n /**\r\n * Circle class\r\n * @class fabric.Circle\r\n * @extends fabric.Object\r\n * @see {@link fabric.Circle#initialize} for constructor definition\r\n */\r\n fabric.Circle = fabric.util.createClass(fabric.Object, /** @lends fabric.Circle.prototype */ {\r\n\r\n /**\r\n * Type of an object\r\n * @type String\r\n * @default\r\n */\r\n type: 'circle',\r\n\r\n /**\r\n * Radius of this circle\r\n * @type Number\r\n * @default\r\n */\r\n radius: 0,\r\n\r\n /**\r\n * degrees of start of the circle.\r\n * probably will change to degrees in next major version\r\n * @type Number 0 - 359\r\n * @default 0\r\n */\r\n startAngle: 0,\r\n\r\n /**\r\n * End angle of the circle\r\n * probably will change to degrees in next major version\r\n * @type Number 1 - 360\r\n * @default 360\r\n */\r\n endAngle: 360,\r\n\r\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('radius', 'startAngle', 'endAngle'),\r\n\r\n /**\r\n * @private\r\n * @param {String} key\r\n * @param {*} value\r\n * @return {fabric.Circle} thisArg\r\n */\r\n _set: function(key, value) {\r\n this.callSuper('_set', key, value);\r\n\r\n if (key === 'radius') {\r\n this.setRadius(value);\r\n }\r\n\r\n return this;\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} object representation of an instance\r\n */\r\n toObject: function(propertiesToInclude) {\r\n return this.callSuper('toObject', ['radius', 'startAngle', 'endAngle'].concat(propertiesToInclude));\r\n },\r\n\r\n /* _TO_SVG_START_ */\r\n\r\n /**\r\n * Returns svg representation of an instance\r\n * @return {Array} an array of strings with the specific svg representation\r\n * of the instance\r\n */\r\n _toSVG: function() {\r\n var svgString, x = 0, y = 0,\r\n angle = (this.endAngle - this.startAngle) % 360;\r\n\r\n if (angle === 0) {\r\n svgString = [\r\n '\\n'\r\n ];\r\n }\r\n else {\r\n var start = degreesToRadians(this.startAngle),\r\n end = degreesToRadians(this.endAngle),\r\n radius = this.radius,\r\n startX = fabric.util.cos(start) * radius,\r\n startY = fabric.util.sin(start) * radius,\r\n endX = fabric.util.cos(end) * radius,\r\n endY = fabric.util.sin(end) * radius,\r\n largeFlag = angle > 180 ? '1' : '0';\r\n svgString = [\r\n '\\n'\r\n ];\r\n }\r\n return svgString;\r\n },\r\n /* _TO_SVG_END_ */\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx context to render on\r\n */\r\n _render: function(ctx) {\r\n ctx.beginPath();\r\n ctx.arc(\r\n 0,\r\n 0,\r\n this.radius,\r\n degreesToRadians(this.startAngle),\r\n degreesToRadians(this.endAngle),\r\n false\r\n );\r\n this._renderPaintInOrder(ctx);\r\n },\r\n\r\n /**\r\n * Returns horizontal radius of an object (according to how an object is scaled)\r\n * @return {Number}\r\n */\r\n getRadiusX: function() {\r\n return this.get('radius') * this.get('scaleX');\r\n },\r\n\r\n /**\r\n * Returns vertical radius of an object (according to how an object is scaled)\r\n * @return {Number}\r\n */\r\n getRadiusY: function() {\r\n return this.get('radius') * this.get('scaleY');\r\n },\r\n\r\n /**\r\n * Sets radius of an object (and updates width accordingly)\r\n * @return {fabric.Circle} thisArg\r\n */\r\n setRadius: function(value) {\r\n this.radius = value;\r\n return this.set('width', value * 2).set('height', value * 2);\r\n },\r\n });\r\n\r\n /* _FROM_SVG_START_ */\r\n /**\r\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Circle.fromElement})\r\n * @static\r\n * @memberOf fabric.Circle\r\n * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement\r\n */\r\n fabric.Circle.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy r'.split(' '));\r\n\r\n /**\r\n * Returns {@link fabric.Circle} instance from an SVG element\r\n * @static\r\n * @memberOf fabric.Circle\r\n * @param {SVGElement} element Element to parse\r\n * @param {Function} [callback] Options callback invoked after parsing is finished\r\n * @param {Object} [options] Options object\r\n * @throws {Error} If value of `r` attribute is missing or invalid\r\n */\r\n fabric.Circle.fromElement = function(element, callback) {\r\n var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES);\r\n\r\n if (!isValidRadius(parsedAttributes)) {\r\n throw new Error('value of `r` attribute is required and can not be negative');\r\n }\r\n\r\n parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.radius;\r\n parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.radius;\r\n callback(new fabric.Circle(parsedAttributes));\r\n };\r\n\r\n /**\r\n * @private\r\n */\r\n function isValidRadius(attributes) {\r\n return (('radius' in attributes) && (attributes.radius >= 0));\r\n }\r\n /* _FROM_SVG_END_ */\r\n\r\n /**\r\n * Returns {@link fabric.Circle} instance from an object representation\r\n * @static\r\n * @memberOf fabric.Circle\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} [callback] invoked with new instance as first argument\r\n * @return {void}\r\n */\r\n fabric.Circle.fromObject = function(object, callback) {\r\n fabric.Object._fromObject('Circle', object, callback);\r\n };\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { });\r\n\r\n if (fabric.Triangle) {\r\n fabric.warn('fabric.Triangle is already defined');\r\n return;\r\n }\r\n\r\n /**\r\n * Triangle class\r\n * @class fabric.Triangle\r\n * @extends fabric.Object\r\n * @return {fabric.Triangle} thisArg\r\n * @see {@link fabric.Triangle#initialize} for constructor definition\r\n */\r\n fabric.Triangle = fabric.util.createClass(fabric.Object, /** @lends fabric.Triangle.prototype */ {\r\n\r\n /**\r\n * Type of an object\r\n * @type String\r\n * @default\r\n */\r\n type: 'triangle',\r\n\r\n /**\r\n * Width is set to 100 to compensate the old initialize code that was setting it to 100\r\n * @type Number\r\n * @default\r\n */\r\n width: 100,\r\n\r\n /**\r\n * Height is set to 100 to compensate the old initialize code that was setting it to 100\r\n * @type Number\r\n * @default\r\n */\r\n height: 100,\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _render: function(ctx) {\r\n var widthBy2 = this.width / 2,\r\n heightBy2 = this.height / 2;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(-widthBy2, heightBy2);\r\n ctx.lineTo(0, -heightBy2);\r\n ctx.lineTo(widthBy2, heightBy2);\r\n ctx.closePath();\r\n\r\n this._renderPaintInOrder(ctx);\r\n },\r\n\r\n /* _TO_SVG_START_ */\r\n /**\r\n * Returns svg representation of an instance\r\n * @return {Array} an array of strings with the specific svg representation\r\n * of the instance\r\n */\r\n _toSVG: function() {\r\n var widthBy2 = this.width / 2,\r\n heightBy2 = this.height / 2,\r\n points = [\r\n -widthBy2 + ' ' + heightBy2,\r\n '0 ' + -heightBy2,\r\n widthBy2 + ' ' + heightBy2\r\n ].join(',');\r\n return [\r\n ''\r\n ];\r\n },\r\n /* _TO_SVG_END_ */\r\n });\r\n\r\n /**\r\n * Returns {@link fabric.Triangle} instance from an object representation\r\n * @static\r\n * @memberOf fabric.Triangle\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} [callback] invoked with new instance as first argument\r\n */\r\n fabric.Triangle.fromObject = function(object, callback) {\r\n return fabric.Object._fromObject('Triangle', object, callback);\r\n };\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n piBy2 = Math.PI * 2;\r\n\r\n if (fabric.Ellipse) {\r\n fabric.warn('fabric.Ellipse is already defined.');\r\n return;\r\n }\r\n\r\n /**\r\n * Ellipse class\r\n * @class fabric.Ellipse\r\n * @extends fabric.Object\r\n * @return {fabric.Ellipse} thisArg\r\n * @see {@link fabric.Ellipse#initialize} for constructor definition\r\n */\r\n fabric.Ellipse = fabric.util.createClass(fabric.Object, /** @lends fabric.Ellipse.prototype */ {\r\n\r\n /**\r\n * Type of an object\r\n * @type String\r\n * @default\r\n */\r\n type: 'ellipse',\r\n\r\n /**\r\n * Horizontal radius\r\n * @type Number\r\n * @default\r\n */\r\n rx: 0,\r\n\r\n /**\r\n * Vertical radius\r\n * @type Number\r\n * @default\r\n */\r\n ry: 0,\r\n\r\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('rx', 'ry'),\r\n\r\n /**\r\n * Constructor\r\n * @param {Object} [options] Options object\r\n * @return {fabric.Ellipse} thisArg\r\n */\r\n initialize: function(options) {\r\n this.callSuper('initialize', options);\r\n this.set('rx', options && options.rx || 0);\r\n this.set('ry', options && options.ry || 0);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {String} key\r\n * @param {*} value\r\n * @return {fabric.Ellipse} thisArg\r\n */\r\n _set: function(key, value) {\r\n this.callSuper('_set', key, value);\r\n switch (key) {\r\n\r\n case 'rx':\r\n this.rx = value;\r\n this.set('width', value * 2);\r\n break;\r\n\r\n case 'ry':\r\n this.ry = value;\r\n this.set('height', value * 2);\r\n break;\r\n\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Returns horizontal radius of an object (according to how an object is scaled)\r\n * @return {Number}\r\n */\r\n getRx: function() {\r\n return this.get('rx') * this.get('scaleX');\r\n },\r\n\r\n /**\r\n * Returns Vertical radius of an object (according to how an object is scaled)\r\n * @return {Number}\r\n */\r\n getRy: function() {\r\n return this.get('ry') * this.get('scaleY');\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} object representation of an instance\r\n */\r\n toObject: function(propertiesToInclude) {\r\n return this.callSuper('toObject', ['rx', 'ry'].concat(propertiesToInclude));\r\n },\r\n\r\n /* _TO_SVG_START_ */\r\n /**\r\n * Returns svg representation of an instance\r\n * @return {Array} an array of strings with the specific svg representation\r\n * of the instance\r\n */\r\n _toSVG: function() {\r\n return [\r\n '\\n'\r\n ];\r\n },\r\n /* _TO_SVG_END_ */\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx context to render on\r\n */\r\n _render: function(ctx) {\r\n ctx.beginPath();\r\n ctx.save();\r\n ctx.transform(1, 0, 0, this.ry / this.rx, 0, 0);\r\n ctx.arc(\r\n 0,\r\n 0,\r\n this.rx,\r\n 0,\r\n piBy2,\r\n false);\r\n ctx.restore();\r\n this._renderPaintInOrder(ctx);\r\n },\r\n });\r\n\r\n /* _FROM_SVG_START_ */\r\n /**\r\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Ellipse.fromElement})\r\n * @static\r\n * @memberOf fabric.Ellipse\r\n * @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement\r\n */\r\n fabric.Ellipse.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy rx ry'.split(' '));\r\n\r\n /**\r\n * Returns {@link fabric.Ellipse} instance from an SVG element\r\n * @static\r\n * @memberOf fabric.Ellipse\r\n * @param {SVGElement} element Element to parse\r\n * @param {Function} [callback] Options callback invoked after parsing is finished\r\n * @return {fabric.Ellipse}\r\n */\r\n fabric.Ellipse.fromElement = function(element, callback) {\r\n\r\n var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES);\r\n\r\n parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.rx;\r\n parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.ry;\r\n callback(new fabric.Ellipse(parsedAttributes));\r\n };\r\n /* _FROM_SVG_END_ */\r\n\r\n /**\r\n * Returns {@link fabric.Ellipse} instance from an object representation\r\n * @static\r\n * @memberOf fabric.Ellipse\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} [callback] invoked with new instance as first argument\r\n * @return {void}\r\n */\r\n fabric.Ellipse.fromObject = function(object, callback) {\r\n fabric.Object._fromObject('Ellipse', object, callback);\r\n };\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n extend = fabric.util.object.extend;\r\n\r\n if (fabric.Rect) {\r\n fabric.warn('fabric.Rect is already defined');\r\n return;\r\n }\r\n\r\n /**\r\n * Rectangle class\r\n * @class fabric.Rect\r\n * @extends fabric.Object\r\n * @return {fabric.Rect} thisArg\r\n * @see {@link fabric.Rect#initialize} for constructor definition\r\n */\r\n fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ {\r\n\r\n /**\r\n * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})\r\n * as well as for history (undo/redo) purposes\r\n * @type Array\r\n */\r\n stateProperties: fabric.Object.prototype.stateProperties.concat('rx', 'ry'),\r\n\r\n /**\r\n * Type of an object\r\n * @type String\r\n * @default\r\n */\r\n type: 'rect',\r\n\r\n /**\r\n * Horizontal border radius\r\n * @type Number\r\n * @default\r\n */\r\n rx: 0,\r\n\r\n /**\r\n * Vertical border radius\r\n * @type Number\r\n * @default\r\n */\r\n ry: 0,\r\n\r\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('rx', 'ry'),\r\n\r\n /**\r\n * Constructor\r\n * @param {Object} [options] Options object\r\n * @return {Object} thisArg\r\n */\r\n initialize: function(options) {\r\n this.callSuper('initialize', options);\r\n this._initRxRy();\r\n },\r\n\r\n /**\r\n * Initializes rx/ry attributes\r\n * @private\r\n */\r\n _initRxRy: function() {\r\n if (this.rx && !this.ry) {\r\n this.ry = this.rx;\r\n }\r\n else if (this.ry && !this.rx) {\r\n this.rx = this.ry;\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _render: function(ctx) {\r\n\r\n // 1x1 case (used in spray brush) optimization was removed because\r\n // with caching and higher zoom level this makes more damage than help\r\n\r\n var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0,\r\n ry = this.ry ? Math.min(this.ry, this.height / 2) : 0,\r\n w = this.width,\r\n h = this.height,\r\n x = -this.width / 2,\r\n y = -this.height / 2,\r\n isRounded = rx !== 0 || ry !== 0,\r\n /* \"magic number\" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */\r\n k = 1 - 0.5522847498;\r\n ctx.beginPath();\r\n\r\n ctx.moveTo(x + rx, y);\r\n\r\n ctx.lineTo(x + w - rx, y);\r\n isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry);\r\n\r\n ctx.lineTo(x + w, y + h - ry);\r\n isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h);\r\n\r\n ctx.lineTo(x + rx, y + h);\r\n isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry);\r\n\r\n ctx.lineTo(x, y + ry);\r\n isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y);\r\n\r\n ctx.closePath();\r\n\r\n this._renderPaintInOrder(ctx);\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} object representation of an instance\r\n */\r\n toObject: function(propertiesToInclude) {\r\n return this.callSuper('toObject', ['rx', 'ry'].concat(propertiesToInclude));\r\n },\r\n\r\n /* _TO_SVG_START_ */\r\n /**\r\n * Returns svg representation of an instance\r\n * @return {Array} an array of strings with the specific svg representation\r\n * of the instance\r\n */\r\n _toSVG: function() {\r\n var x = -this.width / 2, y = -this.height / 2;\r\n return [\r\n '\\n'\r\n ];\r\n },\r\n /* _TO_SVG_END_ */\r\n });\r\n\r\n /* _FROM_SVG_START_ */\r\n /**\r\n * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`)\r\n * @static\r\n * @memberOf fabric.Rect\r\n * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement\r\n */\r\n fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' '));\r\n\r\n /**\r\n * Returns {@link fabric.Rect} instance from an SVG element\r\n * @static\r\n * @memberOf fabric.Rect\r\n * @param {SVGElement} element Element to parse\r\n * @param {Function} callback callback function invoked after parsing\r\n * @param {Object} [options] Options object\r\n */\r\n fabric.Rect.fromElement = function(element, callback, options) {\r\n if (!element) {\r\n return callback(null);\r\n }\r\n options = options || { };\r\n\r\n var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);\r\n parsedAttributes.left = parsedAttributes.left || 0;\r\n parsedAttributes.top = parsedAttributes.top || 0;\r\n parsedAttributes.height = parsedAttributes.height || 0;\r\n parsedAttributes.width = parsedAttributes.width || 0;\r\n var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));\r\n rect.visible = rect.visible && rect.width > 0 && rect.height > 0;\r\n callback(rect);\r\n };\r\n /* _FROM_SVG_END_ */\r\n\r\n /**\r\n * Returns {@link fabric.Rect} instance from an object representation\r\n * @static\r\n * @memberOf fabric.Rect\r\n * @param {Object} object Object to create an instance from\r\n * @param {Function} [callback] Callback to invoke when an fabric.Rect instance is created\r\n */\r\n fabric.Rect.fromObject = function(object, callback) {\r\n return fabric.Object._fromObject('Rect', object, callback);\r\n };\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n extend = fabric.util.object.extend,\r\n min = fabric.util.array.min,\r\n max = fabric.util.array.max,\r\n toFixed = fabric.util.toFixed,\r\n projectStrokeOnPoints = fabric.util.projectStrokeOnPoints;\r\n\r\n if (fabric.Polyline) {\r\n fabric.warn('fabric.Polyline is already defined');\r\n return;\r\n }\r\n\r\n /**\r\n * Polyline class\r\n * @class fabric.Polyline\r\n * @extends fabric.Object\r\n * @see {@link fabric.Polyline#initialize} for constructor definition\r\n */\r\n fabric.Polyline = fabric.util.createClass(fabric.Object, /** @lends fabric.Polyline.prototype */ {\r\n\r\n /**\r\n * Type of an object\r\n * @type String\r\n * @default\r\n */\r\n type: 'polyline',\r\n\r\n /**\r\n * Points array\r\n * @type Array\r\n * @default\r\n */\r\n points: null,\r\n\r\n /**\r\n * WARNING: Feature in progress\r\n * Calculate the exact bounding box taking in account strokeWidth on acute angles\r\n * this will be turned to true by default on fabric 6.0\r\n * maybe will be left in as an optimization since calculations may be slow\r\n * @deprecated\r\n * @type Boolean\r\n * @default false\r\n */\r\n exactBoundingBox: false,\r\n\r\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('points'),\r\n\r\n /**\r\n * Constructor\r\n * @param {Array} points Array of points (where each point is an object with x and y)\r\n * @param {Object} [options] Options object\r\n * @return {fabric.Polyline} thisArg\r\n * @example\r\n * var poly = new fabric.Polyline([\r\n * { x: 10, y: 10 },\r\n * { x: 50, y: 30 },\r\n * { x: 40, y: 70 },\r\n * { x: 60, y: 50 },\r\n * { x: 100, y: 150 },\r\n * { x: 40, y: 100 }\r\n * ], {\r\n * stroke: 'red',\r\n * left: 100,\r\n * top: 100\r\n * });\r\n */\r\n initialize: function(points, options) {\r\n options = options || {};\r\n this.points = points || [];\r\n this.callSuper('initialize', options);\r\n this._setPositionDimensions(options);\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _projectStrokeOnPoints: function () {\r\n return projectStrokeOnPoints(this.points, this, true);\r\n },\r\n\r\n _setPositionDimensions: function(options) {\r\n var calcDim = this._calcDimensions(options), correctLeftTop,\r\n correctSize = this.exactBoundingBox ? this.strokeWidth : 0;\r\n this.width = calcDim.width - correctSize;\r\n this.height = calcDim.height - correctSize;\r\n if (!options.fromSVG) {\r\n correctLeftTop = this.translateToGivenOrigin(\r\n {\r\n // this looks bad, but is one way to keep it optional for now.\r\n x: calcDim.left - this.strokeWidth / 2 + correctSize / 2,\r\n y: calcDim.top - this.strokeWidth / 2 + correctSize / 2\r\n },\r\n 'left',\r\n 'top',\r\n this.originX,\r\n this.originY\r\n );\r\n }\r\n if (typeof options.left === 'undefined') {\r\n this.left = options.fromSVG ? calcDim.left : correctLeftTop.x;\r\n }\r\n if (typeof options.top === 'undefined') {\r\n this.top = options.fromSVG ? calcDim.top : correctLeftTop.y;\r\n }\r\n this.pathOffset = {\r\n x: calcDim.left + this.width / 2 + correctSize / 2,\r\n y: calcDim.top + this.height / 2 + correctSize / 2\r\n };\r\n },\r\n\r\n /**\r\n * Calculate the polygon min and max point from points array,\r\n * returning an object with left, top, width, height to measure the\r\n * polygon size\r\n * @return {Object} object.left X coordinate of the polygon leftmost point\r\n * @return {Object} object.top Y coordinate of the polygon topmost point\r\n * @return {Object} object.width distance between X coordinates of the polygon leftmost and rightmost point\r\n * @return {Object} object.height distance between Y coordinates of the polygon topmost and bottommost point\r\n * @private\r\n */\r\n _calcDimensions: function() {\r\n\r\n var points = this.exactBoundingBox ? this._projectStrokeOnPoints() : this.points,\r\n minX = min(points, 'x') || 0,\r\n minY = min(points, 'y') || 0,\r\n maxX = max(points, 'x') || 0,\r\n maxY = max(points, 'y') || 0,\r\n width = (maxX - minX),\r\n height = (maxY - minY);\r\n\r\n return {\r\n left: minX,\r\n top: minY,\r\n width: width,\r\n height: height,\r\n };\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} Object representation of an instance\r\n */\r\n toObject: function(propertiesToInclude) {\r\n return extend(this.callSuper('toObject', propertiesToInclude), {\r\n points: this.points.concat()\r\n });\r\n },\r\n\r\n /* _TO_SVG_START_ */\r\n /**\r\n * Returns svg representation of an instance\r\n * @return {Array} an array of strings with the specific svg representation\r\n * of the instance\r\n */\r\n _toSVG: function() {\r\n var points = [], diffX = this.pathOffset.x, diffY = this.pathOffset.y,\r\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\r\n\r\n for (var i = 0, len = this.points.length; i < len; i++) {\r\n points.push(\r\n toFixed(this.points[i].x - diffX, NUM_FRACTION_DIGITS), ',',\r\n toFixed(this.points[i].y - diffY, NUM_FRACTION_DIGITS), ' '\r\n );\r\n }\r\n return [\r\n '<' + this.type + ' ', 'COMMON_PARTS',\r\n 'points=\"', points.join(''),\r\n '\" />\\n'\r\n ];\r\n },\r\n /* _TO_SVG_END_ */\r\n\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n commonRender: function(ctx) {\r\n var point, len = this.points.length,\r\n x = this.pathOffset.x,\r\n y = this.pathOffset.y;\r\n\r\n if (!len || isNaN(this.points[len - 1].y)) {\r\n // do not draw if no points or odd points\r\n // NaN comes from parseFloat of a empty string in parser\r\n return false;\r\n }\r\n ctx.beginPath();\r\n ctx.moveTo(this.points[0].x - x, this.points[0].y - y);\r\n for (var i = 0; i < len; i++) {\r\n point = this.points[i];\r\n ctx.lineTo(point.x - x, point.y - y);\r\n }\r\n return true;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _render: function(ctx) {\r\n if (!this.commonRender(ctx)) {\r\n return;\r\n }\r\n this._renderPaintInOrder(ctx);\r\n },\r\n\r\n /**\r\n * Returns complexity of an instance\r\n * @return {Number} complexity of this instance\r\n */\r\n complexity: function() {\r\n return this.get('points').length;\r\n }\r\n });\r\n\r\n /* _FROM_SVG_START_ */\r\n /**\r\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Polyline.fromElement})\r\n * @static\r\n * @memberOf fabric.Polyline\r\n * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement\r\n */\r\n fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat();\r\n\r\n /**\r\n * Returns fabric.Polyline instance from an SVG element\r\n * @static\r\n * @memberOf fabric.Polyline\r\n * @param {SVGElement} element Element to parser\r\n * @param {Function} callback callback function invoked after parsing\r\n * @param {Object} [options] Options object\r\n */\r\n fabric.Polyline.fromElementGenerator = function(_class) {\r\n return function(element, callback, options) {\r\n if (!element) {\r\n return callback(null);\r\n }\r\n options || (options = { });\r\n\r\n var points = fabric.parsePointsAttribute(element.getAttribute('points')),\r\n parsedAttributes = fabric.parseAttributes(element, fabric[_class].ATTRIBUTE_NAMES);\r\n parsedAttributes.fromSVG = true;\r\n callback(new fabric[_class](points, extend(parsedAttributes, options)));\r\n };\r\n };\r\n\r\n fabric.Polyline.fromElement = fabric.Polyline.fromElementGenerator('Polyline');\r\n\r\n /* _FROM_SVG_END_ */\r\n\r\n /**\r\n * Returns fabric.Polyline instance from an object representation\r\n * @static\r\n * @memberOf fabric.Polyline\r\n * @param {Object} object Object to create an instance from\r\n * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\r\n */\r\n fabric.Polyline.fromObject = function(object, callback) {\r\n return fabric.Object._fromObject('Polyline', object, callback, 'points');\r\n };\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = {}),\r\n projectStrokeOnPoints = fabric.util.projectStrokeOnPoints;\r\n\r\n if (fabric.Polygon) {\r\n fabric.warn('fabric.Polygon is already defined');\r\n return;\r\n }\r\n\r\n /**\r\n * Polygon class\r\n * @class fabric.Polygon\r\n * @extends fabric.Polyline\r\n * @see {@link fabric.Polygon#initialize} for constructor definition\r\n */\r\n fabric.Polygon = fabric.util.createClass(fabric.Polyline, /** @lends fabric.Polygon.prototype */ {\r\n\r\n /**\r\n * Type of an object\r\n * @type String\r\n * @default\r\n */\r\n type: 'polygon',\r\n\r\n /**\r\n * @private\r\n */\r\n _projectStrokeOnPoints: function () {\r\n return projectStrokeOnPoints(this.points, this);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _render: function(ctx) {\r\n if (!this.commonRender(ctx)) {\r\n return;\r\n }\r\n ctx.closePath();\r\n this._renderPaintInOrder(ctx);\r\n },\r\n\r\n });\r\n\r\n /* _FROM_SVG_START_ */\r\n /**\r\n * List of attribute names to account for when parsing SVG element (used by `fabric.Polygon.fromElement`)\r\n * @static\r\n * @memberOf fabric.Polygon\r\n * @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement\r\n */\r\n fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat();\r\n\r\n /**\r\n * Returns {@link fabric.Polygon} instance from an SVG element\r\n * @static\r\n * @memberOf fabric.Polygon\r\n * @param {SVGElement} element Element to parse\r\n * @param {Function} callback callback function invoked after parsing\r\n * @param {Object} [options] Options object\r\n */\r\n fabric.Polygon.fromElement = fabric.Polyline.fromElementGenerator('Polygon');\r\n /* _FROM_SVG_END_ */\r\n\r\n /**\r\n * Returns fabric.Polygon instance from an object representation\r\n * @static\r\n * @memberOf fabric.Polygon\r\n * @param {Object} object Object to create an instance from\r\n * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\r\n * @return {void}\r\n */\r\n fabric.Polygon.fromObject = function(object, callback) {\r\n fabric.Object._fromObject('Polygon', object, callback, 'points');\r\n };\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n min = fabric.util.array.min,\r\n max = fabric.util.array.max,\r\n extend = fabric.util.object.extend,\r\n clone = fabric.util.object.clone,\r\n toFixed = fabric.util.toFixed;\r\n\r\n if (fabric.Path) {\r\n fabric.warn('fabric.Path is already defined');\r\n return;\r\n }\r\n\r\n /**\r\n * Path class\r\n * @class fabric.Path\r\n * @extends fabric.Object\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#path_and_pathgroup}\r\n * @see {@link fabric.Path#initialize} for constructor definition\r\n */\r\n fabric.Path = fabric.util.createClass(fabric.Object, /** @lends fabric.Path.prototype */ {\r\n\r\n /**\r\n * Type of an object\r\n * @type String\r\n * @default\r\n */\r\n type: 'path',\r\n\r\n /**\r\n * Array of path points\r\n * @type Array\r\n * @default\r\n */\r\n path: null,\r\n\r\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('path', 'fillRule'),\r\n\r\n stateProperties: fabric.Object.prototype.stateProperties.concat('path'),\r\n\r\n /**\r\n * Constructor\r\n * @param {Array|String} path Path data (sequence of coordinates and corresponding \"command\" tokens)\r\n * @param {Object} [options] Options object\r\n * @return {fabric.Path} thisArg\r\n */\r\n initialize: function (path, options) {\r\n options = clone(options || {});\r\n delete options.path;\r\n this.callSuper('initialize', options);\r\n this._setPath(path || [], options);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Array|String} path Path data (sequence of coordinates and corresponding \"command\" tokens)\r\n * @param {Object} [options] Options object\r\n */\r\n _setPath: function (path, options) {\r\n this.path = fabric.util.makePathSimpler(\r\n Array.isArray(path) ? path : fabric.util.parsePath(path)\r\n );\r\n\r\n fabric.Polyline.prototype._setPositionDimensions.call(this, options || {});\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx context to render path on\r\n */\r\n _renderPathCommands: function(ctx) {\r\n var current, // current instruction\r\n subpathStartX = 0,\r\n subpathStartY = 0,\r\n x = 0, // current x\r\n y = 0, // current y\r\n controlX = 0, // current control point x\r\n controlY = 0, // current control point y\r\n l = -this.pathOffset.x,\r\n t = -this.pathOffset.y;\r\n\r\n ctx.beginPath();\r\n\r\n for (var i = 0, len = this.path.length; i < len; ++i) {\r\n\r\n current = this.path[i];\r\n\r\n switch (current[0]) { // first letter\r\n\r\n case 'L': // lineto, absolute\r\n x = current[1];\r\n y = current[2];\r\n ctx.lineTo(x + l, y + t);\r\n break;\r\n\r\n case 'M': // moveTo, absolute\r\n x = current[1];\r\n y = current[2];\r\n subpathStartX = x;\r\n subpathStartY = y;\r\n ctx.moveTo(x + l, y + t);\r\n break;\r\n\r\n case 'C': // bezierCurveTo, absolute\r\n x = current[5];\r\n y = current[6];\r\n controlX = current[3];\r\n controlY = current[4];\r\n ctx.bezierCurveTo(\r\n current[1] + l,\r\n current[2] + t,\r\n controlX + l,\r\n controlY + t,\r\n x + l,\r\n y + t\r\n );\r\n break;\r\n\r\n case 'Q': // quadraticCurveTo, absolute\r\n ctx.quadraticCurveTo(\r\n current[1] + l,\r\n current[2] + t,\r\n current[3] + l,\r\n current[4] + t\r\n );\r\n x = current[3];\r\n y = current[4];\r\n controlX = current[1];\r\n controlY = current[2];\r\n break;\r\n\r\n case 'z':\r\n case 'Z':\r\n x = subpathStartX;\r\n y = subpathStartY;\r\n ctx.closePath();\r\n break;\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx context to render path on\r\n */\r\n _render: function(ctx) {\r\n this._renderPathCommands(ctx);\r\n this._renderPaintInOrder(ctx);\r\n },\r\n\r\n /**\r\n * Returns string representation of an instance\r\n * @return {String} string representation of an instance\r\n */\r\n toString: function() {\r\n return '#';\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} object representation of an instance\r\n */\r\n toObject: function(propertiesToInclude) {\r\n return extend(this.callSuper('toObject', propertiesToInclude), {\r\n path: this.path.map(function(item) { return item.slice(); }),\r\n });\r\n },\r\n\r\n /**\r\n * Returns dataless object representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} object representation of an instance\r\n */\r\n toDatalessObject: function(propertiesToInclude) {\r\n var o = this.toObject(['sourcePath'].concat(propertiesToInclude));\r\n if (o.sourcePath) {\r\n delete o.path;\r\n }\r\n return o;\r\n },\r\n\r\n /* _TO_SVG_START_ */\r\n /**\r\n * Returns svg representation of an instance\r\n * @return {Array} an array of strings with the specific svg representation\r\n * of the instance\r\n */\r\n _toSVG: function() {\r\n var path = fabric.util.joinPath(this.path);\r\n return [\r\n '\\n'\r\n ];\r\n },\r\n\r\n _getOffsetTransform: function() {\r\n var digits = fabric.Object.NUM_FRACTION_DIGITS;\r\n return ' translate(' + toFixed(-this.pathOffset.x, digits) + ', ' +\r\n toFixed(-this.pathOffset.y, digits) + ')';\r\n },\r\n\r\n /**\r\n * Returns svg clipPath representation of an instance\r\n * @param {Function} [reviver] Method for further parsing of svg representation.\r\n * @return {String} svg representation of an instance\r\n */\r\n toClipPathSVG: function(reviver) {\r\n var additionalTransform = this._getOffsetTransform();\r\n return '\\t' + this._createBaseClipPathSVGMarkup(\r\n this._toSVG(), { reviver: reviver, additionalTransform: additionalTransform }\r\n );\r\n },\r\n\r\n /**\r\n * Returns svg representation of an instance\r\n * @param {Function} [reviver] Method for further parsing of svg representation.\r\n * @return {String} svg representation of an instance\r\n */\r\n toSVG: function(reviver) {\r\n var additionalTransform = this._getOffsetTransform();\r\n return this._createBaseSVGMarkup(this._toSVG(), { reviver: reviver, additionalTransform: additionalTransform });\r\n },\r\n /* _TO_SVG_END_ */\r\n\r\n /**\r\n * Returns number representation of an instance complexity\r\n * @return {Number} complexity of this instance\r\n */\r\n complexity: function() {\r\n return this.path.length;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _calcDimensions: function() {\r\n\r\n var aX = [],\r\n aY = [],\r\n current, // current instruction\r\n subpathStartX = 0,\r\n subpathStartY = 0,\r\n x = 0, // current x\r\n y = 0, // current y\r\n bounds;\r\n\r\n for (var i = 0, len = this.path.length; i < len; ++i) {\r\n\r\n current = this.path[i];\r\n\r\n switch (current[0]) { // first letter\r\n\r\n case 'L': // lineto, absolute\r\n x = current[1];\r\n y = current[2];\r\n bounds = [];\r\n break;\r\n\r\n case 'M': // moveTo, absolute\r\n x = current[1];\r\n y = current[2];\r\n subpathStartX = x;\r\n subpathStartY = y;\r\n bounds = [];\r\n break;\r\n\r\n case 'C': // bezierCurveTo, absolute\r\n bounds = fabric.util.getBoundsOfCurve(x, y,\r\n current[1],\r\n current[2],\r\n current[3],\r\n current[4],\r\n current[5],\r\n current[6]\r\n );\r\n x = current[5];\r\n y = current[6];\r\n break;\r\n\r\n case 'Q': // quadraticCurveTo, absolute\r\n bounds = fabric.util.getBoundsOfCurve(x, y,\r\n current[1],\r\n current[2],\r\n current[1],\r\n current[2],\r\n current[3],\r\n current[4]\r\n );\r\n x = current[3];\r\n y = current[4];\r\n break;\r\n\r\n case 'z':\r\n case 'Z':\r\n x = subpathStartX;\r\n y = subpathStartY;\r\n break;\r\n }\r\n bounds.forEach(function (point) {\r\n aX.push(point.x);\r\n aY.push(point.y);\r\n });\r\n aX.push(x);\r\n aY.push(y);\r\n }\r\n\r\n var minX = min(aX) || 0,\r\n minY = min(aY) || 0,\r\n maxX = max(aX) || 0,\r\n maxY = max(aY) || 0,\r\n deltaX = maxX - minX,\r\n deltaY = maxY - minY;\r\n\r\n return {\r\n left: minX,\r\n top: minY,\r\n width: deltaX,\r\n height: deltaY\r\n };\r\n }\r\n });\r\n\r\n /**\r\n * Creates an instance of fabric.Path from an object\r\n * @static\r\n * @memberOf fabric.Path\r\n * @param {Object} object\r\n * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\r\n */\r\n fabric.Path.fromObject = function(object, callback) {\r\n if (typeof object.sourcePath === 'string') {\r\n var pathUrl = object.sourcePath;\r\n fabric.loadSVGFromURL(pathUrl, function (elements) {\r\n var path = elements[0];\r\n path.setOptions(object);\r\n if (object.clipPath) {\r\n fabric.util.enlivenObjects([object.clipPath], function(elivenedObjects) {\r\n path.clipPath = elivenedObjects[0];\r\n callback && callback(path);\r\n });\r\n }\r\n else {\r\n callback && callback(path);\r\n }\r\n });\r\n }\r\n else {\r\n fabric.Object._fromObject('Path', object, callback, 'path');\r\n }\r\n };\r\n\r\n /* _FROM_SVG_START_ */\r\n /**\r\n * List of attribute names to account for when parsing SVG element (used by `fabric.Path.fromElement`)\r\n * @static\r\n * @memberOf fabric.Path\r\n * @see http://www.w3.org/TR/SVG/paths.html#PathElement\r\n */\r\n fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(['d']);\r\n\r\n /**\r\n * Creates an instance of fabric.Path from an SVG element\r\n * @static\r\n * @memberOf fabric.Path\r\n * @param {SVGElement} element to parse\r\n * @param {Function} callback Callback to invoke when an fabric.Path instance is created\r\n * @param {Object} [options] Options object\r\n * @param {Function} [callback] Options callback invoked after parsing is finished\r\n */\r\n fabric.Path.fromElement = function(element, callback, options) {\r\n var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES);\r\n parsedAttributes.fromSVG = true;\r\n callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options)));\r\n };\r\n /* _FROM_SVG_END_ */\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n min = fabric.util.array.min,\r\n max = fabric.util.array.max;\r\n\r\n if (fabric.Group) {\r\n return;\r\n }\r\n\r\n /**\r\n * Group class\r\n * @class fabric.Group\r\n * @extends fabric.Object\r\n * @mixes fabric.Collection\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#groups}\r\n * @see {@link fabric.Group#initialize} for constructor definition\r\n */\r\n fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection, /** @lends fabric.Group.prototype */ {\r\n\r\n /**\r\n * Type of an object\r\n * @type String\r\n * @default\r\n */\r\n type: 'group',\r\n\r\n /**\r\n * Width of stroke\r\n * @type Number\r\n * @default\r\n */\r\n strokeWidth: 0,\r\n\r\n /**\r\n * Indicates if click, mouseover, mouseout events & hoverCursor should also check for subtargets\r\n * @type Boolean\r\n * @default\r\n */\r\n subTargetCheck: false,\r\n\r\n /**\r\n * Groups are container, do not render anything on theyr own, ence no cache properties\r\n * @type Array\r\n * @default\r\n */\r\n cacheProperties: [],\r\n\r\n /**\r\n * setOnGroup is a method used for TextBox that is no more used since 2.0.0 The behavior is still\r\n * available setting this boolean to true.\r\n * @type Boolean\r\n * @since 2.0.0\r\n * @default\r\n */\r\n useSetOnGroup: false,\r\n\r\n /**\r\n * Constructor\r\n * @param {Object} objects Group objects\r\n * @param {Object} [options] Options object\r\n * @param {Boolean} [isAlreadyGrouped] if true, objects have been grouped already.\r\n * @return {Object} thisArg\r\n */\r\n initialize: function(objects, options, isAlreadyGrouped) {\r\n options = options || {};\r\n this._objects = [];\r\n // if objects enclosed in a group have been grouped already,\r\n // we cannot change properties of objects.\r\n // Thus we need to set options to group without objects,\r\n isAlreadyGrouped && this.callSuper('initialize', options);\r\n this._objects = objects || [];\r\n for (var i = this._objects.length; i--; ) {\r\n this._objects[i].group = this;\r\n }\r\n\r\n if (!isAlreadyGrouped) {\r\n var center = options && options.centerPoint;\r\n // we want to set origins before calculating the bounding box.\r\n // so that the topleft can be set with that in mind.\r\n // if specific top and left are passed, are overwritten later\r\n // with the callSuper('initialize', options)\r\n if (options.originX !== undefined) {\r\n this.originX = options.originX;\r\n }\r\n if (options.originY !== undefined) {\r\n this.originY = options.originY;\r\n }\r\n // if coming from svg i do not want to calc bounds.\r\n // i assume width and height are passed along options\r\n center || this._calcBounds();\r\n this._updateObjectsCoords(center);\r\n delete options.centerPoint;\r\n this.callSuper('initialize', options);\r\n }\r\n else {\r\n this._updateObjectsACoords();\r\n }\r\n\r\n this.setCoords();\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _updateObjectsACoords: function() {\r\n var skipControls = true;\r\n for (var i = this._objects.length; i--; ){\r\n this._objects[i].setCoords(skipControls);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Boolean} [skipCoordsChange] if true, coordinates of objects enclosed in a group do not change\r\n */\r\n _updateObjectsCoords: function(center) {\r\n var center = center || this.getCenterPoint();\r\n for (var i = this._objects.length; i--; ){\r\n this._updateObjectCoords(this._objects[i], center);\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Object} object\r\n * @param {fabric.Point} center, current center of group.\r\n */\r\n _updateObjectCoords: function(object, center) {\r\n var objectLeft = object.left,\r\n objectTop = object.top,\r\n skipControls = true;\r\n\r\n object.set({\r\n left: objectLeft - center.x,\r\n top: objectTop - center.y\r\n });\r\n object.group = this;\r\n object.setCoords(skipControls);\r\n },\r\n\r\n /**\r\n * Returns string represenation of a group\r\n * @return {String}\r\n */\r\n toString: function() {\r\n return '#';\r\n },\r\n\r\n /**\r\n * Adds an object to a group; Then recalculates group's dimension, position.\r\n * @param {Object} object\r\n * @return {fabric.Group} thisArg\r\n * @chainable\r\n */\r\n addWithUpdate: function(object) {\r\n var nested = !!this.group;\r\n this._restoreObjectsState();\r\n fabric.util.resetObjectTransform(this);\r\n if (object) {\r\n if (nested) {\r\n // if this group is inside another group, we need to pre transform the object\r\n fabric.util.removeTransformFromObject(object, this.group.calcTransformMatrix());\r\n }\r\n this._objects.push(object);\r\n object.group = this;\r\n object._set('canvas', this.canvas);\r\n }\r\n this._calcBounds();\r\n this._updateObjectsCoords();\r\n this.dirty = true;\r\n if (nested) {\r\n this.group.addWithUpdate();\r\n }\r\n else {\r\n this.setCoords();\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Removes an object from a group; Then recalculates group's dimension, position.\r\n * @param {Object} object\r\n * @return {fabric.Group} thisArg\r\n * @chainable\r\n */\r\n removeWithUpdate: function(object) {\r\n this._restoreObjectsState();\r\n fabric.util.resetObjectTransform(this);\r\n\r\n this.remove(object);\r\n this._calcBounds();\r\n this._updateObjectsCoords();\r\n this.setCoords();\r\n this.dirty = true;\r\n return this;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _onObjectAdded: function(object) {\r\n this.dirty = true;\r\n object.group = this;\r\n object._set('canvas', this.canvas);\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _onObjectRemoved: function(object) {\r\n this.dirty = true;\r\n delete object.group;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _set: function(key, value) {\r\n var i = this._objects.length;\r\n if (this.useSetOnGroup) {\r\n while (i--) {\r\n this._objects[i].setOnGroup(key, value);\r\n }\r\n }\r\n if (key === 'canvas') {\r\n while (i--) {\r\n this._objects[i]._set(key, value);\r\n }\r\n }\r\n fabric.Object.prototype._set.call(this, key, value);\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} object representation of an instance\r\n */\r\n toObject: function(propertiesToInclude) {\r\n var _includeDefaultValues = this.includeDefaultValues;\r\n var objsToObject = this._objects\r\n .filter(function (obj) {\r\n return !obj.excludeFromExport;\r\n })\r\n .map(function (obj) {\r\n var originalDefaults = obj.includeDefaultValues;\r\n obj.includeDefaultValues = _includeDefaultValues;\r\n var _obj = obj.toObject(propertiesToInclude);\r\n obj.includeDefaultValues = originalDefaults;\r\n return _obj;\r\n });\r\n var obj = fabric.Object.prototype.toObject.call(this, propertiesToInclude);\r\n obj.objects = objsToObject;\r\n return obj;\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance, in dataless mode.\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} object representation of an instance\r\n */\r\n toDatalessObject: function(propertiesToInclude) {\r\n var objsToObject, sourcePath = this.sourcePath;\r\n if (sourcePath) {\r\n objsToObject = sourcePath;\r\n }\r\n else {\r\n var _includeDefaultValues = this.includeDefaultValues;\r\n objsToObject = this._objects.map(function(obj) {\r\n var originalDefaults = obj.includeDefaultValues;\r\n obj.includeDefaultValues = _includeDefaultValues;\r\n var _obj = obj.toDatalessObject(propertiesToInclude);\r\n obj.includeDefaultValues = originalDefaults;\r\n return _obj;\r\n });\r\n }\r\n var obj = fabric.Object.prototype.toDatalessObject.call(this, propertiesToInclude);\r\n obj.objects = objsToObject;\r\n return obj;\r\n },\r\n\r\n /**\r\n * Renders instance on a given context\r\n * @param {CanvasRenderingContext2D} ctx context to render instance on\r\n */\r\n render: function(ctx) {\r\n this._transformDone = true;\r\n this.callSuper('render', ctx);\r\n this._transformDone = false;\r\n },\r\n\r\n /**\r\n * Decide if the object should cache or not. Create its own cache level\r\n * needsItsOwnCache should be used when the object drawing method requires\r\n * a cache step. None of the fabric classes requires it.\r\n * Generally you do not cache objects in groups because the group is already cached.\r\n * @return {Boolean}\r\n */\r\n shouldCache: function() {\r\n var ownCache = fabric.Object.prototype.shouldCache.call(this);\r\n if (ownCache) {\r\n for (var i = 0, len = this._objects.length; i < len; i++) {\r\n if (this._objects[i].willDrawShadow()) {\r\n this.ownCaching = false;\r\n return false;\r\n }\r\n }\r\n }\r\n return ownCache;\r\n },\r\n\r\n /**\r\n * Check if this object or a child object will cast a shadow\r\n * @return {Boolean}\r\n */\r\n willDrawShadow: function() {\r\n if (fabric.Object.prototype.willDrawShadow.call(this)) {\r\n return true;\r\n }\r\n for (var i = 0, len = this._objects.length; i < len; i++) {\r\n if (this._objects[i].willDrawShadow()) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n },\r\n\r\n /**\r\n * Check if this group or its parent group are caching, recursively up\r\n * @return {Boolean}\r\n */\r\n isOnACache: function() {\r\n return this.ownCaching || (this.group && this.group.isOnACache());\r\n },\r\n\r\n /**\r\n * Execute the drawing operation for an object on a specified context\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n drawObject: function(ctx) {\r\n for (var i = 0, len = this._objects.length; i < len; i++) {\r\n this._objects[i].render(ctx);\r\n }\r\n this._drawClipPath(ctx, this.clipPath);\r\n },\r\n\r\n /**\r\n * Check if cache is dirty\r\n */\r\n isCacheDirty: function(skipCanvas) {\r\n if (this.callSuper('isCacheDirty', skipCanvas)) {\r\n return true;\r\n }\r\n if (!this.statefullCache) {\r\n return false;\r\n }\r\n for (var i = 0, len = this._objects.length; i < len; i++) {\r\n if (this._objects[i].isCacheDirty(true)) {\r\n if (this._cacheCanvas) {\r\n // if this group has not a cache canvas there is nothing to clean\r\n var x = this.cacheWidth / this.zoomX, y = this.cacheHeight / this.zoomY;\r\n this._cacheContext.clearRect(-x / 2, -y / 2, x, y);\r\n }\r\n return true;\r\n }\r\n }\r\n return false;\r\n },\r\n\r\n /**\r\n * Restores original state of each of group objects (original state is that which was before group was created).\r\n * if the nested boolean is true, the original state will be restored just for the\r\n * first group and not for all the group chain\r\n * @private\r\n * @param {Boolean} nested tell the function to restore object state up to the parent group and not more\r\n * @return {fabric.Group} thisArg\r\n * @chainable\r\n */\r\n _restoreObjectsState: function() {\r\n var groupMatrix = this.calcOwnMatrix();\r\n this._objects.forEach(function(object) {\r\n // instead of using _this = this;\r\n fabric.util.addTransformToObject(object, groupMatrix);\r\n delete object.group;\r\n object.setCoords();\r\n });\r\n return this;\r\n },\r\n\r\n /**\r\n * Destroys a group (restoring state of its objects)\r\n * @return {fabric.Group} thisArg\r\n * @chainable\r\n */\r\n destroy: function() {\r\n // when group is destroyed objects needs to get a repaint to be eventually\r\n // displayed on canvas.\r\n this._objects.forEach(function(object) {\r\n object.set('dirty', true);\r\n });\r\n return this._restoreObjectsState();\r\n },\r\n\r\n dispose: function () {\r\n this.callSuper('dispose');\r\n this.forEachObject(function (object) {\r\n object.dispose && object.dispose();\r\n });\r\n this._objects = [];\r\n },\r\n\r\n /**\r\n * make a group an active selection, remove the group from canvas\r\n * the group has to be on canvas for this to work.\r\n * @return {fabric.ActiveSelection} thisArg\r\n * @chainable\r\n */\r\n toActiveSelection: function() {\r\n if (!this.canvas) {\r\n return;\r\n }\r\n var objects = this._objects, canvas = this.canvas;\r\n this._objects = [];\r\n var options = this.toObject();\r\n delete options.objects;\r\n var activeSelection = new fabric.ActiveSelection([]);\r\n activeSelection.set(options);\r\n activeSelection.type = 'activeSelection';\r\n canvas.remove(this);\r\n objects.forEach(function(object) {\r\n object.group = activeSelection;\r\n object.dirty = true;\r\n canvas.add(object);\r\n });\r\n activeSelection.canvas = canvas;\r\n activeSelection._objects = objects;\r\n canvas._activeObject = activeSelection;\r\n activeSelection.setCoords();\r\n return activeSelection;\r\n },\r\n\r\n /**\r\n * Destroys a group (restoring state of its objects)\r\n * @return {fabric.Group} thisArg\r\n * @chainable\r\n */\r\n ungroupOnCanvas: function() {\r\n return this._restoreObjectsState();\r\n },\r\n\r\n /**\r\n * Sets coordinates of all objects inside group\r\n * @return {fabric.Group} thisArg\r\n * @chainable\r\n */\r\n setObjectsCoords: function() {\r\n var skipControls = true;\r\n this.forEachObject(function(object) {\r\n object.setCoords(skipControls);\r\n });\r\n return this;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _calcBounds: function(onlyWidthHeight) {\r\n var aX = [],\r\n aY = [],\r\n o, prop, coords,\r\n props = ['tr', 'br', 'bl', 'tl'],\r\n i = 0, iLen = this._objects.length,\r\n j, jLen = props.length;\r\n\r\n for ( ; i < iLen; ++i) {\r\n o = this._objects[i];\r\n coords = o.calcACoords();\r\n for (j = 0; j < jLen; j++) {\r\n prop = props[j];\r\n aX.push(coords[prop].x);\r\n aY.push(coords[prop].y);\r\n }\r\n o.aCoords = coords;\r\n }\r\n\r\n this._getBounds(aX, aY, onlyWidthHeight);\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _getBounds: function(aX, aY, onlyWidthHeight) {\r\n var minXY = new fabric.Point(min(aX), min(aY)),\r\n maxXY = new fabric.Point(max(aX), max(aY)),\r\n top = minXY.y || 0, left = minXY.x || 0,\r\n width = (maxXY.x - minXY.x) || 0,\r\n height = (maxXY.y - minXY.y) || 0;\r\n this.width = width;\r\n this.height = height;\r\n if (!onlyWidthHeight) {\r\n // the bounding box always finds the topleft most corner.\r\n // whatever is the group origin, we set up here the left/top position.\r\n this.setPositionByOrigin({ x: left, y: top }, 'left', 'top');\r\n }\r\n },\r\n\r\n /* _TO_SVG_START_ */\r\n /**\r\n * Returns svg representation of an instance\r\n * @param {Function} [reviver] Method for further parsing of svg representation.\r\n * @return {String} svg representation of an instance\r\n */\r\n _toSVG: function(reviver) {\r\n var svgString = ['\\n'];\r\n\r\n for (var i = 0, len = this._objects.length; i < len; i++) {\r\n svgString.push('\\t\\t', this._objects[i].toSVG(reviver));\r\n }\r\n svgString.push('\\n');\r\n return svgString;\r\n },\r\n\r\n /**\r\n * Returns styles-string for svg-export, specific version for group\r\n * @return {String}\r\n */\r\n getSvgStyles: function() {\r\n var opacity = typeof this.opacity !== 'undefined' && this.opacity !== 1 ?\r\n 'opacity: ' + this.opacity + ';' : '',\r\n visibility = this.visible ? '' : ' visibility: hidden;';\r\n return [\r\n opacity,\r\n this.getSvgFilter(),\r\n visibility\r\n ].join('');\r\n },\r\n\r\n /**\r\n * Returns svg clipPath representation of an instance\r\n * @param {Function} [reviver] Method for further parsing of svg representation.\r\n * @return {String} svg representation of an instance\r\n */\r\n toClipPathSVG: function(reviver) {\r\n var svgString = [];\r\n\r\n for (var i = 0, len = this._objects.length; i < len; i++) {\r\n svgString.push('\\t', this._objects[i].toClipPathSVG(reviver));\r\n }\r\n\r\n return this._createBaseClipPathSVGMarkup(svgString, { reviver: reviver });\r\n },\r\n /* _TO_SVG_END_ */\r\n });\r\n\r\n /**\r\n * Returns {@link fabric.Group} instance from an object representation\r\n * @static\r\n * @memberOf fabric.Group\r\n * @param {Object} object Object to create a group from\r\n * @param {Function} [callback] Callback to invoke when an group instance is created\r\n */\r\n fabric.Group.fromObject = function(object, callback) {\r\n var objects = object.objects,\r\n options = fabric.util.object.clone(object, true);\r\n delete options.objects;\r\n if (typeof objects === 'string') {\r\n // it has to be an url or something went wrong.\r\n fabric.loadSVGFromURL(objects, function (elements) {\r\n var group = fabric.util.groupSVGElements(elements, object, objects);\r\n var clipPath = options.clipPath;\r\n delete options.clipPath;\r\n group.set(options);\r\n if (clipPath) {\r\n fabric.util.enlivenObjects([clipPath], function(elivenedObjects) {\r\n group.clipPath = elivenedObjects[0];\r\n callback && callback(group);\r\n });\r\n }\r\n else {\r\n callback && callback(group);\r\n }\r\n });\r\n return;\r\n }\r\n fabric.util.enlivenObjects(objects, function (enlivenedObjects) {\r\n fabric.util.enlivenObjectEnlivables(object, options, function () {\r\n callback && callback(new fabric.Group(enlivenedObjects, options, true));\r\n });\r\n });\r\n };\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { });\r\n\r\n if (fabric.ActiveSelection) {\r\n return;\r\n }\r\n\r\n /**\r\n * Group class\r\n * @class fabric.ActiveSelection\r\n * @extends fabric.Group\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#groups}\r\n * @see {@link fabric.ActiveSelection#initialize} for constructor definition\r\n */\r\n fabric.ActiveSelection = fabric.util.createClass(fabric.Group, /** @lends fabric.ActiveSelection.prototype */ {\r\n\r\n /**\r\n * Type of an object\r\n * @type String\r\n * @default\r\n */\r\n type: 'activeSelection',\r\n\r\n /**\r\n * Constructor\r\n * @param {Object} objects ActiveSelection objects\r\n * @param {Object} [options] Options object\r\n * @return {Object} thisArg\r\n */\r\n initialize: function(objects, options) {\r\n options = options || {};\r\n this._objects = objects || [];\r\n for (var i = this._objects.length; i--; ) {\r\n this._objects[i].group = this;\r\n }\r\n\r\n if (options.originX) {\r\n this.originX = options.originX;\r\n }\r\n if (options.originY) {\r\n this.originY = options.originY;\r\n }\r\n this._calcBounds();\r\n this._updateObjectsCoords();\r\n fabric.Object.prototype.initialize.call(this, options);\r\n this.setCoords();\r\n },\r\n\r\n /**\r\n * Change te activeSelection to a normal group,\r\n * High level function that automatically adds it to canvas as\r\n * active object. no events fired.\r\n * @since 2.0.0\r\n * @return {fabric.Group}\r\n */\r\n toGroup: function() {\r\n var objects = this._objects.concat();\r\n this._objects = [];\r\n var options = fabric.Object.prototype.toObject.call(this);\r\n var newGroup = new fabric.Group([]);\r\n delete options.type;\r\n newGroup.set(options);\r\n objects.forEach(function(object) {\r\n object.canvas.remove(object);\r\n object.group = newGroup;\r\n });\r\n newGroup._objects = objects;\r\n if (!this.canvas) {\r\n return newGroup;\r\n }\r\n var canvas = this.canvas;\r\n canvas.add(newGroup);\r\n canvas._activeObject = newGroup;\r\n newGroup.setCoords();\r\n return newGroup;\r\n },\r\n\r\n /**\r\n * If returns true, deselection is cancelled.\r\n * @since 2.0.0\r\n * @return {Boolean} [cancel]\r\n */\r\n onDeselect: function() {\r\n this.destroy();\r\n return false;\r\n },\r\n\r\n /**\r\n * Returns string representation of a group\r\n * @return {String}\r\n */\r\n toString: function() {\r\n return '#';\r\n },\r\n\r\n /**\r\n * Decide if the object should cache or not. Create its own cache level\r\n * objectCaching is a global flag, wins over everything\r\n * needsItsOwnCache should be used when the object drawing method requires\r\n * a cache step. None of the fabric classes requires it.\r\n * Generally you do not cache objects in groups because the group outside is cached.\r\n * @return {Boolean}\r\n */\r\n shouldCache: function() {\r\n return false;\r\n },\r\n\r\n /**\r\n * Check if this group or its parent group are caching, recursively up\r\n * @return {Boolean}\r\n */\r\n isOnACache: function() {\r\n return false;\r\n },\r\n\r\n /**\r\n * Renders controls and borders for the object\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @param {Object} [styleOverride] properties to override the object style\r\n * @param {Object} [childrenOverride] properties to override the children overrides\r\n */\r\n _renderControls: function(ctx, styleOverride, childrenOverride) {\r\n ctx.save();\r\n ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\r\n this.callSuper('_renderControls', ctx, styleOverride);\r\n childrenOverride = childrenOverride || { };\r\n if (typeof childrenOverride.hasControls === 'undefined') {\r\n childrenOverride.hasControls = false;\r\n }\r\n childrenOverride.forActiveSelection = true;\r\n for (var i = 0, len = this._objects.length; i < len; i++) {\r\n this._objects[i]._renderControls(ctx, childrenOverride);\r\n }\r\n ctx.restore();\r\n },\r\n });\r\n\r\n /**\r\n * Returns {@link fabric.ActiveSelection} instance from an object representation\r\n * @static\r\n * @memberOf fabric.ActiveSelection\r\n * @param {Object} object Object to create a group from\r\n * @param {Function} [callback] Callback to invoke when an ActiveSelection instance is created\r\n */\r\n fabric.ActiveSelection.fromObject = function(object, callback) {\r\n fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) {\r\n delete object.objects;\r\n callback && callback(new fabric.ActiveSelection(enlivenedObjects, object, true));\r\n });\r\n };\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var extend = fabric.util.object.extend;\r\n\r\n if (!global.fabric) {\r\n global.fabric = { };\r\n }\r\n\r\n if (global.fabric.Image) {\r\n fabric.warn('fabric.Image is already defined.');\r\n return;\r\n }\r\n\r\n /**\r\n * Image class\r\n * @class fabric.Image\r\n * @extends fabric.Object\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#images}\r\n * @see {@link fabric.Image#initialize} for constructor definition\r\n */\r\n fabric.Image = fabric.util.createClass(fabric.Object, /** @lends fabric.Image.prototype */ {\r\n\r\n /**\r\n * Type of an object\r\n * @type String\r\n * @default\r\n */\r\n type: 'image',\r\n\r\n /**\r\n * Width of a stroke.\r\n * For image quality a stroke multiple of 2 gives better results.\r\n * @type Number\r\n * @default\r\n */\r\n strokeWidth: 0,\r\n\r\n /**\r\n * When calling {@link fabric.Image.getSrc}, return value from element src with `element.getAttribute('src')`.\r\n * This allows for relative urls as image src.\r\n * @since 2.7.0\r\n * @type Boolean\r\n * @default\r\n */\r\n srcFromAttribute: false,\r\n\r\n /**\r\n * private\r\n * contains last value of scaleX to detect\r\n * if the Image got resized after the last Render\r\n * @type Number\r\n */\r\n _lastScaleX: 1,\r\n\r\n /**\r\n * private\r\n * contains last value of scaleY to detect\r\n * if the Image got resized after the last Render\r\n * @type Number\r\n */\r\n _lastScaleY: 1,\r\n\r\n /**\r\n * private\r\n * contains last value of scaling applied by the apply filter chain\r\n * @type Number\r\n */\r\n _filterScalingX: 1,\r\n\r\n /**\r\n * private\r\n * contains last value of scaling applied by the apply filter chain\r\n * @type Number\r\n */\r\n _filterScalingY: 1,\r\n\r\n /**\r\n * minimum scale factor under which any resizeFilter is triggered to resize the image\r\n * 0 will disable the automatic resize. 1 will trigger automatically always.\r\n * number bigger than 1 are not implemented yet.\r\n * @type Number\r\n */\r\n minimumScaleTrigger: 0.5,\r\n\r\n /**\r\n * List of properties to consider when checking if\r\n * state of an object is changed ({@link fabric.Object#hasStateChanged})\r\n * as well as for history (undo/redo) purposes\r\n * @type Array\r\n */\r\n stateProperties: fabric.Object.prototype.stateProperties.concat('cropX', 'cropY'),\r\n\r\n /**\r\n * List of properties to consider when checking if cache needs refresh\r\n * Those properties are checked by statefullCache ON ( or lazy mode if we want ) or from single\r\n * calls to Object.set(key, value). If the key is in this list, the object is marked as dirty\r\n * and refreshed at the next render\r\n * @type Array\r\n */\r\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('cropX', 'cropY'),\r\n\r\n /**\r\n * key used to retrieve the texture representing this image\r\n * @since 2.0.0\r\n * @type String\r\n * @default\r\n */\r\n cacheKey: '',\r\n\r\n /**\r\n * Image crop in pixels from original image size.\r\n * @since 2.0.0\r\n * @type Number\r\n * @default\r\n */\r\n cropX: 0,\r\n\r\n /**\r\n * Image crop in pixels from original image size.\r\n * @since 2.0.0\r\n * @type Number\r\n * @default\r\n */\r\n cropY: 0,\r\n\r\n /**\r\n * Indicates whether this canvas will use image smoothing when painting this image.\r\n * Also influence if the cacheCanvas for this image uses imageSmoothing\r\n * @since 4.0.0-beta.11\r\n * @type Boolean\r\n * @default\r\n */\r\n imageSmoothing: true,\r\n\r\n /**\r\n * Constructor\r\n * Image can be initialized with any canvas drawable or a string.\r\n * The string should be a url and will be loaded as an image.\r\n * Canvas and Image element work out of the box, while videos require extra code to work.\r\n * Please check video element events for seeking.\r\n * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | String} element Image element\r\n * @param {Object} [options] Options object\r\n * @param {function} [callback] callback function to call after eventual filters applied.\r\n * @return {fabric.Image} thisArg\r\n */\r\n initialize: function(element, options) {\r\n options || (options = { });\r\n this.filters = [];\r\n this.cacheKey = 'texture' + fabric.Object.__uid++;\r\n this.callSuper('initialize', options);\r\n this._initElement(element, options);\r\n },\r\n\r\n /**\r\n * Returns image element which this instance if based on\r\n * @return {HTMLImageElement} Image element\r\n */\r\n getElement: function() {\r\n return this._element || {};\r\n },\r\n\r\n /**\r\n * Sets image element for this instance to a specified one.\r\n * If filters defined they are applied to new image.\r\n * You might need to call `canvas.renderAll` and `object.setCoords` after replacing, to render new image and update controls area.\r\n * @param {HTMLImageElement} element\r\n * @param {Object} [options] Options object\r\n * @return {fabric.Image} thisArg\r\n * @chainable\r\n */\r\n setElement: function(element, options) {\r\n this.removeTexture(this.cacheKey);\r\n this.removeTexture(this.cacheKey + '_filtered');\r\n this._element = element;\r\n this._originalElement = element;\r\n this._initConfig(options);\r\n if (this.filters.length !== 0) {\r\n this.applyFilters();\r\n }\r\n // resizeFilters work on the already filtered copy.\r\n // we need to apply resizeFilters AFTER normal filters.\r\n // applyResizeFilters is run more often than normal filters\r\n // and is triggered by user interactions rather than dev code\r\n if (this.resizeFilter) {\r\n this.applyResizeFilters();\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Delete a single texture if in webgl mode\r\n */\r\n removeTexture: function(key) {\r\n var backend = fabric.filterBackend;\r\n if (backend && backend.evictCachesForKey) {\r\n backend.evictCachesForKey(key);\r\n }\r\n },\r\n\r\n /**\r\n * Delete textures, reference to elements and eventually JSDOM cleanup\r\n */\r\n dispose: function () {\r\n this.callSuper('dispose');\r\n this.removeTexture(this.cacheKey);\r\n this.removeTexture(this.cacheKey + '_filtered');\r\n this._cacheContext = undefined;\r\n ['_originalElement', '_element', '_filteredEl', '_cacheCanvas'].forEach((function(element) {\r\n fabric.util.cleanUpJsdomNode(this[element]);\r\n this[element] = undefined;\r\n }).bind(this));\r\n },\r\n\r\n /**\r\n * Get the crossOrigin value (of the corresponding image element)\r\n */\r\n getCrossOrigin: function() {\r\n return this._originalElement && (this._originalElement.crossOrigin || null);\r\n },\r\n\r\n /**\r\n * Returns original size of an image\r\n * @return {Object} Object with \"width\" and \"height\" properties\r\n */\r\n getOriginalSize: function() {\r\n var element = this.getElement();\r\n return {\r\n width: element.naturalWidth || element.width,\r\n height: element.naturalHeight || element.height\r\n };\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _stroke: function(ctx) {\r\n if (!this.stroke || this.strokeWidth === 0) {\r\n return;\r\n }\r\n var w = this.width / 2, h = this.height / 2;\r\n ctx.beginPath();\r\n ctx.moveTo(-w, -h);\r\n ctx.lineTo(w, -h);\r\n ctx.lineTo(w, h);\r\n ctx.lineTo(-w, h);\r\n ctx.lineTo(-w, -h);\r\n ctx.closePath();\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} Object representation of an instance\r\n */\r\n toObject: function(propertiesToInclude) {\r\n var filters = [];\r\n\r\n this.filters.forEach(function(filterObj) {\r\n if (filterObj) {\r\n filters.push(filterObj.toObject());\r\n }\r\n });\r\n var object = extend(\r\n this.callSuper(\r\n 'toObject',\r\n ['cropX', 'cropY'].concat(propertiesToInclude)\r\n ), {\r\n src: this.getSrc(),\r\n crossOrigin: this.getCrossOrigin(),\r\n filters: filters,\r\n });\r\n if (this.resizeFilter) {\r\n object.resizeFilter = this.resizeFilter.toObject();\r\n }\r\n return object;\r\n },\r\n\r\n /**\r\n * Returns true if an image has crop applied, inspecting values of cropX,cropY,width,height.\r\n * @return {Boolean}\r\n */\r\n hasCrop: function() {\r\n return this.cropX || this.cropY || this.width < this._element.width || this.height < this._element.height;\r\n },\r\n\r\n /* _TO_SVG_START_ */\r\n /**\r\n * Returns svg representation of an instance\r\n * @return {Array} an array of strings with the specific svg representation\r\n * of the instance\r\n */\r\n _toSVG: function() {\r\n var svgString = [], imageMarkup = [], strokeSvg, element = this._element,\r\n x = -this.width / 2, y = -this.height / 2, clipPath = '', imageRendering = '';\r\n if (!element) {\r\n return [];\r\n }\r\n if (this.hasCrop()) {\r\n var clipPathId = fabric.Object.__uid++;\r\n svgString.push(\r\n '\\n',\r\n '\\t\\n',\r\n '\\n'\r\n );\r\n clipPath = ' clip-path=\"url(#imageCrop_' + clipPathId + ')\" ';\r\n }\r\n if (!this.imageSmoothing) {\r\n imageRendering = '\" image-rendering=\"optimizeSpeed';\r\n }\r\n imageMarkup.push('\\t element with actual transformation, then offsetting object to the top/left\r\n // so that object's center aligns with container's left/top\r\n '\" width=\"', element.width || element.naturalWidth,\r\n '\" height=\"', element.height || element.height,\r\n imageRendering,\r\n '\"', clipPath,\r\n '>\\n');\r\n\r\n if (this.stroke || this.strokeDashArray) {\r\n var origFill = this.fill;\r\n this.fill = null;\r\n strokeSvg = [\r\n '\\t\\n'\r\n ];\r\n this.fill = origFill;\r\n }\r\n if (this.paintFirst !== 'fill') {\r\n svgString = svgString.concat(strokeSvg, imageMarkup);\r\n }\r\n else {\r\n svgString = svgString.concat(imageMarkup, strokeSvg);\r\n }\r\n return svgString;\r\n },\r\n /* _TO_SVG_END_ */\r\n\r\n /**\r\n * Returns source of an image\r\n * @param {Boolean} filtered indicates if the src is needed for svg\r\n * @return {String} Source of an image\r\n */\r\n getSrc: function(filtered) {\r\n var element = filtered ? this._element : this._originalElement;\r\n if (element) {\r\n if (element.toDataURL) {\r\n return element.toDataURL();\r\n }\r\n\r\n if (this.srcFromAttribute) {\r\n return element.getAttribute('src');\r\n }\r\n else {\r\n return element.src;\r\n }\r\n }\r\n else {\r\n return this.src || '';\r\n }\r\n },\r\n\r\n /**\r\n * Sets source of an image\r\n * @param {String} src Source string (URL)\r\n * @param {Function} [callback] Callback is invoked when image has been loaded (and all filters have been applied)\r\n * @param {Object} [options] Options object\r\n * @param {String} [options.crossOrigin] crossOrigin value (one of \"\", \"anonymous\", \"use-credentials\")\r\n * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes\r\n * @return {fabric.Image} thisArg\r\n * @chainable\r\n */\r\n setSrc: function(src, callback, options) {\r\n fabric.util.loadImage(src, function(img, isError) {\r\n this.setElement(img, options);\r\n this._setWidthHeight();\r\n callback && callback(this, isError);\r\n }, this, options && options.crossOrigin);\r\n return this;\r\n },\r\n\r\n /**\r\n * Returns string representation of an instance\r\n * @return {String} String representation of an instance\r\n */\r\n toString: function() {\r\n return '#';\r\n },\r\n\r\n applyResizeFilters: function() {\r\n var filter = this.resizeFilter,\r\n minimumScale = this.minimumScaleTrigger,\r\n objectScale = this.getTotalObjectScaling(),\r\n scaleX = objectScale.scaleX,\r\n scaleY = objectScale.scaleY,\r\n elementToFilter = this._filteredEl || this._originalElement;\r\n if (this.group) {\r\n this.set('dirty', true);\r\n }\r\n if (!filter || (scaleX > minimumScale && scaleY > minimumScale)) {\r\n this._element = elementToFilter;\r\n this._filterScalingX = 1;\r\n this._filterScalingY = 1;\r\n this._lastScaleX = scaleX;\r\n this._lastScaleY = scaleY;\r\n return;\r\n }\r\n if (!fabric.filterBackend) {\r\n fabric.filterBackend = fabric.initFilterBackend();\r\n }\r\n var canvasEl = fabric.util.createCanvasElement(),\r\n cacheKey = this._filteredEl ? (this.cacheKey + '_filtered') : this.cacheKey,\r\n sourceWidth = elementToFilter.width, sourceHeight = elementToFilter.height;\r\n canvasEl.width = sourceWidth;\r\n canvasEl.height = sourceHeight;\r\n this._element = canvasEl;\r\n this._lastScaleX = filter.scaleX = scaleX;\r\n this._lastScaleY = filter.scaleY = scaleY;\r\n fabric.filterBackend.applyFilters(\r\n [filter], elementToFilter, sourceWidth, sourceHeight, this._element, cacheKey);\r\n this._filterScalingX = canvasEl.width / this._originalElement.width;\r\n this._filterScalingY = canvasEl.height / this._originalElement.height;\r\n },\r\n\r\n /**\r\n * Applies filters assigned to this image (from \"filters\" array) or from filter param\r\n * @method applyFilters\r\n * @param {Array} filters to be applied\r\n * @param {Boolean} forResizing specify if the filter operation is a resize operation\r\n * @return {thisArg} return the fabric.Image object\r\n * @chainable\r\n */\r\n applyFilters: function(filters) {\r\n\r\n filters = filters || this.filters || [];\r\n filters = filters.filter(function(filter) { return filter && !filter.isNeutralState(); });\r\n this.set('dirty', true);\r\n\r\n // needs to clear out or WEBGL will not resize correctly\r\n this.removeTexture(this.cacheKey + '_filtered');\r\n\r\n if (filters.length === 0) {\r\n this._element = this._originalElement;\r\n this._filteredEl = null;\r\n this._filterScalingX = 1;\r\n this._filterScalingY = 1;\r\n return this;\r\n }\r\n\r\n var imgElement = this._originalElement,\r\n sourceWidth = imgElement.naturalWidth || imgElement.width,\r\n sourceHeight = imgElement.naturalHeight || imgElement.height;\r\n\r\n if (this._element === this._originalElement) {\r\n // if the element is the same we need to create a new element\r\n var canvasEl = fabric.util.createCanvasElement();\r\n canvasEl.width = sourceWidth;\r\n canvasEl.height = sourceHeight;\r\n this._element = canvasEl;\r\n this._filteredEl = canvasEl;\r\n }\r\n else {\r\n // clear the existing element to get new filter data\r\n // also dereference the eventual resized _element\r\n this._element = this._filteredEl;\r\n this._filteredEl.getContext('2d', { willReadFrequently: true }).clearRect(0, 0, sourceWidth, sourceHeight);\r\n // we also need to resize again at next renderAll, so remove saved _lastScaleX/Y\r\n this._lastScaleX = 1;\r\n this._lastScaleY = 1;\r\n }\r\n if (!fabric.filterBackend) {\r\n fabric.filterBackend = fabric.initFilterBackend();\r\n }\r\n fabric.filterBackend.applyFilters(\r\n filters, this._originalElement, sourceWidth, sourceHeight, this._element, this.cacheKey);\r\n if (this._originalElement.width !== this._element.width ||\r\n this._originalElement.height !== this._element.height) {\r\n this._filterScalingX = this._element.width / this._originalElement.width;\r\n this._filterScalingY = this._element.height / this._originalElement.height;\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _render: function(ctx) {\r\n fabric.util.setImageSmoothing(ctx, this.imageSmoothing);\r\n if (this.isMoving !== true && this.resizeFilter && this._needsResize()) {\r\n this.applyResizeFilters();\r\n }\r\n this._stroke(ctx);\r\n this._renderPaintInOrder(ctx);\r\n },\r\n\r\n /**\r\n * Paint the cached copy of the object on the target context.\r\n * it will set the imageSmoothing for the draw operation\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n drawCacheOnCanvas: function(ctx) {\r\n fabric.util.setImageSmoothing(ctx, this.imageSmoothing);\r\n fabric.Object.prototype.drawCacheOnCanvas.call(this, ctx);\r\n },\r\n\r\n /**\r\n * Decide if the object should cache or not. Create its own cache level\r\n * needsItsOwnCache should be used when the object drawing method requires\r\n * a cache step. None of the fabric classes requires it.\r\n * Generally you do not cache objects in groups because the group outside is cached.\r\n * This is the special image version where we would like to avoid caching where possible.\r\n * Essentially images do not benefit from caching. They may require caching, and in that\r\n * case we do it. Also caching an image usually ends in a loss of details.\r\n * A full performance audit should be done.\r\n * @return {Boolean}\r\n */\r\n shouldCache: function() {\r\n return this.needsItsOwnCache();\r\n },\r\n\r\n _renderFill: function(ctx) {\r\n var elementToDraw = this._element;\r\n if (!elementToDraw) {\r\n return;\r\n }\r\n var scaleX = this._filterScalingX, scaleY = this._filterScalingY,\r\n w = this.width, h = this.height, min = Math.min, max = Math.max,\r\n // crop values cannot be lesser than 0.\r\n cropX = max(this.cropX, 0), cropY = max(this.cropY, 0),\r\n elWidth = elementToDraw.naturalWidth || elementToDraw.width,\r\n elHeight = elementToDraw.naturalHeight || elementToDraw.height,\r\n sX = cropX * scaleX,\r\n sY = cropY * scaleY,\r\n // the width height cannot exceed element width/height, starting from the crop offset.\r\n sW = min(w * scaleX, elWidth - sX),\r\n sH = min(h * scaleY, elHeight - sY),\r\n x = -w / 2, y = -h / 2,\r\n maxDestW = min(w, elWidth / scaleX - cropX),\r\n maxDestH = min(h, elHeight / scaleY - cropY);\r\n\r\n elementToDraw && ctx.drawImage(elementToDraw, sX, sY, sW, sH, x, y, maxDestW, maxDestH);\r\n },\r\n\r\n /**\r\n * needed to check if image needs resize\r\n * @private\r\n */\r\n _needsResize: function() {\r\n var scale = this.getTotalObjectScaling();\r\n return (scale.scaleX !== this._lastScaleX || scale.scaleY !== this._lastScaleY);\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _resetWidthHeight: function() {\r\n this.set(this.getOriginalSize());\r\n },\r\n\r\n /**\r\n * The Image class's initialization method. This method is automatically\r\n * called by the constructor.\r\n * @private\r\n * @param {HTMLImageElement|String} element The element representing the image\r\n * @param {Object} [options] Options object\r\n */\r\n _initElement: function(element, options) {\r\n this.setElement(fabric.util.getById(element), options);\r\n fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Object} [options] Options object\r\n */\r\n _initConfig: function(options) {\r\n options || (options = { });\r\n this.setOptions(options);\r\n this._setWidthHeight(options);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Array} filters to be initialized\r\n * @param {Function} callback Callback to invoke when all fabric.Image.filters instances are created\r\n */\r\n _initFilters: function(filters, callback) {\r\n if (filters && filters.length) {\r\n fabric.util.enlivenObjects(filters, function(enlivenedObjects) {\r\n callback && callback(enlivenedObjects);\r\n }, 'fabric.Image.filters');\r\n }\r\n else {\r\n callback && callback();\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n * Set the width and the height of the image object, using the element or the\r\n * options.\r\n * @param {Object} [options] Object with width/height properties\r\n */\r\n _setWidthHeight: function(options) {\r\n options || (options = { });\r\n var el = this.getElement();\r\n this.width = options.width || el.naturalWidth || el.width || 0;\r\n this.height = options.height || el.naturalHeight || el.height || 0;\r\n },\r\n\r\n /**\r\n * Calculate offset for center and scale factor for the image in order to respect\r\n * the preserveAspectRatio attribute\r\n * @private\r\n * @return {Object}\r\n */\r\n parsePreserveAspectRatioAttribute: function() {\r\n var pAR = fabric.util.parsePreserveAspectRatioAttribute(this.preserveAspectRatio || ''),\r\n rWidth = this._element.width, rHeight = this._element.height,\r\n scaleX = 1, scaleY = 1, offsetLeft = 0, offsetTop = 0, cropX = 0, cropY = 0,\r\n offset, pWidth = this.width, pHeight = this.height, parsedAttributes = { width: pWidth, height: pHeight };\r\n if (pAR && (pAR.alignX !== 'none' || pAR.alignY !== 'none')) {\r\n if (pAR.meetOrSlice === 'meet') {\r\n scaleX = scaleY = fabric.util.findScaleToFit(this._element, parsedAttributes);\r\n offset = (pWidth - rWidth * scaleX) / 2;\r\n if (pAR.alignX === 'Min') {\r\n offsetLeft = -offset;\r\n }\r\n if (pAR.alignX === 'Max') {\r\n offsetLeft = offset;\r\n }\r\n offset = (pHeight - rHeight * scaleY) / 2;\r\n if (pAR.alignY === 'Min') {\r\n offsetTop = -offset;\r\n }\r\n if (pAR.alignY === 'Max') {\r\n offsetTop = offset;\r\n }\r\n }\r\n if (pAR.meetOrSlice === 'slice') {\r\n scaleX = scaleY = fabric.util.findScaleToCover(this._element, parsedAttributes);\r\n offset = rWidth - pWidth / scaleX;\r\n if (pAR.alignX === 'Mid') {\r\n cropX = offset / 2;\r\n }\r\n if (pAR.alignX === 'Max') {\r\n cropX = offset;\r\n }\r\n offset = rHeight - pHeight / scaleY;\r\n if (pAR.alignY === 'Mid') {\r\n cropY = offset / 2;\r\n }\r\n if (pAR.alignY === 'Max') {\r\n cropY = offset;\r\n }\r\n rWidth = pWidth / scaleX;\r\n rHeight = pHeight / scaleY;\r\n }\r\n }\r\n else {\r\n scaleX = pWidth / rWidth;\r\n scaleY = pHeight / rHeight;\r\n }\r\n return {\r\n width: rWidth,\r\n height: rHeight,\r\n scaleX: scaleX,\r\n scaleY: scaleY,\r\n offsetLeft: offsetLeft,\r\n offsetTop: offsetTop,\r\n cropX: cropX,\r\n cropY: cropY\r\n };\r\n }\r\n });\r\n\r\n /**\r\n * Default CSS class name for canvas\r\n * @static\r\n * @type String\r\n * @default\r\n */\r\n fabric.Image.CSS_CANVAS = 'canvas-img';\r\n\r\n /**\r\n * Alias for getSrc\r\n * @static\r\n */\r\n fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc;\r\n\r\n /**\r\n * Creates an instance of fabric.Image from its object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {Function} callback Callback to invoke when an image instance is created\r\n */\r\n fabric.Image.fromObject = function(_object, callback) {\r\n var object = fabric.util.object.clone(_object);\r\n fabric.util.loadImage(object.src, function(img, isError) {\r\n if (isError) {\r\n callback && callback(null, true);\r\n return;\r\n }\r\n fabric.Image.prototype._initFilters.call(object, object.filters, function(filters) {\r\n object.filters = filters || [];\r\n fabric.Image.prototype._initFilters.call(object, [object.resizeFilter], function(resizeFilters) {\r\n object.resizeFilter = resizeFilters[0];\r\n fabric.util.enlivenObjectEnlivables(object, object, function () {\r\n var image = new fabric.Image(img, object);\r\n callback(image, false);\r\n });\r\n });\r\n });\r\n }, null, object.crossOrigin);\r\n };\r\n\r\n /**\r\n * Creates an instance of fabric.Image from an URL string\r\n * @static\r\n * @param {String} url URL to create an image from\r\n * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument). Second argument is a boolean indicating if an error occurred or not.\r\n * @param {Object} [imgOptions] Options object\r\n */\r\n fabric.Image.fromURL = function(url, callback, imgOptions) {\r\n fabric.util.loadImage(url, function(img, isError) {\r\n callback && callback(new fabric.Image(img, imgOptions), isError);\r\n }, null, imgOptions && imgOptions.crossOrigin);\r\n };\r\n\r\n /* _FROM_SVG_START_ */\r\n /**\r\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Image.fromElement})\r\n * @static\r\n * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement}\r\n */\r\n fabric.Image.ATTRIBUTE_NAMES =\r\n fabric.SHARED_ATTRIBUTES.concat(\r\n 'x y width height preserveAspectRatio xlink:href crossOrigin image-rendering'.split(' ')\r\n );\r\n\r\n /**\r\n * Returns {@link fabric.Image} instance from an SVG element\r\n * @static\r\n * @param {SVGElement} element Element to parse\r\n * @param {Object} [options] Options object\r\n * @param {Function} callback Callback to execute when fabric.Image object is created\r\n * @return {fabric.Image} Instance of fabric.Image\r\n */\r\n fabric.Image.fromElement = function(element, callback, options) {\r\n var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES);\r\n fabric.Image.fromURL(parsedAttributes['xlink:href'], callback,\r\n extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));\r\n };\r\n /* _FROM_SVG_END_ */\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\r\n\r\n /**\r\n * @private\r\n * @return {Number} angle value\r\n */\r\n _getAngleValueForStraighten: function() {\r\n var angle = this.angle % 360;\r\n if (angle > 0) {\r\n return Math.round((angle - 1) / 90) * 90;\r\n }\r\n return Math.round(angle / 90) * 90;\r\n },\r\n\r\n /**\r\n * Straightens an object (rotating it from current angle to one of 0, 90, 180, 270, etc. depending on which is closer)\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n straighten: function() {\r\n return this.rotate(this._getAngleValueForStraighten());\r\n },\r\n\r\n /**\r\n * Same as {@link fabric.Object.prototype.straighten} but with animation\r\n * @param {Object} callbacks Object with callback functions\r\n * @param {Function} [callbacks.onComplete] Invoked on completion\r\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\r\n * @return {fabric.Object} thisArg\r\n */\r\n fxStraighten: function(callbacks) {\r\n callbacks = callbacks || { };\r\n\r\n var empty = function() { },\r\n onComplete = callbacks.onComplete || empty,\r\n onChange = callbacks.onChange || empty,\r\n _this = this;\r\n\r\n return fabric.util.animate({\r\n target: this,\r\n startValue: this.get('angle'),\r\n endValue: this._getAngleValueForStraighten(),\r\n duration: this.FX_DURATION,\r\n onChange: function(value) {\r\n _this.rotate(value);\r\n onChange();\r\n },\r\n onComplete: function() {\r\n _this.setCoords();\r\n onComplete();\r\n },\r\n });\r\n }\r\n});\r\n\r\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\r\n\r\n /**\r\n * Straightens object, then rerenders canvas\r\n * @param {fabric.Object} object Object to straighten\r\n * @return {fabric.Canvas} thisArg\r\n * @chainable\r\n */\r\n straightenObject: function (object) {\r\n object.straighten();\r\n this.requestRenderAll();\r\n return this;\r\n },\r\n\r\n /**\r\n * Same as {@link fabric.Canvas.prototype.straightenObject}, but animated\r\n * @param {fabric.Object} object Object to straighten\r\n * @return {fabric.Canvas} thisArg\r\n */\r\n fxStraightenObject: function (object) {\r\n return object.fxStraighten({\r\n onChange: this.requestRenderAllBound\r\n });\r\n }\r\n});\r\n\r\n\r\n(function() {\r\n\r\n 'use strict';\r\n\r\n /**\r\n * Tests if webgl supports certain precision\r\n * @param {WebGL} Canvas WebGL context to test on\r\n * @param {String} Precision to test can be any of following: 'lowp', 'mediump', 'highp'\r\n * @returns {Boolean} Whether the user's browser WebGL supports given precision.\r\n */\r\n function testPrecision(gl, precision){\r\n var fragmentSource = 'precision ' + precision + ' float;\\nvoid main(){}';\r\n var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\r\n gl.shaderSource(fragmentShader, fragmentSource);\r\n gl.compileShader(fragmentShader);\r\n if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Indicate whether this filtering backend is supported by the user's browser.\r\n * @param {Number} tileSize check if the tileSize is supported\r\n * @returns {Boolean} Whether the user's browser supports WebGL.\r\n */\r\n fabric.isWebglSupported = function(tileSize) {\r\n if (fabric.isLikelyNode) {\r\n return false;\r\n }\r\n tileSize = tileSize || fabric.WebglFilterBackend.prototype.tileSize;\r\n var canvas = document.createElement('canvas');\r\n var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\r\n var isSupported = false;\r\n // eslint-disable-next-line\r\n if (gl) {\r\n fabric.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);\r\n isSupported = fabric.maxTextureSize >= tileSize;\r\n var precisions = ['highp', 'mediump', 'lowp'];\r\n for (var i = 0; i < 3; i++){\r\n if (testPrecision(gl, precisions[i])){\r\n fabric.webGlPrecision = precisions[i];\r\n break;\r\n };\r\n }\r\n }\r\n this.isSupported = isSupported;\r\n return isSupported;\r\n };\r\n\r\n fabric.WebglFilterBackend = WebglFilterBackend;\r\n\r\n /**\r\n * WebGL filter backend.\r\n */\r\n function WebglFilterBackend(options) {\r\n if (options && options.tileSize) {\r\n this.tileSize = options.tileSize;\r\n }\r\n this.setupGLContext(this.tileSize, this.tileSize);\r\n this.captureGPUInfo();\r\n };\r\n\r\n WebglFilterBackend.prototype = /** @lends fabric.WebglFilterBackend.prototype */ {\r\n\r\n tileSize: 2048,\r\n\r\n /**\r\n * Experimental. This object is a sort of repository of help layers used to avoid\r\n * of recreating them during frequent filtering. If you are previewing a filter with\r\n * a slider you probably do not want to create help layers every filter step.\r\n * in this object there will be appended some canvases, created once, resized sometimes\r\n * cleared never. Clearing is left to the developer.\r\n **/\r\n resources: {\r\n\r\n },\r\n\r\n /**\r\n * Setup a WebGL context suitable for filtering, and bind any needed event handlers.\r\n */\r\n setupGLContext: function(width, height) {\r\n this.dispose();\r\n this.createWebGLCanvas(width, height);\r\n // eslint-disable-next-line\r\n this.aPosition = new Float32Array([0, 0, 0, 1, 1, 0, 1, 1]);\r\n this.chooseFastestCopyGLTo2DMethod(width, height);\r\n },\r\n\r\n /**\r\n * Pick a method to copy data from GL context to 2d canvas. In some browsers using\r\n * putImageData is faster than drawImage for that specific operation.\r\n */\r\n chooseFastestCopyGLTo2DMethod: function(width, height) {\r\n var canMeasurePerf = typeof window.performance !== 'undefined', canUseImageData;\r\n try {\r\n new ImageData(1, 1);\r\n canUseImageData = true;\r\n }\r\n catch (e) {\r\n canUseImageData = false;\r\n }\r\n // eslint-disable-next-line no-undef\r\n var canUseArrayBuffer = typeof ArrayBuffer !== 'undefined';\r\n // eslint-disable-next-line no-undef\r\n var canUseUint8Clamped = typeof Uint8ClampedArray !== 'undefined';\r\n\r\n if (!(canMeasurePerf && canUseImageData && canUseArrayBuffer && canUseUint8Clamped)) {\r\n return;\r\n }\r\n\r\n var targetCanvas = fabric.util.createCanvasElement();\r\n // eslint-disable-next-line no-undef\r\n var imageBuffer = new ArrayBuffer(width * height * 4);\r\n if (fabric.forceGLPutImageData) {\r\n this.imageBuffer = imageBuffer;\r\n this.copyGLTo2D = copyGLTo2DPutImageData;\r\n return;\r\n }\r\n var testContext = {\r\n imageBuffer: imageBuffer,\r\n destinationWidth: width,\r\n destinationHeight: height,\r\n targetCanvas: targetCanvas\r\n };\r\n var startTime, drawImageTime, putImageDataTime;\r\n targetCanvas.width = width;\r\n targetCanvas.height = height;\r\n\r\n startTime = window.performance.now();\r\n copyGLTo2DDrawImage.call(testContext, this.gl, testContext);\r\n drawImageTime = window.performance.now() - startTime;\r\n\r\n startTime = window.performance.now();\r\n copyGLTo2DPutImageData.call(testContext, this.gl, testContext);\r\n putImageDataTime = window.performance.now() - startTime;\r\n\r\n if (drawImageTime > putImageDataTime) {\r\n this.imageBuffer = imageBuffer;\r\n this.copyGLTo2D = copyGLTo2DPutImageData;\r\n }\r\n else {\r\n this.copyGLTo2D = copyGLTo2DDrawImage;\r\n }\r\n },\r\n\r\n /**\r\n * Create a canvas element and associated WebGL context and attaches them as\r\n * class properties to the GLFilterBackend class.\r\n */\r\n createWebGLCanvas: function(width, height) {\r\n var canvas = fabric.util.createCanvasElement();\r\n canvas.width = width;\r\n canvas.height = height;\r\n var glOptions = {\r\n alpha: true,\r\n premultipliedAlpha: false,\r\n depth: false,\r\n stencil: false,\r\n antialias: false\r\n },\r\n gl = canvas.getContext('webgl', glOptions);\r\n if (!gl) {\r\n gl = canvas.getContext('experimental-webgl', glOptions);\r\n }\r\n if (!gl) {\r\n return;\r\n }\r\n gl.clearColor(0, 0, 0, 0);\r\n // this canvas can fire webglcontextlost and webglcontextrestored\r\n this.canvas = canvas;\r\n this.gl = gl;\r\n },\r\n\r\n /**\r\n * Attempts to apply the requested filters to the source provided, drawing the filtered output\r\n * to the provided target canvas.\r\n *\r\n * @param {Array} filters The filters to apply.\r\n * @param {HTMLImageElement|HTMLCanvasElement} source The source to be filtered.\r\n * @param {Number} width The width of the source input.\r\n * @param {Number} height The height of the source input.\r\n * @param {HTMLCanvasElement} targetCanvas The destination for filtered output to be drawn.\r\n * @param {String|undefined} cacheKey A key used to cache resources related to the source. If\r\n * omitted, caching will be skipped.\r\n */\r\n applyFilters: function(filters, source, width, height, targetCanvas, cacheKey) {\r\n var gl = this.gl;\r\n var cachedTexture;\r\n if (cacheKey) {\r\n cachedTexture = this.getCachedTexture(cacheKey, source);\r\n }\r\n var pipelineState = {\r\n originalWidth: source.width || source.originalWidth,\r\n originalHeight: source.height || source.originalHeight,\r\n sourceWidth: width,\r\n sourceHeight: height,\r\n destinationWidth: width,\r\n destinationHeight: height,\r\n context: gl,\r\n sourceTexture: this.createTexture(gl, width, height, !cachedTexture && source),\r\n targetTexture: this.createTexture(gl, width, height),\r\n originalTexture: cachedTexture ||\r\n this.createTexture(gl, width, height, !cachedTexture && source),\r\n passes: filters.length,\r\n webgl: true,\r\n aPosition: this.aPosition,\r\n programCache: this.programCache,\r\n pass: 0,\r\n filterBackend: this,\r\n targetCanvas: targetCanvas\r\n };\r\n var tempFbo = gl.createFramebuffer();\r\n gl.bindFramebuffer(gl.FRAMEBUFFER, tempFbo);\r\n filters.forEach(function(filter) { filter && filter.applyTo(pipelineState); });\r\n resizeCanvasIfNeeded(pipelineState);\r\n this.copyGLTo2D(gl, pipelineState);\r\n gl.bindTexture(gl.TEXTURE_2D, null);\r\n gl.deleteTexture(pipelineState.sourceTexture);\r\n gl.deleteTexture(pipelineState.targetTexture);\r\n gl.deleteFramebuffer(tempFbo);\r\n targetCanvas.getContext('2d', { willReadFrequently: true }).setTransform(1, 0, 0, 1, 0, 0);\r\n return pipelineState;\r\n },\r\n\r\n /**\r\n * Detach event listeners, remove references, and clean up caches.\r\n */\r\n dispose: function() {\r\n if (this.canvas) {\r\n this.canvas = null;\r\n this.gl = null;\r\n }\r\n this.clearWebGLCaches();\r\n },\r\n\r\n /**\r\n * Wipe out WebGL-related caches.\r\n */\r\n clearWebGLCaches: function() {\r\n this.programCache = {};\r\n this.textureCache = {};\r\n },\r\n\r\n /**\r\n * Create a WebGL texture object.\r\n *\r\n * Accepts specific dimensions to initialize the texture to or a source image.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL context to use for creating the texture.\r\n * @param {Number} width The width to initialize the texture at.\r\n * @param {Number} height The height to initialize the texture.\r\n * @param {HTMLImageElement|HTMLCanvasElement} textureImageSource A source for the texture data.\r\n * @param {Number} filterType gl.NEAREST or gl.LINEAR usually, webgl numeri constants\r\n * @returns {WebGLTexture}\r\n */\r\n createTexture: function(gl, width, height, textureImageSource, filterType) {\r\n var texture = gl.createTexture();\r\n gl.bindTexture(gl.TEXTURE_2D, texture);\r\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filterType || gl.NEAREST);\r\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filterType || gl.NEAREST);\r\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\r\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\r\n if (textureImageSource) {\r\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureImageSource);\r\n }\r\n else {\r\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\r\n }\r\n return texture;\r\n },\r\n\r\n /**\r\n * Can be optionally used to get a texture from the cache array\r\n *\r\n * If an existing texture is not found, a new texture is created and cached.\r\n *\r\n * @param {String} uniqueId A cache key to use to find an existing texture.\r\n * @param {HTMLImageElement|HTMLCanvasElement} textureImageSource A source to use to create the\r\n * texture cache entry if one does not already exist.\r\n */\r\n getCachedTexture: function(uniqueId, textureImageSource) {\r\n if (this.textureCache[uniqueId]) {\r\n return this.textureCache[uniqueId];\r\n }\r\n else {\r\n var texture = this.createTexture(\r\n this.gl, textureImageSource.width, textureImageSource.height, textureImageSource);\r\n this.textureCache[uniqueId] = texture;\r\n return texture;\r\n }\r\n },\r\n\r\n /**\r\n * Clear out cached resources related to a source image that has been\r\n * filtered previously.\r\n *\r\n * @param {String} cacheKey The cache key provided when the source image was filtered.\r\n */\r\n evictCachesForKey: function(cacheKey) {\r\n if (this.textureCache[cacheKey]) {\r\n this.gl.deleteTexture(this.textureCache[cacheKey]);\r\n delete this.textureCache[cacheKey];\r\n }\r\n },\r\n\r\n copyGLTo2D: copyGLTo2DDrawImage,\r\n\r\n /**\r\n * Attempt to extract GPU information strings from a WebGL context.\r\n *\r\n * Useful information when debugging or blacklisting specific GPUs.\r\n *\r\n * @returns {Object} A GPU info object with renderer and vendor strings.\r\n */\r\n captureGPUInfo: function() {\r\n if (this.gpuInfo) {\r\n return this.gpuInfo;\r\n }\r\n var gl = this.gl, gpuInfo = { renderer: '', vendor: '' };\r\n if (!gl) {\r\n return gpuInfo;\r\n }\r\n var ext = gl.getExtension('WEBGL_debug_renderer_info');\r\n if (ext) {\r\n var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);\r\n var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);\r\n if (renderer) {\r\n gpuInfo.renderer = renderer.toLowerCase();\r\n }\r\n if (vendor) {\r\n gpuInfo.vendor = vendor.toLowerCase();\r\n }\r\n }\r\n this.gpuInfo = gpuInfo;\r\n return gpuInfo;\r\n },\r\n };\r\n})();\r\n\r\nfunction resizeCanvasIfNeeded(pipelineState) {\r\n var targetCanvas = pipelineState.targetCanvas,\r\n width = targetCanvas.width, height = targetCanvas.height,\r\n dWidth = pipelineState.destinationWidth,\r\n dHeight = pipelineState.destinationHeight;\r\n\r\n if (width !== dWidth || height !== dHeight) {\r\n targetCanvas.width = dWidth;\r\n targetCanvas.height = dHeight;\r\n }\r\n}\r\n\r\n/**\r\n * Copy an input WebGL canvas on to an output 2D canvas.\r\n *\r\n * The WebGL canvas is assumed to be upside down, with the top-left pixel of the\r\n * desired output image appearing in the bottom-left corner of the WebGL canvas.\r\n *\r\n * @param {WebGLRenderingContext} sourceContext The WebGL context to copy from.\r\n * @param {HTMLCanvasElement} targetCanvas The 2D target canvas to copy on to.\r\n * @param {Object} pipelineState The 2D target canvas to copy on to.\r\n */\r\nfunction copyGLTo2DDrawImage(gl, pipelineState) {\r\n var glCanvas = gl.canvas, targetCanvas = pipelineState.targetCanvas,\r\n ctx = targetCanvas.getContext('2d', { willReadFrequently: true });\r\n ctx.translate(0, targetCanvas.height); // move it down again\r\n ctx.scale(1, -1); // vertical flip\r\n // where is my image on the big glcanvas?\r\n var sourceY = glCanvas.height - targetCanvas.height;\r\n ctx.drawImage(glCanvas, 0, sourceY, targetCanvas.width, targetCanvas.height, 0, 0,\r\n targetCanvas.width, targetCanvas.height);\r\n}\r\n\r\n/**\r\n * Copy an input WebGL canvas on to an output 2D canvas using 2d canvas' putImageData\r\n * API. Measurably faster than using ctx.drawImage in Firefox (version 54 on OSX Sierra).\r\n *\r\n * @param {WebGLRenderingContext} sourceContext The WebGL context to copy from.\r\n * @param {HTMLCanvasElement} targetCanvas The 2D target canvas to copy on to.\r\n * @param {Object} pipelineState The 2D target canvas to copy on to.\r\n */\r\nfunction copyGLTo2DPutImageData(gl, pipelineState) {\r\n var targetCanvas = pipelineState.targetCanvas, ctx = targetCanvas.getContext('2d', { willReadFrequently: true }),\r\n dWidth = pipelineState.destinationWidth,\r\n dHeight = pipelineState.destinationHeight,\r\n numBytes = dWidth * dHeight * 4;\r\n\r\n // eslint-disable-next-line no-undef\r\n var u8 = new Uint8Array(this.imageBuffer, 0, numBytes);\r\n // eslint-disable-next-line no-undef\r\n var u8Clamped = new Uint8ClampedArray(this.imageBuffer, 0, numBytes);\r\n\r\n gl.readPixels(0, 0, dWidth, dHeight, gl.RGBA, gl.UNSIGNED_BYTE, u8);\r\n var imgData = new ImageData(u8Clamped, dWidth, dHeight);\r\n ctx.putImageData(imgData, 0, 0);\r\n}\r\n\r\n\r\n(function() {\r\n\r\n 'use strict';\r\n\r\n var noop = function() {};\r\n\r\n fabric.Canvas2dFilterBackend = Canvas2dFilterBackend;\r\n\r\n /**\r\n * Canvas 2D filter backend.\r\n */\r\n function Canvas2dFilterBackend() {};\r\n\r\n Canvas2dFilterBackend.prototype = /** @lends fabric.Canvas2dFilterBackend.prototype */ {\r\n evictCachesForKey: noop,\r\n dispose: noop,\r\n clearWebGLCaches: noop,\r\n\r\n /**\r\n * Experimental. This object is a sort of repository of help layers used to avoid\r\n * of recreating them during frequent filtering. If you are previewing a filter with\r\n * a slider you probably do not want to create help layers every filter step.\r\n * in this object there will be appended some canvases, created once, resized sometimes\r\n * cleared never. Clearing is left to the developer.\r\n **/\r\n resources: {\r\n\r\n },\r\n\r\n /**\r\n * Apply a set of filters against a source image and draw the filtered output\r\n * to the provided destination canvas.\r\n *\r\n * @param {EnhancedFilter} filters The filter to apply.\r\n * @param {HTMLImageElement|HTMLCanvasElement} sourceElement The source to be filtered.\r\n * @param {Number} sourceWidth The width of the source input.\r\n * @param {Number} sourceHeight The height of the source input.\r\n * @param {HTMLCanvasElement} targetCanvas The destination for filtered output to be drawn.\r\n */\r\n applyFilters: function(filters, sourceElement, sourceWidth, sourceHeight, targetCanvas) {\r\n var ctx = targetCanvas.getContext('2d', { willReadFrequently: true });\r\n ctx.drawImage(sourceElement, 0, 0, sourceWidth, sourceHeight);\r\n var imageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight);\r\n var originalImageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight);\r\n var pipelineState = {\r\n sourceWidth: sourceWidth,\r\n sourceHeight: sourceHeight,\r\n imageData: imageData,\r\n originalEl: sourceElement,\r\n originalImageData: originalImageData,\r\n canvasEl: targetCanvas,\r\n ctx: ctx,\r\n filterBackend: this,\r\n };\r\n filters.forEach(function(filter) { filter.applyTo(pipelineState); });\r\n if (pipelineState.imageData.width !== sourceWidth || pipelineState.imageData.height !== sourceHeight) {\r\n targetCanvas.width = pipelineState.imageData.width;\r\n targetCanvas.height = pipelineState.imageData.height;\r\n }\r\n ctx.putImageData(pipelineState.imageData, 0, 0);\r\n return pipelineState;\r\n },\r\n\r\n };\r\n})();\r\n\r\n\r\n/**\r\n * @namespace fabric.Image.filters\r\n * @memberOf fabric.Image\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#image_filters}\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n */\r\nfabric.Image = fabric.Image || { };\r\nfabric.Image.filters = fabric.Image.filters || { };\r\n\r\n/**\r\n * Root filter class from which all filter classes inherit from\r\n * @class fabric.Image.filters.BaseFilter\r\n * @memberOf fabric.Image.filters\r\n */\r\nfabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Image.filters.BaseFilter.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'BaseFilter',\r\n\r\n /**\r\n * Array of attributes to send with buffers. do not modify\r\n * @private\r\n */\r\n\r\n vertexSource: 'attribute vec2 aPosition;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vTexCoord = aPosition;\\n' +\r\n 'gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\\n' +\r\n '}',\r\n\r\n fragmentSource: 'precision highp float;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'void main() {\\n' +\r\n 'gl_FragColor = texture2D(uTexture, vTexCoord);\\n' +\r\n '}',\r\n\r\n /**\r\n * Constructor\r\n * @param {Object} [options] Options object\r\n */\r\n initialize: function(options) {\r\n if (options) {\r\n this.setOptions(options);\r\n }\r\n },\r\n\r\n /**\r\n * Sets filter's properties from options\r\n * @param {Object} [options] Options object\r\n */\r\n setOptions: function(options) {\r\n for (var prop in options) {\r\n this[prop] = options[prop];\r\n }\r\n },\r\n\r\n /**\r\n * Compile this filter's shader program.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context to use for shader compilation.\r\n * @param {String} fragmentSource fragmentShader source for compilation\r\n * @param {String} vertexSource vertexShader source for compilation\r\n */\r\n createProgram: function(gl, fragmentSource, vertexSource) {\r\n fragmentSource = fragmentSource || this.fragmentSource;\r\n vertexSource = vertexSource || this.vertexSource;\r\n if (fabric.webGlPrecision !== 'highp'){\r\n fragmentSource = fragmentSource.replace(\r\n /precision highp float/g,\r\n 'precision ' + fabric.webGlPrecision + ' float'\r\n );\r\n }\r\n var vertexShader = gl.createShader(gl.VERTEX_SHADER);\r\n gl.shaderSource(vertexShader, vertexSource);\r\n gl.compileShader(vertexShader);\r\n if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {\r\n throw new Error(\r\n // eslint-disable-next-line prefer-template\r\n 'Vertex shader compile error for ' + this.type + ': ' +\r\n gl.getShaderInfoLog(vertexShader)\r\n );\r\n }\r\n\r\n var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\r\n gl.shaderSource(fragmentShader, fragmentSource);\r\n gl.compileShader(fragmentShader);\r\n if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\r\n throw new Error(\r\n // eslint-disable-next-line prefer-template\r\n 'Fragment shader compile error for ' + this.type + ': ' +\r\n gl.getShaderInfoLog(fragmentShader)\r\n );\r\n }\r\n\r\n var program = gl.createProgram();\r\n gl.attachShader(program, vertexShader);\r\n gl.attachShader(program, fragmentShader);\r\n gl.linkProgram(program);\r\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\r\n throw new Error(\r\n // eslint-disable-next-line prefer-template\r\n 'Shader link error for \"${this.type}\" ' +\r\n gl.getProgramInfoLog(program)\r\n );\r\n }\r\n\r\n var attributeLocations = this.getAttributeLocations(gl, program);\r\n var uniformLocations = this.getUniformLocations(gl, program) || { };\r\n uniformLocations.uStepW = gl.getUniformLocation(program, 'uStepW');\r\n uniformLocations.uStepH = gl.getUniformLocation(program, 'uStepH');\r\n return {\r\n program: program,\r\n attributeLocations: attributeLocations,\r\n uniformLocations: uniformLocations\r\n };\r\n },\r\n\r\n /**\r\n * Return a map of attribute names to WebGLAttributeLocation objects.\r\n *\r\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\r\n * @param {WebGLShaderProgram} program The shader program from which to take attribute locations.\r\n * @returns {Object} A map of attribute names to attribute locations.\r\n */\r\n getAttributeLocations: function(gl, program) {\r\n return {\r\n aPosition: gl.getAttribLocation(program, 'aPosition'),\r\n };\r\n },\r\n\r\n /**\r\n * Return a map of uniform names to WebGLUniformLocation objects.\r\n *\r\n * Intended to be overridden by subclasses.\r\n *\r\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\r\n * @param {WebGLShaderProgram} program The shader program from which to take uniform locations.\r\n * @returns {Object} A map of uniform names to uniform locations.\r\n */\r\n getUniformLocations: function (/* gl, program */) {\r\n // in case i do not need any special uniform i need to return an empty object\r\n return { };\r\n },\r\n\r\n /**\r\n * Send attribute data from this filter to its shader program on the GPU.\r\n *\r\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\r\n * @param {Object} attributeLocations A map of shader attribute names to their locations.\r\n */\r\n sendAttributeData: function(gl, attributeLocations, aPositionData) {\r\n var attributeLocation = attributeLocations.aPosition;\r\n var buffer = gl.createBuffer();\r\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\r\n gl.enableVertexAttribArray(attributeLocation);\r\n gl.vertexAttribPointer(attributeLocation, 2, gl.FLOAT, false, 0, 0);\r\n gl.bufferData(gl.ARRAY_BUFFER, aPositionData, gl.STATIC_DRAW);\r\n },\r\n\r\n _setupFrameBuffer: function(options) {\r\n var gl = options.context, width, height;\r\n if (options.passes > 1) {\r\n width = options.destinationWidth;\r\n height = options.destinationHeight;\r\n if (options.sourceWidth !== width || options.sourceHeight !== height) {\r\n gl.deleteTexture(options.targetTexture);\r\n options.targetTexture = options.filterBackend.createTexture(gl, width, height);\r\n }\r\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D,\r\n options.targetTexture, 0);\r\n }\r\n else {\r\n // draw last filter on canvas and not to framebuffer.\r\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\r\n gl.finish();\r\n }\r\n },\r\n\r\n _swapTextures: function(options) {\r\n options.passes--;\r\n options.pass++;\r\n var temp = options.targetTexture;\r\n options.targetTexture = options.sourceTexture;\r\n options.sourceTexture = temp;\r\n },\r\n\r\n /**\r\n * Generic isNeutral implementation for one parameter based filters.\r\n * Used only in image applyFilters to discard filters that will not have an effect\r\n * on the image\r\n * Other filters may need their own version ( ColorMatrix, HueRotation, gamma, ComposedFilter )\r\n * @param {Object} options\r\n **/\r\n isNeutralState: function(/* options */) {\r\n var main = this.mainParameter,\r\n _class = fabric.Image.filters[this.type].prototype;\r\n if (main) {\r\n if (Array.isArray(_class[main])) {\r\n for (var i = _class[main].length; i--;) {\r\n if (this[main][i] !== _class[main][i]) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n else {\r\n return _class[main] === this[main];\r\n }\r\n }\r\n else {\r\n return false;\r\n }\r\n },\r\n\r\n /**\r\n * Apply this filter to the input image data provided.\r\n *\r\n * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\r\n *\r\n * @param {Object} options\r\n * @param {Number} options.passes The number of filters remaining to be executed\r\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\r\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\r\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\r\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\r\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\r\n */\r\n applyTo: function(options) {\r\n if (options.webgl) {\r\n this._setupFrameBuffer(options);\r\n this.applyToWebGL(options);\r\n this._swapTextures(options);\r\n }\r\n else {\r\n this.applyTo2d(options);\r\n }\r\n },\r\n\r\n /**\r\n * Retrieves the cached shader.\r\n * @param {Object} options\r\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\r\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\r\n */\r\n retrieveShader: function(options) {\r\n if (!options.programCache.hasOwnProperty(this.type)) {\r\n options.programCache[this.type] = this.createProgram(options.context);\r\n }\r\n return options.programCache[this.type];\r\n },\r\n\r\n /**\r\n * Apply this filter using webgl.\r\n *\r\n * @param {Object} options\r\n * @param {Number} options.passes The number of filters remaining to be executed\r\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\r\n * @param {WebGLTexture} options.originalTexture The texture of the original input image.\r\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\r\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\r\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\r\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\r\n */\r\n applyToWebGL: function(options) {\r\n var gl = options.context;\r\n var shader = this.retrieveShader(options);\r\n if (options.pass === 0 && options.originalTexture) {\r\n gl.bindTexture(gl.TEXTURE_2D, options.originalTexture);\r\n }\r\n else {\r\n gl.bindTexture(gl.TEXTURE_2D, options.sourceTexture);\r\n }\r\n gl.useProgram(shader.program);\r\n this.sendAttributeData(gl, shader.attributeLocations, options.aPosition);\r\n\r\n gl.uniform1f(shader.uniformLocations.uStepW, 1 / options.sourceWidth);\r\n gl.uniform1f(shader.uniformLocations.uStepH, 1 / options.sourceHeight);\r\n\r\n this.sendUniformData(gl, shader.uniformLocations);\r\n gl.viewport(0, 0, options.destinationWidth, options.destinationHeight);\r\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\r\n },\r\n\r\n bindAdditionalTexture: function(gl, texture, textureUnit) {\r\n gl.activeTexture(textureUnit);\r\n gl.bindTexture(gl.TEXTURE_2D, texture);\r\n // reset active texture to 0 as usual\r\n gl.activeTexture(gl.TEXTURE0);\r\n },\r\n\r\n unbindAdditionalTexture: function(gl, textureUnit) {\r\n gl.activeTexture(textureUnit);\r\n gl.bindTexture(gl.TEXTURE_2D, null);\r\n gl.activeTexture(gl.TEXTURE0);\r\n },\r\n\r\n getMainParameter: function() {\r\n return this[this.mainParameter];\r\n },\r\n\r\n setMainParameter: function(value) {\r\n this[this.mainParameter] = value;\r\n },\r\n\r\n /**\r\n * Send uniform data from this filter to its shader program on the GPU.\r\n *\r\n * Intended to be overridden by subclasses.\r\n *\r\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\r\n * @param {Object} uniformLocations A map of shader uniform names to their locations.\r\n */\r\n sendUniformData: function(/* gl, uniformLocations */) {\r\n // Intentionally left blank. Override me in subclasses.\r\n },\r\n\r\n /**\r\n * If needed by a 2d filter, this functions can create an helper canvas to be used\r\n * remember that options.targetCanvas is available for use till end of chain.\r\n */\r\n createHelpLayer: function(options) {\r\n if (!options.helpLayer) {\r\n var helpLayer = document.createElement('canvas');\r\n helpLayer.width = options.sourceWidth;\r\n helpLayer.height = options.sourceHeight;\r\n options.helpLayer = helpLayer;\r\n }\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @return {Object} Object representation of an instance\r\n */\r\n toObject: function() {\r\n var object = { type: this.type }, mainP = this.mainParameter;\r\n if (mainP) {\r\n object[mainP] = this[mainP];\r\n }\r\n return object;\r\n },\r\n\r\n /**\r\n * Returns a JSON representation of an instance\r\n * @return {Object} JSON\r\n */\r\n toJSON: function() {\r\n // delegate, not alias\r\n return this.toObject();\r\n }\r\n});\r\n\r\nfabric.Image.filters.BaseFilter.fromObject = function(object, callback) {\r\n var filter = new fabric.Image.filters[object.type](object);\r\n callback && callback(filter);\r\n return filter;\r\n};\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Color Matrix filter class\r\n * @class fabric.Image.filters.ColorMatrix\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link fabric.Image.filters.ColorMatrix#initialize} for constructor definition\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @see {@Link http://www.webwasp.co.uk/tutorials/219/Color_Matrix_Filter.php}\r\n * @see {@Link http://phoboslab.org/log/2013/11/fast-image-filters-with-webgl}\r\n * @example Kodachrome filter\r\n * var filter = new fabric.Image.filters.ColorMatrix({\r\n * matrix: [\r\n 1.1285582396593525, -0.3967382283601348, -0.03992559172921793, 0, 63.72958762196502,\r\n -0.16404339962244616, 1.0835251566291304, -0.05498805115633132, 0, 24.732407896706203,\r\n -0.16786010706155763, -0.5603416277695248, 1.6014850761964943, 0, 35.62982807460946,\r\n 0, 0, 0, 1, 0\r\n ]\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n */\r\n filters.ColorMatrix = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.ColorMatrix.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'ColorMatrix',\r\n\r\n fragmentSource: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'uniform mat4 uColorMatrix;\\n' +\r\n 'uniform vec4 uConstants;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\r\n 'color *= uColorMatrix;\\n' +\r\n 'color += uConstants;\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}',\r\n\r\n /**\r\n * Colormatrix for pixels.\r\n * array of 20 floats. Numbers in positions 4, 9, 14, 19 loose meaning\r\n * outside the -1, 1 range.\r\n * 0.0039215686 is the part of 1 that get translated to 1 in 2d\r\n * @param {Array} matrix array of 20 numbers.\r\n * @default\r\n */\r\n matrix: [\r\n 1, 0, 0, 0, 0,\r\n 0, 1, 0, 0, 0,\r\n 0, 0, 1, 0, 0,\r\n 0, 0, 0, 1, 0\r\n ],\r\n\r\n mainParameter: 'matrix',\r\n\r\n /**\r\n * Lock the colormatrix on the color part, skipping alpha, mainly for non webgl scenario\r\n * to save some calculation\r\n * @type Boolean\r\n * @default true\r\n */\r\n colorsOnly: true,\r\n\r\n /**\r\n * Constructor\r\n * @param {Object} [options] Options object\r\n */\r\n initialize: function(options) {\r\n this.callSuper('initialize', options);\r\n // create a new array instead mutating the prototype with push\r\n this.matrix = this.matrix.slice(0);\r\n },\r\n\r\n /**\r\n * Apply the ColorMatrix operation to a Uint8Array representing the pixels of an image.\r\n *\r\n * @param {Object} options\r\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\r\n */\r\n applyTo2d: function(options) {\r\n var imageData = options.imageData,\r\n data = imageData.data,\r\n iLen = data.length,\r\n m = this.matrix,\r\n r, g, b, a, i, colorsOnly = this.colorsOnly;\r\n\r\n for (i = 0; i < iLen; i += 4) {\r\n r = data[i];\r\n g = data[i + 1];\r\n b = data[i + 2];\r\n if (colorsOnly) {\r\n data[i] = r * m[0] + g * m[1] + b * m[2] + m[4] * 255;\r\n data[i + 1] = r * m[5] + g * m[6] + b * m[7] + m[9] * 255;\r\n data[i + 2] = r * m[10] + g * m[11] + b * m[12] + m[14] * 255;\r\n }\r\n else {\r\n a = data[i + 3];\r\n data[i] = r * m[0] + g * m[1] + b * m[2] + a * m[3] + m[4] * 255;\r\n data[i + 1] = r * m[5] + g * m[6] + b * m[7] + a * m[8] + m[9] * 255;\r\n data[i + 2] = r * m[10] + g * m[11] + b * m[12] + a * m[13] + m[14] * 255;\r\n data[i + 3] = r * m[15] + g * m[16] + b * m[17] + a * m[18] + m[19] * 255;\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uColorMatrix: gl.getUniformLocation(program, 'uColorMatrix'),\r\n uConstants: gl.getUniformLocation(program, 'uConstants'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n var m = this.matrix,\r\n matrix = [\r\n m[0], m[1], m[2], m[3],\r\n m[5], m[6], m[7], m[8],\r\n m[10], m[11], m[12], m[13],\r\n m[15], m[16], m[17], m[18]\r\n ],\r\n constants = [m[4], m[9], m[14], m[19]];\r\n gl.uniformMatrix4fv(uniformLocations.uColorMatrix, false, matrix);\r\n gl.uniform4fv(uniformLocations.uConstants, constants);\r\n },\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} [callback] function to invoke after filter creation\r\n * @return {fabric.Image.filters.ColorMatrix} Instance of fabric.Image.filters.ColorMatrix\r\n */\r\n fabric.Image.filters.ColorMatrix.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Brightness filter class\r\n * @class fabric.Image.filters.Brightness\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link fabric.Image.filters.Brightness#initialize} for constructor definition\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example\r\n * var filter = new fabric.Image.filters.Brightness({\r\n * brightness: 0.05\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n */\r\n filters.Brightness = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Brightness.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'Brightness',\r\n\r\n /**\r\n * Fragment source for the brightness program\r\n */\r\n fragmentSource: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uBrightness;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\r\n 'color.rgb += uBrightness;\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}',\r\n\r\n /**\r\n * Brightness value, from -1 to 1.\r\n * translated to -255 to 255 for 2d\r\n * 0.0039215686 is the part of 1 that get translated to 1 in 2d\r\n * @param {Number} brightness\r\n * @default\r\n */\r\n brightness: 0,\r\n\r\n /**\r\n * Describe the property that is the filter parameter\r\n * @param {String} m\r\n * @default\r\n */\r\n mainParameter: 'brightness',\r\n\r\n /**\r\n * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\r\n *\r\n * @param {Object} options\r\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\r\n */\r\n applyTo2d: function(options) {\r\n if (this.brightness === 0) {\r\n return;\r\n }\r\n var imageData = options.imageData,\r\n data = imageData.data, i, len = data.length,\r\n brightness = Math.round(this.brightness * 255);\r\n for (i = 0; i < len; i += 4) {\r\n data[i] = data[i] + brightness;\r\n data[i + 1] = data[i + 1] + brightness;\r\n data[i + 2] = data[i + 2] + brightness;\r\n }\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uBrightness: gl.getUniformLocation(program, 'uBrightness'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n gl.uniform1f(uniformLocations.uBrightness, this.brightness);\r\n },\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.Brightness} Instance of fabric.Image.filters.Brightness\r\n */\r\n fabric.Image.filters.Brightness.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n extend = fabric.util.object.extend,\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Adapted from html5rocks article\r\n * @class fabric.Image.filters.Convolute\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link fabric.Image.filters.Convolute#initialize} for constructor definition\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example Sharpen filter\r\n * var filter = new fabric.Image.filters.Convolute({\r\n * matrix: [ 0, -1, 0,\r\n * -1, 5, -1,\r\n * 0, -1, 0 ]\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n * canvas.renderAll();\r\n * @example Blur filter\r\n * var filter = new fabric.Image.filters.Convolute({\r\n * matrix: [ 1/9, 1/9, 1/9,\r\n * 1/9, 1/9, 1/9,\r\n * 1/9, 1/9, 1/9 ]\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n * canvas.renderAll();\r\n * @example Emboss filter\r\n * var filter = new fabric.Image.filters.Convolute({\r\n * matrix: [ 1, 1, 1,\r\n * 1, 0.7, -1,\r\n * -1, -1, -1 ]\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n * canvas.renderAll();\r\n * @example Emboss filter with opaqueness\r\n * var filter = new fabric.Image.filters.Convolute({\r\n * opaque: true,\r\n * matrix: [ 1, 1, 1,\r\n * 1, 0.7, -1,\r\n * -1, -1, -1 ]\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n * canvas.renderAll();\r\n */\r\n filters.Convolute = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Convolute.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'Convolute',\r\n\r\n /*\r\n * Opaque value (true/false)\r\n */\r\n opaque: false,\r\n\r\n /*\r\n * matrix for the filter, max 9x9\r\n */\r\n matrix: [0, 0, 0, 0, 1, 0, 0, 0, 0],\r\n\r\n /**\r\n * Fragment source for the brightness program\r\n */\r\n fragmentSource: {\r\n Convolute_3_1: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uMatrix[9];\\n' +\r\n 'uniform float uStepW;\\n' +\r\n 'uniform float uStepH;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = vec4(0, 0, 0, 0);\\n' +\r\n 'for (float h = 0.0; h < 3.0; h+=1.0) {\\n' +\r\n 'for (float w = 0.0; w < 3.0; w+=1.0) {\\n' +\r\n 'vec2 matrixPos = vec2(uStepW * (w - 1), uStepH * (h - 1));\\n' +\r\n 'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 3.0 + w)];\\n' +\r\n '}\\n' +\r\n '}\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}',\r\n Convolute_3_0: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uMatrix[9];\\n' +\r\n 'uniform float uStepW;\\n' +\r\n 'uniform float uStepH;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = vec4(0, 0, 0, 1);\\n' +\r\n 'for (float h = 0.0; h < 3.0; h+=1.0) {\\n' +\r\n 'for (float w = 0.0; w < 3.0; w+=1.0) {\\n' +\r\n 'vec2 matrixPos = vec2(uStepW * (w - 1.0), uStepH * (h - 1.0));\\n' +\r\n 'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 3.0 + w)];\\n' +\r\n '}\\n' +\r\n '}\\n' +\r\n 'float alpha = texture2D(uTexture, vTexCoord).a;\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n 'gl_FragColor.a = alpha;\\n' +\r\n '}',\r\n Convolute_5_1: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uMatrix[25];\\n' +\r\n 'uniform float uStepW;\\n' +\r\n 'uniform float uStepH;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = vec4(0, 0, 0, 0);\\n' +\r\n 'for (float h = 0.0; h < 5.0; h+=1.0) {\\n' +\r\n 'for (float w = 0.0; w < 5.0; w+=1.0) {\\n' +\r\n 'vec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\\n' +\r\n 'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 5.0 + w)];\\n' +\r\n '}\\n' +\r\n '}\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}',\r\n Convolute_5_0: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uMatrix[25];\\n' +\r\n 'uniform float uStepW;\\n' +\r\n 'uniform float uStepH;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = vec4(0, 0, 0, 1);\\n' +\r\n 'for (float h = 0.0; h < 5.0; h+=1.0) {\\n' +\r\n 'for (float w = 0.0; w < 5.0; w+=1.0) {\\n' +\r\n 'vec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\\n' +\r\n 'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 5.0 + w)];\\n' +\r\n '}\\n' +\r\n '}\\n' +\r\n 'float alpha = texture2D(uTexture, vTexCoord).a;\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n 'gl_FragColor.a = alpha;\\n' +\r\n '}',\r\n Convolute_7_1: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uMatrix[49];\\n' +\r\n 'uniform float uStepW;\\n' +\r\n 'uniform float uStepH;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = vec4(0, 0, 0, 0);\\n' +\r\n 'for (float h = 0.0; h < 7.0; h+=1.0) {\\n' +\r\n 'for (float w = 0.0; w < 7.0; w+=1.0) {\\n' +\r\n 'vec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\\n' +\r\n 'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 7.0 + w)];\\n' +\r\n '}\\n' +\r\n '}\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}',\r\n Convolute_7_0: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uMatrix[49];\\n' +\r\n 'uniform float uStepW;\\n' +\r\n 'uniform float uStepH;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = vec4(0, 0, 0, 1);\\n' +\r\n 'for (float h = 0.0; h < 7.0; h+=1.0) {\\n' +\r\n 'for (float w = 0.0; w < 7.0; w+=1.0) {\\n' +\r\n 'vec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\\n' +\r\n 'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 7.0 + w)];\\n' +\r\n '}\\n' +\r\n '}\\n' +\r\n 'float alpha = texture2D(uTexture, vTexCoord).a;\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n 'gl_FragColor.a = alpha;\\n' +\r\n '}',\r\n Convolute_9_1: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uMatrix[81];\\n' +\r\n 'uniform float uStepW;\\n' +\r\n 'uniform float uStepH;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = vec4(0, 0, 0, 0);\\n' +\r\n 'for (float h = 0.0; h < 9.0; h+=1.0) {\\n' +\r\n 'for (float w = 0.0; w < 9.0; w+=1.0) {\\n' +\r\n 'vec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\\n' +\r\n 'color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 9.0 + w)];\\n' +\r\n '}\\n' +\r\n '}\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}',\r\n Convolute_9_0: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uMatrix[81];\\n' +\r\n 'uniform float uStepW;\\n' +\r\n 'uniform float uStepH;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = vec4(0, 0, 0, 1);\\n' +\r\n 'for (float h = 0.0; h < 9.0; h+=1.0) {\\n' +\r\n 'for (float w = 0.0; w < 9.0; w+=1.0) {\\n' +\r\n 'vec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\\n' +\r\n 'color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 9.0 + w)];\\n' +\r\n '}\\n' +\r\n '}\\n' +\r\n 'float alpha = texture2D(uTexture, vTexCoord).a;\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n 'gl_FragColor.a = alpha;\\n' +\r\n '}',\r\n },\r\n\r\n /**\r\n * Constructor\r\n * @memberOf fabric.Image.filters.Convolute.prototype\r\n * @param {Object} [options] Options object\r\n * @param {Boolean} [options.opaque=false] Opaque value (true/false)\r\n * @param {Array} [options.matrix] Filter matrix\r\n */\r\n\r\n\r\n /**\r\n * Retrieves the cached shader.\r\n * @param {Object} options\r\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\r\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\r\n */\r\n retrieveShader: function(options) {\r\n var size = Math.sqrt(this.matrix.length);\r\n var cacheKey = this.type + '_' + size + '_' + (this.opaque ? 1 : 0);\r\n var shaderSource = this.fragmentSource[cacheKey];\r\n if (!options.programCache.hasOwnProperty(cacheKey)) {\r\n options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\r\n }\r\n return options.programCache[cacheKey];\r\n },\r\n\r\n /**\r\n * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\r\n *\r\n * @param {Object} options\r\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\r\n */\r\n applyTo2d: function(options) {\r\n var imageData = options.imageData,\r\n data = imageData.data,\r\n weights = this.matrix,\r\n side = Math.round(Math.sqrt(weights.length)),\r\n halfSide = Math.floor(side / 2),\r\n sw = imageData.width,\r\n sh = imageData.height,\r\n output = options.ctx.createImageData(sw, sh),\r\n dst = output.data,\r\n // go through the destination image pixels\r\n alphaFac = this.opaque ? 1 : 0,\r\n r, g, b, a, dstOff,\r\n scx, scy, srcOff, wt,\r\n x, y, cx, cy;\r\n\r\n for (y = 0; y < sh; y++) {\r\n for (x = 0; x < sw; x++) {\r\n dstOff = (y * sw + x) * 4;\r\n // calculate the weighed sum of the source image pixels that\r\n // fall under the convolution matrix\r\n r = 0; g = 0; b = 0; a = 0;\r\n\r\n for (cy = 0; cy < side; cy++) {\r\n for (cx = 0; cx < side; cx++) {\r\n scy = y + cy - halfSide;\r\n scx = x + cx - halfSide;\r\n\r\n // eslint-disable-next-line max-depth\r\n if (scy < 0 || scy >= sh || scx < 0 || scx >= sw) {\r\n continue;\r\n }\r\n\r\n srcOff = (scy * sw + scx) * 4;\r\n wt = weights[cy * side + cx];\r\n\r\n r += data[srcOff] * wt;\r\n g += data[srcOff + 1] * wt;\r\n b += data[srcOff + 2] * wt;\r\n // eslint-disable-next-line max-depth\r\n if (!alphaFac) {\r\n a += data[srcOff + 3] * wt;\r\n }\r\n }\r\n }\r\n dst[dstOff] = r;\r\n dst[dstOff + 1] = g;\r\n dst[dstOff + 2] = b;\r\n if (!alphaFac) {\r\n dst[dstOff + 3] = a;\r\n }\r\n else {\r\n dst[dstOff + 3] = data[dstOff + 3];\r\n }\r\n }\r\n }\r\n options.imageData = output;\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uMatrix: gl.getUniformLocation(program, 'uMatrix'),\r\n uOpaque: gl.getUniformLocation(program, 'uOpaque'),\r\n uHalfSize: gl.getUniformLocation(program, 'uHalfSize'),\r\n uSize: gl.getUniformLocation(program, 'uSize'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n gl.uniform1fv(uniformLocations.uMatrix, this.matrix);\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @return {Object} Object representation of an instance\r\n */\r\n toObject: function() {\r\n return extend(this.callSuper('toObject'), {\r\n opaque: this.opaque,\r\n matrix: this.matrix\r\n });\r\n }\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.Convolute} Instance of fabric.Image.filters.Convolute\r\n */\r\n fabric.Image.filters.Convolute.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Grayscale image filter class\r\n * @class fabric.Image.filters.Grayscale\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example\r\n * var filter = new fabric.Image.filters.Grayscale();\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n */\r\n filters.Grayscale = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Grayscale.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'Grayscale',\r\n\r\n fragmentSource: {\r\n average: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\r\n 'float average = (color.r + color.b + color.g) / 3.0;\\n' +\r\n 'gl_FragColor = vec4(average, average, average, color.a);\\n' +\r\n '}',\r\n lightness: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform int uMode;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 col = texture2D(uTexture, vTexCoord);\\n' +\r\n 'float average = (max(max(col.r, col.g),col.b) + min(min(col.r, col.g),col.b)) / 2.0;\\n' +\r\n 'gl_FragColor = vec4(average, average, average, col.a);\\n' +\r\n '}',\r\n luminosity: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform int uMode;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 col = texture2D(uTexture, vTexCoord);\\n' +\r\n 'float average = 0.21 * col.r + 0.72 * col.g + 0.07 * col.b;\\n' +\r\n 'gl_FragColor = vec4(average, average, average, col.a);\\n' +\r\n '}',\r\n },\r\n\r\n\r\n /**\r\n * Grayscale mode, between 'average', 'lightness', 'luminosity'\r\n * @param {String} type\r\n * @default\r\n */\r\n mode: 'average',\r\n\r\n mainParameter: 'mode',\r\n\r\n /**\r\n * Apply the Grayscale operation to a Uint8Array representing the pixels of an image.\r\n *\r\n * @param {Object} options\r\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\r\n */\r\n applyTo2d: function(options) {\r\n var imageData = options.imageData,\r\n data = imageData.data, i,\r\n len = data.length, value,\r\n mode = this.mode;\r\n for (i = 0; i < len; i += 4) {\r\n if (mode === 'average') {\r\n value = (data[i] + data[i + 1] + data[i + 2]) / 3;\r\n }\r\n else if (mode === 'lightness') {\r\n value = (Math.min(data[i], data[i + 1], data[i + 2]) +\r\n Math.max(data[i], data[i + 1], data[i + 2])) / 2;\r\n }\r\n else if (mode === 'luminosity') {\r\n value = 0.21 * data[i] + 0.72 * data[i + 1] + 0.07 * data[i + 2];\r\n }\r\n data[i] = value;\r\n data[i + 1] = value;\r\n data[i + 2] = value;\r\n }\r\n },\r\n\r\n /**\r\n * Retrieves the cached shader.\r\n * @param {Object} options\r\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\r\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\r\n */\r\n retrieveShader: function(options) {\r\n var cacheKey = this.type + '_' + this.mode;\r\n if (!options.programCache.hasOwnProperty(cacheKey)) {\r\n var shaderSource = this.fragmentSource[this.mode];\r\n options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\r\n }\r\n return options.programCache[cacheKey];\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uMode: gl.getUniformLocation(program, 'uMode'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n // default average mode.\r\n var mode = 1;\r\n gl.uniform1i(uniformLocations.uMode, mode);\r\n },\r\n\r\n /**\r\n * Grayscale filter isNeutralState implementation\r\n * The filter is never neutral\r\n * on the image\r\n **/\r\n isNeutralState: function() {\r\n return false;\r\n },\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.Grayscale} Instance of fabric.Image.filters.Grayscale\r\n */\r\n fabric.Image.filters.Grayscale.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Invert filter class\r\n * @class fabric.Image.filters.Invert\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example\r\n * var filter = new fabric.Image.filters.Invert();\r\n * object.filters.push(filter);\r\n * object.applyFilters(canvas.renderAll.bind(canvas));\r\n */\r\n filters.Invert = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Invert.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'Invert',\r\n\r\n fragmentSource: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform int uInvert;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\r\n 'if (uInvert == 1) {\\n' +\r\n 'gl_FragColor = vec4(1.0 - color.r,1.0 -color.g,1.0 -color.b,color.a);\\n' +\r\n '} else {\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}\\n' +\r\n '}',\r\n\r\n /**\r\n * Filter invert. if false, does nothing\r\n * @param {Boolean} invert\r\n * @default\r\n */\r\n invert: true,\r\n\r\n mainParameter: 'invert',\r\n\r\n /**\r\n * Apply the Invert operation to a Uint8Array representing the pixels of an image.\r\n *\r\n * @param {Object} options\r\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\r\n */\r\n applyTo2d: function(options) {\r\n var imageData = options.imageData,\r\n data = imageData.data, i,\r\n len = data.length;\r\n for (i = 0; i < len; i += 4) {\r\n data[i] = 255 - data[i];\r\n data[i + 1] = 255 - data[i + 1];\r\n data[i + 2] = 255 - data[i + 2];\r\n }\r\n },\r\n\r\n /**\r\n * Invert filter isNeutralState implementation\r\n * Used only in image applyFilters to discard filters that will not have an effect\r\n * on the image\r\n * @param {Object} options\r\n **/\r\n isNeutralState: function() {\r\n return !this.invert;\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uInvert: gl.getUniformLocation(program, 'uInvert'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n gl.uniform1i(uniformLocations.uInvert, this.invert);\r\n },\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.Invert} Instance of fabric.Image.filters.Invert\r\n */\r\n fabric.Image.filters.Invert.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n extend = fabric.util.object.extend,\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Noise filter class\r\n * @class fabric.Image.filters.Noise\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link fabric.Image.filters.Noise#initialize} for constructor definition\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example\r\n * var filter = new fabric.Image.filters.Noise({\r\n * noise: 700\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n * canvas.renderAll();\r\n */\r\n filters.Noise = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Noise.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'Noise',\r\n\r\n /**\r\n * Fragment source for the noise program\r\n */\r\n fragmentSource: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uStepH;\\n' +\r\n 'uniform float uNoise;\\n' +\r\n 'uniform float uSeed;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'float rand(vec2 co, float seed, float vScale) {\\n' +\r\n 'return fract(sin(dot(co.xy * vScale ,vec2(12.9898 , 78.233))) * 43758.5453 * (seed + 0.01) / 2.0);\\n' +\r\n '}\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\r\n 'color.rgb += (0.5 - rand(vTexCoord, uSeed, 0.1 / uStepH)) * uNoise;\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}',\r\n\r\n /**\r\n * Describe the property that is the filter parameter\r\n * @param {String} m\r\n * @default\r\n */\r\n mainParameter: 'noise',\r\n\r\n /**\r\n * Noise value, from\r\n * @param {Number} noise\r\n * @default\r\n */\r\n noise: 0,\r\n\r\n /**\r\n * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\r\n *\r\n * @param {Object} options\r\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\r\n */\r\n applyTo2d: function(options) {\r\n if (this.noise === 0) {\r\n return;\r\n }\r\n var imageData = options.imageData,\r\n data = imageData.data, i, len = data.length,\r\n noise = this.noise, rand;\r\n\r\n for (i = 0, len = data.length; i < len; i += 4) {\r\n\r\n rand = (0.5 - Math.random()) * noise;\r\n\r\n data[i] += rand;\r\n data[i + 1] += rand;\r\n data[i + 2] += rand;\r\n }\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uNoise: gl.getUniformLocation(program, 'uNoise'),\r\n uSeed: gl.getUniformLocation(program, 'uSeed'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n gl.uniform1f(uniformLocations.uNoise, this.noise / 255);\r\n gl.uniform1f(uniformLocations.uSeed, Math.random());\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @return {Object} Object representation of an instance\r\n */\r\n toObject: function() {\r\n return extend(this.callSuper('toObject'), {\r\n noise: this.noise\r\n });\r\n }\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {Function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.Noise} Instance of fabric.Image.filters.Noise\r\n */\r\n fabric.Image.filters.Noise.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Pixelate filter class\r\n * @class fabric.Image.filters.Pixelate\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link fabric.Image.filters.Pixelate#initialize} for constructor definition\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example\r\n * var filter = new fabric.Image.filters.Pixelate({\r\n * blocksize: 8\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n */\r\n filters.Pixelate = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Pixelate.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'Pixelate',\r\n\r\n blocksize: 4,\r\n\r\n mainParameter: 'blocksize',\r\n\r\n /**\r\n * Fragment source for the Pixelate program\r\n */\r\n fragmentSource: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uBlocksize;\\n' +\r\n 'uniform float uStepW;\\n' +\r\n 'uniform float uStepH;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'float blockW = uBlocksize * uStepW;\\n' +\r\n 'float blockH = uBlocksize * uStepW;\\n' +\r\n 'int posX = int(vTexCoord.x / blockW);\\n' +\r\n 'int posY = int(vTexCoord.y / blockH);\\n' +\r\n 'float fposX = float(posX);\\n' +\r\n 'float fposY = float(posY);\\n' +\r\n 'vec2 squareCoords = vec2(fposX * blockW, fposY * blockH);\\n' +\r\n 'vec4 color = texture2D(uTexture, squareCoords);\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}',\r\n\r\n /**\r\n * Apply the Pixelate operation to a Uint8ClampedArray representing the pixels of an image.\r\n *\r\n * @param {Object} options\r\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\r\n */\r\n applyTo2d: function(options) {\r\n var imageData = options.imageData,\r\n data = imageData.data,\r\n iLen = imageData.height,\r\n jLen = imageData.width,\r\n index, i, j, r, g, b, a,\r\n _i, _j, _iLen, _jLen;\r\n\r\n for (i = 0; i < iLen; i += this.blocksize) {\r\n for (j = 0; j < jLen; j += this.blocksize) {\r\n\r\n index = (i * 4) * jLen + (j * 4);\r\n\r\n r = data[index];\r\n g = data[index + 1];\r\n b = data[index + 2];\r\n a = data[index + 3];\r\n\r\n _iLen = Math.min(i + this.blocksize, iLen);\r\n _jLen = Math.min(j + this.blocksize, jLen);\r\n for (_i = i; _i < _iLen; _i++) {\r\n for (_j = j; _j < _jLen; _j++) {\r\n index = (_i * 4) * jLen + (_j * 4);\r\n data[index] = r;\r\n data[index + 1] = g;\r\n data[index + 2] = b;\r\n data[index + 3] = a;\r\n }\r\n }\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * Indicate when the filter is not gonna apply changes to the image\r\n **/\r\n isNeutralState: function() {\r\n return this.blocksize === 1;\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uBlocksize: gl.getUniformLocation(program, 'uBlocksize'),\r\n uStepW: gl.getUniformLocation(program, 'uStepW'),\r\n uStepH: gl.getUniformLocation(program, 'uStepH'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n gl.uniform1f(uniformLocations.uBlocksize, this.blocksize);\r\n },\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {Function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.Pixelate} Instance of fabric.Image.filters.Pixelate\r\n */\r\n fabric.Image.filters.Pixelate.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n extend = fabric.util.object.extend,\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Remove white filter class\r\n * @class fabric.Image.filters.RemoveColor\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link fabric.Image.filters.RemoveColor#initialize} for constructor definition\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example\r\n * var filter = new fabric.Image.filters.RemoveColor({\r\n * threshold: 0.2,\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n * canvas.renderAll();\r\n */\r\n filters.RemoveColor = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.RemoveColor.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'RemoveColor',\r\n\r\n /**\r\n * Color to remove, in any format understood by fabric.Color.\r\n * @param {String} type\r\n * @default\r\n */\r\n color: '#FFFFFF',\r\n\r\n /**\r\n * Fragment source for the brightness program\r\n */\r\n fragmentSource: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform vec4 uLow;\\n' +\r\n 'uniform vec4 uHigh;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'gl_FragColor = texture2D(uTexture, vTexCoord);\\n' +\r\n 'if(all(greaterThan(gl_FragColor.rgb,uLow.rgb)) && all(greaterThan(uHigh.rgb,gl_FragColor.rgb))) {\\n' +\r\n 'gl_FragColor.a = 0.0;\\n' +\r\n '}\\n' +\r\n '}',\r\n\r\n /**\r\n * distance to actual color, as value up or down from each r,g,b\r\n * between 0 and 1\r\n **/\r\n distance: 0.02,\r\n\r\n /**\r\n * For color to remove inside distance, use alpha channel for a smoother deletion\r\n * NOT IMPLEMENTED YET\r\n **/\r\n useAlpha: false,\r\n\r\n /**\r\n * Constructor\r\n * @memberOf fabric.Image.filters.RemoveWhite.prototype\r\n * @param {Object} [options] Options object\r\n * @param {Number} [options.color=#RRGGBB] Threshold value\r\n * @param {Number} [options.distance=10] Distance value\r\n */\r\n\r\n /**\r\n * Applies filter to canvas element\r\n * @param {Object} canvasEl Canvas element to apply filter to\r\n */\r\n applyTo2d: function(options) {\r\n var imageData = options.imageData,\r\n data = imageData.data, i,\r\n distance = this.distance * 255,\r\n r, g, b,\r\n source = new fabric.Color(this.color).getSource(),\r\n lowC = [\r\n source[0] - distance,\r\n source[1] - distance,\r\n source[2] - distance,\r\n ],\r\n highC = [\r\n source[0] + distance,\r\n source[1] + distance,\r\n source[2] + distance,\r\n ];\r\n\r\n\r\n for (i = 0; i < data.length; i += 4) {\r\n r = data[i];\r\n g = data[i + 1];\r\n b = data[i + 2];\r\n\r\n if (r > lowC[0] &&\r\n g > lowC[1] &&\r\n b > lowC[2] &&\r\n r < highC[0] &&\r\n g < highC[1] &&\r\n b < highC[2]) {\r\n data[i + 3] = 0;\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uLow: gl.getUniformLocation(program, 'uLow'),\r\n uHigh: gl.getUniformLocation(program, 'uHigh'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n var source = new fabric.Color(this.color).getSource(),\r\n distance = parseFloat(this.distance),\r\n lowC = [\r\n 0 + source[0] / 255 - distance,\r\n 0 + source[1] / 255 - distance,\r\n 0 + source[2] / 255 - distance,\r\n 1\r\n ],\r\n highC = [\r\n source[0] / 255 + distance,\r\n source[1] / 255 + distance,\r\n source[2] / 255 + distance,\r\n 1\r\n ];\r\n gl.uniform4fv(uniformLocations.uLow, lowC);\r\n gl.uniform4fv(uniformLocations.uHigh, highC);\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @return {Object} Object representation of an instance\r\n */\r\n toObject: function() {\r\n return extend(this.callSuper('toObject'), {\r\n color: this.color,\r\n distance: this.distance\r\n });\r\n }\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {Function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.RemoveColor} Instance of fabric.Image.filters.RemoveWhite\r\n */\r\n fabric.Image.filters.RemoveColor.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n var matrices = {\r\n Brownie: [\r\n 0.59970,0.34553,-0.27082,0,0.186,\r\n -0.03770,0.86095,0.15059,0,-0.1449,\r\n 0.24113,-0.07441,0.44972,0,-0.02965,\r\n 0,0,0,1,0\r\n ],\r\n Vintage: [\r\n 0.62793,0.32021,-0.03965,0,0.03784,\r\n 0.02578,0.64411,0.03259,0,0.02926,\r\n 0.04660,-0.08512,0.52416,0,0.02023,\r\n 0,0,0,1,0\r\n ],\r\n Kodachrome: [\r\n 1.12855,-0.39673,-0.03992,0,0.24991,\r\n -0.16404,1.08352,-0.05498,0,0.09698,\r\n -0.16786,-0.56034,1.60148,0,0.13972,\r\n 0,0,0,1,0\r\n ],\r\n Technicolor: [\r\n 1.91252,-0.85453,-0.09155,0,0.04624,\r\n -0.30878,1.76589,-0.10601,0,-0.27589,\r\n -0.23110,-0.75018,1.84759,0,0.12137,\r\n 0,0,0,1,0\r\n ],\r\n Polaroid: [\r\n 1.438,-0.062,-0.062,0,0,\r\n -0.122,1.378,-0.122,0,0,\r\n -0.016,-0.016,1.483,0,0,\r\n 0,0,0,1,0\r\n ],\r\n Sepia: [\r\n 0.393, 0.769, 0.189, 0, 0,\r\n 0.349, 0.686, 0.168, 0, 0,\r\n 0.272, 0.534, 0.131, 0, 0,\r\n 0, 0, 0, 1, 0\r\n ],\r\n BlackWhite: [\r\n 1.5, 1.5, 1.5, 0, -1,\r\n 1.5, 1.5, 1.5, 0, -1,\r\n 1.5, 1.5, 1.5, 0, -1,\r\n 0, 0, 0, 1, 0,\r\n ]\r\n };\r\n\r\n for (var key in matrices) {\r\n filters[key] = createClass(filters.ColorMatrix, /** @lends fabric.Image.filters.Sepia.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: key,\r\n\r\n /**\r\n * Colormatrix for the effect\r\n * array of 20 floats. Numbers in positions 4, 9, 14, 19 loose meaning\r\n * outside the -1, 1 range.\r\n * @param {Array} matrix array of 20 numbers.\r\n * @default\r\n */\r\n matrix: matrices[key],\r\n\r\n /**\r\n * Lock the matrix export for this kind of static, parameter less filters.\r\n */\r\n mainParameter: false,\r\n /**\r\n * Lock the colormatrix on the color part, skipping alpha\r\n */\r\n colorsOnly: true,\r\n\r\n });\r\n fabric.Image.filters[key].fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n }\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n 'use strict';\r\n\r\n var fabric = global.fabric,\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Color Blend filter class\r\n * @class fabric.Image.filter.BlendColor\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @example\r\n * var filter = new fabric.Image.filters.BlendColor({\r\n * color: '#000',\r\n * mode: 'multiply'\r\n * });\r\n *\r\n * var filter = new fabric.Image.filters.BlendImage({\r\n * image: fabricImageObject,\r\n * mode: 'multiply',\r\n * alpha: 0.5\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n * canvas.renderAll();\r\n */\r\n\r\n filters.BlendColor = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Blend.prototype */ {\r\n type: 'BlendColor',\r\n\r\n /**\r\n * Color to make the blend operation with. default to a reddish color since black or white\r\n * gives always strong result.\r\n * @type String\r\n * @default\r\n **/\r\n color: '#F95C63',\r\n\r\n /**\r\n * Blend mode for the filter: one of multiply, add, diff, screen, subtract,\r\n * darken, lighten, overlay, exclusion, tint.\r\n * @type String\r\n * @default\r\n **/\r\n mode: 'multiply',\r\n\r\n /**\r\n * alpha value. represent the strength of the blend color operation.\r\n * @type Number\r\n * @default\r\n **/\r\n alpha: 1,\r\n\r\n /**\r\n * Fragment source for the Multiply program\r\n */\r\n fragmentSource: {\r\n multiply: 'gl_FragColor.rgb *= uColor.rgb;\\n',\r\n screen: 'gl_FragColor.rgb = 1.0 - (1.0 - gl_FragColor.rgb) * (1.0 - uColor.rgb);\\n',\r\n add: 'gl_FragColor.rgb += uColor.rgb;\\n',\r\n diff: 'gl_FragColor.rgb = abs(gl_FragColor.rgb - uColor.rgb);\\n',\r\n subtract: 'gl_FragColor.rgb -= uColor.rgb;\\n',\r\n lighten: 'gl_FragColor.rgb = max(gl_FragColor.rgb, uColor.rgb);\\n',\r\n darken: 'gl_FragColor.rgb = min(gl_FragColor.rgb, uColor.rgb);\\n',\r\n exclusion: 'gl_FragColor.rgb += uColor.rgb - 2.0 * (uColor.rgb * gl_FragColor.rgb);\\n',\r\n overlay: 'if (uColor.r < 0.5) {\\n' +\r\n 'gl_FragColor.r *= 2.0 * uColor.r;\\n' +\r\n '} else {\\n' +\r\n 'gl_FragColor.r = 1.0 - 2.0 * (1.0 - gl_FragColor.r) * (1.0 - uColor.r);\\n' +\r\n '}\\n' +\r\n 'if (uColor.g < 0.5) {\\n' +\r\n 'gl_FragColor.g *= 2.0 * uColor.g;\\n' +\r\n '} else {\\n' +\r\n 'gl_FragColor.g = 1.0 - 2.0 * (1.0 - gl_FragColor.g) * (1.0 - uColor.g);\\n' +\r\n '}\\n' +\r\n 'if (uColor.b < 0.5) {\\n' +\r\n 'gl_FragColor.b *= 2.0 * uColor.b;\\n' +\r\n '} else {\\n' +\r\n 'gl_FragColor.b = 1.0 - 2.0 * (1.0 - gl_FragColor.b) * (1.0 - uColor.b);\\n' +\r\n '}\\n',\r\n tint: 'gl_FragColor.rgb *= (1.0 - uColor.a);\\n' +\r\n 'gl_FragColor.rgb += uColor.rgb;\\n',\r\n },\r\n\r\n /**\r\n * build the fragment source for the filters, joining the common part with\r\n * the specific one.\r\n * @param {String} mode the mode of the filter, a key of this.fragmentSource\r\n * @return {String} the source to be compiled\r\n * @private\r\n */\r\n buildSource: function(mode) {\r\n return 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform vec4 uColor;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n 'if (color.a > 0.0) {\\n' +\r\n this.fragmentSource[mode] +\r\n '}\\n' +\r\n '}';\r\n },\r\n\r\n /**\r\n * Retrieves the cached shader.\r\n * @param {Object} options\r\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\r\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\r\n */\r\n retrieveShader: function(options) {\r\n var cacheKey = this.type + '_' + this.mode, shaderSource;\r\n if (!options.programCache.hasOwnProperty(cacheKey)) {\r\n shaderSource = this.buildSource(this.mode);\r\n options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\r\n }\r\n return options.programCache[cacheKey];\r\n },\r\n\r\n /**\r\n * Apply the Blend operation to a Uint8ClampedArray representing the pixels of an image.\r\n *\r\n * @param {Object} options\r\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\r\n */\r\n applyTo2d: function(options) {\r\n var imageData = options.imageData,\r\n data = imageData.data, iLen = data.length,\r\n tr, tg, tb,\r\n r, g, b,\r\n source, alpha1 = 1 - this.alpha;\r\n\r\n source = new fabric.Color(this.color).getSource();\r\n tr = source[0] * this.alpha;\r\n tg = source[1] * this.alpha;\r\n tb = source[2] * this.alpha;\r\n\r\n for (var i = 0; i < iLen; i += 4) {\r\n\r\n r = data[i];\r\n g = data[i + 1];\r\n b = data[i + 2];\r\n\r\n switch (this.mode) {\r\n case 'multiply':\r\n data[i] = r * tr / 255;\r\n data[i + 1] = g * tg / 255;\r\n data[i + 2] = b * tb / 255;\r\n break;\r\n case 'screen':\r\n data[i] = 255 - (255 - r) * (255 - tr) / 255;\r\n data[i + 1] = 255 - (255 - g) * (255 - tg) / 255;\r\n data[i + 2] = 255 - (255 - b) * (255 - tb) / 255;\r\n break;\r\n case 'add':\r\n data[i] = r + tr;\r\n data[i + 1] = g + tg;\r\n data[i + 2] = b + tb;\r\n break;\r\n case 'diff':\r\n case 'difference':\r\n data[i] = Math.abs(r - tr);\r\n data[i + 1] = Math.abs(g - tg);\r\n data[i + 2] = Math.abs(b - tb);\r\n break;\r\n case 'subtract':\r\n data[i] = r - tr;\r\n data[i + 1] = g - tg;\r\n data[i + 2] = b - tb;\r\n break;\r\n case 'darken':\r\n data[i] = Math.min(r, tr);\r\n data[i + 1] = Math.min(g, tg);\r\n data[i + 2] = Math.min(b, tb);\r\n break;\r\n case 'lighten':\r\n data[i] = Math.max(r, tr);\r\n data[i + 1] = Math.max(g, tg);\r\n data[i + 2] = Math.max(b, tb);\r\n break;\r\n case 'overlay':\r\n data[i] = tr < 128 ? (2 * r * tr / 255) : (255 - 2 * (255 - r) * (255 - tr) / 255);\r\n data[i + 1] = tg < 128 ? (2 * g * tg / 255) : (255 - 2 * (255 - g) * (255 - tg) / 255);\r\n data[i + 2] = tb < 128 ? (2 * b * tb / 255) : (255 - 2 * (255 - b) * (255 - tb) / 255);\r\n break;\r\n case 'exclusion':\r\n data[i] = tr + r - ((2 * tr * r) / 255);\r\n data[i + 1] = tg + g - ((2 * tg * g) / 255);\r\n data[i + 2] = tb + b - ((2 * tb * b) / 255);\r\n break;\r\n case 'tint':\r\n data[i] = tr + r * alpha1;\r\n data[i + 1] = tg + g * alpha1;\r\n data[i + 2] = tb + b * alpha1;\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uColor: gl.getUniformLocation(program, 'uColor'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n var source = new fabric.Color(this.color).getSource();\r\n source[0] = this.alpha * source[0] / 255;\r\n source[1] = this.alpha * source[1] / 255;\r\n source[2] = this.alpha * source[2] / 255;\r\n source[3] = this.alpha;\r\n gl.uniform4fv(uniformLocations.uColor, source);\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @return {Object} Object representation of an instance\r\n */\r\n toObject: function() {\r\n return {\r\n type: this.type,\r\n color: this.color,\r\n mode: this.mode,\r\n alpha: this.alpha\r\n };\r\n }\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.BlendColor} Instance of fabric.Image.filters.BlendColor\r\n */\r\n fabric.Image.filters.BlendColor.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n 'use strict';\r\n\r\n var fabric = global.fabric,\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Image Blend filter class\r\n * @class fabric.Image.filter.BlendImage\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @example\r\n * var filter = new fabric.Image.filters.BlendColor({\r\n * color: '#000',\r\n * mode: 'multiply'\r\n * });\r\n *\r\n * var filter = new fabric.Image.filters.BlendImage({\r\n * image: fabricImageObject,\r\n * mode: 'multiply',\r\n * alpha: 0.5\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n * canvas.renderAll();\r\n */\r\n\r\n filters.BlendImage = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.BlendImage.prototype */ {\r\n type: 'BlendImage',\r\n\r\n /**\r\n * Color to make the blend operation with. default to a reddish color since black or white\r\n * gives always strong result.\r\n **/\r\n image: null,\r\n\r\n /**\r\n * Blend mode for the filter (one of \"multiply\", \"mask\")\r\n * @type String\r\n * @default\r\n **/\r\n mode: 'multiply',\r\n\r\n /**\r\n * alpha value. represent the strength of the blend image operation.\r\n * not implemented.\r\n **/\r\n alpha: 1,\r\n\r\n vertexSource: 'attribute vec2 aPosition;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'varying vec2 vTexCoord2;\\n' +\r\n 'uniform mat3 uTransformMatrix;\\n' +\r\n 'void main() {\\n' +\r\n 'vTexCoord = aPosition;\\n' +\r\n 'vTexCoord2 = (uTransformMatrix * vec3(aPosition, 1.0)).xy;\\n' +\r\n 'gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\\n' +\r\n '}',\r\n\r\n /**\r\n * Fragment source for the Multiply program\r\n */\r\n fragmentSource: {\r\n multiply: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform sampler2D uImage;\\n' +\r\n 'uniform vec4 uColor;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'varying vec2 vTexCoord2;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\r\n 'vec4 color2 = texture2D(uImage, vTexCoord2);\\n' +\r\n 'color.rgba *= color2.rgba;\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}',\r\n mask: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform sampler2D uImage;\\n' +\r\n 'uniform vec4 uColor;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'varying vec2 vTexCoord2;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\r\n 'vec4 color2 = texture2D(uImage, vTexCoord2);\\n' +\r\n 'color.a = color2.a;\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}',\r\n },\r\n\r\n /**\r\n * Retrieves the cached shader.\r\n * @param {Object} options\r\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\r\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\r\n */\r\n retrieveShader: function(options) {\r\n var cacheKey = this.type + '_' + this.mode;\r\n var shaderSource = this.fragmentSource[this.mode];\r\n if (!options.programCache.hasOwnProperty(cacheKey)) {\r\n options.programCache[cacheKey] = this.createProgram(options.context, shaderSource);\r\n }\r\n return options.programCache[cacheKey];\r\n },\r\n\r\n applyToWebGL: function(options) {\r\n // load texture to blend.\r\n var gl = options.context,\r\n texture = this.createTexture(options.filterBackend, this.image);\r\n this.bindAdditionalTexture(gl, texture, gl.TEXTURE1);\r\n this.callSuper('applyToWebGL', options);\r\n this.unbindAdditionalTexture(gl, gl.TEXTURE1);\r\n },\r\n\r\n createTexture: function(backend, image) {\r\n return backend.getCachedTexture(image.cacheKey, image._element);\r\n },\r\n\r\n /**\r\n * Calculate a transformMatrix to adapt the image to blend over\r\n * @param {Object} options\r\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\r\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\r\n */\r\n calculateMatrix: function() {\r\n var image = this.image,\r\n width = image._element.width,\r\n height = image._element.height;\r\n return [\r\n 1 / image.scaleX, 0, 0,\r\n 0, 1 / image.scaleY, 0,\r\n -image.left / width, -image.top / height, 1\r\n ];\r\n },\r\n\r\n /**\r\n * Apply the Blend operation to a Uint8ClampedArray representing the pixels of an image.\r\n *\r\n * @param {Object} options\r\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\r\n */\r\n applyTo2d: function(options) {\r\n var imageData = options.imageData,\r\n resources = options.filterBackend.resources,\r\n data = imageData.data, iLen = data.length,\r\n width = imageData.width,\r\n height = imageData.height,\r\n tr, tg, tb, ta,\r\n r, g, b, a,\r\n canvas1, context, image = this.image, blendData;\r\n\r\n if (!resources.blendImage) {\r\n resources.blendImage = fabric.util.createCanvasElement();\r\n }\r\n canvas1 = resources.blendImage;\r\n context = canvas1.getContext('2d', { willReadFrequently: true });\r\n if (canvas1.width !== width || canvas1.height !== height) {\r\n canvas1.width = width;\r\n canvas1.height = height;\r\n }\r\n else {\r\n context.clearRect(0, 0, width, height);\r\n }\r\n context.setTransform(image.scaleX, 0, 0, image.scaleY, image.left, image.top);\r\n context.drawImage(image._element, 0, 0, width, height);\r\n blendData = context.getImageData(0, 0, width, height).data;\r\n for (var i = 0; i < iLen; i += 4) {\r\n\r\n r = data[i];\r\n g = data[i + 1];\r\n b = data[i + 2];\r\n a = data[i + 3];\r\n\r\n tr = blendData[i];\r\n tg = blendData[i + 1];\r\n tb = blendData[i + 2];\r\n ta = blendData[i + 3];\r\n\r\n switch (this.mode) {\r\n case 'multiply':\r\n data[i] = r * tr / 255;\r\n data[i + 1] = g * tg / 255;\r\n data[i + 2] = b * tb / 255;\r\n data[i + 3] = a * ta / 255;\r\n break;\r\n case 'mask':\r\n data[i + 3] = ta;\r\n break;\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uTransformMatrix: gl.getUniformLocation(program, 'uTransformMatrix'),\r\n uImage: gl.getUniformLocation(program, 'uImage'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n var matrix = this.calculateMatrix();\r\n gl.uniform1i(uniformLocations.uImage, 1); // texture unit 1.\r\n gl.uniformMatrix3fv(uniformLocations.uTransformMatrix, false, matrix);\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @return {Object} Object representation of an instance\r\n */\r\n toObject: function() {\r\n return {\r\n type: this.type,\r\n image: this.image && this.image.toObject(),\r\n mode: this.mode,\r\n alpha: this.alpha\r\n };\r\n }\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} callback to be invoked after filter creation\r\n * @return {fabric.Image.filters.BlendImage} Instance of fabric.Image.filters.BlendImage\r\n */\r\n fabric.Image.filters.BlendImage.fromObject = function(object, callback) {\r\n fabric.Image.fromObject(object.image, function(image) {\r\n var options = fabric.util.object.clone(object);\r\n options.image = image;\r\n callback(new fabric.Image.filters.BlendImage(options));\r\n });\r\n };\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }), pow = Math.pow, floor = Math.floor,\r\n sqrt = Math.sqrt, abs = Math.abs, round = Math.round, sin = Math.sin,\r\n ceil = Math.ceil,\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Resize image filter class\r\n * @class fabric.Image.filters.Resize\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example\r\n * var filter = new fabric.Image.filters.Resize();\r\n * object.filters.push(filter);\r\n * object.applyFilters(canvas.renderAll.bind(canvas));\r\n */\r\n filters.Resize = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Resize.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'Resize',\r\n\r\n /**\r\n * Resize type\r\n * for webgl resizeType is just lanczos, for canvas2d can be:\r\n * bilinear, hermite, sliceHack, lanczos.\r\n * @param {String} resizeType\r\n * @default\r\n */\r\n resizeType: 'hermite',\r\n\r\n /**\r\n * Scale factor for resizing, x axis\r\n * @param {Number} scaleX\r\n * @default\r\n */\r\n scaleX: 1,\r\n\r\n /**\r\n * Scale factor for resizing, y axis\r\n * @param {Number} scaleY\r\n * @default\r\n */\r\n scaleY: 1,\r\n\r\n /**\r\n * LanczosLobes parameter for lanczos filter, valid for resizeType lanczos\r\n * @param {Number} lanczosLobes\r\n * @default\r\n */\r\n lanczosLobes: 3,\r\n\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uDelta: gl.getUniformLocation(program, 'uDelta'),\r\n uTaps: gl.getUniformLocation(program, 'uTaps'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n gl.uniform2fv(uniformLocations.uDelta, this.horizontal ? [1 / this.width, 0] : [0, 1 / this.height]);\r\n gl.uniform1fv(uniformLocations.uTaps, this.taps);\r\n },\r\n\r\n /**\r\n * Retrieves the cached shader.\r\n * @param {Object} options\r\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\r\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\r\n */\r\n retrieveShader: function(options) {\r\n var filterWindow = this.getFilterWindow(), cacheKey = this.type + '_' + filterWindow;\r\n if (!options.programCache.hasOwnProperty(cacheKey)) {\r\n var fragmentShader = this.generateShader(filterWindow);\r\n options.programCache[cacheKey] = this.createProgram(options.context, fragmentShader);\r\n }\r\n return options.programCache[cacheKey];\r\n },\r\n\r\n getFilterWindow: function() {\r\n var scale = this.tempScale;\r\n return Math.ceil(this.lanczosLobes / scale);\r\n },\r\n\r\n getTaps: function() {\r\n var lobeFunction = this.lanczosCreate(this.lanczosLobes), scale = this.tempScale,\r\n filterWindow = this.getFilterWindow(), taps = new Array(filterWindow);\r\n for (var i = 1; i <= filterWindow; i++) {\r\n taps[i - 1] = lobeFunction(i * scale);\r\n }\r\n return taps;\r\n },\r\n\r\n /**\r\n * Generate vertex and shader sources from the necessary steps numbers\r\n * @param {Number} filterWindow\r\n */\r\n generateShader: function(filterWindow) {\r\n var offsets = new Array(filterWindow),\r\n fragmentShader = this.fragmentSourceTOP, filterWindow;\r\n\r\n for (var i = 1; i <= filterWindow; i++) {\r\n offsets[i - 1] = i + '.0 * uDelta';\r\n }\r\n\r\n fragmentShader += 'uniform float uTaps[' + filterWindow + '];\\n';\r\n fragmentShader += 'void main() {\\n';\r\n fragmentShader += ' vec4 color = texture2D(uTexture, vTexCoord);\\n';\r\n fragmentShader += ' float sum = 1.0;\\n';\r\n\r\n offsets.forEach(function(offset, i) {\r\n fragmentShader += ' color += texture2D(uTexture, vTexCoord + ' + offset + ') * uTaps[' + i + '];\\n';\r\n fragmentShader += ' color += texture2D(uTexture, vTexCoord - ' + offset + ') * uTaps[' + i + '];\\n';\r\n fragmentShader += ' sum += 2.0 * uTaps[' + i + '];\\n';\r\n });\r\n fragmentShader += ' gl_FragColor = color / sum;\\n';\r\n fragmentShader += '}';\r\n return fragmentShader;\r\n },\r\n\r\n fragmentSourceTOP: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform vec2 uDelta;\\n' +\r\n 'varying vec2 vTexCoord;\\n',\r\n\r\n /**\r\n * Apply the resize filter to the image\r\n * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\r\n *\r\n * @param {Object} options\r\n * @param {Number} options.passes The number of filters remaining to be executed\r\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\r\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\r\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\r\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\r\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\r\n */\r\n applyTo: function(options) {\r\n if (options.webgl) {\r\n options.passes++;\r\n this.width = options.sourceWidth;\r\n this.horizontal = true;\r\n this.dW = Math.round(this.width * this.scaleX);\r\n this.dH = options.sourceHeight;\r\n this.tempScale = this.dW / this.width;\r\n this.taps = this.getTaps();\r\n options.destinationWidth = this.dW;\r\n this._setupFrameBuffer(options);\r\n this.applyToWebGL(options);\r\n this._swapTextures(options);\r\n options.sourceWidth = options.destinationWidth;\r\n\r\n this.height = options.sourceHeight;\r\n this.horizontal = false;\r\n this.dH = Math.round(this.height * this.scaleY);\r\n this.tempScale = this.dH / this.height;\r\n this.taps = this.getTaps();\r\n options.destinationHeight = this.dH;\r\n this._setupFrameBuffer(options);\r\n this.applyToWebGL(options);\r\n this._swapTextures(options);\r\n options.sourceHeight = options.destinationHeight;\r\n }\r\n else {\r\n this.applyTo2d(options);\r\n }\r\n },\r\n\r\n isNeutralState: function() {\r\n return this.scaleX === 1 && this.scaleY === 1;\r\n },\r\n\r\n lanczosCreate: function(lobes) {\r\n return function(x) {\r\n if (x >= lobes || x <= -lobes) {\r\n return 0.0;\r\n }\r\n if (x < 1.19209290E-07 && x > -1.19209290E-07) {\r\n return 1.0;\r\n }\r\n x *= Math.PI;\r\n var xx = x / lobes;\r\n return (sin(x) / x) * sin(xx) / xx;\r\n };\r\n },\r\n\r\n /**\r\n * Applies filter to canvas element\r\n * @memberOf fabric.Image.filters.Resize.prototype\r\n * @param {Object} canvasEl Canvas element to apply filter to\r\n * @param {Number} scaleX\r\n * @param {Number} scaleY\r\n */\r\n applyTo2d: function(options) {\r\n var imageData = options.imageData,\r\n scaleX = this.scaleX,\r\n scaleY = this.scaleY;\r\n\r\n this.rcpScaleX = 1 / scaleX;\r\n this.rcpScaleY = 1 / scaleY;\r\n\r\n var oW = imageData.width, oH = imageData.height,\r\n dW = round(oW * scaleX), dH = round(oH * scaleY),\r\n newData;\r\n\r\n if (this.resizeType === 'sliceHack') {\r\n newData = this.sliceByTwo(options, oW, oH, dW, dH);\r\n }\r\n else if (this.resizeType === 'hermite') {\r\n newData = this.hermiteFastResize(options, oW, oH, dW, dH);\r\n }\r\n else if (this.resizeType === 'bilinear') {\r\n newData = this.bilinearFiltering(options, oW, oH, dW, dH);\r\n }\r\n else if (this.resizeType === 'lanczos') {\r\n newData = this.lanczosResize(options, oW, oH, dW, dH);\r\n }\r\n options.imageData = newData;\r\n },\r\n\r\n /**\r\n * Filter sliceByTwo\r\n * @param {Object} canvasEl Canvas element to apply filter to\r\n * @param {Number} oW Original Width\r\n * @param {Number} oH Original Height\r\n * @param {Number} dW Destination Width\r\n * @param {Number} dH Destination Height\r\n * @returns {ImageData}\r\n */\r\n sliceByTwo: function(options, oW, oH, dW, dH) {\r\n var imageData = options.imageData,\r\n mult = 0.5, doneW = false, doneH = false, stepW = oW * mult,\r\n stepH = oH * mult, resources = fabric.filterBackend.resources,\r\n tmpCanvas, ctx, sX = 0, sY = 0, dX = oW, dY = 0;\r\n if (!resources.sliceByTwo) {\r\n resources.sliceByTwo = document.createElement('canvas');\r\n }\r\n tmpCanvas = resources.sliceByTwo;\r\n if (tmpCanvas.width < oW * 1.5 || tmpCanvas.height < oH) {\r\n tmpCanvas.width = oW * 1.5;\r\n tmpCanvas.height = oH;\r\n }\r\n ctx = tmpCanvas.getContext('2d', { willReadFrequently: true });\r\n ctx.clearRect(0, 0, oW * 1.5, oH);\r\n ctx.putImageData(imageData, 0, 0);\r\n\r\n dW = floor(dW);\r\n dH = floor(dH);\r\n\r\n while (!doneW || !doneH) {\r\n oW = stepW;\r\n oH = stepH;\r\n if (dW < floor(stepW * mult)) {\r\n stepW = floor(stepW * mult);\r\n }\r\n else {\r\n stepW = dW;\r\n doneW = true;\r\n }\r\n if (dH < floor(stepH * mult)) {\r\n stepH = floor(stepH * mult);\r\n }\r\n else {\r\n stepH = dH;\r\n doneH = true;\r\n }\r\n ctx.drawImage(tmpCanvas, sX, sY, oW, oH, dX, dY, stepW, stepH);\r\n sX = dX;\r\n sY = dY;\r\n dY += stepH;\r\n }\r\n return ctx.getImageData(sX, sY, dW, dH);\r\n },\r\n\r\n /**\r\n * Filter lanczosResize\r\n * @param {Object} canvasEl Canvas element to apply filter to\r\n * @param {Number} oW Original Width\r\n * @param {Number} oH Original Height\r\n * @param {Number} dW Destination Width\r\n * @param {Number} dH Destination Height\r\n * @returns {ImageData}\r\n */\r\n lanczosResize: function(options, oW, oH, dW, dH) {\r\n\r\n function process(u) {\r\n var v, i, weight, idx, a, red, green,\r\n blue, alpha, fX, fY;\r\n center.x = (u + 0.5) * ratioX;\r\n icenter.x = floor(center.x);\r\n for (v = 0; v < dH; v++) {\r\n center.y = (v + 0.5) * ratioY;\r\n icenter.y = floor(center.y);\r\n a = 0; red = 0; green = 0; blue = 0; alpha = 0;\r\n for (i = icenter.x - range2X; i <= icenter.x + range2X; i++) {\r\n if (i < 0 || i >= oW) {\r\n continue;\r\n }\r\n fX = floor(1000 * abs(i - center.x));\r\n if (!cacheLanc[fX]) {\r\n cacheLanc[fX] = { };\r\n }\r\n for (var j = icenter.y - range2Y; j <= icenter.y + range2Y; j++) {\r\n if (j < 0 || j >= oH) {\r\n continue;\r\n }\r\n fY = floor(1000 * abs(j - center.y));\r\n if (!cacheLanc[fX][fY]) {\r\n cacheLanc[fX][fY] = lanczos(sqrt(pow(fX * rcpRatioX, 2) + pow(fY * rcpRatioY, 2)) / 1000);\r\n }\r\n weight = cacheLanc[fX][fY];\r\n if (weight > 0) {\r\n idx = (j * oW + i) * 4;\r\n a += weight;\r\n red += weight * srcData[idx];\r\n green += weight * srcData[idx + 1];\r\n blue += weight * srcData[idx + 2];\r\n alpha += weight * srcData[idx + 3];\r\n }\r\n }\r\n }\r\n idx = (v * dW + u) * 4;\r\n destData[idx] = red / a;\r\n destData[idx + 1] = green / a;\r\n destData[idx + 2] = blue / a;\r\n destData[idx + 3] = alpha / a;\r\n }\r\n\r\n if (++u < dW) {\r\n return process(u);\r\n }\r\n else {\r\n return destImg;\r\n }\r\n }\r\n\r\n var srcData = options.imageData.data,\r\n destImg = options.ctx.createImageData(dW, dH),\r\n destData = destImg.data,\r\n lanczos = this.lanczosCreate(this.lanczosLobes),\r\n ratioX = this.rcpScaleX, ratioY = this.rcpScaleY,\r\n rcpRatioX = 2 / this.rcpScaleX, rcpRatioY = 2 / this.rcpScaleY,\r\n range2X = ceil(ratioX * this.lanczosLobes / 2),\r\n range2Y = ceil(ratioY * this.lanczosLobes / 2),\r\n cacheLanc = { }, center = { }, icenter = { };\r\n\r\n return process(0);\r\n },\r\n\r\n /**\r\n * bilinearFiltering\r\n * @param {Object} canvasEl Canvas element to apply filter to\r\n * @param {Number} oW Original Width\r\n * @param {Number} oH Original Height\r\n * @param {Number} dW Destination Width\r\n * @param {Number} dH Destination Height\r\n * @returns {ImageData}\r\n */\r\n bilinearFiltering: function(options, oW, oH, dW, dH) {\r\n var a, b, c, d, x, y, i, j, xDiff, yDiff, chnl,\r\n color, offset = 0, origPix, ratioX = this.rcpScaleX,\r\n ratioY = this.rcpScaleY,\r\n w4 = 4 * (oW - 1), img = options.imageData,\r\n pixels = img.data, destImage = options.ctx.createImageData(dW, dH),\r\n destPixels = destImage.data;\r\n for (i = 0; i < dH; i++) {\r\n for (j = 0; j < dW; j++) {\r\n x = floor(ratioX * j);\r\n y = floor(ratioY * i);\r\n xDiff = ratioX * j - x;\r\n yDiff = ratioY * i - y;\r\n origPix = 4 * (y * oW + x);\r\n\r\n for (chnl = 0; chnl < 4; chnl++) {\r\n a = pixels[origPix + chnl];\r\n b = pixels[origPix + 4 + chnl];\r\n c = pixels[origPix + w4 + chnl];\r\n d = pixels[origPix + w4 + 4 + chnl];\r\n color = a * (1 - xDiff) * (1 - yDiff) + b * xDiff * (1 - yDiff) +\r\n c * yDiff * (1 - xDiff) + d * xDiff * yDiff;\r\n destPixels[offset++] = color;\r\n }\r\n }\r\n }\r\n return destImage;\r\n },\r\n\r\n /**\r\n * hermiteFastResize\r\n * @param {Object} canvasEl Canvas element to apply filter to\r\n * @param {Number} oW Original Width\r\n * @param {Number} oH Original Height\r\n * @param {Number} dW Destination Width\r\n * @param {Number} dH Destination Height\r\n * @returns {ImageData}\r\n */\r\n hermiteFastResize: function(options, oW, oH, dW, dH) {\r\n var ratioW = this.rcpScaleX, ratioH = this.rcpScaleY,\r\n ratioWHalf = ceil(ratioW / 2),\r\n ratioHHalf = ceil(ratioH / 2),\r\n img = options.imageData, data = img.data,\r\n img2 = options.ctx.createImageData(dW, dH), data2 = img2.data;\r\n for (var j = 0; j < dH; j++) {\r\n for (var i = 0; i < dW; i++) {\r\n var x2 = (i + j * dW) * 4, weight = 0, weights = 0, weightsAlpha = 0,\r\n gxR = 0, gxG = 0, gxB = 0, gxA = 0, centerY = (j + 0.5) * ratioH;\r\n for (var yy = floor(j * ratioH); yy < (j + 1) * ratioH; yy++) {\r\n var dy = abs(centerY - (yy + 0.5)) / ratioHHalf,\r\n centerX = (i + 0.5) * ratioW, w0 = dy * dy;\r\n for (var xx = floor(i * ratioW); xx < (i + 1) * ratioW; xx++) {\r\n var dx = abs(centerX - (xx + 0.5)) / ratioWHalf,\r\n w = sqrt(w0 + dx * dx);\r\n /* eslint-disable max-depth */\r\n if (w > 1 && w < -1) {\r\n continue;\r\n }\r\n //hermite filter\r\n weight = 2 * w * w * w - 3 * w * w + 1;\r\n if (weight > 0) {\r\n dx = 4 * (xx + yy * oW);\r\n //alpha\r\n gxA += weight * data[dx + 3];\r\n weightsAlpha += weight;\r\n //colors\r\n if (data[dx + 3] < 255) {\r\n weight = weight * data[dx + 3] / 250;\r\n }\r\n gxR += weight * data[dx];\r\n gxG += weight * data[dx + 1];\r\n gxB += weight * data[dx + 2];\r\n weights += weight;\r\n }\r\n /* eslint-enable max-depth */\r\n }\r\n }\r\n data2[x2] = gxR / weights;\r\n data2[x2 + 1] = gxG / weights;\r\n data2[x2 + 2] = gxB / weights;\r\n data2[x2 + 3] = gxA / weightsAlpha;\r\n }\r\n }\r\n return img2;\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @return {Object} Object representation of an instance\r\n */\r\n toObject: function() {\r\n return {\r\n type: this.type,\r\n scaleX: this.scaleX,\r\n scaleY: this.scaleY,\r\n resizeType: this.resizeType,\r\n lanczosLobes: this.lanczosLobes\r\n };\r\n }\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {Function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.Resize} Instance of fabric.Image.filters.Resize\r\n */\r\n fabric.Image.filters.Resize.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Contrast filter class\r\n * @class fabric.Image.filters.Contrast\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link fabric.Image.filters.Contrast#initialize} for constructor definition\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example\r\n * var filter = new fabric.Image.filters.Contrast({\r\n * contrast: 0.25\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n */\r\n filters.Contrast = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Contrast.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'Contrast',\r\n\r\n fragmentSource: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uContrast;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\r\n 'float contrastF = 1.015 * (uContrast + 1.0) / (1.0 * (1.015 - uContrast));\\n' +\r\n 'color.rgb = contrastF * (color.rgb - 0.5) + 0.5;\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}',\r\n\r\n /**\r\n * contrast value, range from -1 to 1.\r\n * @param {Number} contrast\r\n * @default 0\r\n */\r\n contrast: 0,\r\n\r\n mainParameter: 'contrast',\r\n\r\n /**\r\n * Constructor\r\n * @memberOf fabric.Image.filters.Contrast.prototype\r\n * @param {Object} [options] Options object\r\n * @param {Number} [options.contrast=0] Value to contrast the image up (-1...1)\r\n */\r\n\r\n /**\r\n * Apply the Contrast operation to a Uint8Array representing the pixels of an image.\r\n *\r\n * @param {Object} options\r\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\r\n */\r\n applyTo2d: function(options) {\r\n if (this.contrast === 0) {\r\n return;\r\n }\r\n var imageData = options.imageData, i, len,\r\n data = imageData.data, len = data.length,\r\n contrast = Math.floor(this.contrast * 255),\r\n contrastF = 259 * (contrast + 255) / (255 * (259 - contrast));\r\n\r\n for (i = 0; i < len; i += 4) {\r\n data[i] = contrastF * (data[i] - 128) + 128;\r\n data[i + 1] = contrastF * (data[i + 1] - 128) + 128;\r\n data[i + 2] = contrastF * (data[i + 2] - 128) + 128;\r\n }\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uContrast: gl.getUniformLocation(program, 'uContrast'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n gl.uniform1f(uniformLocations.uContrast, this.contrast);\r\n },\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.Contrast} Instance of fabric.Image.filters.Contrast\r\n */\r\n fabric.Image.filters.Contrast.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Saturate filter class\r\n * @class fabric.Image.filters.Saturation\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link fabric.Image.filters.Saturation#initialize} for constructor definition\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example\r\n * var filter = new fabric.Image.filters.Saturation({\r\n * saturation: 1\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n */\r\n filters.Saturation = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Saturation.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'Saturation',\r\n\r\n fragmentSource: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uSaturation;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\r\n 'float rgMax = max(color.r, color.g);\\n' +\r\n 'float rgbMax = max(rgMax, color.b);\\n' +\r\n 'color.r += rgbMax != color.r ? (rgbMax - color.r) * uSaturation : 0.00;\\n' +\r\n 'color.g += rgbMax != color.g ? (rgbMax - color.g) * uSaturation : 0.00;\\n' +\r\n 'color.b += rgbMax != color.b ? (rgbMax - color.b) * uSaturation : 0.00;\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}',\r\n\r\n /**\r\n * Saturation value, from -1 to 1.\r\n * Increases/decreases the color saturation.\r\n * A value of 0 has no effect.\r\n * \r\n * @param {Number} saturation\r\n * @default\r\n */\r\n saturation: 0,\r\n\r\n mainParameter: 'saturation',\r\n\r\n /**\r\n * Constructor\r\n * @memberOf fabric.Image.filters.Saturate.prototype\r\n * @param {Object} [options] Options object\r\n * @param {Number} [options.saturate=0] Value to saturate the image (-1...1)\r\n */\r\n\r\n /**\r\n * Apply the Saturation operation to a Uint8ClampedArray representing the pixels of an image.\r\n *\r\n * @param {Object} options\r\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\r\n */\r\n applyTo2d: function(options) {\r\n if (this.saturation === 0) {\r\n return;\r\n }\r\n var imageData = options.imageData,\r\n data = imageData.data, len = data.length,\r\n adjust = -this.saturation, i, max;\r\n\r\n for (i = 0; i < len; i += 4) {\r\n max = Math.max(data[i], data[i + 1], data[i + 2]);\r\n data[i] += max !== data[i] ? (max - data[i]) * adjust : 0;\r\n data[i + 1] += max !== data[i + 1] ? (max - data[i + 1]) * adjust : 0;\r\n data[i + 2] += max !== data[i + 2] ? (max - data[i + 2]) * adjust : 0;\r\n }\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uSaturation: gl.getUniformLocation(program, 'uSaturation'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n gl.uniform1f(uniformLocations.uSaturation, -this.saturation);\r\n },\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {Function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.Saturation} Instance of fabric.Image.filters.Saturate\r\n */\r\n fabric.Image.filters.Saturation.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Vibrance filter class\r\n * @class fabric.Image.filters.Vibrance\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link fabric.Image.filters.Vibrance#initialize} for constructor definition\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example\r\n * var filter = new fabric.Image.filters.Vibrance({\r\n * vibrance: 1\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n */\r\n filters.Vibrance = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Vibrance.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'Vibrance',\r\n\r\n fragmentSource: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform float uVibrance;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\r\n 'float max = max(color.r, max(color.g, color.b));\\n' +\r\n 'float avg = (color.r + color.g + color.b) / 3.0;\\n' +\r\n 'float amt = (abs(max - avg) * 2.0) * uVibrance;\\n' +\r\n 'color.r += max != color.r ? (max - color.r) * amt : 0.00;\\n' +\r\n 'color.g += max != color.g ? (max - color.g) * amt : 0.00;\\n' +\r\n 'color.b += max != color.b ? (max - color.b) * amt : 0.00;\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n '}',\r\n\r\n /**\r\n * Vibrance value, from -1 to 1.\r\n * Increases/decreases the saturation of more muted colors with less effect on saturated colors.\r\n * A value of 0 has no effect.\r\n * \r\n * @param {Number} vibrance\r\n * @default\r\n */\r\n vibrance: 0,\r\n\r\n mainParameter: 'vibrance',\r\n\r\n /**\r\n * Constructor\r\n * @memberOf fabric.Image.filters.Vibrance.prototype\r\n * @param {Object} [options] Options object\r\n * @param {Number} [options.vibrance=0] Vibrance value for the image (between -1 and 1)\r\n */\r\n\r\n /**\r\n * Apply the Vibrance operation to a Uint8ClampedArray representing the pixels of an image.\r\n *\r\n * @param {Object} options\r\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\r\n */\r\n applyTo2d: function(options) {\r\n if (this.vibrance === 0) {\r\n return;\r\n }\r\n var imageData = options.imageData,\r\n data = imageData.data, len = data.length,\r\n adjust = -this.vibrance, i, max, avg, amt;\r\n\r\n for (i = 0; i < len; i += 4) {\r\n max = Math.max(data[i], data[i + 1], data[i + 2]);\r\n avg = (data[i] + data[i + 1] + data[i + 2]) / 3;\r\n amt = ((Math.abs(max - avg) * 2 / 255) * adjust);\r\n data[i] += max !== data[i] ? (max - data[i]) * amt : 0;\r\n data[i + 1] += max !== data[i + 1] ? (max - data[i + 1]) * amt : 0;\r\n data[i + 2] += max !== data[i + 2] ? (max - data[i + 2]) * amt : 0;\r\n }\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uVibrance: gl.getUniformLocation(program, 'uVibrance'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n gl.uniform1f(uniformLocations.uVibrance, -this.vibrance);\r\n },\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {Function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.Vibrance} Instance of fabric.Image.filters.Vibrance\r\n */\r\n fabric.Image.filters.Vibrance.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Blur filter class\r\n * @class fabric.Image.filters.Blur\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link fabric.Image.filters.Blur#initialize} for constructor definition\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example\r\n * var filter = new fabric.Image.filters.Blur({\r\n * blur: 0.5\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n * canvas.renderAll();\r\n */\r\n filters.Blur = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Blur.prototype */ {\r\n\r\n type: 'Blur',\r\n\r\n /*\r\n'gl_FragColor = vec4(0.0);',\r\n'gl_FragColor += texture2D(texture, vTexCoord + -7 * uDelta)*0.0044299121055113265;',\r\n'gl_FragColor += texture2D(texture, vTexCoord + -6 * uDelta)*0.00895781211794;',\r\n'gl_FragColor += texture2D(texture, vTexCoord + -5 * uDelta)*0.0215963866053;',\r\n'gl_FragColor += texture2D(texture, vTexCoord + -4 * uDelta)*0.0443683338718;',\r\n'gl_FragColor += texture2D(texture, vTexCoord + -3 * uDelta)*0.0776744219933;',\r\n'gl_FragColor += texture2D(texture, vTexCoord + -2 * uDelta)*0.115876621105;',\r\n'gl_FragColor += texture2D(texture, vTexCoord + -1 * uDelta)*0.147308056121;',\r\n'gl_FragColor += texture2D(texture, vTexCoord )*0.159576912161;',\r\n'gl_FragColor += texture2D(texture, vTexCoord + 1 * uDelta)*0.147308056121;',\r\n'gl_FragColor += texture2D(texture, vTexCoord + 2 * uDelta)*0.115876621105;',\r\n'gl_FragColor += texture2D(texture, vTexCoord + 3 * uDelta)*0.0776744219933;',\r\n'gl_FragColor += texture2D(texture, vTexCoord + 4 * uDelta)*0.0443683338718;',\r\n'gl_FragColor += texture2D(texture, vTexCoord + 5 * uDelta)*0.0215963866053;',\r\n'gl_FragColor += texture2D(texture, vTexCoord + 6 * uDelta)*0.00895781211794;',\r\n'gl_FragColor += texture2D(texture, vTexCoord + 7 * uDelta)*0.0044299121055113265;',\r\n*/\r\n\r\n /* eslint-disable max-len */\r\n fragmentSource: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform vec2 uDelta;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'const float nSamples = 15.0;\\n' +\r\n 'vec3 v3offset = vec3(12.9898, 78.233, 151.7182);\\n' +\r\n 'float random(vec3 scale) {\\n' +\r\n /* use the fragment position for a different seed per-pixel */\r\n 'return fract(sin(dot(gl_FragCoord.xyz, scale)) * 43758.5453);\\n' +\r\n '}\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = vec4(0.0);\\n' +\r\n 'float total = 0.0;\\n' +\r\n 'float offset = random(v3offset);\\n' +\r\n 'for (float t = -nSamples; t <= nSamples; t++) {\\n' +\r\n 'float percent = (t + offset - 0.5) / nSamples;\\n' +\r\n 'float weight = 1.0 - abs(percent);\\n' +\r\n 'color += texture2D(uTexture, vTexCoord + uDelta * percent) * weight;\\n' +\r\n 'total += weight;\\n' +\r\n '}\\n' +\r\n 'gl_FragColor = color / total;\\n' +\r\n '}',\r\n /* eslint-enable max-len */\r\n\r\n /**\r\n * blur value, in percentage of image dimensions.\r\n * specific to keep the image blur constant at different resolutions\r\n * range between 0 and 1.\r\n * @type Number\r\n * @default\r\n */\r\n blur: 0,\r\n\r\n mainParameter: 'blur',\r\n\r\n applyTo: function(options) {\r\n if (options.webgl) {\r\n // this aspectRatio is used to give the same blur to vertical and horizontal\r\n this.aspectRatio = options.sourceWidth / options.sourceHeight;\r\n options.passes++;\r\n this._setupFrameBuffer(options);\r\n this.horizontal = true;\r\n this.applyToWebGL(options);\r\n this._swapTextures(options);\r\n this._setupFrameBuffer(options);\r\n this.horizontal = false;\r\n this.applyToWebGL(options);\r\n this._swapTextures(options);\r\n }\r\n else {\r\n this.applyTo2d(options);\r\n }\r\n },\r\n\r\n applyTo2d: function(options) {\r\n // paint canvasEl with current image data.\r\n //options.ctx.putImageData(options.imageData, 0, 0);\r\n options.imageData = this.simpleBlur(options);\r\n },\r\n\r\n simpleBlur: function(options) {\r\n var resources = options.filterBackend.resources, canvas1, canvas2,\r\n width = options.imageData.width,\r\n height = options.imageData.height;\r\n\r\n if (!resources.blurLayer1) {\r\n resources.blurLayer1 = fabric.util.createCanvasElement();\r\n resources.blurLayer2 = fabric.util.createCanvasElement();\r\n }\r\n canvas1 = resources.blurLayer1;\r\n canvas2 = resources.blurLayer2;\r\n if (canvas1.width !== width || canvas1.height !== height) {\r\n canvas2.width = canvas1.width = width;\r\n canvas2.height = canvas1.height = height;\r\n }\r\n var ctx1 = canvas1.getContext('2d', { willReadFrequently: true }),\r\n ctx2 = canvas2.getContext('2d', { willReadFrequently: true }),\r\n nSamples = 15,\r\n random, percent, j, i,\r\n blur = this.blur * 0.06 * 0.5;\r\n\r\n // load first canvas\r\n ctx1.putImageData(options.imageData, 0, 0);\r\n ctx2.clearRect(0, 0, width, height);\r\n\r\n for (i = -nSamples; i <= nSamples; i++) {\r\n random = (Math.random() - 0.5) / 4;\r\n percent = i / nSamples;\r\n j = blur * percent * width + random;\r\n ctx2.globalAlpha = 1 - Math.abs(percent);\r\n ctx2.drawImage(canvas1, j, random);\r\n ctx1.drawImage(canvas2, 0, 0);\r\n ctx2.globalAlpha = 1;\r\n ctx2.clearRect(0, 0, canvas2.width, canvas2.height);\r\n }\r\n for (i = -nSamples; i <= nSamples; i++) {\r\n random = (Math.random() - 0.5) / 4;\r\n percent = i / nSamples;\r\n j = blur * percent * height + random;\r\n ctx2.globalAlpha = 1 - Math.abs(percent);\r\n ctx2.drawImage(canvas1, random, j);\r\n ctx1.drawImage(canvas2, 0, 0);\r\n ctx2.globalAlpha = 1;\r\n ctx2.clearRect(0, 0, canvas2.width, canvas2.height);\r\n }\r\n options.ctx.drawImage(canvas1, 0, 0);\r\n var newImageData = options.ctx.getImageData(0, 0, canvas1.width, canvas1.height);\r\n ctx1.globalAlpha = 1;\r\n ctx1.clearRect(0, 0, canvas1.width, canvas1.height);\r\n return newImageData;\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n delta: gl.getUniformLocation(program, 'uDelta'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n var delta = this.chooseRightDelta();\r\n gl.uniform2fv(uniformLocations.delta, delta);\r\n },\r\n\r\n /**\r\n * choose right value of image percentage to blur with\r\n * @returns {Array} a numeric array with delta values\r\n */\r\n chooseRightDelta: function() {\r\n var blurScale = 1, delta = [0, 0], blur;\r\n if (this.horizontal) {\r\n if (this.aspectRatio > 1) {\r\n // image is wide, i want to shrink radius horizontal\r\n blurScale = 1 / this.aspectRatio;\r\n }\r\n }\r\n else {\r\n if (this.aspectRatio < 1) {\r\n // image is tall, i want to shrink radius vertical\r\n blurScale = this.aspectRatio;\r\n }\r\n }\r\n blur = blurScale * this.blur * 0.12;\r\n if (this.horizontal) {\r\n delta[0] = blur;\r\n }\r\n else {\r\n delta[1] = blur;\r\n }\r\n return delta;\r\n },\r\n });\r\n\r\n /**\r\n * Deserialize a JSON definition of a BlurFilter into a concrete instance.\r\n */\r\n filters.Blur.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * Gamma filter class\r\n * @class fabric.Image.filters.Gamma\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link fabric.Image.filters.Gamma#initialize} for constructor definition\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example\r\n * var filter = new fabric.Image.filters.Gamma({\r\n * gamma: [1, 0.5, 2.1]\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n */\r\n filters.Gamma = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Gamma.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'Gamma',\r\n\r\n fragmentSource: 'precision highp float;\\n' +\r\n 'uniform sampler2D uTexture;\\n' +\r\n 'uniform vec3 uGamma;\\n' +\r\n 'varying vec2 vTexCoord;\\n' +\r\n 'void main() {\\n' +\r\n 'vec4 color = texture2D(uTexture, vTexCoord);\\n' +\r\n 'vec3 correction = (1.0 / uGamma);\\n' +\r\n 'color.r = pow(color.r, correction.r);\\n' +\r\n 'color.g = pow(color.g, correction.g);\\n' +\r\n 'color.b = pow(color.b, correction.b);\\n' +\r\n 'gl_FragColor = color;\\n' +\r\n 'gl_FragColor.rgb *= color.a;\\n' +\r\n '}',\r\n\r\n /**\r\n * Gamma array value, from 0.01 to 2.2.\r\n * @param {Array} gamma\r\n * @default\r\n */\r\n gamma: [1, 1, 1],\r\n\r\n /**\r\n * Describe the property that is the filter parameter\r\n * @param {String} m\r\n * @default\r\n */\r\n mainParameter: 'gamma',\r\n\r\n /**\r\n * Constructor\r\n * @param {Object} [options] Options object\r\n */\r\n initialize: function(options) {\r\n this.gamma = [1, 1, 1];\r\n filters.BaseFilter.prototype.initialize.call(this, options);\r\n },\r\n\r\n /**\r\n * Apply the Gamma operation to a Uint8Array representing the pixels of an image.\r\n *\r\n * @param {Object} options\r\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\r\n */\r\n applyTo2d: function(options) {\r\n var imageData = options.imageData, data = imageData.data,\r\n gamma = this.gamma, len = data.length,\r\n rInv = 1 / gamma[0], gInv = 1 / gamma[1],\r\n bInv = 1 / gamma[2], i;\r\n\r\n if (!this.rVals) {\r\n // eslint-disable-next-line\r\n this.rVals = new Uint8Array(256);\r\n // eslint-disable-next-line\r\n this.gVals = new Uint8Array(256);\r\n // eslint-disable-next-line\r\n this.bVals = new Uint8Array(256);\r\n }\r\n\r\n // This is an optimization - pre-compute a look-up table for each color channel\r\n // instead of performing these pow calls for each pixel in the image.\r\n for (i = 0, len = 256; i < len; i++) {\r\n this.rVals[i] = Math.pow(i / 255, rInv) * 255;\r\n this.gVals[i] = Math.pow(i / 255, gInv) * 255;\r\n this.bVals[i] = Math.pow(i / 255, bInv) * 255;\r\n }\r\n for (i = 0, len = data.length; i < len; i += 4) {\r\n data[i] = this.rVals[data[i]];\r\n data[i + 1] = this.gVals[data[i + 1]];\r\n data[i + 2] = this.bVals[data[i + 2]];\r\n }\r\n },\r\n\r\n /**\r\n * Return WebGL uniform locations for this filter's shader.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {WebGLShaderProgram} program This filter's compiled shader program.\r\n */\r\n getUniformLocations: function(gl, program) {\r\n return {\r\n uGamma: gl.getUniformLocation(program, 'uGamma'),\r\n };\r\n },\r\n\r\n /**\r\n * Send data from this filter to its shader program's uniforms.\r\n *\r\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\r\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\r\n */\r\n sendUniformData: function(gl, uniformLocations) {\r\n gl.uniform3fv(uniformLocations.uGamma, this.gamma);\r\n },\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.Gamma} Instance of fabric.Image.filters.Gamma\r\n */\r\n fabric.Image.filters.Gamma.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * A container class that knows how to apply a sequence of filters to an input image.\r\n */\r\n filters.Composed = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Composed.prototype */ {\r\n\r\n type: 'Composed',\r\n\r\n /**\r\n * A non sparse array of filters to apply\r\n */\r\n subFilters: [],\r\n\r\n /**\r\n * Constructor\r\n * @param {Object} [options] Options object\r\n */\r\n initialize: function(options) {\r\n this.callSuper('initialize', options);\r\n // create a new array instead mutating the prototype with push\r\n this.subFilters = this.subFilters.slice(0);\r\n },\r\n\r\n /**\r\n * Apply this container's filters to the input image provided.\r\n *\r\n * @param {Object} options\r\n * @param {Number} options.passes The number of filters remaining to be applied.\r\n */\r\n applyTo: function(options) {\r\n options.passes += this.subFilters.length - 1;\r\n this.subFilters.forEach(function(filter) {\r\n filter.applyTo(options);\r\n });\r\n },\r\n\r\n /**\r\n * Serialize this filter into JSON.\r\n *\r\n * @returns {Object} A JSON representation of this filter.\r\n */\r\n toObject: function() {\r\n return fabric.util.object.extend(this.callSuper('toObject'), {\r\n subFilters: this.subFilters.map(function(filter) { return filter.toObject(); }),\r\n });\r\n },\r\n\r\n isNeutralState: function() {\r\n return !this.subFilters.some(function(filter) { return !filter.isNeutralState(); });\r\n }\r\n });\r\n\r\n /**\r\n * Deserialize a JSON definition of a ComposedFilter into a concrete instance.\r\n */\r\n fabric.Image.filters.Composed.fromObject = function(object, callback) {\r\n var filters = object.subFilters || [],\r\n subFilters = filters.map(function(filter) {\r\n return new fabric.Image.filters[filter.type](filter);\r\n }),\r\n instance = new fabric.Image.filters.Composed({ subFilters: subFilters });\r\n callback && callback(instance);\r\n return instance;\r\n };\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n filters = fabric.Image.filters,\r\n createClass = fabric.util.createClass;\r\n\r\n /**\r\n * HueRotation filter class\r\n * @class fabric.Image.filters.HueRotation\r\n * @memberOf fabric.Image.filters\r\n * @extends fabric.Image.filters.BaseFilter\r\n * @see {@link fabric.Image.filters.HueRotation#initialize} for constructor definition\r\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\r\n * @example\r\n * var filter = new fabric.Image.filters.HueRotation({\r\n * rotation: -0.5\r\n * });\r\n * object.filters.push(filter);\r\n * object.applyFilters();\r\n */\r\n filters.HueRotation = createClass(filters.ColorMatrix, /** @lends fabric.Image.filters.HueRotation.prototype */ {\r\n\r\n /**\r\n * Filter type\r\n * @param {String} type\r\n * @default\r\n */\r\n type: 'HueRotation',\r\n\r\n /**\r\n * HueRotation value, from -1 to 1.\r\n * the unit is radians\r\n * @param {Number} myParameter\r\n * @default\r\n */\r\n rotation: 0,\r\n\r\n /**\r\n * Describe the property that is the filter parameter\r\n * @param {String} m\r\n * @default\r\n */\r\n mainParameter: 'rotation',\r\n\r\n calculateMatrix: function() {\r\n var rad = this.rotation * Math.PI, cos = fabric.util.cos(rad), sin = fabric.util.sin(rad),\r\n aThird = 1 / 3, aThirdSqtSin = Math.sqrt(aThird) * sin, OneMinusCos = 1 - cos;\r\n this.matrix = [\r\n 1, 0, 0, 0, 0,\r\n 0, 1, 0, 0, 0,\r\n 0, 0, 1, 0, 0,\r\n 0, 0, 0, 1, 0\r\n ];\r\n this.matrix[0] = cos + OneMinusCos / 3;\r\n this.matrix[1] = aThird * OneMinusCos - aThirdSqtSin;\r\n this.matrix[2] = aThird * OneMinusCos + aThirdSqtSin;\r\n this.matrix[5] = aThird * OneMinusCos + aThirdSqtSin;\r\n this.matrix[6] = cos + aThird * OneMinusCos;\r\n this.matrix[7] = aThird * OneMinusCos - aThirdSqtSin;\r\n this.matrix[10] = aThird * OneMinusCos - aThirdSqtSin;\r\n this.matrix[11] = aThird * OneMinusCos + aThirdSqtSin;\r\n this.matrix[12] = cos + aThird * OneMinusCos;\r\n },\r\n\r\n /**\r\n * HueRotation isNeutralState implementation\r\n * Used only in image applyFilters to discard filters that will not have an effect\r\n * on the image\r\n * @param {Object} options\r\n **/\r\n isNeutralState: function(options) {\r\n this.calculateMatrix();\r\n return filters.BaseFilter.prototype.isNeutralState.call(this, options);\r\n },\r\n\r\n /**\r\n * Apply this filter to the input image data provided.\r\n *\r\n * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\r\n *\r\n * @param {Object} options\r\n * @param {Number} options.passes The number of filters remaining to be executed\r\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\r\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\r\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\r\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\r\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\r\n */\r\n applyTo: function(options) {\r\n this.calculateMatrix();\r\n filters.BaseFilter.prototype.applyTo.call(this, options);\r\n },\r\n\r\n });\r\n\r\n /**\r\n * Returns filter instance from an object representation\r\n * @static\r\n * @param {Object} object Object to create an instance from\r\n * @param {function} [callback] to be invoked after filter creation\r\n * @return {fabric.Image.filters.HueRotation} Instance of fabric.Image.filters.HueRotation\r\n */\r\n fabric.Image.filters.HueRotation.fromObject = fabric.Image.filters.BaseFilter.fromObject;\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function(global) {\r\n\r\n 'use strict';\r\n\r\n var fabric = global.fabric || (global.fabric = { }),\r\n clone = fabric.util.object.clone;\r\n\r\n if (fabric.Text) {\r\n fabric.warn('fabric.Text is already defined');\r\n return;\r\n }\r\n\r\n var additionalProps =\r\n ('fontFamily fontWeight fontSize text underline overline linethrough' +\r\n ' textAlign fontStyle lineHeight textBackgroundColor charSpacing styles' +\r\n ' direction path pathStartOffset pathSide pathAlign').split(' ');\r\n\r\n /**\r\n * Text class\r\n * @class fabric.Text\r\n * @extends fabric.Object\r\n * @return {fabric.Text} thisArg\r\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#text}\r\n * @see {@link fabric.Text#initialize} for constructor definition\r\n */\r\n fabric.Text = fabric.util.createClass(fabric.Object, /** @lends fabric.Text.prototype */ {\r\n\r\n /**\r\n * Properties which when set cause object to change dimensions\r\n * @type Array\r\n * @private\r\n */\r\n _dimensionAffectingProps: [\r\n 'fontSize',\r\n 'fontWeight',\r\n 'fontFamily',\r\n 'fontStyle',\r\n 'lineHeight',\r\n 'text',\r\n 'charSpacing',\r\n 'textAlign',\r\n 'styles',\r\n 'path',\r\n 'pathStartOffset',\r\n 'pathSide',\r\n 'pathAlign'\r\n ],\r\n\r\n /**\r\n * @private\r\n */\r\n _reNewline: /\\r?\\n/,\r\n\r\n /**\r\n * Use this regular expression to filter for whitespaces that is not a new line.\r\n * Mostly used when text is 'justify' aligned.\r\n * @private\r\n */\r\n _reSpacesAndTabs: /[ \\t\\r]/g,\r\n\r\n /**\r\n * Use this regular expression to filter for whitespace that is not a new line.\r\n * Mostly used when text is 'justify' aligned.\r\n * @private\r\n */\r\n _reSpaceAndTab: /[ \\t\\r]/,\r\n\r\n /**\r\n * Use this regular expression to filter consecutive groups of non spaces.\r\n * Mostly used when text is 'justify' aligned.\r\n * @private\r\n */\r\n _reWords: /\\S+/g,\r\n\r\n /**\r\n * Type of an object\r\n * @type String\r\n * @default\r\n */\r\n type: 'text',\r\n\r\n /**\r\n * Font size (in pixels)\r\n * @type Number\r\n * @default\r\n */\r\n fontSize: 40,\r\n\r\n /**\r\n * Font weight (e.g. bold, normal, 400, 600, 800)\r\n * @type {(Number|String)}\r\n * @default\r\n */\r\n fontWeight: 'normal',\r\n\r\n /**\r\n * Font family\r\n * @type String\r\n * @default\r\n */\r\n fontFamily: 'Times New Roman',\r\n\r\n /**\r\n * Text decoration underline.\r\n * @type Boolean\r\n * @default\r\n */\r\n underline: false,\r\n\r\n /**\r\n * Text decoration overline.\r\n * @type Boolean\r\n * @default\r\n */\r\n overline: false,\r\n\r\n /**\r\n * Text decoration linethrough.\r\n * @type Boolean\r\n * @default\r\n */\r\n linethrough: false,\r\n\r\n /**\r\n * Text alignment. Possible values: \"left\", \"center\", \"right\", \"justify\",\r\n * \"justify-left\", \"justify-center\" or \"justify-right\".\r\n * @type String\r\n * @default\r\n */\r\n textAlign: 'left',\r\n\r\n /**\r\n * Font style . Possible values: \"\", \"normal\", \"italic\" or \"oblique\".\r\n * @type String\r\n * @default\r\n */\r\n fontStyle: 'normal',\r\n\r\n /**\r\n * Line height\r\n * @type Number\r\n * @default\r\n */\r\n lineHeight: 1.16,\r\n\r\n /**\r\n * Superscript schema object (minimum overlap)\r\n * @type {Object}\r\n * @default\r\n */\r\n superscript: {\r\n size: 0.60, // fontSize factor\r\n baseline: -0.35 // baseline-shift factor (upwards)\r\n },\r\n\r\n /**\r\n * Subscript schema object (minimum overlap)\r\n * @type {Object}\r\n * @default\r\n */\r\n subscript: {\r\n size: 0.60, // fontSize factor\r\n baseline: 0.11 // baseline-shift factor (downwards)\r\n },\r\n\r\n /**\r\n * Background color of text lines\r\n * @type String\r\n * @default\r\n */\r\n textBackgroundColor: '',\r\n\r\n /**\r\n * List of properties to consider when checking if\r\n * state of an object is changed ({@link fabric.Object#hasStateChanged})\r\n * as well as for history (undo/redo) purposes\r\n * @type Array\r\n */\r\n stateProperties: fabric.Object.prototype.stateProperties.concat(additionalProps),\r\n\r\n /**\r\n * List of properties to consider when checking if cache needs refresh\r\n * @type Array\r\n */\r\n cacheProperties: fabric.Object.prototype.cacheProperties.concat(additionalProps),\r\n\r\n /**\r\n * When defined, an object is rendered via stroke and this property specifies its color.\r\n * Backwards incompatibility note: This property was named \"strokeStyle\" until v1.1.6\r\n * @type String\r\n * @default\r\n */\r\n stroke: null,\r\n\r\n /**\r\n * Shadow object representing shadow of this shape.\r\n * Backwards incompatibility note: This property was named \"textShadow\" (String) until v1.2.11\r\n * @type fabric.Shadow\r\n * @default\r\n */\r\n shadow: null,\r\n\r\n /**\r\n * fabric.Path that the text should follow.\r\n * since 4.6.0 the path will be drawn automatically.\r\n * if you want to make the path visible, give it a stroke and strokeWidth or fill value\r\n * if you want it to be hidden, assign visible = false to the path.\r\n * This feature is in BETA, and SVG import/export is not yet supported.\r\n * @type fabric.Path\r\n * @example\r\n * var textPath = new fabric.Text('Text on a path', {\r\n * top: 150,\r\n * left: 150,\r\n * textAlign: 'center',\r\n * charSpacing: -50,\r\n * path: new fabric.Path('M 0 0 C 50 -100 150 -100 200 0', {\r\n * strokeWidth: 1,\r\n * visible: false\r\n * }),\r\n * pathSide: 'left',\r\n * pathStartOffset: 0\r\n * });\r\n * @default\r\n */\r\n path: null,\r\n\r\n /**\r\n * Offset amount for text path starting position\r\n * Only used when text has a path\r\n * @type Number\r\n * @default\r\n */\r\n pathStartOffset: 0,\r\n\r\n /**\r\n * Which side of the path the text should be drawn on.\r\n * Only used when text has a path\r\n * @type {String} 'left|right'\r\n * @default\r\n */\r\n pathSide: 'left',\r\n\r\n /**\r\n * How text is aligned to the path. This property determines\r\n * the perpendicular position of each character relative to the path.\r\n * (one of \"baseline\", \"center\", \"ascender\", \"descender\")\r\n * This feature is in BETA, and its behavior may change\r\n * @type String\r\n * @default\r\n */\r\n pathAlign: 'baseline',\r\n\r\n /**\r\n * @private\r\n */\r\n _fontSizeFraction: 0.222,\r\n\r\n /**\r\n * @private\r\n */\r\n offsets: {\r\n underline: 0.10,\r\n linethrough: -0.315,\r\n overline: -0.88\r\n },\r\n\r\n /**\r\n * Text Line proportion to font Size (in pixels)\r\n * @type Number\r\n * @default\r\n */\r\n _fontSizeMult: 1.13,\r\n\r\n /**\r\n * additional space between characters\r\n * expressed in thousands of em unit\r\n * @type Number\r\n * @default\r\n */\r\n charSpacing: 0,\r\n\r\n /**\r\n * Object containing character styles - top-level properties -> line numbers,\r\n * 2nd-level properties - character numbers\r\n * @type Object\r\n * @default\r\n */\r\n styles: null,\r\n\r\n /**\r\n * Reference to a context to measure text char or couple of chars\r\n * the cacheContext of the canvas will be used or a freshly created one if the object is not on canvas\r\n * once created it will be referenced on fabric._measuringContext to avoid creating a canvas for every\r\n * text object created.\r\n * @type {CanvasRenderingContext2D}\r\n * @default\r\n */\r\n _measuringContext: null,\r\n\r\n /**\r\n * Baseline shift, styles only, keep at 0 for the main text object\r\n * @type {Number}\r\n * @default\r\n */\r\n deltaY: 0,\r\n\r\n /**\r\n * WARNING: EXPERIMENTAL. NOT SUPPORTED YET\r\n * determine the direction of the text.\r\n * This has to be set manually together with textAlign and originX for proper\r\n * experience.\r\n * some interesting link for the future\r\n * https://www.w3.org/International/questions/qa-bidi-unicode-controls\r\n * @since 4.5.0\r\n * @type {String} 'ltr|rtl'\r\n * @default\r\n */\r\n direction: 'ltr',\r\n\r\n /**\r\n * Array of properties that define a style unit (of 'styles').\r\n * @type {Array}\r\n * @default\r\n */\r\n _styleProperties: [\r\n 'stroke',\r\n 'strokeWidth',\r\n 'fill',\r\n 'fontFamily',\r\n 'fontSize',\r\n 'fontWeight',\r\n 'fontStyle',\r\n 'underline',\r\n 'overline',\r\n 'linethrough',\r\n 'deltaY',\r\n 'textBackgroundColor',\r\n ],\r\n\r\n /**\r\n * contains characters bounding boxes\r\n */\r\n __charBounds: [],\r\n\r\n /**\r\n * use this size when measuring text. To avoid IE11 rounding errors\r\n * @type {Number}\r\n * @default\r\n * @readonly\r\n * @private\r\n */\r\n CACHE_FONT_SIZE: 400,\r\n\r\n /**\r\n * contains the min text width to avoid getting 0\r\n * @type {Number}\r\n * @default\r\n */\r\n MIN_TEXT_WIDTH: 2,\r\n\r\n /**\r\n * Constructor\r\n * @param {String} text Text string\r\n * @param {Object} [options] Options object\r\n * @return {fabric.Text} thisArg\r\n */\r\n initialize: function(text, options) {\r\n this.styles = options ? (options.styles || { }) : { };\r\n this.text = text;\r\n this.__skipDimension = true;\r\n this.callSuper('initialize', options);\r\n if (this.path) {\r\n this.setPathInfo();\r\n }\r\n this.__skipDimension = false;\r\n this.initDimensions();\r\n this.setCoords();\r\n this.setupState({ propertySet: '_dimensionAffectingProps' });\r\n },\r\n\r\n /**\r\n * If text has a path, it will add the extra information needed\r\n * for path and text calculations\r\n * @return {fabric.Text} thisArg\r\n */\r\n setPathInfo: function() {\r\n var path = this.path;\r\n if (path) {\r\n path.segmentsInfo = fabric.util.getPathSegmentsInfo(path.path);\r\n }\r\n },\r\n\r\n /**\r\n * Return a context for measurement of text string.\r\n * if created it gets stored for reuse\r\n * this is for internal use, please do not use it\r\n * @private\r\n * @param {String} text Text string\r\n * @param {Object} [options] Options object\r\n * @return {fabric.Text} thisArg\r\n */\r\n getMeasuringContext: function() {\r\n // if we did not return we have to measure something.\r\n if (!fabric._measuringContext) {\r\n fabric._measuringContext = this.canvas && this.canvas.contextCache ||\r\n fabric.util.createCanvasElement().getContext('2d', { willReadFrequently: true });\r\n }\r\n return fabric._measuringContext;\r\n },\r\n\r\n /**\r\n * @private\r\n * Divides text into lines of text and lines of graphemes.\r\n */\r\n _splitText: function() {\r\n var newLines = this._splitTextIntoLines(this.text);\r\n this.textLines = newLines.lines;\r\n this._textLines = newLines.graphemeLines;\r\n this._unwrappedTextLines = newLines._unwrappedLines;\r\n this._text = newLines.graphemeText;\r\n return newLines;\r\n },\r\n\r\n /**\r\n * Initialize or update text dimensions.\r\n * Updates this.width and this.height with the proper values.\r\n * Does not return dimensions.\r\n */\r\n initDimensions: function() {\r\n if (this.__skipDimension) {\r\n return;\r\n }\r\n this._splitText();\r\n this._clearCache();\r\n if (this.path) {\r\n this.width = this.path.width;\r\n this.height = this.path.height;\r\n }\r\n else {\r\n this.width = this.calcTextWidth() || this.cursorWidth || this.MIN_TEXT_WIDTH;\r\n this.height = this.calcTextHeight();\r\n }\r\n if (this.textAlign.indexOf('justify') !== -1) {\r\n // once text is measured we need to make space fatter to make justified text.\r\n this.enlargeSpaces();\r\n }\r\n this.saveState({ propertySet: '_dimensionAffectingProps' });\r\n },\r\n\r\n /**\r\n * Enlarge space boxes and shift the others\r\n */\r\n enlargeSpaces: function() {\r\n var diffSpace, currentLineWidth, numberOfSpaces, accumulatedSpace, line, charBound, spaces;\r\n for (var i = 0, len = this._textLines.length; i < len; i++) {\r\n if (this.textAlign !== 'justify' && (i === len - 1 || this.isEndOfWrapping(i))) {\r\n continue;\r\n }\r\n accumulatedSpace = 0;\r\n line = this._textLines[i];\r\n currentLineWidth = this.getLineWidth(i);\r\n if (currentLineWidth < this.width && (spaces = this.textLines[i].match(this._reSpacesAndTabs))) {\r\n numberOfSpaces = spaces.length;\r\n diffSpace = (this.width - currentLineWidth) / numberOfSpaces;\r\n for (var j = 0, jlen = line.length; j <= jlen; j++) {\r\n charBound = this.__charBounds[i][j];\r\n if (this._reSpaceAndTab.test(line[j])) {\r\n charBound.width += diffSpace;\r\n charBound.kernedWidth += diffSpace;\r\n charBound.left += accumulatedSpace;\r\n accumulatedSpace += diffSpace;\r\n }\r\n else {\r\n charBound.left += accumulatedSpace;\r\n }\r\n }\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * Detect if the text line is ended with an hard break\r\n * text and itext do not have wrapping, return false\r\n * @return {Boolean}\r\n */\r\n isEndOfWrapping: function(lineIndex) {\r\n return lineIndex === this._textLines.length - 1;\r\n },\r\n\r\n /**\r\n * Detect if a line has a linebreak and so we need to account for it when moving\r\n * and counting style.\r\n * It return always for text and Itext.\r\n * @return Number\r\n */\r\n missingNewlineOffset: function() {\r\n return 1;\r\n },\r\n\r\n /**\r\n * Returns string representation of an instance\r\n * @return {String} String representation of text object\r\n */\r\n toString: function() {\r\n return '#';\r\n },\r\n\r\n /**\r\n * Return the dimension and the zoom level needed to create a cache canvas\r\n * big enough to host the object to be cached.\r\n * @private\r\n * @param {Object} dim.x width of object to be cached\r\n * @param {Object} dim.y height of object to be cached\r\n * @return {Object}.width width of canvas\r\n * @return {Object}.height height of canvas\r\n * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\r\n * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\r\n */\r\n _getCacheCanvasDimensions: function() {\r\n var dims = this.callSuper('_getCacheCanvasDimensions');\r\n var fontSize = this.fontSize;\r\n dims.width += fontSize * dims.zoomX;\r\n dims.height += fontSize * dims.zoomY;\r\n return dims;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _render: function(ctx) {\r\n var path = this.path;\r\n path && !path.isNotVisible() && path._render(ctx);\r\n this._setTextStyles(ctx);\r\n this._renderTextLinesBackground(ctx);\r\n this._renderTextDecoration(ctx, 'underline');\r\n this._renderText(ctx);\r\n this._renderTextDecoration(ctx, 'overline');\r\n this._renderTextDecoration(ctx, 'linethrough');\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _renderText: function(ctx) {\r\n if (this.paintFirst === 'stroke') {\r\n this._renderTextStroke(ctx);\r\n this._renderTextFill(ctx);\r\n }\r\n else {\r\n this._renderTextFill(ctx);\r\n this._renderTextStroke(ctx);\r\n }\r\n },\r\n\r\n /**\r\n * Set the font parameter of the context with the object properties or with charStyle\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @param {Object} [charStyle] object with font style properties\r\n * @param {String} [charStyle.fontFamily] Font Family\r\n * @param {Number} [charStyle.fontSize] Font size in pixels. ( without px suffix )\r\n * @param {String} [charStyle.fontWeight] Font weight\r\n * @param {String} [charStyle.fontStyle] Font style (italic|normal)\r\n */\r\n _setTextStyles: function(ctx, charStyle, forMeasuring) {\r\n ctx.textBaseline = 'alphabetical';\r\n if (this.path) {\r\n switch (this.pathAlign) {\r\n case 'center':\r\n ctx.textBaseline = 'middle';\r\n break;\r\n case 'ascender':\r\n ctx.textBaseline = 'top';\r\n break;\r\n case 'descender':\r\n ctx.textBaseline = 'bottom';\r\n break;\r\n }\r\n }\r\n ctx.font = this._getFontDeclaration(charStyle, forMeasuring);\r\n },\r\n\r\n /**\r\n * calculate and return the text Width measuring each line.\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @return {Number} Maximum width of fabric.Text object\r\n */\r\n calcTextWidth: function() {\r\n var maxWidth = this.getLineWidth(0);\r\n\r\n for (var i = 1, len = this._textLines.length; i < len; i++) {\r\n var currentLineWidth = this.getLineWidth(i);\r\n if (currentLineWidth > maxWidth) {\r\n maxWidth = currentLineWidth;\r\n }\r\n }\r\n return maxWidth;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {String} method Method name (\"fillText\" or \"strokeText\")\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @param {String} line Text to render\r\n * @param {Number} left Left position of text\r\n * @param {Number} top Top position of text\r\n * @param {Number} lineIndex Index of a line in a text\r\n */\r\n _renderTextLine: function(method, ctx, line, left, top, lineIndex) {\r\n this._renderChars(method, ctx, line, left, top, lineIndex);\r\n },\r\n\r\n /**\r\n * Renders the text background for lines, taking care of style\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _renderTextLinesBackground: function(ctx) {\r\n if (!this.textBackgroundColor && !this.styleHas('textBackgroundColor')) {\r\n return;\r\n }\r\n var heightOfLine,\r\n lineLeftOffset, originalFill = ctx.fillStyle,\r\n line, lastColor,\r\n leftOffset = this._getLeftOffset(),\r\n lineTopOffset = this._getTopOffset(),\r\n boxStart = 0, boxWidth = 0, charBox, currentColor, path = this.path,\r\n drawStart;\r\n\r\n for (var i = 0, len = this._textLines.length; i < len; i++) {\r\n heightOfLine = this.getHeightOfLine(i);\r\n if (!this.textBackgroundColor && !this.styleHas('textBackgroundColor', i)) {\r\n lineTopOffset += heightOfLine;\r\n continue;\r\n }\r\n line = this._textLines[i];\r\n lineLeftOffset = this._getLineLeftOffset(i);\r\n boxWidth = 0;\r\n boxStart = 0;\r\n lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\r\n for (var j = 0, jlen = line.length; j < jlen; j++) {\r\n charBox = this.__charBounds[i][j];\r\n currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\r\n if (path) {\r\n ctx.save();\r\n ctx.translate(charBox.renderLeft, charBox.renderTop);\r\n ctx.rotate(charBox.angle);\r\n ctx.fillStyle = currentColor;\r\n currentColor && ctx.fillRect(\r\n -charBox.width / 2,\r\n -heightOfLine / this.lineHeight * (1 - this._fontSizeFraction),\r\n charBox.width,\r\n heightOfLine / this.lineHeight\r\n );\r\n ctx.restore();\r\n }\r\n else if (currentColor !== lastColor) {\r\n drawStart = leftOffset + lineLeftOffset + boxStart;\r\n if (this.direction === 'rtl') {\r\n drawStart = this.width - drawStart - boxWidth;\r\n }\r\n ctx.fillStyle = lastColor;\r\n lastColor && ctx.fillRect(\r\n drawStart,\r\n lineTopOffset,\r\n boxWidth,\r\n heightOfLine / this.lineHeight\r\n );\r\n boxStart = charBox.left;\r\n boxWidth = charBox.width;\r\n lastColor = currentColor;\r\n }\r\n else {\r\n boxWidth += charBox.kernedWidth;\r\n }\r\n }\r\n if (currentColor && !path) {\r\n drawStart = leftOffset + lineLeftOffset + boxStart;\r\n if (this.direction === 'rtl') {\r\n drawStart = this.width - drawStart - boxWidth;\r\n }\r\n ctx.fillStyle = currentColor;\r\n ctx.fillRect(\r\n drawStart,\r\n lineTopOffset,\r\n boxWidth,\r\n heightOfLine / this.lineHeight\r\n );\r\n }\r\n lineTopOffset += heightOfLine;\r\n }\r\n ctx.fillStyle = originalFill;\r\n // if there is text background color no\r\n // other shadows should be casted\r\n this._removeShadow(ctx);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Object} decl style declaration for cache\r\n * @param {String} decl.fontFamily fontFamily\r\n * @param {String} decl.fontStyle fontStyle\r\n * @param {String} decl.fontWeight fontWeight\r\n * @return {Object} reference to cache\r\n */\r\n getFontCache: function(decl) {\r\n var fontFamily = decl.fontFamily.toLowerCase();\r\n if (!fabric.charWidthsCache[fontFamily]) {\r\n fabric.charWidthsCache[fontFamily] = { };\r\n }\r\n var cache = fabric.charWidthsCache[fontFamily],\r\n cacheProp = decl.fontStyle.toLowerCase() + '_' + (decl.fontWeight + '').toLowerCase();\r\n if (!cache[cacheProp]) {\r\n cache[cacheProp] = { };\r\n }\r\n return cache[cacheProp];\r\n },\r\n\r\n /**\r\n * measure and return the width of a single character.\r\n * possibly overridden to accommodate different measure logic or\r\n * to hook some external lib for character measurement\r\n * @private\r\n * @param {String} _char, char to be measured\r\n * @param {Object} charStyle style of char to be measured\r\n * @param {String} [previousChar] previous char\r\n * @param {Object} [prevCharStyle] style of previous char\r\n */\r\n _measureChar: function(_char, charStyle, previousChar, prevCharStyle) {\r\n // first i try to return from cache\r\n var fontCache = this.getFontCache(charStyle), fontDeclaration = this._getFontDeclaration(charStyle),\r\n previousFontDeclaration = this._getFontDeclaration(prevCharStyle), couple = previousChar + _char,\r\n stylesAreEqual = fontDeclaration === previousFontDeclaration, width, coupleWidth, previousWidth,\r\n fontMultiplier = charStyle.fontSize / this.CACHE_FONT_SIZE, kernedWidth;\r\n\r\n if (previousChar && fontCache[previousChar] !== undefined) {\r\n previousWidth = fontCache[previousChar];\r\n }\r\n if (fontCache[_char] !== undefined) {\r\n kernedWidth = width = fontCache[_char];\r\n }\r\n if (stylesAreEqual && fontCache[couple] !== undefined) {\r\n coupleWidth = fontCache[couple];\r\n kernedWidth = coupleWidth - previousWidth;\r\n }\r\n if (width === undefined || previousWidth === undefined || coupleWidth === undefined) {\r\n var ctx = this.getMeasuringContext();\r\n // send a TRUE to specify measuring font size CACHE_FONT_SIZE\r\n this._setTextStyles(ctx, charStyle, true);\r\n }\r\n if (width === undefined) {\r\n kernedWidth = width = ctx.measureText(_char).width;\r\n fontCache[_char] = width;\r\n }\r\n if (previousWidth === undefined && stylesAreEqual && previousChar) {\r\n previousWidth = ctx.measureText(previousChar).width;\r\n fontCache[previousChar] = previousWidth;\r\n }\r\n if (stylesAreEqual && coupleWidth === undefined) {\r\n // we can measure the kerning couple and subtract the width of the previous character\r\n coupleWidth = ctx.measureText(couple).width;\r\n fontCache[couple] = coupleWidth;\r\n kernedWidth = coupleWidth - previousWidth;\r\n }\r\n return { width: width * fontMultiplier, kernedWidth: kernedWidth * fontMultiplier };\r\n },\r\n\r\n /**\r\n * Computes height of character at given position\r\n * @param {Number} line the line index number\r\n * @param {Number} _char the character index number\r\n * @return {Number} fontSize of the character\r\n */\r\n getHeightOfChar: function(line, _char) {\r\n return this.getValueOfPropertyAt(line, _char, 'fontSize');\r\n },\r\n\r\n /**\r\n * measure a text line measuring all characters.\r\n * @param {Number} lineIndex line number\r\n * @return {Number} Line width\r\n */\r\n measureLine: function(lineIndex) {\r\n var lineInfo = this._measureLine(lineIndex);\r\n if (this.charSpacing !== 0) {\r\n lineInfo.width -= this._getWidthOfCharSpacing();\r\n }\r\n if (lineInfo.width < 0) {\r\n lineInfo.width = 0;\r\n }\r\n return lineInfo;\r\n },\r\n\r\n /**\r\n * measure every grapheme of a line, populating __charBounds\r\n * @param {Number} lineIndex\r\n * @return {Object} object.width total width of characters\r\n * @return {Object} object.widthOfSpaces length of chars that match this._reSpacesAndTabs\r\n */\r\n _measureLine: function(lineIndex) {\r\n var width = 0, i, grapheme, line = this._textLines[lineIndex], prevGrapheme,\r\n graphemeInfo, numOfSpaces = 0, lineBounds = new Array(line.length),\r\n positionInPath = 0, startingPoint, totalPathLength, path = this.path,\r\n reverse = this.pathSide === 'right';\r\n\r\n this.__charBounds[lineIndex] = lineBounds;\r\n for (i = 0; i < line.length; i++) {\r\n grapheme = line[i];\r\n graphemeInfo = this._getGraphemeBox(grapheme, lineIndex, i, prevGrapheme);\r\n lineBounds[i] = graphemeInfo;\r\n width += graphemeInfo.kernedWidth;\r\n prevGrapheme = grapheme;\r\n }\r\n // this latest bound box represent the last character of the line\r\n // to simplify cursor handling in interactive mode.\r\n lineBounds[i] = {\r\n left: graphemeInfo ? graphemeInfo.left + graphemeInfo.width : 0,\r\n width: 0,\r\n kernedWidth: 0,\r\n height: this.fontSize\r\n };\r\n if (path) {\r\n totalPathLength = path.segmentsInfo[path.segmentsInfo.length - 1].length;\r\n startingPoint = fabric.util.getPointOnPath(path.path, 0, path.segmentsInfo);\r\n startingPoint.x += path.pathOffset.x;\r\n startingPoint.y += path.pathOffset.y;\r\n switch (this.textAlign) {\r\n case 'left':\r\n positionInPath = reverse ? (totalPathLength - width) : 0;\r\n break;\r\n case 'center':\r\n positionInPath = (totalPathLength - width) / 2;\r\n break;\r\n case 'right':\r\n positionInPath = reverse ? 0 : (totalPathLength - width);\r\n break;\r\n //todo - add support for justify\r\n }\r\n positionInPath += this.pathStartOffset * (reverse ? -1 : 1);\r\n for (i = reverse ? line.length - 1 : 0;\r\n reverse ? i >= 0 : i < line.length;\r\n reverse ? i-- : i++) {\r\n graphemeInfo = lineBounds[i];\r\n if (positionInPath > totalPathLength) {\r\n positionInPath %= totalPathLength;\r\n }\r\n else if (positionInPath < 0) {\r\n positionInPath += totalPathLength;\r\n }\r\n // it would probably much faster to send all the grapheme position for a line\r\n // and calculate path position/angle at once.\r\n this._setGraphemeOnPath(positionInPath, graphemeInfo, startingPoint);\r\n positionInPath += graphemeInfo.kernedWidth;\r\n }\r\n }\r\n return { width: width, numOfSpaces: numOfSpaces };\r\n },\r\n\r\n /**\r\n * Calculate the angle and the left,top position of the char that follow a path.\r\n * It appends it to graphemeInfo to be reused later at rendering\r\n * @private\r\n * @param {Number} positionInPath to be measured\r\n * @param {Object} graphemeInfo current grapheme box information\r\n * @param {Object} startingPoint position of the point\r\n */\r\n _setGraphemeOnPath: function(positionInPath, graphemeInfo, startingPoint) {\r\n var centerPosition = positionInPath + graphemeInfo.kernedWidth / 2,\r\n path = this.path;\r\n\r\n // we are at currentPositionOnPath. we want to know what point on the path is.\r\n var info = fabric.util.getPointOnPath(path.path, centerPosition, path.segmentsInfo);\r\n graphemeInfo.renderLeft = info.x - startingPoint.x;\r\n graphemeInfo.renderTop = info.y - startingPoint.y;\r\n graphemeInfo.angle = info.angle + (this.pathSide === 'right' ? Math.PI : 0);\r\n },\r\n\r\n /**\r\n * Measure and return the info of a single grapheme.\r\n * needs the the info of previous graphemes already filled\r\n * @private\r\n * @param {String} grapheme to be measured\r\n * @param {Number} lineIndex index of the line where the char is\r\n * @param {Number} charIndex position in the line\r\n * @param {String} [prevGrapheme] character preceding the one to be measured\r\n */\r\n _getGraphemeBox: function(grapheme, lineIndex, charIndex, prevGrapheme, skipLeft) {\r\n var style = this.getCompleteStyleDeclaration(lineIndex, charIndex),\r\n prevStyle = prevGrapheme ? this.getCompleteStyleDeclaration(lineIndex, charIndex - 1) : { },\r\n info = this._measureChar(grapheme, style, prevGrapheme, prevStyle),\r\n kernedWidth = info.kernedWidth,\r\n width = info.width, charSpacing;\r\n\r\n if (this.charSpacing !== 0) {\r\n charSpacing = this._getWidthOfCharSpacing();\r\n width += charSpacing;\r\n kernedWidth += charSpacing;\r\n }\r\n\r\n var box = {\r\n width: width,\r\n left: 0,\r\n height: style.fontSize,\r\n kernedWidth: kernedWidth,\r\n deltaY: style.deltaY,\r\n };\r\n if (charIndex > 0 && !skipLeft) {\r\n var previousBox = this.__charBounds[lineIndex][charIndex - 1];\r\n box.left = previousBox.left + previousBox.width + info.kernedWidth - info.width;\r\n }\r\n return box;\r\n },\r\n\r\n /**\r\n * Calculate height of line at 'lineIndex'\r\n * @param {Number} lineIndex index of line to calculate\r\n * @return {Number}\r\n */\r\n getHeightOfLine: function(lineIndex) {\r\n if (this.__lineHeights[lineIndex]) {\r\n return this.__lineHeights[lineIndex];\r\n }\r\n\r\n var line = this._textLines[lineIndex],\r\n // char 0 is measured before the line cycle because it nneds to char\r\n // emptylines\r\n maxHeight = this.getHeightOfChar(lineIndex, 0);\r\n for (var i = 1, len = line.length; i < len; i++) {\r\n maxHeight = Math.max(this.getHeightOfChar(lineIndex, i), maxHeight);\r\n }\r\n\r\n return this.__lineHeights[lineIndex] = maxHeight * this.lineHeight * this._fontSizeMult;\r\n },\r\n\r\n /**\r\n * Calculate text box height\r\n */\r\n calcTextHeight: function() {\r\n var lineHeight, height = 0;\r\n for (var i = 0, len = this._textLines.length; i < len; i++) {\r\n lineHeight = this.getHeightOfLine(i);\r\n height += (i === len - 1 ? lineHeight / this.lineHeight : lineHeight);\r\n }\r\n return height;\r\n },\r\n\r\n /**\r\n * @private\r\n * @return {Number} Left offset\r\n */\r\n _getLeftOffset: function() {\r\n return this.direction === 'ltr' ? -this.width / 2 : this.width / 2;\r\n },\r\n\r\n /**\r\n * @private\r\n * @return {Number} Top offset\r\n */\r\n _getTopOffset: function() {\r\n return -this.height / 2;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @param {String} method Method name (\"fillText\" or \"strokeText\")\r\n */\r\n _renderTextCommon: function(ctx, method) {\r\n ctx.save();\r\n var lineHeights = 0, left = this._getLeftOffset(), top = this._getTopOffset();\r\n for (var i = 0, len = this._textLines.length; i < len; i++) {\r\n var heightOfLine = this.getHeightOfLine(i),\r\n maxHeight = heightOfLine / this.lineHeight,\r\n leftOffset = this._getLineLeftOffset(i);\r\n this._renderTextLine(\r\n method,\r\n ctx,\r\n this._textLines[i],\r\n left + leftOffset,\r\n top + lineHeights + maxHeight,\r\n i\r\n );\r\n lineHeights += heightOfLine;\r\n }\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _renderTextFill: function(ctx) {\r\n if (!this.fill && !this.styleHas('fill')) {\r\n return;\r\n }\r\n\r\n this._renderTextCommon(ctx, 'fillText');\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _renderTextStroke: function(ctx) {\r\n if ((!this.stroke || this.strokeWidth === 0) && this.isEmptyStyles()) {\r\n return;\r\n }\r\n\r\n if (this.shadow && !this.shadow.affectStroke) {\r\n this._removeShadow(ctx);\r\n }\r\n\r\n ctx.save();\r\n this._setLineDash(ctx, this.strokeDashArray);\r\n ctx.beginPath();\r\n this._renderTextCommon(ctx, 'strokeText');\r\n ctx.closePath();\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {String} method fillText or strokeText.\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @param {Array} line Content of the line, splitted in an array by grapheme\r\n * @param {Number} left\r\n * @param {Number} top\r\n * @param {Number} lineIndex\r\n */\r\n _renderChars: function(method, ctx, line, left, top, lineIndex) {\r\n // set proper line offset\r\n var lineHeight = this.getHeightOfLine(lineIndex),\r\n isJustify = this.textAlign.indexOf('justify') !== -1,\r\n actualStyle,\r\n nextStyle,\r\n charsToRender = '',\r\n charBox,\r\n boxWidth = 0,\r\n timeToRender,\r\n path = this.path,\r\n shortCut = !isJustify && this.charSpacing === 0 && this.isEmptyStyles(lineIndex) && !path,\r\n isLtr = this.direction === 'ltr', sign = this.direction === 'ltr' ? 1 : -1,\r\n drawingLeft, currentDirection = ctx.canvas.getAttribute('dir');\r\n ctx.save();\r\n if (currentDirection !== this.direction) {\r\n ctx.canvas.setAttribute('dir', isLtr ? 'ltr' : 'rtl');\r\n ctx.direction = isLtr ? 'ltr' : 'rtl';\r\n ctx.textAlign = isLtr ? 'left' : 'right';\r\n }\r\n top -= lineHeight * this._fontSizeFraction / this.lineHeight;\r\n if (shortCut) {\r\n // render all the line in one pass without checking\r\n // drawingLeft = isLtr ? left : left - this.getLineWidth(lineIndex);\r\n this._renderChar(method, ctx, lineIndex, 0, line.join(''), left, top, lineHeight);\r\n ctx.restore();\r\n return;\r\n }\r\n for (var i = 0, len = line.length - 1; i <= len; i++) {\r\n timeToRender = i === len || this.charSpacing || path;\r\n charsToRender += line[i];\r\n charBox = this.__charBounds[lineIndex][i];\r\n if (boxWidth === 0) {\r\n left += sign * (charBox.kernedWidth - charBox.width);\r\n boxWidth += charBox.width;\r\n }\r\n else {\r\n boxWidth += charBox.kernedWidth;\r\n }\r\n if (isJustify && !timeToRender) {\r\n if (this._reSpaceAndTab.test(line[i])) {\r\n timeToRender = true;\r\n }\r\n }\r\n if (!timeToRender) {\r\n // if we have charSpacing, we render char by char\r\n actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\r\n nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\r\n timeToRender = fabric.util.hasStyleChanged(actualStyle, nextStyle, false);\r\n }\r\n if (timeToRender) {\r\n if (path) {\r\n ctx.save();\r\n ctx.translate(charBox.renderLeft, charBox.renderTop);\r\n ctx.rotate(charBox.angle);\r\n this._renderChar(method, ctx, lineIndex, i, charsToRender, -boxWidth / 2, 0, lineHeight);\r\n ctx.restore();\r\n }\r\n else {\r\n drawingLeft = left;\r\n this._renderChar(method, ctx, lineIndex, i, charsToRender, drawingLeft, top, lineHeight);\r\n }\r\n charsToRender = '';\r\n actualStyle = nextStyle;\r\n left += sign * boxWidth;\r\n boxWidth = 0;\r\n }\r\n }\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * This function try to patch the missing gradientTransform on canvas gradients.\r\n * transforming a context to transform the gradient, is going to transform the stroke too.\r\n * we want to transform the gradient but not the stroke operation, so we create\r\n * a transformed gradient on a pattern and then we use the pattern instead of the gradient.\r\n * this method has drawbacks: is slow, is in low resolution, needs a patch for when the size\r\n * is limited.\r\n * @private\r\n * @param {fabric.Gradient} filler a fabric gradient instance\r\n * @return {CanvasPattern} a pattern to use as fill/stroke style\r\n */\r\n _applyPatternGradientTransformText: function(filler) {\r\n var pCanvas = fabric.util.createCanvasElement(), pCtx,\r\n // TODO: verify compatibility with strokeUniform\r\n width = this.width + this.strokeWidth, height = this.height + this.strokeWidth;\r\n pCanvas.width = width;\r\n pCanvas.height = height;\r\n pCtx = pCanvas.getContext('2d', { willReadFrequently: true });\r\n pCtx.beginPath(); pCtx.moveTo(0, 0); pCtx.lineTo(width, 0); pCtx.lineTo(width, height);\r\n pCtx.lineTo(0, height); pCtx.closePath();\r\n pCtx.translate(width / 2, height / 2);\r\n pCtx.fillStyle = filler.toLive(pCtx);\r\n this._applyPatternGradientTransform(pCtx, filler);\r\n pCtx.fill();\r\n return pCtx.createPattern(pCanvas, 'no-repeat');\r\n },\r\n\r\n handleFiller: function(ctx, property, filler) {\r\n var offsetX, offsetY;\r\n if (filler.toLive) {\r\n if (filler.gradientUnits === 'percentage' || filler.gradientTransform || filler.patternTransform) {\r\n // need to transform gradient in a pattern.\r\n // this is a slow process. If you are hitting this codepath, and the object\r\n // is not using caching, you should consider switching it on.\r\n // we need a canvas as big as the current object caching canvas.\r\n offsetX = -this.width / 2;\r\n offsetY = -this.height / 2;\r\n ctx.translate(offsetX, offsetY);\r\n ctx[property] = this._applyPatternGradientTransformText(filler);\r\n return { offsetX: offsetX, offsetY: offsetY };\r\n }\r\n else {\r\n // is a simple gradient or pattern\r\n ctx[property] = filler.toLive(ctx, this);\r\n return this._applyPatternGradientTransform(ctx, filler);\r\n }\r\n }\r\n else {\r\n // is a color\r\n ctx[property] = filler;\r\n }\r\n return { offsetX: 0, offsetY: 0 };\r\n },\r\n\r\n _setStrokeStyles: function(ctx, decl) {\r\n ctx.lineWidth = decl.strokeWidth;\r\n ctx.lineCap = this.strokeLineCap;\r\n ctx.lineDashOffset = this.strokeDashOffset;\r\n ctx.lineJoin = this.strokeLineJoin;\r\n ctx.miterLimit = this.strokeMiterLimit;\r\n return this.handleFiller(ctx, 'strokeStyle', decl.stroke);\r\n },\r\n\r\n _setFillStyles: function(ctx, decl) {\r\n return this.handleFiller(ctx, 'fillStyle', decl.fill);\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {String} method\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n * @param {Number} lineIndex\r\n * @param {Number} charIndex\r\n * @param {String} _char\r\n * @param {Number} left Left coordinate\r\n * @param {Number} top Top coordinate\r\n * @param {Number} lineHeight Height of the line\r\n */\r\n _renderChar: function(method, ctx, lineIndex, charIndex, _char, left, top) {\r\n var decl = this._getStyleDeclaration(lineIndex, charIndex),\r\n fullDecl = this.getCompleteStyleDeclaration(lineIndex, charIndex),\r\n shouldFill = method === 'fillText' && fullDecl.fill,\r\n shouldStroke = method === 'strokeText' && fullDecl.stroke && fullDecl.strokeWidth,\r\n fillOffsets, strokeOffsets;\r\n\r\n if (!shouldStroke && !shouldFill) {\r\n return;\r\n }\r\n ctx.save();\r\n\r\n shouldFill && (fillOffsets = this._setFillStyles(ctx, fullDecl));\r\n shouldStroke && (strokeOffsets = this._setStrokeStyles(ctx, fullDecl));\r\n\r\n ctx.font = this._getFontDeclaration(fullDecl);\r\n\r\n\r\n if (decl && decl.textBackgroundColor) {\r\n this._removeShadow(ctx);\r\n }\r\n if (decl && decl.deltaY) {\r\n top += decl.deltaY;\r\n }\r\n shouldFill && ctx.fillText(_char, left - fillOffsets.offsetX, top - fillOffsets.offsetY);\r\n shouldStroke && ctx.strokeText(_char, left - strokeOffsets.offsetX, top - strokeOffsets.offsetY);\r\n ctx.restore();\r\n },\r\n\r\n /**\r\n * Turns the character into a 'superior figure' (i.e. 'superscript')\r\n * @param {Number} start selection start\r\n * @param {Number} end selection end\r\n * @returns {fabric.Text} thisArg\r\n * @chainable\r\n */\r\n setSuperscript: function(start, end) {\r\n return this._setScript(start, end, this.superscript);\r\n },\r\n\r\n /**\r\n * Turns the character into an 'inferior figure' (i.e. 'subscript')\r\n * @param {Number} start selection start\r\n * @param {Number} end selection end\r\n * @returns {fabric.Text} thisArg\r\n * @chainable\r\n */\r\n setSubscript: function(start, end) {\r\n return this._setScript(start, end, this.subscript);\r\n },\r\n\r\n /**\r\n * Applies 'schema' at given position\r\n * @private\r\n * @param {Number} start selection start\r\n * @param {Number} end selection end\r\n * @param {Number} schema\r\n * @returns {fabric.Text} thisArg\r\n * @chainable\r\n */\r\n _setScript: function(start, end, schema) {\r\n var loc = this.get2DCursorLocation(start, true),\r\n fontSize = this.getValueOfPropertyAt(loc.lineIndex, loc.charIndex, 'fontSize'),\r\n dy = this.getValueOfPropertyAt(loc.lineIndex, loc.charIndex, 'deltaY'),\r\n style = { fontSize: fontSize * schema.size, deltaY: dy + fontSize * schema.baseline };\r\n this.setSelectionStyles(style, start, end);\r\n return this;\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {Number} lineIndex index text line\r\n * @return {Number} Line left offset\r\n */\r\n _getLineLeftOffset: function(lineIndex) {\r\n var lineWidth = this.getLineWidth(lineIndex),\r\n lineDiff = this.width - lineWidth, textAlign = this.textAlign, direction = this.direction,\r\n isEndOfWrapping, leftOffset = 0, isEndOfWrapping = this.isEndOfWrapping(lineIndex);\r\n if (textAlign === 'justify'\r\n || (textAlign === 'justify-center' && !isEndOfWrapping)\r\n || (textAlign === 'justify-right' && !isEndOfWrapping)\r\n || (textAlign === 'justify-left' && !isEndOfWrapping)\r\n ) {\r\n return 0;\r\n }\r\n if (textAlign === 'center') {\r\n leftOffset = lineDiff / 2;\r\n }\r\n if (textAlign === 'right') {\r\n leftOffset = lineDiff;\r\n }\r\n if (textAlign === 'justify-center') {\r\n leftOffset = lineDiff / 2;\r\n }\r\n if (textAlign === 'justify-right') {\r\n leftOffset = lineDiff;\r\n }\r\n if (direction === 'rtl') {\r\n leftOffset -= lineDiff;\r\n }\r\n return leftOffset;\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _clearCache: function() {\r\n this.__lineWidths = [];\r\n this.__lineHeights = [];\r\n this.__charBounds = [];\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _shouldClearDimensionCache: function() {\r\n var shouldClear = this._forceClearCache;\r\n shouldClear || (shouldClear = this.hasStateChanged('_dimensionAffectingProps'));\r\n if (shouldClear) {\r\n this.dirty = true;\r\n this._forceClearCache = false;\r\n }\r\n return shouldClear;\r\n },\r\n\r\n /**\r\n * Measure a single line given its index. Used to calculate the initial\r\n * text bounding box. The values are calculated and stored in __lineWidths cache.\r\n * @private\r\n * @param {Number} lineIndex line number\r\n * @return {Number} Line width\r\n */\r\n getLineWidth: function(lineIndex) {\r\n if (this.__lineWidths[lineIndex] !== undefined) {\r\n return this.__lineWidths[lineIndex];\r\n }\r\n\r\n var lineInfo = this.measureLine(lineIndex);\r\n var width = lineInfo.width;\r\n this.__lineWidths[lineIndex] = width;\r\n return width;\r\n },\r\n\r\n _getWidthOfCharSpacing: function() {\r\n if (this.charSpacing !== 0) {\r\n return this.fontSize * this.charSpacing / 1000;\r\n }\r\n return 0;\r\n },\r\n\r\n /**\r\n * Retrieves the value of property at given character position\r\n * @param {Number} lineIndex the line number\r\n * @param {Number} charIndex the character number\r\n * @param {String} property the property name\r\n * @returns the value of 'property'\r\n */\r\n getValueOfPropertyAt: function(lineIndex, charIndex, property) {\r\n var charStyle = this._getStyleDeclaration(lineIndex, charIndex);\r\n if (charStyle && typeof charStyle[property] !== 'undefined') {\r\n return charStyle[property];\r\n }\r\n return this[property];\r\n },\r\n\r\n /**\r\n * @private\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n _renderTextDecoration: function(ctx, type) {\r\n if (!this[type] && !this.styleHas(type)) {\r\n return;\r\n }\r\n var heightOfLine, size, _size,\r\n lineLeftOffset, dy, _dy,\r\n line, lastDecoration,\r\n leftOffset = this._getLeftOffset(),\r\n topOffset = this._getTopOffset(), top,\r\n boxStart, boxWidth, charBox, currentDecoration,\r\n maxHeight, currentFill, lastFill, path = this.path,\r\n charSpacing = this._getWidthOfCharSpacing(),\r\n offsetY = this.offsets[type];\r\n\r\n for (var i = 0, len = this._textLines.length; i < len; i++) {\r\n heightOfLine = this.getHeightOfLine(i);\r\n if (!this[type] && !this.styleHas(type, i)) {\r\n topOffset += heightOfLine;\r\n continue;\r\n }\r\n line = this._textLines[i];\r\n maxHeight = heightOfLine / this.lineHeight;\r\n lineLeftOffset = this._getLineLeftOffset(i);\r\n boxStart = 0;\r\n boxWidth = 0;\r\n lastDecoration = this.getValueOfPropertyAt(i, 0, type);\r\n lastFill = this.getValueOfPropertyAt(i, 0, 'fill');\r\n top = topOffset + maxHeight * (1 - this._fontSizeFraction);\r\n size = this.getHeightOfChar(i, 0);\r\n dy = this.getValueOfPropertyAt(i, 0, 'deltaY');\r\n for (var j = 0, jlen = line.length; j < jlen; j++) {\r\n charBox = this.__charBounds[i][j];\r\n currentDecoration = this.getValueOfPropertyAt(i, j, type);\r\n currentFill = this.getValueOfPropertyAt(i, j, 'fill');\r\n _size = this.getHeightOfChar(i, j);\r\n _dy = this.getValueOfPropertyAt(i, j, 'deltaY');\r\n if (path && currentDecoration && currentFill) {\r\n ctx.save();\r\n ctx.fillStyle = lastFill;\r\n ctx.translate(charBox.renderLeft, charBox.renderTop);\r\n ctx.rotate(charBox.angle);\r\n ctx.fillRect(\r\n -charBox.kernedWidth / 2,\r\n offsetY * _size + _dy,\r\n charBox.kernedWidth,\r\n this.fontSize / 15\r\n );\r\n ctx.restore();\r\n }\r\n else if (\r\n (currentDecoration !== lastDecoration || currentFill !== lastFill || _size !== size || _dy !== dy)\r\n && boxWidth > 0\r\n ) {\r\n var drawStart = leftOffset + lineLeftOffset + boxStart;\r\n if (this.direction === 'rtl') {\r\n drawStart = this.width - drawStart - boxWidth;\r\n }\r\n if (lastDecoration && lastFill) {\r\n ctx.fillStyle = lastFill;\r\n ctx.fillRect(\r\n drawStart,\r\n top + offsetY * size + dy,\r\n boxWidth,\r\n this.fontSize / 15\r\n );\r\n }\r\n boxStart = charBox.left;\r\n boxWidth = charBox.width;\r\n lastDecoration = currentDecoration;\r\n lastFill = currentFill;\r\n size = _size;\r\n dy = _dy;\r\n }\r\n else {\r\n boxWidth += charBox.kernedWidth;\r\n }\r\n }\r\n var drawStart = leftOffset + lineLeftOffset + boxStart;\r\n if (this.direction === 'rtl') {\r\n drawStart = this.width - drawStart - boxWidth;\r\n }\r\n ctx.fillStyle = currentFill;\r\n currentDecoration && currentFill && ctx.fillRect(\r\n drawStart,\r\n top + offsetY * size + dy,\r\n boxWidth - charSpacing,\r\n this.fontSize / 15\r\n );\r\n topOffset += heightOfLine;\r\n }\r\n // if there is text background color no\r\n // other shadows should be casted\r\n this._removeShadow(ctx);\r\n },\r\n\r\n /**\r\n * return font declaration string for canvas context\r\n * @param {Object} [styleObject] object\r\n * @returns {String} font declaration formatted for canvas context.\r\n */\r\n _getFontDeclaration: function(styleObject, forMeasuring) {\r\n var style = styleObject || this, family = this.fontFamily,\r\n fontIsGeneric = fabric.Text.genericFonts.indexOf(family.toLowerCase()) > -1;\r\n var fontFamily = family === undefined ||\r\n family.indexOf('\\'') > -1 || family.indexOf(',') > -1 ||\r\n family.indexOf('\"') > -1 || fontIsGeneric\r\n ? style.fontFamily : '\"' + style.fontFamily + '\"';\r\n return [\r\n // node-canvas needs \"weight style\", while browsers need \"style weight\"\r\n // verify if this can be fixed in JSDOM\r\n (fabric.isLikelyNode ? style.fontWeight : style.fontStyle),\r\n (fabric.isLikelyNode ? style.fontStyle : style.fontWeight),\r\n forMeasuring ? this.CACHE_FONT_SIZE + 'px' : style.fontSize + 'px',\r\n fontFamily\r\n ].join(' ');\r\n },\r\n\r\n /**\r\n * Renders text instance on a specified context\r\n * @param {CanvasRenderingContext2D} ctx Context to render on\r\n */\r\n render: function(ctx) {\r\n // do not render if object is not visible\r\n if (!this.visible) {\r\n return;\r\n }\r\n if (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) {\r\n return;\r\n }\r\n if (this._shouldClearDimensionCache()) {\r\n this.initDimensions();\r\n }\r\n this.callSuper('render', ctx);\r\n },\r\n\r\n /**\r\n * Returns the text as an array of lines.\r\n * @param {String} text text to split\r\n * @returns {Array} Lines in the text\r\n */\r\n _splitTextIntoLines: function(text) {\r\n var lines = text.split(this._reNewline),\r\n newLines = new Array(lines.length),\r\n newLine = ['\\n'],\r\n newText = [];\r\n for (var i = 0; i < lines.length; i++) {\r\n newLines[i] = fabric.util.string.graphemeSplit(lines[i]);\r\n newText = newText.concat(newLines[i], newLine);\r\n }\r\n newText.pop();\r\n return { _unwrappedLines: newLines, lines: lines, graphemeText: newText, graphemeLines: newLines };\r\n },\r\n\r\n /**\r\n * Returns object representation of an instance\r\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\r\n * @return {Object} Object representation of an instance\r\n */\r\n toObject: function(propertiesToInclude) {\r\n var allProperties = additionalProps.concat(propertiesToInclude);\r\n var obj = this.callSuper('toObject', allProperties);\r\n obj.styles = fabric.util.stylesToArray(this.styles, this.text);\r\n if (obj.path) {\r\n obj.path = this.path.toObject();\r\n }\r\n return obj;\r\n },\r\n\r\n /**\r\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()`.\r\n * @param {String|Object} key Property name or object (if object, iterate over the object properties)\r\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)\r\n * @return {fabric.Object} thisArg\r\n * @chainable\r\n */\r\n set: function(key, value) {\r\n this.callSuper('set', key, value);\r\n var needsDims = false;\r\n var isAddingPath = false;\r\n if (typeof key === 'object') {\r\n for (var _key in key) {\r\n if (_key === 'path') {\r\n this.setPathInfo();\r\n }\r\n needsDims = needsDims || this._dimensionAffectingProps.indexOf(_key) !== -1;\r\n isAddingPath = isAddingPath || _key === 'path';\r\n }\r\n }\r\n else {\r\n needsDims = this._dimensionAffectingProps.indexOf(key) !== -1;\r\n isAddingPath = key === 'path';\r\n }\r\n if (isAddingPath) {\r\n this.setPathInfo();\r\n }\r\n if (needsDims) {\r\n this.initDimensions();\r\n this.setCoords();\r\n }\r\n return this;\r\n },\r\n\r\n /**\r\n * Returns complexity of an instance\r\n * @return {Number} complexity\r\n */\r\n complexity: function() {\r\n return 1;\r\n }\r\n });\r\n\r\n /* _FROM_SVG_START_ */\r\n /**\r\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Text.fromElement})\r\n * @static\r\n * @memberOf fabric.Text\r\n * @see: http://www.w3.org/TR/SVG/text.html#TextElement\r\n */\r\n fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(\r\n 'x y dx dy font-family font-style font-weight font-size letter-spacing text-decoration text-anchor'.split(' '));\r\n\r\n /**\r\n * Default SVG font size\r\n * @static\r\n * @memberOf fabric.Text\r\n */\r\n fabric.Text.DEFAULT_SVG_FONT_SIZE = 16;\r\n\r\n /**\r\n * Returns fabric.Text instance from an SVG element (not yet implemented)\r\n * @static\r\n * @memberOf fabric.Text\r\n * @param {SVGElement} element Element to parse\r\n * @param {Function} callback callback function invoked after parsing\r\n * @param {Object} [options] Options object\r\n */\r\n fabric.Text.fromElement = function(element, callback, options) {\r\n if (!element) {\r\n return callback(null);\r\n }\r\n\r\n var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES),\r\n parsedAnchor = parsedAttributes.textAnchor || 'left';\r\n options = fabric.util.object.extend((options ? clone(options) : { }), parsedAttributes);\r\n\r\n options.top = options.top || 0;\r\n options.left = options.left || 0;\r\n if (parsedAttributes.textDecoration) {\r\n var textDecoration = parsedAttributes.textDecoration;\r\n if (textDecoration.indexOf('underline') !== -1) {\r\n options.underline = true;\r\n }\r\n if (textDecoration.indexOf('overline') !== -1) {\r\n options.overline = true;\r\n }\r\n if (textDecoration.indexOf('line-through') !== -1) {\r\n options.linethrough = true;\r\n }\r\n delete options.textDecoration;\r\n }\r\n if ('dx' in parsedAttributes) {\r\n options.left += parsedAttributes.dx;\r\n }\r\n if ('dy' in parsedAttributes) {\r\n options.top += parsedAttributes.dy;\r\n }\r\n if (!('fontSize' in options)) {\r\n options.fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;\r\n }\r\n\r\n var textContent = '';\r\n\r\n // The XML is not properly parsed in IE9 so a workaround to get\r\n // textContent is through firstChild.data. Another workaround would be\r\n // to convert XML loaded from a file to be converted using DOMParser (same way loadSVGFromString() does)\r\n if (!('textContent' in element)) {\r\n if ('firstChild' in element && element.firstChild !== null) {\r\n if ('data' in element.firstChild && element.firstChild.data !== null) {\r\n textContent = element.firstChild.data;\r\n }\r\n }\r\n }\r\n else {\r\n textContent = element.textContent;\r\n }\r\n\r\n textContent = textContent.replace(/^\\s+|\\s+$|\\n+/g, '').replace(/\\s+/g, ' ');\r\n var originalStrokeWidth = options.strokeWidth;\r\n options.strokeWidth = 0;\r\n\r\n var text = new fabric.Text(textContent, options),\r\n textHeightScaleFactor = text.getScaledHeight() / text.height,\r\n lineHeightDiff = (text.height + text.strokeWidth) * text.lineHeight - text.height,\r\n scaledDiff = lineHeightDiff * textHeightScaleFactor,\r\n textHeight = text.getScaledHeight() + scaledDiff,\r\n offX = 0;\r\n /*\r\n Adjust positioning:\r\n x/y attributes in SVG correspond to the bottom-left corner of text bounding box\r\n fabric output by default at top, left.\r\n */\r\n if (parsedAnchor === 'center') {\r\n offX = text.getScaledWidth() / 2;\r\n }\r\n if (parsedAnchor === 'right') {\r\n offX = text.getScaledWidth();\r\n }\r\n text.set({\r\n left: text.left - offX,\r\n top: text.top - (textHeight - text.fontSize * (0.07 + text._fontSizeFraction)) / text.lineHeight,\r\n strokeWidth: typeof originalStrokeWidth !== 'undefined' ? originalStrokeWidth : 1,\r\n });\r\n callback(text);\r\n };\r\n /* _FROM_SVG_END_ */\r\n\r\n /**\r\n * Returns fabric.Text instance from an object representation\r\n * @static\r\n * @memberOf fabric.Text\r\n * @param {Object} object plain js Object to create an instance from\r\n * @param {Function} [callback] Callback to invoke when an fabric.Text instance is created\r\n */\r\n fabric.Text.fromObject = function(object, callback) {\r\n var objectCopy = clone(object), path = object.path;\r\n delete objectCopy.path;\r\n return fabric.Object._fromObject('Text', objectCopy, function(textInstance) {\r\n textInstance.styles = fabric.util.stylesFromArray(object.styles, object.text);\r\n if (path) {\r\n fabric.Object._fromObject('Path', path, function(pathInstance) {\r\n textInstance.set('path', pathInstance);\r\n callback(textInstance);\r\n }, 'path');\r\n }\r\n else {\r\n callback(textInstance);\r\n }\r\n }, 'text');\r\n };\r\n\r\n fabric.Text.genericFonts = ['sans-serif', 'serif', 'cursive', 'fantasy', 'monospace'];\r\n\r\n fabric.util.createAccessors && fabric.util.createAccessors(fabric.Text);\r\n\r\n})(typeof exports !== 'undefined' ? exports : this);\r\n\r\n\r\n(function() {\r\n fabric.util.object.extend(fabric.Text.prototype, /** @lends fabric.Text.prototype */ {\r\n /**\r\n * Returns true if object has no styling or no styling in a line\r\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\r\n * @return {Boolean}\r\n */\r\n isEmptyStyles: function(lineIndex) {\r\n if (!this.styles) {\r\n return true;\r\n }\r\n if (typeof lineIndex !== 'undefined' && !this.styles[lineIndex]) {\r\n return true;\r\n }\r\n var obj = typeof lineIndex === 'undefined' ? this.styles : { line: this.styles[lineIndex] };\r\n for (var p1 in obj) {\r\n for (var p2 in obj[p1]) {\r\n // eslint-disable-next-line no-unused-vars\r\n for (var p3 in obj[p1][p2]) {\r\n return false;\r\n }\r\n }\r\n }\r\n return true;\r\n },\r\n\r\n /**\r\n * Returns true if object has a style property or has it ina specified line\r\n * This function is used to detect if a text will use a particular property or not.\r\n * @param {String} property to check for\r\n * @param {Number} lineIndex to check the style on\r\n * @return {Boolean}\r\n */\r\n styleHas: function(property, lineIndex) {\r\n if (!this.styles || !property || property === '') {\r\n return false;\r\n }\r\n if (typeof lineIndex !== 'undefined' && !this.styles[lineIndex]) {\r\n return false;\r\n }\r\n var obj = typeof lineIndex === 'undefined' ? this.styles : { 0: this.styles[lineIndex] };\r\n // eslint-disable-next-line\r\n for (var p1 in obj) {\r\n // eslint-disable-next-line\r\n for (var p2 in obj[p1]) {\r\n if (typeof obj[p1][p2][property] !== 'undefined') {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n },\r\n\r\n /**\r\n * Check if characters in a text have a value for a property\r\n * whose value matches the textbox's value for that property. If so,\r\n * the character-level property is deleted. If the character\r\n * has no other properties, then it is also deleted. Finally,\r\n * if the line containing that character has no other characters\r\n * then it also is deleted.\r\n *\r\n * @param {string} property The property to compare between characters and text.\r\n */\r\n cleanStyle: function(property) {\r\n if (!this.styles || !property || property === '') {\r\n return false;\r\n }\r\n var obj = this.styles, stylesCount = 0, letterCount, stylePropertyValue,\r\n allStyleObjectPropertiesMatch = true, graphemeCount = 0, styleObject;\r\n // eslint-disable-next-line\r\n for (var p1 in obj) {\r\n letterCount = 0;\r\n // eslint-disable-next-line\r\n for (var p2 in obj[p1]) {\r\n var styleObject = obj[p1][p2],\r\n stylePropertyHasBeenSet = styleObject.hasOwnProperty(property);\r\n\r\n stylesCount++;\r\n\r\n if (stylePropertyHasBeenSet) {\r\n if (!stylePropertyValue) {\r\n stylePropertyValue = styleObject[property];\r\n }\r\n else if (styleObject[property] !== stylePropertyValue) {\r\n allStyleObjectPropertiesMatch = false;\r\n }\r\n\r\n if (styleObject[property] === this[property]) {\r\n delete styleObject[property];\r\n }\r\n }\r\n else {\r\n allStyleObjectPropertiesMatch = false;\r\n }\r\n\r\n if (Object.keys(styleObject).length !== 0) {\r\n letterCount++;\r\n }\r\n else {\r\n delete obj[p1][p2];\r\n }\r\n }\r\n\r\n if (letterCount === 0) {\r\n delete obj[p1];\r\n }\r\n }\r\n // if every grapheme has the same style set then\r\n // delete those styles and set it on the parent\r\n for (var i = 0; i < this._textLines.length; i++) {\r\n graphemeCount += this._textLines[i].length;\r\n }\r\n if (allStyleObjectPropertiesMatch && stylesCount === graphemeCount) {\r\n this[property] = stylePropertyValue;\r\n this.removeStyle(property);\r\n }\r\n },\r\n\r\n /**\r\n * Remove a style property or properties from all individual character styles\r\n * in a text object. Deletes the character style object if it contains no other style\r\n * props. Deletes a line style object if it contains no other character styles.\r\n *\r\n * @param {String} props The property to remove from character styles.\r\n */\r\n removeStyle: function(property) {\r\n if (!this.styles || !property || property === '') {\r\n return;\r\n }\r\n var obj = this.styles, line, lineNum, charNum;\r\n for (lineNum in obj) {\r\n line = obj[lineNum];\r\n for (charNum in line) {\r\n delete line[charNum][property];\r\n if (Object.keys(line[charNum]).length === 0) {\r\n delete line[charNum];\r\n }\r\n }\r\n if (Object.keys(line).length === 0) {\r\n delete obj[lineNum];\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n _extendStyles: function(index, styles) {\r\n var loc = this.get2DCursorLocation(index);\r\n\r\n if (!this._getLineStyle(loc.lineIndex)) {\r\n this._setLineStyle(loc.lineIndex);\r\n }\r\n\r\n if (!this._getStyleDeclaration(loc.lineIndex, loc.charIndex)) {\r\n this._setStyleDeclaration(loc.lineIndex, loc.charIndex, {});\r\n }\r\n\r\n fabric.util.object.extend(this._getStyleDeclaration(loc.lineIndex, loc.charIndex), styles);\r\n },\r\n\r\n /**\r\n * Returns 2d representation (lineIndex and charIndex) of cursor (or selection start)\r\n * @param {Number} [selectionStart] Optional index. When not given, current selectionStart is used.\r\n * @param {Boolean} [skipWrapping] consider the location for unwrapped lines. useful to manage styles.\r\n */\r\n get2DCursorLocation: function(selectionStart, skipWrapping) {\r\n if (typeof selectionStart === 'undefined') {\r\n selectionStart = this.selectionStart;\r\n }\r\n var lines = skipWrapping ? this._unwrappedTextLines : this._textLines,\r\n len = lines.length;\r\n for (var i = 0; i < len; i++) {\r\n if (selectionStart <= lines[i].length) {\r\n return {\r\n lineIndex: i,\r\n charIndex: selectionStart\r\n };\r\n }\r\n selectionStart -= lines[i].length + this.missingNewlineOffset(i);\r\n }\r\n return {\r\n lineIndex: i - 1,\r\n charIndex: lines[i - 1].length < selectionStart ? lines[i - 1].length : selectionStart\r\n };\r\n },\r\n\r\n /**\r\n * Gets style of a current selection/cursor (at the start position)\r\n * if startIndex or endIndex are not provided, selectionStart or selectionEnd will be used.\r\n * @param {Number} [startIndex] Start index to get styles at\r\n * @param {Number} [endIndex] End index to get styles at, if not specified selectionEnd or startIndex + 1\r\n * @param {Boolean} [complete] get full style or not\r\n * @return {Array} styles an array with one, zero or more Style objects\r\n */\r\n getSelectionStyles: function(startIndex, endIndex, complete) {\r\n if (typeof startIndex === 'undefined') {\r\n startIndex = this.selectionStart || 0;\r\n }\r\n if (typeof endIndex === 'undefined') {\r\n endIndex = this.selectionEnd || startIndex;\r\n }\r\n var styles = [];\r\n for (var i = startIndex; i < endIndex; i++) {\r\n styles.push(this.getStyleAtPosition(i, complete));\r\n }\r\n return styles;\r\n },\r\n\r\n /**\r\n * Gets style of a current selection/cursor position\r\n * @param {Number} position to get styles at\r\n * @param {Boolean} [complete] full style if true\r\n * @return {Object} style Style object at a specified index\r\n * @private\r\n */\r\n getStyleAtPosition: function(position, complete) {\r\n var loc = this.get2DCursorLocation(position),\r\n style = complete ? this.getCompleteStyleDeclaration(loc.lineIndex, loc.charIndex) :\r\n this._getStyleDeclaration(loc.lineIndex, loc.charIndex);\r\n return style || {};\r\n },\r\n\r\n /**\r\n * Sets style of a current selection, if no selection exist, do not set anything.\r\n * @param {Object} [styles] Styles object\r\n * @param {Number} [startIndex] Start index to get styles at\r\n * @param {Number} [endIndex] End index to get styles at, if not specified selectionEnd or startIndex + 1\r\n * @return {fabric.IText} thisArg\r\n * @chainable\r\n */\r\n setSelectionStyles: function(styles, startIndex, endIndex) {\r\n if (typeof startIndex === 'undefined') {\r\n startIndex = this.selectionStart || 0;\r\n }\r\n if (typeof endIndex === 'undefined') {\r\n endIndex = this.selectionEnd || startIndex;\r\n }\r\n for (var i = startIndex; i < endIndex; i++) {\r\n this._extendStyles(i, styles);\r\n }\r\n /* not included in _extendStyles to avoid clearing cache more than once */\r\n this._forceClearCache = true;\r\n return this;\r\n },\r\n\r\n /**\r\n * get the reference, not a clone, of the style object for a given character\r\n * @param {Number} lineIndex\r\n * @param {Number} charIndex\r\n * @return {Object} style object\r\n */\r\n _getStyleDeclaration: function(lineIndex, charIndex) {\r\n var lineStyle = this.styles && this.styles[lineIndex];\r\n if (!lineStyle) {\r\n return null;\r\n }\r\n return lineStyle[charIndex];\r\n },\r\n\r\n /**\r\n * return a new object that contains all the style property for a character\r\n * the object returned is newly created\r\n * @param {Number} lineIndex of the line where the character is\r\n * @param {Number} charIndex position of the character on the line\r\n * @return {Object} style object\r\n */\r\n getCompleteStyleDeclaration: function(lineIndex, charIndex) {\r\n var style = this._getStyleDeclaration(lineIndex, charIndex) || { },\r\n styleObject = { }, prop;\r\n for (var i = 0; i < this._styleProperties.length; i++) {\r\n prop = this._styleProperties[i];\r\n styleObject[prop] = typeof style[prop] === 'undefined' ? this[prop] : style[prop];\r\n }\r\n return styleObject;\r\n },\r\n\r\n /**\r\n * @param {Number} lineIndex\r\n * @param {Number} charIndex\r\n * @param {Object} style\r\n * @private\r\n */\r\n _setStyleDeclaration: function(lineIndex, charIndex, style) {\r\n this.styles[lineIndex][charIndex] = style;\r\n },\r\n\r\n /**\r\n *\r\n * @param {Number} lineIndex\r\n * @param {Number} charIndex\r\n * @private\r\n */\r\n _deleteStyleDeclaration: function(lineIndex, charIndex) {\r\n delete this.styles[lineIndex][charIndex];\r\n },\r\n\r\n /**\r\n * @param {Number} lineIndex\r\n * @return {Boolean} if the line exists or not\r\n * @private\r\n */\r\n _getLineStyle: function(lineIndex) {\r\n return !!this.styles[lineIndex];\r\n },\r\n\r\n /**\r\n * Set the line style to an empty object so that is initialized\r\n * @param {Number} lineIndex\r\n * @private\r\n */\r\n _setLineStyle: function(lineIndex) {\r\n this.styles[lineIndex] = {};\r\n },\r\n\r\n /**\r\n * @param {Number} lineIndex\r\n * @private\r\n */\r\n _deleteLineStyle: function(lineIndex) {\r\n delete this.styles[lineIndex];\r\n }\r\n });\r\n})();\r\n\r\n\r\n(function() {\r\n\r\n function parseDecoration(object) {\r\n if (object.textDecoration) {\r\n object.textDecoration.indexOf('underline') > -1 && (object.underline = true);\r\n object.textDecoration.indexOf('line-through') > -1 && (object.linethrough = true);\r\n object.textDecoration.indexOf('overline') > -1 && (object.overline = true);\r\n delete object.textDecoration;\r\n }\r\n }\r\n\r\n /**\r\n * IText class (introduced in v1.4) Events are also fired with \"text:\"\r\n * prefix when observing canvas.\r\n * @class fabric.IText\r\n * @extends fabric.Text\r\n * @mixes fabric.Observable\r\n *\r\n * @fires changed\r\n * @fires selection:changed\r\n * @fires editing:entered\r\n * @fires editing:exited\r\n *\r\n * @return {fabric.IText} thisArg\r\n * @see {@link fabric.IText#initialize} for constructor definition\r\n *\r\n *

Supported key combinations:

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

Supported mouse/touch combination

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