{"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","resizeCanvasIfNeeded","pipelineState","targetCanvas","width","height","dWidth","destinationWidth","dHeight","destinationHeight","copyGLTo2DDrawImage","gl","glCanvas","canvas","ctx","getContext","willReadFrequently","translate","scale","sourceY","drawImage","copyGLTo2DPutImageData","numBytes","u8","Uint8Array","this","imageBuffer","u8Clamped","Uint8ClampedArray","readPixels","RGBA","UNSIGNED_BYTE","imgData","ImageData","putImageData","isTouchSupported","navigator","maxTouchPoints","isLikelyNode","Buffer","SHARED_ATTRIBUTES","DPI","reNum","commaWsp","rePathCommand","reNonWord","fontPaths","iMatrix","svgNS","perfLimitSizeTotal","maxCacheSideLimit","minCacheSideLimit","charWidthsCache","textureSize","disableStyleCopyPaste","enableGLFiltering","devicePixelRatio","webkitDevicePixelRatio","mozDevicePixelRatio","browserShadowBlurConstant","arcToSegmentsCache","boundsOfCurveCache","cachesBoundsOfCurve","forceGLPutImageData","initFilterBackend","isWebglSupported","console","log","maxTextureSize","WebglFilterBackend","tileSize","Canvas2dFilterBackend","_removeEventListener","eventName","handler","__eventListeners","eventListener","indexOf","util","array","fill","_once","_handler","apply","arguments","off","bind","on","Observable","fire","options","listenersForEvent","i","len","length","call","filter","value","prop","push","once","Collection","_objects","add","_onObjectAdded","renderOnAddRemove","requestRenderAll","insertAt","object","index","nonSplicing","objects","splice","remove","somethingRemoved","_onObjectRemoved","forEachObject","callback","context","getObjects","type","concat","o","item","isEmpty","size","contains","deep","some","obj","complexity","reduce","memo","current","CommonMethods","_setOptions","set","_initGradient","filler","property","colorStops","Gradient","_initPattern","source","Pattern","_setObject","_set","key","toggle","get","global","sqrt","Math","atan2","pow","PiBy180","PI","PiBy2","cos","angle","sin","sign","removeFromArray","idx","getRandomInt","min","max","floor","random","degreesToRadians","degrees","radiansToDegrees","radians","rotatePoint","point","origin","newPoint","Point","x","y","v","rotateVector","addEquals","vector","createVector","from","to","calcAngleBetweenVectors","a","b","acos","hypot","getHatVector","multiply","getBisector","A","B","C","AB","AC","alpha","phi","projectStrokeOnPoints","points","openPath","coords","s","strokeWidth","strokeUniformScalar","strokeUniform","scaleX","scaleY","getStrokeHatVector","scalar","forEach","p","miterVector","bisector","bisectorVector","strokeLineJoin","strokeMiterLimit","subtract","SQRT2","transformPoint","t","ignoreOffset","makeBoundingBoxFromPoints","transform","xPoints","minX","yPoints","minY","left","top","invertTransform","r","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","substring","loadImageInDom","div","createElement","style","position","appendChild","querySelector","parentNode","removeChild","enlivenObjects","reviver","enlivenedObjects","numLoadedObjects","numTotalObjects","onLoaded","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","newCanvas","toDataURL","canvasEl","format","quality","multiplyTransformMatrices","is2x2","qrDecompose","denom","skewX","skewY","translateX","translateY","calcRotateMatrix","theta","calcDimensionsMatrix","scaleMatrix","flipX","flipY","tan","composeMatrix","matrix","resetObjectTransform","target","rotate","saveObjectTransform","isTransparent","tolerance","_isTransparent","imageData","getImageData","l","data","parsePreserveAspectRatioAttribute","attribute","align","meetOrSlice","aspectRatioAttrs","pop","alignX","alignY","clearFabricFontCache","fontFamily","toLowerCase","limitDimsByArea","ar","maximumArea","roughWidth","perfLimitSizeY","capValue","findScaleToFit","findScaleToCover","matrixToSVG","NUM_FRACTION_DIGITS","join","removeTransformFromObject","inverted","finalTransform","calcOwnMatrix","applyTransformToObject","addTransformToObject","center","setPositionByOrigin","sizeAfterTransform","dimX","dimY","transformMatrix","bbox","mergeClipPaths","c1","c2","calcTransformMatrix","clipPath","hasStyleChanged","prevStyle","thisStyle","forTextSpans","stroke","fontWeight","fontStyle","textBackgroundColor","deltaY","overline","underline","linethrough","stylesToArray","styles","text","clone","textLines","charIndex","stylesArray","c","keys","start","end","stylesFromArray","styleIndex","stylesObject","assign","_join","prototype","commandLengths","m","h","q","repeatedCommands","M","segmentToBezier","th2","th3","cosTh","sinTh","rx","ry","cx1","cy1","mT","fromX","fromY","costh2","sinth2","costh3","sinth3","toX","toY","calcVectorAngle","ux","uy","vx","vy","ta","tb","fromArcToBeziers","fx","fy","rot","large","sweep","segsNorm","arcToSegments","rotateX","th","px","py","rx2","abs","ry2","py2","px2","pl","root","cx","cy","mTheta","dtheta","segments","ceil","result","mDelta","calcLineLength","x1","y1","x2","y2","getPointOnCubicBezierIterator","p1x","p1y","p2x","p2y","p3x","p3y","p4x","p4y","pct","CB1","CB2","c3","CB3","c4","CB4","getTangentCubicIterator","invT","tangentX","tangentY","getPointOnQuadraticBezierIterator","QB1","QB2","QB3","getTangentQuadraticIterator","pathIterator","iterator","perc","tempP","tmpLen","findPercentageForDistance","segInfo","distance","nextLen","lastPerc","nextStep","angleFinder","getPathSegmentsInfo","tempInfo","totalLength","info","command","destX","destY","joinPath","pathData","segment","parsePath","pathString","currentPath","parsed","match","coordsStr","re","rNumber","rNumberCommaWsp","rFlagCommaWsp","regArcArgumentSequence","RegExp","coordsParsed","trim","args","j","jlen","isNaN","commandLength","repeatedCommand","k","klen","makePathSimpler","converted","previous","controlX","controlY","destinationPath","getSmoothPathFromPoints","correction","p1","p2","multSignX","multSignY","manyPoints","eq","midPoint","midPointFrom","getBoundsOfCurve","x0","y0","x3","y3","argsString","t1","t2","b2ac","sqrtb2ac","tvalues","bounds","mt","getPointOnPath","infos","segPercent","lerp","transformPath","pathOffset","pathSegment","newSegment","find","byProperty","condition","invoke","method","value1","value2","extend","Element","hasOwnProperty","getWholeChar","str","code","charCodeAt","next","prev","replace","character","capitalize","firstLetterOnly","escapeXml","graphemeSplit","textstring","chr","graphemes","emptyFunction","IS_DONTENUM_BUGGY","toString","addMethods","klass","parent","superclass","constructor","returnValue","valueOf","Subclass","callSuper","methodName","parentMethod","_this","superClassMethod","createClass","initialize","shift","subclasses","couldUseAttachEvent","attachEvent","touchEvents","addListener","element","addEventListener","removeListener","removeEventListener","getPointer","event","scroll","getScrollLeftTop","_evt","getTouchInfo","touchProp","changedTouches","clientX","clientY","isTouchEvent","pointerType","parseEl","supportsOpacity","opacity","supportsFilters","reOpacity","setOpacity","es","currentStyle","hasLayout","zoom","test","setStyle","elementStyle","cssText","normalizedProperty","styleFloat","setProperty","_slice","sliceCanConvertNodelists","getElementStyle","selectProp","toArray","arrayLike","childNodes","err","makeElement","tagName","el","className","htmlFor","setAttribute","docElement","documentElement","body","scrollLeft","scrollTop","host","nodeType","arr","defaultView","getComputedStyle","attr","undefined","makeElementUnselectable","onselectstart","unselectable","makeElementSelectable","setImageSmoothing","imageSmoothingEnabled","webkitImageSmoothingEnabled","mozImageSmoothingEnabled","msImageSmoothingEnabled","oImageSmoothingEnabled","getById","id","getElementById","addClass","wrapElement","wrapper","replaceChild","getElementOffset","docElem","scrollLeftTop","doc","ownerDocument","box","offset","offsetAttributes","borderLeftWidth","borderTopWidth","paddingLeft","paddingTop","parseInt","getBoundingClientRect","clientLeft","clientTop","getNodeCanvas","impl","_canvas","_image","cleanUpJsdomNode","_currentSrc","_attributes","_classList","emptyFn","request","onComplete","xhr","XMLHttpRequest","parameters","onreadystatechange","readyState","addParamToUrl","param","open","setRequestHeader","send","warn","message","RUNNING_ANIMATIONS","noop","defaultEasing","d","cancelAll","animations","animation","cancel","cancelByCanvas","cancelled","cancelByTarget","findAnimationsByTarget","findAnimationIndex","cancelFunc","findAnimation","_requestAnimFrame","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","setTimeout","_cancelAnimFrame","cancelAnimationFrame","clearTimeout","requestAnimFrame","animate","removeFromRegistry","runningAnimations","currentValue","startValue","completionRate","durationRate","timestamp","time","Date","duration","finish","onChange","abort","easing","isMany","endValue","byValue","onStart","tick","ticktime","currentTime","timePerc","_value","valuePerc","cancelAnimFrame","calculateColor","begin","pos","color","animateColor","fromColor","toColor","startColor","Color","getSource","endColor","originalOnComplete","originalOnChange","colorEasing","normalize","asin","elastic","opts","easeInBounce","easeOutBounce","ease","easeInQuad","easeOutQuad","easeInOutQuad","easeInCubic","easeOutCubic","easeInOutCubic","easeInQuart","easeOutQuart","easeInOutQuart","easeInQuint","easeOutQuint","easeInOutQuint","easeInSine","easeOutSine","easeInOutSine","easeInExpo","easeOutExpo","easeInOutExpo","easeInCirc","easeOutCirc","easeInOutCirc","easeInElastic","easeOutElastic","easeInOutElastic","easeInBack","easeOutBack","easeInOutBack","easeInOutBounce","attributesMap","display","visibility","colorAttributes","fSize","cPath","normalizeAttr","normalizeValue","parentAttributes","parseTransformAttribute","visible","fillIndex","strokeIndex","getSvgRegex","_getMultipleNodes","nodeNames","nodeName","nodeList","nodeArray","getElementsByTagName","elementMatchesRule","selectors","firstMatching","parentMatching","selectorMatches","doesSomeParentMatch","selector","matcher","classNames","getAttribute","elementById","node","nodelist","svgValidTagNamesRegEx","svgViewBoxElementsRegEx","svgInvalidAncestorsRegEx","svgValidParentsRegEx","cssRules","gradientDefs","clipPaths","skewMatrix","reTransformList","reTransform","attributeValue","matrices","operation","translateMatrix","rotateMatrix","multiplierX","multiplierY","combinedMatrix","reViewBoxAttrValue","applyViewboxTransform","viewBoxWidth","viewBoxHeight","viewBoxAttr","widthAttr","heightAttr","preserveAspectRatio","missingViewBox","missingDimAttr","toBeParsed","parsedDim","widthDiff","heightDiff","removeAttribute","createElementNS","firstChild","recursivelyParseGradientsXlink","gradient","xlinkAttr","referencedGradient","hasAttribute","children","referenceClone","cloneNode","parseSVGDocument","parsingOptions","parseUseDirectives","xlinkAttribute","attrs","xlink","el2","currentTrans","oldLength","el3","setAttributeNS","nodeValue","svgUid","__uid","descendants","selectNodes","hasAncestorWithNodeName","getGradientDefs","getCSSRules","parseElements","instances","reFontDeclaration","parseFontDeclaration","oStyle","lineHeight","elList","parseAttributes","parentFontSize","ownAttributes","cssAttrs","getGlobalStylesForElement","rule","parseStyleAttribute","normalizedAttr","normalizedValue","normalizedStyle","font","mergedAttrs","_setStrokeFillOpacity","setAlpha","getAlpha","toRgba","ElementsParser","parse","parseStyleString","chunk","pair","parseStyleObject","parsePointsAttribute","parsedPoints","allRules","styleContents","textContent","ruleObj","propertyValuePairs","_rule","loadSVGFromURL","xml","responseXML","results","_options","allElements","loadSVGFromString","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","_tryParsingColor","setSource","hue2rgb","colorNameMap","sourceFromHex","sourceFromRgb","sourceFromHsl","_rgbToHsl","g","round","_source","toRgb","toHsl","hsl","toHsla","toHex","toHexa","toGrayscale","average","currentAlpha","toBlackWhite","threshold","overlayWith","otherColor","otherSource","reRGBa","reHSLa","reHex","aliceblue","antiquewhite","aqua","aquamarine","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","fromRgb","fromSource","fromRgba","fromHsl","fromHsla","fromHex","isShortNotation","isRGBa","oColor","scaleMap","skewMap","controls","LEFT","TOP","RIGHT","BOTTOM","CENTER","opposite","bottom","right","findCornerQuadrant","fabricObject","control","cornerAngle","fireEvent","canvasOptions","scaleIsProportional","eventData","uniformIsToggled","uniScaleKey","uniformScaling","isTransformCentered","originX","originY","scalingIsForbidden","by","scaleProportionally","lockX","lockScalingX","lockY","lockScalingY","commonEventInfo","e","pointer","wrapWithFixedAnchor","actionHandler","getCenterPoint","constraint","translateToOriginPoint","actionPerformed","wrapWithFireEvent","getLocalPoint","corner","getZoom","padding","localPoint","toLocalPoint","offsetX","offsetY","targetHasOneFlip","compensateScaleForSkew","oppositeSkew","scaleToCompensate","axis","reference","newValue","_getTransformedDimensions","skewObjectX","newSkew","dimNoSkew","totalSkewSize","currentSkew","hasSkewed","dimBeforeSkewing","skewObjectY","scaleObject","dim","signX","signY","forbidScaling","gestureScale","lockScalingFlip","original","oldScaleX","oldScaleY","scaleCursorStyleHandler","n","skewCursorStyleHandler","notAllowed","lockSkewingY","lockSkewingX","scaleSkewCursorStyleHandler","altActionKey","rotationWithSnapping","pivotPoint","lockRotation","hasRotated","lastAngle","ey","ex","curAngle","snapAngle","snapThreshold","rightAngleLocked","leftAngleLocked","scalingEqually","scaleObjectFromCorner","scalingX","scaleObjectX","scalingY","scaleObjectY","scalingYOrSkewingX","skewHandlerX","scalingXOrSkewingY","skewHandlerY","changeWidth","strokePadding","multiplier","oldWidth","newWidth","finalHandler","dragHandler","newLeft","newTop","moveX","moveY","scaleOrSkewActionName","isAlternative","rotationStyleHandler","cursorStyle","controlsUtils","renderCircleControl","styleOverride","xSize","sizeX","cornerSize","ySize","sizeY","transparentCorners","cornerStrokeColor","myLeft","myTop","save","fillStyle","cornerColor","strokeStyle","lineWidth","beginPath","arc","restore","renderSquareControl","xSizeBy2","ySizeBy2","strokeRect","Control","actionName","touchSizeX","touchSizeY","withConnection","mouseDownHandler","mouseUpHandler","getActionHandler","getMouseDownHandler","getMouseUpHandler","cursorStyleHandler","getActionName","getVisibility","controlKey","objectVisibility","_controlsVisibility","setVisibility","positionHandler","finalMatrix","calcCornerCoords","objectAngle","objectCornerSize","centerX","centerY","isTouch","cosHalfOffset","sinHalfOffset","cosHalfOffsetComp","sinHalfOffsetComp","controlTriangleAngle","cornerHypotenuse","newTheta","newThetaComp","tl","tr","bl","br","render","cornerStyle","getColorStop","colorAlpha","keyValuePairs","gradientTransform","gradientUnits","option","addColorStop","toObject","propertiesToInclude","toSVG","markup","commonAttributes","needsSwap","withViewport","additionalTransform","sort","reverse","minRadius","percentageShift","colorStop","toLive","createLinearGradient","createRadialGradient","instance","svgOptions","colorStopEls","getLinearCoords","getRadialCoords","__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","StaticCanvas","CANVAS_INIT_ERROR","Error","renderAndResetBound","renderAndReset","requestRenderAllBound","_initStatic","backgroundColor","backgroundImage","overlayColor","overlayImage","stateful","controlsAboveOverlay","allowTouchScrolling","viewportTransform","backgroundVpt","overlayVpt","enableRetinaScaling","vptCoords","skipOffscreen","cb","_createLowerCanvas","_initOptions","interactive","_initRetinaScaling","setOverlayImage","setBackgroundImage","setBackgroundColor","setOverlayColor","calcOffset","_isRetinaScaling","getRetinaScaling","scaleRatio","__initRetinaScaling","lowerCanvasEl","contextContainer","upperCanvasEl","contextTop","_offset","image","__setBgOverlayImage","__setBgOverlayColor","_createCanvasElement","_originalCanvasStyle","_applyCanvasStyle","getWidth","getHeight","setWidth","setDimensions","setHeight","dimensions","cssValue","cssOnly","_setBackstoreDimension","hasLostContext","backstoreOnly","_setCssDimension","_isCurrentlyDrawing","freeDrawingBrush","_setBrushStyles","cacheCanvasEl","wrapperEl","setViewportTransform","vpt","activeObject","_activeObject","backgroundObject","overlayObject","group","setCoords","calcViewportBoundaries","zoomToPoint","before","after","setZoom","absolutePan","relativePan","getElement","setupState","clearContext","clearRect","clear","_hasITextHandlers","_mouseUpITextHandler","_iTextInstances","renderAll","canvasToDrawOn","renderCanvas","isRendering","iVpt","cancelRequestedRender","_renderBackground","_renderObjects","drawControls","shouldCache","_transformDone","renderCache","forClipping","drawClipPathOnCanvas","_renderOverlay","globalCompositeOperation","zoomX","zoomY","_cacheCanvas","cacheTranslationX","cacheTranslationY","_renderBackgroundOrOverlay","needsVpt","moveTo","lineTo","closePath","getCenter","centerObjectH","_centerObject","centerObjectV","centerObject","viewportCenterObject","vpCenter","getVpCenter","viewportCenterObjectH","viewportCenterObjectV","toDatalessJSON","toDatalessObject","_toObjectMethod","_toObjects","excludeFromExport","_toObject","__serializeBgOverlay","originalValue","bgImage","bgColor","background","overlay","svgViewportTransformation","_setSVGPreamble","_setSVGHeader","clipPathId","_setSVGBgOverlayColor","_setSVGBgOverlayImage","_setSVGObjects","suppressPreamble","encoding","viewBox","createSVGFontFacesMarkup","createSVGRefElementsMarkup","createSVGClipPathMarkup","toClipPathSVG","shouldTransform","row","rowIndex","fontList","_setSVGObject","finalWidth","finalHeight","sendToBack","objs","activeSelection","unshift","bringToFront","sendBackwards","intersecting","newIdx","objsMoved","_findNewLowerIndex","intersectsWithObject","isContainedWithinObject","bringForward","_findNewUpperIndex","dispose","classList","DataURLExporter","EMPTY_JSON","supports","setLineDash","toJSON","createPNGStream","createJPEGStream","BaseBrush","strokeLineCap","strokeDashArray","limitedToCanvasSize","lineCap","miterLimit","lineJoin","_saveAndTransform","_setShadow","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY","needsFullRender","_resetShadow","_isOutSideCanvas","PencilBrush","decimate","drawStraightLine","straightLineKey","_points","_hasStraightLine","_drawSegment","quadraticCurveTo","onMouseDown","_isMainEvent","_prepareForDrawing","_captureDrawingPath","_render","onMouseMove","oldEnd","onMouseUp","_finalizeAndAddPath","_reset","_addPoint","pointerPoint","convertPointsToSVGPath","_isEmptySVGPath","createPath","Path","decimatePoints","adjustedDistance","lastPoint","newPoints","CircleBrush","drawDot","addPoint","dot","radius","originalRenderOnAddRemove","circles","circle","Circle","circleRadius","circleColor","SprayBrush","density","dotWidth","dotWidthVariance","randomOpacity","optimizeOverlapping","sprayChunks","addSprayChunk","sprayChunkPoints","rects","ilen","sprayChunk","rect","Rect","_getOptimizedRects","uniqueRects","uniqueRectsArray","globalAlpha","fillRect","PatternBrush","getPatternSrc","patternCanvas","patternCtx","getPatternSrcFunction","String","getPattern","topLeft","_getLeftTopCoords","_initInteractive","_createCacheCanvas","centeredScaling","centeredRotation","centeredKey","selection","selectionKey","altSelectionKey","selectionColor","selectionDashArray","selectionBorderColor","selectionLineWidth","selectionFullyContained","hoverCursor","moveCursor","defaultCursor","freeDrawingCursor","notAllowedCursor","containerClass","perPixelTargetFind","targetFindTolerance","skipTargetFind","isDrawingMode","preserveObjectStacking","stopContextMenu","fireRightClick","fireMiddleClick","targets","enablePointerEvents","_hoveredTarget","_hoveredTargets","_currentTransform","_groupSelector","_initWrapperElement","_createUpperCanvas","_initEventListeners","_chooseObjectsToRender","objsToRender","activeGroupObjects","activeObjects","getActiveObjects","contextTopDirty","renderTopLayer","_drawSelection","renderTop","_normalizePointer","invertedM","vptPointer","restorePointerVpt","isTargetTransparent","normalizedPointer","targetRelativeX","targetRelativeY","_cacheContext","contextCache","originalColor","selectionBackgroundColor","_isSelectionKeyPressed","_shouldClearSelection","evented","selectable","_shouldCenterTransform","action","altKey","centerTransform","_getOriginFromCorner","_getActionFromCorner","alreadySelected","_setupCurrentTransform","__corner","lastX","lastY","shiftKey","_beforeTransform","setCursor","cursor","viewportStart","viewportExtent","extent","maxX","maxY","strokeOffset","_setLineDash","findTarget","skipGroup","activeTarget","activeTargetSubs","aObjects","shouldLookForActive","_findTargetCorner","_searchPossibleTargets","_checkTarget","globalPointer","containsPoint","isEditing","subTarget","objToCheck","pointerToUse","subTargetCheck","ignoreZoom","_absolutePointer","_pointer","cssScale","boundsWidth","boundsHeight","retinaScaling","lowerCanvasClass","_copyCanvasStyle","getTopContext","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","originalValues","clearContextTop","addEventOptions","passive","checkClick","button","mainTouchId","_bindEvents","addOrRemove","_getEventPrefix","functor","eventjsFunctor","canvasElement","eventTypePrefix","_onResize","_onMouseDown","_onMouseMove","_onMouseOut","_onMouseEnter","_onMouseWheel","_onContextMenu","_onDoubleClick","_onDragOver","_onDragEnter","_onDragLeave","_onDrop","_onTouchStart","eventjs","_onGesture","_onDrag","_onOrientationChange","_onShake","_onLongPress","_onMouseUp","_onTouchEnd","eventsBound","_simpleEventHandler","self","__onTransformGesture","__onDrag","__onMouseWheel","_target","__onOrientationChange","__onShake","__onLongPress","preventDefault","_fireEnterLeaveEvents","stopPropagation","_cacheTransformEventData","_handleEvent","_resetTransformEventData","getPointerId","evt","identifier","pointerId","isPrimary","touches","__onMouseDown","__onMouseUp","_willAddMouseDown","__onMouseMove","_shouldRender","groupSelector","shouldRender","isClick","_onMouseUpInDrawingMode","_finalizeCurrentTransform","targetWasActive","_maybeGroupObjects","activeOn","isMoving","originalControl","originalMouseUpHandler","_setCursorFromEvent","eventType","subTargets","absolutePointer","currentTarget","currentSubTargets","_scaling","hasStateChanged","_fire","_onMouseDownInDrawingMode","_onMouseMoveInDrawingMode","_previousPointer","shouldGroup","_shouldGroup","_handleGrouping","saveState","_transformObject","_fireOverOutEvents","fireSyntheticInOutEvents","oldTarget","evtOut","canvasEvtOut","evtIn","canvasEvtIn","_draggedoverTarget","config","inOpt","outOpt","inFires","targetChanged","previousTarget","nextTarget","reset","_performTransformAction","getCornerCursor","_updateActiveSelection","_createActiveSelection","currentActiveObjects","removeWithUpdate","addWithUpdate","_createGroup","groupObjects","exitEditing","ActiveSelection","_groupSelectedObjects","aGroup","_collectObjects","currentObject","selectionX1Y1","selectionX2Y2","allowIntersect","intersectsWithRect","isContainedWithinRect","toCanvasElement","cropping","scaledWidth","scaledHeight","originalWidth","originalHeight","newZoom","vp","originalInteractive","newVp","originalRetina","originalContextTop","loadFromJSON","json","serialized","JSON","_enlivenObjects","_setBgOverlay","enlivenedCanvasClip","__setupCanvas","loaded","cbIfLoaded","__setBgOverlay","enlivedObject","_toDataURL","_toDataURLWithMultiplier","toDataURLWithMultiplier","stringify","cloneWithoutData","backgroundImageOpacity","backgroundImageStretch","objectCaching","touchCornerSize","borderColor","borderDashArray","cornerDashArray","strokeDashOffset","borderOpacityWhenMoving","borderScaleFactor","minScaleLimit","hasControls","hasBorders","lockMovementX","lockMovementY","statefullCache","noScaleCache","dirty","paintFirst","stateProperties","cacheProperties","colorProperties","absolutePositioned","_cacheProperties","_updateCacheCanvas","_limitCacheSize","dims","limitedDims","capped","_getCacheCanvasDimensions","objectScale","getTotalObjectScaling","neededX","neededY","drawingWidth","drawingHeight","minCacheSize","dimensionsChanged","cacheWidth","cacheHeight","zoomChanged","shouldRedraw","additionalWidth","additionalHeight","shouldResizeCanvas","canvasWidth","canvasHeight","sizeGrowing","getHeightOfLine","setTransform","needFullTransform","_removeDefaultValues","getObjectScaling","retina","getObjectOpacity","shouldConstrainValue","isChanged","groupNeedsUpdate","_constrainScale","isOnACache","setOnGroup","getViewportTransform","isNotVisible","isOnScreen","_setupCompositeOperation","drawSelectionBackground","_setOpacity","drawCacheOnCanvas","_removeCacheCanvas","drawObject","propertySet","isCacheDirty","hasStroke","hasFill","needsItsOwnCache","ownCaching","willDrawShadow","drawClipPathOnCache","originalFill","originalStroke","_setClippingProperties","_drawClipPath","skipCanvas","_getNonTransformedDimensions","_removeShadow","_setStrokeStyles","decl","lineDashOffset","_applyPatternForTransformedGradient","_applyPatternGradientTransform","_setFillStyles","dashArray","drawBorders","forActiveSelection","drawBordersInGroup","scaling","multX","multY","_renderPaintInOrder","_renderStroke","_renderFill","pCtx","pCanvas","_findCenterFromElement","_assignTransformMatrixProps","preserveAspectRatioOptions","cropX","cropY","offsetLeft","offsetTop","objectForm","_fromObject","cloneAsImage","utils","origParams","originalGroup","originalShadow","withoutTransform","withoutShadow","boundingRect","getBoundingRect","shadowOffset","originalCanvas","isType","includes","shouldCenterOrigin","_setOriginToCenter","_resetOrigin","centerH","viewportCenterH","centerV","viewportCenterV","viewportCenter","getLocalPointer","pClicked","objectLeftTop","createAccessors","extraParam","originXOffset","originYOffset","translateToGivenOrigin","fromOriginX","fromOriginY","toOriginX","toOriginY","translateToCenterPoint","leftTop","getPointByOrigin","adjustPosition","offsetFrom","offsetTo","hypotFull","getScaledWidth","xFull","yFull","_originalOriginX","_originalOriginY","originPoint","multiplyMatrices","oCoords","aCoords","lineCoords","ownMatrixCache","matrixCache","_getCoords","absolute","calculate","calcACoords","calcLineCoords","getCoords","arrayFromCoords","pointTL","pointBR","other","otherCoords","lines","_getImageLines","_findCrossPoints","_containsCenterOfCanvas","isPartiallyOnScreen","every","topline","rightline","bottomline","leftline","xi","iLine","xcount","lineKey","getScaledHeight","scaleToWidth","boundingRectFactor","scaleToHeight","cosP","sinP","cosPSinP","cosPMinusSinP","calcOCoords","_calcRotateMatrix","_calcTranslateMatrix","startMatrix","_calculateCurrentDimensions","forEachControl","w","skipCorners","_setCornerCoords","transformMatrixKey","sep","prefix","cache","tMatrix","noSkew","_finalizeDimensions","getSvgColorString","getSvgStyles","skipShadow","getSvgFilter","getSvgSpanStyles","useWhiteSpace","term","textDecoration","getSvgTextDecoration","decoration","getSvgCommons","getSvgTransform","full","_setSVGBg","textBgRects","_getFillAttributes","_createBaseSVGMarkup","_toSVG","_createBaseClipPathSVGMarkup","objectMarkup","commonPieces","clipPathMarkup","noStyle","styleInfo","shadowInfo","withShadow","vectorEffect","absoluteClipPath","addPaintOrder","originalSet","saveProps","props","tmpObj","_isEqual","origValue","firstPass","dashedPropertySet","forTouch","isControlVisible","touchCorner","fn","controlObject","wh","shouldStroke","setControlVisible","setControlsVisibility","FX_DURATION","fxCenterObjectH","callbacks","empty","fxCenterObjectV","fxRemove","skipCallbacks","propsToAnimate","out","_animate","propPair","propIsColor","valueProgress","timeProgress","coordProps","makeEdgeToOriginGetter","propertyNames","originValues","axis1","axis2","dimension","nearest","farthest","Line","_setWidthHeight","_getLeftToOriginX","_getTopToOriginY","calcLinePoints","origStrokeStyle","xMult","yMult","ATTRIBUTE_NAMES","parsedAttributes","_callback","startAngle","endAngle","setRadius","svgString","getRadiusX","getRadiusY","isValidRadius","Triangle","widthBy2","heightBy2","piBy2","Ellipse","getRx","getRy","_initRxRy","isRounded","bezierCurveTo","Polyline","exactBoundingBox","_setPositionDimensions","_projectStrokeOnPoints","correctLeftTop","calcDim","_calcDimensions","correctSize","fromSVG","diffX","diffY","commonRender","fromElementGenerator","_class","Polygon","_setPath","_renderPathCommands","subpathStartX","subpathStartY","_getOffsetTransform","digits","aX","aY","pathUrl","elivenedObjects","useSetOnGroup","isAlreadyGrouped","_updateObjectsACoords","_calcBounds","_updateObjectsCoords","_updateObjectCoords","objectLeft","objectTop","nested","_restoreObjectsState","_includeDefaultValues","objsToObject","originalDefaults","_obj","ownCache","groupMatrix","destroy","toActiveSelection","ungroupOnCanvas","setObjectsCoords","onlyWidthHeight","iLen","jLen","_getBounds","minXY","maxXY","toGroup","newGroup","childrenOverride","srcFromAttribute","_lastScaleX","_lastScaleY","_filterScalingX","_filterScalingY","minimumScaleTrigger","cacheKey","imageSmoothing","filters","_initElement","_element","setElement","removeTexture","_initConfig","applyFilters","resizeFilter","applyResizeFilters","backend","filterBackend","evictCachesForKey","getCrossOrigin","getOriginalSize","_stroke","filterObj","getSrc","hasCrop","strokeSvg","imageMarkup","imageRendering","getSvgSrc","origFill","filtered","setSrc","minimumScale","elementToFilter","_filteredEl","sourceWidth","sourceHeight","isNeutralState","imgElement","_needsResize","elementToDraw","elWidth","elHeight","sX","sY","sW","sH","maxDestW","maxDestH","_resetWidthHeight","CSS_CANVAS","_initFilters","pAR","rWidth","rHeight","pWidth","pHeight","_object","resizeFilters","fromURL","imgOptions","_getAngleValueForStraighten","straighten","fxStraighten","straightenObject","fxStraightenObject","testPrecision","precision","fragmentSource","fragmentShader","createShader","FRAGMENT_SHADER","shaderSource","compileShader","getShaderParameter","COMPILE_STATUS","setupGLContext","captureGPUInfo","isSupported","getParameter","MAX_TEXTURE_SIZE","precisions","webGlPrecision","createWebGLCanvas","aPosition","Float32Array","chooseFastestCopyGLTo2DMethod","canUseImageData","canMeasurePerf","performance","canUseArrayBuffer","ArrayBuffer","canUseUint8Clamped","copyGLTo2D","startTime","drawImageTime","testContext","now","glOptions","premultipliedAlpha","depth","stencil","antialias","clearColor","cachedTexture","getCachedTexture","sourceTexture","createTexture","targetTexture","originalTexture","passes","webgl","programCache","pass","tempFbo","createFramebuffer","bindFramebuffer","FRAMEBUFFER","applyTo","bindTexture","TEXTURE_2D","deleteTexture","deleteFramebuffer","clearWebGLCaches","textureCache","textureImageSource","filterType","texture","texParameteri","TEXTURE_MAG_FILTER","NEAREST","TEXTURE_MIN_FILTER","TEXTURE_WRAP_S","CLAMP_TO_EDGE","TEXTURE_WRAP_T","texImage2D","uniqueId","gpuInfo","renderer","vendor","ext","getExtension","UNMASKED_RENDERER_WEBGL","UNMASKED_VENDOR_WEBGL","sourceElement","originalEl","originalImageData","BaseFilter","vertexSource","createProgram","vertexShader","VERTEX_SHADER","getShaderInfoLog","program","attachShader","linkProgram","getProgramParameter","LINK_STATUS","getProgramInfoLog","attributeLocations","getAttributeLocations","uniformLocations","getUniformLocations","uStepW","getUniformLocation","uStepH","getAttribLocation","sendAttributeData","aPositionData","attributeLocation","buffer","createBuffer","bindBuffer","ARRAY_BUFFER","enableVertexAttribArray","vertexAttribPointer","FLOAT","bufferData","STATIC_DRAW","_setupFrameBuffer","framebufferTexture2D","COLOR_ATTACHMENT0","_swapTextures","temp","main","mainParameter","applyToWebGL","applyTo2d","retrieveShader","shader","useProgram","uniform1f","sendUniformData","viewport","drawArrays","TRIANGLE_STRIP","bindAdditionalTexture","textureUnit","activeTexture","TEXTURE0","unbindAdditionalTexture","getMainParameter","setMainParameter","createHelpLayer","helpLayer","mainP","ColorMatrix","colorsOnly","uColorMatrix","uConstants","constants","uniformMatrix4fv","uniform4fv","Brightness","brightness","uBrightness","Convolute","opaque","Convolute_3_1","Convolute_3_0","Convolute_5_1","Convolute_5_0","Convolute_7_1","Convolute_7_0","Convolute_9_1","Convolute_9_0","dstOff","scx","scy","srcOff","wt","weights","side","halfSide","sw","sh","output","createImageData","dst","alphaFac","uMatrix","uOpaque","uHalfSize","uSize","uniform1fv","Grayscale","lightness","luminosity","mode","uMode","uniform1i","Invert","invert","uInvert","Noise","noise","rand","uNoise","uSeed","Pixelate","blocksize","_i","_j","_iLen","_jLen","uBlocksize","RemoveColor","useAlpha","lowC","highC","uLow","uHigh","Brownie","Vintage","Kodachrome","Technicolor","Polaroid","Sepia","BlackWhite","BlendColor","screen","diff","lighten","darken","exclusion","tint","buildSource","tg","alpha1","uColor","BlendImage","mask","TEXTURE1","calculateMatrix","canvas1","blendData","blendImage","uTransformMatrix","uImage","uniformMatrix3fv","Resize","resizeType","lanczosLobes","uDelta","uTaps","uniform2fv","horizontal","taps","filterWindow","getFilterWindow","generateShader","tempScale","getTaps","lobeFunction","lanczosCreate","offsets","fragmentSourceTOP","dW","dH","lobes","xx","rcpScaleX","rcpScaleY","newData","oW","oH","sliceByTwo","hermiteFastResize","bilinearFiltering","lanczosResize","tmpCanvas","mult","doneW","doneH","stepW","stepH","dX","dY","srcData","destImg","destData","lanczos","ratioX","ratioY","rcpRatioX","rcpRatioY","range2X","range2Y","cacheLanc","icenter","process","u","weight","fX","fY","xDiff","yDiff","chnl","origPix","w4","pixels","destImage","destPixels","ratioW","ratioH","ratioWHalf","ratioHHalf","img2","data2","weightsAlpha","gxR","gxG","gxB","gxA","yy","w0","Contrast","contrast","contrastF","uContrast","Saturation","saturation","adjust","uSaturation","Vibrance","vibrance","avg","amt","uVibrance","Blur","aspectRatio","simpleBlur","canvas2","blurLayer1","blurLayer2","percent","ctx1","ctx2","nSamples","newImageData","delta","chooseRightDelta","blurScale","Gamma","gamma","rInv","gInv","bInv","rVals","gVals","bVals","uGamma","uniform3fv","Composed","subFilters","HueRotation","rotation","rad","aThird","aThirdSqtSin","OneMinusCos","additionalProps","_dimensionAffectingProps","_reNewline","_reSpacesAndTabs","_reSpaceAndTab","_reWords","textAlign","superscript","baseline","subscript","pathStartOffset","pathSide","pathAlign","_fontSizeFraction","_fontSizeMult","charSpacing","_measuringContext","direction","_styleProperties","__charBounds","CACHE_FONT_SIZE","MIN_TEXT_WIDTH","__skipDimension","setPathInfo","initDimensions","segmentsInfo","getMeasuringContext","_splitText","newLines","_splitTextIntoLines","_textLines","graphemeLines","_unwrappedTextLines","_unwrappedLines","_text","graphemeText","_clearCache","calcTextWidth","cursorWidth","calcTextHeight","enlargeSpaces","diffSpace","currentLineWidth","numberOfSpaces","accumulatedSpace","line","charBound","spaces","isEndOfWrapping","getLineWidth","kernedWidth","lineIndex","missingNewlineOffset","_setTextStyles","_renderTextLinesBackground","_renderTextDecoration","_renderText","_renderTextStroke","_renderTextFill","charStyle","forMeasuring","textBaseline","_getFontDeclaration","maxWidth","_renderTextLine","_renderChars","styleHas","heightOfLine","lineLeftOffset","lastColor","charBox","currentColor","drawStart","leftOffset","_getLeftOffset","lineTopOffset","_getTopOffset","boxStart","boxWidth","_getLineLeftOffset","getValueOfPropertyAt","renderLeft","getFontCache","cacheProp","_measureChar","_char","previousChar","prevCharStyle","coupleWidth","previousWidth","fontCache","couple","stylesAreEqual","fontMultiplier","measureText","getHeightOfChar","measureLine","lineInfo","_measureLine","_getWidthOfCharSpacing","grapheme","prevGrapheme","graphemeInfo","startingPoint","totalPathLength","lineBounds","positionInPath","_getGraphemeBox","_setGraphemeOnPath","numOfSpaces","centerPosition","skipLeft","getCompleteStyleDeclaration","previousBox","__lineHeights","maxHeight","_renderTextCommon","lineHeights","isEmptyStyles","actualStyle","nextStyle","timeToRender","drawingLeft","isJustify","charsToRender","shortCut","isLtr","currentDirection","_renderChar","_applyPatternGradientTransformText","handleFiller","fillOffsets","strokeOffsets","_getStyleDeclaration","fullDecl","shouldFill","fillText","strokeText","setSuperscript","_setScript","setSubscript","schema","loc","get2DCursorLocation","setSelectionStyles","lineDiff","__lineWidths","_shouldClearDimensionCache","shouldClear","_forceClearCache","_size","_dy","lastDecoration","currentDecoration","currentFill","lastFill","topOffset","styleObject","family","fontIsGeneric","genericFonts","newLine","newText","allProperties","needsDims","isAddingPath","_key","parsedAnchor","textAnchor","originalStrokeWidth","textHeightScaleFactor","scaledDiff","textHeight","offX","objectCopy","textInstance","pathInstance","p3","cleanStyle","letterCount","stylePropertyValue","stylesCount","allStyleObjectPropertiesMatch","graphemeCount","removeStyle","lineNum","charNum","_extendStyles","_getLineStyle","_setLineStyle","_setStyleDeclaration","selectionStart","skipWrapping","getSelectionStyles","startIndex","endIndex","selectionEnd","getStyleAtPosition","lineStyle","_deleteStyleDeclaration","_deleteLineStyle","parseDecoration","IText","editable","editingBorderColor","cursorColor","cursorDelay","cursorDuration","caching","hiddenTextareaContainer","_reSpace","_currentCursorOpacity","_selectionDirection","_abortCursorAnimation","__widthOfSpace","inCompositionMode","initBehavior","setSelectionStart","_updateAndFire","setSelectionEnd","_fireSelectionChanged","_updateTextarea","initDelayedCursor","cursorOffsetCache","renderCursorOrSelection","skipRestore","_clearTextArea","boundaries","_getCursorBoundaries","renderCursor","renderSelection","_getCursorBoundariesOffsets","cursorPosition","bound","cursorLocation","charHeight","__isMousedown","hiddenTextarea","startLine","endLine","startChar","endChar","realLineHeight","lineOffset","boxEnd","drawWidth","drawHeight","extraTop","compositionColor","getCurrentCharFontSize","cp","_getCurrentCharIndex","getCurrentCharColor","objCopy","initAddedHandler","initRemovedHandler","initCursorSelectionHandlers","initDoubleClickSimulation","mouseMoveHandler","_initCanvasHandlers","_removeCanvasHandlers","_tick","_currentTickState","_animateCursor","targetOpacity","completeMethod","tickState","isAborted","_onTickComplete","_cursorTimeout1","_currentTickCompleteState","restart","delay","abortCursorAnimation","_cursorTimeout2","selectAll","getSelectedText","findWordBoundaryLeft","startFrom","findWordBoundaryRight","findLineBoundaryLeft","findLineBoundaryRight","searchWordBoundary","selectWord","newSelectionStart","newSelectionEnd","selectLine","enterEditing","exitEditingOnOthers","initHiddenTextarea","focus","_saveEditingProps","_setEditingProps","_textBeforeEdit","initMouseMoveHandler","activeElement","getSelectionStartFromPointer","currentStart","currentEnd","__selectionStartOnMouseDown","restartCursorIfNeeded","fromStringToGraphemeSelection","smallerTextStart","graphemeStart","smallerTextEnd","fromGraphemeToStringSelection","newSelection","updateTextareaPosition","updateFromTextArea","_calcTextareaPosition","desiredPosition","compositionStart","upperCanvas","upperCanvasWidth","upperCanvasHeight","clientWidth","clientHeight","_savedProps","_restoreEditingProps","isTextChanged","_removeExtraneousStyles","removeStyleFromTo","styleObj","cursorStart","cursorEnd","lineStart","charStart","lineEnd","charEnd","shiftLineStyles","numericChar","clonedStyles","numericLine","insertNewlineStyleObject","qty","copiedStyle","currentCharStyle","newLineStyles","somethingAdded","isEndOfLine","numIndex","styleCarriedOver","insertCharStyleObject","quantity","currentLineStyles","currentLineStylesCloned","numericIndex","newStyle","insertNewStyleBlock","insertedText","cursorLoc","addedLines","linesLength","setSelectionStartEndWithShift","setSelectionInBoundaries","__lastClickTime","__lastLastClickTime","__lastPointer","__newClickTime","newPointer","isTripleClick","_stopEvent","__lastIsEditing","__lastSelected","initMousedownHandler","initMouseupHandler","initClicks","doubleClickHandler","tripleClickHandler","_mouseDownHandler","setCursorByClick","_mouseDownHandlerBefore","currentActive","mouseOffset","prevWidth","_getNewSelectionStartFromOffset","distanceBtwLastCharAndCursor","distanceBtwNextCharAndCursor","onKeyDown","onKeyUp","onInput","copy","paste","onCompositionStart","onCompositionUpdate","onCompositionEnd","_clickHandlerInitialized","onClick","keysMap","keysMapRtl","ctrlKeysMapUp","ctrlKeysMapDown","keyMap","keyCode","ctrlKey","metaKey","stopImmediatePropagation","_copyDone","fromPaste","removedText","removeFrom","removeTo","nextText","charCount","nextCharCount","charDiff","textareaSelection","backDelete","copiedText","copiedTextStyle","compositionEnd","_getClipboardData","clipboardData","_getWidthBeforeCursor","widthBeforeCursor","getDownCursorOffset","isRight","selectionProp","_getSelectionForOffset","indexOnOtherLine","_getIndexOnLine","getUpCursorOffset","textBeforeCursor","charWidth","foundMatch","widthOfCharsOnLine","indexOnLine","leftEdge","rightEdge","offsetFromLeftEdge","moveCursorDown","_moveCursorUpOrDown","moveCursorUp","moveCursorWithShift","moveCursorWithoutShift","moveCursorLeft","_moveCursorLeftOrRight","_move","_moveLeft","_moveRight","moveCursorLeftWithoutShift","change","moveCursorLeftWithShift","moveCursorRight","moveCursorRightWithShift","moveCursorRightWithoutShift","changed","removeChars","insertChars","multipleSpacesRegex","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","lineTop","textSpans","textTopOffset","textLeftOffset","_setSVGTextLineBg","_setSVGTextLineText","_createTextCharSpan","styleDecl","shouldUseWhitespace","styleProps","fillStyles","dySpan","_pushTextBgRect","fillColor","_getSVGLineTopOffset","lastHeight","Textbox","minWidth","dynamicMinWidth","__cachedLines","_wordJoiners","splitByGrapheme","_styleMap","_generateStyleMap","textInfo","realLineCount","realLineCharCount","isWrapping","nextOffset","shouldLimit","mapNextLine","_wrapText","desiredWidth","wrapped","_wrapLine","_measureWord","word","charOffset","_line","reservedSpace","words","infix","wordWidth","infixWidth","largestWordWidth","lineJustStarted","additionalSpace","getMinWidth","linesToKeep","scaleSkewStyleHandler","scaleStyleHandler","objectControls","ml","mr","mb","mtr","textBoxControls","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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","ignoreList":[]}